Index: tools/llvm-strings/CMakeLists.txt =================================================================== --- /dev/null +++ tools/llvm-strings/CMakeLists.txt @@ -0,0 +1,8 @@ +set(LLVM_LINK_COMPONENTS + Object + ) + +add_llvm_tool(llvm-strings + llvm-strings.cpp + ) + Index: tools/llvm-strings/LLVMBuild.txt =================================================================== --- /dev/null +++ tools/llvm-strings/LLVMBuild.txt @@ -0,0 +1,22 @@ +;===- ./tools/llvm-strings/LLVMBuild.txt -----------------------*- Conf -*--===; +; +; The LLVM Compiler Infrastructure +; +; This file is distributed under the University of Illinois Open Source +; License. See LICENSE.TXT for details. +; +;===------------------------------------------------------------------------===; +; +; This is an LLVMBuild description file for the components in this subdirectory. +; +; For more information on the LLVMBuild system, please see: +; +; http://llvm.org/docs/LLVMBuild.html +; +;===------------------------------------------------------------------------===; + +[component_0] +type = Tool +name = llvm-strings +parent = Tools +required_libraries = Archive Object Index: tools/llvm-strings/llvm-strings.cpp =================================================================== --- /dev/null +++ tools/llvm-strings/llvm-strings.cpp @@ -0,0 +1,116 @@ +//===-- llvm-strings.cpp - Printable String dumping utility ---------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This program is a utility that works like binutils "strings", that is, it +// prints out printable strings in a binary, objdump, or archive file. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/LLVMContext.h" +#include "llvm/Object/Archive.h" +#include "llvm/Object/Binary.h" +#include "llvm/Object/ObjectFile.h" +#include "llvm/Support/CommandLine.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/PrettyStackTrace.h" +#include "llvm/Support/Program.h" +#include "llvm/Support/Signals.h" +#include + +using namespace llvm; +using namespace llvm::object; + +static cl::list InputFileNames(cl::Positional, + cl::desc(""), + cl::ZeroOrMore); + +namespace { +class Strings { + LLVMContext Context; + + void Dump(StringRef Contents) { + const char *S = nullptr; + for (const char *P = Contents.begin(), *E = Contents.end(); P < E; ++P) { + if (std::isgraph(*P) || std::isblank(*P)) { + if (S == nullptr) + S = P; + } else if (S) { + if (P - S > 3) + llvm::outs() << StringRef(S, P - S) << '\n'; + S = nullptr; + } + } + } + + void Dump(const ObjectFile *O) { + for (const auto &S : O->sections()) { + StringRef Contents; + if (!S.getContents(Contents)) + Dump(Contents); + } + } + + void Dump(const Archive *A) { + Error E; + for (auto &Element : A->children(E)) { + if (Expected> Child = + Element.getAsBinary(&Context)) { + Dump(dyn_cast(&**Child)); + } else { + if (auto E = isNotObjectErrorInvalidFileType(Child.takeError())) { + errs() << A->getFileName(); + if (Expected Name = Element.getName()) + errs() << '(' << *Name << ')'; + logAllUnhandledErrors(std::move(E), errs(), ""); + errs() << '\n'; + } + } + } + static_cast(E); + } + +public: + void Scan(StringRef File) { + ErrorOr> Buffer = + MemoryBuffer::getFileOrSTDIN(File); + if (std::error_code EC = Buffer.getError()) { + errs() << File << ": " << EC.message() << '\n'; + return; + } + + if (Expected> B = + createBinary(Buffer.get()->getMemBufferRef(), &Context)) { + if (auto *A = dyn_cast(&**B)) + return Dump(A); + if (auto *O = dyn_cast(&**B)) + return Dump(O); + Dump(Buffer.get()->getMemBufferRef().getBuffer()); + } else { + consumeError(B.takeError()); + Dump(Buffer.get()->getMemBufferRef().getBuffer()); + } + } +}; +} + +int main(int argc, char **argv) { + sys::PrintStackTraceOnErrorSignal(argv[0]); + PrettyStackTraceProgram X(argc, argv); + + cl::ParseCommandLineOptions(argc, argv, "llvm string dumper\n"); + + if (InputFileNames.empty()) + InputFileNames.push_back("-"); + + Strings S; + std::for_each(InputFileNames.begin(), InputFileNames.end(), + [&S](StringRef F) { S.Scan(F); }); + return EXIT_SUCCESS; +}