|  | //===- StripSymbols.cpp - Strip symbols and debug info from a module ------===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file was developed by the LLVM research group and is distributed under | 
|  | // the University of Illinois Open Source License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | // | 
|  | // The StripSymbols transformation implements code stripping. Specifically, it | 
|  | // can delete: | 
|  | // | 
|  | //   * names for virtual registers | 
|  | //   * symbols for internal globals and functions | 
|  | //   * debug information | 
|  | // | 
|  | // Note that this transformation makes code much less readable, so it should | 
|  | // only be used in situations where the 'strip' utility would be used, such as | 
|  | // reducing code size or making it harder to reverse engineer code. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #include "llvm/Transforms/IPO.h" | 
|  | #include "llvm/Constants.h" | 
|  | #include "llvm/DerivedTypes.h" | 
|  | #include "llvm/Instructions.h" | 
|  | #include "llvm/Module.h" | 
|  | #include "llvm/Pass.h" | 
|  | #include "llvm/ValueSymbolTable.h" | 
|  | #include "llvm/TypeSymbolTable.h" | 
|  | #include "llvm/Support/Compiler.h" | 
|  | using namespace llvm; | 
|  |  | 
|  | namespace { | 
|  | class VISIBILITY_HIDDEN StripSymbols : public ModulePass { | 
|  | bool OnlyDebugInfo; | 
|  | public: | 
|  | static char ID; // Pass identification, replacement for typeid | 
|  | explicit StripSymbols(bool ODI = false) | 
|  | : ModulePass((intptr_t)&ID), OnlyDebugInfo(ODI) {} | 
|  |  | 
|  | virtual bool runOnModule(Module &M); | 
|  |  | 
|  | virtual void getAnalysisUsage(AnalysisUsage &AU) const { | 
|  | AU.setPreservesAll(); | 
|  | } | 
|  | }; | 
|  |  | 
|  | char StripSymbols::ID = 0; | 
|  | RegisterPass<StripSymbols> X("strip", "Strip all symbols from a module"); | 
|  | } | 
|  |  | 
|  | ModulePass *llvm::createStripSymbolsPass(bool OnlyDebugInfo) { | 
|  | return new StripSymbols(OnlyDebugInfo); | 
|  | } | 
|  |  | 
|  | static void RemoveDeadConstant(Constant *C) { | 
|  | assert(C->use_empty() && "Constant is not dead!"); | 
|  | std::vector<Constant*> Operands; | 
|  | for (unsigned i = 0, e = C->getNumOperands(); i != e; ++i) | 
|  | if (isa<DerivedType>(C->getOperand(i)->getType()) && | 
|  | C->getOperand(i)->hasOneUse()) | 
|  | Operands.push_back(C->getOperand(i)); | 
|  | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(C)) { | 
|  | if (!GV->hasInternalLinkage()) return;   // Don't delete non static globals. | 
|  | GV->eraseFromParent(); | 
|  | } | 
|  | else if (!isa<Function>(C)) | 
|  | C->destroyConstant(); | 
|  |  | 
|  | // If the constant referenced anything, see if we can delete it as well. | 
|  | while (!Operands.empty()) { | 
|  | RemoveDeadConstant(Operands.back()); | 
|  | Operands.pop_back(); | 
|  | } | 
|  | } | 
|  |  | 
|  | // Strip the symbol table of its names. | 
|  | // | 
|  | static void StripSymtab(ValueSymbolTable &ST) { | 
|  | for (ValueSymbolTable::iterator VI = ST.begin(), VE = ST.end(); VI != VE; ) { | 
|  | Value *V = VI->getValue(); | 
|  | ++VI; | 
|  | if (!isa<GlobalValue>(V) || cast<GlobalValue>(V)->hasInternalLinkage()) { | 
|  | // Set name to "", removing from symbol table! | 
|  | V->setName(""); | 
|  | } | 
|  | } | 
|  | } | 
|  |  | 
|  | // Strip the symbol table of its names. | 
|  | static void StripTypeSymtab(TypeSymbolTable &ST) { | 
|  | for (TypeSymbolTable::iterator TI = ST.begin(), E = ST.end(); TI != E; ) | 
|  | ST.remove(TI++); | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  | bool StripSymbols::runOnModule(Module &M) { | 
|  | // If we're not just stripping debug info, strip all symbols from the | 
|  | // functions and the names from any internal globals. | 
|  | if (!OnlyDebugInfo) { | 
|  | for (Module::global_iterator I = M.global_begin(), E = M.global_end(); | 
|  | I != E; ++I) | 
|  | if (I->hasInternalLinkage()) | 
|  | I->setName("");     // Internal symbols can't participate in linkage | 
|  |  | 
|  | for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { | 
|  | if (I->hasInternalLinkage()) | 
|  | I->setName("");     // Internal symbols can't participate in linkage | 
|  | StripSymtab(I->getValueSymbolTable()); | 
|  | } | 
|  |  | 
|  | // Remove all names from types. | 
|  | StripTypeSymtab(M.getTypeSymbolTable()); | 
|  | } | 
|  |  | 
|  | // Strip debug info in the module if it exists.  To do this, we remove | 
|  | // llvm.dbg.func.start, llvm.dbg.stoppoint, and llvm.dbg.region.end calls, and | 
|  | // any globals they point to if now dead. | 
|  | Function *FuncStart = M.getFunction("llvm.dbg.func.start"); | 
|  | Function *StopPoint = M.getFunction("llvm.dbg.stoppoint"); | 
|  | Function *RegionStart = M.getFunction("llvm.dbg.region.start"); | 
|  | Function *RegionEnd = M.getFunction("llvm.dbg.region.end"); | 
|  | Function *Declare = M.getFunction("llvm.dbg.declare"); | 
|  | if (!FuncStart && !StopPoint && !RegionStart && !RegionEnd && !Declare) | 
|  | return true; | 
|  |  | 
|  | std::vector<GlobalVariable*> DeadGlobals; | 
|  |  | 
|  | // Remove all of the calls to the debugger intrinsics, and remove them from | 
|  | // the module. | 
|  | if (FuncStart) { | 
|  | while (!FuncStart->use_empty()) { | 
|  | CallInst *CI = cast<CallInst>(FuncStart->use_back()); | 
|  | Value *Arg = CI->getOperand(1); | 
|  | assert(CI->use_empty() && "llvm.dbg intrinsic should have void result"); | 
|  | CI->eraseFromParent(); | 
|  | if (Arg->use_empty()) | 
|  | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Arg)) | 
|  | DeadGlobals.push_back(GV); | 
|  | } | 
|  | FuncStart->eraseFromParent(); | 
|  | } | 
|  | if (StopPoint) { | 
|  | while (!StopPoint->use_empty()) { | 
|  | CallInst *CI = cast<CallInst>(StopPoint->use_back()); | 
|  | Value *Arg = CI->getOperand(3); | 
|  | assert(CI->use_empty() && "llvm.dbg intrinsic should have void result"); | 
|  | CI->eraseFromParent(); | 
|  | if (Arg->use_empty()) | 
|  | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Arg)) | 
|  | DeadGlobals.push_back(GV); | 
|  | } | 
|  | StopPoint->eraseFromParent(); | 
|  | } | 
|  | if (RegionStart) { | 
|  | while (!RegionStart->use_empty()) { | 
|  | CallInst *CI = cast<CallInst>(RegionStart->use_back()); | 
|  | Value *Arg = CI->getOperand(1); | 
|  | assert(CI->use_empty() && "llvm.dbg intrinsic should have void result"); | 
|  | CI->eraseFromParent(); | 
|  | if (Arg->use_empty()) | 
|  | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Arg)) | 
|  | DeadGlobals.push_back(GV); | 
|  | } | 
|  | RegionStart->eraseFromParent(); | 
|  | } | 
|  | if (RegionEnd) { | 
|  | while (!RegionEnd->use_empty()) { | 
|  | CallInst *CI = cast<CallInst>(RegionEnd->use_back()); | 
|  | Value *Arg = CI->getOperand(1); | 
|  | assert(CI->use_empty() && "llvm.dbg intrinsic should have void result"); | 
|  | CI->eraseFromParent(); | 
|  | if (Arg->use_empty()) | 
|  | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Arg)) | 
|  | DeadGlobals.push_back(GV); | 
|  | } | 
|  | RegionEnd->eraseFromParent(); | 
|  | } | 
|  | if (Declare) { | 
|  | while (!Declare->use_empty()) { | 
|  | CallInst *CI = cast<CallInst>(Declare->use_back()); | 
|  | Value *Arg = CI->getOperand(2); | 
|  | assert(CI->use_empty() && "llvm.dbg intrinsic should have void result"); | 
|  | CI->eraseFromParent(); | 
|  | if (Arg->use_empty()) | 
|  | if (GlobalVariable *GV = dyn_cast<GlobalVariable>(Arg)) | 
|  | DeadGlobals.push_back(GV); | 
|  | } | 
|  | Declare->eraseFromParent(); | 
|  | } | 
|  |  | 
|  | // Finally, delete any internal globals that were only used by the debugger | 
|  | // intrinsics. | 
|  | while (!DeadGlobals.empty()) { | 
|  | GlobalVariable *GV = DeadGlobals.back(); | 
|  | DeadGlobals.pop_back(); | 
|  | if (GV->hasInternalLinkage()) | 
|  | RemoveDeadConstant(GV); | 
|  | } | 
|  |  | 
|  | return true; | 
|  | } |