1 //===-- 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/lldb-python.h"
11
12 #include "lldb/Core/Disassembler.h"
13
14 // C Includes
15 // C++ Includes
16 // Other libraries and framework includes
17 // Project includes
18 #include "lldb/lldb-private.h"
19 #include "lldb/Core/Error.h"
20 #include "lldb/Core/DataBufferHeap.h"
21 #include "lldb/Core/DataExtractor.h"
22 #include "lldb/Core/Debugger.h"
23 #include "lldb/Core/EmulateInstruction.h"
24 #include "lldb/Core/Module.h"
25 #include "lldb/Core/PluginManager.h"
26 #include "lldb/Core/RegularExpression.h"
27 #include "lldb/Core/Timer.h"
28 #include "lldb/Interpreter/OptionValue.h"
29 #include "lldb/Interpreter/OptionValueArray.h"
30 #include "lldb/Interpreter/OptionValueDictionary.h"
31 #include "lldb/Interpreter/OptionValueString.h"
32 #include "lldb/Interpreter/OptionValueUInt64.h"
33 #include "lldb/Symbol/ClangNamespaceDecl.h"
34 #include "lldb/Symbol/Function.h"
35 #include "lldb/Symbol/ObjectFile.h"
36 #include "lldb/Target/ExecutionContext.h"
37 #include "lldb/Target/Process.h"
38 #include "lldb/Target/StackFrame.h"
39 #include "lldb/Target/Target.h"
40
41 #define DEFAULT_DISASM_BYTE_SIZE 32
42
43 using namespace lldb;
44 using namespace lldb_private;
45
46
47 DisassemblerSP
FindPlugin(const ArchSpec & arch,const char * flavor,const char * plugin_name)48 Disassembler::FindPlugin (const ArchSpec &arch, const char *flavor, const char *plugin_name)
49 {
50 Timer scoped_timer (__PRETTY_FUNCTION__,
51 "Disassembler::FindPlugin (arch = %s, plugin_name = %s)",
52 arch.GetArchitectureName(),
53 plugin_name);
54
55 DisassemblerCreateInstance create_callback = NULL;
56
57 if (plugin_name)
58 {
59 ConstString const_plugin_name (plugin_name);
60 create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName (const_plugin_name);
61 if (create_callback)
62 {
63 DisassemblerSP disassembler_sp(create_callback(arch, flavor));
64
65 if (disassembler_sp.get())
66 return disassembler_sp;
67 }
68 }
69 else
70 {
71 for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != NULL; ++idx)
72 {
73 DisassemblerSP disassembler_sp(create_callback(arch, flavor));
74
75 if (disassembler_sp.get())
76 return disassembler_sp;
77 }
78 }
79 return DisassemblerSP();
80 }
81
82 DisassemblerSP
FindPluginForTarget(const TargetSP target_sp,const ArchSpec & arch,const char * flavor,const char * plugin_name)83 Disassembler::FindPluginForTarget(const TargetSP target_sp, const ArchSpec &arch, const char *flavor, const char *plugin_name)
84 {
85 if (target_sp && flavor == NULL)
86 {
87 // FIXME - we don't have the mechanism in place to do per-architecture settings. But since we know that for now
88 // we only support flavors on x86 & x86_64,
89 if (arch.GetTriple().getArch() == llvm::Triple::x86
90 || arch.GetTriple().getArch() == llvm::Triple::x86_64)
91 flavor = target_sp->GetDisassemblyFlavor();
92 }
93 return FindPlugin(arch, flavor, plugin_name);
94 }
95
96
97 static void
ResolveAddress(const ExecutionContext & exe_ctx,const Address & addr,Address & resolved_addr)98 ResolveAddress (const ExecutionContext &exe_ctx,
99 const Address &addr,
100 Address &resolved_addr)
101 {
102 if (!addr.IsSectionOffset())
103 {
104 // If we weren't passed in a section offset address range,
105 // try and resolve it to something
106 Target *target = exe_ctx.GetTargetPtr();
107 if (target)
108 {
109 if (target->GetSectionLoadList().IsEmpty())
110 {
111 target->GetImages().ResolveFileAddress (addr.GetOffset(), resolved_addr);
112 }
113 else
114 {
115 target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), resolved_addr);
116 }
117 // We weren't able to resolve the address, just treat it as a
118 // raw address
119 if (resolved_addr.IsValid())
120 return;
121 }
122 }
123 resolved_addr = addr;
124 }
125
126 size_t
Disassemble(Debugger & debugger,const ArchSpec & arch,const char * plugin_name,const char * flavor,const ExecutionContext & exe_ctx,SymbolContextList & sc_list,uint32_t num_instructions,uint32_t num_mixed_context_lines,uint32_t options,Stream & strm)127 Disassembler::Disassemble
128 (
129 Debugger &debugger,
130 const ArchSpec &arch,
131 const char *plugin_name,
132 const char *flavor,
133 const ExecutionContext &exe_ctx,
134 SymbolContextList &sc_list,
135 uint32_t num_instructions,
136 uint32_t num_mixed_context_lines,
137 uint32_t options,
138 Stream &strm
139 )
140 {
141 size_t success_count = 0;
142 const size_t count = sc_list.GetSize();
143 SymbolContext sc;
144 AddressRange range;
145 const uint32_t scope = eSymbolContextBlock | eSymbolContextFunction | eSymbolContextSymbol;
146 const bool use_inline_block_range = true;
147 for (size_t i=0; i<count; ++i)
148 {
149 if (sc_list.GetContextAtIndex(i, sc) == false)
150 break;
151 for (uint32_t range_idx = 0; sc.GetAddressRange(scope, range_idx, use_inline_block_range, range); ++range_idx)
152 {
153 if (Disassemble (debugger,
154 arch,
155 plugin_name,
156 flavor,
157 exe_ctx,
158 range,
159 num_instructions,
160 num_mixed_context_lines,
161 options,
162 strm))
163 {
164 ++success_count;
165 strm.EOL();
166 }
167 }
168 }
169 return success_count;
170 }
171
172 bool
Disassemble(Debugger & debugger,const ArchSpec & arch,const char * plugin_name,const char * flavor,const ExecutionContext & exe_ctx,const ConstString & name,Module * module,uint32_t num_instructions,uint32_t num_mixed_context_lines,uint32_t options,Stream & strm)173 Disassembler::Disassemble
174 (
175 Debugger &debugger,
176 const ArchSpec &arch,
177 const char *plugin_name,
178 const char *flavor,
179 const ExecutionContext &exe_ctx,
180 const ConstString &name,
181 Module *module,
182 uint32_t num_instructions,
183 uint32_t num_mixed_context_lines,
184 uint32_t options,
185 Stream &strm
186 )
187 {
188 SymbolContextList sc_list;
189 if (name)
190 {
191 const bool include_symbols = true;
192 const bool include_inlines = true;
193 if (module)
194 {
195 module->FindFunctions (name,
196 NULL,
197 eFunctionNameTypeAuto,
198 include_symbols,
199 include_inlines,
200 true,
201 sc_list);
202 }
203 else if (exe_ctx.GetTargetPtr())
204 {
205 exe_ctx.GetTargetPtr()->GetImages().FindFunctions (name,
206 eFunctionNameTypeAuto,
207 include_symbols,
208 include_inlines,
209 false,
210 sc_list);
211 }
212 }
213
214 if (sc_list.GetSize ())
215 {
216 return Disassemble (debugger,
217 arch,
218 plugin_name,
219 flavor,
220 exe_ctx,
221 sc_list,
222 num_instructions,
223 num_mixed_context_lines,
224 options,
225 strm);
226 }
227 return false;
228 }
229
230
231 lldb::DisassemblerSP
DisassembleRange(const ArchSpec & arch,const char * plugin_name,const char * flavor,const ExecutionContext & exe_ctx,const AddressRange & range)232 Disassembler::DisassembleRange
233 (
234 const ArchSpec &arch,
235 const char *plugin_name,
236 const char *flavor,
237 const ExecutionContext &exe_ctx,
238 const AddressRange &range
239 )
240 {
241 lldb::DisassemblerSP disasm_sp;
242 if (range.GetByteSize() > 0 && range.GetBaseAddress().IsValid())
243 {
244 disasm_sp = Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name);
245
246 if (disasm_sp)
247 {
248 const bool prefer_file_cache = false;
249 size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, NULL, prefer_file_cache);
250 if (bytes_disassembled == 0)
251 disasm_sp.reset();
252 }
253 }
254 return disasm_sp;
255 }
256
257 lldb::DisassemblerSP
DisassembleBytes(const ArchSpec & arch,const char * plugin_name,const char * flavor,const Address & start,const void * src,size_t src_len,uint32_t num_instructions,bool data_from_file)258 Disassembler::DisassembleBytes (const ArchSpec &arch,
259 const char *plugin_name,
260 const char *flavor,
261 const Address &start,
262 const void *src,
263 size_t src_len,
264 uint32_t num_instructions,
265 bool data_from_file)
266 {
267 lldb::DisassemblerSP disasm_sp;
268
269 if (src)
270 {
271 disasm_sp = Disassembler::FindPlugin(arch, flavor, plugin_name);
272
273 if (disasm_sp)
274 {
275 DataExtractor data(src, src_len, arch.GetByteOrder(), arch.GetAddressByteSize());
276
277 (void)disasm_sp->DecodeInstructions (start,
278 data,
279 0,
280 num_instructions,
281 false,
282 data_from_file);
283 }
284 }
285
286 return disasm_sp;
287 }
288
289
290 bool
Disassemble(Debugger & debugger,const ArchSpec & arch,const char * plugin_name,const char * flavor,const ExecutionContext & exe_ctx,const AddressRange & disasm_range,uint32_t num_instructions,uint32_t num_mixed_context_lines,uint32_t options,Stream & strm)291 Disassembler::Disassemble
292 (
293 Debugger &debugger,
294 const ArchSpec &arch,
295 const char *plugin_name,
296 const char *flavor,
297 const ExecutionContext &exe_ctx,
298 const AddressRange &disasm_range,
299 uint32_t num_instructions,
300 uint32_t num_mixed_context_lines,
301 uint32_t options,
302 Stream &strm
303 )
304 {
305 if (disasm_range.GetByteSize())
306 {
307 lldb::DisassemblerSP disasm_sp (Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(), arch, flavor, plugin_name));
308
309 if (disasm_sp.get())
310 {
311 AddressRange range;
312 ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress());
313 range.SetByteSize (disasm_range.GetByteSize());
314 const bool prefer_file_cache = false;
315 size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx, range, &strm, prefer_file_cache);
316 if (bytes_disassembled == 0)
317 return false;
318
319 bool result = PrintInstructions (disasm_sp.get(),
320 debugger,
321 arch,
322 exe_ctx,
323 num_instructions,
324 num_mixed_context_lines,
325 options,
326 strm);
327
328 // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions.
329 // I'll fix that but for now, just clear the list and it will go away nicely.
330 disasm_sp->GetInstructionList().Clear();
331 return result;
332 }
333 }
334 return false;
335 }
336
337 bool
Disassemble(Debugger & debugger,const ArchSpec & arch,const char * plugin_name,const char * flavor,const ExecutionContext & exe_ctx,const Address & start_address,uint32_t num_instructions,uint32_t num_mixed_context_lines,uint32_t options,Stream & strm)338 Disassembler::Disassemble
339 (
340 Debugger &debugger,
341 const ArchSpec &arch,
342 const char *plugin_name,
343 const char *flavor,
344 const ExecutionContext &exe_ctx,
345 const Address &start_address,
346 uint32_t num_instructions,
347 uint32_t num_mixed_context_lines,
348 uint32_t options,
349 Stream &strm
350 )
351 {
352 if (num_instructions > 0)
353 {
354 lldb::DisassemblerSP disasm_sp (Disassembler::FindPluginForTarget(exe_ctx.GetTargetSP(),
355 arch,
356 flavor,
357 plugin_name));
358 if (disasm_sp.get())
359 {
360 Address addr;
361 ResolveAddress (exe_ctx, start_address, addr);
362 const bool prefer_file_cache = false;
363 size_t bytes_disassembled = disasm_sp->ParseInstructions (&exe_ctx,
364 addr,
365 num_instructions,
366 prefer_file_cache);
367 if (bytes_disassembled == 0)
368 return false;
369 bool result = PrintInstructions (disasm_sp.get(),
370 debugger,
371 arch,
372 exe_ctx,
373 num_instructions,
374 num_mixed_context_lines,
375 options,
376 strm);
377
378 // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions.
379 // I'll fix that but for now, just clear the list and it will go away nicely.
380 disasm_sp->GetInstructionList().Clear();
381 return result;
382 }
383 }
384 return false;
385 }
386
387 bool
PrintInstructions(Disassembler * disasm_ptr,Debugger & debugger,const ArchSpec & arch,const ExecutionContext & exe_ctx,uint32_t num_instructions,uint32_t num_mixed_context_lines,uint32_t options,Stream & strm)388 Disassembler::PrintInstructions
389 (
390 Disassembler *disasm_ptr,
391 Debugger &debugger,
392 const ArchSpec &arch,
393 const ExecutionContext &exe_ctx,
394 uint32_t num_instructions,
395 uint32_t num_mixed_context_lines,
396 uint32_t options,
397 Stream &strm
398 )
399 {
400 // We got some things disassembled...
401 size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize();
402
403 if (num_instructions > 0 && num_instructions < num_instructions_found)
404 num_instructions_found = num_instructions;
405
406 const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize ();
407 uint32_t offset = 0;
408 SymbolContext sc;
409 SymbolContext prev_sc;
410 AddressRange sc_range;
411 const Address *pc_addr_ptr = NULL;
412 ExecutionContextScope *exe_scope = exe_ctx.GetBestExecutionContextScope();
413 StackFrame *frame = exe_ctx.GetFramePtr();
414
415 TargetSP target_sp (exe_ctx.GetTargetSP());
416 SourceManager &source_manager = target_sp ? target_sp->GetSourceManager() : debugger.GetSourceManager();
417
418 if (frame)
419 pc_addr_ptr = &frame->GetFrameCodeAddress();
420 const uint32_t scope = eSymbolContextLineEntry | eSymbolContextFunction | eSymbolContextSymbol;
421 const bool use_inline_block_range = false;
422 for (size_t i=0; i<num_instructions_found; ++i)
423 {
424 Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get();
425 if (inst)
426 {
427 const Address &addr = inst->GetAddress();
428 const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr;
429
430 prev_sc = sc;
431
432 ModuleSP module_sp (addr.GetModule());
433 if (module_sp)
434 {
435 uint32_t resolved_mask = module_sp->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc);
436 if (resolved_mask)
437 {
438 if (num_mixed_context_lines)
439 {
440 if (!sc_range.ContainsFileAddress (addr))
441 {
442 sc.GetAddressRange (scope, 0, use_inline_block_range, sc_range);
443
444 if (sc != prev_sc)
445 {
446 if (offset != 0)
447 strm.EOL();
448
449 sc.DumpStopContext(&strm, exe_ctx.GetProcessPtr(), addr, false, true, false);
450 strm.EOL();
451
452 if (sc.comp_unit && sc.line_entry.IsValid())
453 {
454 source_manager.DisplaySourceLinesWithLineNumbers (sc.line_entry.file,
455 sc.line_entry.line,
456 num_mixed_context_lines,
457 num_mixed_context_lines,
458 ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""),
459 &strm);
460 }
461 }
462 }
463 }
464 else if ((sc.function || sc.symbol) && (sc.function != prev_sc.function || sc.symbol != prev_sc.symbol))
465 {
466 if (prev_sc.function || prev_sc.symbol)
467 strm.EOL();
468
469 bool show_fullpaths = false;
470 bool show_module = true;
471 bool show_inlined_frames = true;
472 sc.DumpStopContext (&strm,
473 exe_scope,
474 addr,
475 show_fullpaths,
476 show_module,
477 show_inlined_frames);
478
479 strm << ":\n";
480 }
481 }
482 else
483 {
484 sc.Clear(true);
485 }
486 }
487
488 if ((options & eOptionMarkPCAddress) && pc_addr_ptr)
489 {
490 strm.PutCString(inst_is_at_pc ? "-> " : " ");
491 }
492 const bool show_bytes = (options & eOptionShowBytes) != 0;
493 inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx);
494 strm.EOL();
495 }
496 else
497 {
498 break;
499 }
500 }
501
502 return true;
503 }
504
505
506 bool
Disassemble(Debugger & debugger,const ArchSpec & arch,const char * plugin_name,const char * flavor,const ExecutionContext & exe_ctx,uint32_t num_instructions,uint32_t num_mixed_context_lines,uint32_t options,Stream & strm)507 Disassembler::Disassemble
508 (
509 Debugger &debugger,
510 const ArchSpec &arch,
511 const char *plugin_name,
512 const char *flavor,
513 const ExecutionContext &exe_ctx,
514 uint32_t num_instructions,
515 uint32_t num_mixed_context_lines,
516 uint32_t options,
517 Stream &strm
518 )
519 {
520 AddressRange range;
521 StackFrame *frame = exe_ctx.GetFramePtr();
522 if (frame)
523 {
524 SymbolContext sc(frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol));
525 if (sc.function)
526 {
527 range = sc.function->GetAddressRange();
528 }
529 else if (sc.symbol && sc.symbol->ValueIsAddress())
530 {
531 range.GetBaseAddress() = sc.symbol->GetAddress();
532 range.SetByteSize (sc.symbol->GetByteSize());
533 }
534 else
535 {
536 range.GetBaseAddress() = frame->GetFrameCodeAddress();
537 }
538
539 if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0)
540 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE);
541 }
542
543 return Disassemble (debugger,
544 arch,
545 plugin_name,
546 flavor,
547 exe_ctx,
548 range,
549 num_instructions,
550 num_mixed_context_lines,
551 options,
552 strm);
553 }
554
Instruction(const Address & address,AddressClass addr_class)555 Instruction::Instruction(const Address &address, AddressClass addr_class) :
556 m_address (address),
557 m_address_class (addr_class),
558 m_opcode(),
559 m_calculated_strings(false)
560 {
561 }
562
~Instruction()563 Instruction::~Instruction()
564 {
565 }
566
567 AddressClass
GetAddressClass()568 Instruction::GetAddressClass ()
569 {
570 if (m_address_class == eAddressClassInvalid)
571 m_address_class = m_address.GetAddressClass();
572 return m_address_class;
573 }
574
575 void
Dump(lldb_private::Stream * s,uint32_t max_opcode_byte_size,bool show_address,bool show_bytes,const ExecutionContext * exe_ctx)576 Instruction::Dump (lldb_private::Stream *s,
577 uint32_t max_opcode_byte_size,
578 bool show_address,
579 bool show_bytes,
580 const ExecutionContext* exe_ctx)
581 {
582 size_t opcode_column_width = 7;
583 const size_t operand_column_width = 25;
584
585 CalculateMnemonicOperandsAndCommentIfNeeded (exe_ctx);
586
587 StreamString ss;
588
589 if (show_address)
590 {
591 m_address.Dump(&ss,
592 exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL,
593 Address::DumpStyleLoadAddress,
594 Address::DumpStyleModuleWithFileAddress,
595 0);
596
597 ss.PutCString(": ");
598 }
599
600 if (show_bytes)
601 {
602 if (m_opcode.GetType() == Opcode::eTypeBytes)
603 {
604 // x86_64 and i386 are the only ones that use bytes right now so
605 // pad out the byte dump to be able to always show 15 bytes (3 chars each)
606 // plus a space
607 if (max_opcode_byte_size > 0)
608 m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1);
609 else
610 m_opcode.Dump (&ss, 15 * 3 + 1);
611 }
612 else
613 {
614 // Else, we have ARM which can show up to a uint32_t 0x00000000 (10 spaces)
615 // plus two for padding...
616 if (max_opcode_byte_size > 0)
617 m_opcode.Dump (&ss, max_opcode_byte_size * 3 + 1);
618 else
619 m_opcode.Dump (&ss, 12);
620 }
621 }
622
623 const size_t opcode_pos = ss.GetSize();
624
625 // The default opcode size of 7 characters is plenty for most architectures
626 // but some like arm can pull out the occasional vqrshrun.s16. We won't get
627 // consistent column spacing in these cases, unfortunately.
628 if (m_opcode_name.length() >= opcode_column_width)
629 {
630 opcode_column_width = m_opcode_name.length() + 1;
631 }
632
633 ss.PutCString (m_opcode_name.c_str());
634 ss.FillLastLineToColumn (opcode_pos + opcode_column_width, ' ');
635 ss.PutCString (m_mnemonics.c_str());
636
637 if (!m_comment.empty())
638 {
639 ss.FillLastLineToColumn (opcode_pos + opcode_column_width + operand_column_width, ' ');
640 ss.PutCString (" ; ");
641 ss.PutCString (m_comment.c_str());
642 }
643 s->Write (ss.GetData(), ss.GetSize());
644 }
645
646 bool
DumpEmulation(const ArchSpec & arch)647 Instruction::DumpEmulation (const ArchSpec &arch)
648 {
649 std::unique_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL));
650 if (insn_emulator_ap.get())
651 {
652 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress(), NULL);
653 return insn_emulator_ap->EvaluateInstruction (0);
654 }
655
656 return false;
657 }
658
659 OptionValueSP
ReadArray(FILE * in_file,Stream * out_stream,OptionValue::Type data_type)660 Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type)
661 {
662 bool done = false;
663 char buffer[1024];
664
665 OptionValueSP option_value_sp (new OptionValueArray (1u << data_type));
666
667 int idx = 0;
668 while (!done)
669 {
670 if (!fgets (buffer, 1023, in_file))
671 {
672 out_stream->Printf ("Instruction::ReadArray: Error reading file (fgets).\n");
673 option_value_sp.reset ();
674 return option_value_sp;
675 }
676
677 std::string line (buffer);
678
679 size_t len = line.size();
680 if (line[len-1] == '\n')
681 {
682 line[len-1] = '\0';
683 line.resize (len-1);
684 }
685
686 if ((line.size() == 1) && line[0] == ']')
687 {
688 done = true;
689 line.clear();
690 }
691
692 if (line.size() > 0)
693 {
694 std::string value;
695 static RegularExpression g_reg_exp ("^[ \t]*([^ \t]+)[ \t]*$");
696 RegularExpression::Match regex_match(1);
697 bool reg_exp_success = g_reg_exp.Execute (line.c_str(), ®ex_match);
698 if (reg_exp_success)
699 regex_match.GetMatchAtIndex (line.c_str(), 1, value);
700 else
701 value = line;
702
703 OptionValueSP data_value_sp;
704 switch (data_type)
705 {
706 case OptionValue::eTypeUInt64:
707 data_value_sp.reset (new OptionValueUInt64 (0, 0));
708 data_value_sp->SetValueFromCString (value.c_str());
709 break;
710 // Other types can be added later as needed.
711 default:
712 data_value_sp.reset (new OptionValueString (value.c_str(), ""));
713 break;
714 }
715
716 option_value_sp->GetAsArray()->InsertValue (idx, data_value_sp);
717 ++idx;
718 }
719 }
720
721 return option_value_sp;
722 }
723
724 OptionValueSP
ReadDictionary(FILE * in_file,Stream * out_stream)725 Instruction::ReadDictionary (FILE *in_file, Stream *out_stream)
726 {
727 bool done = false;
728 char buffer[1024];
729
730 OptionValueSP option_value_sp (new OptionValueDictionary());
731 static ConstString encoding_key ("data_encoding");
732 OptionValue::Type data_type = OptionValue::eTypeInvalid;
733
734
735 while (!done)
736 {
737 // Read the next line in the file
738 if (!fgets (buffer, 1023, in_file))
739 {
740 out_stream->Printf ("Instruction::ReadDictionary: Error reading file (fgets).\n");
741 option_value_sp.reset ();
742 return option_value_sp;
743 }
744
745 // Check to see if the line contains the end-of-dictionary marker ("}")
746 std::string line (buffer);
747
748 size_t len = line.size();
749 if (line[len-1] == '\n')
750 {
751 line[len-1] = '\0';
752 line.resize (len-1);
753 }
754
755 if ((line.size() == 1) && (line[0] == '}'))
756 {
757 done = true;
758 line.clear();
759 }
760
761 // Try to find a key-value pair in the current line and add it to the dictionary.
762 if (line.size() > 0)
763 {
764 static RegularExpression g_reg_exp ("^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$");
765 RegularExpression::Match regex_match(2);
766
767 bool reg_exp_success = g_reg_exp.Execute (line.c_str(), ®ex_match);
768 std::string key;
769 std::string value;
770 if (reg_exp_success)
771 {
772 regex_match.GetMatchAtIndex (line.c_str(), 1, key);
773 regex_match.GetMatchAtIndex (line.c_str(), 2, value);
774 }
775 else
776 {
777 out_stream->Printf ("Instruction::ReadDictionary: Failure executing regular expression.\n");
778 option_value_sp.reset();
779 return option_value_sp;
780 }
781
782 ConstString const_key (key.c_str());
783 // Check value to see if it's the start of an array or dictionary.
784
785 lldb::OptionValueSP value_sp;
786 assert (value.empty() == false);
787 assert (key.empty() == false);
788
789 if (value[0] == '{')
790 {
791 assert (value.size() == 1);
792 // value is a dictionary
793 value_sp = ReadDictionary (in_file, out_stream);
794 if (value_sp.get() == NULL)
795 {
796 option_value_sp.reset ();
797 return option_value_sp;
798 }
799 }
800 else if (value[0] == '[')
801 {
802 assert (value.size() == 1);
803 // value is an array
804 value_sp = ReadArray (in_file, out_stream, data_type);
805 if (value_sp.get() == NULL)
806 {
807 option_value_sp.reset ();
808 return option_value_sp;
809 }
810 // We've used the data_type to read an array; re-set the type to Invalid
811 data_type = OptionValue::eTypeInvalid;
812 }
813 else if ((value[0] == '0') && (value[1] == 'x'))
814 {
815 value_sp.reset (new OptionValueUInt64 (0, 0));
816 value_sp->SetValueFromCString (value.c_str());
817 }
818 else
819 {
820 size_t len = value.size();
821 if ((value[0] == '"') && (value[len-1] == '"'))
822 value = value.substr (1, len-2);
823 value_sp.reset (new OptionValueString (value.c_str(), ""));
824 }
825
826
827
828 if (const_key == encoding_key)
829 {
830 // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data indicating the
831 // data type of an upcoming array (usually the next bit of data to be read in).
832 if (strcmp (value.c_str(), "uint32_t") == 0)
833 data_type = OptionValue::eTypeUInt64;
834 }
835 else
836 option_value_sp->GetAsDictionary()->SetValueForKey (const_key, value_sp, false);
837 }
838 }
839
840 return option_value_sp;
841 }
842
843 bool
TestEmulation(Stream * out_stream,const char * file_name)844 Instruction::TestEmulation (Stream *out_stream, const char *file_name)
845 {
846 if (!out_stream)
847 return false;
848
849 if (!file_name)
850 {
851 out_stream->Printf ("Instruction::TestEmulation: Missing file_name.");
852 return false;
853 }
854
855 FILE *test_file = fopen (file_name, "r");
856 if (!test_file)
857 {
858 out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed.");
859 return false;
860 }
861
862 char buffer[256];
863 if (!fgets (buffer, 255, test_file))
864 {
865 out_stream->Printf ("Instruction::TestEmulation: Error reading first line of test file.\n");
866 fclose (test_file);
867 return false;
868 }
869
870 if (strncmp (buffer, "InstructionEmulationState={", 27) != 0)
871 {
872 out_stream->Printf ("Instructin::TestEmulation: Test file does not contain emulation state dictionary\n");
873 fclose (test_file);
874 return false;
875 }
876
877 // Read all the test information from the test file into an OptionValueDictionary.
878
879 OptionValueSP data_dictionary_sp (ReadDictionary (test_file, out_stream));
880 if (data_dictionary_sp.get() == NULL)
881 {
882 out_stream->Printf ("Instruction::TestEmulation: Error reading Dictionary Object.\n");
883 fclose (test_file);
884 return false;
885 }
886
887 fclose (test_file);
888
889 OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionary();
890 static ConstString description_key ("assembly_string");
891 static ConstString triple_key ("triple");
892
893 OptionValueSP value_sp = data_dictionary->GetValueForKey (description_key);
894
895 if (value_sp.get() == NULL)
896 {
897 out_stream->Printf ("Instruction::TestEmulation: Test file does not contain description string.\n");
898 return false;
899 }
900
901 SetDescription (value_sp->GetStringValue());
902
903
904 value_sp = data_dictionary->GetValueForKey (triple_key);
905 if (value_sp.get() == NULL)
906 {
907 out_stream->Printf ("Instruction::TestEmulation: Test file does not contain triple.\n");
908 return false;
909 }
910
911 ArchSpec arch;
912 arch.SetTriple (llvm::Triple (value_sp->GetStringValue()));
913
914 bool success = false;
915 std::unique_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL));
916 if (insn_emulator_ap.get())
917 success = insn_emulator_ap->TestEmulation (out_stream, arch, data_dictionary);
918
919 if (success)
920 out_stream->Printf ("Emulation test succeeded.");
921 else
922 out_stream->Printf ("Emulation test failed.");
923
924 return success;
925 }
926
927 bool
Emulate(const ArchSpec & arch,uint32_t evaluate_options,void * baton,EmulateInstruction::ReadMemoryCallback read_mem_callback,EmulateInstruction::WriteMemoryCallback write_mem_callback,EmulateInstruction::ReadRegisterCallback read_reg_callback,EmulateInstruction::WriteRegisterCallback write_reg_callback)928 Instruction::Emulate (const ArchSpec &arch,
929 uint32_t evaluate_options,
930 void *baton,
931 EmulateInstruction::ReadMemoryCallback read_mem_callback,
932 EmulateInstruction::WriteMemoryCallback write_mem_callback,
933 EmulateInstruction::ReadRegisterCallback read_reg_callback,
934 EmulateInstruction::WriteRegisterCallback write_reg_callback)
935 {
936 std::unique_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL));
937 if (insn_emulator_ap.get())
938 {
939 insn_emulator_ap->SetBaton (baton);
940 insn_emulator_ap->SetCallbacks (read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback);
941 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress(), NULL);
942 return insn_emulator_ap->EvaluateInstruction (evaluate_options);
943 }
944
945 return false;
946 }
947
948
949 uint32_t
GetData(DataExtractor & data)950 Instruction::GetData (DataExtractor &data)
951 {
952 return m_opcode.GetData(data);
953 }
954
InstructionList()955 InstructionList::InstructionList() :
956 m_instructions()
957 {
958 }
959
~InstructionList()960 InstructionList::~InstructionList()
961 {
962 }
963
964 size_t
GetSize() const965 InstructionList::GetSize() const
966 {
967 return m_instructions.size();
968 }
969
970 uint32_t
GetMaxOpcocdeByteSize() const971 InstructionList::GetMaxOpcocdeByteSize () const
972 {
973 uint32_t max_inst_size = 0;
974 collection::const_iterator pos, end;
975 for (pos = m_instructions.begin(), end = m_instructions.end();
976 pos != end;
977 ++pos)
978 {
979 uint32_t inst_size = (*pos)->GetOpcode().GetByteSize();
980 if (max_inst_size < inst_size)
981 max_inst_size = inst_size;
982 }
983 return max_inst_size;
984 }
985
986
987
988 InstructionSP
GetInstructionAtIndex(size_t idx) const989 InstructionList::GetInstructionAtIndex (size_t idx) const
990 {
991 InstructionSP inst_sp;
992 if (idx < m_instructions.size())
993 inst_sp = m_instructions[idx];
994 return inst_sp;
995 }
996
997 void
Dump(Stream * s,bool show_address,bool show_bytes,const ExecutionContext * exe_ctx)998 InstructionList::Dump (Stream *s,
999 bool show_address,
1000 bool show_bytes,
1001 const ExecutionContext* exe_ctx)
1002 {
1003 const uint32_t max_opcode_byte_size = GetMaxOpcocdeByteSize();
1004 collection::const_iterator pos, begin, end;
1005 for (begin = m_instructions.begin(), end = m_instructions.end(), pos = begin;
1006 pos != end;
1007 ++pos)
1008 {
1009 if (pos != begin)
1010 s->EOL();
1011 (*pos)->Dump(s, max_opcode_byte_size, show_address, show_bytes, exe_ctx);
1012 }
1013 }
1014
1015
1016 void
Clear()1017 InstructionList::Clear()
1018 {
1019 m_instructions.clear();
1020 }
1021
1022 void
Append(lldb::InstructionSP & inst_sp)1023 InstructionList::Append (lldb::InstructionSP &inst_sp)
1024 {
1025 if (inst_sp)
1026 m_instructions.push_back(inst_sp);
1027 }
1028
1029 uint32_t
GetIndexOfNextBranchInstruction(uint32_t start) const1030 InstructionList::GetIndexOfNextBranchInstruction(uint32_t start) const
1031 {
1032 size_t num_instructions = m_instructions.size();
1033
1034 uint32_t next_branch = UINT32_MAX;
1035 for (size_t i = start; i < num_instructions; i++)
1036 {
1037 if (m_instructions[i]->DoesBranch())
1038 {
1039 next_branch = i;
1040 break;
1041 }
1042 }
1043 return next_branch;
1044 }
1045
1046 uint32_t
GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr,Target & target)1047 InstructionList::GetIndexOfInstructionAtLoadAddress (lldb::addr_t load_addr, Target &target)
1048 {
1049 Address address;
1050 address.SetLoadAddress(load_addr, &target);
1051 size_t num_instructions = m_instructions.size();
1052 uint32_t index = UINT32_MAX;
1053 for (size_t i = 0; i < num_instructions; i++)
1054 {
1055 if (m_instructions[i]->GetAddress() == address)
1056 {
1057 index = i;
1058 break;
1059 }
1060 }
1061 return index;
1062 }
1063
1064 size_t
ParseInstructions(const ExecutionContext * exe_ctx,const AddressRange & range,Stream * error_strm_ptr,bool prefer_file_cache)1065 Disassembler::ParseInstructions (const ExecutionContext *exe_ctx,
1066 const AddressRange &range,
1067 Stream *error_strm_ptr,
1068 bool prefer_file_cache)
1069 {
1070 if (exe_ctx)
1071 {
1072 Target *target = exe_ctx->GetTargetPtr();
1073 const addr_t byte_size = range.GetByteSize();
1074 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid())
1075 return 0;
1076
1077 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
1078 DataBufferSP data_sp(heap_buffer);
1079
1080 Error error;
1081 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
1082 const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(),
1083 prefer_file_cache,
1084 heap_buffer->GetBytes(),
1085 heap_buffer->GetByteSize(),
1086 error,
1087 &load_addr);
1088
1089 if (bytes_read > 0)
1090 {
1091 if (bytes_read != heap_buffer->GetByteSize())
1092 heap_buffer->SetByteSize (bytes_read);
1093 DataExtractor data (data_sp,
1094 m_arch.GetByteOrder(),
1095 m_arch.GetAddressByteSize());
1096 const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
1097 return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false, data_from_file);
1098 }
1099 else if (error_strm_ptr)
1100 {
1101 const char *error_cstr = error.AsCString();
1102 if (error_cstr)
1103 {
1104 error_strm_ptr->Printf("error: %s\n", error_cstr);
1105 }
1106 }
1107 }
1108 else if (error_strm_ptr)
1109 {
1110 error_strm_ptr->PutCString("error: invalid execution context\n");
1111 }
1112 return 0;
1113 }
1114
1115 size_t
ParseInstructions(const ExecutionContext * exe_ctx,const Address & start,uint32_t num_instructions,bool prefer_file_cache)1116 Disassembler::ParseInstructions (const ExecutionContext *exe_ctx,
1117 const Address &start,
1118 uint32_t num_instructions,
1119 bool prefer_file_cache)
1120 {
1121 m_instruction_list.Clear();
1122
1123 if (exe_ctx == NULL || num_instructions == 0 || !start.IsValid())
1124 return 0;
1125
1126 Target *target = exe_ctx->GetTargetPtr();
1127 // Calculate the max buffer size we will need in order to disassemble
1128 const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize();
1129
1130 if (target == NULL || byte_size == 0)
1131 return 0;
1132
1133 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0');
1134 DataBufferSP data_sp (heap_buffer);
1135
1136 Error error;
1137 lldb::addr_t load_addr = LLDB_INVALID_ADDRESS;
1138 const size_t bytes_read = target->ReadMemory (start,
1139 prefer_file_cache,
1140 heap_buffer->GetBytes(),
1141 byte_size,
1142 error,
1143 &load_addr);
1144
1145 const bool data_from_file = load_addr == LLDB_INVALID_ADDRESS;
1146
1147 if (bytes_read == 0)
1148 return 0;
1149 DataExtractor data (data_sp,
1150 m_arch.GetByteOrder(),
1151 m_arch.GetAddressByteSize());
1152
1153 const bool append_instructions = true;
1154 DecodeInstructions (start,
1155 data,
1156 0,
1157 num_instructions,
1158 append_instructions,
1159 data_from_file);
1160
1161 return m_instruction_list.GetSize();
1162 }
1163
1164 //----------------------------------------------------------------------
1165 // Disassembler copy constructor
1166 //----------------------------------------------------------------------
Disassembler(const ArchSpec & arch,const char * flavor)1167 Disassembler::Disassembler(const ArchSpec& arch, const char *flavor) :
1168 m_arch (arch),
1169 m_instruction_list(),
1170 m_base_addr(LLDB_INVALID_ADDRESS),
1171 m_flavor ()
1172 {
1173 if (flavor == NULL)
1174 m_flavor.assign("default");
1175 else
1176 m_flavor.assign(flavor);
1177 }
1178
1179 //----------------------------------------------------------------------
1180 // Destructor
1181 //----------------------------------------------------------------------
~Disassembler()1182 Disassembler::~Disassembler()
1183 {
1184 }
1185
1186 InstructionList &
GetInstructionList()1187 Disassembler::GetInstructionList ()
1188 {
1189 return m_instruction_list;
1190 }
1191
1192 const InstructionList &
GetInstructionList() const1193 Disassembler::GetInstructionList () const
1194 {
1195 return m_instruction_list;
1196 }
1197
1198 //----------------------------------------------------------------------
1199 // Class PseudoInstruction
1200 //----------------------------------------------------------------------
PseudoInstruction()1201 PseudoInstruction::PseudoInstruction () :
1202 Instruction (Address(), eAddressClassUnknown),
1203 m_description ()
1204 {
1205 }
1206
~PseudoInstruction()1207 PseudoInstruction::~PseudoInstruction ()
1208 {
1209 }
1210
1211 bool
DoesBranch()1212 PseudoInstruction::DoesBranch ()
1213 {
1214 // This is NOT a valid question for a pseudo instruction.
1215 return false;
1216 }
1217
1218 size_t
Decode(const lldb_private::Disassembler & disassembler,const lldb_private::DataExtractor & data,lldb::offset_t data_offset)1219 PseudoInstruction::Decode (const lldb_private::Disassembler &disassembler,
1220 const lldb_private::DataExtractor &data,
1221 lldb::offset_t data_offset)
1222 {
1223 return m_opcode.GetByteSize();
1224 }
1225
1226
1227 void
SetOpcode(size_t opcode_size,void * opcode_data)1228 PseudoInstruction::SetOpcode (size_t opcode_size, void *opcode_data)
1229 {
1230 if (!opcode_data)
1231 return;
1232
1233 switch (opcode_size)
1234 {
1235 case 8:
1236 {
1237 uint8_t value8 = *((uint8_t *) opcode_data);
1238 m_opcode.SetOpcode8 (value8);
1239 break;
1240 }
1241 case 16:
1242 {
1243 uint16_t value16 = *((uint16_t *) opcode_data);
1244 m_opcode.SetOpcode16 (value16);
1245 break;
1246 }
1247 case 32:
1248 {
1249 uint32_t value32 = *((uint32_t *) opcode_data);
1250 m_opcode.SetOpcode32 (value32);
1251 break;
1252 }
1253 case 64:
1254 {
1255 uint64_t value64 = *((uint64_t *) opcode_data);
1256 m_opcode.SetOpcode64 (value64);
1257 break;
1258 }
1259 default:
1260 break;
1261 }
1262 }
1263
1264 void
SetDescription(const char * description)1265 PseudoInstruction::SetDescription (const char *description)
1266 {
1267 if (description && strlen (description) > 0)
1268 m_description = description;
1269 }
1270