blob: 9c55042640f3c245fba3e99731eb9f3d4c204d0a [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
Greg Clayton7bc39082011-03-24 23:53:38 +000035DataExtractorByteReader (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 Clayton7bc39082011-03-24 23:53:38 +000077DisassemblerLLVM::InstructionLLVM::InstructionLLVM (const Address &addr, EDDisassemblerRef disassembler) :
Greg Clayton5c4c7462010-10-06 03:09:58 +000078 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 Clayton149731c2011-03-25 18:03:16 +0000103 bool show_bytes,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000104 const lldb_private::ExecutionContext* exe_ctx,
Chris Lattner24943d22010-06-08 16:52:24 +0000105 bool raw
106)
107{
108 const size_t opcodeColumnWidth = 7;
109 const size_t operandColumnWidth = 25;
110
Greg Clayton5c4c7462010-10-06 03:09:58 +0000111 ExecutionContextScope *exe_scope = NULL;
112 if (exe_ctx)
113 exe_scope = exe_ctx->GetBestExecutionContextScope();
114
Chris Lattner24943d22010-06-08 16:52:24 +0000115 // If we have an address, print it out
Sean Callanan91557b02010-11-10 01:38:28 +0000116 if (GetAddress().IsValid() && show_address)
Greg Clayton70436352010-06-30 23:03:03 +0000117 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000118 if (GetAddress().Dump (s,
119 exe_scope,
120 Address::DumpStyleLoadAddress,
121 Address::DumpStyleModuleWithFileAddress,
122 0))
Greg Clayton70436352010-06-30 23:03:03 +0000123 s->PutCString(": ");
124 }
Chris Lattner24943d22010-06-08 16:52:24 +0000125
126 // If we are supposed to show bytes, "bytes" will be non-NULL.
Greg Clayton149731c2011-03-25 18:03:16 +0000127 if (show_bytes)
Chris Lattner24943d22010-06-08 16:52:24 +0000128 {
Greg Clayton149731c2011-03-25 18:03:16 +0000129 if (m_opcode.GetType() == Opcode::eTypeBytes)
Chris Lattner24943d22010-06-08 16:52:24 +0000130 {
Greg Clayton149731c2011-03-25 18:03:16 +0000131 // x86_64 and i386 are the only ones that use bytes right now so
132 // pad out the byte dump to be able to always show 15 bytes (3 chars each)
133 // plus a space
134 m_opcode.Dump (s, 15 * 3 + 1);
135 }
136 else
137 {
138 // Else, we have ARM which can show up to a uint32_t 0x00000000 (10 spaces)
139 // plus two for padding...
140 m_opcode.Dump (s, 12);
Chris Lattner24943d22010-06-08 16:52:24 +0000141 }
142 }
143
144 int numTokens = EDNumTokens(m_inst);
145
146 int currentOpIndex = -1;
147
Sean Callanan8541f2f2010-07-23 02:19:15 +0000148 std::auto_ptr<RegisterReaderArg> rra;
149
150 if (!raw)
151 {
152 addr_t base_addr = LLDB_INVALID_ADDRESS;
Greg Clayton5c4c7462010-10-06 03:09:58 +0000153 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
154 base_addr = GetAddress().GetLoadAddress (exe_ctx->target);
Sean Callanan8541f2f2010-07-23 02:19:15 +0000155 if (base_addr == LLDB_INVALID_ADDRESS)
Greg Clayton5c4c7462010-10-06 03:09:58 +0000156 base_addr = GetAddress().GetFileAddress ();
Sean Callanan8541f2f2010-07-23 02:19:15 +0000157
158 rra.reset(new RegisterReaderArg(base_addr + EDInstByteSize(m_inst), m_disassembler));
159 }
Chris Lattner24943d22010-06-08 16:52:24 +0000160
161 bool printTokenized = false;
162
163 if (numTokens != -1)
164 {
165 printTokenized = true;
166
167 // Handle the opcode column.
168
169 StreamString opcode;
170
171 int tokenIndex = 0;
172
173 EDTokenRef token;
174 const char *tokenStr;
175
176 if (EDGetToken(&token, m_inst, tokenIndex))
177 printTokenized = false;
178
179 if (!printTokenized || !EDTokenIsOpcode(token))
180 printTokenized = false;
181
182 if (!printTokenized || EDGetTokenString(&tokenStr, token))
183 printTokenized = false;
184
185 // Put the token string into our opcode string
186 opcode.PutCString(tokenStr);
187
188 // If anything follows, it probably starts with some whitespace. Skip it.
189
190 tokenIndex++;
191
192 if (printTokenized && tokenIndex < numTokens)
193 {
194 if(!printTokenized || EDGetToken(&token, m_inst, tokenIndex))
195 printTokenized = false;
196
197 if(!printTokenized || !EDTokenIsWhitespace(token))
198 printTokenized = false;
199 }
200
201 tokenIndex++;
202
203 // Handle the operands and the comment.
204
205 StreamString operands;
206 StreamString comment;
207
208 if (printTokenized)
209 {
210 bool show_token;
211
212 for (; tokenIndex < numTokens; ++tokenIndex)
213 {
214 if (EDGetToken(&token, m_inst, tokenIndex))
215 return;
216
217 if (raw)
218 {
219 show_token = true;
220 }
221 else
222 {
223 int operandIndex = EDOperandIndexForToken(token);
224
225 if (operandIndex >= 0)
226 {
227 if (operandIndex != currentOpIndex)
228 {
229 show_token = true;
230
231 currentOpIndex = operandIndex;
232 EDOperandRef operand;
233
234 if (!EDGetOperand(&operand, m_inst, currentOpIndex))
235 {
236 if (EDOperandIsMemory(operand))
237 {
238 uint64_t operand_value;
239
Sean Callanan8541f2f2010-07-23 02:19:15 +0000240 if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, rra.get()))
Chris Lattner24943d22010-06-08 16:52:24 +0000241 {
242 if (EDInstIsBranch(m_inst))
243 {
244 operands.Printf("0x%llx ", operand_value);
245 show_token = false;
246 }
247 else
248 {
249 // Put the address value into the comment
250 comment.Printf("0x%llx ", operand_value);
251 }
252
253 lldb_private::Address so_addr;
Greg Clayton5c4c7462010-10-06 03:09:58 +0000254 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
Chris Lattner24943d22010-06-08 16:52:24 +0000255 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000256 if (exe_ctx->target->GetSectionLoadList().ResolveLoadAddress (operand_value, so_addr))
Greg Claytoncf7f1ad2010-07-01 01:26:43 +0000257 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
Greg Clayton70436352010-06-30 23:03:03 +0000258 }
Greg Clayton5c4c7462010-10-06 03:09:58 +0000259 else
Greg Clayton70436352010-06-30 23:03:03 +0000260 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000261 Module *module = GetAddress().GetModule();
Greg Clayton70436352010-06-30 23:03:03 +0000262 if (module)
Chris Lattner24943d22010-06-08 16:52:24 +0000263 {
Greg Clayton70436352010-06-30 23:03:03 +0000264 if (module->ResolveFileAddress (operand_value, so_addr))
Greg Claytoncf7f1ad2010-07-01 01:26:43 +0000265 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
Chris Lattner24943d22010-06-08 16:52:24 +0000266 }
267 }
Greg Clayton70436352010-06-30 23:03:03 +0000268
Chris Lattner24943d22010-06-08 16:52:24 +0000269 } // EDEvaluateOperand
270 } // EDOperandIsMemory
271 } // EDGetOperand
272 } // operandIndex != currentOpIndex
273 } // operandIndex >= 0
274 } // else(raw)
275
276 if (show_token)
277 {
278 if(EDGetTokenString(&tokenStr, token))
279 {
280 printTokenized = false;
281 break;
282 }
283
284 operands.PutCString(tokenStr);
285 }
286 } // for (tokenIndex)
287
288 if (printTokenized)
289 {
290 if (operands.GetString().empty())
291 {
292 s->PutCString(opcode.GetString().c_str());
293 }
294 else
295 {
296 PadString(s, opcode.GetString(), opcodeColumnWidth);
297
298 if (comment.GetString().empty())
299 {
300 s->PutCString(operands.GetString().c_str());
301 }
302 else
303 {
304 PadString(s, operands.GetString(), operandColumnWidth);
305
306 s->PutCString("; ");
307 s->PutCString(comment.GetString().c_str());
308 } // else (comment.GetString().empty())
309 } // else (operands.GetString().empty())
310 } // printTokenized
311 } // for (tokenIndex)
312 } // numTokens != -1
313
314 if (!printTokenized)
315 {
316 const char *str;
317
318 if (EDGetInstString(&str, m_inst))
319 return;
320 else
321 s->PutCString(str);
322 }
323}
324
325bool
Greg Clayton5c4c7462010-10-06 03:09:58 +0000326DisassemblerLLVM::InstructionLLVM::DoesBranch() const
Chris Lattner24943d22010-06-08 16:52:24 +0000327{
328 return EDInstIsBranch(m_inst);
329}
330
331size_t
Greg Clayton7bc39082011-03-24 23:53:38 +0000332DisassemblerLLVM::InstructionLLVM::Extract (const Disassembler &disassembler,
333 const lldb_private::DataExtractor &data,
334 uint32_t data_offset)
Chris Lattner24943d22010-06-08 16:52:24 +0000335{
336 if (EDCreateInsts(&m_inst, 1, m_disassembler, DataExtractorByteReader, data_offset, (void*)(&data)))
Greg Clayton7bc39082011-03-24 23:53:38 +0000337 {
338 const int byte_size = EDInstByteSize(m_inst);
339 uint32_t offset = data_offset;
340 // Make a copy of the opcode in m_opcode
341 switch (disassembler.GetArchitecture().GetMachine())
342 {
343 case llvm::Triple::x86:
344 case llvm::Triple::x86_64:
345 m_opcode.SetOpcodeBytes (data.PeekData (data_offset, byte_size), byte_size);
346 break;
347
348 case llvm::Triple::arm:
Greg Clayton7bc39082011-03-24 23:53:38 +0000349 case llvm::Triple::thumb:
Greg Clayton149731c2011-03-25 18:03:16 +0000350 switch (byte_size)
351 {
352 case 2:
353 m_opcode.SetOpcode16 (data.GetU16 (&offset));
354 break;
355
356 case 4:
Greg Clayton7bc39082011-03-24 23:53:38 +0000357 m_opcode.SetOpcode32 (data.GetU32 (&offset));
Greg Clayton149731c2011-03-25 18:03:16 +0000358 break;
359
360 default:
361 assert (!"Invalid ARM opcode size");
362 break;
363 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000364 break;
365
366 default:
367 assert (!"This shouldn't happen since we control the architecture we allow DisassemblerLLVM to be created for");
368 break;
369 }
370 return byte_size;
371 }
Chris Lattner24943d22010-06-08 16:52:24 +0000372 else
373 return 0;
374}
375
Chris Lattner24943d22010-06-08 16:52:24 +0000376static inline EDAssemblySyntax_t
Greg Claytoncf015052010-06-11 03:25:34 +0000377SyntaxForArchSpec (const ArchSpec &arch)
Chris Lattner24943d22010-06-08 16:52:24 +0000378{
Greg Clayton940b1032011-02-23 00:35:02 +0000379 switch (arch.GetMachine ())
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000380 {
Greg Clayton940b1032011-02-23 00:35:02 +0000381 case llvm::Triple::x86:
382 case llvm::Triple::x86_64:
Chris Lattner24943d22010-06-08 16:52:24 +0000383 return kEDAssemblySyntaxX86ATT;
Sean Callanand151c8a2011-03-09 01:02:51 +0000384 case llvm::Triple::arm:
385 return kEDAssemblySyntaxARMUAL;
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000386 default:
387 break;
388 }
Greg Claytoncf015052010-06-11 03:25:34 +0000389 return (EDAssemblySyntax_t)0; // default
Chris Lattner24943d22010-06-08 16:52:24 +0000390}
391
392Disassembler *
393DisassemblerLLVM::CreateInstance(const ArchSpec &arch)
394{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000395 std::auto_ptr<DisassemblerLLVM> disasm_ap (new DisassemblerLLVM(arch));
396
397 if (disasm_ap->IsValid())
398 return disasm_ap.release();
Chris Lattner24943d22010-06-08 16:52:24 +0000399
Greg Claytoncf015052010-06-11 03:25:34 +0000400 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000401}
402
403DisassemblerLLVM::DisassemblerLLVM(const ArchSpec &arch) :
Greg Claytonb01000f2011-01-17 03:46:26 +0000404 Disassembler (arch),
Greg Claytonb1888f22011-03-19 01:12:21 +0000405 m_disassembler (NULL),
406 m_disassembler_thumb (NULL) // For ARM only
Chris Lattner24943d22010-06-08 16:52:24 +0000407{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000408 const std::string &arch_triple = arch.GetTriple().str();
409 if (!arch_triple.empty())
Greg Claytoncf015052010-06-11 03:25:34 +0000410 {
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000411 if (EDGetDisassembler(&m_disassembler, arch_triple.c_str(), SyntaxForArchSpec (arch)))
412 m_disassembler = NULL;
Greg Claytonb1888f22011-03-19 01:12:21 +0000413 llvm::Triple::ArchType llvm_arch = arch.GetTriple().getArch();
414 if (llvm_arch == llvm::Triple::arm)
415 {
416 if (EDGetDisassembler(&m_disassembler_thumb, "thumb-apple-darwin", kEDAssemblySyntaxARMUAL))
417 m_disassembler_thumb = NULL;
418 }
419 else if (llvm_arch == llvm::Triple::thumb)
420 {
421 m_disassembler_thumb = m_disassembler;
422 if (EDGetDisassembler(&m_disassembler, "arm-apple-darwin-unknown", kEDAssemblySyntaxARMUAL))
423 m_disassembler = NULL;
424 }
Greg Claytoncf015052010-06-11 03:25:34 +0000425 }
Chris Lattner24943d22010-06-08 16:52:24 +0000426}
427
428DisassemblerLLVM::~DisassemblerLLVM()
429{
430}
431
432size_t
Greg Clayton70436352010-06-30 23:03:03 +0000433DisassemblerLLVM::DecodeInstructions
Chris Lattner24943d22010-06-08 16:52:24 +0000434(
Greg Clayton5c4c7462010-10-06 03:09:58 +0000435 const Address &base_addr,
Chris Lattner24943d22010-06-08 16:52:24 +0000436 const DataExtractor& data,
437 uint32_t data_offset,
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000438 uint32_t num_instructions,
439 bool append
Chris Lattner24943d22010-06-08 16:52:24 +0000440)
441{
Greg Claytonb01000f2011-01-17 03:46:26 +0000442 if (m_disassembler == NULL)
443 return 0;
444
Chris Lattner24943d22010-06-08 16:52:24 +0000445 size_t total_inst_byte_size = 0;
446
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000447 if (!append)
448 m_instruction_list.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000449
450 while (data.ValidOffset(data_offset) && num_instructions)
451 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000452 Address inst_addr (base_addr);
453 inst_addr.Slide(data_offset);
Greg Claytonb1888f22011-03-19 01:12:21 +0000454
455 bool use_thumb = false;
456 // If we have a thumb disassembler, then we have an ARM architecture
457 // so we need to check what the instruction address class is to make
458 // sure we shouldn't be disassembling as thumb...
459 if (m_disassembler_thumb)
460 {
461 if (inst_addr.GetAddressClass () == eAddressClassCodeAlternateISA)
462 use_thumb = true;
463 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000464 InstructionSP inst_sp (new InstructionLLVM (inst_addr,
465 use_thumb ? m_disassembler_thumb : m_disassembler));
Chris Lattner24943d22010-06-08 16:52:24 +0000466
Greg Clayton7bc39082011-03-24 23:53:38 +0000467 size_t inst_byte_size = inst_sp->Extract (*this, data, data_offset);
Chris Lattner24943d22010-06-08 16:52:24 +0000468
469 if (inst_byte_size == 0)
470 break;
471
Greg Clayton5c4c7462010-10-06 03:09:58 +0000472 m_instruction_list.Append (inst_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000473
474 total_inst_byte_size += inst_byte_size;
475 data_offset += inst_byte_size;
476 num_instructions--;
477 }
478
479 return total_inst_byte_size;
480}
481
482void
483DisassemblerLLVM::Initialize()
484{
485 PluginManager::RegisterPlugin (GetPluginNameStatic(),
486 GetPluginDescriptionStatic(),
487 CreateInstance);
488}
489
490void
491DisassemblerLLVM::Terminate()
492{
493 PluginManager::UnregisterPlugin (CreateInstance);
494}
495
496
497const char *
498DisassemblerLLVM::GetPluginNameStatic()
499{
Greg Clayton149731c2011-03-25 18:03:16 +0000500 return "llvm";
Chris Lattner24943d22010-06-08 16:52:24 +0000501}
502
503const char *
504DisassemblerLLVM::GetPluginDescriptionStatic()
505{
Greg Clayton149731c2011-03-25 18:03:16 +0000506 return "Disassembler that uses LLVM opcode tables to disassemble i386, x86_64 and ARM.";
Chris Lattner24943d22010-06-08 16:52:24 +0000507}
508
509//------------------------------------------------------------------
510// PluginInterface protocol
511//------------------------------------------------------------------
512const char *
513DisassemblerLLVM::GetPluginName()
514{
515 return "DisassemblerLLVM";
516}
517
518const char *
519DisassemblerLLVM::GetShortPluginName()
520{
521 return GetPluginNameStatic();
522}
523
524uint32_t
525DisassemblerLLVM::GetPluginVersion()
526{
527 return 1;
528}
529