1 //===-- IRMemoryMap.cpp ---------------------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "lldb/Expression/IRMemoryMap.h"
10 #include "lldb/Target/MemoryRegionInfo.h"
11 #include "lldb/Target/Process.h"
12 #include "lldb/Target/Target.h"
13 #include "lldb/Utility/DataBufferHeap.h"
14 #include "lldb/Utility/DataExtractor.h"
15 #include "lldb/Utility/LLDBAssert.h"
16 #include "lldb/Utility/LLDBLog.h"
17 #include "lldb/Utility/Log.h"
18 #include "lldb/Utility/Scalar.h"
19 #include "lldb/Utility/Status.h"
21 using namespace lldb_private
;
23 IRMemoryMap::IRMemoryMap(lldb::TargetSP target_sp
) : m_target_wp(target_sp
) {
25 m_process_wp
= target_sp
->GetProcessSP();
28 IRMemoryMap::~IRMemoryMap() {
29 lldb::ProcessSP process_sp
= m_process_wp
.lock();
32 AllocationMap::iterator iter
;
36 while ((iter
= m_allocations
.begin()) != m_allocations
.end()) {
38 if (iter
->second
.m_leak
)
39 m_allocations
.erase(iter
);
41 Free(iter
->first
, err
);
46 lldb::addr_t
IRMemoryMap::FindSpace(size_t size
) {
47 // The FindSpace algorithm's job is to find a region of memory that the
48 // underlying process is unlikely to be using.
50 // The memory returned by this function will never be written to. The only
51 // point is that it should not shadow process memory if possible, so that
52 // expressions processing real values from the process do not use the wrong
55 // If the process can in fact allocate memory (CanJIT() lets us know this)
56 // then this can be accomplished just be allocating memory in the inferior.
57 // Then no guessing is required.
59 lldb::TargetSP target_sp
= m_target_wp
.lock();
60 lldb::ProcessSP process_sp
= m_process_wp
.lock();
62 const bool process_is_alive
= process_sp
&& process_sp
->IsAlive();
64 lldb::addr_t ret
= LLDB_INVALID_ADDRESS
;
68 if (process_is_alive
&& process_sp
->CanJIT()) {
71 ret
= process_sp
->AllocateMemory(size
, lldb::ePermissionsReadable
|
72 lldb::ePermissionsWritable
,
75 if (!alloc_error
.Success())
76 return LLDB_INVALID_ADDRESS
;
81 // At this point we know that we need to hunt.
83 // First, go to the end of the existing allocations we've made if there are
84 // any allocations. Otherwise start at the beginning of memory.
86 if (m_allocations
.empty()) {
89 auto back
= m_allocations
.rbegin();
90 lldb::addr_t addr
= back
->first
;
91 size_t alloc_size
= back
->second
.m_size
;
92 ret
= llvm::alignTo(addr
+ alloc_size
, 4096);
95 uint64_t end_of_memory
;
96 switch (GetAddressByteSize()) {
98 end_of_memory
= 0xffffull
;
101 end_of_memory
= 0xffffffffull
;
104 end_of_memory
= 0xffffffffffffffffull
;
107 lldbassert(false && "Invalid address size.");
108 return LLDB_INVALID_ADDRESS
;
111 // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped
112 // regions, walk forward through memory until a region is found that has
113 // adequate space for our allocation.
114 if (process_is_alive
) {
115 MemoryRegionInfo region_info
;
116 Status err
= process_sp
->GetMemoryRegionInfo(ret
, region_info
);
119 if (region_info
.GetReadable() != MemoryRegionInfo::OptionalBool::eNo
||
120 region_info
.GetWritable() != MemoryRegionInfo::OptionalBool::eNo
||
121 region_info
.GetExecutable() !=
122 MemoryRegionInfo::OptionalBool::eNo
) {
123 if (region_info
.GetRange().GetRangeEnd() - 1 >= end_of_memory
) {
124 ret
= LLDB_INVALID_ADDRESS
;
127 ret
= region_info
.GetRange().GetRangeEnd();
129 } else if (ret
+ size
< region_info
.GetRange().GetRangeEnd()) {
132 // ret stays the same. We just need to walk a bit further.
135 err
= process_sp
->GetMemoryRegionInfo(
136 region_info
.GetRange().GetRangeEnd(), region_info
);
138 lldbassert(0 && "GetMemoryRegionInfo() succeeded, then failed");
139 ret
= LLDB_INVALID_ADDRESS
;
146 // We've tried our algorithm, and it didn't work. Now we have to reset back
147 // to the end of the allocations we've already reported, or use a 'sensible'
148 // default if this is our first allocation.
149 if (m_allocations
.empty()) {
150 uint64_t alloc_address
= target_sp
->GetExprAllocAddress();
151 if (alloc_address
> 0) {
152 if (alloc_address
>= end_of_memory
) {
153 lldbassert(0 && "The allocation address for expression evaluation must "
154 "be within process address space");
155 return LLDB_INVALID_ADDRESS
;
159 uint32_t address_byte_size
= GetAddressByteSize();
160 if (address_byte_size
!= UINT32_MAX
) {
161 switch (address_byte_size
) {
169 ret
= 0xdead0fff00000000ull
;
172 lldbassert(false && "Invalid address size.");
173 return LLDB_INVALID_ADDRESS
;
178 auto back
= m_allocations
.rbegin();
179 lldb::addr_t addr
= back
->first
;
180 size_t alloc_size
= back
->second
.m_size
;
181 uint64_t align
= target_sp
->GetExprAllocAlign();
184 ret
= llvm::alignTo(addr
+ alloc_size
, align
);
190 IRMemoryMap::AllocationMap::iterator
191 IRMemoryMap::FindAllocation(lldb::addr_t addr
, size_t size
) {
192 if (addr
== LLDB_INVALID_ADDRESS
)
193 return m_allocations
.end();
195 AllocationMap::iterator iter
= m_allocations
.lower_bound(addr
);
197 if (iter
== m_allocations
.end() || iter
->first
> addr
) {
198 if (iter
== m_allocations
.begin())
199 return m_allocations
.end();
203 if (iter
->first
<= addr
&& iter
->first
+ iter
->second
.m_size
>= addr
+ size
)
206 return m_allocations
.end();
209 bool IRMemoryMap::IntersectsAllocation(lldb::addr_t addr
, size_t size
) const {
210 if (addr
== LLDB_INVALID_ADDRESS
)
213 AllocationMap::const_iterator iter
= m_allocations
.lower_bound(addr
);
215 // Since we only know that the returned interval begins at a location greater
216 // than or equal to where the given interval begins, it's possible that the
217 // given interval intersects either the returned interval or the previous
218 // interval. Thus, we need to check both. Note that we only need to check
219 // these two intervals. Since all intervals are disjoint it is not possible
220 // that an adjacent interval does not intersect, but a non-adjacent interval
222 if (iter
!= m_allocations
.end()) {
223 if (AllocationsIntersect(addr
, size
, iter
->second
.m_process_start
,
224 iter
->second
.m_size
))
228 if (iter
!= m_allocations
.begin()) {
230 if (AllocationsIntersect(addr
, size
, iter
->second
.m_process_start
,
231 iter
->second
.m_size
))
238 bool IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1
, size_t size1
,
239 lldb::addr_t addr2
, size_t size2
) {
240 // Given two half open intervals [A, B) and [X, Y), the only 6 permutations
241 // that satisfy A<B and X<Y are the following:
243 // A X B Y (intersects)
244 // A X Y B (intersects)
245 // X A B Y (intersects)
246 // X A Y B (intersects)
248 // The first is B <= X, and the last is Y <= A. So the condition is !(B <= X
249 // || Y <= A)), or (X < B && A < Y)
250 return (addr2
< (addr1
+ size1
)) && (addr1
< (addr2
+ size2
));
253 lldb::ByteOrder
IRMemoryMap::GetByteOrder() {
254 lldb::ProcessSP process_sp
= m_process_wp
.lock();
257 return process_sp
->GetByteOrder();
259 lldb::TargetSP target_sp
= m_target_wp
.lock();
262 return target_sp
->GetArchitecture().GetByteOrder();
264 return lldb::eByteOrderInvalid
;
267 uint32_t IRMemoryMap::GetAddressByteSize() {
268 lldb::ProcessSP process_sp
= m_process_wp
.lock();
271 return process_sp
->GetAddressByteSize();
273 lldb::TargetSP target_sp
= m_target_wp
.lock();
276 return target_sp
->GetArchitecture().GetAddressByteSize();
281 ExecutionContextScope
*IRMemoryMap::GetBestExecutionContextScope() const {
282 lldb::ProcessSP process_sp
= m_process_wp
.lock();
285 return process_sp
.get();
287 lldb::TargetSP target_sp
= m_target_wp
.lock();
290 return target_sp
.get();
295 IRMemoryMap::Allocation::Allocation(lldb::addr_t process_alloc
,
296 lldb::addr_t process_start
, size_t size
,
297 uint32_t permissions
, uint8_t alignment
,
298 AllocationPolicy policy
)
299 : m_process_alloc(process_alloc
), m_process_start(process_start
),
300 m_size(size
), m_policy(policy
), m_leak(false), m_permissions(permissions
),
301 m_alignment(alignment
) {
304 llvm_unreachable("Invalid AllocationPolicy");
305 case eAllocationPolicyHostOnly
:
306 case eAllocationPolicyMirror
:
307 m_data
.SetByteSize(size
);
309 case eAllocationPolicyProcessOnly
:
314 lldb::addr_t
IRMemoryMap::Malloc(size_t size
, uint8_t alignment
,
315 uint32_t permissions
, AllocationPolicy policy
,
316 bool zero_memory
, Status
&error
) {
317 lldb_private::Log
*log(GetLog(LLDBLog::Expressions
));
320 lldb::ProcessSP process_sp
;
321 lldb::addr_t allocation_address
= LLDB_INVALID_ADDRESS
;
322 lldb::addr_t aligned_address
= LLDB_INVALID_ADDRESS
;
324 size_t allocation_size
;
327 // FIXME: Malloc(0) should either return an invalid address or assert, in
328 // order to cut down on unnecessary allocations.
329 allocation_size
= alignment
;
331 // Round up the requested size to an aligned value.
332 allocation_size
= llvm::alignTo(size
, alignment
);
334 // The process page cache does not see the requested alignment. We can't
335 // assume its result will be any more than 1-byte aligned. To work around
336 // this, request `alignment - 1` additional bytes.
337 allocation_size
+= alignment
- 1;
342 error
.SetErrorToGenericError();
343 error
.SetErrorString("Couldn't malloc: invalid allocation policy");
344 return LLDB_INVALID_ADDRESS
;
345 case eAllocationPolicyHostOnly
:
346 allocation_address
= FindSpace(allocation_size
);
347 if (allocation_address
== LLDB_INVALID_ADDRESS
) {
348 error
.SetErrorToGenericError();
349 error
.SetErrorString("Couldn't malloc: address space is full");
350 return LLDB_INVALID_ADDRESS
;
353 case eAllocationPolicyMirror
:
354 process_sp
= m_process_wp
.lock();
356 "IRMemoryMap::%s process_sp=0x%" PRIxPTR
357 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s",
358 __FUNCTION__
, reinterpret_cast<uintptr_t>(process_sp
.get()),
359 process_sp
&& process_sp
->CanJIT() ? "true" : "false",
360 process_sp
&& process_sp
->IsAlive() ? "true" : "false");
361 if (process_sp
&& process_sp
->CanJIT() && process_sp
->IsAlive()) {
364 process_sp
->AllocateMemory(allocation_size
, permissions
, error
);
367 process_sp
->CallocateMemory(allocation_size
, permissions
, error
);
369 if (!error
.Success())
370 return LLDB_INVALID_ADDRESS
;
373 "IRMemoryMap::%s switching to eAllocationPolicyHostOnly "
374 "due to failed condition (see previous expr log message)",
376 policy
= eAllocationPolicyHostOnly
;
377 allocation_address
= FindSpace(allocation_size
);
378 if (allocation_address
== LLDB_INVALID_ADDRESS
) {
379 error
.SetErrorToGenericError();
380 error
.SetErrorString("Couldn't malloc: address space is full");
381 return LLDB_INVALID_ADDRESS
;
385 case eAllocationPolicyProcessOnly
:
386 process_sp
= m_process_wp
.lock();
388 if (process_sp
->CanJIT() && process_sp
->IsAlive()) {
391 process_sp
->AllocateMemory(allocation_size
, permissions
, error
);
394 process_sp
->CallocateMemory(allocation_size
, permissions
, error
);
396 if (!error
.Success())
397 return LLDB_INVALID_ADDRESS
;
399 error
.SetErrorToGenericError();
400 error
.SetErrorString(
401 "Couldn't malloc: process doesn't support allocating memory");
402 return LLDB_INVALID_ADDRESS
;
405 error
.SetErrorToGenericError();
406 error
.SetErrorString("Couldn't malloc: process doesn't exist, and this "
407 "memory must be in the process");
408 return LLDB_INVALID_ADDRESS
;
413 lldb::addr_t mask
= alignment
- 1;
414 aligned_address
= (allocation_address
+ mask
) & (~mask
);
416 m_allocations
.emplace(
417 std::piecewise_construct
, std::forward_as_tuple(aligned_address
),
418 std::forward_as_tuple(allocation_address
, aligned_address
,
419 allocation_size
, permissions
, alignment
, policy
));
423 std::vector
<uint8_t> zero_buf(size
, 0);
424 WriteMemory(aligned_address
, zero_buf
.data(), size
, write_error
);
428 const char *policy_string
;
432 policy_string
= "<invalid policy>";
434 case eAllocationPolicyHostOnly
:
435 policy_string
= "eAllocationPolicyHostOnly";
437 case eAllocationPolicyProcessOnly
:
438 policy_string
= "eAllocationPolicyProcessOnly";
440 case eAllocationPolicyMirror
:
441 policy_string
= "eAllocationPolicyMirror";
446 "IRMemoryMap::Malloc (%" PRIu64
", 0x%" PRIx64
", 0x%" PRIx64
447 ", %s) -> 0x%" PRIx64
,
448 (uint64_t)allocation_size
, (uint64_t)alignment
,
449 (uint64_t)permissions
, policy_string
, aligned_address
);
452 return aligned_address
;
455 void IRMemoryMap::Leak(lldb::addr_t process_address
, Status
&error
) {
458 AllocationMap::iterator iter
= m_allocations
.find(process_address
);
460 if (iter
== m_allocations
.end()) {
461 error
.SetErrorToGenericError();
462 error
.SetErrorString("Couldn't leak: allocation doesn't exist");
466 Allocation
&allocation
= iter
->second
;
468 allocation
.m_leak
= true;
471 void IRMemoryMap::Free(lldb::addr_t process_address
, Status
&error
) {
474 AllocationMap::iterator iter
= m_allocations
.find(process_address
);
476 if (iter
== m_allocations
.end()) {
477 error
.SetErrorToGenericError();
478 error
.SetErrorString("Couldn't free: allocation doesn't exist");
482 Allocation
&allocation
= iter
->second
;
484 switch (allocation
.m_policy
) {
486 case eAllocationPolicyHostOnly
: {
487 lldb::ProcessSP process_sp
= m_process_wp
.lock();
489 if (process_sp
->CanJIT() && process_sp
->IsAlive())
490 process_sp
->DeallocateMemory(
491 allocation
.m_process_alloc
); // FindSpace allocated this for real
496 case eAllocationPolicyMirror
:
497 case eAllocationPolicyProcessOnly
: {
498 lldb::ProcessSP process_sp
= m_process_wp
.lock();
500 process_sp
->DeallocateMemory(allocation
.m_process_alloc
);
504 if (lldb_private::Log
*log
= GetLog(LLDBLog::Expressions
)) {
506 "IRMemoryMap::Free (0x%" PRIx64
") freed [0x%" PRIx64
508 (uint64_t)process_address
, iter
->second
.m_process_start
,
509 iter
->second
.m_process_start
+ iter
->second
.m_size
);
512 m_allocations
.erase(iter
);
515 bool IRMemoryMap::GetAllocSize(lldb::addr_t address
, size_t &size
) {
516 AllocationMap::iterator iter
= FindAllocation(address
, size
);
517 if (iter
== m_allocations
.end())
520 Allocation
&al
= iter
->second
;
522 if (address
> (al
.m_process_start
+ al
.m_size
)) {
527 if (address
> al
.m_process_start
) {
528 int dif
= address
- al
.m_process_start
;
529 size
= al
.m_size
- dif
;
537 void IRMemoryMap::WriteMemory(lldb::addr_t process_address
,
538 const uint8_t *bytes
, size_t size
,
542 AllocationMap::iterator iter
= FindAllocation(process_address
, size
);
544 if (iter
== m_allocations
.end()) {
545 lldb::ProcessSP process_sp
= m_process_wp
.lock();
548 process_sp
->WriteMemory(process_address
, bytes
, size
, error
);
552 error
.SetErrorToGenericError();
553 error
.SetErrorString("Couldn't write: no allocation contains the target "
554 "range and the process doesn't exist");
558 Allocation
&allocation
= iter
->second
;
560 uint64_t offset
= process_address
- allocation
.m_process_start
;
562 lldb::ProcessSP process_sp
;
564 switch (allocation
.m_policy
) {
566 error
.SetErrorToGenericError();
567 error
.SetErrorString("Couldn't write: invalid allocation policy");
569 case eAllocationPolicyHostOnly
:
570 if (!allocation
.m_data
.GetByteSize()) {
571 error
.SetErrorToGenericError();
572 error
.SetErrorString("Couldn't write: data buffer is empty");
575 ::memcpy(allocation
.m_data
.GetBytes() + offset
, bytes
, size
);
577 case eAllocationPolicyMirror
:
578 if (!allocation
.m_data
.GetByteSize()) {
579 error
.SetErrorToGenericError();
580 error
.SetErrorString("Couldn't write: data buffer is empty");
583 ::memcpy(allocation
.m_data
.GetBytes() + offset
, bytes
, size
);
584 process_sp
= m_process_wp
.lock();
586 process_sp
->WriteMemory(process_address
, bytes
, size
, error
);
587 if (!error
.Success())
591 case eAllocationPolicyProcessOnly
:
592 process_sp
= m_process_wp
.lock();
594 process_sp
->WriteMemory(process_address
, bytes
, size
, error
);
595 if (!error
.Success())
601 if (lldb_private::Log
*log
= GetLog(LLDBLog::Expressions
)) {
603 "IRMemoryMap::WriteMemory (0x%" PRIx64
", 0x%" PRIxPTR
604 ", 0x%" PRId64
") went to [0x%" PRIx64
"..0x%" PRIx64
")",
605 (uint64_t)process_address
, reinterpret_cast<uintptr_t>(bytes
), (uint64_t)size
,
606 (uint64_t)allocation
.m_process_start
,
607 (uint64_t)allocation
.m_process_start
+
608 (uint64_t)allocation
.m_size
);
612 void IRMemoryMap::WriteScalarToMemory(lldb::addr_t process_address
,
613 Scalar
&scalar
, size_t size
,
617 if (size
== UINT32_MAX
)
618 size
= scalar
.GetByteSize();
622 const size_t mem_size
=
623 scalar
.GetAsMemoryData(buf
, size
, GetByteOrder(), error
);
625 return WriteMemory(process_address
, buf
, mem_size
, error
);
627 error
.SetErrorToGenericError();
628 error
.SetErrorString(
629 "Couldn't write scalar: failed to get scalar as memory data");
632 error
.SetErrorToGenericError();
633 error
.SetErrorString("Couldn't write scalar: its size was zero");
637 void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address
,
638 lldb::addr_t address
, Status
&error
) {
641 Scalar
scalar(address
);
643 WriteScalarToMemory(process_address
, scalar
, GetAddressByteSize(), error
);
646 void IRMemoryMap::ReadMemory(uint8_t *bytes
, lldb::addr_t process_address
,
647 size_t size
, Status
&error
) {
650 AllocationMap::iterator iter
= FindAllocation(process_address
, size
);
652 if (iter
== m_allocations
.end()) {
653 lldb::ProcessSP process_sp
= m_process_wp
.lock();
656 process_sp
->ReadMemory(process_address
, bytes
, size
, error
);
660 lldb::TargetSP target_sp
= m_target_wp
.lock();
663 Address
absolute_address(process_address
);
664 target_sp
->ReadMemory(absolute_address
, bytes
, size
, error
, true);
668 error
.SetErrorToGenericError();
669 error
.SetErrorString("Couldn't read: no allocation contains the target "
670 "range, and neither the process nor the target exist");
674 Allocation
&allocation
= iter
->second
;
676 uint64_t offset
= process_address
- allocation
.m_process_start
;
678 if (offset
> allocation
.m_size
) {
679 error
.SetErrorToGenericError();
680 error
.SetErrorString("Couldn't read: data is not in the allocation");
684 lldb::ProcessSP process_sp
;
686 switch (allocation
.m_policy
) {
688 error
.SetErrorToGenericError();
689 error
.SetErrorString("Couldn't read: invalid allocation policy");
691 case eAllocationPolicyHostOnly
:
692 if (!allocation
.m_data
.GetByteSize()) {
693 error
.SetErrorToGenericError();
694 error
.SetErrorString("Couldn't read: data buffer is empty");
697 if (allocation
.m_data
.GetByteSize() < offset
+ size
) {
698 error
.SetErrorToGenericError();
699 error
.SetErrorString("Couldn't read: not enough underlying data");
703 ::memcpy(bytes
, allocation
.m_data
.GetBytes() + offset
, size
);
705 case eAllocationPolicyMirror
:
706 process_sp
= m_process_wp
.lock();
708 process_sp
->ReadMemory(process_address
, bytes
, size
, error
);
709 if (!error
.Success())
712 if (!allocation
.m_data
.GetByteSize()) {
713 error
.SetErrorToGenericError();
714 error
.SetErrorString("Couldn't read: data buffer is empty");
717 ::memcpy(bytes
, allocation
.m_data
.GetBytes() + offset
, size
);
720 case eAllocationPolicyProcessOnly
:
721 process_sp
= m_process_wp
.lock();
723 process_sp
->ReadMemory(process_address
, bytes
, size
, error
);
724 if (!error
.Success())
730 if (lldb_private::Log
*log
= GetLog(LLDBLog::Expressions
)) {
732 "IRMemoryMap::ReadMemory (0x%" PRIx64
", 0x%" PRIxPTR
733 ", 0x%" PRId64
") came from [0x%" PRIx64
"..0x%" PRIx64
")",
734 (uint64_t)process_address
, reinterpret_cast<uintptr_t>(bytes
), (uint64_t)size
,
735 (uint64_t)allocation
.m_process_start
,
736 (uint64_t)allocation
.m_process_start
+
737 (uint64_t)allocation
.m_size
);
741 void IRMemoryMap::ReadScalarFromMemory(Scalar
&scalar
,
742 lldb::addr_t process_address
,
743 size_t size
, Status
&error
) {
747 DataBufferHeap
buf(size
, 0);
748 ReadMemory(buf
.GetBytes(), process_address
, size
, error
);
750 if (!error
.Success())
753 DataExtractor
extractor(buf
.GetBytes(), buf
.GetByteSize(), GetByteOrder(),
754 GetAddressByteSize());
756 lldb::offset_t offset
= 0;
760 error
.SetErrorToGenericError();
761 error
.SetErrorStringWithFormat(
762 "Couldn't read scalar: unsupported size %" PRIu64
, (uint64_t)size
);
765 scalar
= extractor
.GetU8(&offset
);
768 scalar
= extractor
.GetU16(&offset
);
771 scalar
= extractor
.GetU32(&offset
);
774 scalar
= extractor
.GetU64(&offset
);
778 error
.SetErrorToGenericError();
779 error
.SetErrorString("Couldn't read scalar: its size was zero");
783 void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t
*address
,
784 lldb::addr_t process_address
,
788 Scalar pointer_scalar
;
789 ReadScalarFromMemory(pointer_scalar
, process_address
, GetAddressByteSize(),
792 if (!error
.Success())
795 *address
= pointer_scalar
.ULongLong();
798 void IRMemoryMap::GetMemoryData(DataExtractor
&extractor
,
799 lldb::addr_t process_address
, size_t size
,
804 AllocationMap::iterator iter
= FindAllocation(process_address
, size
);
806 if (iter
== m_allocations
.end()) {
807 error
.SetErrorToGenericError();
808 error
.SetErrorStringWithFormat(
809 "Couldn't find an allocation containing [0x%" PRIx64
"..0x%" PRIx64
811 process_address
, process_address
+ size
);
815 Allocation
&allocation
= iter
->second
;
817 switch (allocation
.m_policy
) {
819 error
.SetErrorToGenericError();
820 error
.SetErrorString(
821 "Couldn't get memory data: invalid allocation policy");
823 case eAllocationPolicyProcessOnly
:
824 error
.SetErrorToGenericError();
825 error
.SetErrorString(
826 "Couldn't get memory data: memory is only in the target");
828 case eAllocationPolicyMirror
: {
829 lldb::ProcessSP process_sp
= m_process_wp
.lock();
831 if (!allocation
.m_data
.GetByteSize()) {
832 error
.SetErrorToGenericError();
833 error
.SetErrorString("Couldn't get memory data: data buffer is empty");
837 process_sp
->ReadMemory(allocation
.m_process_start
,
838 allocation
.m_data
.GetBytes(),
839 allocation
.m_data
.GetByteSize(), error
);
840 if (!error
.Success())
842 uint64_t offset
= process_address
- allocation
.m_process_start
;
843 extractor
= DataExtractor(allocation
.m_data
.GetBytes() + offset
, size
,
844 GetByteOrder(), GetAddressByteSize());
848 case eAllocationPolicyHostOnly
:
849 if (!allocation
.m_data
.GetByteSize()) {
850 error
.SetErrorToGenericError();
851 error
.SetErrorString("Couldn't get memory data: data buffer is empty");
854 uint64_t offset
= process_address
- allocation
.m_process_start
;
855 extractor
= DataExtractor(allocation
.m_data
.GetBytes() + offset
, size
,
856 GetByteOrder(), GetAddressByteSize());
860 error
.SetErrorToGenericError();
861 error
.SetErrorString("Couldn't get memory data: its size was zero");