Path: blob/main/contrib/llvm-project/lldb/source/Expression/IRMemoryMap.cpp
39587 views
//===-- IRMemoryMap.cpp ---------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "lldb/Expression/IRMemoryMap.h"9#include "lldb/Target/MemoryRegionInfo.h"10#include "lldb/Target/Process.h"11#include "lldb/Target/Target.h"12#include "lldb/Utility/DataBufferHeap.h"13#include "lldb/Utility/DataExtractor.h"14#include "lldb/Utility/LLDBAssert.h"15#include "lldb/Utility/LLDBLog.h"16#include "lldb/Utility/Log.h"17#include "lldb/Utility/Scalar.h"18#include "lldb/Utility/Status.h"1920using namespace lldb_private;2122IRMemoryMap::IRMemoryMap(lldb::TargetSP target_sp) : m_target_wp(target_sp) {23if (target_sp)24m_process_wp = target_sp->GetProcessSP();25}2627IRMemoryMap::~IRMemoryMap() {28lldb::ProcessSP process_sp = m_process_wp.lock();2930if (process_sp) {31AllocationMap::iterator iter;3233Status err;3435while ((iter = m_allocations.begin()) != m_allocations.end()) {36err.Clear();37if (iter->second.m_leak)38m_allocations.erase(iter);39else40Free(iter->first, err);41}42}43}4445lldb::addr_t IRMemoryMap::FindSpace(size_t size) {46// The FindSpace algorithm's job is to find a region of memory that the47// underlying process is unlikely to be using.48//49// The memory returned by this function will never be written to. The only50// point is that it should not shadow process memory if possible, so that51// expressions processing real values from the process do not use the wrong52// data.53//54// If the process can in fact allocate memory (CanJIT() lets us know this)55// then this can be accomplished just be allocating memory in the inferior.56// Then no guessing is required.5758lldb::TargetSP target_sp = m_target_wp.lock();59lldb::ProcessSP process_sp = m_process_wp.lock();6061const bool process_is_alive = process_sp && process_sp->IsAlive();6263lldb::addr_t ret = LLDB_INVALID_ADDRESS;64if (size == 0)65return ret;6667if (process_is_alive && process_sp->CanJIT()) {68Status alloc_error;6970ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable |71lldb::ePermissionsWritable,72alloc_error);7374if (!alloc_error.Success())75return LLDB_INVALID_ADDRESS;76else77return ret;78}7980// At this point we know that we need to hunt.81//82// First, go to the end of the existing allocations we've made if there are83// any allocations. Otherwise start at the beginning of memory.8485if (m_allocations.empty()) {86ret = 0x0;87} else {88auto back = m_allocations.rbegin();89lldb::addr_t addr = back->first;90size_t alloc_size = back->second.m_size;91ret = llvm::alignTo(addr + alloc_size, 4096);92}9394uint64_t end_of_memory;95switch (GetAddressByteSize()) {96case 2:97end_of_memory = 0xffffull;98break;99case 4:100end_of_memory = 0xffffffffull;101break;102case 8:103end_of_memory = 0xffffffffffffffffull;104break;105default:106lldbassert(false && "Invalid address size.");107return LLDB_INVALID_ADDRESS;108}109110// Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped111// regions, walk forward through memory until a region is found that has112// adequate space for our allocation.113if (process_is_alive) {114MemoryRegionInfo region_info;115Status err = process_sp->GetMemoryRegionInfo(ret, region_info);116if (err.Success()) {117while (true) {118if (region_info.GetReadable() != MemoryRegionInfo::OptionalBool::eNo ||119region_info.GetWritable() != MemoryRegionInfo::OptionalBool::eNo ||120region_info.GetExecutable() !=121MemoryRegionInfo::OptionalBool::eNo) {122if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory) {123ret = LLDB_INVALID_ADDRESS;124break;125} else {126ret = region_info.GetRange().GetRangeEnd();127}128} else if (ret + size < region_info.GetRange().GetRangeEnd()) {129return ret;130} else {131// ret stays the same. We just need to walk a bit further.132}133134err = process_sp->GetMemoryRegionInfo(135region_info.GetRange().GetRangeEnd(), region_info);136if (err.Fail()) {137lldbassert(0 && "GetMemoryRegionInfo() succeeded, then failed");138ret = LLDB_INVALID_ADDRESS;139break;140}141}142}143}144145// We've tried our algorithm, and it didn't work. Now we have to reset back146// to the end of the allocations we've already reported, or use a 'sensible'147// default if this is our first allocation.148if (m_allocations.empty()) {149uint64_t alloc_address = target_sp->GetExprAllocAddress();150if (alloc_address > 0) {151if (alloc_address >= end_of_memory) {152lldbassert(0 && "The allocation address for expression evaluation must "153"be within process address space");154return LLDB_INVALID_ADDRESS;155}156ret = alloc_address;157} else {158uint32_t address_byte_size = GetAddressByteSize();159if (address_byte_size != UINT32_MAX) {160switch (address_byte_size) {161case 2:162ret = 0x8000ull;163break;164case 4:165ret = 0xee000000ull;166break;167case 8:168ret = 0xdead0fff00000000ull;169break;170default:171lldbassert(false && "Invalid address size.");172return LLDB_INVALID_ADDRESS;173}174}175}176} else {177auto back = m_allocations.rbegin();178lldb::addr_t addr = back->first;179size_t alloc_size = back->second.m_size;180uint64_t align = target_sp->GetExprAllocAlign();181if (align == 0)182align = 4096;183ret = llvm::alignTo(addr + alloc_size, align);184}185186return ret;187}188189IRMemoryMap::AllocationMap::iterator190IRMemoryMap::FindAllocation(lldb::addr_t addr, size_t size) {191if (addr == LLDB_INVALID_ADDRESS)192return m_allocations.end();193194AllocationMap::iterator iter = m_allocations.lower_bound(addr);195196if (iter == m_allocations.end() || iter->first > addr) {197if (iter == m_allocations.begin())198return m_allocations.end();199iter--;200}201202if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)203return iter;204205return m_allocations.end();206}207208bool IRMemoryMap::IntersectsAllocation(lldb::addr_t addr, size_t size) const {209if (addr == LLDB_INVALID_ADDRESS)210return false;211212AllocationMap::const_iterator iter = m_allocations.lower_bound(addr);213214// Since we only know that the returned interval begins at a location greater215// than or equal to where the given interval begins, it's possible that the216// given interval intersects either the returned interval or the previous217// interval. Thus, we need to check both. Note that we only need to check218// these two intervals. Since all intervals are disjoint it is not possible219// that an adjacent interval does not intersect, but a non-adjacent interval220// does intersect.221if (iter != m_allocations.end()) {222if (AllocationsIntersect(addr, size, iter->second.m_process_start,223iter->second.m_size))224return true;225}226227if (iter != m_allocations.begin()) {228--iter;229if (AllocationsIntersect(addr, size, iter->second.m_process_start,230iter->second.m_size))231return true;232}233234return false;235}236237bool IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1,238lldb::addr_t addr2, size_t size2) {239// Given two half open intervals [A, B) and [X, Y), the only 6 permutations240// that satisfy A<B and X<Y are the following:241// A B X Y242// A X B Y (intersects)243// A X Y B (intersects)244// X A B Y (intersects)245// X A Y B (intersects)246// X Y A B247// The first is B <= X, and the last is Y <= A. So the condition is !(B <= X248// || Y <= A)), or (X < B && A < Y)249return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));250}251252lldb::ByteOrder IRMemoryMap::GetByteOrder() {253lldb::ProcessSP process_sp = m_process_wp.lock();254255if (process_sp)256return process_sp->GetByteOrder();257258lldb::TargetSP target_sp = m_target_wp.lock();259260if (target_sp)261return target_sp->GetArchitecture().GetByteOrder();262263return lldb::eByteOrderInvalid;264}265266uint32_t IRMemoryMap::GetAddressByteSize() {267lldb::ProcessSP process_sp = m_process_wp.lock();268269if (process_sp)270return process_sp->GetAddressByteSize();271272lldb::TargetSP target_sp = m_target_wp.lock();273274if (target_sp)275return target_sp->GetArchitecture().GetAddressByteSize();276277return UINT32_MAX;278}279280ExecutionContextScope *IRMemoryMap::GetBestExecutionContextScope() const {281lldb::ProcessSP process_sp = m_process_wp.lock();282283if (process_sp)284return process_sp.get();285286lldb::TargetSP target_sp = m_target_wp.lock();287288if (target_sp)289return target_sp.get();290291return nullptr;292}293294IRMemoryMap::Allocation::Allocation(lldb::addr_t process_alloc,295lldb::addr_t process_start, size_t size,296uint32_t permissions, uint8_t alignment,297AllocationPolicy policy)298: m_process_alloc(process_alloc), m_process_start(process_start),299m_size(size), m_policy(policy), m_leak(false), m_permissions(permissions),300m_alignment(alignment) {301switch (policy) {302default:303llvm_unreachable("Invalid AllocationPolicy");304case eAllocationPolicyHostOnly:305case eAllocationPolicyMirror:306m_data.SetByteSize(size);307break;308case eAllocationPolicyProcessOnly:309break;310}311}312313lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment,314uint32_t permissions, AllocationPolicy policy,315bool zero_memory, Status &error) {316lldb_private::Log *log(GetLog(LLDBLog::Expressions));317error.Clear();318319lldb::ProcessSP process_sp;320lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;321lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;322323size_t allocation_size;324325if (size == 0) {326// FIXME: Malloc(0) should either return an invalid address or assert, in327// order to cut down on unnecessary allocations.328allocation_size = alignment;329} else {330// Round up the requested size to an aligned value.331allocation_size = llvm::alignTo(size, alignment);332333// The process page cache does not see the requested alignment. We can't334// assume its result will be any more than 1-byte aligned. To work around335// this, request `alignment - 1` additional bytes.336allocation_size += alignment - 1;337}338339switch (policy) {340default:341error.SetErrorToGenericError();342error.SetErrorString("Couldn't malloc: invalid allocation policy");343return LLDB_INVALID_ADDRESS;344case eAllocationPolicyHostOnly:345allocation_address = FindSpace(allocation_size);346if (allocation_address == LLDB_INVALID_ADDRESS) {347error.SetErrorToGenericError();348error.SetErrorString("Couldn't malloc: address space is full");349return LLDB_INVALID_ADDRESS;350}351break;352case eAllocationPolicyMirror:353process_sp = m_process_wp.lock();354LLDB_LOGF(log,355"IRMemoryMap::%s process_sp=0x%" PRIxPTR356", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s",357__FUNCTION__, reinterpret_cast<uintptr_t>(process_sp.get()),358process_sp && process_sp->CanJIT() ? "true" : "false",359process_sp && process_sp->IsAlive() ? "true" : "false");360if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) {361if (!zero_memory)362allocation_address =363process_sp->AllocateMemory(allocation_size, permissions, error);364else365allocation_address =366process_sp->CallocateMemory(allocation_size, permissions, error);367368if (!error.Success())369return LLDB_INVALID_ADDRESS;370} else {371LLDB_LOGF(log,372"IRMemoryMap::%s switching to eAllocationPolicyHostOnly "373"due to failed condition (see previous expr log message)",374__FUNCTION__);375policy = eAllocationPolicyHostOnly;376allocation_address = FindSpace(allocation_size);377if (allocation_address == LLDB_INVALID_ADDRESS) {378error.SetErrorToGenericError();379error.SetErrorString("Couldn't malloc: address space is full");380return LLDB_INVALID_ADDRESS;381}382}383break;384case eAllocationPolicyProcessOnly:385process_sp = m_process_wp.lock();386if (process_sp) {387if (process_sp->CanJIT() && process_sp->IsAlive()) {388if (!zero_memory)389allocation_address =390process_sp->AllocateMemory(allocation_size, permissions, error);391else392allocation_address =393process_sp->CallocateMemory(allocation_size, permissions, error);394395if (!error.Success())396return LLDB_INVALID_ADDRESS;397} else {398error.SetErrorToGenericError();399error.SetErrorString(400"Couldn't malloc: process doesn't support allocating memory");401return LLDB_INVALID_ADDRESS;402}403} else {404error.SetErrorToGenericError();405error.SetErrorString("Couldn't malloc: process doesn't exist, and this "406"memory must be in the process");407return LLDB_INVALID_ADDRESS;408}409break;410}411412lldb::addr_t mask = alignment - 1;413aligned_address = (allocation_address + mask) & (~mask);414415m_allocations.emplace(416std::piecewise_construct, std::forward_as_tuple(aligned_address),417std::forward_as_tuple(allocation_address, aligned_address,418allocation_size, permissions, alignment, policy));419420if (zero_memory) {421Status write_error;422std::vector<uint8_t> zero_buf(size, 0);423WriteMemory(aligned_address, zero_buf.data(), size, write_error);424}425426if (log) {427const char *policy_string;428429switch (policy) {430default:431policy_string = "<invalid policy>";432break;433case eAllocationPolicyHostOnly:434policy_string = "eAllocationPolicyHostOnly";435break;436case eAllocationPolicyProcessOnly:437policy_string = "eAllocationPolicyProcessOnly";438break;439case eAllocationPolicyMirror:440policy_string = "eAllocationPolicyMirror";441break;442}443444LLDB_LOGF(log,445"IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64446", %s) -> 0x%" PRIx64,447(uint64_t)allocation_size, (uint64_t)alignment,448(uint64_t)permissions, policy_string, aligned_address);449}450451return aligned_address;452}453454void IRMemoryMap::Leak(lldb::addr_t process_address, Status &error) {455error.Clear();456457AllocationMap::iterator iter = m_allocations.find(process_address);458459if (iter == m_allocations.end()) {460error.SetErrorToGenericError();461error.SetErrorString("Couldn't leak: allocation doesn't exist");462return;463}464465Allocation &allocation = iter->second;466467allocation.m_leak = true;468}469470void IRMemoryMap::Free(lldb::addr_t process_address, Status &error) {471error.Clear();472473AllocationMap::iterator iter = m_allocations.find(process_address);474475if (iter == m_allocations.end()) {476error.SetErrorToGenericError();477error.SetErrorString("Couldn't free: allocation doesn't exist");478return;479}480481Allocation &allocation = iter->second;482483switch (allocation.m_policy) {484default:485case eAllocationPolicyHostOnly: {486lldb::ProcessSP process_sp = m_process_wp.lock();487if (process_sp) {488if (process_sp->CanJIT() && process_sp->IsAlive())489process_sp->DeallocateMemory(490allocation.m_process_alloc); // FindSpace allocated this for real491}492493break;494}495case eAllocationPolicyMirror:496case eAllocationPolicyProcessOnly: {497lldb::ProcessSP process_sp = m_process_wp.lock();498if (process_sp)499process_sp->DeallocateMemory(allocation.m_process_alloc);500}501}502503if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {504LLDB_LOGF(log,505"IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64506"..0x%" PRIx64 ")",507(uint64_t)process_address, iter->second.m_process_start,508iter->second.m_process_start + iter->second.m_size);509}510511m_allocations.erase(iter);512}513514bool IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size) {515AllocationMap::iterator iter = FindAllocation(address, size);516if (iter == m_allocations.end())517return false;518519Allocation &al = iter->second;520521if (address > (al.m_process_start + al.m_size)) {522size = 0;523return false;524}525526if (address > al.m_process_start) {527int dif = address - al.m_process_start;528size = al.m_size - dif;529return true;530}531532size = al.m_size;533return true;534}535536void IRMemoryMap::WriteMemory(lldb::addr_t process_address,537const uint8_t *bytes, size_t size,538Status &error) {539error.Clear();540541AllocationMap::iterator iter = FindAllocation(process_address, size);542543if (iter == m_allocations.end()) {544lldb::ProcessSP process_sp = m_process_wp.lock();545546if (process_sp) {547process_sp->WriteMemory(process_address, bytes, size, error);548return;549}550551error.SetErrorToGenericError();552error.SetErrorString("Couldn't write: no allocation contains the target "553"range and the process doesn't exist");554return;555}556557Allocation &allocation = iter->second;558559uint64_t offset = process_address - allocation.m_process_start;560561lldb::ProcessSP process_sp;562563switch (allocation.m_policy) {564default:565error.SetErrorToGenericError();566error.SetErrorString("Couldn't write: invalid allocation policy");567return;568case eAllocationPolicyHostOnly:569if (!allocation.m_data.GetByteSize()) {570error.SetErrorToGenericError();571error.SetErrorString("Couldn't write: data buffer is empty");572return;573}574::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);575break;576case eAllocationPolicyMirror:577if (!allocation.m_data.GetByteSize()) {578error.SetErrorToGenericError();579error.SetErrorString("Couldn't write: data buffer is empty");580return;581}582::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);583process_sp = m_process_wp.lock();584if (process_sp) {585process_sp->WriteMemory(process_address, bytes, size, error);586if (!error.Success())587return;588}589break;590case eAllocationPolicyProcessOnly:591process_sp = m_process_wp.lock();592if (process_sp) {593process_sp->WriteMemory(process_address, bytes, size, error);594if (!error.Success())595return;596}597break;598}599600if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {601LLDB_LOGF(log,602"IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIxPTR603", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",604(uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,605(uint64_t)allocation.m_process_start,606(uint64_t)allocation.m_process_start +607(uint64_t)allocation.m_size);608}609}610611void IRMemoryMap::WriteScalarToMemory(lldb::addr_t process_address,612Scalar &scalar, size_t size,613Status &error) {614error.Clear();615616if (size == UINT32_MAX)617size = scalar.GetByteSize();618619if (size > 0) {620uint8_t buf[32];621const size_t mem_size =622scalar.GetAsMemoryData(buf, size, GetByteOrder(), error);623if (mem_size > 0) {624return WriteMemory(process_address, buf, mem_size, error);625} else {626error.SetErrorToGenericError();627error.SetErrorString(628"Couldn't write scalar: failed to get scalar as memory data");629}630} else {631error.SetErrorToGenericError();632error.SetErrorString("Couldn't write scalar: its size was zero");633}634}635636void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address,637lldb::addr_t address, Status &error) {638error.Clear();639640Scalar scalar(address);641642WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);643}644645void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address,646size_t size, Status &error) {647error.Clear();648649AllocationMap::iterator iter = FindAllocation(process_address, size);650651if (iter == m_allocations.end()) {652lldb::ProcessSP process_sp = m_process_wp.lock();653654if (process_sp) {655process_sp->ReadMemory(process_address, bytes, size, error);656return;657}658659lldb::TargetSP target_sp = m_target_wp.lock();660661if (target_sp) {662Address absolute_address(process_address);663target_sp->ReadMemory(absolute_address, bytes, size, error, true);664return;665}666667error.SetErrorToGenericError();668error.SetErrorString("Couldn't read: no allocation contains the target "669"range, and neither the process nor the target exist");670return;671}672673Allocation &allocation = iter->second;674675uint64_t offset = process_address - allocation.m_process_start;676677if (offset > allocation.m_size) {678error.SetErrorToGenericError();679error.SetErrorString("Couldn't read: data is not in the allocation");680return;681}682683lldb::ProcessSP process_sp;684685switch (allocation.m_policy) {686default:687error.SetErrorToGenericError();688error.SetErrorString("Couldn't read: invalid allocation policy");689return;690case eAllocationPolicyHostOnly:691if (!allocation.m_data.GetByteSize()) {692error.SetErrorToGenericError();693error.SetErrorString("Couldn't read: data buffer is empty");694return;695}696if (allocation.m_data.GetByteSize() < offset + size) {697error.SetErrorToGenericError();698error.SetErrorString("Couldn't read: not enough underlying data");699return;700}701702::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);703break;704case eAllocationPolicyMirror:705process_sp = m_process_wp.lock();706if (process_sp) {707process_sp->ReadMemory(process_address, bytes, size, error);708if (!error.Success())709return;710} else {711if (!allocation.m_data.GetByteSize()) {712error.SetErrorToGenericError();713error.SetErrorString("Couldn't read: data buffer is empty");714return;715}716::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);717}718break;719case eAllocationPolicyProcessOnly:720process_sp = m_process_wp.lock();721if (process_sp) {722process_sp->ReadMemory(process_address, bytes, size, error);723if (!error.Success())724return;725}726break;727}728729if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {730LLDB_LOGF(log,731"IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIxPTR732", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",733(uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,734(uint64_t)allocation.m_process_start,735(uint64_t)allocation.m_process_start +736(uint64_t)allocation.m_size);737}738}739740void IRMemoryMap::ReadScalarFromMemory(Scalar &scalar,741lldb::addr_t process_address,742size_t size, Status &error) {743error.Clear();744745if (size > 0) {746DataBufferHeap buf(size, 0);747ReadMemory(buf.GetBytes(), process_address, size, error);748749if (!error.Success())750return;751752DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(),753GetAddressByteSize());754755lldb::offset_t offset = 0;756757switch (size) {758default:759error.SetErrorToGenericError();760error.SetErrorStringWithFormat(761"Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);762return;763case 1:764scalar = extractor.GetU8(&offset);765break;766case 2:767scalar = extractor.GetU16(&offset);768break;769case 4:770scalar = extractor.GetU32(&offset);771break;772case 8:773scalar = extractor.GetU64(&offset);774break;775}776} else {777error.SetErrorToGenericError();778error.SetErrorString("Couldn't read scalar: its size was zero");779}780}781782void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t *address,783lldb::addr_t process_address,784Status &error) {785error.Clear();786787Scalar pointer_scalar;788ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(),789error);790791if (!error.Success())792return;793794*address = pointer_scalar.ULongLong();795}796797void IRMemoryMap::GetMemoryData(DataExtractor &extractor,798lldb::addr_t process_address, size_t size,799Status &error) {800error.Clear();801802if (size > 0) {803AllocationMap::iterator iter = FindAllocation(process_address, size);804805if (iter == m_allocations.end()) {806error.SetErrorToGenericError();807error.SetErrorStringWithFormat(808"Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64809")",810process_address, process_address + size);811return;812}813814Allocation &allocation = iter->second;815816switch (allocation.m_policy) {817default:818error.SetErrorToGenericError();819error.SetErrorString(820"Couldn't get memory data: invalid allocation policy");821return;822case eAllocationPolicyProcessOnly:823error.SetErrorToGenericError();824error.SetErrorString(825"Couldn't get memory data: memory is only in the target");826return;827case eAllocationPolicyMirror: {828lldb::ProcessSP process_sp = m_process_wp.lock();829830if (!allocation.m_data.GetByteSize()) {831error.SetErrorToGenericError();832error.SetErrorString("Couldn't get memory data: data buffer is empty");833return;834}835if (process_sp) {836process_sp->ReadMemory(allocation.m_process_start,837allocation.m_data.GetBytes(),838allocation.m_data.GetByteSize(), error);839if (!error.Success())840return;841uint64_t offset = process_address - allocation.m_process_start;842extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,843GetByteOrder(), GetAddressByteSize());844return;845}846} break;847case eAllocationPolicyHostOnly:848if (!allocation.m_data.GetByteSize()) {849error.SetErrorToGenericError();850error.SetErrorString("Couldn't get memory data: data buffer is empty");851return;852}853uint64_t offset = process_address - allocation.m_process_start;854extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,855GetByteOrder(), GetAddressByteSize());856return;857}858} else {859error.SetErrorToGenericError();860error.SetErrorString("Couldn't get memory data: its size was zero");861return;862}863}864865866