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 for (Function &OuterDef : M->functions()) {
47 if (OuterDef.isDeclaration())
48 continue;
49
50 // Find the Inner version of Outer's function.
51 Function *InnerDef = cast<Function>(VMap[&OuterDef]);
52
53 // Apply some attributes to both Inner and Outer defs.
54 {
55 // Unoptimized module wants no inlining at all.
56 InnerDef->addFnAttr(Attribute::NoInline);
57 InnerDef->removeFnAttr(Attribute::AlwaysInline);
58
59 // Apply optnone, remove clashing attributes.
60 InnerDef->addFnAttr(Attribute::OptimizeNone);
61 InnerDef->removeFnAttr(Attribute::OptimizeForSize);
62 InnerDef->removeFnAttr(Attribute::MinSize);
63
64 // Add attributes to the outer-object functions to ensure they're
65 // always patchable.
66 //
67 // The debugger patches outer (optimized) functions to redirect to inner
68 // (unoptimized) functions. Block interprocedural analysis to ensure
69 // the two function implementations share the same interface.
70 OuterDef.addFnAttr(Attribute::NoIPA);
71 // Outlining creates specialized functions in the outer (optimized)
72 // module without an inner (unoptimized) equivalent, meaning the debugger
73 // can't switch to an unoptimized version, so block outlining.
74 OuterDef.addFnAttr(Attribute::NoOutline);
75 // TODO: Add patch bytes size/value for other targets.
76 if (M->getTargetTriple().isX86_64()) {
77 OuterDef.addFnAttr("tail-pad-to-size", "5");
78 OuterDef.addFnAttr("tail-pad-value", "144"); // 0x90
79 }
80 }
81
82 // Apply COMDAT grouping to the clone if OuterDef is in one.
83 if (OuterDef.hasComdat()) {
84 std::string NewComdat =
85 Twine("__dyndbg." + OuterDef.getComdat()->getName()).str();
86 Comdat *C = M->getOrInsertComdat(NewComdat);
87 C->setSelectionKind(OuterDef.getComdat()->getSelectionKind());
88 InnerDef->setComdat(C);
89 }
90
91 // Rename Inner's copy and set appropriate linkage depending on whether
92 // it'll get promoted in Outer or not.
93 if (ShouldPromoteGlobal(OuterDef)) {
94 InnerDef->setName("__dyndbg." + InnerDef->getName() + PromotionSuffix);
97 } else {
98 InnerDef->setName("__dyndbg." + InnerDef->getName());
99 InnerDef->setLinkage(OuterDef.getLinkage());
100 InnerDef->setVisibility(OuterDef.getVisibility());
101 }
102
103 // Create Inner's external reference to Outer's version.
104 Function *InnerDeclOfOuterDef = Function::Create(
105 cast<FunctionType>(OuterDef.getValueType()), OuterDef.getLinkage(),
106 OuterDef.getAddressSpace(), OuterDef.getName(), UnoptM.get());
107 InnerDeclOfOuterDef->copyAttributesFrom(&OuterDef);
108 // Re-set linkage and visibility after copyAttributesFrom.
109 InnerDeclOfOuterDef->setLinkage(GlobalValue::ExternalLinkage);
110 InnerDeclOfOuterDef->setPersonalityFn(nullptr);
111
112 // Replace Inner uses of function with that external reference.
113 InnerDef->replaceAllUsesWith(InnerDeclOfOuterDef);
114
115 VMap[&OuterDef] = InnerDeclOfOuterDef;
116 }
117
118 // Add Outer aliases for globals with internal linkage, adding
119 // ".dyndbg.<TU-unique-hash>" suffix. Update Inner's external references to
120 // these promoted functions to use their new names.
121 SmallVector<GlobalValue *> GlobalsToPreserve;
122 for (GlobalValue &GV : M->global_values()) {
123 // If the global is used but may be discarded after optimizations
124 // (e.g. inlining) then ensure it's marked as compiler-used to prevent
125 // that. It may be referenced from the inner module.
126 if (GV.isDiscardableIfUnused()) {
127 if (GV.getNumUses()) {
128 GlobalsToPreserve.push_back(&GV);
129 // Name unnamed globals. Compiler-used expects named globals only.
130 if (GV.getName().empty())
131 GV.setName("__unnamed");
132 } else {
133 // No uses, so the inner module doesn't need a reference nor do we need
134 // to produce an alias.
135 // Remove the inner module reference.
136 auto GVAndUnoptPair = VMap.find(&GV);
137 assert(GVAndUnoptPair != VMap.end() && "Unmapped global?");
138 // Delete the external reference - VMap should only contain mappings to
139 // those declarations now.
140 assert(cast<GlobalValue>(GVAndUnoptPair->second)->isDeclaration() &&
141 "expected only declarations in VMap now");
142 cast<GlobalValue>(GVAndUnoptPair->second)->eraseFromParent();
143 GVAndUnoptPair->second = nullptr;
144 // Nothing else to do for this global.
145 continue;
146 }
147 }
148
149 if (!ShouldPromoteGlobal(GV))
150 continue;
151
152 // We need external aliases with a mangled name and hidden visibility.
154 GV.getName() + PromotionSuffix, &GV);
155 Alias->setVisibility(GlobalValue::HiddenVisibility);
156
157 // Update the Inner external reference that corresponds to the promoted
158 // Outer global (created just now as an alias in opt) to reference the new
159 // alias.
160 GlobalValue *UnoptGV = cast<GlobalValue>(VMap[&GV]);
161 UnoptGV->setName(Alias->getName());
164 "Expected ExternalLinkage from CloneModule or inserted decl");
165 }
166
167 // Preserve functions that may be discarded after optimizing away call sites
168 // (e.g. ODR-weak). Another desirable effect of this is that it prevents
169 // GlobalOpt promoting the alias. If the function-preservation mechanism
170 // changes in the future GlobalOpt alias promotion must be handled another
171 // way.
172 appendToCompilerUsed(*M, GlobalsToPreserve);
173
174 return UnoptM;
175}
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:641
static Function * Create(FunctionType *Ty, LinkageTypes Linkage, unsigned AddrSpace, const Twine &N="", Module *M=nullptr)
Definition Function.h:169
void setPersonalityFn(Constant *Fn)
void removeFnAttr(Attribute::AttrKind Kind)
Remove function attributes from this function.
Definition Function.cpp:689
void copyAttributesFrom(const Function *Src)
copyAttributesFrom - copy all additional attributes (those not needed to create a Function) from the ...
Definition Function.cpp:846
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:68
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:390
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:549
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:315
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.