LLVM 23.0.0git
JMCInstrumenter.cpp
Go to the documentation of this file.
1//===- JMCInstrumenter.cpp - JMC 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//
9// JMCInstrumenter pass:
10// - instrument each function with a call to __CheckForDebuggerJustMyCode. The
11// sole argument should be defined in .msvcjmc. Each flag is 1 byte initilized
12// to 1.
13// - create the dummy COMDAT function __JustMyCode_Default to prevent linking
14// error if __CheckForDebuggerJustMyCode is not available.
15// - For MSVC:
16// add "/alternatename:__CheckForDebuggerJustMyCode=__JustMyCode_Default" to
17// "llvm.linker.options"
18// For ELF:
19// Rename __JustMyCode_Default to __CheckForDebuggerJustMyCode and mark it as
20// weak symbol.
21//===----------------------------------------------------------------------===//
22
26#include "llvm/CodeGen/Passes.h"
27#include "llvm/IR/DIBuilder.h"
30#include "llvm/IR/Function.h"
32#include "llvm/IR/LLVMContext.h"
33#include "llvm/IR/Module.h"
34#include "llvm/IR/Type.h"
36#include "llvm/Pass.h"
37#include "llvm/Support/DJB.h"
38#include "llvm/Support/Path.h"
40
41using namespace llvm;
42
43#define DEBUG_TYPE "jmc-instrumenter"
44
45static bool runImpl(Module &M);
46namespace {
47struct JMCInstrumenter : public ModulePass {
48 static char ID;
49 JMCInstrumenter() : ModulePass(ID) {}
50 bool runOnModule(Module &M) override { return runImpl(M); }
51};
52char JMCInstrumenter::ID = 0;
53} // namespace
54
59
61 JMCInstrumenter, DEBUG_TYPE,
62 "Instrument function entry with call to __CheckForDebuggerJustMyCode",
63 false, false)
64
65ModulePass *llvm::createJMCInstrumenterPass() { return new JMCInstrumenter(); }
66
67namespace {
68const char CheckFunctionName[] = "__CheckForDebuggerJustMyCode";
69
70std::string getFlagName(DISubprogram &SP, bool UseX86FastCall) {
71 // absolute windows path: windows_backslash
72 // relative windows backslash path: windows_backslash
73 // relative windows slash path: posix
74 // absolute posix path: posix
75 // relative posix path: posix
76 sys::path::Style PathStyle =
78 SP.getDirectory().contains("\\") ||
79 SP.getFilename().contains("\\")
82 // Best effort path normalization. This is to guarantee an unique flag symbol
83 // is produced for the same directory. Some builds may want to use relative
84 // paths, or paths with a specific prefix (see the -fdebug-compilation-dir
85 // flag), so only hash paths in debuginfo. Don't expand them to absolute
86 // paths.
87 SmallString<256> FilePath(SP.getDirectory());
88 sys::path::append(FilePath, PathStyle, SP.getFilename());
89 sys::path::native(FilePath, PathStyle);
90 sys::path::remove_dots(FilePath, /*remove_dot_dot=*/true, PathStyle);
91
92 // The naming convention for the flag name is __<hash>_<file name> with '.' in
93 // <file name> replaced with '@'. For example C:\file.any.c would have a flag
94 // __D032E919_file@any@c. The naming convention match MSVC's format however
95 // the match is not required to make JMC work. The hashing function used here
96 // is different from MSVC's.
97
98 std::string Suffix;
99 for (auto C : sys::path::filename(FilePath, PathStyle))
100 Suffix.push_back(C == '.' ? '@' : C);
101
102 sys::path::remove_filename(FilePath, PathStyle);
103 return (UseX86FastCall ? "_" : "__") +
104 utohexstr(djbHash(FilePath), /*LowerCase=*/false,
105 /*Width=*/8) +
106 "_" + Suffix;
107}
108
109void attachDebugInfo(GlobalVariable &GV, DISubprogram &SP) {
110 Module &M = *GV.getParent();
111 DICompileUnit *CU = SP.getUnit();
112 assert(CU);
113 DIBuilder DB(M, false, CU);
114
115 auto *DType =
116 DB.createBasicType("unsigned char", 8, dwarf::DW_ATE_unsigned_char,
117 llvm::DINode::FlagArtificial);
118
119 auto *DGVE = DB.createGlobalVariableExpression(
120 CU, GV.getName(), /*LinkageName=*/StringRef(), SP.getFile(),
121 /*LineNo=*/0, DType, /*IsLocalToUnit=*/true, /*IsDefined=*/true);
122 GV.addMetadata(LLVMContext::MD_dbg, *DGVE);
123 DB.finalize();
124}
125
126FunctionType *getCheckFunctionType(LLVMContext &Ctx) {
127 Type *VoidTy = Type::getVoidTy(Ctx);
128 PointerType *VoidPtrTy = PointerType::getUnqual(Ctx);
129 return FunctionType::get(VoidTy, VoidPtrTy, false);
130}
131
132Function *createDefaultCheckFunction(Module &M, bool UseX86FastCall) {
133 LLVMContext &Ctx = M.getContext();
134 const char *DefaultCheckFunctionName =
135 UseX86FastCall ? "_JustMyCode_Default" : "__JustMyCode_Default";
136 // Create the function.
137 Function *DefaultCheckFunc =
138 Function::Create(getCheckFunctionType(Ctx), GlobalValue::ExternalLinkage,
139 DefaultCheckFunctionName, &M);
141 DefaultCheckFunc->addParamAttr(0, Attribute::NoUndef);
142 if (UseX86FastCall)
143 DefaultCheckFunc->addParamAttr(0, Attribute::InReg);
144
145 BasicBlock *EntryBB = BasicBlock::Create(Ctx, "", DefaultCheckFunc);
146 ReturnInst::Create(Ctx, EntryBB);
147 return DefaultCheckFunc;
148}
149} // namespace
150
151bool runImpl(Module &M) {
152 bool Changed = false;
153 LLVMContext &Ctx = M.getContext();
154 Triple ModuleTriple(M.getTargetTriple());
155 bool IsMSVC = ModuleTriple.isKnownWindowsMSVCEnvironment();
156 bool IsELF = ModuleTriple.isOSBinFormatELF();
157 assert((IsELF || IsMSVC) && "Unsupported triple for JMC");
158 bool UseX86FastCall = IsMSVC && ModuleTriple.getArch() == Triple::x86;
159 const char *const FlagSymbolSection = IsELF ? ".data.just.my.code" : ".msvcjmc";
160
161 GlobalValue *CheckFunction = nullptr;
163 for (auto &F : M) {
164 if (F.isDeclaration())
165 continue;
166 auto *SP = F.getSubprogram();
167 if (!SP)
168 continue;
169
170 Constant *&Flag = SavedFlags[SP];
171 if (!Flag) {
172 std::string FlagName = getFlagName(*SP, UseX86FastCall);
173 IntegerType *FlagTy = Type::getInt8Ty(Ctx);
174 Flag = M.getOrInsertGlobal(FlagName, FlagTy, [&] {
175 // FIXME: Put the GV in comdat and have linkonce_odr linkage to save
176 // .msvcjmc section space? maybe not worth it.
178 M, FlagTy, /*isConstant=*/false, GlobalValue::InternalLinkage,
179 ConstantInt::get(FlagTy, 1), FlagName);
180 GV->setSection(FlagSymbolSection);
181 GV->setAlignment(Align(1));
183 attachDebugInfo(*GV, *SP);
184 return GV;
185 });
186 }
187
188 if (!CheckFunction) {
189 Function *DefaultCheckFunc =
190 createDefaultCheckFunction(M, UseX86FastCall);
191 if (IsELF) {
192 DefaultCheckFunc->setName(CheckFunctionName);
193 DefaultCheckFunc->setLinkage(GlobalValue::WeakAnyLinkage);
194 CheckFunction = DefaultCheckFunc;
195 } else {
196 assert(!M.getFunction(CheckFunctionName) &&
197 "JMC instrument more than once?");
198 auto *CheckFunc = cast<Function>(
199 M.getOrInsertFunction(CheckFunctionName, getCheckFunctionType(Ctx))
200 .getCallee());
201 CheckFunc->setUnnamedAddr(GlobalValue::UnnamedAddr::Global);
202 CheckFunc->addParamAttr(0, Attribute::NoUndef);
203 if (UseX86FastCall) {
204 CheckFunc->setCallingConv(CallingConv::X86_FastCall);
205 CheckFunc->addParamAttr(0, Attribute::InReg);
206 }
207 CheckFunction = CheckFunc;
208
209 StringRef DefaultCheckFunctionName = DefaultCheckFunc->getName();
210 appendToUsed(M, {DefaultCheckFunc});
211 Comdat *C = M.getOrInsertComdat(DefaultCheckFunctionName);
212 C->setSelectionKind(Comdat::Any);
213 DefaultCheckFunc->setComdat(C);
214 // Add a linker option /alternatename to set the default implementation
215 // for the check function.
216 // https://devblogs.microsoft.com/oldnewthing/20200731-00/?p=104024
217 std::string AltOption = std::string("/alternatename:") +
218 CheckFunctionName + "=" +
219 DefaultCheckFunctionName.str();
220 llvm::Metadata *Ops[] = {llvm::MDString::get(Ctx, AltOption)};
221 MDTuple *N = MDNode::get(Ctx, Ops);
222 M.getOrInsertNamedMetadata("llvm.linker.options")->addOperand(N);
223 }
224 }
225 // FIXME: it would be nice to make CI scheduling boundary, although in
226 // practice it does not matter much.
227 auto *CI = CallInst::Create(getCheckFunctionType(Ctx), CheckFunction,
228 {Flag}, "", F.begin()->getFirstInsertionPt());
229 CI->addParamAttr(0, Attribute::NoUndef);
230 if (UseX86FastCall) {
231 CI->setCallingConv(CallingConv::X86_FastCall);
232 CI->addParamAttr(0, Attribute::InReg);
233 }
234
235 Changed = true;
236 }
237 return Changed;
238}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static bool runImpl(Function &F, const TargetLowering &TLI, const LibcallLoweringInfo &Libcalls, AssumptionCache *AC)
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
const AbstractManglingParser< Derived, Alloc >::OperatorInfo AbstractManglingParser< Derived, Alloc >::Ops[]
static bool runImpl(Module &M)
#define F(x, y, z)
Definition MD5.cpp:54
Machine Check Debug Module
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
Definition PassSupport.h:56
This file defines the SmallString class.
This file contains some functions that are useful when dealing with strings.
LLVM Basic Block Representation.
Definition BasicBlock.h:62
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition BasicBlock.h:206
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", InsertPosition InsertBefore=nullptr)
@ Any
The linker may choose any COMDAT.
Definition Comdat.h:37
This is an important base class in LLVM.
Definition Constant.h:43
Subprogram description. Uses SubclassData1.
Class to represent function types.
static LLVM_ABI FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:166
void addParamAttr(unsigned ArgNo, Attribute::AttrKind Kind)
adds the attribute to the list of attributes for the given arg.
Definition Function.cpp:667
LLVM_ABI void setComdat(Comdat *C)
Definition Globals.cpp:215
LLVM_ABI void setSection(StringRef S)
Change the section for this global.
Definition Globals.cpp:276
LLVM_ABI void addMetadata(unsigned KindID, MDNode &MD)
Add a metadata attachment.
void setUnnamedAddr(UnnamedAddr Val)
void setLinkage(LinkageTypes LT)
Module * getParent()
Get the module that this global value is contained inside of...
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
Definition GlobalValue.h:57
void setAlignment(Align Align)
Sets the alignment attribute of the GlobalVariable.
Class to represent integer types.
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition Metadata.h:1571
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:614
Tuple of metadata.
Definition Metadata.h:1499
Root of the metadata hierarchy.
Definition Metadata.h:64
ModulePass class - This class is used to implement unstructured interprocedural optimizations and ana...
Definition Pass.h:255
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
Class to represent pointers.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the default address space (address sp...
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
static ReturnInst * Create(LLVMContext &C, Value *retVal=nullptr, InsertPosition InsertBefore=nullptr)
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
StringRef - Represent a constant reference to a string, i.e.
Definition StringRef.h:55
std::string str() const
str - Get the contents as an std::string.
Definition StringRef.h:225
Triple - Helper class for working with autoconf configuration names.
Definition Triple.h:47
ArchType getArch() const
Get the parsed architecture type of this triple.
Definition Triple.h:418
bool isOSBinFormatELF() const
Tests whether the OS uses the ELF binary format.
Definition Triple.h:791
bool isKnownWindowsMSVCEnvironment() const
Checks if the environment is MSVC.
Definition Triple.h:705
The instances of the Type class are immutable: once they are created, they are never changed.
Definition Type.h:45
static LLVM_ABI Type * getVoidTy(LLVMContext &C)
Definition Type.cpp:280
static LLVM_ABI IntegerType * getInt8Ty(LLVMContext &C)
Definition Type.cpp:294
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:397
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:322
Changed
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
@ X86_FastCall
'fast' analog of X86_StdCall.
LLVM_ABI void remove_filename(SmallVectorImpl< char > &path, Style style=Style::native)
Remove the last component from path unless it is the root dir.
Definition Path.cpp:475
LLVM_ABI bool has_root_name(const Twine &path, Style style=Style::native)
Has root name?
Definition Path.cpp:616
LLVM_ABI bool remove_dots(SmallVectorImpl< char > &path, bool remove_dot_dot=false, Style style=Style::native)
In-place remove any '.
Definition Path.cpp:765
LLVM_ABI StringRef filename(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Get filename.
Definition Path.cpp:578
LLVM_ABI void append(SmallVectorImpl< char > &path, const Twine &a, const Twine &b="", const Twine &c="", const Twine &d="")
Append to path.
Definition Path.cpp:457
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
LLVM_ABI ModulePass * createJMCInstrumenterPass()
JMC instrument pass.
std::string utohexstr(uint64_t X, bool LowerCase=false, unsigned Width=0)
uint32_t djbHash(StringRef Buffer, uint32_t H=5381)
The Bernstein hash function used by the DWARF accelerator tables.
Definition DJB.h:22
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI void appendToUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.used list.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
#define N
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition Alignment.h:39