assembly - 链接器如何找到主函数?

标签 assembly x86 x86-64

链接器如何在 x86-64 ELF 格式的可执行文件中找到 main 函数?

最佳答案

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

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

实际切入点不太可能main但是crt中的一些符号调用main。 LD 默认查找符号 start除非您指定 something different .

链接代码以 .text 结尾。可执行文件的部分,可能看起来像这样(非常简化):

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

当链接器写入 ELF header 时,它会将入口点指定为地址 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;
}

无论符号是否被剥离,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

寻找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>:

请注意,我在 Windows 上使用 Cygwin,因此您的结果会略有不同。看起来像 main住在 00401170为了我。

关于assembly - 链接器如何找到主函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17708649/

相关文章:

linux - 程序使用 gdb 运行但不使用 ./ProgramName 运行

compiler-construction - 给定一个指令地址,能否确定包含它的函数的起始地址?

assembly - 通过 USB 驱动器启动的自定义引导加载程序在某些计算机上产生不正确的输出

linux - 在 64 位操作系统上开发有什么优势吗?

x86 - 引用 x86 相关 CPU 的 32 位和 64 位版本程序的最正确方法是什么?

assembly - x86-64上的红色区域到底在哪里?

arrays - NASM x86 16 位中的索引 float 组

c++ - 调试程序集时,如何在 VS2019 watch 窗口中将内存地址转换为用户定义的类型?

c++ - shufps 比内存访问慢吗?

c - gcc 8.2+ 在调用 x86 之前并不总是对齐堆栈?