链接程序和库指南

使用插入

使用特殊句柄 RTLD_NEXT,应用程序可在符号范围内查找下一个符号。例如,如果应用程序 prog 包含以下代码片段:


        if ((fptr = (int (*)())dlsym(RTLD_NEXT, "foo")) == NULL) {

                (void) printf("dlsym: %s\n", dlerror());

                exit (1);

        }

 

        return ((*fptr)());

则会在与 prog 关联的共享库(在此情况下为 /lib/libc.so.1)中搜索 foo。如果此代码片段包含在图 3–1 中显示的示例的文件 B.so.1 中,则仅会在 C.so.1 中搜索 foo

使用 RTLD_NEXT 提供了使用符号插入的方法。例如,可通过前面的目标文件插入目标文件中的函数,然后扩充原始函数的处理。例如,在共享库 malloc.so.1 中放置以下代码片段。


#include    <sys/types.h>

#include    <dlfcn.h>

#include    <stdio.h>

 

void *

malloc(size_t size)

{

        static void * (* fptr)() = 0;

        char             buffer[50];

 

        if (fptr == 0) {

                fptr = (void * (*)())dlsym(RTLD_NEXT, "malloc");

                if (fptr == NULL) {

                        (void) printf("dlopen: %s\n", dlerror());

                        return (0);

                }

        }

 

        (void) sprintf(buffer, "malloc: %#x bytes\n", size);

        (void) write(1, buffer, strlen(buffer));

        return ((*fptr)(size));

}

malloc.so.1 可插入到 malloc(3C) 通常所在的系统库 /lib/libc.so.1 之前。现在,在调用原始函数以完成分配之前,插入对 malloc() 的调用:


$ cc -o malloc.so.1 -G -K pic malloc.c

$ cc -o prog file1.o file2.o ..... -R. malloc.so.1

$ prog

malloc: 0x32 bytes

malloc: 0x14 bytes

..........

或者,可使用以下代码实现相同插入:


$ cc -o malloc.so.1 -G -K pic malloc.c

$ cc -o prog main.c

$ LD_PRELOAD=./malloc.so.1 prog

malloc: 0x32 bytes

malloc: 0x14 bytes

..........

注 –

使用任何插入方法的用户在处理任何可能的递归时都必须小心。前面的示例使用 sprintf(3C),而不是直接使用 printf(3C) 来格式化诊断消息,以避免由于 printf(3C) 可能使用 malloc(3C) 而导致产生递归。


在动态可执行文件或预装入的目标文件中使用 RTLD_NEXT,可提供可预测的插入方法。在一般目标文件依赖项中使用此方法时应该十分小心,因为目标文件的实际装入顺序有时无法预测。