blob: c765e6cb939c58013dd6934c506adad975eae536 [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"
Caroline Ticede2fb9c2011-04-22 05:08:45 +000024#include "lldb/Core/RegularExpression.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000025#include "lldb/Core/Timer.h"
Caroline Ticede2fb9c2011-04-22 05:08:45 +000026#include "lldb/Interpreter/NamedOptionValue.h"
Chris Lattner30fdc8d2010-06-08 16:52:24 +000027#include "lldb/Symbol/ObjectFile.h"
28#include "lldb/Target/ExecutionContext.h"
29#include "lldb/Target/Process.h"
30#include "lldb/Target/StackFrame.h"
31#include "lldb/Target/Target.h"
32
33#define DEFAULT_DISASM_BYTE_SIZE 32
34
35using namespace lldb;
36using namespace lldb_private;
37
38
39Disassembler*
Greg Clayton1080edbc2011-03-25 18:03:16 +000040Disassembler::FindPlugin (const ArchSpec &arch, const char *plugin_name)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000041{
42 Timer scoped_timer (__PRETTY_FUNCTION__,
Greg Clayton1080edbc2011-03-25 18:03:16 +000043 "Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
44 arch.GetArchitectureName(),
45 plugin_name);
Chris Lattner30fdc8d2010-06-08 16:52:24 +000046
47 std::auto_ptr<Disassembler> disassembler_ap;
Greg Clayton1080edbc2011-03-25 18:03:16 +000048 DisassemblerCreateInstance create_callback = NULL;
49
50 if (plugin_name)
Chris Lattner30fdc8d2010-06-08 16:52:24 +000051 {
Greg Clayton1080edbc2011-03-25 18:03:16 +000052 create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName (plugin_name);
53 if (create_callback)
54 {
55 disassembler_ap.reset (create_callback(arch));
56
57 if (disassembler_ap.get())
58 return disassembler_ap.release();
59 }
60 }
61 else
62 {
63 for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != NULL; ++idx)
64 {
65 disassembler_ap.reset (create_callback(arch));
Chris Lattner30fdc8d2010-06-08 16:52:24 +000066
Greg Clayton1080edbc2011-03-25 18:03:16 +000067 if (disassembler_ap.get())
68 return disassembler_ap.release();
69 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +000070 }
71 return NULL;
72}
73
Greg Claytondda4f7b2010-06-30 23:03:03 +000074
Greg Clayton357132e2011-03-26 19:14:58 +000075static void
76ResolveAddress (const ExecutionContext &exe_ctx,
77 const Address &addr,
78 Address &resolved_addr)
79{
80 if (!addr.IsSectionOffset())
81 {
82 // If we weren't passed in a section offset address range,
83 // try and resolve it to something
84 if (exe_ctx.target)
85 {
86 if (exe_ctx.target->GetSectionLoadList().IsEmpty())
87 {
88 exe_ctx.target->GetImages().ResolveFileAddress (addr.GetOffset(), resolved_addr);
89 }
90 else
91 {
92 exe_ctx.target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), resolved_addr);
93 }
94 // We weren't able to resolve the address, just treat it as a
95 // raw address
96 if (resolved_addr.IsValid())
97 return;
98 }
99 }
100 resolved_addr = addr;
101}
Greg Claytondda4f7b2010-06-30 23:03:03 +0000102
103size_t
104Disassembler::Disassemble
105(
106 Debugger &debugger,
107 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000108 const char *plugin_name,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000109 const ExecutionContext &exe_ctx,
110 SymbolContextList &sc_list,
Jim Ingham37023b02011-03-22 01:48:42 +0000111 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000112 uint32_t num_mixed_context_lines,
113 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000114 bool raw,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000115 Stream &strm
116)
117{
118 size_t success_count = 0;
119 const size_t count = sc_list.GetSize();
120 SymbolContext sc;
121 AddressRange range;
Greg Clayton7e14f912011-04-23 02:04:55 +0000122 const uint32_t scope = eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol;
123 const bool use_inline_block_range = true;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000124 for (size_t i=0; i<count; ++i)
125 {
126 if (sc_list.GetContextAtIndex(i, sc) == false)
127 break;
Greg Clayton7e14f912011-04-23 02:04:55 +0000128 for (uint32_t range_idx = 0; sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); ++range_idx)
Greg Claytondda4f7b2010-06-30 23:03:03 +0000129 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000130 if (Disassemble (debugger,
131 arch,
132 plugin_name,
133 exe_ctx,
134 range,
135 num_instructions,
136 num_mixed_context_lines,
137 show_bytes,
138 raw,
139 strm))
Greg Claytondda4f7b2010-06-30 23:03:03 +0000140 {
141 ++success_count;
142 strm.EOL();
143 }
144 }
145 }
146 return success_count;
147}
148
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000149bool
150Disassembler::Disassemble
151(
Greg Clayton66111032010-06-23 01:19:29 +0000152 Debugger &debugger,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000153 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000154 const char *plugin_name,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000155 const ExecutionContext &exe_ctx,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000156 const ConstString &name,
157 Module *module,
Jim Ingham37023b02011-03-22 01:48:42 +0000158 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000159 uint32_t num_mixed_context_lines,
160 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000161 bool raw,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000162 Stream &strm
163)
164{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000165 SymbolContextList sc_list;
Greg Clayton931180e2011-01-27 06:44:37 +0000166 if (name)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000167 {
Greg Clayton931180e2011-01-27 06:44:37 +0000168 const bool include_symbols = true;
169 if (module)
170 {
171 module->FindFunctions (name,
172 eFunctionNameTypeBase |
173 eFunctionNameTypeFull |
174 eFunctionNameTypeMethod |
175 eFunctionNameTypeSelector,
176 include_symbols,
177 true,
178 sc_list);
179 }
180 else if (exe_ctx.target)
181 {
182 exe_ctx.target->GetImages().FindFunctions (name,
Greg Clayton6dbd3982010-09-15 05:51:24 +0000183 eFunctionNameTypeBase |
184 eFunctionNameTypeFull |
185 eFunctionNameTypeMethod |
186 eFunctionNameTypeSelector,
Greg Clayton931180e2011-01-27 06:44:37 +0000187 include_symbols,
Sean Callanan8ade1042010-07-27 00:55:47 +0000188 false,
Greg Clayton931180e2011-01-27 06:44:37 +0000189 sc_list);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000190 }
Greg Clayton931180e2011-01-27 06:44:37 +0000191 }
192
193 if (sc_list.GetSize ())
194 {
195 return Disassemble (debugger,
196 arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000197 plugin_name,
Greg Clayton931180e2011-01-27 06:44:37 +0000198 exe_ctx,
Jim Ingham37023b02011-03-22 01:48:42 +0000199 sc_list,
200 num_instructions,
Greg Clayton931180e2011-01-27 06:44:37 +0000201 num_mixed_context_lines,
Sean Callananb3396b22011-03-10 23:35:12 +0000202 show_bytes,
203 raw,
Greg Clayton931180e2011-01-27 06:44:37 +0000204 strm);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000205 }
206 return false;
207}
208
Greg Clayton1d273162010-10-06 03:09:58 +0000209
210lldb::DisassemblerSP
211Disassembler::DisassembleRange
212(
213 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000214 const char *plugin_name,
Greg Clayton1d273162010-10-06 03:09:58 +0000215 const ExecutionContext &exe_ctx,
216 const AddressRange &range
217)
218{
219 lldb::DisassemblerSP disasm_sp;
220 if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid())
221 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000222 disasm_sp.reset (Disassembler::FindPlugin(arch, plugin_name));
Greg Clayton1d273162010-10-06 03:09:58 +0000223
224 if (disasm_sp)
225 {
Greg Clayton357132e2011-03-26 19:14:58 +0000226 size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range);
Greg Clayton1d273162010-10-06 03:09:58 +0000227 if (bytes_disassembled == 0)
228 disasm_sp.reset();
229 }
230 }
231 return disasm_sp;
232}
233
234
Greg Claytondda4f7b2010-06-30 23:03:03 +0000235bool
236Disassembler::Disassemble
237(
238 Debugger &debugger,
239 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000240 const char *plugin_name,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000241 const ExecutionContext &exe_ctx,
242 const AddressRange &disasm_range,
Jim Ingham37023b02011-03-22 01:48:42 +0000243 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000244 uint32_t num_mixed_context_lines,
245 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000246 bool raw,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000247 Stream &strm
248)
249{
250 if (disasm_range.GetByteSize())
251 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000252 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name));
Greg Claytondda4f7b2010-06-30 23:03:03 +0000253
Greg Clayton1d273162010-10-06 03:09:58 +0000254 if (disasm_ap.get())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000255 {
Greg Clayton357132e2011-03-26 19:14:58 +0000256 AddressRange range;
257 ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress());
258 range.SetByteSize (disasm_range.GetByteSize());
Greg Claytondda4f7b2010-06-30 23:03:03 +0000259
Greg Clayton357132e2011-03-26 19:14:58 +0000260 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, range);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000261 if (bytes_disassembled == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000262 return false;
Greg Clayton1080edbc2011-03-25 18:03:16 +0000263
264 return PrintInstructions (disasm_ap.get(),
265 debugger,
266 arch,
267 exe_ctx,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000268 num_instructions,
269 num_mixed_context_lines,
270 show_bytes,
271 raw,
272 strm);
Jim Ingham37023b02011-03-22 01:48:42 +0000273 }
274 }
275 return false;
276}
277
278bool
279Disassembler::Disassemble
280(
281 Debugger &debugger,
282 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000283 const char *plugin_name,
Jim Ingham37023b02011-03-22 01:48:42 +0000284 const ExecutionContext &exe_ctx,
285 const Address &start_address,
286 uint32_t num_instructions,
287 uint32_t num_mixed_context_lines,
288 bool show_bytes,
289 bool raw,
290 Stream &strm
291)
292{
293 if (num_instructions > 0)
294 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000295 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name));
Jim Ingham37023b02011-03-22 01:48:42 +0000296 if (disasm_ap.get())
297 {
Greg Clayton357132e2011-03-26 19:14:58 +0000298 Address addr;
299 ResolveAddress (exe_ctx, start_address, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000300
Greg Clayton357132e2011-03-26 19:14:58 +0000301 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, addr, num_instructions);
Jim Ingham37023b02011-03-22 01:48:42 +0000302 if (bytes_disassembled == 0)
Jim Ingham37023b02011-03-22 01:48:42 +0000303 return false;
Greg Clayton1080edbc2011-03-25 18:03:16 +0000304 return PrintInstructions (disasm_ap.get(),
305 debugger,
306 arch,
307 exe_ctx,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000308 num_instructions,
309 num_mixed_context_lines,
310 show_bytes,
311 raw,
312 strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000313 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000314 }
315 return false;
316}
Jim Ingham37023b02011-03-22 01:48:42 +0000317
318bool
319Disassembler::PrintInstructions
320(
321 Disassembler *disasm_ptr,
Jim Ingham37023b02011-03-22 01:48:42 +0000322 Debugger &debugger,
323 const ArchSpec &arch,
324 const ExecutionContext &exe_ctx,
Jim Ingham37023b02011-03-22 01:48:42 +0000325 uint32_t num_instructions,
326 uint32_t num_mixed_context_lines,
327 bool show_bytes,
328 bool raw,
329 Stream &strm
330)
331{
332 // We got some things disassembled...
333 size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
334
335 if (num_instructions > 0 && num_instructions < num_instructions_found)
336 num_instructions_found = num_instructions;
337
Greg Clayton357132e2011-03-26 19:14:58 +0000338 const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
Jim Ingham37023b02011-03-22 01:48:42 +0000339 uint32_t offset = 0;
340 SymbolContext sc;
341 SymbolContext prev_sc;
342 AddressRange sc_range;
Greg Clayton32e0a752011-03-30 18:16:51 +0000343 Address *pc_addr_ptr = NULL;
Greg Clayton7e14f912011-04-23 02:04:55 +0000344 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton32e0a752011-03-30 18:16:51 +0000345 if (exe_ctx.frame)
346 pc_addr_ptr = &exe_ctx.frame->GetFrameCodeAddress();
Greg Clayton7e14f912011-04-23 02:04:55 +0000347 const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
348 const bool use_inline_block_range = false;
Jim Ingham37023b02011-03-22 01:48:42 +0000349
350 for (size_t i=0; i<num_instructions_found; ++i)
351 {
352 Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
353 if (inst)
354 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000355 const Address &addr = inst->GetAddress();
356 const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
Jim Ingham37023b02011-03-22 01:48:42 +0000357
358 prev_sc = sc;
359
Greg Clayton32e0a752011-03-30 18:16:51 +0000360 Module *module = addr.GetModule();
361 if (module)
Jim Ingham37023b02011-03-22 01:48:42 +0000362 {
Jim Ingham37023b02011-03-22 01:48:42 +0000363 uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
364 if (resolved_mask)
365 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000366 if (num_mixed_context_lines)
367 {
368 if (!sc_range.ContainsFileAddress (addr))
369 {
Greg Clayton7e14f912011-04-23 02:04:55 +0000370 sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range);
Greg Clayton32e0a752011-03-30 18:16:51 +0000371
372 if (sc != prev_sc)
373 {
374 if (offset != 0)
375 strm.EOL();
376
377 sc.DumpStopContext(&strm, exe_ctx.process, addr, false, true, false);
378 strm.EOL();
379
380 if (sc.comp_unit && sc.line_entry.IsValid())
381 {
Greg Clayton7e14f912011-04-23 02:04:55 +0000382 debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (debugger.GetTargetList().GetSelectedTarget().get(),
383 sc.line_entry.file,
Greg Clayton32e0a752011-03-30 18:16:51 +0000384 sc.line_entry.line,
385 num_mixed_context_lines,
386 num_mixed_context_lines,
387 num_mixed_context_lines ? "->" : "",
388 &strm);
389 }
390 }
391 }
392 }
393 else if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol))
Jim Ingham37023b02011-03-22 01:48:42 +0000394 {
395 if (prev_sc.function || prev_sc.symbol)
396 strm.EOL();
397
Greg Clayton7e14f912011-04-23 02:04:55 +0000398 bool show_fullpaths = false;
399 bool show_module = true;
400 bool show_inlined_frames = true;
401 sc.DumpStopContext (&strm,
402 exe_scope,
403 addr,
404 show_fullpaths,
405 show_module,
406 show_inlined_frames);
Jim Ingham37023b02011-03-22 01:48:42 +0000407
Jim Ingham37023b02011-03-22 01:48:42 +0000408 strm << ":\n";
409 }
Jim Ingham37023b02011-03-22 01:48:42 +0000410 }
411 else
412 {
413 sc.Clear();
414 }
415 }
Jim Ingham37023b02011-03-22 01:48:42 +0000416
Greg Clayton32e0a752011-03-30 18:16:51 +0000417 if (pc_addr_ptr)
418 {
419 if (inst_is_at_pc)
420 strm.PutCString("-> ");
421 else
422 strm.PutCString(" ");
423 }
424 inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, raw);
425 strm.EOL();
Jim Ingham37023b02011-03-22 01:48:42 +0000426 }
427 else
428 {
429 break;
430 }
431 }
Jim Ingham37023b02011-03-22 01:48:42 +0000432
433 return true;
434}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000435
Greg Claytondda4f7b2010-06-30 23:03:03 +0000436
437bool
438Disassembler::Disassemble
439(
440 Debugger &debugger,
441 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000442 const char *plugin_name,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000443 const ExecutionContext &exe_ctx,
Jim Ingham37023b02011-03-22 01:48:42 +0000444 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000445 uint32_t num_mixed_context_lines,
446 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000447 bool raw,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000448 Stream &strm
449)
450{
451 AddressRange range;
452 if (exe_ctx.frame)
453 {
454 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
455 if (sc.function)
456 {
457 range = sc.function->GetAddressRange();
458 }
459 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
460 {
461 range = *sc.symbol->GetAddressRangePtr();
462 }
463 else
464 {
Greg Clayton9da7bd02010-08-24 21:05:24 +0000465 range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
Greg Claytondda4f7b2010-06-30 23:03:03 +0000466 }
467
468 if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
469 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
470 }
471
Greg Clayton1080edbc2011-03-25 18:03:16 +0000472 return Disassemble (debugger,
473 arch,
474 plugin_name,
475 exe_ctx,
476 range,
477 num_instructions,
478 num_mixed_context_lines,
479 show_bytes,
480 raw,
481 strm);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000482}
483
Greg Clayton357132e2011-03-26 19:14:58 +0000484Instruction::Instruction(const Address &address, AddressClass addr_class) :
Greg Clayton1080edbc2011-03-25 18:03:16 +0000485 m_address (address),
Greg Clayton357132e2011-03-26 19:14:58 +0000486 m_address_class (addr_class),
Greg Clayton1080edbc2011-03-25 18:03:16 +0000487 m_opcode()
Greg Clayton0ae96272011-03-24 23:53:38 +0000488{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000489}
490
Greg Clayton1d273162010-10-06 03:09:58 +0000491Instruction::~Instruction()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000492{
493}
494
Greg Clayton357132e2011-03-26 19:14:58 +0000495AddressClass
496Instruction::GetAddressClass ()
497{
498 if (m_address_class == eAddressClassInvalid)
499 m_address_class = m_address.GetAddressClass();
500 return m_address_class;
501}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000502
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000503bool
504Instruction::DumpEmulation (const ArchSpec &arch)
505{
506 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL));
507 if (insn_emulator_ap.get())
508 {
509 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress());
510 return insn_emulator_ap->EvaluateInstruction ();
511 }
512
513 return false;
514}
515
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000516OptionValueSP
517Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type)
518{
519 bool done = false;
520 char buffer[1024];
521
522 OptionValueSP option_value_sp (new OptionValueArray (1u << data_type));
523
524 int idx = 0;
525 while (!done)
526 {
527 if (!fgets (buffer, 1023, in_file))
528 {
529 out_stream->Printf ("Instruction::ReadArray: Erroe reading file (fgets).\n");
530 option_value_sp.reset ();
531 return option_value_sp;
532 }
533
534 std::string line (buffer);
535
536 int len = line.size();
537 if (line[len-1] == '\n')
538 {
539 line[len-1] = '\0';
540 line.resize (len-1);
541 }
542
543 if ((line.size() == 1) && line[0] == ']')
544 {
545 done = true;
546 line.clear();
547 }
548
549 if (line.size() > 0)
550 {
551 std::string value;
552 RegularExpression reg_exp ("^[ \t]*([^ \t]+)[ \t]*$");
553 bool reg_exp_success = reg_exp.Execute (line.c_str(), 1);
554 if (reg_exp_success)
555 reg_exp.GetMatchAtIndex (line.c_str(), 1, value);
556 else
557 value = line;
558
559 OptionValueSP data_value_sp;
560 switch (data_type)
561 {
562 case OptionValue::eTypeUInt64:
563 data_value_sp.reset (new OptionValueUInt64 (0, 0));
564 data_value_sp->SetValueFromCString (value.c_str());
565 break;
566 // Other types can be added later as needed.
567 default:
568 data_value_sp.reset (new OptionValueString (value.c_str(), ""));
569 break;
570 }
571
572 option_value_sp->GetAsArrayValue()->InsertValue (idx, data_value_sp);
573 ++idx;
574 }
575 }
576
577 return option_value_sp;
578}
579
580OptionValueSP
581Instruction::ReadDictionary (FILE *in_file, Stream *out_stream)
582{
583 bool done = false;
584 char buffer[1024];
585
586 OptionValueSP option_value_sp (new OptionValueDictionary());
587 static ConstString encoding_key ("data_encoding");
588 OptionValue::Type data_type = OptionValue::eTypeInvalid;
589
590
591 while (!done)
592 {
593 // Read the next line in the file
594 if (!fgets (buffer, 1023, in_file))
595 {
596 out_stream->Printf ("Instruction::ReadDictionary: Error reading file (fgets).\n");
597 option_value_sp.reset ();
598 return option_value_sp;
599 }
600
601 // Check to see if the line contains the end-of-dictionary marker ("}")
602 std::string line (buffer);
603
604 int len = line.size();
605 if (line[len-1] == '\n')
606 {
607 line[len-1] = '\0';
608 line.resize (len-1);
609 }
610
611 if ((line.size() == 1) && (line[0] == '}'))
612 {
613 done = true;
614 line.clear();
615 }
616
617 // Try to find a key-value pair in the current line and add it to the dictionary.
618 if (line.size() > 0)
619 {
620 RegularExpression reg_exp ("^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$");
621 bool reg_exp_success = reg_exp.Execute (line.c_str(), 2);
622 std::string key;
623 std::string value;
624 if (reg_exp_success)
625 {
626 reg_exp.GetMatchAtIndex (line.c_str(), 1, key);
627 reg_exp.GetMatchAtIndex (line.c_str(), 2, value);
628 }
629 else
630 {
631 out_stream->Printf ("Instruction::ReadDictionary: Failure executing regular expression.\n");
632 option_value_sp.reset();
633 return option_value_sp;
634 }
635
636 ConstString const_key (key.c_str());
637 // Check value to see if it's the start of an array or dictionary.
638
639 lldb::OptionValueSP value_sp;
640 assert (value.empty() == false);
641 assert (key.empty() == false);
642
643 if (value[0] == '{')
644 {
645 assert (value.size() == 1);
646 // value is a dictionary
647 value_sp = ReadDictionary (in_file, out_stream);
648 if (value_sp.get() == NULL)
649 {
650 option_value_sp.reset ();
651 return option_value_sp;
652 }
653 }
654 else if (value[0] == '[')
655 {
656 assert (value.size() == 1);
657 // value is an array
658 value_sp = ReadArray (in_file, out_stream, data_type);
659 if (value_sp.get() == NULL)
660 {
661 option_value_sp.reset ();
662 return option_value_sp;
663 }
664 // We've used the data_type to read an array; re-set the type to Invalid
665 data_type = OptionValue::eTypeInvalid;
666 }
667 else if ((value[0] == '0') && (value[1] == 'x'))
668 {
669 value_sp.reset (new OptionValueUInt64 (0, 0));
670 value_sp->SetValueFromCString (value.c_str());
671 }
672 else
673 {
674 int len = value.size();
675 if ((value[0] == '"') && (value[len-1] == '"'))
676 value = value.substr (1, len-2);
677 value_sp.reset (new OptionValueString (value.c_str(), ""));
678 }
679
680
681
682 if (const_key == encoding_key)
683 {
684 // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data indicating the
685 // data type of an upcoming array (usually the next bit of data to be read in).
686 if (strcmp (value.c_str(), "uint32_t") == 0)
687 data_type = OptionValue::eTypeUInt64;
688 }
689 else
690 option_value_sp->GetAsDictionaryValue()->SetValueForKey (const_key, value_sp, false);
691 }
692 }
693
694 return option_value_sp;
695}
696
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000697bool
Caroline Tice3ac67112011-04-19 23:30:03 +0000698Instruction::TestEmulation (Stream *out_stream, const char *file_name)
699{
700 if (!out_stream)
701 return false;
702
703 if (!file_name)
704 {
Johnny Chenea80ba82011-04-21 20:27:45 +0000705 out_stream->Printf ("Instruction::TestEmulation: Missing file_name.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000706 return false;
707 }
708
709 FILE *test_file = fopen (file_name, "r");
710 if (!test_file)
711 {
Johnny Chenea80ba82011-04-21 20:27:45 +0000712 out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000713 return false;
714 }
715
Caroline Tice3ac67112011-04-19 23:30:03 +0000716 char buffer[256];
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000717 if (!fgets (buffer, 255, test_file))
Caroline Tice3ac67112011-04-19 23:30:03 +0000718 {
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000719 out_stream->Printf ("Instruction::TestEmulation: Error reading first line of test file.\n");
Caroline Tice3ac67112011-04-19 23:30:03 +0000720 fclose (test_file);
721 return false;
722 }
723
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000724 if (strncmp (buffer, "InstructionEmulationState={", 27) != 0)
725 {
726 out_stream->Printf ("Instructin::TestEmulation: Test file does not contain emulation state dictionary\n");
727 fclose (test_file);
728 return false;
729 }
730
731 // Read all the test information from the test file into an OptionValueDictionary.
732
733 OptionValueSP data_dictionary_sp (ReadDictionary (test_file, out_stream));
734 if (data_dictionary_sp.get() == NULL)
735 {
736 out_stream->Printf ("Instruction::TestEmulation: Error reading Dictionary Object.\n");
737 fclose (test_file);
738 return false;
739 }
740
741 fclose (test_file);
742
743 OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionaryValue();
744 static ConstString description_key ("assembly_string");
745 static ConstString triple_key ("triple");
746
747 OptionValueSP value_sp = data_dictionary->GetValueForKey (description_key);
748
749 if (value_sp.get() == NULL)
750 {
751 out_stream->Printf ("Instruction::TestEmulation: Test file does not contain description string.\n");
752 return false;
753 }
754
755 SetDescription (value_sp->GetStringValue());
756
757
758 value_sp = data_dictionary->GetValueForKey (triple_key);
759 if (value_sp.get() == NULL)
760 {
761 out_stream->Printf ("Instruction::TestEmulation: Test file does not contain triple.\n");
762 return false;
763 }
764
765 ArchSpec arch;
766 arch.SetTriple (llvm::Triple (value_sp->GetStringValue()));
Caroline Tice3ac67112011-04-19 23:30:03 +0000767
768 bool success = false;
769 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL));
770 if (insn_emulator_ap.get())
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000771 success = insn_emulator_ap->TestEmulation (out_stream, arch, data_dictionary);
Caroline Tice3ac67112011-04-19 23:30:03 +0000772
Caroline Tice3ac67112011-04-19 23:30:03 +0000773 if (success)
Johnny Chenea80ba82011-04-21 20:27:45 +0000774 out_stream->Printf ("Emulation test succeeded.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000775 else
Johnny Chenea80ba82011-04-21 20:27:45 +0000776 out_stream->Printf ("Emulation test failed.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000777
778 return success;
779}
780
781bool
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000782Instruction::Emulate (const ArchSpec &arch,
Caroline Tice25d61ac2011-04-08 23:33:06 +0000783 bool auto_advance_pc,
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000784 void *baton,
785 EmulateInstruction::ReadMemory read_mem_callback,
786 EmulateInstruction::WriteMemory write_mem_callback,
787 EmulateInstruction::ReadRegister read_reg_callback,
788 EmulateInstruction::WriteRegister write_reg_callback)
789{
790 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL));
791 if (insn_emulator_ap.get())
792 {
793 insn_emulator_ap->SetBaton (baton);
794 insn_emulator_ap->SetCallbacks (read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback);
795 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress());
Caroline Tice25d61ac2011-04-08 23:33:06 +0000796 insn_emulator_ap->SetAdvancePC (auto_advance_pc);
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000797 return insn_emulator_ap->EvaluateInstruction ();
798 }
799
800 return false;
801}
802
Greg Clayton1d273162010-10-06 03:09:58 +0000803InstructionList::InstructionList() :
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000804 m_instructions()
805{
806}
807
Greg Clayton1d273162010-10-06 03:09:58 +0000808InstructionList::~InstructionList()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000809{
810}
811
812size_t
Greg Clayton1d273162010-10-06 03:09:58 +0000813InstructionList::GetSize() const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000814{
815 return m_instructions.size();
816}
817
Greg Clayton357132e2011-03-26 19:14:58 +0000818uint32_t
819InstructionList::GetMaxOpcocdeByteSize () const
820{
821 uint32_t max_inst_size = 0;
822 collection::const_iterator pos, end;
823 for (pos = m_instructions.begin(), end = m_instructions.end();
824 pos != end;
825 ++pos)
826 {
827 uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
828 if (max_inst_size < inst_size)
829 max_inst_size = inst_size;
830 }
831 return max_inst_size;
832}
833
834
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000835
Greg Clayton1d273162010-10-06 03:09:58 +0000836InstructionSP
837InstructionList::GetInstructionAtIndex (uint32_t idx) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000838{
Greg Clayton1d273162010-10-06 03:09:58 +0000839 InstructionSP inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000840 if (idx < m_instructions.size())
Greg Clayton1d273162010-10-06 03:09:58 +0000841 inst_sp = m_instructions[idx];
842 return inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000843}
844
845void
Greg Clayton1d273162010-10-06 03:09:58 +0000846InstructionList::Clear()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000847{
848 m_instructions.clear();
849}
850
851void
Greg Clayton1d273162010-10-06 03:09:58 +0000852InstructionList::Append (lldb::InstructionSP &inst_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000853{
854 if (inst_sp)
855 m_instructions.push_back(inst_sp);
856}
857
858
859size_t
860Disassembler::ParseInstructions
861(
862 const ExecutionContext *exe_ctx,
Greg Clayton357132e2011-03-26 19:14:58 +0000863 const AddressRange &range
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000864)
865{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000866 Target *target = exe_ctx->target;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000867 const addr_t byte_size = range.GetByteSize();
868 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000869 return 0;
870
Greg Claytondda4f7b2010-06-30 23:03:03 +0000871 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
872 DataBufferSP data_sp(heap_buffer);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000873
874 Error error;
Greg Clayton357132e2011-03-26 19:14:58 +0000875 const bool prefer_file_cache = true;
876 const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(),
877 prefer_file_cache,
878 heap_buffer->GetBytes(),
879 heap_buffer->GetByteSize(),
880 error);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000881
882 if (bytes_read > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000883 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000884 if (bytes_read != heap_buffer->GetByteSize())
885 heap_buffer->SetByteSize (bytes_read);
Greg Clayton357132e2011-03-26 19:14:58 +0000886 DataExtractor data (data_sp,
887 m_arch.GetByteOrder(),
888 m_arch.GetAddressByteSize());
Jim Ingham37023b02011-03-22 01:48:42 +0000889 return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000890 }
891
892 return 0;
893}
894
Jim Ingham37023b02011-03-22 01:48:42 +0000895size_t
896Disassembler::ParseInstructions
897(
898 const ExecutionContext *exe_ctx,
899 const Address &start,
Greg Clayton357132e2011-03-26 19:14:58 +0000900 uint32_t num_instructions
Jim Ingham37023b02011-03-22 01:48:42 +0000901)
902{
Greg Clayton357132e2011-03-26 19:14:58 +0000903 m_instruction_list.Clear();
904
905 if (num_instructions == 0 || !start.IsValid())
Jim Ingham37023b02011-03-22 01:48:42 +0000906 return 0;
907
908 Target *target = exe_ctx->target;
Greg Clayton357132e2011-03-26 19:14:58 +0000909 // Calculate the max buffer size we will need in order to disassemble
910 const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize();
Jim Ingham37023b02011-03-22 01:48:42 +0000911
Greg Clayton357132e2011-03-26 19:14:58 +0000912 if (target == NULL || byte_size == 0)
Jim Ingham37023b02011-03-22 01:48:42 +0000913 return 0;
914
915 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
Greg Clayton357132e2011-03-26 19:14:58 +0000916 DataBufferSP data_sp (heap_buffer);
Jim Ingham37023b02011-03-22 01:48:42 +0000917
918 Error error;
919 bool prefer_file_cache = true;
Greg Clayton357132e2011-03-26 19:14:58 +0000920 const size_t bytes_read = target->ReadMemory (start,
921 prefer_file_cache,
922 heap_buffer->GetBytes(),
923 byte_size,
924 error);
925
926 if (bytes_read == 0)
927 return 0;
928 DataExtractor data (data_sp,
929 m_arch.GetByteOrder(),
930 m_arch.GetAddressByteSize());
931
932 const bool append_instructions = true;
933 DecodeInstructions (start,
934 data,
935 0,
936 num_instructions,
937 append_instructions);
938
Jim Ingham37023b02011-03-22 01:48:42 +0000939 return m_instruction_list.GetSize();
940}
941
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000942//----------------------------------------------------------------------
943// Disassembler copy constructor
944//----------------------------------------------------------------------
945Disassembler::Disassembler(const ArchSpec& arch) :
946 m_arch (arch),
947 m_instruction_list(),
948 m_base_addr(LLDB_INVALID_ADDRESS)
949{
950
951}
952
953//----------------------------------------------------------------------
954// Destructor
955//----------------------------------------------------------------------
956Disassembler::~Disassembler()
957{
958}
959
Greg Clayton1d273162010-10-06 03:09:58 +0000960InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000961Disassembler::GetInstructionList ()
962{
963 return m_instruction_list;
964}
965
Greg Clayton1d273162010-10-06 03:09:58 +0000966const InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000967Disassembler::GetInstructionList () const
968{
969 return m_instruction_list;
970}
Caroline Tice3ac67112011-04-19 23:30:03 +0000971
972//----------------------------------------------------------------------
973// Class PseudoInstruction
974//----------------------------------------------------------------------
975PseudoInstruction::PseudoInstruction () :
976 Instruction (Address(), eAddressClassUnknown),
977 m_description ()
978{
979}
980
981PseudoInstruction::~PseudoInstruction ()
982{
983}
984
985void
986PseudoInstruction::Dump (lldb_private::Stream *s,
987 uint32_t max_opcode_byte_size,
988 bool show_address,
989 bool show_bytes,
990 const lldb_private::ExecutionContext* exe_ctx,
991 bool raw)
992{
993 if (!s)
994 return;
995
996 if (show_bytes)
997 m_opcode.Dump (s, max_opcode_byte_size);
998
999 if (m_description.size() > 0)
1000 s->Printf ("%s", m_description.c_str());
1001 else
1002 s->Printf ("<unknown>");
1003
1004}
1005
1006bool
1007PseudoInstruction::DoesBranch () const
1008{
1009 // This is NOT a valid question for a pseudo instruction.
1010 return false;
1011}
1012
1013size_t
1014PseudoInstruction::Decode (const lldb_private::Disassembler &disassembler,
1015 const lldb_private::DataExtractor &data,
1016 uint32_t data_offset)
1017{
1018 return m_opcode.GetByteSize();
1019}
1020
1021
1022void
1023PseudoInstruction::SetOpcode (size_t opcode_size, void *opcode_data)
1024{
1025 if (!opcode_data)
1026 return;
1027
1028 switch (opcode_size)
1029 {
1030 case 8:
1031 {
1032 uint8_t value8 = *((uint8_t *) opcode_data);
1033 m_opcode.SetOpcode8 (value8);
1034 break;
1035 }
1036 case 16:
1037 {
1038 uint16_t value16 = *((uint16_t *) opcode_data);
1039 m_opcode.SetOpcode16 (value16);
1040 break;
1041 }
1042 case 32:
1043 {
1044 uint32_t value32 = *((uint32_t *) opcode_data);
1045 m_opcode.SetOpcode32 (value32);
1046 break;
1047 }
1048 case 64:
1049 {
1050 uint64_t value64 = *((uint64_t *) opcode_data);
1051 m_opcode.SetOpcode64 (value64);
1052 break;
1053 }
1054 default:
1055 break;
1056 }
1057}
1058
1059void
1060PseudoInstruction::SetDescription (const char *description)
1061{
1062 if (description && strlen (description) > 0)
1063 m_description = description;
1064}