stub的三种方式

stub的三种方式

使用stub是为了用我们自己的函数来替换目标文件里调用的函数,有三种方式:

  • 编译时打桩
  • 链接时打桩
  • 运行时打桩

使用一个示例描述:用我们自己包装的mymalloc函数和myfree来替换系统的malloc和free,使其打印信息。

/* mymalloc.c */
/* lcl 20190424 */
#ifdef CMPILETIME
#include <stdio.h>
#include <malloc.h>

/* malloc wrapper function */
void *mymalloc(size_t size){
    void *ptr = malloc(size);
    printf("malloc(%d)=%p\n",(int)size,ptr);
    return ptr;
}

/* free wrapper funtion */
void myfree(void *ptr){
    free(ptr);
    printf("free(%p)\n",ptr);
}

示例程序

/* example stub */
/* int.c */
/* lcl 20190424 */
#include <stdio.h>
#include <malloc.h>

int main(){
    int *p = malloc(32);
    free(p);
    return 0;
}

编译时打桩

准备本地头文件

/* malloc.h on local */
#define malloc(size) mymalloc(size)
#define free(ptr) myfree(ptr)
void *mymalloc(size_t size);
void myfree(void* ptr);

使用库编译mymalloc

gcc -DCOMPILETIME -c mymalloc.c

使用本地头文件替换malloc头文件

gcc -I . int.c mymalloc.o -o int

结果

[root@linuxkit-00155ddc0103 stub]# ./intl
malloc(32)=0x15cb010
free(0x15cb010)

链接时打桩

使用链接器--wrap f选项,告诉链接器,把对f的引用解析成__wrap_f,把__real_f解析成f,从而达到打桩的目的

/* mymalloc.c */
/* lcl 20190424 */
#ifdef LINKTIME
#include <stdio.h>
void *__real_malloc(size_t t);
void __real_fee(void *ptr);

/* malloc wrapper function */
void *__wrap_malloc(size_t size){
    void *ptr = __real_malloc(size);
    printf("malloc(%d)=%p\n",(int)size,ptr);
    return ptr;
}

/* free wrapper funtion */
void __wrap_free(void *ptr){
    __real_free(ptr);
    printf("free(%p)\n",ptr);
}

makefile

intl: int.o mymalloc.o                                             
    gcc -Wl,--wrap,malloc -Wl,--wrap,free int.o mymalloc.o -o intl 
int.o: int.c                                                       
    gcc -c int.c                                                   
mymalloc.o: mymalloc.c                                             
    gcc -DLINKTIME -c mymalloc.c 

结果

[root@linuxkit-00155ddc0103 stub]# ./intl
malloc(32)=0x15cb010
free(0x15cb010)

运行时打桩

使用LD_PRELOAD环境变量,使程序优先链接我们的库,在我们的函数里使用dlsym来获取真正的函数mallocp = dlsym(RTLD_NEXT,"malloc")

/* mymalloc.c */
/* lcl 20190425 */
#ifdef RUNTIME
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <difcn.h>

void *malloc(size_t size)
{
    void *(*mallocp)(size_t);
    char *error;

    mallocp = dlsym(RTLD_NEXT,"malloc");
    if((error = dlerror())!=NULL){
        fputs(error,stderr);
        exit(1);
    }
    char *ptr = mallocp(size);
    printf("malloc(%d) = %p\n",(int)size, ptr);
    return ptr;
}

void free(void *ptr){
    void (*freep)(void *) = NULL;
    char *error;
    if(!ptr) return;

    freep = dlsym(RTLD_NEXT,"free");
    if ((error=dlerror())!=NULL){
        fputs(error,stderr);
        exit(1);
    }
    freep(ptr);
    printf("free(%p)\n",ptr);
}
#endif

编译

intr: int.c
    gcc -DRUNTIME -shared -fpic mymalloc.c -ldl -o mymalloc.so
    gcc int.c -o intr

结果

[root@linuxkit-00155ddc0103 stub]# LD_PRELOAD="./mymalloc.so" ./intr
malloc(32) = 0x11eb010
free(0x11eb010)

甚至还可以对其他程序应用

[root@linuxkit-00155ddc0103 stub]# LD_PRELOAD="./mymalloc.so" date
malloc(34) = 0x2225010
malloc(10) = 0x2225040
malloc(15) = 0x2225060
malloc(568) = 0x2225080
malloc(29) = 0x22252c0
free(0x2225080)
malloc(20) = 0x2225080
Thu Apr 25 12:53:41 UTC 2019

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 一、温故而知新 1. 内存不够怎么办 内存简单分配策略的问题地址空间不隔离内存使用效率低程序运行的地址不确定 关于...
    SeanCST阅读 8,138评论 0 27
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 14,259评论 0 38
  • 第一章:编译和安装SCons第二章:简单编译第三章:编译相关的一些事情第四章:编译和链接库文件第五章:节点对象第六...
    仙灵儿阅读 12,354评论 0 3
  • 动态链接,在可执行文件装载时或运行时,由操作系统的装载程序加载库。大多数操作系统将解析外部引用(比如库)作为加载过...
    小5筒阅读 5,782评论 0 3
  • 官网 中文版本 好的网站 Content-type: text/htmlBASH Section: User ...
    不排版阅读 4,723评论 0 5

友情链接更多精彩内容