Computer Systems Practical - Part 4: Data Sections

Abstract

This article describes data sections of ELF64 file and the difference among data sections. This is a interesting part to begin to get to know about PIC (Position Independent code) data reference and function call.

Difference between .bss, .data, and .rodata sections

Section Diff 1 Diff 2
.rodata Read-only data, constant strings, global, variables with const modification and static variables. Occupy space in object files
.data Global, static variables with an initial value of non-zero (without const). Occupy space in object files
.bss Global, static variables are not initialized or have an initial value of 0 (without const). No space in object files.
  • Local non-static variables - runtime stack.
  • gcc marks the uninitialized global variables in C programs (file .c) as COMMON instead of putting them in .bss section.
  • C++ programs, uninitialized global variables in the program will be placed in .bss section.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
ethanol@ethanol:~/Desktop/sections$ readelf -S datasection
There are 13 section headers, starting at offset 0x388:

Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .text PROGBITS 0000000000000000 00000040
0000000000000018 0000000000000000 AX 0 0 1
[ 2] .data PROGBITS 0000000000000000 00000058
0000000000000008 0000000000000000 WA 0 0 4
[ 3] .bss NOBITS 0000000000000000 00000060
000000000000000c 0000000000000000 WA 0 0 4
[ 4] .rodata PROGBITS 0000000000000000 00000060
0000000000000004 0000000000000000 A 0 0 4
[ 5] .comment PROGBITS 0000000000000000 00000064
000000000000002b 0000000000000001 MS 0 0 1
[ 6] .note.GNU-stack PROGBITS 0000000000000000 0000008f
0000000000000000 0000000000000000 0 0 1
[ 7] .note.gnu.propert NOTE 0000000000000000 00000090
0000000000000020 0000000000000000 A 0 0 8
[ 8] .eh_frame PROGBITS 0000000000000000 000000b0
0000000000000038 0000000000000000 A 0 0 8
[ 9] .rela.eh_frame RELA 0000000000000000 00000300
0000000000000018 0000000000000018 I 10 8 8
[10] .symtab SYMTAB 0000000000000000 000000e8
0000000000000198 0000000000000018 11 16 8
[11] .strtab STRTAB 0000000000000000 00000280
0000000000000080 0000000000000000 0 0 1
[12] .shstrtab STRTAB 0000000000000000 00000318
000000000000006f 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
l (large), p (processor specific)
ethanol@ethanol:~/Desktop/sections$ cat datasection.cpp
int sum(int a, int b) {
static int val_1;
static int val_2 = 0;
static int val_3 = 1;
static int val_4 = 0;
static int val_5 = 2;
const static int val_6 = 0;
return a + b;
}
  • .rodata: size = 0x4 $\rightarrow$ val_6
  • .data: size = 0x8 $\rightarrow$ val_3 and val_5
  • .bss: size = 0xc $\rightarrow$ val_1, val_2 and val_4
  • Futher reading: view offset.

The difference between .plt and .plt.sec, .plt.got, .got, .got.plt sections

Section Segment Access Use
.plt code segment RE PLT
.plt.got code segment RE PLT entry _cxa_finalize function
.got data segment RW - Address of global variable
- Address of funtions that do not require delay biding.
.got.plt data segment RW - Address of the function that requires delay binding.

View the program table.

1
readelf -l main_mix		
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
03 .init .plt .plt.sec .text .fini
04 .rodata .eh_frame_hdr .eh_frame
05 .init_array .fini_array .dynamic .got .got.plt .data .bss
06 .dynamic
07 .note.gnu.property
08 .note.gnu.build-id .note.ABI-tag
09 .note.gnu.property
10 .eh_frame_hdr
11
12 .init_array .fini_array .dynamic .got
  • .plt, .plt.sec, .text are located in the code segment.
  • .got, .got.plt and .data in the same segment.

.plt and .plt.sec

.plt

  • Call dynamic link.
1
objdump -d --section=.plt main_mix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Disassembly of section .plt:

0000000000401020 <.plt>:
401020: ff 35 e2 2f 00 00 pushq 0x2fe2(%rip) # 404008 <_GLOBAL_OFFSET_TABLE_+0x8>
401026: f2 ff 25 e3 2f 00 00 bnd jmpq *0x2fe3(%rip) # 404010 <_GLOBAL_OFFSET_TABLE_+0x10>
40102d: 0f 1f 00 nopl (%rax)
401030: f3 0f 1e fa endbr64
401034: 68 00 00 00 00 pushq $0x0
401039: f2 e9 e1 ff ff ff bnd jmpq 401020 <.plt>
40103f: 90 nop
401040: f3 0f 1e fa endbr64
401044: 68 01 00 00 00 pushq $0x1
401049: f2 e9 d1 ff ff ff bnd jmpq 401020 <.plt>
40104f: 90 nop

.plt.sec

  • Call function.
  • If not $\rightarrow$ call dynamic link.
1
2
3
4
5
6
7
8
9
10
11
Disassembly of section .plt.sec:

0000000000401050 <_Z3addii@plt>:
401050: f3 0f 1e fa endbr64
401054: f2 ff 25 bd 2f 00 00 bnd jmpq *0x2fbd(%rip) # 404018 <_Z3addii@got.plt>
40105b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)

