如何在 LLVM IR 中获取引用函数指针?
How to get the referencing function pointer in LLVM IR?
我正在编写一个 LLVM 模块传递,它将获得 pthread_create
中的第三个参数。根据man page pthread_create
的函数原型是
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
例如我的目标C源代码如下。
void *pthread_task(void *args) {
sleep(4);
return NULL;
}
int main(int argc, char *argv[]) {
pthread_t tid;
pthread_create(&tid, NULL, pthread_task, NULL);
pthread_join(tid, NULL);
return 0;
}
我想要输出 "pthread_task"。我能够访问正确的函数并列出所有参数。但是,由于第三个参数是一个函数指针,我不知道如何访问它所指向的函数。
我还附上了我如何实现我的模块传递如下。
namespace {
~ int32_t indexOfPthreadCreate(CallGraphNode *node) {
~ for (int32_t i = 0; i < node -> size(); i++) {
~ Function *f = (*node)[i] -> getFunction();
~ if (f && f -> getName().compare("pthread_create") == 0) {
+ for (auto &A: f->args()) {
// I would like to access the third parameter of pthread_create here.
+ A.print(errs());
+ }
+ return i;
+ }
}
~ return -1;
}
struct PthreadScopeDetectPass : public ModulePass {
static char ID;
PthreadScopeDetectPass() : ModulePass(ID) { }
bool runOnModule(Module &M) override {
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
uint32_t nSCC = 0;
for (scc_iterator<CallGraph *> iterSCC = scc_begin(&CG); !iterSCC.isAtEnd(); ++iterSCC) {
auto nodes = *iterSCC;
for (CallGraphNode *node: nodes) {
Function *currFunc = node -> getFunction();
~ int32_t target_i = indexOfPthreadCreate(node);
~ if (target_i > 0 && currFunc) {
+ insertTimer(currFunc);
}
}
}
return true;
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
AU.addRequired<CallGraphWrapperPass>();
}
};
}
感谢@arnt 的评论。我已经解决了这个问题。我是这样解决的。
~ int32_t indexOfPthreadCreate(CallGraphNode *node) {
~ for (int32_t i = 0; i < node -> size(); i++) {
~ Function *f = (*node)[i] -> getFunction();
~ if (f && f -> getName().compare("pthread_create") == 0) {
+ for (auto &inst: instructions(f)) {
~ if (inst.getOpcode() == 56) {
~ CallInst *ci = dyn_cast<CallInst>(&inst);
~ if (ci && ci->getCalledFunction()->getName().compare("pthread_create") == 0) {
~ Function *pthread_task = dyn_cast<Function>(ci->getArgOperand(2));
~_ errs() << "pthread is going to execute " << pthread_task->getName() << "function \n";
}
+ }
+ A.print(errs());
+ }
+ return i;
+ }
}
~ return -1;
}
我正在编写一个 LLVM 模块传递,它将获得 pthread_create
中的第三个参数。根据man page pthread_create
的函数原型是
int pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start_routine) (void *), void *arg);
例如我的目标C源代码如下。
void *pthread_task(void *args) {
sleep(4);
return NULL;
}
int main(int argc, char *argv[]) {
pthread_t tid;
pthread_create(&tid, NULL, pthread_task, NULL);
pthread_join(tid, NULL);
return 0;
}
我想要输出 "pthread_task"。我能够访问正确的函数并列出所有参数。但是,由于第三个参数是一个函数指针,我不知道如何访问它所指向的函数。
我还附上了我如何实现我的模块传递如下。
namespace {
~ int32_t indexOfPthreadCreate(CallGraphNode *node) {
~ for (int32_t i = 0; i < node -> size(); i++) {
~ Function *f = (*node)[i] -> getFunction();
~ if (f && f -> getName().compare("pthread_create") == 0) {
+ for (auto &A: f->args()) {
// I would like to access the third parameter of pthread_create here.
+ A.print(errs());
+ }
+ return i;
+ }
}
~ return -1;
}
struct PthreadScopeDetectPass : public ModulePass {
static char ID;
PthreadScopeDetectPass() : ModulePass(ID) { }
bool runOnModule(Module &M) override {
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
uint32_t nSCC = 0;
for (scc_iterator<CallGraph *> iterSCC = scc_begin(&CG); !iterSCC.isAtEnd(); ++iterSCC) {
auto nodes = *iterSCC;
for (CallGraphNode *node: nodes) {
Function *currFunc = node -> getFunction();
~ int32_t target_i = indexOfPthreadCreate(node);
~ if (target_i > 0 && currFunc) {
+ insertTimer(currFunc);
}
}
}
return true;
}
void getAnalysisUsage(AnalysisUsage &AU) const override {
AU.setPreservesAll();
AU.addRequired<CallGraphWrapperPass>();
}
};
}
感谢@arnt 的评论。我已经解决了这个问题。我是这样解决的。
~ int32_t indexOfPthreadCreate(CallGraphNode *node) {
~ for (int32_t i = 0; i < node -> size(); i++) {
~ Function *f = (*node)[i] -> getFunction();
~ if (f && f -> getName().compare("pthread_create") == 0) {
+ for (auto &inst: instructions(f)) {
~ if (inst.getOpcode() == 56) {
~ CallInst *ci = dyn_cast<CallInst>(&inst);
~ if (ci && ci->getCalledFunction()->getName().compare("pthread_create") == 0) {
~ Function *pthread_task = dyn_cast<Function>(ci->getArgOperand(2));
~_ errs() << "pthread is going to execute " << pthread_task->getName() << "function \n";
}
+ }
+ A.print(errs());
+ }
+ return i;
+ }
}
~ return -1;
}