首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >加载共享库时未定义的符号

加载共享库时未定义的符号
EN

Stack Overflow用户
提问于 2015-03-20 20:29:15
回答 2查看 27.5K关注 0票数 7

在我的程序中,我需要使用dlopen()动态加载共享库。程序和共享库都已成功地交叉编译为ARM体系结构,并在我的x86上安装了交叉编译器。但是,每当程序试图在ARM上运行时加载库时,它都会失败,从而导致以下错误:

未定义符号:_dl_hwcap

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

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

代码语言:javascript
运行
复制
/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是实现module1.cppmodule2.cpp直接调用/引用的对象.o文件的一个大型存档。这些对象文件是由其他人为与我相同的ARM架构编译的,具有相同的编译器标志,但使用的是稍微更新的g++编译器(v4.9而不是my v4.8.3)。不幸的是,我无法控制这些物体的建造。
  3. --sysroot /home/me/arm/sysroot/表示我的ARM OS的远程文件系统,本地g++交叉编译器可以从该文件系统获取链接时的本机库。
  4. -Wl,--no-as-needed -ldl -lX11 -lXext:当程序加载共享库时,需要使用这些标志来强制动态加载器加载系统上的X11库。特别是,需要--no-as-needed是因为X11库不是由module1.omodule2.o直接引用的;相反,X11库仅由静态库引用。

请注意,上述所有设置都在x86上工作。只是我不明白为什么当程序试图在_dl_hwcap上加载库时,ARM符号没有被解析。

你知道如何调查这个问题吗?

EN

回答 2

Stack Overflow用户

发布于 2015-03-20 21:42:45

有无数的事情可能是有问题的,但这里有四条探索的途径。我把注意力集中在链接行中的-shared上,但最后一项也解决了这个问题。(关于共享库的一个很好的方法在这里:http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html

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

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

代码语言:javascript
运行
复制
% nm -D /usr/lib64/libpython2.6.so | grep initgc
000003404300cf0 T initgc

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

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

代码语言:javascript
运行
复制
% 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文件。

我希望这能帮到你。

票数 10
EN

Stack Overflow用户

发布于 2015-03-20 22:43:20

我认为这个符号可能在"Xext“所需的"ld-lsb”库中。在我的系统中,库是一个符号链接“/lsb 64/ld-lsb-x86-64”,所以-> ld-linux-x86-64.so.2",但我确信这在手臂上是不一样的。或者在你的链接线上旋转一下?

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29175308

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档