为什么在同一节中引用全局函数的函数只能在 link 时解决,而局部函数将在编译时解决?
Why function that refers to a global function in the same section can only be solved at link time while local functions will be solve at compile time?
我有这个汇编文件 prog.S :
.text
#------------------------------main----------------------------------
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
call myGlobalFunction # call to my global func
call myLocalFunction # call to my local func
popl %ebp
ret
.Lmain_end:
.size main, .Lmain_end-main
#-------------------------myGlobalFunction---------------------------
.globl myGlobalFunction
.type myGlobalFunction,@function
myGlobalFunction:
pushl %ebp
movl %esp, %ebp
movl , %eax # return 1
popl %ebp
ret
.LmyGlobalFunction_end:
.size myGlobalFunction, .LmyGlobalFunction_end-myGlobalFunction
#-------------------------myLocalFunction---------------------------
.type myLocalFunction,@function
myLocalFunction:
pushl %ebp
movl %esp, %ebp
movl , %eax #return 2
popl %ebp
ret
.LmyLocalFunction:
.size myLocalFunction, .LmyLocalFunction-myLocalFunction
这三个函数位于同一个 .text 部分,main 调用全局函数,然后调用局部函数。
当我用 clang 编译这个文件时:
clang.exe -target i386-none prog.S -o prog.o -c
这是我得到的部分:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .strtab STRTAB 00000000 0000a0 000041 00 0 0 1
[ 2] .text PROGBITS 00000000 000034 000023 00 AX 0 0 4
[ 3] .rel.text REL 00000000 000098 000008 08 I 4 2 4
[ 4] .symtab SYMTAB 00000000 000058 000040 10 1 2 4
重定位节 '.rel.text' :
Relocation section '.rel.text' at offset 0x98 contains 1 entry:
Offset Info Type Sym.Value Sym. Name
00000004 00000302 R_386_PC32 0000000f myGlobalFunction
符号table:
Symbol table '.symtab' contains 4 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000019 10 FUNC LOCAL DEFAULT 2 myLocalFunction
2: 00000000 15 FUNC GLOBAL DEFAULT 2 main
3: 0000000f 10 FUNC GLOBAL DEFAULT 2 myGlobalFunction
和 .text 部分反汇编代码
00000000 <main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: e8 fc ff ff ff call 4 <main+0x4>
8: e8 0c 00 00 00 call 19 <myLocalFunction>
d: 5d pop %ebp
e: c3 ret
0000000f <myGlobalFunction>:
f: 55 push %ebp
10: 89 e5 mov %esp,%ebp
12: b8 01 00 00 00 mov [=16=]x1,%eax
17: 5d pop %ebp
18: c3 ret
00000019 <myLocalFunction>:
19: 55 push %ebp
1a: 89 e5 mov %esp,%ebp
1c: b8 02 00 00 00 mov [=16=]x2,%eax
21: 5d pop %ebp
22: c3 ret
从反汇编代码可以看出局部函数已经解决了PC相对调用,但是全局函数在链接过程中还没有解决..
我不明白的是为什么汇编程序无法解决与主函数在同一部分的全局函数调用(因此,据我了解,将始终位于与 main 相同的相对位置,因为它们位于同一部分)。
显然,如果 'main' 和 'myGlobalFunction' 不在同一节中,则汇编器无法解决 PC 相对调用,因为链接器可以将不同的节放在 'where it want'(或者我们想要的链接描述文件)。
编辑:有类似的 question 但没有正确的答案
汇编程序可以解决jumping/callingmyGlobalFunction
在asm-time的同一部分中定义,有时它会这样做,如[=22= 】 调查。
但是,由于该函数被声明为 global,因此假定它也可以从其他部分获得。
汇编程序认为文件 prog.o
中的 .text
部分可能在 link 时对其他程序静态 link 可用。你是对的,在这种情况下 other.o
将 myGlobalFunction
声明为 external,搬迁记录应该生成到 other.o
,搬迁 [=16] =] 在 prog.o
中是多余的。也许 clang.exe 假设符号 myGlobalFunction
可能是 弱 并且它可以在 link 时用 [=] 中定义的同名全局符号替换19=],也 link 与 other.o
和 prog.o
。
同一节中全局函数的调用可以在编译时解决。我的猜测是 Clang 将此延迟到 link 时间并生成 RIP 相对重定位,以便将来能够从其他模块替换目标函数。
我有这个汇编文件 prog.S :
.text
#------------------------------main----------------------------------
.globl main
.type main,@function
main:
pushl %ebp
movl %esp, %ebp
call myGlobalFunction # call to my global func
call myLocalFunction # call to my local func
popl %ebp
ret
.Lmain_end:
.size main, .Lmain_end-main
#-------------------------myGlobalFunction---------------------------
.globl myGlobalFunction
.type myGlobalFunction,@function
myGlobalFunction:
pushl %ebp
movl %esp, %ebp
movl , %eax # return 1
popl %ebp
ret
.LmyGlobalFunction_end:
.size myGlobalFunction, .LmyGlobalFunction_end-myGlobalFunction
#-------------------------myLocalFunction---------------------------
.type myLocalFunction,@function
myLocalFunction:
pushl %ebp
movl %esp, %ebp
movl , %eax #return 2
popl %ebp
ret
.LmyLocalFunction:
.size myLocalFunction, .LmyLocalFunction-myLocalFunction
这三个函数位于同一个 .text 部分,main 调用全局函数,然后调用局部函数。
当我用 clang 编译这个文件时:
clang.exe -target i386-none prog.S -o prog.o -c
这是我得到的部分:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .strtab STRTAB 00000000 0000a0 000041 00 0 0 1
[ 2] .text PROGBITS 00000000 000034 000023 00 AX 0 0 4
[ 3] .rel.text REL 00000000 000098 000008 08 I 4 2 4
[ 4] .symtab SYMTAB 00000000 000058 000040 10 1 2 4
重定位节 '.rel.text' :
Relocation section '.rel.text' at offset 0x98 contains 1 entry:
Offset Info Type Sym.Value Sym. Name
00000004 00000302 R_386_PC32 0000000f myGlobalFunction
符号table:
Symbol table '.symtab' contains 4 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000019 10 FUNC LOCAL DEFAULT 2 myLocalFunction
2: 00000000 15 FUNC GLOBAL DEFAULT 2 main
3: 0000000f 10 FUNC GLOBAL DEFAULT 2 myGlobalFunction
和 .text 部分反汇编代码
00000000 <main>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: e8 fc ff ff ff call 4 <main+0x4>
8: e8 0c 00 00 00 call 19 <myLocalFunction>
d: 5d pop %ebp
e: c3 ret
0000000f <myGlobalFunction>:
f: 55 push %ebp
10: 89 e5 mov %esp,%ebp
12: b8 01 00 00 00 mov [=16=]x1,%eax
17: 5d pop %ebp
18: c3 ret
00000019 <myLocalFunction>:
19: 55 push %ebp
1a: 89 e5 mov %esp,%ebp
1c: b8 02 00 00 00 mov [=16=]x2,%eax
21: 5d pop %ebp
22: c3 ret
从反汇编代码可以看出局部函数已经解决了PC相对调用,但是全局函数在链接过程中还没有解决..
我不明白的是为什么汇编程序无法解决与主函数在同一部分的全局函数调用(因此,据我了解,将始终位于与 main 相同的相对位置,因为它们位于同一部分)。
显然,如果 'main' 和 'myGlobalFunction' 不在同一节中,则汇编器无法解决 PC 相对调用,因为链接器可以将不同的节放在 'where it want'(或者我们想要的链接描述文件)。
编辑:有类似的 question 但没有正确的答案
汇编程序可以解决jumping/callingmyGlobalFunction
在asm-time的同一部分中定义,有时它会这样做,如[=22= 】 调查。
但是,由于该函数被声明为 global,因此假定它也可以从其他部分获得。
汇编程序认为文件 prog.o
中的 .text
部分可能在 link 时对其他程序静态 link 可用。你是对的,在这种情况下 other.o
将 myGlobalFunction
声明为 external,搬迁记录应该生成到 other.o
,搬迁 [=16] =] 在 prog.o
中是多余的。也许 clang.exe 假设符号 myGlobalFunction
可能是 弱 并且它可以在 link 时用 [=] 中定义的同名全局符号替换19=],也 link 与 other.o
和 prog.o
。
同一节中全局函数的调用可以在编译时解决。我的猜测是 Clang 将此延迟到 link 时间并生成 RIP 相对重定位,以便将来能够从其他模块替换目标函数。