blob: 972d9a3ad166c37f6a78e28f6e8e3306d0ebbf26 [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}
Johnny Chend254eb92011-05-23 23:29:23 +0000101static void
102AddSymbolicInfo(const ExecutionContext *exe_ctx, ExecutionContextScope *exe_scope,
103 StreamString &comment, uint64_t operand_value, const Address &inst_addr)
104{
105 Address so_addr;
106 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
107 {
108 if (exe_ctx->target->GetSectionLoadList().ResolveLoadAddress(operand_value, so_addr))
109 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
110 }
111 else
112 {
113 Module *module = inst_addr.GetModule();
114 if (module)
115 {
116 if (module->ResolveFileAddress(operand_value, so_addr))
117 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
118 }
119 }
120}
Chris Lattner24943d22010-06-08 16:52:24 +0000121
Johnny Chen51ff2482011-05-19 01:05:37 +0000122#include "llvm/ADT/StringRef.h"
Johnny Chend254eb92011-05-23 23:29:23 +0000123static inline void StripSpaces(llvm::StringRef &Str)
Johnny Chen51ff2482011-05-19 01:05:37 +0000124{
125 while (!Str.empty() && isspace(Str[0]))
126 Str = Str.substr(1);
127 while (!Str.empty() && isspace(Str.back()))
128 Str = Str.substr(0, Str.size()-1);
129}
Johnny Chend254eb92011-05-23 23:29:23 +0000130static inline void RStrip(llvm::StringRef &Str, char c)
131{
132 if (!Str.empty() && Str.back() == c)
133 Str = Str.substr(0, Str.size()-1);
134}
Johnny Chen3930cbe2011-05-24 20:36:40 +0000135// Aligns the raw disassembly (passed as 'str') with the rest of edis'ed disassembly output.
136// This is called from non-raw mode when edis of the current m_inst fails for some reason.
Johnny Chen84d42e82011-05-21 00:55:57 +0000137static void
Johnny Chend17f8012011-05-23 18:00:40 +0000138Align(Stream *s, const char *str, size_t opcodeColWidth, size_t operandColWidth)
Johnny Chen84d42e82011-05-21 00:55:57 +0000139{
140 llvm::StringRef raw_disasm(str);
141 StripSpaces(raw_disasm);
Johnny Chend17f8012011-05-23 18:00:40 +0000142 // Split the raw disassembly into opcode and operands.
143 std::pair<llvm::StringRef, llvm::StringRef> p = raw_disasm.split('\t');
144 PadString(s, p.first, opcodeColWidth);
145 if (!p.second.empty())
146 PadString(s, p.second, operandColWidth);
Johnny Chen84d42e82011-05-21 00:55:57 +0000147}
Johnny Chen51ff2482011-05-19 01:05:37 +0000148
Chris Lattner24943d22010-06-08 16:52:24 +0000149void
Caroline Ticeaf591802011-04-05 23:22:54 +0000150InstructionLLVM::Dump
Chris Lattner24943d22010-06-08 16:52:24 +0000151(
152 Stream *s,
Greg Clayton889fbd02011-03-26 19:14:58 +0000153 uint32_t max_opcode_byte_size,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000154 bool show_address,
Greg Clayton149731c2011-03-25 18:03:16 +0000155 bool show_bytes,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000156 const lldb_private::ExecutionContext* exe_ctx,
Chris Lattner24943d22010-06-08 16:52:24 +0000157 bool raw
158)
159{
160 const size_t opcodeColumnWidth = 7;
161 const size_t operandColumnWidth = 25;
162
Greg Clayton5c4c7462010-10-06 03:09:58 +0000163 ExecutionContextScope *exe_scope = NULL;
164 if (exe_ctx)
165 exe_scope = exe_ctx->GetBestExecutionContextScope();
166
Chris Lattner24943d22010-06-08 16:52:24 +0000167 // If we have an address, print it out
Sean Callanan91557b02010-11-10 01:38:28 +0000168 if (GetAddress().IsValid() && show_address)
Greg Clayton70436352010-06-30 23:03:03 +0000169 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000170 if (GetAddress().Dump (s,
171 exe_scope,
172 Address::DumpStyleLoadAddress,
173 Address::DumpStyleModuleWithFileAddress,
174 0))
Greg Clayton70436352010-06-30 23:03:03 +0000175 s->PutCString(": ");
176 }
Chris Lattner24943d22010-06-08 16:52:24 +0000177
178 // If we are supposed to show bytes, "bytes" will be non-NULL.
Greg Clayton149731c2011-03-25 18:03:16 +0000179 if (show_bytes)
Chris Lattner24943d22010-06-08 16:52:24 +0000180 {
Greg Clayton149731c2011-03-25 18:03:16 +0000181 if (m_opcode.GetType() == Opcode::eTypeBytes)
Chris Lattner24943d22010-06-08 16:52:24 +0000182 {
Greg Clayton149731c2011-03-25 18:03:16 +0000183 // x86_64 and i386 are the only ones that use bytes right now so
184 // pad out the byte dump to be able to always show 15 bytes (3 chars each)
185 // plus a space
Greg Clayton889fbd02011-03-26 19:14:58 +0000186 if (max_opcode_byte_size > 0)
187 m_opcode.Dump (s, max_opcode_byte_size * 3 + 1);
188 else
189 m_opcode.Dump (s, 15 * 3 + 1);
Greg Clayton149731c2011-03-25 18:03:16 +0000190 }
191 else
192 {
193 // Else, we have ARM which can show up to a uint32_t 0x00000000 (10 spaces)
194 // plus two for padding...
Greg Clayton889fbd02011-03-26 19:14:58 +0000195 if (max_opcode_byte_size > 0)
196 m_opcode.Dump (s, max_opcode_byte_size * 3 + 1);
197 else
198 m_opcode.Dump (s, 12);
Chris Lattner24943d22010-06-08 16:52:24 +0000199 }
200 }
201
Greg Claytonf15996e2011-04-07 22:46:35 +0000202 int numTokens = -1;
203
Johnny Chen80ab18e2011-05-12 22:25:53 +0000204 // FIXME!!!
205 /* Remove the following section of code related to force_raw .... */
Johnny Chend17f8012011-05-23 18:00:40 +0000206 /*
Johnny Chen80ab18e2011-05-12 22:25:53 +0000207 bool force_raw = m_arch_type == llvm::Triple::arm ||
208 m_arch_type == llvm::Triple::thumb;
Greg Claytonf15996e2011-04-07 22:46:35 +0000209 if (!raw)
Johnny Chen80ab18e2011-05-12 22:25:53 +0000210 raw = force_raw;
Johnny Chend17f8012011-05-23 18:00:40 +0000211 */
Johnny Chen80ab18e2011-05-12 22:25:53 +0000212 /* .... when we fix the edis for arm/thumb. */
Greg Claytonabe0fed2011-04-18 08:33:37 +0000213
214 if (!raw)
Greg Claytonf15996e2011-04-07 22:46:35 +0000215 numTokens = EDNumTokens(m_inst);
Chris Lattner24943d22010-06-08 16:52:24 +0000216
217 int currentOpIndex = -1;
218
Greg Claytonf15996e2011-04-07 22:46:35 +0000219 bool printTokenized = false;
220
221 if (numTokens != -1 && !raw)
Sean Callanan8541f2f2010-07-23 02:19:15 +0000222 {
223 addr_t base_addr = LLDB_INVALID_ADDRESS;
Greg Claytonf15996e2011-04-07 22:46:35 +0000224
Greg Clayton5c4c7462010-10-06 03:09:58 +0000225 if (exe_ctx && exe_ctx->target && !exe_ctx->target->GetSectionLoadList().IsEmpty())
226 base_addr = GetAddress().GetLoadAddress (exe_ctx->target);
Sean Callanan8541f2f2010-07-23 02:19:15 +0000227 if (base_addr == LLDB_INVALID_ADDRESS)
Greg Clayton5c4c7462010-10-06 03:09:58 +0000228 base_addr = GetAddress().GetFileAddress ();
Greg Claytonf15996e2011-04-07 22:46:35 +0000229
Johnny Chen80ab18e2011-05-12 22:25:53 +0000230 lldb::addr_t PC = base_addr + EDInstByteSize(m_inst);
231
232 // When executing an ARM instruction, PC reads as the address of the
233 // current instruction plus 8. And for Thumb, it is plus 4.
234 if (m_arch_type == llvm::Triple::arm)
235 PC = base_addr + 8;
236 else if (m_arch_type == llvm::Triple::thumb)
237 PC = base_addr + 4;
238
239 RegisterReaderArg rra(PC, m_disassembler);
Johnny Chenc5272bf2011-05-12 18:48:11 +0000240
Chris Lattner24943d22010-06-08 16:52:24 +0000241 printTokenized = true;
242
243 // Handle the opcode column.
244
245 StreamString opcode;
246
247 int tokenIndex = 0;
248
249 EDTokenRef token;
250 const char *tokenStr;
251
Johnny Chenff8fea62011-05-18 22:48:41 +0000252 if (EDGetToken(&token, m_inst, tokenIndex)) // 0 on success
253 printTokenized = false;
254 else if (!EDTokenIsOpcode(token))
255 printTokenized = false;
256 else if (EDGetTokenString(&tokenStr, token)) // 0 on success
Chris Lattner24943d22010-06-08 16:52:24 +0000257 printTokenized = false;
258
Johnny Chenff8fea62011-05-18 22:48:41 +0000259 if (printTokenized)
Chris Lattner24943d22010-06-08 16:52:24 +0000260 {
Johnny Chenff8fea62011-05-18 22:48:41 +0000261 // Put the token string into our opcode string
262 opcode.PutCString(tokenStr);
Chris Lattner24943d22010-06-08 16:52:24 +0000263
Johnny Chenff8fea62011-05-18 22:48:41 +0000264 // If anything follows, it probably starts with some whitespace. Skip it.
265 if (++tokenIndex < numTokens)
266 {
267 if (EDGetToken(&token, m_inst, tokenIndex)) // 0 on success
268 printTokenized = false;
269 else if (!EDTokenIsWhitespace(token))
270 printTokenized = false;
271 }
272
273 ++tokenIndex;
Chris Lattner24943d22010-06-08 16:52:24 +0000274 }
275
Chris Lattner24943d22010-06-08 16:52:24 +0000276 // Handle the operands and the comment.
Chris Lattner24943d22010-06-08 16:52:24 +0000277 StreamString operands;
278 StreamString comment;
279
280 if (printTokenized)
281 {
Johnny Chen51ff2482011-05-19 01:05:37 +0000282 bool show_token = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000283
284 for (; tokenIndex < numTokens; ++tokenIndex)
285 {
286 if (EDGetToken(&token, m_inst, tokenIndex))
287 return;
288
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000289 int operandIndex = EDOperandIndexForToken(token);
Chris Lattner24943d22010-06-08 16:52:24 +0000290
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000291 if (operandIndex >= 0)
292 {
293 if (operandIndex != currentOpIndex)
Chris Lattner24943d22010-06-08 16:52:24 +0000294 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000295 show_token = true;
296
297 currentOpIndex = operandIndex;
298 EDOperandRef operand;
299
300 if (!EDGetOperand(&operand, m_inst, currentOpIndex))
Chris Lattner24943d22010-06-08 16:52:24 +0000301 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000302 if (EDOperandIsMemory(operand))
Chris Lattner24943d22010-06-08 16:52:24 +0000303 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000304 uint64_t operand_value;
305
306 if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, &rra))
Chris Lattner24943d22010-06-08 16:52:24 +0000307 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000308 if (EDInstIsBranch(m_inst))
Chris Lattner24943d22010-06-08 16:52:24 +0000309 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000310 operands.Printf("0x%llx ", operand_value);
311 show_token = false;
312 }
313 else
314 {
315 // Put the address value into the comment
316 comment.Printf("0x%llx ", operand_value);
317 }
Chris Lattner24943d22010-06-08 16:52:24 +0000318
Johnny Chend254eb92011-05-23 23:29:23 +0000319 AddSymbolicInfo(exe_ctx, exe_scope, comment, operand_value, GetAddress());
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000320 } // EDEvaluateOperand
321 } // EDOperandIsMemory
322 } // EDGetOperand
323 } // operandIndex != currentOpIndex
324 } // operandIndex >= 0
Chris Lattner24943d22010-06-08 16:52:24 +0000325
326 if (show_token)
327 {
Enrico Granata4c3fb4b2011-07-19 18:03:25 +0000328 if (EDGetTokenString(&tokenStr, token))
Chris Lattner24943d22010-06-08 16:52:24 +0000329 {
330 printTokenized = false;
331 break;
332 }
333
334 operands.PutCString(tokenStr);
335 }
336 } // for (tokenIndex)
337
Johnny Chende5cc8c2011-05-20 17:27:37 +0000338 // FIXME!!!
339 // Workaround for llvm::tB's operands not properly parsed by ARMAsmParser.
340 if (m_arch_type == llvm::Triple::thumb && opcode.GetString() == "b") {
341 const char *inst_str;
Peter Collingbourned77c0392011-05-20 22:42:59 +0000342 const char *pos = NULL;
Johnny Chenc298a982011-05-23 19:41:31 +0000343 operands.Clear(); comment.Clear();
Johnny Chende5cc8c2011-05-20 17:27:37 +0000344 if (EDGetInstString(&inst_str, m_inst) == 0 && (pos = strstr(inst_str, "#")) != NULL) {
345 uint64_t operand_value = PC + atoi(++pos);
Johnny Chend254eb92011-05-23 23:29:23 +0000346 // Put the address value into the operands.
Johnny Chende5cc8c2011-05-20 17:27:37 +0000347 operands.Printf("0x%llx ", operand_value);
Johnny Chend254eb92011-05-23 23:29:23 +0000348 AddSymbolicInfo(exe_ctx, exe_scope, comment, operand_value, GetAddress());
Johnny Chende5cc8c2011-05-20 17:27:37 +0000349 }
350 }
Johnny Chenc298a982011-05-23 19:41:31 +0000351 // Yet more workaround for "bl #..." and "blx #...".
352 if ((m_arch_type == llvm::Triple::arm || m_arch_type == llvm::Triple::thumb) &&
353 (opcode.GetString() == "bl" || opcode.GetString() == "blx")) {
354 const char *inst_str;
355 const char *pos = NULL;
356 operands.Clear(); comment.Clear();
357 if (EDGetInstString(&inst_str, m_inst) == 0 && (pos = strstr(inst_str, "#")) != NULL) {
358 uint64_t operand_value = PC + atoi(++pos);
Johnny Chend254eb92011-05-23 23:29:23 +0000359 // Put the address value into the comment.
Johnny Chenc298a982011-05-23 19:41:31 +0000360 comment.Printf("0x%llx ", operand_value);
Johnny Chend254eb92011-05-23 23:29:23 +0000361 // And the original token string into the operands.
362 llvm::StringRef Str(pos - 1);
363 RStrip(Str, '\n');
364 operands.PutCString(Str.str().c_str());
365 AddSymbolicInfo(exe_ctx, exe_scope, comment, operand_value, GetAddress());
Johnny Chenc298a982011-05-23 19:41:31 +0000366 }
367 }
Johnny Chende5cc8c2011-05-20 17:27:37 +0000368 // END of workaround.
369
Johnny Chen51ff2482011-05-19 01:05:37 +0000370 // If both operands and comment are empty, we will just print out
371 // the raw disassembly.
372 if (operands.GetString().empty() && comment.GetString().empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000373 {
Johnny Chen51ff2482011-05-19 01:05:37 +0000374 const char *str;
375
376 if (EDGetInstString(&str, m_inst))
377 return;
Johnny Chend17f8012011-05-23 18:00:40 +0000378 Align(s, str, opcodeColumnWidth, operandColumnWidth);
Johnny Chen51ff2482011-05-19 01:05:37 +0000379 }
380 else
381 {
382 PadString(s, opcode.GetString(), opcodeColumnWidth);
383
384 if (comment.GetString().empty())
385 s->PutCString(operands.GetString().c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000386 else
387 {
Johnny Chen51ff2482011-05-19 01:05:37 +0000388 PadString(s, operands.GetString(), operandColumnWidth);
Chris Lattner24943d22010-06-08 16:52:24 +0000389
Johnny Chen51ff2482011-05-19 01:05:37 +0000390 s->PutCString("; ");
391 s->PutCString(comment.GetString().c_str());
392 } // else (comment.GetString().empty())
393 } // else (operands.GetString().empty() && comment.GetString().empty())
394 } // printTokenized
Chris Lattner24943d22010-06-08 16:52:24 +0000395 } // numTokens != -1
396
397 if (!printTokenized)
398 {
399 const char *str;
400
Johnny Chen51ff2482011-05-19 01:05:37 +0000401 if (EDGetInstString(&str, m_inst)) // 0 on success
Chris Lattner24943d22010-06-08 16:52:24 +0000402 return;
Johnny Chen08251ef2011-05-21 00:44:42 +0000403 if (raw)
404 s->Write(str, strlen(str) - 1);
405 else
406 {
407 // EDis fails to parse the tokens of this inst. Need to align this
Johnny Chen84d42e82011-05-21 00:55:57 +0000408 // raw disassembly's opcode with the rest of output.
Johnny Chend17f8012011-05-23 18:00:40 +0000409 Align(s, str, opcodeColumnWidth, operandColumnWidth);
Johnny Chen08251ef2011-05-21 00:44:42 +0000410 }
Chris Lattner24943d22010-06-08 16:52:24 +0000411 }
412}
413
414bool
Caroline Ticeaf591802011-04-05 23:22:54 +0000415InstructionLLVM::DoesBranch() const
Chris Lattner24943d22010-06-08 16:52:24 +0000416{
417 return EDInstIsBranch(m_inst);
418}
419
420size_t
Caroline Ticeaf591802011-04-05 23:22:54 +0000421InstructionLLVM::Decode (const Disassembler &disassembler,
422 const lldb_private::DataExtractor &data,
423 uint32_t data_offset)
Chris Lattner24943d22010-06-08 16:52:24 +0000424{
425 if (EDCreateInsts(&m_inst, 1, m_disassembler, DataExtractorByteReader, data_offset, (void*)(&data)))
Greg Clayton7bc39082011-03-24 23:53:38 +0000426 {
427 const int byte_size = EDInstByteSize(m_inst);
428 uint32_t offset = data_offset;
429 // Make a copy of the opcode in m_opcode
430 switch (disassembler.GetArchitecture().GetMachine())
431 {
432 case llvm::Triple::x86:
433 case llvm::Triple::x86_64:
434 m_opcode.SetOpcodeBytes (data.PeekData (data_offset, byte_size), byte_size);
435 break;
436
437 case llvm::Triple::arm:
Greg Clayton7bc39082011-03-24 23:53:38 +0000438 case llvm::Triple::thumb:
Greg Clayton149731c2011-03-25 18:03:16 +0000439 switch (byte_size)
440 {
441 case 2:
442 m_opcode.SetOpcode16 (data.GetU16 (&offset));
443 break;
444
445 case 4:
Caroline Tice6b8d3b52011-04-19 23:30:03 +0000446 {
447 if (GetAddressClass() == eAddressClassCodeAlternateISA)
448 {
449 // If it is a 32-bit THUMB instruction, we need to swap the upper & lower halves.
450 uint32_t orig_bytes = data.GetU32 (&offset);
451 uint16_t upper_bits = (orig_bytes >> 16) & ((1u << 16) - 1);
452 uint16_t lower_bits = orig_bytes & ((1u << 16) - 1);
453 uint32_t swapped = (lower_bits << 16) | upper_bits;
454 m_opcode.SetOpcode32 (swapped);
455 }
456 else
457 m_opcode.SetOpcode32 (data.GetU32 (&offset));
458 }
Greg Clayton149731c2011-03-25 18:03:16 +0000459 break;
460
461 default:
462 assert (!"Invalid ARM opcode size");
463 break;
464 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000465 break;
466
467 default:
468 assert (!"This shouldn't happen since we control the architecture we allow DisassemblerLLVM to be created for");
469 break;
470 }
471 return byte_size;
472 }
Chris Lattner24943d22010-06-08 16:52:24 +0000473 else
474 return 0;
475}
476
Chris Lattner24943d22010-06-08 16:52:24 +0000477static inline EDAssemblySyntax_t
Greg Claytoncf015052010-06-11 03:25:34 +0000478SyntaxForArchSpec (const ArchSpec &arch)
Chris Lattner24943d22010-06-08 16:52:24 +0000479{
Greg Clayton940b1032011-02-23 00:35:02 +0000480 switch (arch.GetMachine ())
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000481 {
Greg Clayton940b1032011-02-23 00:35:02 +0000482 case llvm::Triple::x86:
483 case llvm::Triple::x86_64:
Chris Lattner24943d22010-06-08 16:52:24 +0000484 return kEDAssemblySyntaxX86ATT;
Sean Callanand151c8a2011-03-09 01:02:51 +0000485 case llvm::Triple::arm:
Greg Clayton889fbd02011-03-26 19:14:58 +0000486 case llvm::Triple::thumb:
Sean Callanand151c8a2011-03-09 01:02:51 +0000487 return kEDAssemblySyntaxARMUAL;
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000488 default:
489 break;
490 }
Greg Claytoncf015052010-06-11 03:25:34 +0000491 return (EDAssemblySyntax_t)0; // default
Chris Lattner24943d22010-06-08 16:52:24 +0000492}
493
494Disassembler *
495DisassemblerLLVM::CreateInstance(const ArchSpec &arch)
496{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000497 std::auto_ptr<DisassemblerLLVM> disasm_ap (new DisassemblerLLVM(arch));
498
Caroline Tice080bf612011-04-05 18:46:00 +0000499 if (disasm_ap.get() && disasm_ap->IsValid())
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000500 return disasm_ap.release();
Chris Lattner24943d22010-06-08 16:52:24 +0000501
Greg Claytoncf015052010-06-11 03:25:34 +0000502 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000503}
504
505DisassemblerLLVM::DisassemblerLLVM(const ArchSpec &arch) :
Greg Claytonb01000f2011-01-17 03:46:26 +0000506 Disassembler (arch),
Greg Claytonb1888f22011-03-19 01:12:21 +0000507 m_disassembler (NULL),
508 m_disassembler_thumb (NULL) // For ARM only
Chris Lattner24943d22010-06-08 16:52:24 +0000509{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000510 const std::string &arch_triple = arch.GetTriple().str();
511 if (!arch_triple.empty())
Greg Claytoncf015052010-06-11 03:25:34 +0000512 {
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000513 if (EDGetDisassembler(&m_disassembler, arch_triple.c_str(), SyntaxForArchSpec (arch)))
514 m_disassembler = NULL;
Greg Claytonb1888f22011-03-19 01:12:21 +0000515 llvm::Triple::ArchType llvm_arch = arch.GetTriple().getArch();
Greg Clayton889fbd02011-03-26 19:14:58 +0000516 // Don't have the lldb::Triple::thumb architecture here. If someone specifies
517 // "thumb" as the architecture, we want a thumb only disassembler. But if any
518 // architecture starting with "arm" if specified, we want to auto detect the
519 // arm/thumb code automatically using the AddressClass from section offset
520 // addresses.
Greg Claytonb1888f22011-03-19 01:12:21 +0000521 if (llvm_arch == llvm::Triple::arm)
522 {
523 if (EDGetDisassembler(&m_disassembler_thumb, "thumb-apple-darwin", kEDAssemblySyntaxARMUAL))
524 m_disassembler_thumb = NULL;
525 }
Greg Claytoncf015052010-06-11 03:25:34 +0000526 }
Chris Lattner24943d22010-06-08 16:52:24 +0000527}
528
529DisassemblerLLVM::~DisassemblerLLVM()
530{
531}
532
533size_t
Greg Clayton70436352010-06-30 23:03:03 +0000534DisassemblerLLVM::DecodeInstructions
Chris Lattner24943d22010-06-08 16:52:24 +0000535(
Greg Clayton5c4c7462010-10-06 03:09:58 +0000536 const Address &base_addr,
Chris Lattner24943d22010-06-08 16:52:24 +0000537 const DataExtractor& data,
538 uint32_t data_offset,
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000539 uint32_t num_instructions,
540 bool append
Chris Lattner24943d22010-06-08 16:52:24 +0000541)
542{
Greg Claytonb01000f2011-01-17 03:46:26 +0000543 if (m_disassembler == NULL)
544 return 0;
545
Chris Lattner24943d22010-06-08 16:52:24 +0000546 size_t total_inst_byte_size = 0;
547
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000548 if (!append)
549 m_instruction_list.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000550
551 while (data.ValidOffset(data_offset) && num_instructions)
552 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000553 Address inst_addr (base_addr);
554 inst_addr.Slide(data_offset);
Greg Claytonb1888f22011-03-19 01:12:21 +0000555
556 bool use_thumb = false;
557 // If we have a thumb disassembler, then we have an ARM architecture
558 // so we need to check what the instruction address class is to make
559 // sure we shouldn't be disassembling as thumb...
Greg Clayton889fbd02011-03-26 19:14:58 +0000560 AddressClass inst_address_class = eAddressClassInvalid;
Greg Claytonb1888f22011-03-19 01:12:21 +0000561 if (m_disassembler_thumb)
562 {
Greg Clayton889fbd02011-03-26 19:14:58 +0000563 inst_address_class = inst_addr.GetAddressClass ();
564 if (inst_address_class == eAddressClassCodeAlternateISA)
Greg Claytonb1888f22011-03-19 01:12:21 +0000565 use_thumb = true;
566 }
Johnny Chen80ab18e2011-05-12 22:25:53 +0000567
Greg Clayton7bc39082011-03-24 23:53:38 +0000568 InstructionSP inst_sp (new InstructionLLVM (inst_addr,
Greg Clayton889fbd02011-03-26 19:14:58 +0000569 inst_address_class,
Greg Claytonabe0fed2011-04-18 08:33:37 +0000570 use_thumb ? m_disassembler_thumb : m_disassembler,
Johnny Chen1608c872011-05-18 18:22:16 +0000571 use_thumb ? llvm::Triple::thumb : m_arch.GetMachine()));
Chris Lattner24943d22010-06-08 16:52:24 +0000572
Greg Clayton889fbd02011-03-26 19:14:58 +0000573 size_t inst_byte_size = inst_sp->Decode (*this, data, data_offset);
Chris Lattner24943d22010-06-08 16:52:24 +0000574
575 if (inst_byte_size == 0)
576 break;
577
Greg Clayton5c4c7462010-10-06 03:09:58 +0000578 m_instruction_list.Append (inst_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000579
580 total_inst_byte_size += inst_byte_size;
581 data_offset += inst_byte_size;
582 num_instructions--;
583 }
584
585 return total_inst_byte_size;
586}
587
588void
589DisassemblerLLVM::Initialize()
590{
591 PluginManager::RegisterPlugin (GetPluginNameStatic(),
592 GetPluginDescriptionStatic(),
593 CreateInstance);
594}
595
596void
597DisassemblerLLVM::Terminate()
598{
599 PluginManager::UnregisterPlugin (CreateInstance);
600}
601
602
603const char *
604DisassemblerLLVM::GetPluginNameStatic()
605{
Greg Clayton149731c2011-03-25 18:03:16 +0000606 return "llvm";
Chris Lattner24943d22010-06-08 16:52:24 +0000607}
608
609const char *
610DisassemblerLLVM::GetPluginDescriptionStatic()
611{
Greg Clayton149731c2011-03-25 18:03:16 +0000612 return "Disassembler that uses LLVM opcode tables to disassemble i386, x86_64 and ARM.";
Chris Lattner24943d22010-06-08 16:52:24 +0000613}
614
615//------------------------------------------------------------------
616// PluginInterface protocol
617//------------------------------------------------------------------
618const char *
619DisassemblerLLVM::GetPluginName()
620{
621 return "DisassemblerLLVM";
622}
623
624const char *
625DisassemblerLLVM::GetShortPluginName()
626{
627 return GetPluginNameStatic();
628}
629
630uint32_t
631DisassemblerLLVM::GetPluginVersion()
632{
633 return 1;
634}
635