//---------------------------------------------------------------------- // Get the section data the file on disk //---------------------------------------------------------------------- size_t ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data) const { if (IsInMemory()) { ProcessSP process_sp (m_process_wp.lock()); if (process_sp) { DataBufferSP data_sp (ReadMemory (process_sp, section->GetLoadBaseAddress (&process_sp->GetTarget()), section->GetByteSize())); if (data_sp) { section_data.SetData (data_sp, 0, data_sp->GetByteSize()); section_data.SetByteOrder (process_sp->GetByteOrder()); section_data.SetAddressByteSize (process_sp->GetAddressByteSize()); return section_data.GetByteSize(); } } } else { // The object file now contains a full mmap'ed copy of the object file data, so just use this return MemoryMapSectionData (section, section_data); } section_data.Clear(); return 0; }
uint32_t Opcode::GetData(DataExtractor &data) const { uint32_t byte_size = GetByteSize(); uint8_t swap_buf[8]; const void *buf = nullptr; if (byte_size > 0) { if (!GetEndianSwap()) { if (m_type == Opcode::eType16_2) { // 32 bit thumb instruction, we need to sizzle this a bit swap_buf[0] = m_data.inst.bytes[2]; swap_buf[1] = m_data.inst.bytes[3]; swap_buf[2] = m_data.inst.bytes[0]; swap_buf[3] = m_data.inst.bytes[1]; buf = swap_buf; } else { buf = GetOpcodeDataBytes(); } } else { switch (m_type) { case Opcode::eTypeInvalid: break; case Opcode::eType8: buf = GetOpcodeDataBytes(); break; case Opcode::eType16: *(uint16_t *)swap_buf = llvm::ByteSwap_16(m_data.inst16); buf = swap_buf; break; case Opcode::eType16_2: swap_buf[0] = m_data.inst.bytes[1]; swap_buf[1] = m_data.inst.bytes[0]; swap_buf[2] = m_data.inst.bytes[3]; swap_buf[3] = m_data.inst.bytes[2]; buf = swap_buf; break; case Opcode::eType32: *(uint32_t *)swap_buf = llvm::ByteSwap_32(m_data.inst32); buf = swap_buf; break; case Opcode::eType64: *(uint32_t *)swap_buf = llvm::ByteSwap_64(m_data.inst64); buf = swap_buf; break; case Opcode::eTypeBytes: buf = GetOpcodeDataBytes(); break; } } } if (buf != nullptr) { DataBufferSP buffer_sp; buffer_sp.reset(new DataBufferHeap(buf, byte_size)); data.SetByteOrder(GetDataByteOrder()); data.SetData(buffer_sp); return byte_size; } data.Clear(); return 0; }
bool Value::GetData (DataExtractor &data) { switch (m_value_type) { default: break; case eValueTypeScalar: if (m_value.GetData (data)) return true; break; case eValueTypeLoadAddress: case eValueTypeFileAddress: case eValueTypeHostAddress: if (m_data_buffer.GetByteSize()) { data.SetData(m_data_buffer.GetBytes(), m_data_buffer.GetByteSize(), data.GetByteOrder()); return true; } break; } return false; }
size_t ObjectFile::GetData (off_t offset, size_t length, DataExtractor &data) const { // The entire file has already been mmap'ed into m_data, so just copy from there // as the back mmap buffer will be shared with shared pointers. return data.SetData (m_data, offset, length); }
//---------------------------------------------------------------------- // Get the section data the file on disk //---------------------------------------------------------------------- size_t ObjectFile::ReadSectionData (const Section *section, DataExtractor& section_data) const { // If some other objectfile owns this data, pass this to them. if (section->GetObjectFile() != this) return section->GetObjectFile()->ReadSectionData (section, section_data); if (IsInMemory()) { ProcessSP process_sp (m_process_wp.lock()); if (process_sp) { const addr_t base_load_addr = section->GetLoadBaseAddress (&process_sp->GetTarget()); if (base_load_addr != LLDB_INVALID_ADDRESS) { DataBufferSP data_sp (ReadMemory (process_sp, base_load_addr, section->GetByteSize())); if (data_sp) { section_data.SetData (data_sp, 0, data_sp->GetByteSize()); section_data.SetByteOrder (process_sp->GetByteOrder()); section_data.SetAddressByteSize (process_sp->GetAddressByteSize()); return section_data.GetByteSize(); } } } } else { // The object file now contains a full mmap'ed copy of the object file data, so just use this return MemoryMapSectionData (section, section_data); } section_data.Clear(); return 0; }
bool Type::ReadFromMemory(ExecutionContext *exe_ctx, lldb::addr_t addr, AddressType address_type, DataExtractor &data) { if (address_type == eAddressTypeFile) { // Can't convert a file address to anything valid without more // context (which Module it came from) return false; } const uint64_t byte_size = GetByteSize(); if (data.GetByteSize() < byte_size) { lldb::DataBufferSP data_sp(new DataBufferHeap(byte_size, '\0')); data.SetData(data_sp); } uint8_t *dst = const_cast<uint8_t *>(data.PeekData(0, byte_size)); if (dst != nullptr) { if (address_type == eAddressTypeHost) { // The address is an address in this process, so just copy it if (addr == 0) return false; memcpy(dst, (uint8_t *)nullptr + addr, byte_size); return true; } else { if (exe_ctx) { Process *process = exe_ctx->GetProcessPtr(); if (process) { Error error; return exe_ctx->GetProcessPtr()->ReadMemory(addr, dst, byte_size, error) == byte_size; } } } } return false; }
void EventDataBytes::Dump(Stream *s) const { size_t num_printable_chars = std::count_if(m_bytes.begin(), m_bytes.end(), isprint); if (num_printable_chars == m_bytes.size()) { s->Printf("\"%s\"", m_bytes.c_str()); } else if (!m_bytes.empty()) { DataExtractor data; data.SetData(m_bytes.data(), m_bytes.size(), endian::InlHostByteOrder()); data.Dump(s, 0, eFormatBytes, 1, m_bytes.size(), 32, LLDB_INVALID_ADDRESS, 0, 0); } }
//---------------------------------------------------------------------- // Get the section data from a complete contiguous copy of the // entire executable image. //---------------------------------------------------------------------- size_t Section::GetSectionDataFromImage (const DataExtractor& image_data, DataExtractor& section_data) const { size_t file_size = GetByteSize(); if (file_size > 0) { off_t file_offset = GetFileOffset(); if (section_data.SetData (image_data, file_offset, file_size) == file_size) return true; } return false; }
uint32_t Opcode::GetData (DataExtractor &data, lldb::AddressClass address_class) const { uint32_t byte_size = GetByteSize (); DataBufferSP buffer_sp; if (byte_size > 0) { switch (m_type) { case Opcode::eTypeInvalid: break; case Opcode::eType8: buffer_sp.reset (new DataBufferHeap (&m_data.inst8, byte_size)); break; case Opcode::eType16: buffer_sp.reset (new DataBufferHeap (&m_data.inst16, byte_size)); break; case Opcode::eType32: { // The only thing that uses eAddressClassCodeAlternateISA currently // is Thumb. If this ever changes, we will need to pass in more // information like an additional "const ArchSpec &arch". For now // this will do if (address_class == eAddressClassCodeAlternateISA) { // 32 bit thumb instruction, we need to sizzle this a bit uint8_t buf[4]; buf[0] = m_data.inst.bytes[2]; buf[1] = m_data.inst.bytes[3]; buf[2] = m_data.inst.bytes[0]; buf[3] = m_data.inst.bytes[1]; buffer_sp.reset (new DataBufferHeap (buf, byte_size)); break; } buffer_sp.reset (new DataBufferHeap (&m_data.inst32, byte_size)); } break; case Opcode::eType64: buffer_sp.reset (new DataBufferHeap (&m_data.inst64, byte_size)); break; case Opcode::eTypeBytes:buffer_sp.reset (new DataBufferHeap (GetOpcodeBytes(), byte_size)); break; break; } } if (buffer_sp) { data.SetByteOrder(GetDataByteOrder()); data.SetData (buffer_sp); return byte_size; } data.Clear(); return 0; }
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; }
bool RegisterContextMacOSXFrameBackchain::ReadRegisterBytes (uint32_t reg, DataExtractor &data) { Scalar reg_value; if (ReadRegisterValue (reg, reg_value)) { if (reg_value.GetData(data)) { // "reg_value" is local and now "data" points to the data within // "reg_value", so we must make a copy that will live within "data" DataBufferSP data_sp (new DataBufferHeap (data.GetDataStart(), data.GetByteSize())); data.SetData (data_sp, 0, data.GetByteSize()); return true; } } return false; }
ObjectContainer *ObjectContainerUniversalMachO::CreateInstance( const lldb::ModuleSP &module_sp, DataBufferSP &data_sp, lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length) { // We get data when we aren't trying to look for cached container information, // so only try and look for an architecture slice if we get data if (data_sp) { DataExtractor data; data.SetData(data_sp, data_offset, length); if (ObjectContainerUniversalMachO::MagicBytesMatch(data)) { std::unique_ptr<ObjectContainerUniversalMachO> container_ap( new ObjectContainerUniversalMachO(module_sp, data_sp, data_offset, file, file_offset, length)); if (container_ap->ParseHeader()) { return container_ap.release(); } } } return NULL; }
size_t Disassembler::ParseInstructions ( const ExecutionContext *exe_ctx, const AddressRange &range, DataExtractor& data ) { Target *target = exe_ctx->target; const addr_t byte_size = range.GetByteSize(); if (target == NULL || byte_size == 0 || !range.GetBaseAddress().IsValid()) return 0; DataBufferHeap *heap_buffer = new DataBufferHeap (byte_size, '\0'); DataBufferSP data_sp(heap_buffer); Error error; const size_t bytes_read = target->ReadMemory (range.GetBaseAddress(), heap_buffer->GetBytes(), heap_buffer->GetByteSize(), error); if (bytes_read > 0) { if (bytes_read != heap_buffer->GetByteSize()) heap_buffer->SetByteSize (bytes_read); data.SetData(data_sp); if (exe_ctx->process) { data.SetByteOrder(exe_ctx->process->GetByteOrder()); data.SetAddressByteSize(exe_ctx->process->GetAddressByteSize()); } else { data.SetByteOrder(target->GetArchitecture().GetDefaultEndian()); data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); } return DecodeInstructions (data, 0, UINT32_MAX); } return 0; }
size_t Section::MemoryMapSectionDataFromObjectFile(const ObjectFile* objfile, DataExtractor& section_data) const { if (objfile == NULL) return 0; const FileSpec& file = objfile->GetFileSpec(); if (file) { size_t section_file_size = GetFileSize(); if (section_file_size > 0) { off_t section_file_offset = GetFileOffset() + objfile->GetOffset(); DataBufferSP section_data_sp(file.MemoryMapFileContents(section_file_offset, section_file_size)); section_data.SetByteOrder(objfile->GetByteOrder()); section_data.SetAddressByteSize(objfile->GetAddressByteSize()); return section_data.SetData (section_data_sp); } } return 0; }
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; }
DataExtractor ObjectFilePECOFF::ReadImageData(uint32_t offset, size_t size) { if (m_file) { // A bit of a hack, but we intend to write to this buffer, so we can't // mmap it. auto buffer_sp = DataBufferLLVM::CreateSliceFromPath(m_file.GetPath(), size, offset, true); return DataExtractor(buffer_sp, GetByteOrder(), GetAddressByteSize()); } ProcessSP process_sp(m_process_wp.lock()); DataExtractor data; if (process_sp) { auto data_ap = llvm::make_unique<DataBufferHeap>(size, 0); Status readmem_error; size_t bytes_read = process_sp->ReadMemory(m_image_base + offset, data_ap->GetBytes(), data_ap->GetByteSize(), readmem_error); if (bytes_read == size) { DataBufferSP buffer_sp(data_ap.release()); data.SetData(buffer_sp, 0, buffer_sp->GetByteSize()); } } return data; }
ObjectContainer * ObjectContainerBSDArchive::CreateInstance ( const lldb::ModuleSP &module_sp, DataBufferSP& data_sp, const FileSpec *file, addr_t offset, addr_t length) { DataExtractor data; data.SetData (data_sp, offset, length); if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data)) { Timer scoped_timer (__PRETTY_FUNCTION__, "ObjectContainerBSDArchive::CreateInstance (module = %s/%s, file = %p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")", module_sp->GetFileSpec().GetDirectory().AsCString(), module_sp->GetFileSpec().GetFilename().AsCString(), file, (uint64_t) offset, (uint64_t) length); Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file, module_sp->GetArchitecture(), module_sp->GetModificationTime())); std::auto_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module_sp, data_sp, file, offset, length)); if (container_ap.get()) { if (archive_sp) { // We already have this archive in our cache, use it container_ap->SetArchive (archive_sp); return container_ap.release(); } else if (container_ap->ParseHeader()) return container_ap.release(); } } return NULL; }
size_t ObjectContainerUniversalMachO::GetModuleSpecifications( const lldb_private::FileSpec &file, lldb::DataBufferSP &data_sp, lldb::offset_t data_offset, lldb::offset_t file_offset, lldb::offset_t file_size, lldb_private::ModuleSpecList &specs) { const size_t initial_count = specs.GetSize(); DataExtractor data; data.SetData(data_sp, data_offset, data_sp->GetByteSize()); if (ObjectContainerUniversalMachO::MagicBytesMatch(data)) { llvm::MachO::fat_header header; std::vector<llvm::MachO::fat_arch> fat_archs; if (ParseHeader(data, header, fat_archs)) { for (const llvm::MachO::fat_arch &fat_arch : fat_archs) { const lldb::offset_t slice_file_offset = fat_arch.offset + file_offset; if (fat_arch.offset < file_size && file_size > slice_file_offset) { ObjectFile::GetModuleSpecifications( file, slice_file_offset, file_size - slice_file_offset, specs); } } } } return specs.GetSize() - initial_count; }
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; }
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; }
ObjectContainer * ObjectContainerBSDArchive::CreateInstance ( const lldb::ModuleSP &module_sp, DataBufferSP& data_sp, lldb::offset_t data_offset, const FileSpec *file, lldb::offset_t file_offset, lldb::offset_t length) { ConstString object_name (module_sp->GetObjectName()); if (object_name) { if (data_sp) { // We have data, which means this is the first 512 bytes of the file // Check to see if the magic bytes match and if they do, read the entire // table of contents for the archive and cache it DataExtractor data; data.SetData (data_sp, data_offset, length); if (file && data_sp && ObjectContainerBSDArchive::MagicBytesMatch(data)) { Timer scoped_timer (__PRETTY_FUNCTION__, "ObjectContainerBSDArchive::CreateInstance (module = %s, file = %p, file_offset = 0x%8.8" PRIx64 ", file_size = 0x%8.8" PRIx64 ")", module_sp->GetFileSpec().GetPath().c_str(), file, (uint64_t) file_offset, (uint64_t) length); // Map the entire .a file to be sure that we don't lose any data if the file // gets updated by a new build while this .a file is being used for debugging DataBufferSP archive_data_sp (file->MemoryMapFileContents(file_offset, length)); lldb::offset_t archive_data_offset = 0; Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file, module_sp->GetArchitecture(), module_sp->GetModificationTime(), file_offset)); std::unique_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module_sp, archive_data_sp, archive_data_offset, file, file_offset, length)); if (container_ap.get()) { if (archive_sp) { // We already have this archive in our cache, use it container_ap->SetArchive (archive_sp); return container_ap.release(); } else if (container_ap->ParseHeader()) return container_ap.release(); } } } else { // No data, just check for a cached archive Archive::shared_ptr archive_sp (Archive::FindCachedArchive (*file, module_sp->GetArchitecture(), module_sp->GetModificationTime(), file_offset)); if (archive_sp) { std::unique_ptr<ObjectContainerBSDArchive> container_ap(new ObjectContainerBSDArchive (module_sp, data_sp, data_offset, file, file_offset, length)); if (container_ap.get()) { // We already have this archive in our cache, use it container_ap->SetArchive (archive_sp); return container_ap.release(); } } } } return NULL; }
bool RegisterContextMach_i386::ReadRegisterBytes (uint32_t reg, DataExtractor &data) { int set = RegisterContextMach_i386::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) return false; 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: data.SetData(&gpr.eax + reg - gpr_eax, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case fpu_fcw: data.SetData(&fpu.fcw, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case fpu_fsw: data.SetData(&fpu.fsw, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case fpu_ftw: data.SetData(&fpu.ftw, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case fpu_fop: data.SetData(&fpu.fop, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case fpu_ip: data.SetData(&fpu.ip, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case fpu_cs: data.SetData(&fpu.cs, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case fpu_dp: data.SetData(&fpu.dp, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case fpu_ds: data.SetData(&fpu.ds, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case fpu_mxcsr: data.SetData(&fpu.mxcsr, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case fpu_mxcsrmask: data.SetData(&fpu.mxcsrmask, reg_info->byte_size, lldb::endian::InlHostByteOrder()); 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: data.SetData(fpu.stmm[reg - fpu_stmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case fpu_xmm0: case fpu_xmm1: case fpu_xmm2: case fpu_xmm3: case fpu_xmm4: case fpu_xmm5: case fpu_xmm6: case fpu_xmm7: data.SetData(fpu.xmm[reg - fpu_xmm0].bytes, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case exc_trapno: data.SetData(&exc.trapno, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case exc_err: data.SetData(&exc.err, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; case exc_faultvaddr: data.SetData(&exc.faultvaddr, reg_info->byte_size, lldb::endian::InlHostByteOrder()); break; default: return false; } return true; }
bool RegisterValue::GetData (DataExtractor &data) const { return data.SetData(GetBytes(), GetByteSize(), GetByteOrder()) > 0; }
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; } }
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; }
Error Value::GetValueAsData (ExecutionContext *exe_ctx, clang::ASTContext *ast_context, DataExtractor &data, uint32_t data_offset, Module *module) { data.Clear(); Error error; lldb::addr_t address = LLDB_INVALID_ADDRESS; AddressType address_type = eAddressTypeFile; Address file_so_addr; switch (m_value_type) { default: error.SetErrorStringWithFormat("invalid value type %i", m_value_type); break; case eValueTypeScalar: data.SetByteOrder (lldb::endian::InlHostByteOrder()); if (m_context_type == eContextTypeClangType && ast_context) { uint32_t ptr_bit_width = ClangASTType::GetClangTypeBitWidth (ast_context, ClangASTContext::GetVoidPtrType(ast_context, false)); uint32_t ptr_byte_size = (ptr_bit_width + 7) / 8; data.SetAddressByteSize (ptr_byte_size); } else data.SetAddressByteSize(sizeof(void *)); if (m_value.GetData (data)) return error; // Success; error.SetErrorStringWithFormat("extracting data from value failed"); break; case eValueTypeLoadAddress: if (exe_ctx == NULL) { error.SetErrorString ("can't read load address (no execution context)"); } else { Process *process = exe_ctx->GetProcessPtr(); if (process == NULL) { error.SetErrorString ("can't read load address (invalid process)"); } else { address = m_value.ULongLong(LLDB_INVALID_ADDRESS); address_type = eAddressTypeLoad; data.SetByteOrder(process->GetTarget().GetArchitecture().GetByteOrder()); data.SetAddressByteSize(process->GetTarget().GetArchitecture().GetAddressByteSize()); } } break; case eValueTypeFileAddress: if (exe_ctx == NULL) { error.SetErrorString ("can't read file address (no execution context)"); } else if (exe_ctx->GetTargetPtr() == NULL) { error.SetErrorString ("can't read file address (invalid target)"); } else { address = m_value.ULongLong(LLDB_INVALID_ADDRESS); if (address == LLDB_INVALID_ADDRESS) { error.SetErrorString ("invalid file address"); } else { if (module == NULL) { // The only thing we can currently lock down to a module so that // we can resolve a file address, is a variable. Variable *variable = GetVariable(); if (variable) { SymbolContext var_sc; variable->CalculateSymbolContext(&var_sc); module = var_sc.module_sp.get(); } } if (module) { bool resolved = false; ObjectFile *objfile = module->GetObjectFile(); if (objfile) { Address so_addr(address, objfile->GetSectionList()); addr_t load_address = so_addr.GetLoadAddress (exe_ctx->GetTargetPtr()); bool process_launched_and_stopped = exe_ctx->GetProcessPtr() ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(), true /* must_exist */) : false; // Don't use the load address if the process has exited. if (load_address != LLDB_INVALID_ADDRESS && process_launched_and_stopped) { resolved = true; address = load_address; address_type = eAddressTypeLoad; data.SetByteOrder(exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder()); data.SetAddressByteSize(exe_ctx->GetTargetRef().GetArchitecture().GetAddressByteSize()); } else { if (so_addr.IsSectionOffset()) { resolved = true; file_so_addr = so_addr; data.SetByteOrder(objfile->GetByteOrder()); data.SetAddressByteSize(objfile->GetAddressByteSize()); } } } if (!resolved) { Variable *variable = GetVariable(); if (module) { if (variable) error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s' in %s%s%s", address, variable->GetName().AsCString(""), module->GetFileSpec().GetDirectory().GetCString(), module->GetFileSpec().GetDirectory() ? "/" : "", module->GetFileSpec().GetFilename().GetCString()); else error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx in %s%s%s", address, module->GetFileSpec().GetDirectory().GetCString(), module->GetFileSpec().GetDirectory() ? "/" : "", module->GetFileSpec().GetFilename().GetCString()); } else { if (variable) error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx for variable '%s'", address, variable->GetName().AsCString("")); else error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%llx", address); } } } else { // Can't convert a file address to anything valid without more // context (which Module it came from) error.SetErrorString ("can't read memory from file address without more context"); } } } break; case eValueTypeHostAddress: address = m_value.ULongLong(LLDB_INVALID_ADDRESS); address_type = eAddressTypeHost; if (exe_ctx) { Target *target = exe_ctx->GetTargetPtr(); if (target) { data.SetByteOrder(target->GetArchitecture().GetByteOrder()); data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); break; } } // fallback to host settings data.SetByteOrder(lldb::endian::InlHostByteOrder()); data.SetAddressByteSize(sizeof(void *)); break; } // Bail if we encountered any errors if (error.Fail()) return error; if (address == LLDB_INVALID_ADDRESS) { error.SetErrorStringWithFormat ("invalid %s address", address_type == eAddressTypeHost ? "host" : "load"); return error; } // If we got here, we need to read the value from memory uint32_t byte_size = GetValueByteSize (ast_context, &error); // Bail if we encountered any errors getting the byte size if (error.Fail()) return error; // Make sure we have enough room within "data", and if we don't make // something large enough that does if (!data.ValidOffsetForDataOfSize (data_offset, byte_size)) { DataBufferSP data_sp(new DataBufferHeap (data_offset + byte_size, '\0')); data.SetData(data_sp); } uint8_t* dst = const_cast<uint8_t*>(data.PeekData (data_offset, byte_size)); if (dst != NULL) { if (address_type == eAddressTypeHost) { // The address is an address in this process, so just copy it memcpy (dst, (uint8_t*)NULL + address, byte_size); } else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile)) { if (file_so_addr.IsValid()) { // We have a file address that we were able to translate into a // section offset address so we might be able to read this from // the object files if we don't have a live process. Lets always // try and read from the process if we have one though since we // want to read the actual value by setting "prefer_file_cache" // to false. const bool prefer_file_cache = false; if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, prefer_file_cache, dst, byte_size, error) != byte_size) { error.SetErrorStringWithFormat("read memory from 0x%llx failed", (uint64_t)address); } } else { // The execution context might have a NULL process, but it // might have a valid process in the exe_ctx->target, so use // the ExecutionContext::GetProcess accessor to ensure we // get the process if there is one. Process *process = exe_ctx->GetProcessPtr(); if (process) { const size_t bytes_read = process->ReadMemory(address, dst, byte_size, error); if (bytes_read != byte_size) error.SetErrorStringWithFormat("read memory from 0x%llx failed (%u of %u bytes read)", (uint64_t)address, (uint32_t)bytes_read, (uint32_t)byte_size); } else { error.SetErrorStringWithFormat("read memory from 0x%llx failed (invalid process)", (uint64_t)address); } } } else { error.SetErrorStringWithFormat ("unsupported AddressType value (%i)", address_type); } } else { error.SetErrorStringWithFormat ("out of memory"); } return error; }
bool TypeFormatImpl_Format::FormatObject (ValueObject *valobj, std::string& dest) const { if (!valobj) return false; if (valobj->CanProvideValue()) { Value& value(valobj->GetValue()); const Value::ContextType context_type = value.GetContextType(); ExecutionContext exe_ctx (valobj->GetExecutionContextRef()); DataExtractor data; if (context_type == Value::eContextTypeRegisterInfo) { const RegisterInfo *reg_info = value.GetRegisterInfo(); if (reg_info) { Error error; valobj->GetData(data, error); if (error.Fail()) return false; StreamString reg_sstr; data.Dump (®_sstr, 0, GetFormat(), reg_info->byte_size, 1, UINT32_MAX, LLDB_INVALID_ADDRESS, 0, 0, exe_ctx.GetBestExecutionContextScope()); dest.swap(reg_sstr.GetString()); } } else { CompilerType compiler_type = value.GetCompilerType (); if (compiler_type) { // put custom bytes to display in the DataExtractor to override the default value logic if (GetFormat() == eFormatCString) { lldb_private::Flags type_flags(compiler_type.GetTypeInfo(NULL)); // disambiguate w.r.t. TypeFormatImpl::Flags if (type_flags.Test(eTypeIsPointer) && !type_flags.Test(eTypeIsObjC)) { // if we are dumping a pointer as a c-string, get the pointee data as a string TargetSP target_sp(valobj->GetTargetSP()); if (target_sp) { size_t max_len = target_sp->GetMaximumSizeOfStringSummary(); Error error; DataBufferSP buffer_sp(new DataBufferHeap(max_len+1,0)); Address address(valobj->GetPointerValue()); if (target_sp->ReadCStringFromMemory(address, (char*)buffer_sp->GetBytes(), max_len, error) && error.Success()) data.SetData(buffer_sp); } } } else { Error error; valobj->GetData(data, error); if (error.Fail()) return false; } StreamString sstr; compiler_type.DumpTypeValue (&sstr, // The stream to use for display GetFormat(), // Format to display this type with data, // Data to extract from 0, // Byte offset into "m_data" valobj->GetByteSize(), // Byte size of item in "m_data" valobj->GetBitfieldBitSize(), // Bitfield bit size valobj->GetBitfieldBitOffset(), // Bitfield bit offset exe_ctx.GetBestExecutionContextScope()); // Given that we do not want to set the ValueObject's m_error // for a formatting error (or else we wouldn't be able to reformat // until a next update), an empty string is treated as a "false" // return from here, but that's about as severe as we get // CompilerType::DumpTypeValue() should always return // something, even if that something is an error message if (sstr.GetString().empty()) dest.clear(); else dest.swap(sstr.GetString()); } } return !dest.empty(); } else return false; }
const char * ValueObject::GetSummaryAsCString (ExecutionContextScope *exe_scope) { if (UpdateValueIfNeeded (exe_scope)) { if (m_summary_str.empty()) { void *clang_type = GetOpaqueClangQualType(); // See if this is a pointer to a C string? uint32_t fixed_length = 0; if (clang_type && ClangASTContext::IsCStringType (clang_type, fixed_length)) { Process *process = exe_scope->CalculateProcess(); if (process != NULL) { StreamString sstr; lldb::addr_t cstr_address = LLDB_INVALID_ADDRESS; lldb::AddressType cstr_address_type = eAddressTypeInvalid; switch (GetValue().GetValueType()) { case Value::eValueTypeScalar: cstr_address = m_value.GetScalar().ULongLong(LLDB_INVALID_ADDRESS); cstr_address_type = eAddressTypeLoad; break; case Value::eValueTypeLoadAddress: case Value::eValueTypeFileAddress: case Value::eValueTypeHostAddress: { uint32_t data_offset = 0; cstr_address = m_data.GetPointer(&data_offset); cstr_address_type = m_value.GetValueAddressType(); if (cstr_address_type == eAddressTypeInvalid) cstr_address_type = eAddressTypeLoad; } break; } if (cstr_address != LLDB_INVALID_ADDRESS) { DataExtractor data; size_t bytes_read = 0; std::vector<char> data_buffer; std::vector<char> cstr_buffer; size_t cstr_length; Error error; if (fixed_length > 0) { data_buffer.resize(fixed_length); // Resize the formatted buffer in case every character // uses the "\xXX" format and one extra byte for a NULL cstr_buffer.resize(data_buffer.size() * 4 + 1); data.SetData (data_buffer.data(), data_buffer.size(), eByteOrderHost); bytes_read = process->ReadMemory (cstr_address, data_buffer.data(), fixed_length, error); if (bytes_read > 0) { sstr << '"'; cstr_length = data.Dump (&sstr, 0, // Start offset in "data" eFormatChar, // Print as characters 1, // Size of item (1 byte for a char!) bytes_read, // How many bytes to print? UINT32_MAX, // num per line LLDB_INVALID_ADDRESS,// base address 0, // bitfield bit size 0); // bitfield bit offset sstr << '"'; } } else { const size_t k_max_buf_size = 256; data_buffer.resize (k_max_buf_size + 1); // NULL terminate in case we don't get the entire C string data_buffer.back() = '\0'; // Make a formatted buffer that can contain take 4 // bytes per character in case each byte uses the // "\xXX" format and one extra byte for a NULL cstr_buffer.resize (k_max_buf_size * 4 + 1); data.SetData (data_buffer.data(), data_buffer.size(), eByteOrderHost); size_t total_cstr_len = 0; while ((bytes_read = process->ReadMemory (cstr_address, data_buffer.data(), k_max_buf_size, error)) > 0) { size_t len = strlen(data_buffer.data()); if (len == 0) break; if (len > bytes_read) len = bytes_read; if (sstr.GetSize() == 0) sstr << '"'; cstr_length = data.Dump (&sstr, 0, // Start offset in "data" eFormatChar, // Print as characters 1, // Size of item (1 byte for a char!) len, // How many bytes to print? UINT32_MAX, // num per line LLDB_INVALID_ADDRESS,// base address 0, // bitfield bit size 0); // bitfield bit offset if (len < k_max_buf_size) break; cstr_address += total_cstr_len; } if (sstr.GetSize() > 0) sstr << '"'; } if (sstr.GetSize() > 0) m_summary_str.assign (sstr.GetData(), sstr.GetSize()); } } } } } if (m_summary_str.empty()) return NULL; return m_summary_str.c_str(); }
Error Value::GetValueAsData (ExecutionContext *exe_ctx, DataExtractor &data, uint32_t data_offset, Module *module) { data.Clear(); Error error; lldb::addr_t address = LLDB_INVALID_ADDRESS; AddressType address_type = eAddressTypeFile; Address file_so_addr; const CompilerType &ast_type = GetCompilerType(); switch (m_value_type) { case eValueTypeVector: if (ast_type.IsValid()) data.SetAddressByteSize (ast_type.GetPointerByteSize()); else data.SetAddressByteSize(sizeof(void *)); data.SetData(m_vector.bytes, m_vector.length, m_vector.byte_order); break; case eValueTypeScalar: { data.SetByteOrder (endian::InlHostByteOrder()); if (ast_type.IsValid()) data.SetAddressByteSize (ast_type.GetPointerByteSize()); else data.SetAddressByteSize(sizeof(void *)); uint32_t limit_byte_size = UINT32_MAX; if (ast_type.IsValid() && ast_type.IsScalarType()) { uint64_t type_encoding_count = 0; lldb::Encoding type_encoding = ast_type.GetEncoding(type_encoding_count); if (type_encoding == eEncodingUint || type_encoding == eEncodingSint) limit_byte_size = ast_type.GetByteSize(exe_ctx ? exe_ctx->GetBestExecutionContextScope() : nullptr); } if (m_value.GetData (data, limit_byte_size)) return error; // Success; error.SetErrorStringWithFormat("extracting data from value failed"); break; } case eValueTypeLoadAddress: if (exe_ctx == NULL) { error.SetErrorString ("can't read load address (no execution context)"); } else { Process *process = exe_ctx->GetProcessPtr(); if (process == NULL || !process->IsAlive()) { Target *target = exe_ctx->GetTargetPtr(); if (target) { // Allow expressions to run and evaluate things when the target // has memory sections loaded. This allows you to use "target modules load" // to load your executable and any shared libraries, then execute // commands where you can look at types in data sections. const SectionLoadList &target_sections = target->GetSectionLoadList(); if (!target_sections.IsEmpty()) { address = m_value.ULongLong(LLDB_INVALID_ADDRESS); if (target_sections.ResolveLoadAddress(address, file_so_addr)) { address_type = eAddressTypeLoad; data.SetByteOrder(target->GetArchitecture().GetByteOrder()); data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); } else address = LLDB_INVALID_ADDRESS; } // else // { // ModuleSP exe_module_sp (target->GetExecutableModule()); // if (exe_module_sp) // { // address = m_value.ULongLong(LLDB_INVALID_ADDRESS); // if (address != LLDB_INVALID_ADDRESS) // { // if (exe_module_sp->ResolveFileAddress(address, file_so_addr)) // { // data.SetByteOrder(target->GetArchitecture().GetByteOrder()); // data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); // address_type = eAddressTypeFile; // } // else // { // address = LLDB_INVALID_ADDRESS; // } // } // } // } } else { error.SetErrorString ("can't read load address (invalid process)"); } } else { address = m_value.ULongLong(LLDB_INVALID_ADDRESS); address_type = eAddressTypeLoad; data.SetByteOrder(process->GetTarget().GetArchitecture().GetByteOrder()); data.SetAddressByteSize(process->GetTarget().GetArchitecture().GetAddressByteSize()); } } break; case eValueTypeFileAddress: if (exe_ctx == NULL) { error.SetErrorString ("can't read file address (no execution context)"); } else if (exe_ctx->GetTargetPtr() == NULL) { error.SetErrorString ("can't read file address (invalid target)"); } else { address = m_value.ULongLong(LLDB_INVALID_ADDRESS); if (address == LLDB_INVALID_ADDRESS) { error.SetErrorString ("invalid file address"); } else { if (module == NULL) { // The only thing we can currently lock down to a module so that // we can resolve a file address, is a variable. Variable *variable = GetVariable(); if (variable) { SymbolContext var_sc; variable->CalculateSymbolContext(&var_sc); module = var_sc.module_sp.get(); } } if (module) { bool resolved = false; ObjectFile *objfile = module->GetObjectFile(); if (objfile) { Address so_addr(address, objfile->GetSectionList()); addr_t load_address = so_addr.GetLoadAddress (exe_ctx->GetTargetPtr()); bool process_launched_and_stopped = exe_ctx->GetProcessPtr() ? StateIsStoppedState(exe_ctx->GetProcessPtr()->GetState(), true /* must_exist */) : false; // Don't use the load address if the process has exited. if (load_address != LLDB_INVALID_ADDRESS && process_launched_and_stopped) { resolved = true; address = load_address; address_type = eAddressTypeLoad; data.SetByteOrder(exe_ctx->GetTargetRef().GetArchitecture().GetByteOrder()); data.SetAddressByteSize(exe_ctx->GetTargetRef().GetArchitecture().GetAddressByteSize()); } else { if (so_addr.IsSectionOffset()) { resolved = true; file_so_addr = so_addr; data.SetByteOrder(objfile->GetByteOrder()); data.SetAddressByteSize(objfile->GetAddressByteSize()); } } } if (!resolved) { Variable *variable = GetVariable(); if (module) { if (variable) error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " for variable '%s' in %s", address, variable->GetName().AsCString(""), module->GetFileSpec().GetPath().c_str()); else error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " in %s", address, module->GetFileSpec().GetPath().c_str()); } else { if (variable) error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64 " for variable '%s'", address, variable->GetName().AsCString("")); else error.SetErrorStringWithFormat ("unable to resolve the module for file address 0x%" PRIx64, address); } } } else { // Can't convert a file address to anything valid without more // context (which Module it came from) error.SetErrorString ("can't read memory from file address without more context"); } } } break; case eValueTypeHostAddress: address = m_value.ULongLong(LLDB_INVALID_ADDRESS); address_type = eAddressTypeHost; if (exe_ctx) { Target *target = exe_ctx->GetTargetPtr(); if (target) { data.SetByteOrder(target->GetArchitecture().GetByteOrder()); data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize()); break; } } // fallback to host settings data.SetByteOrder(endian::InlHostByteOrder()); data.SetAddressByteSize(sizeof(void *)); break; } // Bail if we encountered any errors if (error.Fail()) return error; if (address == LLDB_INVALID_ADDRESS) { error.SetErrorStringWithFormat ("invalid %s address", address_type == eAddressTypeHost ? "host" : "load"); return error; } // If we got here, we need to read the value from memory size_t byte_size = GetValueByteSize (&error, exe_ctx); // Bail if we encountered any errors getting the byte size if (error.Fail()) return error; // Make sure we have enough room within "data", and if we don't make // something large enough that does if (!data.ValidOffsetForDataOfSize (data_offset, byte_size)) { DataBufferSP data_sp(new DataBufferHeap (data_offset + byte_size, '\0')); data.SetData(data_sp); } uint8_t* dst = const_cast<uint8_t*>(data.PeekData (data_offset, byte_size)); if (dst != NULL) { if (address_type == eAddressTypeHost) { // The address is an address in this process, so just copy it. if (address == 0) { error.SetErrorStringWithFormat("trying to read from host address of 0."); return error; } memcpy (dst, (uint8_t*)NULL + address, byte_size); } else if ((address_type == eAddressTypeLoad) || (address_type == eAddressTypeFile)) { if (file_so_addr.IsValid()) { // We have a file address that we were able to translate into a // section offset address so we might be able to read this from // the object files if we don't have a live process. Lets always // try and read from the process if we have one though since we // want to read the actual value by setting "prefer_file_cache" // to false. const bool prefer_file_cache = false; if (exe_ctx->GetTargetRef().ReadMemory(file_so_addr, prefer_file_cache, dst, byte_size, error) != byte_size) { error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed", (uint64_t)address); } } else { // The execution context might have a NULL process, but it // might have a valid process in the exe_ctx->target, so use // the ExecutionContext::GetProcess accessor to ensure we // get the process if there is one. Process *process = exe_ctx->GetProcessPtr(); if (process) { const size_t bytes_read = process->ReadMemory(address, dst, byte_size, error); if (bytes_read != byte_size) error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed (%u of %u bytes read)", (uint64_t)address, (uint32_t)bytes_read, (uint32_t)byte_size); } else { error.SetErrorStringWithFormat("read memory from 0x%" PRIx64 " failed (invalid process)", (uint64_t)address); } } } else { error.SetErrorStringWithFormat ("unsupported AddressType value (%i)", address_type); } } else { error.SetErrorStringWithFormat ("out of memory"); } return error; }
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; }