菜鸟笔记
提升您的技术认知

内存泄漏检测组件 -ag真人游戏

hook malloc与free出现的问题

#define _gnu_source
#include 
#include 
#include 
/*****************************hook******************************/
typedef void *(*malloc_t)(size_t);
malloc_t malloc_f;
typedef void (*free_t)(void *);
free_t free_f;
static int init_hook() {
    malloc_f = dlsym(rtld_next, "malloc");
    free_f = dlsym(rtld_next, "free");
}
void *malloc(size_t size) {
    printf("in malloc\n");
    return null;
}
void free(void *ptr) {
    printf("in free\n");
}
/***************************************************************/
int main() {
	init_hook();
    void *p1 = malloc(10);
    void *p2 = malloc(20);
    free(p1);
}

出现段错误,gdb看一看 

        printf函数底层会调用malloc函数,如果程序陷入死循环,会不停的调用malloc。我们下面就要去破坏这个递归

        让第一次进入函数的部分执行我们的流程,而递归进去的算第二次进入函数,返回即可。

#define _gnu_source
#include 
#include 
#include 
/*****************************hook******************************/
typedef void *(*malloc_t)(size_t);
int enable_malloc_hook = 1;
malloc_t malloc_f;
typedef void (*free_t)(void *);
int enable_free_hook = 1;
free_t free_f;
static int init_hook() {
    malloc_f = dlsym(rtld_next, "malloc");
    free_f = dlsym(rtld_next, "free");
}
void *malloc(size_t size) {
    if (enable_malloc_hook) {
        enable_malloc_hook = 0;
        void *p = malloc_f(size);
        printf("malloc--->ptr:%p size:%zu\n", p, size);
        enable_malloc_hook = 1;
        return p;
    }
    else {
        return null;
    }
}
void free(void *ptr) {
    if (enable_free_hook) {
        enable_free_hook = 0;
        printf("free  --->ptr:%p\n", ptr);
        free_f(ptr);
        enable_free_hook = 1;
    }
    else {
        return ;
    }
}
/***************************************************************/
int main() {
	init_hook();
    void *p1 = malloc(10);
    void *p2 = malloc(20);
    free(p1);
}

builtin_return_address(n)

# 编译器提供的函数,返回第n层调用函数 

1、gcc默认不支持__builtin_return_address(level)的参数为非0。好像只支持参数为0。

2、__builtin_return_address(0)的含义是,得到当前函数返回地址,即此函数被别的函数调用,然后此函数执行完毕后,返回,所谓返回地址就是那时候的地址。

3、__builtin_return_address(1)的含义是,得到当前函数的调用者的返回地址。注意是调用者的返回地址,而不是函数起始地址。

在__builtin_return_address函数外面套了一层converttovma。目的是把返回的内存地址转换成vma地址。

#define _gnu_source
#include 
#include 
#include 
#include 
#include 
#include 
#include 
/*****************************hook******************************/
//
// created by 68725 on 2022/8/13.
//
#define _gnu_source
#include 
#include 
#include 
#include 
#include 
typedef void *(*malloc_t)(size_t);
int enable_malloc_hook = 1;
malloc_t malloc_f;
typedef void (*free_t)(void *);
int enable_free_hook = 1;
free_t free_f;
static int init_hook() {
    malloc_f = dlsym(rtld_next, "malloc");
    free_f = dlsym(rtld_next, "free");
}
void *converttovma(void *addr) {
    dl_info info;
    struct link_map *link_map;
    dladdr1((void *) addr, &info, (void **) &link_map, rtld_dl_linkmap);
    return addr - link_map->l_addr;
}
void *malloc(size_t size) {
    if (enable_malloc_hook) {
        enable_malloc_hook = 0;
        void *p = malloc_f(size);
        void *caller = converttovma(__builtin_return_address(0));
        printf("[ %p]--->ptr:%p size:%zu\n", caller, p, size);
        char command[256];
        dl_info info;
        dladdr(malloc, &info);
        snprintf(command, sizeof(command), "addr2line -f -e %s -a %p > ./mem/%p.mem", info.dli_fname, caller, p);
        system(command);
        enable_malloc_hook = 1;
        return p;
    }
    else {
        return malloc_f(size);
    }
}
void free(void *ptr) {
    if (enable_free_hook) {
        enable_free_hook = 0;
        void *caller = converttovma(__builtin_return_address(0));
        printf("[-%p]--->ptr:%p\n", caller, ptr);
        char buff[128] = {0};
        sprintf(buff, "./mem/%p.mem", ptr);
        if (unlink(buff) < 0) {
            printf("double kill:%p\n",ptr);
        }
        free_f(ptr);
        enable_free_hook = 1;
    }
    else {
        return free_f(ptr);
    }
}
int main() {
    init_hook();
    void *p1 = malloc(10);
    void *p2 = malloc(20);
    free(p1);
}
网站地图