1cfca06d7SDimitry Andric //===-- IRMemoryMap.cpp ---------------------------------------------------===//
2f034231aSEd Maste //
35f29bb8aSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45f29bb8aSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
55f29bb8aSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f034231aSEd Maste //
7f034231aSEd Maste //===----------------------------------------------------------------------===//
8f034231aSEd Maste
914f1b3e8SDimitry Andric #include "lldb/Expression/IRMemoryMap.h"
10f3fbd1c0SDimitry Andric #include "lldb/Target/MemoryRegionInfo.h"
11f034231aSEd Maste #include "lldb/Target/Process.h"
12f034231aSEd Maste #include "lldb/Target/Target.h"
1374a628f7SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
1474a628f7SDimitry Andric #include "lldb/Utility/DataExtractor.h"
15f3fbd1c0SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
16145449b1SDimitry Andric #include "lldb/Utility/LLDBLog.h"
1774a628f7SDimitry Andric #include "lldb/Utility/Log.h"
1894994d37SDimitry Andric #include "lldb/Utility/Scalar.h"
19b76161e4SDimitry Andric #include "lldb/Utility/Status.h"
20f034231aSEd Maste
21f034231aSEd Maste using namespace lldb_private;
22f034231aSEd Maste
IRMemoryMap(lldb::TargetSP target_sp)2314f1b3e8SDimitry Andric IRMemoryMap::IRMemoryMap(lldb::TargetSP target_sp) : m_target_wp(target_sp) {
24f034231aSEd Maste if (target_sp)
25f034231aSEd Maste m_process_wp = target_sp->GetProcessSP();
26f034231aSEd Maste }
27f034231aSEd Maste
~IRMemoryMap()2814f1b3e8SDimitry Andric IRMemoryMap::~IRMemoryMap() {
29f034231aSEd Maste lldb::ProcessSP process_sp = m_process_wp.lock();
30f034231aSEd Maste
3114f1b3e8SDimitry Andric if (process_sp) {
32f034231aSEd Maste AllocationMap::iterator iter;
33f034231aSEd Maste
34b76161e4SDimitry Andric Status err;
35f034231aSEd Maste
3614f1b3e8SDimitry Andric while ((iter = m_allocations.begin()) != m_allocations.end()) {
37f034231aSEd Maste err.Clear();
38f034231aSEd Maste if (iter->second.m_leak)
39f034231aSEd Maste m_allocations.erase(iter);
40f034231aSEd Maste else
41f034231aSEd Maste Free(iter->first, err);
42f034231aSEd Maste }
43f034231aSEd Maste }
44f034231aSEd Maste }
45f034231aSEd Maste
FindSpace(size_t size)4614f1b3e8SDimitry Andric lldb::addr_t IRMemoryMap::FindSpace(size_t size) {
47f3fbd1c0SDimitry Andric // The FindSpace algorithm's job is to find a region of memory that the
48f3fbd1c0SDimitry Andric // underlying process is unlikely to be using.
49f3fbd1c0SDimitry Andric //
50f3fbd1c0SDimitry Andric // The memory returned by this function will never be written to. The only
51f3fbd1c0SDimitry Andric // point is that it should not shadow process memory if possible, so that
52f73363f1SDimitry Andric // expressions processing real values from the process do not use the wrong
53f73363f1SDimitry Andric // data.
54f3fbd1c0SDimitry Andric //
55f3fbd1c0SDimitry Andric // If the process can in fact allocate memory (CanJIT() lets us know this)
56f3fbd1c0SDimitry Andric // then this can be accomplished just be allocating memory in the inferior.
57f3fbd1c0SDimitry Andric // Then no guessing is required.
58f3fbd1c0SDimitry Andric
59f034231aSEd Maste lldb::TargetSP target_sp = m_target_wp.lock();
60f034231aSEd Maste lldb::ProcessSP process_sp = m_process_wp.lock();
61f034231aSEd Maste
62f3fbd1c0SDimitry Andric const bool process_is_alive = process_sp && process_sp->IsAlive();
63f3fbd1c0SDimitry Andric
64f034231aSEd Maste lldb::addr_t ret = LLDB_INVALID_ADDRESS;
650cac4ca3SEd Maste if (size == 0)
660cac4ca3SEd Maste return ret;
67f034231aSEd Maste
6814f1b3e8SDimitry Andric if (process_is_alive && process_sp->CanJIT()) {
69b76161e4SDimitry Andric Status alloc_error;
70f034231aSEd Maste
7114f1b3e8SDimitry Andric ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable |
7214f1b3e8SDimitry Andric lldb::ePermissionsWritable,
7314f1b3e8SDimitry Andric alloc_error);
74f034231aSEd Maste
75f034231aSEd Maste if (!alloc_error.Success())
76f034231aSEd Maste return LLDB_INVALID_ADDRESS;
77f034231aSEd Maste else
78f034231aSEd Maste return ret;
79f034231aSEd Maste }
80f034231aSEd Maste
81f3fbd1c0SDimitry Andric // At this point we know that we need to hunt.
82f3fbd1c0SDimitry Andric //
83f3fbd1c0SDimitry Andric // First, go to the end of the existing allocations we've made if there are
84f3fbd1c0SDimitry Andric // any allocations. Otherwise start at the beginning of memory.
85f3fbd1c0SDimitry Andric
8614f1b3e8SDimitry Andric if (m_allocations.empty()) {
87f3fbd1c0SDimitry Andric ret = 0x0;
8814f1b3e8SDimitry Andric } else {
890cac4ca3SEd Maste auto back = m_allocations.rbegin();
900cac4ca3SEd Maste lldb::addr_t addr = back->first;
910cac4ca3SEd Maste size_t alloc_size = back->second.m_size;
92f3fbd1c0SDimitry Andric ret = llvm::alignTo(addr + alloc_size, 4096);
93f3fbd1c0SDimitry Andric }
94f3fbd1c0SDimitry Andric
957fa27ce4SDimitry Andric uint64_t end_of_memory;
967fa27ce4SDimitry Andric switch (GetAddressByteSize()) {
977fa27ce4SDimitry Andric case 2:
987fa27ce4SDimitry Andric end_of_memory = 0xffffull;
997fa27ce4SDimitry Andric break;
1007fa27ce4SDimitry Andric case 4:
1017fa27ce4SDimitry Andric end_of_memory = 0xffffffffull;
1027fa27ce4SDimitry Andric break;
1037fa27ce4SDimitry Andric case 8:
1047fa27ce4SDimitry Andric end_of_memory = 0xffffffffffffffffull;
1057fa27ce4SDimitry Andric break;
1067fa27ce4SDimitry Andric default:
1077fa27ce4SDimitry Andric lldbassert(false && "Invalid address size.");
1087fa27ce4SDimitry Andric return LLDB_INVALID_ADDRESS;
1097fa27ce4SDimitry Andric }
1107fa27ce4SDimitry Andric
111f3fbd1c0SDimitry Andric // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped
112f73363f1SDimitry Andric // regions, walk forward through memory until a region is found that has
113f73363f1SDimitry Andric // adequate space for our allocation.
11414f1b3e8SDimitry Andric if (process_is_alive) {
115f3fbd1c0SDimitry Andric MemoryRegionInfo region_info;
116b76161e4SDimitry Andric Status err = process_sp->GetMemoryRegionInfo(ret, region_info);
11714f1b3e8SDimitry Andric if (err.Success()) {
11814f1b3e8SDimitry Andric while (true) {
119f3fbd1c0SDimitry Andric if (region_info.GetReadable() != MemoryRegionInfo::OptionalBool::eNo ||
120f3fbd1c0SDimitry Andric region_info.GetWritable() != MemoryRegionInfo::OptionalBool::eNo ||
12114f1b3e8SDimitry Andric region_info.GetExecutable() !=
12214f1b3e8SDimitry Andric MemoryRegionInfo::OptionalBool::eNo) {
12314f1b3e8SDimitry Andric if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory) {
124f3fbd1c0SDimitry Andric ret = LLDB_INVALID_ADDRESS;
125f3fbd1c0SDimitry Andric break;
12614f1b3e8SDimitry Andric } else {
127f3fbd1c0SDimitry Andric ret = region_info.GetRange().GetRangeEnd();
128f3fbd1c0SDimitry Andric }
12914f1b3e8SDimitry Andric } else if (ret + size < region_info.GetRange().GetRangeEnd()) {
130f3fbd1c0SDimitry Andric return ret;
13114f1b3e8SDimitry Andric } else {
132f3fbd1c0SDimitry Andric // ret stays the same. We just need to walk a bit further.
133f3fbd1c0SDimitry Andric }
134f3fbd1c0SDimitry Andric
13514f1b3e8SDimitry Andric err = process_sp->GetMemoryRegionInfo(
13614f1b3e8SDimitry Andric region_info.GetRange().GetRangeEnd(), region_info);
13714f1b3e8SDimitry Andric if (err.Fail()) {
138a4092fcbSDimitry Andric lldbassert(0 && "GetMemoryRegionInfo() succeeded, then failed");
139f3fbd1c0SDimitry Andric ret = LLDB_INVALID_ADDRESS;
140f3fbd1c0SDimitry Andric break;
141f3fbd1c0SDimitry Andric }
142f3fbd1c0SDimitry Andric }
143f3fbd1c0SDimitry Andric }
144f3fbd1c0SDimitry Andric }
145f3fbd1c0SDimitry Andric
146f3fbd1c0SDimitry Andric // We've tried our algorithm, and it didn't work. Now we have to reset back
147f3fbd1c0SDimitry Andric // to the end of the allocations we've already reported, or use a 'sensible'
148f3fbd1c0SDimitry Andric // default if this is our first allocation.
14914f1b3e8SDimitry Andric if (m_allocations.empty()) {
1507fa27ce4SDimitry Andric uint64_t alloc_address = target_sp->GetExprAllocAddress();
1517fa27ce4SDimitry Andric if (alloc_address > 0) {
1527fa27ce4SDimitry Andric if (alloc_address >= end_of_memory) {
1537fa27ce4SDimitry Andric lldbassert(0 && "The allocation address for expression evaluation must "
1547fa27ce4SDimitry Andric "be within process address space");
1557fa27ce4SDimitry Andric return LLDB_INVALID_ADDRESS;
1567fa27ce4SDimitry Andric }
1577fa27ce4SDimitry Andric ret = alloc_address;
1587fa27ce4SDimitry Andric } else {
159f3fbd1c0SDimitry Andric uint32_t address_byte_size = GetAddressByteSize();
16014f1b3e8SDimitry Andric if (address_byte_size != UINT32_MAX) {
16114f1b3e8SDimitry Andric switch (address_byte_size) {
1627fa27ce4SDimitry Andric case 2:
1637fa27ce4SDimitry Andric ret = 0x8000ull;
164f3fbd1c0SDimitry Andric break;
165f3fbd1c0SDimitry Andric case 4:
166f3fbd1c0SDimitry Andric ret = 0xee000000ull;
167f3fbd1c0SDimitry Andric break;
1687fa27ce4SDimitry Andric case 8:
1697fa27ce4SDimitry Andric ret = 0xdead0fff00000000ull;
170f3fbd1c0SDimitry Andric break;
1717fa27ce4SDimitry Andric default:
1727fa27ce4SDimitry Andric lldbassert(false && "Invalid address size.");
1737fa27ce4SDimitry Andric return LLDB_INVALID_ADDRESS;
1747fa27ce4SDimitry Andric }
175f3fbd1c0SDimitry Andric }
176f3fbd1c0SDimitry Andric }
17714f1b3e8SDimitry Andric } else {
178f3fbd1c0SDimitry Andric auto back = m_allocations.rbegin();
179f3fbd1c0SDimitry Andric lldb::addr_t addr = back->first;
180f3fbd1c0SDimitry Andric size_t alloc_size = back->second.m_size;
1817fa27ce4SDimitry Andric uint64_t align = target_sp->GetExprAllocAlign();
1827fa27ce4SDimitry Andric if (align == 0)
1837fa27ce4SDimitry Andric align = 4096;
1847fa27ce4SDimitry Andric ret = llvm::alignTo(addr + alloc_size, align);
185f034231aSEd Maste }
186f034231aSEd Maste
187f034231aSEd Maste return ret;
188f034231aSEd Maste }
189f034231aSEd Maste
190f034231aSEd Maste IRMemoryMap::AllocationMap::iterator
FindAllocation(lldb::addr_t addr,size_t size)19114f1b3e8SDimitry Andric IRMemoryMap::FindAllocation(lldb::addr_t addr, size_t size) {
192f034231aSEd Maste if (addr == LLDB_INVALID_ADDRESS)
193f034231aSEd Maste return m_allocations.end();
194f034231aSEd Maste
195f034231aSEd Maste AllocationMap::iterator iter = m_allocations.lower_bound(addr);
196f034231aSEd Maste
19714f1b3e8SDimitry Andric if (iter == m_allocations.end() || iter->first > addr) {
198f034231aSEd Maste if (iter == m_allocations.begin())
199f034231aSEd Maste return m_allocations.end();
200f034231aSEd Maste iter--;
201f034231aSEd Maste }
202f034231aSEd Maste
203f034231aSEd Maste if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
204f034231aSEd Maste return iter;
205f034231aSEd Maste
206f034231aSEd Maste return m_allocations.end();
207f034231aSEd Maste }
208f034231aSEd Maste
IntersectsAllocation(lldb::addr_t addr,size_t size) const20914f1b3e8SDimitry Andric bool IRMemoryMap::IntersectsAllocation(lldb::addr_t addr, size_t size) const {
210f034231aSEd Maste if (addr == LLDB_INVALID_ADDRESS)
211f034231aSEd Maste return false;
212f034231aSEd Maste
2130cac4ca3SEd Maste AllocationMap::const_iterator iter = m_allocations.lower_bound(addr);
214f034231aSEd Maste
21514f1b3e8SDimitry Andric // Since we only know that the returned interval begins at a location greater
216f73363f1SDimitry Andric // than or equal to where the given interval begins, it's possible that the
217f73363f1SDimitry Andric // given interval intersects either the returned interval or the previous
218f73363f1SDimitry Andric // interval. Thus, we need to check both. Note that we only need to check
219f73363f1SDimitry Andric // these two intervals. Since all intervals are disjoint it is not possible
220f73363f1SDimitry Andric // that an adjacent interval does not intersect, but a non-adjacent interval
221f73363f1SDimitry Andric // does intersect.
2220cac4ca3SEd Maste if (iter != m_allocations.end()) {
22314f1b3e8SDimitry Andric if (AllocationsIntersect(addr, size, iter->second.m_process_start,
22414f1b3e8SDimitry Andric iter->second.m_size))
225f034231aSEd Maste return true;
2260cac4ca3SEd Maste }
227f034231aSEd Maste
2280cac4ca3SEd Maste if (iter != m_allocations.begin()) {
2290cac4ca3SEd Maste --iter;
23014f1b3e8SDimitry Andric if (AllocationsIntersect(addr, size, iter->second.m_process_start,
23114f1b3e8SDimitry Andric iter->second.m_size))
2320cac4ca3SEd Maste return true;
233f034231aSEd Maste }
234f034231aSEd Maste
235f034231aSEd Maste return false;
236f034231aSEd Maste }
237f034231aSEd Maste
AllocationsIntersect(lldb::addr_t addr1,size_t size1,lldb::addr_t addr2,size_t size2)23814f1b3e8SDimitry Andric bool IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1,
23914f1b3e8SDimitry Andric lldb::addr_t addr2, size_t size2) {
24014f1b3e8SDimitry Andric // Given two half open intervals [A, B) and [X, Y), the only 6 permutations
241f73363f1SDimitry Andric // that satisfy A<B and X<Y are the following:
2420cac4ca3SEd Maste // A B X Y
2430cac4ca3SEd Maste // A X B Y (intersects)
2440cac4ca3SEd Maste // A X Y B (intersects)
2450cac4ca3SEd Maste // X A B Y (intersects)
2460cac4ca3SEd Maste // X A Y B (intersects)
2470cac4ca3SEd Maste // X Y A B
248f73363f1SDimitry Andric // The first is B <= X, and the last is Y <= A. So the condition is !(B <= X
249f73363f1SDimitry Andric // || Y <= A)), or (X < B && A < Y)
2500cac4ca3SEd Maste return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
2510cac4ca3SEd Maste }
2520cac4ca3SEd Maste
GetByteOrder()25314f1b3e8SDimitry Andric lldb::ByteOrder IRMemoryMap::GetByteOrder() {
254f034231aSEd Maste lldb::ProcessSP process_sp = m_process_wp.lock();
255f034231aSEd Maste
256f034231aSEd Maste if (process_sp)
257f034231aSEd Maste return process_sp->GetByteOrder();
258f034231aSEd Maste
259f034231aSEd Maste lldb::TargetSP target_sp = m_target_wp.lock();
260f034231aSEd Maste
261f034231aSEd Maste if (target_sp)
262f034231aSEd Maste return target_sp->GetArchitecture().GetByteOrder();
263f034231aSEd Maste
264f034231aSEd Maste return lldb::eByteOrderInvalid;
265f034231aSEd Maste }
266f034231aSEd Maste
GetAddressByteSize()26714f1b3e8SDimitry Andric uint32_t IRMemoryMap::GetAddressByteSize() {
268f034231aSEd Maste lldb::ProcessSP process_sp = m_process_wp.lock();
269f034231aSEd Maste
270f034231aSEd Maste if (process_sp)
271f034231aSEd Maste return process_sp->GetAddressByteSize();
272f034231aSEd Maste
273f034231aSEd Maste lldb::TargetSP target_sp = m_target_wp.lock();
274f034231aSEd Maste
275f034231aSEd Maste if (target_sp)
276f034231aSEd Maste return target_sp->GetArchitecture().GetAddressByteSize();
277f034231aSEd Maste
278f034231aSEd Maste return UINT32_MAX;
279f034231aSEd Maste }
280f034231aSEd Maste
GetBestExecutionContextScope() const28114f1b3e8SDimitry Andric ExecutionContextScope *IRMemoryMap::GetBestExecutionContextScope() const {
282f034231aSEd Maste lldb::ProcessSP process_sp = m_process_wp.lock();
283f034231aSEd Maste
284f034231aSEd Maste if (process_sp)
285f034231aSEd Maste return process_sp.get();
286f034231aSEd Maste
287f034231aSEd Maste lldb::TargetSP target_sp = m_target_wp.lock();
288f034231aSEd Maste
289f034231aSEd Maste if (target_sp)
290f034231aSEd Maste return target_sp.get();
291f034231aSEd Maste
2925f29bb8aSDimitry Andric return nullptr;
293f034231aSEd Maste }
294f034231aSEd Maste
Allocation(lldb::addr_t process_alloc,lldb::addr_t process_start,size_t size,uint32_t permissions,uint8_t alignment,AllocationPolicy policy)295f034231aSEd Maste IRMemoryMap::Allocation::Allocation(lldb::addr_t process_alloc,
29614f1b3e8SDimitry Andric lldb::addr_t process_start, size_t size,
29714f1b3e8SDimitry Andric uint32_t permissions, uint8_t alignment,
29814f1b3e8SDimitry Andric AllocationPolicy policy)
29914f1b3e8SDimitry Andric : m_process_alloc(process_alloc), m_process_start(process_start),
30094994d37SDimitry Andric m_size(size), m_policy(policy), m_leak(false), m_permissions(permissions),
30194994d37SDimitry Andric m_alignment(alignment) {
30214f1b3e8SDimitry Andric switch (policy) {
303f034231aSEd Maste default:
3045f29bb8aSDimitry Andric llvm_unreachable("Invalid AllocationPolicy");
305f034231aSEd Maste case eAllocationPolicyHostOnly:
306f034231aSEd Maste case eAllocationPolicyMirror:
307f034231aSEd Maste m_data.SetByteSize(size);
30894994d37SDimitry Andric break;
30994994d37SDimitry Andric case eAllocationPolicyProcessOnly:
310f034231aSEd Maste break;
311f034231aSEd Maste }
312f034231aSEd Maste }
313f034231aSEd Maste
Malloc(size_t size,uint8_t alignment,uint32_t permissions,AllocationPolicy policy,bool zero_memory,Status & error)31414f1b3e8SDimitry Andric lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment,
31514f1b3e8SDimitry Andric uint32_t permissions, AllocationPolicy policy,
316b76161e4SDimitry Andric bool zero_memory, Status &error) {
317145449b1SDimitry Andric lldb_private::Log *log(GetLog(LLDBLog::Expressions));
318f034231aSEd Maste error.Clear();
319f034231aSEd Maste
320f034231aSEd Maste lldb::ProcessSP process_sp;
321f034231aSEd Maste lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
322f034231aSEd Maste lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
323f034231aSEd Maste
324f034231aSEd Maste size_t allocation_size;
325f034231aSEd Maste
326f73363f1SDimitry Andric if (size == 0) {
327f73363f1SDimitry Andric // FIXME: Malloc(0) should either return an invalid address or assert, in
328f73363f1SDimitry Andric // order to cut down on unnecessary allocations.
329f034231aSEd Maste allocation_size = alignment;
330f73363f1SDimitry Andric } else {
331f73363f1SDimitry Andric // Round up the requested size to an aligned value.
332f73363f1SDimitry Andric allocation_size = llvm::alignTo(size, alignment);
333f73363f1SDimitry Andric
334f73363f1SDimitry Andric // The process page cache does not see the requested alignment. We can't
335f73363f1SDimitry Andric // assume its result will be any more than 1-byte aligned. To work around
336f73363f1SDimitry Andric // this, request `alignment - 1` additional bytes.
337f73363f1SDimitry Andric allocation_size += alignment - 1;
338f73363f1SDimitry Andric }
339f034231aSEd Maste
34014f1b3e8SDimitry Andric switch (policy) {
341f034231aSEd Maste default:
342f034231aSEd Maste error.SetErrorToGenericError();
343f034231aSEd Maste error.SetErrorString("Couldn't malloc: invalid allocation policy");
344f034231aSEd Maste return LLDB_INVALID_ADDRESS;
345f034231aSEd Maste case eAllocationPolicyHostOnly:
346f034231aSEd Maste allocation_address = FindSpace(allocation_size);
34714f1b3e8SDimitry Andric if (allocation_address == LLDB_INVALID_ADDRESS) {
348f034231aSEd Maste error.SetErrorToGenericError();
349f034231aSEd Maste error.SetErrorString("Couldn't malloc: address space is full");
350f034231aSEd Maste return LLDB_INVALID_ADDRESS;
351f034231aSEd Maste }
352f034231aSEd Maste break;
353f034231aSEd Maste case eAllocationPolicyMirror:
354f034231aSEd Maste process_sp = m_process_wp.lock();
355ead24645SDimitry Andric LLDB_LOGF(log,
356706b4fc4SDimitry Andric "IRMemoryMap::%s process_sp=0x%" PRIxPTR
35714f1b3e8SDimitry Andric ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s",
358706b4fc4SDimitry Andric __FUNCTION__, reinterpret_cast<uintptr_t>(process_sp.get()),
35914f1b3e8SDimitry Andric process_sp && process_sp->CanJIT() ? "true" : "false",
36014f1b3e8SDimitry Andric process_sp && process_sp->IsAlive() ? "true" : "false");
36114f1b3e8SDimitry Andric if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) {
362e81d9d49SDimitry Andric if (!zero_memory)
36314f1b3e8SDimitry Andric allocation_address =
36414f1b3e8SDimitry Andric process_sp->AllocateMemory(allocation_size, permissions, error);
365e81d9d49SDimitry Andric else
36614f1b3e8SDimitry Andric allocation_address =
36714f1b3e8SDimitry Andric process_sp->CallocateMemory(allocation_size, permissions, error);
368e81d9d49SDimitry Andric
369f034231aSEd Maste if (!error.Success())
370f034231aSEd Maste return LLDB_INVALID_ADDRESS;
37114f1b3e8SDimitry Andric } else {
372ead24645SDimitry Andric LLDB_LOGF(log,
373ead24645SDimitry Andric "IRMemoryMap::%s switching to eAllocationPolicyHostOnly "
37414f1b3e8SDimitry Andric "due to failed condition (see previous expr log message)",
37514f1b3e8SDimitry Andric __FUNCTION__);
376f034231aSEd Maste policy = eAllocationPolicyHostOnly;
377f034231aSEd Maste allocation_address = FindSpace(allocation_size);
37814f1b3e8SDimitry Andric if (allocation_address == LLDB_INVALID_ADDRESS) {
379f034231aSEd Maste error.SetErrorToGenericError();
380f034231aSEd Maste error.SetErrorString("Couldn't malloc: address space is full");
381f034231aSEd Maste return LLDB_INVALID_ADDRESS;
382f034231aSEd Maste }
383f034231aSEd Maste }
384f034231aSEd Maste break;
385f034231aSEd Maste case eAllocationPolicyProcessOnly:
386f034231aSEd Maste process_sp = m_process_wp.lock();
38714f1b3e8SDimitry Andric if (process_sp) {
38814f1b3e8SDimitry Andric if (process_sp->CanJIT() && process_sp->IsAlive()) {
389e81d9d49SDimitry Andric if (!zero_memory)
39014f1b3e8SDimitry Andric allocation_address =
39114f1b3e8SDimitry Andric process_sp->AllocateMemory(allocation_size, permissions, error);
392e81d9d49SDimitry Andric else
39314f1b3e8SDimitry Andric allocation_address =
39414f1b3e8SDimitry Andric process_sp->CallocateMemory(allocation_size, permissions, error);
395e81d9d49SDimitry Andric
396f034231aSEd Maste if (!error.Success())
397f034231aSEd Maste return LLDB_INVALID_ADDRESS;
39814f1b3e8SDimitry Andric } else {
399f034231aSEd Maste error.SetErrorToGenericError();
40014f1b3e8SDimitry Andric error.SetErrorString(
40114f1b3e8SDimitry Andric "Couldn't malloc: process doesn't support allocating memory");
402f034231aSEd Maste return LLDB_INVALID_ADDRESS;
403f034231aSEd Maste }
40414f1b3e8SDimitry Andric } else {
405f034231aSEd Maste error.SetErrorToGenericError();
40614f1b3e8SDimitry Andric error.SetErrorString("Couldn't malloc: process doesn't exist, and this "
40714f1b3e8SDimitry Andric "memory must be in the process");
408f034231aSEd Maste return LLDB_INVALID_ADDRESS;
409f034231aSEd Maste }
410f034231aSEd Maste break;
411f034231aSEd Maste }
412f034231aSEd Maste
413f034231aSEd Maste lldb::addr_t mask = alignment - 1;
414f034231aSEd Maste aligned_address = (allocation_address + mask) & (~mask);
415f034231aSEd Maste
41694994d37SDimitry Andric m_allocations.emplace(
41794994d37SDimitry Andric std::piecewise_construct, std::forward_as_tuple(aligned_address),
41894994d37SDimitry Andric std::forward_as_tuple(allocation_address, aligned_address,
41994994d37SDimitry Andric allocation_size, permissions, alignment, policy));
420f034231aSEd Maste
42114f1b3e8SDimitry Andric if (zero_memory) {
422b76161e4SDimitry Andric Status write_error;
423f3fbd1c0SDimitry Andric std::vector<uint8_t> zero_buf(size, 0);
424f3fbd1c0SDimitry Andric WriteMemory(aligned_address, zero_buf.data(), size, write_error);
425f3fbd1c0SDimitry Andric }
426f3fbd1c0SDimitry Andric
42714f1b3e8SDimitry Andric if (log) {
428f034231aSEd Maste const char *policy_string;
429f034231aSEd Maste
43014f1b3e8SDimitry Andric switch (policy) {
431f034231aSEd Maste default:
432f034231aSEd Maste policy_string = "<invalid policy>";
433f034231aSEd Maste break;
434f034231aSEd Maste case eAllocationPolicyHostOnly:
435f034231aSEd Maste policy_string = "eAllocationPolicyHostOnly";
436f034231aSEd Maste break;
437f034231aSEd Maste case eAllocationPolicyProcessOnly:
438f034231aSEd Maste policy_string = "eAllocationPolicyProcessOnly";
439f034231aSEd Maste break;
440f034231aSEd Maste case eAllocationPolicyMirror:
441f034231aSEd Maste policy_string = "eAllocationPolicyMirror";
442f034231aSEd Maste break;
443f034231aSEd Maste }
444f034231aSEd Maste
445ead24645SDimitry Andric LLDB_LOGF(log,
446ead24645SDimitry Andric "IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64
44714f1b3e8SDimitry Andric ", %s) -> 0x%" PRIx64,
44814f1b3e8SDimitry Andric (uint64_t)allocation_size, (uint64_t)alignment,
44914f1b3e8SDimitry Andric (uint64_t)permissions, policy_string, aligned_address);
450f034231aSEd Maste }
451f034231aSEd Maste
452f034231aSEd Maste return aligned_address;
453f034231aSEd Maste }
454f034231aSEd Maste
Leak(lldb::addr_t process_address,Status & error)455b76161e4SDimitry Andric void IRMemoryMap::Leak(lldb::addr_t process_address, Status &error) {
456f034231aSEd Maste error.Clear();
457f034231aSEd Maste
458f034231aSEd Maste AllocationMap::iterator iter = m_allocations.find(process_address);
459f034231aSEd Maste
46014f1b3e8SDimitry Andric if (iter == m_allocations.end()) {
461f034231aSEd Maste error.SetErrorToGenericError();
462f034231aSEd Maste error.SetErrorString("Couldn't leak: allocation doesn't exist");
463f034231aSEd Maste return;
464f034231aSEd Maste }
465f034231aSEd Maste
466f034231aSEd Maste Allocation &allocation = iter->second;
467f034231aSEd Maste
468f034231aSEd Maste allocation.m_leak = true;
469f034231aSEd Maste }
470f034231aSEd Maste
Free(lldb::addr_t process_address,Status & error)471b76161e4SDimitry Andric void IRMemoryMap::Free(lldb::addr_t process_address, Status &error) {
472f034231aSEd Maste error.Clear();
473f034231aSEd Maste
474f034231aSEd Maste AllocationMap::iterator iter = m_allocations.find(process_address);
475f034231aSEd Maste
47614f1b3e8SDimitry Andric if (iter == m_allocations.end()) {
477f034231aSEd Maste error.SetErrorToGenericError();
478f034231aSEd Maste error.SetErrorString("Couldn't free: allocation doesn't exist");
479f034231aSEd Maste return;
480f034231aSEd Maste }
481f034231aSEd Maste
482f034231aSEd Maste Allocation &allocation = iter->second;
483f034231aSEd Maste
48414f1b3e8SDimitry Andric switch (allocation.m_policy) {
485f034231aSEd Maste default:
48614f1b3e8SDimitry Andric case eAllocationPolicyHostOnly: {
487f034231aSEd Maste lldb::ProcessSP process_sp = m_process_wp.lock();
48814f1b3e8SDimitry Andric if (process_sp) {
489f034231aSEd Maste if (process_sp->CanJIT() && process_sp->IsAlive())
49014f1b3e8SDimitry Andric process_sp->DeallocateMemory(
49114f1b3e8SDimitry Andric allocation.m_process_alloc); // FindSpace allocated this for real
492f034231aSEd Maste }
493f034231aSEd Maste
494f034231aSEd Maste break;
495f034231aSEd Maste }
496f034231aSEd Maste case eAllocationPolicyMirror:
49714f1b3e8SDimitry Andric case eAllocationPolicyProcessOnly: {
498f034231aSEd Maste lldb::ProcessSP process_sp = m_process_wp.lock();
499f034231aSEd Maste if (process_sp)
500f034231aSEd Maste process_sp->DeallocateMemory(allocation.m_process_alloc);
501f034231aSEd Maste }
502f034231aSEd Maste }
503f034231aSEd Maste
504145449b1SDimitry Andric if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {
505ead24645SDimitry Andric LLDB_LOGF(log,
506ead24645SDimitry Andric "IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64
50714f1b3e8SDimitry Andric "..0x%" PRIx64 ")",
50814f1b3e8SDimitry Andric (uint64_t)process_address, iter->second.m_process_start,
509f034231aSEd Maste iter->second.m_process_start + iter->second.m_size);
510f034231aSEd Maste }
511f034231aSEd Maste
512f034231aSEd Maste m_allocations.erase(iter);
513f034231aSEd Maste }
514f034231aSEd Maste
GetAllocSize(lldb::addr_t address,size_t & size)51514f1b3e8SDimitry Andric bool IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size) {
516027f1c96SDimitry Andric AllocationMap::iterator iter = FindAllocation(address, size);
517027f1c96SDimitry Andric if (iter == m_allocations.end())
518027f1c96SDimitry Andric return false;
519027f1c96SDimitry Andric
520027f1c96SDimitry Andric Allocation &al = iter->second;
521027f1c96SDimitry Andric
52214f1b3e8SDimitry Andric if (address > (al.m_process_start + al.m_size)) {
523027f1c96SDimitry Andric size = 0;
524027f1c96SDimitry Andric return false;
525027f1c96SDimitry Andric }
526027f1c96SDimitry Andric
52714f1b3e8SDimitry Andric if (address > al.m_process_start) {
528027f1c96SDimitry Andric int dif = address - al.m_process_start;
529027f1c96SDimitry Andric size = al.m_size - dif;
530027f1c96SDimitry Andric return true;
531027f1c96SDimitry Andric }
532027f1c96SDimitry Andric
533027f1c96SDimitry Andric size = al.m_size;
534027f1c96SDimitry Andric return true;
535027f1c96SDimitry Andric }
536027f1c96SDimitry Andric
WriteMemory(lldb::addr_t process_address,const uint8_t * bytes,size_t size,Status & error)53714f1b3e8SDimitry Andric void IRMemoryMap::WriteMemory(lldb::addr_t process_address,
538b76161e4SDimitry Andric const uint8_t *bytes, size_t size,
539b76161e4SDimitry Andric Status &error) {
540f034231aSEd Maste error.Clear();
541f034231aSEd Maste
542f034231aSEd Maste AllocationMap::iterator iter = FindAllocation(process_address, size);
543f034231aSEd Maste
54414f1b3e8SDimitry Andric if (iter == m_allocations.end()) {
545f034231aSEd Maste lldb::ProcessSP process_sp = m_process_wp.lock();
546f034231aSEd Maste
54714f1b3e8SDimitry Andric if (process_sp) {
548f034231aSEd Maste process_sp->WriteMemory(process_address, bytes, size, error);
549f034231aSEd Maste return;
550f034231aSEd Maste }
551f034231aSEd Maste
552f034231aSEd Maste error.SetErrorToGenericError();
55314f1b3e8SDimitry Andric error.SetErrorString("Couldn't write: no allocation contains the target "
55414f1b3e8SDimitry Andric "range and the process doesn't exist");
555f034231aSEd Maste return;
556f034231aSEd Maste }
557f034231aSEd Maste
558f034231aSEd Maste Allocation &allocation = iter->second;
559f034231aSEd Maste
560f034231aSEd Maste uint64_t offset = process_address - allocation.m_process_start;
561f034231aSEd Maste
562f034231aSEd Maste lldb::ProcessSP process_sp;
563f034231aSEd Maste
56414f1b3e8SDimitry Andric switch (allocation.m_policy) {
565f034231aSEd Maste default:
566f034231aSEd Maste error.SetErrorToGenericError();
567f034231aSEd Maste error.SetErrorString("Couldn't write: invalid allocation policy");
568f034231aSEd Maste return;
569f034231aSEd Maste case eAllocationPolicyHostOnly:
57014f1b3e8SDimitry Andric if (!allocation.m_data.GetByteSize()) {
571f034231aSEd Maste error.SetErrorToGenericError();
572f034231aSEd Maste error.SetErrorString("Couldn't write: data buffer is empty");
573f034231aSEd Maste return;
574f034231aSEd Maste }
575f034231aSEd Maste ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
576f034231aSEd Maste break;
577f034231aSEd Maste case eAllocationPolicyMirror:
57814f1b3e8SDimitry Andric if (!allocation.m_data.GetByteSize()) {
579f034231aSEd Maste error.SetErrorToGenericError();
580f034231aSEd Maste error.SetErrorString("Couldn't write: data buffer is empty");
581f034231aSEd Maste return;
582f034231aSEd Maste }
583f034231aSEd Maste ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
584f034231aSEd Maste process_sp = m_process_wp.lock();
58514f1b3e8SDimitry Andric if (process_sp) {
586f034231aSEd Maste process_sp->WriteMemory(process_address, bytes, size, error);
587f034231aSEd Maste if (!error.Success())
588f034231aSEd Maste return;
589f034231aSEd Maste }
590f034231aSEd Maste break;
591f034231aSEd Maste case eAllocationPolicyProcessOnly:
592f034231aSEd Maste process_sp = m_process_wp.lock();
59314f1b3e8SDimitry Andric if (process_sp) {
594f034231aSEd Maste process_sp->WriteMemory(process_address, bytes, size, error);
595f034231aSEd Maste if (!error.Success())
596f034231aSEd Maste return;
597f034231aSEd Maste }
598f034231aSEd Maste break;
599f034231aSEd Maste }
600f034231aSEd Maste
601145449b1SDimitry Andric if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {
602ead24645SDimitry Andric LLDB_LOGF(log,
603706b4fc4SDimitry Andric "IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIxPTR
60414f1b3e8SDimitry Andric ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
605706b4fc4SDimitry Andric (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,
606f034231aSEd Maste (uint64_t)allocation.m_process_start,
60714f1b3e8SDimitry Andric (uint64_t)allocation.m_process_start +
60814f1b3e8SDimitry Andric (uint64_t)allocation.m_size);
609f034231aSEd Maste }
610f034231aSEd Maste }
611f034231aSEd Maste
WriteScalarToMemory(lldb::addr_t process_address,Scalar & scalar,size_t size,Status & error)61214f1b3e8SDimitry Andric void IRMemoryMap::WriteScalarToMemory(lldb::addr_t process_address,
61314f1b3e8SDimitry Andric Scalar &scalar, size_t size,
614b76161e4SDimitry Andric Status &error) {
615f034231aSEd Maste error.Clear();
616f034231aSEd Maste
617f034231aSEd Maste if (size == UINT32_MAX)
618f034231aSEd Maste size = scalar.GetByteSize();
619f034231aSEd Maste
62014f1b3e8SDimitry Andric if (size > 0) {
621f034231aSEd Maste uint8_t buf[32];
62214f1b3e8SDimitry Andric const size_t mem_size =
62314f1b3e8SDimitry Andric scalar.GetAsMemoryData(buf, size, GetByteOrder(), error);
62414f1b3e8SDimitry Andric if (mem_size > 0) {
625f034231aSEd Maste return WriteMemory(process_address, buf, mem_size, error);
62614f1b3e8SDimitry Andric } else {
627f034231aSEd Maste error.SetErrorToGenericError();
62814f1b3e8SDimitry Andric error.SetErrorString(
62914f1b3e8SDimitry Andric "Couldn't write scalar: failed to get scalar as memory data");
630f034231aSEd Maste }
63114f1b3e8SDimitry Andric } else {
632f034231aSEd Maste error.SetErrorToGenericError();
633f034231aSEd Maste error.SetErrorString("Couldn't write scalar: its size was zero");
634f034231aSEd Maste }
635f034231aSEd Maste }
636f034231aSEd Maste
WritePointerToMemory(lldb::addr_t process_address,lldb::addr_t address,Status & error)63714f1b3e8SDimitry Andric void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address,
638b76161e4SDimitry Andric lldb::addr_t address, Status &error) {
639f034231aSEd Maste error.Clear();
640f034231aSEd Maste
641f034231aSEd Maste Scalar scalar(address);
642f034231aSEd Maste
643f034231aSEd Maste WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
644f034231aSEd Maste }
645f034231aSEd Maste
ReadMemory(uint8_t * bytes,lldb::addr_t process_address,size_t size,Status & error)64614f1b3e8SDimitry Andric void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address,
647b76161e4SDimitry Andric size_t size, Status &error) {
648f034231aSEd Maste error.Clear();
649f034231aSEd Maste
650f034231aSEd Maste AllocationMap::iterator iter = FindAllocation(process_address, size);
651f034231aSEd Maste
65214f1b3e8SDimitry Andric if (iter == m_allocations.end()) {
653f034231aSEd Maste lldb::ProcessSP process_sp = m_process_wp.lock();
654f034231aSEd Maste
65514f1b3e8SDimitry Andric if (process_sp) {
656f034231aSEd Maste process_sp->ReadMemory(process_address, bytes, size, error);
657f034231aSEd Maste return;
658f034231aSEd Maste }
659f034231aSEd Maste
660f034231aSEd Maste lldb::TargetSP target_sp = m_target_wp.lock();
661f034231aSEd Maste
66214f1b3e8SDimitry Andric if (target_sp) {
663f034231aSEd Maste Address absolute_address(process_address);
664344a3780SDimitry Andric target_sp->ReadMemory(absolute_address, bytes, size, error, true);
665f034231aSEd Maste return;
666f034231aSEd Maste }
667f034231aSEd Maste
668f034231aSEd Maste error.SetErrorToGenericError();
66914f1b3e8SDimitry Andric error.SetErrorString("Couldn't read: no allocation contains the target "
67014f1b3e8SDimitry Andric "range, and neither the process nor the target exist");
671f034231aSEd Maste return;
672f034231aSEd Maste }
673f034231aSEd Maste
674f034231aSEd Maste Allocation &allocation = iter->second;
675f034231aSEd Maste
676f034231aSEd Maste uint64_t offset = process_address - allocation.m_process_start;
677f034231aSEd Maste
67814f1b3e8SDimitry Andric if (offset > allocation.m_size) {
6790cac4ca3SEd Maste error.SetErrorToGenericError();
6800cac4ca3SEd Maste error.SetErrorString("Couldn't read: data is not in the allocation");
6810cac4ca3SEd Maste return;
6820cac4ca3SEd Maste }
6830cac4ca3SEd Maste
684f034231aSEd Maste lldb::ProcessSP process_sp;
685f034231aSEd Maste
68614f1b3e8SDimitry Andric switch (allocation.m_policy) {
687f034231aSEd Maste default:
688f034231aSEd Maste error.SetErrorToGenericError();
689f034231aSEd Maste error.SetErrorString("Couldn't read: invalid allocation policy");
690f034231aSEd Maste return;
691f034231aSEd Maste case eAllocationPolicyHostOnly:
69214f1b3e8SDimitry Andric if (!allocation.m_data.GetByteSize()) {
693f034231aSEd Maste error.SetErrorToGenericError();
694f034231aSEd Maste error.SetErrorString("Couldn't read: data buffer is empty");
695f034231aSEd Maste return;
696f034231aSEd Maste }
69714f1b3e8SDimitry Andric if (allocation.m_data.GetByteSize() < offset + size) {
6980cac4ca3SEd Maste error.SetErrorToGenericError();
6990cac4ca3SEd Maste error.SetErrorString("Couldn't read: not enough underlying data");
7000cac4ca3SEd Maste return;
7010cac4ca3SEd Maste }
7020cac4ca3SEd Maste
703f034231aSEd Maste ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
704f034231aSEd Maste break;
705f034231aSEd Maste case eAllocationPolicyMirror:
706f034231aSEd Maste process_sp = m_process_wp.lock();
70714f1b3e8SDimitry Andric if (process_sp) {
708f034231aSEd Maste process_sp->ReadMemory(process_address, bytes, size, error);
709f034231aSEd Maste if (!error.Success())
710f034231aSEd Maste return;
71114f1b3e8SDimitry Andric } else {
71214f1b3e8SDimitry Andric if (!allocation.m_data.GetByteSize()) {
713f034231aSEd Maste error.SetErrorToGenericError();
714f034231aSEd Maste error.SetErrorString("Couldn't read: data buffer is empty");
715f034231aSEd Maste return;
716f034231aSEd Maste }
717f034231aSEd Maste ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
718f034231aSEd Maste }
719f034231aSEd Maste break;
720f034231aSEd Maste case eAllocationPolicyProcessOnly:
721f034231aSEd Maste process_sp = m_process_wp.lock();
72214f1b3e8SDimitry Andric if (process_sp) {
723f034231aSEd Maste process_sp->ReadMemory(process_address, bytes, size, error);
724f034231aSEd Maste if (!error.Success())
725f034231aSEd Maste return;
726f034231aSEd Maste }
727f034231aSEd Maste break;
728f034231aSEd Maste }
729f034231aSEd Maste
730145449b1SDimitry Andric if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {
731ead24645SDimitry Andric LLDB_LOGF(log,
732706b4fc4SDimitry Andric "IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIxPTR
73314f1b3e8SDimitry Andric ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
734706b4fc4SDimitry Andric (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,
735f034231aSEd Maste (uint64_t)allocation.m_process_start,
73614f1b3e8SDimitry Andric (uint64_t)allocation.m_process_start +
73714f1b3e8SDimitry Andric (uint64_t)allocation.m_size);
738f034231aSEd Maste }
739f034231aSEd Maste }
740f034231aSEd Maste
ReadScalarFromMemory(Scalar & scalar,lldb::addr_t process_address,size_t size,Status & error)74114f1b3e8SDimitry Andric void IRMemoryMap::ReadScalarFromMemory(Scalar &scalar,
74214f1b3e8SDimitry Andric lldb::addr_t process_address,
743b76161e4SDimitry Andric size_t size, Status &error) {
744f034231aSEd Maste error.Clear();
745f034231aSEd Maste
74614f1b3e8SDimitry Andric if (size > 0) {
747f034231aSEd Maste DataBufferHeap buf(size, 0);
748f034231aSEd Maste ReadMemory(buf.GetBytes(), process_address, size, error);
749f034231aSEd Maste
750f034231aSEd Maste if (!error.Success())
751f034231aSEd Maste return;
752f034231aSEd Maste
75314f1b3e8SDimitry Andric DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(),
75414f1b3e8SDimitry Andric GetAddressByteSize());
755f034231aSEd Maste
756f034231aSEd Maste lldb::offset_t offset = 0;
757f034231aSEd Maste
75814f1b3e8SDimitry Andric switch (size) {
759f034231aSEd Maste default:
760f034231aSEd Maste error.SetErrorToGenericError();
76114f1b3e8SDimitry Andric error.SetErrorStringWithFormat(
76214f1b3e8SDimitry Andric "Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
763f034231aSEd Maste return;
76414f1b3e8SDimitry Andric case 1:
76514f1b3e8SDimitry Andric scalar = extractor.GetU8(&offset);
76614f1b3e8SDimitry Andric break;
76714f1b3e8SDimitry Andric case 2:
76814f1b3e8SDimitry Andric scalar = extractor.GetU16(&offset);
76914f1b3e8SDimitry Andric break;
77014f1b3e8SDimitry Andric case 4:
77114f1b3e8SDimitry Andric scalar = extractor.GetU32(&offset);
77214f1b3e8SDimitry Andric break;
77314f1b3e8SDimitry Andric case 8:
77414f1b3e8SDimitry Andric scalar = extractor.GetU64(&offset);
77514f1b3e8SDimitry Andric break;
776f034231aSEd Maste }
77714f1b3e8SDimitry Andric } else {
778f034231aSEd Maste error.SetErrorToGenericError();
779f034231aSEd Maste error.SetErrorString("Couldn't read scalar: its size was zero");
780f034231aSEd Maste }
781f034231aSEd Maste }
782f034231aSEd Maste
ReadPointerFromMemory(lldb::addr_t * address,lldb::addr_t process_address,Status & error)78314f1b3e8SDimitry Andric void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t *address,
78414f1b3e8SDimitry Andric lldb::addr_t process_address,
785b76161e4SDimitry Andric Status &error) {
786f034231aSEd Maste error.Clear();
787f034231aSEd Maste
788f034231aSEd Maste Scalar pointer_scalar;
78914f1b3e8SDimitry Andric ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(),
79014f1b3e8SDimitry Andric error);
791f034231aSEd Maste
792f034231aSEd Maste if (!error.Success())
793f034231aSEd Maste return;
794f034231aSEd Maste
795f034231aSEd Maste *address = pointer_scalar.ULongLong();
796f034231aSEd Maste }
797f034231aSEd Maste
GetMemoryData(DataExtractor & extractor,lldb::addr_t process_address,size_t size,Status & error)79814f1b3e8SDimitry Andric void IRMemoryMap::GetMemoryData(DataExtractor &extractor,
79914f1b3e8SDimitry Andric lldb::addr_t process_address, size_t size,
800b76161e4SDimitry Andric Status &error) {
801f034231aSEd Maste error.Clear();
802f034231aSEd Maste
80314f1b3e8SDimitry Andric if (size > 0) {
804f034231aSEd Maste AllocationMap::iterator iter = FindAllocation(process_address, size);
805f034231aSEd Maste
80614f1b3e8SDimitry Andric if (iter == m_allocations.end()) {
807f034231aSEd Maste error.SetErrorToGenericError();
80814f1b3e8SDimitry Andric error.SetErrorStringWithFormat(
80914f1b3e8SDimitry Andric "Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64
81014f1b3e8SDimitry Andric ")",
81114f1b3e8SDimitry Andric process_address, process_address + size);
812f034231aSEd Maste return;
813f034231aSEd Maste }
814f034231aSEd Maste
815f034231aSEd Maste Allocation &allocation = iter->second;
816f034231aSEd Maste
81714f1b3e8SDimitry Andric switch (allocation.m_policy) {
818f034231aSEd Maste default:
819f034231aSEd Maste error.SetErrorToGenericError();
82014f1b3e8SDimitry Andric error.SetErrorString(
82114f1b3e8SDimitry Andric "Couldn't get memory data: invalid allocation policy");
822f034231aSEd Maste return;
823f034231aSEd Maste case eAllocationPolicyProcessOnly:
824f034231aSEd Maste error.SetErrorToGenericError();
82514f1b3e8SDimitry Andric error.SetErrorString(
82614f1b3e8SDimitry Andric "Couldn't get memory data: memory is only in the target");
827f034231aSEd Maste return;
82814f1b3e8SDimitry Andric case eAllocationPolicyMirror: {
829f034231aSEd Maste lldb::ProcessSP process_sp = m_process_wp.lock();
830f034231aSEd Maste
83114f1b3e8SDimitry Andric if (!allocation.m_data.GetByteSize()) {
832f034231aSEd Maste error.SetErrorToGenericError();
833f034231aSEd Maste error.SetErrorString("Couldn't get memory data: data buffer is empty");
834f034231aSEd Maste return;
835f034231aSEd Maste }
83614f1b3e8SDimitry Andric if (process_sp) {
83714f1b3e8SDimitry Andric process_sp->ReadMemory(allocation.m_process_start,
83814f1b3e8SDimitry Andric allocation.m_data.GetBytes(),
83914f1b3e8SDimitry Andric allocation.m_data.GetByteSize(), error);
840f034231aSEd Maste if (!error.Success())
841f034231aSEd Maste return;
842f034231aSEd Maste uint64_t offset = process_address - allocation.m_process_start;
84314f1b3e8SDimitry Andric extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
84414f1b3e8SDimitry Andric GetByteOrder(), GetAddressByteSize());
845f034231aSEd Maste return;
846f034231aSEd Maste }
84714f1b3e8SDimitry Andric } break;
848f034231aSEd Maste case eAllocationPolicyHostOnly:
84914f1b3e8SDimitry Andric if (!allocation.m_data.GetByteSize()) {
850f034231aSEd Maste error.SetErrorToGenericError();
851f034231aSEd Maste error.SetErrorString("Couldn't get memory data: data buffer is empty");
852f034231aSEd Maste return;
853f034231aSEd Maste }
854f034231aSEd Maste uint64_t offset = process_address - allocation.m_process_start;
85514f1b3e8SDimitry Andric extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
85614f1b3e8SDimitry Andric GetByteOrder(), GetAddressByteSize());
857f034231aSEd Maste return;
858f034231aSEd Maste }
85914f1b3e8SDimitry Andric } else {
860f034231aSEd Maste error.SetErrorToGenericError();
861f034231aSEd Maste error.SetErrorString("Couldn't get memory data: its size was zero");
862f034231aSEd Maste return;
863f034231aSEd Maste }
864f034231aSEd Maste }
865