链接器如何找到主要功能?

Rou*_*per 5 x86 assembly x86-64

链接器如何在x86-64 ELF格式的可执行文件中找到主要功能?

Dav*_*ger 3

一个非常通用的概述,链接器将地址分配给由符号 标识的代码块main。正如它对目标文件中的所有符号所做的那样。

实际上,它并不分配真实地址,而是分配相对于某个基址的地址,该基址将在程序执行时由加载器转换为真实地址。

实际的入口点不太可能,main而是 crt 中调用 main 的某个符号。LD 默认情况下会查找符号,start除非您指定不同的内容

链接的代码最终出现在.text可执行文件的部分中,可能看起来像这样(非常简单):

Address | Code
1000      someFunction
...
2000      start
2001        call 3000
...
3000      main
...
Run Code Online (Sandbox Code Playgroud)

当链接器写入 ELF 头时,它将指定入口点为地址 2000。

main您可以通过使用类似 的内容转储可执行文件的内容来获取 的相对地址objdump。要在运行时获取实际地址,您只需读取符号,funcptr ptr = main;其中funcptr定义为指向签名为 的函数的指针main

typedef int (*funcptr)(int argc, char* argv[]);

int main(int argc, char* argv[])
{
    funcptr ptr = main;
    printf("%p\n", ptr);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

无论符号是否被剥离,main 的地址都将被正确解析,因为链接器将首先将符号解析main为其相对地址。

像这样使用 objdump:

$ 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
Run Code Online (Sandbox Code Playgroud)

具体寻找main,在我的机器上我得到这个:

$ 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>:
Run Code Online (Sandbox Code Playgroud)

请注意,我在 Windows 上使用 Cygwin,因此您的结果会略有不同。它看起来对我来说就像main生活00401170