Monday, 23 January 2017

Global Varible access using GOT (Global Offset Table)



section:“.bss” contains the uninitialized global data,  while .data contains all the initialized data.
In general, the data segment of the executable contains initialized global/static variables and the BSS segment contains uninitialized global/static variables.

Figure 1. Memory access via the GOT


The GOT is private to each process, and the process must have write permissions to it. Conversely the library code is shared and the process should have only read and execute permissions on the code; it would be a serious security breach if the process could modify code.

------------------------------------------------------------------------------------------------
jtony@genoa:~/scrum/s7$ cat got.c
extern int i;
void test(void)
{
  i = 100;
}
------------------------------------------------------------------------------------------------

Above we create a simple shared library which refers to an external symbol. We do not know the address of this symbol at compile time, so we leave it for the dynamic linker to fix up at runtime. But we want our code to remain sharable, in case other processes want to use our code as well.
------------------------------------------------------------------------------------------------
$ clang -nostdlib  -shared -o got.so ./got.c
$  readelf --sections ./got.so
 Section Headers:
  [Nr] Name              Type             Address           Offset
       Size              EntSize          Flags  Link  Info  Align
  [ 0]                   NULL             0000000000000000  00000000
       0000000000000000  0000000000000000           0     0     0
  [ 1] .gnu.hash         GNU_HASH         0000000000000158  00000158
       0000000000000034  0000000000000000   A       2     0     8
  [ 9] .got              PROGBITS         0000000000020000  00010000
       0000000000000010  0000000000000008  WA       0     0     8
  [10] .comment          PROGBITS         0000000000000000  00010010
       00000000000000a5  0000000000000001  MS       0     0     1
------------------------------------------------------------------------------------------------

If we have a look at the readelf output above we can see that the .got section starts 0x20000 bytes past where library was loaded into memory.  Thus if the library were to be loaded into memory at address 0x6000000000000000 the .got would be at 0x6000000000020000,  The disassembly reveals just how we do this with the .got.

-----------------------------------
objdump --disassemble ./got.so 
Disassembly of section .text:
0000000000000290 <test>:
 290:   02 00 4c 3c     addis   r2,r12,2
 294:   70 7d 42 38     addi    r2,r2,32112
 298:   64 00 60 38     li      r3,100
 29c:   00 00 00 60     nop
 2a0:   08 80 82 e8     ld      r4,-32760(r2)
 2a4:   00 00 64 90     stw     r3,0(r4)
 2a8:   20 00 80 4e     blr
        ...

On ppc64le, the register r2 is known as the Toc pointer and always points to TOC base address.
The symbol .TOC. may be used to access the GOT or in TOC-relative addressing to other data constructs. The symbol may be offset by 0x8000 bytes, or another offset, from the start of the .got section. I think after line 290 – 294 (addis, addi) [need to confirm] , r2 will point to .GOT + 0x8000 (i.e 32768).  Then the ld on line 2a0, will set r4 point to .GOT + (32768 – 32760), i.e. r4 point to .GOT + 8

Table 4:  Relocation
-----------------------------------
jtony@genoa:~/scrum/s7$ readelf --relocs ./got.so
Relocation section '.rela.dyn' at offset 0x270 contains 1 entries:
000000020008  000300000026 R_PPC64_ADDR64    0000000000000000 i + 0
-----------------------------------


The relocation says "replace the value at offset 0x20008 with the memory location that symbol i is stored at".
We know that the .got starts at offset 0x20000 from the previous output. We have also seen how the code loads an address 0x8 past this ( using ld      r4,-32760(r2))  giving us an address of 0x20000 + 0x8 = 0x20008 ... the address which the relocation is for!
So before the program begins, the dynamic linker will have fixed up the relocation to ensure that the value of the memory at offset 0x20008 is the address of the global variable i!

No comments:

Post a Comment