跳转至

库打桩


更新于:2022-05-09

系统调时,用自定义函数取代共享库函数。

作用

  • 追踪某个特殊库函数的调用次数
  • 验证和追踪它的输入输出值
  • 替换函数实现

流程

创建一个和目标函数原型一样的包装函数,
使用打桩机制让系统调用包装函数,包装函数内再调用目标函数。

编译时打桩

对目标函数进程一层封装,在封装函数内调用目标函数。

通过对mallocfree的打桩进行说明

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
//main.c
#include <stdio.h>
#include <malloc.h>

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

重写malloc.h,如下

C
1
2
3
//malloc.h
#define malloc(size) Malloc(size)
#define free(ptr) Free(ptr)

实现自定义的mallocfree

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
//Malloc.c
#include <stdio.h>
#include <malloc.h>

void* Malloc(size_t size)
{
    void * ptr = malloc(ptr);
    printf("malloc:%s %d\n", ptr, size);
    return ptr;
}

void Free(void* ptr)
{
    free(ptr);
    printf("free:%p\n", ptr);
}

Bash
1
2
3
4
#先编译自行封装的malloc和free
gcc -c Malloc.c
#通过只用 -I. 编译时,将有限搜索当前目录,即使用./malloc.h,而不是/usr/include/malloc.h 
gcc -I. -o a.out main.c Malloc.o

链接时打桩

使用linux静态链接器的--wrap fun标志。
该标志告诉连接器把对f的引用解析成__warp_fun,
对符号__real_fun的引用解析成fun

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
//main.c
#include <stdio.h>
#include <malloc.h>

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

C
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
//Malloc.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(ptr);
    printf("malloc:%s %d\n", ptr, size);
    return ptr;
}

void __wrap_free(void* ptr)
{
    __real_free(ptr);
    printf("free:%p\n", ptr);
}
Bash
1
2
3
4
5
#正常编译Mallic和main
gcc -c Malloc.c
gcc -c main.c
#通过-Wl,----warp,fun向链接器传递参数
gcc -Wl,--wrap,malloc -Wl,--wrap,free -0 a.out Malloc.o main.o

运行时打桩

设置环境变量LD_LIBRARY_PATH
指定运行时依赖动态库路径
使用调试库