undefined reference to _GLOBAL_OFFSET_TABLE_ (only when generating binaries)
Asked Answered
A

1

11

this is the problem:
When I link my scripts in C, using ld, when I generate elf32-i386 files as output format in ld, putting it as OUTPUT_FORMAT() in the ld script, I dont have any error, but if I try to put in this last OUTPUT_FORMAT() "binary" or try to output a file with .bin extension, I get a mixture of errors like:

kernel.o: In function `k_main':
kernel.c:(.text+0xe): undefined reference to `_GLOBAL_OFFSET_TABLE_'
kernelutils.o: In function `k_clear_screen':
kernelutils.c:(.text+0xc): undefined reference to `_GLOBAL_OFFSET_TABLE_'
kernelutils.o: In function `k_clear_screen_front':
kernelutils.c:(.text+0x56): undefined reference to `_GLOBAL_OFFSET_TABLE_'
kernelutils.o: In function `k_printf':
kernelutils.c:(.text+0xa0): undefined reference to `_GLOBAL_OFFSET_TABLE_'
kernelutils.o: In function `k_sleep_3sec':
kernelutils.c:(.text+0x152): undefined reference to `_GLOBAL_OFFSET_TABLE_'
kernelmalloc.o:kernelmalloc.c:(.text+0xc): more undefined references to `_GLOBAL_OFFSET_TABLE_' follow

This not only happens when compiling specific scripts, all scripts that try to use ld to link, or gcc since this calls ld, die in the attempt of get a binary with .bin extension.
When showing the symbols of one of the executables (kernel.o in the output of above) I see that the symbol _GLOBAL_OFFSET_TABLE_ isnt defined, and the most scary part, all the functions that returned error in the error output of above have their symbols removed, this is the nm output:

cristian@mymethodman:~/Desktop/kernel/0.0.3/Archivos$ nm kernel.o
         U _GLOBAL_OFFSET_TABLE_
         U k_clear_screen
         U k_clear_screen_front
00000000 T k_main
         U k_malloc
         U k_printf
         U k_sleep_3sec
00000000 T __x86.get_pc_thunk.bx

How I can solve this? I will leave the linker script below to ensure it isn a problem of the .ld file, with both "to get elf" and "to get binary" versions. Thanks in advance!

Ld scripts:
To get binary:

ENTRY(loader)
OUTPUT_FORMAT(binary)

SECTIONS {
   /* The kernel will live at 3GB + 1MB in the virtual
      address space, which will be mapped to 1MB in the
      physical address space. */
   . = 0xC0100000;

   .text : AT(ADDR(.text) - 0xC0000000) {
       *(.text)
       *(.rodata*)
   }

   .data ALIGN (0x1000) : AT(ADDR(.data) - 0xC0000000) {
       *(.data)
   }

   .bss : AT(ADDR(.bss) - 0xC0000000) {
       _sbss = .;
       *(COMMON)
       *(.bss)
       _ebss = .;
   }
}

To get ELF:

ENTRY(loader)
OUTPUT_FORMAT(elf32-i386)

SECTIONS {
   /* The kernel will live at 3GB + 1MB in the virtual
      address space, which will be mapped to 1MB in the
      physical address space. */
   . = 0xC0100000;

   .text : AT(ADDR(.text) - 0xC0000000) {
       *(.text)
       *(.rodata*)
   }

   .data ALIGN (0x1000) : AT(ADDR(.data) - 0xC0000000) {
       *(.data)
   }

   .bss : AT(ADDR(.bss) - 0xC0000000) {
       _sbss = .;
       *(COMMON)
       *(.bss)
       _ebss = .;
   }
}

As yo ucan see between both only changes the OUTPUT_FORMAT() line.

Autotruck answered 31/7, 2017 at 17:55 Comment(4)
Looks like your host GCC environment (Likely a newer version of something like Ubuntu 16.04+ or Debian 9+) is generating position independent code. When you compile with GCC you might want to try and compile all the files with -fno-pic . This is a good reason to use a GCC cross compiler for Operating System development. You can read about creating one here: wiki.osdev.org/GCC_Cross-CompilerAbutting
Thanks, I will build the cross compilerAutotruck
On a side note - why are you generating a binary file? I know you were using a multiboot compliant loader previously. To use a binary file will likely cause you issues unless you were now writing your own bootloader or you have altered your multiboot header to support the a.out kludge.Abutting
@MichaelPetch I had a similar problem I am trying to debug. I am using -fpie with GCC but the linker is emitting GOT-relative relocation entries. I'm sure I've used an incorrect set of input flags for this to happen (even feeding the binaries into IDA Pro it reports to me that the binary uses "non-standard" relocations!). Any thoughts? Similar to the OP, _GLOBAL_OFFSET_TABLE_ is undefined and there is no .got section. Indeed removing -fpic from the argument set prevented the GOT-relative relocations (now ABS) (but still no .got section). Would you mind helping me to understand?Hoisch
S
21

Your toolchain probably defaults to generating position-independent executables (PIE). Try compiling with gcc -fno-pie.

If you want to keep PIE for security reasons, you'll need a more complicated linker script and something that performs the initial relocation (such as a dynamic linker, but simpler constructions are possible as well).

Szabo answered 31/7, 2017 at 18:3 Comment(1)
I've run into a similar problem. I've written a runtime ELF relocator for an ARM target and the linker will emit GOT-relative relocation entries. In the same way as shown here, there is a symbol _GLOBAL_OFFSET_TABLE_, but it is undefined and not associated to any section (because there is no .got section emitted). I was explicitly compiling the code to be PIE (.e.g. -fpie). In what ways is a more complicated linker script needed when generating PIE code? Was also using GCC if that matters. Removing -fpie prevented this from happening. Why is that?Hoisch

© 2022 - 2024 — McMap. All rights reserved.