链接器如何找到主函数? [英] How does the linker find the main function?
问题描述
链接器如何在 x86-64 ELF 格式的可执行文件中找到 main 函数?
How does the linker find the main function in an x86-64 ELF-format executable?
推荐答案
一个非常通用的概述,链接器将地址分配给由符号 main
标识的代码块.就像对目标文件中的所有符号一样.
A very generic overview, the linker assigns the address to the block of code identified by the symbol main
. As it does for all the symbols in your object files.
实际上,它不分配实际地址,而是分配相对于某个基址的地址,该基址将在程序执行时由加载程序转换为实际地址.
Actually, it doesn't assign a real address but assigns an address relative to some base which will get translated to a real address by the loader when the program is executed.
实际的入口点可能不是 main
而是 crt 中调用 main 的某个符号.LD 默认查找符号 start
除非您指定 不同的东西.
The actual entry point is not likely main
but some symbol in the crt that calls main. LD by default looks for the symbol start
unless you specify something different.
链接的代码在可执行文件的 .text
部分结束,看起来像这样(非常简化):
The linked code ends up in the .text
section of the executable and could look something like this (very simplified):
Address | Code
1000 someFunction
...
2000 start
2001 call 3000
...
3000 main
...
当链接器写入 ELF 标头时,它会将入口点指定为地址 2000.
When the linker writes the ELF header it would specify the entry point as address 2000.
您可以通过使用类似 objdump
的内容转储可执行文件的内容来获取 main
的相对地址.要在运行时获取实际地址,您只需读取符号 funcptr ptr = main;
其中 funcptr
被定义为指向具有 main 签名的函数的指针
.
You can get the relative address of main
by dumping the contents of the executable with something like objdump
. To get the actual address at runtime you can just read the symbol funcptr ptr = main;
where funcptr
is defined as a pointer to a function with the signature of main
.
typedef int (*funcptr)(int argc, char* argv[]);
int main(int argc, char* argv[])
{
funcptr ptr = main;
printf("%p\n", ptr);
return 0;
}
无论符号是否被剥离,main 的地址都将被正确解析,因为链接器首先将符号 main
解析为其相对地址.
The address of main will be correctly resolved regardless if symbols have been stripped since the linker will first resolve the symbol main
to its relative address.
像这样使用 objdump:
Use objdump like this:
$ objdump -f funcptr.exe
funcptr.exe: file format pei-i386
architecture: i386, flags 0x0000013a:
EXEC_P, HAS_DEBUG, HAS_SYMS, HAS_LOCALS, D_PAGED
start address 0x00401000
特别寻找 main
,在我的机器上我得到了这个:
Looking for main
specifically, on my machine I get this:
$ objdump -D funcptr.exe | grep main
40102c: e8 af 01 00 00 call 4011e0 <_cygwin_premain0>
401048: e8 a3 01 00 00 call 4011f0 <_cygwin_premain1>
401064: e8 97 01 00 00 call 401200 <_cygwin_premain2>
401080: e8 8b 01 00 00 call 401210 <_cygwin_premain3>
00401170 <_main>:
401179: e8 a2 00 00 00 call 401220 <___main>
004011e0 <_cygwin_premain0>:
004011f0 <_cygwin_premain1>:
00401200 <_cygwin_premain2>:
00401210 <_cygwin_premain3>:
00401220 <___main>:
请注意,我在 Windows 上使用 Cygwin,因此您的结果会略有不同.看起来 main
对我来说住在 00401170
.
Note that I am on Windows using Cygwin so your results will differ slightly. It looks like main
lives at 00401170
for me.
这篇关于链接器如何找到主函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!