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/Timer.h" 25 #include "lldb/Symbol/ObjectFile.h" 26 #include "lldb/Target/ExecutionContext.h" 27 #include "lldb/Target/Process.h" 28 #include "lldb/Target/StackFrame.h" 29 #include "lldb/Target/Target.h" 30 31 #define DEFAULT_DISASM_BYTE_SIZE 32 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 37 Disassembler* 38 Disassembler::FindPlugin (const ArchSpec &arch, const char *plugin_name) 39 { 40 Timer scoped_timer (__PRETTY_FUNCTION__, 41 "Disassembler::FindPlugin (arch = %s, plugin_name = %s)", 42 arch.GetArchitectureName(), 43 plugin_name); 44 45 std::auto_ptr<Disassembler> disassembler_ap; 46 DisassemblerCreateInstance create_callback = NULL; 47 48 if (plugin_name) 49 { 50 create_callback = PluginManager::GetDisassemblerCreateCallbackForPluginName (plugin_name); 51 if (create_callback) 52 { 53 disassembler_ap.reset (create_callback(arch)); 54 55 if (disassembler_ap.get()) 56 return disassembler_ap.release(); 57 } 58 } 59 else 60 { 61 for (uint32_t idx = 0; (create_callback = PluginManager::GetDisassemblerCreateCallbackAtIndex(idx)) != NULL; ++idx) 62 { 63 disassembler_ap.reset (create_callback(arch)); 64 65 if (disassembler_ap.get()) 66 return disassembler_ap.release(); 67 } 68 } 69 return NULL; 70 } 71 72 73 static void 74 ResolveAddress (const ExecutionContext &exe_ctx, 75 const Address &addr, 76 Address &resolved_addr) 77 { 78 if (!addr.IsSectionOffset()) 79 { 80 // If we weren't passed in a section offset address range, 81 // try and resolve it to something 82 if (exe_ctx.target) 83 { 84 if (exe_ctx.target->GetSectionLoadList().IsEmpty()) 85 { 86 exe_ctx.target->GetImages().ResolveFileAddress (addr.GetOffset(), resolved_addr); 87 } 88 else 89 { 90 exe_ctx.target->GetSectionLoadList().ResolveLoadAddress (addr.GetOffset(), resolved_addr); 91 } 92 // We weren't able to resolve the address, just treat it as a 93 // raw address 94 if (resolved_addr.IsValid()) 95 return; 96 } 97 } 98 resolved_addr = addr; 99 } 100 101 size_t 102 Disassembler::Disassemble 103 ( 104 Debugger &debugger, 105 const ArchSpec &arch, 106 const char *plugin_name, 107 const ExecutionContext &exe_ctx, 108 SymbolContextList &sc_list, 109 uint32_t num_instructions, 110 uint32_t num_mixed_context_lines, 111 bool show_bytes, 112 bool raw, 113 Stream &strm 114 ) 115 { 116 size_t success_count = 0; 117 const size_t count = sc_list.GetSize(); 118 SymbolContext sc; 119 AddressRange range; 120 121 for (size_t i=0; i<count; ++i) 122 { 123 if (sc_list.GetContextAtIndex(i, sc) == false) 124 break; 125 if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range)) 126 { 127 if (Disassemble (debugger, 128 arch, 129 plugin_name, 130 exe_ctx, 131 range, 132 num_instructions, 133 num_mixed_context_lines, 134 show_bytes, 135 raw, 136 strm)) 137 { 138 ++success_count; 139 strm.EOL(); 140 } 141 } 142 } 143 return success_count; 144 } 145 146 bool 147 Disassembler::Disassemble 148 ( 149 Debugger &debugger, 150 const ArchSpec &arch, 151 const char *plugin_name, 152 const ExecutionContext &exe_ctx, 153 const ConstString &name, 154 Module *module, 155 uint32_t num_instructions, 156 uint32_t num_mixed_context_lines, 157 bool show_bytes, 158 bool raw, 159 Stream &strm 160 ) 161 { 162 SymbolContextList sc_list; 163 if (name) 164 { 165 const bool include_symbols = true; 166 if (module) 167 { 168 module->FindFunctions (name, 169 eFunctionNameTypeBase | 170 eFunctionNameTypeFull | 171 eFunctionNameTypeMethod | 172 eFunctionNameTypeSelector, 173 include_symbols, 174 true, 175 sc_list); 176 } 177 else if (exe_ctx.target) 178 { 179 exe_ctx.target->GetImages().FindFunctions (name, 180 eFunctionNameTypeBase | 181 eFunctionNameTypeFull | 182 eFunctionNameTypeMethod | 183 eFunctionNameTypeSelector, 184 include_symbols, 185 false, 186 sc_list); 187 } 188 } 189 190 if (sc_list.GetSize ()) 191 { 192 return Disassemble (debugger, 193 arch, 194 plugin_name, 195 exe_ctx, 196 sc_list, 197 num_instructions, 198 num_mixed_context_lines, 199 show_bytes, 200 raw, 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 bool show_bytes, 243 bool raw, 244 Stream &strm 245 ) 246 { 247 if (disasm_range.GetByteSize()) 248 { 249 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name)); 250 251 if (disasm_ap.get()) 252 { 253 AddressRange range; 254 ResolveAddress (exe_ctx, disasm_range.GetBaseAddress(), range.GetBaseAddress()); 255 range.SetByteSize (disasm_range.GetByteSize()); 256 257 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, range); 258 if (bytes_disassembled == 0) 259 return false; 260 261 return PrintInstructions (disasm_ap.get(), 262 debugger, 263 arch, 264 exe_ctx, 265 num_instructions, 266 num_mixed_context_lines, 267 show_bytes, 268 raw, 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 bool show_bytes, 286 bool raw, 287 Stream &strm 288 ) 289 { 290 if (num_instructions > 0) 291 { 292 std::auto_ptr<Disassembler> disasm_ap (Disassembler::FindPlugin(arch, plugin_name)); 293 if (disasm_ap.get()) 294 { 295 Address addr; 296 ResolveAddress (exe_ctx, start_address, addr); 297 298 size_t bytes_disassembled = disasm_ap->ParseInstructions (&exe_ctx, addr, num_instructions); 299 if (bytes_disassembled == 0) 300 return false; 301 return PrintInstructions (disasm_ap.get(), 302 debugger, 303 arch, 304 exe_ctx, 305 num_instructions, 306 num_mixed_context_lines, 307 show_bytes, 308 raw, 309 strm); 310 } 311 } 312 return false; 313 } 314 315 bool 316 Disassembler::PrintInstructions 317 ( 318 Disassembler *disasm_ptr, 319 Debugger &debugger, 320 const ArchSpec &arch, 321 const ExecutionContext &exe_ctx, 322 uint32_t num_instructions, 323 uint32_t num_mixed_context_lines, 324 bool show_bytes, 325 bool raw, 326 Stream &strm 327 ) 328 { 329 // We got some things disassembled... 330 size_t num_instructions_found = disasm_ptr->GetInstructionList().GetSize(); 331 332 if (num_instructions > 0 && num_instructions < num_instructions_found) 333 num_instructions_found = num_instructions; 334 335 const uint32_t max_opcode_byte_size = disasm_ptr->GetInstructionList().GetMaxOpcocdeByteSize (); 336 uint32_t offset = 0; 337 SymbolContext sc; 338 SymbolContext prev_sc; 339 AddressRange sc_range; 340 Address *pc_addr_ptr = NULL; 341 if (exe_ctx.frame) 342 pc_addr_ptr = &exe_ctx.frame->GetFrameCodeAddress(); 343 344 for (size_t i=0; i<num_instructions_found; ++i) 345 { 346 Instruction *inst = disasm_ptr->GetInstructionList().GetInstructionAtIndex (i).get(); 347 if (inst) 348 { 349 const Address &addr = inst->GetAddress(); 350 const bool inst_is_at_pc = pc_addr_ptr && addr == *pc_addr_ptr; 351 352 prev_sc = sc; 353 354 Module *module = addr.GetModule(); 355 if (module) 356 { 357 uint32_t resolved_mask = module->ResolveSymbolContextForAddress(addr, eSymbolContextEverything, sc); 358 if (resolved_mask) 359 { 360 if (num_mixed_context_lines) 361 { 362 if (!sc_range.ContainsFileAddress (addr)) 363 { 364 sc.GetAddressRange (eSymbolContextEverything, sc_range); 365 366 if (sc != prev_sc) 367 { 368 if (offset != 0) 369 strm.EOL(); 370 371 sc.DumpStopContext(&strm, exe_ctx.process, addr, false, true, false); 372 strm.EOL(); 373 374 if (sc.comp_unit && sc.line_entry.IsValid()) 375 { 376 debugger.GetSourceManager().DisplaySourceLinesWithLineNumbers (sc.line_entry.file, 377 sc.line_entry.line, 378 num_mixed_context_lines, 379 num_mixed_context_lines, 380 num_mixed_context_lines ? "->" : "", 381 &strm); 382 } 383 } 384 } 385 } 386 else if (!(prev_sc.function == sc.function || prev_sc.symbol == sc.symbol)) 387 { 388 if (prev_sc.function || prev_sc.symbol) 389 strm.EOL(); 390 391 strm << sc.module_sp->GetFileSpec().GetFilename(); 392 393 if (sc.function) 394 strm << '`' << sc.function->GetMangled().GetName(); 395 else if (sc.symbol) 396 strm << '`' << sc.symbol->GetMangled().GetName(); 397 strm << ":\n"; 398 } 399 } 400 else 401 { 402 sc.Clear(); 403 } 404 } 405 406 if (pc_addr_ptr) 407 { 408 if (inst_is_at_pc) 409 strm.PutCString("-> "); 410 else 411 strm.PutCString(" "); 412 } 413 inst->Dump(&strm, max_opcode_byte_size, true, show_bytes, &exe_ctx, raw); 414 strm.EOL(); 415 } 416 else 417 { 418 break; 419 } 420 } 421 422 return true; 423 } 424 425 426 bool 427 Disassembler::Disassemble 428 ( 429 Debugger &debugger, 430 const ArchSpec &arch, 431 const char *plugin_name, 432 const ExecutionContext &exe_ctx, 433 uint32_t num_instructions, 434 uint32_t num_mixed_context_lines, 435 bool show_bytes, 436 bool raw, 437 Stream &strm 438 ) 439 { 440 AddressRange range; 441 if (exe_ctx.frame) 442 { 443 SymbolContext sc(exe_ctx.frame->GetSymbolContext(eSymbolContextFunction | eSymbolContextSymbol)); 444 if (sc.function) 445 { 446 range = sc.function->GetAddressRange(); 447 } 448 else if (sc.symbol && sc.symbol->GetAddressRangePtr()) 449 { 450 range = *sc.symbol->GetAddressRangePtr(); 451 } 452 else 453 { 454 range.GetBaseAddress() = exe_ctx.frame->GetFrameCodeAddress(); 455 } 456 457 if (range.GetBaseAddress().IsValid() && range.GetByteSize() == 0) 458 range.SetByteSize (DEFAULT_DISASM_BYTE_SIZE); 459 } 460 461 return Disassemble (debugger, 462 arch, 463 plugin_name, 464 exe_ctx, 465 range, 466 num_instructions, 467 num_mixed_context_lines, 468 show_bytes, 469 raw, 470 strm); 471 } 472 473 Instruction::Instruction(const Address &address, AddressClass addr_class) : 474 m_address (address), 475 m_address_class (addr_class), 476 m_opcode() 477 { 478 } 479 480 Instruction::~Instruction() 481 { 482 } 483 484 AddressClass 485 Instruction::GetAddressClass () 486 { 487 if (m_address_class == eAddressClassInvalid) 488 m_address_class = m_address.GetAddressClass(); 489 return m_address_class; 490 } 491 492 bool 493 Instruction::DumpEmulation (const ArchSpec &arch) 494 { 495 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL)); 496 if (insn_emulator_ap.get()) 497 { 498 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress()); 499 return insn_emulator_ap->EvaluateInstruction (); 500 } 501 502 return false; 503 } 504 505 bool 506 Instruction::Emulate (const ArchSpec &arch, 507 bool auto_advance_pc, 508 void *baton, 509 EmulateInstruction::ReadMemory read_mem_callback, 510 EmulateInstruction::WriteMemory write_mem_callback, 511 EmulateInstruction::ReadRegister read_reg_callback, 512 EmulateInstruction::WriteRegister write_reg_callback) 513 { 514 std::auto_ptr<EmulateInstruction> insn_emulator_ap (EmulateInstruction::FindPlugin (arch, NULL)); 515 if (insn_emulator_ap.get()) 516 { 517 insn_emulator_ap->SetBaton (baton); 518 insn_emulator_ap->SetCallbacks (read_mem_callback, write_mem_callback, read_reg_callback, write_reg_callback); 519 insn_emulator_ap->SetInstruction (GetOpcode(), GetAddress()); 520 insn_emulator_ap->SetAdvancePC (auto_advance_pc); 521 return insn_emulator_ap->EvaluateInstruction (); 522 } 523 524 return false; 525 } 526 527 InstructionList::InstructionList() : 528 m_instructions() 529 { 530 } 531 532 InstructionList::~InstructionList() 533 { 534 } 535 536 size_t 537 InstructionList::GetSize() const 538 { 539 return m_instructions.size(); 540 } 541 542 uint32_t 543 InstructionList::GetMaxOpcocdeByteSize () const 544 { 545 uint32_t max_inst_size = 0; 546 collection::const_iterator pos, end; 547 for (pos = m_instructions.begin(), end = m_instructions.end(); 548 pos != end; 549 ++pos) 550 { 551 uint32_t inst_size = (*pos)->GetOpcode().GetByteSize(); 552 if (max_inst_size < inst_size) 553 max_inst_size = inst_size; 554 } 555 return max_inst_size; 556 } 557 558 559 560 InstructionSP 561 InstructionList::GetInstructionAtIndex (uint32_t idx) const 562 { 563 InstructionSP inst_sp; 564 if (idx < m_instructions.size()) 565 inst_sp = m_instructions[idx]; 566 return inst_sp; 567 } 568 569 void 570 InstructionList::Clear() 571 { 572 m_instructions.clear(); 573 } 574 575 void 576 InstructionList::Append (lldb::InstructionSP &inst_sp) 577 { 578 if (inst_sp) 579 m_instructions.push_back(inst_sp); 580 } 581 582 583 size_t 584 Disassembler::ParseInstructions 585 ( 586 const ExecutionContext *exe_ctx, 587 const AddressRange &range 588 ) 589 { 590 Target *target = exe_ctx->target; 591 const addr_t byte_size = range.GetByteSize(); 592 if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid()) 593 return 0; 594 595 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0'); 596 DataBufferSP data_sp(heap_buffer); 597 598 Error error; 599 const bool prefer_file_cache = true; 600 const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), 601 prefer_file_cache, 602 heap_buffer->GetBytes(), 603 heap_buffer->GetByteSize(), 604 error); 605 606 if (bytes_read > 0) 607 { 608 if (bytes_read != heap_buffer->GetByteSize()) 609 heap_buffer->SetByteSize (bytes_read); 610 DataExtractor data (data_sp, 611 m_arch.GetByteOrder(), 612 m_arch.GetAddressByteSize()); 613 return DecodeInstructions (range.GetBaseAddress(), data, 0, UINT32_MAX, false); 614 } 615 616 return 0; 617 } 618 619 size_t 620 Disassembler::ParseInstructions 621 ( 622 const ExecutionContext *exe_ctx, 623 const Address &start, 624 uint32_t num_instructions 625 ) 626 { 627 m_instruction_list.Clear(); 628 629 if (num_instructions == 0 || !start.IsValid()) 630 return 0; 631 632 Target *target = exe_ctx->target; 633 // Calculate the max buffer size we will need in order to disassemble 634 const addr_t byte_size = num_instructions * m_arch.GetMaximumOpcodeByteSize(); 635 636 if (target == NULL || byte_size == 0) 637 return 0; 638 639 DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0'); 640 DataBufferSP data_sp (heap_buffer); 641 642 Error error; 643 bool prefer_file_cache = true; 644 const size_t bytes_read = target->ReadMemory (start, 645 prefer_file_cache, 646 heap_buffer->GetBytes(), 647 byte_size, 648 error); 649 650 if (bytes_read == 0) 651 return 0; 652 DataExtractor data (data_sp, 653 m_arch.GetByteOrder(), 654 m_arch.GetAddressByteSize()); 655 656 const bool append_instructions = true; 657 DecodeInstructions (start, 658 data, 659 0, 660 num_instructions, 661 append_instructions); 662 663 return m_instruction_list.GetSize(); 664 } 665 666 //---------------------------------------------------------------------- 667 // Disassembler copy constructor 668 //---------------------------------------------------------------------- 669 Disassembler::Disassembler(const ArchSpec& arch) : 670 m_arch (arch), 671 m_instruction_list(), 672 m_base_addr(LLDB_INVALID_ADDRESS) 673 { 674 675 } 676 677 //---------------------------------------------------------------------- 678 // Destructor 679 //---------------------------------------------------------------------- 680 Disassembler::~Disassembler() 681 { 682 } 683 684 InstructionList & 685 Disassembler::GetInstructionList () 686 { 687 return m_instruction_list; 688 } 689 690 const InstructionList & 691 Disassembler::GetInstructionList () const 692 { 693 return m_instruction_list; 694 } 695