前言
参考第 2 章
笔记
静态链接
测试程序如下:
//a.c | // b.c
extern int shared; | int shared =1;
int main() | void swap( int* a, int* b )
{ | {
int a = 100; | *a ^= *b ^= *a ^= *b;
swap( &a, &shared ); | }
} |
======================================================================================================================================
// 编译中目标文件: gcc -c a.c b.c
======================================================================================================================================
$ readelf -s a.o | $ readelf -s b.o
|
Symbol table '.symtab' contains 10 entries: | Symbol table '.symtab' contains 9 entries:
Num: Value Size Type Bind Vis Ndx Name | Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND | 0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS a.c | 1: 00000000 0 FILE LOCAL DEFAULT ABS b.c
2: 00000000 0 SECTION LOCAL DEFAULT 1 | 2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3 | 3: 00000000 0 SECTION LOCAL DEFAULT 2
4: 00000000 0 SECTION LOCAL DEFAULT 4 | 4: 00000000 0 SECTION LOCAL DEFAULT 3
5: 00000000 0 SECTION LOCAL DEFAULT 6 | 5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000000 0 SECTION LOCAL DEFAULT 5 | 6: 00000000 0 SECTION LOCAL DEFAULT 4
7: 00000000 39 FUNC GLOBAL DEFAULT 1 main | 7: 00000000 4 OBJECT GLOBAL DEFAULT 2 shared
8: 00000000 0 NOTYPE GLOBAL DEFAULT UND shared | 8: 00000000 58 FUNC GLOBAL DEFAULT 1 swap
9: 00000000 0 NOTYPE GLOBAL DEFAULT UND swap |
链接这两个目标文件:
$ ld a.o b.o -e main -o ab
-e main: 表示将 main 函数作为程序入口,ld 链接器默认的程序入口为 _start
-o ab: 表示链接输出文件名为 ab,默认为 a.out
使用 objdump -h 查看链接前后地址的分配情况:
注:
VMA 表示 Virtual Memory Address 即虚拟地址,LMA 表示 Load Memory Address,即加载地址,
正常情况下这两个值应该是一样的,但是在有些嵌入式系统中,特别是在那些程序存放在 ROM 的系统
中时,LMA 和 VMA 是不相同的。这里我们只要关注 VMA 即可。
////////////////////////////////////////////////////////////////////////////////////
$ objdump -h a.o
a.o: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000027 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 00000000 00000000 0000005c 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 0000005c 2**2
ALLOC
3 .comment 00000024 00000000 00000000 0000005c 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 00000000 00000000 00000080 2**0
CONTENTS, READONLY
book@book-desktop:/work/link_test$ objdump -h b.o
////////////////////////////////////////////////////////////////////////////////////
$ objdump -h b.o
b.o: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000003a 00000000 00000000 00000034 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000004 00000000 00000000 00000070 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 00000000 00000000 00000074 2**2
ALLOC
3 .comment 00000024 00000000 00000000 00000074 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 00000000 00000000 00000098 2**0
CONTENTS, READONLY
////////////////////////////////////////////////////////////////////////////////////
$ objdump -h ab
ab: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000062 08048094 08048094 00000094 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000004 080490f8 080490f8 000000f8 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .comment 00000023 00000000 00000000 000000fc 2**0
CONTENTS, READONLY
链接前后的程序中所使用的地址已经是程序在进程中的虚拟地址,即我们关心上面各个段中的 VMA 和 Size,
而忽略文件偏移。可以看到,在链接之前,目标文件中的所有段的 VMA 都是 0,因为虚拟空间还没有被分配,所
以它们默认都为 0.等到链接之后,可执行文件 ab 中的各个段都被分配了相应的虚拟地址。这里的输出程序 ab
中,.text 段被分配地址 0x0808 8094,大小为 0x72 字节,.data 段从地址 0x0804 9108 开始,大小为 4 字
节。