From 030ff0f2155b5b1f34a8edd650402cd322b11de0 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 11 Nov 2016 03:44:12 +0000 Subject: llvm-strings: introduce basic strings tool This is a replacement to binutils' string tool. It prints strings found in a binary (object file, executable, or archive library). It is rather bare and not functionally equivalent, however, it lays the groundwork necessary for the strings tool, enabling iterative development of features to reach feature parity. llvm-svn: 286556 --- llvm/tools/llvm-strings/llvm-strings.cpp | 120 +++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 llvm/tools/llvm-strings/llvm-strings.cpp (limited to 'llvm/tools/llvm-strings/llvm-strings.cpp') diff --git a/llvm/tools/llvm-strings/llvm-strings.cpp b/llvm/tools/llvm-strings/llvm-strings.cpp new file mode 100644 index 00000000000..daabcd6e6d9 --- /dev/null +++ b/llvm/tools/llvm-strings/llvm-strings.cpp @@ -0,0 +1,120 @@ +//===-- 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); + +static void dump(raw_ostream &OS, 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) + OS << StringRef(S, P - S) << '\n'; + S = nullptr; + } + } +} + +namespace { +class Strings { + LLVMContext Context; + raw_ostream &OS; + + void dump(const ObjectFile *O) { + for (const auto &S : O->sections()) { + StringRef Contents; + if (!S.getContents(Contents)) + ::dump(OS, 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: + Strings(raw_ostream &S) : OS(S) {} + + 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(OS, Buffer.get()->getMemBufferRef().getBuffer()); + } else { + consumeError(B.takeError()); + ::dump(OS, 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(llvm::outs()); + std::for_each(InputFileNames.begin(), InputFileNames.end(), + [&S](StringRef F) { S.scan(F); }); + return EXIT_SUCCESS; +} + -- cgit v1.2.3