blob: ca51db346fc917d12d892b54631866faf524f0f9 [file] [log] [blame]
Chris Lattner24943d22010-06-08 16:52:24 +00001//===-- DisassemblerLLVM.cpp ------------------------------------*- C++ -*-===//
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#include "DisassemblerLLVM.h"
11
12#include "llvm-c/EnhancedDisassembly.h"
13
14#include "lldb/Core/Address.h"
15#include "lldb/Core/DataExtractor.h"
16#include "lldb/Core/Disassembler.h"
17#include "lldb/Core/Module.h"
18#include "lldb/Core/PluginManager.h"
19#include "lldb/Core/Stream.h"
20#include "lldb/Core/StreamString.h"
21#include "lldb/Symbol/SymbolContext.h"
22
23#include "lldb/Target/ExecutionContext.h"
24#include "lldb/Target/Process.h"
25#include "lldb/Target/RegisterContext.h"
26#include "lldb/Target/Target.h"
27
Greg Claytonb01000f2011-01-17 03:46:26 +000028#include <assert.h>
Chris Lattner24943d22010-06-08 16:52:24 +000029
30using namespace lldb;
31using namespace lldb_private;
32
33
Greg Claytonb1888f22011-03-19 01:12:21 +000034static int
35DataExtractorByteReader(uint8_t *byte, uint64_t address, void *arg)
Chris Lattner24943d22010-06-08 16:52:24 +000036{
37 DataExtractor &extractor = *((DataExtractor *)arg);
38
39 if (extractor.ValidOffset(address))
40 {
41 *byte = *(extractor.GetDataStart() + address);
42 return 0;
43 }
44 else
45 {
46 return -1;
47 }
48}
49
50namespace {
51 struct RegisterReaderArg {
52 const lldb::addr_t instructionPointer;
53 const EDDisassemblerRef disassembler;
54
55 RegisterReaderArg(lldb::addr_t ip,
56 EDDisassemblerRef dis) :
57 instructionPointer(ip),
58 disassembler(dis)
59 {
60 }
61 };
62}
63
64static int IPRegisterReader(uint64_t *value, unsigned regID, void* arg)
65{
66 uint64_t instructionPointer = ((RegisterReaderArg*)arg)->instructionPointer;
67 EDDisassemblerRef disassembler = ((RegisterReaderArg*)arg)->disassembler;
68
Greg Claytonb1888f22011-03-19 01:12:21 +000069 if (EDRegisterIsProgramCounter(disassembler, regID)) {
Chris Lattner24943d22010-06-08 16:52:24 +000070 *value = instructionPointer;
71 return 0;
72 }
73
74 return -1;
75}
76
Greg Clayton5c4c7462010-10-06 03:09:58 +000077DisassemblerLLVM::InstructionLLVM::InstructionLLVM (EDDisassemblerRef disassembler, const Address &addr) :
78 Instruction (addr),
Chris Lattner24943d22010-06-08 16:52:24 +000079 m_disassembler (disassembler)
80{
81}
82
Greg Clayton5c4c7462010-10-06 03:09:58 +000083DisassemblerLLVM::InstructionLLVM::~InstructionLLVM()
Chris Lattner24943d22010-06-08 16:52:24 +000084{
85}
86
87static void
88PadString(Stream *s, const std::string &str, size_t width)
89{
90 int diff = width - str.length();
91
92 if (diff > 0)
93 s->Printf("%s%*.*s", str.c_str(), diff, diff, "");
94 else
95 s->Printf("%s ", str.c_str());
96}
97
98void
Greg Clayton5c4c7462010-10-06 03:09:58 +000099DisassemblerLLVM::InstructionLLVM::Dump
Chris Lattner24943d22010-06-08 16:52:24 +0000100(
101 Stream *s,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000102 bool show_address,
Greg Clayton70436352010-06-30 23:03:03 +0000103 const DataExtractor *bytes,
Chris Lattner24943d22010-06-08 16:52:24 +0000104 uint32_t bytes_offset,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000105 const lldb_private::ExecutionContext* exe_ctx,
Chris Lattner24943d22010-06-08 16:52:24 +0000106 bool raw
107)
108{
109 const size_t opcodeColumnWidth = 7;
110 const size_t operandColumnWidth = 25;
111
Greg Clayton5c4c7462010-10-06 03:09:58 +0000112 ExecutionContextScope *exe_scope = NULL;
113 if (exe_ctx)
114 exe_scope = exe_ctx->GetBestExecutionContextScope();
115
Chris Lattner24943d22010-06-08 16:52:24 +0000116 // If we have an address, print it out
Sean Callanan91557b02010-11-10 01:38:28 +0000117 if (GetAddress().IsValid() && show_address)
Greg Clayton70436352010-06-30 23:03:03 +0000118 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000119 if (GetAddress().Dump (s,
120 exe_scope,
121 Address::DumpStyleLoadAddress,
122 Address::DumpStyleModuleWithFileAddress,
123 0))
Greg Clayton70436352010-06-30 23:03:03 +0000124 s->PutCString(": ");
125 }
Chris Lattner24943d22010-06-08 16:52:24 +0000126
127 // If we are supposed to show bytes, "bytes" will be non-NULL.
128 if (bytes)
129 {
130 uint32_t bytes_dumped = bytes->Dump(s, bytes_offset, eFormatBytes, 1, EDInstByteSize(m_inst), UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0) - bytes_offset;
Greg Clayton1e2e2712011-01-08 22:55:04 +0000131 // Allow for 15 bytes of opcodes since this is the max for x86_64.
132 // TOOD: We need to taylor this better for different architectures. For
133 // ARM we would want to show 16 bit opcodes for Thumb as properly byte
134 // swapped uint16_t values, or 32 bit values swapped values for ARM.
135 const uint32_t default_num_opcode_bytes = 15;
Chris Lattner24943d22010-06-08 16:52:24 +0000136 if (bytes_dumped * 3 < (default_num_opcode_bytes*3))
137 {
Greg Clayton1e2e2712011-01-08 22:55:04 +0000138 uint32_t indent_level = (default_num_opcode_bytes*3) - (bytes_dumped * 3) + 1;
Chris Lattner24943d22010-06-08 16:52:24 +0000139 s->Printf("%*.*s", indent_level, indent_level, "");
140 }
141 }
142
143 int numTokens = EDNumTokens(m_inst);
144
145 int currentOpIndex = -1;
146
Sean Callanan8541f2f2010-07-23 02:19:15 +0000147 std::auto_ptr<RegisterReaderArg> rra;
148
149 if (!raw)
150 {
151 addr_t base_addr = LLDB_INVALID_ADDRESS;
Greg Clayton5c4c7462010-10-06 03:09:58 +0000152 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
153 base_addr = GetAddress().GetLoadAddress (exe_ctx->target);
Sean Callanan8541f2f2010-07-23 02:19:15 +0000154 if (base_addr == LLDB_INVALID_ADDRESS)
Greg Clayton5c4c7462010-10-06 03:09:58 +0000155 base_addr = GetAddress().GetFileAddress ();
Sean Callanan8541f2f2010-07-23 02:19:15 +0000156
157 rra.reset(new RegisterReaderArg(base_addr + EDInstByteSize(m_inst), m_disassembler));
158 }
Chris Lattner24943d22010-06-08 16:52:24 +0000159
160 bool printTokenized = false;
161
162 if (numTokens != -1)
163 {
164 printTokenized = true;
165
166 // Handle the opcode column.
167
168 StreamString opcode;
169
170 int tokenIndex = 0;
171
172 EDTokenRef token;
173 const char *tokenStr;
174
175 if (EDGetToken(&token, m_inst, tokenIndex))
176 printTokenized = false;
177
178 if (!printTokenized || !EDTokenIsOpcode(token))
179 printTokenized = false;
180
181 if (!printTokenized || EDGetTokenString(&tokenStr, token))
182 printTokenized = false;
183
184 // Put the token string into our opcode string
185 opcode.PutCString(tokenStr);
186
187 // If anything follows, it probably starts with some whitespace. Skip it.
188
189 tokenIndex++;
190
191 if (printTokenized && tokenIndex < numTokens)
192 {
193 if(!printTokenized || EDGetToken(&token, m_inst, tokenIndex))
194 printTokenized = false;
195
196 if(!printTokenized || !EDTokenIsWhitespace(token))
197 printTokenized = false;
198 }
199
200 tokenIndex++;
201
202 // Handle the operands and the comment.
203
204 StreamString operands;
205 StreamString comment;
206
207 if (printTokenized)
208 {
209 bool show_token;
210
211 for (; tokenIndex < numTokens; ++tokenIndex)
212 {
213 if (EDGetToken(&token, m_inst, tokenIndex))
214 return;
215
216 if (raw)
217 {
218 show_token = true;
219 }
220 else
221 {
222 int operandIndex = EDOperandIndexForToken(token);
223
224 if (operandIndex >= 0)
225 {
226 if (operandIndex != currentOpIndex)
227 {
228 show_token = true;
229
230 currentOpIndex = operandIndex;
231 EDOperandRef operand;
232
233 if (!EDGetOperand(&operand, m_inst, currentOpIndex))
234 {
235 if (EDOperandIsMemory(operand))
236 {
237 uint64_t operand_value;
238
Sean Callanan8541f2f2010-07-23 02:19:15 +0000239 if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, rra.get()))
Chris Lattner24943d22010-06-08 16:52:24 +0000240 {
241 if (EDInstIsBranch(m_inst))
242 {
243 operands.Printf("0x%llx ", operand_value);
244 show_token = false;
245 }
246 else
247 {
248 // Put the address value into the comment
249 comment.Printf("0x%llx ", operand_value);
250 }
251
252 lldb_private::Address so_addr;
Greg Clayton5c4c7462010-10-06 03:09:58 +0000253 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
Chris Lattner24943d22010-06-08 16:52:24 +0000254 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000255 if (exe_ctx->target->GetSectionLoadList().ResolveLoadAddress (operand_value, so_addr))
Greg Claytoncf7f1ad2010-07-01 01:26:43 +0000256 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
Greg Clayton70436352010-06-30 23:03:03 +0000257 }
Greg Clayton5c4c7462010-10-06 03:09:58 +0000258 else
Greg Clayton70436352010-06-30 23:03:03 +0000259 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000260 Module *module = GetAddress().GetModule();
Greg Clayton70436352010-06-30 23:03:03 +0000261 if (module)
Chris Lattner24943d22010-06-08 16:52:24 +0000262 {
Greg Clayton70436352010-06-30 23:03:03 +0000263 if (module->ResolveFileAddress (operand_value, so_addr))
Greg Claytoncf7f1ad2010-07-01 01:26:43 +0000264 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
Chris Lattner24943d22010-06-08 16:52:24 +0000265 }
266 }
Greg Clayton70436352010-06-30 23:03:03 +0000267
Chris Lattner24943d22010-06-08 16:52:24 +0000268 } // EDEvaluateOperand
269 } // EDOperandIsMemory
270 } // EDGetOperand
271 } // operandIndex != currentOpIndex
272 } // operandIndex >= 0
273 } // else(raw)
274
275 if (show_token)
276 {
277 if(EDGetTokenString(&tokenStr, token))
278 {
279 printTokenized = false;
280 break;
281 }
282
283 operands.PutCString(tokenStr);
284 }
285 } // for (tokenIndex)
286
287 if (printTokenized)
288 {
289 if (operands.GetString().empty())
290 {
291 s->PutCString(opcode.GetString().c_str());
292 }
293 else
294 {
295 PadString(s, opcode.GetString(), opcodeColumnWidth);
296
297 if (comment.GetString().empty())
298 {
299 s->PutCString(operands.GetString().c_str());
300 }
301 else
302 {
303 PadString(s, operands.GetString(), operandColumnWidth);
304
305 s->PutCString("; ");
306 s->PutCString(comment.GetString().c_str());
307 } // else (comment.GetString().empty())
308 } // else (operands.GetString().empty())
309 } // printTokenized
310 } // for (tokenIndex)
311 } // numTokens != -1
312
313 if (!printTokenized)
314 {
315 const char *str;
316
317 if (EDGetInstString(&str, m_inst))
318 return;
319 else
320 s->PutCString(str);
321 }
322}
323
324bool
Greg Clayton5c4c7462010-10-06 03:09:58 +0000325DisassemblerLLVM::InstructionLLVM::DoesBranch() const
Chris Lattner24943d22010-06-08 16:52:24 +0000326{
327 return EDInstIsBranch(m_inst);
328}
329
330size_t
Greg Clayton5c4c7462010-10-06 03:09:58 +0000331DisassemblerLLVM::InstructionLLVM::GetByteSize() const
Chris Lattner24943d22010-06-08 16:52:24 +0000332{
333 return EDInstByteSize(m_inst);
334}
335
336size_t
Greg Clayton5c4c7462010-10-06 03:09:58 +0000337DisassemblerLLVM::InstructionLLVM::Extract(const DataExtractor &data, uint32_t data_offset)
Chris Lattner24943d22010-06-08 16:52:24 +0000338{
339 if (EDCreateInsts(&m_inst, 1, m_disassembler, DataExtractorByteReader, data_offset, (void*)(&data)))
340 return EDInstByteSize(m_inst);
341 else
342 return 0;
343}
344
Chris Lattner24943d22010-06-08 16:52:24 +0000345static inline EDAssemblySyntax_t
Greg Claytoncf015052010-06-11 03:25:34 +0000346SyntaxForArchSpec (const ArchSpec &arch)
Chris Lattner24943d22010-06-08 16:52:24 +0000347{
Greg Clayton940b1032011-02-23 00:35:02 +0000348 switch (arch.GetMachine ())
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000349 {
Greg Clayton940b1032011-02-23 00:35:02 +0000350 case llvm::Triple::x86:
351 case llvm::Triple::x86_64:
Chris Lattner24943d22010-06-08 16:52:24 +0000352 return kEDAssemblySyntaxX86ATT;
Sean Callanand151c8a2011-03-09 01:02:51 +0000353 case llvm::Triple::arm:
354 return kEDAssemblySyntaxARMUAL;
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000355 default:
356 break;
357 }
Greg Claytoncf015052010-06-11 03:25:34 +0000358 return (EDAssemblySyntax_t)0; // default
Chris Lattner24943d22010-06-08 16:52:24 +0000359}
360
361Disassembler *
362DisassemblerLLVM::CreateInstance(const ArchSpec &arch)
363{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000364 std::auto_ptr<DisassemblerLLVM> disasm_ap (new DisassemblerLLVM(arch));
365
366 if (disasm_ap->IsValid())
367 return disasm_ap.release();
Chris Lattner24943d22010-06-08 16:52:24 +0000368
Greg Claytoncf015052010-06-11 03:25:34 +0000369 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000370}
371
372DisassemblerLLVM::DisassemblerLLVM(const ArchSpec &arch) :
Greg Claytonb01000f2011-01-17 03:46:26 +0000373 Disassembler (arch),
Greg Claytonb1888f22011-03-19 01:12:21 +0000374 m_disassembler (NULL),
375 m_disassembler_thumb (NULL) // For ARM only
Chris Lattner24943d22010-06-08 16:52:24 +0000376{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000377 const std::string &arch_triple = arch.GetTriple().str();
378 if (!arch_triple.empty())
Greg Claytoncf015052010-06-11 03:25:34 +0000379 {
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000380 if (EDGetDisassembler(&m_disassembler, arch_triple.c_str(), SyntaxForArchSpec (arch)))
381 m_disassembler = NULL;
Greg Claytonb1888f22011-03-19 01:12:21 +0000382 llvm::Triple::ArchType llvm_arch = arch.GetTriple().getArch();
383 if (llvm_arch == llvm::Triple::arm)
384 {
385 if (EDGetDisassembler(&m_disassembler_thumb, "thumb-apple-darwin", kEDAssemblySyntaxARMUAL))
386 m_disassembler_thumb = NULL;
387 }
388 else if (llvm_arch == llvm::Triple::thumb)
389 {
390 m_disassembler_thumb = m_disassembler;
391 if (EDGetDisassembler(&m_disassembler, "arm-apple-darwin-unknown", kEDAssemblySyntaxARMUAL))
392 m_disassembler = NULL;
393 }
Greg Claytoncf015052010-06-11 03:25:34 +0000394 }
Chris Lattner24943d22010-06-08 16:52:24 +0000395}
396
397DisassemblerLLVM::~DisassemblerLLVM()
398{
399}
400
401size_t
Greg Clayton70436352010-06-30 23:03:03 +0000402DisassemblerLLVM::DecodeInstructions
Chris Lattner24943d22010-06-08 16:52:24 +0000403(
Greg Clayton5c4c7462010-10-06 03:09:58 +0000404 const Address &base_addr,
Chris Lattner24943d22010-06-08 16:52:24 +0000405 const DataExtractor& data,
406 uint32_t data_offset,
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000407 uint32_t num_instructions,
408 bool append
Chris Lattner24943d22010-06-08 16:52:24 +0000409)
410{
Greg Claytonb01000f2011-01-17 03:46:26 +0000411 if (m_disassembler == NULL)
412 return 0;
413
Chris Lattner24943d22010-06-08 16:52:24 +0000414 size_t total_inst_byte_size = 0;
415
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000416 if (!append)
417 m_instruction_list.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000418
419 while (data.ValidOffset(data_offset) && num_instructions)
420 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000421 Address inst_addr (base_addr);
422 inst_addr.Slide(data_offset);
Greg Claytonb1888f22011-03-19 01:12:21 +0000423
424 bool use_thumb = false;
425 // If we have a thumb disassembler, then we have an ARM architecture
426 // so we need to check what the instruction address class is to make
427 // sure we shouldn't be disassembling as thumb...
428 if (m_disassembler_thumb)
429 {
430 if (inst_addr.GetAddressClass () == eAddressClassCodeAlternateISA)
431 use_thumb = true;
432 }
433 InstructionSP inst_sp (new InstructionLLVM (use_thumb ? m_disassembler_thumb : m_disassembler,
434 inst_addr));
Chris Lattner24943d22010-06-08 16:52:24 +0000435
Greg Clayton5c4c7462010-10-06 03:09:58 +0000436 size_t inst_byte_size = inst_sp->Extract (data, data_offset);
Chris Lattner24943d22010-06-08 16:52:24 +0000437
438 if (inst_byte_size == 0)
439 break;
440
Greg Clayton5c4c7462010-10-06 03:09:58 +0000441 m_instruction_list.Append (inst_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000442
443 total_inst_byte_size += inst_byte_size;
444 data_offset += inst_byte_size;
445 num_instructions--;
446 }
447
448 return total_inst_byte_size;
449}
450
451void
452DisassemblerLLVM::Initialize()
453{
454 PluginManager::RegisterPlugin (GetPluginNameStatic(),
455 GetPluginDescriptionStatic(),
456 CreateInstance);
457}
458
459void
460DisassemblerLLVM::Terminate()
461{
462 PluginManager::UnregisterPlugin (CreateInstance);
463}
464
465
466const char *
467DisassemblerLLVM::GetPluginNameStatic()
468{
469 return "disassembler.llvm";
470}
471
472const char *
473DisassemblerLLVM::GetPluginDescriptionStatic()
474{
475 return "Disassembler that uses LLVM opcode tables to disassemble i386 and x86_64.";
476}
477
478//------------------------------------------------------------------
479// PluginInterface protocol
480//------------------------------------------------------------------
481const char *
482DisassemblerLLVM::GetPluginName()
483{
484 return "DisassemblerLLVM";
485}
486
487const char *
488DisassemblerLLVM::GetShortPluginName()
489{
490 return GetPluginNameStatic();
491}
492
493uint32_t
494DisassemblerLLVM::GetPluginVersion()
495{
496 return 1;
497}
498