blob: 4ebe6888e35ed62cb5ae4d919a8dfd346d0f34f0 [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
Greg Claytonc14ee322011-09-22 04:58:26 +000084 Target *target = exe_ctx.GetTargetPtr();
85 if (target)
Greg Clayton357132e2011-03-26 19:14:58 +000086 {
Greg Claytonc14ee322011-09-22 04:58:26 +000087 if (target->GetSectionLoadList().IsEmpty())
Greg Clayton357132e2011-03-26 19:14:58 +000088 {
Greg Claytonc14ee322011-09-22 04:58:26 +000089 target->GetImages().ResolveFileAddress (addr.GetOffset(), resolved_addr);
Greg Clayton357132e2011-03-26 19:14:58 +000090 }
91 else
92 {
Greg Claytonc14ee322011-09-22 04:58:26 +000093 target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), resolved_addr);
Greg Clayton357132e2011-03-26 19:14:58 +000094 }
95 // We weren't able to resolve the address, just treat it as a
96 // raw address
97 if (resolved_addr.IsValid())
98 return;
99 }
100 }
101 resolved_addr = addr;
102}
Greg Claytondda4f7b2010-06-30 23:03:03 +0000103
104size_t
105Disassembler::Disassemble
106(
107 Debugger &debugger,
108 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000109 const char *plugin_name,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000110 const ExecutionContext &exe_ctx,
111 SymbolContextList &sc_list,
Jim Ingham37023b02011-03-22 01:48:42 +0000112 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000113 uint32_t num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000114 uint32_t options,
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,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000137 options,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000138 strm))
Greg Claytondda4f7b2010-06-30 23:03:03 +0000139 {
140 ++success_count;
141 strm.EOL();
142 }
143 }
144 }
145 return success_count;
146}
147
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000148bool
149Disassembler::Disassemble
150(
Greg Clayton66111032010-06-23 01:19:29 +0000151 Debugger &debugger,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000152 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000153 const char *plugin_name,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000154 const ExecutionContext &exe_ctx,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000155 const ConstString &name,
156 Module *module,
Jim Ingham37023b02011-03-22 01:48:42 +0000157 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000158 uint32_t num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000159 uint32_t options,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000160 Stream &strm
161)
162{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000163 SymbolContextList sc_list;
Greg Clayton931180e2011-01-27 06:44:37 +0000164 if (name)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000165 {
Greg Clayton931180e2011-01-27 06:44:37 +0000166 const bool include_symbols = true;
167 if (module)
168 {
169 module->FindFunctions (name,
170 eFunctionNameTypeBase |
171 eFunctionNameTypeFull |
172 eFunctionNameTypeMethod |
173 eFunctionNameTypeSelector,
174 include_symbols,
175 true,
176 sc_list);
177 }
Greg Claytonc14ee322011-09-22 04:58:26 +0000178 else if (exe_ctx.GetTargetPtr())
Greg Clayton931180e2011-01-27 06:44:37 +0000179 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000180 exe_ctx.GetTargetPtr()->GetImages().FindFunctions (name,
181 eFunctionNameTypeBase |
182 eFunctionNameTypeFull |
183 eFunctionNameTypeMethod |
184 eFunctionNameTypeSelector,
185 include_symbols,
186 false,
187 sc_list);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000188 }
Greg Clayton931180e2011-01-27 06:44:37 +0000189 }
190
191 if (sc_list.GetSize ())
192 {
193 return Disassemble (debugger,
194 arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000195 plugin_name,
Greg Clayton931180e2011-01-27 06:44:37 +0000196 exe_ctx,
Jim Ingham37023b02011-03-22 01:48:42 +0000197 sc_list,
198 num_instructions,
Greg Clayton931180e2011-01-27 06:44:37 +0000199 num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000200 options,
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,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000242 uint32_t options,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000243 Stream &strm
244)
245{
246 if (disasm_range.GetByteSize())
247 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000248 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name));
Greg Claytondda4f7b2010-06-30 23:03:03 +0000249
Greg Clayton1d273162010-10-06 03:09:58 +0000250 if (disasm_ap.get())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000251 {
Greg Clayton357132e2011-03-26 19:14:58 +0000252 AddressRange range;
253 ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress());
254 range.SetByteSize (disasm_range.GetByteSize());
Greg Claytondda4f7b2010-06-30 23:03:03 +0000255
Greg Clayton357132e2011-03-26 19:14:58 +0000256 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, range);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000257 if (bytes_disassembled == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000258 return false;
Greg Clayton1080edbc2011-03-25 18:03:16 +0000259
260 return PrintInstructions (disasm_ap.get(),
261 debugger,
262 arch,
263 exe_ctx,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000264 num_instructions,
265 num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000266 options,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000267 strm);
Jim Ingham37023b02011-03-22 01:48:42 +0000268 }
269 }
270 return false;
271}
272
273bool
274Disassembler::Disassemble
275(
276 Debugger &debugger,
277 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000278 const char *plugin_name,
Jim Ingham37023b02011-03-22 01:48:42 +0000279 const ExecutionContext &exe_ctx,
280 const Address &start_address,
281 uint32_t num_instructions,
282 uint32_t num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000283 uint32_t options,
Jim Ingham37023b02011-03-22 01:48:42 +0000284 Stream &strm
285)
286{
287 if (num_instructions > 0)
288 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000289 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name));
Jim Ingham37023b02011-03-22 01:48:42 +0000290 if (disasm_ap.get())
291 {
Greg Clayton357132e2011-03-26 19:14:58 +0000292 Address addr;
293 ResolveAddress (exe_ctx, start_address, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000294
Greg Clayton357132e2011-03-26 19:14:58 +0000295 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, addr, num_instructions);
Jim Ingham37023b02011-03-22 01:48:42 +0000296 if (bytes_disassembled == 0)
Jim Ingham37023b02011-03-22 01:48:42 +0000297 return false;
Greg Clayton1080edbc2011-03-25 18:03:16 +0000298 return PrintInstructions (disasm_ap.get(),
299 debugger,
300 arch,
301 exe_ctx,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000302 num_instructions,
303 num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000304 options,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000305 strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000306 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000307 }
308 return false;
309}
Jim Ingham37023b02011-03-22 01:48:42 +0000310
311bool
312Disassembler::PrintInstructions
313(
314 Disassembler *disasm_ptr,
Jim Ingham37023b02011-03-22 01:48:42 +0000315 Debugger &debugger,
316 const ArchSpec &arch,
317 const ExecutionContext &exe_ctx,
Jim Ingham37023b02011-03-22 01:48:42 +0000318 uint32_t num_instructions,
319 uint32_t num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000320 uint32_t options,
Jim Ingham37023b02011-03-22 01:48:42 +0000321 Stream &strm
322)
323{
324 // We got some things disassembled...
325 size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
326
327 if (num_instructions > 0 && num_instructions < num_instructions_found)
328 num_instructions_found = num_instructions;
329
Greg Clayton357132e2011-03-26 19:14:58 +0000330 const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
Jim Ingham37023b02011-03-22 01:48:42 +0000331 uint32_t offset = 0;
332 SymbolContext sc;
333 SymbolContext prev_sc;
334 AddressRange sc_range;
Greg Clayton34132752011-07-06 04:07:21 +0000335 const Address *pc_addr_ptr = NULL;
Greg Clayton7e14f912011-04-23 02:04:55 +0000336 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
Greg Claytonc14ee322011-09-22 04:58:26 +0000337 StackFrame *frame = exe_ctx.GetFramePtr();
338
339 if (frame)
340 pc_addr_ptr = &frame->GetFrameCodeAddress();
Greg Clayton7e14f912011-04-23 02:04:55 +0000341 const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
342 const bool use_inline_block_range = false;
Jim Ingham37023b02011-03-22 01:48:42 +0000343 for (size_t i=0; i<num_instructions_found; ++i)
344 {
345 Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
346 if (inst)
347 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000348 const Address &addr = inst->GetAddress();
349 const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
Jim Ingham37023b02011-03-22 01:48:42 +0000350
351 prev_sc = sc;
352
Greg Clayton32e0a752011-03-30 18:16:51 +0000353 Module *module = addr.GetModule();
354 if (module)
Jim Ingham37023b02011-03-22 01:48:42 +0000355 {
Jim Ingham37023b02011-03-22 01:48:42 +0000356 uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
357 if (resolved_mask)
358 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000359 if (num_mixed_context_lines)
360 {
361 if (!sc_range.ContainsFileAddress (addr))
362 {
Greg Clayton7e14f912011-04-23 02:04:55 +0000363 sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range);
Greg Clayton32e0a752011-03-30 18:16:51 +0000364
365 if (sc != prev_sc)
366 {
367 if (offset != 0)
368 strm.EOL();
369
Greg Claytonc14ee322011-09-22 04:58:26 +0000370 sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false);
Greg Clayton32e0a752011-03-30 18:16:51 +0000371 strm.EOL();
372
373 if (sc.comp_unit && sc.line_entry.IsValid())
374 {
Jim Inghamb7f6b2f2011-09-08 22:13:49 +0000375 debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
Greg Clayton32e0a752011-03-30 18:16:51 +0000376 sc.line_entry.line,
377 num_mixed_context_lines,
378 num_mixed_context_lines,
Greg Claytonb10d72f2011-06-28 19:01:40 +0000379 ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""),
Greg Clayton32e0a752011-03-30 18:16:51 +0000380 &strm);
381 }
382 }
383 }
384 }
385 else if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol))
Jim Ingham37023b02011-03-22 01:48:42 +0000386 {
387 if (prev_sc.function || prev_sc.symbol)
388 strm.EOL();
389
Greg Clayton7e14f912011-04-23 02:04:55 +0000390 bool show_fullpaths = false;
391 bool show_module = true;
392 bool show_inlined_frames = true;
393 sc.DumpStopContext (&strm,
394 exe_scope,
395 addr,
396 show_fullpaths,
397 show_module,
398 show_inlined_frames);
Jim Ingham37023b02011-03-22 01:48:42 +0000399
Jim Ingham37023b02011-03-22 01:48:42 +0000400 strm << ":\n";
401 }
Jim Ingham37023b02011-03-22 01:48:42 +0000402 }
403 else
404 {
405 sc.Clear();
406 }
407 }
Jim Ingham37023b02011-03-22 01:48:42 +0000408
Greg Claytonb10d72f2011-06-28 19:01:40 +0000409 if ((options & eOptionMarkPCAddress) && pc_addr_ptr)
Greg Clayton32e0a752011-03-30 18:16:51 +0000410 {
Greg Claytonb10d72f2011-06-28 19:01:40 +0000411 strm.PutCString(inst_is_at_pc ? "-> " : " ");
Greg Clayton32e0a752011-03-30 18:16:51 +0000412 }
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000413 const bool show_bytes = (options & eOptionShowBytes) != 0;
414 const bool raw = (options & eOptionRawOuput) != 0;
Greg Clayton32e0a752011-03-30 18:16:51 +0000415 inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, raw);
416 strm.EOL();
Jim Ingham37023b02011-03-22 01:48:42 +0000417 }
418 else
419 {
420 break;
421 }
422 }
Jim Ingham37023b02011-03-22 01:48:42 +0000423
424 return true;
425}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000426
Greg Claytondda4f7b2010-06-30 23:03:03 +0000427
428bool
429Disassembler::Disassemble
430(
431 Debugger &debugger,
432 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000433 const char *plugin_name,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000434 const ExecutionContext &exe_ctx,
Jim Ingham37023b02011-03-22 01:48:42 +0000435 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000436 uint32_t num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000437 uint32_t options,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000438 Stream &strm
439)
440{
441 AddressRange range;
Greg Claytonc14ee322011-09-22 04:58:26 +0000442 StackFrame *frame = exe_ctx.GetFramePtr();
443 if (frame)
Greg Claytondda4f7b2010-06-30 23:03:03 +0000444 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000445 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
Greg Claytondda4f7b2010-06-30 23:03:03 +0000446 if (sc.function)
447 {
448 range = sc.function->GetAddressRange();
449 }
450 else if (sc.symbol && sc.symbol->GetAddressRangePtr())
451 {
452 range = *sc.symbol->GetAddressRangePtr();
453 }
454 else
455 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000456 range.GetBaseAddress() = frame->GetFrameCodeAddress();
Greg Claytondda4f7b2010-06-30 23:03:03 +0000457 }
458
459 if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
460 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
461 }
462
Greg Clayton1080edbc2011-03-25 18:03:16 +0000463 return Disassemble (debugger,
464 arch,
465 plugin_name,
466 exe_ctx,
467 range,
468 num_instructions,
469 num_mixed_context_lines,
Greg Clayton1da6f9d2011-06-22 01:39:49 +0000470 options,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000471 strm);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000472}
473
Greg Clayton357132e2011-03-26 19:14:58 +0000474Instruction::Instruction(const Address &address, AddressClass addr_class) :
Greg Clayton1080edbc2011-03-25 18:03:16 +0000475 m_address (address),
Greg Clayton357132e2011-03-26 19:14:58 +0000476 m_address_class (addr_class),
Greg Clayton1080edbc2011-03-25 18:03:16 +0000477 m_opcode()
Greg Clayton0ae96272011-03-24 23:53:38 +0000478{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000479}
480
Greg Clayton1d273162010-10-06 03:09:58 +0000481Instruction::~Instruction()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000482{
483}
484
Greg Clayton357132e2011-03-26 19:14:58 +0000485AddressClass
486Instruction::GetAddressClass ()
487{
488 if (m_address_class == eAddressClassInvalid)
489 m_address_class = m_address.GetAddressClass();
490 return m_address_class;
491}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000492
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000493bool
494Instruction::DumpEmulation (const ArchSpec &arch)
495{
Greg Clayton2ed751b2011-04-26 04:39:08 +0000496 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL));
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000497 if (insn_emulator_ap.get())
498 {
Greg Clayton2ed751b2011-04-26 04:39:08 +0000499 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress(), NULL);
500 return insn_emulator_ap->EvaluateInstruction (0);
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000501 }
502
503 return false;
504}
505
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000506OptionValueSP
507Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type)
508{
509 bool done = false;
510 char buffer[1024];
511
512 OptionValueSP option_value_sp (new OptionValueArray (1u << data_type));
513
514 int idx = 0;
515 while (!done)
516 {
517 if (!fgets (buffer, 1023, in_file))
518 {
Greg Clayton762f7132011-09-18 18:59:15 +0000519 out_stream->Printf ("Instruction::ReadArray: Error reading file (fgets).\n");
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000520 option_value_sp.reset ();
521 return option_value_sp;
522 }
523
524 std::string line (buffer);
525
526 int len = line.size();
527 if (line[len-1] == '\n')
528 {
529 line[len-1] = '\0';
530 line.resize (len-1);
531 }
532
533 if ((line.size() == 1) && line[0] == ']')
534 {
535 done = true;
536 line.clear();
537 }
538
539 if (line.size() > 0)
540 {
541 std::string value;
542 RegularExpression reg_exp ("^[ \t]*([^ \t]+)[ \t]*$");
543 bool reg_exp_success = reg_exp.Execute (line.c_str(), 1);
544 if (reg_exp_success)
545 reg_exp.GetMatchAtIndex (line.c_str(), 1, value);
546 else
547 value = line;
548
549 OptionValueSP data_value_sp;
550 switch (data_type)
551 {
552 case OptionValue::eTypeUInt64:
553 data_value_sp.reset (new OptionValueUInt64 (0, 0));
554 data_value_sp->SetValueFromCString (value.c_str());
555 break;
556 // Other types can be added later as needed.
557 default:
558 data_value_sp.reset (new OptionValueString (value.c_str(), ""));
559 break;
560 }
561
Greg Clayton84c39662011-04-27 22:04:39 +0000562 option_value_sp->GetAsArray()->InsertValue (idx, data_value_sp);
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000563 ++idx;
564 }
565 }
566
567 return option_value_sp;
568}
569
570OptionValueSP
571Instruction::ReadDictionary (FILE *in_file, Stream *out_stream)
572{
573 bool done = false;
574 char buffer[1024];
575
576 OptionValueSP option_value_sp (new OptionValueDictionary());
577 static ConstString encoding_key ("data_encoding");
578 OptionValue::Type data_type = OptionValue::eTypeInvalid;
579
580
581 while (!done)
582 {
583 // Read the next line in the file
584 if (!fgets (buffer, 1023, in_file))
585 {
586 out_stream->Printf ("Instruction::ReadDictionary: Error reading file (fgets).\n");
587 option_value_sp.reset ();
588 return option_value_sp;
589 }
590
591 // Check to see if the line contains the end-of-dictionary marker ("}")
592 std::string line (buffer);
593
594 int len = line.size();
595 if (line[len-1] == '\n')
596 {
597 line[len-1] = '\0';
598 line.resize (len-1);
599 }
600
601 if ((line.size() == 1) && (line[0] == '}'))
602 {
603 done = true;
604 line.clear();
605 }
606
607 // Try to find a key-value pair in the current line and add it to the dictionary.
608 if (line.size() > 0)
609 {
610 RegularExpression reg_exp ("^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$");
611 bool reg_exp_success = reg_exp.Execute (line.c_str(), 2);
612 std::string key;
613 std::string value;
614 if (reg_exp_success)
615 {
616 reg_exp.GetMatchAtIndex (line.c_str(), 1, key);
617 reg_exp.GetMatchAtIndex (line.c_str(), 2, value);
618 }
619 else
620 {
621 out_stream->Printf ("Instruction::ReadDictionary: Failure executing regular expression.\n");
622 option_value_sp.reset();
623 return option_value_sp;
624 }
625
626 ConstString const_key (key.c_str());
627 // Check value to see if it's the start of an array or dictionary.
628
629 lldb::OptionValueSP value_sp;
630 assert (value.empty() == false);
631 assert (key.empty() == false);
632
633 if (value[0] == '{')
634 {
635 assert (value.size() == 1);
636 // value is a dictionary
637 value_sp = ReadDictionary (in_file, out_stream);
638 if (value_sp.get() == NULL)
639 {
640 option_value_sp.reset ();
641 return option_value_sp;
642 }
643 }
644 else if (value[0] == '[')
645 {
646 assert (value.size() == 1);
647 // value is an array
648 value_sp = ReadArray (in_file, out_stream, data_type);
649 if (value_sp.get() == NULL)
650 {
651 option_value_sp.reset ();
652 return option_value_sp;
653 }
654 // We've used the data_type to read an array; re-set the type to Invalid
655 data_type = OptionValue::eTypeInvalid;
656 }
657 else if ((value[0] == '0') && (value[1] == 'x'))
658 {
659 value_sp.reset (new OptionValueUInt64 (0, 0));
660 value_sp->SetValueFromCString (value.c_str());
661 }
662 else
663 {
664 int len = value.size();
665 if ((value[0] == '"') && (value[len-1] == '"'))
666 value = value.substr (1, len-2);
667 value_sp.reset (new OptionValueString (value.c_str(), ""));
668 }
669
670
671
672 if (const_key == encoding_key)
673 {
674 // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data indicating the
675 // data type of an upcoming array (usually the next bit of data to be read in).
676 if (strcmp (value.c_str(), "uint32_t") == 0)
677 data_type = OptionValue::eTypeUInt64;
678 }
679 else
Greg Clayton84c39662011-04-27 22:04:39 +0000680 option_value_sp->GetAsDictionary()->SetValueForKey (const_key, value_sp, false);
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000681 }
682 }
683
684 return option_value_sp;
685}
686
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000687bool
Caroline Tice3ac67112011-04-19 23:30:03 +0000688Instruction::TestEmulation (Stream *out_stream, const char *file_name)
689{
690 if (!out_stream)
691 return false;
692
693 if (!file_name)
694 {
Johnny Chenea80ba82011-04-21 20:27:45 +0000695 out_stream->Printf ("Instruction::TestEmulation: Missing file_name.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000696 return false;
697 }
698
699 FILE *test_file = fopen (file_name, "r");
700 if (!test_file)
701 {
Johnny Chenea80ba82011-04-21 20:27:45 +0000702 out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000703 return false;
704 }
705
Caroline Tice3ac67112011-04-19 23:30:03 +0000706 char buffer[256];
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000707 if (!fgets (buffer, 255, test_file))
Caroline Tice3ac67112011-04-19 23:30:03 +0000708 {
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000709 out_stream->Printf ("Instruction::TestEmulation: Error reading first line of test file.\n");
Caroline Tice3ac67112011-04-19 23:30:03 +0000710 fclose (test_file);
711 return false;
712 }
713
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000714 if (strncmp (buffer, "InstructionEmulationState={", 27) != 0)
715 {
716 out_stream->Printf ("Instructin::TestEmulation: Test file does not contain emulation state dictionary\n");
717 fclose (test_file);
718 return false;
719 }
720
721 // Read all the test information from the test file into an OptionValueDictionary.
722
723 OptionValueSP data_dictionary_sp (ReadDictionary (test_file, out_stream));
724 if (data_dictionary_sp.get() == NULL)
725 {
726 out_stream->Printf ("Instruction::TestEmulation: Error reading Dictionary Object.\n");
727 fclose (test_file);
728 return false;
729 }
730
731 fclose (test_file);
732
Greg Clayton84c39662011-04-27 22:04:39 +0000733 OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionary();
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000734 static ConstString description_key ("assembly_string");
735 static ConstString triple_key ("triple");
736
737 OptionValueSP value_sp = data_dictionary->GetValueForKey (description_key);
738
739 if (value_sp.get() == NULL)
740 {
741 out_stream->Printf ("Instruction::TestEmulation: Test file does not contain description string.\n");
742 return false;
743 }
744
745 SetDescription (value_sp->GetStringValue());
746
747
748 value_sp = data_dictionary->GetValueForKey (triple_key);
749 if (value_sp.get() == NULL)
750 {
751 out_stream->Printf ("Instruction::TestEmulation: Test file does not contain triple.\n");
752 return false;
753 }
754
755 ArchSpec arch;
756 arch.SetTriple (llvm::Triple (value_sp->GetStringValue()));
Caroline Tice3ac67112011-04-19 23:30:03 +0000757
758 bool success = false;
Greg Clayton2ed751b2011-04-26 04:39:08 +0000759 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL));
Caroline Tice3ac67112011-04-19 23:30:03 +0000760 if (insn_emulator_ap.get())
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000761 success = insn_emulator_ap->TestEmulation (out_stream, arch, data_dictionary);
Caroline Tice3ac67112011-04-19 23:30:03 +0000762
Caroline Tice3ac67112011-04-19 23:30:03 +0000763 if (success)
Johnny Chenea80ba82011-04-21 20:27:45 +0000764 out_stream->Printf ("Emulation test succeeded.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000765 else
Johnny Chenea80ba82011-04-21 20:27:45 +0000766 out_stream->Printf ("Emulation test failed.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000767
768 return success;
769}
770
771bool
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000772Instruction::Emulate (const ArchSpec &arch,
Greg Clayton2ed751b2011-04-26 04:39:08 +0000773 uint32_t evaluate_options,
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000774 void *baton,
Greg Clayton7349bd92011-05-09 20:18:18 +0000775 EmulateInstruction::ReadMemoryCallback read_mem_callback,
776 EmulateInstruction::WriteMemoryCallback write_mem_callback,
777 EmulateInstruction::ReadRegisterCallback read_reg_callback,
778 EmulateInstruction::WriteRegisterCallback write_reg_callback)
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000779{
Greg Clayton2ed751b2011-04-26 04:39:08 +0000780 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL));
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000781 if (insn_emulator_ap.get())
782 {
783 insn_emulator_ap->SetBaton (baton);
784 insn_emulator_ap->SetCallbacks (read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback);
Greg Clayton2ed751b2011-04-26 04:39:08 +0000785 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress(), NULL);
786 return insn_emulator_ap->EvaluateInstruction (evaluate_options);
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000787 }
788
789 return false;
790}
791
Greg Clayton1d273162010-10-06 03:09:58 +0000792InstructionList::InstructionList() :
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000793 m_instructions()
794{
795}
796
Greg Clayton1d273162010-10-06 03:09:58 +0000797InstructionList::~InstructionList()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000798{
799}
800
801size_t
Greg Clayton1d273162010-10-06 03:09:58 +0000802InstructionList::GetSize() const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000803{
804 return m_instructions.size();
805}
806
Greg Clayton357132e2011-03-26 19:14:58 +0000807uint32_t
808InstructionList::GetMaxOpcocdeByteSize () const
809{
810 uint32_t max_inst_size = 0;
811 collection::const_iterator pos, end;
812 for (pos = m_instructions.begin(), end = m_instructions.end();
813 pos != end;
814 ++pos)
815 {
816 uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
817 if (max_inst_size < inst_size)
818 max_inst_size = inst_size;
819 }
820 return max_inst_size;
821}
822
823
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000824
Greg Clayton1d273162010-10-06 03:09:58 +0000825InstructionSP
826InstructionList::GetInstructionAtIndex (uint32_t idx) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000827{
Greg Clayton1d273162010-10-06 03:09:58 +0000828 InstructionSP inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000829 if (idx < m_instructions.size())
Greg Clayton1d273162010-10-06 03:09:58 +0000830 inst_sp = m_instructions[idx];
831 return inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000832}
833
834void
Greg Clayton1d273162010-10-06 03:09:58 +0000835InstructionList::Clear()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000836{
837 m_instructions.clear();
838}
839
840void
Greg Clayton1d273162010-10-06 03:09:58 +0000841InstructionList::Append (lldb::InstructionSP &inst_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000842{
843 if (inst_sp)
844 m_instructions.push_back(inst_sp);
845}
846
847
848size_t
849Disassembler::ParseInstructions
850(
851 const ExecutionContext *exe_ctx,
Greg Clayton357132e2011-03-26 19:14:58 +0000852 const AddressRange &range
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000853)
854{
Greg Claytonc14ee322011-09-22 04:58:26 +0000855 if (exe_ctx)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000856 {
Greg Claytonc14ee322011-09-22 04:58:26 +0000857 Target *target = exe_ctx->GetTargetPtr();
858 const addr_t byte_size = range.GetByteSize();
859 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
860 return 0;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000861
Greg Claytonc14ee322011-09-22 04:58:26 +0000862 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
863 DataBufferSP data_sp(heap_buffer);
864
865 Error error;
866 const bool prefer_file_cache = true;
867 const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(),
868 prefer_file_cache,
869 heap_buffer->GetBytes(),
870 heap_buffer->GetByteSize(),
871 error);
872
873 if (bytes_read > 0)
874 {
875 if (bytes_read != heap_buffer->GetByteSize())
876 heap_buffer->SetByteSize (bytes_read);
877 DataExtractor data (data_sp,
878 m_arch.GetByteOrder(),
879 m_arch.GetAddressByteSize());
880 return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false);
881 }
882 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000883 return 0;
884}
885
Jim Ingham37023b02011-03-22 01:48:42 +0000886size_t
887Disassembler::ParseInstructions
888(
889 const ExecutionContext *exe_ctx,
890 const Address &start,
Greg Clayton357132e2011-03-26 19:14:58 +0000891 uint32_t num_instructions
Jim Ingham37023b02011-03-22 01:48:42 +0000892)
893{
Greg Clayton357132e2011-03-26 19:14:58 +0000894 m_instruction_list.Clear();
895
Greg Claytonc14ee322011-09-22 04:58:26 +0000896 if (exe_ctx == NULL || num_instructions == 0 || !start.IsValid())
Jim Ingham37023b02011-03-22 01:48:42 +0000897 return 0;
898
Greg Claytonc14ee322011-09-22 04:58:26 +0000899 Target *target = exe_ctx->GetTargetPtr();
Greg Clayton357132e2011-03-26 19:14:58 +0000900 // Calculate the max buffer size we will need in order to disassemble
901 const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize();
Jim Ingham37023b02011-03-22 01:48:42 +0000902
Greg Clayton357132e2011-03-26 19:14:58 +0000903 if (target == NULL || byte_size == 0)
Jim Ingham37023b02011-03-22 01:48:42 +0000904 return 0;
905
906 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
Greg Clayton357132e2011-03-26 19:14:58 +0000907 DataBufferSP data_sp (heap_buffer);
Jim Ingham37023b02011-03-22 01:48:42 +0000908
909 Error error;
910 bool prefer_file_cache = true;
Greg Clayton357132e2011-03-26 19:14:58 +0000911 const size_t bytes_read = target->ReadMemory (start,
912 prefer_file_cache,
913 heap_buffer->GetBytes(),
914 byte_size,
915 error);
916
917 if (bytes_read == 0)
918 return 0;
919 DataExtractor data (data_sp,
920 m_arch.GetByteOrder(),
921 m_arch.GetAddressByteSize());
922
923 const bool append_instructions = true;
924 DecodeInstructions (start,
925 data,
926 0,
927 num_instructions,
928 append_instructions);
929
Jim Ingham37023b02011-03-22 01:48:42 +0000930 return m_instruction_list.GetSize();
931}
932
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000933//----------------------------------------------------------------------
934// Disassembler copy constructor
935//----------------------------------------------------------------------
936Disassembler::Disassembler(const ArchSpec& arch) :
937 m_arch (arch),
938 m_instruction_list(),
939 m_base_addr(LLDB_INVALID_ADDRESS)
940{
941
942}
943
944//----------------------------------------------------------------------
945// Destructor
946//----------------------------------------------------------------------
947Disassembler::~Disassembler()
948{
949}
950
Greg Clayton1d273162010-10-06 03:09:58 +0000951InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000952Disassembler::GetInstructionList ()
953{
954 return m_instruction_list;
955}
956
Greg Clayton1d273162010-10-06 03:09:58 +0000957const InstructionList &
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000958Disassembler::GetInstructionList () const
959{
960 return m_instruction_list;
961}
Caroline Tice3ac67112011-04-19 23:30:03 +0000962
963//----------------------------------------------------------------------
964// Class PseudoInstruction
965//----------------------------------------------------------------------
966PseudoInstruction::PseudoInstruction () :
967 Instruction (Address(), eAddressClassUnknown),
968 m_description ()
969{
970}
971
972PseudoInstruction::~PseudoInstruction ()
973{
974}
975
976void
977PseudoInstruction::Dump (lldb_private::Stream *s,
978 uint32_t max_opcode_byte_size,
979 bool show_address,
980 bool show_bytes,
981 const lldb_private::ExecutionContext* exe_ctx,
982 bool raw)
983{
984 if (!s)
985 return;
986
987 if (show_bytes)
988 m_opcode.Dump (s, max_opcode_byte_size);
989
990 if (m_description.size() > 0)
991 s->Printf ("%s", m_description.c_str());
992 else
993 s->Printf ("<unknown>");
994
995}
996
997bool
998PseudoInstruction::DoesBranch () const
999{
1000 // This is NOT a valid question for a pseudo instruction.
1001 return false;
1002}
1003
1004size_t
1005PseudoInstruction::Decode (const lldb_private::Disassembler &disassembler,
1006 const lldb_private::DataExtractor &data,
1007 uint32_t data_offset)
1008{
1009 return m_opcode.GetByteSize();
1010}
1011
1012
1013void
1014PseudoInstruction::SetOpcode (size_t opcode_size, void *opcode_data)
1015{
1016 if (!opcode_data)
1017 return;
1018
1019 switch (opcode_size)
1020 {
1021 case 8:
1022 {
1023 uint8_t value8 = *((uint8_t *) opcode_data);
1024 m_opcode.SetOpcode8 (value8);
1025 break;
1026 }
1027 case 16:
1028 {
1029 uint16_t value16 = *((uint16_t *) opcode_data);
1030 m_opcode.SetOpcode16 (value16);
1031 break;
1032 }
1033 case 32:
1034 {
1035 uint32_t value32 = *((uint32_t *) opcode_data);
1036 m_opcode.SetOpcode32 (value32);
1037 break;
1038 }
1039 case 64:
1040 {
1041 uint64_t value64 = *((uint64_t *) opcode_data);
1042 m_opcode.SetOpcode64 (value64);
1043 break;
1044 }
1045 default:
1046 break;
1047 }
1048}
1049
1050void
1051PseudoInstruction::SetDescription (const char *description)
1052{
1053 if (description && strlen (description) > 0)
1054 m_description = description;
1055}