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