/// GetAllUndefinedSymbols - calculates the set of undefined symbols that still /// exist in an LLVM module. This is a bit tricky because there may be two /// symbols with the same name but different LLVM types that will be resolved to /// each other but aren't currently (thus we need to treat it as resolved). /// /// Inputs: /// M - The module in which to find undefined symbols. /// /// Outputs: /// UndefinedSymbols - A set of C++ strings containing the name of all /// undefined symbols. /// static void GetAllUndefinedSymbols(Module *M, std::set<std::string> &UndefinedSymbols) { std::set<std::string> DefinedSymbols; UndefinedSymbols.clear(); // If the program doesn't define a main, try pulling one in from a .a file. // This is needed for programs where the main function is defined in an // archive, such f2c'd programs. Function *Main = M->getFunction("main"); if (Main == 0 || Main->isDeclaration()) UndefinedSymbols.insert("main"); for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) if (I->hasName()) { if (I->isDeclaration()) UndefinedSymbols.insert(I->getName()); else if (!I->hasLocalLinkage()) { assert(!I->hasDLLImportLinkage() && "Found dllimported non-external symbol!"); DefinedSymbols.insert(I->getName()); } } for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasName()) { if (I->isDeclaration()) UndefinedSymbols.insert(I->getName()); else if (!I->hasLocalLinkage()) { assert(!I->hasDLLImportLinkage() && "Found dllimported non-external symbol!"); DefinedSymbols.insert(I->getName()); } } for (Module::alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) if (I->hasName()) DefinedSymbols.insert(I->getName()); // Prune out any defined symbols from the undefined symbols set... for (std::set<std::string>::iterator I = UndefinedSymbols.begin(); I != UndefinedSymbols.end(); ) if (DefinedSymbols.count(*I)) UndefinedSymbols.erase(I++); // This symbol really is defined! else ++I; // Keep this symbol in the undefined symbols list }
void AndroidBitcodeLinker::GetAllSymbols(Module *M, std::set<std::string> &UndefinedSymbols, std::set<std::string> &DefinedSymbols) { UndefinedSymbols.clear(); DefinedSymbols.clear(); Function *Main = M->getFunction("main"); if (Main == 0 || Main->isDeclaration()) UndefinedSymbols.insert("main"); for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) if (I->hasName()) { if (I->isDeclaration()) UndefinedSymbols.insert(I->getName()); else if (!I->hasLocalLinkage()) { assert(!I->hasDLLImportStorageClass() && "Found dllimported non-external symbol!"); DefinedSymbols.insert(I->getName()); } } for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasName()) { if (I->isDeclaration()) UndefinedSymbols.insert(I->getName()); else if (!I->hasLocalLinkage()) { assert(!I->hasDLLImportStorageClass() && "Found dllimported non-external symbol!"); DefinedSymbols.insert(I->getName()); } } for (Module::alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) if (I->hasName()) DefinedSymbols.insert(I->getName()); for (std::set<std::string>::iterator I = UndefinedSymbols.begin(); I != UndefinedSymbols.end(); ) if (DefinedSymbols.count(*I)) UndefinedSymbols.erase(I++); else ++I; }
static void getSymbols(Module*M, std::vector<std::string>& symbols) { // Loop over global variables for (Module::global_iterator GI = M->global_begin(), GE=M->global_end(); GI != GE; ++GI) if (!GI->isDeclaration() && !GI->hasLocalLinkage()) if (!GI->getName().empty()) symbols.push_back(GI->getName()); // Loop over functions for (Module::iterator FI = M->begin(), FE = M->end(); FI != FE; ++FI) if (!FI->isDeclaration() && !FI->hasLocalLinkage()) if (!FI->getName().empty()) symbols.push_back(FI->getName()); // Loop over aliases for (Module::alias_iterator AI = M->alias_begin(), AE = M->alias_end(); AI != AE; ++AI) { if (AI->hasName()) symbols.push_back(AI->getName()); } }
bool InternalizePass::runOnModule(Module &M) { CallGraph *CG = getAnalysisIfAvailable<CallGraph>(); CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0; if (ExternalNames.empty()) { // Return if we're not in 'all but main' mode and have no external api if (!AllButMain) return false; // If no list or file of symbols was specified, check to see if there is a // "main" symbol defined in the module. If so, use it, otherwise do not // internalize the module, it must be a library or something. // Function *MainFunc = M.getFunction("main"); if (MainFunc == 0 || MainFunc->isDeclaration()) return false; // No main found, must be a library... // Preserve main, internalize all else. ExternalNames.insert(MainFunc->getName()); } bool Changed = false; // Never internalize functions which code-gen might insert. ExternalNames.insert("__stack_chk_fail"); // Mark all functions not in the api as internal. // FIXME: maybe use private linkage? for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!I->isDeclaration() && // Function must be defined here // Available externally is really just a "declaration with a body". !I->hasAvailableExternallyLinkage() && !I->hasLocalLinkage() && // Can't already have internal linkage !ExternalNames.count(I->getName())) {// Not marked to keep external? I->setLinkage(GlobalValue::InternalLinkage); // Remove a callgraph edge from the external node to this function. if (ExternalNode) ExternalNode->removeOneAbstractEdgeTo((*CG)[I]); Changed = true; ++NumFunctions; DEBUG(dbgs() << "Internalizing func " << I->getName() << "\n"); } // Never internalize the llvm.used symbol. It is used to implement // attribute((used)). // FIXME: Shouldn't this just filter on llvm.metadata section?? ExternalNames.insert("llvm.used"); ExternalNames.insert("llvm.compiler.used"); // Never internalize anchors used by the machine module info, else the info // won't find them. (see MachineModuleInfo.) ExternalNames.insert("llvm.global_ctors"); ExternalNames.insert("llvm.global_dtors"); ExternalNames.insert("llvm.global.annotations"); // Never internalize symbols code-gen inserts. ExternalNames.insert("__stack_chk_guard"); // Mark all global variables with initializers that are not in the api as // internal as well. // FIXME: maybe use private linkage? for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) if (!I->isDeclaration() && !I->hasLocalLinkage() && // Available externally is really just a "declaration with a body". !I->hasAvailableExternallyLinkage() && !ExternalNames.count(I->getName())) { I->setLinkage(GlobalValue::InternalLinkage); Changed = true; ++NumGlobals; DEBUG(dbgs() << "Internalized gvar " << I->getName() << "\n"); } // Mark all aliases that are not in the api as internal as well. for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) if (!I->isDeclaration() && !I->hasInternalLinkage() && // Available externally is really just a "declaration with a body". !I->hasAvailableExternallyLinkage() && !ExternalNames.count(I->getName())) { I->setLinkage(GlobalValue::InternalLinkage); Changed = true; ++NumAliases; DEBUG(dbgs() << "Internalized alias " << I->getName() << "\n"); } return Changed; }
bool PNaClABIVerifyModule::runOnModule(Module &M) { if (!M.getModuleInlineAsm().empty()) { Reporter->addError() << "Module contains disallowed top-level inline assembly\n"; } for (Module::const_global_iterator MI = M.global_begin(), ME = M.global_end(); MI != ME; ++MI) { checkGlobalIsFlattened(MI); checkGlobalValueCommon(MI); if (MI->isThreadLocal()) { Reporter->addError() << "Variable " << MI->getName() << " has disallowed \"thread_local\" attribute\n"; } } // No aliases allowed for now. for (Module::alias_iterator MI = M.alias_begin(), E = M.alias_end(); MI != E; ++MI) { Reporter->addError() << "Variable " << MI->getName() << " is an alias (disallowed)\n"; } for (Module::const_iterator MI = M.begin(), ME = M.end(); MI != ME; ++MI) { if (MI->isIntrinsic()) { // Check intrinsics. if (!isWhitelistedIntrinsic(MI, MI->getIntrinsicID())) { Reporter->addError() << "Function " << MI->getName() << " is a disallowed LLVM intrinsic\n"; } } else { // Check types of functions and their arguments. Not necessary // for intrinsics, whose types are fixed anyway, and which have // argument types that we disallow such as i8. if (!PNaClABITypeChecker::isValidFunctionType(MI->getFunctionType())) { Reporter->addError() << "Function " << MI->getName() << " has disallowed type: " << PNaClABITypeChecker::getTypeName(MI->getFunctionType()) << "\n"; } // This check is disabled in streaming mode because it would // reject a function that is defined but not read in yet. // Unfortunately this means we simply don't check this property // when translating a pexe in the browser. // TODO(mseaborn): Enforce this property in the bitcode reader. if (!StreamingMode && MI->isDeclaration()) { Reporter->addError() << "Function " << MI->getName() << " is declared but not defined (disallowed)\n"; } if (!MI->getAttributes().isEmpty()) { Reporter->addError() << "Function " << MI->getName() << " has disallowed attributes:" << getAttributesAsString(MI->getAttributes()) << "\n"; } if (MI->getCallingConv() != CallingConv::C) { Reporter->addError() << "Function " << MI->getName() << " has disallowed calling convention: " << MI->getCallingConv() << "\n"; } } checkGlobalValueCommon(MI); if (MI->hasGC()) { Reporter->addError() << "Function " << MI->getName() << " has disallowed \"gc\" attribute\n"; } // Knowledge of what function alignments are useful is // architecture-specific and sandbox-specific, so PNaCl pexes // should not be able to specify function alignment. if (MI->getAlignment() != 0) { Reporter->addError() << "Function " << MI->getName() << " has disallowed \"align\" attribute\n"; } } // Check named metadata nodes for (Module::const_named_metadata_iterator I = M.named_metadata_begin(), E = M.named_metadata_end(); I != E; ++I) { if (!isWhitelistedMetadata(I)) { Reporter->addError() << "Named metadata node " << I->getName() << " is disallowed\n"; } } Reporter->checkForFatalErrors(); return false; }
bool InternalizePass::runOnModule(Module &M) { CallGraph *CG = getAnalysisIfAvailable<CallGraph>(); CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0; bool Changed = false; // Never internalize functions which code-gen might insert. // FIXME: We should probably add this (and the __stack_chk_guard) via some // type of call-back in CodeGen. ExternalNames.insert("__stack_chk_fail"); // Mark all functions not in the api as internal. // FIXME: maybe use private linkage? for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) if (!I->isDeclaration() && // Function must be defined here // Available externally is really just a "declaration with a body". !I->hasAvailableExternallyLinkage() && !I->hasLocalLinkage() && // Can't already have internal linkage !ExternalNames.count(I->getName())) {// Not marked to keep external? I->setLinkage(GlobalValue::InternalLinkage); // Remove a callgraph edge from the external node to this function. if (ExternalNode) ExternalNode->removeOneAbstractEdgeTo((*CG)[I]); Changed = true; ++NumFunctions; DEBUG(dbgs() << "Internalizing func " << I->getName() << "\n"); } // Never internalize the llvm.used symbol. It is used to implement // attribute((used)). // FIXME: Shouldn't this just filter on llvm.metadata section?? ExternalNames.insert("llvm.used"); ExternalNames.insert("llvm.compiler.used"); // Never internalize anchors used by the machine module info, else the info // won't find them. (see MachineModuleInfo.) ExternalNames.insert("llvm.global_ctors"); ExternalNames.insert("llvm.global_dtors"); ExternalNames.insert("llvm.global.annotations"); // Never internalize symbols code-gen inserts. ExternalNames.insert("__stack_chk_guard"); // Mark all global variables with initializers that are not in the api as // internal as well. // FIXME: maybe use private linkage? for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) if (!I->isDeclaration() && !I->hasLocalLinkage() && // Available externally is really just a "declaration with a body". !I->hasAvailableExternallyLinkage() && !ExternalNames.count(I->getName())) { I->setLinkage(GlobalValue::InternalLinkage); Changed = true; ++NumGlobals; DEBUG(dbgs() << "Internalized gvar " << I->getName() << "\n"); } // Mark all aliases that are not in the api as internal as well. for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) if (!I->isDeclaration() && !I->hasInternalLinkage() && // Available externally is really just a "declaration with a body". !I->hasAvailableExternallyLinkage() && !ExternalNames.count(I->getName())) { I->setLinkage(GlobalValue::InternalLinkage); Changed = true; ++NumAliases; DEBUG(dbgs() << "Internalized alias " << I->getName() << "\n"); } return Changed; }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(argv[0]); PrettyStackTraceProgram X(argc, argv); LLVMContext Context; llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); // Use lazy loading, since we only care about selected global values. SMDiagnostic Err; std::unique_ptr<Module> M = getLazyIRFileModule(InputFilename, Err, Context); if (!M.get()) { Err.print(argv[0], errs()); return 1; } // Use SetVector to avoid duplicates. SetVector<GlobalValue *> GVs; // Figure out which aliases we should extract. for (size_t i = 0, e = ExtractAliases.size(); i != e; ++i) { GlobalAlias *GA = M->getNamedAlias(ExtractAliases[i]); if (!GA) { errs() << argv[0] << ": program doesn't contain alias named '" << ExtractAliases[i] << "'!\n"; return 1; } GVs.insert(GA); } // Extract aliases via regular expression matching. for (size_t i = 0, e = ExtractRegExpAliases.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpAliases[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpAliases[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::alias_iterator GA = M->alias_begin(), E = M->alias_end(); GA != E; GA++) { if (RegEx.match(GA->getName())) { GVs.insert(&*GA); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpAliases[i] << "'!\n"; return 1; } } // Figure out which globals we should extract. for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { GlobalValue *GV = M->getNamedGlobal(ExtractGlobals[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractGlobals[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract globals via regular expression matching. for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpGlobals[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' " "invalid regex: " << Error; } bool match = false; for (auto &GV : M->globals()) { if (RegEx.match(GV.getName())) { GVs.insert(&GV); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpGlobals[i] << "'!\n"; return 1; } } // Figure out which functions we should extract. for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { GlobalValue *GV = M->getFunction(ExtractFuncs[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain function named '" << ExtractFuncs[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract functions via regular expression matching. for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) { std::string Error; StringRef RegExStr = ExtractRegExpFuncs[i]; Regex RegEx(RegExStr); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::iterator F = M->begin(), E = M->end(); F != E; F++) { if (RegEx.match(F->getName())) { GVs.insert(&*F); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpFuncs[i] << "'!\n"; return 1; } } auto Materialize = [&](GlobalValue &GV) { if (std::error_code EC = GV.materialize()) { errs() << argv[0] << ": error reading input: " << EC.message() << "\n"; exit(1); } }; // Materialize requisite global values. if (!DeleteFn) { for (size_t i = 0, e = GVs.size(); i != e; ++i) Materialize(*GVs[i]); } else { // Deleting. Materialize every GV that's *not* in GVs. SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end()); for (auto &F : *M) { if (!GVSet.count(&F)) Materialize(F); } } { std::vector<GlobalValue *> Gvs(GVs.begin(), GVs.end()); legacy::PassManager Extract; Extract.add(createGVExtractionPass(Gvs, DeleteFn)); Extract.run(*M); // Now that we have all the GVs we want, mark the module as fully // materialized. // FIXME: should the GVExtractionPass handle this? M->materializeAll(); } // In addition to deleting all other functions, we also want to spiff it // up a little bit. Do this now. legacy::PassManager Passes; if (!DeleteFn) Passes.add(createGlobalDCEPass()); // Delete unreachable globals Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls std::error_code EC; tool_output_file Out(OutputFilename, EC, sys::fs::F_None); if (EC) { errs() << EC.message() << '\n'; return 1; } if (OutputAssembly) Passes.add( createPrintModulePass(Out.os(), "", PreserveAssemblyUseListOrder)); else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) Passes.add(createBitcodeWriterPass(Out.os(), PreserveBitcodeUseListOrder)); Passes.run(*M.get()); // Declare success. Out.keep(); return 0; }
int main(int argc, char **argv) { InitLLVM X(argc, argv); LLVMContext Context; cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); // Use lazy loading, since we only care about selected global values. SMDiagnostic Err; std::unique_ptr<Module> M = getLazyIRFileModule(InputFilename, Err, Context); if (!M.get()) { Err.print(argv[0], errs()); return 1; } // Use SetVector to avoid duplicates. SetVector<GlobalValue *> GVs; // Figure out which aliases we should extract. for (size_t i = 0, e = ExtractAliases.size(); i != e; ++i) { GlobalAlias *GA = M->getNamedAlias(ExtractAliases[i]); if (!GA) { errs() << argv[0] << ": program doesn't contain alias named '" << ExtractAliases[i] << "'!\n"; return 1; } GVs.insert(GA); } // Extract aliases via regular expression matching. for (size_t i = 0, e = ExtractRegExpAliases.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpAliases[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpAliases[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::alias_iterator GA = M->alias_begin(), E = M->alias_end(); GA != E; GA++) { if (RegEx.match(GA->getName())) { GVs.insert(&*GA); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpAliases[i] << "'!\n"; return 1; } } // Figure out which globals we should extract. for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { GlobalValue *GV = M->getNamedGlobal(ExtractGlobals[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractGlobals[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract globals via regular expression matching. for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpGlobals[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' " "invalid regex: " << Error; } bool match = false; for (auto &GV : M->globals()) { if (RegEx.match(GV.getName())) { GVs.insert(&GV); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpGlobals[i] << "'!\n"; return 1; } } // Figure out which functions we should extract. for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { GlobalValue *GV = M->getFunction(ExtractFuncs[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain function named '" << ExtractFuncs[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract functions via regular expression matching. for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) { std::string Error; StringRef RegExStr = ExtractRegExpFuncs[i]; Regex RegEx(RegExStr); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::iterator F = M->begin(), E = M->end(); F != E; F++) { if (RegEx.match(F->getName())) { GVs.insert(&*F); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpFuncs[i] << "'!\n"; return 1; } } // Figure out which BasicBlocks we should extract. SmallVector<BasicBlock *, 4> BBs; for (StringRef StrPair : ExtractBlocks) { auto BBInfo = StrPair.split(':'); // Get the function. Function *F = M->getFunction(BBInfo.first); if (!F) { errs() << argv[0] << ": program doesn't contain a function named '" << BBInfo.first << "'!\n"; return 1; } // Do not materialize this function. GVs.insert(F); // Get the basic block. auto Res = llvm::find_if(*F, [&](const BasicBlock &BB) { return BB.getName().equals(BBInfo.second); }); if (Res == F->end()) { errs() << argv[0] << ": function " << F->getName() << " doesn't contain a basic block named '" << BBInfo.second << "'!\n"; return 1; } BBs.push_back(&*Res); } // Use *argv instead of argv[0] to work around a wrong GCC warning. ExitOnError ExitOnErr(std::string(*argv) + ": error reading input: "); if (Recursive) { std::vector<llvm::Function *> Workqueue; for (GlobalValue *GV : GVs) { if (auto *F = dyn_cast<Function>(GV)) { Workqueue.push_back(F); } } while (!Workqueue.empty()) { Function *F = &*Workqueue.back(); Workqueue.pop_back(); ExitOnErr(F->materialize()); for (auto &BB : *F) { for (auto &I : BB) { auto *CI = dyn_cast<CallInst>(&I); if (!CI) continue; Function *CF = CI->getCalledFunction(); if (!CF) continue; if (CF->isDeclaration() || GVs.count(CF)) continue; GVs.insert(CF); Workqueue.push_back(CF); } } } } auto Materialize = [&](GlobalValue &GV) { ExitOnErr(GV.materialize()); }; // Materialize requisite global values. if (!DeleteFn) { for (size_t i = 0, e = GVs.size(); i != e; ++i) Materialize(*GVs[i]); } else { // Deleting. Materialize every GV that's *not* in GVs. SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end()); for (auto &F : *M) { if (!GVSet.count(&F)) Materialize(F); } } { std::vector<GlobalValue *> Gvs(GVs.begin(), GVs.end()); legacy::PassManager Extract; Extract.add(createGVExtractionPass(Gvs, DeleteFn)); Extract.run(*M); // Now that we have all the GVs we want, mark the module as fully // materialized. // FIXME: should the GVExtractionPass handle this? ExitOnErr(M->materializeAll()); } // Extract the specified basic blocks from the module and erase the existing // functions. if (!ExtractBlocks.empty()) { legacy::PassManager PM; PM.add(createBlockExtractorPass(BBs, true)); PM.run(*M); } // In addition to deleting all other functions, we also want to spiff it // up a little bit. Do this now. legacy::PassManager Passes; if (!DeleteFn) Passes.add(createGlobalDCEPass()); // Delete unreachable globals Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls std::error_code EC; ToolOutputFile Out(OutputFilename, EC, sys::fs::F_None); if (EC) { errs() << EC.message() << '\n'; return 1; } if (OutputAssembly) Passes.add( createPrintModulePass(Out.os(), "", PreserveAssemblyUseListOrder)); else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) Passes.add(createBitcodeWriterPass(Out.os(), PreserveBitcodeUseListOrder)); Passes.run(*M.get()); // Declare success. Out.keep(); return 0; }
bool InternalizePass::runOnModule(Module &M) { CallGraphWrapperPass *CGPass = getAnalysisIfAvailable<CallGraphWrapperPass>(); CallGraph *CG = CGPass ? &CGPass->getCallGraph() : 0; CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0; bool Changed = false; SmallPtrSet<GlobalValue *, 8> Used; collectUsedGlobalVariables(M, Used, false); // We must assume that globals in llvm.used have a reference that not even // the linker can see, so we don't internalize them. // For llvm.compiler.used the situation is a bit fuzzy. The assembler and // linker can drop those symbols. If this pass is running as part of LTO, // one might think that it could just drop llvm.compiler.used. The problem // is that even in LTO llvm doesn't see every reference. For example, // we don't see references from function local inline assembly. To be // conservative, we internalize symbols in llvm.compiler.used, but we // keep llvm.compiler.used so that the symbol is not deleted by llvm. for (SmallPtrSet<GlobalValue *, 8>::iterator I = Used.begin(), E = Used.end(); I != E; ++I) { GlobalValue *V = *I; ExternalNames.insert(V->getName()); } // Mark all functions not in the api as internal. for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) { if (!shouldInternalize(*I, ExternalNames, OnlyHidden)) continue; I->setLinkage(GlobalValue::InternalLinkage); if (ExternalNode) // Remove a callgraph edge from the external node to this function. ExternalNode->removeOneAbstractEdgeTo((*CG)[I]); Changed = true; ++NumFunctions; DEBUG(dbgs() << "Internalizing func " << I->getName() << "\n"); } // Never internalize the llvm.used symbol. It is used to implement // attribute((used)). // FIXME: Shouldn't this just filter on llvm.metadata section?? ExternalNames.insert("llvm.used"); ExternalNames.insert("llvm.compiler.used"); // Never internalize anchors used by the machine module info, else the info // won't find them. (see MachineModuleInfo.) ExternalNames.insert("llvm.global_ctors"); ExternalNames.insert("llvm.global_dtors"); ExternalNames.insert("llvm.global.annotations"); // Never internalize symbols code-gen inserts. // FIXME: We should probably add this (and the __stack_chk_guard) via some // type of call-back in CodeGen. ExternalNames.insert("__stack_chk_fail"); ExternalNames.insert("__stack_chk_guard"); // Mark all global variables with initializers that are not in the api as // internal as well. for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I) { if (!shouldInternalize(*I, ExternalNames, OnlyHidden)) continue; I->setLinkage(GlobalValue::InternalLinkage); Changed = true; ++NumGlobals; DEBUG(dbgs() << "Internalized gvar " << I->getName() << "\n"); } // Mark all aliases that are not in the api as internal as well. for (Module::alias_iterator I = M.alias_begin(), E = M.alias_end(); I != E; ++I) { if (!shouldInternalize(*I, ExternalNames, OnlyHidden)) continue; I->setLinkage(GlobalValue::InternalLinkage); Changed = true; ++NumAliases; DEBUG(dbgs() << "Internalized alias " << I->getName() << "\n"); } return Changed; }
/// Based on GetAllUndefinedSymbols() from LLVM3.2 /// /// GetAllUndefinedSymbols - calculates the set of undefined symbols that still /// exist in an LLVM module. This is a bit tricky because there may be two /// symbols with the same name but different LLVM types that will be resolved to /// each other but aren't currently (thus we need to treat it as resolved). /// /// Inputs: /// M - The module in which to find undefined symbols. /// /// Outputs: /// UndefinedSymbols - A set of C++ strings containing the name of all /// undefined symbols. /// static void GetAllUndefinedSymbols(Module *M, std::set<std::string> &UndefinedSymbols) { static const std::string llvmIntrinsicPrefix="llvm."; std::set<std::string> DefinedSymbols; UndefinedSymbols.clear(); KLEE_DEBUG_WITH_TYPE("klee_linker", dbgs() << "*** Computing undefined symbols ***\n"); for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) if (I->hasName()) { if (I->isDeclaration()) UndefinedSymbols.insert(I->getName()); else if (!I->hasLocalLinkage()) { #if LLVM_VERSION_CODE < LLVM_VERSION(3, 5) assert(!I->hasDLLImportLinkage() && "Found dllimported non-external symbol!"); #else assert(!I->hasDLLImportStorageClass() && "Found dllimported non-external symbol!"); #endif DefinedSymbols.insert(I->getName()); } } for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasName()) { if (I->isDeclaration()) UndefinedSymbols.insert(I->getName()); else if (!I->hasLocalLinkage()) { #if LLVM_VERSION_CODE < LLVM_VERSION(3, 5) assert(!I->hasDLLImportLinkage() && "Found dllimported non-external symbol!"); #else assert(!I->hasDLLImportStorageClass() && "Found dllimported non-external symbol!"); #endif DefinedSymbols.insert(I->getName()); } } for (Module::alias_iterator I = M->alias_begin(), E = M->alias_end(); I != E; ++I) if (I->hasName()) DefinedSymbols.insert(I->getName()); // Prune out any defined symbols from the undefined symbols set // and other symbols we don't want to treat as an undefined symbol std::vector<std::string> SymbolsToRemove; for (std::set<std::string>::iterator I = UndefinedSymbols.begin(); I != UndefinedSymbols.end(); ++I ) { if (DefinedSymbols.count(*I)) { SymbolsToRemove.push_back(*I); continue; } // Strip out llvm intrinsics if ( (I->size() >= llvmIntrinsicPrefix.size() ) && (I->compare(0, llvmIntrinsicPrefix.size(), llvmIntrinsicPrefix) == 0) ) { KLEE_DEBUG_WITH_TYPE("klee_linker", dbgs() << "LLVM intrinsic " << *I << " has will be removed from undefined symbols"<< "\n"); SymbolsToRemove.push_back(*I); continue; } // Symbol really is undefined KLEE_DEBUG_WITH_TYPE("klee_linker", dbgs() << "Symbol " << *I << " is undefined.\n"); } // Remove KLEE intrinsics from set of undefined symbols for (SpecialFunctionHandler::const_iterator sf = SpecialFunctionHandler::begin(), se = SpecialFunctionHandler::end(); sf != se; ++sf) { if (UndefinedSymbols.find(sf->name) == UndefinedSymbols.end()) continue; SymbolsToRemove.push_back(sf->name); KLEE_DEBUG_WITH_TYPE("klee_linker", dbgs() << "KLEE intrinsic " << sf->name << " has will be removed from undefined symbols"<< "\n"); } // Now remove the symbols from undefined set. for (size_t i = 0, j = SymbolsToRemove.size(); i < j; ++i ) UndefinedSymbols.erase(SymbolsToRemove[i]); KLEE_DEBUG_WITH_TYPE("klee_linker", dbgs() << "*** Finished computing undefined symbols ***\n"); }
int main(int argc, char **argv) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); PrettyStackTraceProgram X(argc, argv); LLVMContext &Context = getGlobalContext(); llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. cl::ParseCommandLineOptions(argc, argv, "llvm extractor\n"); // Use lazy loading, since we only care about selected global values. SMDiagnostic Err; std::unique_ptr<Module> M; M.reset(getLazyIRFileModule(InputFilename, Err, Context)); if (!M.get()) { Err.print(argv[0], errs()); return 1; } // Use SetVector to avoid duplicates. SetVector<GlobalValue *> GVs; // Figure out which aliases we should extract. for (size_t i = 0, e = ExtractAliases.size(); i != e; ++i) { GlobalAlias *GA = M->getNamedAlias(ExtractAliases[i]); if (!GA) { errs() << argv[0] << ": program doesn't contain alias named '" << ExtractAliases[i] << "'!\n"; return 1; } GVs.insert(GA); } // Extract aliases via regular expression matching. for (size_t i = 0, e = ExtractRegExpAliases.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpAliases[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpAliases[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::alias_iterator GA = M->alias_begin(), E = M->alias_end(); GA != E; GA++) { if (RegEx.match(GA->getName())) { GVs.insert(&*GA); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpAliases[i] << "'!\n"; return 1; } } // Figure out which globals we should extract. for (size_t i = 0, e = ExtractGlobals.size(); i != e; ++i) { GlobalValue *GV = M->getNamedGlobal(ExtractGlobals[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractGlobals[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract globals via regular expression matching. for (size_t i = 0, e = ExtractRegExpGlobals.size(); i != e; ++i) { std::string Error; Regex RegEx(ExtractRegExpGlobals[i]); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpGlobals[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::global_iterator GV = M->global_begin(), E = M->global_end(); GV != E; GV++) { if (RegEx.match(GV->getName())) { GVs.insert(&*GV); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpGlobals[i] << "'!\n"; return 1; } } // Figure out which functions we should extract. for (size_t i = 0, e = ExtractFuncs.size(); i != e; ++i) { GlobalValue *GV = M->getFunction(ExtractFuncs[i]); if (!GV) { errs() << argv[0] << ": program doesn't contain function named '" << ExtractFuncs[i] << "'!\n"; return 1; } GVs.insert(GV); } // Extract functions via regular expression matching. for (size_t i = 0, e = ExtractRegExpFuncs.size(); i != e; ++i) { std::string Error; StringRef RegExStr = ExtractRegExpFuncs[i]; Regex RegEx(RegExStr); if (!RegEx.isValid(Error)) { errs() << argv[0] << ": '" << ExtractRegExpFuncs[i] << "' " "invalid regex: " << Error; } bool match = false; for (Module::iterator F = M->begin(), E = M->end(); F != E; F++) { if (RegEx.match(F->getName())) { GVs.insert(&*F); match = true; } } if (!match) { errs() << argv[0] << ": program doesn't contain global named '" << ExtractRegExpFuncs[i] << "'!\n"; return 1; } } // Materialize requisite global values. if (!DeleteFn) for (size_t i = 0, e = GVs.size(); i != e; ++i) { GlobalValue *GV = GVs[i]; if (GV->isMaterializable()) { std::string ErrInfo; if (GV->Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } } } else { // Deleting. Materialize every GV that's *not* in GVs. SmallPtrSet<GlobalValue *, 8> GVSet(GVs.begin(), GVs.end()); for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) { GlobalVariable *G = I; if (!GVSet.count(G) && G->isMaterializable()) { std::string ErrInfo; if (G->Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } } } for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) { Function *F = I; if (!GVSet.count(F) && F->isMaterializable()) { std::string ErrInfo; if (F->Materialize(&ErrInfo)) { errs() << argv[0] << ": error reading input: " << ErrInfo << "\n"; return 1; } } } } // In addition to deleting all other functions, we also want to spiff it // up a little bit. Do this now. PassManager Passes; Passes.add(new DataLayoutPass(M.get())); // Use correct DataLayout std::vector<GlobalValue*> Gvs(GVs.begin(), GVs.end()); Passes.add(createGVExtractionPass(Gvs, DeleteFn)); if (!DeleteFn) Passes.add(createGlobalDCEPass()); // Delete unreachable globals Passes.add(createStripDeadDebugInfoPass()); // Remove dead debug info Passes.add(createStripDeadPrototypesPass()); // Remove dead func decls std::string ErrorInfo; tool_output_file Out(OutputFilename.c_str(), ErrorInfo, sys::fs::F_None); if (!ErrorInfo.empty()) { errs() << ErrorInfo << '\n'; return 1; } if (OutputAssembly) Passes.add(createPrintModulePass(Out.os())); else if (Force || !CheckBitcodeOutputToConsole(Out.os(), true)) Passes.add(createBitcodeWriterPass(Out.os())); Passes.run(*M.get()); // Declare success. Out.keep(); return 0; }