Linux平台下hook技术研究

说明

  • 之前公司,C项目中为了程序检测内存泄漏问题,采用一个自己实现的库,能够记录内存分配和释放操作,程序结束或者通过信号可以生成dump信息来分析内存问题。

技术分析

  • 内存分配和释放记录主要是通过hook(钩子)技术来获取的。

hook技术

通过预处理实现

  • 实现方式:
  1. 创建一个头文件,通过宏替换的方式替换掉内存分配(malloc,calloc,realloc)和释放函数(free)。
  2. 创建一个源文件,定义替换函数,在替换函数中记录调用和调用真正的目标函数和做相应处理。
  • 代码示例:
* 头文件 MemHook.h
#if defined(__cplusplus)
extern "C" {
#endif

#define malloc(size) mmalloc(size , __FILE__, __LINE__)
#define calloc(size) mcalloc(size, __FILE__, __LINE__)
.....
#define free(p) mfree(p)

#if defined(__cplusplus)
}
#endif

* 源码
#include 
#include 
//不能引入 MemHook.h 

void *mmalloc (unsigned long counts, const char* const file , const unsigned long line)
{
	void *buf;
	
	printf("%s , %ld\n", file , line);
  	if (NULL == (buf = malloc(counts)))
	{
	    ....
		return NULL;
	}
	//记录内存分配
    ....
	return buf;
}
.....
void mfree (void *p)
{
	if (p)
	{
	    //记录内存释放
	    .....
		free(p);
	}
}
  • 方式优缺点:
  1. 需要手动引入该头文件,如果有源码未引入该头文件,会导致操作未记录。

LD_PRELOAD 环境变量方式

  • 方式简介:
  • LD_PRELOAD 是在所有动态库前加载该环境变量定义的动态库。
  • 方式说明:
  1. 实现一个动态库,通过LD_PRELOAD环境变量,在所有动态库前加载。
  2. 动态库中定义标准的内存分配和释放函数,例如:malloc,calloc,free等;由于先加载,变量设置后运行的程序中调用的这些函数都会被指向该库中的实现。
  3. 在该库中记录分配和释放记录,以及调用真正的malloc,calloc,free等函数。
  • 代码示例:
* 库源码
#define _GNU_SOURCE

#include 
#include 
#include  

static void *(*true_malloc)(size_t);
static void (*true_free)(void *ptr);

void *malloc(size_t size)
{
    void *ptr;
    
    if (true_malloc == NULL)
    {    
        true_malloc = dlsym(RTLD_NEXT, "malloc");
    }  
    
    printf(%d\n", size);  
    ptr = true_malloc(size);
    //记录分配操作
    ....
   
    return ptr;   
}
.....
void free(void* ptr)
{
    if (true_free == NULL)
    {    
        true_free = dlsym(RTLD_NEXT, "free");
    }    

    //记录释放操作
    ....
    printf("%p\n", ptr);     
    return true_free(ptr);   
}

* 注意:
1. 函数定义需要和标准的一样。
2. 生成动态库时需要链接 dl库。
* 编译生成动态库
* 设置环境变量 
export LD_PRELOAD=./libxxxx.so 
* 执行其它程序
  • 方式优缺点
  1. 替换方式简单,环境变量设置和取消非常方便。

你可能感兴趣的:(嵌入式)