EntryExitInstrumenter.cpp 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. //===- EntryExitInstrumenter.cpp - Function Entry/Exit Instrumentation ----===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
  9. #include "llvm/Analysis/GlobalsModRef.h"
  10. #include "llvm/IR/DebugInfoMetadata.h"
  11. #include "llvm/IR/Function.h"
  12. #include "llvm/IR/Instructions.h"
  13. #include "llvm/IR/Module.h"
  14. #include "llvm/IR/Type.h"
  15. #include "llvm/Pass.h"
  16. #include "llvm/Transforms/Utils.h"
  17. using namespace llvm;
  18. static void insertCall(Function &CurFn, StringRef Func,
  19. Instruction *InsertionPt, DebugLoc DL) {
  20. Module &M = *InsertionPt->getParent()->getParent()->getParent();
  21. LLVMContext &C = InsertionPt->getParent()->getContext();
  22. if (Func == "mcount" ||
  23. Func == ".mcount" ||
  24. Func == "\01__gnu_mcount_nc" ||
  25. Func == "\01_mcount" ||
  26. Func == "\01mcount" ||
  27. Func == "__mcount" ||
  28. Func == "_mcount" ||
  29. Func == "__cyg_profile_func_enter_bare") {
  30. FunctionCallee Fn = M.getOrInsertFunction(Func, Type::getVoidTy(C));
  31. CallInst *Call = CallInst::Create(Fn, "", InsertionPt);
  32. Call->setDebugLoc(DL);
  33. return;
  34. }
  35. if (Func == "__cyg_profile_func_enter" || Func == "__cyg_profile_func_exit") {
  36. Type *ArgTypes[] = {Type::getInt8PtrTy(C), Type::getInt8PtrTy(C)};
  37. FunctionCallee Fn = M.getOrInsertFunction(
  38. Func, FunctionType::get(Type::getVoidTy(C), ArgTypes, false));
  39. Instruction *RetAddr = CallInst::Create(
  40. Intrinsic::getDeclaration(&M, Intrinsic::returnaddress),
  41. ArrayRef<Value *>(ConstantInt::get(Type::getInt32Ty(C), 0)), "",
  42. InsertionPt);
  43. RetAddr->setDebugLoc(DL);
  44. Value *Args[] = {ConstantExpr::getBitCast(&CurFn, Type::getInt8PtrTy(C)),
  45. RetAddr};
  46. CallInst *Call =
  47. CallInst::Create(Fn, ArrayRef<Value *>(Args), "", InsertionPt);
  48. Call->setDebugLoc(DL);
  49. return;
  50. }
  51. // We only know how to call a fixed set of instrumentation functions, because
  52. // they all expect different arguments, etc.
  53. report_fatal_error(Twine("Unknown instrumentation function: '") + Func + "'");
  54. }
  55. static bool runOnFunction(Function &F, bool PostInlining) {
  56. StringRef EntryAttr = PostInlining ? "instrument-function-entry-inlined"
  57. : "instrument-function-entry";
  58. StringRef ExitAttr = PostInlining ? "instrument-function-exit-inlined"
  59. : "instrument-function-exit";
  60. StringRef EntryFunc = F.getFnAttribute(EntryAttr).getValueAsString();
  61. StringRef ExitFunc = F.getFnAttribute(ExitAttr).getValueAsString();
  62. bool Changed = false;
  63. // If the attribute is specified, insert instrumentation and then "consume"
  64. // the attribute so that it's not inserted again if the pass should happen to
  65. // run later for some reason.
  66. if (!EntryFunc.empty()) {
  67. DebugLoc DL;
  68. if (auto SP = F.getSubprogram())
  69. DL = DebugLoc::get(SP->getScopeLine(), 0, SP);
  70. insertCall(F, EntryFunc, &*F.begin()->getFirstInsertionPt(), DL);
  71. Changed = true;
  72. F.removeAttribute(AttributeList::FunctionIndex, EntryAttr);
  73. }
  74. if (!ExitFunc.empty()) {
  75. for (BasicBlock &BB : F) {
  76. Instruction *T = BB.getTerminator();
  77. if (!isa<ReturnInst>(T))
  78. continue;
  79. // If T is preceded by a musttail call, that's the real terminator.
  80. Instruction *Prev = T->getPrevNode();
  81. if (BitCastInst *BCI = dyn_cast_or_null<BitCastInst>(Prev))
  82. Prev = BCI->getPrevNode();
  83. if (CallInst *CI = dyn_cast_or_null<CallInst>(Prev)) {
  84. if (CI->isMustTailCall())
  85. T = CI;
  86. }
  87. DebugLoc DL;
  88. if (DebugLoc TerminatorDL = T->getDebugLoc())
  89. DL = TerminatorDL;
  90. else if (auto SP = F.getSubprogram())
  91. DL = DebugLoc::get(0, 0, SP);
  92. insertCall(F, ExitFunc, T, DL);
  93. Changed = true;
  94. }
  95. F.removeAttribute(AttributeList::FunctionIndex, ExitAttr);
  96. }
  97. return Changed;
  98. }
  99. namespace {
  100. struct EntryExitInstrumenter : public FunctionPass {
  101. static char ID;
  102. EntryExitInstrumenter() : FunctionPass(ID) {
  103. initializeEntryExitInstrumenterPass(*PassRegistry::getPassRegistry());
  104. }
  105. void getAnalysisUsage(AnalysisUsage &AU) const override {
  106. AU.addPreserved<GlobalsAAWrapperPass>();
  107. }
  108. bool runOnFunction(Function &F) override { return ::runOnFunction(F, false); }
  109. };
  110. char EntryExitInstrumenter::ID = 0;
  111. struct PostInlineEntryExitInstrumenter : public FunctionPass {
  112. static char ID;
  113. PostInlineEntryExitInstrumenter() : FunctionPass(ID) {
  114. initializePostInlineEntryExitInstrumenterPass(
  115. *PassRegistry::getPassRegistry());
  116. }
  117. void getAnalysisUsage(AnalysisUsage &AU) const override {
  118. AU.addPreserved<GlobalsAAWrapperPass>();
  119. }
  120. bool runOnFunction(Function &F) override { return ::runOnFunction(F, true); }
  121. };
  122. char PostInlineEntryExitInstrumenter::ID = 0;
  123. }
  124. INITIALIZE_PASS(
  125. EntryExitInstrumenter, "ee-instrument",
  126. "Instrument function entry/exit with calls to e.g. mcount() (pre inlining)",
  127. false, false)
  128. INITIALIZE_PASS(PostInlineEntryExitInstrumenter, "post-inline-ee-instrument",
  129. "Instrument function entry/exit with calls to e.g. mcount() "
  130. "(post inlining)",
  131. false, false)
  132. FunctionPass *llvm::createEntryExitInstrumenterPass() {
  133. return new EntryExitInstrumenter();
  134. }
  135. FunctionPass *llvm::createPostInlineEntryExitInstrumenterPass() {
  136. return new PostInlineEntryExitInstrumenter();
  137. }
  138. PreservedAnalyses
  139. llvm::EntryExitInstrumenterPass::run(Function &F, FunctionAnalysisManager &AM) {
  140. runOnFunction(F, PostInlining);
  141. PreservedAnalyses PA;
  142. PA.preserveSet<CFGAnalyses>();
  143. return PA;
  144. }