美文网首页
链接和运行时打桩

链接和运行时打桩

作者: Teech | 来源:发表于2019-05-16 18:08 被阅读0次

这里说个很有意思的东西,就库打桩技术。允许我们在编译,链接,以及加载阶段替换部分系统函数的调用。比如malloc,free。
举个例子 编译时打桩,其实就是用#define 替换掉一些系统函数名,这个没什么好说的。

  • 链接时打桩
//inc.c
#include<stdio.h>
int main(){
    void* p = malloc(32);
    free(p);
    return 0;
}
//mymalloc.c
#include<stdio.h>
void* __real_malloc(size_t size);
void __real_free(void* ptr);

void* __wrap_malloc(size_t size){
    void*ptr = __real_malloc(size);
    printf("malloc size(%d) ptr=%x\n",size,(unsigned long)ptr);
    return ptr;
}
void __wrap_free(void* ptr){
    printf("free ptr=%x\n",(unsigned long)ptr);
    __real_free(ptr);
}
#Makefile
intc : inc.o mymalloc.o
    gcc -Wl,--wrap=malloc,--wrap=free -o intc inc.o mymalloc.o
mymalloc.o : mymalloc.c
    gcc -c mymalloc.c
inc.o : inc.c
    gcc  -c inc.c
clean :
    rm intc inc.o mymalloc.o

其中-Wl,--wrap=malloc,--wrap=free的意思,链接时替换掉“引用符号表”里的malloc为__wrap_malloc,free替换为__wrap_free。
编译后inc.o文件里有未解的引用"malloc","free",ld链接的时候把这两个符号替换掉成__wrap_malloc和__wrap_free。这样mymalloc.o文件的就能找到定义的地方,这样就替换glib里的malloc。

  • 加载时打桩
    这个意思就是加载时,也就是运行应用程序时,我们也可以修改glibc的一些函数以便于我们进行统计或者注入一些其他代码。
//inc.c
#include<stdio.h>
int main(){
    void* p = malloc(32);
    free(p);
    return 0;
}
//mymalloc.c
#define _GNU_SOURCE
#include<stdio.h>
#include<stdlib.h>
#include<dlfcn.h>

void* malloc(size_t size){
        void* (*mallocp)(size_t size); 
        char* error;
        mallocp = dlsym(RTLD_NEXT,"malloc");
        if ((error = dlerror()) != NULL){
            fputs(error,stderr);
            exit(1);
        }
        char* ptr = mallocp(size);
        fputs("newmalloc\n",stderr);
        //printf("malloc size(%d) ptr=%x\n",size,(unsigned long)ptr);
        return ptr;
}

void free(void* ptr){
    void (*freep)(void*) = NULL;
    char* error;
    freep = dlsym(RTLD_NEXT,"free");
    if ((error = dlerror()) != NULL){
        fputs(error,stderr);
        exit(1);
    }   
    freep(ptr);
    fputs("newfree\n",stderr);
    //printf("free ptr=%x\n",(unsigned long)ptr);
}
#生成mymalloc.so 
mymalloc.so : mymalloc.o
    gcc -shared -o mymalloc.so mymalloc.o -ldl
mymalloc.o : mymalloc.c
    gcc -fPIC -c mymalloc.c

然后在执行这个命令,生成inc可执行程序,这里默认的是使用glibc里的malloc.

gcc -o inc inc.c 

我们运行时想使用我们的打桩函数

LD_PRELOAD = "./mymalloc.so" ./inc

意味着解引用的时候,先从我们LD_PRELOAD这个定义的文件里找,也就是调用了mymalloc.so里的malloc和free函数。
在看看dlsym函数里的第一个参数RTLD_NEXT,我们查看man文档。
Find the next occurrence of the desired symbol in the search order after the current object. This allows one to provide a wrapper around a function in another shared object, so that, for example, the definition of a function in a preloaded shared
object (see LD_PRELOAD in ld.so(8)) can find and invoke the "real" function provided in another shared object (or for that matter, the "next" definition of the function in cases where there are multiple layers of preloading).
解引用的时候,首先找到的是mymalloc.so,因为设置了RTLD_NEXT,所以接着往下找,肯定找到时glibc里的malloc。
这里注释掉了malloc里的printf函数,因为printf内部一定有调用malloc函数的,这样会形成死循环了,堆栈溢出了。如果打开printf后的core文件的dump如下。printf里的malloc调用到mymalloc.so里的malloc函数,然后mymalloc.so里的malloc函数又会调用到printf。这样就会出现死循环。

其实打桩技术在用来做内存泄露检测工具的时候非常有用,记录下文件名以及行号,比如对比两次内存快照这样来辅助查找内存泄露的地方。

相关文章

  • 链接和运行时打桩

    这里说个很有意思的东西,就库打桩技术。允许我们在编译,链接,以及加载阶段替换部分系统函数的调用。比如malloc,...

  • linux 链接器 库打桩

    @(linux 编程) 翻看 CSAPP 看到库函数打桩,记录下。 linux 链接器支持库打桩(library ...

  • linux 程序打桩,截获系统库调用,执行自己的代码

    无意看到之前笔记里面记录的程序打桩方法,重新看了遍,这里也随便记录下。 linux 链接器支持库打桩(librar...

  • 一文搞懂linux的库打桩

    Linux下的链接器支持一个强大的库打桩(library interpositioning),允许你拦截对系统标准...

  • RunTime

    runtime:Objective-C是动态语言,它将很多静态语言在编译和链接时做的事放到了运行时,这个运行时系统...

  • 打桩

    某一天 我像举行祭祀大典一样 斟酌反复 选了一个良辰吉日 开始打桩 都未围成栏 这是第几桩? 我惧 门中人 还好 ...

  • 打桩

    打桩好辛苦, 汗滴额上土。 下雨无干襟, 太阳晒屁股。

  • 打桩

    二十五米入岩孔, 穿过岁月土层封。 地质万变无可入, 强干地球唯命从。

  • c++ 单元测试中的打桩

    gmock 借助于C++运行时多态实现,派生需要打桩的类,使用桩函数覆盖原来的实现,将指向原类的指针指向桩类 mo...

  • 单元测试

    全局变量可通过GoStub框架打桩过程可通过Monkey框架打桩函数可通过Monkey框架打桩方法可通过Monke...

网友评论

      本文标题:链接和运行时打桩

      本文链接:https://www.haomeiwen.com/subject/dyliaqtx.html