blob: f4192b18f4af4fcfb58fe78d987ddc7ce6646c97 [file] [log] [blame]
Sean Callanan95e5c632012-02-17 00:53:45 +00001//===-- DisassemblerLLVMC.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 "DisassemblerLLVMC.h"
11
12#include "llvm-c/Disassembler.h"
Jim Ingham0f063ba2013-03-02 00:26:47 +000013#include "llvm/MC/MCAsmInfo.h"
14#include "llvm/MC/MCContext.h"
15#include "llvm/MC/MCDisassembler.h"
16#include "llvm/MC/MCInst.h"
17#include "llvm/MC/MCInstPrinter.h"
18#include "llvm/MC/MCInstrInfo.h"
19#include "llvm/MC/MCRegisterInfo.h"
20#include "llvm/MC/MCSubtargetInfo.h"
21#include "llvm/Support/ErrorHandling.h"
22#include "llvm/Support/MemoryObject.h"
23#include "llvm/Support/TargetRegistry.h"
Sean Callanan95e5c632012-02-17 00:53:45 +000024#include "llvm/Support/TargetSelect.h"
Jim Ingham0f063ba2013-03-02 00:26:47 +000025#include "llvm/ADT/SmallString.h"
26
Sean Callanan95e5c632012-02-17 00:53:45 +000027
28#include "lldb/Core/Address.h"
29#include "lldb/Core/DataExtractor.h"
Greg Clayton1f746072012-08-29 21:13:06 +000030#include "lldb/Core/Module.h"
Sean Callanan95e5c632012-02-17 00:53:45 +000031#include "lldb/Core/Stream.h"
32#include "lldb/Symbol/SymbolContext.h"
33#include "lldb/Target/ExecutionContext.h"
34#include "lldb/Target/Process.h"
35#include "lldb/Target/RegisterContext.h"
36#include "lldb/Target/Target.h"
37#include "lldb/Target/StackFrame.h"
38
39#include <regex.h>
40
41using namespace lldb;
42using namespace lldb_private;
43
44class InstructionLLVMC : public lldb_private::Instruction
45{
46public:
47 InstructionLLVMC (DisassemblerLLVMC &disasm,
48 const lldb_private::Address &address,
Greg Claytonc8e0c242012-04-13 00:07:34 +000049 AddressClass addr_class) :
Sean Callanan95e5c632012-02-17 00:53:45 +000050 Instruction(address, addr_class),
Sean Callanan95e5c632012-02-17 00:53:45 +000051 m_is_valid(false),
Bill Wendlinge6eeef02012-04-06 00:09:59 +000052 m_disasm(disasm),
Sean Callanan7e6d4e52012-08-01 18:50:59 +000053 m_disasm_sp(disasm.shared_from_this()),
Sean Callanan7725a462012-03-02 23:22:53 +000054 m_does_branch(eLazyBoolCalculate)
Sean Callanan95e5c632012-02-17 00:53:45 +000055 {
56 }
57
58 virtual
59 ~InstructionLLVMC ()
60 {
61 }
62
63 static void
64 PadToWidth (lldb_private::StreamString &ss,
65 int new_width)
66 {
67 int old_width = ss.GetSize();
68
69 if (old_width < new_width)
70 {
71 ss.Printf("%*s", new_width - old_width, "");
72 }
73 }
Sean Callanan95e5c632012-02-17 00:53:45 +000074
Sean Callanan95e5c632012-02-17 00:53:45 +000075 virtual bool
76 DoesBranch () const
77 {
Sean Callanan7725a462012-03-02 23:22:53 +000078 return m_does_branch == eLazyBoolYes;
Sean Callanan95e5c632012-02-17 00:53:45 +000079 }
80
81 virtual size_t
82 Decode (const lldb_private::Disassembler &disassembler,
83 const lldb_private::DataExtractor &data,
Greg Claytonc7bece562013-01-25 18:06:21 +000084 lldb::offset_t data_offset)
Sean Callanan95e5c632012-02-17 00:53:45 +000085 {
Greg Claytonba812f42012-05-10 02:52:23 +000086 // All we have to do is read the opcode which can be easy for some
87 // architetures
88 bool got_op = false;
89 const ArchSpec &arch = m_disasm.GetArchitecture();
Sean Callanan95e5c632012-02-17 00:53:45 +000090
Greg Claytonba812f42012-05-10 02:52:23 +000091 const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize();
92 const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize();
93 if (min_op_byte_size == max_op_byte_size)
94 {
95 // Fixed size instructions, just read that amount of data.
96 if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size))
97 return false;
98
99 switch (min_op_byte_size)
100 {
101 case 1:
102 m_opcode.SetOpcode8 (data.GetU8 (&data_offset));
103 got_op = true;
104 break;
105
106 case 2:
107 m_opcode.SetOpcode16 (data.GetU16 (&data_offset));
108 got_op = true;
109 break;
110
111 case 4:
112 m_opcode.SetOpcode32 (data.GetU32 (&data_offset));
113 got_op = true;
114 break;
115
116 case 8:
117 m_opcode.SetOpcode64 (data.GetU64 (&data_offset));
118 got_op = true;
119 break;
120
121 default:
122 m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), min_op_byte_size);
123 got_op = true;
124 break;
125 }
126 }
127 if (!got_op)
128 {
Jim Ingham0f063ba2013-03-02 00:26:47 +0000129 DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = m_disasm.m_disasm_ap.get();
Greg Claytonba812f42012-05-10 02:52:23 +0000130
131 bool is_altnernate_isa = false;
Jim Ingham0f063ba2013-03-02 00:26:47 +0000132 if (m_disasm.m_alternate_disasm_ap.get() != NULL)
Greg Claytonba812f42012-05-10 02:52:23 +0000133 {
134 const AddressClass address_class = GetAddressClass ();
135
136 if (address_class == eAddressClassCodeAlternateISA)
137 {
Jim Ingham0f063ba2013-03-02 00:26:47 +0000138 mc_disasm_ptr = m_disasm.m_alternate_disasm_ap.get();
Greg Claytonba812f42012-05-10 02:52:23 +0000139 is_altnernate_isa = true;
140 }
141 }
Jim Ingham0f063ba2013-03-02 00:26:47 +0000142
Greg Claytonba812f42012-05-10 02:52:23 +0000143 const llvm::Triple::ArchType machine = arch.GetMachine();
144 if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb)
145 {
146 if (machine == llvm::Triple::thumb || is_altnernate_isa)
147 {
Greg Clayton79101b52012-08-07 01:29:29 +0000148 uint32_t thumb_opcode = data.GetU16(&data_offset);
Greg Claytonba812f42012-05-10 02:52:23 +0000149 if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0))
150 {
151 m_opcode.SetOpcode16 (thumb_opcode);
Sean Callanan5c97c2f2012-08-06 23:42:52 +0000152 m_is_valid = true;
Greg Claytonba812f42012-05-10 02:52:23 +0000153 }
154 else
155 {
Greg Clayton79101b52012-08-07 01:29:29 +0000156 thumb_opcode <<= 16;
157 thumb_opcode |= data.GetU16(&data_offset);
158 m_opcode.SetOpcode16_2 (thumb_opcode);
Greg Claytonba812f42012-05-10 02:52:23 +0000159 m_is_valid = true;
160 }
161 }
162 else
163 {
164 m_opcode.SetOpcode32 (data.GetU32(&data_offset));
Sean Callanan5c97c2f2012-08-06 23:42:52 +0000165 m_is_valid = true;
Greg Claytonba812f42012-05-10 02:52:23 +0000166 }
167 }
168 else
169 {
170 // The opcode isn't evenly sized, so we need to actually use the llvm
171 // disassembler to parse it and get the size.
Greg Claytonba812f42012-05-10 02:52:23 +0000172 m_disasm.Lock(this, NULL);
173 uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1));
174 const size_t opcode_data_len = data.GetByteSize() - data_offset;
175 const addr_t pc = m_address.GetFileAddress();
Jim Ingham0f063ba2013-03-02 00:26:47 +0000176 llvm::MCInst inst;
177
178 const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data,
179 opcode_data_len,
180 pc,
181 inst);
Greg Claytonba812f42012-05-10 02:52:23 +0000182 m_disasm.Unlock();
183 if (inst_size == 0)
184 m_opcode.Clear();
185 else
186 {
187 m_opcode.SetOpcodeBytes(opcode_data, inst_size);
188 m_is_valid = true;
189 }
190 }
191 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000192 return m_opcode.GetByteSize();
193 }
194
195 void
Greg Claytonba812f42012-05-10 02:52:23 +0000196 AppendComment (std::string &description)
Sean Callanan95e5c632012-02-17 00:53:45 +0000197 {
Greg Claytonba812f42012-05-10 02:52:23 +0000198 if (m_comment.empty())
199 m_comment.swap (description);
Sean Callanan95e5c632012-02-17 00:53:45 +0000200 else
Greg Claytonba812f42012-05-10 02:52:23 +0000201 {
202 m_comment.append(", ");
203 m_comment.append(description);
204 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000205 }
206
207 virtual void
Greg Claytonba812f42012-05-10 02:52:23 +0000208 CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx)
Sean Callanan95e5c632012-02-17 00:53:45 +0000209 {
Greg Claytonba812f42012-05-10 02:52:23 +0000210 DataExtractor data;
211 const AddressClass address_class = GetAddressClass ();
212
Sean Callanancd4ae1a2012-08-07 01:44:58 +0000213 if (m_opcode.GetData(data))
Greg Claytonba812f42012-05-10 02:52:23 +0000214 {
215 char out_string[512];
216
Jim Ingham0f063ba2013-03-02 00:26:47 +0000217 DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr;
Greg Claytonba812f42012-05-10 02:52:23 +0000218
219 if (address_class == eAddressClassCodeAlternateISA)
Jim Ingham0f063ba2013-03-02 00:26:47 +0000220 mc_disasm_ptr = m_disasm.m_alternate_disasm_ap.get();
Greg Claytonba812f42012-05-10 02:52:23 +0000221 else
Jim Ingham0f063ba2013-03-02 00:26:47 +0000222 mc_disasm_ptr = m_disasm.m_disasm_ap.get();
Greg Claytonba812f42012-05-10 02:52:23 +0000223
224 lldb::addr_t pc = LLDB_INVALID_ADDRESS;
225
226 if (exe_ctx)
227 {
228 Target *target = exe_ctx->GetTargetPtr();
229 if (target)
230 pc = m_address.GetLoadAddress(target);
231 }
232
233 if (pc == LLDB_INVALID_ADDRESS)
234 pc = m_address.GetFileAddress();
235
236 m_disasm.Lock(this, exe_ctx);
Jim Ingham0f063ba2013-03-02 00:26:47 +0000237
Greg Claytonba812f42012-05-10 02:52:23 +0000238 uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (0, 1));
239 const size_t opcode_data_len = data.GetByteSize();
Jim Ingham0f063ba2013-03-02 00:26:47 +0000240 llvm::MCInst inst;
241 size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data,
Greg Claytonba812f42012-05-10 02:52:23 +0000242 opcode_data_len,
243 pc,
Jim Ingham0f063ba2013-03-02 00:26:47 +0000244 inst);
245
246 if (inst_size > 0)
247 mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string));
Greg Claytonba812f42012-05-10 02:52:23 +0000248
249 m_disasm.Unlock();
250
251 if (inst_size == 0)
252 {
253 m_comment.assign ("unknown opcode");
254 inst_size = m_opcode.GetByteSize();
255 StreamString mnemonic_strm;
Greg Claytonc7bece562013-01-25 18:06:21 +0000256 lldb::offset_t offset = 0;
Greg Claytonba812f42012-05-10 02:52:23 +0000257 switch (inst_size)
258 {
259 case 1:
260 {
261 const uint8_t uval8 = data.GetU8 (&offset);
262 m_opcode.SetOpcode8 (uval8);
263 m_opcode_name.assign (".byte");
264 mnemonic_strm.Printf("0x%2.2x", uval8);
265 }
266 break;
267 case 2:
268 {
269 const uint16_t uval16 = data.GetU16(&offset);
270 m_opcode.SetOpcode16(uval16);
271 m_opcode_name.assign (".short");
272 mnemonic_strm.Printf("0x%4.4x", uval16);
273 }
274 break;
275 case 4:
276 {
277 const uint32_t uval32 = data.GetU32(&offset);
278 m_opcode.SetOpcode32(uval32);
279 m_opcode_name.assign (".long");
280 mnemonic_strm.Printf("0x%8.8x", uval32);
281 }
282 break;
283 case 8:
284 {
285 const uint64_t uval64 = data.GetU64(&offset);
286 m_opcode.SetOpcode64(uval64);
287 m_opcode_name.assign (".quad");
Daniel Malead01b2952012-11-29 21:49:15 +0000288 mnemonic_strm.Printf("0x%16.16" PRIx64, uval64);
Greg Claytonba812f42012-05-10 02:52:23 +0000289 }
290 break;
291 default:
292 if (inst_size == 0)
293 return;
294 else
295 {
296 const uint8_t *bytes = data.PeekData(offset, inst_size);
297 if (bytes == NULL)
298 return;
299 m_opcode_name.assign (".byte");
300 m_opcode.SetOpcodeBytes(bytes, inst_size);
301 mnemonic_strm.Printf("0x%2.2x", bytes[0]);
302 for (uint32_t i=1; i<inst_size; ++i)
303 mnemonic_strm.Printf(" 0x%2.2x", bytes[i]);
304 }
305 break;
306 }
Jim Ingham0f063ba2013-03-02 00:26:47 +0000307 m_mnemonics.swap(mnemonic_strm.GetString());
Greg Claytonba812f42012-05-10 02:52:23 +0000308 return;
309 }
310 else
311 {
312 if (m_does_branch == eLazyBoolCalculate)
313 {
Jim Ingham0f063ba2013-03-02 00:26:47 +0000314 bool can_branch = mc_disasm_ptr->CanBranch(inst);
315 if (can_branch)
Greg Claytonba812f42012-05-10 02:52:23 +0000316 m_does_branch = eLazyBoolYes;
317 else
318 m_does_branch = eLazyBoolNo;
Jim Ingham0f063ba2013-03-02 00:26:47 +0000319
Greg Claytonba812f42012-05-10 02:52:23 +0000320 }
321 }
322
323 if (!s_regex_compiled)
324 {
325 ::regcomp(&s_regex, "[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED);
326 s_regex_compiled = true;
327 }
328
329 ::regmatch_t matches[3];
330
331 if (!::regexec(&s_regex, out_string, sizeof(matches) / sizeof(::regmatch_t), matches, 0))
332 {
333 if (matches[1].rm_so != -1)
334 m_opcode_name.assign(out_string + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so);
335 if (matches[2].rm_so != -1)
Jim Ingham0f063ba2013-03-02 00:26:47 +0000336 m_mnemonics.assign(out_string + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so);
Greg Claytonba812f42012-05-10 02:52:23 +0000337 }
338 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000339 }
340
341 bool
342 IsValid ()
343 {
344 return m_is_valid;
345 }
346
347 size_t
348 GetByteSize ()
349 {
350 return m_opcode.GetByteSize();
351 }
352protected:
Sean Callanan95e5c632012-02-17 00:53:45 +0000353
Sean Callanan95e5c632012-02-17 00:53:45 +0000354 bool m_is_valid;
355 DisassemblerLLVMC &m_disasm;
Sean Callanan7e6d4e52012-08-01 18:50:59 +0000356 DisassemblerSP m_disasm_sp; // for ownership
Sean Callanan7725a462012-03-02 23:22:53 +0000357 LazyBool m_does_branch;
Sean Callanan95e5c632012-02-17 00:53:45 +0000358
359 static bool s_regex_compiled;
360 static ::regex_t s_regex;
361};
362
363bool InstructionLLVMC::s_regex_compiled = false;
364::regex_t InstructionLLVMC::s_regex;
365
Jim Ingham0f063ba2013-03-02 00:26:47 +0000366DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner):
367 m_is_valid(true)
368{
369 std::string Error;
370 const llvm::Target *curr_target = llvm::TargetRegistry::lookupTarget(triple, Error);
371 if (!curr_target)
372 {
373 m_is_valid = false;
374 return;
375 }
376
377 m_instr_info_ap.reset(curr_target->createMCInstrInfo());
378 m_reg_info_ap.reset (curr_target->createMCRegInfo(triple));
379
380 std::string features_str;
381
382 m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, "",
383 features_str));
384
385 m_asm_info_ap.reset(curr_target->createMCAsmInfo(triple));
386
387 if (m_instr_info_ap.get() == NULL || m_reg_info_ap.get() == NULL || m_subtarget_info_ap.get() == NULL || m_asm_info_ap.get() == NULL)
388 {
Matt Kopec787d1622013-03-12 17:45:38 +0000389 m_is_valid = false;
Jim Ingham0f063ba2013-03-02 00:26:47 +0000390 return;
391 }
392
393 m_context_ap.reset(new llvm::MCContext(*m_asm_info_ap.get(), *(m_reg_info_ap.get()), 0));
394
395 m_disasm_ap.reset(curr_target->createMCDisassembler(*m_subtarget_info_ap.get()));
396 if (m_disasm_ap.get())
397 {
398 m_disasm_ap->setupForSymbolicDisassembly(NULL,
399 DisassemblerLLVMC::SymbolLookupCallback,
400 (void *) &owner,
401 m_context_ap.get());
402
403 unsigned asm_printer_variant;
404 if (flavor == ~0U)
405 asm_printer_variant = m_asm_info_ap->getAssemblerDialect();
406 else
407 {
408 asm_printer_variant = flavor;
409 }
410
411 m_instr_printer_ap.reset(curr_target->createMCInstPrinter(asm_printer_variant,
412 *m_asm_info_ap.get(),
413 *m_instr_info_ap.get(),
414 *m_reg_info_ap.get(),
415 *m_subtarget_info_ap.get()));
416 if (m_instr_printer_ap.get() == NULL)
417 {
418 m_disasm_ap.reset();
419 m_is_valid = false;
420 }
421 }
422 else
423 m_is_valid = false;
424}
425
426namespace {
427 // This is the memory object we use in GetInstruction.
428 class LLDBDisasmMemoryObject : public llvm::MemoryObject {
429 uint8_t *m_bytes;
430 uint64_t m_size;
431 uint64_t m_base_PC;
432 public:
433 LLDBDisasmMemoryObject(uint8_t *bytes, uint64_t size, uint64_t basePC) :
434 m_bytes(bytes), m_size(size), m_base_PC(basePC) {}
435
436 uint64_t getBase() const { return m_base_PC; }
437 uint64_t getExtent() const { return m_size; }
438
439 int readByte(uint64_t addr, uint8_t *byte) const {
440 if (addr - m_base_PC >= m_size)
441 return -1;
442 *byte = m_bytes[addr - m_base_PC];
443 return 0;
444 }
445 };
446} // End Anonymous Namespace
447
448uint64_t
449DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (
450 uint8_t *opcode_data,
451 size_t opcode_data_len,
452 lldb::addr_t pc,
453 llvm::MCInst &mc_inst)
454{
455 LLDBDisasmMemoryObject memory_object (opcode_data, opcode_data_len, pc);
456 llvm::MCInst inst;
457 llvm::MCDisassembler::DecodeStatus status;
458
459 uint64_t new_inst_size;
460 status = m_disasm_ap->getInstruction(mc_inst,
461 new_inst_size,
462 memory_object,
463 pc,
464 llvm::nulls(),
465 llvm::nulls());
466 if (status == llvm::MCDisassembler::Success)
467 return new_inst_size;
468 else
469 return 0;
470}
471
472uint64_t
473DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst, char *output_buffer, size_t out_buffer_len)
474{
475 llvm::StringRef unused_annotations;
476 llvm::SmallString<64> inst_string;
477 llvm::raw_svector_ostream inst_stream(inst_string);
478 m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations);
479 inst_stream.flush();
480
481 size_t output_size = std::min(out_buffer_len -1, inst_string.size());
482 std::memcpy(output_buffer, inst_string.data(), output_size);
483 output_buffer[output_size] = '\0';
484
485 return output_size;
486}
487
488bool
489DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst)
490{
491 return m_instr_info_ap->get(mc_inst.getOpcode()).mayAffectControlFlow(mc_inst, *m_reg_info_ap.get());
492}
493
494bool
495DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor)
496{
497 llvm::Triple triple = arch.GetTriple();
498 if (flavor == NULL || strcmp (flavor, "default") == 0)
499 return true;
500
501 if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64)
502 {
503 if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0)
504 return true;
505 else
506 return false;
507 }
508 else
509 return false;
510}
511
512
Sean Callanan95e5c632012-02-17 00:53:45 +0000513Disassembler *
Jim Ingham0f063ba2013-03-02 00:26:47 +0000514DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor)
Sean Callanan95e5c632012-02-17 00:53:45 +0000515{
Greg Clayton9e6cffc2012-09-19 22:25:17 +0000516 if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch)
517 {
Jim Ingham0f063ba2013-03-02 00:26:47 +0000518 std::auto_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor));
Sean Callanan95e5c632012-02-17 00:53:45 +0000519
Greg Clayton9e6cffc2012-09-19 22:25:17 +0000520 if (disasm_ap.get() && disasm_ap->IsValid())
521 return disasm_ap.release();
522 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000523 return NULL;
524}
525
Jim Ingham0f063ba2013-03-02 00:26:47 +0000526DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) :
527 Disassembler(arch, flavor_string),
Greg Claytonba812f42012-05-10 02:52:23 +0000528 m_exe_ctx (NULL),
Jim Ingham0f063ba2013-03-02 00:26:47 +0000529 m_inst (NULL)
Sean Callanan95e5c632012-02-17 00:53:45 +0000530{
Jim Ingham0f063ba2013-03-02 00:26:47 +0000531 if (!FlavorValidForArchSpec (arch, m_flavor.c_str()))
532 {
533 m_flavor.assign("default");
534 }
535
536 const char *triple = arch.GetTriple().getTriple().c_str();
537 unsigned flavor = ~0U;
538
539 // So far the only supported flavor is "intel" on x86. The base class will set this
540 // correctly coming in.
541 if (arch.GetTriple().getArch() == llvm::Triple::x86
542 || arch.GetTriple().getArch() == llvm::Triple::x86_64)
543 {
544 if (m_flavor == "intel")
545 {
546 flavor = 1;
547 }
548 else if (m_flavor == "att")
549 {
550 flavor = 0;
551 }
552 }
553
554 m_disasm_ap.reset (new LLVMCDisassembler(triple, flavor, *this));
555 if (!m_disasm_ap->IsValid())
556 {
557 // We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason,
558 // we reset it, and then we won't be valid and FindPlugin will fail and we won't get used.
559 m_disasm_ap.reset();
560 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000561
562 if (arch.GetTriple().getArch() == llvm::Triple::arm)
563 {
Greg Claytonba812f42012-05-10 02:52:23 +0000564 ArchSpec thumb_arch(arch);
565 thumb_arch.GetTriple().setArchName(llvm::StringRef("thumbv7"));
566 std::string thumb_triple(thumb_arch.GetTriple().getTriple());
567
Jim Ingham0f063ba2013-03-02 00:26:47 +0000568 m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), flavor, *this));
569 if (!m_alternate_disasm_ap->IsValid())
570 {
571 m_disasm_ap.reset();
572 m_alternate_disasm_ap.reset();
573 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000574 }
575}
576
577DisassemblerLLVMC::~DisassemblerLLVMC()
578{
579}
580
581size_t
582DisassemblerLLVMC::DecodeInstructions (const Address &base_addr,
583 const DataExtractor& data,
Greg Claytonc7bece562013-01-25 18:06:21 +0000584 lldb::offset_t data_offset,
585 size_t num_instructions,
Sean Callanan95e5c632012-02-17 00:53:45 +0000586 bool append)
587{
588 if (!append)
589 m_instruction_list.Clear();
590
591 if (!IsValid())
592 return 0;
593
594 uint32_t data_cursor = data_offset;
Greg Claytonba812f42012-05-10 02:52:23 +0000595 const size_t data_byte_size = data.GetByteSize();
Sean Callanan95e5c632012-02-17 00:53:45 +0000596 uint32_t instructions_parsed = 0;
Greg Claytonba812f42012-05-10 02:52:23 +0000597 Address inst_addr(base_addr);
Sean Callanan95e5c632012-02-17 00:53:45 +0000598
Greg Claytonba812f42012-05-10 02:52:23 +0000599 while (data_cursor < data_byte_size && instructions_parsed < num_instructions)
Sean Callanan95e5c632012-02-17 00:53:45 +0000600 {
Sean Callanan95e5c632012-02-17 00:53:45 +0000601
Greg Claytonba812f42012-05-10 02:52:23 +0000602 AddressClass address_class = eAddressClassCode;
Sean Callanan95e5c632012-02-17 00:53:45 +0000603
Jim Ingham0f063ba2013-03-02 00:26:47 +0000604 if (m_alternate_disasm_ap.get() != NULL)
Greg Claytonba812f42012-05-10 02:52:23 +0000605 address_class = inst_addr.GetAddressClass ();
Sean Callanan95e5c632012-02-17 00:53:45 +0000606
607 InstructionSP inst_sp(new InstructionLLVMC(*this,
Greg Claytonba812f42012-05-10 02:52:23 +0000608 inst_addr,
Sean Callanan95e5c632012-02-17 00:53:45 +0000609 address_class));
610
611 if (!inst_sp)
Greg Claytonba812f42012-05-10 02:52:23 +0000612 break;
613
Sean Callanan95e5c632012-02-17 00:53:45 +0000614 uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor);
615
Greg Claytonba812f42012-05-10 02:52:23 +0000616 if (inst_size == 0)
617 break;
618
Sean Callanan95e5c632012-02-17 00:53:45 +0000619 m_instruction_list.Append(inst_sp);
Sean Callanan95e5c632012-02-17 00:53:45 +0000620 data_cursor += inst_size;
Greg Claytonba812f42012-05-10 02:52:23 +0000621 inst_addr.Slide(inst_size);
Sean Callanan95e5c632012-02-17 00:53:45 +0000622 instructions_parsed++;
623 }
624
625 return data_cursor - data_offset;
626}
627
628void
629DisassemblerLLVMC::Initialize()
630{
631 PluginManager::RegisterPlugin (GetPluginNameStatic(),
632 GetPluginDescriptionStatic(),
633 CreateInstance);
634
635 llvm::InitializeAllTargetInfos();
636 llvm::InitializeAllTargetMCs();
637 llvm::InitializeAllAsmParsers();
638 llvm::InitializeAllDisassemblers();
639}
640
641void
642DisassemblerLLVMC::Terminate()
643{
644 PluginManager::UnregisterPlugin (CreateInstance);
645}
646
647
648const char *
649DisassemblerLLVMC::GetPluginNameStatic()
650{
Greg Claytonf8712de2012-03-22 00:49:15 +0000651 return "llvm-mc";
Sean Callanan95e5c632012-02-17 00:53:45 +0000652}
653
654const char *
655DisassemblerLLVMC::GetPluginDescriptionStatic()
656{
Greg Claytonf8712de2012-03-22 00:49:15 +0000657 return "Disassembler that uses LLVM MC to disassemble i386, x86_64 and ARM.";
Sean Callanan95e5c632012-02-17 00:53:45 +0000658}
659
Greg Claytonba812f42012-05-10 02:52:23 +0000660int DisassemblerLLVMC::OpInfoCallback (void *disassembler,
661 uint64_t pc,
662 uint64_t offset,
663 uint64_t size,
664 int tag_type,
665 void *tag_bug)
Sean Callanan95e5c632012-02-17 00:53:45 +0000666{
Greg Claytonba812f42012-05-10 02:52:23 +0000667 return static_cast<DisassemblerLLVMC*>(disassembler)->OpInfo (pc,
668 offset,
669 size,
670 tag_type,
671 tag_bug);
Sean Callanan95e5c632012-02-17 00:53:45 +0000672}
673
Greg Claytonba812f42012-05-10 02:52:23 +0000674const char *DisassemblerLLVMC::SymbolLookupCallback (void *disassembler,
675 uint64_t value,
676 uint64_t *type,
677 uint64_t pc,
678 const char **name)
Sean Callanan95e5c632012-02-17 00:53:45 +0000679{
Greg Claytonba812f42012-05-10 02:52:23 +0000680 return static_cast<DisassemblerLLVMC*>(disassembler)->SymbolLookup(value,
681 type,
682 pc,
683 name);
Sean Callanan95e5c632012-02-17 00:53:45 +0000684}
685
686int DisassemblerLLVMC::OpInfo (uint64_t PC,
687 uint64_t Offset,
688 uint64_t Size,
Greg Claytonba812f42012-05-10 02:52:23 +0000689 int tag_type,
690 void *tag_bug)
Sean Callanan95e5c632012-02-17 00:53:45 +0000691{
Greg Claytonba812f42012-05-10 02:52:23 +0000692 switch (tag_type)
Sean Callanan95e5c632012-02-17 00:53:45 +0000693 {
694 default:
695 break;
696 case 1:
Greg Claytonba812f42012-05-10 02:52:23 +0000697 bzero (tag_bug, sizeof(::LLVMOpInfo1));
Sean Callanan95e5c632012-02-17 00:53:45 +0000698 break;
699 }
700 return 0;
701}
702
Greg Claytonba812f42012-05-10 02:52:23 +0000703const char *DisassemblerLLVMC::SymbolLookup (uint64_t value,
704 uint64_t *type_ptr,
705 uint64_t pc,
706 const char **name)
Sean Callanan95e5c632012-02-17 00:53:45 +0000707{
Greg Claytonba812f42012-05-10 02:52:23 +0000708 if (*type_ptr)
709 {
710 if (m_exe_ctx && m_inst)
711 {
712 //std::string remove_this_prior_to_checkin;
713 Address reference_address;
Sean Callanan95e5c632012-02-17 00:53:45 +0000714
Greg Claytonba812f42012-05-10 02:52:23 +0000715 Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : NULL;
716
717 if (target && !target->GetSectionLoadList().IsEmpty())
718 target->GetSectionLoadList().ResolveLoadAddress(value, reference_address);
719 else
720 {
721 ModuleSP module_sp(m_inst->GetAddress().GetModule());
722 if (module_sp)
723 module_sp->ResolveFileAddress(value, reference_address);
724 }
725
Sean Callanan6f298a62012-02-23 23:43:28 +0000726 if (reference_address.IsValid() && reference_address.GetSection())
Sean Callanan95e5c632012-02-17 00:53:45 +0000727 {
Sean Callanan95e5c632012-02-17 00:53:45 +0000728 StreamString ss;
729
Sean Callanan6f298a62012-02-23 23:43:28 +0000730 reference_address.Dump (&ss,
731 target,
732 Address::DumpStyleResolvedDescriptionNoModule,
733 Address::DumpStyleSectionNameOffset);
Sean Callanan95e5c632012-02-17 00:53:45 +0000734
Sean Callanan745af462012-03-22 20:04:23 +0000735 if (!ss.GetString().empty())
Greg Claytonba812f42012-05-10 02:52:23 +0000736 {
737 //remove_this_prior_to_checkin = ss.GetString();
738 //if (*type_ptr)
739 m_inst->AppendComment(ss.GetString());
740 }
Sean Callanan95e5c632012-02-17 00:53:45 +0000741 }
Daniel Malead01b2952012-11-29 21:49:15 +0000742 //printf ("DisassemblerLLVMC::SymbolLookup (value=0x%16.16" PRIx64 ", type=%" PRIu64 ", pc=0x%16.16" PRIx64 ", name=\"%s\") m_exe_ctx=%p, m_inst=%p\n", value, *type_ptr, pc, remove_this_prior_to_checkin.c_str(), m_exe_ctx, m_inst);
Sean Callanan95e5c632012-02-17 00:53:45 +0000743 }
744 }
Greg Claytonba812f42012-05-10 02:52:23 +0000745
746 *type_ptr = LLVMDisassembler_ReferenceType_InOut_None;
747 *name = NULL;
748 return NULL;
Sean Callanan95e5c632012-02-17 00:53:45 +0000749}
750
751//------------------------------------------------------------------
752// PluginInterface protocol
753//------------------------------------------------------------------
754const char *
755DisassemblerLLVMC::GetPluginName()
756{
757 return "DisassemblerLLVMC";
758}
759
760const char *
761DisassemblerLLVMC::GetShortPluginName()
762{
763 return GetPluginNameStatic();
764}
765
766uint32_t
767DisassemblerLLVMC::GetPluginVersion()
768{
769 return 1;
770}
771