blob: a8c807dd99aaf8cb040e04193e44838f8f96788c [file] [log] [blame]
Chris Lattner30fdc8d2010-06-08 16:52:24 +00001//===-- Disassembler.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 "lldb/Core/Disassembler.h"
11
12// C Includes
13// C++ Includes
14// Other libraries and framework includes
15// Project includes
16#include "lldb/lldb-private.h"
17#include "lldb/Core/Error.h"
18#include "lldb/Core/DataBufferHeap.h"
19#include "lldb/Core/DataExtractor.h"
20#include "lldb/Core/Debugger.h"
Caroline Ticead379efc2011-04-05 18:46:00 +000021#include "lldb/Core/EmulateInstruction.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000022#include "lldb/Core/Module.h"
23#include "lldb/Core/PluginManager.h"
24#include "lldb/Core/Timer.h"
25#include "lldb/Symbol/ObjectFile.h"
26#include "lldb/Target/ExecutionContext.h"
27#include "lldb/Target/Process.h"
28#include "lldb/Target/StackFrame.h"
29#include "lldb/Target/Target.h"
30
31#define DEFAULT_DISASM_BYTE_SIZE 32
32
33using namespace lldb;
34using namespace lldb_private;
35
36
37Disassembler*
Greg Clayton1080edbc2011-03-25 18:03:16 +000038Disassembler::FindPlugin (const ArchSpec &arch, const char *plugin_name)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000039{
40 Timer scoped_timer (__PRETTY_FUNCTION__,
Greg Clayton1080edbc2011-03-25 18:03:16 +000041 "Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
42 arch.GetArchitectureName(),
43 plugin_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000044
45 std::auto_ptr<Disassembler> disassembler_ap;
Greg Clayton1080edbc2011-03-25 18:03:16 +000046 DisassemblerCreateInstance create_callback = NULL;
47
48 if (plugin_name)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000049 {
Greg Clayton1080edbc2011-03-25 18:03:16 +000050 create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName (plugin_name);
51 if (create_callback)
52 {
53 disassembler_ap.reset (create_callback(arch));
54
55 if (disassembler_ap.get())
56 return disassembler_ap.release();
57 }
58 }
59 else
60 {
61 for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != NULL; ++idx)
62 {
63 disassembler_ap.reset (create_callback(arch));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000064
Greg Clayton1080edbc2011-03-25 18:03:16 +000065 if (disassembler_ap.get())
66 return disassembler_ap.release();
67 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000068 }
69 return NULL;
70}
71
Greg Claytondda4f7b2010-06-30 23:03:03 +000072
Greg Clayton357132e2011-03-26 19:14:58 +000073static void
74ResolveAddress (const ExecutionContext &exe_ctx,
75 const Address &addr,
76 Address &resolved_addr)
77{
78 if (!addr.IsSectionOffset())
79 {
80 // If we weren't passed in a section offset address range,
81 // try and resolve it to something
82 if (exe_ctx.target)
83 {
84 if (exe_ctx.target->GetSectionLoadList().IsEmpty())
85 {
86 exe_ctx.target->GetImages().ResolveFileAddress (addr.GetOffset(), resolved_addr);
87 }
88 else
89 {
90 exe_ctx.target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), resolved_addr);
91 }
92 // We weren't able to resolve the address, just treat it as a
93 // raw address
94 if (resolved_addr.IsValid())
95 return;
96 }
97 }
98 resolved_addr = addr;
99}
Greg Claytondda4f7b2010-06-30 23:03:03 +0000100
101size_t
102Disassembler::Disassemble
103(
104 Debugger &debugger,
105 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000106 const char *plugin_name,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000107 const ExecutionContext &exe_ctx,
108 SymbolContextList &sc_list,
Jim Ingham37023b02011-03-22 01:48:42 +0000109 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000110 uint32_t num_mixed_context_lines,
111 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000112 bool raw,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000113 Stream &strm
114)
115{
116 size_t success_count = 0;
117 const size_t count = sc_list.GetSize();
118 SymbolContext sc;
119 AddressRange range;
Jim Ingham37023b02011-03-22 01:48:42 +0000120
Greg Claytondda4f7b2010-06-30 23:03:03 +0000121 for (size_t i=0; i<count; ++i)
122 {
123 if (sc_list.GetContextAtIndex(i, sc) == false)
124 break;
125 if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
126 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000127 if (Disassemble (debugger,
128 arch,
129 plugin_name,
130 exe_ctx,
131 range,
132 num_instructions,
133 num_mixed_context_lines,
134 show_bytes,
135 raw,
136 strm))
Greg Claytondda4f7b2010-06-30 23:03:03 +0000137 {
138 ++success_count;
139 strm.EOL();
140 }
141 }
142 }
143 return success_count;
144}
145
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000146bool
147Disassembler::Disassemble
148(
Greg Clayton66111032010-06-23 01:19:29 +0000149 Debugger &debugger,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000150 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000151 const char *plugin_name,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000152 const ExecutionContext &exe_ctx,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000153 const ConstString &name,
154 Module *module,
Jim Ingham37023b02011-03-22 01:48:42 +0000155 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000156 uint32_t num_mixed_context_lines,
157 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000158 bool raw,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000159 Stream &strm
160)
161{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000162 SymbolContextList sc_list;
Greg Clayton931180e2011-01-27 06:44:37 +0000163 if (name)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000164 {
Greg Clayton931180e2011-01-27 06:44:37 +0000165 const bool include_symbols = true;
166 if (module)
167 {
168 module->FindFunctions (name,
169 eFunctionNameTypeBase |
170 eFunctionNameTypeFull |
171 eFunctionNameTypeMethod |
172 eFunctionNameTypeSelector,
173 include_symbols,
174 true,
175 sc_list);
176 }
177 else if (exe_ctx.target)
178 {
179 exe_ctx.target->GetImages().FindFunctions (name,
Greg Clayton6dbd3982010-09-15 05:51:24 +0000180 eFunctionNameTypeBase |
181 eFunctionNameTypeFull |
182 eFunctionNameTypeMethod |
183 eFunctionNameTypeSelector,
Greg Clayton931180e2011-01-27 06:44:37 +0000184 include_symbols,
Sean Callanan8ade1042010-07-27 00:55:47 +0000185 false,
Greg Clayton931180e2011-01-27 06:44:37 +0000186 sc_list);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000187 }
Greg Clayton931180e2011-01-27 06:44:37 +0000188 }
189
190 if (sc_list.GetSize ())
191 {
192 return Disassemble (debugger,
193 arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000194 plugin_name,
Greg Clayton931180e2011-01-27 06:44:37 +0000195 exe_ctx,
Jim Ingham37023b02011-03-22 01:48:42 +0000196 sc_list,
197 num_instructions,
Greg Clayton931180e2011-01-27 06:44:37 +0000198 num_mixed_context_lines,
Sean Callananb3396b22011-03-10 23:35:12 +0000199 show_bytes,
200 raw,
Greg Clayton931180e2011-01-27 06:44:37 +0000201 strm);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000202 }
203 return false;
204}
205
Greg Clayton1d273162010-10-06 03:09:58 +0000206
207lldb::DisassemblerSP
208Disassembler::DisassembleRange
209(
210 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000211 const char *plugin_name,
Greg Clayton1d273162010-10-06 03:09:58 +0000212 const ExecutionContext &exe_ctx,
213 const AddressRange &range
214)
215{
216 lldb::DisassemblerSP disasm_sp;
217 if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid())
218 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000219 disasm_sp.reset (Disassembler::FindPlugin(arch, plugin_name));
Greg Clayton1d273162010-10-06 03:09:58 +0000220
221 if (disasm_sp)
222 {
Greg Clayton357132e2011-03-26 19:14:58 +0000223 size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range);
Greg Clayton1d273162010-10-06 03:09:58 +0000224 if (bytes_disassembled == 0)
225 disasm_sp.reset();
226 }
227 }
228 return disasm_sp;
229}
230
231
Greg Claytondda4f7b2010-06-30 23:03:03 +0000232bool
233Disassembler::Disassemble
234(
235 Debugger &debugger,
236 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000237 const char *plugin_name,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000238 const ExecutionContext &exe_ctx,
239 const AddressRange &disasm_range,
Jim Ingham37023b02011-03-22 01:48:42 +0000240 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000241 uint32_t num_mixed_context_lines,
242 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000243 bool raw,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000244 Stream &strm
245)
246{
247 if (disasm_range.GetByteSize())
248 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000249 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name));
Greg Claytondda4f7b2010-06-30 23:03:03 +0000250
Greg Clayton1d273162010-10-06 03:09:58 +0000251 if (disasm_ap.get())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000252 {
Greg Clayton357132e2011-03-26 19:14:58 +0000253 AddressRange range;
254 ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress());
255 range.SetByteSize (disasm_range.GetByteSize());
Greg Claytondda4f7b2010-06-30 23:03:03 +0000256
Greg Clayton357132e2011-03-26 19:14:58 +0000257 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, range);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000258 if (bytes_disassembled == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000259 return false;
Greg Clayton1080edbc2011-03-25 18:03:16 +0000260
261 return PrintInstructions (disasm_ap.get(),
262 debugger,
263 arch,
264 exe_ctx,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000265 num_instructions,
266 num_mixed_context_lines,
267 show_bytes,
268 raw,
269 strm);
Jim Ingham37023b02011-03-22 01:48:42 +0000270 }
271 }
272 return false;
273}
274
275bool
276Disassembler::Disassemble
277(
278 Debugger &debugger,
279 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000280 const char *plugin_name,
Jim Ingham37023b02011-03-22 01:48:42 +0000281 const ExecutionContext &exe_ctx,
282 const Address &start_address,
283 uint32_t num_instructions,
284 uint32_t num_mixed_context_lines,
285 bool show_bytes,
286 bool raw,
287 Stream &strm
288)
289{
290 if (num_instructions > 0)
291 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000292 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name));
Jim Ingham37023b02011-03-22 01:48:42 +0000293 if (disasm_ap.get())
294 {
Greg Clayton357132e2011-03-26 19:14:58 +0000295 Address addr;
296 ResolveAddress (exe_ctx, start_address, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000297
Greg Clayton357132e2011-03-26 19:14:58 +0000298 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, addr, num_instructions);
Jim Ingham37023b02011-03-22 01:48:42 +0000299 if (bytes_disassembled == 0)
Jim Ingham37023b02011-03-22 01:48:42 +0000300 return false;
Greg Clayton1080edbc2011-03-25 18:03:16 +0000301 return PrintInstructions (disasm_ap.get(),
302 debugger,
303 arch,
304 exe_ctx,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000305 num_instructions,
306 num_mixed_context_lines,
307 show_bytes,
308 raw,
309 strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000310 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000311 }
312 return false;
313}
Jim Ingham37023b02011-03-22 01:48:42 +0000314
315bool
316Disassembler::PrintInstructions
317(
318 Disassembler *disasm_ptr,
Jim Ingham37023b02011-03-22 01:48:42 +0000319 Debugger &debugger,
320 const ArchSpec &arch,
321 const ExecutionContext &exe_ctx,
Jim Ingham37023b02011-03-22 01:48:42 +0000322 uint32_t num_instructions,
323 uint32_t num_mixed_context_lines,
324 bool show_bytes,
325 bool raw,
326 Stream &strm
327)
328{
329 // We got some things disassembled...
330 size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
331
332 if (num_instructions > 0 && num_instructions < num_instructions_found)
333 num_instructions_found = num_instructions;
334
Greg Clayton357132e2011-03-26 19:14:58 +0000335 const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
Jim Ingham37023b02011-03-22 01:48:42 +0000336 uint32_t offset = 0;
337 SymbolContext sc;
338 SymbolContext prev_sc;
339 AddressRange sc_range;
Greg Clayton32e0a752011-03-30 18:16:51 +0000340 Address *pc_addr_ptr = NULL;
341 if (exe_ctx.frame)
342 pc_addr_ptr = &exe_ctx.frame->GetFrameCodeAddress();
Jim Ingham37023b02011-03-22 01:48:42 +0000343
344 for (size_t i=0; i<num_instructions_found; ++i)
345 {
346 Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
347 if (inst)
348 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000349 const Address &addr = inst->GetAddress();
350 const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
Jim Ingham37023b02011-03-22 01:48:42 +0000351
352 prev_sc = sc;
353
Greg Clayton32e0a752011-03-30 18:16:51 +0000354 Module *module = addr.GetModule();
355 if (module)
Jim Ingham37023b02011-03-22 01:48:42 +0000356 {
Jim Ingham37023b02011-03-22 01:48:42 +0000357 uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
358 if (resolved_mask)
359 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000360 if (num_mixed_context_lines)
361 {
362 if (!sc_range.ContainsFileAddress (addr))
363 {
364 sc.GetAddressRange (eSymbolContextEverything, sc_range);
365
366 if (sc != prev_sc)
367 {
368 if (offset != 0)
369 strm.EOL();
370
371 sc.DumpStopContext(&strm, exe_ctx.process, addr, false, true, false);
372 strm.EOL();
373
374 if (sc.comp_unit && sc.line_entry.IsValid())
375 {
376 debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
377 sc.line_entry.line,
378 num_mixed_context_lines,
379 num_mixed_context_lines,
380 num_mixed_context_lines ? "->" : "",
381 &strm);
382 }
383 }
384 }
385 }
386 else if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol))
Jim Ingham37023b02011-03-22 01:48:42 +0000387 {
388 if (prev_sc.function || prev_sc.symbol)
389 strm.EOL();
390
391 strm << sc.module_sp->GetFileSpec().GetFilename();
392
393 if (sc.function)
394 strm << '`' << sc.function->GetMangled().GetName();
395 else if (sc.symbol)
396 strm << '`' << sc.symbol->GetMangled().GetName();
397 strm << ":\n";
398 }
Jim Ingham37023b02011-03-22 01:48:42 +0000399 }
400 else
401 {
402 sc.Clear();
403 }
404 }
Jim Ingham37023b02011-03-22 01:48:42 +0000405
Greg Clayton32e0a752011-03-30 18:16:51 +0000406 if (pc_addr_ptr)
407 {
408 if (inst_is_at_pc)
409 strm.PutCString("-> ");
410 else
411 strm.PutCString(" ");
412 }
413 inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, raw);
414 strm.EOL();
Jim Ingham37023b02011-03-22 01:48:42 +0000415 }
416 else
417 {
418 break;
419 }
420 }
Jim Ingham37023b02011-03-22 01:48:42 +0000421
422 return true;
423}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000424
Greg Claytondda4f7b2010-06-30 23:03:03 +0000425
426bool
427Disassembler::Disassemble
428(
429 Debugger &debugger,
430 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000431 const char *plugin_name,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000432 const ExecutionContext &exe_ctx,
Jim Ingham37023b02011-03-22 01:48:42 +0000433 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000434 uint32_t num_mixed_context_lines,
435 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000436 bool raw,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000437 Stream &strm
438)
439{
440 AddressRange range;
441 if (exe_ctx.frame)
442 {
443 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
444 if (sc.function)
445 {
446 range = sc.function->GetAddressRange();
447 }
448 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
449 {
450 range = *sc.symbol->GetAddressRangePtr();
451 }
452 else
453 {
Greg Clayton9da7bd02010-08-24 21:05:24 +0000454 range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
Greg Claytondda4f7b2010-06-30 23:03:03 +0000455 }
456
457 if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
458 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
459 }
460
Greg Clayton1080edbc2011-03-25 18:03:16 +0000461 return Disassemble (debugger,
462 arch,
463 plugin_name,
464 exe_ctx,
465 range,
466 num_instructions,
467 num_mixed_context_lines,
468 show_bytes,
469 raw,
470 strm);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000471}
472
Greg Clayton357132e2011-03-26 19:14:58 +0000473Instruction::Instruction(const Address &address, AddressClass addr_class) :
Greg Clayton1080edbc2011-03-25 18:03:16 +0000474 m_address (address),
Greg Clayton357132e2011-03-26 19:14:58 +0000475 m_address_class (addr_class),
Greg Clayton1080edbc2011-03-25 18:03:16 +0000476 m_opcode()
Greg Clayton0ae96272011-03-24 23:53:38 +0000477{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000478}
479
Greg Clayton1d273162010-10-06 03:09:58 +0000480Instruction::~Instruction()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000481{
482}
483
Greg Clayton357132e2011-03-26 19:14:58 +0000484AddressClass
485Instruction::GetAddressClass ()
486{
487 if (m_address_class == eAddressClassInvalid)
488 m_address_class = m_address.GetAddressClass();
489 return m_address_class;
490}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000491
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000492bool
493Instruction::DumpEmulation (const ArchSpec &arch)
494{
495 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL));
496 if (insn_emulator_ap.get())
497 {
498 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress());
499 return insn_emulator_ap->EvaluateInstruction ();
500 }
501
502 return false;
503}
504
505bool
Caroline Tice3ac67112011-04-19 23:30:03 +0000506Instruction::TestEmulation (Stream *out_stream, const char *file_name)
507{
508 if (!out_stream)
509 return false;
510
511 if (!file_name)
512 {
Johnny Chenea80ba82011-04-21 20:27:45 +0000513 out_stream->Printf ("Instruction::TestEmulation: Missing file_name.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000514 return false;
515 }
516
517 FILE *test_file = fopen (file_name, "r");
518 if (!test_file)
519 {
Johnny Chenea80ba82011-04-21 20:27:45 +0000520 out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000521 return false;
522 }
523
524 ArchSpec arch;
525 char buffer[256];
526 if (!fgets (buffer,255, test_file)) // Read/skip first line of file, which should be a comment line (description).
527 {
Johnny Chenea80ba82011-04-21 20:27:45 +0000528 out_stream->Printf ("Instruction::TestEmulation: Read comment line failed.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000529 fclose (test_file);
530 return false;
531 }
532 SetDescription (buffer);
533
534 if (fscanf (test_file, "%s", buffer) != 1) // Read the arch or arch-triple from the file
535 {
Johnny Chenea80ba82011-04-21 20:27:45 +0000536 out_stream->Printf ("Instruction::TestEmulation: Read arch failed.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000537 fclose (test_file);
538 return false;
539 }
540
541 const char *cptr = buffer;
542 arch.SetTriple (llvm::Triple (cptr));
543
544 bool success = false;
545 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL));
546 if (insn_emulator_ap.get())
547 success = insn_emulator_ap->TestEmulation (out_stream, test_file, arch);
548
549 fclose (test_file);
550
551 if (success)
Johnny Chenea80ba82011-04-21 20:27:45 +0000552 out_stream->Printf ("Emulation test succeeded.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000553 else
Johnny Chenea80ba82011-04-21 20:27:45 +0000554 out_stream->Printf ("Emulation test failed.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000555
556 return success;
557}
558
559bool
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000560Instruction::Emulate (const ArchSpec &arch,
Caroline Tice25d61ac2011-04-08 23:33:06 +0000561 bool auto_advance_pc,
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000562 void *baton,
563 EmulateInstruction::ReadMemory read_mem_callback,
564 EmulateInstruction::WriteMemory write_mem_callback,
565 EmulateInstruction::ReadRegister read_reg_callback,
566 EmulateInstruction::WriteRegister write_reg_callback)
567{
568 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL));
569 if (insn_emulator_ap.get())
570 {
571 insn_emulator_ap->SetBaton (baton);
572 insn_emulator_ap->SetCallbacks (read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback);
573 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress());
Caroline Tice25d61ac2011-04-08 23:33:06 +0000574 insn_emulator_ap->SetAdvancePC (auto_advance_pc);
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000575 return insn_emulator_ap->EvaluateInstruction ();
576 }
577
578 return false;
579}
580
Greg Clayton1d273162010-10-06 03:09:58 +0000581InstructionList::InstructionList() :
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000582 m_instructions()
583{
584}
585
Greg Clayton1d273162010-10-06 03:09:58 +0000586InstructionList::~InstructionList()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000587{
588}
589
590size_t
Greg Clayton1d273162010-10-06 03:09:58 +0000591InstructionList::GetSize() const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000592{
593 return m_instructions.size();
594}
595
Greg Clayton357132e2011-03-26 19:14:58 +0000596uint32_t
597InstructionList::GetMaxOpcocdeByteSize () const
598{
599 uint32_t max_inst_size = 0;
600 collection::const_iterator pos, end;
601 for (pos = m_instructions.begin(), end = m_instructions.end();
602 pos != end;
603 ++pos)
604 {
605 uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
606 if (max_inst_size < inst_size)
607 max_inst_size = inst_size;
608 }
609 return max_inst_size;
610}
611
612
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000613
Greg Clayton1d273162010-10-06 03:09:58 +0000614InstructionSP
615InstructionList::GetInstructionAtIndex (uint32_t idx) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000616{
Greg Clayton1d273162010-10-06 03:09:58 +0000617 InstructionSP inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000618 if (idx < m_instructions.size())
Greg Clayton1d273162010-10-06 03:09:58 +0000619 inst_sp = m_instructions[idx];
620 return inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000621}
622
623void
Greg Clayton1d273162010-10-06 03:09:58 +0000624InstructionList::Clear()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000625{
626 m_instructions.clear();
627}
628
629void
Greg Clayton1d273162010-10-06 03:09:58 +0000630InstructionList::Append (lldb::InstructionSP &inst_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000631{
632 if (inst_sp)
633 m_instructions.push_back(inst_sp);
634}
635
636
637size_t
638Disassembler::ParseInstructions
639(
640 const ExecutionContext *exe_ctx,
Greg Clayton357132e2011-03-26 19:14:58 +0000641 const AddressRange &range
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000642)
643{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000644 Target *target = exe_ctx->target;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000645 const addr_t byte_size = range.GetByteSize();
646 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000647 return 0;
648
Greg Claytondda4f7b2010-06-30 23:03:03 +0000649 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
650 DataBufferSP data_sp(heap_buffer);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000651
652 Error error;
Greg Clayton357132e2011-03-26 19:14:58 +0000653 const bool prefer_file_cache = true;
654 const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(),
655 prefer_file_cache,
656 heap_buffer->GetBytes(),
657 heap_buffer->GetByteSize(),
658 error);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000659
660 if (bytes_read > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000661 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000662 if (bytes_read != heap_buffer->GetByteSize())
663 heap_buffer->SetByteSize (bytes_read);
Greg Clayton357132e2011-03-26 19:14:58 +0000664 DataExtractor data (data_sp,
665 m_arch.GetByteOrder(),
666 m_arch.GetAddressByteSize());
Jim Ingham37023b02011-03-22 01:48:42 +0000667 return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000668 }
669
670 return 0;
671}
672
Jim Ingham37023b02011-03-22 01:48:42 +0000673size_t
674Disassembler::ParseInstructions
675(
676 const ExecutionContext *exe_ctx,
677 const Address &start,
Greg Clayton357132e2011-03-26 19:14:58 +0000678 uint32_t num_instructions
Jim Ingham37023b02011-03-22 01:48:42 +0000679)
680{
Greg Clayton357132e2011-03-26 19:14:58 +0000681 m_instruction_list.Clear();
682
683 if (num_instructions == 0 || !start.IsValid())
Jim Ingham37023b02011-03-22 01:48:42 +0000684 return 0;
685
686 Target *target = exe_ctx->target;
Greg Clayton357132e2011-03-26 19:14:58 +0000687 // Calculate the max buffer size we will need in order to disassemble
688 const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize();
Jim Ingham37023b02011-03-22 01:48:42 +0000689
Greg Clayton357132e2011-03-26 19:14:58 +0000690 if (target == NULL || byte_size == 0)
Jim Ingham37023b02011-03-22 01:48:42 +0000691 return 0;
692
693 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
Greg Clayton357132e2011-03-26 19:14:58 +0000694 DataBufferSP data_sp (heap_buffer);
Jim Ingham37023b02011-03-22 01:48:42 +0000695
696 Error error;
697 bool prefer_file_cache = true;
Greg Clayton357132e2011-03-26 19:14:58 +0000698 const size_t bytes_read = target->ReadMemory (start,
699 prefer_file_cache,
700 heap_buffer->GetBytes(),
701 byte_size,
702 error);
703
704 if (bytes_read == 0)
705 return 0;
706 DataExtractor data (data_sp,
707 m_arch.GetByteOrder(),
708 m_arch.GetAddressByteSize());
709
710 const bool append_instructions = true;
711 DecodeInstructions (start,
712 data,
713 0,
714 num_instructions,
715 append_instructions);
716
Jim Ingham37023b02011-03-22 01:48:42 +0000717 return m_instruction_list.GetSize();
718}
719
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000720//----------------------------------------------------------------------
721// Disassembler copy constructor
722//----------------------------------------------------------------------
723Disassembler::Disassembler(const ArchSpec& arch) :
724 m_arch (arch),
725 m_instruction_list(),
726 m_base_addr(LLDB_INVALID_ADDRESS)
727{
728
729}
730
731//----------------------------------------------------------------------
732// Destructor
733//----------------------------------------------------------------------
734Disassembler::~Disassembler()
735{
736}
737
Greg Clayton1d273162010-10-06 03:09:58 +0000738InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000739Disassembler::GetInstructionList ()
740{
741 return m_instruction_list;
742}
743
Greg Clayton1d273162010-10-06 03:09:58 +0000744const InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000745Disassembler::GetInstructionList () const
746{
747 return m_instruction_list;
748}
Caroline Tice3ac67112011-04-19 23:30:03 +0000749
750//----------------------------------------------------------------------
751// Class PseudoInstruction
752//----------------------------------------------------------------------
753PseudoInstruction::PseudoInstruction () :
754 Instruction (Address(), eAddressClassUnknown),
755 m_description ()
756{
757}
758
759PseudoInstruction::~PseudoInstruction ()
760{
761}
762
763void
764PseudoInstruction::Dump (lldb_private::Stream *s,
765 uint32_t max_opcode_byte_size,
766 bool show_address,
767 bool show_bytes,
768 const lldb_private::ExecutionContext* exe_ctx,
769 bool raw)
770{
771 if (!s)
772 return;
773
774 if (show_bytes)
775 m_opcode.Dump (s, max_opcode_byte_size);
776
777 if (m_description.size() > 0)
778 s->Printf ("%s", m_description.c_str());
779 else
780 s->Printf ("<unknown>");
781
782}
783
784bool
785PseudoInstruction::DoesBranch () const
786{
787 // This is NOT a valid question for a pseudo instruction.
788 return false;
789}
790
791size_t
792PseudoInstruction::Decode (const lldb_private::Disassembler &disassembler,
793 const lldb_private::DataExtractor &data,
794 uint32_t data_offset)
795{
796 return m_opcode.GetByteSize();
797}
798
799
800void
801PseudoInstruction::SetOpcode (size_t opcode_size, void *opcode_data)
802{
803 if (!opcode_data)
804 return;
805
806 switch (opcode_size)
807 {
808 case 8:
809 {
810 uint8_t value8 = *((uint8_t *) opcode_data);
811 m_opcode.SetOpcode8 (value8);
812 break;
813 }
814 case 16:
815 {
816 uint16_t value16 = *((uint16_t *) opcode_data);
817 m_opcode.SetOpcode16 (value16);
818 break;
819 }
820 case 32:
821 {
822 uint32_t value32 = *((uint32_t *) opcode_data);
823 m_opcode.SetOpcode32 (value32);
824 break;
825 }
826 case 64:
827 {
828 uint64_t value64 = *((uint64_t *) opcode_data);
829 m_opcode.SetOpcode64 (value64);
830 break;
831 }
832 default:
833 break;
834 }
835}
836
837void
838PseudoInstruction::SetDescription (const char *description)
839{
840 if (description && strlen (description) > 0)
841 m_description = description;
842}