分类:
2008-06-21 16:40:58
|
级别: 初级
Jay Allen (), 程序员, IBM
2002 年 4 月 01 日
一种调试 glibc 函数的好方法是用您自己的版本覆盖所关注的函数。在没有root 许可权和不必重新编译 libc 源代码的情况下就可以完成这个任务。想象一下编写您自己的
open()
版本该有多激动啊!
如果您没有应用程序的源代码并且由于 C 的 GNU 库(glibc)函数正将某些错误信息返回给该应用程序而使它失败,那么您该怎么办? 因为 glibc 是开放源码,所以您当然可以获得其源代码、对它进行更改、重新构建和安装。 然而,这不适合那些胆怯的人,因为虽然 API 有很好的文档说明,但 GNU C 库的内部组织却没有。 查找正确的函数原型只是众多挑战中的第一个。 它还是一个很大的包,所以第一次编译时,它将花一些时间(glibc 2.2.2 有 8552 个文件和 1775440 行代码,包括注释)。
比重新构建 glibc 更好的方法是选择性地覆盖一个函数。许多现代的 Unix 都支持预装入用户定义库这一概念。
这些库可以是完整的替代(即,glibc 的专用版本)也可以是子集 ― 甚至是一个函数。
首先,通过设置
LD_LIBRARY_PATH
来包含库的专用版本,您可以使用 glibc 的专用
版本。可通过使用
LD_PRELOAD
环境值来使用您编写的库例程的子集。
LD_LIBRARY_PATH
和
LD_PRELOAD
都是由动态 ELF 链接器/装入器控制的。
它使用第一个匹配来满足任何符号名。通过预装入您自己的库或函数版本,您“短路”了正常路径,这样就允许您覆盖它。
这里是一个示例 makefile,它覆盖 glibc 函数
setresgid()
:
# |
文件
libfuncs.c
包含我的
setresgid()
专用版本。
实现它以支持与原始
setresgid()
相同的参数数目时要小心,并在其它方面完成与原始
setresgid()
相同的操作,尽管我的版本欺骗该应用程序并始终返回 0。
关注的第二个文件是
setresgid-tester.c
。它通过调用
setresgid()
试验新函数。
这是动态库的源代码:
/* |
您还需要一个简单方法来测试您的
setresgid()
专用版本。可以使用 strace 或 ltrace 来监视进程运行。这是普通测试示例的源代码:
/* |
现在,编译该库,设置
LD_PRELOAD
shell 变量,然后运行测试应用程序。您可能还需要设置
LD_LIBRARY_PATH
。
export LD_PRELOAD=libfuncs.so |
还可以通过使用 ldd 列出动态链接库来确认是否正在使用专用库:
[jay@prion ld_preload]$ ldd setresgid-tester |
|
编写 GNU C 库函数的专用版本是调试系统问题或进行快速修正的好方法。
使用
LD_PRELOAD
shell 变量,可以选择性地用您自己的专用版本来覆盖系
统 C 库函数。这种技术可用于 Linux 和 Solaris 环境。
Jay Allen 是 IBM Linux for Service Providers Lab(LSPL)的程序员。可以通过 与 Jay 联系。 |