LLVM 19.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"
34#include "llvm/Transforms/IPO.h"
37
38using namespace llvm;
39
40static cl::opt<bool>
41 StripGlobalConstants("strip-global-constants", cl::init(false), cl::Hidden,
42 cl::desc("Removes debug compile units which reference "
43 "to non-existing global constants"));
44
45/// OnlyUsedBy - Return true if V is only used by Usr.
46static bool OnlyUsedBy(Value *V, Value *Usr) {
47 for (User *U : V->users())
48 if (U != Usr)
49 return false;
50
51 return true;
52}
53
55 assert(C->use_empty() && "Constant is not dead!");
57 for (Value *Op : C->operands())
58 if (OnlyUsedBy(Op, C))
59 Operands.insert(cast<Constant>(Op));
60 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
61 if (!GV->hasLocalLinkage()) return; // Don't delete non-static globals.
62 GV->eraseFromParent();
63 } else if (!isa<Function>(C)) {
64 // FIXME: Why does the type of the constant matter here?
65 if (isa<StructType>(C->getType()) || isa<ArrayType>(C->getType()) ||
66 isa<VectorType>(C->getType()))
67 C->destroyConstant();
68 }
69
70 // If the constant referenced anything, see if we can delete it as well.
71 for (Constant *O : Operands)
73}
74
75// Strip the symbol table of its names.
76//
77static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) {
78 for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) {
79 Value *V = VI->getValue();
80 ++VI;
81 if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasLocalLinkage()) {
82 if (!PreserveDbgInfo || !V->getName().starts_with("llvm.dbg"))
83 // Set name to "", removing from symbol table!
84 V->setName("");
85 }
86 }
87}
88
89// Strip any named types of their names.
90static void StripTypeNames(Module &M, bool PreserveDbgInfo) {
91 TypeFinder StructTypes;
92 StructTypes.run(M, false);
93
94 for (StructType *STy : StructTypes) {
95 if (STy->isLiteral() || STy->getName().empty()) continue;
96
97 if (PreserveDbgInfo && STy->getName().starts_with("llvm.dbg"))
98 continue;
99
100 STy->setName("");
101 }
102}
103
104/// Find values that are marked as llvm.used.
105static void findUsedValues(GlobalVariable *LLVMUsed,
107 if (!LLVMUsed) return;
108 UsedValues.insert(LLVMUsed);
109
110 ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer());
111
112 for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i)
113 if (GlobalValue *GV =
114 dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts()))
115 UsedValues.insert(GV);
116}
117
118/// StripSymbolNames - Strip symbol names.
119static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) {
120
122 findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues);
123 findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues);
124
125 for (GlobalVariable &GV : M.globals()) {
126 if (GV.hasLocalLinkage() && !llvmUsedValues.contains(&GV))
127 if (!PreserveDbgInfo || !GV.getName().starts_with("llvm.dbg"))
128 GV.setName(""); // Internal symbols can't participate in linkage
129 }
130
131 for (Function &I : M) {
132 if (I.hasLocalLinkage() && !llvmUsedValues.contains(&I))
133 if (!PreserveDbgInfo || !I.getName().starts_with("llvm.dbg"))
134 I.setName(""); // Internal symbols can't participate in linkage
135 if (auto *Symtab = I.getValueSymbolTable())
136 StripSymtab(*Symtab, PreserveDbgInfo);
137 }
138
139 // Remove all names from types.
140 StripTypeNames(M, PreserveDbgInfo);
141
142 return true;
143}
144
146
147 Function *Declare = M.getFunction("llvm.dbg.declare");
148 std::vector<Constant*> DeadConstants;
149
150 if (Declare) {
151 while (!Declare->use_empty()) {
152 CallInst *CI = cast<CallInst>(Declare->user_back());
153 Value *Arg1 = CI->getArgOperand(0);
154 Value *Arg2 = CI->getArgOperand(1);
155 assert(CI->use_empty() && "llvm.dbg intrinsic should have void result");
156 CI->eraseFromParent();
157 if (Arg1->use_empty()) {
158 if (Constant *C = dyn_cast<Constant>(Arg1))
159 DeadConstants.push_back(C);
160 else
162 }
163 if (Arg2->use_empty())
164 if (Constant *C = dyn_cast<Constant>(Arg2))
165 DeadConstants.push_back(C);
166 }
167 Declare->eraseFromParent();
168 }
169
170 while (!DeadConstants.empty()) {
171 Constant *C = DeadConstants.back();
172 DeadConstants.pop_back();
173 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) {
174 if (GV->hasLocalLinkage())
176 } else
178 }
179
180 return true;
181}
182
184 bool Changed = false;
185
186 LLVMContext &C = M.getContext();
187
188 // Find all debug info in F. This is actually overkill in terms of what we
189 // want to do, but we want to try and be as resilient as possible in the face
190 // of potential debug info changes by using the formal interfaces given to us
191 // as much as possible.
193 F.processModule(M);
194
195 // For each compile unit, find the live set of global variables/functions and
196 // replace the current list of potentially dead global variables/functions
197 // with the live list.
198 SmallVector<Metadata *, 64> LiveGlobalVariables;
200
201 std::set<DIGlobalVariableExpression *> LiveGVs;
202 for (GlobalVariable &GV : M.globals()) {
204 GV.getDebugInfo(GVEs);
205 for (auto *GVE : GVEs)
206 LiveGVs.insert(GVE);
207 }
208
209 std::set<DICompileUnit *> LiveCUs;
210 DebugInfoFinder LiveCUFinder;
211 for (const Function &F : M.functions()) {
212 if (auto *SP = cast_or_null<DISubprogram>(F.getSubprogram()))
213 LiveCUFinder.processSubprogram(SP);
214 for (const Instruction &I : instructions(F))
215 LiveCUFinder.processInstruction(M, I);
216 }
217 auto FoundCUs = LiveCUFinder.compile_units();
218 LiveCUs.insert(FoundCUs.begin(), FoundCUs.end());
219
220 bool HasDeadCUs = false;
221 for (DICompileUnit *DIC : F.compile_units()) {
222 // Create our live global variable list.
223 bool GlobalVariableChange = false;
224 for (auto *DIG : DIC->getGlobalVariables()) {
225 if (DIG->getExpression() && DIG->getExpression()->isConstant() &&
227 LiveGVs.insert(DIG);
228
229 // Make sure we only visit each global variable only once.
230 if (!VisitedSet.insert(DIG).second)
231 continue;
232
233 // If a global variable references DIG, the global variable is live.
234 if (LiveGVs.count(DIG))
235 LiveGlobalVariables.push_back(DIG);
236 else
237 GlobalVariableChange = true;
238 }
239
240 if (!LiveGlobalVariables.empty())
241 LiveCUs.insert(DIC);
242 else if (!LiveCUs.count(DIC))
243 HasDeadCUs = true;
244
245 // If we found dead global variables, replace the current global
246 // variable list with our new live global variable list.
247 if (GlobalVariableChange) {
248 DIC->replaceGlobalVariables(MDTuple::get(C, LiveGlobalVariables));
249 Changed = true;
250 }
251
252 // Reset lists for the next iteration.
253 LiveGlobalVariables.clear();
254 }
255
256 if (HasDeadCUs) {
257 // Delete the old node and replace it with a new one
258 NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu");
259 NMD->clearOperands();
260 if (!LiveCUs.empty()) {
261 for (DICompileUnit *CU : LiveCUs)
262 NMD->addOperand(CU);
263 }
264 Changed = true;
265 }
266
267 return Changed;
268}
269
272 StripSymbolNames(M, false);
275 return PA;
276}
277
280 StripSymbolNames(M, true);
283 return PA;
284}
285
291 return PA;
292}
293
299 return PA;
300}
Expand Atomic instructions
This file contains the declarations for the subclasses of Constant, which represent the different fla...
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
mir Rename Register Operands
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
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:321
Represents analyses that only rely on functions' control flow.
Definition: Analysis.h:70
Value * getArgOperand(unsigned i) const
Definition: InstrTypes.h:1660
This class represents a function call, abstracting a target machine's calling convention.
ConstantArray - Constant Array Declarations.
Definition: Constants.h:423
This is an important base class in LLVM.
Definition: Constant.h:41
This class represents an Operation in the Expression.
Utility to find all debug info in a module.
Definition: DebugInfo.h:103
void processInstruction(const Module &M, const Instruction &I)
Process a single instruction and collect debug info anchors.
Definition: DebugInfo.cpp:242
void processSubprogram(DISubprogram *SP)
Process subprogram.
Definition: DebugInfo.cpp:317
iterator_range< compile_unit_iterator > compile_units() const
Definition: DebugInfo.h:143
Implements a dense probed hash-table based set.
Definition: DenseSet.h:271
void eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing module and deletes it.
Definition: Function.cpp:403
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.
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:1498
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:1729
void clearOperands()
Drop all references to this node's operands.
Definition: Metadata.cpp:1397
void addOperand(MDNode *M)
Definition: Metadata.cpp:1388
A set of analyses that are preserved following a run of a transformation pass.
Definition: Analysis.h:109
void preserveSet()
Mark an analysis set as preserved.
Definition: Analysis.h:144
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
Definition: SmallPtrSet.h:321
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:342
bool contains(ConstPtrType Ptr) const
Definition: SmallPtrSet.h:366
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
Definition: SmallPtrSet.h:427
bool empty() const
Definition: SmallVector.h:94
iterator insert(iterator I, T &&Elt)
Definition: SmallVector.h:818
void push_back(const T &Elt)
Definition: SmallVector.h:426
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
Class to represent struct types.
Definition: DerivedTypes.h:216
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:169
unsigned getNumOperands() const
Definition: User.h:191
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:693
bool use_empty() const
Definition: Value.h:344
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
initializer< Ty > init(const Ty &Val)
Definition: CommandLine.h:450
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:539
bool StripDebugInfo(Module &M)
Strip debug info in the module if it exists.
Definition: DebugInfo.cpp:594
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)