本文介绍了加载共享库时未定义的符号的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的程序中,我需要使用 dlopen() 动态加载共享库.程序和共享库都成功地为 ARM 架构交叉编译,交叉编译器安装在我的 x86 上.但是,每当程序尝试在 ARM 上运行时加载库时,它都会失败并给出以下错误:

In my program I need to load a shared library dynamically with dlopen(). Both the program and the shared library are successfully cross-compiled for an ARM architecture with the cross-compiler installed on my x86. However, whenever the program tries to load the library at run time on ARM, it fails giving this error:

未定义符号:_dl_hwcap

我找不到这个错误的罪魁祸首.

I cannot find the culprit of this error.

让我先详细说明共享库 (libmyplugin.so) 是如何构建在 x86 上的.我使用 g++ 交叉编译器如下:

Let me give details on how the shared library (libmyplugin.so) is built on x86 first. I use the g++ cross-compiler as below:

/home/me/arm/gcc-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ -march=armv7-a -mfloat-abi=hard -c -s -fPIC -o build/module1.o module1.cpp
/home/me/arm/gcc-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ -march=armv7-a -mfloat-abi=hard -c -s -fPIC -o build/module2.o module2.cpp
/home/me/arm/gcc-arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++ -o dist/libmyplugin.so build/module1.o build/module2.o --sysroot /home/me/arm/sysroot/ -Wl,--no-as-needed -ldl -lX11 -lXext /home/me/arm/libstatic.a -shared -s -fPIC

请注意以下注意事项:

  1. module1.cppmodule2.cpp 是我的源代码文件.
  2. libstatic.a 是一个大型的对象 .o 文件存档,实现了由 module1.cpp 直接调用/引用的东西>module2.cpp.这些目标文件已由其他人针对与我的 ARM 架构相同的 ARM 架构进行编译,使用相同的编译器标志,但使用稍微更新的 g++ 编译器(v4.9 而不是我的 v4.8.3).不幸的是,我无法控制这些对象的构建.
  3. --sysroot/home/me/arm/sysroot/ 代表我的 ARM OS 的远程文件系统,本地 g++ 从中交叉-compiler 可以在链接时获取本机库.
  4. -Wl,--no-as-needed -ldl -lX11 -lXext:需要这些标志来强制动态加载器加载现有的 X11 库程序加载我的共享库时的系统.特别是 --no-as-needed 是必需的,因为 X11 库不是由 module1.omodule2 直接引用的.o;相反,X11 库仅被静态库引用.
  1. module1.cpp and module2.cpp are my source code files.
  2. libstatic.a is a big archive of object .o files implementing the stuff directly invoked/referenced by module1.cpp and module2.cpp. These object files have been compiled by others for the same ARM architecture as mine, with the same compiler flags, but using a slightly more updated g++ compiler (v4.9 instead of my v4.8.3). Unfortunately, I have no control on the building of these objects.
  3. --sysroot /home/me/arm/sysroot/ represents the remote filesystem of my ARM OS from which the local g++ cross-compiler can take the native libraries while linking.
  4. -Wl,--no-as-needed -ldl -lX11 -lXext: these flags are required to force the dynamic loader to load the X11 libraries present on the system when my shared library is loaded by the program. In particular, --no-as-needed is required because the X11 libraries are NOT directly referenced by module1.o and module2.o; on the contrary the X11 libraries are referenced by the static library only.

请注意,以上所有设置都适用于 x86.只是我不明白当程序试图在 ARM 上加载库时,_dl_hwcap 符号未解析的原因是什么.

Note that all the above setup works on x86. It's just that I don't understand what is the reason of the _dl_hwcap symbol not resolved when the program tried to load the library on ARM.

您知道如何调查此问题吗?

Do you have any idea how to investigate this issue?

推荐答案

