《深入理解计算机系统》第 7 章 链接

链接是将各种代码和数据部分收集起来并组合成为一个单一文件的过程,这个文件可被加载(或被拷贝)到存储器并执行。

在现代系统中,链接是由链接器的程序自动执行的。

理解链接器将帮助你构造大型程序。

理解链接器将帮助你避免一些危险的编程错误

理解链接将帮助你理解语言的作用域规则是如何实现的

理解链接将帮助你理解其他重要的系统概念

理解链接将使你能够利用共享库

编译器驱动程序:

1.预编译

[xyk@xyk linking]$ gcc -E main.c -o main.i
[xyk@xyk linking]$ gcc -E swap.c -o swap.i

2.编译
[xyk@xyk linking]$ gcc -S swap.i -o swap.s
[xyk@xyk linking]$ gcc -S main.i -o main.s

3.汇编

[xyk@xyk linking]$ gcc -c main.s -o main.o
[xyk@xyk linking]$ gcc -c swap.s -o swap.o

4.链接
[xyk@xyk linking]$ gcc -o p main.o swap.o

静态链接

静态链接器:以一组可重定位目标文件和命令行参数作为输入,生成一个完全链接的可以加载和运行的可执行目标文件作为输出。

为了构造可执行文件,链接器必须完成两个主要任务:

1.符号解析:目标文件定义和引用符号。符号解析的目的是将每个符号的引用刚好和一个符号定义联系起来。

2.重定位:编译器和汇编器生成从地址0开始的代码和数据节。链接器通过把每个符号定义与一个存储器位置联系起来,然后修改所有对这些符号的引用,使得它们指向这个存储器位置,从而重定位这些节。

目标文件:可重定位目标文件;可执行目标文件;共享目标文件。

可重定位目标文件:

ELF可重定位目标文件的格式

ELF头
.text:已编译程序的机器代码
.rodata:只读数据
.data:已初始化的全局C变量
.bss:未初始化的全局C变量
.symtab:一个符号表,它存放在程序中定义和引用的函数和全局变量的信息
.rel.text:一个.text节中位置的列表
.rel.data:被模块引用或定义的任何全局变量的重定位信息
.debug:一个调试符号表
.line:原始C源程序中的行号和.text节中机器指令之间的映射。
.strtab:一个字符串表,其内容包括.symtab和.debug节中的符号表以及节头部中的节名字。字符串表就是以null结尾的字符串序列.
节头部表

符号和符号表

在链接器的上下文中,有三种不同的符号:

1.由目标模块定义并能被其他模块引用的全局符号

2.由其他模块定义并被目标模块引用的全局变量

3.只被目标模块定义和引用的本地符号。

[xyk@xyk linking]$ readelf -a main.o
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          200 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         10
  Section header string table index: 7

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000034 000014 00  AX  0   0  4
  [ 2] .rel.text         REL             00000000 000310 000008 08      8   1  4
  [ 3] .data             PROGBITS        00000000 000048 000008 00  WA  0   0  4
  [ 4] .bss              NOBITS          00000000 000050 000000 00  WA  0   0  4
  [ 5] .comment          PROGBITS        00000000 000050 00002d 01  MS  0   0  1
  [ 6] .note.GNU-stack   PROGBITS        00000000 00007d 000000 00      0   0  1
  [ 7] .shstrtab         STRTAB          00000000 00007d 000049 00      0   0  1
  [ 8] .symtab           SYMTAB          00000000 000258 0000a0 10      9   7  4
  [ 9] .strtab           STRTAB          00000000 0002f8 000016 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

There are no program headers in this file.

Relocation section '.rel.text' at offset 0x310 contains 1 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000007  00000902 R_386_PC32        00000000   swap

There are no unwind sections in this file.

Symbol table '.symtab' contains 10 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS main.c
     2: 00000000     0 SECTION LOCAL  DEFAULT    1
     3: 00000000     0 SECTION LOCAL  DEFAULT    3
     4: 00000000     0 SECTION LOCAL  DEFAULT    4
     5: 00000000     0 SECTION LOCAL  DEFAULT    6
     6: 00000000     0 SECTION LOCAL  DEFAULT    5
     7: 00000000     8 OBJECT  GLOBAL DEFAULT    3 buf
     8: 00000000    20 FUNC    GLOBAL DEFAULT    1 main
     9: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND swap


[xyk@xyk linking]$ readelf -a swap.o
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              REL (Relocatable file)
  Machine:                           Intel 80386
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          0 (bytes into file)
  Start of section headers:          236 (bytes into file)
  Flags:                             0x0
  Size of this header:               52 (bytes)
  Size of program headers:           0 (bytes)
  Number of program headers:         0
  Size of section headers:           40 (bytes)
  Number of section headers:         11
  Section header string table index: 8

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .text             PROGBITS        00000000 000034 000035 00  AX  0   0  4
  [ 2] .rel.text         REL             00000000 000374 000030 08      9   1  4
  [ 3] .data             PROGBITS        00000000 00006c 000004 00  WA  0   0  4
  [ 4] .rel.data         REL             00000000 0003a4 000008 08      9   3  4
  [ 5] .bss              NOBITS          00000000 000070 000000 00  WA  0   0  4
  [ 6] .comment          PROGBITS        00000000 000070 00002d 01  MS  0   0  1
  [ 7] .note.GNU-stack   PROGBITS        00000000 00009d 000000 00      0   0  1
  [ 8] .shstrtab         STRTAB          00000000 00009d 00004d 00      0   0  1
  [ 9] .symtab           SYMTAB          00000000 0002a4 0000b0 10     10   7  4
  [10] .strtab           STRTAB          00000000 000354 00001d 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

There are no program headers in this file.

Relocation section '.rel.text' at offset 0x374 contains 6 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000008  00000901 R_386_32          00000004   bufp1
0000000c  00000801 R_386_32          00000000   buf
00000011  00000701 R_386_32          00000000   bufp0
0000001b  00000701 R_386_32          00000000   bufp0
00000021  00000901 R_386_32          00000004   bufp1
0000002a  00000901 R_386_32          00000004   bufp1

Relocation section '.rel.data' at offset 0x3a4 contains 1 entries:
 Offset     Info    Type            Sym.Value  Sym. Name
00000000  00000801 R_386_32          00000000   buf

There are no unwind sections in this file.

Symbol table '.symtab' contains 11 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND
     1: 00000000     0 FILE    LOCAL  DEFAULT  ABS swap.c
     2: 00000000     0 SECTION LOCAL  DEFAULT    1
     3: 00000000     0 SECTION LOCAL  DEFAULT    3
     4: 00000000     0 SECTION LOCAL  DEFAULT    5
     5: 00000000     0 SECTION LOCAL  DEFAULT    7
     6: 00000000     0 SECTION LOCAL  DEFAULT    6
     7: 00000000     4 OBJECT  GLOBAL DEFAULT    3 bufp0
     8: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND buf
     9: 00000004     4 OBJECT  GLOBAL DEFAULT  COM bufp1
    10: 00000000    53 FUNC    GLOBAL DEFAULT    1 swap

符号解析

编译器如何解析多重定义的全局符号

在编译时,编译器向汇编器输出每个全局符号,或者强或者弱,而汇编器把这个信息隐含的编码在可重定位目标文件的符号表里。函数和已初始化的的全局变量是强符号,未初始化的全局变量是弱符号。根据强弱符号的定义,Unix链接器使用下面的规则来处理多重定义的符号:

规则1:不允许有多个强符号

规则2:如果有一个强符号和多个弱符号,那么选择强符号

规则3:如果有多个弱符号,那么从这些弱符号中任意选择一个。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值