xref: /src/contrib/llvm-project/lldb/source/Expression/IRMemoryMap.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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