Как получить указатель на функцию ссылки в LLVM IR? - PullRequest
0 голосов
/ 04 марта 2020

Я пишу проход модуля LLVM, который получит третий аргумент в pthread_create. Согласно справочной странице прототип функции 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;
  }

I хотел бы иметь вывод "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>();
      }
    };
  }


1 Ответ

0 голосов
/ 05 марта 2020

Спасибо за комментарий @ 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;
    }
...