为什么 _main 不总是第一个过程?

问题描述 投票:0回答:3

我使用

Apple clang version 14.0.0 (clang-1400.0.29.202)
在运行 macOS 13.2.1 的 M1(即 ARM)Mac 上编译了 curl,并使用

反汇编了生成的可执行文件
objdump -D --macho ./src/curl

我看到的第一行是

/Users/space/code/third-party/curl/src/curl:
(__TEXT,__text) section
_slist_wc_append:
100003924:      ff c3 00 d1     sub     sp, sp, #48
100003928:      fd 7b 02 a9     stp     x29, x30, [sp, #32]
10000392c:      fd 83 00 91     add     x29, sp, #32
100003930:      e0 0b 00 f9     str     x0, [sp, #16]
100003934:      e1 07 00 f9     str     x1, [sp, #8]
100003938:      e1 07 40 f9     ldr     x1, [sp, #8]
10000393c:      00 00 80 d2     mov     x0, #0
100003940:      8e 66 02 94     bl      _curl_slist_append
[...]

_main
直到字节
1000147b4
才出现(反汇编中的第 17388 行)。
slist_wc_append()
与 curl 的
--libcurl
参数有关,这导致它也生成 C 代码,发出与它发出的相同的网络请求并将其保存到文件中,为什么它是可执行文件中的第一个过程?

我期望可执行文件总是从第一条指令开始执行,并且它将是

_main
的第一条指令。我反汇编了 CPython 和 Bash,他们这样做了。操作系统是否在符号表中查找
_main
的位置并在执行之前将堆栈指针设置为该位置?我已经看到可以告诉汇编程序使用不同的名称而不是
_main
.global _different_name
。 curl 在调用
_main
之前做了什么特别的事情吗?

c assembly compilation arm
3个回答
2
投票

在 macOS 上,Mach-O 文件的

eip
字段用于设置指令指针。

https://github.com/corkami/pics/blob/master/binary/macho101/macho101-64.pdf

ELF on Linux 也有类似的

e_entry
字段

https://github.com/corkami/pics/blob/master/binary/elf101/elf101-64.pdf


1
投票

启动程序要复杂得多。操作系统将文件加载到内存中,做很多其他事情(比如重新定位地址,确保动态加载的库不会有任何地址冲突等)并最终将控制权传递给你的程序。但它不是

main
功能;它通常是别的东西,称为启动代码。它准备环境、初始化变量并执行调用
main
函数所需的所有必要操作,该函数是程序的启动点。


1
投票

在将控制转移到程序入口点时,操作系统不一定遵循标准调用约定。此外,入口点不是一个函数——它没有被“调用”,也不能“返回”给它的调用者,因为没有函数——所以程序入口点有点特殊,它的主要目的是开始正常的函数调用,即与

main
.

所以,

_start
是入口点的通用名称,它的工作是调用
main
作为函数,并在必要时终止可执行文件(通过一些系统调用),如果函数
main
返回。

为什么 _main 不总是第一个过程?

它可以是第一个过程/功能,但在调用

main
之前可能不是由于其他要求。在任何情况下
_start
不是真正的程序,因此不能作为第一个程序/功能。

© www.soinside.com 2019 - 2024. All rights reserved.