void IRMemoryMap::WriteScalarToMemory(lldb::addr_t process_address, Scalar &scalar, size_t size, Status &error) { error.Clear(); if (size == UINT32_MAX) size = scalar.GetByteSize(); if (size > 0) { uint8_t buf[32]; const size_t mem_size = scalar.GetAsMemoryData(buf, size, GetByteOrder(), error); if (mem_size > 0) { return WriteMemory(process_address, buf, mem_size, error); } else { error.SetErrorToGenericError(); error.SetErrorString( "Couldn't write scalar: failed to get scalar as memory data"); } } else { error.SetErrorToGenericError(); error.SetErrorString("Couldn't write scalar: its size was zero"); } return; }
uint32_t CommunicationKDP::SendRequestWriteMemory(lldb::addr_t addr, const void *src, uint32_t src_len, Status &error) { PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, m_byte_order); bool use_64 = (GetVersion() >= 11); uint32_t command_addr_byte_size = use_64 ? 8 : 4; const CommandType command = use_64 ? KDP_WRITEMEM64 : KDP_WRITEMEM; // Size is header + address size + uint32_t length const uint32_t command_length = 8 + command_addr_byte_size + 4 + src_len; MakeRequestPacketHeader(command, request_packet, command_length); request_packet.PutMaxHex64(addr, command_addr_byte_size); request_packet.PutHex32(src_len); request_packet.PutRawBytes(src, src_len); DataExtractor reply_packet; if (SendRequestAndGetReply(command, request_packet, reply_packet)) { lldb::offset_t offset = 8; uint32_t kdp_error = reply_packet.GetU32(&offset); if (kdp_error) error.SetErrorStringWithFormat("kdp write memory failed (error %u)", kdp_error); else { error.Clear(); return src_len; } } else { error.SetErrorString("failed to send packet"); } return 0; }
bool CommunicationKDP::SendRawRequest( uint8_t command_byte, const void *src, // Raw packet payload bytes uint32_t src_len, // Raw packet payload length DataExtractor &reply_packet, Status &error) { PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, m_byte_order); // Size is header + address size + uint32_t length const uint32_t command_length = 8 + src_len; const CommandType command = (CommandType)command_byte; MakeRequestPacketHeader(command, request_packet, command_length); request_packet.PutRawBytes(src, src_len); if (SendRequestAndGetReply(command, request_packet, reply_packet)) { lldb::offset_t offset = 8; uint32_t kdp_error = reply_packet.GetU32(&offset); if (kdp_error && (command_byte != KDP_DUMPINFO)) error.SetErrorStringWithFormat("request packet 0x%8.8x failed (error %u)", command_byte, kdp_error); else { error.Clear(); return true; } } else { error.SetErrorString("failed to send packet"); } return false; }
addr_t ProcessFreeBSD::DoAllocateMemory(size_t size, uint32_t permissions, Status &error) { addr_t allocated_addr = LLDB_INVALID_ADDRESS; unsigned prot = 0; if (permissions & lldb::ePermissionsReadable) prot |= eMmapProtRead; if (permissions & lldb::ePermissionsWritable) prot |= eMmapProtWrite; if (permissions & lldb::ePermissionsExecutable) prot |= eMmapProtExec; if (InferiorCallMmap(this, allocated_addr, 0, size, prot, eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) { m_addr_to_mmap_size[allocated_addr] = size; error.Clear(); } else { allocated_addr = LLDB_INVALID_ADDRESS; error.SetErrorStringWithFormat( "unable to allocate %zu bytes of memory with permissions %s", size, GetPermissionsAsCString(permissions)); } return allocated_addr; }
NativeSocket Socket::AcceptSocket(NativeSocket sockfd, struct sockaddr *addr, socklen_t *addrlen, bool child_processes_inherit, Status &error) { error.Clear(); #if defined(ANDROID_USE_ACCEPT_WORKAROUND) // Hack: // This enables static linking lldb-server to an API 21 libc, but still // having it run on older devices. It is necessary because API 21 libc's // implementation of accept() uses the accept4 syscall(), which is not // available in older kernels. Using an older libc would fix this issue, but // introduce other ones, as the old libraries were quite buggy. int fd = syscall(__NR_accept, sockfd, addr, addrlen); if (fd >= 0 && !child_processes_inherit) { int flags = ::fcntl(fd, F_GETFD); if (flags != -1 && ::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) != -1) return fd; SetLastError(error); close(fd); } return fd; #elif defined(SOCK_CLOEXEC) && defined(HAVE_ACCEPT4) int flags = 0; if (!child_processes_inherit) { flags |= SOCK_CLOEXEC; } NativeSocket fd = ::accept4(sockfd, addr, addrlen, flags); #else NativeSocket fd = ::accept(sockfd, addr, addrlen); #endif if (fd == kInvalidSocketValue) SetLastError(error); return fd; }
bool BreakpointID::StringIsBreakpointName(llvm::StringRef str, Status &error) { error.Clear(); if (str.empty()) { error.SetErrorStringWithFormat("Empty breakpoint names are not allowed"); return false; } // First character must be a letter or _ if (!isalpha(str[0]) && str[0] != '_') { error.SetErrorStringWithFormat("Breakpoint names must start with a " "character or underscore: %s", str.str().c_str()); return false; } // Cannot contain ., -, or space. if (str.find_first_of(".- ") != llvm::StringRef::npos) { error.SetErrorStringWithFormat("Breakpoint names cannot contain " "'.' or '-': \"%s\"", str.str().c_str()); return false; } return true; }
void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address, lldb::addr_t address, Status &error) { error.Clear(); Scalar scalar(address); WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error); }
NativeSocket Socket::CreateSocket(const int domain, const int type, const int protocol, bool child_processes_inherit, Status &error) { error.Clear(); auto socket_type = type; #ifdef SOCK_CLOEXEC if (!child_processes_inherit) socket_type |= SOCK_CLOEXEC; #endif auto sock = ::socket(domain, socket_type, protocol); if (sock == kInvalidSocketValue) SetLastError(error); return sock; }
void IRMemoryMap::Leak(lldb::addr_t process_address, Status &error) { error.Clear(); AllocationMap::iterator iter = m_allocations.find(process_address); if (iter == m_allocations.end()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't leak: allocation doesn't exist"); return; } Allocation &allocation = iter->second; allocation.m_leak = true; }
void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t *address, lldb::addr_t process_address, Status &error) { error.Clear(); Scalar pointer_scalar; ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error); if (!error.Success()) return; *address = pointer_scalar.ULongLong(); return; }
IRMemoryMap::~IRMemoryMap() { lldb::ProcessSP process_sp = m_process_wp.lock(); if (process_sp) { AllocationMap::iterator iter; Status err; while ((iter = m_allocations.begin()) != m_allocations.end()) { err.Clear(); if (iter->second.m_leak) m_allocations.erase(iter); else Free(iter->first, err); } } }
void IRMemoryMap::Free(lldb::addr_t process_address, Status &error) { error.Clear(); AllocationMap::iterator iter = m_allocations.find(process_address); if (iter == m_allocations.end()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't free: allocation doesn't exist"); return; } Allocation &allocation = iter->second; switch (allocation.m_policy) { default: case eAllocationPolicyHostOnly: { lldb::ProcessSP process_sp = m_process_wp.lock(); if (process_sp) { if (process_sp->CanJIT() && process_sp->IsAlive()) process_sp->DeallocateMemory( allocation.m_process_alloc); // FindSpace allocated this for real } break; } case eAllocationPolicyMirror: case eAllocationPolicyProcessOnly: { lldb::ProcessSP process_sp = m_process_wp.lock(); if (process_sp) process_sp->DeallocateMemory(allocation.m_process_alloc); } } if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")", (uint64_t)process_address, iter->second.m_process_start, iter->second.m_process_start + iter->second.m_size); } m_allocations.erase(iter); }
void IRMemoryMap::ReadScalarFromMemory(Scalar &scalar, lldb::addr_t process_address, size_t size, Status &error) { error.Clear(); if (size > 0) { DataBufferHeap buf(size, 0); ReadMemory(buf.GetBytes(), process_address, size, error); if (!error.Success()) return; DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize()); lldb::offset_t offset = 0; switch (size) { default: error.SetErrorToGenericError(); error.SetErrorStringWithFormat( "Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size); return; case 1: scalar = extractor.GetU8(&offset); break; case 2: scalar = extractor.GetU16(&offset); break; case 4: scalar = extractor.GetU32(&offset); break; case 8: scalar = extractor.GetU64(&offset); break; } } else { error.SetErrorToGenericError(); error.SetErrorString("Couldn't read scalar: its size was zero"); } return; }
uint32_t CommunicationKDP::SendRequestReadRegisters(uint32_t cpu, uint32_t flavor, void *dst, uint32_t dst_len, Status &error) { PacketStreamType request_packet(Stream::eBinary, m_addr_byte_size, m_byte_order); const CommandType command = KDP_READREGS; // Size is header + 4 byte cpu and 4 byte flavor const uint32_t command_length = 8 + 4 + 4; MakeRequestPacketHeader(command, request_packet, command_length); request_packet.PutHex32(cpu); request_packet.PutHex32(flavor); DataExtractor reply_packet; if (SendRequestAndGetReply(command, request_packet, reply_packet)) { lldb::offset_t offset = 8; uint32_t kdp_error = reply_packet.GetU32(&offset); uint32_t src_len = reply_packet.GetByteSize() - 12; if (src_len > 0) { const uint32_t bytes_to_copy = std::min<uint32_t>(src_len, dst_len); const void *src = reply_packet.GetData(&offset, bytes_to_copy); if (src) { ::memcpy(dst, src, bytes_to_copy); error.Clear(); // Return the number of bytes we could have returned regardless if we // copied them or not, just so we know when things don't match up return src_len; } } if (kdp_error) error.SetErrorStringWithFormat( "failed to read kdp registers for cpu %u flavor %u (error %u)", cpu, flavor, kdp_error); else error.SetErrorStringWithFormat( "failed to read kdp registers for cpu %u flavor %u", cpu, flavor); } else { error.SetErrorString("failed to send packet"); } return 0; }
std::unique_ptr<Socket> Socket::Create(const SocketProtocol protocol, bool child_processes_inherit, Status &error) { error.Clear(); std::unique_ptr<Socket> socket_up; switch (protocol) { case ProtocolTcp: socket_up = llvm::make_unique<TCPSocket>(true, child_processes_inherit); break; case ProtocolUdp: socket_up = llvm::make_unique<UDPSocket>(true, child_processes_inherit); break; case ProtocolUnixDomain: #ifndef LLDB_DISABLE_POSIX socket_up = llvm::make_unique<DomainSocket>(true, child_processes_inherit); #else error.SetErrorString( "Unix domain sockets are not supported on this platform."); #endif break; case ProtocolUnixAbstract: #ifdef __linux__ socket_up = llvm::make_unique<AbstractSocket>(child_processes_inherit); #else error.SetErrorString( "Abstract domain sockets are not supported on this platform."); #endif break; } if (error.Fail()) socket_up.reset(); return socket_up; }
TEST_F(GDBRemoteCommunicationClientTest, SendStartTracePacket) { TraceOptions options; Status error; options.setType(lldb::TraceType::eTraceTypeProcessorTrace); options.setMetaDataBufferSize(8192); options.setTraceBufferSize(8192); options.setThreadID(0x23); StructuredData::DictionarySP custom_params = std::make_shared<StructuredData::Dictionary>(); custom_params->AddStringItem("tracetech", "intel-pt"); custom_params->AddIntegerItem("psb", 0x01); options.setTraceParams(custom_params); std::future<lldb::user_id_t> result = std::async(std::launch::async, [&] { return client.SendStartTracePacket(options, error); }); // Since the line is exceeding 80 characters. std::string expected_packet1 = R"(jTraceStart:{"buffersize" : 8192,"metabuffersize" : 8192,"params" :)"; std::string expected_packet2 = R"( {"psb" : 1,"tracetech" : "intel-pt"},"threadid" : 35,"type" : 1})"; HandlePacket(server, (expected_packet1 + expected_packet2), "1"); ASSERT_TRUE(error.Success()); ASSERT_EQ(result.get(), 1u); error.Clear(); result = std::async(std::launch::async, [&] { return client.SendStartTracePacket(options, error); }); HandlePacket(server, (expected_packet1 + expected_packet2), "E23"); ASSERT_EQ(result.get(), LLDB_INVALID_UID); ASSERT_FALSE(error.Success()); }
HostProcess MonitoringProcessLauncher::LaunchProcess(const ProcessLaunchInfo &launch_info, Status &error) { ProcessLaunchInfo resolved_info(launch_info); error.Clear(); char exe_path[PATH_MAX]; PlatformSP host_platform_sp(Platform::GetHostPlatform()); const ArchSpec &arch_spec = resolved_info.GetArchitecture(); FileSpec exe_spec(resolved_info.GetExecutableFile()); llvm::sys::fs::file_status stats; status(exe_spec.GetPath(), stats); if (!is_regular_file(stats)) { ModuleSpec module_spec(exe_spec, arch_spec); lldb::ModuleSP exe_module_sp; error = host_platform_sp->ResolveExecutable(module_spec, exe_module_sp, NULL); if (error.Fail()) return HostProcess(); if (exe_module_sp) { exe_spec = exe_module_sp->GetFileSpec(); status(exe_spec.GetPath(), stats); } } if (exists(stats)) { exe_spec.GetPath(exe_path, sizeof(exe_path)); } else { resolved_info.GetExecutableFile().GetPath(exe_path, sizeof(exe_path)); error.SetErrorStringWithFormat("executable doesn't exist: '%s'", exe_path); return HostProcess(); } resolved_info.SetExecutableFile(exe_spec, false); assert(!resolved_info.GetFlags().Test(eLaunchFlagLaunchInTTY)); HostProcess process = m_delegate_launcher->LaunchProcess(resolved_info, error); if (process.GetProcessId() != LLDB_INVALID_PROCESS_ID) { Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); Host::MonitorChildProcessCallback callback = launch_info.GetMonitorProcessCallback(); bool monitor_signals = false; if (callback) { // If the ProcessLaunchInfo specified a callback, use that. monitor_signals = launch_info.GetMonitorSignals(); } else { callback = Process::SetProcessExitStatus; } process.StartMonitoring(callback, monitor_signals); if (log) log->PutCString("started monitoring child process."); } else { // Invalid process ID, something didn't go well if (error.Success()) error.SetErrorString("process launch failed for unknown reasons"); } return process; }
lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, bool zero_memory, Status &error) { lldb_private::Log *log( lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)); error.Clear(); lldb::ProcessSP process_sp; lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS; lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS; size_t allocation_size; if (size == 0) { // FIXME: Malloc(0) should either return an invalid address or assert, in // order to cut down on unnecessary allocations. allocation_size = alignment; } else { // Round up the requested size to an aligned value. allocation_size = llvm::alignTo(size, alignment); // The process page cache does not see the requested alignment. We can't // assume its result will be any more than 1-byte aligned. To work around // this, request `alignment - 1` additional bytes. allocation_size += alignment - 1; } switch (policy) { default: error.SetErrorToGenericError(); error.SetErrorString("Couldn't malloc: invalid allocation policy"); return LLDB_INVALID_ADDRESS; case eAllocationPolicyHostOnly: allocation_address = FindSpace(allocation_size); if (allocation_address == LLDB_INVALID_ADDRESS) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't malloc: address space is full"); return LLDB_INVALID_ADDRESS; } break; case eAllocationPolicyMirror: process_sp = m_process_wp.lock(); if (log) log->Printf("IRMemoryMap::%s process_sp=0x%" PRIx64 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", __FUNCTION__, (lldb::addr_t)process_sp.get(), process_sp && process_sp->CanJIT() ? "true" : "false", process_sp && process_sp->IsAlive() ? "true" : "false"); if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) { if (!zero_memory) allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error); else allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error); if (!error.Success()) return LLDB_INVALID_ADDRESS; } else { if (log) log->Printf("IRMemoryMap::%s switching to eAllocationPolicyHostOnly " "due to failed condition (see previous expr log message)", __FUNCTION__); policy = eAllocationPolicyHostOnly; allocation_address = FindSpace(allocation_size); if (allocation_address == LLDB_INVALID_ADDRESS) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't malloc: address space is full"); return LLDB_INVALID_ADDRESS; } } break; case eAllocationPolicyProcessOnly: process_sp = m_process_wp.lock(); if (process_sp) { if (process_sp->CanJIT() && process_sp->IsAlive()) { if (!zero_memory) allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error); else allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error); if (!error.Success()) return LLDB_INVALID_ADDRESS; } else { error.SetErrorToGenericError(); error.SetErrorString( "Couldn't malloc: process doesn't support allocating memory"); return LLDB_INVALID_ADDRESS; } } else { error.SetErrorToGenericError(); error.SetErrorString("Couldn't malloc: process doesn't exist, and this " "memory must be in the process"); return LLDB_INVALID_ADDRESS; } break; } lldb::addr_t mask = alignment - 1; aligned_address = (allocation_address + mask) & (~mask); m_allocations.emplace( std::piecewise_construct, std::forward_as_tuple(aligned_address), std::forward_as_tuple(allocation_address, aligned_address, allocation_size, permissions, alignment, policy)); if (zero_memory) { Status write_error; std::vector<uint8_t> zero_buf(size, 0); WriteMemory(aligned_address, zero_buf.data(), size, write_error); } if (log) { const char *policy_string; switch (policy) { default: policy_string = "<invalid policy>"; break; case eAllocationPolicyHostOnly: policy_string = "eAllocationPolicyHostOnly"; break; case eAllocationPolicyProcessOnly: policy_string = "eAllocationPolicyProcessOnly"; break; case eAllocationPolicyMirror: policy_string = "eAllocationPolicyMirror"; break; } log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64, (uint64_t)allocation_size, (uint64_t)alignment, (uint64_t)permissions, policy_string, aligned_address); } return aligned_address; }
Status PlatformRemoteDarwinDevice::GetSharedModule( const ModuleSpec &module_spec, Process *process, ModuleSP &module_sp, const FileSpecList *module_search_paths_ptr, ModuleSP *old_module_sp_ptr, bool *did_create_ptr) { // For iOS, the SDK files are all cached locally on the host system. So first // we ask for the file in the cached SDK, then we attempt to get a shared // module for the right architecture with the right UUID. const FileSpec &platform_file = module_spec.GetFileSpec(); Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); Status error; char platform_file_path[PATH_MAX]; if (platform_file.GetPath(platform_file_path, sizeof(platform_file_path))) { ModuleSpec platform_module_spec(module_spec); UpdateSDKDirectoryInfosIfNeeded(); const uint32_t num_sdk_infos = m_sdk_directory_infos.size(); // If we are connected we migth be able to correctly deduce the SDK // directory using the OS build. const uint32_t connected_sdk_idx = GetConnectedSDKIndex(); if (connected_sdk_idx < num_sdk_infos) { LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, m_sdk_directory_infos[connected_sdk_idx].directory); if (GetFileInSDK(platform_file_path, connected_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); error = ResolveExecutable(platform_module_spec, module_sp, NULL); if (module_sp) { m_last_module_sdk_idx = connected_sdk_idx; error.Clear(); return error; } } } // Try the last SDK index if it is set as most files from an SDK will tend // to be valid in that same SDK. if (m_last_module_sdk_idx < num_sdk_infos) { LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, m_sdk_directory_infos[m_last_module_sdk_idx].directory); if (GetFileInSDK(platform_file_path, m_last_module_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); error = ResolveExecutable(platform_module_spec, module_sp, NULL); if (module_sp) { error.Clear(); return error; } } } // First try for an exact match of major, minor and update: If a particalar // SDK version was specified via --version or --build, look for a match on // disk. const SDKDirectoryInfo *current_sdk_info = GetSDKDirectoryForCurrentOSVersion(); const uint32_t current_sdk_idx = GetSDKIndexBySDKDirectoryInfo(current_sdk_info); if (current_sdk_idx < num_sdk_infos && current_sdk_idx != m_last_module_sdk_idx) { LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, m_sdk_directory_infos[current_sdk_idx].directory); if (GetFileInSDK(platform_file_path, current_sdk_idx, platform_module_spec.GetFileSpec())) { module_sp.reset(); error = ResolveExecutable(platform_module_spec, module_sp, NULL); if (module_sp) { m_last_module_sdk_idx = current_sdk_idx; error.Clear(); return error; } } } // Second try all SDKs that were found. for (uint32_t sdk_idx = 0; sdk_idx < num_sdk_infos; ++sdk_idx) { if (m_last_module_sdk_idx == sdk_idx) { // Skip the last module SDK index if we already searched it above continue; } LLDB_LOGV(log, "Searching for {0} in sdk path {1}", platform_file, m_sdk_directory_infos[sdk_idx].directory); if (GetFileInSDK(platform_file_path, sdk_idx, platform_module_spec.GetFileSpec())) { // printf ("sdk[%u]: '%s'\n", sdk_idx, local_file.GetPath().c_str()); error = ResolveExecutable(platform_module_spec, module_sp, NULL); if (module_sp) { // Remember the index of the last SDK that we found a file in in case // the wrong SDK was selected. m_last_module_sdk_idx = sdk_idx; error.Clear(); return error; } } } } // Not the module we are looking for... Nothing to see here... module_sp.reset(); // This may not be an SDK-related module. Try whether we can bring in the // thing to our local cache. error = GetSharedModuleWithLocalCache(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); if (error.Success()) return error; // See if the file is present in any of the module_search_paths_ptr // directories. if (!module_sp) error = PlatformDarwin::FindBundleBinaryInExecSearchPaths (module_spec, process, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr); if (error.Success()) return error; const bool always_create = false; error = ModuleList::GetSharedModule( module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr, always_create); if (module_sp) module_sp->SetPlatformFileSpec(platform_file); return error; }
void IRMemoryMap::WriteMemory(lldb::addr_t process_address, const uint8_t *bytes, size_t size, Status &error) { error.Clear(); AllocationMap::iterator iter = FindAllocation(process_address, size); if (iter == m_allocations.end()) { lldb::ProcessSP process_sp = m_process_wp.lock(); if (process_sp) { process_sp->WriteMemory(process_address, bytes, size, error); return; } error.SetErrorToGenericError(); error.SetErrorString("Couldn't write: no allocation contains the target " "range and the process doesn't exist"); return; } Allocation &allocation = iter->second; uint64_t offset = process_address - allocation.m_process_start; lldb::ProcessSP process_sp; switch (allocation.m_policy) { default: error.SetErrorToGenericError(); error.SetErrorString("Couldn't write: invalid allocation policy"); return; case eAllocationPolicyHostOnly: if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't write: data buffer is empty"); return; } ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size); break; case eAllocationPolicyMirror: if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't write: data buffer is empty"); return; } ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size); process_sp = m_process_wp.lock(); if (process_sp) { process_sp->WriteMemory(process_address, bytes, size, error); if (!error.Success()) return; } break; case eAllocationPolicyProcessOnly: process_sp = m_process_wp.lock(); if (process_sp) { process_sp->WriteMemory(process_address, bytes, size, error); if (!error.Success()) return; } break; } if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")", (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size, (uint64_t)allocation.m_process_start, (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size); } }
void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address, size_t size, Status &error) { error.Clear(); AllocationMap::iterator iter = FindAllocation(process_address, size); if (iter == m_allocations.end()) { lldb::ProcessSP process_sp = m_process_wp.lock(); if (process_sp) { process_sp->ReadMemory(process_address, bytes, size, error); return; } lldb::TargetSP target_sp = m_target_wp.lock(); if (target_sp) { Address absolute_address(process_address); target_sp->ReadMemory(absolute_address, false, bytes, size, error); return; } error.SetErrorToGenericError(); error.SetErrorString("Couldn't read: no allocation contains the target " "range, and neither the process nor the target exist"); return; } Allocation &allocation = iter->second; uint64_t offset = process_address - allocation.m_process_start; if (offset > allocation.m_size) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't read: data is not in the allocation"); return; } lldb::ProcessSP process_sp; switch (allocation.m_policy) { default: error.SetErrorToGenericError(); error.SetErrorString("Couldn't read: invalid allocation policy"); return; case eAllocationPolicyHostOnly: if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't read: data buffer is empty"); return; } if (allocation.m_data.GetByteSize() < offset + size) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't read: not enough underlying data"); return; } ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size); break; case eAllocationPolicyMirror: process_sp = m_process_wp.lock(); if (process_sp) { process_sp->ReadMemory(process_address, bytes, size, error); if (!error.Success()) return; } else { if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't read: data buffer is empty"); return; } ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size); } break; case eAllocationPolicyProcessOnly: process_sp = m_process_wp.lock(); if (process_sp) { process_sp->ReadMemory(process_address, bytes, size, error); if (!error.Success()) return; } break; } if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) { log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")", (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size, (uint64_t)allocation.m_process_start, (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size); } }
bool BreakpointLocation::ConditionSaysStop(ExecutionContext &exe_ctx, Status &error) { Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS); std::lock_guard<std::mutex> guard(m_condition_mutex); size_t condition_hash; const char *condition_text = GetConditionText(&condition_hash); if (!condition_text) { m_user_expression_sp.reset(); return false; } error.Clear(); DiagnosticManager diagnostics; if (condition_hash != m_condition_hash || !m_user_expression_sp || !m_user_expression_sp->MatchesContext(exe_ctx)) { LanguageType language = eLanguageTypeUnknown; // See if we can figure out the language from the frame, otherwise use the // default language: CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit(); if (comp_unit) language = comp_unit->GetLanguage(); m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage( condition_text, llvm::StringRef(), language, Expression::eResultTypeAny, EvaluateExpressionOptions(), nullptr, error)); if (error.Fail()) { if (log) log->Printf("Error getting condition expression: %s.", error.AsCString()); m_user_expression_sp.reset(); return true; } if (!m_user_expression_sp->Parse(diagnostics, exe_ctx, eExecutionPolicyOnlyWhenNeeded, true, false)) { error.SetErrorStringWithFormat( "Couldn't parse conditional expression:\n%s", diagnostics.GetString().c_str()); m_user_expression_sp.reset(); return true; } m_condition_hash = condition_hash; } // We need to make sure the user sees any parse errors in their condition, so // we'll hook the constructor errors up to the debugger's Async I/O. ValueObjectSP result_value_sp; EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); options.SetTryAllThreads(true); options.SetResultIsInternal( true); // Don't generate a user variable for condition expressions. Status expr_error; diagnostics.Clear(); ExpressionVariableSP result_variable_sp; ExpressionResults result_code = m_user_expression_sp->Execute( diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp); bool ret; if (result_code == eExpressionCompleted) { if (!result_variable_sp) { error.SetErrorString("Expression did not return a result"); return false; } result_value_sp = result_variable_sp->GetValueObject(); if (result_value_sp) { ret = result_value_sp->IsLogicalTrue(error); if (log) { if (error.Success()) { log->Printf("Condition successfully evaluated, result is %s.\n", ret ? "true" : "false"); } else { error.SetErrorString( "Failed to get an integer result from the expression"); ret = false; } } } else { ret = false; error.SetErrorString("Failed to get any result from the expression"); } } else { ret = false; error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", diagnostics.GetString().c_str()); } return ret; }
void IRMemoryMap::GetMemoryData(DataExtractor &extractor, lldb::addr_t process_address, size_t size, Status &error) { error.Clear(); if (size > 0) { AllocationMap::iterator iter = FindAllocation(process_address, size); if (iter == m_allocations.end()) { error.SetErrorToGenericError(); error.SetErrorStringWithFormat( "Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size); return; } Allocation &allocation = iter->second; switch (allocation.m_policy) { default: error.SetErrorToGenericError(); error.SetErrorString( "Couldn't get memory data: invalid allocation policy"); return; case eAllocationPolicyProcessOnly: error.SetErrorToGenericError(); error.SetErrorString( "Couldn't get memory data: memory is only in the target"); return; case eAllocationPolicyMirror: { lldb::ProcessSP process_sp = m_process_wp.lock(); if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't get memory data: data buffer is empty"); return; } if (process_sp) { process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error); if (!error.Success()) return; uint64_t offset = process_address - allocation.m_process_start; extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize()); return; } } break; case eAllocationPolicyHostOnly: if (!allocation.m_data.GetByteSize()) { error.SetErrorToGenericError(); error.SetErrorString("Couldn't get memory data: data buffer is empty"); return; } uint64_t offset = process_address - allocation.m_process_start; extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize()); return; } } else { error.SetErrorToGenericError(); error.SetErrorString("Couldn't get memory data: its size was zero"); return; } }
void Dematerialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, lldb::addr_t frame_top, lldb::addr_t frame_bottom, Status &err) override { err.Clear(); ExecutionContextScope *exe_scope = map.GetBestExecutionContextScope(); if (!exe_scope) { err.SetErrorString("Couldn't dematerialize a result variable: invalid " "execution context scope"); return; } lldb::addr_t address; Status read_error; const lldb::addr_t load_addr = process_address + m_offset; map.ReadPointerFromMemory(&address, load_addr, read_error); if (!read_error.Success()) { err.SetErrorString("Couldn't dematerialize a result variable: couldn't " "read its address"); return; } lldb::TargetSP target_sp = exe_scope->CalculateTarget(); if (!target_sp) { err.SetErrorString("Couldn't dematerialize a result variable: no target"); return; } Status type_system_error; TypeSystem *type_system = target_sp->GetScratchTypeSystemForLanguage( &type_system_error, m_type.GetMinimumLanguage()); if (!type_system) { err.SetErrorStringWithFormat("Couldn't dematerialize a result variable: " "couldn't get the corresponding type " "system: %s", type_system_error.AsCString()); return; } PersistentExpressionState *persistent_state = type_system->GetPersistentExpressionState(); if (!persistent_state) { err.SetErrorString("Couldn't dematerialize a result variable: " "corresponding type system doesn't handle persistent " "variables"); return; } ConstString name = m_delegate ? m_delegate->GetName() : persistent_state->GetNextPersistentVariableName(); lldb::ExpressionVariableSP ret = persistent_state->CreatePersistentVariable( exe_scope, name, m_type, map.GetByteOrder(), map.GetAddressByteSize()); if (!ret) { err.SetErrorStringWithFormat("couldn't dematerialize a result variable: " "failed to make persistent variable %s", name.AsCString()); return; } lldb::ProcessSP process_sp = map.GetBestExecutionContextScope()->CalculateProcess(); if (m_delegate) { m_delegate->DidDematerialize(ret); } bool can_persist = (m_is_program_reference && process_sp && process_sp->CanJIT() && !(address >= frame_bottom && address < frame_top)); if (can_persist && m_keep_in_memory) { ret->m_live_sp = ValueObjectConstResult::Create(exe_scope, m_type, name, address, eAddressTypeLoad, map.GetAddressByteSize()); } ret->ValueUpdated(); const size_t pvar_byte_size = ret->GetByteSize(); uint8_t *pvar_data = ret->GetValueBytes(); map.ReadMemory(pvar_data, address, pvar_byte_size, read_error); if (!read_error.Success()) { err.SetErrorString( "Couldn't dematerialize a result variable: couldn't read its memory"); return; } if (!can_persist || !m_keep_in_memory) { ret->m_flags |= ExpressionVariable::EVNeedsAllocation; if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { Status free_error; map.Free(m_temporary_allocation, free_error); } } else { ret->m_flags |= ExpressionVariable::EVIsLLDBAllocated; } m_temporary_allocation = LLDB_INVALID_ADDRESS; m_temporary_allocation_size = 0; }