Global Offset Table
The exact mechanism of the Global Offset Table is not clear from the ELF documentation. The purpose of the GOT is to define a place where position independent code can access global data. There is an ELF section named .got, but it can be all zeroes apart from perhaps the first entry. Special relocation types, such as the Sparc R_SPARC_GLOB_DAT actually set the values of the GOT to the address of particular symbols. Thus, the GOT can actually be set up as part of the relocation process.Various instructions reference the global offset table, possibly with the aid of other relocation types such as R_SPARC_GOT22 (but I have not seen these). Here is an example of Sparc code, from the second function in libelf.so.1:
_elf_armem: 00002A4C: 9DE3BFA0 save %sp, -96, %sp 00002A50: 40000002 call 0x00002a58 ; PC -> %o7 00002A54: 2F000066 sethi %hi(0x19800), %l7 ; Set %l7 to... ... 00002A5C: AE15E07C or %l7, 0x7C, %l7 ; 0x1987C 00002A60: AE05C00F add %l7, %o7, %l7 ; Base+0x1C2CC->%l7 ... 00002A74: D605E138 ld [%l7+312], %o3 ; Ref the GOTNote that the gcc linker just initialises the GOT. (Use either -fpic or -fPIC to generate Position Independent Code). For example, consider this simple function:
extern char* name;
void func2()
{
printf("Me too! <%s>\n", name);
}
The format string as well as the external global will have to
be made position independent. Here is the resultant object (.o) code, using
gcc -fpic:
00000000: 9DE3BF90 save %sp, -112, %sp 00000004: 40000002 call 0x0000000c 00000008: 01000000 nop 0000000C: 2F000000 sethi %hi(0x0), %l7 00000010: AE15E000 or %l7, 0, %l7 ; See below 00000014: AE05C00F add %l7, %o7, %l7 ; %l7 now points to GOT 00000018: D205E000 ld [%l7+0], %o1 ; Some GOT entry (format str) 0000001C: D405E000 ld [%l7+0], %o2 ; Another GOT entry (name) 00000020: 9010000A mov %o2, %o0 ; first arg (format string) 00000024: D2024000 ld [%o1], %o1 ; name 00000028: 40000000 call 0x00000028 ; printf 0000002C: 01000000 nop 00000030: 81C7E008 ret 00000034: 81E80000 restoreThe instructions at offsets 0C, 10, 18, and 1C have relocation entries:
Relocation Section Table .rela.text
Address = 0000000C
Info = 00000911 Addend = 00000008
Sym = 9 Type = R_SPARC_PC22
Address = 00000010
Info = 00000910 Addend = 0000000C
Sym = 9 Type = R_SPARC_PC10
Address = 00000018
Info = 0000080E Addend = 00000000
Sym = 8 Type = R_SPARC_GOT13
Address = 0000001C
Info = 0000020E Addend = 00000000
Sym = 2 Type = R_SPARC_GOT13
The first two are complex relocations that have the effect of setting %l7
to be the address of symbol 9 (_GLOBAL_OFFSET_TABLE) relative to the
instruction at offset 4. Note how gcc has not even allocated any offsets
in the GOT; in fact, the object file does not even have a .got section at
all! The GOT is created by the link editor, and all offsets within it are
managed by the GOT. Presumably, the Sun compiler uses different relocation
types which result in the different GOT organisation, or more likely, the
Sun linker chooses to initialise the GOT differently.
