1 //===- EntryExitInstrumenter.cpp - Function Entry/Exit Instrumentation ----===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/Transforms/Utils/EntryExitInstrumenter.h"
10 #include "llvm/Analysis/GlobalsModRef.h"
11 #include "llvm/IR/DebugInfoMetadata.h"
12 #include "llvm/IR/Dominators.h"
13 #include "llvm/IR/Function.h"
14 #include "llvm/IR/Instructions.h"
15 #include "llvm/IR/Intrinsics.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/IR/Type.h"
18 #include "llvm/TargetParser/Triple.h"
22 static void insertCall(Function
&CurFn
, StringRef Func
,
23 Instruction
*InsertionPt
, DebugLoc DL
) {
24 Module
&M
= *InsertionPt
->getParent()->getParent()->getParent();
25 LLVMContext
&C
= InsertionPt
->getParent()->getContext();
27 if (Func
== "mcount" ||
29 Func
== "llvm.arm.gnu.eabi.mcount" ||
30 Func
== "\01_mcount" ||
31 Func
== "\01mcount" ||
34 Func
== "__cyg_profile_func_enter_bare") {
35 Triple
TargetTriple(M
.getTargetTriple());
36 if (TargetTriple
.isOSAIX() && Func
== "__mcount") {
37 Type
*SizeTy
= M
.getDataLayout().getIntPtrType(C
);
38 Type
*SizePtrTy
= PointerType::getUnqual(C
);
39 GlobalVariable
*GV
= new GlobalVariable(M
, SizeTy
, /*isConstant=*/false,
40 GlobalValue::InternalLinkage
,
41 ConstantInt::get(SizeTy
, 0));
42 CallInst
*Call
= CallInst::Create(
43 M
.getOrInsertFunction(Func
,
44 FunctionType::get(Type::getVoidTy(C
), {SizePtrTy
},
46 {GV
}, "", InsertionPt
);
47 Call
->setDebugLoc(DL
);
49 FunctionCallee Fn
= M
.getOrInsertFunction(Func
, Type::getVoidTy(C
));
50 CallInst
*Call
= CallInst::Create(Fn
, "", InsertionPt
);
51 Call
->setDebugLoc(DL
);
56 if (Func
== "__cyg_profile_func_enter" || Func
== "__cyg_profile_func_exit") {
57 Type
*ArgTypes
[] = {PointerType::getUnqual(C
), PointerType::getUnqual(C
)};
59 FunctionCallee Fn
= M
.getOrInsertFunction(
60 Func
, FunctionType::get(Type::getVoidTy(C
), ArgTypes
, false));
62 Instruction
*RetAddr
= CallInst::Create(
63 Intrinsic::getDeclaration(&M
, Intrinsic::returnaddress
),
64 ArrayRef
<Value
*>(ConstantInt::get(Type::getInt32Ty(C
), 0)), "",
66 RetAddr
->setDebugLoc(DL
);
68 Value
*Args
[] = {&CurFn
, RetAddr
};
70 CallInst::Create(Fn
, ArrayRef
<Value
*>(Args
), "", InsertionPt
);
71 Call
->setDebugLoc(DL
);
75 // We only know how to call a fixed set of instrumentation functions, because
76 // they all expect different arguments, etc.
77 report_fatal_error(Twine("Unknown instrumentation function: '") + Func
+ "'");
80 static bool runOnFunction(Function
&F
, bool PostInlining
) {
81 // The asm in a naked function may reasonably expect the argument registers
82 // and the return address register (if present) to be live. An inserted
83 // function call will clobber these registers. Simply skip naked functions for
85 if (F
.hasFnAttribute(Attribute::Naked
))
88 StringRef EntryAttr
= PostInlining
? "instrument-function-entry-inlined"
89 : "instrument-function-entry";
91 StringRef ExitAttr
= PostInlining
? "instrument-function-exit-inlined"
92 : "instrument-function-exit";
94 StringRef EntryFunc
= F
.getFnAttribute(EntryAttr
).getValueAsString();
95 StringRef ExitFunc
= F
.getFnAttribute(ExitAttr
).getValueAsString();
99 // If the attribute is specified, insert instrumentation and then "consume"
100 // the attribute so that it's not inserted again if the pass should happen to
101 // run later for some reason.
103 if (!EntryFunc
.empty()) {
105 if (auto SP
= F
.getSubprogram())
106 DL
= DILocation::get(SP
->getContext(), SP
->getScopeLine(), 0, SP
);
108 insertCall(F
, EntryFunc
, &*F
.begin()->getFirstInsertionPt(), DL
);
110 F
.removeFnAttr(EntryAttr
);
113 if (!ExitFunc
.empty()) {
114 for (BasicBlock
&BB
: F
) {
115 Instruction
*T
= BB
.getTerminator();
116 if (!isa
<ReturnInst
>(T
))
119 // If T is preceded by a musttail call, that's the real terminator.
120 if (CallInst
*CI
= BB
.getTerminatingMustTailCall())
124 if (DebugLoc TerminatorDL
= T
->getDebugLoc())
126 else if (auto SP
= F
.getSubprogram())
127 DL
= DILocation::get(SP
->getContext(), 0, 0, SP
);
129 insertCall(F
, ExitFunc
, T
, DL
);
132 F
.removeFnAttr(ExitAttr
);
139 llvm::EntryExitInstrumenterPass::run(Function
&F
, FunctionAnalysisManager
&AM
) {
140 runOnFunction(F
, PostInlining
);
141 PreservedAnalyses PA
;
142 PA
.preserveSet
<CFGAnalyses
>();
146 void llvm::EntryExitInstrumenterPass::printPipeline(
147 raw_ostream
&OS
, function_ref
<StringRef(StringRef
)> MapClassName2PassName
) {
148 static_cast<PassInfoMixin
<llvm::EntryExitInstrumenterPass
> *>(this)
149 ->printPipeline(OS
, MapClassName2PassName
);