我正在尝试编写LLVM模块通行证,以描述给定程序在运行时发生的所有唯一函数调用者/被调用者对的出现次数。
在线上似乎有大量的示例说明了如何执行此操作,但是没有一个示例能够说明间接函数调用。
我目前正在使用LLVM 11的最新版本,因此与此相关的许多在线帖子也有过时的信息。
在我的设置中,除存在间接函数调用外,当前一切正常。
基本代码设置...
for (auto &F : M) {
for (auto &BB : F) {
for (auto &I : BB) {
if (auto *CB = dyn_cast<CallBase>(&I)){
caller_name = F->getName().str();
Value *callee = CB->getCalledFunction();
// Indirect Call
if (callee == nullptr){
/* Help needed here! */
}
// Direct Call
else{
callee_name = callee.getName().str()
/* Update caller/callee pair counter */
}
}
}
}
}
是否存在某种使用LLVM检索间接函数调用的被叫方名称的已知方法?我知道LLVM 11 AbstractCallSite
中有一个新类,它似乎可能会有所帮助,但是我找不到任何有关如何正确使用它的示例。
我最能解决的方法是,在发生间接呼叫时,在IR中注入一个呼叫以打印被呼叫者的值。
if (callee == nullptr) {
IRBuilder<> IndirectBuilder(CB);
auto *callee_ptr_val = IndirectBuilder.CreatePtrToInt(
CB->getCalledValue(), Type::getInt64Ty(Ctx));
IndirectBuilder.CreateCall(print_callee_val,
callee_ptr_val);
}
在运行时打印此值时,我可以在二进制文件的符号表中查找并查看调用的内容,但这确实很烦人,如果有更好的解决方案,那就太好了。
谢谢!