blob: a8c423f44e6f506488f577fab956cf0a73bd6a74 [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;
Greg Clayton567e7f32011-09-22 04:58:26 +0000106 Target *target = NULL;
107 if (exe_ctx)
108 target = exe_ctx->GetTargetPtr();
109 if (target && !target->GetSectionLoadList().IsEmpty())
Johnny Chend254eb92011-05-23 23:29:23 +0000110 {
Greg Clayton567e7f32011-09-22 04:58:26 +0000111 if (target->GetSectionLoadList().ResolveLoadAddress(operand_value, so_addr))
Johnny Chend254eb92011-05-23 23:29:23 +0000112 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
113 }
114 else
115 {
116 Module *module = inst_addr.GetModule();
117 if (module)
118 {
119 if (module->ResolveFileAddress(operand_value, so_addr))
120 so_addr.Dump(&comment, exe_scope, Address::DumpStyleResolvedDescriptionNoModule, Address::DumpStyleSectionNameOffset);
121 }
122 }
123}
Chris Lattner24943d22010-06-08 16:52:24 +0000124
Johnny Chen51ff2482011-05-19 01:05:37 +0000125#include "llvm/ADT/StringRef.h"
Johnny Chend254eb92011-05-23 23:29:23 +0000126static inline void StripSpaces(llvm::StringRef &Str)
Johnny Chen51ff2482011-05-19 01:05:37 +0000127{
128 while (!Str.empty() && isspace(Str[0]))
129 Str = Str.substr(1);
130 while (!Str.empty() && isspace(Str.back()))
131 Str = Str.substr(0, Str.size()-1);
132}
Johnny Chend254eb92011-05-23 23:29:23 +0000133static inline void RStrip(llvm::StringRef &Str, char c)
134{
135 if (!Str.empty() && Str.back() == c)
136 Str = Str.substr(0, Str.size()-1);
137}
Johnny Chen3930cbe2011-05-24 20:36:40 +0000138// Aligns the raw disassembly (passed as 'str') with the rest of edis'ed disassembly output.
139// 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 +0000140static void
Johnny Chend17f8012011-05-23 18:00:40 +0000141Align(Stream *s, const char *str, size_t opcodeColWidth, size_t operandColWidth)
Johnny Chen84d42e82011-05-21 00:55:57 +0000142{
143 llvm::StringRef raw_disasm(str);
144 StripSpaces(raw_disasm);
Johnny Chend17f8012011-05-23 18:00:40 +0000145 // Split the raw disassembly into opcode and operands.
146 std::pair<llvm::StringRef, llvm::StringRef> p = raw_disasm.split('\t');
147 PadString(s, p.first, opcodeColWidth);
148 if (!p.second.empty())
149 PadString(s, p.second, operandColWidth);
Johnny Chen84d42e82011-05-21 00:55:57 +0000150}
Johnny Chen51ff2482011-05-19 01:05:37 +0000151
Johnny Chen66786762011-08-03 04:50:37 +0000152#define AlignPC(pc_val) (pc_val & 0xFFFFFFFC)
Chris Lattner24943d22010-06-08 16:52:24 +0000153void
Caroline Ticeaf591802011-04-05 23:22:54 +0000154InstructionLLVM::Dump
Chris Lattner24943d22010-06-08 16:52:24 +0000155(
156 Stream *s,
Greg Clayton889fbd02011-03-26 19:14:58 +0000157 uint32_t max_opcode_byte_size,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000158 bool show_address,
Greg Clayton149731c2011-03-25 18:03:16 +0000159 bool show_bytes,
Greg Clayton5c4c7462010-10-06 03:09:58 +0000160 const lldb_private::ExecutionContext* exe_ctx,
Chris Lattner24943d22010-06-08 16:52:24 +0000161 bool raw
162)
163{
164 const size_t opcodeColumnWidth = 7;
165 const size_t operandColumnWidth = 25;
166
Greg Clayton5c4c7462010-10-06 03:09:58 +0000167 ExecutionContextScope *exe_scope = NULL;
168 if (exe_ctx)
169 exe_scope = exe_ctx->GetBestExecutionContextScope();
170
Chris Lattner24943d22010-06-08 16:52:24 +0000171 // If we have an address, print it out
Sean Callanan91557b02010-11-10 01:38:28 +0000172 if (GetAddress().IsValid() && show_address)
Greg Clayton70436352010-06-30 23:03:03 +0000173 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000174 if (GetAddress().Dump (s,
175 exe_scope,
176 Address::DumpStyleLoadAddress,
177 Address::DumpStyleModuleWithFileAddress,
178 0))
Greg Clayton70436352010-06-30 23:03:03 +0000179 s->PutCString(": ");
180 }
Chris Lattner24943d22010-06-08 16:52:24 +0000181
182 // If we are supposed to show bytes, "bytes" will be non-NULL.
Greg Clayton149731c2011-03-25 18:03:16 +0000183 if (show_bytes)
Chris Lattner24943d22010-06-08 16:52:24 +0000184 {
Greg Clayton149731c2011-03-25 18:03:16 +0000185 if (m_opcode.GetType() == Opcode::eTypeBytes)
Chris Lattner24943d22010-06-08 16:52:24 +0000186 {
Greg Clayton149731c2011-03-25 18:03:16 +0000187 // x86_64 and i386 are the only ones that use bytes right now so
188 // pad out the byte dump to be able to always show 15 bytes (3 chars each)
189 // plus a space
Greg Clayton889fbd02011-03-26 19:14:58 +0000190 if (max_opcode_byte_size > 0)
191 m_opcode.Dump (s, max_opcode_byte_size * 3 + 1);
192 else
193 m_opcode.Dump (s, 15 * 3 + 1);
Greg Clayton149731c2011-03-25 18:03:16 +0000194 }
195 else
196 {
197 // Else, we have ARM which can show up to a uint32_t 0x00000000 (10 spaces)
198 // plus two for padding...
Greg Clayton889fbd02011-03-26 19:14:58 +0000199 if (max_opcode_byte_size > 0)
200 m_opcode.Dump (s, max_opcode_byte_size * 3 + 1);
201 else
202 m_opcode.Dump (s, 12);
Chris Lattner24943d22010-06-08 16:52:24 +0000203 }
204 }
205
Greg Claytonf15996e2011-04-07 22:46:35 +0000206 int numTokens = -1;
207
Johnny Chen80ab18e2011-05-12 22:25:53 +0000208 // FIXME!!!
209 /* Remove the following section of code related to force_raw .... */
Johnny Chend17f8012011-05-23 18:00:40 +0000210 /*
Johnny Chen80ab18e2011-05-12 22:25:53 +0000211 bool force_raw = m_arch_type == llvm::Triple::arm ||
212 m_arch_type == llvm::Triple::thumb;
Greg Claytonf15996e2011-04-07 22:46:35 +0000213 if (!raw)
Johnny Chen80ab18e2011-05-12 22:25:53 +0000214 raw = force_raw;
Johnny Chend17f8012011-05-23 18:00:40 +0000215 */
Johnny Chen80ab18e2011-05-12 22:25:53 +0000216 /* .... when we fix the edis for arm/thumb. */
Greg Claytonabe0fed2011-04-18 08:33:37 +0000217
Johnny Chen611b7e92011-08-19 17:31:59 +0000218 if (!raw)
Greg Claytonf15996e2011-04-07 22:46:35 +0000219 numTokens = EDNumTokens(m_inst);
Chris Lattner24943d22010-06-08 16:52:24 +0000220
221 int currentOpIndex = -1;
222
Greg Claytonf15996e2011-04-07 22:46:35 +0000223 bool printTokenized = false;
224
225 if (numTokens != -1 && !raw)
Sean Callanan8541f2f2010-07-23 02:19:15 +0000226 {
227 addr_t base_addr = LLDB_INVALID_ADDRESS;
Greg Claytonf15996e2011-04-07 22:46:35 +0000228
Greg Clayton567e7f32011-09-22 04:58:26 +0000229 Target *target = NULL;
230 if (exe_ctx)
231 target = exe_ctx->GetTargetPtr();
232 if (target && !target->GetSectionLoadList().IsEmpty())
233 base_addr = GetAddress().GetLoadAddress (target);
Sean Callanan8541f2f2010-07-23 02:19:15 +0000234 if (base_addr == LLDB_INVALID_ADDRESS)
Greg Clayton5c4c7462010-10-06 03:09:58 +0000235 base_addr = GetAddress().GetFileAddress ();
Greg Claytonf15996e2011-04-07 22:46:35 +0000236
Johnny Chen80ab18e2011-05-12 22:25:53 +0000237 lldb::addr_t PC = base_addr + EDInstByteSize(m_inst);
238
239 // When executing an ARM instruction, PC reads as the address of the
240 // current instruction plus 8. And for Thumb, it is plus 4.
241 if (m_arch_type == llvm::Triple::arm)
242 PC = base_addr + 8;
243 else if (m_arch_type == llvm::Triple::thumb)
244 PC = base_addr + 4;
245
246 RegisterReaderArg rra(PC, m_disassembler);
Johnny Chenc5272bf2011-05-12 18:48:11 +0000247
Chris Lattner24943d22010-06-08 16:52:24 +0000248 printTokenized = true;
249
250 // Handle the opcode column.
251
252 StreamString opcode;
253
254 int tokenIndex = 0;
255
256 EDTokenRef token;
257 const char *tokenStr;
258
Johnny Chenff8fea62011-05-18 22:48:41 +0000259 if (EDGetToken(&token, m_inst, tokenIndex)) // 0 on success
260 printTokenized = false;
261 else if (!EDTokenIsOpcode(token))
262 printTokenized = false;
263 else if (EDGetTokenString(&tokenStr, token)) // 0 on success
Chris Lattner24943d22010-06-08 16:52:24 +0000264 printTokenized = false;
265
Johnny Chenff8fea62011-05-18 22:48:41 +0000266 if (printTokenized)
Chris Lattner24943d22010-06-08 16:52:24 +0000267 {
Johnny Chenff8fea62011-05-18 22:48:41 +0000268 // Put the token string into our opcode string
269 opcode.PutCString(tokenStr);
Chris Lattner24943d22010-06-08 16:52:24 +0000270
Johnny Chenff8fea62011-05-18 22:48:41 +0000271 // If anything follows, it probably starts with some whitespace. Skip it.
272 if (++tokenIndex < numTokens)
273 {
274 if (EDGetToken(&token, m_inst, tokenIndex)) // 0 on success
275 printTokenized = false;
276 else if (!EDTokenIsWhitespace(token))
277 printTokenized = false;
278 }
279
280 ++tokenIndex;
Chris Lattner24943d22010-06-08 16:52:24 +0000281 }
282
Chris Lattner24943d22010-06-08 16:52:24 +0000283 // Handle the operands and the comment.
Chris Lattner24943d22010-06-08 16:52:24 +0000284 StreamString operands;
285 StreamString comment;
286
287 if (printTokenized)
288 {
Johnny Chen51ff2482011-05-19 01:05:37 +0000289 bool show_token = false;
Chris Lattner24943d22010-06-08 16:52:24 +0000290
291 for (; tokenIndex < numTokens; ++tokenIndex)
292 {
293 if (EDGetToken(&token, m_inst, tokenIndex))
294 return;
295
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000296 int operandIndex = EDOperandIndexForToken(token);
Chris Lattner24943d22010-06-08 16:52:24 +0000297
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000298 if (operandIndex >= 0)
299 {
300 if (operandIndex != currentOpIndex)
Chris Lattner24943d22010-06-08 16:52:24 +0000301 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000302 show_token = true;
303
304 currentOpIndex = operandIndex;
305 EDOperandRef operand;
306
307 if (!EDGetOperand(&operand, m_inst, currentOpIndex))
Chris Lattner24943d22010-06-08 16:52:24 +0000308 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000309 if (EDOperandIsMemory(operand))
Chris Lattner24943d22010-06-08 16:52:24 +0000310 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000311 uint64_t operand_value;
312
313 if (!EDEvaluateOperand(&operand_value, operand, IPRegisterReader, &rra))
Chris Lattner24943d22010-06-08 16:52:24 +0000314 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000315 if (EDInstIsBranch(m_inst))
Chris Lattner24943d22010-06-08 16:52:24 +0000316 {
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000317 operands.Printf("0x%llx ", operand_value);
318 show_token = false;
319 }
320 else
321 {
322 // Put the address value into the comment
323 comment.Printf("0x%llx ", operand_value);
324 }
Chris Lattner24943d22010-06-08 16:52:24 +0000325
Johnny Chend254eb92011-05-23 23:29:23 +0000326 AddSymbolicInfo(exe_ctx, exe_scope, comment, operand_value, GetAddress());
Johnny Chen6d61ebf2011-05-18 22:08:52 +0000327 } // EDEvaluateOperand
328 } // EDOperandIsMemory
329 } // EDGetOperand
330 } // operandIndex != currentOpIndex
331 } // operandIndex >= 0
Chris Lattner24943d22010-06-08 16:52:24 +0000332
333 if (show_token)
334 {
Enrico Granata4c3fb4b2011-07-19 18:03:25 +0000335 if (EDGetTokenString(&tokenStr, token))
Chris Lattner24943d22010-06-08 16:52:24 +0000336 {
337 printTokenized = false;
338 break;
339 }
340
341 operands.PutCString(tokenStr);
342 }
343 } // for (tokenIndex)
344
Johnny Chende5cc8c2011-05-20 17:27:37 +0000345 // FIXME!!!
346 // Workaround for llvm::tB's operands not properly parsed by ARMAsmParser.
347 if (m_arch_type == llvm::Triple::thumb && opcode.GetString() == "b") {
348 const char *inst_str;
Peter Collingbourned77c0392011-05-20 22:42:59 +0000349 const char *pos = NULL;
Johnny Chenc298a982011-05-23 19:41:31 +0000350 operands.Clear(); comment.Clear();
Johnny Chende5cc8c2011-05-20 17:27:37 +0000351 if (EDGetInstString(&inst_str, m_inst) == 0 && (pos = strstr(inst_str, "#")) != NULL) {
352 uint64_t operand_value = PC + atoi(++pos);
Johnny Chend254eb92011-05-23 23:29:23 +0000353 // Put the address value into the operands.
Johnny Chende5cc8c2011-05-20 17:27:37 +0000354 operands.Printf("0x%llx ", operand_value);
Johnny Chend254eb92011-05-23 23:29:23 +0000355 AddSymbolicInfo(exe_ctx, exe_scope, comment, operand_value, GetAddress());
Johnny Chende5cc8c2011-05-20 17:27:37 +0000356 }
357 }
Johnny Chenc298a982011-05-23 19:41:31 +0000358 // Yet more workaround for "bl #..." and "blx #...".
359 if ((m_arch_type == llvm::Triple::arm || m_arch_type == llvm::Triple::thumb) &&
360 (opcode.GetString() == "bl" || opcode.GetString() == "blx")) {
361 const char *inst_str;
362 const char *pos = NULL;
363 operands.Clear(); comment.Clear();
364 if (EDGetInstString(&inst_str, m_inst) == 0 && (pos = strstr(inst_str, "#")) != NULL) {
Johnny Chen66786762011-08-03 04:50:37 +0000365 if (m_arch_type == llvm::Triple::thumb && opcode.GetString() == "blx") {
366 // A8.6.23 BLX (immediate)
367 // Target Address = Align(PC,4) + offset value
368 PC = AlignPC(PC);
369 }
Johnny Chenc298a982011-05-23 19:41:31 +0000370 uint64_t operand_value = PC + atoi(++pos);
Johnny Chend254eb92011-05-23 23:29:23 +0000371 // Put the address value into the comment.
Johnny Chenc298a982011-05-23 19:41:31 +0000372 comment.Printf("0x%llx ", operand_value);
Johnny Chend254eb92011-05-23 23:29:23 +0000373 // And the original token string into the operands.
374 llvm::StringRef Str(pos - 1);
375 RStrip(Str, '\n');
376 operands.PutCString(Str.str().c_str());
377 AddSymbolicInfo(exe_ctx, exe_scope, comment, operand_value, GetAddress());
Johnny Chenc298a982011-05-23 19:41:31 +0000378 }
379 }
Johnny Chende5cc8c2011-05-20 17:27:37 +0000380 // END of workaround.
381
Johnny Chen51ff2482011-05-19 01:05:37 +0000382 // If both operands and comment are empty, we will just print out
383 // the raw disassembly.
384 if (operands.GetString().empty() && comment.GetString().empty())
Chris Lattner24943d22010-06-08 16:52:24 +0000385 {
Johnny Chen51ff2482011-05-19 01:05:37 +0000386 const char *str;
387
388 if (EDGetInstString(&str, m_inst))
389 return;
Johnny Chend17f8012011-05-23 18:00:40 +0000390 Align(s, str, opcodeColumnWidth, operandColumnWidth);
Johnny Chen51ff2482011-05-19 01:05:37 +0000391 }
392 else
393 {
394 PadString(s, opcode.GetString(), opcodeColumnWidth);
395
396 if (comment.GetString().empty())
397 s->PutCString(operands.GetString().c_str());
Chris Lattner24943d22010-06-08 16:52:24 +0000398 else
399 {
Johnny Chen51ff2482011-05-19 01:05:37 +0000400 PadString(s, operands.GetString(), operandColumnWidth);
Chris Lattner24943d22010-06-08 16:52:24 +0000401
Johnny Chen51ff2482011-05-19 01:05:37 +0000402 s->PutCString("; ");
403 s->PutCString(comment.GetString().c_str());
404 } // else (comment.GetString().empty())
405 } // else (operands.GetString().empty() && comment.GetString().empty())
406 } // printTokenized
Chris Lattner24943d22010-06-08 16:52:24 +0000407 } // numTokens != -1
408
409 if (!printTokenized)
410 {
411 const char *str;
412
Johnny Chen51ff2482011-05-19 01:05:37 +0000413 if (EDGetInstString(&str, m_inst)) // 0 on success
Chris Lattner24943d22010-06-08 16:52:24 +0000414 return;
Johnny Chen08251ef2011-05-21 00:44:42 +0000415 if (raw)
416 s->Write(str, strlen(str) - 1);
417 else
418 {
419 // EDis fails to parse the tokens of this inst. Need to align this
Johnny Chen84d42e82011-05-21 00:55:57 +0000420 // raw disassembly's opcode with the rest of output.
Johnny Chend17f8012011-05-23 18:00:40 +0000421 Align(s, str, opcodeColumnWidth, operandColumnWidth);
Johnny Chen08251ef2011-05-21 00:44:42 +0000422 }
Chris Lattner24943d22010-06-08 16:52:24 +0000423 }
424}
425
426bool
Caroline Ticeaf591802011-04-05 23:22:54 +0000427InstructionLLVM::DoesBranch() const
Chris Lattner24943d22010-06-08 16:52:24 +0000428{
429 return EDInstIsBranch(m_inst);
430}
431
432size_t
Caroline Ticeaf591802011-04-05 23:22:54 +0000433InstructionLLVM::Decode (const Disassembler &disassembler,
434 const lldb_private::DataExtractor &data,
435 uint32_t data_offset)
Chris Lattner24943d22010-06-08 16:52:24 +0000436{
437 if (EDCreateInsts(&m_inst, 1, m_disassembler, DataExtractorByteReader, data_offset, (void*)(&data)))
Greg Clayton7bc39082011-03-24 23:53:38 +0000438 {
439 const int byte_size = EDInstByteSize(m_inst);
440 uint32_t offset = data_offset;
441 // Make a copy of the opcode in m_opcode
442 switch (disassembler.GetArchitecture().GetMachine())
443 {
444 case llvm::Triple::x86:
445 case llvm::Triple::x86_64:
446 m_opcode.SetOpcodeBytes (data.PeekData (data_offset, byte_size), byte_size);
447 break;
448
449 case llvm::Triple::arm:
Greg Clayton7bc39082011-03-24 23:53:38 +0000450 case llvm::Triple::thumb:
Greg Clayton149731c2011-03-25 18:03:16 +0000451 switch (byte_size)
452 {
453 case 2:
454 m_opcode.SetOpcode16 (data.GetU16 (&offset));
455 break;
456
457 case 4:
Caroline Tice6b8d3b52011-04-19 23:30:03 +0000458 {
459 if (GetAddressClass() == eAddressClassCodeAlternateISA)
460 {
461 // If it is a 32-bit THUMB instruction, we need to swap the upper & lower halves.
462 uint32_t orig_bytes = data.GetU32 (&offset);
463 uint16_t upper_bits = (orig_bytes >> 16) & ((1u << 16) - 1);
464 uint16_t lower_bits = orig_bytes & ((1u << 16) - 1);
465 uint32_t swapped = (lower_bits << 16) | upper_bits;
466 m_opcode.SetOpcode32 (swapped);
467 }
468 else
469 m_opcode.SetOpcode32 (data.GetU32 (&offset));
470 }
Greg Clayton149731c2011-03-25 18:03:16 +0000471 break;
472
473 default:
474 assert (!"Invalid ARM opcode size");
475 break;
476 }
Greg Clayton7bc39082011-03-24 23:53:38 +0000477 break;
478
479 default:
480 assert (!"This shouldn't happen since we control the architecture we allow DisassemblerLLVM to be created for");
481 break;
482 }
483 return byte_size;
484 }
Chris Lattner24943d22010-06-08 16:52:24 +0000485 else
486 return 0;
487}
488
Chris Lattner24943d22010-06-08 16:52:24 +0000489static inline EDAssemblySyntax_t
Greg Claytoncf015052010-06-11 03:25:34 +0000490SyntaxForArchSpec (const ArchSpec &arch)
Chris Lattner24943d22010-06-08 16:52:24 +0000491{
Greg Clayton940b1032011-02-23 00:35:02 +0000492 switch (arch.GetMachine ())
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000493 {
Greg Clayton940b1032011-02-23 00:35:02 +0000494 case llvm::Triple::x86:
495 case llvm::Triple::x86_64:
Chris Lattner24943d22010-06-08 16:52:24 +0000496 return kEDAssemblySyntaxX86ATT;
Sean Callanand151c8a2011-03-09 01:02:51 +0000497 case llvm::Triple::arm:
Greg Clayton889fbd02011-03-26 19:14:58 +0000498 case llvm::Triple::thumb:
Sean Callanand151c8a2011-03-09 01:02:51 +0000499 return kEDAssemblySyntaxARMUAL;
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000500 default:
501 break;
502 }
Greg Claytoncf015052010-06-11 03:25:34 +0000503 return (EDAssemblySyntax_t)0; // default
Chris Lattner24943d22010-06-08 16:52:24 +0000504}
505
506Disassembler *
507DisassemblerLLVM::CreateInstance(const ArchSpec &arch)
508{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000509 std::auto_ptr<DisassemblerLLVM> disasm_ap (new DisassemblerLLVM(arch));
510
Caroline Tice080bf612011-04-05 18:46:00 +0000511 if (disasm_ap.get() && disasm_ap->IsValid())
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000512 return disasm_ap.release();
Chris Lattner24943d22010-06-08 16:52:24 +0000513
Greg Claytoncf015052010-06-11 03:25:34 +0000514 return NULL;
Chris Lattner24943d22010-06-08 16:52:24 +0000515}
516
517DisassemblerLLVM::DisassemblerLLVM(const ArchSpec &arch) :
Greg Claytonb01000f2011-01-17 03:46:26 +0000518 Disassembler (arch),
Greg Claytonb1888f22011-03-19 01:12:21 +0000519 m_disassembler (NULL),
520 m_disassembler_thumb (NULL) // For ARM only
Chris Lattner24943d22010-06-08 16:52:24 +0000521{
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000522 const std::string &arch_triple = arch.GetTriple().str();
523 if (!arch_triple.empty())
Greg Claytoncf015052010-06-11 03:25:34 +0000524 {
Greg Clayton5e4f4a22011-02-16 00:00:43 +0000525 if (EDGetDisassembler(&m_disassembler, arch_triple.c_str(), SyntaxForArchSpec (arch)))
526 m_disassembler = NULL;
Greg Claytonb1888f22011-03-19 01:12:21 +0000527 llvm::Triple::ArchType llvm_arch = arch.GetTriple().getArch();
Greg Clayton889fbd02011-03-26 19:14:58 +0000528 // Don't have the lldb::Triple::thumb architecture here. If someone specifies
529 // "thumb" as the architecture, we want a thumb only disassembler. But if any
530 // architecture starting with "arm" if specified, we want to auto detect the
531 // arm/thumb code automatically using the AddressClass from section offset
532 // addresses.
Greg Claytonb1888f22011-03-19 01:12:21 +0000533 if (llvm_arch == llvm::Triple::arm)
534 {
535 if (EDGetDisassembler(&m_disassembler_thumb, "thumb-apple-darwin", kEDAssemblySyntaxARMUAL))
536 m_disassembler_thumb = NULL;
537 }
Greg Claytoncf015052010-06-11 03:25:34 +0000538 }
Chris Lattner24943d22010-06-08 16:52:24 +0000539}
540
541DisassemblerLLVM::~DisassemblerLLVM()
542{
543}
544
545size_t
Greg Clayton70436352010-06-30 23:03:03 +0000546DisassemblerLLVM::DecodeInstructions
Chris Lattner24943d22010-06-08 16:52:24 +0000547(
Greg Clayton5c4c7462010-10-06 03:09:58 +0000548 const Address &base_addr,
Chris Lattner24943d22010-06-08 16:52:24 +0000549 const DataExtractor& data,
550 uint32_t data_offset,
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000551 uint32_t num_instructions,
552 bool append
Chris Lattner24943d22010-06-08 16:52:24 +0000553)
554{
Greg Claytonb01000f2011-01-17 03:46:26 +0000555 if (m_disassembler == NULL)
556 return 0;
557
Chris Lattner24943d22010-06-08 16:52:24 +0000558 size_t total_inst_byte_size = 0;
559
Jim Inghamaa3e3e12011-03-22 01:48:42 +0000560 if (!append)
561 m_instruction_list.Clear();
Chris Lattner24943d22010-06-08 16:52:24 +0000562
563 while (data.ValidOffset(data_offset) && num_instructions)
564 {
Greg Clayton5c4c7462010-10-06 03:09:58 +0000565 Address inst_addr (base_addr);
566 inst_addr.Slide(data_offset);
Greg Claytonb1888f22011-03-19 01:12:21 +0000567
568 bool use_thumb = false;
569 // If we have a thumb disassembler, then we have an ARM architecture
570 // so we need to check what the instruction address class is to make
571 // sure we shouldn't be disassembling as thumb...
Greg Clayton889fbd02011-03-26 19:14:58 +0000572 AddressClass inst_address_class = eAddressClassInvalid;
Greg Claytonb1888f22011-03-19 01:12:21 +0000573 if (m_disassembler_thumb)
574 {
Greg Clayton889fbd02011-03-26 19:14:58 +0000575 inst_address_class = inst_addr.GetAddressClass ();
576 if (inst_address_class == eAddressClassCodeAlternateISA)
Greg Claytonb1888f22011-03-19 01:12:21 +0000577 use_thumb = true;
578 }
Johnny Chen80ab18e2011-05-12 22:25:53 +0000579
Greg Clayton7bc39082011-03-24 23:53:38 +0000580 InstructionSP inst_sp (new InstructionLLVM (inst_addr,
Greg Clayton889fbd02011-03-26 19:14:58 +0000581 inst_address_class,
Greg Claytonabe0fed2011-04-18 08:33:37 +0000582 use_thumb ? m_disassembler_thumb : m_disassembler,
Johnny Chen1608c872011-05-18 18:22:16 +0000583 use_thumb ? llvm::Triple::thumb : m_arch.GetMachine()));
Chris Lattner24943d22010-06-08 16:52:24 +0000584
Greg Clayton889fbd02011-03-26 19:14:58 +0000585 size_t inst_byte_size = inst_sp->Decode (*this, data, data_offset);
Chris Lattner24943d22010-06-08 16:52:24 +0000586
587 if (inst_byte_size == 0)
588 break;
589
Greg Clayton5c4c7462010-10-06 03:09:58 +0000590 m_instruction_list.Append (inst_sp);
Chris Lattner24943d22010-06-08 16:52:24 +0000591
592 total_inst_byte_size += inst_byte_size;
593 data_offset += inst_byte_size;
594 num_instructions--;
595 }
596
597 return total_inst_byte_size;
598}
599
600void
601DisassemblerLLVM::Initialize()
602{
603 PluginManager::RegisterPlugin (GetPluginNameStatic(),
604 GetPluginDescriptionStatic(),
605 CreateInstance);
606}
607
608void
609DisassemblerLLVM::Terminate()
610{
611 PluginManager::UnregisterPlugin (CreateInstance);
612}
613
614
615const char *
616DisassemblerLLVM::GetPluginNameStatic()
617{
Greg Clayton149731c2011-03-25 18:03:16 +0000618 return "llvm";
Chris Lattner24943d22010-06-08 16:52:24 +0000619}
620
621const char *
622DisassemblerLLVM::GetPluginDescriptionStatic()
623{
Greg Clayton149731c2011-03-25 18:03:16 +0000624 return "Disassembler that uses LLVM opcode tables to disassemble i386, x86_64 and ARM.";
Chris Lattner24943d22010-06-08 16:52:24 +0000625}
626
627//------------------------------------------------------------------
628// PluginInterface protocol
629//------------------------------------------------------------------
630const char *
631DisassemblerLLVM::GetPluginName()
632{
633 return "DisassemblerLLVM";
634}
635
636const char *
637DisassemblerLLVM::GetShortPluginName()
638{
639 return GetPluginNameStatic();
640}
641
642uint32_t
643DisassemblerLLVM::GetPluginVersion()
644{
645 return 1;
646}
647