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