bool CompilerType::ReadFromMemory (lldb_private::ExecutionContext *exe_ctx, lldb::addr_t addr, AddressType address_type, lldb_private::DataExtractor &data) { if (!IsValid()) return false; // Can't convert a file address to anything valid without more // context (which Module it came from) if (address_type == eAddressTypeFile) return false; if (!GetCompleteType()) return false; const uint64_t byte_size = GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : NULL); if (data.GetByteSize() < byte_size) { lldb::DataBufferSP data_sp(new DataBufferHeap (byte_size, '\0')); data.SetData(data_sp); } uint8_t* dst = const_cast<uint8_t*>(data.PeekData(0, byte_size)); if (dst != nullptr) { if (address_type == eAddressTypeHost) { if (addr == 0) return false; // The address is an address in this process, so just copy it memcpy (dst, (uint8_t*)nullptr + addr, byte_size); return true; } else { Process *process = nullptr; if (exe_ctx) process = exe_ctx->GetProcessPtr(); if (process) { Error error; return process->ReadMemory(addr, dst, byte_size, error) == byte_size; } } } return false; }
virtual size_t Decode (const lldb_private::Disassembler &disassembler, const lldb_private::DataExtractor &data, lldb::offset_t data_offset) { // All we have to do is read the opcode which can be easy for some // architectures bool got_op = false; DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); const ArchSpec &arch = llvm_disasm.GetArchitecture(); const lldb::ByteOrder byte_order = data.GetByteOrder(); const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize(); const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize(); if (min_op_byte_size == max_op_byte_size) { // Fixed size instructions, just read that amount of data. if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size)) return false; switch (min_op_byte_size) { case 1: m_opcode.SetOpcode8 (data.GetU8 (&data_offset), byte_order); got_op = true; break; case 2: m_opcode.SetOpcode16 (data.GetU16 (&data_offset), byte_order); got_op = true; break; case 4: m_opcode.SetOpcode32 (data.GetU32 (&data_offset), byte_order); got_op = true; break; case 8: m_opcode.SetOpcode64 (data.GetU64 (&data_offset), byte_order); got_op = true; break; default: m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), min_op_byte_size); got_op = true; break; } } if (!got_op) { bool is_alternate_isa = false; DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr = GetDisasmToUse (is_alternate_isa); const llvm::Triple::ArchType machine = arch.GetMachine(); if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) { if (machine == llvm::Triple::thumb || is_alternate_isa) { uint32_t thumb_opcode = data.GetU16(&data_offset); if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0)) { m_opcode.SetOpcode16 (thumb_opcode, byte_order); m_is_valid = true; } else { thumb_opcode <<= 16; thumb_opcode |= data.GetU16(&data_offset); m_opcode.SetOpcode16_2 (thumb_opcode, byte_order); m_is_valid = true; } } else { m_opcode.SetOpcode32 (data.GetU32(&data_offset), byte_order); m_is_valid = true; } } else { // The opcode isn't evenly sized, so we need to actually use the llvm // disassembler to parse it and get the size. uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1)); const size_t opcode_data_len = data.BytesLeft(data_offset); const addr_t pc = m_address.GetFileAddress(); llvm::MCInst inst; llvm_disasm.Lock(this, NULL); const size_t inst_size = mc_disasm_ptr->GetMCInst(opcode_data, opcode_data_len, pc, inst); llvm_disasm.Unlock(); if (inst_size == 0) m_opcode.Clear(); else { m_opcode.SetOpcodeBytes(opcode_data, inst_size); m_is_valid = true; } } } return m_opcode.GetByteSize(); }
virtual size_t Decode (const lldb_private::Disassembler &disassembler, const lldb_private::DataExtractor &data, uint32_t data_offset) { // All we have to do is read the opcode which can be easy for some // architetures bool got_op = false; const ArchSpec &arch = m_disasm.GetArchitecture(); const uint32_t min_op_byte_size = arch.GetMinimumOpcodeByteSize(); const uint32_t max_op_byte_size = arch.GetMaximumOpcodeByteSize(); if (min_op_byte_size == max_op_byte_size) { // Fixed size instructions, just read that amount of data. if (!data.ValidOffsetForDataOfSize(data_offset, min_op_byte_size)) return false; switch (min_op_byte_size) { case 1: m_opcode.SetOpcode8 (data.GetU8 (&data_offset)); got_op = true; break; case 2: m_opcode.SetOpcode16 (data.GetU16 (&data_offset)); got_op = true; break; case 4: m_opcode.SetOpcode32 (data.GetU32 (&data_offset)); got_op = true; break; case 8: m_opcode.SetOpcode64 (data.GetU64 (&data_offset)); got_op = true; break; default: m_opcode.SetOpcodeBytes(data.PeekData(data_offset, min_op_byte_size), min_op_byte_size); got_op = true; break; } } if (!got_op) { ::LLVMDisasmContextRef disasm_context = m_disasm.m_disasm_context; bool is_altnernate_isa = false; if (m_disasm.m_alternate_disasm_context) { const AddressClass address_class = GetAddressClass (); if (address_class == eAddressClassCodeAlternateISA) { disasm_context = m_disasm.m_alternate_disasm_context; is_altnernate_isa = true; } } const llvm::Triple::ArchType machine = arch.GetMachine(); if (machine == llvm::Triple::arm || machine == llvm::Triple::thumb) { if (machine == llvm::Triple::thumb || is_altnernate_isa) { uint32_t thumb_opcode = data.GetU16(&data_offset); if ((thumb_opcode & 0xe000) != 0xe000 || ((thumb_opcode & 0x1800u) == 0)) { m_opcode.SetOpcode16 (thumb_opcode); } else { thumb_opcode <<= 16; thumb_opcode |= data.GetU16(&data_offset); m_opcode.SetOpcode32 (thumb_opcode); m_is_valid = true; } } else { m_opcode.SetOpcode32 (data.GetU32(&data_offset)); } } else { // The opcode isn't evenly sized, so we need to actually use the llvm // disassembler to parse it and get the size. char out_string[512]; m_disasm.Lock(this, NULL); uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (data_offset, 1)); const size_t opcode_data_len = data.GetByteSize() - data_offset; const addr_t pc = m_address.GetFileAddress(); const size_t inst_size = ::LLVMDisasmInstruction (disasm_context, opcode_data, opcode_data_len, pc, // PC value out_string, sizeof(out_string)); // The address lookup function could have caused us to fill in our comment m_comment.clear(); m_disasm.Unlock(); if (inst_size == 0) m_opcode.Clear(); else { m_opcode.SetOpcodeBytes(opcode_data, inst_size); m_is_valid = true; } } } return m_opcode.GetByteSize(); }