Linker 为什么clang从声明为';的函数中删除下划线;“外部”;"';?

Linker 为什么clang从声明为';的函数中删除下划线;“外部”;"';?,linker,clang++,Linker,Clang++,我正在观看,试图更好地理解对象文件。演示者将以下内容用作生成非常简单的对象文件的程序示例: extern "C" void _start() { asm("mov $60, %eax\n" "mov $24567837, %edi\n" "syscall\n"); } 该程序是通过 clang++ -c step0.cpp -O1 -o step0.o 并通过 ld -static step0.o -o step0 我在尝试链接时收到此错误消息: U

我正在观看,试图更好地理解对象文件。演示者将以下内容用作生成非常简单的对象文件的程序示例:

extern "C" void _start() {
    asm("mov $60, %eax\n"
        "mov $24567837, %edi\n"
        "syscall\n");
}
该程序是通过

clang++ -c step0.cpp -O1 -o step0.o
并通过

ld -static step0.o -o step0
我在尝试链接时收到此错误消息:

Undefined symbols for architecture x86_64:
  "start", referenced from:
     -u command line option
     (maybe you meant: __start)
ld: symbol(s) not found for inferred architecture x86_64

我没有传递-u命令行选项,因此我不确定为什么会收到该错误消息。

clang不是删除下划线,而是添加下划线。您的程序实际上正在导出一个
\u start
符号,但ld希望您的入口点有一个
start
符号,即默认情况下,对于您的体系结构,ld使用
-u start
运行

您可以使用
-U start
(抑制未定义的
start
符号引起的错误)或通过
-undefined suppress
(抑制所有未定义的符号错误)禁用此签入ld。但是,您最终会得到一个没有体系结构入口点的可执行文件,因此该程序实际上无法工作

与其抑制错误,我建议控制clang直接选择的符号。通过使用独立的
asm
声明,您可以告诉clang要生成的符号:

void _start() asm ("start");
确保此独立声明与函数定义分开

您可以在此处阅读有关控制gcc生成的符号的更多信息:

此外,正如在对类似答案的评论中所指出的,您很可能希望在函数定义上使用
\uuuu attribute\uuuu((裸))
,以防止clang在条目上生成堆栈帧。见: