gcc - 如何自动测量每个基本块

时间:2017-05-16 20:52:32

标签: c++ c gcc instrumentation

海湾合作委员会有一个auto-instrument options for function entry/exit.

  

-finstrument-functions 生成用于进入和退出函数的检测调用。在功能输入之后和功能之前   退出时,将调用以下分析函数   当前函数的地址及其调用站点。 (在某些平台上,   __builtin_return_address在当前函数之外不起作用,因此调用站点信息可能无法用于分析   其他功能。)             void __cyg_profile_func_enter(void * this_fn,                                            void * call_site);             void __cyg_profile_func_exit(void * this_fn,                                            void * call_site);

我希望每个"basic block"都有这样的东西,这样我就可以动态地记录每个分支的执行。

我该怎么做?

1 个答案:

答案 0 :(得分:0)

有一个名为American Fuzzy Lop的模糊器,它解决了非常类似的问题,即在基本块之间设置跳跃以收集边缘覆盖:如果基本块是顶点,则会遇到跳跃(边缘)执行。可能值得看看它的来源。它有三种方法:

  • afl-gcc是gcc的包装器,它根据基本块标签和跳转指令用包装器重写汇编代码替换as
  • Clang编译器的插件
  • 用于检测已编译代码的QEMU补丁

另一个也许最简单的选择可能是使用DynamoRIO动态检测系统。与QEMU不同,它专门用于实现自定义检测(或者手动重写机器代码,或者只是在某些情况下插入甚至可能自动内联的调用,如果我得到正确的文档)。如果您认为动态检测是非常困难的,请查看它们的示例 - 它们只有大约100-200行(但您仍需要至少阅读here的文档和使用过的函数,因为它可能包含重要的点:例如DR constructs dynamic basic blocks, which are distinct from a compiler's classic basic blocks)。使用动态检测,您甚至可以检测使用过的系统库。如果它不是你想要的,你可以使用像

这样的东西
static module_data_t *traced_module;

// in dr_client_main
traced_module = dr_get_main_module();

// in basic block event handler
void *app_pc = dr_fragment_app_pc(tag);
if (!dr_module_contains_addr(traced_module, app_pc)) {
    return DR_EMIT_DEFAULT;
}