10b57cec5SDimitry Andric //===- StripSymbols.cpp - Strip symbols and debug info from a module ------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // The StripSymbols transformation implements code stripping. Specifically, it 100b57cec5SDimitry Andric // can delete: 110b57cec5SDimitry Andric // 120b57cec5SDimitry Andric // * names for virtual registers 130b57cec5SDimitry Andric // * symbols for internal globals and functions 140b57cec5SDimitry Andric // * debug information 150b57cec5SDimitry Andric // 160b57cec5SDimitry Andric // Note that this transformation makes code much less readable, so it should 170b57cec5SDimitry Andric // only be used in situations where the 'strip' utility would be used, such as 180b57cec5SDimitry Andric // reducing code size or making it harder to reverse engineer code. 190b57cec5SDimitry Andric // 200b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 210b57cec5SDimitry Andric 22e8d8bef9SDimitry Andric #include "llvm/Transforms/IPO/StripSymbols.h" 230b57cec5SDimitry Andric #include "llvm/ADT/SmallPtrSet.h" 240b57cec5SDimitry Andric #include "llvm/IR/Constants.h" 250b57cec5SDimitry Andric #include "llvm/IR/DebugInfo.h" 260b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h" 27bdd1243dSDimitry Andric #include "llvm/IR/InstIterator.h" 280b57cec5SDimitry Andric #include "llvm/IR/Instructions.h" 290b57cec5SDimitry Andric #include "llvm/IR/Module.h" 30e8d8bef9SDimitry Andric #include "llvm/IR/PassManager.h" 310b57cec5SDimitry Andric #include "llvm/IR/TypeFinder.h" 320b57cec5SDimitry Andric #include "llvm/IR/ValueSymbolTable.h" 33*5f757f3fSDimitry Andric #include "llvm/Support/CommandLine.h" 340b57cec5SDimitry Andric #include "llvm/Transforms/IPO.h" 35bdd1243dSDimitry Andric #include "llvm/Transforms/IPO/StripSymbols.h" 36480093f4SDimitry Andric #include "llvm/Transforms/Utils/Local.h" 37e8d8bef9SDimitry Andric 380b57cec5SDimitry Andric using namespace llvm; 390b57cec5SDimitry Andric 40*5f757f3fSDimitry Andric static cl::opt<bool> 41*5f757f3fSDimitry Andric StripGlobalConstants("strip-global-constants", cl::init(false), cl::Hidden, 42*5f757f3fSDimitry Andric cl::desc("Removes debug compile units which reference " 43*5f757f3fSDimitry Andric "to non-existing global constants")); 44*5f757f3fSDimitry Andric 450b57cec5SDimitry Andric /// OnlyUsedBy - Return true if V is only used by Usr. 460b57cec5SDimitry Andric static bool OnlyUsedBy(Value *V, Value *Usr) { 470b57cec5SDimitry Andric for (User *U : V->users()) 480b57cec5SDimitry Andric if (U != Usr) 490b57cec5SDimitry Andric return false; 500b57cec5SDimitry Andric 510b57cec5SDimitry Andric return true; 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric static void RemoveDeadConstant(Constant *C) { 550b57cec5SDimitry Andric assert(C->use_empty() && "Constant is not dead!"); 560b57cec5SDimitry Andric SmallPtrSet<Constant*, 4> Operands; 570b57cec5SDimitry Andric for (Value *Op : C->operands()) 580b57cec5SDimitry Andric if (OnlyUsedBy(Op, C)) 590b57cec5SDimitry Andric Operands.insert(cast<Constant>(Op)); 600b57cec5SDimitry Andric if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) { 610b57cec5SDimitry Andric if (!GV->hasLocalLinkage()) return; // Don't delete non-static globals. 620b57cec5SDimitry Andric GV->eraseFromParent(); 635ffd83dbSDimitry Andric } else if (!isa<Function>(C)) { 645ffd83dbSDimitry Andric // FIXME: Why does the type of the constant matter here? 655ffd83dbSDimitry Andric if (isa<StructType>(C->getType()) || isa<ArrayType>(C->getType()) || 665ffd83dbSDimitry Andric isa<VectorType>(C->getType())) 670b57cec5SDimitry Andric C->destroyConstant(); 685ffd83dbSDimitry Andric } 690b57cec5SDimitry Andric 700b57cec5SDimitry Andric // If the constant referenced anything, see if we can delete it as well. 710b57cec5SDimitry Andric for (Constant *O : Operands) 720b57cec5SDimitry Andric RemoveDeadConstant(O); 730b57cec5SDimitry Andric } 740b57cec5SDimitry Andric 750b57cec5SDimitry Andric // Strip the symbol table of its names. 760b57cec5SDimitry Andric // 770b57cec5SDimitry Andric static void StripSymtab(ValueSymbolTable &ST, bool PreserveDbgInfo) { 780b57cec5SDimitry Andric for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) { 790b57cec5SDimitry Andric Value *V = VI->getValue(); 800b57cec5SDimitry Andric ++VI; 810b57cec5SDimitry Andric if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasLocalLinkage()) { 82*5f757f3fSDimitry Andric if (!PreserveDbgInfo || !V->getName().starts_with("llvm.dbg")) 830b57cec5SDimitry Andric // Set name to "", removing from symbol table! 840b57cec5SDimitry Andric V->setName(""); 850b57cec5SDimitry Andric } 860b57cec5SDimitry Andric } 870b57cec5SDimitry Andric } 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric // Strip any named types of their names. 900b57cec5SDimitry Andric static void StripTypeNames(Module &M, bool PreserveDbgInfo) { 910b57cec5SDimitry Andric TypeFinder StructTypes; 920b57cec5SDimitry Andric StructTypes.run(M, false); 930b57cec5SDimitry Andric 94bdd1243dSDimitry Andric for (StructType *STy : StructTypes) { 950b57cec5SDimitry Andric if (STy->isLiteral() || STy->getName().empty()) continue; 960b57cec5SDimitry Andric 97*5f757f3fSDimitry Andric if (PreserveDbgInfo && STy->getName().starts_with("llvm.dbg")) 980b57cec5SDimitry Andric continue; 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric STy->setName(""); 1010b57cec5SDimitry Andric } 1020b57cec5SDimitry Andric } 1030b57cec5SDimitry Andric 1040b57cec5SDimitry Andric /// Find values that are marked as llvm.used. 1050b57cec5SDimitry Andric static void findUsedValues(GlobalVariable *LLVMUsed, 1060b57cec5SDimitry Andric SmallPtrSetImpl<const GlobalValue*> &UsedValues) { 1070b57cec5SDimitry Andric if (!LLVMUsed) return; 1080b57cec5SDimitry Andric UsedValues.insert(LLVMUsed); 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric ConstantArray *Inits = cast<ConstantArray>(LLVMUsed->getInitializer()); 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric for (unsigned i = 0, e = Inits->getNumOperands(); i != e; ++i) 1130b57cec5SDimitry Andric if (GlobalValue *GV = 1140b57cec5SDimitry Andric dyn_cast<GlobalValue>(Inits->getOperand(i)->stripPointerCasts())) 1150b57cec5SDimitry Andric UsedValues.insert(GV); 1160b57cec5SDimitry Andric } 1170b57cec5SDimitry Andric 1180b57cec5SDimitry Andric /// StripSymbolNames - Strip symbol names. 1190b57cec5SDimitry Andric static bool StripSymbolNames(Module &M, bool PreserveDbgInfo) { 1200b57cec5SDimitry Andric 1210b57cec5SDimitry Andric SmallPtrSet<const GlobalValue*, 8> llvmUsedValues; 1220b57cec5SDimitry Andric findUsedValues(M.getGlobalVariable("llvm.used"), llvmUsedValues); 1230b57cec5SDimitry Andric findUsedValues(M.getGlobalVariable("llvm.compiler.used"), llvmUsedValues); 1240b57cec5SDimitry Andric 125fe6060f1SDimitry Andric for (GlobalVariable &GV : M.globals()) { 126349cc55cSDimitry Andric if (GV.hasLocalLinkage() && !llvmUsedValues.contains(&GV)) 127*5f757f3fSDimitry Andric if (!PreserveDbgInfo || !GV.getName().starts_with("llvm.dbg")) 128fe6060f1SDimitry Andric GV.setName(""); // Internal symbols can't participate in linkage 1290b57cec5SDimitry Andric } 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric for (Function &I : M) { 132349cc55cSDimitry Andric if (I.hasLocalLinkage() && !llvmUsedValues.contains(&I)) 133*5f757f3fSDimitry Andric if (!PreserveDbgInfo || !I.getName().starts_with("llvm.dbg")) 1340b57cec5SDimitry Andric I.setName(""); // Internal symbols can't participate in linkage 1350b57cec5SDimitry Andric if (auto *Symtab = I.getValueSymbolTable()) 1360b57cec5SDimitry Andric StripSymtab(*Symtab, PreserveDbgInfo); 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric 1390b57cec5SDimitry Andric // Remove all names from types. 1400b57cec5SDimitry Andric StripTypeNames(M, PreserveDbgInfo); 1410b57cec5SDimitry Andric 1420b57cec5SDimitry Andric return true; 1430b57cec5SDimitry Andric } 1440b57cec5SDimitry Andric 145e8d8bef9SDimitry Andric static bool stripDebugDeclareImpl(Module &M) { 1460b57cec5SDimitry Andric 1470b57cec5SDimitry Andric Function *Declare = M.getFunction("llvm.dbg.declare"); 1480b57cec5SDimitry Andric std::vector<Constant*> DeadConstants; 1490b57cec5SDimitry Andric 1500b57cec5SDimitry Andric if (Declare) { 1510b57cec5SDimitry Andric while (!Declare->use_empty()) { 1520b57cec5SDimitry Andric CallInst *CI = cast<CallInst>(Declare->user_back()); 1530b57cec5SDimitry Andric Value *Arg1 = CI->getArgOperand(0); 1540b57cec5SDimitry Andric Value *Arg2 = CI->getArgOperand(1); 1550b57cec5SDimitry Andric assert(CI->use_empty() && "llvm.dbg intrinsic should have void result"); 1560b57cec5SDimitry Andric CI->eraseFromParent(); 1570b57cec5SDimitry Andric if (Arg1->use_empty()) { 1580b57cec5SDimitry Andric if (Constant *C = dyn_cast<Constant>(Arg1)) 1590b57cec5SDimitry Andric DeadConstants.push_back(C); 1600b57cec5SDimitry Andric else 1610b57cec5SDimitry Andric RecursivelyDeleteTriviallyDeadInstructions(Arg1); 1620b57cec5SDimitry Andric } 1630b57cec5SDimitry Andric if (Arg2->use_empty()) 1640b57cec5SDimitry Andric if (Constant *C = dyn_cast<Constant>(Arg2)) 1650b57cec5SDimitry Andric DeadConstants.push_back(C); 1660b57cec5SDimitry Andric } 1670b57cec5SDimitry Andric Declare->eraseFromParent(); 1680b57cec5SDimitry Andric } 1690b57cec5SDimitry Andric 1700b57cec5SDimitry Andric while (!DeadConstants.empty()) { 1710b57cec5SDimitry Andric Constant *C = DeadConstants.back(); 1720b57cec5SDimitry Andric DeadConstants.pop_back(); 1730b57cec5SDimitry Andric if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) { 1740b57cec5SDimitry Andric if (GV->hasLocalLinkage()) 1750b57cec5SDimitry Andric RemoveDeadConstant(GV); 1760b57cec5SDimitry Andric } else 1770b57cec5SDimitry Andric RemoveDeadConstant(C); 1780b57cec5SDimitry Andric } 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric return true; 1810b57cec5SDimitry Andric } 1820b57cec5SDimitry Andric 183e8d8bef9SDimitry Andric static bool stripDeadDebugInfoImpl(Module &M) { 1840b57cec5SDimitry Andric bool Changed = false; 1850b57cec5SDimitry Andric 1860b57cec5SDimitry Andric LLVMContext &C = M.getContext(); 1870b57cec5SDimitry Andric 1880b57cec5SDimitry Andric // Find all debug info in F. This is actually overkill in terms of what we 1890b57cec5SDimitry Andric // want to do, but we want to try and be as resilient as possible in the face 1900b57cec5SDimitry Andric // of potential debug info changes by using the formal interfaces given to us 1910b57cec5SDimitry Andric // as much as possible. 1920b57cec5SDimitry Andric DebugInfoFinder F; 1930b57cec5SDimitry Andric F.processModule(M); 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric // For each compile unit, find the live set of global variables/functions and 1960b57cec5SDimitry Andric // replace the current list of potentially dead global variables/functions 1970b57cec5SDimitry Andric // with the live list. 1980b57cec5SDimitry Andric SmallVector<Metadata *, 64> LiveGlobalVariables; 1990b57cec5SDimitry Andric DenseSet<DIGlobalVariableExpression *> VisitedSet; 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric std::set<DIGlobalVariableExpression *> LiveGVs; 2020b57cec5SDimitry Andric for (GlobalVariable &GV : M.globals()) { 2030b57cec5SDimitry Andric SmallVector<DIGlobalVariableExpression *, 1> GVEs; 2040b57cec5SDimitry Andric GV.getDebugInfo(GVEs); 2050b57cec5SDimitry Andric for (auto *GVE : GVEs) 2060b57cec5SDimitry Andric LiveGVs.insert(GVE); 2070b57cec5SDimitry Andric } 2080b57cec5SDimitry Andric 2090b57cec5SDimitry Andric std::set<DICompileUnit *> LiveCUs; 21006c3fb27SDimitry Andric DebugInfoFinder LiveCUFinder; 21106c3fb27SDimitry Andric for (const Function &F : M.functions()) { 21206c3fb27SDimitry Andric if (auto *SP = cast_or_null<DISubprogram>(F.getSubprogram())) 21306c3fb27SDimitry Andric LiveCUFinder.processSubprogram(SP); 21406c3fb27SDimitry Andric for (const Instruction &I : instructions(F)) 21506c3fb27SDimitry Andric LiveCUFinder.processInstruction(M, I); 216bdd1243dSDimitry Andric } 21706c3fb27SDimitry Andric auto FoundCUs = LiveCUFinder.compile_units(); 21806c3fb27SDimitry Andric LiveCUs.insert(FoundCUs.begin(), FoundCUs.end()); 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric bool HasDeadCUs = false; 2210b57cec5SDimitry Andric for (DICompileUnit *DIC : F.compile_units()) { 2220b57cec5SDimitry Andric // Create our live global variable list. 2230b57cec5SDimitry Andric bool GlobalVariableChange = false; 2240b57cec5SDimitry Andric for (auto *DIG : DIC->getGlobalVariables()) { 225*5f757f3fSDimitry Andric if (DIG->getExpression() && DIG->getExpression()->isConstant() && 226*5f757f3fSDimitry Andric !StripGlobalConstants) 2270b57cec5SDimitry Andric LiveGVs.insert(DIG); 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric // Make sure we only visit each global variable only once. 2300b57cec5SDimitry Andric if (!VisitedSet.insert(DIG).second) 2310b57cec5SDimitry Andric continue; 2320b57cec5SDimitry Andric 2330b57cec5SDimitry Andric // If a global variable references DIG, the global variable is live. 2340b57cec5SDimitry Andric if (LiveGVs.count(DIG)) 2350b57cec5SDimitry Andric LiveGlobalVariables.push_back(DIG); 2360b57cec5SDimitry Andric else 2370b57cec5SDimitry Andric GlobalVariableChange = true; 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric if (!LiveGlobalVariables.empty()) 2410b57cec5SDimitry Andric LiveCUs.insert(DIC); 2420b57cec5SDimitry Andric else if (!LiveCUs.count(DIC)) 2430b57cec5SDimitry Andric HasDeadCUs = true; 2440b57cec5SDimitry Andric 2450b57cec5SDimitry Andric // If we found dead global variables, replace the current global 2460b57cec5SDimitry Andric // variable list with our new live global variable list. 2470b57cec5SDimitry Andric if (GlobalVariableChange) { 2480b57cec5SDimitry Andric DIC->replaceGlobalVariables(MDTuple::get(C, LiveGlobalVariables)); 2490b57cec5SDimitry Andric Changed = true; 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric // Reset lists for the next iteration. 2530b57cec5SDimitry Andric LiveGlobalVariables.clear(); 2540b57cec5SDimitry Andric } 2550b57cec5SDimitry Andric 2560b57cec5SDimitry Andric if (HasDeadCUs) { 2570b57cec5SDimitry Andric // Delete the old node and replace it with a new one 2580b57cec5SDimitry Andric NamedMDNode *NMD = M.getOrInsertNamedMetadata("llvm.dbg.cu"); 2590b57cec5SDimitry Andric NMD->clearOperands(); 2600b57cec5SDimitry Andric if (!LiveCUs.empty()) { 2610b57cec5SDimitry Andric for (DICompileUnit *CU : LiveCUs) 2620b57cec5SDimitry Andric NMD->addOperand(CU); 2630b57cec5SDimitry Andric } 2640b57cec5SDimitry Andric Changed = true; 2650b57cec5SDimitry Andric } 2660b57cec5SDimitry Andric 2670b57cec5SDimitry Andric return Changed; 2680b57cec5SDimitry Andric } 269e8d8bef9SDimitry Andric 270e8d8bef9SDimitry Andric PreservedAnalyses StripSymbolsPass::run(Module &M, ModuleAnalysisManager &AM) { 271e8d8bef9SDimitry Andric StripDebugInfo(M); 272e8d8bef9SDimitry Andric StripSymbolNames(M, false); 27306c3fb27SDimitry Andric PreservedAnalyses PA; 27406c3fb27SDimitry Andric PA.preserveSet<CFGAnalyses>(); 27506c3fb27SDimitry Andric return PA; 276e8d8bef9SDimitry Andric } 277e8d8bef9SDimitry Andric 278e8d8bef9SDimitry Andric PreservedAnalyses StripNonDebugSymbolsPass::run(Module &M, 279e8d8bef9SDimitry Andric ModuleAnalysisManager &AM) { 280e8d8bef9SDimitry Andric StripSymbolNames(M, true); 28106c3fb27SDimitry Andric PreservedAnalyses PA; 28206c3fb27SDimitry Andric PA.preserveSet<CFGAnalyses>(); 28306c3fb27SDimitry Andric return PA; 284e8d8bef9SDimitry Andric } 285e8d8bef9SDimitry Andric 286e8d8bef9SDimitry Andric PreservedAnalyses StripDebugDeclarePass::run(Module &M, 287e8d8bef9SDimitry Andric ModuleAnalysisManager &AM) { 288e8d8bef9SDimitry Andric stripDebugDeclareImpl(M); 28906c3fb27SDimitry Andric PreservedAnalyses PA; 29006c3fb27SDimitry Andric PA.preserveSet<CFGAnalyses>(); 29106c3fb27SDimitry Andric return PA; 292e8d8bef9SDimitry Andric } 293e8d8bef9SDimitry Andric 294e8d8bef9SDimitry Andric PreservedAnalyses StripDeadDebugInfoPass::run(Module &M, 295e8d8bef9SDimitry Andric ModuleAnalysisManager &AM) { 296e8d8bef9SDimitry Andric stripDeadDebugInfoImpl(M); 29706c3fb27SDimitry Andric PreservedAnalyses PA; 29806c3fb27SDimitry Andric PA.preserveSet<CFGAnalyses>(); 29906c3fb27SDimitry Andric return PA; 300e8d8bef9SDimitry Andric } 301