//---------------------------------------------------------------------- // 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; }
//---------------------------------------------------------------------- // 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; }
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; }
size_t CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock (DataExtractor &packet, uint32_t timeout_usec) { uint8_t buffer[8192]; Error error; LogSP log (ProcessKDPLog::GetLogIfAllCategoriesSet (KDP_LOG_PACKETS | KDP_LOG_VERBOSE)); // Check for a packet from our cache first without trying any reading... if (CheckForPacket (NULL, 0, packet)) return packet.GetByteSize(); bool timed_out = false; while (IsConnected() && !timed_out) { lldb::ConnectionStatus status = eConnectionStatusNoConnection; size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error); if (log) log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64, __PRETTY_FUNCTION__, timeout_usec, Communication::ConnectionStatusAsCString (status), error.AsCString(), (uint64_t)bytes_read); if (bytes_read > 0) { if (CheckForPacket (buffer, bytes_read, packet)) return packet.GetByteSize(); } else { switch (status) { case eConnectionStatusTimedOut: timed_out = true; break; case eConnectionStatusSuccess: //printf ("status = success but error = %s\n", error.AsCString("<invalid>")); break; case eConnectionStatusEndOfFile: case eConnectionStatusNoConnection: case eConnectionStatusLostConnection: case eConnectionStatusError: Disconnect(); break; } } } packet.Clear (); return 0; }
size_t CommunicationKDP::WaitForPacketWithTimeoutMicroSecondsNoLock( DataExtractor &packet, uint32_t timeout_usec) { uint8_t buffer[8192]; Status error; Log *log(ProcessKDPLog::GetLogIfAllCategoriesSet(KDP_LOG_PACKETS)); // Check for a packet from our cache first without trying any reading... if (CheckForPacket(NULL, 0, packet)) return packet.GetByteSize(); bool timed_out = false; while (IsConnected() && !timed_out) { lldb::ConnectionStatus status = eConnectionStatusNoConnection; size_t bytes_read = Read(buffer, sizeof(buffer), timeout_usec == UINT32_MAX ? Timeout<std::micro>(llvm::None) : std::chrono::microseconds(timeout_usec), status, &error); LLDB_LOGV(log, "Read (buffer, sizeof(buffer), timeout_usec = 0x{0:x}, " "status = {1}, error = {2}) => bytes_read = {4}", timeout_usec, Communication::ConnectionStatusAsCString(status), error, bytes_read); if (bytes_read > 0) { if (CheckForPacket(buffer, bytes_read, packet)) return packet.GetByteSize(); } else { switch (status) { case eConnectionStatusInterrupted: case eConnectionStatusTimedOut: timed_out = true; break; case eConnectionStatusSuccess: // printf ("status = success but error = %s\n", // error.AsCString("<invalid>")); break; case eConnectionStatusEndOfFile: case eConnectionStatusNoConnection: case eConnectionStatusLostConnection: case eConnectionStatusError: Disconnect(); break; } } } packet.Clear(); return 0; }
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 ObjectFile::MemoryMapSectionData (const Section *section, DataExtractor& section_data) const { if (IsInMemory()) { return ReadSectionData (section, section_data); } else { // The object file now contains a full mmap'ed copy of the object file data, so just use this return GetData(section->GetFileOffset(), section->GetFileSize(), section_data); } section_data.Clear(); return 0; }
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; }
size_t ObjectFile::MemoryMapSectionData (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()->MemoryMapSectionData (section, section_data); if (IsInMemory()) { return ReadSectionData (section, section_data); } else { // The object file now contains a full mmap'ed copy of the object file data, so just use this return GetData(section->GetFileOffset(), section->GetFileSize(), section_data); } section_data.Clear(); return 0; }
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::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; }
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; }