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