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