bool ObjectContainerUniversalMachO::ParseHeader( lldb_private::DataExtractor &data, llvm::MachO::fat_header &header, std::vector<llvm::MachO::fat_arch> &fat_archs) { bool success = false; // Store the file offset for this universal file as we could have a universal // .o file // in a BSD archive, or be contained in another kind of object. // Universal mach-o files always have their headers in big endian. lldb::offset_t offset = 0; data.SetByteOrder(eByteOrderBig); header.magic = data.GetU32(&offset); fat_archs.clear(); if (header.magic == FAT_MAGIC) { data.SetAddressByteSize(4); header.nfat_arch = data.GetU32(&offset); // Now we should have enough data for all of the fat headers, so lets index // them so we know how many architectures that this universal binary // contains. uint32_t arch_idx = 0; for (arch_idx = 0; arch_idx < header.nfat_arch; ++arch_idx) { if (data.ValidOffsetForDataOfSize(offset, sizeof(fat_arch))) { fat_arch arch; if (data.GetU32(&offset, &arch, sizeof(fat_arch) / sizeof(uint32_t))) fat_archs.push_back(arch); } } success = true; } else { memset(&header, 0, sizeof(header)); } return success; }
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(); }