加载共享库时未定义的符号 [英] Undefined symbol when loading a shared library

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

问题描述

在我的程序中,我需要使用 dlopen()动态加载共享库。对于 ARM 架构,程序和共享库都成功交叉编译,交叉编译器安装在 x86 。但是,无论何时程序试图在 ARM 上运行时加载库,它都会失败并报错:


未定义符号:_dl_hwcap

我无法找到此错误的元凶。



让我详细介绍共享库( libmyplugin.so )是如何构建在 x86

  / 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.cpp module2.cpp 是我的源代码文件。

  2. libstatic.a 是对象 .o 的大档案文件,实现了直接调用/ code> module1.cpp module2.cpp 。这些目标文件已被其他人编译为与我的ARM架构相同的编译器标志,但使用稍微更新的 g ++ 编译器( v4.9 而不是我的 v4.8.3 )。不幸的是,我无法控制这些对象的构建。

  3. - sysroot / home / me / arm / sysroot / 表示我的 ARM OS 的远程文件系统,本地 g ++ 交叉编译器可以在链接时使用本地库。 / li>
  4. -Wl, - no-as-needed -ldl -lX11 -lXext :这些标记是强制​​动态加载器当我的共享库被程序加载时,加载系统上存在的 X11 库。特别是, - 不需要是必需的,因为 X11 库不会被<$ c直接引用$ c> module1.o module2.o ;相反, X11 库仅由静态库引用。

请注意,上述所有设置均适用于 x86 。这只是我不明白当程序试图在 ARM 上加载库时未解析 _dl_hwcap 符号的原因c $ c>。



您是否有任何想法来研究这个问题?

解决方案

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



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



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

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

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



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

 %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中指定),库将变为空。



d)我有点担心你的链接看到'.a'文件带有-shared选项。一些编译器/链接器不能使用'.a'(归档)文件来创建'.so'文件。 '.so'文件通常必须由用-fPIC编译的其他'.so'文件或'.o'文件制作。



我会推荐(如果可以的话),重新编译/home/me/arm/libstatic.a,以便它是.so。如果你做不到,你可能不得不把你的最终输出做成'.a'文件。 (换句话说,摆脱-shared命令行选项)。

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



我希望这有助于。


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:

undefined symbol: _dl_hwcap

I cannot find the culprit of this error.

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

Please pay attention to the following notes:

  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.

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?

解决方案

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) 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) 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 symbols in 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

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) 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)

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) 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.

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).

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.

I hope this helps.

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

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