DisassemblerLLVMC.cpp revision 263508
11539Srgrimes//===-- DisassemblerLLVMC.cpp -----------------------------------*- C++ -*-===// 21539Srgrimes// 31539Srgrimes// The LLVM Compiler Infrastructure 41539Srgrimes// 51539Srgrimes// This file is distributed under the University of Illinois Open Source 61539Srgrimes// License. See LICENSE.TXT for details. 71539Srgrimes// 81539Srgrimes//===----------------------------------------------------------------------===// 91539Srgrimes 101539Srgrimes#include "DisassemblerLLVMC.h" 111539Srgrimes 121539Srgrimes#include "llvm-c/Disassembler.h" 13203964Simp#include "llvm/ADT/OwningPtr.h" 141539Srgrimes#include "llvm/MC/MCAsmInfo.h" 151539Srgrimes#include "llvm/MC/MCContext.h" 161539Srgrimes#include "llvm/MC/MCDisassembler.h" 171539Srgrimes#include "llvm/MC/MCInst.h" 181539Srgrimes#include "llvm/MC/MCInstPrinter.h" 191539Srgrimes#include "llvm/MC/MCInstrInfo.h" 201539Srgrimes#include "llvm/MC/MCRegisterInfo.h" 211539Srgrimes#include "llvm/MC/MCRelocationInfo.h" 221539Srgrimes#include "llvm/MC/MCSubtargetInfo.h" 231539Srgrimes#include "llvm/Support/ErrorHandling.h" 241539Srgrimes#include "llvm/Support/MemoryObject.h" 251539Srgrimes#include "llvm/Support/TargetRegistry.h" 261539Srgrimes#include "llvm/Support/TargetSelect.h" 271539Srgrimes#include "llvm/ADT/SmallString.h" 281539Srgrimes 2923657Speter 3055031Sbde#include "lldb/Core/Address.h" 311539Srgrimes#include "lldb/Core/DataExtractor.h" 321539Srgrimes#include "lldb/Core/Module.h" 331539Srgrimes#include "lldb/Core/Stream.h" 347865Sbde#include "lldb/Symbol/SymbolContext.h" 351539Srgrimes#include "lldb/Target/ExecutionContext.h" 3633861Sbde#include "lldb/Target/Process.h" 37123257Smarcel#include "lldb/Target/RegisterContext.h" 38102227Smike#include "lldb/Target/Target.h" 3933861Sbde#include "lldb/Target/StackFrame.h" 40103728Swollman 41102227Smike#include "lldb/Core/RegularExpression.h" 42102227Smike 43102227Smikeusing namespace lldb; 4415483Sbdeusing namespace lldb_private; 4515483Sbde 4615483Sbdeclass InstructionLLVMC : public lldb_private::Instruction 47102227Smike{ 48102227Smikepublic: 49102227Smike InstructionLLVMC (DisassemblerLLVMC &disasm, 501539Srgrimes const lldb_private::Address &address, 511539Srgrimes AddressClass addr_class) : 5299640Sobrien Instruction (address, addr_class), 53102227Smike m_disasm_sp (disasm.shared_from_this()), 54102227Smike m_does_branch (eLazyBoolCalculate), 55102227Smike m_is_valid (false), 561539Srgrimes m_using_file_addr (false) 5799640Sobrien { 581539Srgrimes } 591539Srgrimes 60103766Sbde virtual 61103766Sbde ~InstructionLLVMC () 621539Srgrimes { 631539Srgrimes } 641539Srgrimes 65103766Sbde virtual bool 66103766Sbde DoesBranch () 671539Srgrimes { 681539Srgrimes if (m_does_branch == eLazyBoolCalculate) 691539Srgrimes { 701539Srgrimes GetDisassemblerLLVMC().Lock(this, NULL); 711539Srgrimes DataExtractor data; 721539Srgrimes if (m_opcode.GetData(data)) 731539Srgrimes { 74227753Stheraven bool is_alternate_isa; 751539Srgrimes lldb::addr_t pc = m_address.GetFileAddress(); 76227753Stheraven 77227753Stheraven DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); 781539Srgrimes const uint8_t *opcode_data = data.GetDataStart(); 79228330Stheraven const size_t opcode_data_len = data.GetByteSize(); 8093032Simp llvm::MCInst inst; 8193032Simp const size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, 8293032Simp opcode_data_len, 8393032Simp pc, 8493032Simp inst); 8593032Simp // Be conservative, if we didn't understand the instruction, say it might branch... 8693032Simp if (inst_size == 0) 87187961Sdas m_does_branch = eLazyBoolYes; 8893032Simp else 89228330Stheraven { 9093032Simp const bool can_branch = mc_disasm_ptr->CanBranch(inst); 9193032Simp if (can_branch) 9293032Simp m_does_branch = eLazyBoolYes; 9393032Simp else 94187961Sdas m_does_branch = eLazyBoolNo; 95103728Swollman } 96103766Sbde } 97103728Swollman GetDisassemblerLLVMC().Unlock(); 9893032Simp } 9993032Simp return m_does_branch == eLazyBoolYes; 10093032Simp } 10193032Simp 10293032Simp DisassemblerLLVMC::LLVMCDisassembler * 103103766Sbde GetDisasmToUse (bool &is_alternate_isa) 104112163Sdas { 105103766Sbde is_alternate_isa = false; 106112163Sdas DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); 107112163Sdas if (llvm_disasm.m_alternate_disasm_ap.get() != NULL) 1081539Srgrimes { 109103012Stjr const AddressClass address_class = GetAddressClass (); 11093032Simp 11193032Simp if (address_class == eAddressClassCodeAlternateISA) 112103012Stjr { 1131539Srgrimes is_alternate_isa = true; 114103728Swollman return llvm_disasm.m_alternate_disasm_ap.get(); 115103728Swollman } 116103728Swollman } 117103728Swollman return llvm_disasm.m_disasm_ap.get(); 118103728Swollman } 119103728Swollman 120103728Swollman virtual size_t 121103728Swollman Decode (const lldb_private::Disassembler &disassembler, 122103728Swollman const lldb_private::DataExtractor &data, 123103728Swollman lldb::offset_t data_offset) 124103728Swollman { 125103728Swollman // All we have to do is read the opcode which can be easy for some 126103728Swollman // architectures 127103728Swollman bool got_op = false; 128103728Swollman DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); 129103728Swollman const ArchSpec &arch = llvm_disasm.GetArchitecture(); 130103728Swollman 13169201Sphk const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize(); 132103728Swollman const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize(); 133103728Swollman if (min_op_byte_size == max_op_byte_size) 134103728Swollman { 135103728Swollman // Fixed size instructions, just read that amount of data. 136103728Swollman if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size)) 137103728Swollman return false; 138103728Swollman 139103728Swollman switch (min_op_byte_size) 140103728Swollman { 141103766Sbde case 1: 142103766Sbde m_opcode.SetOpcode8 (data.GetU8 (&data_offset)); 143103728Swollman got_op = true; 144103728Swollman break; 145103766Sbde 146103728Swollman case 2: 147103728Swollman m_opcode.SetOpcode16 (data.GetU16 (&data_offset)); 148228330Stheraven got_op = true; 149103728Swollman break; 150103728Swollman 151103728Swollman case 4: 152228322Stheraven m_opcode.SetOpcode32 (data.GetU32 (&data_offset)); 153228322Stheraven got_op = true; 154228901Sed break; 155228901Sed 156228901Sed case 8: 157228901Sed m_opcode.SetOpcode64 (data.GetU64 (&data_offset)); 158228901Sed got_op = true; 159228322Stheraven break; 160103728Swollman 161103728Swollman default: 162103728Swollman m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), min_op_byte_size); 163103728Swollman got_op = true; 164103728Swollman break; 165154250Sjasone } 166103728Swollman } 167206997Skib if (!got_op) 16893032Simp { 169171195Sscf bool is_alternate_isa = false; 170103728Swollman DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); 1711539Srgrimes 172189349Sdas const llvm::Triple::ArchType machine = arch.GetMachine(); 173189349Sdas if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) 174189349Sdas { 175189349Sdas if (machine == llvm::Triple::thumb || is_alternate_isa) 176189349Sdas { 177189349Sdas uint32_t thumb_opcode = data.GetU16(&data_offset); 178189349Sdas if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0)) 179189349Sdas { 180189349Sdas m_opcode.SetOpcode16 (thumb_opcode); 181189349Sdas m_is_valid = true; 182189349Sdas } 183189349Sdas else 184103728Swollman { 185103728Swollman thumb_opcode <<= 16; 186103728Swollman thumb_opcode |= data.GetU16(&data_offset); 187103728Swollman m_opcode.SetOpcode16_2 (thumb_opcode); 188103728Swollman m_is_valid = true; 189103728Swollman } 190103728Swollman } 191103728Swollman else 192153707Strhodes { 19393032Simp m_opcode.SetOpcode32 (data.GetU32(&data_offset)); 194103766Sbde m_is_valid = true; 19593032Simp } 196103766Sbde } 197103766Sbde else 198108574Sjmallett { 199103728Swollman // The opcode isn't evenly sized, so we need to actually use the llvm 20093032Simp // disassembler to parse it and get the size. 201153707Strhodes uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1)); 20293032Simp const size_t opcode_data_len = data.BytesLeft(data_offset); 20393032Simp const addr_t pc = m_address.GetFileAddress(); 204189782Sdas llvm::MCInst inst; 205103728Swollman 206103766Sbde llvm_disasm.Lock(this, NULL); 207103728Swollman const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data, 20893032Simp opcode_data_len, 20993032Simp pc, 210108574Sjmallett inst); 211108574Sjmallett llvm_disasm.Unlock(); 212171195Sscf if (inst_size == 0) 213103728Swollman m_opcode.Clear(); 2147865Sbde else 21593032Simp { 216103728Swollman m_opcode.SetOpcodeBytes(opcode_data, inst_size); 217103728Swollman m_is_valid = true; 218103728Swollman } 219103728Swollman } 220103728Swollman } 22193032Simp return m_opcode.GetByteSize(); 222103728Swollman } 223108574Sjmallett 224103728Swollman void 2254749Sats AppendComment (std::string &description) 226103728Swollman { 227103728Swollman if (m_comment.empty()) 228103766Sbde m_comment.swap (description); 229103766Sbde else 230103728Swollman { 231116397Sdes m_comment.append(", "); 232116397Sdes m_comment.append(description); 233116397Sdes } 234116397Sdes } 235116397Sdes 236116397Sdes virtual void 237116397Sdes CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx) 238116397Sdes { 239116397Sdes DataExtractor data; 240116831Sobrien const AddressClass address_class = GetAddressClass (); 241116831Sobrien 242116397Sdes if (m_opcode.GetData(data)) 243116831Sobrien { 244116831Sobrien char out_string[512]; 245116397Sdes 246116397Sdes DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); 247189820Sdas 24841927Sdt DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr; 24993032Simp 250180658Sache if (address_class == eAddressClassCodeAlternateISA) 251180658Sache mc_disasm_ptr = llvm_disasm.m_alternate_disasm_ap.get(); 25293032Simp else 253180689Sache mc_disasm_ptr = llvm_disasm.m_disasm_ap.get(); 254180689Sache 255108445Sobrien lldb::addr_t pc = m_address.GetFileAddress(); 256103728Swollman m_using_file_addr = true; 25793032Simp 25893032Simp const bool data_from_file = GetDisassemblerLLVMC().m_data_from_file; 25993032Simp bool use_hex_immediates = true; 26093032Simp Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC; 26193032Simp 26293032Simp if (exe_ctx) 26393032Simp { 26493032Simp Target *target = exe_ctx->GetTargetPtr(); 26593032Simp if (target) 26693032Simp { 2671539Srgrimes use_hex_immediates = target->GetUseHexImmediates(); 26893032Simp hex_style = target->GetHexImmediateStyle(); 269150052Sstefanf 270150052Sstefanf if (!data_from_file) 271188497Sed { 272188497Sed const lldb::addr_t load_addr = m_address.GetLoadAddress(target); 27393032Simp if (load_addr != LLDB_INVALID_ADDRESS) 274228468Sed { 27593032Simp pc = load_addr; 2761539Srgrimes m_using_file_addr = false; 27793032Simp } 278153707Strhodes } 27993032Simp } 280103164Swollman } 281103164Swollman 28293032Simp llvm_disasm.Lock(this, exe_ctx); 28393032Simp 28493032Simp const uint8_t *opcode_data = data.GetDataStart(); 285139922Stjr const size_t opcode_data_len = data.GetByteSize(); 28693032Simp llvm::MCInst inst; 287103164Swollman size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, 288103164Swollman opcode_data_len, 28993032Simp pc, 29093032Simp inst); 291156707Sandre 292156707Sandre if (inst_size > 0) 293103728Swollman { 294103728Swollman mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); 295103766Sbde mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string)); 296103766Sbde } 29741927Sdt 29893032Simp llvm_disasm.Unlock(); 299126136Sache 300126136Sache if (inst_size == 0) 301103728Swollman { 3021539Srgrimes m_comment.assign ("unknown opcode"); 3031539Srgrimes inst_size = m_opcode.GetByteSize(); 3047865Sbde StreamString mnemonic_strm; 305 lldb::offset_t offset = 0; 306 switch (inst_size) 307 { 308 case 1: 309 { 310 const uint8_t uval8 = data.GetU8 (&offset); 311 m_opcode.SetOpcode8 (uval8); 312 m_opcode_name.assign (".byte"); 313 mnemonic_strm.Printf("0x%2.2x", uval8); 314 } 315 break; 316 case 2: 317 { 318 const uint16_t uval16 = data.GetU16(&offset); 319 m_opcode.SetOpcode16(uval16); 320 m_opcode_name.assign (".short"); 321 mnemonic_strm.Printf("0x%4.4x", uval16); 322 } 323 break; 324 case 4: 325 { 326 const uint32_t uval32 = data.GetU32(&offset); 327 m_opcode.SetOpcode32(uval32); 328 m_opcode_name.assign (".long"); 329 mnemonic_strm.Printf("0x%8.8x", uval32); 330 } 331 break; 332 case 8: 333 { 334 const uint64_t uval64 = data.GetU64(&offset); 335 m_opcode.SetOpcode64(uval64); 336 m_opcode_name.assign (".quad"); 337 mnemonic_strm.Printf("0x%16.16" PRIx64, uval64); 338 } 339 break; 340 default: 341 if (inst_size == 0) 342 return; 343 else 344 { 345 const uint8_t *bytes = data.PeekData(offset, inst_size); 346 if (bytes == NULL) 347 return; 348 m_opcode_name.assign (".byte"); 349 m_opcode.SetOpcodeBytes(bytes, inst_size); 350 mnemonic_strm.Printf("0x%2.2x", bytes[0]); 351 for (uint32_t i=1; i<inst_size; ++i) 352 mnemonic_strm.Printf(" 0x%2.2x", bytes[i]); 353 } 354 break; 355 } 356 m_mnemonics.swap(mnemonic_strm.GetString()); 357 return; 358 } 359 else 360 { 361 if (m_does_branch == eLazyBoolCalculate) 362 { 363 const bool can_branch = mc_disasm_ptr->CanBranch(inst); 364 if (can_branch) 365 m_does_branch = eLazyBoolYes; 366 else 367 m_does_branch = eLazyBoolNo; 368 369 } 370 } 371 372 static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED); 373 374 RegularExpression::Match matches(3); 375 376 if (s_regex.Execute(out_string, &matches)) 377 { 378 matches.GetMatchAtIndex(out_string, 1, m_opcode_name); 379 matches.GetMatchAtIndex(out_string, 2, m_mnemonics); 380 } 381 } 382 } 383 384 bool 385 IsValid () const 386 { 387 return m_is_valid; 388 } 389 390 bool 391 UsingFileAddress() const 392 { 393 return m_using_file_addr; 394 } 395 size_t 396 GetByteSize () const 397 { 398 return m_opcode.GetByteSize(); 399 } 400 401 DisassemblerLLVMC & 402 GetDisassemblerLLVMC () 403 { 404 return *(DisassemblerLLVMC *)m_disasm_sp.get(); 405 } 406protected: 407 408 DisassemblerSP m_disasm_sp; // for ownership 409 LazyBool m_does_branch; 410 bool m_is_valid; 411 bool m_using_file_addr; 412}; 413 414 415 416DisassemblerLLVMC::LLVMCDisassembler::LLVMCDisassembler (const char *triple, unsigned flavor, DisassemblerLLVMC &owner): 417 m_is_valid(true) 418{ 419 std::string Error; 420 const llvm::Target *curr_target = llvm::TargetRegistry::lookupTarget(triple, Error); 421 if (!curr_target) 422 { 423 m_is_valid = false; 424 return; 425 } 426 427 m_instr_info_ap.reset(curr_target->createMCInstrInfo()); 428 m_reg_info_ap.reset (curr_target->createMCRegInfo(triple)); 429 430 std::string features_str; 431 432 m_subtarget_info_ap.reset(curr_target->createMCSubtargetInfo(triple, "", 433 features_str)); 434 435 m_asm_info_ap.reset(curr_target->createMCAsmInfo(*curr_target->createMCRegInfo(triple), triple)); 436 437 if (m_instr_info_ap.get() == NULL || m_reg_info_ap.get() == NULL || m_subtarget_info_ap.get() == NULL || m_asm_info_ap.get() == NULL) 438 { 439 m_is_valid = false; 440 return; 441 } 442 443 m_context_ap.reset(new llvm::MCContext(m_asm_info_ap.get(), m_reg_info_ap.get(), 0)); 444 445 m_disasm_ap.reset(curr_target->createMCDisassembler(*m_subtarget_info_ap.get())); 446 if (m_disasm_ap.get() && m_context_ap.get()) 447 { 448 llvm::OwningPtr<llvm::MCRelocationInfo> RelInfo(curr_target->createMCRelocationInfo(triple, *m_context_ap.get())); 449 if (!RelInfo) 450 { 451 m_is_valid = false; 452 return; 453 } 454 m_disasm_ap->setupForSymbolicDisassembly(NULL, 455 DisassemblerLLVMC::SymbolLookupCallback, 456 (void *) &owner, 457 m_context_ap.get(), 458 RelInfo); 459 460 unsigned asm_printer_variant; 461 if (flavor == ~0U) 462 asm_printer_variant = m_asm_info_ap->getAssemblerDialect(); 463 else 464 { 465 asm_printer_variant = flavor; 466 } 467 468 m_instr_printer_ap.reset(curr_target->createMCInstPrinter(asm_printer_variant, 469 *m_asm_info_ap.get(), 470 *m_instr_info_ap.get(), 471 *m_reg_info_ap.get(), 472 *m_subtarget_info_ap.get())); 473 if (m_instr_printer_ap.get() == NULL) 474 { 475 m_disasm_ap.reset(); 476 m_is_valid = false; 477 } 478 } 479 else 480 m_is_valid = false; 481} 482 483DisassemblerLLVMC::LLVMCDisassembler::~LLVMCDisassembler() 484{ 485} 486 487namespace { 488 // This is the memory object we use in GetInstruction. 489 class LLDBDisasmMemoryObject : public llvm::MemoryObject { 490 const uint8_t *m_bytes; 491 uint64_t m_size; 492 uint64_t m_base_PC; 493 public: 494 LLDBDisasmMemoryObject(const uint8_t *bytes, uint64_t size, uint64_t basePC) : 495 m_bytes(bytes), m_size(size), m_base_PC(basePC) {} 496 497 uint64_t getBase() const { return m_base_PC; } 498 uint64_t getExtent() const { return m_size; } 499 500 int readByte(uint64_t addr, uint8_t *byte) const { 501 if (addr - m_base_PC >= m_size) 502 return -1; 503 *byte = m_bytes[addr - m_base_PC]; 504 return 0; 505 } 506 }; 507} // End Anonymous Namespace 508 509uint64_t 510DisassemblerLLVMC::LLVMCDisassembler::GetMCInst (const uint8_t *opcode_data, 511 size_t opcode_data_len, 512 lldb::addr_t pc, 513 llvm::MCInst &mc_inst) 514{ 515 LLDBDisasmMemoryObject memory_object (opcode_data, opcode_data_len, pc); 516 llvm::MCDisassembler::DecodeStatus status; 517 518 uint64_t new_inst_size; 519 status = m_disasm_ap->getInstruction(mc_inst, 520 new_inst_size, 521 memory_object, 522 pc, 523 llvm::nulls(), 524 llvm::nulls()); 525 if (status == llvm::MCDisassembler::Success) 526 return new_inst_size; 527 else 528 return 0; 529} 530 531uint64_t 532DisassemblerLLVMC::LLVMCDisassembler::PrintMCInst (llvm::MCInst &mc_inst, 533 char *dst, 534 size_t dst_len) 535{ 536 llvm::StringRef unused_annotations; 537 llvm::SmallString<64> inst_string; 538 llvm::raw_svector_ostream inst_stream(inst_string); 539 m_instr_printer_ap->printInst (&mc_inst, inst_stream, unused_annotations); 540 inst_stream.flush(); 541 const size_t output_size = std::min(dst_len - 1, inst_string.size()); 542 std::memcpy(dst, inst_string.data(), output_size); 543 dst[output_size] = '\0'; 544 545 return output_size; 546} 547 548void 549DisassemblerLLVMC::LLVMCDisassembler::SetStyle (bool use_hex_immed, HexImmediateStyle hex_style) 550{ 551 m_instr_printer_ap->setPrintImmHex(use_hex_immed); 552 switch(hex_style) 553 { 554 case eHexStyleC: m_instr_printer_ap->setPrintImmHex(llvm::HexStyle::C); break; 555 case eHexStyleAsm: m_instr_printer_ap->setPrintImmHex(llvm::HexStyle::Asm); break; 556 } 557} 558 559bool 560DisassemblerLLVMC::LLVMCDisassembler::CanBranch (llvm::MCInst &mc_inst) 561{ 562 return m_instr_info_ap->get(mc_inst.getOpcode()).mayAffectControlFlow(mc_inst, *m_reg_info_ap.get()); 563} 564 565bool 566DisassemblerLLVMC::FlavorValidForArchSpec (const lldb_private::ArchSpec &arch, const char *flavor) 567{ 568 llvm::Triple triple = arch.GetTriple(); 569 if (flavor == NULL || strcmp (flavor, "default") == 0) 570 return true; 571 572 if (triple.getArch() == llvm::Triple::x86 || triple.getArch() == llvm::Triple::x86_64) 573 { 574 if (strcmp (flavor, "intel") == 0 || strcmp (flavor, "att") == 0) 575 return true; 576 else 577 return false; 578 } 579 else 580 return false; 581} 582 583 584Disassembler * 585DisassemblerLLVMC::CreateInstance (const ArchSpec &arch, const char *flavor) 586{ 587 if (arch.GetTriple().getArch() != llvm::Triple::UnknownArch) 588 { 589 std::unique_ptr<DisassemblerLLVMC> disasm_ap (new DisassemblerLLVMC(arch, flavor)); 590 591 if (disasm_ap.get() && disasm_ap->IsValid()) 592 return disasm_ap.release(); 593 } 594 return NULL; 595} 596 597DisassemblerLLVMC::DisassemblerLLVMC (const ArchSpec &arch, const char *flavor_string) : 598 Disassembler(arch, flavor_string), 599 m_exe_ctx (NULL), 600 m_inst (NULL), 601 m_data_from_file (false) 602{ 603 if (!FlavorValidForArchSpec (arch, m_flavor.c_str())) 604 { 605 m_flavor.assign("default"); 606 } 607 608 const char *triple = arch.GetTriple().getTriple().c_str(); 609 unsigned flavor = ~0U; 610 611 // So far the only supported flavor is "intel" on x86. The base class will set this 612 // correctly coming in. 613 if (arch.GetTriple().getArch() == llvm::Triple::x86 614 || arch.GetTriple().getArch() == llvm::Triple::x86_64) 615 { 616 if (m_flavor == "intel") 617 { 618 flavor = 1; 619 } 620 else if (m_flavor == "att") 621 { 622 flavor = 0; 623 } 624 } 625 626 ArchSpec thumb_arch(arch); 627 if (arch.GetTriple().getArch() == llvm::Triple::arm) 628 { 629 std::string thumb_arch_name (thumb_arch.GetTriple().getArchName().str()); 630 // Replace "arm" with "thumb" so we get all thumb variants correct 631 if (thumb_arch_name.size() > 3) 632 { 633 thumb_arch_name.erase(0,3); 634 thumb_arch_name.insert(0, "thumb"); 635 } 636 else 637 { 638 thumb_arch_name = "thumbv7"; 639 } 640 thumb_arch.GetTriple().setArchName(llvm::StringRef(thumb_arch_name.c_str())); 641 } 642 643 // Cortex-M3 devices (e.g. armv7m) can only execute thumb (T2) instructions, 644 // so hardcode the primary disassembler to thumb mode. Same for Cortex-M4 (armv7em). 645 // 646 // Handle the Cortex-M0 (armv6m) the same; the ISA is a subset of the T and T32 647 // instructions defined in ARMv7-A. 648 649 if (arch.GetTriple().getArch() == llvm::Triple::arm 650 && (arch.GetCore() == ArchSpec::Core::eCore_arm_armv7m 651 || arch.GetCore() == ArchSpec::Core::eCore_arm_armv7em 652 || arch.GetCore() == ArchSpec::Core::eCore_arm_armv6m)) 653 { 654 triple = thumb_arch.GetTriple().getTriple().c_str(); 655 } 656 657 m_disasm_ap.reset (new LLVMCDisassembler(triple, flavor, *this)); 658 if (!m_disasm_ap->IsValid()) 659 { 660 // We use m_disasm_ap.get() to tell whether we are valid or not, so if this isn't good for some reason, 661 // we reset it, and then we won't be valid and FindPlugin will fail and we won't get used. 662 m_disasm_ap.reset(); 663 } 664 665 // For arm CPUs that can execute arm or thumb instructions, also create a thumb instruction disassembler. 666 if (arch.GetTriple().getArch() == llvm::Triple::arm) 667 { 668 std::string thumb_triple(thumb_arch.GetTriple().getTriple()); 669 m_alternate_disasm_ap.reset(new LLVMCDisassembler(thumb_triple.c_str(), flavor, *this)); 670 if (!m_alternate_disasm_ap->IsValid()) 671 { 672 m_disasm_ap.reset(); 673 m_alternate_disasm_ap.reset(); 674 } 675 } 676} 677 678DisassemblerLLVMC::~DisassemblerLLVMC() 679{ 680} 681 682size_t 683DisassemblerLLVMC::DecodeInstructions (const Address &base_addr, 684 const DataExtractor& data, 685 lldb::offset_t data_offset, 686 size_t num_instructions, 687 bool append, 688 bool data_from_file) 689{ 690 if (!append) 691 m_instruction_list.Clear(); 692 693 if (!IsValid()) 694 return 0; 695 696 m_data_from_file = data_from_file; 697 uint32_t data_cursor = data_offset; 698 const size_t data_byte_size = data.GetByteSize(); 699 uint32_t instructions_parsed = 0; 700 Address inst_addr(base_addr); 701 702 while (data_cursor < data_byte_size && instructions_parsed < num_instructions) 703 { 704 705 AddressClass address_class = eAddressClassCode; 706 707 if (m_alternate_disasm_ap.get() != NULL) 708 address_class = inst_addr.GetAddressClass (); 709 710 InstructionSP inst_sp(new InstructionLLVMC(*this, 711 inst_addr, 712 address_class)); 713 714 if (!inst_sp) 715 break; 716 717 uint32_t inst_size = inst_sp->Decode(*this, data, data_cursor); 718 719 if (inst_size == 0) 720 break; 721 722 m_instruction_list.Append(inst_sp); 723 data_cursor += inst_size; 724 inst_addr.Slide(inst_size); 725 instructions_parsed++; 726 } 727 728 return data_cursor - data_offset; 729} 730 731void 732DisassemblerLLVMC::Initialize() 733{ 734 PluginManager::RegisterPlugin (GetPluginNameStatic(), 735 "Disassembler that uses LLVM MC to disassemble i386, x86_64 and ARM.", 736 CreateInstance); 737 738 llvm::InitializeAllTargetInfos(); 739 llvm::InitializeAllTargetMCs(); 740 llvm::InitializeAllAsmParsers(); 741 llvm::InitializeAllDisassemblers(); 742} 743 744void 745DisassemblerLLVMC::Terminate() 746{ 747 PluginManager::UnregisterPlugin (CreateInstance); 748} 749 750 751ConstString 752DisassemblerLLVMC::GetPluginNameStatic() 753{ 754 static ConstString g_name("llvm-mc"); 755 return g_name; 756} 757 758int DisassemblerLLVMC::OpInfoCallback (void *disassembler, 759 uint64_t pc, 760 uint64_t offset, 761 uint64_t size, 762 int tag_type, 763 void *tag_bug) 764{ 765 return static_cast<DisassemblerLLVMC*>(disassembler)->OpInfo (pc, 766 offset, 767 size, 768 tag_type, 769 tag_bug); 770} 771 772const char *DisassemblerLLVMC::SymbolLookupCallback (void *disassembler, 773 uint64_t value, 774 uint64_t *type, 775 uint64_t pc, 776 const char **name) 777{ 778 return static_cast<DisassemblerLLVMC*>(disassembler)->SymbolLookup(value, 779 type, 780 pc, 781 name); 782} 783 784int DisassemblerLLVMC::OpInfo (uint64_t PC, 785 uint64_t Offset, 786 uint64_t Size, 787 int tag_type, 788 void *tag_bug) 789{ 790 switch (tag_type) 791 { 792 default: 793 break; 794 case 1: 795 memset (tag_bug, 0, sizeof(::LLVMOpInfo1)); 796 break; 797 } 798 return 0; 799} 800 801const char *DisassemblerLLVMC::SymbolLookup (uint64_t value, 802 uint64_t *type_ptr, 803 uint64_t pc, 804 const char **name) 805{ 806 if (*type_ptr) 807 { 808 if (m_exe_ctx && m_inst) 809 { 810 //std::string remove_this_prior_to_checkin; 811 Target *target = m_exe_ctx ? m_exe_ctx->GetTargetPtr() : NULL; 812 Address value_so_addr; 813 if (m_inst->UsingFileAddress()) 814 { 815 ModuleSP module_sp(m_inst->GetAddress().GetModule()); 816 if (module_sp) 817 module_sp->ResolveFileAddress(value, value_so_addr); 818 } 819 else if (target && !target->GetSectionLoadList().IsEmpty()) 820 { 821 target->GetSectionLoadList().ResolveLoadAddress(value, value_so_addr); 822 } 823 824 if (value_so_addr.IsValid() && value_so_addr.GetSection()) 825 { 826 StreamString ss; 827 828 value_so_addr.Dump (&ss, 829 target, 830 Address::DumpStyleResolvedDescriptionNoModule, 831 Address::DumpStyleSectionNameOffset); 832 833 if (!ss.GetString().empty()) 834 { 835 m_inst->AppendComment(ss.GetString()); 836 } 837 } 838 } 839 } 840 841 *type_ptr = LLVMDisassembler_ReferenceType_InOut_None; 842 *name = NULL; 843 return NULL; 844} 845 846//------------------------------------------------------------------ 847// PluginInterface protocol 848//------------------------------------------------------------------ 849ConstString 850DisassemblerLLVMC::GetPluginName() 851{ 852 return GetPluginNameStatic(); 853} 854 855uint32_t 856DisassemblerLLVMC::GetPluginVersion() 857{ 858 return 1; 859} 860 861