0000000000401060 <_Z3subii@plt>:
401060: f3 0f 1e fa endbr64
401064: f2 ff 25 b5 2f 00 00 bnd jmpq *0x2fb5(%rip) # 404020 <_Z3subii@got.plt>
40106b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)

Conclusion: Call dynamic link.

.plt.got

1
objdump -d libadd_debug.so
1
2
3
4
5
6
7
8
9
10
11
ethanol@ethanol:~/Desktop/pic$ objdump -d --section=.plt.got libadd_debug.so

libadd_debug.so: file format elf64-x86-64


Disassembly of section .plt.got:

0000000000001030 <__cxa_finalize@plt>:
1030: f3 0f 1e fa endbr64
1034: f2 ff 25 9d 2f 00 00 bnd jmpq *0x2f9d(%rip) # 3fd8 <__cxa_finalize>
103b: 0f 1f 44 00 00 nopl 0x0(%rax,%rax,1)
  • Debug with GDB and xfiles
  • The second instruction in plt.got is jump to the first address of .got of libadd_debug.so.
1
2
3
4
5
6
7
8
9
0x00007ffff7fc3020 0x00007ffff7fc3030 .plt                  ./libadd_debug.so
0x00007ffff7fc3030 0x00007ffff7fc3040 .plt.got ./libadd_debug.so
0x00007ffff7fc5fd8 0x00007ffff7fc6000 .got ./libadd_debug.so
0x00007ffff7fc6000 0x00007ffff7fc6018 .got.plt ./libadd_debug.so

0x00007ffff7fbe020 0x00007ffff7fbe030 .plt ./libsub_debug.so
0x00007ffff7fbe030 0x00007ffff7fbe040 .plt.got ./libsub_debug.so
0x00007ffff7fc0fd8 0x00007ffff7fc1000 .got ./libsub_debug.so
0x00007ffff7fc1000 0x00007ffff7fc1018 .got.plt ./libsub_debug.so
1
2
3
4
gef➤  x/3i 0x00007ffff7fc3030
0x7ffff7fc3030 <__cxa_finalize@plt>: endbr64
0x7ffff7fc3034 <__cxa_finalize@plt+4>: bnd jmp QWORD PTR [rip+0x2f9d] # 0x7ffff7fc5fd8
0x7ffff7fc303b <__cxa_finalize@plt+11>: nop DWORD PTR [rax+rax*1+0x0]

Conclusion: plt.got is used to hold the PLT entry for the <__cxa_finalize@plt>.

.got

1
2
3
4
5
6
7
8
gef➤  x/10gx 0x7ffff7fc5fd8
0x7ffff7fc5fd8: 0x00007ffff7e03090 0x00007ffff7fc6024
0x7ffff7fc5fe8: 0x0000000000000000 0x0000000000000000
0x7ffff7fc5ff8: 0x0000000000000000 0x0000000000003e88
0x7ffff7fc6008: 0x0000000000000000 0x0000000000000000
0x7ffff7fc6018: 0x00007ffff7fc6018 0x0000000000000000
gef➤ p/x &g_sum
$1 = 0x7ffff7fc6024
  • GOT[2] hold global variables g_sum.
1
2
3
4
5
6
7
8
9
10
gef➤  disas 0x00007ffff7e03090, 0x00007ffff7e03090+0x10
Dump of assembler code from 0x7ffff7e03090 to 0x7ffff7e030a0:
0x00007ffff7e03090 <__cxa_finalize+0>: endbr64
0x00007ffff7e03094 <__cxa_finalize+4>: push r15
0x00007ffff7e03096 <__cxa_finalize+6>: push r14
0x00007ffff7e03098 <__cxa_finalize+8>: push r13
0x00007ffff7e0309a <__cxa_finalize+10>: push r12
0x00007ffff7e0309c <__cxa_finalize+12>: push rbp
0x00007ffff7e0309d <__cxa_finalize+13>: mov rbp,rdi
End of assembler dump.
  • GOT[1] hold the address of function <__cxa_finalize>.

.got.plt

  • GOT Table.
1
0x0000000000404000 0x0000000000404028 .got.plt              /home/ethanol/Desktop/pic/main_mix
1
2
3
4
5
6
7
8
9
10
11
12
gef➤  x/10gx 0x404000
0x404000: 0x0000000000403e00 0x00007ffff7ffe190
0x404010: 0x00007ffff7fe7ae0 0x00007ffff7fc30f9
0x404020 <_Z3subii@got.plt>: 0x00007ffff7fbe0f9 0x0000000000000000
0x404030: 0x0000000000000000 0x0000000000000000
0x404040: 0x0000000000000000 0x0000000000000000
gef➤ info symbol 0x00007ffff7fc30f9
add(int, int) in section .text of ./libadd_debug.so
gef➤ info symbol 0x00007ffff7fbe0f9
sub(int, int) in section .text of ./libsub_debug.so
gef➤ info symbol 0x0000000000403e00
_DYNAMIC in section .dynamic of /home/ethanol/Desktop/pic/main_mix