首页 > 解决方案 > 调用图生成的更快回溯?

问题描述

我使用以下方法来生成调用图。

https://github.com/tarun27sh/gdb_graphs

但是 gdb 因回溯而显着减慢(x100)。有没有更快的方法来生成调用图?

标签: debugginggdbllvmbacktracecall-graph

解决方案


由于您在 SO 上发布此问题并使用llvm对其进行标记,因此我认为这意味着您正在寻找使用 LLVM 的编程解决方案。

编写一个转换程序中每个函数的过程,以便在每次调用之前添加三个新指令。像这样的东西:

struct RecordCallGraph : public PassInfoMixin<RecordCallGraph> {
  RecordCallGraph() = default;
  PreservedAnalyses run(Function &F, FunctionAnalysisManager &FAM);
};

您需要实现 run(),这将是大约 15 行代码。扫描函数中的基本块,检查每条指令是否isa<CallBase>存在,如果是,则在CallBase之前插入一点额外的代码。(CallBase 是调用函数的指令的基类。)您插入对新函数的调用,void emitTraceInfo(char* caller, char* called)或类似的东西。由于 LLVM IR 是类型安全的,因此您需要将调用者 ( &F) 和被调用函数 ( callBase->getCalledValue()) 转换为函数的正确类型(char*在示例中)。

获得该演员表的最简单方法可能是CastInst::Create(CastInst::BitCast, &F, charStarType, "", callBase)创建一个新演员表 from &FtocharStarType并将其插入之前callBase

最后,您必须实施新的emitTraceInfo并将其链接到程序中。每次一个函数调用另一个函数时都会调用它,并且可以记录调用。你会发现它比 gdb 快一百倍。最慢的部分可能是将 16 多个字节写入文件。


推荐阅读