链接和名称篡改是如何工作的

How does linkage and name mangling work?

本文关键字:何工作 工作 链接      更新时间:2023-10-16

让我们取这个代码示例

//header
struct A { };
struct B { };
struct C { };
extern C c;
//code
A myfunc(B&b){ A a; return a; }
void myfunc(B&b, C&c){}
C c;

让我们从代码部分开始逐行执行此操作。当编译器看到第一个myfunc方法时,它不关心A或B,因为它的使用是内部的。每个c++文件都会知道它接收了什么,返回了什么。虽然两个重载中的每一个都需要有一个名称,但如何选择,链接器如何知道哪个是什么意思?其次是C C;我曾经有一个错误,链接器无法重新配置,因此允许我访问其他C++文件中的C。这是因为cpp不知道c是extern,我必须在标题中将它标记为extern,然后才能成功链接。现在我不确定类类型是否与链接器和变量C有关。我不知道RTTI将如何涉及,但我知道C需要被其他文件可见。

链接器是如何工作的以及名称篡改等等。

我们首先需要了解编译结束和链接开始的位置。编译包括获取一个编译单元(一个C或C++源文件)并将其转换为一个对象文件。简单地说,这包括为每个函数生成机器代码片段,以及为所有函数和静态(全局)变量生成符号表。占位符用于编译单元所需的在所述编译单元外部的任何符号。

然后,链接器负责加载所有对象文件,并解析具有实际地址(或机器独立代码的偏移量)的所有占位符符号。它被放置在操作系统的动态加载程序在加载可执行文件时可以读取的各个部分中。

具体情况也是如此。为了避免链接过程中出现错误,编译器要求您声明当前编译单元将使用的所有外部符号。对于全局变量,必须使用extern关键字,对于函数,这是可选的。

编译单元中定义的所有函数和全局变量都有外部链接(即,可以被其他编译单元引用),除非用static关键字(或C++中未命名的命名空间)声明。在C++中,vtable还将具有链接所需的符号。

现在在C++中,由于函数可以重载,因此参数也构成了函数名称的一部分。由于机器代码只是地址和寄存器,因此需要在符号表中的函数名称中添加额外的信息。这些额外的参数信息以损坏的名称的形式出现,并确保链接器链接到重载函数的正确版本。

如果你真的对血腥的细节感兴趣,可以看看Linux上广泛使用的ELF文件格式(PDF)。Windows有不同的格式,但原理可以预期是相同的。Itanuim(和ARM)平台上的名称篡改可以在这里找到。

http://en.wikipedia.org/wiki/Name_mangling