发布于 2019-01-22 18:56:52
有更快的方法来生成调用图吗?
当然有(在这方面使用GDB是完全不合适的)。
最简单的解决方案是使用GCC -finstrument-functions
在每个函数的输入和退出处插入一个调用,并在这些“注入”函数中实现数据收集。有一个例子,这里。
发布于 2019-01-21 23:50:10
由于您在SO上发布了这个问题并将其标记为勒夫姆,所以我假设这意味着您正在寻找一个使用LLVM的编程解决方案。
编写一个pass,转换程序中的每个函数,在每次调用之前添加三个新指令。就像这样:
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是类型类型,所以需要将调用方(&F
)和被调用函数(callBase->getCalledValue()
)转换为正确的函数类型(示例中的char*
)。
获得该转换的最简单方法可能是CastInst::Create(CastInst::BitCast, &F, charStarType, "", callBase)
,它从&F
创建一个新的强制转换到charStarType
,并将其插入到callBase
之前。
最后,您必须实现新的emitTraceInfo
并将其链接到程序中。每次函数调用另一个函数时,都会调用它,并且可以记录调用。你会发现它比gdb快一百倍。最慢的部分可能是将16字节写入文件。
https://stackoverflow.com/questions/54301187
复制相似问题