ELF文件格式
参考:
- https://blog.csdn.net/wxh0000mm/article/details/127635576
- https://blog.csdn.net/GrayOnDream/article/details/124564129
1. 前言
在嵌入式开发中,我们编写的程序最终会被编译成一个可执行的文件,这个文件可被系统加载执行。
能被加载执行,说明这个可行执行文件具备统一的符合规范的文件。那么它的格式是啥呢?
ARM 系统基本文件格式有三种 :
- BIN,平板式二进制格式 , 一般用于直接烧写到Flash 中,也可以用于加载到monitor程序中 。
- ELF,EXECUTABLE AND LINKABLE FORMAT, 一种通用的 OBJECT文件格式 , 一般由 GNIJ COMPILER COLLECTION (GCC)产生 。
- AXF,BIN格式的扩展版 , 主体部分同BIN , 在文件头和尾加入了调试用的信息 。
现在的编译器基本上都是gcc了,所以重点学习ELF文件格式。
ELF的英文全称是The Executable and Linking Format,最初是由UNIX系统实验室开发、发布的ABI(Application Binary Interface)接口的一部分,也是Linux的主要可执行文件格式。
从使用上来说,主要的ELF文件的种类主要有三类:
- 可执行文件(.out):Executable File,包含代码和数据,是可以直接运行的程序。其代码和数据都有固定的地址 (或相对于基地址的偏移 ),系统可根据这些地址信息把程序加载到内存执行。
- 可重定位文件(.o文件):Relocatable File,包含基础代码和数据,但它的代码及数据都没有指定绝对地址,因此它适合于与其他目标文件链接来创建可执行文件或者共享目标文件。
- 共享目标文件(.so):Shared Object File,也称动态库文件,包含了代码和数据,这些数据是在链接时被链接器(ld)和运行时动态链接器(ld.so.l、libc.so.l、ld-linux.so.l)使用的。
2. ELF文件格式
在编译过程中ELF文件格式在链接和程序的运行阶段的格式不同。链接阶段每个.o文件都是一个独立的ELF文件,为了效率和便利性他们的段需要进行合并才能生成对应的可执行文件。
ELF文件包含一个Header描述文件的基本信息;
程序头表告诉系统如何构建进程的内存镜像,因此只有可执行文件有程序头表;
Sections描述了链接过程中的需要的符号表、数据、指令等信息,而在可执行文件中是Segments,是经过合并的Secitons;
节/段头表指明了对应section/segment在文件中的偏移,链接阶段的ELF文件必须包含该表头;
而每个节/段头描述了对应的section/segment的大小,入口等基本信息。
2.1. ELF Header
32bit和64bit的区别仅仅是字长的区别,字段上没有实际上的差别。
- 魔数: 取值为固定的0x7f E L F,标记当前文件为一个ELF文件;
- 位宽:0:表示非法的类别;1:表示32bit;2:表示64bit;
- 端模式:0表示非法;1表示小端;2表示大端;
- 版本
- 目标系统体系结构
- 程序虚拟入口地址
- 程序头表的偏移
- 段/节头表的偏移
- 处理器相关标志位
- ELF Header大小
- 程序头表中单项的大小
- 程序头表中的项数
- 节表中单项的大小
- 节表中项的数量
- 节表中节名的索引
下面是一个例子:
root@firefly:~/work/test# readelf -h test
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: AArch64
Version: 0x1
Entry point address: 0x660
Start of program headers: 64 (bytes into file)
Start of section headers: 10064 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 33
Section header string table index: 32
2.2. 程序头表
可执行文件或者共享目标文件的程序头部是一个结构数组,每个结构描述了一个段 或者系统准备程序执行所必需的其它信息。程序头表描述了ELF文件中Segment在文件中的布局,描述了OS该如何装载可执行文件到内存。
- 当前Segment的类型:可装载段;动态段;字符串等;
- 当前段相对于文件起始位置的偏移量
- 段的第一个字节将被映射到到内存中的虚拟地址
- 段在文件映像中所占的字节数,可能为 0;
- 段在内存映像中占用的字节数,可能为 0;
- 段相关的标志;
- 段在文件中和内存中如何对齐:0和1表示不需要对齐;其他值必须为2的幂次方,且必须p_addr ∣ p_align == p_offset ∣ palign。
root@firefly:~/work/test# readelf -l test
Elf file type is DYN (Shared object file)
Entry point 0x660
There are 9 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040
0x00000000000001f8 0x00000000000001f8 R 0x8
INTERP 0x0000000000000238 0x0000000000000238 0x0000000000000238
0x000000000000001b 0x000000000000001b R 0x1
[Requesting program interpreter: /lib/ld-linux-aarch64.so.1]
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000abc 0x0000000000000abc R E 0x10000
LOAD 0x0000000000000d80 0x0000000000010d80 0x0000000000010d80
0x0000000000000290 0x0000000000000298 RW 0x10000
DYNAMIC 0x0000000000000d90 0x0000000000010d90 0x0000000000010d90
0x00000000000001f0 0x00000000000001f0 RW 0x8
NOTE 0x0000000000000254 0x0000000000000254 0x0000000000000254
0x0000000000000044 0x0000000000000044 R 0x4
GNU_EH_FRAME 0x0000000000000938 0x0000000000000938 0x0000000000000938
0x0000000000000054 0x0000000000000054 R 0x4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 0x10
GNU_RELRO 0x0000000000000d80 0x0000000000010d80 0x0000000000010d80
0x0000000000000280 0x0000000000000280 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .dynamic .got .data .bss
04 .dynamic
05 .note.gnu.build-id .note.ABI-tag
06 .eh_frame_hdr
07
08 .init_array .fini_array .dynamic .got
2.3. 节头表
节头表描述了ELF文件中的节的基本信息。可执行文件不一定由节头表但是一定有节,节头表可利用特殊的方式去除。
段和节的区别是:
* 段包含了程序装载可执行的基本信息,段告诉OS如何装载当前段到虚拟内存以及当前段的权限等和执行相关的信息,一个段可以包含0个或多个节;
* 节包含了程序的代码和数据等内容,链接器会将多个节合并为一个段。
包括一下信息:
- 节名称
- 节的类型和语义
- 装载信息
- 当前节的首地址相对于文件的偏移
- 节的大小
- 地址约束对齐
- 其他信息
root@firefly:~/work/test# readelf -S test
There are 33 section headers, starting at offset 0x2750:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000000238 00000238
000000000000001b 0000000000000000 A 0 0 1
[ 2] .note.gnu.build-i NOTE 0000000000000254 00000254
0000000000000024 0000000000000000 A 0 0 4
[ 3] .note.ABI-tag NOTE 0000000000000278 00000278
0000000000000020 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000000298 00000298
000000000000001c 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 00000000000002b8 000002b8
00000000000000f0 0000000000000018 A 6 3 8
[ 6] .dynstr STRTAB 00000000000003a8 000003a8
0000000000000089 0000000000000000 A 0 0 1
[ 7] .gnu.version VERSYM 0000000000000432 00000432
0000000000000014 0000000000000002 A 5 0 2
[ 8] .gnu.version_r VERNEED 0000000000000448 00000448
0000000000000020 0000000000000000 A 6 1 8
[ 9] .rela.dyn RELA 0000000000000468 00000468
00000000000000f0 0000000000000018 A 5 0 8
[10] .rela.plt RELA 0000000000000558 00000558
0000000000000078 0000000000000018 AI 5 21 8
[11] .init PROGBITS 00000000000005d0 000005d0
0000000000000014 0000000000000000 AX 0 0 4
[12] .plt PROGBITS 00000000000005f0 000005f0
0000000000000070 0000000000000010 AX 0 0 16
[13] .text PROGBITS 0000000000000660 00000660
0000000000000294 0000000000000000 AX 0 0 8
[14] .fini PROGBITS 00000000000008f4 000008f4
0000000000000010 0000000000000000 AX 0 0 4
[15] .rodata PROGBITS 0000000000000908 00000908
000000000000002d 0000000000000000 A 0 0 8
[16] .eh_frame_hdr PROGBITS 0000000000000938 00000938
0000000000000054 0000000000000000 A 0 0 4
[17] .eh_frame PROGBITS 0000000000000990 00000990
000000000000012c 0000000000000000 A 0 0 8
[18] .init_array INIT_ARRAY 0000000000010d80 00000d80
0000000000000008 0000000000000008 WA 0 0 8
[19] .fini_array FINI_ARRAY 0000000000010d88 00000d88
0000000000000008 0000000000000008 WA 0 0 8
[20] .dynamic DYNAMIC 0000000000010d90 00000d90
00000000000001f0 0000000000000010 WA 6 0 8
[21] .got PROGBITS 0000000000010f80 00000f80
0000000000000080 0000000000000008 WA 0 0 8
[22] .data PROGBITS 0000000000011000 00001000
0000000000000010 0000000000000000 WA 0 0 8
[23] .bss NOBITS 0000000000011010 00001010
0000000000000008 0000000000000000 WA 0 0 1
[24] .comment PROGBITS 0000000000000000 00001010
000000000000002b 0000000000000001 MS 0 0 1
[25] .debug_aranges PROGBITS 0000000000000000 0000103b
0000000000000030 0000000000000000 0 0 1
[26] .debug_info PROGBITS 0000000000000000 0000106b
00000000000003ea 0000000000000000 0 0 1
[27] .debug_abbrev PROGBITS 0000000000000000 00001455
000000000000011f 0000000000000000 0 0 1
[28] .debug_line PROGBITS 0000000000000000 00001574
0000000000000147 0000000000000000 0 0 1
[29] .debug_str PROGBITS 0000000000000000 000016bb
00000000000002b8 0000000000000001 MS 0 0 1
[30] .symtab SYMTAB 0000000000000000 00001978
0000000000000960 0000000000000018 31 74 8
[31] .strtab STRTAB 0000000000000000 000022d8
000000000000033a 0000000000000000 0 0 1
[32] .shstrtab STRTAB 0000000000000000 00002612
000000000000013a 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),
p (processor specific)
2.4. 一些特殊的节
ELF文件中有一些预定义的节来保存程序、数据和一些控制信息,这些节被用来链接或者装载程序。每个操作系统都支持一组链接模式,主要分为两类(也就是常说的动态库和静态库):
- Static:静态绑定的一组目标文件、系统库和库档案(比如静态库),解析包含的符号引用并创建一个完全自包含的可执行文件;
- Dynamic:一组目标文件、库、系统共享资源和其他共享库链接在一起创建可执行文件。当加载此可执行文件时必须使系统中其他共享资源和动态库可用,程序才能正常运行。
库文件无论是动态库还是静态库在其文件中都包含对应的节,一些特殊的节其功能如下:
.bss,类型SHT_NOBITS,属性SHF_ALLOC|SHF_WRITE:存储未经初始化的数据。根据定义程序开始执行时,系统会将这些数据初始化为0,且此节不占用文件空间;
.comment,类型SHT_PROGBITS,属性none:存储版本控制信息;
.data,类型SHT_PROGBITS,属性SHF_ALLOC|SHF_WRITE:存放初始化的数据;
.data1,类型SHT_PROGBITS,属性SHF_ALLOC|SHF_WRITE:存放初始化的数据;
.debug,类型SHT_PROGBITS,属性none:存放用于符号调试的信息;
.dynamic,类型SHT_DYNAMIC,属性SHF_ALLOC,是否有属性SHF_WRITE屈居于处理器:包含动态链接的信息,
.hash,类型SHT_HASH,属性SHF_ALLOC:
.line,类型SHT_PROGBITS,属性none:存储调试的行号信息,描述源代码和机器码之间的对应关系;
.note,类型SHT_NOTE,属性none:
.rodata,类型SHT_PROGBITS,属性SHF_ALLOC:存储只读数据;
.rodata1,类型SHT_PROGBITS,属性SHF_ALLOC:存储只读数据;
.shstrtab,类型SHT_STRTAB,属性none:存储节的名称;
.strtab,类型SHT_STRTAB:存储常见的与符号表关联的字符串。如果文件有一个包含符号字符串表的可加载段,则该段的属性将包括 SHF_ALLOC 位; 否则,该位将关闭;
.symtab,类型SHT_SYMTAB,属性``````:存储一个符号表。如果文件具有包含符号表的可加载段,则该节的属性将包括 SHF_ALLOC 位;否则,该位将关闭;
.text,类型SHT_PROGBITS,属性SHF_ALLOC|SHF_EXECINSTR:存储程序的代码指令;
.dynstr,类型SHT_STRTAB,属性SHF_ALLOC:存储动态链接所需的字符串,最常见的是表示与符号表条目关联的名称的字符串;
.dynsym,类型SHT_DYNSYM,属性SHF_ALLOC:存储动态链接符号表;
.fini,类型SHT_PROGBITS,属性SHF_ALLOC|SHF_EXECINSTR:存储有助于进程终止代码的可执行指令。 当程序正常退出时,系统执行本节代码;
.init,类型SHT_PROGBITS,属性SHF_ALLOC|SHF_EXECINSTR:存储有助于进程初始化代码的可执行指令。 当程序开始运行时,系统会在调用主程序入口点(C 程序称为 main)之前执行本节中的代码;
.interp,类型SHT_PROGBITS:保存程序解释器的路径名。 如果文件有一个包含该节的可加载段,则该节的属性将包括 SHF_ALLOC 位; 否则,该位将关闭;
.relname,类型SHT_REL:包含重定位信息。如果文件具有包含重定位的可加载段,则这些部分的属性将包括 SHF_ALLOC 位;否则,该位将关闭。通常,名称由 重定位适用的部分。因此.text的重定位部分通常具有名称.rel.text或.rela.text;
.relaname,类型SHT_RELA:同relname。
其他:对于C++程序有些版本会有.ctors和dtors两个节存储构造和析构相关的代码。
带有点 (.) 前缀的部分名称是为系统保留的,但如果它们的现有含义令人满意,应用程序可以使用这些部分。 应用程序可以使用不带前缀的名称以避免与系统部分冲突。 目标文件格式允许定义不在上面列表中的部分。 一个目标文件可能有多个同名的部分。
2.5. 字符串表
字符串表是一个存储字符串的表格,而每个字符串是以NULL也就是\0为结尾的。字符串表格中索引为0处的字符串被定义为空字符串。符号表中保存的字符串是节名和目标文件中使用到的符号。而需要使用对应字符串时,只需要在需要使用的地方指明对应字符在字符串表中的索引即可,使用的字符串就是索引处到第一个\0之间的字符串
2.6. 符号表
目标文件的符号表包含定位和重定位程序的符号定义和引用所需的信息。符号表索引是该数组的下标。索引0既指定表中的第一个条目,又用作未定义的符号索引。
root@firefly:~/work/test# readelf -s test
Symbol table '.dynsym' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000000005d0 0 SECTION LOCAL DEFAULT 11
2: 0000000000011000 0 SECTION LOCAL DEFAULT 22
3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
4: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@GLIBC_2.17 (2)
5: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.17 (2)
6: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
7: 0000000000000000 0 FUNC GLOBAL DEFAULT UND abort@GLIBC_2.17 (2)
8: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
9: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.17 (2)
Symbol table '.symtab' contains 100 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000238 0 SECTION LOCAL DEFAULT 1
2: 0000000000000254 0 SECTION LOCAL DEFAULT 2
3: 0000000000000278 0 SECTION LOCAL DEFAULT 3
4: 0000000000000298 0 SECTION LOCAL DEFAULT 4
5: 00000000000002b8 0 SECTION LOCAL DEFAULT 5
6: 00000000000003a8 0 SECTION LOCAL DEFAULT 6
7: 0000000000000432 0 SECTION LOCAL DEFAULT 7
8: 0000000000000448 0 SECTION LOCAL DEFAULT 8
9: 0000000000000468 0 SECTION LOCAL DEFAULT 9
10: 0000000000000558 0 SECTION LOCAL DEFAULT 10
11: 00000000000005d0 0 SECTION LOCAL DEFAULT 11
12: 00000000000005f0 0 SECTION LOCAL DEFAULT 12
13: 0000000000000660 0 SECTION LOCAL DEFAULT 13
14: 00000000000008f4 0 SECTION LOCAL DEFAULT 14
15: 0000000000000908 0 SECTION LOCAL DEFAULT 15
16: 0000000000000938 0 SECTION LOCAL DEFAULT 16
17: 0000000000000990 0 SECTION LOCAL DEFAULT 17
18: 0000000000010d80 0 SECTION LOCAL DEFAULT 18
19: 0000000000010d88 0 SECTION LOCAL DEFAULT 19
20: 0000000000010d90 0 SECTION LOCAL DEFAULT 20
21: 0000000000010f80 0 SECTION LOCAL DEFAULT 21
22: 0000000000011000 0 SECTION LOCAL DEFAULT 22
23: 0000000000011010 0 SECTION LOCAL DEFAULT 23
24: 0000000000000000 0 SECTION LOCAL DEFAULT 24
25: 0000000000000000 0 SECTION LOCAL DEFAULT 25
26: 0000000000000000 0 SECTION LOCAL DEFAULT 26
27: 0000000000000000 0 SECTION LOCAL DEFAULT 27
28: 0000000000000000 0 SECTION LOCAL DEFAULT 28
29: 0000000000000000 0 SECTION LOCAL DEFAULT 29
30: 0000000000000000 0 FILE LOCAL DEFAULT ABS /usr/lib/gcc/aarch64-linu
31: 0000000000000278 0 NOTYPE LOCAL DEFAULT 3 $d
32: 0000000000000660 0 NOTYPE LOCAL DEFAULT 13 $x
33: 0000000000000908 0 NOTYPE LOCAL DEFAULT 15 $d
34: 0000000000000000 0 FILE LOCAL DEFAULT ABS /usr/lib/gcc/aarch64-linu
35: 0000000000000698 0 NOTYPE LOCAL DEFAULT 13 $x
36: 0000000000000698 20 FUNC LOCAL DEFAULT 13 call_weak_fn
37: 00000000000005d0 0 NOTYPE LOCAL DEFAULT 11 $x
38: 00000000000008f4 0 NOTYPE LOCAL DEFAULT 14 $x
39: 0000000000000000 0 FILE LOCAL DEFAULT ABS /usr/lib/gcc/aarch64-linu
40: 00000000000005dc 0 NOTYPE LOCAL DEFAULT 11 $x
41: 00000000000008fc 0 NOTYPE LOCAL DEFAULT 14 $x
42: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
43: 00000000000006b0 0 NOTYPE LOCAL DEFAULT 13 $x
44: 00000000000006b0 0 FUNC LOCAL DEFAULT 13 deregister_tm_clones
45: 00000000000006e0 0 FUNC LOCAL DEFAULT 13 register_tm_clones
46: 0000000000011008 0 NOTYPE LOCAL DEFAULT 22 $d
47: 0000000000000720 0 FUNC LOCAL DEFAULT 13 __do_global_dtors_aux
48: 0000000000011010 1 OBJECT LOCAL DEFAULT 23 completed.9189
49: 0000000000010d88 0 NOTYPE LOCAL DEFAULT 19 $d
50: 0000000000010d88 0 OBJECT LOCAL DEFAULT 19 __do_global_dtors_aux_fin
51: 0000000000000768 0 FUNC LOCAL DEFAULT 13 frame_dummy
52: 0000000000010d80 0 NOTYPE LOCAL DEFAULT 18 $d
53: 0000000000010d80 0 OBJECT LOCAL DEFAULT 18 __frame_dummy_init_array_
54: 00000000000009a4 0 NOTYPE LOCAL DEFAULT 17 $d
55: 0000000000011010 0 NOTYPE LOCAL DEFAULT 23 $d
56: 0000000000000000 0 FILE LOCAL DEFAULT ABS test.c
57: 000000000000076c 0 NOTYPE LOCAL DEFAULT 13 $x
58: 0000000000000910 0 NOTYPE LOCAL DEFAULT 15 $d
59: 0000000000000a08 0 NOTYPE LOCAL DEFAULT 17 $d
60: 0000000000000000 0 FILE LOCAL DEFAULT ABS elf-init.oS
61: 0000000000000870 0 NOTYPE LOCAL DEFAULT 13 $x
62: 0000000000000a70 0 NOTYPE LOCAL DEFAULT 17 $d
63: 0000000000000000 0 FILE LOCAL DEFAULT ABS crtstuff.c
64: 0000000000000ab8 0 NOTYPE LOCAL DEFAULT 17 $d
65: 0000000000000ab8 0 OBJECT LOCAL DEFAULT 17 __FRAME_END__
66: 0000000000000000 0 FILE LOCAL DEFAULT ABS
67: 0000000000010d88 0 NOTYPE LOCAL DEFAULT 18 __init_array_end
68: 0000000000010d90 0 OBJECT LOCAL DEFAULT ABS _DYNAMIC
69: 0000000000010d80 0 NOTYPE LOCAL DEFAULT 18 __init_array_start
70: 0000000000000938 0 NOTYPE LOCAL DEFAULT 16 __GNU_EH_FRAME_HDR
71: 0000000000010fc0 0 OBJECT LOCAL DEFAULT ABS _GLOBAL_OFFSET_TABLE_
72: 00000000000005d0 0 FUNC LOCAL DEFAULT 11 _init
73: 00000000000005f0 0 NOTYPE LOCAL DEFAULT 12 $x
74: 00000000000008f0 4 FUNC GLOBAL DEFAULT 13 __libc_csu_fini
75: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_deregisterTMCloneTab
76: 0000000000011000 0 NOTYPE WEAK DEFAULT 22 data_start
77: 0000000000011010 0 NOTYPE GLOBAL DEFAULT 23 __bss_start__
78: 0000000000000000 0 FUNC WEAK DEFAULT UND __cxa_finalize@@GLIBC_2.1
79: 0000000000011018 0 NOTYPE GLOBAL DEFAULT 23 _bss_end__
80: 0000000000011010 0 NOTYPE GLOBAL DEFAULT 22 _edata
81: 00000000000008f4 0 FUNC GLOBAL HIDDEN 14 _fini
82: 0000000000011018 0 NOTYPE GLOBAL DEFAULT 23 __bss_end__
83: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@@GLIBC_
84: 0000000000011000 0 NOTYPE GLOBAL DEFAULT 22 __data_start
85: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
86: 0000000000011008 0 OBJECT GLOBAL HIDDEN 22 __dso_handle
87: 0000000000000000 0 FUNC GLOBAL DEFAULT UND abort@@GLIBC_2.17
88: 0000000000000908 4 OBJECT GLOBAL DEFAULT 15 _IO_stdin_used
89: 0000000000000870 124 FUNC GLOBAL DEFAULT 13 __libc_csu_init
90: 000000000000076c 100 FUNC GLOBAL DEFAULT 13 fibonacci
91: 0000000000011018 0 NOTYPE GLOBAL DEFAULT 23 _end
92: 0000000000000660 0 FUNC GLOBAL DEFAULT 13 _start
93: 0000000000011018 0 NOTYPE GLOBAL DEFAULT 23 __end__
94: 0000000000011010 0 NOTYPE GLOBAL DEFAULT 23 __bss_start
95: 0000000000000814 88 FUNC GLOBAL DEFAULT 13 main
96: 0000000000011010 0 OBJECT GLOBAL HIDDEN 22 __TMC_END__
97: 0000000000000000 0 NOTYPE WEAK DEFAULT UND _ITM_registerTMCloneTable
98: 00000000000007d0 68 FUNC GLOBAL DEFAULT 13 get_fibonacci_sub
99: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@@GLIBC_2.17