assembly – 链接器如何找到main函数?

链接器如何在x86-64 ELF格式的可执行文件中找到main函数? 最佳答案 这是一个非常通用的概述,链接器将地址分配给符号main标识的代码块.就像对象文件中的所有符号一样.

实际上,它并没有分配一个真实的地址,而是分配一个相对于某个base的地址,当执行程序时,它将被加载器转换为一个真实的地址.

实际的入口点可能不是主要的,而是在crt中调用main的一些符号.除非您指定something different,否则默认情况下LD会查找符号start.

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

Address | Code
1000      someFunction
...
2000      start
2001        call 3000
...
3000      main
...

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

您可以通过使用objdump等转储可执行文件的内容来获取main的相对地址.要在运行时获取实际地址,您只需读取符号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;
}

无论是否已剥离符号,都将正确解析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

特别寻找主要,在我的机器上,我得到这个:

$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,因此您的结果会略有不同.它看起来像00401170的主要生活对我来说.

点赞