LLVM 20.0.0git
StripSymbols.cpp
Go to the documentation of this file.
1//===- StripSymbols.cpp - Strip symbols and debug info from a module ------===//
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// The StripSymbols transformation implements code stripping. Specifically, it
10// can delete:
11//
12// * names for virtual registers
13// * symbols for internal globals and functions
14// * debug information
15//
16// Note that this transformation makes code much less readable, so it should
17// only be used in situations where the 'strip' utility would be used, such as
18// reducing code size or making it harder to reverse engineer code.
19//
20//===----------------------------------------------------------------------===//
21
24#include "llvm/IR/Constants.h"
25#include "llvm/IR/DebugInfo.h"
29#include "llvm/IR/Module.h"
30#include "llvm/IR/PassManager.h"
31#include "llvm/IR/TypeFinder.h"
36
37using namespace llvm;
38
39static cl::opt<bool>
40 StripGlobalConstants("strip-global-constants", cl::init(false), cl::Hidden,
41 cl::desc("Removes debug compile units which reference "
42 "to non-existing global constants"));
43
44/// OnlyUsedBy - Return true if V is only used by Usr.
45static bool OnlyUsedBy(Value *V, Value *Usr) {
46 for (User *U : V->users())
47 if (U != Usr)
48 return false;
49
50 return true;
51}
52
54 assert(C->use_empty() && "Constant is not dead!");
56 for (Value *Op : C->operands())
57 if (OnlyUsedBy(Op, C))
58 Operands.insert(cast<Constant>(Op));
59 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
60 if (!GV->hasLocalLinkage()) return; // Don't delete non-static globals.
61 GV->eraseFromParent();
62 } else if (!isa<Function>(C)) {
63 // FIXME: Why does the type of the constant matter here?
64 if (isa<StructType>(C->getType()) || isa<ArrayType>(C->getType()) ||
65 isa<VectorType>(C->getType()))
66 C->destroyConstant();
67 }
68
69 // If the constant referenced anything, see if we can delete it as well.
70 for (Constant *O : Operands)
72}
73
74// Strip the symbol table of its names.
75//
76static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) {
77 for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) {
78 Value *V = VI->getValue();
79 ++VI;
80 if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasLocalLinkage()) {
81 if (!PreserveDbgInfo || !V->getName().starts_with("llvm.dbg"))
82 // Set name to "", removing from symbol table!
83 V->setName("");
84 }
85 }
86}
87
88// Strip any named types of their names.
89static void StripTypeNames(Module &M, bool PreserveDbgInfo) {
90 TypeFinder StructTypes;
91 StructTypes.run(M, false);
92
93 for (StructType *STy : StructTypes) {
94 if (STy->isLiteral() || STy->getName().empty()) continue;
95
96 if (PreserveDbgInfo && STy->getName().starts_with("llvm.dbg"))
97 continue;
98
99 STy->setName("");
100 }
101}
102
103/// Find values that are marked as llvm.used.
104static void findUsedValues(GlobalVariable *LLVMUsed,
106 if (!LLVMUsed) return;
107 UsedValues.insert(LLVMUsed);
108
109 ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
110
111 for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
112 if (GlobalValue *GV =
113 dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
114 UsedValues.insert(GV);
115}
116
117/// StripSymbolNames - Strip symbol names.
118static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {
119
121 findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues);
122 findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues);
123
124 for (GlobalVariable &GV : M.globals()) {
125 if (GV.hasLocalLinkage() && !llvmUsedValues.contains(&GV))
126 if (!PreserveDbgInfo || !GV.getName().starts_with("llvm.dbg"))
127 GV.setName(""); // Internal symbols can't participate in linkage
128 }
129
130 for (Function &I : M) {
131 if (I.hasLocalLinkage() && !llvmUsedValues.contains(&I))
132 if (!PreserveDbgInfo || !I.getName().starts_with("llvm.dbg"))
133 I.setName(""); // Internal symbols can't participate in linkage
134 if (auto *Symtab = I.getValueSymbolTable())
135 StripSymtab(*Symtab, PreserveDbgInfo);
136 }
137
138 // Remove all names from types.
139 StripTypeNames(M, PreserveDbgInfo);
140
141 return true;
142}
143
145 Function *Declare =
146 Intrinsic::getDeclarationIfExists(&M, Intrinsic::dbg_declare);
147 std::vector<Constant*> DeadConstants;
148
149 if (Declare) {
150 while (!Declare->use_empty()) {
151 CallInst *CI = cast<CallInst>(Declare->user_back());
152 Value *Arg1 = CI->getArgOperand(0);
153 Value *Arg2 = CI->getArgOperand(1);
154 assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
155 CI->eraseFromParent();
156 if (Arg1->use_empty()) {
157 if (Constant *C = dyn_cast<Constant>(Arg1))
158 DeadConstants.push_back(C);
159 else
161 }
162 if (Arg2->use_empty())
163 if (Constant *C = dyn_cast<Constant>(Arg2))
164 DeadConstants.push_back(C);
165 }
166 Declare->eraseFromParent();
167 }
168
169 while (!DeadConstants.empty()) {
170 Constant *C = DeadConstants.back();
171 DeadConstants.pop_back();
172 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
173 if (GV->hasLocalLinkage())
175 } else
177 }
178
179 return true;
180}
181
183 bool Changed = false;
184
185 LLVMContext &C = M.getContext();
186
187 // Find all debug info in F. This is actually overkill in terms of what we
188 // want to do, but we want to try and be as resilient as possible in the face
189 // of potential debug info changes by using the formal interfaces given to us
190 // as much as possible.
192 F.processModule(M);
193
194 // For each compile unit, find the live set of global variables/functions and
195 // replace the current list of potentially dead global variables/functions
196 // with the live list.
197 SmallVector<Metadata *, 64> LiveGlobalVariables;
199
200 std::set<DIGlobalVariableExpression *> LiveGVs;
201 for (GlobalVariable &GV : M.globals()) {
203 GV.getDebugInfo(GVEs);
204 for (auto *GVE : GVEs)
205 LiveGVs.insert(GVE);
206 }
207
208 std::set<DICompileUnit *> LiveCUs;
209 DebugInfoFinder LiveCUFinder;
210 for (const Function &F : M.functions()) {
211 if (auto *SP = cast_or_null<DISubprogram>(F.getSubprogram()))
212 LiveCUFinder.processSubprogram(SP);
213 for (const Instruction &I : instructions(F))
214 LiveCUFinder.processInstruction(M, I);
215 }
216 auto FoundCUs = LiveCUFinder.compile_units();
217 LiveCUs.insert(FoundCUs.begin(), FoundCUs.end());
218
219 bool HasDeadCUs = false;
220 for (DICompileUnit *DIC : F.compile_units()) {
221 // Create our live global variable list.
222 bool GlobalVariableChange = false;
223 for (auto *DIG : DIC->getGlobalVariables()) {
224 if (DIG->getExpression() && DIG->getExpression()->isConstant() &&
226 LiveGVs.insert(DIG);
227
228 // Make sure we only visit each global variable only once.
229 if (!VisitedSet.insert(DIG).second)
230 continue;
231
232 // If a global variable references DIG, the global variable is live.
233 if (LiveGVs.count(DIG))
234 LiveGlobalVariables.push_back(DIG);
235 else
236 GlobalVariableChange = true;
237 }
238
239 if (!LiveGlobalVariables.empty())
240 LiveCUs.insert(DIC);
241 else if (!LiveCUs.count(DIC))
242 HasDeadCUs = true;
243
244 // If we found dead global variables, replace the current global
245 // variable list with our new live global variable list.
246 if (GlobalVariableChange) {
247 DIC->replaceGlobalVariables(MDTuple::get(C, LiveGlobalVariables));
248 Changed = true;
249 }
250
251 // Reset lists for the next iteration.
252 LiveGlobalVariables.clear();
253 }
254
255 if (HasDeadCUs) {
256 // Delete the old node and replace it with a new one
257 NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu");
258 NMD->clearOperands();
259 if (!LiveCUs.empty()) {
260 for (DICompileUnit *CU : LiveCUs)
261 NMD->addOperand(CU);
262 }
263 Changed = true;
264 }
265
266 return Changed;
267}
268
271 StripSymbolNames(M, false);
274 return PA;
275}
276
279 StripSymbolNames(M, true);
282 return PA;
283}
284
290 return PA;
291}
292
298 return PA;
299}
Expand Atomic instructions
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
mir Rename Register Operands
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallPtrSet class.
static bool stripDeadDebugInfoImpl(Module &M)
static bool stripDebugDeclareImpl(Module &M)
static bool OnlyUsedBy(Value *V, Value *Usr)
OnlyUsedBy - Return true if V is only used by Usr.
static cl::opt< bool > StripGlobalConstants("strip-global-constants", cl::init(false), cl::Hidden, cl::desc("Removes debug compile units which reference " "to non-existing global constants"))
static void findUsedValues(GlobalVariable *LLVMUsed, SmallPtrSetImpl< const GlobalValue * > &UsedValues)
Find values that are marked as llvm.used.
static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo)
static void StripTypeNames(Module &M, bool PreserveDbgInfo)
static bool StripSymbolNames(Module &M, bool PreserveDbgInfo)
StripSymbolNames - Strip symbol names.
static void RemoveDeadConstant(Constant *C)
A container for analyses that lazily runs them and caches their results.
Definition: PassManager.h:253
Represents analyses that only rely on functions' control flow.
Definition: Analysis.h:72
Value * getArgOperand(unsigned i) const
Definition: InstrTypes.h:1294
This class represents a function call, abstracting a target machine's calling convention.
ConstantArray - Constant Array Declarations.
Definition: Constants.h:427
This is an important base class in LLVM.
Definition: Constant.h:42
This class represents an Operation in the Expression.
Utility to find all debug info in a module.
Definition: DebugInfo.h:105
void processInstruction(const Module &M, const Instruction &I)
Process a single instruction and collect debug info anchors.
Definition: DebugInfo.cpp:256
void processSubprogram(DISubprogram *SP)
Process subprogram.
Definition: DebugInfo.cpp:331
iterator_range< compile_unit_iterator > compile_units() const
Definition: DebugInfo.h:145
Implements a dense probed hash-table based set.
Definition: DenseSet.h:278
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition: Function.cpp:458
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:92
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
Definition: Metadata.h:1500
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
A tuple of MDNodes.
Definition: Metadata.h:1731
void clearOperands()
Drop all references to this node's operands.
Definition: Metadata.cpp:1440
void addOperand(MDNode *M)
Definition: Metadata.cpp:1431
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:111
void preserveSet()
Mark an analysis set as preserved.
Definition: Analysis.h:146
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
Definition: SmallPtrSet.h:363
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
Definition: SmallPtrSet.h:384
bool contains(ConstPtrType Ptr) const
Definition: SmallPtrSet.h:458
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:519
bool empty() const
Definition: SmallVector.h:81
iterator insert(iterator I, T &&Elt)
Definition: SmallVector.h:805
void push_back(const T &Elt)
Definition: SmallVector.h:413
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
Class to represent struct types.
Definition: DerivedTypes.h:218
TypeFinder - Walk over a module, identifying all of the types that are used by the module.
Definition: TypeFinder.h:31
void run(const Module &M, bool onlyNamed)
Definition: TypeFinder.cpp:34
Value * getOperand(unsigned i) const
Definition: User.h:228
unsigned getNumOperands() const
Definition: User.h:250
This class provides a symbol table of name/value pairs.
LLVM Value Representation.
Definition: Value.h:74
User * user_back()
Definition: Value.h:407
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
Definition: Value.cpp:694
bool use_empty() const
Definition: Value.h:344
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:213
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
Function * getDeclarationIfExists(Module *M, ID id, ArrayRef< Type * > Tys, FunctionType *FT=nullptr)
This version supports overloaded intrinsics.
Definition: Intrinsics.cpp:746
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:443
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr, MemorySSAUpdater *MSSAU=nullptr, std::function< void(Value *)> AboutToDeleteCallback=std::function< void(Value *)>())
If the specified value is a trivially dead instruction, delete it.
Definition: Local.cpp:546
bool StripDebugInfo(Module &M)
Strip debug info in the module if it exists.
Definition: DebugInfo.cpp:608
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)