题一:符号解析
考察可重定位目标文件各个节的内容,本质分类,那就分类:
节 | 内容 |
---|---|
.text | 已编译程序的机器代码,函数 |
.data | 已初始化的全局 C 变量,包括已初始化的extend,带static 属性的本地变量,不带static的全局变量 |
.bss | 未初始化的全局 C 变量,包括未初始化的不带static的全局变量,带static 属性的本地变量 |
- 注意带有static属性的变量或函数都被认为是本地变量或函数Local
分析过程如下:
① buf由关键字extend引入,是外部变量,swap.o.symtab条目中会存放由其他模块定义并被模块 m 引用的全局符号,这个外部是指的main.o,查看CSAPP前面的main.c代码可以发现buf是已经被初始化的全局变量,因此保存在节.data中
② bufp0是定义在全局的已初始化变量,因此会被swap.o.symtab条目存放;它在swap.o中定义,存放于.data节
③ bufp1是带static属性的静态未初始化全局变量,因此会被swap.o.symtab条目存放;由于它只能在模块内使用,因此属于local类型变量。它在swap.o中定义,存放于.bss节
④ swap是非静态的全局函数,定义在swap.o中,并且会被swap.o.symtab条目存放,函数存放在.text代码节
⑤ temp是局部变量,不会被Swap.o.symtab条目存放;局部 C 变量在运 行时保存在栈中,既不出现在 .data 节中,也不出现在 .bss 节中
⑥ incr是带有static属性的本地函数符号,会被Swap.o.symtab条目存放,类型为本地,存放在text中
⑦ count是带有static属性的一已初始化静态局部变量,会被Swap.o.symtab条目存放,类型为本地,由于已经初始化,因此保存在.data中。
符号 | Swap.o.symtab条目 | 符号类型 | 定义符号的模块 | 节 |
---|---|---|---|---|
buf | 是 | extend | main.o | .data |
bufp0 | 是 | global | swap.o | .data |
bufp1 | 是 | local | swap.o | .bss |
swap | 是 | global | swap.o | .text |
temp | 否 | ----- | ------ | ------ |
incr | 是 | local | swap.o | .text |
count | 是 | Local | swap.o | .data |
除了以上的逐个分析方法之外,还可以通过READELF工具查看,如图:
linux> gcc -c 7.6.c
linux> readelf -a 7.6.o
题二 重定位绝对引用
这道题我在网上看了解答,基本上所有的答案都认为存储器的地址是指的运行时PC的位置,存储器的值是符号的地址。但是这和书上P464页的绝对引用处理有些出入,仍需要更深入的思考:
① 在line3出现符号bufp0,对应到图7-10是15行,看到汇编指令 mov 0x804945c,%edx得到运行时存储器的值是0x0804945C,运行时存储器的是地址是0x80483C9+2=0x080483CB
② 在line5的重定向buf[1],对应到图7-10是16行,运行时存储器的是地址是0x80483CF+1=0x80483D0,看到汇编指令 mov 0x8049458,%eax得到存储器的值是
0x8049458
③ 在line10的重定向bufp1,对应到图7-10是18行,运行时存储器的是地址是0x080483D6+2=0x80483D8,看到机器指令c7 05 48 95 04 08 58得到存储器的值是0x8049548
④ 在line11的重定向buf[1],对应到图7-10是18行,运行时存储器的是地址是0x080483D6+2+4=0x80483DC,看到机器指令c7 05 48 95 04 08 58 94 04 08得到存储器的值是0x08049458
⑤ 在line16的重定向bufp1,对应到图7-10是23行,运行时存储器的是地址是0x080483E6+1=0x80483E7,看到汇编指令mov 0x8049548,%eax得到存储器的值是0x8049548
符号 | 行号 | 运行时存储器地址 | 值 |
---|---|---|---|
bufp0 | 15 | 0x080483CB | 0x0804945C |
buf[1] | 16 | 0x80483D0 | 0x08049458 |
bufp1 | 18 | 0x080483D8 | 0x08049548 |
buf[1] | 18 | 0x080483DC | 0x08049458 |
bufp1 | 23 | 0x080483E7 | 0x08049548 |
题三:重定位相对引用
A:.text节共有三处需要重定位。
① Line12:可以看到在line12 call 指令调用函数,由于调用函数,由PC计算被调用函数的位置,因此需要重定位。节偏移为0x12,重定位为PC 相对引用类型R386_PC32
② Line14:在line14行将0x0存放在%eax,但是由于全局变量x被存放在了绝对地址中,因此对于x的引用也需要重定位。0x0需要被重定位为绝对地址。可以直接查看左侧可重定向的运行地址是18,加上机器指令a1,所有节偏移为0x19,重定位为绝对引用类型R_386_32
③ Line17:在line17 call 指令调用函数,由于调用函数,由PC计算被调用函数的位置,因此需要重定位。节偏移为0x21,重定位为PC相对引用类型R_386_PC32
行号 | 符号名字 | 节偏移 | 重定位类型 |
---|---|---|---|
12 | P3 | 0x12 | R_386_PC32(相对) |
14 | Xp | 0x19 | R_386_32(绝对) |
17 | p2 | 0x21 | R_386_PC32(相对) |
B:由于x符号不是引用符号所以不需要被重定位,而xp需要被重定位为x的地址。因此,其节偏移为0x4,类型为绝对类型。
行号 | 符号名字 | 节偏移 | 重定位类型 |
---|---|---|---|
12 | x | 0x4 | R_386_32(绝对) |