动态库加载时出现 Undefined Symbol 的排查思路
本文记录加载动态库时遇到 undefined symbol 问题的排查思路
问题1
问题背景:
非英伟达镜像使用 cmake 编译 FasterTransformer
调用链
1 |
|
第一步先 c++filt 看这个符号 demangle 后的是什么,得到fastertransformer::TensorMap::TensorMap(std::initializer_list<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, fastertransformer::Tensor> >)
去代码找,发现这块代码编译后的打包路径是 libtensor.a -> libth_utils.a -> libth_transformer.so
用 nm 找下这个 TensorMap 相关的函数签名
1 |
|
U 意味着这个符号 unsolved
grep initializer_list
看下,发现一个相似的符号_ZN17fastertransformer9TensorMapC1ESt16initializer_listISt4pairINSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEENS_6TensorEEE
demangle 出来是 fastertransformer::TensorMap::TensorMap(std::initializer_list<std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, fastertransformer::Tensor> >)
函数签名上差了一个 __cxx11
,说明是 ABI 问题,全局搜 ABI 相关的编译选项,在根目录的 CMakeLists.txt 发现这么一段
1 |
|
想到可能是没有设置 -DCMAKE_BUILD_TYPE=Release 导致的,设置完毕后问题解决
问题2
问题背景:
非英伟达镜像使用 bazel 编译 FasterTransformer
调用链
1 |
|
demangle 出来是fastertransformer::MoeGemmRunner<__half, cutlass::integer_subbyte<4, false> >::moe_gemm(__half const*, cutlass::integer_subbyte<4, false> const*, __half const*, __half*, long*, long, long, long, int, CUstream_st*)
排查步骤类似,区别在于 nm -D grep moe_gemm
相似的只有fastertransformer::MoeGemmRunner<__half, __half>::moe_gemm(__half const*, __half const*, __half const*, __half*, long*, long, long, long, int, CUstream_st*)
想到编译时没有把所有数据类型的 gemm 文件都编译进去,加上后解决
思考
- 动态库依赖静态库是否会将符号加入到动态库中?
会 - 动态库A依赖动态库B是否会将符号加入到动态库中?
只会包含 A 直接调 B 的部分,并且 nm -D A 这部分也是 unsolved 的 - FT cmake 中大部分的 add_library 都产出静态库,只有暴露给外部使用的是动态库,也有少数 add_library 产出动态库,为什么这么做
不知道,有空补充 - A.so 依赖 B.so 中的函数 f,在 C++ 中调用 A 的函数,执行到 f 调用时,会报什么错误
应该是类似shared library not found
的问题,而不是本文的 undefined symbol,换句话说本文得到的两个思路,一个是需要 check 是否相关的 src 文件被加入编译,另一个是需要 check 是否有 ABI 不一致的问题
Question: nm -D 是看动态库的,静态库符号怎么看
nm -gC -S libyourlibrary.a