为什么我们不编写可以处理C++标识符的汇编器和链接器?



我对为什么我们使用名称重整的理解是汇编器和链接器只能处理C标识符。 "int foo::bar::baz<spam::eggs>(const MoreSpam&)"不能被任何现有的汇编器用作标签,现有的链接器也不会将其识别为有效的函数签名,所以它变成了类似于"_ZN3foo3bar3bazIN4spam4eggsEEEiRK8MoreSpam"的东西,它(或多或少(是一个有效的C标识符。

但这似乎是我们工具的一个相对微不足道的限制。有什么很好的理由为什么我们不能或不编写一个汇编器和链接器,其中像这样的东西:

int foo::bar::baz<spam::eggs>(MoreSpam const&):
; opcodes go here
ret

很好,允许吗?

您实际上可以使用int foo::bar::baz<spam::eggs>(const MoreSpam&)作为 GNU 汇编程序的标识符,您只需要将名称放在引号中:

"int foo::bar::baz<spam::eggs>(MoreSpam const&)":
ret
$ as -o test.o test.s
$ nm test.o
0000000000000000 t int foo::bar::baz<spam::eggs>(MoreSpam const&)
$ ld test.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
$ nm a.out
0000000000402000 T __bss_start
0000000000402000 T _edata
0000000000402000 T _end
0000000000401000 t int foo::bar::baz<spam::eggs>(MoreSpam const&)
U _start

这样做的一个问题是,除了在很多上下文中处理带有空格和符号的符号很痛苦之外,并非所有C++损坏的标识符都可以明确地表示为C++源片段。同一C++"符号"可以有多个损坏的表示,一些损坏的符号没有C++表示。

例如,GNU C++编译器使用的 Itanium C++ ABI 定义了 5 种不同的方法来修改同一构造函数的名称,具体取决于编译器生成的构造函数变体。 同样,有三种不同的方法来破坏给定析构函数的名称。 符号_ZN3fooC1Ev_ZN3fooC2Ev都像foo::foo()一样解散,并且都可以存在于同一个程序中。

当然,你可以发明新的类似C++的语法来表示这些东西,但你只是发明了更冗长的符号处理方式。

最后,也许C++编译器以这种方式修改名称的最重要原因是他们可以使用各种工具。 虽然它今天不太常见,但 GNU C++编译器可以与 GAS 以外的汇编器一起使用。

最新更新