我正在尝试理解 Linux 和*.so
文件。这很难。
我试图弄清楚,如何找到文件中可用的模块*.so
,例如:
在我的 httpd 配置文件中我发现了以下行:
LoadModule wsgi_module modules/mod_wsgi.so
我认为wsgi_module
是“内部”的一个模块mod_wsgi.so
。
问题:如何列出或查找*.so
文件的所有模块?
答案1
一般来说,所有.so
文件(无论是库还是模块)都是通过导出命名的符号– 通常表示函数或有时表示“外部”变量 – 程序将使用“动态链接器”按名称导入这些变量。大多模块与库相同。
对于 Apache httpd 模块,“模块名称”wsgi_module
实际上只是 .so 文件导出的符号的名称(最有可能指向一个结构变量,该变量包含指向 Apache 开始将其用作模块所需的所有函数的指针)。主程序将使用 加载 .sodlopen()
并使用 查找指定的符号dlsym()
。
(对于使用 .so 模块的其他程序,情况可能会有所不同,因为每个程序基本上都有自己的特点;例如,许多程序希望所有模块都提供一个符号相同的每次都说出名字。
要查看 .so 文件导出的名称,您可以使用nm
binutils:
$ nm -D -Ux /usr/lib/httpd/modules/mod_rewrite.so
0000000000012020 D rewrite_module
这里-D
使 nm 显示“动态”符号,并将-U
列表修剪为仅“定义”的符号(即导出 - 完整列表还包含正在进口来自其他图书馆)。
(根据一切,它应该只是-U
,而不是-Ux
,但显然我拥有的 nm/binutils 版本错误地要求为短选项提供一个参数,所以我不得不使用-Usomething
。长选项--defined-only
按预期工作。)
你可以将它与.so
一个普通的 C 库文件进行比较,它的工作方式大致相同(符号是通常完成后在编译时解析gcc hello.c -lcrypt
,但也可以使用 dlsym 加载):
$ nm -D -Ux /usr/lib/libcrypt.so
0000000000000000 A XCRYPT_2.0
0000000000000000 A XCRYPT_4.3
0000000000000000 A XCRYPT_4.4
0000000000010e30 T crypt@@XCRYPT_2.0
0000000000011090 T crypt_checksalt@@XCRYPT_4.3
000000000000f4d0 T crypt_gensalt@@XCRYPT_2.0
0000000000011000 T crypt_gensalt_ra@@XCRYPT_2.0
0000000000010e50 T crypt_gensalt_rn@@XCRYPT_2.0
0000000000011120 T crypt_preferred_method@@XCRYPT_4.4
0000000000010de0 T crypt_r@@XCRYPT_2.0
0000000000010d20 T crypt_ra@@XCRYPT_2.0
0000000000010c90 T crypt_rn@@XCRYPT_2.0
的替代方案nm
,来自David的评论:
答案2
您的假设是错误的:.so
文件只是通过链接一个或多个目标文件创建的共享库。
具体来说, LoadModule 指令 语法如下:
LoadModule module filename
该指令的描述如下:
LoadModule 指令链接目标文件或库文件名,并将名为 module 的模块结构添加到活动模块列表中。Module 是文件中 module 类型的外部变量的名称,并在模块文档中列为模块标识符。
这意味着这module
是 Apache 中使用的特定名称。并非所有.so
库都是 Apache 模块,而且它们肯定不是由 Apache 模块组成的。
.so
库由链接器从目标文件创建。有时这些文件也称为“模块”。一旦链接完成,它们就不能再解压到其原始目标文件中,因为这些信息不再可用。
库中剩下的只有.so
原始对象文件提供的入口点以及它们最初所属的对象文件的名称。但是,如果不反汇编库,您就无法猜测每个对象文件的代码从哪里开始或结束。