bool DWARFCompileUnit::Extract(const DataExtractor &debug_info, uint32_t* offset_ptr) { Clear(); m_offset = *offset_ptr; if (debug_info.ValidOffset(*offset_ptr)) { dw_offset_t abbr_offset; const DWARFDebugAbbrev *abbr = m_dwarf2Data->DebugAbbrev(); m_length = debug_info.GetU32(offset_ptr); m_version = debug_info.GetU16(offset_ptr); abbr_offset = debug_info.GetU32(offset_ptr); m_addr_size = debug_info.GetU8 (offset_ptr); bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1); bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset); bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && abbr != NULL) { m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset); return true; } // reset the offset to where we tried to parse from if anything went wrong *offset_ptr = m_offset; } return false; }
Error AdbClient::Stat (const FileSpec &remote_file, uint32_t &mode, uint32_t &size, uint32_t &mtime) { auto error = StartSync (); if (error.Fail ()) return error; const std::string remote_file_path (remote_file.GetPath (false)); error = SendSyncRequest (kSTAT, remote_file_path.length (), remote_file_path.c_str ()); if (error.Fail ()) return Error ("Failed to send request: %s", error.AsCString ()); static const size_t stat_len = strlen (kSTAT); static const size_t response_len = stat_len + (sizeof (uint32_t) * 3); std::vector<char> buffer (response_len); error = ReadAllBytes (&buffer[0], buffer.size ()); if (error.Fail ()) return Error ("Failed to read response: %s", error.AsCString ()); DataExtractor extractor (&buffer[0], buffer.size (), eByteOrderLittle, sizeof (void*)); offset_t offset = 0; const void* command = extractor.GetData (&offset, stat_len); if (!command) return Error ("Failed to get response command"); const char* command_str = static_cast<const char*> (command); if (strncmp (command_str, kSTAT, stat_len)) return Error ("Got invalid stat command: %s", command_str); mode = extractor.GetU32 (&offset); size = extractor.GetU32 (&offset); mtime = extractor.GetU32 (&offset); return Error (); }
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. static void ParseFreeBSDPrStatus(ThreadData *thread_data, DataExtractor &data, ArchSpec &arch) { lldb::offset_t offset = 0; bool have_padding = (arch.GetMachine() == llvm::Triple::mips64 || arch.GetMachine() == llvm::Triple::x86_64); int pr_version = data.GetU32(&offset); Log *log (ProcessPOSIXLog::GetLogIfAllCategoriesSet (POSIX_LOG_PROCESS)); if (log) { if (pr_version > 1) log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version); } if (have_padding) offset += 4; offset += 28; // pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate thread_data->signo = data.GetU32(&offset); // pr_cursig offset += 4; // pr_pid if (have_padding) offset += 4; size_t len = data.GetByteSize() - offset; thread_data->gpregset = DataExtractor(data, offset, len); }
// Parse a FreeBSD NT_PRSTATUS note - see FreeBSD sys/procfs.h for details. static void ParseFreeBSDPrStatus(ThreadData &thread_data, DataExtractor &data, ArchSpec &arch) { lldb::offset_t offset = 0; bool lp64 = (arch.GetMachine() == llvm::Triple::aarch64 || arch.GetMachine() == llvm::Triple::mips64 || arch.GetMachine() == llvm::Triple::ppc64 || arch.GetMachine() == llvm::Triple::x86_64); int pr_version = data.GetU32(&offset); Log *log (GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); if (log) { if (pr_version > 1) log->Printf("FreeBSD PRSTATUS unexpected version %d", pr_version); } // Skip padding, pr_statussz, pr_gregsetsz, pr_fpregsetsz, pr_osreldate if (lp64) offset += 32; else offset += 16; thread_data.signo = data.GetU32(&offset); // pr_cursig thread_data.tid = data.GetU32(&offset); // pr_pid if (lp64) offset += 4; size_t len = data.GetByteSize() - offset; thread_data.gpregset = DataExtractor(data, offset, len); }
Error ELFLinuxPrPsInfo::Parse(DataExtractor &data, ArchSpec &arch) { Error error; ByteOrder byteorder = data.GetByteOrder(); if (GetSize(arch) > data.GetByteSize()) { error.SetErrorStringWithFormat("NT_PRPSINFO size should be %lu, but the remaining bytes are: %lu", GetSize(arch), data.GetByteSize()); return error; } switch(arch.GetCore()) { case ArchSpec::eCore_s390x_generic: case ArchSpec::eCore_x86_64_x86_64: data.ExtractBytes(0, sizeof(ELFLinuxPrPsInfo), byteorder, this); break; case ArchSpec::eCore_x86_32_i386: case ArchSpec::eCore_x86_32_i486: { // Parsing from a 32 bit ELF core file, and populating/reusing the structure // properly, because the struct is for the 64 bit version size_t size = 0; offset_t offset = 0; pr_state = data.GetU8(&offset); pr_sname = data.GetU8(&offset); pr_zomb = data.GetU8(&offset); pr_nice = data.GetU8(&offset); pr_flag = data.GetU32(&offset); pr_uid = data.GetU16(&offset); pr_gid = data.GetU16(&offset); pr_pid = data.GetU32(&offset); pr_ppid = data.GetU32(&offset); pr_pgrp = data.GetU32(&offset); pr_sid = data.GetU32(&offset); size = 16; data.ExtractBytes(offset, size, byteorder, pr_fname); offset += size; size = 80; data.ExtractBytes(offset, size, byteorder, pr_psargs); offset += size; break; } default: error.SetErrorStringWithFormat("ELFLinuxPrPsInfo::%s Unknown architecture", __FUNCTION__); break; } return error; }
bool DynamicLoaderDarwinKernel::ReadKextSummaryHeader () { Mutex::Locker locker(m_mutex); // the all image infos is already valid for this process stop ID m_kext_summaries.clear(); if (m_kext_summary_header_ptr_addr.IsValid()) { const uint32_t addr_size = m_kernel.GetAddressByteSize (); const ByteOrder byte_order = m_kernel.GetByteOrder(); Error error; // Read enough bytes for a "OSKextLoadedKextSummaryHeader" structure // which is currenty 4 uint32_t and a pointer. uint8_t buf[24]; DataExtractor data (buf, sizeof(buf), byte_order, addr_size); const size_t count = 4 * sizeof(uint32_t) + addr_size; const bool prefer_file_cache = false; if (m_process->GetTarget().ReadPointerFromMemory (m_kext_summary_header_ptr_addr, prefer_file_cache, error, m_kext_summary_header_addr)) { // We got a valid address for our kext summary header and make sure it isn't NULL if (m_kext_summary_header_addr.IsValid() && m_kext_summary_header_addr.GetFileAddress() != 0) { const size_t bytes_read = m_process->GetTarget().ReadMemory (m_kext_summary_header_addr, prefer_file_cache, buf, count, error); if (bytes_read == count) { uint32_t offset = 0; m_kext_summary_header.version = data.GetU32(&offset); if (m_kext_summary_header.version >= 2) { m_kext_summary_header.entry_size = data.GetU32(&offset); } else { // Versions less than 2 didn't have an entry size, it was hard coded m_kext_summary_header.entry_size = KERNEL_MODULE_ENTRY_SIZE_VERSION_1; } m_kext_summary_header.entry_count = data.GetU32(&offset); return true; } } } } m_kext_summary_header_addr.Clear(); return false; }
bool CommunicationKDP::SendRawRequest( uint8_t command_byte, const void *src, // Raw packet payload bytes uint32_t src_len, // Raw packet payload length DataExtractor &reply_packet, Status &error) { PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, m_byte_order); // Size is header + address size + uint32_t length const uint32_t command_length = 8 + src_len; const CommandType command = (CommandType)command_byte; MakeRequestPacketHeader(command, request_packet, command_length); request_packet.PutRawBytes(src, src_len); if (SendRequestAndGetReply(command, request_packet, reply_packet)) { lldb::offset_t offset = 8; uint32_t kdp_error = reply_packet.GetU32(&offset); if (kdp_error && (command_byte != KDP_DUMPINFO)) error.SetErrorStringWithFormat("request packet 0x%8.8x failed (error %u)", command_byte, kdp_error); else { error.Clear(); return true; } } else { error.SetErrorString("failed to send packet"); } return false; }
//---------------------------------------------------------------------- // ParseDOSHeader //---------------------------------------------------------------------- bool ObjectFilePECOFF::ParseDOSHeader(DataExtractor &data, dos_header_t &dos_header) { bool success = false; lldb::offset_t offset = 0; success = data.ValidOffsetForDataOfSize(0, sizeof(dos_header)); if (success) { dos_header.e_magic = data.GetU16(&offset); // Magic number success = dos_header.e_magic == IMAGE_DOS_SIGNATURE; if (success) { dos_header.e_cblp = data.GetU16(&offset); // Bytes on last page of file dos_header.e_cp = data.GetU16(&offset); // Pages in file dos_header.e_crlc = data.GetU16(&offset); // Relocations dos_header.e_cparhdr = data.GetU16(&offset); // Size of header in paragraphs dos_header.e_minalloc = data.GetU16(&offset); // Minimum extra paragraphs needed dos_header.e_maxalloc = data.GetU16(&offset); // Maximum extra paragraphs needed dos_header.e_ss = data.GetU16(&offset); // Initial (relative) SS value dos_header.e_sp = data.GetU16(&offset); // Initial SP value dos_header.e_csum = data.GetU16(&offset); // Checksum dos_header.e_ip = data.GetU16(&offset); // Initial IP value dos_header.e_cs = data.GetU16(&offset); // Initial (relative) CS value dos_header.e_lfarlc = data.GetU16(&offset); // File address of relocation table dos_header.e_ovno = data.GetU16(&offset); // Overlay number dos_header.e_res[0] = data.GetU16(&offset); // Reserved words dos_header.e_res[1] = data.GetU16(&offset); // Reserved words dos_header.e_res[2] = data.GetU16(&offset); // Reserved words dos_header.e_res[3] = data.GetU16(&offset); // Reserved words dos_header.e_oemid = data.GetU16(&offset); // OEM identifier (for e_oeminfo) dos_header.e_oeminfo = data.GetU16(&offset); // OEM information; e_oemid specific dos_header.e_res2[0] = data.GetU16(&offset); // Reserved words dos_header.e_res2[1] = data.GetU16(&offset); // Reserved words dos_header.e_res2[2] = data.GetU16(&offset); // Reserved words dos_header.e_res2[3] = data.GetU16(&offset); // Reserved words dos_header.e_res2[4] = data.GetU16(&offset); // Reserved words dos_header.e_res2[5] = data.GetU16(&offset); // Reserved words dos_header.e_res2[6] = data.GetU16(&offset); // Reserved words dos_header.e_res2[7] = data.GetU16(&offset); // Reserved words dos_header.e_res2[8] = data.GetU16(&offset); // Reserved words dos_header.e_res2[9] = data.GetU16(&offset); // Reserved words dos_header.e_lfanew = data.GetU32(&offset); // File address of new exe header } } if (!success) memset(&dos_header, 0, sizeof(dos_header)); return success; }
//---------------------------------------------------------------------- // ParserCOFFHeader //---------------------------------------------------------------------- bool ObjectFilePECOFF::ParseCOFFHeader(DataExtractor &data, lldb::offset_t *offset_ptr, coff_header_t &coff_header) { bool success = data.ValidOffsetForDataOfSize(*offset_ptr, sizeof(coff_header)); if (success) { coff_header.machine = data.GetU16(offset_ptr); coff_header.nsects = data.GetU16(offset_ptr); coff_header.modtime = data.GetU32(offset_ptr); coff_header.symoff = data.GetU32(offset_ptr); coff_header.nsyms = data.GetU32(offset_ptr); coff_header.hdrsize = data.GetU16(offset_ptr); coff_header.flags = data.GetU16(offset_ptr); } if (!success) memset(&coff_header, 0, sizeof(coff_header)); return success; }
dw_offset_t DWARFCompileUnit::Extract(dw_offset_t offset, const DataExtractor& debug_info_data, const DWARFAbbreviationDeclarationSet* abbrevs) { Clear(); m_offset = offset; if (debug_info_data.ValidOffset(offset)) { m_length = debug_info_data.GetU32(&offset); m_version = debug_info_data.GetU16(&offset); bool abbrevs_OK = debug_info_data.GetU32(&offset) == abbrevs->GetOffset(); m_abbrevs = abbrevs; m_addr_size = debug_info_data.GetU8 (&offset); bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); if (version_OK && addr_size_OK && abbrevs_OK && debug_info_data.ValidOffset(offset)) return offset; } return DW_INVALID_OFFSET; }
void ThreadKDP::SetStopInfoFrom_KDP_EXCEPTION (const DataExtractor &exc_reply_packet) { lldb::offset_t offset = 0; uint8_t reply_command = exc_reply_packet.GetU8(&offset); if (reply_command == CommunicationKDP::KDP_EXCEPTION) { offset = 8; const uint32_t count = exc_reply_packet.GetU32 (&offset); if (count >= 1) { //const uint32_t cpu = exc_reply_packet.GetU32 (&offset); offset += 4; // Skip the useless CPU field const uint32_t exc_type = exc_reply_packet.GetU32 (&offset); const uint32_t exc_code = exc_reply_packet.GetU32 (&offset); const uint32_t exc_subcode = exc_reply_packet.GetU32 (&offset); // We have to make a copy of the stop info because the thread list // will iterate through the threads and clear all stop infos.. // Let the StopInfoMachException::CreateStopReasonWithMachException() // function update the PC if needed as we might hit a software breakpoint // and need to decrement the PC (i386 and x86_64 need this) and KDP // doesn't do this for us. const bool pc_already_adjusted = false; const bool adjust_pc_if_needed = true; m_cached_stop_info_sp = StopInfoMachException::CreateStopReasonWithMachException (*this, exc_type, 2, exc_code, exc_subcode, 0, pc_already_adjusted, adjust_pc_if_needed); } } }
Error AdbClient::ReadSyncHeader (std::string &response_id, uint32_t &data_len) { char buffer[kSyncPacketLen]; auto error = ReadAllBytes (buffer, kSyncPacketLen); if (error.Success ()) { response_id.assign (&buffer[0], 4); DataExtractor extractor (&buffer[4], 4, eByteOrderLittle, sizeof (void*)); offset_t offset = 0; data_len = extractor.GetU32 (&offset); } return error; }
size_t ObjectFilePECOFF::GetModuleSpecifications (const lldb_private::FileSpec& file, lldb::DataBufferSP& data_sp, lldb::offset_t data_offset, lldb::offset_t file_offset, lldb::offset_t length, lldb_private::ModuleSpecList &specs) { const size_t initial_count = specs.GetSize(); if (ObjectFilePECOFF::MagicBytesMatch(data_sp)) { DataExtractor data; data.SetData(data_sp, data_offset, length); data.SetByteOrder(eByteOrderLittle); dos_header_t dos_header; coff_header_t coff_header; if (ParseDOSHeader(data, dos_header)) { lldb::offset_t offset = dos_header.e_lfanew; uint32_t pe_signature = data.GetU32(&offset); if (pe_signature != IMAGE_NT_SIGNATURE) return false; if (ParseCOFFHeader(data, &offset, coff_header)) { ArchSpec spec; if (coff_header.machine == MachineAmd64) { spec.SetTriple("x86_64-pc-windows"); specs.Append(ModuleSpec(file, spec)); } else if (coff_header.machine == MachineX86) { spec.SetTriple("i386-pc-windows"); specs.Append(ModuleSpec(file, spec)); spec.SetTriple("i686-pc-windows"); specs.Append(ModuleSpec(file, spec)); } } } } return specs.GetSize() - initial_count; }
static bool FileAtPathContainsArchAndUUID ( const FileSpec &file_spec, const ArchSpec *arch, const lldb_private::UUID *uuid ) { DataExtractor data; off_t file_offset = 0; DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, 0x1000)); if (data_buffer_sp && data_buffer_sp->GetByteSize() > 0) { data.SetData(data_buffer_sp); uint32_t data_offset = 0; uint32_t magic = data.GetU32(&data_offset); switch (magic) { // 32 bit mach-o file case HeaderMagic32: case HeaderMagic32Swapped: case HeaderMagic64: case HeaderMagic64Swapped: return SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic); // fat mach-o file case UniversalMagic: case UniversalMagicSwapped: return UniversalMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset, data, data_offset, magic); default: break; } } return false; }
bool RegisterContextMach_i386::WriteRegisterBytes (uint32_t reg, DataExtractor &data, uint32_t data_offset) { int set = GetSetForNativeRegNum (reg); if (set == -1) return false; if (ReadRegisterSet(set, false) != KERN_SUCCESS) return false; const RegisterInfo * reg_info = GetRegisterInfoAtIndex (reg); if (reg_info == NULL && data.ValidOffsetForDataOfSize(data_offset, reg_info->byte_size)) return false; uint32_t offset = data_offset; switch (reg) { case gpr_eax: case gpr_ebx: case gpr_ecx: case gpr_edx: case gpr_edi: case gpr_esi: case gpr_ebp: case gpr_esp: case gpr_ss: case gpr_eflags: case gpr_eip: case gpr_cs: case gpr_ds: case gpr_es: case gpr_fs: case gpr_gs: (&gpr.eax)[reg - gpr_eax] = data.GetU32 (&offset); break; case fpu_fcw: fpu.fcw = data.GetU16(&offset); break; case fpu_fsw: fpu.fsw = data.GetU16(&offset); break; case fpu_ftw: fpu.ftw = data.GetU8(&offset); break; case fpu_fop: fpu.fop = data.GetU16(&offset); break; case fpu_ip: fpu.ip = data.GetU32(&offset); break; case fpu_cs: fpu.cs = data.GetU16(&offset); break; case fpu_dp: fpu.dp = data.GetU32(&offset); break; case fpu_ds: fpu.ds = data.GetU16(&offset); break; case fpu_mxcsr: fpu.mxcsr = data.GetU32(&offset); break; case fpu_mxcsrmask: fpu.mxcsrmask = data.GetU32(&offset); break; case fpu_stmm0: case fpu_stmm1: case fpu_stmm2: case fpu_stmm3: case fpu_stmm4: case fpu_stmm5: case fpu_stmm6: case fpu_stmm7: ::memcpy (fpu.stmm[reg - fpu_stmm0].bytes, data.PeekData(offset, reg_info->byte_size), reg_info->byte_size); return false; case fpu_xmm0: case fpu_xmm1: case fpu_xmm2: case fpu_xmm3: case fpu_xmm4: case fpu_xmm5: case fpu_xmm6: case fpu_xmm7: // These values don't fit into scalar types, RegisterContext::ReadRegisterBytes() // must be used for these registers ::memcpy (fpu.xmm[reg - fpu_xmm0].bytes, data.PeekData(offset, reg_info->byte_size), reg_info->byte_size); return false; case exc_trapno: exc.trapno = data.GetU32 (&offset); break; case exc_err: exc.err = data.GetU32 (&offset); break; case exc_faultvaddr: exc.faultvaddr = data.GetU32 (&offset); break; default: return false; } return WriteRegisterSet(set) == KERN_SUCCESS; }
static int print_dwarf_exp_op (Stream &s, const DataExtractor& data, uint32_t* offset_ptr, int address_size, int dwarf_ref_size) { uint8_t opcode = data.GetU8(offset_ptr); DRC_class opcode_class; uint64_t uint; int64_t sint; int size; opcode_class = DW_OP_value_to_class (opcode) & (~DRC_DWARFv3); s.Printf("%s ", DW_OP_value_to_name (opcode)); /* Does this take zero parameters? If so we can shortcut this function. */ if (opcode_class == DRC_ZEROOPERANDS) return 0; if (opcode_class == DRC_TWOOPERANDS && opcode == DW_OP_bregx) { uint = data.GetULEB128(offset_ptr); sint = data.GetSLEB128(offset_ptr); s.Printf("%llu %lli", uint, sint); return 0; } if (opcode_class != DRC_ONEOPERAND) { s.Printf("UNKNOWN OP %u", opcode); return 1; } switch (opcode) { case DW_OP_addr: size = address_size; break; case DW_OP_const1u: size = 1; break; case DW_OP_const1s: size = -1; break; case DW_OP_const2u: size = 2; break; case DW_OP_const2s: size = -2; break; case DW_OP_const4u: size = 4; break; case DW_OP_const4s: size = -4; break; case DW_OP_const8u: size = 8; break; case DW_OP_const8s: size = -8; break; case DW_OP_constu: size = 128; break; case DW_OP_consts: size = -128; break; case DW_OP_fbreg: size = -128; break; case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: case DW_OP_breg3: case DW_OP_breg4: case DW_OP_breg5: case DW_OP_breg6: case DW_OP_breg7: case DW_OP_breg8: case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11: case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15: case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19: case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23: case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27: case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31: size = -128; break; case DW_OP_pick: size = 1; break; case DW_OP_deref_size: size = 1; break; case DW_OP_xderef_size: size = 1; break; case DW_OP_plus_uconst: size = 128; break; case DW_OP_skip: size = -2; break; case DW_OP_bra: size = -2; break; case DW_OP_call2: size = 2; break; case DW_OP_call4: size = 4; break; case DW_OP_call_ref: size = dwarf_ref_size; break; case DW_OP_piece: size = 128; break; case DW_OP_regx: size = 128; break; default: s.Printf("UNKNOWN ONE-OPERAND OPCODE, #%u", opcode); return 1; } switch (size) { case -1: sint = (int8_t) data.GetU8(offset_ptr); s.Printf("%+lli", sint); break; case -2: sint = (int16_t) data.GetU16(offset_ptr); s.Printf("%+lli", sint); break; case -4: sint = (int32_t) data.GetU32(offset_ptr); s.Printf("%+lli", sint); break; case -8: sint = (int64_t) data.GetU64(offset_ptr); s.Printf("%+lli", sint); break; case -128: sint = data.GetSLEB128(offset_ptr); s.Printf("%+lli", sint); break; case 1: uint = data.GetU8(offset_ptr); s.Printf("0x%2.2llx", uint); break; case 2: uint = data.GetU16(offset_ptr); s.Printf("0x%4.4llx", uint); break; case 4: uint = data.GetU32(offset_ptr); s.Printf("0x%8.8llx", uint); break; case 8: uint = data.GetU64(offset_ptr); s.Printf("0x%16.16llx", uint); break; case 128: uint = data.GetULEB128(offset_ptr); s.Printf("0x%llx", uint); break; } return 0; }
//---------------------------------------------------------------------- // Try and figure out where dyld is by first asking the Process // if it knows (which currently calls down in the lldb::Process // to get the DYLD info (available on SnowLeopard only). If that fails, // then check in the default addresses. //---------------------------------------------------------------------- void DynamicLoaderMacOSXDYLD::DoInitialImageFetch() { if (m_dyld_all_image_infos_addr == LLDB_INVALID_ADDRESS) { // Check the image info addr as it might point to the // mach header for dyld, or it might point to the // dyld_all_image_infos struct const addr_t shlib_addr = m_process->GetImageInfoAddress (); if (shlib_addr != LLDB_INVALID_ADDRESS) { ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder(); uint8_t buf[4]; DataExtractor data (buf, sizeof(buf), byte_order, 4); Error error; if (m_process->ReadMemory (shlib_addr, buf, 4, error) == 4) { lldb::offset_t offset = 0; uint32_t magic = data.GetU32 (&offset); switch (magic) { case llvm::MachO::MH_MAGIC: case llvm::MachO::MH_MAGIC_64: case llvm::MachO::MH_CIGAM: case llvm::MachO::MH_CIGAM_64: m_process_image_addr_is_all_images_infos = false; ReadDYLDInfoFromMemoryAndSetNotificationCallback(shlib_addr); return; default: break; } } // Maybe it points to the all image infos? m_dyld_all_image_infos_addr = shlib_addr; m_process_image_addr_is_all_images_infos = true; } } if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) { if (ReadAllImageInfosStructure ()) { if (m_dyld_all_image_infos.dyldImageLoadAddress != LLDB_INVALID_ADDRESS) ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos.dyldImageLoadAddress); else ReadDYLDInfoFromMemoryAndSetNotificationCallback (m_dyld_all_image_infos_addr & 0xfffffffffff00000ull); return; } } // Check some default values Module *executable = m_process->GetTarget().GetExecutableModulePointer(); if (executable) { const ArchSpec &exe_arch = executable->GetArchitecture(); if (exe_arch.GetAddressByteSize() == 8) { ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x7fff5fc00000ull); } else if (exe_arch.GetMachine() == llvm::Triple::arm || exe_arch.GetMachine() == llvm::Triple::thumb || exe_arch.GetMachine() == llvm::Triple::aarch64) { ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x2fe00000); } else { ReadDYLDInfoFromMemoryAndSetNotificationCallback(0x8fe00000); } } return; }
void CommunicationKDP::DumpPacket(Stream &s, const DataExtractor &packet) { const char *error_desc = NULL; if (packet.GetByteSize() < 8) { error_desc = "error: invalid packet (too short): "; } else { lldb::offset_t offset = 0; const uint8_t first_packet_byte = packet.GetU8(&offset); const uint8_t sequence_id = packet.GetU8(&offset); const uint16_t length = packet.GetU16(&offset); const uint32_t key = packet.GetU32(&offset); const CommandType command = ExtractCommand(first_packet_byte); const char *command_name = GetCommandAsCString(command); if (command_name) { const bool is_reply = ExtractIsReply(first_packet_byte); s.Printf("(running=%i) %s %24s: 0x%2.2x 0x%2.2x 0x%4.4x 0x%8.8x ", IsRunning(), is_reply ? "<--" : "-->", command_name, first_packet_byte, sequence_id, length, key); if (is_reply) { // Dump request reply packets switch (command) { // Commands that return a single 32 bit error case KDP_CONNECT: case KDP_WRITEMEM: case KDP_WRITEMEM64: case KDP_BREAKPOINT_SET: case KDP_BREAKPOINT_REMOVE: case KDP_BREAKPOINT_SET64: case KDP_BREAKPOINT_REMOVE64: case KDP_WRITEREGS: case KDP_LOAD: case KDP_WRITEIOPORT: case KDP_WRITEMSR64: { const uint32_t error = packet.GetU32(&offset); s.Printf(" (error=0x%8.8x)", error); } break; case KDP_DISCONNECT: case KDP_REATTACH: case KDP_HOSTREBOOT: case KDP_SUSPEND: case KDP_RESUMECPUS: case KDP_EXCEPTION: case KDP_TERMINATION: // No return value for the reply, just the header to ack s.PutCString(" ()"); break; case KDP_HOSTINFO: { const uint32_t cpu_mask = packet.GetU32(&offset); const uint32_t cpu_type = packet.GetU32(&offset); const uint32_t cpu_subtype = packet.GetU32(&offset); s.Printf(" (cpu_mask=0x%8.8x, cpu_type=0x%8.8x, cpu_subtype=0x%8.8x)", cpu_mask, cpu_type, cpu_subtype); } break; case KDP_VERSION: { const uint32_t version = packet.GetU32(&offset); const uint32_t feature = packet.GetU32(&offset); s.Printf(" (version=0x%8.8x, feature=0x%8.8x)", version, feature); } break; case KDP_REGIONS: { const uint32_t region_count = packet.GetU32(&offset); s.Printf(" (count = %u", region_count); for (uint32_t i = 0; i < region_count; ++i) { const addr_t region_addr = packet.GetPointer(&offset); const uint32_t region_size = packet.GetU32(&offset); const uint32_t region_prot = packet.GetU32(&offset); s.Printf("\n\tregion[%" PRIu64 "] = { range = [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 "), size = 0x%8.8x, prot = %s }", region_addr, region_addr, region_addr + region_size, region_size, GetPermissionsAsCString(region_prot)); } } break; case KDP_READMEM: case KDP_READMEM64: case KDP_READPHYSMEM64: { const uint32_t error = packet.GetU32(&offset); const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (error = 0x%8.8x:\n", error); if (count > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatBytesWithASCII, // Format to use 1, // Size of each item // in bytes count, // Number of items 16, // Number per line m_last_read_memory_addr, // Don't show addresses // before each line 0, 0); // No bitfields } break; case KDP_READREGS: { const uint32_t error = packet.GetU32(&offset); const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (error = 0x%8.8x regs:\n", error); if (count > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatHex, // Format to use m_addr_byte_size, // Size of each item // in bytes count / m_addr_byte_size, // Number of items 16 / m_addr_byte_size, // Number per line LLDB_INVALID_ADDRESS, // Don't // show addresses before // each line 0, 0); // No bitfields } break; case KDP_KERNELVERSION: { const char *kernel_version = packet.PeekCStr(8); s.Printf(" (version = \"%s\")", kernel_version); } break; case KDP_MAXBYTES: { const uint32_t max_bytes = packet.GetU32(&offset); s.Printf(" (max_bytes = 0x%8.8x (%u))", max_bytes, max_bytes); } break; case KDP_IMAGEPATH: { const char *path = packet.GetCStr(&offset); s.Printf(" (path = \"%s\")", path); } break; case KDP_READIOPORT: case KDP_READMSR64: { const uint32_t error = packet.GetU32(&offset); const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (error = 0x%8.8x io:\n", error); if (count > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatHex, // Format to use 1, // Size of each item in bytes count, // Number of items 16, // Number per line LLDB_INVALID_ADDRESS, // Don't show addresses // before each line 0, 0); // No bitfields } break; case KDP_DUMPINFO: { const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (count = %u, bytes = \n", count); if (count > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatHex, // Format to use 1, // Size of each item in // bytes count, // Number of items 16, // Number per line LLDB_INVALID_ADDRESS, // Don't show addresses // before each line 0, 0); // No bitfields } break; default: s.Printf(" (add support for dumping this packet reply!!!"); break; } } else { // Dump request packets switch (command) { case KDP_CONNECT: { const uint16_t reply_port = ntohs(packet.GetU16(&offset)); const uint16_t exc_port = ntohs(packet.GetU16(&offset)); s.Printf(" (reply_port = %u, exc_port = %u, greeting = \"%s\")", reply_port, exc_port, packet.GetCStr(&offset)); } break; case KDP_DISCONNECT: case KDP_HOSTREBOOT: case KDP_HOSTINFO: case KDP_VERSION: case KDP_REGIONS: case KDP_KERNELVERSION: case KDP_MAXBYTES: case KDP_IMAGEPATH: case KDP_SUSPEND: // No args, just the header in the request... s.PutCString(" ()"); break; case KDP_RESUMECPUS: { const uint32_t cpu_mask = packet.GetU32(&offset); s.Printf(" (cpu_mask = 0x%8.8x)", cpu_mask); } break; case KDP_READMEM: { const uint32_t addr = packet.GetU32(&offset); const uint32_t size = packet.GetU32(&offset); s.Printf(" (addr = 0x%8.8x, size = %u)", addr, size); m_last_read_memory_addr = addr; } break; case KDP_WRITEMEM: { const uint32_t addr = packet.GetU32(&offset); const uint32_t size = packet.GetU32(&offset); s.Printf(" (addr = 0x%8.8x, size = %u, bytes = \n", addr, size); if (size > 0) DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); } break; case KDP_READMEM64: { const uint64_t addr = packet.GetU64(&offset); const uint32_t size = packet.GetU32(&offset); s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u)", addr, size); m_last_read_memory_addr = addr; } break; case KDP_READPHYSMEM64: { const uint64_t addr = packet.GetU64(&offset); const uint32_t size = packet.GetU32(&offset); const uint32_t lcpu = packet.GetU16(&offset); s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u)", addr, size, lcpu); m_last_read_memory_addr = addr; } break; case KDP_WRITEMEM64: { const uint64_t addr = packet.GetU64(&offset); const uint32_t size = packet.GetU32(&offset); s.Printf(" (addr = 0x%16.16" PRIx64 ", size = %u, bytes = \n", addr, size); if (size > 0) DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); } break; case KDP_WRITEPHYSMEM64: { const uint64_t addr = packet.GetU64(&offset); const uint32_t size = packet.GetU32(&offset); const uint32_t lcpu = packet.GetU16(&offset); s.Printf(" (addr = 0x%16.16llx, size = %u, lcpu = %u, bytes = \n", addr, size, lcpu); if (size > 0) DumpHexBytes(&s, packet.GetData(&offset, size), size, 32, addr); } break; case KDP_READREGS: { const uint32_t cpu = packet.GetU32(&offset); const uint32_t flavor = packet.GetU32(&offset); s.Printf(" (cpu = %u, flavor = %u)", cpu, flavor); } break; case KDP_WRITEREGS: { const uint32_t cpu = packet.GetU32(&offset); const uint32_t flavor = packet.GetU32(&offset); const uint32_t nbytes = packet.GetByteSize() - offset; s.Printf(" (cpu = %u, flavor = %u, regs = \n", cpu, flavor); if (nbytes > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within // "packet" eFormatHex, // Format to use m_addr_byte_size, // Size of each item in // bytes nbytes / m_addr_byte_size, // Number of items 16 / m_addr_byte_size, // Number per line LLDB_INVALID_ADDRESS, // Don't show addresses // before each line 0, 0); // No bitfields } break; case KDP_BREAKPOINT_SET: case KDP_BREAKPOINT_REMOVE: { const uint32_t addr = packet.GetU32(&offset); s.Printf(" (addr = 0x%8.8x)", addr); } break; case KDP_BREAKPOINT_SET64: case KDP_BREAKPOINT_REMOVE64: { const uint64_t addr = packet.GetU64(&offset); s.Printf(" (addr = 0x%16.16" PRIx64 ")", addr); } break; case KDP_LOAD: { const char *path = packet.GetCStr(&offset); s.Printf(" (path = \"%s\")", path); } break; case KDP_EXCEPTION: { const uint32_t count = packet.GetU32(&offset); for (uint32_t i = 0; i < count; ++i) { const uint32_t cpu = packet.GetU32(&offset); const uint32_t exc = packet.GetU32(&offset); const uint32_t code = packet.GetU32(&offset); const uint32_t subcode = packet.GetU32(&offset); const char *exc_cstr = NULL; switch (exc) { case 1: exc_cstr = "EXC_BAD_ACCESS"; break; case 2: exc_cstr = "EXC_BAD_INSTRUCTION"; break; case 3: exc_cstr = "EXC_ARITHMETIC"; break; case 4: exc_cstr = "EXC_EMULATION"; break; case 5: exc_cstr = "EXC_SOFTWARE"; break; case 6: exc_cstr = "EXC_BREAKPOINT"; break; case 7: exc_cstr = "EXC_SYSCALL"; break; case 8: exc_cstr = "EXC_MACH_SYSCALL"; break; case 9: exc_cstr = "EXC_RPC_ALERT"; break; case 10: exc_cstr = "EXC_CRASH"; break; default: break; } s.Printf("{ cpu = 0x%8.8x, exc = %s (%u), code = %u (0x%8.8x), " "subcode = %u (0x%8.8x)} ", cpu, exc_cstr, exc, code, code, subcode, subcode); } } break; case KDP_TERMINATION: { const uint32_t term_code = packet.GetU32(&offset); const uint32_t exit_code = packet.GetU32(&offset); s.Printf(" (term_code = 0x%8.8x (%u), exit_code = 0x%8.8x (%u))", term_code, term_code, exit_code, exit_code); } break; case KDP_REATTACH: { const uint16_t reply_port = ntohs(packet.GetU16(&offset)); s.Printf(" (reply_port = %u)", reply_port); } break; case KDP_READMSR64: { const uint32_t address = packet.GetU32(&offset); const uint16_t lcpu = packet.GetU16(&offset); s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x)", address, lcpu); } break; case KDP_WRITEMSR64: { const uint32_t address = packet.GetU32(&offset); const uint16_t lcpu = packet.GetU16(&offset); const uint32_t nbytes = packet.GetByteSize() - offset; s.Printf(" (address=0x%8.8x, lcpu=0x%4.4x, nbytes=0x%8.8x)", lcpu, address, nbytes); if (nbytes > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatHex, // Format to use 1, // Size of each item in // bytes nbytes, // Number of items 16, // Number per line LLDB_INVALID_ADDRESS, // Don't show addresses // before each line 0, 0); // No bitfields } break; case KDP_READIOPORT: { const uint16_t lcpu = packet.GetU16(&offset); const uint16_t address = packet.GetU16(&offset); const uint16_t nbytes = packet.GetU16(&offset); s.Printf(" (lcpu=0x%4.4x, address=0x%4.4x, nbytes=%u)", lcpu, address, nbytes); } break; case KDP_WRITEIOPORT: { const uint16_t lcpu = packet.GetU16(&offset); const uint16_t address = packet.GetU16(&offset); const uint16_t nbytes = packet.GetU16(&offset); s.Printf(" (lcpu = %u, addr = 0x%4.4x, nbytes = %u, bytes = \n", lcpu, address, nbytes); if (nbytes > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatHex, // Format to use 1, // Size of each item in // bytes nbytes, // Number of items 16, // Number per line LLDB_INVALID_ADDRESS, // Don't show addresses // before each line 0, 0); // No bitfields } break; case KDP_DUMPINFO: { const uint32_t count = packet.GetByteSize() - offset; s.Printf(" (count = %u, bytes = \n", count); if (count > 0) DumpDataExtractor(packet, &s, // Stream to dump to offset, // Offset within "packet" eFormatHex, // Format to use 1, // Size of each item in bytes count, // Number of items 16, // Number per line LLDB_INVALID_ADDRESS, // Don't show addresses before each line 0, 0); // No bitfields } break; } } } else { error_desc = "error: invalid packet command: "; } } if (error_desc) { s.PutCString(error_desc); DumpDataExtractor(packet, &s, // Stream to dump to 0, // Offset into "packet" eFormatBytes, // Dump as hex bytes 1, // Size of each item is 1 for // single bytes packet.GetByteSize(), // Number of bytes UINT32_MAX, // Num bytes per line LLDB_INVALID_ADDRESS, // Base address 0, 0); // Bitfield info set to not do // anything bitfield related } }
bool DynamicLoaderMacOSXDYLD::ReadAllImageInfosStructure () { std::lock_guard<std::recursive_mutex> guard(m_mutex); // the all image infos is already valid for this process stop ID if (m_process->GetStopID() == m_dyld_all_image_infos_stop_id) return true; m_dyld_all_image_infos.Clear(); if (m_dyld_all_image_infos_addr != LLDB_INVALID_ADDRESS) { ByteOrder byte_order = m_process->GetTarget().GetArchitecture().GetByteOrder(); uint32_t addr_size = 4; if (m_dyld_all_image_infos_addr > UINT32_MAX) addr_size = 8; uint8_t buf[256]; DataExtractor data (buf, sizeof(buf), byte_order, addr_size); lldb::offset_t offset = 0; const size_t count_v2 = sizeof (uint32_t) + // version sizeof (uint32_t) + // infoArrayCount addr_size + // infoArray addr_size + // notification addr_size + // processDetachedFromSharedRegion + libSystemInitialized + pad addr_size; // dyldImageLoadAddress const size_t count_v11 = count_v2 + addr_size + // jitInfo addr_size + // dyldVersion addr_size + // errorMessage addr_size + // terminationFlags addr_size + // coreSymbolicationShmPage addr_size + // systemOrderFlag addr_size + // uuidArrayCount addr_size + // uuidArray addr_size + // dyldAllImageInfosAddress addr_size + // initialImageCount addr_size + // errorKind addr_size + // errorClientOfDylibPath addr_size + // errorTargetDylibPath addr_size; // errorSymbol const size_t count_v13 = count_v11 + addr_size + // sharedCacheSlide sizeof (uuid_t); // sharedCacheUUID UNUSED_IF_ASSERT_DISABLED(count_v13); assert (sizeof (buf) >= count_v13); Error error; if (m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, 4, error) == 4) { m_dyld_all_image_infos.version = data.GetU32(&offset); // If anything in the high byte is set, we probably got the byte // order incorrect (the process might not have it set correctly // yet due to attaching to a program without a specified file). if (m_dyld_all_image_infos.version & 0xff000000) { // We have guessed the wrong byte order. Swap it and try // reading the version again. if (byte_order == eByteOrderLittle) byte_order = eByteOrderBig; else byte_order = eByteOrderLittle; data.SetByteOrder (byte_order); offset = 0; m_dyld_all_image_infos.version = data.GetU32(&offset); } } else { return false; } const size_t count = (m_dyld_all_image_infos.version >= 11) ? count_v11 : count_v2; const size_t bytes_read = m_process->ReadMemory (m_dyld_all_image_infos_addr, buf, count, error); if (bytes_read == count) { offset = 0; m_dyld_all_image_infos.version = data.GetU32(&offset); m_dyld_all_image_infos.dylib_info_count = data.GetU32(&offset); m_dyld_all_image_infos.dylib_info_addr = data.GetPointer(&offset); m_dyld_all_image_infos.notification = data.GetPointer(&offset); m_dyld_all_image_infos.processDetachedFromSharedRegion = data.GetU8(&offset); m_dyld_all_image_infos.libSystemInitialized = data.GetU8(&offset); // Adjust for padding. offset += addr_size - 2; m_dyld_all_image_infos.dyldImageLoadAddress = data.GetPointer(&offset); if (m_dyld_all_image_infos.version >= 11) { offset += addr_size * 8; uint64_t dyld_all_image_infos_addr = data.GetPointer(&offset); // When we started, we were given the actual address of the all_image_infos // struct (probably via TASK_DYLD_INFO) in memory - this address is stored in // m_dyld_all_image_infos_addr and is the most accurate address we have. // We read the dyld_all_image_infos struct from memory; it contains its own address. // If the address in the struct does not match the actual address, // the dyld we're looking at has been loaded at a different location (slid) from // where it intended to load. The addresses in the dyld_all_image_infos struct // are the original, non-slid addresses, and need to be adjusted. Most importantly // the address of dyld and the notification address need to be adjusted. if (dyld_all_image_infos_addr != m_dyld_all_image_infos_addr) { uint64_t image_infos_offset = dyld_all_image_infos_addr - m_dyld_all_image_infos.dyldImageLoadAddress; uint64_t notification_offset = m_dyld_all_image_infos.notification - m_dyld_all_image_infos.dyldImageLoadAddress; m_dyld_all_image_infos.dyldImageLoadAddress = m_dyld_all_image_infos_addr - image_infos_offset; m_dyld_all_image_infos.notification = m_dyld_all_image_infos.dyldImageLoadAddress + notification_offset; } } m_dyld_all_image_infos_stop_id = m_process->GetStopID(); return true; } } return false; }
bool CommunicationKDP::CheckForPacket(const uint8_t *src, size_t src_len, DataExtractor &packet) { // Put the packet data into the buffer in a thread safe fashion std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); if (src && src_len > 0) { if (log && log->GetVerbose()) { PacketStreamType log_strm; DumpHexBytes(&log_strm, src, src_len, UINT32_MAX, LLDB_INVALID_ADDRESS); log->Printf("CommunicationKDP::%s adding %u bytes: %s", __FUNCTION__, (uint32_t)src_len, log_strm.GetData()); } m_bytes.append((const char *)src, src_len); } // Make sure we at least have enough bytes for a packet header const size_t bytes_available = m_bytes.size(); if (bytes_available >= 8) { packet.SetData(&m_bytes[0], bytes_available, m_byte_order); lldb::offset_t offset = 0; uint8_t reply_command = packet.GetU8(&offset); switch (reply_command) { case ePacketTypeRequest | KDP_EXCEPTION: case ePacketTypeRequest | KDP_TERMINATION: // We got an exception request, so be sure to send an ACK { PacketStreamType request_ack_packet(Stream::eBinary, m_addr_byte_size, m_byte_order); // Set the reply but and make the ACK packet request_ack_packet.PutHex8(reply_command | ePacketTypeReply); request_ack_packet.PutHex8(packet.GetU8(&offset)); request_ack_packet.PutHex16(packet.GetU16(&offset)); request_ack_packet.PutHex32(packet.GetU32(&offset)); m_is_running.SetValue(false, eBroadcastAlways); // Ack to the exception or termination SendRequestPacketNoLock(request_ack_packet); } // Fall through to case below to get packet contents LLVM_FALLTHROUGH; case ePacketTypeReply | KDP_CONNECT: case ePacketTypeReply | KDP_DISCONNECT: case ePacketTypeReply | KDP_HOSTINFO: case ePacketTypeReply | KDP_VERSION: case ePacketTypeReply | KDP_MAXBYTES: case ePacketTypeReply | KDP_READMEM: case ePacketTypeReply | KDP_WRITEMEM: case ePacketTypeReply | KDP_READREGS: case ePacketTypeReply | KDP_WRITEREGS: case ePacketTypeReply | KDP_LOAD: case ePacketTypeReply | KDP_IMAGEPATH: case ePacketTypeReply | KDP_SUSPEND: case ePacketTypeReply | KDP_RESUMECPUS: case ePacketTypeReply | KDP_BREAKPOINT_SET: case ePacketTypeReply | KDP_BREAKPOINT_REMOVE: case ePacketTypeReply | KDP_REGIONS: case ePacketTypeReply | KDP_REATTACH: case ePacketTypeReply | KDP_HOSTREBOOT: case ePacketTypeReply | KDP_READMEM64: case ePacketTypeReply | KDP_WRITEMEM64: case ePacketTypeReply | KDP_BREAKPOINT_SET64: case ePacketTypeReply | KDP_BREAKPOINT_REMOVE64: case ePacketTypeReply | KDP_KERNELVERSION: case ePacketTypeReply | KDP_READPHYSMEM64: case ePacketTypeReply | KDP_WRITEPHYSMEM64: case ePacketTypeReply | KDP_READIOPORT: case ePacketTypeReply | KDP_WRITEIOPORT: case ePacketTypeReply | KDP_READMSR64: case ePacketTypeReply | KDP_WRITEMSR64: case ePacketTypeReply | KDP_DUMPINFO: { offset = 2; const uint16_t length = packet.GetU16(&offset); if (length <= bytes_available) { // We have an entire packet ready, we need to copy the data bytes into // a buffer that will be owned by the packet and erase the bytes from // our communcation buffer "m_bytes" packet.SetData(DataBufferSP(new DataBufferHeap(&m_bytes[0], length))); m_bytes.erase(0, length); if (log) { PacketStreamType log_strm; DumpPacket(log_strm, packet); log->Printf("%.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); } return true; } } break; default: // Unrecognized reply command byte, erase this byte and try to get back // on track if (log) log->Printf("CommunicationKDP::%s: tossing junk byte: 0x%2.2x", __FUNCTION__, (uint8_t)m_bytes[0]); m_bytes.erase(0, 1); break; } } packet.Clear(); return false; }
void SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR (lldb::addr_t queues_buffer, uint64_t queues_buffer_size, uint64_t count, lldb_private::QueueList &queue_list) { Error error; DataBufferHeap data (queues_buffer_size, 0); Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); if (m_process->ReadMemory (queues_buffer, data.GetBytes(), queues_buffer_size, error) == queues_buffer_size && error.Success()) { // We've read the information out of inferior memory; free it on the next call we make m_page_to_free = queues_buffer; m_page_to_free_size = queues_buffer_size; DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize()); offset_t offset = 0; uint64_t queues_read = 0; // The information about the queues is stored in this format (v1): // typedef struct introspection_dispatch_queue_info_s { // uint32_t offset_to_next; // dispatch_queue_t queue; // uint64_t serialnum; // queue's serialnum in the process, as provided by libdispatch // uint32_t running_work_items_count; // uint32_t pending_work_items_count; // // char data[]; // Starting here, we have variable-length data: // // char queue_label[]; // } introspection_dispatch_queue_info_s; while (queues_read < count && offset < queues_buffer_size) { offset_t start_of_this_item = offset; uint32_t offset_to_next = extractor.GetU32 (&offset); offset += 4; // Skip over the 4 bytes of reserved space addr_t queue = extractor.GetPointer (&offset); uint64_t serialnum = extractor.GetU64 (&offset); uint32_t running_work_items_count = extractor.GetU32 (&offset); uint32_t pending_work_items_count = extractor.GetU32 (&offset); // Read the first field of the variable length data offset = start_of_this_item + m_lib_backtrace_recording_info.queue_info_data_offset; const char *queue_label = extractor.GetCStr (&offset); if (queue_label == NULL) queue_label = ""; offset_t start_of_next_item = start_of_this_item + offset_to_next; offset = start_of_next_item; if (log) log->Printf ("SystemRuntimeMacOSX::PopulateQueuesUsingLibBTR added queue with dispatch_queue_t 0x%" PRIx64 ", serial number 0x%" PRIx64 ", running items %d, pending items %d, name '%s'", queue, serialnum, running_work_items_count, pending_work_items_count, queue_label); QueueSP queue_sp (new Queue (m_process->shared_from_this(), serialnum, queue_label)); queue_sp->SetNumRunningWorkItems (running_work_items_count); queue_sp->SetNumPendingWorkItems (pending_work_items_count); queue_sp->SetLibdispatchQueueAddress (queue); queue_sp->SetKind (GetQueueKind (queue)); queue_list.AddQueue (queue_sp); queues_read++; } } }
SystemRuntimeMacOSX::PendingItemsForQueue SystemRuntimeMacOSX::GetPendingItemRefsForQueue (lldb::addr_t queue) { PendingItemsForQueue pending_item_refs; AppleGetPendingItemsHandler::GetPendingItemsReturnInfo pending_items_pointer; ThreadSP cur_thread_sp (m_process->GetThreadList().GetSelectedThread()); if (cur_thread_sp) { Error error; pending_items_pointer = m_get_pending_items_handler.GetPendingItems (*cur_thread_sp.get(), queue, m_page_to_free, m_page_to_free_size, error); m_page_to_free = LLDB_INVALID_ADDRESS; m_page_to_free_size = 0; if (error.Success()) { if (pending_items_pointer.count > 0 && pending_items_pointer.items_buffer_size > 0 && pending_items_pointer.items_buffer_ptr != 0 && pending_items_pointer.items_buffer_ptr != LLDB_INVALID_ADDRESS) { DataBufferHeap data (pending_items_pointer.items_buffer_size, 0); if (m_process->ReadMemory (pending_items_pointer.items_buffer_ptr, data.GetBytes(), pending_items_pointer.items_buffer_size, error)) { DataExtractor extractor (data.GetBytes(), data.GetByteSize(), m_process->GetByteOrder(), m_process->GetAddressByteSize()); // We either have an array of // void* item_ref // (old style) or we have a structure returned which looks like // // struct introspection_dispatch_pending_item_info_s { // void *item_ref; // void *function_or_block; // }; // // struct introspection_dispatch_pending_items_array_s { // uint32_t version; // uint32_t size_of_item_info; // introspection_dispatch_pending_item_info_s items[]; // } offset_t offset = 0; int i = 0; uint32_t version = extractor.GetU32(&offset); if (version == 1) { pending_item_refs.new_style = true; uint32_t item_size = extractor.GetU32(&offset); uint32_t start_of_array_offset = offset; while (offset < pending_items_pointer.items_buffer_size && static_cast<size_t>(i) < pending_items_pointer.count) { offset = start_of_array_offset + (i * item_size); ItemRefAndCodeAddress item; item.item_ref = extractor.GetPointer (&offset); item.code_address = extractor.GetPointer (&offset); pending_item_refs.item_refs_and_code_addresses.push_back (item); i++; } } else { offset = 0; pending_item_refs.new_style = false; while (offset < pending_items_pointer.items_buffer_size && static_cast<size_t>(i) < pending_items_pointer.count) { ItemRefAndCodeAddress item; item.item_ref = extractor.GetPointer (&offset); item.code_address = LLDB_INVALID_ADDRESS; pending_item_refs.item_refs_and_code_addresses.push_back (item); i++; } } } m_page_to_free = pending_items_pointer.items_buffer_ptr; m_page_to_free_size = pending_items_pointer.items_buffer_size; } } } return pending_item_refs; }
// Parse the load commands for an image uint32_t DynamicLoaderMacOSXDYLD::ParseLoadCommands(const DataExtractor &data, ImageInfo &dylib_info, FileSpec *lc_id_dylinker) { lldb::offset_t offset = 0; uint32_t cmd_idx; Segment segment; dylib_info.Clear(true); for (cmd_idx = 0; cmd_idx < dylib_info.header.ncmds; cmd_idx++) { // Clear out any load command specific data from DYLIB_INFO since we are // about to read it. if (data.ValidOffsetForDataOfSize(offset, sizeof(llvm::MachO::load_command))) { llvm::MachO::load_command load_cmd; lldb::offset_t load_cmd_offset = offset; load_cmd.cmd = data.GetU32(&offset); load_cmd.cmdsize = data.GetU32(&offset); switch (load_cmd.cmd) { case llvm::MachO::LC_SEGMENT: { segment.name.SetTrimmedCStringWithLength( (const char *)data.GetData(&offset, 16), 16); // We are putting 4 uint32_t values 4 uint64_t values so we have to use // multiple 32 bit gets below. segment.vmaddr = data.GetU32(&offset); segment.vmsize = data.GetU32(&offset); segment.fileoff = data.GetU32(&offset); segment.filesize = data.GetU32(&offset); // Extract maxprot, initprot, nsects and flags all at once data.GetU32(&offset, &segment.maxprot, 4); dylib_info.segments.push_back(segment); } break; case llvm::MachO::LC_SEGMENT_64: { segment.name.SetTrimmedCStringWithLength( (const char *)data.GetData(&offset, 16), 16); // Extract vmaddr, vmsize, fileoff, and filesize all at once data.GetU64(&offset, &segment.vmaddr, 4); // Extract maxprot, initprot, nsects and flags all at once data.GetU32(&offset, &segment.maxprot, 4); dylib_info.segments.push_back(segment); } break; case llvm::MachO::LC_ID_DYLINKER: if (lc_id_dylinker) { const lldb::offset_t name_offset = load_cmd_offset + data.GetU32(&offset); const char *path = data.PeekCStr(name_offset); lc_id_dylinker->SetFile(path, FileSpec::Style::native); FileSystem::Instance().Resolve(*lc_id_dylinker); } break; case llvm::MachO::LC_UUID: dylib_info.uuid = UUID::fromOptionalData(data.GetData(&offset, 16), 16); break; default: break; } // Set offset to be the beginning of the next load command. offset = load_cmd_offset + load_cmd.cmdsize; } } // All sections listed in the dyld image info structure will all either be // fixed up already, or they will all be off by a single slide amount that is // determined by finding the first segment that is at file offset zero which // also has bytes (a file size that is greater than zero) in the object file. // Determine the slide amount (if any) const size_t num_sections = dylib_info.segments.size(); for (size_t i = 0; i < num_sections; ++i) { // Iterate through the object file sections to find the first section that // starts of file offset zero and that has bytes in the file... if ((dylib_info.segments[i].fileoff == 0 && dylib_info.segments[i].filesize > 0) || (dylib_info.segments[i].name == "__TEXT")) { dylib_info.slide = dylib_info.address - dylib_info.segments[i].vmaddr; // We have found the slide amount, so we can exit this for loop. break; } } return cmd_idx; }
virtual void CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx) { DataExtractor data; const AddressClass address_class = GetAddressClass (); if (m_opcode.GetData(data)) { char out_string[512]; DisassemblerLLVMC &llvm_disasm = GetDisassemblerLLVMC(); DisassemblerLLVMC::LLVMCDisassembler *mc_disasm_ptr; if (address_class == eAddressClassCodeAlternateISA) mc_disasm_ptr = llvm_disasm.m_alternate_disasm_ap.get(); else mc_disasm_ptr = llvm_disasm.m_disasm_ap.get(); lldb::addr_t pc = m_address.GetFileAddress(); m_using_file_addr = true; const bool data_from_file = GetDisassemblerLLVMC().m_data_from_file; bool use_hex_immediates = true; Disassembler::HexImmediateStyle hex_style = Disassembler::eHexStyleC; if (exe_ctx) { Target *target = exe_ctx->GetTargetPtr(); if (target) { use_hex_immediates = target->GetUseHexImmediates(); hex_style = target->GetHexImmediateStyle(); if (!data_from_file) { const lldb::addr_t load_addr = m_address.GetLoadAddress(target); if (load_addr != LLDB_INVALID_ADDRESS) { pc = load_addr; m_using_file_addr = false; } } } } llvm_disasm.Lock(this, exe_ctx); const uint8_t *opcode_data = data.GetDataStart(); const size_t opcode_data_len = data.GetByteSize(); llvm::MCInst inst; size_t inst_size = mc_disasm_ptr->GetMCInst (opcode_data, opcode_data_len, pc, inst); if (inst_size > 0) { mc_disasm_ptr->SetStyle(use_hex_immediates, hex_style); mc_disasm_ptr->PrintMCInst(inst, out_string, sizeof(out_string)); } llvm_disasm.Unlock(); if (inst_size == 0) { m_comment.assign ("unknown opcode"); inst_size = m_opcode.GetByteSize(); StreamString mnemonic_strm; lldb::offset_t offset = 0; lldb::ByteOrder byte_order = data.GetByteOrder(); switch (inst_size) { case 1: { const uint8_t uval8 = data.GetU8 (&offset); m_opcode.SetOpcode8 (uval8, byte_order); m_opcode_name.assign (".byte"); mnemonic_strm.Printf("0x%2.2x", uval8); } break; case 2: { const uint16_t uval16 = data.GetU16(&offset); m_opcode.SetOpcode16(uval16, byte_order); m_opcode_name.assign (".short"); mnemonic_strm.Printf("0x%4.4x", uval16); } break; case 4: { const uint32_t uval32 = data.GetU32(&offset); m_opcode.SetOpcode32(uval32, byte_order); m_opcode_name.assign (".long"); mnemonic_strm.Printf("0x%8.8x", uval32); } break; case 8: { const uint64_t uval64 = data.GetU64(&offset); m_opcode.SetOpcode64(uval64, byte_order); m_opcode_name.assign (".quad"); mnemonic_strm.Printf("0x%16.16" PRIx64, uval64); } break; default: if (inst_size == 0) return; else { const uint8_t *bytes = data.PeekData(offset, inst_size); if (bytes == NULL) return; m_opcode_name.assign (".byte"); m_opcode.SetOpcodeBytes(bytes, inst_size); mnemonic_strm.Printf("0x%2.2x", bytes[0]); for (uint32_t i=1; i<inst_size; ++i) mnemonic_strm.Printf(" 0x%2.2x", bytes[i]); } break; } m_mnemonics.swap(mnemonic_strm.GetString()); return; } else { if (m_does_branch == eLazyBoolCalculate) { const bool can_branch = mc_disasm_ptr->CanBranch(inst); if (can_branch) m_does_branch = eLazyBoolYes; else m_does_branch = eLazyBoolNo; } } static RegularExpression s_regex("[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED); RegularExpression::Match matches(3); if (s_regex.Execute(out_string, &matches)) { matches.GetMatchAtIndex(out_string, 1, m_opcode_name); matches.GetMatchAtIndex(out_string, 2, m_mnemonics); } } }
bool ObjectContainerUniversalMachO::MagicBytesMatch(const DataExtractor &data) { lldb::offset_t offset = 0; uint32_t magic = data.GetU32(&offset); return magic == FAT_MAGIC || magic == FAT_CIGAM; }
virtual void CalculateMnemonicOperandsAndComment (const lldb_private::ExecutionContext *exe_ctx) { DataExtractor data; const AddressClass address_class = GetAddressClass (); if (m_opcode.GetData(data, address_class)) { char out_string[512]; ::LLVMDisasmContextRef disasm_context; if (address_class == eAddressClassCodeAlternateISA) disasm_context = m_disasm.m_alternate_disasm_context; else disasm_context = m_disasm.m_disasm_context; lldb::addr_t pc = LLDB_INVALID_ADDRESS; if (exe_ctx) { Target *target = exe_ctx->GetTargetPtr(); if (target) pc = m_address.GetLoadAddress(target); } if (pc == LLDB_INVALID_ADDRESS) pc = m_address.GetFileAddress(); m_disasm.Lock(this, exe_ctx); uint8_t *opcode_data = const_cast<uint8_t *>(data.PeekData (0, 1)); const size_t opcode_data_len = data.GetByteSize(); size_t inst_size = ::LLVMDisasmInstruction (disasm_context, opcode_data, opcode_data_len, pc, out_string, sizeof(out_string)); m_disasm.Unlock(); if (inst_size == 0) { m_comment.assign ("unknown opcode"); inst_size = m_opcode.GetByteSize(); StreamString mnemonic_strm; uint32_t offset = 0; switch (inst_size) { case 1: { const uint8_t uval8 = data.GetU8 (&offset); m_opcode.SetOpcode8 (uval8); m_opcode_name.assign (".byte"); mnemonic_strm.Printf("0x%2.2x", uval8); } break; case 2: { const uint16_t uval16 = data.GetU16(&offset); m_opcode.SetOpcode16(uval16); m_opcode_name.assign (".short"); mnemonic_strm.Printf("0x%4.4x", uval16); } break; case 4: { const uint32_t uval32 = data.GetU32(&offset); m_opcode.SetOpcode32(uval32); m_opcode_name.assign (".long"); mnemonic_strm.Printf("0x%8.8x", uval32); } break; case 8: { const uint64_t uval64 = data.GetU64(&offset); m_opcode.SetOpcode64(uval64); m_opcode_name.assign (".quad"); mnemonic_strm.Printf("0x%16.16llx", uval64); } break; default: if (inst_size == 0) return; else { const uint8_t *bytes = data.PeekData(offset, inst_size); if (bytes == NULL) return; m_opcode_name.assign (".byte"); m_opcode.SetOpcodeBytes(bytes, inst_size); mnemonic_strm.Printf("0x%2.2x", bytes[0]); for (uint32_t i=1; i<inst_size; ++i) mnemonic_strm.Printf(" 0x%2.2x", bytes[i]); } break; } m_mnemocics.swap(mnemonic_strm.GetString()); return; } else { if (m_does_branch == eLazyBoolCalculate) { if (StringRepresentsBranch (out_string, strlen(out_string))) m_does_branch = eLazyBoolYes; else m_does_branch = eLazyBoolNo; } } if (!s_regex_compiled) { ::regcomp(&s_regex, "[ \t]*([^ ^\t]+)[ \t]*([^ ^\t].*)?", REG_EXTENDED); s_regex_compiled = true; } ::regmatch_t matches[3]; if (!::regexec(&s_regex, out_string, sizeof(matches) / sizeof(::regmatch_t), matches, 0)) { if (matches[1].rm_so != -1) m_opcode_name.assign(out_string + matches[1].rm_so, matches[1].rm_eo - matches[1].rm_so); if (matches[2].rm_so != -1) m_mnemocics.assign(out_string + matches[2].rm_so, matches[2].rm_eo - matches[2].rm_so); } } }
bool UniversalMachOFileContainsArchAndUUID ( const FileSpec &file_spec, const ArchSpec *arch, const lldb_private::UUID *uuid, off_t file_offset, DataExtractor& data, uint32_t data_offset, const uint32_t magic ) { assert(magic == UniversalMagic || magic == UniversalMagicSwapped); // Universal mach-o files always have their headers encoded as BIG endian data.SetByteOrder(eByteOrderBig); uint32_t i; const uint32_t nfat_arch = data.GetU32(&data_offset); // number of structs that follow const uint32_t fat_header_and_arch_size = sizeof(struct fat_header) + nfat_arch * sizeof(struct fat_arch); if (data.GetByteSize() < fat_header_and_arch_size) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, fat_header_and_arch_size)); data.SetData (data_buffer_sp); } for (i=0; i<nfat_arch; i++) { cpu_type_t arch_cputype = data.GetU32(&data_offset); // cpu specifier (int) cpu_subtype_t arch_cpusubtype = data.GetU32(&data_offset); // machine specifier (int) uint32_t arch_offset = data.GetU32(&data_offset); // file offset to this object file // uint32_t arch_size = data.GetU32(&data_offset); // size of this object file // uint32_t arch_align = data.GetU32(&data_offset); // alignment as a power of 2 data_offset += 8; // Skip size and align as we don't need those // Only process this slice if the cpu type/subtype matches if (arch) { ArchSpec fat_arch(eArchTypeMachO, arch_cputype, arch_cpusubtype); if (fat_arch != *arch) continue; } // Create a buffer with only the arch slice date in it DataExtractor arch_data; DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset + arch_offset, 0x1000)); arch_data.SetData(data_buffer_sp); uint32_t arch_data_offset = 0; uint32_t arch_magic = arch_data.GetU32(&arch_data_offset); switch (arch_magic) { case HeaderMagic32: case HeaderMagic32Swapped: case HeaderMagic64: case HeaderMagic64Swapped: if (SkinnyMachOFileContainsArchAndUUID (file_spec, arch, uuid, file_offset + arch_offset, arch_data, arch_data_offset, arch_magic)) return true; break; } } return false; }
static bool SkinnyMachOFileContainsArchAndUUID ( const FileSpec &file_spec, const ArchSpec *arch, const lldb_private::UUID *uuid, // the UUID we are looking for off_t file_offset, DataExtractor& data, lldb::offset_t data_offset, const uint32_t magic ) { assert(magic == HeaderMagic32 || magic == HeaderMagic32Swapped || magic == HeaderMagic64 || magic == HeaderMagic64Swapped); if (magic == HeaderMagic32 || magic == HeaderMagic64) data.SetByteOrder (lldb::endian::InlHostByteOrder()); else if (lldb::endian::InlHostByteOrder() == eByteOrderBig) data.SetByteOrder (eByteOrderLittle); else data.SetByteOrder (eByteOrderBig); uint32_t i; const uint32_t cputype = data.GetU32(&data_offset); // cpu specifier const uint32_t cpusubtype = data.GetU32(&data_offset); // machine specifier data_offset+=4; // Skip mach file type const uint32_t ncmds = data.GetU32(&data_offset); // number of load commands const uint32_t sizeofcmds = data.GetU32(&data_offset); // the size of all the load commands data_offset+=4; // Skip flags // Check the architecture if we have a valid arch pointer if (arch) { ArchSpec file_arch(eArchTypeMachO, cputype, cpusubtype); if (!file_arch.IsCompatibleMatch(*arch)) return false; } // The file exists, and if a valid arch pointer was passed in we know // if already matches, so we can return if we aren't looking for a specific // UUID if (uuid == NULL) return true; if (magic == HeaderMagic64Swapped || magic == HeaderMagic64) data_offset += 4; // Skip reserved field for in mach_header_64 // Make sure we have enough data for all the load commands if (magic == HeaderMagic64Swapped || magic == HeaderMagic64) { if (data.GetByteSize() < sizeof(struct mach_header_64) + sizeofcmds) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header_64) + sizeofcmds)); data.SetData (data_buffer_sp); } } else { if (data.GetByteSize() < sizeof(struct mach_header) + sizeofcmds) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header) + sizeofcmds)); data.SetData (data_buffer_sp); } } for (i=0; i<ncmds; i++) { const lldb::offset_t cmd_offset = data_offset; // Save this data_offset in case parsing of the segment goes awry! uint32_t cmd = data.GetU32(&data_offset); uint32_t cmd_size = data.GetU32(&data_offset); if (cmd == LoadCommandUUID) { lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16); if (file_uuid == *uuid) return true; return false; } data_offset = cmd_offset + cmd_size; } return false; }
static bool SkinnyMachOFileContainsArchAndUUID ( const FileSpec &file_spec, const ArchSpec *arch, const lldb_private::UUID *uuid, // the UUID we are looking for off_t file_offset, DataExtractor& data, uint32_t data_offset, const uint32_t magic ) { assert(magic == HeaderMagic32 || magic == HeaderMagic32Swapped || magic == HeaderMagic64 || magic == HeaderMagic64Swapped); if (magic == HeaderMagic32 || magic == HeaderMagic64) data.SetByteOrder (lldb::endian::InlHostByteOrder()); else if (lldb::endian::InlHostByteOrder() == eByteOrderBig) data.SetByteOrder (eByteOrderLittle); else data.SetByteOrder (eByteOrderBig); uint32_t i; const uint32_t cputype = data.GetU32(&data_offset); // cpu specifier const uint32_t cpusubtype = data.GetU32(&data_offset); // machine specifier data_offset+=4; // Skip mach file type const uint32_t ncmds = data.GetU32(&data_offset); // number of load commands const uint32_t sizeofcmds = data.GetU32(&data_offset); // the size of all the load commands data_offset+=4; // Skip flags // Check the architecture if we have a valid arch pointer if (arch) { ArchSpec file_arch(eArchTypeMachO, cputype, cpusubtype); if (file_arch != *arch) return false; } // The file exists, and if a valid arch pointer was passed in we know // if already matches, so we can return if we aren't looking for a specific // UUID if (uuid == NULL) return true; if (magic == HeaderMagic64Swapped || magic == HeaderMagic64) data_offset += 4; // Skip reserved field for in mach_header_64 // Make sure we have enough data for all the load commands if (magic == HeaderMagic64Swapped || magic == HeaderMagic64) { if (data.GetByteSize() < sizeof(struct mach_header_64) + sizeofcmds) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header_64) + sizeofcmds)); data.SetData (data_buffer_sp); } } else { if (data.GetByteSize() < sizeof(struct mach_header) + sizeofcmds) { DataBufferSP data_buffer_sp (file_spec.ReadFileContents (file_offset, sizeof(struct mach_header) + sizeofcmds)); data.SetData (data_buffer_sp); } } for (i=0; i<ncmds; i++) { const uint32_t cmd_offset = data_offset; // Save this data_offset in case parsing of the segment goes awry! uint32_t cmd = data.GetU32(&data_offset); uint32_t cmd_size = data.GetU32(&data_offset); if (cmd == LoadCommandUUID) { lldb_private::UUID file_uuid (data.GetData(&data_offset, 16), 16); if (file_uuid == *uuid) return true; // Emit some warning messages since the UUIDs do not match! char path_buf[PATH_MAX]; path_buf[0] = '\0'; const char *path = file_spec.GetPath(path_buf, PATH_MAX) ? path_buf : file_spec.GetFilename().AsCString(); Host::SystemLog (Host::eSystemLogWarning, "warning: UUID mismatch detected between binary and:\n\t'%s'\n", path); return false; } data_offset = cmd_offset + cmd_size; } return false; }
void AppleObjCRuntimeV1::UpdateISAToDescriptorMapIfNeeded() { // TODO: implement HashTableSignature... Process *process = GetProcess(); if (process) { // Update the process stop ID that indicates the last time we updated the // map, whether it was successful or not. m_isa_to_descriptor_stop_id = process->GetStopID(); Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); ProcessSP process_sp = process->shared_from_this(); ModuleSP objc_module_sp(GetObjCModule()); if (!objc_module_sp) return; uint32_t isa_count = 0; lldb::addr_t hash_table_ptr = GetISAHashTablePointer (); if (hash_table_ptr != LLDB_INVALID_ADDRESS) { // Read the NXHashTable struct: // // typedef struct { // const NXHashTablePrototype *prototype; // unsigned count; // unsigned nbBuckets; // void *buckets; // const void *info; // } NXHashTable; Error error; DataBufferHeap buffer(1024, 0); if (process->ReadMemory(hash_table_ptr, buffer.GetBytes(), 20, error) == 20) { const uint32_t addr_size = m_process->GetAddressByteSize(); const ByteOrder byte_order = m_process->GetByteOrder(); DataExtractor data (buffer.GetBytes(), buffer.GetByteSize(), byte_order, addr_size); lldb::offset_t offset = addr_size; // Skip prototype const uint32_t count = data.GetU32(&offset); const uint32_t num_buckets = data.GetU32(&offset); const addr_t buckets_ptr = data.GetPointer(&offset); if (m_hash_signature.NeedsUpdate (count, num_buckets, buckets_ptr)) { m_hash_signature.UpdateSignature (count, num_buckets, buckets_ptr); const uint32_t data_size = num_buckets * 2 * sizeof(uint32_t); buffer.SetByteSize(data_size); if (process->ReadMemory(buckets_ptr, buffer.GetBytes(), data_size, error) == data_size) { data.SetData(buffer.GetBytes(), buffer.GetByteSize(), byte_order); offset = 0; for (uint32_t bucket_idx = 0; bucket_idx < num_buckets; ++bucket_idx) { const uint32_t bucket_isa_count = data.GetU32 (&offset); const lldb::addr_t bucket_data = data.GetU32 (&offset); if (bucket_isa_count == 0) continue; isa_count += bucket_isa_count; ObjCISA isa; if (bucket_isa_count == 1) { // When we only have one entry in the bucket, the bucket data is the "isa" isa = bucket_data; if (isa) { if (!ISAIsCached(isa)) { ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp)); if (log && log->GetVerbose()) log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa); AddClass (isa, descriptor_sp); } } } else { // When we have more than one entry in the bucket, the bucket data is a pointer // to an array of "isa" values addr_t isa_addr = bucket_data; for (uint32_t isa_idx = 0; isa_idx < bucket_isa_count; ++isa_idx, isa_addr += addr_size) { isa = m_process->ReadPointerFromMemory(isa_addr, error); if (isa && isa != LLDB_INVALID_ADDRESS) { if (!ISAIsCached(isa)) { ClassDescriptorSP descriptor_sp (new ClassDescriptorV1(isa, process_sp)); if (log && log->GetVerbose()) log->Printf("AppleObjCRuntimeV1 added (ObjCISA)0x%" PRIx64 " from _objc_debug_class_hash to isa->descriptor cache", isa); AddClass (isa, descriptor_sp); } } } } } } } } } } else { m_isa_to_descriptor_stop_id = UINT32_MAX; } }