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/Transforms/IPO/StripSymbols.h" 23 #include "llvm/ADT/SmallPtrSet.h" 24 #include "llvm/IR/Constants.h" 25 #include "llvm/IR/DebugInfo.h" 26 #include "llvm/IR/DerivedTypes.h" 27 #include "llvm/IR/InstIterator.h" 28 #include "llvm/IR/Instructions.h" 29 #include "llvm/IR/Module.h" 30 #include "llvm/IR/PassManager.h" 31 #include "llvm/IR/TypeFinder.h" 32 #include "llvm/IR/ValueSymbolTable.h" 33 #include "llvm/Transforms/IPO.h" 34 #include "llvm/Transforms/IPO/StripSymbols.h" 35 #include "llvm/Transforms/Utils/Local.h" 36 37 using namespace llvm; 38 39 /// OnlyUsedBy - Return true if V is only used by Usr. 40 static bool OnlyUsedBy(Value *V, Value *Usr) { 41 for (User *U : V->users()) 42 if (U != Usr) 43 return false; 44 45 return true; 46 } 47 48 static void RemoveDeadConstant(Constant *C) { 49 assert(C->use_empty() && "Constant is not dead!"); 50 SmallPtrSet<Constant*, 4> Operands; 51 for (Value *Op : C->operands()) 52 if (OnlyUsedBy(Op, C)) 53 Operands.insert(cast<Constant>(Op)); 54 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) { 55 if (!GV->hasLocalLinkage()) return; // Don't delete non-static globals. 56 GV->eraseFromParent(); 57 } else if (!isa<Function>(C)) { 58 // FIXME: Why does the type of the constant matter here? 59 if (isa<StructType>(C->getType()) || isa<ArrayType>(C->getType()) || 60 isa<VectorType>(C->getType())) 61 C->destroyConstant(); 62 } 63 64 // If the constant referenced anything, see if we can delete it as well. 65 for (Constant *O : Operands) 66 RemoveDeadConstant(O); 67 } 68 69 // Strip the symbol table of its names. 70 // 71 static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) { 72 for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) { 73 Value *V = VI->getValue(); 74 ++VI; 75 if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasLocalLinkage()) { 76 if (!PreserveDbgInfo || !V->getName().startswith("llvm.dbg")) 77 // Set name to "", removing from symbol table! 78 V->setName(""); 79 } 80 } 81 } 82 83 // Strip any named types of their names. 84 static void StripTypeNames(Module &M, bool PreserveDbgInfo) { 85 TypeFinder StructTypes; 86 StructTypes.run(M, false); 87 88 for (StructType *STy : StructTypes) { 89 if (STy->isLiteral() || STy->getName().empty()) continue; 90 91 if (PreserveDbgInfo && STy->getName().startswith("llvm.dbg")) 92 continue; 93 94 STy->setName(""); 95 } 96 } 97 98 /// Find values that are marked as llvm.used. 99 static void findUsedValues(GlobalVariable *LLVMUsed, 100 SmallPtrSetImpl<const GlobalValue*> &UsedValues) { 101 if (!LLVMUsed) return; 102 UsedValues.insert(LLVMUsed); 103 104 ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer()); 105 106 for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) 107 if (GlobalValue *GV = 108 dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts())) 109 UsedValues.insert(GV); 110 } 111 112 /// StripSymbolNames - Strip symbol names. 113 static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) { 114 115 SmallPtrSet<const GlobalValue*, 8> llvmUsedValues; 116 findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues); 117 findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues); 118 119 for (GlobalVariable &GV : M.globals()) { 120 if (GV.hasLocalLinkage() && !llvmUsedValues.contains(&GV)) 121 if (!PreserveDbgInfo || !GV.getName().startswith("llvm.dbg")) 122 GV.setName(""); // Internal symbols can't participate in linkage 123 } 124 125 for (Function &I : M) { 126 if (I.hasLocalLinkage() && !llvmUsedValues.contains(&I)) 127 if (!PreserveDbgInfo || !I.getName().startswith("llvm.dbg")) 128 I.setName(""); // Internal symbols can't participate in linkage 129 if (auto *Symtab = I.getValueSymbolTable()) 130 StripSymtab(*Symtab, PreserveDbgInfo); 131 } 132 133 // Remove all names from types. 134 StripTypeNames(M, PreserveDbgInfo); 135 136 return true; 137 } 138 139 static bool stripDebugDeclareImpl(Module &M) { 140 141 Function *Declare = M.getFunction("llvm.dbg.declare"); 142 std::vector<Constant*> DeadConstants; 143 144 if (Declare) { 145 while (!Declare->use_empty()) { 146 CallInst *CI = cast<CallInst>(Declare->user_back()); 147 Value *Arg1 = CI->getArgOperand(0); 148 Value *Arg2 = CI->getArgOperand(1); 149 assert(CI->use_empty() && "llvm.dbg intrinsic should have void result"); 150 CI->eraseFromParent(); 151 if (Arg1->use_empty()) { 152 if (Constant *C = dyn_cast<Constant>(Arg1)) 153 DeadConstants.push_back(C); 154 else 155 RecursivelyDeleteTriviallyDeadInstructions(Arg1); 156 } 157 if (Arg2->use_empty()) 158 if (Constant *C = dyn_cast<Constant>(Arg2)) 159 DeadConstants.push_back(C); 160 } 161 Declare->eraseFromParent(); 162 } 163 164 while (!DeadConstants.empty()) { 165 Constant *C = DeadConstants.back(); 166 DeadConstants.pop_back(); 167 if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) { 168 if (GV->hasLocalLinkage()) 169 RemoveDeadConstant(GV); 170 } else 171 RemoveDeadConstant(C); 172 } 173 174 return true; 175 } 176 177 static bool stripDeadDebugInfoImpl(Module &M) { 178 bool Changed = false; 179 180 LLVMContext &C = M.getContext(); 181 182 // Find all debug info in F. This is actually overkill in terms of what we 183 // want to do, but we want to try and be as resilient as possible in the face 184 // of potential debug info changes by using the formal interfaces given to us 185 // as much as possible. 186 DebugInfoFinder F; 187 F.processModule(M); 188 189 // For each compile unit, find the live set of global variables/functions and 190 // replace the current list of potentially dead global variables/functions 191 // with the live list. 192 SmallVector<Metadata *, 64> LiveGlobalVariables; 193 DenseSet<DIGlobalVariableExpression *> VisitedSet; 194 195 std::set<DIGlobalVariableExpression *> LiveGVs; 196 for (GlobalVariable &GV : M.globals()) { 197 SmallVector<DIGlobalVariableExpression *, 1> GVEs; 198 GV.getDebugInfo(GVEs); 199 for (auto *GVE : GVEs) 200 LiveGVs.insert(GVE); 201 } 202 203 std::set<DICompileUnit *> LiveCUs; 204 DebugInfoFinder LiveCUFinder; 205 for (const Function &F : M.functions()) { 206 if (auto *SP = cast_or_null<DISubprogram>(F.getSubprogram())) 207 LiveCUFinder.processSubprogram(SP); 208 for (const Instruction &I : instructions(F)) 209 LiveCUFinder.processInstruction(M, I); 210 } 211 auto FoundCUs = LiveCUFinder.compile_units(); 212 LiveCUs.insert(FoundCUs.begin(), FoundCUs.end()); 213 214 bool HasDeadCUs = false; 215 for (DICompileUnit *DIC : F.compile_units()) { 216 // Create our live global variable list. 217 bool GlobalVariableChange = false; 218 for (auto *DIG : DIC->getGlobalVariables()) { 219 if (DIG->getExpression() && DIG->getExpression()->isConstant()) 220 LiveGVs.insert(DIG); 221 222 // Make sure we only visit each global variable only once. 223 if (!VisitedSet.insert(DIG).second) 224 continue; 225 226 // If a global variable references DIG, the global variable is live. 227 if (LiveGVs.count(DIG)) 228 LiveGlobalVariables.push_back(DIG); 229 else 230 GlobalVariableChange = true; 231 } 232 233 if (!LiveGlobalVariables.empty()) 234 LiveCUs.insert(DIC); 235 else if (!LiveCUs.count(DIC)) 236 HasDeadCUs = true; 237 238 // If we found dead global variables, replace the current global 239 // variable list with our new live global variable list. 240 if (GlobalVariableChange) { 241 DIC->replaceGlobalVariables(MDTuple::get(C, LiveGlobalVariables)); 242 Changed = true; 243 } 244 245 // Reset lists for the next iteration. 246 LiveGlobalVariables.clear(); 247 } 248 249 if (HasDeadCUs) { 250 // Delete the old node and replace it with a new one 251 NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); 252 NMD->clearOperands(); 253 if (!LiveCUs.empty()) { 254 for (DICompileUnit *CU : LiveCUs) 255 NMD->addOperand(CU); 256 } 257 Changed = true; 258 } 259 260 return Changed; 261 } 262 263 PreservedAnalyses StripSymbolsPass::run(Module &M, ModuleAnalysisManager &AM) { 264 StripDebugInfo(M); 265 StripSymbolNames(M, false); 266 PreservedAnalyses PA; 267 PA.preserveSet<CFGAnalyses>(); 268 return PA; 269 } 270 271 PreservedAnalyses StripNonDebugSymbolsPass::run(Module &M, 272 ModuleAnalysisManager &AM) { 273 StripSymbolNames(M, true); 274 PreservedAnalyses PA; 275 PA.preserveSet<CFGAnalyses>(); 276 return PA; 277 } 278 279 PreservedAnalyses StripDebugDeclarePass::run(Module &M, 280 ModuleAnalysisManager &AM) { 281 stripDebugDeclareImpl(M); 282 PreservedAnalyses PA; 283 PA.preserveSet<CFGAnalyses>(); 284 return PA; 285 } 286 287 PreservedAnalyses StripDeadDebugInfoPass::run(Module &M, 288 ModuleAnalysisManager &AM) { 289 stripDeadDebugInfoImpl(M); 290 PreservedAnalyses PA; 291 PA.preserveSet<CFGAnalyses>(); 292 return PA; 293 } 294