LLVM 24.0.0git
DynamicDebugging.cpp
Go to the documentation of this file.
1//===- DynamicDebugging.cpp - Dynamic Debugging utils --------------------===//
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
10#include "llvm/IR/Module.h"
14
15using namespace llvm;
16
17std::unique_ptr<Module>
19 using namespace llvm;
20 assert(M->getNamedMetadata("llvm.dbg.cu") &&
21 "Expected module with debug info");
22
23 auto ShouldPromoteGlobal = [](const GlobalValue &GV) {
24 if (!GV.hasLocalLinkage())
25 return false;
26
27 // Local symbols in a comdat shouldn't be promoted either.
28 // This can happen with (at least) __cxx_global_var_init (which is local
29 // and may initialize an ODR-weak global variable).
30 if (GV.hasComdat())
31 return false;
32
33 return true;
34 };
35
36 // Clone functions definitions only - CloneModule will clone data definitions
37 // as declarations. We rename these and explicitly set their linkage later.
38 auto ShouldCloneDefinition = [](const GlobalValue *GV) {
39 return isa<Function>(GV);
40 };
42 std::unique_ptr<Module> UnoptM = CloneModule(*M, VMap, ShouldCloneDefinition);
43
44 // Insert declarations into Inner that point to Outer, apply attributes to
45 // Outer functions.
46 DenseMap<Function *, Function *> OuterDefToInnerDecl;
47 for (Function &OuterDef : M->functions()) {
48 if (OuterDef.isDeclaration())
49 continue;
50
51 // Find the Inner version of Outer's function.
52 Function *InnerDef = cast<Function>(VMap[&OuterDef]);
53
54 // Apply some attributes to both Inner and Outer defs.
55 {
56 // Unoptimized module wants no inlining at all.
57 InnerDef->addFnAttr(Attribute::NoInline);
58 InnerDef->removeFnAttr(Attribute::AlwaysInline);
59
60 // Apply optnone, remove clashing attributes.
61 InnerDef->addFnAttr(Attribute::OptimizeNone);
62 InnerDef->removeFnAttr(Attribute::OptimizeForSize);
63 InnerDef->removeFnAttr(Attribute::MinSize);
64
65 // Add attributes to the outer-object functions to ensure they're
66 // always patchable.
67 //
68 // The debugger patches outer (optimized) functions to redirect to inner
69 // (unoptimized) functions. Block interprocedural analysis to ensure
70 // the two function implementations share the same interface.
71 OuterDef.addFnAttr(Attribute::NoIPA);
72 // Outlining creates specialized functions in the outer (optimized)
73 // module without an inner (unoptimized) equivalent, meaning the debugger
74 // can't switch to an unoptimized version, so block outlining.
75 OuterDef.addFnAttr(Attribute::NoOutline);
76 // TODO: Add patch bytes size/value for other targets.
77 if (M->getTargetTriple().isX86_64()) {
78 OuterDef.addFnAttr("tail-pad-to-size", "5");
79 OuterDef.addFnAttr("tail-pad-value", "144"); // 0x90
80 }
81 }
82
83 // Apply COMDAT grouping to the clone if OuterDef is in one.
84 if (OuterDef.hasComdat()) {
85 std::string NewComdat =
86 Twine("__dyndbg." + OuterDef.getComdat()->getName()).str();
87 Comdat *C = M->getOrInsertComdat(NewComdat);
88 C->setSelectionKind(OuterDef.getComdat()->getSelectionKind());
89 InnerDef->setComdat(C);
90 }
91
92 // Rename Inner's copy and set appropriate linkage depending on whether
93 // it'll get promoted in Outer or not.
94 if (ShouldPromoteGlobal(OuterDef)) {
95 InnerDef->setName("__dyndbg." + InnerDef->getName() + PromotionSuffix);
98 } else {
99 InnerDef->setName("__dyndbg." + InnerDef->getName());
100 InnerDef->setLinkage(OuterDef.getLinkage());
101 InnerDef->setVisibility(OuterDef.getVisibility());
102 }
103
104 // Create Inner's external reference to Outer's version.
105 Function *InnerDeclOfOuterDef = Function::Create(
106 cast<FunctionType>(OuterDef.getValueType()), OuterDef.getLinkage(),
107 OuterDef.getAddressSpace(), OuterDef.getName(), UnoptM.get());
108 InnerDeclOfOuterDef->copyAttributesFrom(&OuterDef);
109 // Re-set linkage and visibility after copyAttributesFrom.
110 InnerDeclOfOuterDef->setLinkage(GlobalValue::ExternalLinkage);
111 InnerDeclOfOuterDef->setPersonalityFn(nullptr);
112
113 // Replace Inner uses of function with that external reference.
114 InnerDef->replaceAllUsesWith(InnerDeclOfOuterDef);
115
116 VMap[&OuterDef] = InnerDeclOfOuterDef;
117 }
118
119 // Add Outer aliases for globals with internal linkage, adding
120 // ".dyndbg.<TU-unique-hash>" suffix. Update Inner's external references to
121 // these promoted functions to use their new names.
122 SmallVector<GlobalValue *> GlobalsToPreserve;
123 for (GlobalValue &GV : M->global_values()) {
124 // If the global is used but may be discarded after optimizations
125 // (e.g. inlining) then ensure it's marked as compiler-used to prevent
126 // that. It may be referenced from the inner module.
127 if (GV.isDiscardableIfUnused()) {
128 if (GV.getNumUses()) {
129 GlobalsToPreserve.push_back(&GV);
130 // Name unnamed globals. Compiler-used expects named globals only.
131 if (GV.getName().empty())
132 GV.setName("__unnamed");
133 } else {
134 // No uses, so the inner module doesn't need a reference nor do we need
135 // to produce an alias.
136 // Remove the inner module reference.
137 auto GVAndUnoptPair = VMap.find(&GV);
138 assert(GVAndUnoptPair != VMap.end() && "Unmapped global?");
139 // Delete the external reference - VMap should only contain mappings to
140 // those declarations now.
141 assert(cast<GlobalValue>(GVAndUnoptPair->second)->isDeclaration() &&
142 "expected only declarations in VMap now");
143 cast<GlobalValue>(GVAndUnoptPair->second)->eraseFromParent();
144 GVAndUnoptPair->second = nullptr;
145 // Nothing else to do for this global.
146 continue;
147 }
148 }
149
150 if (!ShouldPromoteGlobal(GV))
151 continue;
152
153 // We need external aliases with a mangled name and hidden visibility.
155 GV.getName() + PromotionSuffix, &GV);
156 Alias->setVisibility(GlobalValue::HiddenVisibility);
157
158 // Update the Inner external reference that corresponds to the promoted
159 // Outer global (created just now as an alias in opt) to reference the new
160 // alias.
161 GlobalValue *UnoptGV = cast<GlobalValue>(VMap[&GV]);
162 UnoptGV->setName(Alias->getName());
165 "Expected ExternalLinkage from CloneModule or inserted decl");
166 }
167
168 // Preserve functions that may be discarded after optimizing away call sites
169 // (e.g. ODR-weak). Another desirable effect of this is that it prevents
170 // GlobalOpt promoting the alias. If the function-preservation mechanism
171 // changes in the future GlobalOpt alias promotion must be handled another
172 // way.
173 appendToCompilerUsed(*M, GlobalsToPreserve);
174
175 return UnoptM;
176}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
Module.h This file contains the declarations for the Module class.
void addFnAttr(Attribute::AttrKind Kind)
Add function attributes to this function.
Definition Function.cpp:637
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:168
void setPersonalityFn(Constant *Fn)
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
Definition Function.cpp:685
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
Definition Function.cpp:842
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
Definition Globals.cpp:692
LLVM_ABI void setComdat(Comdat *C)
Definition Globals.cpp:287
LinkageTypes getLinkage() const
void setLinkage(LinkageTypes LT)
@ HiddenVisibility
The GV is hidden.
Definition GlobalValue.h:69
void setVisibility(VisibilityTypes V)
@ ExternalLinkage
Externally visible function.
Definition GlobalValue.h:53
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
Definition Twine.cpp:17
iterator find(const KeyT &Val)
Definition ValueMap.h:160
iterator end()
Definition ValueMap.h:139
LLVM_ABI void setName(const Twine &Name)
Change the name of the value.
Definition Value.cpp:394
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:553
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
This is an optimization pass for GlobalISel generic memory operations.
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
LLVM_ABI std::unique_ptr< Module > CloneModule(const Module &M)
Return an exact copy of the specified module.
LLVM_ABI std::unique_ptr< Module > prepareForDynamicDebugging(Module *M, StringRef PromotionSuffix)
Modify M to prepare it for dynamic debugging before running optimizations.