赞
踩
目录
可执行文件也是ELF文件,这里同样从ELF文件的观点分析可执行文件的结构
使用如下两端代码来模拟多个文件生成一个可执行文件的过程
- //add.c
- extern int times;
-
- int add(int n1, int n2) {
- times++;
- return n1 + n2;
- }
- //main.c
- #include <stdio.h>
-
- extern int add(int, int);
- int times = 0;
-
- int main(void)
- {
- int a = 2;
- int b = 3;
-
- printf("%d, The sum of a and b is %d\n", times, add(a,b));
-
- return 0;
- }
使用命令如下,先生成两个可重定位文件,然后对其进行链接,生成可执行文件add
- gcc -c add.c -o add.o
- gcc -c main.c -o main.o
- gcc -o add add.o main.o
注意,假如下面查看可执行文件,发现type是共享库文件类型,可能是因为gcc默认加了--enable-default-pie选项,可以使用-no-pie禁用,如下
gcc -o add add.c main.c -no-pie
使用readelf查看文件
- $ readelf -h add
- 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: EXEC (Executable file)
- Machine: Advanced Micro Devices X86-64
- Version: 0x1
- Entry point address: 0x401050
- Start of program headers: 64 (bytes into file)
- Start of section headers: 14736 (bytes into file)
- Flags: 0x0
- Size of this header: 64 (bytes)
- Size of program headers: 56 (bytes)
- Number of program headers: 13
- Size of section headers: 64 (bytes)
- Number of section headers: 31
- Section header string table index: 30
字段分析如下
这里可以看出,链接之后生成的可执行文件,该文件结构具有了完整的ELF文件结构。
从ELF Header中可以看出 add 有31个 section,使用readelf查看section的内容
- $ readelf -S add
- There are 31 section headers, starting at offset 0x3990:
-
- 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 0000000000400318 00000318
- 000000000000001c 0000000000000000 A 0 0 1
- [ 2] .note.gnu.propert NOTE 0000000000400338 00000338
- 0000000000000020 0000000000000000 A 0 0 8
- [ 3] .note.gnu.build-i NOTE 0000000000400358 00000358
- 0000000000000024 0000000000000000 A 0 0 4
- [ 4] .note.ABI-tag NOTE 000000000040037c 0000037c
- 0000000000000020 0000000000000000 A 0 0 4
- [ 5] .gnu.hash GNU_HASH 00000000004003a0 000003a0
- 000000000000001c 0000000000000000 A 6 0 8
- [ 6] .dynsym DYNSYM 00000000004003c0 000003c0
- 0000000000000060 0000000000000018 A 7 1 8
- [ 7] .dynstr STRTAB 0000000000400420 00000420
- 000000000000003f 0000000000000000 A 0 0 1
- [ 8] .gnu.version VERSYM 0000000000400460 00000460
- 0000000000000008 0000000000000002 A 6 0 2
- [ 9] .gnu.version_r VERNEED 0000000000400468 00000468
- 0000000000000020 0000000000000000 A 7 1 8
- [10] .rela.dyn RELA 0000000000400488 00000488
- 0000000000000030 0000000000000018 A 6 0 8
- [11] .rela.plt RELA 00000000004004b8 000004b8
- 0000000000000018 0000000000000018 AI 6 24 8
- [12] .init PROGBITS 0000000000401000 00001000
- 000000000000001b 0000000000000000 AX 0 0 4
- [13] .plt PROGBITS 0000000000401020 00001020
- 0000000000000020 0000000000000010 AX 0 0 16
- [14] .plt.sec PROGBITS 0000000000401040 00001040
- 0000000000000010 0000000000000010 AX 0 0 16
- [15] .text PROGBITS 0000000000401050 00001050
- 00000000000001d5 0000000000000000 AX 0 0 16
- [16] .fini PROGBITS 0000000000401228 00001228
- 000000000000000d 0000000000000000 AX 0 0 4
- [17] .rodata PROGBITS 0000000000402000 00002000
- 0000000000000021 0000000000000000 A 0 0 4
- [18] .eh_frame_hdr PROGBITS 0000000000402024 00002024
- 000000000000004c 0000000000000000 A 0 0 4
- [19] .eh_frame PROGBITS 0000000000402070 00002070
- 0000000000000120 0000000000000000 A 0 0 8
- [20] .init_array INIT_ARRAY 0000000000403e10 00002e10
- 0000000000000008 0000000000000008 WA 0 0 8
- [21] .fini_array FINI_ARRAY 0000000000403e18 00002e18
- 0000000000000008 0000000000000008 WA 0 0 8
- [22] .dynamic DYNAMIC 0000000000403e20 00002e20
- 00000000000001d0 0000000000000010 WA 7 0 8
- [23] .got PROGBITS 0000000000403ff0 00002ff0
- 0000000000000010 0000000000000008 WA 0 0 8
- [24] .got.plt PROGBITS 0000000000404000 00003000
- 0000000000000020 0000000000000008 WA 0 0 8
- [25] .data PROGBITS 0000000000404020 00003020
- 0000000000000010 0000000000000000 WA 0 0 8
- [26] .bss NOBITS 0000000000404030 00003030
- 0000000000000008 0000000000000000 WA 0 0 4
- [27] .comment PROGBITS 0000000000000000 00003030
- 000000000000002a 0000000000000001 MS 0 0 1
- [28] .symtab SYMTAB 0000000000000000 00003060
- 0000000000000630 0000000000000018 29 46 8
- [29] .strtab STRTAB 0000000000000000 00003690
- 00000000000001da 0000000000000000 0 0 1
- [30] .shstrtab STRTAB 0000000000000000 0000386a
- 000000000000011f 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)
- $ readelf -s add
-
- Symbol table '.dynsym' contains 4 entries:
- Num: Value Size Type Bind Vis Ndx Name
- 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
- 1: 0000000000000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.2.5 (2)
- 2: 0000000000000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.2.5 (2)
- 3: 0000000000000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__
- $ readelf -V add
-
- Version symbols section '.gnu.version' contains 4 entries:
- Addr: 0x0000000000400460 Offset: 0x000460 Link: 6 (.dynsym)
- 000: 0 (*local*) 2 (GLIBC_2.2.5) 2 (GLIBC_2.2.5) 0 (*local*)
从其中的内容可以知道,.gnu.version的四个条目解释了.dynsym与之相对应的四个条目的版本。比如,printf这个符号对应的是GLIBC_2.2.5这个版本中的printf函数。
segment是由section组成的,可以从 readelf -l add 输出的 program header table 中得到相关的信息
- $ readelf -l add
-
- Elf file type is EXEC (Executable file)
- Entry point 0x401050
- There are 13 program headers, starting at offset 64
-
- Program Headers:
- Type Offset VirtAddr PhysAddr
- FileSiz MemSiz Flags Align
- PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
- 0x00000000000002d8 0x00000000000002d8 R 0x8
- INTERP 0x0000000000000318 0x0000000000400318 0x0000000000400318
- 0x000000000000001c 0x000000000000001c R 0x1
- [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
- LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
- 0x00000000000004d0 0x00000000000004d0 R 0x1000
- LOAD 0x0000000000001000 0x0000000000401000 0x0000000000401000
- 0x0000000000000235 0x0000000000000235 R E 0x1000
- LOAD 0x0000000000002000 0x0000000000402000 0x0000000000402000
- 0x0000000000000190 0x0000000000000190 R 0x1000
- LOAD 0x0000000000002e10 0x0000000000403e10 0x0000000000403e10
- 0x0000000000000220 0x0000000000000228 RW 0x1000
- DYNAMIC 0x0000000000002e20 0x0000000000403e20 0x0000000000403e20
- 0x00000000000001d0 0x00000000000001d0 RW 0x8
- NOTE 0x0000000000000338 0x0000000000400338 0x0000000000400338
- 0x0000000000000020 0x0000000000000020 R 0x8
- NOTE 0x0000000000000358 0x0000000000400358 0x0000000000400358
- 0x0000000000000044 0x0000000000000044 R 0x4
- GNU_PROPERTY 0x0000000000000338 0x0000000000400338 0x0000000000400338
- 0x0000000000000020 0x0000000000000020 R 0x8
- GNU_EH_FRAME 0x0000000000002024 0x0000000000402024 0x0000000000402024
- 0x000000000000004c 0x000000000000004c R 0x4
- GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
- 0x0000000000000000 0x0000000000000000 RW 0x10
- GNU_RELRO 0x0000000000002e10 0x0000000000403e10 0x0000000000403e10
- 0x00000000000001f0 0x00000000000001f0 R 0x1
-
- 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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。