blob: bb4a77bc7966152432f5361a35369f292a0fdeb8 [file] [log] [blame]
Michael J. Spencer92e1deb2011-01-20 06:39:06 +00001//===-- llvm-objdump.cpp - Object file dumping utility for llvm -----------===//
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 "objdump", that is, it
11// dumps out a plethora of information about an object file depending on the
12// flags.
13//
14//===----------------------------------------------------------------------===//
15
Benjamin Kramer0b8b7712011-09-19 17:56:04 +000016#include "llvm-objdump.h"
Benjamin Kramer685a2502011-07-20 19:37:35 +000017#include "MCFunction.h"
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000018#include "llvm/Object/ObjectFile.h"
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000019#include "llvm/ADT/OwningPtr.h"
20#include "llvm/ADT/Triple.h"
Benjamin Kramer739b65b2011-07-15 18:39:24 +000021#include "llvm/ADT/STLExtras.h"
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000022#include "llvm/MC/MCAsmInfo.h"
23#include "llvm/MC/MCDisassembler.h"
24#include "llvm/MC/MCInst.h"
25#include "llvm/MC/MCInstPrinter.h"
Evan Cheng78011362011-08-23 20:15:21 +000026#include "llvm/MC/MCInstrAnalysis.h"
Benjamin Kramer685a2502011-07-20 19:37:35 +000027#include "llvm/MC/MCInstrDesc.h"
28#include "llvm/MC/MCInstrInfo.h"
James Molloyb9505852011-09-07 17:24:38 +000029#include "llvm/MC/MCSubtargetInfo.h"
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000030#include "llvm/Support/CommandLine.h"
31#include "llvm/Support/Debug.h"
32#include "llvm/Support/Format.h"
Benjamin Kramer853b0fd2011-07-25 23:04:36 +000033#include "llvm/Support/GraphWriter.h"
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000034#include "llvm/Support/Host.h"
35#include "llvm/Support/ManagedStatic.h"
36#include "llvm/Support/MemoryBuffer.h"
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000037#include "llvm/Support/MemoryObject.h"
38#include "llvm/Support/PrettyStackTrace.h"
39#include "llvm/Support/Signals.h"
40#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000041#include "llvm/Support/TargetRegistry.h"
42#include "llvm/Support/TargetSelect.h"
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000043#include "llvm/Support/raw_ostream.h"
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000044#include "llvm/Support/system_error.h"
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000045#include <algorithm>
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000046#include <cstring>
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000047using namespace llvm;
48using namespace object;
49
Benjamin Kramer0b8b7712011-09-19 17:56:04 +000050static cl::list<std::string>
51InputFilenames(cl::Positional, cl::desc("<input object files>"),cl::ZeroOrMore);
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000052
Benjamin Kramer0b8b7712011-09-19 17:56:04 +000053static cl::opt<bool>
54Disassemble("disassemble",
55 cl::desc("Display assembler mnemonics for the machine instructions"));
56static cl::alias
57Disassembled("d", cl::desc("Alias for --disassemble"),
58 cl::aliasopt(Disassemble));
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000059
Benjamin Kramer0b8b7712011-09-19 17:56:04 +000060static cl::opt<bool>
61MachO("macho", cl::desc("Use MachO specific object file parser"));
62static cl::alias
63MachOm("m", cl::desc("Alias for --macho"), cl::aliasopt(MachO));
Benjamin Kramer685a2502011-07-20 19:37:35 +000064
Benjamin Kramer0b8b7712011-09-19 17:56:04 +000065cl::opt<std::string>
66llvm::TripleName("triple", cl::desc("Target triple to disassemble for, "
67 "see -version for available targets"));
68
69cl::opt<std::string>
70llvm::ArchName("arch", cl::desc("Target arch to disassemble for, "
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000071 "see -version for available targets"));
72
Benjamin Kramer0b8b7712011-09-19 17:56:04 +000073static StringRef ToolName;
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000074
Benjamin Kramer0b8b7712011-09-19 17:56:04 +000075static bool error(error_code ec) {
76 if (!ec) return false;
Michael J. Spencer25b15772011-06-25 17:55:23 +000077
Benjamin Kramer0b8b7712011-09-19 17:56:04 +000078 outs() << ToolName << ": error reading file: " << ec.message() << ".\n";
79 outs().flush();
80 return true;
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000081}
82
83static const Target *GetTarget(const ObjectFile *Obj = NULL) {
84 // Figure out the target triple.
85 llvm::Triple TT("unknown-unknown-unknown");
Michael J. Spencerd11699d2011-01-20 07:22:04 +000086 if (TripleName.empty()) {
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000087 if (Obj)
88 TT.setArch(Triple::ArchType(Obj->getArch()));
Michael J. Spencerd11699d2011-01-20 07:22:04 +000089 } else
Michael J. Spencer92e1deb2011-01-20 06:39:06 +000090 TT.setTriple(Triple::normalize(TripleName));
91
92 if (!ArchName.empty())
93 TT.setArchName(ArchName);
94
95 TripleName = TT.str();
96
97 // Get the target specific parser.
98 std::string Error;
99 const Target *TheTarget = TargetRegistry::lookupTarget(TripleName, Error);
100 if (TheTarget)
101 return TheTarget;
102
103 errs() << ToolName << ": error: unable to get target for '" << TripleName
104 << "', see --version and --triple.\n";
105 return 0;
106}
107
Benjamin Kramer0b8b7712011-09-19 17:56:04 +0000108void llvm::DumpBytes(StringRef bytes) {
109 static const char hex_rep[] = "0123456789abcdef";
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000110 // FIXME: The real way to do this is to figure out the longest instruction
111 // and align to that size before printing. I'll fix this when I get
112 // around to outputting relocations.
113 // 15 is the longest x86 instruction
114 // 3 is for the hex rep of a byte + a space.
115 // 1 is for the null terminator.
116 enum { OutputSize = (15 * 3) + 1 };
117 char output[OutputSize];
118
119 assert(bytes.size() <= 15
120 && "DumpBytes only supports instructions of up to 15 bytes");
121 memset(output, ' ', sizeof(output));
122 unsigned index = 0;
123 for (StringRef::iterator i = bytes.begin(),
124 e = bytes.end(); i != e; ++i) {
125 output[index] = hex_rep[(*i & 0xF0) >> 4];
126 output[index + 1] = hex_rep[*i & 0xF];
127 index += 3;
128 }
129
130 output[sizeof(output) - 1] = 0;
131 outs() << output;
132}
133
Benjamin Kramer0b8b7712011-09-19 17:56:04 +0000134void llvm::DisassembleInputLibObject(StringRef Filename) {
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000135 OwningPtr<MemoryBuffer> Buff;
136
137 if (error_code ec = MemoryBuffer::getFileOrSTDIN(Filename, Buff)) {
138 errs() << ToolName << ": " << Filename << ": " << ec.message() << "\n";
139 return;
140 }
141
142 OwningPtr<ObjectFile> Obj(ObjectFile::createObjectFile(Buff.take()));
143
144 const Target *TheTarget = GetTarget(Obj.get());
145 if (!TheTarget) {
146 // GetTarget prints out stuff.
147 return;
148 }
Benjamin Kramer685a2502011-07-20 19:37:35 +0000149 const MCInstrInfo *InstrInfo = TheTarget->createMCInstrInfo();
Benjamin Kramer41ab14b2011-08-08 18:56:44 +0000150 OwningPtr<MCInstrAnalysis>
151 InstrAnalysis(TheTarget->createMCInstrAnalysis(InstrInfo));
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000152
153 outs() << '\n';
154 outs() << Filename
Benjamin Kramer739b65b2011-07-15 18:39:24 +0000155 << ":\tfile format " << Obj->getFileFormatName() << "\n\n";
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000156
Michael J. Spencer25b15772011-06-25 17:55:23 +0000157 error_code ec;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000158 for (section_iterator i = Obj->begin_sections(),
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000159 e = Obj->end_sections();
Michael J. Spencer25b15772011-06-25 17:55:23 +0000160 i != e; i.increment(ec)) {
161 if (error(ec)) break;
162 bool text;
163 if (error(i->isText(text))) break;
164 if (!text) continue;
165
Benjamin Kramer739b65b2011-07-15 18:39:24 +0000166 // Make a list of all the symbols in this section.
167 std::vector<std::pair<uint64_t, StringRef> > Symbols;
Michael J. Spencer4344b1e2011-10-07 19:25:32 +0000168 for (symbol_iterator si = Obj->begin_symbols(),
Benjamin Kramer739b65b2011-07-15 18:39:24 +0000169 se = Obj->end_symbols();
170 si != se; si.increment(ec)) {
171 bool contains;
172 if (!error(i->containsSymbol(*si, contains)) && contains) {
173 uint64_t Address;
Benjamin Kramerac241fe2011-09-14 01:22:52 +0000174 if (error(si->getOffset(Address))) break;
Benjamin Kramer739b65b2011-07-15 18:39:24 +0000175 StringRef Name;
176 if (error(si->getName(Name))) break;
177 Symbols.push_back(std::make_pair(Address, Name));
178 }
179 }
180
181 // Sort the symbols by address, just in case they didn't come in that way.
182 array_pod_sort(Symbols.begin(), Symbols.end());
183
Michael J. Spencer25b15772011-06-25 17:55:23 +0000184 StringRef name;
185 if (error(i->getName(name))) break;
Benjamin Kramer739b65b2011-07-15 18:39:24 +0000186 outs() << "Disassembly of section " << name << ':';
187
188 // If the section has no symbols just insert a dummy one and disassemble
189 // the whole section.
190 if (Symbols.empty())
191 Symbols.push_back(std::make_pair(0, name));
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000192
193 // Set up disassembler.
Evan Cheng1abf2cb2011-07-14 23:50:31 +0000194 OwningPtr<const MCAsmInfo> AsmInfo(TheTarget->createMCAsmInfo(TripleName));
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000195
196 if (!AsmInfo) {
197 errs() << "error: no assembly info for target " << TripleName << "\n";
198 return;
199 }
200
James Molloyb9505852011-09-07 17:24:38 +0000201 OwningPtr<const MCSubtargetInfo> STI(TheTarget->createMCSubtargetInfo(TripleName, "", ""));
202
203 if (!STI) {
204 errs() << "error: no subtarget info for target " << TripleName << "\n";
205 return;
206 }
207
208 OwningPtr<const MCDisassembler> DisAsm(TheTarget->createMCDisassembler(*STI));
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000209 if (!DisAsm) {
210 errs() << "error: no disassembler for target " << TripleName << "\n";
211 return;
212 }
213
214 int AsmPrinterVariant = AsmInfo->getAssemblerDialect();
215 OwningPtr<MCInstPrinter> IP(TheTarget->createMCInstPrinter(
James Molloyb9505852011-09-07 17:24:38 +0000216 AsmPrinterVariant, *AsmInfo, *STI));
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000217 if (!IP) {
218 errs() << "error: no instruction printer for target " << TripleName << '\n';
219 return;
220 }
221
Michael J. Spencer25b15772011-06-25 17:55:23 +0000222 StringRef Bytes;
223 if (error(i->getContents(Bytes))) break;
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000224 StringRefMemoryObject memoryObject(Bytes);
225 uint64_t Size;
226 uint64_t Index;
Benjamin Kramer739b65b2011-07-15 18:39:24 +0000227 uint64_t SectSize;
228 if (error(i->getSize(SectSize))) break;
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000229
Benjamin Kramer739b65b2011-07-15 18:39:24 +0000230 // Disassemble symbol by symbol.
231 for (unsigned si = 0, se = Symbols.size(); si != se; ++si) {
232 uint64_t Start = Symbols[si].first;
233 uint64_t End = si == se-1 ? SectSize : Symbols[si + 1].first - 1;
234 outs() << '\n' << Symbols[si].second << ":\n";
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000235
Benjamin Kramer739b65b2011-07-15 18:39:24 +0000236#ifndef NDEBUG
237 raw_ostream &DebugOut = DebugFlag ? dbgs() : nulls();
238#else
239 raw_ostream &DebugOut = nulls();
240#endif
241
Benjamin Kramer0b8b7712011-09-19 17:56:04 +0000242 for (Index = Start; Index < End; Index += Size) {
243 MCInst Inst;
Owen Anderson98c5dda2011-09-15 23:38:46 +0000244
Benjamin Kramer0b8b7712011-09-19 17:56:04 +0000245 if (DisAsm->getInstruction(Inst, Size, memoryObject, Index,
246 DebugOut, nulls())) {
247 uint64_t addr;
248 if (error(i->getAddress(addr))) break;
249 outs() << format("%8x:\t", addr + Index);
250 DumpBytes(StringRef(Bytes.data() + Index, Size));
251 IP->printInst(&Inst, outs(), "");
252 outs() << "\n";
253 } else {
254 errs() << ToolName << ": warning: invalid instruction encoding\n";
255 if (Size == 0)
256 Size = 1; // skip illegible bytes
Benjamin Kramer739b65b2011-07-15 18:39:24 +0000257 }
Benjamin Kramer685a2502011-07-20 19:37:35 +0000258 }
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000259 }
260 }
261}
262
263int main(int argc, char **argv) {
264 // Print a stack trace if we signal out.
265 sys::PrintStackTraceOnErrorSignal();
266 PrettyStackTraceProgram X(argc, argv);
267 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
268
269 // Initialize targets and assembly printers/parsers.
270 llvm::InitializeAllTargetInfos();
Evan Chenge78085a2011-07-22 21:58:54 +0000271 llvm::InitializeAllTargetMCs();
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000272 llvm::InitializeAllAsmParsers();
273 llvm::InitializeAllDisassemblers();
274
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000275 cl::ParseCommandLineOptions(argc, argv, "llvm object file dumper\n");
276 TripleName = Triple::normalize(TripleName);
277
278 ToolName = argv[0];
279
280 // Defaults to a.out if no filenames specified.
281 if (InputFilenames.size() == 0)
282 InputFilenames.push_back("a.out");
283
284 // -d is the only flag that is currently implemented, so just print help if
285 // it is not set.
286 if (!Disassemble) {
287 cl::PrintHelpMessage();
288 return 2;
289 }
290
Benjamin Kramer0b8b7712011-09-19 17:56:04 +0000291 if (MachO)
292 std::for_each(InputFilenames.begin(), InputFilenames.end(),
293 DisassembleInputMachO);
294 else
295 std::for_each(InputFilenames.begin(), InputFilenames.end(),
296 DisassembleInputLibObject);
Michael J. Spencer92e1deb2011-01-20 06:39:06 +0000297
298 return 0;
299}