我想了解GNU的以下行为。
OS X上的以下测试程序(Apple cctools-822 / GNU为1.38)
.globl foo
jmp foo
foo:
ret
编码为
00000000 e900000000 jmp 0x00000005
foo:
00000005 c3 ret
而GNU在Linux上(GNU为2.22)编码为
.global foo
0000 E9FCFFFF jmp 0x35 # foo
FF
foo:
0005 C3 ret
后者为什么会(对我而言)奇怪的跳跃?
此外,显然这个神奇的0xfcffffff
地址用于
每跳到一个全球标签:
test2.s
.globl foo
jmp foo
.globl bar
jmp bar
.globl baz
jmp baz
foo:
push $1
ret
bar:
push $2
ret
baz:
push $3
ret
使用GNU生成Linux(GNU为2.22)
.globl foo
0000 E9FCFFFF jmp foo
FF
.globl bar
0005 E9FCFFFF jmp bar
FF
.globl baz
000a E9FCFFFF jmp baz
FF
foo:
000f 6A01 push $1
0011 C3 ret
bar:
0012 6A02 push $2
0014 C3 ret
baz:
0015 6A03 push $3
0017 C3 ret
任何人都可以解释这种行为吗?
答案 0 :(得分:2)
它只是一种不同类型的重定位条目(R_386_PC32)。
您不必担心,链接器将插入正确的地址。
如果您为-r
添加objdump
选项,则可以看到重定位条目,例如
objdump -Dr test2.o
请注意,值为0xfffffffc = -4
,因为x86是小端。
答案 1 :(得分:1)
我假设您正在拆卸对象而不是可执行文件?这对于所有工具链来说都是非常典型的,所有工具链都是在喜欢之前编译为对象的所有语言。链接器...链接...对象,将全局链接在一起,函数名称,变量等。直到链接阶段,你无法知道你所在的地址空间以及变量名称,所以一些本地人依赖关于指令集和覆盖范围以及全局变量在链接时间之前无法解析,因此对象将放置某种填充数据而不是可能以奇怪的方式拆解的指令。