因为科研,我编译了github项目seahorn,在最后一步linker的时候,出现undefined reference
[build] [ 98%] Built target SeaDsaAnalysis
[build] [ 98%] Linking CXX executable ../../bin/seapp
[build] ../../lib/libSeaTransformsScalar.a(PromoteVerifierCalls.cc.o): In function ‘seahorn::PromoteVerifierCalls::runOnFunction(llvm::Function&)':
[build] PromoteVerifierCalls.cc:(.text._ZN7seahorn20PromoteVerifierCalls13runOnFunctionERN4llvm8FunctionE+0x925): undefined reference to ’seahorn::isPartialFn(llvm::Function const&)'
[build] clang: error: linker command failed with exit code 1 (use -v to see invocation)
..
[build] make: *** [seapp] Error 2
[build] Build finished with exit code 2
我最后链接的是可执行文件是seapp
,他需要若干个静态库,其中一个就是libSeaTransformsScalar.a
。文件PromoteVerifierCalls
是该库中的一个,需要调用另外一个静态libSeaInstrumentation.a
的GeneratePartialFnPass.c
文件,未定义的函数isPartialFn
就在GeneratePartialFnPass
中。
其中,另外一个可执行文件seahorn
也是如此配置(依赖相同的静态库),他就可以成功链接(没有调用到函数isPartialFn
)。
还有一个奇怪的现象,我使用nm fine.a
查看库的接口,出现了许多奇怪的信息。如下
运行 nm libSeaInstrumentation
...
GeneratePartialFnPass.cc.o:
0000000000000000 V _ZN4llvm30VerifyDisableABIBreakingChecksE
0000000000000000 T _ZN4llvm35initializeGeneratePartialFnPassPassERNS_12PassRegistryE
0000000000000000 W _ZN4llvm4Pass14doFinalizationERNS_6ModuleE
0000000000000000 W _ZN4llvm4Pass16doInitializationERNS_6ModuleE
0000000000000000 W _ZN4llvm8CallInst6CreateEPNS_12FunctionTypeEPNS_5ValueENS_8ArrayRefIS4_EENS5_INS_17OperandBundleDefTIS4_EEEERKNS_5TwineEPNS_11InstructionE
自信看,出现了很多前缀。
我查看别的项目的lib,人家就是这样的
free_var_collector.o:
U _GLOBAL_OFFSET_TABLE_
U alloc_pstack_array
0000000000000b50 T cleanup_fvar_collector
00000000000000c0 T delete_fvar_collector
U delete_harray_store
U delete_pstack
U delete_ptr_hmap
U free_pstack_array
0000000000000020 t fvar_dead_harray
0000000000000000 t fvar_dead_hmap_pair
0000000000000100 T get_free_vars_of_term
U harray_remove_elem
0000000000000090 T init_fvar_collector
我的问题出在哪里了?
附件
seapp 的CMakeLists.txt
set (USED_LIBS
SeaInstrumentation 被引用的库
SeaTransformsScalar 这里出问题了
SeaTransformsUtils
SeaAnalysis
SeaSmt
${SEA_DSA_LIBS}
SeaSupport
${LLVM_SEAHORN_LIBS}
${Boost_SYSTEM_LIBRARY}
SeaLlvmIpo
${GMP_LIB}
${RT_LIB}
)
set(LLVM_LINK_COMPONENTS
BitWriter
IRReader
IPO
ScalarOpts
Instrumentation
Core
# XXX not clear why these last two are required
CodeGen
ObjCARCOpts)
add_llvm_executable(seapp DISABLE_LLVM_LINK_LLVM_DYLIB seapp.cc)
target_link_libraries (seapp PRIVATE ${USED_LIBS})
llvm_config (seapp ${LLVM_LINK_COMPONENTS})
install(TARGETS seapp RUNTIME DESTINATION bin)
if (SEAHORN_STATIC_EXE)
set (CMAKE_EXE_LINKER_FLAGS "-static -static-libgcc -static-libstdc++")
set_target_properties (seapp PROPERTIES LINK_SEARCH_START_STATIC ON)
set_target_properties (seapp PROPERTIES LINK_SEARCH_END_STATIC ON)
endif()
编辑libSeaTransformsScalar的CMakeLists.txt
add_llvm_library (SeaTransformsScalar DISABLE_LLVM_LINK_LLVM_DYLIB
..
LowerLibCxxAbiFunctions.cc
PromoteVerifierCalls.cc 这个文件中引用了isPartialFn
CutLoops.cc
PromoteMalloc.cc
..
)
被引用的SeaInstrumentation 的CMakeLists.txt
add_llvm_library(SeaInstrumentation DISABLE_LLVM_LINK_LLVM_DYLIB
...
BranchSentinelPass.cc
GeneratePartialFnPass.cc 这里定义了isPartialFn
)
你的库有前缀是因为函数重载,用g++编译时,符号表中除了函数名,还有返回类型和参数类型;而别人的库是gcc编译的,C语言没有函数重载,符号表中只有函数名。你在调别人的头文件时,加上extern "C"试试。