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 (sc.line_entry.file, 373 sc.line_entry.line, 374 num_mixed_context_lines, 375 num_mixed_context_lines, 376 ((inst_is_at_pc && (options & eOptionMarkPCSourceLine)) ? "->" : ""), 377 &strm); 378 } 379 } 380 } 381 } 382 else if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol)) 383 { 384 if (prev_sc.function || prev_sc.symbol) 385 strm.EOL(); 386 387 bool show_fullpaths = false; 388 bool show_module = true; 389 bool show_inlined_frames = true; 390 sc.DumpStopContext (&strm, 391 exe_scope, 392 addr, 393 show_fullpaths, 394 show_module, 395 show_inlined_frames); 396 397 strm << ":\n"; 398 } 399 } 400 else 401 { 402 sc.Clear(); 403 } 404 } 405 406 if ((options & eOptionMarkPCAddress) && pc_addr_ptr) 407 { 408 strm.PutCString(inst_is_at_pc ? "-> " : " "); 409 } 410 const bool show_bytes = (options & eOptionShowBytes) != 0; 411 const bool raw = (options & eOptionRawOuput) != 0; 412 inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, raw); 413 strm.EOL(); 414 } 415 else 416 { 417 break; 418 } 419 } 420 421 return true; 422 } 423 424 425 bool 426 Disassembler::Disassemble 427 ( 428 Debugger &debugger, 429 const ArchSpec &arch, 430 const char *plugin_name, 431 const ExecutionContext &exe_ctx, 432 uint32_t num_instructions, 433 uint32_t num_mixed_context_lines, 434 uint32_t options, 435 Stream &strm 436 ) 437 { 438 AddressRange range; 439 if (exe_ctx.frame) 440 { 441 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 442 if (sc.function) 443 { 444 range = sc.function->GetAddressRange(); 445 } 446 else if (sc.symbol && sc.symbol->GetAddressRangePtr()) 447 { 448 range = *sc.symbol->GetAddressRangePtr(); 449 } 450 else 451 { 452 range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress(); 453 } 454 455 if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0) 456 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE); 457 } 458 459 return Disassemble (debugger, 460 arch, 461 plugin_name, 462 exe_ctx, 463 range, 464 num_instructions, 465 num_mixed_context_lines, 466 options, 467 strm); 468 } 469 470 Instruction::Instruction(const Address &address, AddressClass addr_class) : 471 m_address (address), 472 m_address_class (addr_class), 473 m_opcode() 474 { 475 } 476 477 Instruction::~Instruction() 478 { 479 } 480 481 AddressClass 482 Instruction::GetAddressClass () 483 { 484 if (m_address_class == eAddressClassInvalid) 485 m_address_class = m_address.GetAddressClass(); 486 return m_address_class; 487 } 488 489 bool 490 Instruction::DumpEmulation (const ArchSpec &arch) 491 { 492 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL)); 493 if (insn_emulator_ap.get()) 494 { 495 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress(), NULL); 496 return insn_emulator_ap->EvaluateInstruction (0); 497 } 498 499 return false; 500 } 501 502 OptionValueSP 503 Instruction::ReadArray (FILE *in_file, Stream *out_stream, OptionValue::Type data_type) 504 { 505 bool done = false; 506 char buffer[1024]; 507 508 OptionValueSP option_value_sp (new OptionValueArray (1u << data_type)); 509 510 int idx = 0; 511 while (!done) 512 { 513 if (!fgets (buffer, 1023, in_file)) 514 { 515 out_stream->Printf ("Instruction::ReadArray: Erroe reading file (fgets).\n"); 516 option_value_sp.reset (); 517 return option_value_sp; 518 } 519 520 std::string line (buffer); 521 522 int len = line.size(); 523 if (line[len-1] == '\n') 524 { 525 line[len-1] = '\0'; 526 line.resize (len-1); 527 } 528 529 if ((line.size() == 1) && line[0] == ']') 530 { 531 done = true; 532 line.clear(); 533 } 534 535 if (line.size() > 0) 536 { 537 std::string value; 538 RegularExpression reg_exp ("^[ \t]*([^ \t]+)[ \t]*$"); 539 bool reg_exp_success = reg_exp.Execute (line.c_str(), 1); 540 if (reg_exp_success) 541 reg_exp.GetMatchAtIndex (line.c_str(), 1, value); 542 else 543 value = line; 544 545 OptionValueSP data_value_sp; 546 switch (data_type) 547 { 548 case OptionValue::eTypeUInt64: 549 data_value_sp.reset (new OptionValueUInt64 (0, 0)); 550 data_value_sp->SetValueFromCString (value.c_str()); 551 break; 552 // Other types can be added later as needed. 553 default: 554 data_value_sp.reset (new OptionValueString (value.c_str(), "")); 555 break; 556 } 557 558 option_value_sp->GetAsArray()->InsertValue (idx, data_value_sp); 559 ++idx; 560 } 561 } 562 563 return option_value_sp; 564 } 565 566 OptionValueSP 567 Instruction::ReadDictionary (FILE *in_file, Stream *out_stream) 568 { 569 bool done = false; 570 char buffer[1024]; 571 572 OptionValueSP option_value_sp (new OptionValueDictionary()); 573 static ConstString encoding_key ("data_encoding"); 574 OptionValue::Type data_type = OptionValue::eTypeInvalid; 575 576 577 while (!done) 578 { 579 // Read the next line in the file 580 if (!fgets (buffer, 1023, in_file)) 581 { 582 out_stream->Printf ("Instruction::ReadDictionary: Error reading file (fgets).\n"); 583 option_value_sp.reset (); 584 return option_value_sp; 585 } 586 587 // Check to see if the line contains the end-of-dictionary marker ("}") 588 std::string line (buffer); 589 590 int len = line.size(); 591 if (line[len-1] == '\n') 592 { 593 line[len-1] = '\0'; 594 line.resize (len-1); 595 } 596 597 if ((line.size() == 1) && (line[0] == '}')) 598 { 599 done = true; 600 line.clear(); 601 } 602 603 // Try to find a key-value pair in the current line and add it to the dictionary. 604 if (line.size() > 0) 605 { 606 RegularExpression reg_exp ("^[ \t]*([a-zA-Z_][a-zA-Z0-9_]*)[ \t]*=[ \t]*(.*)[ \t]*$"); 607 bool reg_exp_success = reg_exp.Execute (line.c_str(), 2); 608 std::string key; 609 std::string value; 610 if (reg_exp_success) 611 { 612 reg_exp.GetMatchAtIndex (line.c_str(), 1, key); 613 reg_exp.GetMatchAtIndex (line.c_str(), 2, value); 614 } 615 else 616 { 617 out_stream->Printf ("Instruction::ReadDictionary: Failure executing regular expression.\n"); 618 option_value_sp.reset(); 619 return option_value_sp; 620 } 621 622 ConstString const_key (key.c_str()); 623 // Check value to see if it's the start of an array or dictionary. 624 625 lldb::OptionValueSP value_sp; 626 assert (value.empty() == false); 627 assert (key.empty() == false); 628 629 if (value[0] == '{') 630 { 631 assert (value.size() == 1); 632 // value is a dictionary 633 value_sp = ReadDictionary (in_file, out_stream); 634 if (value_sp.get() == NULL) 635 { 636 option_value_sp.reset (); 637 return option_value_sp; 638 } 639 } 640 else if (value[0] == '[') 641 { 642 assert (value.size() == 1); 643 // value is an array 644 value_sp = ReadArray (in_file, out_stream, data_type); 645 if (value_sp.get() == NULL) 646 { 647 option_value_sp.reset (); 648 return option_value_sp; 649 } 650 // We've used the data_type to read an array; re-set the type to Invalid 651 data_type = OptionValue::eTypeInvalid; 652 } 653 else if ((value[0] == '0') && (value[1] == 'x')) 654 { 655 value_sp.reset (new OptionValueUInt64 (0, 0)); 656 value_sp->SetValueFromCString (value.c_str()); 657 } 658 else 659 { 660 int len = value.size(); 661 if ((value[0] == '"') && (value[len-1] == '"')) 662 value = value.substr (1, len-2); 663 value_sp.reset (new OptionValueString (value.c_str(), "")); 664 } 665 666 667 668 if (const_key == encoding_key) 669 { 670 // A 'data_encoding=..." is NOT a normal key-value pair; it is meta-data indicating the 671 // data type of an upcoming array (usually the next bit of data to be read in). 672 if (strcmp (value.c_str(), "uint32_t") == 0) 673 data_type = OptionValue::eTypeUInt64; 674 } 675 else 676 option_value_sp->GetAsDictionary()->SetValueForKey (const_key, value_sp, false); 677 } 678 } 679 680 return option_value_sp; 681 } 682 683 bool 684 Instruction::TestEmulation (Stream *out_stream, const char *file_name) 685 { 686 if (!out_stream) 687 return false; 688 689 if (!file_name) 690 { 691 out_stream->Printf ("Instruction::TestEmulation: Missing file_name."); 692 return false; 693 } 694 695 FILE *test_file = fopen (file_name, "r"); 696 if (!test_file) 697 { 698 out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed."); 699 return false; 700 } 701 702 char buffer[256]; 703 if (!fgets (buffer, 255, test_file)) 704 { 705 out_stream->Printf ("Instruction::TestEmulation: Error reading first line of test file.\n"); 706 fclose (test_file); 707 return false; 708 } 709 710 if (strncmp (buffer, "InstructionEmulationState={", 27) != 0) 711 { 712 out_stream->Printf ("Instructin::TestEmulation: Test file does not contain emulation state dictionary\n"); 713 fclose (test_file); 714 return false; 715 } 716 717 // Read all the test information from the test file into an OptionValueDictionary. 718 719 OptionValueSP data_dictionary_sp (ReadDictionary (test_file, out_stream)); 720 if (data_dictionary_sp.get() == NULL) 721 { 722 out_stream->Printf ("Instruction::TestEmulation: Error reading Dictionary Object.\n"); 723 fclose (test_file); 724 return false; 725 } 726 727 fclose (test_file); 728 729 OptionValueDictionary *data_dictionary = data_dictionary_sp->GetAsDictionary(); 730 static ConstString description_key ("assembly_string"); 731 static ConstString triple_key ("triple"); 732 733 OptionValueSP value_sp = data_dictionary->GetValueForKey (description_key); 734 735 if (value_sp.get() == NULL) 736 { 737 out_stream->Printf ("Instruction::TestEmulation: Test file does not contain description string.\n"); 738 return false; 739 } 740 741 SetDescription (value_sp->GetStringValue()); 742 743 744 value_sp = data_dictionary->GetValueForKey (triple_key); 745 if (value_sp.get() == NULL) 746 { 747 out_stream->Printf ("Instruction::TestEmulation: Test file does not contain triple.\n"); 748 return false; 749 } 750 751 ArchSpec arch; 752 arch.SetTriple (llvm::Triple (value_sp->GetStringValue())); 753 754 bool success = false; 755 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL)); 756 if (insn_emulator_ap.get()) 757 success = insn_emulator_ap->TestEmulation (out_stream, arch, data_dictionary); 758 759 if (success) 760 out_stream->Printf ("Emulation test succeeded."); 761 else 762 out_stream->Printf ("Emulation test failed."); 763 764 return success; 765 } 766 767 bool 768 Instruction::Emulate (const ArchSpec &arch, 769 uint32_t evaluate_options, 770 void *baton, 771 EmulateInstruction::ReadMemoryCallback read_mem_callback, 772 EmulateInstruction::WriteMemoryCallback write_mem_callback, 773 EmulateInstruction::ReadRegisterCallback read_reg_callback, 774 EmulateInstruction::WriteRegisterCallback write_reg_callback) 775 { 776 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, eInstructionTypeAny, NULL)); 777 if (insn_emulator_ap.get()) 778 { 779 insn_emulator_ap->SetBaton (baton); 780 insn_emulator_ap->SetCallbacks (read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback); 781 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress(), NULL); 782 return insn_emulator_ap->EvaluateInstruction (evaluate_options); 783 } 784 785 return false; 786 } 787 788 InstructionList::InstructionList() : 789 m_instructions() 790 { 791 } 792 793 InstructionList::~InstructionList() 794 { 795 } 796 797 size_t 798 InstructionList::GetSize() const 799 { 800 return m_instructions.size(); 801 } 802 803 uint32_t 804 InstructionList::GetMaxOpcocdeByteSize () const 805 { 806 uint32_t max_inst_size = 0; 807 collection::const_iterator pos, end; 808 for (pos = m_instructions.begin(), end = m_instructions.end(); 809 pos != end; 810 ++pos) 811 { 812 uint32_t inst_size = (*pos)->GetOpcode().GetByteSize(); 813 if (max_inst_size < inst_size) 814 max_inst_size = inst_size; 815 } 816 return max_inst_size; 817 } 818 819 820 821 InstructionSP 822 InstructionList::GetInstructionAtIndex (uint32_t idx) const 823 { 824 InstructionSP inst_sp; 825 if (idx < m_instructions.size()) 826 inst_sp = m_instructions[idx]; 827 return inst_sp; 828 } 829 830 void 831 InstructionList::Clear() 832 { 833 m_instructions.clear(); 834 } 835 836 void 837 InstructionList::Append (lldb::InstructionSP &inst_sp) 838 { 839 if (inst_sp) 840 m_instructions.push_back(inst_sp); 841 } 842 843 844 size_t 845 Disassembler::ParseInstructions 846 ( 847 const ExecutionContext *exe_ctx, 848 const AddressRange &range 849 ) 850 { 851 Target *target = exe_ctx->target; 852 const addr_t byte_size = range.GetByteSize(); 853 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid()) 854 return 0; 855 856 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0'); 857 DataBufferSP data_sp(heap_buffer); 858 859 Error error; 860 const bool prefer_file_cache = true; 861 const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), 862 prefer_file_cache, 863 heap_buffer->GetBytes(), 864 heap_buffer->GetByteSize(), 865 error); 866 867 if (bytes_read > 0) 868 { 869 if (bytes_read != heap_buffer->GetByteSize()) 870 heap_buffer->SetByteSize (bytes_read); 871 DataExtractor data (data_sp, 872 m_arch.GetByteOrder(), 873 m_arch.GetAddressByteSize()); 874 return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false); 875 } 876 877 return 0; 878 } 879 880 size_t 881 Disassembler::ParseInstructions 882 ( 883 const ExecutionContext *exe_ctx, 884 const Address &start, 885 uint32_t num_instructions 886 ) 887 { 888 m_instruction_list.Clear(); 889 890 if (num_instructions == 0 || !start.IsValid()) 891 return 0; 892 893 Target *target = exe_ctx->target; 894 // Calculate the max buffer size we will need in order to disassemble 895 const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize(); 896 897 if (target == NULL || byte_size == 0) 898 return 0; 899 900 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0'); 901 DataBufferSP data_sp (heap_buffer); 902 903 Error error; 904 bool prefer_file_cache = true; 905 const size_t bytes_read = target->ReadMemory (start, 906 prefer_file_cache, 907 heap_buffer->GetBytes(), 908 byte_size, 909 error); 910 911 if (bytes_read == 0) 912 return 0; 913 DataExtractor data (data_sp, 914 m_arch.GetByteOrder(), 915 m_arch.GetAddressByteSize()); 916 917 const bool append_instructions = true; 918 DecodeInstructions (start, 919 data, 920 0, 921 num_instructions, 922 append_instructions); 923 924 return m_instruction_list.GetSize(); 925 } 926 927 //---------------------------------------------------------------------- 928 // Disassembler copy constructor 929 //---------------------------------------------------------------------- 930 Disassembler::Disassembler(const ArchSpec& arch) : 931 m_arch (arch), 932 m_instruction_list(), 933 m_base_addr(LLDB_INVALID_ADDRESS) 934 { 935 936 } 937 938 //---------------------------------------------------------------------- 939 // Destructor 940 //---------------------------------------------------------------------- 941 Disassembler::~Disassembler() 942 { 943 } 944 945 InstructionList & 946 Disassembler::GetInstructionList () 947 { 948 return m_instruction_list; 949 } 950 951 const InstructionList & 952 Disassembler::GetInstructionList () const 953 { 954 return m_instruction_list; 955 } 956 957 //---------------------------------------------------------------------- 958 // Class PseudoInstruction 959 //---------------------------------------------------------------------- 960 PseudoInstruction::PseudoInstruction () : 961 Instruction (Address(), eAddressClassUnknown), 962 m_description () 963 { 964 } 965 966 PseudoInstruction::~PseudoInstruction () 967 { 968 } 969 970 void 971 PseudoInstruction::Dump (lldb_private::Stream *s, 972 uint32_t max_opcode_byte_size, 973 bool show_address, 974 bool show_bytes, 975 const lldb_private::ExecutionContext* exe_ctx, 976 bool raw) 977 { 978 if (!s) 979 return; 980 981 if (show_bytes) 982 m_opcode.Dump (s, max_opcode_byte_size); 983 984 if (m_description.size() > 0) 985 s->Printf ("%s", m_description.c_str()); 986 else 987 s->Printf ("<unknown>"); 988 989 } 990 991 bool 992 PseudoInstruction::DoesBranch () const 993 { 994 // This is NOT a valid question for a pseudo instruction. 995 return false; 996 } 997 998 size_t 999 PseudoInstruction::Decode (const lldb_private::Disassembler &disassembler, 1000 const lldb_private::DataExtractor &data, 1001 uint32_t data_offset) 1002 { 1003 return m_opcode.GetByteSize(); 1004 } 1005 1006 1007 void 1008 PseudoInstruction::SetOpcode (size_t opcode_size, void *opcode_data) 1009 { 1010 if (!opcode_data) 1011 return; 1012 1013 switch (opcode_size) 1014 { 1015 case 8: 1016 { 1017 uint8_t value8 = *((uint8_t *) opcode_data); 1018 m_opcode.SetOpcode8 (value8); 1019 break; 1020 } 1021 case 16: 1022 { 1023 uint16_t value16 = *((uint16_t *) opcode_data); 1024 m_opcode.SetOpcode16 (value16); 1025 break; 1026 } 1027 case 32: 1028 { 1029 uint32_t value32 = *((uint32_t *) opcode_data); 1030 m_opcode.SetOpcode32 (value32); 1031 break; 1032 } 1033 case 64: 1034 { 1035 uint64_t value64 = *((uint64_t *) opcode_data); 1036 m_opcode.SetOpcode64 (value64); 1037 break; 1038 } 1039 default: 1040 break; 1041 } 1042 } 1043 1044 void 1045 PseudoInstruction::SetDescription (const char *description) 1046 { 1047 if (description && strlen (description) > 0) 1048 m_description = description; 1049 } 1050