blob: 0e0ea053ef001db5a994979746048222ad96fd6d [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;
Jim Ingham37023b02011-03-22 01:48:42 +0000122
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;
127 if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
128 {
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,
136 show_bytes,
137 raw,
138 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,
159 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000160 bool raw,
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000161 Stream &strm
162)
163{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000164 SymbolContextList sc_list;
Greg Clayton931180e2011-01-27 06:44:37 +0000165 if (name)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000166 {
Greg Clayton931180e2011-01-27 06:44:37 +0000167 const bool include_symbols = true;
168 if (module)
169 {
170 module->FindFunctions (name,
171 eFunctionNameTypeBase |
172 eFunctionNameTypeFull |
173 eFunctionNameTypeMethod |
174 eFunctionNameTypeSelector,
175 include_symbols,
176 true,
177 sc_list);
178 }
179 else if (exe_ctx.target)
180 {
181 exe_ctx.target->GetImages().FindFunctions (name,
Greg Clayton6dbd3982010-09-15 05:51:24 +0000182 eFunctionNameTypeBase |
183 eFunctionNameTypeFull |
184 eFunctionNameTypeMethod |
185 eFunctionNameTypeSelector,
Greg Clayton931180e2011-01-27 06:44:37 +0000186 include_symbols,
Sean Callanan8ade1042010-07-27 00:55:47 +0000187 false,
Greg Clayton931180e2011-01-27 06:44:37 +0000188 sc_list);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000189 }
Greg Clayton931180e2011-01-27 06:44:37 +0000190 }
191
192 if (sc_list.GetSize ())
193 {
194 return Disassemble (debugger,
195 arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000196 plugin_name,
Greg Clayton931180e2011-01-27 06:44:37 +0000197 exe_ctx,
Jim Ingham37023b02011-03-22 01:48:42 +0000198 sc_list,
199 num_instructions,
Greg Clayton931180e2011-01-27 06:44:37 +0000200 num_mixed_context_lines,
Sean Callananb3396b22011-03-10 23:35:12 +0000201 show_bytes,
202 raw,
Greg Clayton931180e2011-01-27 06:44:37 +0000203 strm);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000204 }
205 return false;
206}
207
Greg Clayton1d273162010-10-06 03:09:58 +0000208
209lldb::DisassemblerSP
210Disassembler::DisassembleRange
211(
212 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000213 const char *plugin_name,
Greg Clayton1d273162010-10-06 03:09:58 +0000214 const ExecutionContext &exe_ctx,
215 const AddressRange &range
216)
217{
218 lldb::DisassemblerSP disasm_sp;
219 if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid())
220 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000221 disasm_sp.reset (Disassembler::FindPlugin(arch, plugin_name));
Greg Clayton1d273162010-10-06 03:09:58 +0000222
223 if (disasm_sp)
224 {
Greg Clayton357132e2011-03-26 19:14:58 +0000225 size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range);
Greg Clayton1d273162010-10-06 03:09:58 +0000226 if (bytes_disassembled == 0)
227 disasm_sp.reset();
228 }
229 }
230 return disasm_sp;
231}
232
233
Greg Claytondda4f7b2010-06-30 23:03:03 +0000234bool
235Disassembler::Disassemble
236(
237 Debugger &debugger,
238 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000239 const char *plugin_name,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000240 const ExecutionContext &exe_ctx,
241 const AddressRange &disasm_range,
Jim Ingham37023b02011-03-22 01:48:42 +0000242 uint32_t num_instructions,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000243 uint32_t num_mixed_context_lines,
244 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000245 bool raw,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000246 Stream &strm
247)
248{
249 if (disasm_range.GetByteSize())
250 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000251 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name));
Greg Claytondda4f7b2010-06-30 23:03:03 +0000252
Greg Clayton1d273162010-10-06 03:09:58 +0000253 if (disasm_ap.get())
Greg Claytondda4f7b2010-06-30 23:03:03 +0000254 {
Greg Clayton357132e2011-03-26 19:14:58 +0000255 AddressRange range;
256 ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress());
257 range.SetByteSize (disasm_range.GetByteSize());
Greg Claytondda4f7b2010-06-30 23:03:03 +0000258
Greg Clayton357132e2011-03-26 19:14:58 +0000259 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, range);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000260 if (bytes_disassembled == 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000261 return false;
Greg Clayton1080edbc2011-03-25 18:03:16 +0000262
263 return PrintInstructions (disasm_ap.get(),
264 debugger,
265 arch,
266 exe_ctx,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000267 num_instructions,
268 num_mixed_context_lines,
269 show_bytes,
270 raw,
271 strm);
Jim Ingham37023b02011-03-22 01:48:42 +0000272 }
273 }
274 return false;
275}
276
277bool
278Disassembler::Disassemble
279(
280 Debugger &debugger,
281 const ArchSpec &arch,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000282 const char *plugin_name,
Jim Ingham37023b02011-03-22 01:48:42 +0000283 const ExecutionContext &exe_ctx,
284 const Address &start_address,
285 uint32_t num_instructions,
286 uint32_t num_mixed_context_lines,
287 bool show_bytes,
288 bool raw,
289 Stream &strm
290)
291{
292 if (num_instructions > 0)
293 {
Greg Clayton1080edbc2011-03-25 18:03:16 +0000294 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name));
Jim Ingham37023b02011-03-22 01:48:42 +0000295 if (disasm_ap.get())
296 {
Greg Clayton357132e2011-03-26 19:14:58 +0000297 Address addr;
298 ResolveAddress (exe_ctx, start_address, addr);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000299
Greg Clayton357132e2011-03-26 19:14:58 +0000300 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, addr, num_instructions);
Jim Ingham37023b02011-03-22 01:48:42 +0000301 if (bytes_disassembled == 0)
Jim Ingham37023b02011-03-22 01:48:42 +0000302 return false;
Greg Clayton1080edbc2011-03-25 18:03:16 +0000303 return PrintInstructions (disasm_ap.get(),
304 debugger,
305 arch,
306 exe_ctx,
Greg Clayton1080edbc2011-03-25 18:03:16 +0000307 num_instructions,
308 num_mixed_context_lines,
309 show_bytes,
310 raw,
311 strm);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000312 }
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000313 }
314 return false;
315}
Jim Ingham37023b02011-03-22 01:48:42 +0000316
317bool
318Disassembler::PrintInstructions
319(
320 Disassembler *disasm_ptr,
Jim Ingham37023b02011-03-22 01:48:42 +0000321 Debugger &debugger,
322 const ArchSpec &arch,
323 const ExecutionContext &exe_ctx,
Jim Ingham37023b02011-03-22 01:48:42 +0000324 uint32_t num_instructions,
325 uint32_t num_mixed_context_lines,
326 bool show_bytes,
327 bool raw,
328 Stream &strm
329)
330{
331 // We got some things disassembled...
332 size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
333
334 if (num_instructions > 0 && num_instructions < num_instructions_found)
335 num_instructions_found = num_instructions;
336
Greg Clayton357132e2011-03-26 19:14:58 +0000337 const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
Jim Ingham37023b02011-03-22 01:48:42 +0000338 uint32_t offset = 0;
339 SymbolContext sc;
340 SymbolContext prev_sc;
341 AddressRange sc_range;
Greg Clayton32e0a752011-03-30 18:16:51 +0000342 Address *pc_addr_ptr = NULL;
343 if (exe_ctx.frame)
344 pc_addr_ptr = &exe_ctx.frame->GetFrameCodeAddress();
Jim Ingham37023b02011-03-22 01:48:42 +0000345
346 for (size_t i=0; i<num_instructions_found; ++i)
347 {
348 Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
349 if (inst)
350 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000351 const Address &addr = inst->GetAddress();
352 const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
Jim Ingham37023b02011-03-22 01:48:42 +0000353
354 prev_sc = sc;
355
Greg Clayton32e0a752011-03-30 18:16:51 +0000356 Module *module = addr.GetModule();
357 if (module)
Jim Ingham37023b02011-03-22 01:48:42 +0000358 {
Jim Ingham37023b02011-03-22 01:48:42 +0000359 uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
360 if (resolved_mask)
361 {
Greg Clayton32e0a752011-03-30 18:16:51 +0000362 if (num_mixed_context_lines)
363 {
364 if (!sc_range.ContainsFileAddress (addr))
365 {
366 sc.GetAddressRange (eSymbolContextEverything, sc_range);
367
368 if (sc != prev_sc)
369 {
370 if (offset != 0)
371 strm.EOL();
372
373 sc.DumpStopContext(&strm, exe_ctx.process, addr, false, true, false);
374 strm.EOL();
375
376 if (sc.comp_unit && sc.line_entry.IsValid())
377 {
378 debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
379 sc.line_entry.line,
380 num_mixed_context_lines,
381 num_mixed_context_lines,
382 num_mixed_context_lines ? "->" : "",
383 &strm);
384 }
385 }
386 }
387 }
388 else if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol))
Jim Ingham37023b02011-03-22 01:48:42 +0000389 {
390 if (prev_sc.function || prev_sc.symbol)
391 strm.EOL();
392
393 strm << sc.module_sp->GetFileSpec().GetFilename();
394
395 if (sc.function)
396 strm << '`' << sc.function->GetMangled().GetName();
397 else if (sc.symbol)
398 strm << '`' << sc.symbol->GetMangled().GetName();
399 strm << ":\n";
400 }
Jim Ingham37023b02011-03-22 01:48:42 +0000401 }
402 else
403 {
404 sc.Clear();
405 }
406 }
Jim Ingham37023b02011-03-22 01:48:42 +0000407
Greg Clayton32e0a752011-03-30 18:16:51 +0000408 if (pc_addr_ptr)
409 {
410 if (inst_is_at_pc)
411 strm.PutCString("-> ");
412 else
413 strm.PutCString(" ");
414 }
415 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,
437 bool show_bytes,
Sean Callananb3396b22011-03-10 23:35:12 +0000438 bool raw,
Greg Claytondda4f7b2010-06-30 23:03:03 +0000439 Stream &strm
440)
441{
442 AddressRange range;
443 if (exe_ctx.frame)
444 {
445 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
446 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 Clayton9da7bd02010-08-24 21:05:24 +0000456 range.GetBaseAddress() = exe_ctx.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,
470 show_bytes,
471 raw,
472 strm);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000473}
474
Greg Clayton357132e2011-03-26 19:14:58 +0000475Instruction::Instruction(const Address &address, AddressClass addr_class) :
Greg Clayton1080edbc2011-03-25 18:03:16 +0000476 m_address (address),
Greg Clayton357132e2011-03-26 19:14:58 +0000477 m_address_class (addr_class),
Greg Clayton1080edbc2011-03-25 18:03:16 +0000478 m_opcode()
Greg Clayton0ae96272011-03-24 23:53:38 +0000479{
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000480}
481
Greg Clayton1d273162010-10-06 03:09:58 +0000482Instruction::~Instruction()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000483{
484}
485
Greg Clayton357132e2011-03-26 19:14:58 +0000486AddressClass
487Instruction::GetAddressClass ()
488{
489 if (m_address_class == eAddressClassInvalid)
490 m_address_class = m_address.GetAddressClass();
491 return m_address_class;
492}
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000493
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000494bool
495Instruction::DumpEmulation (const ArchSpec &arch)
496{
497 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL));
498 if (insn_emulator_ap.get())
499 {
500 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress());
501 return insn_emulator_ap->EvaluateInstruction ();
502 }
503
504 return false;
505}
506
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000507OptionValueSP
508Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type)
509{
510 bool done = false;
511 char buffer[1024];
512
513 OptionValueSP option_value_sp (new OptionValueArray (1u << data_type));
514
515 int idx = 0;
516 while (!done)
517 {
518 if (!fgets (buffer, 1023, in_file))
519 {
520 out_stream->Printf ("Instruction::ReadArray: Erroe reading file (fgets).\n");
521 option_value_sp.reset ();
522 return option_value_sp;
523 }
524
525 std::string line (buffer);
526
527 int len = line.size();
528 if (line[len-1] == '\n')
529 {
530 line[len-1] = '\0';
531 line.resize (len-1);
532 }
533
534 if ((line.size() == 1) && line[0] == ']')
535 {
536 done = true;
537 line.clear();
538 }
539
540 if (line.size() > 0)
541 {
542 std::string value;
543 RegularExpression reg_exp ("^[ \t]*([^ \t]+)[ \t]*$");
544 bool reg_exp_success = reg_exp.Execute (line.c_str(), 1);
545 if (reg_exp_success)
546 reg_exp.GetMatchAtIndex (line.c_str(), 1, value);
547 else
548 value = line;
549
550 OptionValueSP data_value_sp;
551 switch (data_type)
552 {
553 case OptionValue::eTypeUInt64:
554 data_value_sp.reset (new OptionValueUInt64 (0, 0));
555 data_value_sp->SetValueFromCString (value.c_str());
556 break;
557 // Other types can be added later as needed.
558 default:
559 data_value_sp.reset (new OptionValueString (value.c_str(), ""));
560 break;
561 }
562
563 option_value_sp->GetAsArrayValue()->InsertValue (idx, data_value_sp);
564 ++idx;
565 }
566 }
567
568 return option_value_sp;
569}
570
571OptionValueSP
572Instruction::ReadDictionary (FILE *in_file, Stream *out_stream)
573{
574 bool done = false;
575 char buffer[1024];
576
577 OptionValueSP option_value_sp (new OptionValueDictionary());
578 static ConstString encoding_key ("data_encoding");
579 OptionValue::Type data_type = OptionValue::eTypeInvalid;
580
581
582 while (!done)
583 {
584 // Read the next line in the file
585 if (!fgets (buffer, 1023, in_file))
586 {
587 out_stream->Printf ("Instruction::ReadDictionary: Error reading file (fgets).\n");
588 option_value_sp.reset ();
589 return option_value_sp;
590 }
591
592 // Check to see if the line contains the end-of-dictionary marker ("}")
593 std::string line (buffer);
594
595 int len = line.size();
596 if (line[len-1] == '\n')
597 {
598 line[len-1] = '\0';
599 line.resize (len-1);
600 }
601
602 if ((line.size() == 1) && (line[0] == '}'))
603 {
604 done = true;
605 line.clear();
606 }
607
608 // Try to find a key-value pair in the current line and add it to the dictionary.
609 if (line.size() > 0)
610 {
611 RegularExpression reg_exp ("^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$");
612 bool reg_exp_success = reg_exp.Execute (line.c_str(), 2);
613 std::string key;
614 std::string value;
615 if (reg_exp_success)
616 {
617 reg_exp.GetMatchAtIndex (line.c_str(), 1, key);
618 reg_exp.GetMatchAtIndex (line.c_str(), 2, value);
619 }
620 else
621 {
622 out_stream->Printf ("Instruction::ReadDictionary: Failure executing regular expression.\n");
623 option_value_sp.reset();
624 return option_value_sp;
625 }
626
627 ConstString const_key (key.c_str());
628 // Check value to see if it's the start of an array or dictionary.
629
630 lldb::OptionValueSP value_sp;
631 assert (value.empty() == false);
632 assert (key.empty() == false);
633
634 if (value[0] == '{')
635 {
636 assert (value.size() == 1);
637 // value is a dictionary
638 value_sp = ReadDictionary (in_file, out_stream);
639 if (value_sp.get() == NULL)
640 {
641 option_value_sp.reset ();
642 return option_value_sp;
643 }
644 }
645 else if (value[0] == '[')
646 {
647 assert (value.size() == 1);
648 // value is an array
649 value_sp = ReadArray (in_file, out_stream, data_type);
650 if (value_sp.get() == NULL)
651 {
652 option_value_sp.reset ();
653 return option_value_sp;
654 }
655 // We've used the data_type to read an array; re-set the type to Invalid
656 data_type = OptionValue::eTypeInvalid;
657 }
658 else if ((value[0] == '0') && (value[1] == 'x'))
659 {
660 value_sp.reset (new OptionValueUInt64 (0, 0));
661 value_sp->SetValueFromCString (value.c_str());
662 }
663 else
664 {
665 int len = value.size();
666 if ((value[0] == '"') && (value[len-1] == '"'))
667 value = value.substr (1, len-2);
668 value_sp.reset (new OptionValueString (value.c_str(), ""));
669 }
670
671
672
673 if (const_key == encoding_key)
674 {
675 // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data indicating the
676 // data type of an upcoming array (usually the next bit of data to be read in).
677 if (strcmp (value.c_str(), "uint32_t") == 0)
678 data_type = OptionValue::eTypeUInt64;
679 }
680 else
681 option_value_sp->GetAsDictionaryValue()->SetValueForKey (const_key, value_sp, false);
682 }
683 }
684
685 return option_value_sp;
686}
687
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000688bool
Caroline Tice3ac67112011-04-19 23:30:03 +0000689Instruction::TestEmulation (Stream *out_stream, const char *file_name)
690{
691 if (!out_stream)
692 return false;
693
694 if (!file_name)
695 {
Johnny Chenea80ba82011-04-21 20:27:45 +0000696 out_stream->Printf ("Instruction::TestEmulation: Missing file_name.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000697 return false;
698 }
699
700 FILE *test_file = fopen (file_name, "r");
701 if (!test_file)
702 {
Johnny Chenea80ba82011-04-21 20:27:45 +0000703 out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000704 return false;
705 }
706
Caroline Tice3ac67112011-04-19 23:30:03 +0000707 char buffer[256];
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000708 if (!fgets (buffer, 255, test_file))
Caroline Tice3ac67112011-04-19 23:30:03 +0000709 {
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000710 out_stream->Printf ("Instruction::TestEmulation: Error reading first line of test file.\n");
Caroline Tice3ac67112011-04-19 23:30:03 +0000711 fclose (test_file);
712 return false;
713 }
714
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000715 if (strncmp (buffer, "InstructionEmulationState={", 27) != 0)
716 {
717 out_stream->Printf ("Instructin::TestEmulation: Test file does not contain emulation state dictionary\n");
718 fclose (test_file);
719 return false;
720 }
721
722 // Read all the test information from the test file into an OptionValueDictionary.
723
724 OptionValueSP data_dictionary_sp (ReadDictionary (test_file, out_stream));
725 if (data_dictionary_sp.get() == NULL)
726 {
727 out_stream->Printf ("Instruction::TestEmulation: Error reading Dictionary Object.\n");
728 fclose (test_file);
729 return false;
730 }
731
732 fclose (test_file);
733
734 OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionaryValue();
735 static ConstString description_key ("assembly_string");
736 static ConstString triple_key ("triple");
737
738 OptionValueSP value_sp = data_dictionary->GetValueForKey (description_key);
739
740 if (value_sp.get() == NULL)
741 {
742 out_stream->Printf ("Instruction::TestEmulation: Test file does not contain description string.\n");
743 return false;
744 }
745
746 SetDescription (value_sp->GetStringValue());
747
748
749 value_sp = data_dictionary->GetValueForKey (triple_key);
750 if (value_sp.get() == NULL)
751 {
752 out_stream->Printf ("Instruction::TestEmulation: Test file does not contain triple.\n");
753 return false;
754 }
755
756 ArchSpec arch;
757 arch.SetTriple (llvm::Triple (value_sp->GetStringValue()));
Caroline Tice3ac67112011-04-19 23:30:03 +0000758
759 bool success = false;
760 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL));
761 if (insn_emulator_ap.get())
Caroline Ticede2fb9c2011-04-22 05:08:45 +0000762 success = insn_emulator_ap->TestEmulation (out_stream, arch, data_dictionary);
Caroline Tice3ac67112011-04-19 23:30:03 +0000763
Caroline Tice3ac67112011-04-19 23:30:03 +0000764 if (success)
Johnny Chenea80ba82011-04-21 20:27:45 +0000765 out_stream->Printf ("Emulation test succeeded.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000766 else
Johnny Chenea80ba82011-04-21 20:27:45 +0000767 out_stream->Printf ("Emulation test failed.");
Caroline Tice3ac67112011-04-19 23:30:03 +0000768
769 return success;
770}
771
772bool
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000773Instruction::Emulate (const ArchSpec &arch,
Caroline Tice25d61ac2011-04-08 23:33:06 +0000774 bool auto_advance_pc,
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000775 void *baton,
776 EmulateInstruction::ReadMemory read_mem_callback,
777 EmulateInstruction::WriteMemory write_mem_callback,
778 EmulateInstruction::ReadRegister read_reg_callback,
779 EmulateInstruction::WriteRegister write_reg_callback)
780{
781 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL));
782 if (insn_emulator_ap.get())
783 {
784 insn_emulator_ap->SetBaton (baton);
785 insn_emulator_ap->SetCallbacks (read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback);
786 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress());
Caroline Tice25d61ac2011-04-08 23:33:06 +0000787 insn_emulator_ap->SetAdvancePC (auto_advance_pc);
Caroline Tice7c9dd3c2011-04-05 23:22:54 +0000788 return insn_emulator_ap->EvaluateInstruction ();
789 }
790
791 return false;
792}
793
Greg Clayton1d273162010-10-06 03:09:58 +0000794InstructionList::InstructionList() :
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000795 m_instructions()
796{
797}
798
Greg Clayton1d273162010-10-06 03:09:58 +0000799InstructionList::~InstructionList()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000800{
801}
802
803size_t
Greg Clayton1d273162010-10-06 03:09:58 +0000804InstructionList::GetSize() const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000805{
806 return m_instructions.size();
807}
808
Greg Clayton357132e2011-03-26 19:14:58 +0000809uint32_t
810InstructionList::GetMaxOpcocdeByteSize () const
811{
812 uint32_t max_inst_size = 0;
813 collection::const_iterator pos, end;
814 for (pos = m_instructions.begin(), end = m_instructions.end();
815 pos != end;
816 ++pos)
817 {
818 uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
819 if (max_inst_size < inst_size)
820 max_inst_size = inst_size;
821 }
822 return max_inst_size;
823}
824
825
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000826
Greg Clayton1d273162010-10-06 03:09:58 +0000827InstructionSP
828InstructionList::GetInstructionAtIndex (uint32_t idx) const
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000829{
Greg Clayton1d273162010-10-06 03:09:58 +0000830 InstructionSP inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000831 if (idx < m_instructions.size())
Greg Clayton1d273162010-10-06 03:09:58 +0000832 inst_sp = m_instructions[idx];
833 return inst_sp;
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000834}
835
836void
Greg Clayton1d273162010-10-06 03:09:58 +0000837InstructionList::Clear()
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000838{
839 m_instructions.clear();
840}
841
842void
Greg Clayton1d273162010-10-06 03:09:58 +0000843InstructionList::Append (lldb::InstructionSP &inst_sp)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000844{
845 if (inst_sp)
846 m_instructions.push_back(inst_sp);
847}
848
849
850size_t
851Disassembler::ParseInstructions
852(
853 const ExecutionContext *exe_ctx,
Greg Clayton357132e2011-03-26 19:14:58 +0000854 const AddressRange &range
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000855)
856{
Greg Claytondda4f7b2010-06-30 23:03:03 +0000857 Target *target = exe_ctx->target;
Greg Claytondda4f7b2010-06-30 23:03:03 +0000858 const addr_t byte_size = range.GetByteSize();
859 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000860 return 0;
861
Greg Claytondda4f7b2010-06-30 23:03:03 +0000862 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
863 DataBufferSP data_sp(heap_buffer);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000864
865 Error error;
Greg Clayton357132e2011-03-26 19:14:58 +0000866 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);
Greg Claytondda4f7b2010-06-30 23:03:03 +0000872
873 if (bytes_read > 0)
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000874 {
Greg Claytondda4f7b2010-06-30 23:03:03 +0000875 if (bytes_read != heap_buffer->GetByteSize())
876 heap_buffer->SetByteSize (bytes_read);
Greg Clayton357132e2011-03-26 19:14:58 +0000877 DataExtractor data (data_sp,
878 m_arch.GetByteOrder(),
879 m_arch.GetAddressByteSize());
Jim Ingham37023b02011-03-22 01:48:42 +0000880 return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false);
Chris Lattner30fdc8d2010-06-08 16:52:24 +0000881 }
882
883 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
896 if (num_instructions == 0 || !start.IsValid())
Jim Ingham37023b02011-03-22 01:48:42 +0000897 return 0;
898
899 Target *target = exe_ctx->target;
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}