可能有很多问题,但这里有四种探索途径.我专注于您链接行中的 -shared ,但最后一项也解决了这个问题.(关于共享库的一个很好的 HOWTO 在这里:http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

There are a myriad of things that could be problematic, but here are four avenues of exploration. I am concentrating on the -shared in your link line, but the last item addresses that as well.(A nice HOWTO on shared libraries is here:http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

a) 检查您的环境变量 LD_LIBRARY_PATH.由于您没有对链接器使用 RPATH(RPATH 嵌入了 .so 的完整路径,因此您可以在运行时找到它),因此链接器可以找到您的代码的唯一方法是搜索 LD_LIBRARY_PATH.确保您想要的 .so 或 .0 在路径中.

a) Check your environment variable LD_LIBRARY_PATH. Since you aren't using RPATH to the linker (RPATH embeds a full path to the .so so you can find it at runtime), then the only way the linker can find your code is to search the LD_LIBRARY_PATH.Make sure the .so or .0 you want is in the path.

b) 使用 UNIX 实用程序nm"为该符号搜索 .so(共享对象)和 .a 文件.例如,'nm -D/usr/lib64/libpython2.6.so' 将显示所有动态符号在 libpython.so 中,您可以查找感兴趣的符号:例如,'initgc' 是在 libpython 中定义或使用的吗?

b) Use the UNIX utility 'nm' to search .so (shared objects) and .a files for that symbol. For example, 'nm -D /usr/lib64/libpython2.6.so' will show all dynamic symbolsin the libpython.so, and you can look for symbols of interest:For example, Is 'initgc' defined or used in libpython?

% nm -D /usr/lib64/libpython2.6.so | grep initgc
000003404300cf0 T initgc

'T' 表示文本,或者,是的,它在那里定义.查看是否可以使用 grep 和 nm 在感兴趣的模块中找到符号.(U"表示未定义,这意味着它是在另一个模块中定义的).

The 'T' means TEXT or, yes, it is defined there. See if you can find the symbol in the module of interest using grep and nm. (A 'U' means undefined, which means it is defined in another module).

c) 另一个有用的工具是ldd".它显示了您正在查看的库所依赖的所有动态库.例如:

c) Another useful tool is 'ldd'. It shows all dynamic libraries that the library you are looking on depends on. For example:

% ldd /usr/lib64/libpython2.6.so
linux-vdso.so.1 =>  (0x00007fffa49ff000)
libpthread.so.0 => /lib64/libpthread.so.0 (0x00000033f0200000)
libdl.so.2 => /lib64/libdl.so.2 (0x00000033f0600000)
libutil.so.1 => /lib64/libutil.so.1 (0x00000033fea00000)
libm.so.6 => /lib64/libm.so.6 (0x00000033f0a00000)
libc.so.6 => /lib64/libc.so.6 (0x00000033efe00000)
/lib64/ld-linux-x86-64.so.2 (0x00000033efa00000)

如果找不到库(因为它不在 LD_LIBRARY_PATH 上或未在 RPATH 中指定),该库将变为空.

If it can't find a library (because it's not on the LD_LIBRARY_PATH or wasn't specified in the RPATH), the library will turn up empty.

d) 从您的链接行看到带有 -shared 选项的.a"文件,我有点担心.某些编译器/链接器无法使用.a"(存档)文件来创建.so"文件..so"文件通常必须由其他.so"文件或已使用 -fPIC 编译的.o"文件制成.

d) I am a little worried from your link line of seeing a '.a' file with a -shared option. Some compilers/linkers cannot use a '.a' (archive) file to create a '.so' file. '.so' files usually have to made from other '.so' files or '.o' files that have been compiled with -fPIC.

我建议(如果可以的话)重新编译/home/me/arm/libstatic.a,使其成为 .so.如果您不能这样做,您可能还必须将最终输出设为.a"文件.(换句话说,去掉 -shared 命令行选项).

I would recommend (if you can), recompile /home/me/arm/libstatic.a so that it's a .so. If you can't do, you might have to make your final output a '.a' file as well. (In other words, get rid of the -shared command line option).

总结:检查您的 LD_LIBRARY_PATH,使用 nm 和 ldd 环顾您的 .a 和 .so 文件,但我认为最终结果是您可能无法组合 .so 和 .a 文件.

In summary: Check your LD_LIBRARY_PATH, use nm and ldd to look around at your .a and .so files, but I think the end result is that you may not be able to combine .so and .a files.

我希望这会有所帮助.

这篇关于加载共享库时未定义的符号的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 14:42