如何确定哪个.SO库被赋予C函数?

时间:2015-02-05 13:53:01

标签: c++ c linux shared-libraries

我在Linux编程中一直有这个问题。只要Linux的所有手册和几乎所有源代码都是以C为中心的,所有对某些函数的引用只需要一些include <something.h>行,并且可以从C / C ++代码访问该函数。

但我用汇编语言编程,对C / C ++几乎一无所知。

为了能够调用某个函数,我必须从相应的.so库中导入它。

如何确定库的文件名?它通常不同于库本身的名称,并且未在手册中指定。

例如,XLib的名称实际上是libX11.so.6。 XShm扩展库的名称似乎是libXext.so.6

使用提供的C手册和参考资料,是否有简单的方法来确定库的秘密实名?

4 个答案:

答案 0 :(得分:3)

这是另一种不是100%准确的方法,它可以为您提供一些关于如何缩小范围的想法。它没有完全适合这个问题,因为它使用常见的Linux实用程序而不是man文件,但它可能仍然有用。

使用您的发行版的软件包管理软件。

例如,在Arch Linux上,如果您对GLFW/glfw3.h中的某个函数感兴趣,可以找出该文件的拥有者:

$ pacman -Qo /usr/include/GLFW/glfw3.h
/usr/include/GLFW/glfw3.h is owned by glfw 3.1-1

找出该软件包中的.so个文件:

$ pacman -Ql glfw | grep 'so$'
glfw /usr/lib/libglfw.so

并且,如果需要,找到链接指向的实际文件:

$ readlink -f /usr/lib/libglfw.so
/usr/lib/libglfw.so.3.1

这取决于您的发行版。我相信Ubuntu / Debian你会改用dpkg-query


修改:DevSolar在评论中指出您可以使用apt-file search <header>apt-file list <package>代替dpkg-query -S <header>dpkg-query -L <package>apt-file似乎适用于尚未安装的软件包(虽然看起来更慢?)。

我还注意到(至少在我的Ubuntu VM上),例如 libglfw-dev 包含libglfw.so符号链接,而 libglfw2 包含实际libglfw.so.2对象。


获得一组.so个文件后,您可以查看它们对您感兴趣的任何功能:

$ nm -D /usr/lib/libglfw.so | grep "glfwCreateWindow"
0000000000007cd0 T glfwCreateWindow

请注意,我从previous question的评论中提取了最后一步,并且完全不了解它。也许你甚至可以跳过前面的步骤,仅依靠nmgrep

答案 1 :(得分:2)

这不是一种确定的消防途径,但在许多情况下它可以提供帮助。

基本上,您通常可以在man页面的底部找到库名称。

例如,man XCreateWindow在最后一行显示libX11。然后,您查找libX11.so并使用nmreadelf查看所有导出的函数。

另一个例子,man XShm在底部说libXext。等等。

<强>更新

如果该函数位于手册页的第(2)部分,则它是系统调用(参见man man)并由glibc提供,它将是libc-2.??.so

最后(感谢Basile),如果函数没有提到库,它也很可能是由glibc提供的。

免责声明:同样,这不是100%准确的方法 - 但在大多数情况下它应该有所帮助。

答案 2 :(得分:0)

正如我评论的那样,您可以使用gcc来关联您的计划,然后它应该能够接受-lX11;使用gcc -v代替gcc,您可以找出实际链接的内容以及内容。

但是,与查找lib*.so.*相比,您有一个更重要的问题;大多数C或C ++ API在头文件中描述,这些C或C ++头文件还包含符号常量(如open(2)O_RDONLY ...)或宏(如POSIX wait中的WIFEXITED ...)您应在头文件或文档中手动查找其值或扩展名。 (通常,这些常量是预处理器#define - d常量或enum值)。此外,一些标题 - 特别是在C ++中 - 包含许多inline - d函数(或宏)!

一种可能的方法是生成一些C文件来查找所有这些常量,枚举,宏,内联函数......,和/或自定义GCC编译器(例如MELT。 ..)找到它们。

所以我的信息是,无论好坏,C语言深深地与Linux&amp; POSIX。

您可能会限制自己仅使用汇编程序代码中的syscalls(2)。然后你不会使用libX11而你不需要任何标题或常量(系统调用的除外,从<asm/unistd.h>开始)。

BTW,在2015年,出于性能原因在汇编程序中完全编码是一个错误。编译器生成的代码比你合理的更好(只要你有超过几百个机器指令)。实际上,您可以使用C函数中的扩展asm指令在汇编程序中使用GCC进行编码。

或者您正在构建自己的编译器?那么你应该在你的问题中告诉你了!

另请阅读Program Library HowTo&amp; Linux Assembly HowTo

答案 3 :(得分:0)

您可以要求gcc告诉您它将用于链接的文件:

gcc --print-file-name=libX11.so

示例输出:

/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/libX11.so

此文件通常是符号链接,因此您必须通过readlinkrealpath来管理它以获取实际文件。例如:

readlink -f $(gcc --print-file-name=libXext.so)

示例输出:

/usr/lib/x86_64-linux-gnu/libXext.so.6.4.0