opt: undefined symbol when load

0. 问题描述

跟着教程写第一个llvm pass的时候,在opt load动态库的时候遇到了下面的报错

$ opt -load ./libLLVMmypass.so 
Error opening './libLLVMmypass.so': ./libLLVMmypass.so: undefined symbol: _ZTIN4llvm12FunctionPassE
  -load request ignored.
 
$ c++filt _ZTIN4llvm12FunctionPassE
typeinfo for llvm::FunctionPass

报错的原因是动态链接器没有找到typeinfo for llvm::FunctionPass这个类的定义。为了理解这个类,我们需要一些背景。

1. rtti in c++

C++里的dynamic_casttypeid运算符使用到了RTTI(run-time type identification),用于在运行时动态获取变量的类型信息。typeid返回的是一个具有static storage duration作用域的std::type_info类的引用,C++中每个类型都至少有一个对应的type_info类(可能会存在多个,考虑模板+动态库的情形,主程序实例化头文件中的某个模板类,因此主程序中有一个type_info,主程序再load一个动态库,该动态库也用同样的方法实例化了该头文件中的同一个模板类,因此该动态库中也存在对应同一个类的type_info)。

注意不要把rtti与多态搞混了,从No RTTI but still virtual methods可以看出,在没有rrti的情况下,vtable也会正常工作。

另外从文档中可以看出,异常处理也貌似依赖于rtti,不过这部分我从来没用过,就暂时不讨论了。

2. 问题解答

gcc中关于-fno-rtti的论述如下:

-fno-rtti
Disable generation of information about every class with virtual functions for use by the C++ run-time type identification features (“dynamic_cast” and “typeid”). If you don’t use those parts of the language, you can save some space by using this flag. Note that exception handling uses the same information, but G++ generates it as needed. The “dynamic_cast” operator can still be used for casts that do not require run-time type information, i.e. casts to “void *” or to unambiguous base classes.
Mixing code compiled with -frtti with that compiled with -fno-rtti may not work. For example, programs may fail to link if a class compiled with -fno-rtti is used as a base for a class compiled with -frtti.

最后一段解释了问题所在,表明我编译LLVM时没有保留rtti的信息。查询文档发现

LLVM_ENABLE_RTTI:BOOL
Build LLVM with run-time type information. Defaults to OFF.

这下找到了问题的根源。在LLVMConfig.cmake定义了LLVM_ENABLE_RTTI来表明LLVM是否包含RTTI信息。因此在cmake中可以这样写

if(NOT LLVM_ENABLE_RTTI)
target_compile_options(${mypass} PRIVATE "-fno-rtti")
endif()

3. 其它可能出问题的地方

通常编译LLVM时我们会设置LLVM_BUILD_LLVM_DYLIB=ON来得到一个包含所有符号的LLVM动态库,但还有一个重要的设置是LLVM_LINK_LLVM_DYLIB,这个变量控制生成的二进制工具是与各个components静态链接还是与这个大的LLVM动态库进行动态链接。

如果没有设置LLVM_LINK_LLVM_DYLIBldd opt会发现opt并不依赖于任何llvm相关的库(因为是静态链接的)。这时候在编译自己的pass的时候,就不要链接任何LLVM的库了(因为opt中已经静态链接过一次了),否则会得到类似于下面的报错

: CommandLine Error: Option 'help-list' registered more than once!
LLVM ERROR: inconsistency in registered CommandLine options
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值