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
[] = {Type::getInt8PtrTy(C
), Type::getInt8PtrTy(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
[] = {ConstantExpr::getBitCast(&CurFn
, Type::getInt8PtrTy(C
)),
72 CallInst::Create(Fn
, ArrayRef
<Value
*>(Args
), "", InsertionPt
);
73 Call
->setDebugLoc(DL
);
77 // We only know how to call a fixed set of instrumentation functions, because
78 // they all expect different arguments, etc.
79 report_fatal_error(Twine("Unknown instrumentation function: '") + Func
+ "'");
82 static bool runOnFunction(Function
&F
, bool PostInlining
) {
83 // The asm in a naked function may reasonably expect the argument registers
84 // and the return address register (if present) to be live. An inserted
85 // function call will clobber these registers. Simply skip naked functions for
87 if (F
.hasFnAttribute(Attribute::Naked
))
90 StringRef EntryAttr
= PostInlining
? "instrument-function-entry-inlined"
91 : "instrument-function-entry";
93 StringRef ExitAttr
= PostInlining
? "instrument-function-exit-inlined"
94 : "instrument-function-exit";
96 StringRef EntryFunc
= F
.getFnAttribute(EntryAttr
).getValueAsString();
97 StringRef ExitFunc
= F
.getFnAttribute(ExitAttr
).getValueAsString();
101 // If the attribute is specified, insert instrumentation and then "consume"
102 // the attribute so that it's not inserted again if the pass should happen to
103 // run later for some reason.
105 if (!EntryFunc
.empty()) {
107 if (auto SP
= F
.getSubprogram())
108 DL
= DILocation::get(SP
->getContext(), SP
->getScopeLine(), 0, SP
);
110 insertCall(F
, EntryFunc
, &*F
.begin()->getFirstInsertionPt(), DL
);
112 F
.removeFnAttr(EntryAttr
);
115 if (!ExitFunc
.empty()) {
116 for (BasicBlock
&BB
: F
) {
117 Instruction
*T
= BB
.getTerminator();
118 if (!isa
<ReturnInst
>(T
))
121 // If T is preceded by a musttail call, that's the real terminator.
122 if (CallInst
*CI
= BB
.getTerminatingMustTailCall())
126 if (DebugLoc TerminatorDL
= T
->getDebugLoc())
128 else if (auto SP
= F
.getSubprogram())
129 DL
= DILocation::get(SP
->getContext(), 0, 0, SP
);
131 insertCall(F
, ExitFunc
, T
, DL
);
134 F
.removeFnAttr(ExitAttr
);
141 llvm::EntryExitInstrumenterPass::run(Function
&F
, FunctionAnalysisManager
&AM
) {
142 runOnFunction(F
, PostInlining
);
143 PreservedAnalyses PA
;
144 PA
.preserveSet
<CFGAnalyses
>();
148 void llvm::EntryExitInstrumenterPass::printPipeline(
149 raw_ostream
&OS
, function_ref
<StringRef(StringRef
)> MapClassName2PassName
) {
150 static_cast<PassInfoMixin
<llvm::EntryExitInstrumenterPass
> *>(this)
151 ->printPipeline(OS
, MapClassName2PassName
);