有没有一种“简单”的方法可以让 ld 输出解离功能名称?

Is there a "simple" way to have ld output demangled funtion names?

提问人:Javier Vilarroig 提问时间:9/29/2020 最后编辑:Akib Azmain TurjaJavier Vilarroig 更新时间:10/8/2020 访问量:2372

问:

我发现必须修复在链接时发生的 C++ 错误(尤其是未定义的引用错误)非常令人沮丧,因为所有函数名称都被破坏了。一个被破坏的名字的例子:

_ZNK5boost7archive6detail11oserializerINS0_13text_oarchiveEN9galandria8UniverseEE16save_object_dataERNS1_14basic_oarchiveEPKv

它很难阅读,找到实际功能更难。

有没有办法说服输出分离的名字?ld

C C++-常见问题

评论

0赞 Adrian Mole 9/29/2020
如果你去破坏函数名称,那么你实际上是在破坏 C++ ...它的主要功能之一是能够对函数进行不同的重载,这依赖于名称修改。
0赞 cigien 9/29/2020
你试过吗?c++filt
0赞 Javier Vilarroig 9/29/2020
我的意思是,在错误消息中。必须找到_ZNK5boost7archive6detail11oserializerINS0_13text_oarchiveEN9galandria8UniverseEE16save_object_dataERNS1_14basic_oarchiveEPKv的东西可能会变得非常困难。
4赞 cigien 9/29/2020
添加怎么样?这可能会有所帮助。--demangle
1赞 Marek R 9/29/2020
关于 --demangle 的 ld 文档These options control whether to demangle symbol names in error messages and other output.

答:

0赞 Richard 9/29/2020 #1

我以两种方式处理这些问题:

  1. 该命令使事物变得混乱。c++filt

  2. 有时使用 clang 而不是 gcc 进行编译,反之亦然,可以深入了解编译问题。

不幸的是,我不确定是否可以直接从链接器获得解耦输出:-(

评论

0赞 Javier Vilarroig 9/29/2020
是的。我同意。只是我发现 c++filt 太手动了。我希望 ld 能够消除错误消息,但我无法得到它。
3赞 Swift - Friday Pie 9/29/2020
链接器不能这样做,这些名称是它从 ELF 文件输入的内容
0赞 Akib Azmain Turja 10/8/2020
@Swift-FridayPie:为什么?诚然,链接器的名称被破坏了,但它会进行一些处理来解开它。
0赞 Swift - Friday Pie 10/8/2020
@AkibAzmain并非所有实现。关键字是,如果编译器已知且兼容,它会尝试提供可读的输出。对于链接,它不是必需的。这就是修改的原因 - 为所有重载函数和嵌套变量\members 提供唯一的名称,因此链接器可以只将字符串关联到字符串。ELF 格式与语言无关,并且假设两个具有不同单位全局链接的相等符号引用同一实体。
2赞 Akib Azmain Turja 9/30/2020 #2

ld(GNU 链接器)能够解解 C++ 函数名称。 有关demangling的文档,来自它的页面:(可在此处在线获得)ldman

       --demangle[=style]
       --no-demangle
           These options control whether to demangle symbol names in error
           messages and other output.  When the linker is told to demangle,
           it tries to present symbol names in a readable fashion: it strips
           leading underscores if they are used by the object file format,
           and converts C++ mangled symbol names into user readable names.
           Different compilers have different mangling styles.  The optional
           demangling style argument can be used to choose an appropriate
           demangling style for your compiler.  The linker will demangle by
           default unless the environment variable COLLECT_NO_DEMANGLE is
           set.  These options may be used to override the default.

让我们看一个例子:

void foo();
void foo(int);
int main() {
    foo();
    foo(5);
}

这是一个简单有效的代码。这将编译但无法成功链接,因为这里没有 和 的实现。现在我们将使用以下命令编译它:foo()foo(int)

g++ main.cpp -c -o main.o

它将成功编译。现在,让我们尝试使用以下命令将其与禁用的 demangling 链接:

g++ main.o -Wl,--no-demangle

它应该显示一些奇怪的损坏名称的链接错误,如下所示:

main.o: In function `main':
main.cpp:(.text+0x5): undefined reference to `_Z3foov'
main.cpp:(.text+0xf): undefined reference to `_Z3fooi'
collect2: error: ld returned 1 exit status

在 Coliru 上观看直播

现在,让我们尝试使用以下命令进行链接,并启用解构:

g++ main.o -Wl,--demangle

我们将得到带有如下参数的解散函数名称的错误:

main.o: In function `main':
main.cpp:(.text+0x5): undefined reference to `foo()'
main.cpp:(.text+0xf): undefined reference to `foo(int)'
collect2: error: ld returned 1 exit status

在 Coliru 上观看直播

这里表示链接器的参数。-Wl

据我所知,可以自动进行去线。g++