blob: 6d16e35918a21994f3fe811ec966798c4b9ea900 [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,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000113 uint32_t options,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000114 Stream &strm
115)
116{
117 size_t success_count = 0;
118 const size_t count = sc_list.GetSize();
119 SymbolContext sc;
120 AddressRange range;
Greg Clayton7e14f912011-04-23 02:04:55 +0000121 const uint32_t scope = eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol;
122 const bool use_inline_block_range = true;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000123 for (size_t i=0; i<count; ++i)
124 {
125 if (sc_list.GetContextAtIndex(i, sc) == false)
126 break;
Greg Clayton7e14f912011-04-23 02:04:55 +0000127 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 +0000128 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000129 if (Disassemble (debugger,
130 arch,
131 plugin_name,
132 exe_ctx,
133 range,
134 num_instructions,
135 num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000136 options,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000137 strm))
Greg Claytondda4f7b2010-06-30 23:03:03 +0000138 {
139 ++success_count;
140 strm.EOL();
141 }
142 }
143 }
144 return success_count;
145}
146
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000147bool
148Disassembler::Disassemble
149(
Greg Clayton66111032010-06-23 01:19:29 +0000150 Debugger &debugger,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000151 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000152 const char *plugin_name,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000153 const ExecutionContext &exe_ctx,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000154 const ConstString &name,
155 Module *module,
Jim Ingham37023b02011-03-22 01:48:42 +0000156 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000157 uint32_t num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000158 uint32_t options,
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,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000199 options,
Greg Clayton931180e2011-01-27 06:44:37 +0000200 strm);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000201 }
202 return false;
203}
204
Greg Clayton1d273162010-10-06 03:09:58 +0000205
206lldb::DisassemblerSP
207Disassembler::DisassembleRange
208(
209 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000210 const char *plugin_name,
Greg Clayton1d273162010-10-06 03:09:58 +0000211 const ExecutionContext &exe_ctx,
212 const AddressRange &range
213)
214{
215 lldb::DisassemblerSP disasm_sp;
216 if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid())
217 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000218 disasm_sp.reset (Disassembler::FindPlugin(arch, plugin_name));
Greg Clayton1d273162010-10-06 03:09:58 +0000219
220 if (disasm_sp)
221 {
Greg Clayton357132e2011-03-26 19:14:58 +0000222 size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range);
Greg Clayton1d273162010-10-06 03:09:58 +0000223 if (bytes_disassembled == 0)
224 disasm_sp.reset();
225 }
226 }
227 return disasm_sp;
228}
229
230
Greg Claytondda4f7b2010-06-30 23:03:03 +0000231bool
232Disassembler::Disassemble
233(
234 Debugger &debugger,
235 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000236 const char *plugin_name,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000237 const ExecutionContext &exe_ctx,
238 const AddressRange &disasm_range,
Jim Ingham37023b02011-03-22 01:48:42 +0000239 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000240 uint32_t num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000241 uint32_t options,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000242 Stream &strm
243)
244{
245 if (disasm_range.GetByteSize())
246 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000247 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name));
Greg Claytondda4f7b2010-06-30 23:03:03 +0000248
Greg Clayton1d273162010-10-06 03:09:58 +0000249 if (disasm_ap.get())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000250 {
Greg Clayton357132e2011-03-26 19:14:58 +0000251 AddressRange range;
252 ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress());
253 range.SetByteSize (disasm_range.GetByteSize());
Greg Claytondda4f7b2010-06-30 23:03:03 +0000254
Greg Clayton357132e2011-03-26 19:14:58 +0000255 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, range);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000256 if (bytes_disassembled == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000257 return false;
Greg Clayton1080edbc2011-03-25 18:03:16 +0000258
259 return PrintInstructions (disasm_ap.get(),
260 debugger,
261 arch,
262 exe_ctx,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000263 num_instructions,
264 num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000265 options,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000266 strm);
Jim Ingham37023b02011-03-22 01:48:42 +0000267 }
268 }
269 return false;
270}
271
272bool
273Disassembler::Disassemble
274(
275 Debugger &debugger,
276 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000277 const char *plugin_name,
Jim Ingham37023b02011-03-22 01:48:42 +0000278 const ExecutionContext &exe_ctx,
279 const Address &start_address,
280 uint32_t num_instructions,
281 uint32_t num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000282 uint32_t options,
Jim Ingham37023b02011-03-22 01:48:42 +0000283 Stream &strm
284)
285{
286 if (num_instructions > 0)
287 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000288 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name));
Jim Ingham37023b02011-03-22 01:48:42 +0000289 if (disasm_ap.get())
290 {
Greg Clayton357132e2011-03-26 19:14:58 +0000291 Address addr;
292 ResolveAddress (exe_ctx, start_address, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000293
Greg Clayton357132e2011-03-26 19:14:58 +0000294 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, addr, num_instructions);
Jim Ingham37023b02011-03-22 01:48:42 +0000295 if (bytes_disassembled == 0)
Jim Ingham37023b02011-03-22 01:48:42 +0000296 return false;
Greg Clayton1080edbc2011-03-25 18:03:16 +0000297 return PrintInstructions (disasm_ap.get(),
298 debugger,
299 arch,
300 exe_ctx,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000301 num_instructions,
302 num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000303 options,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000304 strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000305 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000306 }
307 return false;
308}
Jim Ingham37023b02011-03-22 01:48:42 +0000309
310bool
311Disassembler::PrintInstructions
312(
313 Disassembler *disasm_ptr,
Jim Ingham37023b02011-03-22 01:48:42 +0000314 Debugger &debugger,
315 const ArchSpec &arch,
316 const ExecutionContext &exe_ctx,
Jim Ingham37023b02011-03-22 01:48:42 +0000317 uint32_t num_instructions,
318 uint32_t num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000319 uint32_t options,
Jim Ingham37023b02011-03-22 01:48:42 +0000320 Stream &strm
321)
322{
323 // We got some things disassembled...
324 size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
325
326 if (num_instructions > 0 && num_instructions < num_instructions_found)
327 num_instructions_found = num_instructions;
328
Greg Clayton357132e2011-03-26 19:14:58 +0000329 const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
Jim Ingham37023b02011-03-22 01:48:42 +0000330 uint32_t offset = 0;
331 SymbolContext sc;
332 SymbolContext prev_sc;
333 AddressRange sc_range;
Greg Clayton32e0a752011-03-30 18:16:51 +0000334 Address *pc_addr_ptr = NULL;
Greg Clayton7e14f912011-04-23 02:04:55 +0000335 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Clayton32e0a752011-03-30 18:16:51 +0000336 if (exe_ctx.frame)
337 pc_addr_ptr = &exe_ctx.frame->GetFrameCodeAddress();
Greg Clayton7e14f912011-04-23 02:04:55 +0000338 const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
339 const bool use_inline_block_range = false;
Jim Ingham37023b02011-03-22 01:48:42 +0000340 for (size_t i=0; i<num_instructions_found; ++i)
341 {
342 Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
343 if (inst)
344 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000345 const Address &addr = inst->GetAddress();
346 const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
Jim Ingham37023b02011-03-22 01:48:42 +0000347
348 prev_sc = sc;
349
Greg Clayton32e0a752011-03-30 18:16:51 +0000350 Module *module = addr.GetModule();
351 if (module)
Jim Ingham37023b02011-03-22 01:48:42 +0000352 {
Jim Ingham37023b02011-03-22 01:48:42 +0000353 uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
354 if (resolved_mask)
355 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000356 if (num_mixed_context_lines)
357 {
358 if (!sc_range.ContainsFileAddress (addr))
359 {
Greg Clayton7e14f912011-04-23 02:04:55 +0000360 sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range);
Greg Clayton32e0a752011-03-30 18:16:51 +0000361
362 if (sc != prev_sc)
363 {
364 if (offset != 0)
365 strm.EOL();
366
367 sc.DumpStopContext(&strm, exe_ctx.process, addr, false, true, false);
368 strm.EOL();
369
370 if (sc.comp_unit && sc.line_entry.IsValid())
371 {
Greg Clayton7e14f912011-04-23 02:04:55 +0000372 debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (debugger.GetTargetList().GetSelectedTarget().get(),
373 sc.line_entry.file,
Greg Clayton32e0a752011-03-30 18:16:51 +0000374 sc.line_entry.line,
375 num_mixed_context_lines,
376 num_mixed_context_lines,
Greg Claytonb10d72f2011-06-28 19:01:40 +0000377 ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""),
Greg Clayton32e0a752011-03-30 18:16:51 +0000378 &strm);
379 }
380 }
381 }
382 }
383 else if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol))
Jim Ingham37023b02011-03-22 01:48:42 +0000384 {
385 if (prev_sc.function || prev_sc.symbol)
386 strm.EOL();
387
Greg Clayton7e14f912011-04-23 02:04:55 +0000388 bool show_fullpaths = false;
389 bool show_module = true;
390 bool show_inlined_frames = true;
391 sc.DumpStopContext (&strm,
392 exe_scope,
393 addr,
394 show_fullpaths,
395 show_module,
396 show_inlined_frames);
Jim Ingham37023b02011-03-22 01:48:42 +0000397
Jim Ingham37023b02011-03-22 01:48:42 +0000398 strm << ":\n";
399 }
Jim Ingham37023b02011-03-22 01:48:42 +0000400 }
401 else
402 {
403 sc.Clear();
404 }
405 }
Jim Ingham37023b02011-03-22 01:48:42 +0000406
Greg Claytonb10d72f2011-06-28 19:01:40 +0000407 if ((options & eOptionMarkPCAddress) && pc_addr_ptr)
Greg Clayton32e0a752011-03-30 18:16:51 +0000408 {
Greg Claytonb10d72f2011-06-28 19:01:40 +0000409 strm.PutCString(inst_is_at_pc ? "-> " : " ");
Greg Clayton32e0a752011-03-30 18:16:51 +0000410 }
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000411 const bool show_bytes = (options & eOptionShowBytes) != 0;
412 const bool raw = (options & eOptionRawOuput) != 0;
Greg Clayton32e0a752011-03-30 18:16:51 +0000413 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,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000435 uint32_t options,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000436 Stream &strm
437)
438{
439 AddressRange range;
440 if (exe_ctx.frame)
441 {
442 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
443 if (sc.function)
444 {
445 range = sc.function->GetAddressRange();
446 }
447 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
448 {
449 range = *sc.symbol->GetAddressRangePtr();
450 }
451 else
452 {
Greg Clayton9da7bd02010-08-24 21:05:24 +0000453 range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress();
Greg Claytondda4f7b2010-06-30 23:03:03 +0000454 }
455
456 if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
457 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
458 }
459
Greg Clayton1080edbc2011-03-25 18:03:16 +0000460 return Disassemble (debugger,
461 arch,
462 plugin_name,
463 exe_ctx,
464 range,
465 num_instructions,
466 num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000467 options,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000468 strm);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000469}
470
Greg Clayton357132e2011-03-26 19:14:58 +0000471Instruction::Instruction(const Address &address, AddressClass addr_class) :
Greg Clayton1080edbc2011-03-25 18:03:16 +0000472 m_address (address),
Greg Clayton357132e2011-03-26 19:14:58 +0000473 m_address_class (addr_class),
Greg Clayton1080edbc2011-03-25 18:03:16 +0000474 m_opcode()
Greg Clayton0ae96272011-03-24 23:53:38 +0000475{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000476}
477
Greg Clayton1d273162010-10-06 03:09:58 +0000478Instruction::~Instruction()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000479{
480}
481
Greg Clayton357132e2011-03-26 19:14:58 +0000482AddressClass
483Instruction::GetAddressClass ()
484{
485 if (m_address_class == eAddressClassInvalid)
486 m_address_class = m_address.GetAddressClass();
487 return m_address_class;
488}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000489
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000490bool
491Instruction::DumpEmulation (const ArchSpec &arch)
492{
Greg Clayton2ed751b2011-04-26 04:39:08 +0000493 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL));
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000494 if (insn_emulator_ap.get())
495 {
Greg Clayton2ed751b2011-04-26 04:39:08 +0000496 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress(), NULL);
497 return insn_emulator_ap->EvaluateInstruction (0);
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000498 }
499
500 return false;
501}
502
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000503OptionValueSP
504Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type)
505{
506 bool done = false;
507 char buffer[1024];
508
509 OptionValueSP option_value_sp (new OptionValueArray (1u << data_type));
510
511 int idx = 0;
512 while (!done)
513 {
514 if (!fgets (buffer, 1023, in_file))
515 {
516 out_stream->Printf ("Instruction::ReadArray: Erroe reading file (fgets).\n");
517 option_value_sp.reset ();
518 return option_value_sp;
519 }
520
521 std::string line (buffer);
522
523 int len = line.size();
524 if (line[len-1] == '\n')
525 {
526 line[len-1] = '\0';
527 line.resize (len-1);
528 }
529
530 if ((line.size() == 1) && line[0] == ']')
531 {
532 done = true;
533 line.clear();
534 }
535
536 if (line.size() > 0)
537 {
538 std::string value;
539 RegularExpression reg_exp ("^[ \t]*([^ \t]+)[ \t]*$");
540 bool reg_exp_success = reg_exp.Execute (line.c_str(), 1);
541 if (reg_exp_success)
542 reg_exp.GetMatchAtIndex (line.c_str(), 1, value);
543 else
544 value = line;
545
546 OptionValueSP data_value_sp;
547 switch (data_type)
548 {
549 case OptionValue::eTypeUInt64:
550 data_value_sp.reset (new OptionValueUInt64 (0, 0));
551 data_value_sp->SetValueFromCString (value.c_str());
552 break;
553 // Other types can be added later as needed.
554 default:
555 data_value_sp.reset (new OptionValueString (value.c_str(), ""));
556 break;
557 }
558
Greg Clayton84c39662011-04-27 22:04:39 +0000559 option_value_sp->GetAsArray()->InsertValue (idx, data_value_sp);
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000560 ++idx;
561 }
562 }
563
564 return option_value_sp;
565}
566
567OptionValueSP
568Instruction::ReadDictionary (FILE *in_file, Stream *out_stream)
569{
570 bool done = false;
571 char buffer[1024];
572
573 OptionValueSP option_value_sp (new OptionValueDictionary());
574 static ConstString encoding_key ("data_encoding");
575 OptionValue::Type data_type = OptionValue::eTypeInvalid;
576
577
578 while (!done)
579 {
580 // Read the next line in the file
581 if (!fgets (buffer, 1023, in_file))
582 {
583 out_stream->Printf ("Instruction::ReadDictionary: Error reading file (fgets).\n");
584 option_value_sp.reset ();
585 return option_value_sp;
586 }
587
588 // Check to see if the line contains the end-of-dictionary marker ("}")
589 std::string line (buffer);
590
591 int len = line.size();
592 if (line[len-1] == '\n')
593 {
594 line[len-1] = '\0';
595 line.resize (len-1);
596 }
597
598 if ((line.size() == 1) && (line[0] == '}'))
599 {
600 done = true;
601 line.clear();
602 }
603
604 // Try to find a key-value pair in the current line and add it to the dictionary.
605 if (line.size() > 0)
606 {
607 RegularExpression reg_exp ("^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$");
608 bool reg_exp_success = reg_exp.Execute (line.c_str(), 2);
609 std::string key;
610 std::string value;
611 if (reg_exp_success)
612 {
613 reg_exp.GetMatchAtIndex (line.c_str(), 1, key);
614 reg_exp.GetMatchAtIndex (line.c_str(), 2, value);
615 }
616 else
617 {
618 out_stream->Printf ("Instruction::ReadDictionary: Failure executing regular expression.\n");
619 option_value_sp.reset();
620 return option_value_sp;
621 }
622
623 ConstString const_key (key.c_str());
624 // Check value to see if it's the start of an array or dictionary.
625
626 lldb::OptionValueSP value_sp;
627 assert (value.empty() == false);
628 assert (key.empty() == false);
629
630 if (value[0] == '{')
631 {
632 assert (value.size() == 1);
633 // value is a dictionary
634 value_sp = ReadDictionary (in_file, out_stream);
635 if (value_sp.get() == NULL)
636 {
637 option_value_sp.reset ();
638 return option_value_sp;
639 }
640 }
641 else if (value[0] == '[')
642 {
643 assert (value.size() == 1);
644 // value is an array
645 value_sp = ReadArray (in_file, out_stream, data_type);
646 if (value_sp.get() == NULL)
647 {
648 option_value_sp.reset ();
649 return option_value_sp;
650 }
651 // We've used the data_type to read an array; re-set the type to Invalid
652 data_type = OptionValue::eTypeInvalid;
653 }
654 else if ((value[0] == '0') && (value[1] == 'x'))
655 {
656 value_sp.reset (new OptionValueUInt64 (0, 0));
657 value_sp->SetValueFromCString (value.c_str());
658 }
659 else
660 {
661 int len = value.size();
662 if ((value[0] == '"') && (value[len-1] == '"'))
663 value = value.substr (1, len-2);
664 value_sp.reset (new OptionValueString (value.c_str(), ""));
665 }
666
667
668
669 if (const_key == encoding_key)
670 {
671 // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data indicating the
672 // data type of an upcoming array (usually the next bit of data to be read in).
673 if (strcmp (value.c_str(), "uint32_t") == 0)
674 data_type = OptionValue::eTypeUInt64;
675 }
676 else
Greg Clayton84c39662011-04-27 22:04:39 +0000677 option_value_sp->GetAsDictionary()->SetValueForKey (const_key, value_sp, false);
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000678 }
679 }
680
681 return option_value_sp;
682}
683
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000684bool
Caroline Tice3ac67112011-04-19 23:30:03 +0000685Instruction::TestEmulation (Stream *out_stream, const char *file_name)
686{
687 if (!out_stream)
688 return false;
689
690 if (!file_name)
691 {
Johnny Chenea80ba82011-04-21 20:27:45 +0000692 out_stream->Printf ("Instruction::TestEmulation: Missing file_name.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000693 return false;
694 }
695
696 FILE *test_file = fopen (file_name, "r");
697 if (!test_file)
698 {
Johnny Chenea80ba82011-04-21 20:27:45 +0000699 out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000700 return false;
701 }
702
Caroline Tice3ac67112011-04-19 23:30:03 +0000703 char buffer[256];
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000704 if (!fgets (buffer, 255, test_file))
Caroline Tice3ac67112011-04-19 23:30:03 +0000705 {
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000706 out_stream->Printf ("Instruction::TestEmulation: Error reading first line of test file.\n");
Caroline Tice3ac67112011-04-19 23:30:03 +0000707 fclose (test_file);
708 return false;
709 }
710
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000711 if (strncmp (buffer, "InstructionEmulationState={", 27) != 0)
712 {
713 out_stream->Printf ("Instructin::TestEmulation: Test file does not contain emulation state dictionary\n");
714 fclose (test_file);
715 return false;
716 }
717
718 // Read all the test information from the test file into an OptionValueDictionary.
719
720 OptionValueSP data_dictionary_sp (ReadDictionary (test_file, out_stream));
721 if (data_dictionary_sp.get() == NULL)
722 {
723 out_stream->Printf ("Instruction::TestEmulation: Error reading Dictionary Object.\n");
724 fclose (test_file);
725 return false;
726 }
727
728 fclose (test_file);
729
Greg Clayton84c39662011-04-27 22:04:39 +0000730 OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionary();
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000731 static ConstString description_key ("assembly_string");
732 static ConstString triple_key ("triple");
733
734 OptionValueSP value_sp = data_dictionary->GetValueForKey (description_key);
735
736 if (value_sp.get() == NULL)
737 {
738 out_stream->Printf ("Instruction::TestEmulation: Test file does not contain description string.\n");
739 return false;
740 }
741
742 SetDescription (value_sp->GetStringValue());
743
744
745 value_sp = data_dictionary->GetValueForKey (triple_key);
746 if (value_sp.get() == NULL)
747 {
748 out_stream->Printf ("Instruction::TestEmulation: Test file does not contain triple.\n");
749 return false;
750 }
751
752 ArchSpec arch;
753 arch.SetTriple (llvm::Triple (value_sp->GetStringValue()));
Caroline Tice3ac67112011-04-19 23:30:03 +0000754
755 bool success = false;
Greg Clayton2ed751b2011-04-26 04:39:08 +0000756 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL));
Caroline Tice3ac67112011-04-19 23:30:03 +0000757 if (insn_emulator_ap.get())
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000758 success = insn_emulator_ap->TestEmulation (out_stream, arch, data_dictionary);
Caroline Tice3ac67112011-04-19 23:30:03 +0000759
Caroline Tice3ac67112011-04-19 23:30:03 +0000760 if (success)
Johnny Chenea80ba82011-04-21 20:27:45 +0000761 out_stream->Printf ("Emulation test succeeded.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000762 else
Johnny Chenea80ba82011-04-21 20:27:45 +0000763 out_stream->Printf ("Emulation test failed.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000764
765 return success;
766}
767
768bool
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000769Instruction::Emulate (const ArchSpec &arch,
Greg Clayton2ed751b2011-04-26 04:39:08 +0000770 uint32_t evaluate_options,
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000771 void *baton,
Greg Clayton7349bd92011-05-09 20:18:18 +0000772 EmulateInstruction::ReadMemoryCallback read_mem_callback,
773 EmulateInstruction::WriteMemoryCallback write_mem_callback,
774 EmulateInstruction::ReadRegisterCallback read_reg_callback,
775 EmulateInstruction::WriteRegisterCallback write_reg_callback)
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000776{
Greg Clayton2ed751b2011-04-26 04:39:08 +0000777 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL));
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000778 if (insn_emulator_ap.get())
779 {
780 insn_emulator_ap->SetBaton (baton);
781 insn_emulator_ap->SetCallbacks (read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback);
Greg Clayton2ed751b2011-04-26 04:39:08 +0000782 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress(), NULL);
783 return insn_emulator_ap->EvaluateInstruction (evaluate_options);
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000784 }
785
786 return false;
787}
788
Greg Clayton1d273162010-10-06 03:09:58 +0000789InstructionList::InstructionList() :
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000790 m_instructions()
791{
792}
793
Greg Clayton1d273162010-10-06 03:09:58 +0000794InstructionList::~InstructionList()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000795{
796}
797
798size_t
Greg Clayton1d273162010-10-06 03:09:58 +0000799InstructionList::GetSize() const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000800{
801 return m_instructions.size();
802}
803
Greg Clayton357132e2011-03-26 19:14:58 +0000804uint32_t
805InstructionList::GetMaxOpcocdeByteSize () const
806{
807 uint32_t max_inst_size = 0;
808 collection::const_iterator pos, end;
809 for (pos = m_instructions.begin(), end = m_instructions.end();
810 pos != end;
811 ++pos)
812 {
813 uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
814 if (max_inst_size < inst_size)
815 max_inst_size = inst_size;
816 }
817 return max_inst_size;
818}
819
820
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000821
Greg Clayton1d273162010-10-06 03:09:58 +0000822InstructionSP
823InstructionList::GetInstructionAtIndex (uint32_t idx) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000824{
Greg Clayton1d273162010-10-06 03:09:58 +0000825 InstructionSP inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000826 if (idx < m_instructions.size())
Greg Clayton1d273162010-10-06 03:09:58 +0000827 inst_sp = m_instructions[idx];
828 return inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000829}
830
831void
Greg Clayton1d273162010-10-06 03:09:58 +0000832InstructionList::Clear()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000833{
834 m_instructions.clear();
835}
836
837void
Greg Clayton1d273162010-10-06 03:09:58 +0000838InstructionList::Append (lldb::InstructionSP &inst_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000839{
840 if (inst_sp)
841 m_instructions.push_back(inst_sp);
842}
843
844
845size_t
846Disassembler::ParseInstructions
847(
848 const ExecutionContext *exe_ctx,
Greg Clayton357132e2011-03-26 19:14:58 +0000849 const AddressRange &range
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000850)
851{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000852 Target *target = exe_ctx->target;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000853 const addr_t byte_size = range.GetByteSize();
854 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000855 return 0;
856
Greg Claytondda4f7b2010-06-30 23:03:03 +0000857 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
858 DataBufferSP data_sp(heap_buffer);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000859
860 Error error;
Greg Clayton357132e2011-03-26 19:14:58 +0000861 const bool prefer_file_cache = true;
862 const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(),
863 prefer_file_cache,
864 heap_buffer->GetBytes(),
865 heap_buffer->GetByteSize(),
866 error);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000867
868 if (bytes_read > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000869 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000870 if (bytes_read != heap_buffer->GetByteSize())
871 heap_buffer->SetByteSize (bytes_read);
Greg Clayton357132e2011-03-26 19:14:58 +0000872 DataExtractor data (data_sp,
873 m_arch.GetByteOrder(),
874 m_arch.GetAddressByteSize());
Jim Ingham37023b02011-03-22 01:48:42 +0000875 return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000876 }
877
878 return 0;
879}
880
Jim Ingham37023b02011-03-22 01:48:42 +0000881size_t
882Disassembler::ParseInstructions
883(
884 const ExecutionContext *exe_ctx,
885 const Address &start,
Greg Clayton357132e2011-03-26 19:14:58 +0000886 uint32_t num_instructions
Jim Ingham37023b02011-03-22 01:48:42 +0000887)
888{
Greg Clayton357132e2011-03-26 19:14:58 +0000889 m_instruction_list.Clear();
890
891 if (num_instructions == 0 || !start.IsValid())
Jim Ingham37023b02011-03-22 01:48:42 +0000892 return 0;
893
894 Target *target = exe_ctx->target;
Greg Clayton357132e2011-03-26 19:14:58 +0000895 // Calculate the max buffer size we will need in order to disassemble
896 const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize();
Jim Ingham37023b02011-03-22 01:48:42 +0000897
Greg Clayton357132e2011-03-26 19:14:58 +0000898 if (target == NULL || byte_size == 0)
Jim Ingham37023b02011-03-22 01:48:42 +0000899 return 0;
900
901 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
Greg Clayton357132e2011-03-26 19:14:58 +0000902 DataBufferSP data_sp (heap_buffer);
Jim Ingham37023b02011-03-22 01:48:42 +0000903
904 Error error;
905 bool prefer_file_cache = true;
Greg Clayton357132e2011-03-26 19:14:58 +0000906 const size_t bytes_read = target->ReadMemory (start,
907 prefer_file_cache,
908 heap_buffer->GetBytes(),
909 byte_size,
910 error);
911
912 if (bytes_read == 0)
913 return 0;
914 DataExtractor data (data_sp,
915 m_arch.GetByteOrder(),
916 m_arch.GetAddressByteSize());
917
918 const bool append_instructions = true;
919 DecodeInstructions (start,
920 data,
921 0,
922 num_instructions,
923 append_instructions);
924
Jim Ingham37023b02011-03-22 01:48:42 +0000925 return m_instruction_list.GetSize();
926}
927
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000928//----------------------------------------------------------------------
929// Disassembler copy constructor
930//----------------------------------------------------------------------
931Disassembler::Disassembler(const ArchSpec& arch) :
932 m_arch (arch),
933 m_instruction_list(),
934 m_base_addr(LLDB_INVALID_ADDRESS)
935{
936
937}
938
939//----------------------------------------------------------------------
940// Destructor
941//----------------------------------------------------------------------
942Disassembler::~Disassembler()
943{
944}
945
Greg Clayton1d273162010-10-06 03:09:58 +0000946InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000947Disassembler::GetInstructionList ()
948{
949 return m_instruction_list;
950}
951
Greg Clayton1d273162010-10-06 03:09:58 +0000952const InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000953Disassembler::GetInstructionList () const
954{
955 return m_instruction_list;
956}
Caroline Tice3ac67112011-04-19 23:30:03 +0000957
958//----------------------------------------------------------------------
959// Class PseudoInstruction
960//----------------------------------------------------------------------
961PseudoInstruction::PseudoInstruction () :
962 Instruction (Address(), eAddressClassUnknown),
963 m_description ()
964{
965}
966
967PseudoInstruction::~PseudoInstruction ()
968{
969}
970
971void
972PseudoInstruction::Dump (lldb_private::Stream *s,
973 uint32_t max_opcode_byte_size,
974 bool show_address,
975 bool show_bytes,
976 const lldb_private::ExecutionContext* exe_ctx,
977 bool raw)
978{
979 if (!s)
980 return;
981
982 if (show_bytes)
983 m_opcode.Dump (s, max_opcode_byte_size);
984
985 if (m_description.size() > 0)
986 s->Printf ("%s", m_description.c_str());
987 else
988 s->Printf ("<unknown>");
989
990}
991
992bool
993PseudoInstruction::DoesBranch () const
994{
995 // This is NOT a valid question for a pseudo instruction.
996 return false;
997}
998
999size_t
1000PseudoInstruction::Decode (const lldb_private::Disassembler &disassembler,
1001 const lldb_private::DataExtractor &data,
1002 uint32_t data_offset)
1003{
1004 return m_opcode.GetByteSize();
1005}
1006
1007
1008void
1009PseudoInstruction::SetOpcode (size_t opcode_size, void *opcode_data)
1010{
1011 if (!opcode_data)
1012 return;
1013
1014 switch (opcode_size)
1015 {
1016 case 8:
1017 {
1018 uint8_t value8 = *((uint8_t *) opcode_data);
1019 m_opcode.SetOpcode8 (value8);
1020 break;
1021 }
1022 case 16:
1023 {
1024 uint16_t value16 = *((uint16_t *) opcode_data);
1025 m_opcode.SetOpcode16 (value16);
1026 break;
1027 }
1028 case 32:
1029 {
1030 uint32_t value32 = *((uint32_t *) opcode_data);
1031 m_opcode.SetOpcode32 (value32);
1032 break;
1033 }
1034 case 64:
1035 {
1036 uint64_t value64 = *((uint64_t *) opcode_data);
1037 m_opcode.SetOpcode64 (value64);
1038 break;
1039 }
1040 default:
1041 break;
1042 }
1043}
1044
1045void
1046PseudoInstruction::SetDescription (const char *description)
1047{
1048 if (description && strlen (description) > 0)
1049 m_description = description;
1050}