Index: test/Other/bcanalyzer-funcs-globals.txt =================================================================== --- /dev/null +++ test/Other/bcanalyzer-funcs-globals.txt @@ -0,0 +1,7 @@ +RUN: llvm-bcanalyzer -print-funcs-and-globals %S/Inputs/funcs-globals.bc | FileCheck -check-prefix=CHECK %s + +CHECK: funcs-globals.bc: 12343254354 +CHECK: funcs-globals.bc: Hello world +CHECK-NEXT: funcs-globals.bc: main +CHECK-NEXT: funcs-globals.bc: printf +CHECK-NEXT: funcs-globals.bc: puts \ No newline at end of file Index: tools/llvm-bcanalyzer/CMakeLists.txt =================================================================== --- tools/llvm-bcanalyzer/CMakeLists.txt +++ tools/llvm-bcanalyzer/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS BitReader + Core Support ) Index: tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp =================================================================== --- tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp +++ tools/llvm-bcanalyzer/llvm-bcanalyzer.cpp @@ -31,6 +31,7 @@ #include "llvm/Bitcode/BitcodeReader.h" #include "llvm/Bitcode/BitstreamReader.h" #include "llvm/Bitcode/LLVMBitCodes.h" +#include "llvm/IR/Constants.h" #include "llvm/IR/Verifier.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Format.h" @@ -59,6 +60,10 @@ cl::desc("Do not print per-code histogram")); static cl::opt +PrintFuncAndGlobals("print-funcs-and-globals", + cl::desc("Printing functions and global variables")); + +static cl::opt NonSymbolic("non-symbolic", cl::desc("Emit numeric info in dump even if" " symbolic info is available")); @@ -753,6 +758,54 @@ return false; } +static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) { + raw_ostream &OS = errs(); + OS << (char *)Context << ": "; + switch (DI.getSeverity()) { + case DS_Error: + OS << "error: "; + break; + case DS_Warning: + OS << "warning: "; + break; + case DS_Remark: + OS << "remark: "; + break; + case DS_Note: + OS << "note: "; + break; + } +} + +static void printGlobalVariablesAsString(const Module &Mod) { + const Module::GlobalListType &GlobalList = Mod.getGlobalList(); + for (Module::const_global_iterator I = GlobalList.begin(), + E = GlobalList.end(); I != E; ++I) { + outs() << InputFilename + ": "; + outs() << I->getName() + "\n"; + if (const ConstantDataArray *CA = + dyn_cast(I->getOperandList()->get())) { + if (!CA->isString()) + continue; + StringRef PrintStr = CA->getAsString(); + PrintStr = PrintStr.ltrim("\n"); + size_t pos = PrintStr.find_first_of("\n"); + PrintStr = PrintStr.substr(0, pos); + outs() << InputFilename + ": "; + outs() << PrintStr + "\n"; + } + } +} + +static void printFunctionNamesAsString(const Module &Mod) { + const Module::FunctionListType &FunctionList = Mod.getFunctionList(); + for (Module::const_iterator I = FunctionList.begin(), + E = FunctionList.end(); I!=E; ++I) { + outs() << InputFilename + ": "; + outs() << I->getName() + "\n"; + } +} + /// AnalyzeBitcode - Analyze the bitcode file specified by InputFilename. static int AnalyzeBitcode() { std::unique_ptr StreamBuffer; @@ -807,6 +860,18 @@ ++NumTopBlocks; } + if (PrintFuncAndGlobals) { + ExitOnError ExitOnErr; + LLVMContext Context; + Context.setDiagnosticHandler(diagnosticHandler, nullptr); + std::unique_ptr M = + ExitOnErr(getOwningLazyBitcodeModule(std::move(StreamBuffer), Context, + /*ShouldLazyLoadMetadata=*/true)); + outs() << "Functions and globals of " << InputFilename << ":\n"; + printGlobalVariablesAsString(*M); + printFunctionNamesAsString(*M); + } + if (Dump) outs() << "\n\n"; uint64_t BufferSizeBits = Stream.getBitcodeBytes().size() * CHAR_BIT;