You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何Clang/lld无法找到__dlopen、__dlclose和__dlsym符号?

问题描述

我正在编译一个面向旧版Linux系统的C/C++项目,为获取目标系统的旧版库,复制了目标系统的根文件系统。由于GCC库路径是硬编码的,无法直接针对旧版libc交叉编译,因此选择Clang + lld,但链接阶段出现以下错误:

[ 71%] Linking CXX executable single_lidar_listener
Ubuntu clang version 14.0.0-1ubuntu1.1
Target: arm-unknown-linux-gnueabihf
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /home/abertulli/box-root-inst/usr/lib/gcc/arm-linux-gnueabihf/6
Found candidate GCC installation: /home/abertulli/box-root-inst/usr/lib/gcc/arm-linux-gnueabihf/6.3.0
Selected GCC installation: /home/abertulli/box-root-inst/usr/lib/gcc/arm-linux-gnueabihf/6.3.0
Candidate multilib: .;@m32
Selected multilib: .;@m32
 "/usr/bin/ld.lld" --sysroot=/home/abertulli/box-root-inst -pie -EL -z relro -X --hash-style=gnu --build-id --eh-frame-hdr -m armelf_linux_eabi -dynamic-linker /lib/ld-linux-armhf.so.3 -o single_lidar_listener /home/abertulli/box-root-inst/usr/lib/arm-linux-gnueabihf/Scrt1.o /home/abertulli/box-root-inst/usr/lib/arm-linux-gnueabihf/crti.o /home/abertulli/box-root-inst/usr/lib/gcc/arm-linux-gnueabihf/6.3.0/crtbeginS.o -L/home/abertulli/box-root-inst/usr/lib/gcc/arm-linux-gnueabihf/6.3.0 -L/home/abertulli/box-root-inst/usr/lib/gcc/arm-linux-gnueabihf/6.3.0/../../../../lib -L/home/abertulli/box-root-inst/lib/arm-linux-gnueabihf -L/home/abertulli/box-root-inst/lib/../lib -L/home/abertulli/box-root-inst/usr/lib/arm-linux-gnueabihf -L/home/abertulli/box-root-inst/usr/lib/../lib -L/home/abertulli/box-root-inst/lib -L/home/abertulli/box-root-inst/usr/lib CMakeFiles/single_lidar_listener.dir/single_lidar.cpp.o CMakeFiles/single_lidar_listener.dir/sick_scan_xd_api_wrapper.c.o libtoojpeg.a -ldl -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /home/abertulli/box-root-inst/usr/lib/gcc/arm-linux-gnueabihf/6.3.0/crtendS.o /home/abertulli/box-root-inst/usr/lib/arm-linux-gnueabihf/crtn.o
ld.lld: error: undefined symbol: __dlopen
>>> referenced by dlopen.o:(dlopen) in archive /home/abertulli/box-root-inst/usr/lib/arm-linux-gnueabihf/libdl.a

ld.lld: error: undefined symbol: __dlclose
>>> referenced by dlclose.o:(.text+0x0) in archive /home/abertulli/box-root-inst/usr/lib/arm-linux-gnueabihf/libdl.a

ld.lld: error: undefined symbol: __dlsym
>>> referenced by dlsym.o:(dlsym) in archive /home/abertulli/box-root-inst/usr/lib/arm-linux-gnueabihf/libdl.a
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make[2]: *** [CMakeFiles/single_lidar_listener.dir/build.make:114: single_lidar_listener] Error 1
make[1]: *** [CMakeFiles/Makefile2:113: CMakeFiles/single_lidar_listener.dir/all] Error 2
make: *** [Makefile:91: all] Error 2

分析目标根文件系统中的libc.a后,确认__dlopen、__dlclose、__dlsym符号确实存在,但Clang/lld无法找到。已设置sysroot,且GCC安装路径正确(基于目标根文件系统)。附上我的toolchain文件:

# the name of the target operating system
set(CMAKE_SYSTEM_NAME Linux)

include(CMakePrintHelpers)
cmake_print_variables(CMAKE_DL_LIBS)

# where is the target environment located
set(root_fs_dir /home/abertulli/box-root-inst)

set(CMAKE_FIND_ROOT_PATH ${root_fs_dir})
set(CMAKE_SYSROOT ${root_fs_dir})


# which compilers to use for C and C++
set(CMAKE_C_COMPILER   "clang")
set(CMAKE_CXX_COMPILER "clang++")

set(CMAKE_LINKER       "ld.lld")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=lld -v")
set(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   --gcc-toolchain=${CMAKE_SYSROOT}/usr")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} --gcc-toolchain=${CMAKE_SYSROOT}/usr")

set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) # to avoid trying to link and execute test programs
set(CMAKE_C_COMPILER_TARGET   arm-unknown-linux-gnueabihf)
set(CMAKE_CXX_COMPILER_TARGET arm-unknown-linux-gnueabihf)


# adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)

# search headers and libraries in the target environment
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
解决方案分析
  • 调整链接库顺序:从链接命令可见,-ldl位于-lc之前,但libdl.a中的符号依赖libc.a的实现。lld按顺序解析库,先处理-ldl时无法找到依赖符号,需将-ldl移至-lc之后。可通过修改CMake的target_link_libraries顺序,或直接在CMAKE_EXE_LINKER_FLAGS中调整库的位置。
  • 修正GCC工具链路径:--gcc-toolchain参数应指向完整的交叉编译工具链根目录,而非/usr子目录。将toolchain文件中的--gcc-toolchain=${CMAKE_SYSROOT}/usr改为--gcc-toolchain=${root_fs_dir},确保Clang能正确识别完整工具链组件。
  • 强制链接库成员:临时方案可添加-Wl,--no-as-needed到链接flags中,强制lld包含libdl.a的所有成员,避免因符号未被提前引用而被忽略,但优先推荐调整库顺序。
  • 验证库版本兼容性:用arm-linux-gnueabihf-nm工具检查libc.a中的符号名称是否与libdl.a的引用完全匹配(注意下划线数量差异,部分旧版本可能为_dlopen而非__dlopen),同时确认libdl.a与libc.a为同一版本编译,避免版本不匹配导致的符号问题。

内容的提问来源于stack exchange,提问作者Alessandro Bertulli

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 21:25:55