llvm-6502/lib/Transforms/IPO/StripSymbols.cpp
Devang Patel 3e15bf33e0 Use 'static const char' instead of 'static const int'.
Due to darwin gcc bug, one version of darwin linker coalesces
static const int, which defauts PassID based pass identification.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@36652 91177308-0d34-0410-b5e6-96231b3b80d8
2007-05-02 21:39:20 +00:00

207 lines
7.0 KiB
C++

//===- 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.
//
//===----------------------------------------------------------------------===//
//
// This file implements stripping symbols out of symbol tables.
//
// Specifically, this allows you to strip all of the symbols out of:
// * All functions in a module
// * All non-essential symbols in a module (all function symbols + all module
// scope symbols)
// * Debug information.
//
// Notice that:
// * This pass 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, and 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 const char ID; // Pass identifcation, replacement for typeid
StripSymbols(bool ODI = false)
: ModulePass((intptr_t)&ID), OnlyDebugInfo(ODI) {}
virtual bool runOnModule(Module &M);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}
};
const 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;
}