/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Transforms/IPO/StripSymbols.cpp
Line | Count | Source (jump to first uncovered line) |
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 | | |
22 | | #include "llvm/ADT/SmallPtrSet.h" |
23 | | #include "llvm/Transforms/Utils/Local.h" |
24 | | #include "llvm/IR/Constants.h" |
25 | | #include "llvm/IR/DebugInfo.h" |
26 | | #include "llvm/IR/DerivedTypes.h" |
27 | | #include "llvm/IR/Instructions.h" |
28 | | #include "llvm/IR/Module.h" |
29 | | #include "llvm/IR/TypeFinder.h" |
30 | | #include "llvm/IR/ValueSymbolTable.h" |
31 | | #include "llvm/Pass.h" |
32 | | #include "llvm/Transforms/IPO.h" |
33 | | using namespace llvm; |
34 | | |
35 | | namespace { |
36 | | class StripSymbols : public ModulePass { |
37 | | bool OnlyDebugInfo; |
38 | | public: |
39 | | static char ID; // Pass identification, replacement for typeid |
40 | | explicit StripSymbols(bool ODI = false) |
41 | 26 | : ModulePass(ID), OnlyDebugInfo(ODI) { |
42 | 26 | initializeStripSymbolsPass(*PassRegistry::getPassRegistry()); |
43 | 26 | } |
44 | | |
45 | | bool runOnModule(Module &M) override; |
46 | | |
47 | 26 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
48 | 26 | AU.setPreservesAll(); |
49 | 26 | } |
50 | | }; |
51 | | |
52 | | class StripNonDebugSymbols : public ModulePass { |
53 | | public: |
54 | | static char ID; // Pass identification, replacement for typeid |
55 | | explicit StripNonDebugSymbols() |
56 | 0 | : ModulePass(ID) { |
57 | 0 | initializeStripNonDebugSymbolsPass(*PassRegistry::getPassRegistry()); |
58 | 0 | } |
59 | | |
60 | | bool runOnModule(Module &M) override; |
61 | | |
62 | 0 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
63 | 0 | AU.setPreservesAll(); |
64 | 0 | } |
65 | | }; |
66 | | |
67 | | class StripDebugDeclare : public ModulePass { |
68 | | public: |
69 | | static char ID; // Pass identification, replacement for typeid |
70 | | explicit StripDebugDeclare() |
71 | 0 | : ModulePass(ID) { |
72 | 0 | initializeStripDebugDeclarePass(*PassRegistry::getPassRegistry()); |
73 | 0 | } |
74 | | |
75 | | bool runOnModule(Module &M) override; |
76 | | |
77 | 0 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
78 | 0 | AU.setPreservesAll(); |
79 | 0 | } |
80 | | }; |
81 | | |
82 | | class StripDeadDebugInfo : public ModulePass { |
83 | | public: |
84 | | static char ID; // Pass identification, replacement for typeid |
85 | | explicit StripDeadDebugInfo() |
86 | 21 | : ModulePass(ID) { |
87 | 21 | initializeStripDeadDebugInfoPass(*PassRegistry::getPassRegistry()); |
88 | 21 | } |
89 | | |
90 | | bool runOnModule(Module &M) override; |
91 | | |
92 | 21 | void getAnalysisUsage(AnalysisUsage &AU) const override { |
93 | 21 | AU.setPreservesAll(); |
94 | 21 | } |
95 | | }; |
96 | | } |
97 | | |
98 | | char StripSymbols::ID = 0; |
99 | | INITIALIZE_PASS(StripSymbols, "strip", |
100 | | "Strip all symbols from a module", false, false) |
101 | | |
102 | 11 | ModulePass *llvm::createStripSymbolsPass(bool OnlyDebugInfo) { |
103 | 11 | return new StripSymbols(OnlyDebugInfo); |
104 | 11 | } |
105 | | |
106 | | char StripNonDebugSymbols::ID = 0; |
107 | | INITIALIZE_PASS(StripNonDebugSymbols, "strip-nondebug", |
108 | | "Strip all symbols, except dbg symbols, from a module", |
109 | | false, false) |
110 | | |
111 | 0 | ModulePass *llvm::createStripNonDebugSymbolsPass() { |
112 | 0 | return new StripNonDebugSymbols(); |
113 | 0 | } |
114 | | |
115 | | char StripDebugDeclare::ID = 0; |
116 | | INITIALIZE_PASS(StripDebugDeclare, "strip-debug-declare", |
117 | | "Strip all llvm.dbg.declare intrinsics", false, false) |
118 | | |
119 | 0 | ModulePass *llvm::createStripDebugDeclarePass() { |
120 | 0 | return new StripDebugDeclare(); |
121 | 0 | } |
122 | | |
123 | | char StripDeadDebugInfo::ID = 0; |
124 | | INITIALIZE_PASS(StripDeadDebugInfo, "strip-dead-debug-info", |
125 | | "Strip debug info for unused symbols", false, false) |
126 | | |
127 | 19 | ModulePass *llvm::createStripDeadDebugInfoPass() { |
128 | 19 | return new StripDeadDebugInfo(); |
129 | 19 | } |
130 | | |
131 | | /// OnlyUsedBy - Return true if V is only used by Usr. |
132 | 0 | static bool OnlyUsedBy(Value *V, Value *Usr) { |
133 | 0 | for (User *U : V->users()) |
134 | 0 | if (U != Usr) |
135 | 0 | return false; |
136 | 0 |
|
137 | 0 | return true; |
138 | 0 | } |
139 | | |
140 | 0 | static void RemoveDeadConstant(Constant *C) { |
141 | 0 | assert(C->use_empty() && "Constant is not dead!"); |
142 | 0 | SmallPtrSet<Constant*, 4> Operands; |
143 | 0 | for (Value *Op : C->operands()) |
144 | 0 | if (OnlyUsedBy(Op, C)) |
145 | 0 | Operands.insert(cast<Constant>(Op)); |
146 | 0 | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) { |
147 | 0 | if (!GV->hasLocalLinkage()) return; // Don't delete non-static globals. |
148 | 0 | GV->eraseFromParent(); |
149 | 0 | } |
150 | 0 | else if (!isa<Function>(C)) |
151 | 0 | if (isa<CompositeType>(C->getType())) |
152 | 0 | C->destroyConstant(); |
153 | 0 |
|
154 | 0 | // If the constant referenced anything, see if we can delete it as well. |
155 | 0 | for (Constant *O : Operands) |
156 | 0 | RemoveDeadConstant(O); |
157 | 0 | } |
158 | | |
159 | | // Strip the symbol table of its names. |
160 | | // |
161 | 44 | static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) { |
162 | 126 | for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) { |
163 | 82 | Value *V = VI->getValue(); |
164 | 82 | ++VI; |
165 | 82 | if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasLocalLinkage()0 ) { |
166 | 82 | if (!PreserveDbgInfo || !V->getName().startswith("llvm.dbg")0 ) |
167 | 82 | // Set name to "", removing from symbol table! |
168 | 82 | V->setName(""); |
169 | 82 | } |
170 | 82 | } |
171 | 44 | } |
172 | | |
173 | | // Strip any named types of their names. |
174 | 15 | static void StripTypeNames(Module &M, bool PreserveDbgInfo) { |
175 | 15 | TypeFinder StructTypes; |
176 | 15 | StructTypes.run(M, false); |
177 | 15 | |
178 | 20 | for (unsigned i = 0, e = StructTypes.size(); i != e; ++i5 ) { |
179 | 5 | StructType *STy = StructTypes[i]; |
180 | 5 | if (STy->isLiteral() || STy->getName().empty()) continue0 ; |
181 | 5 | |
182 | 5 | if (PreserveDbgInfo && STy->getName().startswith("llvm.dbg")0 ) |
183 | 0 | continue; |
184 | 5 | |
185 | 5 | STy->setName(""); |
186 | 5 | } |
187 | 15 | } |
188 | | |
189 | | /// Find values that are marked as llvm.used. |
190 | | static void findUsedValues(GlobalVariable *LLVMUsed, |
191 | 30 | SmallPtrSetImpl<const GlobalValue*> &UsedValues) { |
192 | 30 | if (!LLVMUsed) return29 ; |
193 | 1 | UsedValues.insert(LLVMUsed); |
194 | 1 | |
195 | 1 | ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer()); |
196 | 1 | |
197 | 3 | for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i2 ) |
198 | 2 | if (GlobalValue *GV = |
199 | 2 | dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts())) |
200 | 2 | UsedValues.insert(GV); |
201 | 1 | } |
202 | | |
203 | | /// StripSymbolNames - Strip symbol names. |
204 | 15 | static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) { |
205 | 15 | |
206 | 15 | SmallPtrSet<const GlobalValue*, 8> llvmUsedValues; |
207 | 15 | findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues); |
208 | 15 | findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues); |
209 | 15 | |
210 | 15 | for (Module::global_iterator I = M.global_begin(), E = M.global_end(); |
211 | 30 | I != E; ++I15 ) { |
212 | 15 | if (I->hasLocalLinkage() && llvmUsedValues.count(&*I) == 01 ) |
213 | 0 | if (!PreserveDbgInfo || !I->getName().startswith("llvm.dbg")) |
214 | 0 | I->setName(""); // Internal symbols can't participate in linkage |
215 | 15 | } |
216 | 15 | |
217 | 44 | for (Function &I : M) { |
218 | 44 | if (I.hasLocalLinkage() && llvmUsedValues.count(&I) == 01 ) |
219 | 0 | if (!PreserveDbgInfo || !I.getName().startswith("llvm.dbg")) |
220 | 0 | I.setName(""); // Internal symbols can't participate in linkage |
221 | 44 | if (auto *Symtab = I.getValueSymbolTable()) |
222 | 44 | StripSymtab(*Symtab, PreserveDbgInfo); |
223 | 44 | } |
224 | 15 | |
225 | 15 | // Remove all names from types. |
226 | 15 | StripTypeNames(M, PreserveDbgInfo); |
227 | 15 | |
228 | 15 | return true; |
229 | 15 | } |
230 | | |
231 | 26 | bool StripSymbols::runOnModule(Module &M) { |
232 | 26 | if (skipModule(M)) |
233 | 0 | return false; |
234 | 26 | |
235 | 26 | bool Changed = false; |
236 | 26 | Changed |= StripDebugInfo(M); |
237 | 26 | if (!OnlyDebugInfo) |
238 | 15 | Changed |= StripSymbolNames(M, false); |
239 | 26 | return Changed; |
240 | 26 | } |
241 | | |
242 | 0 | bool StripNonDebugSymbols::runOnModule(Module &M) { |
243 | 0 | if (skipModule(M)) |
244 | 0 | return false; |
245 | 0 | |
246 | 0 | return StripSymbolNames(M, true); |
247 | 0 | } |
248 | | |
249 | 0 | bool StripDebugDeclare::runOnModule(Module &M) { |
250 | 0 | if (skipModule(M)) |
251 | 0 | return false; |
252 | 0 | |
253 | 0 | Function *Declare = M.getFunction("llvm.dbg.declare"); |
254 | 0 | std::vector<Constant*> DeadConstants; |
255 | 0 |
|
256 | 0 | if (Declare) { |
257 | 0 | while (!Declare->use_empty()) { |
258 | 0 | CallInst *CI = cast<CallInst>(Declare->user_back()); |
259 | 0 | Value *Arg1 = CI->getArgOperand(0); |
260 | 0 | Value *Arg2 = CI->getArgOperand(1); |
261 | 0 | assert(CI->use_empty() && "llvm.dbg intrinsic should have void result"); |
262 | 0 | CI->eraseFromParent(); |
263 | 0 | if (Arg1->use_empty()) { |
264 | 0 | if (Constant *C = dyn_cast<Constant>(Arg1)) |
265 | 0 | DeadConstants.push_back(C); |
266 | 0 | else |
267 | 0 | RecursivelyDeleteTriviallyDeadInstructions(Arg1); |
268 | 0 | } |
269 | 0 | if (Arg2->use_empty()) |
270 | 0 | if (Constant *C = dyn_cast<Constant>(Arg2)) |
271 | 0 | DeadConstants.push_back(C); |
272 | 0 | } |
273 | 0 | Declare->eraseFromParent(); |
274 | 0 | } |
275 | 0 |
|
276 | 0 | while (!DeadConstants.empty()) { |
277 | 0 | Constant *C = DeadConstants.back(); |
278 | 0 | DeadConstants.pop_back(); |
279 | 0 | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) { |
280 | 0 | if (GV->hasLocalLinkage()) |
281 | 0 | RemoveDeadConstant(GV); |
282 | 0 | } else |
283 | 0 | RemoveDeadConstant(C); |
284 | 0 | } |
285 | 0 |
|
286 | 0 | return true; |
287 | 0 | } |
288 | | |
289 | | /// Remove any debug info for global variables/functions in the given module for |
290 | | /// which said global variable/function no longer exists (i.e. is null). |
291 | | /// |
292 | | /// Debugging information is encoded in llvm IR using metadata. This is designed |
293 | | /// such a way that debug info for symbols preserved even if symbols are |
294 | | /// optimized away by the optimizer. This special pass removes debug info for |
295 | | /// such symbols. |
296 | 21 | bool StripDeadDebugInfo::runOnModule(Module &M) { |
297 | 21 | if (skipModule(M)) |
298 | 0 | return false; |
299 | 21 | |
300 | 21 | bool Changed = false; |
301 | 21 | |
302 | 21 | LLVMContext &C = M.getContext(); |
303 | 21 | |
304 | 21 | // Find all debug info in F. This is actually overkill in terms of what we |
305 | 21 | // want to do, but we want to try and be as resilient as possible in the face |
306 | 21 | // of potential debug info changes by using the formal interfaces given to us |
307 | 21 | // as much as possible. |
308 | 21 | DebugInfoFinder F; |
309 | 21 | F.processModule(M); |
310 | 21 | |
311 | 21 | // For each compile unit, find the live set of global variables/functions and |
312 | 21 | // replace the current list of potentially dead global variables/functions |
313 | 21 | // with the live list. |
314 | 21 | SmallVector<Metadata *, 64> LiveGlobalVariables; |
315 | 21 | DenseSet<DIGlobalVariableExpression *> VisitedSet; |
316 | 21 | |
317 | 21 | std::set<DIGlobalVariableExpression *> LiveGVs; |
318 | 21 | for (GlobalVariable &GV : M.globals()) { |
319 | 8 | SmallVector<DIGlobalVariableExpression *, 1> GVEs; |
320 | 8 | GV.getDebugInfo(GVEs); |
321 | 8 | for (auto *GVE : GVEs) |
322 | 1 | LiveGVs.insert(GVE); |
323 | 8 | } |
324 | 21 | |
325 | 21 | std::set<DICompileUnit *> LiveCUs; |
326 | 21 | // Any CU referenced from a subprogram is live. |
327 | 21 | for (DISubprogram *SP : F.subprograms()) { |
328 | 4 | if (SP->getUnit()) |
329 | 4 | LiveCUs.insert(SP->getUnit()); |
330 | 4 | } |
331 | 21 | |
332 | 21 | bool HasDeadCUs = false; |
333 | 21 | for (DICompileUnit *DIC : F.compile_units()) { |
334 | 5 | // Create our live global variable list. |
335 | 5 | bool GlobalVariableChange = false; |
336 | 5 | for (auto *DIG : DIC->getGlobalVariables()) { |
337 | 4 | if (DIG->getExpression() && DIG->getExpression()->isConstant()) |
338 | 1 | LiveGVs.insert(DIG); |
339 | 4 | |
340 | 4 | // Make sure we only visit each global variable only once. |
341 | 4 | if (!VisitedSet.insert(DIG).second) |
342 | 0 | continue; |
343 | 4 | |
344 | 4 | // If a global variable references DIG, the global variable is live. |
345 | 4 | if (LiveGVs.count(DIG)) |
346 | 2 | LiveGlobalVariables.push_back(DIG); |
347 | 2 | else |
348 | 2 | GlobalVariableChange = true; |
349 | 4 | } |
350 | 5 | |
351 | 5 | if (!LiveGlobalVariables.empty()) |
352 | 2 | LiveCUs.insert(DIC); |
353 | 3 | else if (!LiveCUs.count(DIC)) |
354 | 1 | HasDeadCUs = true; |
355 | 5 | |
356 | 5 | // If we found dead global variables, replace the current global |
357 | 5 | // variable list with our new live global variable list. |
358 | 5 | if (GlobalVariableChange) { |
359 | 2 | DIC->replaceGlobalVariables(MDTuple::get(C, LiveGlobalVariables)); |
360 | 2 | Changed = true; |
361 | 2 | } |
362 | 5 | |
363 | 5 | // Reset lists for the next iteration. |
364 | 5 | LiveGlobalVariables.clear(); |
365 | 5 | } |
366 | 21 | |
367 | 21 | if (HasDeadCUs) { |
368 | 1 | // Delete the old node and replace it with a new one |
369 | 1 | NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); |
370 | 1 | NMD->clearOperands(); |
371 | 1 | if (!LiveCUs.empty()) { |
372 | 1 | for (DICompileUnit *CU : LiveCUs) |
373 | 3 | NMD->addOperand(CU); |
374 | 1 | } |
375 | 1 | Changed = true; |
376 | 1 | } |
377 | 21 | |
378 | 21 | return Changed; |
379 | 21 | } |