【问题标题】:gcc - how to auto instrument every basic blockgcc - 如何自动检测每个基本块
【发布时间】:2017-10-16 02:53:45
【问题描述】:

GCC 有一个auto-instrument options for function entry/exit.

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

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

我该怎么做?

【问题讨论】:

  • 你不能。至少不是单独使用 GCC。
  • @EugeneSh。如何做到这一点的大致轮廓是什么?我在想:代码 -> 预处理器输出 -> 使用 Python 在每个 {} 添加自己的函数 -> 继续编译。 . .还有其他方法吗?
  • 有些人会反对,但您可以使用一些宏来包围感兴趣的块。那么,是的,您将只使用 GCC。
  • 我看到的主要问题是{} 的存在既不是“基本块”的必要属性,也不是足够的属性。
  • 然后只需搜索/替换 {BLOCK_START}BLOCK_END。好吧,在数组初始化的情况下,它可能会有一些误报......

标签: c++ c gcc instrumentation


【解决方案1】:

有一个名为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;
}

【讨论】:

    猜你喜欢
    • 2012-07-16
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-02
    相关资源
    最近更新 更多