【问题标题】:Name mangling confusion in LLVMLLVM 中的命名混淆
【发布时间】:2017-02-03 17:25:47
【问题描述】:

我一直在尝试构建和执行 LLVM 模块。我生成模块的代码很长,所以我不会在这里发布。相反,我的问题是关于 Clang 和 LLVM 如何协同工作以实现名称修改。我将解释我的具体问题以激发问题。

这是我的 LLVM 模块之一的源代码:

#include <iostream>

int main() {
  std::cout << "Hello, world. " << std::endl;
  return 0;
}

Here is the generated LLVM IR;对于 StackOverflow 来说太大了。

当我尝试使用lli 执行我的模块时,我收到以下错误:

LLVM ERROR: Program used external function '__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc' which could not be resolved!

通过 demangler 运行符号,缺少的符号是:

_std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string(unsigned long, char)

多余的_很可疑,IR中好像存在没有前导下划线的函数!

; Function Attrs: alwaysinline ssp uwtable
define available_externally hidden void @_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc(%"class.std::__1::basic_string"*, i64, i8 signext) unnamed_addr #2 align 2 {
  %4 = alloca %"class.std::__1::basic_string"*, align 8
  %5 = alloca i64, align 8
  %6 = alloca i8, align 1
  store %"class.std::__1::basic_string"* %0, %"class.std::__1::basic_string"** %4, align 8
  store i64 %1, i64* %5, align 8
  store i8 %2, i8* %6, align 1
  %7 = load %"class.std::__1::basic_string"*, %"class.std::__1::basic_string"** %4, align 8
  %8 = load i64, i64* %5, align 8
  %9 = load i8, i8* %6, align 1
  call void @_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC2Emc(%"class.std::__1::basic_string"* %7, i64 %8, i8 signext %9)
  ret void
}

我在 macOS 上,因此可以预期前导下划线,但我认为 Clang 可能会添加它两次

我查看了 LLVM/Clang 源码,似乎有两个 mangling 步骤:

  1. 采用可能重载的 C++ 函数并将它们修改为 LLVM IR 的唯一名称
  2. 从 LLVM IR 中获取错误名称并添加任何特定于平台的怪癖,例如前导下划线

但是,这只是我的理论。有人可以解释一下 Clang 和 LLVM 中的重整过程是如何工作的吗?我应该如何创建我的 llvm::DataLayout 对象来为我的平台获得正确的修饰?


nm -gU /usr/lib/libc++.dylib` and `nm -gU /usr/lib/libc++abi.dylib` do not contain `__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorI‌​cEEEC1Emc

当我尝试编译 IR 时,我得到这个错误:

llc generated.ll
clang++ generated.s

Undefined symbols for architecture x86_64:
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::data() const", referenced from:
  std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > std::__1::__pad_and_output<char, std::__1::char_traits<char> >(std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> >, char const*, char const*, char const*, std::__1::ios_base&, char) in generated-b4252a.o
"std::__1::basic_ostream<char, std::__1::char_traits<char> >::sentry::operator bool() const", referenced from:
  std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in generated-b4252a.o
"std::__1::basic_ios<char, std::__1::char_traits<char> >::fill() const", referenced from:
  std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in generated-b4252a.o
"std::__1::basic_ios<char, std::__1::char_traits<char> >::rdbuf() const", referenced from:
  std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> >::ostreambuf_iterator(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) in generated-b4252a.o
"std::__1::basic_ios<char, std::__1::char_traits<char> >::widen(char) const", referenced from:
  std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::endl<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) in generated-b4252a.o
"std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::basic_string(unsigned long, char)", referenced from:
  std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> > std::__1::__pad_and_output<char, std::__1::char_traits<char> >(std::__1::ostreambuf_iterator<char, std::__1::char_traits<char> >, char const*, char const*, char const*, std::__1::ios_base&, char) in generated-b4252a.o
"std::__1::basic_ios<char, std::__1::char_traits<char> >::setstate(unsigned int)", referenced from:
  std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::__put_character_sequence<char, std::__1::char_traits<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, char const*, unsigned long) in generated-b4252a.o
ld: symbol(s) not found for architecture x86_64
clang-3.9: error: linker command failed with exit code 1 (use -v to see invocation)

【问题讨论】:

  • 我不认为这是一个名称修改问题。只要你不碰名字,你应该没问题。相反,这是一个链接问题。 lli 不链接任何库,因此无法解析 STL 符号。如果您编译并链接模块,您应该没问题... llc test.ll、clang++ test.s(或任何其他编译器)。让我知道这是否有帮助,我会将其添加为答案。
  • ...您是否使用 clang++ -S -emit-llvm 生成了 IR?以任何方式编辑文件?您是希望它运行还是想知道名称是如何被修改的 b/c 您想自己生成一个修改后的名称?
  • @Tobias 我使用clang::CreateLLVMCodeGen 工厂和HandleTopLevelDecl 生成了LLVM
  • @Tobias 我不相信这是一个链接问题,因为nm -gU /usr/lib/libc++.dylibnm -gU /usr/lib/libc++abi.dylib 不包含__ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc
  • @Tobias 我在使用llc 时遇到了类似的错误(请参阅上面的问题)。我的下一个最佳猜测是我的 LLVM IR 是针对错误的标准库生成的。

标签: c++ llvm llvm-ir lli


【解决方案1】:

我不会怀疑名称修改问题。 C++ 名称修改发生在前端(即clang),它是定义良好/记录良好的ABI standard 的一部分。

此外,我认为没有虚假的下划线,因为它不会返回有效的 C++ 名称,并且您提供的 pastebin 链接中的错误名称显示为:

_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEC1Emc

我不在 Mac OS 上,而是在 Linux 上使用我的 LLVM 3.8.1 进行模拟(使用 --stdlib=libc++),使用相同的源并逐行匹配 IR, 我得到以下符号:

_ZNSt3__112basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEE6__initEmc

哪一个 demangles 回到:

std::__1::basic_string&lt;char, std::__1::char_traits&lt;char&gt;, std::__1::allocator&lt;char&gt; &gt;::__init(unsigned long, char)

我猜这在某种结构上几乎是相同的。

所以,我认为您的链接器选择了错误的libc++ 版本。

您可以检查libc++ 中可用的符号,该符号与您正在使用的clang/LLVM 相关联,在llvm-config --libdir 给出的目录中找到,甚至可以使用readelf -d $(which lli) 检查工具链二进制文件的rpath 条目.

如果有多个 LLVM 安装(例如,您自己从源代码编译的一个系统和一个系统),您可能需要使用 clang-L 选项,它指示 ld 将该路径添加到它的搜索列表。 一个快速的替代方法(我不建议经常使用)是在命令行上执行此操作:

LD_LIBRARY_PATH=$(llvm-config --libdir) clang generated.s

【讨论】:

    猜你喜欢
    • 2015-06-01
    • 2012-09-06
    • 2017-12-07
    • 1970-01-01
    • 2015-10-12
    • 1970-01-01
    • 2012-03-29
    • 2014-04-14
    • 2011-03-07
    相关资源
    最近更新 更多