选择显示字体大小

覆盖 gnu c 库 — 轻而易举


一种调试 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():

覆盖 setresgid() 的 makefile
#
# 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() 试验新函数。

这是动态库的源代码:

替换库
/*
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 来监视进程运行。这是普通测试示例的源代码:

普通测试示例
/*
setresgid() system/library call tester
*/
#include
#include
main(){
setresgid(0,0,0);
}



现在,编译该库,设置 ld_preload shell 变量,然后运行测试应用程序。您可能还需要设置 ld_library_path。

运行测试应用程序
export ld_preload=libfuncs.so
export ld_library_path=.:$ld_library_path
./setresgid-tester
it's me the shim, hi there!



还可以通过使用 ldd 列出动态链接库来确认是否正在使用专用库:

确认专用库的使用
[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 环境。

关于作者
jay allen 是 ibm linux for service providers lab(lspl)的程序员。可以通过 jaydallen@us.ibm.com 与 jay 联系。

  


 


关键字 本文所属关键字

相关 与本文相关文章

分类 所有文章关键字导航

源码编程相关

Java   Asp   PHP   .Net   XML   C/C++   CGI   VB   Jsp   J2ee   J2se   J2me   EJB   Servlet   Tomcat   Resin   Struts   Weblogic   Eclipse   ANT   GUI   JMS   Web servise   IDEA   Webphere   Hibernate   Spring   Jboss   Applet   Swing   Socket   Javamail   Perl   Ajax   P2P   安全   模式   框架   测试   开源   游戏

SQL数据库相关

My-SQL   Ms-SQL   Access   DB2   Oracle   Sybase   SQLserver   索引   存储过程   加密   数据库   分页   视图  

手机无线相关

3G   Wap   CDMA   GRPS   GSM   IVR   彩信   短信   无线   增值业务

网页设计制作相关

HTML   CSS   网页配色   网页特效   Javascript   VBscript   Dreamweaver   Frontpage   JS   Web   网站设计

网站建设推广相关

建站经验   网站优化   网站排名   推广   Alexa

操作系统/服务器相关

Windows XP   Windows 2000   Windows 2003   Windows Me   Windows 9.x   Linux   UNIX   注册表   操作系统   服务器   应用服务器

图形图像多媒体相关

Photoshop   Fireworks   Flash   Coreldraw   Illustrator   Freehand   Photoimpact   多媒体   图形图像

标准 网站致力的规范

Valid CSS!

无不良内容,无不良广告,无恶意代码

Valid XHTML 1.0 Transitional

creativecommons