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 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; }
bool CommunicationKDP::SendRequestAndGetReply (const CommandType command, const uint8_t request_sequence_id, const PacketStreamType &request_packet, DataExtractor &reply_packet) { if (IsRunning()) { LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS)); if (log) { PacketStreamType log_strm; DumpPacket (log_strm, request_packet.GetData(), request_packet.GetSize()); log->Printf("error: kdp running, not sending packet: %.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); } return false; } Mutex::Locker locker(m_sequence_mutex); #ifdef LLDB_CONFIGURATION_DEBUG // NOTE: this only works for packets that are in native endian byte order assert (request_packet.GetSize() == *((uint16_t *)(request_packet.GetData() + 2))); #endif if (SendRequestPacketNoLock(request_packet)) { if (WaitForPacketWithTimeoutMicroSecondsNoLock (reply_packet, GetPacketTimeoutInMicroSeconds ())) { uint32_t offset = 0; const uint8_t reply_command = reply_packet.GetU8 (&offset); const uint8_t reply_sequence_id = reply_packet.GetU8 (&offset); if ((reply_command & eCommandTypeMask) == command) { if (request_sequence_id == reply_sequence_id) { if (command == KDP_RESUMECPUS) m_is_running.SetValue(true, eBroadcastAlways); return true; } } } } reply_packet.Clear(); return false; }
bool DWARFDebugMacinfoEntry::Extract(const DataExtractor& mac_info_data, dw_offset_t* offset_ptr) { if (mac_info_data.ValidOffset(*offset_ptr)) { m_type_code = mac_info_data.GetU8(offset_ptr); switch (m_type_code) { case DW_MACINFO_define: case DW_MACINFO_undef: // 2 operands: // Arg 1: operand encodes the line number of the source line on which // the relevant defining or undefining pre-processor directives // appeared. m_line = mac_info_data.GetULEB128(offset_ptr); // Arg 2: define string m_op2.cstr = mac_info_data.GetCStr(offset_ptr); break; case DW_MACINFO_start_file: // 2 operands: // Op 1: line number of the source line on which the inclusion // pre-processor directive occurred. m_line = mac_info_data.GetULEB128(offset_ptr); // Op 2: a source file name index to a file number in the statement // information table for the relevant compilation unit. m_op2.file_idx = mac_info_data.GetULEB128(offset_ptr); break; case 0: // End of list case DW_MACINFO_end_file: // No operands m_line = DW_INVALID_OFFSET; m_op2.cstr = NULL; break; default: // Vendor specific entries always have a ULEB128 and a string m_line = mac_info_data.GetULEB128(offset_ptr); m_op2.cstr = mac_info_data.GetCStr(offset_ptr); break; } return true; } else m_type_code = 0; return false; }
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); } } }
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; }
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 CommunicationKDP::SendRequestAndGetReply( const CommandType command, const PacketStreamType &request_packet, DataExtractor &reply_packet) { if (IsRunning()) { Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); if (log) { PacketStreamType log_strm; DumpPacket(log_strm, request_packet.GetData(), request_packet.GetSize()); log->Printf("error: kdp running, not sending packet: %.*s", (uint32_t)log_strm.GetSize(), log_strm.GetData()); } return false; } std::lock_guard<std::recursive_mutex> guard(m_sequence_mutex); #ifdef LLDB_CONFIGURATION_DEBUG // NOTE: this only works for packets that are in native endian byte order assert(request_packet.GetSize() == *((const uint16_t *)(request_packet.GetData() + 2))); #endif lldb::offset_t offset = 1; const uint32_t num_retries = 3; for (uint32_t i = 0; i < num_retries; ++i) { if (SendRequestPacketNoLock(request_packet)) { const uint8_t request_sequence_id = (uint8_t)request_packet.GetData()[1]; while (1) { if (WaitForPacketWithTimeoutMicroSecondsNoLock( reply_packet, std::chrono::microseconds(GetPacketTimeout()).count())) { offset = 0; const uint8_t reply_command = reply_packet.GetU8(&offset); const uint8_t reply_sequence_id = reply_packet.GetU8(&offset); if (request_sequence_id == reply_sequence_id) { // The sequent ID was correct, now verify we got the response we // were looking for if ((reply_command & eCommandTypeMask) == command) { // Success if (command == KDP_RESUMECPUS) m_is_running.SetValue(true, eBroadcastAlways); return true; } else { // Failed to get the correct response, bail reply_packet.Clear(); return false; } } else if (reply_sequence_id > request_sequence_id) { // Sequence ID was greater than the sequence ID of the packet we // sent, something is really wrong... reply_packet.Clear(); return false; } else { // The reply sequence ID was less than our current packet's // sequence ID so we should keep trying to get a response because // this was a response for a previous packet that we must have // retried. } } else { // Break and retry sending the packet as we didn't get a response due // to timeout break; } } } } reply_packet.Clear(); 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; }
bool DWARFFormValue::SkipValue(dw_form_t form, const DataExtractor& debug_info_data, lldb::offset_t *offset_ptr, const DWARFCompileUnit* cu) { switch (form) { // Blocks if inlined data that have a length field and the data bytes // inlined in the .debug_info case DW_FORM_exprloc: case DW_FORM_block: { dw_uleb128_t size = debug_info_data.GetULEB128(offset_ptr); *offset_ptr += size; } return true; case DW_FORM_block1: { dw_uleb128_t size = debug_info_data.GetU8(offset_ptr); *offset_ptr += size; } return true; case DW_FORM_block2: { dw_uleb128_t size = debug_info_data.GetU16(offset_ptr); *offset_ptr += size; } return true; case DW_FORM_block4: { dw_uleb128_t size = debug_info_data.GetU32(offset_ptr); *offset_ptr += size; } return true; // Inlined NULL terminated C-strings case DW_FORM_string: debug_info_data.GetCStr(offset_ptr); return true; // Compile unit address sized values case DW_FORM_addr: *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu); return true; case DW_FORM_ref_addr: if (cu->GetVersion() <= 2) *offset_ptr += DWARFCompileUnit::GetAddressByteSize(cu); else *offset_ptr += 4;// 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet return true; // 0 bytes values (implied from DW_FORM) case DW_FORM_flag_present: return true; // 1 byte values case DW_FORM_data1: case DW_FORM_flag: case DW_FORM_ref1: *offset_ptr += 1; return true; // 2 byte values case DW_FORM_data2: case DW_FORM_ref2: *offset_ptr += 2; return true; // 32 bit for DWARF 32, 64 for DWARF 64 case DW_FORM_sec_offset: *offset_ptr += 4; return true; // 4 byte values case DW_FORM_strp: case DW_FORM_data4: case DW_FORM_ref4: *offset_ptr += 4; return true; // 8 byte values case DW_FORM_data8: case DW_FORM_ref8: case DW_FORM_ref_sig8: *offset_ptr += 8; return true; // signed or unsigned LEB 128 values case DW_FORM_sdata: case DW_FORM_udata: case DW_FORM_ref_udata: debug_info_data.Skip_LEB128(offset_ptr); return true; case DW_FORM_indirect: { dw_form_t indirect_form = debug_info_data.GetULEB128(offset_ptr); return DWARFFormValue::SkipValue (indirect_form, debug_info_data, offset_ptr, cu); } default: break; } return false; }
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; }
lldb::offset_t lldb_private::DumpDataExtractor( const DataExtractor &DE, Stream *s, offset_t start_offset, lldb::Format item_format, size_t item_byte_size, size_t item_count, size_t num_per_line, uint64_t base_addr, uint32_t item_bit_size, // If zero, this is not a bitfield value, if // non-zero, the value is a bitfield uint32_t item_bit_offset, // If "item_bit_size" is non-zero, this is the // shift amount to apply to a bitfield ExecutionContextScope *exe_scope) { if (s == nullptr) return start_offset; if (item_format == eFormatPointer) { if (item_byte_size != 4 && item_byte_size != 8) item_byte_size = s->GetAddressByteSize(); } offset_t offset = start_offset; if (item_format == eFormatInstruction) { TargetSP target_sp; if (exe_scope) target_sp = exe_scope->CalculateTarget(); if (target_sp) { DisassemblerSP disassembler_sp(Disassembler::FindPlugin( target_sp->GetArchitecture(), target_sp->GetDisassemblyFlavor(), nullptr)); if (disassembler_sp) { lldb::addr_t addr = base_addr + start_offset; lldb_private::Address so_addr; bool data_from_file = true; if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) { data_from_file = false; } else { if (target_sp->GetSectionLoadList().IsEmpty() || !target_sp->GetImages().ResolveFileAddress(addr, so_addr)) so_addr.SetRawAddress(addr); } size_t bytes_consumed = disassembler_sp->DecodeInstructions( so_addr, DE, start_offset, item_count, false, data_from_file); if (bytes_consumed) { offset += bytes_consumed; const bool show_address = base_addr != LLDB_INVALID_ADDRESS; const bool show_bytes = true; ExecutionContext exe_ctx; exe_scope->CalculateExecutionContext(exe_ctx); disassembler_sp->GetInstructionList().Dump(s, show_address, show_bytes, &exe_ctx); } } } else s->Printf("invalid target"); return offset; } if ((item_format == eFormatOSType || item_format == eFormatAddressInfo) && item_byte_size > 8) item_format = eFormatHex; lldb::offset_t line_start_offset = start_offset; for (uint32_t count = 0; DE.ValidOffset(offset) && count < item_count; ++count) { if ((count % num_per_line) == 0) { if (count > 0) { if (item_format == eFormatBytesWithASCII && offset > line_start_offset) { s->Printf("%*s", static_cast<int>( (num_per_line - (offset - line_start_offset)) * 3 + 2), ""); DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1, offset - line_start_offset, SIZE_MAX, LLDB_INVALID_ADDRESS, 0, 0); } s->EOL(); } if (base_addr != LLDB_INVALID_ADDRESS) s->Printf("0x%8.8" PRIx64 ": ", (uint64_t)(base_addr + (offset - start_offset) / DE.getTargetByteSize())); line_start_offset = offset; } else if (item_format != eFormatChar && item_format != eFormatCharPrintable && item_format != eFormatCharArray && count > 0) { s->PutChar(' '); } switch (item_format) { case eFormatBoolean: if (item_byte_size <= 8) s->Printf("%s", DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset) ? "true" : "false"); else { s->Printf("error: unsupported byte size (%" PRIu64 ") for boolean format", (uint64_t)item_byte_size); return offset; } break; case eFormatBinary: if (item_byte_size <= 8) { uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset); // Avoid std::bitset<64>::to_string() since it is missing in // earlier C++ libraries std::string binary_value(64, '0'); std::bitset<64> bits(uval64); for (uint32_t i = 0; i < 64; ++i) if (bits[i]) binary_value[64 - 1 - i] = '1'; if (item_bit_size > 0) s->Printf("0b%s", binary_value.c_str() + 64 - item_bit_size); else if (item_byte_size > 0 && item_byte_size <= 8) s->Printf("0b%s", binary_value.c_str() + 64 - item_byte_size * 8); } else { const bool is_signed = false; const unsigned radix = 2; offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix); } break; case eFormatBytes: case eFormatBytesWithASCII: for (uint32_t i = 0; i < item_byte_size; ++i) { s->Printf("%2.2x", DE.GetU8(&offset)); } // Put an extra space between the groups of bytes if more than one // is being dumped in a group (item_byte_size is more than 1). if (item_byte_size > 1) s->PutChar(' '); break; case eFormatChar: case eFormatCharPrintable: case eFormatCharArray: { // If we are only printing one character surround it with single // quotes if (item_count == 1 && item_format == eFormatChar) s->PutChar('\''); const uint64_t ch = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset); if (isprint(ch)) s->Printf("%c", (char)ch); else if (item_format != eFormatCharPrintable) { switch (ch) { case '\033': s->Printf("\\e"); break; case '\a': s->Printf("\\a"); break; case '\b': s->Printf("\\b"); break; case '\f': s->Printf("\\f"); break; case '\n': s->Printf("\\n"); break; case '\r': s->Printf("\\r"); break; case '\t': s->Printf("\\t"); break; case '\v': s->Printf("\\v"); break; case '\0': s->Printf("\\0"); break; default: if (item_byte_size == 1) s->Printf("\\x%2.2x", (uint8_t)ch); else s->Printf("%" PRIu64, ch); break; } } else { s->PutChar(NON_PRINTABLE_CHAR); } // If we are only printing one character surround it with single quotes if (item_count == 1 && item_format == eFormatChar) s->PutChar('\''); } break; case eFormatEnum: // Print enum value as a signed integer when we don't get // the enum type case eFormatDecimal: if (item_byte_size <= 8) s->Printf("%" PRId64, DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset)); else { const bool is_signed = true; const unsigned radix = 10; offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix); } break; case eFormatUnsigned: if (item_byte_size <= 8) s->Printf("%" PRIu64, DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset)); else { const bool is_signed = false; const unsigned radix = 10; offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix); } break; case eFormatOctal: if (item_byte_size <= 8) s->Printf("0%" PRIo64, DE.GetMaxS64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset)); else { const bool is_signed = false; const unsigned radix = 8; offset = DumpAPInt(s, DE, offset, item_byte_size, is_signed, radix); } break; case eFormatOSType: { uint64_t uval64 = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset); s->PutChar('\''); for (uint32_t i = 0; i < item_byte_size; ++i) { uint8_t ch = (uint8_t)(uval64 >> ((item_byte_size - i - 1) * 8)); if (isprint(ch)) s->Printf("%c", ch); else { switch (ch) { case '\033': s->Printf("\\e"); break; case '\a': s->Printf("\\a"); break; case '\b': s->Printf("\\b"); break; case '\f': s->Printf("\\f"); break; case '\n': s->Printf("\\n"); break; case '\r': s->Printf("\\r"); break; case '\t': s->Printf("\\t"); break; case '\v': s->Printf("\\v"); break; case '\0': s->Printf("\\0"); break; default: s->Printf("\\x%2.2x", ch); break; } } } s->PutChar('\''); } break; case eFormatCString: { const char *cstr = DE.GetCStr(&offset); if (!cstr) { s->Printf("NULL"); offset = LLDB_INVALID_OFFSET; } else { s->PutChar('\"'); while (const char c = *cstr) { if (isprint(c)) { s->PutChar(c); } else { switch (c) { case '\033': s->Printf("\\e"); break; case '\a': s->Printf("\\a"); break; case '\b': s->Printf("\\b"); break; case '\f': s->Printf("\\f"); break; case '\n': s->Printf("\\n"); break; case '\r': s->Printf("\\r"); break; case '\t': s->Printf("\\t"); break; case '\v': s->Printf("\\v"); break; default: s->Printf("\\x%2.2x", c); break; } } ++cstr; } s->PutChar('\"'); } } break; case eFormatPointer: s->Address(DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset), sizeof(addr_t)); break; case eFormatComplexInteger: { size_t complex_int_byte_size = item_byte_size / 2; if (complex_int_byte_size > 0 && complex_int_byte_size <= 8) { s->Printf("%" PRIu64, DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0)); s->Printf(" + %" PRIu64 "i", DE.GetMaxU64Bitfield(&offset, complex_int_byte_size, 0, 0)); } else { s->Printf("error: unsupported byte size (%" PRIu64 ") for complex integer format", (uint64_t)item_byte_size); return offset; } } break; case eFormatComplex: if (sizeof(float) * 2 == item_byte_size) { float f32_1 = DE.GetFloat(&offset); float f32_2 = DE.GetFloat(&offset); s->Printf("%g + %gi", f32_1, f32_2); break; } else if (sizeof(double) * 2 == item_byte_size) { double d64_1 = DE.GetDouble(&offset); double d64_2 = DE.GetDouble(&offset); s->Printf("%lg + %lgi", d64_1, d64_2); break; } else if (sizeof(long double) * 2 == item_byte_size) { long double ld64_1 = DE.GetLongDouble(&offset); long double ld64_2 = DE.GetLongDouble(&offset); s->Printf("%Lg + %Lgi", ld64_1, ld64_2); break; } else { s->Printf("error: unsupported byte size (%" PRIu64 ") for complex float format", (uint64_t)item_byte_size); return offset; } break; default: case eFormatDefault: case eFormatHex: case eFormatHexUppercase: { bool wantsuppercase = (item_format == eFormatHexUppercase); switch (item_byte_size) { case 1: case 2: case 4: case 8: s->Printf(wantsuppercase ? "0x%*.*" PRIX64 : "0x%*.*" PRIx64, (int)(2 * item_byte_size), (int)(2 * item_byte_size), DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset)); break; default: { assert(item_bit_size == 0 && item_bit_offset == 0); const uint8_t *bytes = (const uint8_t *)DE.GetData(&offset, item_byte_size); if (bytes) { s->PutCString("0x"); uint32_t idx; if (DE.GetByteOrder() == eByteOrderBig) { for (idx = 0; idx < item_byte_size; ++idx) s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[idx]); } else { for (idx = 0; idx < item_byte_size; ++idx) s->Printf(wantsuppercase ? "%2.2X" : "%2.2x", bytes[item_byte_size - 1 - idx]); } } } break; } } break; case eFormatFloat: { TargetSP target_sp; bool used_apfloat = false; if (exe_scope) target_sp = exe_scope->CalculateTarget(); if (target_sp) { ClangASTContext *clang_ast = target_sp->GetScratchClangASTContext(); if (clang_ast) { clang::ASTContext *ast = clang_ast->getASTContext(); if (ast) { llvm::SmallVector<char, 256> sv; // Show full precision when printing float values const unsigned format_precision = 0; const unsigned format_max_padding = 100; size_t item_bit_size = item_byte_size * 8; if (item_bit_size == ast->getTypeSize(ast->FloatTy)) { llvm::APInt apint(item_bit_size, DE.GetMaxU64(&offset, item_byte_size)); llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->FloatTy), apint); apfloat.toString(sv, format_precision, format_max_padding); } else if (item_bit_size == ast->getTypeSize(ast->DoubleTy)) { llvm::APInt apint; if (GetAPInt(DE, &offset, item_byte_size, apint)) { llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->DoubleTy), apint); apfloat.toString(sv, format_precision, format_max_padding); } } else if (item_bit_size == ast->getTypeSize(ast->LongDoubleTy)) { const auto &semantics = ast->getFloatTypeSemantics(ast->LongDoubleTy); const auto byte_size = (llvm::APFloat::getSizeInBits(semantics) + 7) / 8; llvm::APInt apint; if (GetAPInt(DE, &offset, byte_size, apint)) { llvm::APFloat apfloat(semantics, apint); apfloat.toString(sv, format_precision, format_max_padding); } } else if (item_bit_size == ast->getTypeSize(ast->HalfTy)) { llvm::APInt apint(item_bit_size, DE.GetU16(&offset)); llvm::APFloat apfloat(ast->getFloatTypeSemantics(ast->HalfTy), apint); apfloat.toString(sv, format_precision, format_max_padding); } if (!sv.empty()) { s->Printf("%*.*s", (int)sv.size(), (int)sv.size(), sv.data()); used_apfloat = true; } } } } if (!used_apfloat) { std::ostringstream ss; if (item_byte_size == sizeof(float) || item_byte_size == 2) { float f; if (item_byte_size == 2) { uint16_t half = DE.GetU16(&offset); f = half2float(half); } else { f = DE.GetFloat(&offset); } ss.precision(std::numeric_limits<float>::digits10); ss << f; } else if (item_byte_size == sizeof(double)) { ss.precision(std::numeric_limits<double>::digits10); ss << DE.GetDouble(&offset); } else if (item_byte_size == sizeof(long double) || item_byte_size == 10) { ss.precision(std::numeric_limits<long double>::digits10); ss << DE.GetLongDouble(&offset); } else { s->Printf("error: unsupported byte size (%" PRIu64 ") for float format", (uint64_t)item_byte_size); return offset; } ss.flush(); s->Printf("%s", ss.str().c_str()); } } break; case eFormatUnicode16: s->Printf("U+%4.4x", DE.GetU16(&offset)); break; case eFormatUnicode32: s->Printf("U+0x%8.8x", DE.GetU32(&offset)); break; case eFormatAddressInfo: { addr_t addr = DE.GetMaxU64Bitfield(&offset, item_byte_size, item_bit_size, item_bit_offset); s->Printf("0x%*.*" PRIx64, (int)(2 * item_byte_size), (int)(2 * item_byte_size), addr); if (exe_scope) { TargetSP target_sp(exe_scope->CalculateTarget()); lldb_private::Address so_addr; if (target_sp) { if (target_sp->GetSectionLoadList().ResolveLoadAddress(addr, so_addr)) { s->PutChar(' '); so_addr.Dump(s, exe_scope, Address::DumpStyleResolvedDescription, Address::DumpStyleModuleWithFileAddress); } else { so_addr.SetOffset(addr); so_addr.Dump(s, exe_scope, Address::DumpStyleResolvedPointerDescription); } } } } break; case eFormatHexFloat: if (sizeof(float) == item_byte_size) { char float_cstr[256]; llvm::APFloat ap_float(DE.GetFloat(&offset)); ap_float.convertToHexString(float_cstr, 0, false, llvm::APFloat::rmNearestTiesToEven); s->Printf("%s", float_cstr); break; } else if (sizeof(double) == item_byte_size) { char float_cstr[256]; llvm::APFloat ap_float(DE.GetDouble(&offset)); ap_float.convertToHexString(float_cstr, 0, false, llvm::APFloat::rmNearestTiesToEven); s->Printf("%s", float_cstr); break; } else { s->Printf("error: unsupported byte size (%" PRIu64 ") for hex float format", (uint64_t)item_byte_size); return offset; } break; // please keep the single-item formats below in sync with // FormatManager::GetSingleItemFormat // if you fail to do so, users will start getting different outputs // depending on internal // implementation details they should not care about || case eFormatVectorOfChar: // || s->PutChar('{'); // \/ offset = DumpDataExtractor(DE, s, offset, eFormatCharArray, 1, item_byte_size, item_byte_size, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfSInt8: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatDecimal, 1, item_byte_size, item_byte_size, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfUInt8: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatHex, 1, item_byte_size, item_byte_size, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfSInt16: s->PutChar('{'); offset = DumpDataExtractor( DE, s, offset, eFormatDecimal, sizeof(uint16_t), item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t), LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfUInt16: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint16_t), item_byte_size / sizeof(uint16_t), item_byte_size / sizeof(uint16_t), LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfSInt32: s->PutChar('{'); offset = DumpDataExtractor( DE, s, offset, eFormatDecimal, sizeof(uint32_t), item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t), LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfUInt32: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint32_t), item_byte_size / sizeof(uint32_t), item_byte_size / sizeof(uint32_t), LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfSInt64: s->PutChar('{'); offset = DumpDataExtractor( DE, s, offset, eFormatDecimal, sizeof(uint64_t), item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t), LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfUInt64: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatHex, sizeof(uint64_t), item_byte_size / sizeof(uint64_t), item_byte_size / sizeof(uint64_t), LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfFloat16: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatFloat, 2, item_byte_size / 2, item_byte_size / 2, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfFloat32: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatFloat, 4, item_byte_size / 4, item_byte_size / 4, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfFloat64: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatFloat, 8, item_byte_size / 8, item_byte_size / 8, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; case eFormatVectorOfUInt128: s->PutChar('{'); offset = DumpDataExtractor(DE, s, offset, eFormatHex, 16, item_byte_size / 16, item_byte_size / 16, LLDB_INVALID_ADDRESS, 0, 0); s->PutChar('}'); break; } } if (item_format == eFormatBytesWithASCII && offset > line_start_offset) { s->Printf("%*s", static_cast<int>( (num_per_line - (offset - line_start_offset)) * 3 + 2), ""); DumpDataExtractor(DE, s, line_start_offset, eFormatCharPrintable, 1, offset - line_start_offset, SIZE_MAX, LLDB_INVALID_ADDRESS, 0, 0); } return offset; // Return the offset at which we ended up }
bool DWARFDebugArangeSet::Extract(const DataExtractor &data, lldb::offset_t *offset_ptr) { if (data.ValidOffset(*offset_ptr)) { m_arange_descriptors.clear(); m_offset = *offset_ptr; // 7.20 Address Range Table // // Each set of entries in the table of address ranges contained in // the .debug_aranges section begins with a header consisting of: a // 4-byte length containing the length of the set of entries for this // compilation unit, not including the length field itself; a 2-byte // version identifier containing the value 2 for DWARF Version 2; a // 4-byte offset into the.debug_infosection; a 1-byte unsigned integer // containing the size in bytes of an address (or the offset portion of // an address for segmented addressing) on the target system; and a // 1-byte unsigned integer containing the size in bytes of a segment // descriptor on the target system. This header is followed by a series // of tuples. Each tuple consists of an address and a length, each in // the size appropriate for an address on the target architecture. m_header.length = data.GetU32(offset_ptr); m_header.version = data.GetU16(offset_ptr); m_header.cu_offset = data.GetU32(offset_ptr); m_header.addr_size = data.GetU8(offset_ptr); m_header.seg_size = data.GetU8(offset_ptr); // The first tuple following the header in each set begins at an offset // that is a multiple of the size of a single tuple (that is, twice the // size of an address). The header is padded, if necessary, to the // appropriate boundary. const uint32_t header_size = *offset_ptr - m_offset; const uint32_t tuple_size = m_header.addr_size << 1; uint32_t first_tuple_offset = 0; while (first_tuple_offset < header_size) first_tuple_offset += tuple_size; *offset_ptr = m_offset + first_tuple_offset; Descriptor arangeDescriptor; assert(sizeof(arangeDescriptor.address) == sizeof(arangeDescriptor.length)); assert(sizeof(arangeDescriptor.address) >= m_header.addr_size); while (data.ValidOffset(*offset_ptr)) { arangeDescriptor.address = data.GetMaxU64(offset_ptr, m_header.addr_size); arangeDescriptor.length = data.GetMaxU64(offset_ptr, m_header.addr_size); // Each set of tuples is terminated by a 0 for the address and 0 // for the length. if (arangeDescriptor.address || arangeDescriptor.length) m_arange_descriptors.push_back(arangeDescriptor); else break; // We are done if we get a zero address and length } return !m_arange_descriptors.empty(); } return false; }
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); } } }
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 DWARFFormValue::ExtractValue(const DataExtractor& data, lldb::offset_t* offset_ptr, const DWARFCompileUnit* cu) { bool indirect = false; bool is_block = false; m_value.data = NULL; // Read the value for the form into value and follow and DW_FORM_indirect instances we run into do { indirect = false; switch (m_form) { case DW_FORM_addr: m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu)); break; case DW_FORM_block2: m_value.value.uval = data.GetU16(offset_ptr); is_block = true; break; case DW_FORM_block4: m_value.value.uval = data.GetU32(offset_ptr); is_block = true; break; case DW_FORM_data2: m_value.value.uval = data.GetU16(offset_ptr); break; case DW_FORM_data4: m_value.value.uval = data.GetU32(offset_ptr); break; case DW_FORM_data8: m_value.value.uval = data.GetU64(offset_ptr); break; case DW_FORM_string: m_value.value.cstr = data.GetCStr(offset_ptr); // Set the string value to also be the data for inlined cstr form values only // so we can tell the differnence between DW_FORM_string and DW_FORM_strp form // values; m_value.data = (uint8_t*)m_value.value.cstr; break; case DW_FORM_exprloc: case DW_FORM_block: m_value.value.uval = data.GetULEB128(offset_ptr); is_block = true; break; case DW_FORM_block1: m_value.value.uval = data.GetU8(offset_ptr); is_block = true; break; case DW_FORM_data1: m_value.value.uval = data.GetU8(offset_ptr); break; case DW_FORM_flag: m_value.value.uval = data.GetU8(offset_ptr); break; case DW_FORM_sdata: m_value.value.sval = data.GetSLEB128(offset_ptr); break; case DW_FORM_strp: m_value.value.uval = data.GetU32(offset_ptr); break; // case DW_FORM_APPLE_db_str: case DW_FORM_udata: m_value.value.uval = data.GetULEB128(offset_ptr); break; case DW_FORM_ref_addr: if (cu->GetVersion() <= 2) m_value.value.uval = data.GetMaxU64(offset_ptr, DWARFCompileUnit::GetAddressByteSize(cu)); else m_value.value.uval = data.GetU32(offset_ptr); // 4 for DWARF32, 8 for DWARF64, but we don't support DWARF64 yet break; case DW_FORM_ref1: m_value.value.uval = data.GetU8(offset_ptr); break; case DW_FORM_ref2: m_value.value.uval = data.GetU16(offset_ptr); break; case DW_FORM_ref4: m_value.value.uval = data.GetU32(offset_ptr); break; case DW_FORM_ref8: m_value.value.uval = data.GetU64(offset_ptr); break; case DW_FORM_ref_udata: m_value.value.uval = data.GetULEB128(offset_ptr); break; case DW_FORM_indirect: m_form = data.GetULEB128(offset_ptr); indirect = true; break; case DW_FORM_sec_offset: m_value.value.uval = data.GetU32(offset_ptr); break; case DW_FORM_flag_present: m_value.value.uval = 1; break; case DW_FORM_ref_sig8: m_value.value.uval = data.GetU64(offset_ptr); break; default: return false; break; } } while (indirect); if (is_block) { m_value.data = data.PeekData(*offset_ptr, m_value.value.uval); if (m_value.data != NULL) { *offset_ptr += m_value.value.uval; } } return true; }