OpenSSL 内存管理分析笔记

面向开发者使用的最外层接口:

OPENSSL_malloc(num)

<===> CRYPTO_malloc((int)num,__FILE__,__LINE__)

 

OPENSSL_realloc(addr,num)

<===> CRYPTO_realloc((char *)addr, (int)num__FILE____LINE__)

 

OPENSSL_realloc_clean(addr,old_num,num)

<===> CRYPTO_realloc_clean(addr,old_num,num,__FILE__,__LINE__)

 

OPENSSL_remalloc(addr,num)

<===> CRYPTO_remalloc((char **)addr,(int)num,__FILE__,__LINE__)

 

OPENSSL_free(addr)

<===> CRYPTO_free(addr)

 

OPENSSL_malloc_locked(num)

<===> CRYPTO_malloc_locked((int)num,__FILE__,__LINE__)

 

OPENSSL_free_locked(addr)

<===> CRYPTO_free_locked(addr)

 

CRYPTO_XXXX Crypto.h中声明, Mem.c来实现。Mem.c中,使用了两类内存申请函数,

一类为直接调用mallocdefault_XXXXX), 一类为调用Mem_dbg.c中的dbg版本的函数(CRYPTO_dbg_XXXX)

================================================================================

malloc_func, malloc_ex_func, realloc_func, realloc_ex_func, free_func

malloc_locked_func, malloc_locked_ex_funcmalloc_debug_funcrealloc_debug_func

free_debug_funcset_debug_options_funcget_debug_options_func

这些函数由,CRYPTO_XXXX 来调用(其内部首先判断Debug版本的是否为NULL,如果不为NULL

则调用Debug版本的,否则调用非Debug版本的。Debug版本的调用比较特殊,会调用两次。

0: called before the actual memory allocation has taken place

1: called after the actual memory allocation has taken place

================================================================================

static void *(*malloc_func)(size_t) = malloc;

static void *default_malloc_ex(size_t num, const char *file, int line)

{ return malloc_func(num); }

static void *(*malloc_ex_func)(size_t, const char *file, int line)

= default_malloc_ex;

 

static void *(*realloc_func)(void *, size_t)= realloc;

static void *default_realloc_ex(void *str, size_t num,

const char *file, int line)

{ return realloc_func(str,num); }

static void *(*realloc_ex_func)(void *, size_t, const char *file, int line)

= default_realloc_ex;

 

static void (*free_func)(void *) = free;

 

static void *(*malloc_locked_func)(size_t) = malloc;

static void *default_malloc_locked_ex(size_t num, const char *file, int line)

{ return malloc_locked_func(num); }

static void *(*malloc_locked_ex_func)(size_t, const char *file, int line)

= default_malloc_locked_ex;

 

static void (*free_locked_func)(void *) = free;

================================================================================

#ifdef CRYPTO_MDEBUG

/* use default functions from mem_dbg.c */

static void (*malloc_debug_func)(void *,int,const char *,int,int)

= CRYPTO_dbg_malloc;

static void (*realloc_debug_func)(void *,void *,int,const char *,int,int)

= CRYPTO_dbg_realloc;

static void (*free_debug_func)(void *,int) = CRYPTO_dbg_free;

static void (*set_debug_options_func)(long) = CRYPTO_dbg_set_options;

static long (*get_debug_options_func)(void) = CRYPTO_dbg_get_options;

#else

/* applications can use CRYPTO_malloc_debug_init() to select above case

* at run-time */

static void (*malloc_debug_func)(void *,int,const char *,int,int) = NULL;

static void (*realloc_debug_func)(void *,void *,int,const char *,int,int)

= NULL;

static void (*free_debug_func)(void *,int) = NULL;

static void (*set_debug_options_func)(long) = NULL;

static long (*get_debug_options_func)(void) = NULL;

#endif

================================================================================

 

如何使用(使用最外层函数,也就俗称的接口,这里成为Openssl API):

1. 初始化

#define CRYPTO_malloc_init() CRYPTO_set_mem_functions(malloc, realloc, free)

 

如果编译Openssl的时候定义了CRYPTO_MDEBUG  CRYPTO_MDEBUG_ALL

 CRYPTO_MDEBUG_TIME  CRYPTO_MDEBUG_THREAD,则此函数无需调用,默认是被设置好的。详情见Mem.c

#define CRYPTO_malloc_debug_init() do {\

CRYPTO_set_mem_debug_functions(\

CRYPTO_dbg_malloc,\

CRYPTO_dbg_realloc,\

CRYPTO_dbg_free,\

CRYPTO_dbg_set_options,\

CRYPTO_dbg_get_options);\

} while(0)

2. 配置选项

/* Adds time to the memory checking information */

#define V_CRYPTO_MDEBUG_TIME 0x1

/* Adds thread number to the memory checking information */

#define V_CRYPTO_MDEBUG_THREAD 0x2

#define V_CRYPTO_MDEBUG_ALL (V_CRYPTO_MDEBUG_TIME | V_CRYPTO_MDEBUG_THREAD)

// 设置显示信息,显示时间和Thread ID

CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);

 

    /* for applications */

#define CRYPTO_MEM_CHECK_OFF 0x0

#define CRYPTO_MEM_CHECK_ON 0x1

/* for libs*/

#define CRYPTO_MEM_CHECK_ENABLE 0x2

#define CRYPTO_MEM_CHECK_DISABLE 0x3

 

// 可以直接调用这个,也可以调用底下的接口函数

int CRYPTO_mem_ctrl(int mode);

int CRYPTO_is_mem_check_on(void);

 

/* for applications */

#define MemCheck_start() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON)

#define MemCheck_stop() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF)

 

/* for library-internal use */

#define MemCheck_on() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ENABLE)

#define MemCheck_off() CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_DISABLE)

#define is_MemCheck_on() CRYPTO_is_mem_check_on()

 

 

 

3. 使用最外层接口

OPENSSL_malloc(num)

OPENSSL_realloc(addr,num)

OPENSSL_realloc_clean(addr,old_num,num)

OPENSSL_remalloc(addr,num)

OPENSSL_free(addr)

OPENSSL_malloc_locked(num)

OPENSSL_free_locked(addr)

 

示例:

int main()

{

char *= NULL;

BIO *= NULL;

CRYPTO_malloc_debug_init();

CRYPTO_set_mem_debug_options(V_CRYPTO_MDEBUG_ALL);

CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

= (char*)OPENSSL_malloc(4);

CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_OFF);

= BIO_new_file("leak.log","w");

CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);

CRYPTO_mem_leaks(b);

OPENSSL_free(p);

BIO_free(b);

return 0;

}

 

所以,提取OpenSSL中部分代码,只需要重新定义OPENSSL_XXXX这几个宏即可。

posted @ 2013-07-22 19:48  楼上人  阅读(1601)  评论(0编辑  收藏  举报