深入理解计算机系统--链接

本文介绍了三种内存分配打桩技术:编译时打桩、链接时打桩和运行时库打桩。通过示例展示了如何使用这些技术来监控malloc和free函数的调用,并提供了详细的实现代码和编译命令。


编译时打桩,编译命令

gcc -DCOMPILETIME -c my_malloc.c
gcc -I. -o main main.c my_malloc.o 

//my_malloc.h
#define malloc(size) mymalloc(size)
#define free(ptr) myfree(ptr)

void *mymalloc(size_t size);
void myfree(void *ptr);



//my_malloc.c
#ifdef COMPILETIME
#include <stdio.h>
#include <malloc.h>

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

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

#endif



//main.c
#include <stdio.h>
#include <malloc.h>

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





链接时打桩,编译命令

gcc -DLINKTIME -c my_malloc.c 
gcc -c main.c
gcc -Wl,--wrap,malloc -Wl,--wrap,free -o main main.o my_malloc.o

//my_malloc.c
#ifdef LINKTIME
#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(%d) = %p\n", (int)size, ptr);
    return ptr;
}

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

#endif




//main.c
#include <stdio.h>
#include <malloc.h>

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

运行结果

malloc(4) = 0x746010
free(0x746010)





运行时库打桩机制

对 malloc,free函数的包装

#define _GUN_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>
//#define NULL 0;

void *malloc(size_t size) {
    void *(*malloc_func)(size_t size);
    char *error;
/*       
    void *handle = dlopen("/lib64/libc.so.6", RTLD_LAZY);
    if (!handle) {
        fprintf (stderr, "%s ", dlerror());
        exit(1);
    }
*/

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


void free(void *ptr) {

    void (*free_func) (void *) = NULL;
    char *error;
    if(!ptr) {
        return;
    }
    free_func = dlsym(RTLD_NEXT, "free");
    if((error=dlerror()) != NULL) {
        fputs(error,stderr);
        exit(1);
    }
    free_func(ptr);
    printf("free (%p)\n",ptr);

}

编译命令

gcc -D_GNU_SOURCE -DRUNTIME -shared -fPIC -o mymalloc.so mymalloc.c -ldl

执行

LD_PRELOAD="./mymalloc.so" uptime  

运行结果

malloc(37) = 0x2526040
。。。
free (0x2527020)
free (0x2526fe0)
malloc(12) = 0x2526fe0
malloc(12) = 0x2527020
free (0x25273e0)
free (0x2527110)
 23:44:38 up 349 days,  6:35,  5 users,  load average: 0.00, 0.01, 0.05




 

一些相关的命令

名称含义
ar创建静态库,插入删除列出和提取成员
ldd列出一个可执行文件在运行时所需要的共享库
gcc强大的编译工具
nm列出一个目标文件的符号表中定义的符号
size列出目标文件中section的名字和大小
objdump

所有二进制工具之母

能够显示一个目标文件中所有的信息

最大的作用是反汇编.text 片段中的二进制指令

readelf

显示一个目标文件的完整结构

包括ELF头中编码的所有信息,包含size和nm的功能

strace跟踪调试工具
strip删除多余的段

 

 

 

 

 

参考

关于Linux静态库和动态库的分析

程序的编译链接过程

程序运行流程——链接、装载及执行







 

一些相关的命令

名称含义
ar创建静态库,插入删除列出和提取成员
ldd列出一个可执行文件在运行时所需要的共享库
gcc强大的编译工具
nm列出一个目标文件的符号表中定义的符号
size列出目标文件中section的名字和大小
objdump

所有二进制工具之母

能够显示一个目标文件中所有的信息

最大的作用是反汇编.text 片段中的二进制指令

readelf

显示一个目标文件的完整结构

包括ELF头中编码的所有信息,包含size和nm的功能

strace跟踪调试工具
strip删除多余的段

 

 

 

 

 

参考

关于Linux静态库和动态库的分析

程序的编译链接过程

程序运行流程——链接、装载及执行

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值