首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

覆盖 GNU C 库 ― 轻而易举 调试系统问题并进行快速修订

覆盖 GNU C 库 ― 轻而易举 调试系统问题并进行快速修订

如果您没有应用程序的源代码并且由于 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() :      
覆盖 setresgid() 的 Makefile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#
# Makefile
#
all: libs setresgid-tester
#
# Make a shared Library
#
libs: libfuncs.c
        gcc -shared -Wl,-soname,libfuncs.so.1 -o libfuncs.so.1.0  libfuncs.c
        ln -s libfuncs.so.1.0 libfuncs.so.1
        ln -s libfuncs.so.1 libfuncs.so
#
# Here is a program that calls setresgid() for testing
#
setresgid-tester: setresgid-tester.c
        gcc -o setresgid-tester setresgid-tester.c




文件         libfuncs.c 包含我的         setresgid() 专用版本。实现它以支持与原始         setresgid() 相同的参数数目时要小心,并在其它方面完成与原始         setresgid() 相同的操作,尽管我的版本欺骗该应用程序并始终返回 0。      
关注的第二个文件是         setresgid-tester.c 。它通过调用         setresgid() 试验新函数。      
这是动态库的源代码:
替换库
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
/*
Put all the functions you want to override here
*/
#include
#include
#include
int errno;
int
setresgid(rgid, egid, sgid)
        gid_t rgid,egid,sgid;
{
   errno=1;
   printf("It me the shim, Hi there!\n");
   return(0);
}




您还需要一个简单方法来测试您的         setresgid() 专用版本。可以使用 strace 或 ltrace 来监视进程运行。这是普通测试示例的源代码:      
普通测试示例
1
2
3
4
5
6
7
8
/*
  setresgid() system/library call tester
*/
#include
#include
main(){
   setresgid(0,0,0);
}




现在,编译该库,设置         LD_PRELOAD shell 变量,然后运行测试应用程序。您可能还需要设置         LD_LIBRARY_PATH 。      
运行测试应用程序
1
2
3
4
export LD_PRELOAD=libfuncs.so
export LD_LIBRARY_PATH=.LD_LIBRARY_PATH
./setresgid-tester
It's me the shim, Hi there!




还可以通过使用 ldd 列出动态链接库来确认是否正在使用专用库:
确认专用库的使用
1
2
3
4
[jay@prion ld_preload]$ ldd setresgid-tester
        libfuncs.so => libfuncs.so (0x40018000)
        libc.so.6 => /lib/libc.so.6 (0x40022000)
        /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x40000000)




结束语编写 GNU C 库函数的专用版本是调试系统问题或进行快速修正的好方法。使用         LD_PRELOAD shell 变量,可以选择性地用您自己的专用版本来覆盖系统 C 库函数。这种技术可用于 Linux 和 Solaris 环境。
返回列表