如何确定在哪个.SO库中给定了C函数
How to determine in which .SO library is given C function?
我在Linux编程中一直遇到这个问题。只要Linux的所有手册和几乎所有源代码都是以C为中心的,那么对某个函数的所有引用都只需要一些include <something.h>
行,并且该函数可以从C/C++代码中访问。
但我是用汇编语言编程的,对C/C++几乎一无所知。
为了能够调用一些函数,我必须从相应的.so库中导入它。
如何确定库的文件名?它通常与库本身的名称不同,并且在手册中没有指定。
例如,XLib的名称实际上是libX11.so.6
。XShm扩展库的名称似乎是libXext.so.6
。
有没有简单的方法可以使用提供的C手册和参考资料来确定图书馆的秘密真实名称?
这是另一种不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虚拟机上),例如,libglfw-dev包含libglfw.so
符号链接,而libglfw2则包含实际的libglfw.so.2
对象。
一旦你有了一组.so
文件,你就可以检查它们是否有你感兴趣的任何功能:
$ nm -D /usr/lib/libglfw.so | grep "glfwCreateWindow"
0000000000007cd0 T glfwCreateWindow
请注意,我从上一个问题的评论中提取了最后一步,但并没有完全理解。也许你甚至可以跳过前面的步骤,只依靠nm
和grep
?
这不是一种可靠的方法,但在许多情况下都会有所帮助。
基本上,您通常可以在man
页面的底部找到库名称。
例如,man XCreateWindow
在最后一行说libX11
。然后查找libX11.so
并使用nm
或readelf
查看所有导出的函数。
另一个例子,man XShm
在底部显示libXext
。等等。
更新
如果该函数位于手册页的第(2)节中,则它是一个系统调用(请参见man man
),由glibc提供,即libc-2.??.so
。
最后(感谢Basile),如果函数没有提到库,那么它很可能也是由glibc提供的。
免责声明:同样,这不是一个100%准确的方法,但在大多数情况下应该会有所帮助。
您可以要求gcc
告诉您它将使用哪个文件进行链接,如下所示:
gcc --print-file-name=libX11.so
样本输出:
/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../x86_64-linux-gnu/libX11.so
这个文件通常是一个符号链接,所以你必须通过readlink
或realpath
来获得实际的文件。例如:
readlink -f $(gcc --print-file-name=libXext.so)
样本输出:
/usr/lib/x86_64-linux-gnu/libXext.so.6.4.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&POSIX。
您可能会限制自己只能使用汇编代码中的系统调用(2)。那么就不需要使用libX11
,也不需要任何头或常量(除了从<asm/unistd.h>
开始用于系统调用的头或常量)。
BTW,2015年,出于性能原因,在汇编程序中完全编码是一个错误。编译器生成的代码比你合理的能力要好(只要你有几百条以上的机器指令)。在实践中,您可以通过在C函数中使用扩展的asm
指令,使用GCC在汇编程序中进行编码。
或者您正在构建自己的编译器?那么你应该在你的问题中这么说!
另请阅读程序库HowTo&Linux程序集HowTo
- 函数何时会在c++中包含stack_Unwind_Resume调用
- C++setiosflags函数操纵器-未确定的缩进
- 编译器如何在使用SFINAE的函数和标准函数之间确定两者是否可行
- 通过构造函数动态确定类实现
- 无论如何,我可以确定构造函数是否存在吗?
- compare_exchange C++函数如何确定竞争条件?
- 标准对此指向成员函数类型模板参数有何说明?是我的代码有误,还是 MSVS 16.6 有问题?
- 是否有一个 std::set 函数来确定不超过数字 x 的最大元素?
- 在确定函数的时间复杂度时需要帮助
- 使用std::conditional中的模板来确定函数参数类型
- c++ 将字符串发送到函数以确定字符串的长度
- 通过函数参数确定结构体成员
- 确定以下函数是否确定数组是否按升序排序
- 如何在C ++中返回字符数组?数组长度由函数本身确定
- 在类中定义数组,但大小在构造函数中确定
- C++中是否有一个函数可以确定给定目录中是否存在特定的文件夹
- C++如何使用返回布尔值的函数来确定素数
- Template:通过函数原型确定模板参数
- 从模板函数参数确定参数类型
- 是否有stl或boost函数来确定字符串是否为数字