看CSAPP第七章时,老是感觉迷迷糊糊的,所以实际看看程序的可重定位目标文件和可执行目标文件的内容。
我这里以书中的代码为例
//main.c
int sum(int *a, int n);
int array[2] = {1,2};
int main(){
int val = sum(array,2);
return val;
}
//sum.c
int sum(int *a, int n){
int i,s = 0;
for(i=0; i<n; i++){
s += a[i];
}
return s;
}
然后在命令行中运行
gcc -Og -c main.c
可以得到main.c
的可重定位目标文件main.o
,然后使用以下命令行查看该ELF文件
readelf -a -x .text -x .data main.o
可重定位目标文件的ELF格式包含以下内容
我们依次查看其中不同的数据节
ELF头:
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: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 704 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 12
Section header string table index: 11
可以看到ELF头主要描述改文件的生成信息,并且包含了节头部表的开始地址Start of section headers
。
节头部表:
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
000000000000001a 0000000000000000 AX 0 0 1
[ 2] .rela.text RELA 0000000000000000 00000218
0000000000000030 0000000000000018 I 9 1 8
[ 3] .data PROGBITS 0000000000000000 00000060
0000000000000008 0000000000000000 WA 0 0 8
[ 4] .bss NOBITS 0000000000000000 00000068
0000000000000000 0000000000000000 WA 0 0 1
[ 5] .comment PROGBITS 0000000000000000 00000068
000000000000002c 0000000000000001 MS 0 0 1
[ 6] .note.GNU-stack PROGBITS 0000000000000000 00000094
0000000000000000 0000000000000000 0 0 1
[ 7] .eh_frame PROGBITS 0000000000000000 00000098
0000000000000030 0000000000000000 A 0 0 8
[ 8] .rela.eh_frame RELA 0000000000000000 00000248
0000000000000018 0000000000000018 I 9 7 8
[ 9] .symtab SYMTAB 0000000000000000 000000c8
0000000000000120 0000000000000018 10 8 8
[10] .strtab STRTAB 0000000000000000 000001e8
000000000000002d 0000000000000000 0 0 1
[11] .shstrtab STRTAB 0000000000000000 00000260
0000000000000059 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)
可以看到,节头部表中含有一个表,其中每个数据项含有以下内容(我只挑我会的说):Nr
数据项的索引;Name
数据项的名字,即该数据项是描述哪个数据节的;Address
数据节所在的内存地址;offset
数据节在目标文件中的偏移量;size
数据节的大小。
**注意:**编译器和汇编器会从地址0开始生成数据节,没有考虑实际的内存地址,所以这里的address
都是0。
.text: