llvm-readobj.cpp revision ee37b6e4cd53b8e2412c522eeab4e39b434f00c6
1//===- llvm-readobj.cpp - Dump contents of an Object File -----------------===//
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 traditional Unix "readelf",
11// except that it can handle any type of object file recognized by lib/Object.
12//
13// It makes use of the generic ObjectFile interface.
14//
15// Caution: This utility is new, experimental, unsupported, and incomplete.
16//
17//===----------------------------------------------------------------------===//
18
19#include "llvm/Object/ObjectFile.h"
20#include "llvm/Analysis/Verifier.h"
21#include "llvm/ADT/Triple.h"
22#include "llvm/Support/Format.h"
23#include "llvm/Support/CommandLine.h"
24#include "llvm/Support/PrettyStackTrace.h"
25#include "llvm/Support/Debug.h"
26#include "llvm/Support/Signals.h"
27#include "llvm/Support/FormattedStream.h"
28
29using namespace llvm;
30using namespace llvm::object;
31
32static cl::opt<std::string>
33InputFilename(cl::Positional, cl::desc("<input object>"), cl::init(""));
34
35void DumpSymbolHeader() {
36  outs() << format("  %-32s", (const char*)"Name")
37         << format("  %-4s", (const char*)"Type")
38         << format("  %-16s", (const char*)"Address")
39         << format("  %-16s", (const char*)"Size")
40         << format("  %-16s", (const char*)"FileOffset")
41         << format("  %-26s", (const char*)"Flags")
42         << "\n";
43}
44
45const char *GetTypeStr(SymbolRef::Type Type) {
46  switch (Type) {
47  case SymbolRef::ST_Unknown: return "?";
48  case SymbolRef::ST_Data: return "DATA";
49  case SymbolRef::ST_Debug: return "DBG";
50  case SymbolRef::ST_File: return "FILE";
51  case SymbolRef::ST_Function: return "FUNC";
52  case SymbolRef::ST_Other: return "-";
53  }
54  return "INV";
55}
56
57std::string GetFlagStr(uint32_t Flags) {
58  std::string result;
59  if (Flags & SymbolRef::SF_Undefined)
60    result += "undef,";
61  if (Flags & SymbolRef::SF_Global)
62    result += "global,";
63  if (Flags & SymbolRef::SF_Weak)
64    result += "weak,";
65  if (Flags & SymbolRef::SF_Absolute)
66    result += "absolute,";
67  if (Flags & SymbolRef::SF_ThreadLocal)
68    result += "threadlocal,";
69  if (Flags & SymbolRef::SF_Common)
70    result += "common,";
71  if (Flags & SymbolRef::SF_FormatSpecific)
72    result += "formatspecific,";
73
74  // Remove trailing comma
75  if (result.size() > 0) {
76    result.erase(result.size() - 1);
77  }
78  return result;
79}
80
81void DumpSymbol(const SymbolRef &sym) {
82    StringRef Name;
83    SymbolRef::Type Type;
84    uint32_t Flags;
85    uint64_t Address;
86    uint64_t Size;
87    uint64_t FileOffset;
88    sym.getName(Name);
89    sym.getAddress(Address);
90    sym.getSize(Size);
91    sym.getFileOffset(FileOffset);
92    sym.getType(Type);
93    sym.getFlags(Flags);
94
95    // format() can't handle StringRefs
96    outs() << format("  %-32s", Name.str().c_str())
97           << format("  %-4s", GetTypeStr(Type))
98           << format("  %16"PRIx64, Address)
99           << format("  %16"PRIx64, Size)
100           << format("  %16"PRIx64, FileOffset)
101           << "  " << GetFlagStr(Flags)
102           << "\n";
103}
104
105
106// Iterate through the normal symbols in the ObjectFile
107void DumpSymbols(const ObjectFile *obj) {
108  error_code ec;
109  uint32_t count = 0;
110  outs() << "Symbols:\n";
111  symbol_iterator it = obj->begin_symbols();
112  symbol_iterator ie = obj->end_symbols();
113  while (it != ie) {
114    DumpSymbol(*it);
115    it.increment(ec);
116    if (ec)
117      report_fatal_error("Symbol iteration failed");
118    ++count;
119  }
120  outs() << "  Total: " << count << "\n\n";
121}
122
123// Iterate through the dynamic symbols in the ObjectFile.
124void DumpDynamicSymbols(const ObjectFile *obj) {
125  error_code ec;
126  uint32_t count = 0;
127  outs() << "Dynamic Symbols:\n";
128  symbol_iterator it = obj->begin_dynamic_symbols();
129  symbol_iterator ie = obj->end_dynamic_symbols();
130  while (it != ie) {
131    DumpSymbol(*it);
132    it.increment(ec);
133    if (ec)
134      report_fatal_error("Symbol iteration failed");
135    ++count;
136  }
137  outs() << "  Total: " << count << "\n\n";
138}
139
140void DumpLibrary(const LibraryRef &lib) {
141  StringRef path;
142  lib.getPath(path);
143  outs() << "  " << path << "\n";
144}
145
146// Iterate through needed libraries
147void DumpLibrariesNeeded(const ObjectFile *obj) {
148  error_code ec;
149  uint32_t count = 0;
150  library_iterator it = obj->begin_libraries_needed();
151  library_iterator ie = obj->end_libraries_needed();
152  outs() << "Libraries needed:\n";
153  while (it != ie) {
154    DumpLibrary(*it);
155    it.increment(ec);
156    if (ec)
157      report_fatal_error("Needed libraries iteration failed");
158    ++count;
159  }
160  outs() << "  Total: " << count << "\n\n";
161}
162
163void DumpHeaders(const ObjectFile *obj) {
164  outs() << "File Format : " << obj->getFileFormatName() << "\n";
165  outs() << "Arch        : "
166         << Triple::getArchTypeName((llvm::Triple::ArchType)obj->getArch())
167         << "\n";
168  outs() << "Address Size: " << (8*obj->getBytesInAddress()) << " bits\n";
169  outs() << "Load Name   : " << obj->getLoadName() << "\n";
170  outs() << "\n";
171}
172
173int main(int argc, char** argv) {
174  error_code ec;
175  sys::PrintStackTraceOnErrorSignal();
176  PrettyStackTraceProgram X(argc, argv);
177
178  cl::ParseCommandLineOptions(argc, argv,
179                              "LLVM Object Reader\n");
180
181  if (InputFilename.empty()) {
182    errs() << "Please specify an input filename\n";
183    return 1;
184  }
185
186  // Open the object file
187  OwningPtr<MemoryBuffer> File;
188  if (MemoryBuffer::getFile(InputFilename, File)) {
189    errs() << InputFilename << ": Open failed\n";
190    return 1;
191  }
192
193  ObjectFile *obj = ObjectFile::createObjectFile(File.take());
194  if (!obj) {
195    errs() << InputFilename << ": Object type not recognized\n";
196  }
197
198  DumpHeaders(obj);
199  DumpSymbols(obj);
200  DumpDynamicSymbols(obj);
201  DumpLibrariesNeeded(obj);
202  return 0;
203}
204
205