【程序员的自我修养—静态链接】

静态链接例子

// a.c
extern int shared;
int main() {
    int a = 100;
    swap(&a, &shared);
}
// b.c
int shared = 1;
void swap(int* a, int* b) {
    *a ^= *b ^= *a ^= *b;
}
$ gcc -c a.c b.c -fno-stack-protector
a.c: In function ‘main’:
a.c:4:5: warning: implicit declaration of function ‘swap’ [-Wimplicit-function-declaration]
    4 |     swap(&a, &shared);
      |     ^~~~
// -e 表示将main函数作为程序的入口,ld连接器默认的程序入口为_start
$ ld a.o b.o -e main -o ab
ld: a.o: in function `main':
a.c:(.text+0x4f): undefined reference to `__stack_chk_fail'
// 解决方法参考 https://blog.csdn.net/wuqindeyunque/article/details/131593357

空间与地址分配

分配的概念:

  • 只关注虚拟地址空间的分配

分配方法:

  • 按序叠加:直接将各个目标文件一次合并,但是会造成大量的内部碎片(因为需要按页对齐)
  • 相似段合并:将同样的段,比如各个目标文件中的.text合并在一起等;

使用第二种方法的链接器一般采用两部链接

  1. 空间与地址分配
    1. 扫面所有目标文件,获取各个段的长度、属性和位置;
    2. 将符号表中的所有符号定义和符号引用收集起来,放到全局符号表中;
    3. 根据获取到的段长度与输出文件建立映射关系。
  2. 符号解析与重定位
    • 读取输入文件中的段的数据、重定位信息;
    • 进行符号解析与重定位、调整代码中的地址。
$ objdump -h a.o
a.o:     file format elf64-x86-64
Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         00000032  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
  1 .data         00000000  0000000000000000  0000000000000000  00000072  2**0
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  0000000000000000  0000000000000000  00000072  2**0
                  ALLOC
$ objdump -h b.o
b.o:     file format elf64-x86-64
Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  0 .text         0000004f  0000000000000000  0000000000000000  00000040  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  1 .data         00000004  0000000000000000  0000000000000000  00000090  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  2 .bss          00000000  0000000000000000  0000000000000000  00000094  2**0
                  ALLOC

$ objdump -h ab
ab:     file format elf64-x86-64
Sections:
Idx Name          Size      VMA               LMA               File off  Algn
  1 .text         00000081  0000000000401000  0000000000401000  00001000  2**0
                  CONTENTS, ALLOC, LOAD, READONLY, CODE
  3 .data         00000004  0000000000404000  0000000000404000  00003000  2**2
                  CONTENTS, ALLOC, LOAD, DATA
  • VMA :虚拟地址,未链接的时候是0,链接后会分配地址;
  • size:文件大小,.a和.b的问价大小相加刚好等于ab的文件大小
  • 符号地址:根据符号在原始.text文件中的相对偏移和确定的虚拟地址计算全局符号表的地址;

符号解析与重定位

重定位:会将符合的地址用一个假的临时地址地替代,真正地址的计算留给了链接器;

每一个ELF文件包含一个重定位表:

  • 代码段的重定位表:.rel.text
  • 数据段的重定位表:.rel.data

对于32位Intel X86 系列处理器,重定位表的结构是由下面结构数组定义,每个元素代表一个重定位入口

typedef struct {
    Elf32_Addr r_offset; // 重定位入口的偏移
    Elf32_Word r_info; // 重定位入口的类型和符号,低8位代表类型,高24位代表符号在符号表中的下标
} Elf32_Rel;
$ objdump -r a.o
a.o:     file format elf64-x86-64

RELOCATION RECORDS FOR [.text]: # 代表代码段的重定位表
OFFSET           TYPE              VALUE 
000000000000001a R_X86_64_PC32     shared-0x0000000000000004
0000000000000027 R_X86_64_PLT32    swap-0x0000000000000004
$ objdump -d a.o
a.o:     file format elf64-x86-64
Disassembly of section .text:

0000000000000000 
: 0: f3 0f 1e fa endbr64 4: 55 push %rbp 5: 48 89 e5 mov %rsp,%rbp 8: 48 83 ec 10 sub $0x10,%rsp c: c7 45 fc 64 00 00 00 movl $0x64,-0x4(%rbp) 13: 48 8d 45 fc lea -0x4(%rbp),%rax 17: 48 8d 35 00 00 00 00 lea 0x0(%rip),%rsi # 1e 1e: 48 89 c7 mov %rax,%rdi 21: b8 00 00 00 00 mov $0x0,%eax 26: e8 00 00 00 00 callq 2b 2b: b8 00 00 00 00 mov $0x0,%eax 30: c9 leaveq 31: c3 retq $ objdump -d ab ab: file format elf64-x86-64 Disassembly of section .text: 0000000000401000
: 401000: f3 0f 1e fa endbr64 401004: 55 push %rbp 401005: 48 89 e5 mov %rsp,%rbp 401008: 48 83 ec 10 sub $0x10,%rsp 40100c: c7 45 fc 64 00 00 00 movl $0x64,-0x4(%rbp) 401013: 48 8d 45 fc lea -0x4(%rbp),%rax 401017: 48 8d 35 e2 2f 00 00 lea 0x2fe2(%rip),%rsi # 404000 40101e: 48 89 c7 mov %rax,%rdi 401021: b8 00 00 00 00 mov $0x0,%eax 401026: e8 07 00 00 00 callq 401032 40102b: b8 00 00 00 00 mov $0x0,%eax 401030: c9 leaveq 401031: c3 retq 0000000000401032 : 401032: f3 0f 1e fa endbr64 401036: 55 push %rbp ...

你可能感兴趣的:(算法,数据结构)