首先注意,本例子 开头
#include “utils.h”
utils 不是extension ,只是封装了一个创建 日志文件 的函数,源码在 utils.c 里,可以在 samples 文件夹里找到。
所以,我们需要在 CMakeLists.txt 里这样写:
add_library( cbrtrace SHARED cbrtrace.c utils.c)
//然后要多加一个 drx extension:
use_DynamoRIO_extension(bbcount drx)
//这个 extension 是在 utils.c 里面调用的。
首先来看 dr_client_main 函数,该函数是最初被调用的函数,我们一般在里面注册各种事件的回调函数:
DR_EXPORT
void
dr_client_main(client_id_t id, int argc, const char *argv[])
{
drmgr_init();
client_id = id;
tls_idx = drmgr_register_tls_field();
dr_register_exit_event(event_exit);
if (!drmgr_register_thread_init_event(event_thread_init) ||
!drmgr_register_thread_exit_event(event_thread_exit) ||
!drmgr_register_bb_instrumentation_event(NULL, event_app_instruction, NULL))
DR_ASSERT(false);
}
drmgr_init() 用来初始化插件 drmgr。
drmgr_register_tls_field() 为每个线程保留 线程本地存储(tls)插槽。返回槽的索引,该索引可以传递给drmgr_get_tls_field()和drmgr_set_tls_field()。如果没有可用的插槽,则返回-1。所谓 tls 就是每个线程专属的一个存储器。通过 drmgr_set_tls_field() 来设定tls里的值,用 drmgr_get_tls_field() 用来获取tls 里面的值。
dr_register_exit_event 为 进程退出事件注册 回调函数(event_exit)。
drmgr_register_thread_init_event 为线程初始化事件 注册回调函数(event_thread_init)。
drmgr_register_thread_exit_event 为线程退出事件 注册回调函数 (event_thread_exit)。
drmgr_register_bb_instrumentation_event 为 basic block 创建事件 注册回调函数 event_app_instruction。
DR_ASSERT 则是一个断言,用来确保上面的初始化都正确完成。
提醒一下,以dr_ 开头的函数都是 DynamoRIO 原始的API ,而以drmgr_ 开头的函数则是 drmgr extension 所使用的API。二者有什么关系,部分 drmgr_ 函数是对 dr_ 函数的增强。比如 drmgr_register_bb_instrumentation_event 是对 dr_register_bb_event 函数的增强,强在哪里?原函数 只对应 basic block 创建时刻,而 drmgr 版本则将该时刻细分为4个步骤,我们可以对其中 的两个步骤设置回调函数。具体的可以查阅文档。
接下来看那些注册的回调函数:
首先是 event_thread_init :
static void
event_thread_init(void *drcontext)
{
file_t log;
log =
log_file_open(client_id, drcontext, NULL /* using client lib path */, "cbrtrace",
#ifndef WINDOWS
DR_FILE_CLOSE_ON_FORK |
#endif
DR_FILE_ALLOW_LARGE);
DR_ASSERT(log != INVALID_FILE);