海湾合作委员会有一个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"都有这样的东西,这样我就可以动态地记录每个分支的执行。
我该怎么做?
答案 0 :(得分:0)
有一个名为American Fuzzy Lop的模糊器,它解决了非常类似的问题,即在基本块之间设置跳跃以收集边缘覆盖:如果基本块是顶点,则会遇到跳跃(边缘)执行。可能值得看看它的来源。它有三种方法:
afl-gcc
是gcc的包装器,它根据基本块标签和跳转指令用包装器重写汇编代码替换as
另一个也许最简单的选择可能是使用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;
}