Skip to content

Commit 030ff0f

Browse files
committed
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
1 parent 03a8568 commit 030ff0f

File tree

3 files changed

+150
-0
lines changed

3 files changed

+150
-0
lines changed
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
set(LLVM_LINK_COMPONENTS
2+
Object
3+
)
4+
5+
add_llvm_tool(llvm-strings
6+
llvm-strings.cpp
7+
)
8+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
;===- ./tools/llvm-strings/LLVMBuild.txt -----------------------*- Conf -*--===;
2+
;
3+
; The LLVM Compiler Infrastructure
4+
;
5+
; This file is distributed under the University of Illinois Open Source
6+
; License. See LICENSE.TXT for details.
7+
;
8+
;===------------------------------------------------------------------------===;
9+
;
10+
; This is an LLVMBuild description file for the components in this subdirectory.
11+
;
12+
; For more information on the LLVMBuild system, please see:
13+
;
14+
; http://llvm.org/docs/LLVMBuild.html
15+
;
16+
;===------------------------------------------------------------------------===;
17+
18+
[component_0]
19+
type = Tool
20+
name = llvm-strings
21+
parent = Tools
22+
required_libraries = Archive Object
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
//===-- llvm-strings.cpp - Printable String dumping utility ---------------===//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
//
10+
// This program is a utility that works like binutils "strings", that is, it
11+
// prints out printable strings in a binary, objdump, or archive file.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "llvm/IR/LLVMContext.h"
16+
#include "llvm/Object/Archive.h"
17+
#include "llvm/Object/Binary.h"
18+
#include "llvm/Object/ObjectFile.h"
19+
#include "llvm/Support/CommandLine.h"
20+
#include "llvm/Support/Error.h"
21+
#include "llvm/Support/MemoryBuffer.h"
22+
#include "llvm/Support/PrettyStackTrace.h"
23+
#include "llvm/Support/Program.h"
24+
#include "llvm/Support/Signals.h"
25+
#include <string>
26+
27+
using namespace llvm;
28+
using namespace llvm::object;
29+
30+
static cl::list<std::string> InputFileNames(cl::Positional,
31+
cl::desc("<input object files>"),
32+
cl::ZeroOrMore);
33+
34+
static void dump(raw_ostream &OS, StringRef Contents) {
35+
const char *S = nullptr;
36+
for (const char *P = Contents.begin(), *E = Contents.end(); P < E; ++P) {
37+
if (std::isgraph(*P) || std::isblank(*P)) {
38+
if (S == nullptr)
39+
S = P;
40+
} else if (S) {
41+
if (P - S > 3)
42+
OS << StringRef(S, P - S) << '\n';
43+
S = nullptr;
44+
}
45+
}
46+
}
47+
48+
namespace {
49+
class Strings {
50+
LLVMContext Context;
51+
raw_ostream &OS;
52+
53+
void dump(const ObjectFile *O) {
54+
for (const auto &S : O->sections()) {
55+
StringRef Contents;
56+
if (!S.getContents(Contents))
57+
::dump(OS, Contents);
58+
}
59+
}
60+
61+
void dump(const Archive *A) {
62+
Error E;
63+
for (auto &Element : A->children(E)) {
64+
if (Expected<std::unique_ptr<Binary>> Child =
65+
Element.getAsBinary(&Context)) {
66+
dump(dyn_cast<ObjectFile>(&**Child));
67+
} else {
68+
if (auto E = isNotObjectErrorInvalidFileType(Child.takeError())) {
69+
errs() << A->getFileName();
70+
if (Expected<StringRef> Name = Element.getName())
71+
errs() << '(' << *Name << ')';
72+
logAllUnhandledErrors(std::move(E), errs(), "");
73+
errs() << '\n';
74+
}
75+
}
76+
}
77+
static_cast<bool>(E);
78+
}
79+
80+
public:
81+
Strings(raw_ostream &S) : OS(S) {}
82+
83+
void scan(StringRef File) {
84+
ErrorOr<std::unique_ptr<MemoryBuffer>> Buffer =
85+
MemoryBuffer::getFileOrSTDIN(File);
86+
if (std::error_code EC = Buffer.getError()) {
87+
errs() << File << ": " << EC.message() << '\n';
88+
return;
89+
}
90+
91+
if (Expected<std::unique_ptr<Binary>> B =
92+
createBinary(Buffer.get()->getMemBufferRef(), &Context)) {
93+
if (auto *A = dyn_cast<Archive>(&**B))
94+
return dump(A);
95+
if (auto *O = dyn_cast<ObjectFile>(&**B))
96+
return dump(O);
97+
::dump(OS, Buffer.get()->getMemBufferRef().getBuffer());
98+
} else {
99+
consumeError(B.takeError());
100+
::dump(OS, Buffer.get()->getMemBufferRef().getBuffer());
101+
}
102+
}
103+
};
104+
}
105+
106+
int main(int argc, char **argv) {
107+
sys::PrintStackTraceOnErrorSignal(argv[0]);
108+
PrettyStackTraceProgram X(argc, argv);
109+
110+
cl::ParseCommandLineOptions(argc, argv, "llvm string dumper\n");
111+
112+
if (InputFileNames.empty())
113+
InputFileNames.push_back("-");
114+
115+
Strings S(llvm::outs());
116+
std::for_each(InputFileNames.begin(), InputFileNames.end(),
117+
[&S](StringRef F) { S.scan(F); });
118+
return EXIT_SUCCESS;
119+
}
120+

0 commit comments

Comments
 (0)