Readelf -h XXX.o
读ELF头
读可重定位目标文件的ELF头:
lsy@lsy-VirtualBox:~/Documents$ readelf -h Hello.o
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 #魔数,代表ELF
Class: ELF64 #64位ELF
Data: 2's complement, little endian #二进制补码,小端法
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file) #类型为可重定位文件
Machine: Advanced Micro Devices X86-64#在64位机器上运行
Version: 0x1
Entry point address: 0x0 #起始地址(虚拟空间)
Start of program headers: 0 (bytes into file) #程序头表起始地址为0(可重定目 标文件没有程序表头
Start of section headers: 680 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes) #ELF头共64B
Size of program headers: 0 (bytes) #ELF头大小为0未存放数据,不是可执行程序,所以为0
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 13
Section header string table index: 10 #节头部表在表中的位置索引
对比读可执行文件的ELF头:
lsy@lsy-VirtualBox:~/Documents$ readelf -h Hello
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: 0x400430#可执行文件加载入内存,所以有起始地址
Start of program headers: 64 (bytes into file)#可执行文件有程序表头
Start of section headers: 6624 (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: 31
Section header string table index: 28
readelf -l XXX
读程序头表(program header)
程序表头(program header):描述了可执行文件中的节与虚拟空间中的存储段之间的映射关系。可重定位文件中的节经过链接生成可执行文件时会组合为对应的段,程序表头就是描述了这些段与节的关系。所以程序表头也只有可执行文件里有而可重定位文件是没有的
lsy@lsy-VirtualBox:~/Documents$ readelf -l Hello
Elf file type is EXEC (Executable file)
Entry point 0x400430
There are 9 program headers, starting at offset 64
Program Headers:
Type 偏移位置 虚拟空间地址 物理地址
FileSiz MemSiz 操作标志 对齐
PHDR 0x0000000000000040 0x0000000000400040 0x0000000000400040
0x00000000000001f8 0x00000000000001f8 R E 8
INTERP 0x0000000000000238 0x0000000000400238 0x0000000000400238
0x000000000000001c 0x000000000000001c R 1
[Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000006fc 0x00000000000006fc R E 200000
LOAD 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10
0x0000000000000228 0x0000000000000230 RW 200000
DYNAMIC 0x0000000000000e28 0x0000000000600e28 0x0000000000600e28
0x00000000000001d0 0x00000000000001d0 RW 8
NOTE 0x0000000000000254 0x0000000000400254 0x0000000000400254
0x0000000000000044 0x0000000000000044 R 4
GNU_EH_FRAME 0x00000000000005d0 0x00000000004005d0 0x00000000004005d0
0x0000000000000034 0x0000000000000034 R 4
GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x0000000000000000 0x0000000000000000 RW 10
GNU_RELRO 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10
0x00000000000001f0 0x00000000000001f0 R
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .note.gnu.build-id .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag .note.gnu.build-id
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got
读可重定位文件时,无程序头表:
lsy@lsy-VirtualBox:~/Documents$ readelf -l Hello.o
There are no program headers in this file.
readelf -s XXX.o
读符号表(.symbols)
root@lsy-VirtualBox:/mnt/Wshare/chap7_code# readelf -s Symbols.o
Symbol table '.symtab' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 0000000000000000 0 FILE LOCAL DEFAULT ABS symbols.c
2: 0000000000000000 0 SECTION LOCAL DEFAULT 1
3: 0000000000000000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 0 SECTION LOCAL DEFAULT 5
6: 0000000000000000 0 SECTION LOCAL DEFAULT 7
7: 0000000000000000 0 SECTION LOCAL DEFAULT 8
8: 0000000000000000 0 SECTION LOCAL DEFAULT 6
#####前9个是链接器内部使用的局部符号####################
9: 0000000000000000 4 FUNC GLOBAL DEFAULT 1 foo
10: 0000000000000004 41 FUNC GLOBAL DEFAULT 1 main
11: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND printf
12: 0000000000000004 4 OBJECT GLOBAL DEFAULT COM time
Ndx:1~8为ELF头中的位置索引,比如1表示存放在.text节;ABS表示不该被重定位;UND表示未定义,一般是外部引用;COM表示未初始化数据
symbols.c的代码:
#include <stdio.h>
int time;
int foo(int a) {
int b = a + 1;
return b;
}
int main(int argc, char *argv[])
{
printf("%d\n", foo(5));
return 0;
}
readelf -S XXX
读节头部表
节头部表(Section header):描述了每个节的节名,在文件中的偏移,大小,访问属性 ,对齐方式等
读可重定位文件:
root@lsy-VirtualBox:/mnt/Wshare/chap7_code# readelf -S Symbols.o
There are 13 section headers, starting at offset 0x320:
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
000000000000002d 0000000000000000 AX 0 0 1
[ 2] .rela.text RELA 0000000000000000 00000240
0000000000000048 0000000000000018 I 10 1 8
[ 3] .data PROGBITS 0000000000000000 0000006d
0000000000000000 0000000000000000 WA 0 0 1
[ 4] .bss NOBITS 0000000000000000 0000006d
0000000000000000 0000000000000000 WA 0 0 1
[ 5] .rodata.str1.1 PROGBITS 0000000000000000 0000006d
0000000000000004 0000000000000001 AMS 0 0 1
[ 6] .comment PROGBITS 0000000000000000 00000071
000000000000002e 0000000000000001 MS 0 0 1
[ 7] .note.GNU-stack PROGBITS 0000000000000000 0000009f
0000000000000000 0000000000000000 0 0 1
[ 8] .eh_frame PROGBITS 0000000000000000 000000a0
0000000000000048 0000000000000000 A 0 0 8
[ 9] .rela.eh_frame RELA 0000000000000000 00000288
0000000000000030 0000000000000018 I 10 8 8
[10] .symtab SYMTAB 0000000000000000 000000e8
0000000000000138 0000000000000018 11 9 8
[11] .strtab STRTAB 0000000000000000 00000220
0000000000000020 0000000000000000 0 0 1
[12] .shstrtab STRTAB 0000000000000000 000002b8
0000000000000068 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific
可以观察到,在可重定位目标文件中.bss是没有分配空间的,它不占据实际空间,仅仅是一个占位符
读可执行文件:
root@lsy-VirtualBox:/mnt/Wshare/chap7_code# readelf -S Symbols
There are 31 section headers, starting at offset 0x1a18:
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 0000000000400238 00000238
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 0000000000400254 00000254
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.build-i NOTE 0000000000400274 00000274
0000000000000024 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400298 00000298
000000000000001c 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 00000000004002b8 000002b8
0000000000000060 0000000000000018 A 6 1 8
[ 6] .dynstr STRTAB 0000000000400318 00000318
000000000000003f 0000000000000000 A 0 0 1
[ 7] .gnu.version VERSYM 0000000000400358 00000358
0000000000000008 0000000000000002 A 5 0 2
[ 8] .gnu.version_r VERNEED 0000000000400360 00000360
0000000000000020 0000000000000000 A 6 1 8
[ 9] .rela.dyn RELA 0000000000400380 00000380
0000000000000018 0000000000000018 A 5 0 8
[10] .rela.plt RELA 0000000000400398 00000398
0000000000000030 0000000000000018 AI 5 24 8
[11] .init PROGBITS 00000000004003c8 000003c8
000000000000001a 0000000000000000 AX 0 0 4
[12] .plt PROGBITS 00000000004003f0 000003f0
0000000000000030 0000000000000010 AX 0 0 16
[13] .plt.got PROGBITS 0000000000400420 00000420
0000000000000008 0000000000000000 AX 0 0 8
[14] .text PROGBITS 0000000000400430 00000430
00000000000001b2 0000000000000000 AX 0 0 16
[15] .fini PROGBITS 00000000004005e4 000005e4
0000000000000009 0000000000000000 AX 0 0 4
[16] .rodata PROGBITS 00000000004005f0 000005f0
0000000000000008 0000000000000000 A 0 0 4
[17] .eh_frame_hdr PROGBITS 00000000004005f8 000005f8
000000000000003c 0000000000000000 A 0 0 4
[18] .eh_frame PROGBITS 0000000000400638 00000638
0000000000000114 0000000000000000 A 0 0 8
[19] .init_array INIT_ARRAY 0000000000600e10 00000e10
0000000000000008 0000000000000000 WA 0 0 8
[20] .fini_array FINI_ARRAY 0000000000600e18 00000e18
0000000000000008 0000000000000000 WA 0 0 8
[21] .jcr PROGBITS 0000000000600e20 00000e20
0000000000000008 0000000000000000 WA 0 0 8
[22] .dynamic DYNAMIC 0000000000600e28 00000e28
00000000000001d0 0000000000000010 WA 6 0 8
[23] .got PROGBITS 0000000000600ff8 00000ff8
0000000000000008 0000000000000008 WA 0 0 8
[24] .got.plt PROGBITS 0000000000601000 00001000
0000000000000028 0000000000000008 WA 0 0 8
[25] .data PROGBITS 0000000000601028 00001028
0000000000000010 0000000000000000 WA 0 0 8
[26] .bss NOBITS 0000000000601038 00001038
0000000000000008 0000000000000000 WA 0 0 4
[27] .comment PROGBITS 0000000000000000 00001038
0000000000000035 0000000000000001 MS 0 0 1
[28] .shstrtab STRTAB 0000000000000000 00001909
000000000000010c 0000000000000000 0 0 1
[29] .symtab SYMTAB 0000000000000000 00001070
0000000000000678 0000000000000018 30 47 8
[30] .strtab STRTAB 0000000000000000 000016e8
0000000000000221 0000000000000000 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), l (large)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
观察到可执行目标文件中.bss有了实际空间,是因为运行时将这些未初始化的变量加载入内存并赋初值为0.
另外我们可以观察到可执行目标文件比可重定位文件多了一个程序头表和init节,少了rel.text,rel.data。事实上,可执行目标文件只留下了ELF头, .text, .rodata, .data, .bss。