blob: ea31a82798cb3708e5eae2d0d95358c4a9d6d4e0 [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
Caroline Ticeaf591802011-04-05 23:22:54 +000077InstructionLLVM::InstructionLLVM (const Address &addr,
78 AddressClass addr_class,
Greg Claytonabe0fed2011-04-18 08:33:37 +000079 EDDisassemblerRef disassembler,
Johnny Chen80ab18e2011-05-12 22:25:53 +000080 llvm::Triple::ArchType arch_type) :
Greg Clayton889fbd02011-03-26 19:14:58 +000081 Instruction (addr, addr_class),
Greg Claytonabe0fed2011-04-18 08:33:37 +000082 m_disassembler (disassembler),
Johnny Chen80ab18e2011-05-12 22:25:53 +000083 m_arch_type (arch_type)
Chris Lattner24943d22010-06-08 16:52:24 +000084{
85}
86
Caroline Ticeaf591802011-04-05 23:22:54 +000087InstructionLLVM::~InstructionLLVM()
Chris Lattner24943d22010-06-08 16:52:24 +000088{
89}
90
91static void
92PadString(Stream *s, const std::string &str, size_t width)
93{
94 int diff = width - str.length();
95
96 if (diff > 0)
97 s->Printf("%s%*.*s", str.c_str(), diff, diff, "");
98 else
99 s->Printf("%s ", str.c_str());
100}
101
Johnny Chen51ff2482011-05-19 01:05:37 +0000102#include "llvm/ADT/StringRef.h"
103static void
104StripSpaces(llvm::StringRef &Str)
105{
106 while (!Str.empty() && isspace(Str[0]))
107 Str = Str.substr(1);
108 while (!Str.empty() && isspace(Str.back()))
109 Str = Str.substr(0, Str.size()-1);
110}
Johnny Chen84d42e82011-05-21 00:55:57 +0000111static void
112Align(Stream *s, const char *str)
113{
114 llvm::StringRef raw_disasm(str);
115 StripSpaces(raw_disasm);
116 s->PutCString(raw_disasm.str().c_str());
117}
Johnny Chen51ff2482011-05-19 01:05:37 +0000118
Chris Lattner24943d22010-06-08 16:52:24 +0000119void
Caroline Ticeaf591802011-04-05 23:22:54 +0000120InstructionLLVM::Dump
Chris Lattner24943d22010-06-08 16:52:24 +0000121(
122 Stream *s,
Greg Clayton889fbd02011-03-26 19:14:58 +0000123 uint32_t max_opcode_byte_size,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000124 bool show_address,
Greg Clayton149731c2011-03-25 18:03:16 +0000125 bool show_bytes,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000126 const lldb_private::ExecutionContext* exe_ctx,
Chris Lattner24943d22010-06-08 16:52:24 +0000127 bool raw
128)
129{
130 const size_t opcodeColumnWidth = 7;
131 const size_t operandColumnWidth = 25;
132
Greg Clayton5c4c7462010-10-06 03:09:58 +0000133 ExecutionContextScope *exe_scope = NULL;
134 if (exe_ctx)
135 exe_scope = exe_ctx->GetBestExecutionContextScope();
136
Chris Lattner24943d22010-06-08 16:52:24 +0000137 // If we have an address, print it out
Sean Callanan91557b02010-11-10 01:38:28 +0000138 if (GetAddress().IsValid() && show_address)
Greg Clayton70436352010-06-30 23:03:03 +0000139 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000140 if (GetAddress().Dump (s,
141 exe_scope,
142 Address::DumpStyleLoadAddress,
143 Address::DumpStyleModuleWithFileAddress,
144 0))
Greg Clayton70436352010-06-30 23:03:03 +0000145 s->PutCString(": ");
146 }
Chris Lattner24943d22010-06-08 16:52:24 +0000147
148 // If we are supposed to show bytes, "bytes" will be non-NULL.
Greg Clayton149731c2011-03-25 18:03:16 +0000149 if (show_bytes)
Chris Lattner24943d22010-06-08 16:52:24 +0000150 {
Greg Clayton149731c2011-03-25 18:03:16 +0000151 if (m_opcode.GetType() == Opcode::eTypeBytes)
Chris Lattner24943d22010-06-08 16:52:24 +0000152 {
Greg Clayton149731c2011-03-25 18:03:16 +0000153 // x86_64 and i386 are the only ones that use bytes right now so
154 // pad out the byte dump to be able to always show 15 bytes (3 chars each)
155 // plus a space
Greg Clayton889fbd02011-03-26 19:14:58 +0000156 if (max_opcode_byte_size > 0)
157 m_opcode.Dump (s, max_opcode_byte_size * 3 + 1);
158 else
159 m_opcode.Dump (s, 15 * 3 + 1);
Greg Clayton149731c2011-03-25 18:03:16 +0000160 }
161 else
162 {
163 // Else, we have ARM which can show up to a uint32_t 0x00000000 (10 spaces)
164 // plus two for padding...
Greg Clayton889fbd02011-03-26 19:14:58 +0000165 if (max_opcode_byte_size > 0)
166 m_opcode.Dump (s, max_opcode_byte_size * 3 + 1);
167 else
168 m_opcode.Dump (s, 12);
Chris Lattner24943d22010-06-08 16:52:24 +0000169 }
170 }
171
Greg Claytonf15996e2011-04-07 22:46:35 +0000172 int numTokens = -1;
173
Johnny Chen80ab18e2011-05-12 22:25:53 +0000174 // FIXME!!!
175 /* Remove the following section of code related to force_raw .... */
176 bool force_raw = m_arch_type == llvm::Triple::arm ||
177 m_arch_type == llvm::Triple::thumb;
Greg Claytonf15996e2011-04-07 22:46:35 +0000178 if (!raw)
Johnny Chen80ab18e2011-05-12 22:25:53 +0000179 raw = force_raw;
180 /* .... when we fix the edis for arm/thumb. */
Greg Claytonabe0fed2011-04-18 08:33:37 +0000181
182 if (!raw)
Greg Claytonf15996e2011-04-07 22:46:35 +0000183 numTokens = EDNumTokens(m_inst);
Chris Lattner24943d22010-06-08 16:52:24 +0000184
185 int currentOpIndex = -1;
186
Greg Claytonf15996e2011-04-07 22:46:35 +0000187 bool printTokenized = false;
188
189 if (numTokens != -1 && !raw)
Sean Callanan8541f2f2010-07-23 02:19:15 +0000190 {
191 addr_t base_addr = LLDB_INVALID_ADDRESS;
Greg Claytonf15996e2011-04-07 22:46:35 +0000192
Greg Clayton5c4c7462010-10-06 03:09:58 +0000193 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
194 base_addr = GetAddress().GetLoadAddress (exe_ctx->target);
Sean Callanan8541f2f2010-07-23 02:19:15 +0000195 if (base_addr == LLDB_INVALID_ADDRESS)
Greg Clayton5c4c7462010-10-06 03:09:58 +0000196 base_addr = GetAddress().GetFileAddress ();
Greg Claytonf15996e2011-04-07 22:46:35 +0000197
Johnny Chen80ab18e2011-05-12 22:25:53 +0000198 lldb::addr_t PC = base_addr + EDInstByteSize(m_inst);
199
200 // When executing an ARM instruction, PC reads as the address of the
201 // current instruction plus 8. And for Thumb, it is plus 4.
202 if (m_arch_type == llvm::Triple::arm)
203 PC = base_addr + 8;
204 else if (m_arch_type == llvm::Triple::thumb)
205 PC = base_addr + 4;
206
207 RegisterReaderArg rra(PC, m_disassembler);
Johnny Chenc5272bf2011-05-12 18:48:11 +0000208
Chris Lattner24943d22010-06-08 16:52:24 +0000209 printTokenized = true;
210
211 // Handle the opcode column.
212
213 StreamString opcode;
214
215 int tokenIndex = 0;
216
217 EDTokenRef token;
218 const char *tokenStr;
219
Johnny Chenff8fea62011-05-18 22:48:41 +0000220 if (EDGetToken(&token, m_inst, tokenIndex)) // 0 on success
221 printTokenized = false;
222 else if (!EDTokenIsOpcode(token))
223 printTokenized = false;
224 else if (EDGetTokenString(&tokenStr, token)) // 0 on success
Chris Lattner24943d22010-06-08 16:52:24 +0000225 printTokenized = false;
226
Johnny Chenff8fea62011-05-18 22:48:41 +0000227 if (printTokenized)
Chris Lattner24943d22010-06-08 16:52:24 +0000228 {
Johnny Chenff8fea62011-05-18 22:48:41 +0000229 // Put the token string into our opcode string
230 opcode.PutCString(tokenStr);
Chris Lattner24943d22010-06-08 16:52:24 +0000231
Johnny Chenff8fea62011-05-18 22:48:41 +0000232 // If anything follows, it probably starts with some whitespace. Skip it.
233 if (++tokenIndex < numTokens)
234 {
235 if (EDGetToken(&token, m_inst, tokenIndex)) // 0 on success
236 printTokenized = false;
237 else if (!EDTokenIsWhitespace(token))
238 printTokenized = false;
239 }
240
241 ++tokenIndex;
Chris Lattner24943d22010-06-08 16:52:24 +0000242 }
243
Chris Lattner24943d22010-06-08 16:52:24 +0000244 // Handle the operands and the comment.
Chris Lattner24943d22010-06-08 16:52:24 +0000245 StreamString operands;
246 StreamString comment;
247
248 if (printTokenized)
249 {
Johnny Chen51ff2482011-05-19 01:05:37 +0000250 bool show_token = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000251
252 for (; tokenIndex < numTokens; ++tokenIndex)
253 {
254 if (EDGetToken(&token, m_inst, tokenIndex))
255 return;
256
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000257 int operandIndex = EDOperandIndexForToken(token);
Chris Lattner24943d22010-06-08 16:52:24 +0000258
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000259 if (operandIndex >= 0)
260 {
261 if (operandIndex != currentOpIndex)
Chris Lattner24943d22010-06-08 16:52:24 +0000262 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000263 show_token = true;
264
265 currentOpIndex = operandIndex;
266 EDOperandRef operand;
267
268 if (!EDGetOperand(&operand, m_inst, currentOpIndex))
Chris Lattner24943d22010-06-08 16:52:24 +0000269 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000270 if (EDOperandIsMemory(operand))
Chris Lattner24943d22010-06-08 16:52:24 +0000271 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000272 uint64_t operand_value;
273
274 if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, &rra))
Chris Lattner24943d22010-06-08 16:52:24 +0000275 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000276 if (EDInstIsBranch(m_inst))
Chris Lattner24943d22010-06-08 16:52:24 +0000277 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000278 operands.Printf("0x%llx ", operand_value);
279 show_token = false;
280 }
281 else
282 {
283 // Put the address value into the comment
284 comment.Printf("0x%llx ", operand_value);
285 }
Chris Lattner24943d22010-06-08 16:52:24 +0000286
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000287 lldb_private::Address so_addr;
288 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
289 {
290 if (exe_ctx->target->GetSectionLoadList().ResolveLoadAddress (operand_value, so_addr))
291 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
292 }
293 else
294 {
295 Module *module = GetAddress().GetModule();
296 if (module)
Chris Lattner24943d22010-06-08 16:52:24 +0000297 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000298 if (module->ResolveFileAddress (operand_value, so_addr))
Greg Claytoncf7f1ad2010-07-01 01:26:43 +0000299 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
Greg Clayton70436352010-06-30 23:03:03 +0000300 }
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000301 }
302 } // EDEvaluateOperand
303 } // EDOperandIsMemory
304 } // EDGetOperand
305 } // operandIndex != currentOpIndex
306 } // operandIndex >= 0
Chris Lattner24943d22010-06-08 16:52:24 +0000307
308 if (show_token)
309 {
310 if(EDGetTokenString(&tokenStr, token))
311 {
312 printTokenized = false;
313 break;
314 }
315
316 operands.PutCString(tokenStr);
317 }
318 } // for (tokenIndex)
319
Johnny Chende5cc8c2011-05-20 17:27:37 +0000320 // FIXME!!!
321 // Workaround for llvm::tB's operands not properly parsed by ARMAsmParser.
322 if (m_arch_type == llvm::Triple::thumb && opcode.GetString() == "b") {
323 const char *inst_str;
Peter Collingbourned77c0392011-05-20 22:42:59 +0000324 const char *pos = NULL;
Johnny Chende5cc8c2011-05-20 17:27:37 +0000325 if (EDGetInstString(&inst_str, m_inst) == 0 && (pos = strstr(inst_str, "#")) != NULL) {
326 uint64_t operand_value = PC + atoi(++pos);
327 operands.Printf("0x%llx ", operand_value);
328
329 lldb_private::Address so_addr;
330 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty()) {
331 if (exe_ctx->target->GetSectionLoadList().ResolveLoadAddress (operand_value, so_addr))
332 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
333 } else {
334 Module *module = GetAddress().GetModule();
335 if (module) {
336 if (module->ResolveFileAddress (operand_value, so_addr))
337 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
338 }
339 }
340 }
341 }
342 // END of workaround.
343
Johnny Chen51ff2482011-05-19 01:05:37 +0000344 // If both operands and comment are empty, we will just print out
345 // the raw disassembly.
346 if (operands.GetString().empty() && comment.GetString().empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000347 {
Johnny Chen51ff2482011-05-19 01:05:37 +0000348 const char *str;
349
350 if (EDGetInstString(&str, m_inst))
351 return;
Johnny Chen84d42e82011-05-21 00:55:57 +0000352 Align(s, str);
Johnny Chen51ff2482011-05-19 01:05:37 +0000353 }
354 else
355 {
356 PadString(s, opcode.GetString(), opcodeColumnWidth);
357
358 if (comment.GetString().empty())
359 s->PutCString(operands.GetString().c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000360 else
361 {
Johnny Chen51ff2482011-05-19 01:05:37 +0000362 PadString(s, operands.GetString(), operandColumnWidth);
Chris Lattner24943d22010-06-08 16:52:24 +0000363
Johnny Chen51ff2482011-05-19 01:05:37 +0000364 s->PutCString("; ");
365 s->PutCString(comment.GetString().c_str());
366 } // else (comment.GetString().empty())
367 } // else (operands.GetString().empty() && comment.GetString().empty())
368 } // printTokenized
Chris Lattner24943d22010-06-08 16:52:24 +0000369 } // numTokens != -1
370
371 if (!printTokenized)
372 {
373 const char *str;
374
Johnny Chen51ff2482011-05-19 01:05:37 +0000375 if (EDGetInstString(&str, m_inst)) // 0 on success
Chris Lattner24943d22010-06-08 16:52:24 +0000376 return;
Johnny Chen08251ef2011-05-21 00:44:42 +0000377 if (raw)
378 s->Write(str, strlen(str) - 1);
379 else
380 {
381 // EDis fails to parse the tokens of this inst. Need to align this
Johnny Chen84d42e82011-05-21 00:55:57 +0000382 // raw disassembly's opcode with the rest of output.
383 Align(s, str);
Johnny Chen08251ef2011-05-21 00:44:42 +0000384 }
Chris Lattner24943d22010-06-08 16:52:24 +0000385 }
386}
387
388bool
Caroline Ticeaf591802011-04-05 23:22:54 +0000389InstructionLLVM::DoesBranch() const
Chris Lattner24943d22010-06-08 16:52:24 +0000390{
391 return EDInstIsBranch(m_inst);
392}
393
394size_t
Caroline Ticeaf591802011-04-05 23:22:54 +0000395InstructionLLVM::Decode (const Disassembler &disassembler,
396 const lldb_private::DataExtractor &data,
397 uint32_t data_offset)
Chris Lattner24943d22010-06-08 16:52:24 +0000398{
399 if (EDCreateInsts(&m_inst, 1, m_disassembler, DataExtractorByteReader, data_offset, (void*)(&data)))
Greg Clayton7bc39082011-03-24 23:53:38 +0000400 {
401 const int byte_size = EDInstByteSize(m_inst);
402 uint32_t offset = data_offset;
403 // Make a copy of the opcode in m_opcode
404 switch (disassembler.GetArchitecture().GetMachine())
405 {
406 case llvm::Triple::x86:
407 case llvm::Triple::x86_64:
408 m_opcode.SetOpcodeBytes (data.PeekData (data_offset, byte_size), byte_size);
409 break;
410
411 case llvm::Triple::arm:
Greg Clayton7bc39082011-03-24 23:53:38 +0000412 case llvm::Triple::thumb:
Greg Clayton149731c2011-03-25 18:03:16 +0000413 switch (byte_size)
414 {
415 case 2:
416 m_opcode.SetOpcode16 (data.GetU16 (&offset));
417 break;
418
419 case 4:
Caroline Tice6b8d3b52011-04-19 23:30:03 +0000420 {
421 if (GetAddressClass() == eAddressClassCodeAlternateISA)
422 {
423 // If it is a 32-bit THUMB instruction, we need to swap the upper & lower halves.
424 uint32_t orig_bytes = data.GetU32 (&offset);
425 uint16_t upper_bits = (orig_bytes >> 16) & ((1u << 16) - 1);
426 uint16_t lower_bits = orig_bytes & ((1u << 16) - 1);
427 uint32_t swapped = (lower_bits << 16) | upper_bits;
428 m_opcode.SetOpcode32 (swapped);
429 }
430 else
431 m_opcode.SetOpcode32 (data.GetU32 (&offset));
432 }
Greg Clayton149731c2011-03-25 18:03:16 +0000433 break;
434
435 default:
436 assert (!"Invalid ARM opcode size");
437 break;
438 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000439 break;
440
441 default:
442 assert (!"This shouldn't happen since we control the architecture we allow DisassemblerLLVM to be created for");
443 break;
444 }
445 return byte_size;
446 }
Chris Lattner24943d22010-06-08 16:52:24 +0000447 else
448 return 0;
449}
450
Chris Lattner24943d22010-06-08 16:52:24 +0000451static inline EDAssemblySyntax_t
Greg Claytoncf015052010-06-11 03:25:34 +0000452SyntaxForArchSpec (const ArchSpec &arch)
Chris Lattner24943d22010-06-08 16:52:24 +0000453{
Greg Clayton940b1032011-02-23 00:35:02 +0000454 switch (arch.GetMachine ())
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000455 {
Greg Clayton940b1032011-02-23 00:35:02 +0000456 case llvm::Triple::x86:
457 case llvm::Triple::x86_64:
Chris Lattner24943d22010-06-08 16:52:24 +0000458 return kEDAssemblySyntaxX86ATT;
Sean Callanand151c8a2011-03-09 01:02:51 +0000459 case llvm::Triple::arm:
Greg Clayton889fbd02011-03-26 19:14:58 +0000460 case llvm::Triple::thumb:
Sean Callanand151c8a2011-03-09 01:02:51 +0000461 return kEDAssemblySyntaxARMUAL;
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000462 default:
463 break;
464 }
Greg Claytoncf015052010-06-11 03:25:34 +0000465 return (EDAssemblySyntax_t)0; // default
Chris Lattner24943d22010-06-08 16:52:24 +0000466}
467
468Disassembler *
469DisassemblerLLVM::CreateInstance(const ArchSpec &arch)
470{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000471 std::auto_ptr<DisassemblerLLVM> disasm_ap (new DisassemblerLLVM(arch));
472
Caroline Tice080bf612011-04-05 18:46:00 +0000473 if (disasm_ap.get() && disasm_ap->IsValid())
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000474 return disasm_ap.release();
Chris Lattner24943d22010-06-08 16:52:24 +0000475
Greg Claytoncf015052010-06-11 03:25:34 +0000476 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000477}
478
479DisassemblerLLVM::DisassemblerLLVM(const ArchSpec &arch) :
Greg Claytonb01000f2011-01-17 03:46:26 +0000480 Disassembler (arch),
Greg Claytonb1888f22011-03-19 01:12:21 +0000481 m_disassembler (NULL),
482 m_disassembler_thumb (NULL) // For ARM only
Chris Lattner24943d22010-06-08 16:52:24 +0000483{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000484 const std::string &arch_triple = arch.GetTriple().str();
485 if (!arch_triple.empty())
Greg Claytoncf015052010-06-11 03:25:34 +0000486 {
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000487 if (EDGetDisassembler(&m_disassembler, arch_triple.c_str(), SyntaxForArchSpec (arch)))
488 m_disassembler = NULL;
Greg Claytonb1888f22011-03-19 01:12:21 +0000489 llvm::Triple::ArchType llvm_arch = arch.GetTriple().getArch();
Greg Clayton889fbd02011-03-26 19:14:58 +0000490 // Don't have the lldb::Triple::thumb architecture here. If someone specifies
491 // "thumb" as the architecture, we want a thumb only disassembler. But if any
492 // architecture starting with "arm" if specified, we want to auto detect the
493 // arm/thumb code automatically using the AddressClass from section offset
494 // addresses.
Greg Claytonb1888f22011-03-19 01:12:21 +0000495 if (llvm_arch == llvm::Triple::arm)
496 {
497 if (EDGetDisassembler(&m_disassembler_thumb, "thumb-apple-darwin", kEDAssemblySyntaxARMUAL))
498 m_disassembler_thumb = NULL;
499 }
Greg Claytoncf015052010-06-11 03:25:34 +0000500 }
Chris Lattner24943d22010-06-08 16:52:24 +0000501}
502
503DisassemblerLLVM::~DisassemblerLLVM()
504{
505}
506
507size_t
Greg Clayton70436352010-06-30 23:03:03 +0000508DisassemblerLLVM::DecodeInstructions
Chris Lattner24943d22010-06-08 16:52:24 +0000509(
Greg Clayton5c4c7462010-10-06 03:09:58 +0000510 const Address &base_addr,
Chris Lattner24943d22010-06-08 16:52:24 +0000511 const DataExtractor& data,
512 uint32_t data_offset,
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000513 uint32_t num_instructions,
514 bool append
Chris Lattner24943d22010-06-08 16:52:24 +0000515)
516{
Greg Claytonb01000f2011-01-17 03:46:26 +0000517 if (m_disassembler == NULL)
518 return 0;
519
Chris Lattner24943d22010-06-08 16:52:24 +0000520 size_t total_inst_byte_size = 0;
521
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000522 if (!append)
523 m_instruction_list.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000524
525 while (data.ValidOffset(data_offset) && num_instructions)
526 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000527 Address inst_addr (base_addr);
528 inst_addr.Slide(data_offset);
Greg Claytonb1888f22011-03-19 01:12:21 +0000529
530 bool use_thumb = false;
531 // If we have a thumb disassembler, then we have an ARM architecture
532 // so we need to check what the instruction address class is to make
533 // sure we shouldn't be disassembling as thumb...
Greg Clayton889fbd02011-03-26 19:14:58 +0000534 AddressClass inst_address_class = eAddressClassInvalid;
Greg Claytonb1888f22011-03-19 01:12:21 +0000535 if (m_disassembler_thumb)
536 {
Greg Clayton889fbd02011-03-26 19:14:58 +0000537 inst_address_class = inst_addr.GetAddressClass ();
538 if (inst_address_class == eAddressClassCodeAlternateISA)
Greg Claytonb1888f22011-03-19 01:12:21 +0000539 use_thumb = true;
540 }
Johnny Chen80ab18e2011-05-12 22:25:53 +0000541
Greg Clayton7bc39082011-03-24 23:53:38 +0000542 InstructionSP inst_sp (new InstructionLLVM (inst_addr,
Greg Clayton889fbd02011-03-26 19:14:58 +0000543 inst_address_class,
Greg Claytonabe0fed2011-04-18 08:33:37 +0000544 use_thumb ? m_disassembler_thumb : m_disassembler,
Johnny Chen1608c872011-05-18 18:22:16 +0000545 use_thumb ? llvm::Triple::thumb : m_arch.GetMachine()));
Chris Lattner24943d22010-06-08 16:52:24 +0000546
Greg Clayton889fbd02011-03-26 19:14:58 +0000547 size_t inst_byte_size = inst_sp->Decode (*this, data, data_offset);
Chris Lattner24943d22010-06-08 16:52:24 +0000548
549 if (inst_byte_size == 0)
550 break;
551
Greg Clayton5c4c7462010-10-06 03:09:58 +0000552 m_instruction_list.Append (inst_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000553
554 total_inst_byte_size += inst_byte_size;
555 data_offset += inst_byte_size;
556 num_instructions--;
557 }
558
559 return total_inst_byte_size;
560}
561
562void
563DisassemblerLLVM::Initialize()
564{
565 PluginManager::RegisterPlugin (GetPluginNameStatic(),
566 GetPluginDescriptionStatic(),
567 CreateInstance);
568}
569
570void
571DisassemblerLLVM::Terminate()
572{
573 PluginManager::UnregisterPlugin (CreateInstance);
574}
575
576
577const char *
578DisassemblerLLVM::GetPluginNameStatic()
579{
Greg Clayton149731c2011-03-25 18:03:16 +0000580 return "llvm";
Chris Lattner24943d22010-06-08 16:52:24 +0000581}
582
583const char *
584DisassemblerLLVM::GetPluginDescriptionStatic()
585{
Greg Clayton149731c2011-03-25 18:03:16 +0000586 return "Disassembler that uses LLVM opcode tables to disassemble i386, x86_64 and ARM.";
Chris Lattner24943d22010-06-08 16:52:24 +0000587}
588
589//------------------------------------------------------------------
590// PluginInterface protocol
591//------------------------------------------------------------------
592const char *
593DisassemblerLLVM::GetPluginName()
594{
595 return "DisassemblerLLVM";
596}
597
598const char *
599DisassemblerLLVM::GetShortPluginName()
600{
601 return GetPluginNameStatic();
602}
603
604uint32_t
605DisassemblerLLVM::GetPluginVersion()
606{
607 return 1;
608}
609