链接器如何找到主函数? [英] How does the linker find the main function?

查看:27
本文介绍了链接器如何找到主函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

链接器如何在 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