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