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