1ac7ddfbfSEd Maste //===-- IRMemoryMap.cpp -----------------------------------------*- C++ -*-===//
2ac7ddfbfSEd Maste //
3ac7ddfbfSEd Maste //                     The LLVM Compiler Infrastructure
4ac7ddfbfSEd Maste //
5ac7ddfbfSEd Maste // This file is distributed under the University of Illinois Open Source
6ac7ddfbfSEd Maste // License. See LICENSE.TXT for details.
7ac7ddfbfSEd Maste //
8ac7ddfbfSEd Maste //===----------------------------------------------------------------------===//
9ac7ddfbfSEd Maste 
10435933ddSDimitry Andric #include "lldb/Expression/IRMemoryMap.h"
114bb0738eSEd Maste #include "lldb/Target/MemoryRegionInfo.h"
12ac7ddfbfSEd Maste #include "lldb/Target/Process.h"
13ac7ddfbfSEd Maste #include "lldb/Target/Target.h"
14f678e45dSDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
15f678e45dSDimitry Andric #include "lldb/Utility/DataExtractor.h"
164bb0738eSEd Maste #include "lldb/Utility/LLDBAssert.h"
17f678e45dSDimitry Andric #include "lldb/Utility/Log.h"
18*b5893f02SDimitry Andric #include "lldb/Utility/Scalar.h"
195517e702SDimitry Andric #include "lldb/Utility/Status.h"
20ac7ddfbfSEd Maste 
21ac7ddfbfSEd Maste using namespace lldb_private;
22ac7ddfbfSEd Maste 
IRMemoryMap(lldb::TargetSP target_sp)23435933ddSDimitry Andric IRMemoryMap::IRMemoryMap(lldb::TargetSP target_sp) : m_target_wp(target_sp) {
24ac7ddfbfSEd Maste   if (target_sp)
25ac7ddfbfSEd Maste     m_process_wp = target_sp->GetProcessSP();
26ac7ddfbfSEd Maste }
27ac7ddfbfSEd Maste 
~IRMemoryMap()28435933ddSDimitry Andric IRMemoryMap::~IRMemoryMap() {
29ac7ddfbfSEd Maste   lldb::ProcessSP process_sp = m_process_wp.lock();
30ac7ddfbfSEd Maste 
31435933ddSDimitry Andric   if (process_sp) {
32ac7ddfbfSEd Maste     AllocationMap::iterator iter;
33ac7ddfbfSEd Maste 
345517e702SDimitry Andric     Status err;
35ac7ddfbfSEd Maste 
36435933ddSDimitry Andric     while ((iter = m_allocations.begin()) != m_allocations.end()) {
37ac7ddfbfSEd Maste       err.Clear();
38ac7ddfbfSEd Maste       if (iter->second.m_leak)
39ac7ddfbfSEd Maste         m_allocations.erase(iter);
40ac7ddfbfSEd Maste       else
41ac7ddfbfSEd Maste         Free(iter->first, err);
42ac7ddfbfSEd Maste     }
43ac7ddfbfSEd Maste   }
44ac7ddfbfSEd Maste }
45ac7ddfbfSEd Maste 
FindSpace(size_t size)46435933ddSDimitry Andric lldb::addr_t IRMemoryMap::FindSpace(size_t size) {
474bb0738eSEd Maste   // The FindSpace algorithm's job is to find a region of memory that the
484bb0738eSEd Maste   // underlying process is unlikely to be using.
494bb0738eSEd Maste   //
504bb0738eSEd Maste   // The memory returned by this function will never be written to.  The only
514bb0738eSEd Maste   // point is that it should not shadow process memory if possible, so that
524ba319b5SDimitry Andric   // expressions processing real values from the process do not use the wrong
534ba319b5SDimitry Andric   // data.
544bb0738eSEd Maste   //
554bb0738eSEd Maste   // If the process can in fact allocate memory (CanJIT() lets us know this)
564bb0738eSEd Maste   // then this can be accomplished just be allocating memory in the inferior.
574bb0738eSEd Maste   // Then no guessing is required.
584bb0738eSEd Maste 
59ac7ddfbfSEd Maste   lldb::TargetSP target_sp = m_target_wp.lock();
60ac7ddfbfSEd Maste   lldb::ProcessSP process_sp = m_process_wp.lock();
61ac7ddfbfSEd Maste 
624bb0738eSEd Maste   const bool process_is_alive = process_sp && process_sp->IsAlive();
634bb0738eSEd Maste 
64ac7ddfbfSEd Maste   lldb::addr_t ret = LLDB_INVALID_ADDRESS;
650127ef0fSEd Maste   if (size == 0)
660127ef0fSEd Maste     return ret;
67ac7ddfbfSEd Maste 
68435933ddSDimitry Andric   if (process_is_alive && process_sp->CanJIT()) {
695517e702SDimitry Andric     Status alloc_error;
70ac7ddfbfSEd Maste 
71435933ddSDimitry Andric     ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable |
72435933ddSDimitry Andric                                                lldb::ePermissionsWritable,
73435933ddSDimitry Andric                                      alloc_error);
74ac7ddfbfSEd Maste 
75ac7ddfbfSEd Maste     if (!alloc_error.Success())
76ac7ddfbfSEd Maste       return LLDB_INVALID_ADDRESS;
77ac7ddfbfSEd Maste     else
78ac7ddfbfSEd Maste       return ret;
79ac7ddfbfSEd Maste   }
80ac7ddfbfSEd Maste 
814bb0738eSEd Maste   // At this point we know that we need to hunt.
824bb0738eSEd Maste   //
834bb0738eSEd Maste   // First, go to the end of the existing allocations we've made if there are
844bb0738eSEd Maste   // any allocations.  Otherwise start at the beginning of memory.
854bb0738eSEd Maste 
86435933ddSDimitry Andric   if (m_allocations.empty()) {
874bb0738eSEd Maste     ret = 0x0;
88435933ddSDimitry Andric   } else {
890127ef0fSEd Maste     auto back = m_allocations.rbegin();
900127ef0fSEd Maste     lldb::addr_t addr = back->first;
910127ef0fSEd Maste     size_t alloc_size = back->second.m_size;
924bb0738eSEd Maste     ret = llvm::alignTo(addr + alloc_size, 4096);
934bb0738eSEd Maste   }
944bb0738eSEd Maste 
954bb0738eSEd Maste   // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped
964ba319b5SDimitry Andric   // regions, walk forward through memory until a region is found that has
974ba319b5SDimitry Andric   // adequate space for our allocation.
98435933ddSDimitry Andric   if (process_is_alive) {
99435933ddSDimitry Andric     const uint64_t end_of_memory = process_sp->GetAddressByteSize() == 8
100435933ddSDimitry Andric                                        ? 0xffffffffffffffffull
101435933ddSDimitry Andric                                        : 0xffffffffull;
1024bb0738eSEd Maste 
103435933ddSDimitry Andric     lldbassert(process_sp->GetAddressByteSize() == 4 ||
104435933ddSDimitry Andric                end_of_memory != 0xffffffffull);
1054bb0738eSEd Maste 
1064bb0738eSEd Maste     MemoryRegionInfo region_info;
1075517e702SDimitry Andric     Status err = process_sp->GetMemoryRegionInfo(ret, region_info);
108435933ddSDimitry Andric     if (err.Success()) {
109435933ddSDimitry Andric       while (true) {
1104bb0738eSEd Maste         if (region_info.GetReadable() != MemoryRegionInfo::OptionalBool::eNo ||
1114bb0738eSEd Maste             region_info.GetWritable() != MemoryRegionInfo::OptionalBool::eNo ||
112435933ddSDimitry Andric             region_info.GetExecutable() !=
113435933ddSDimitry Andric                 MemoryRegionInfo::OptionalBool::eNo) {
114435933ddSDimitry Andric           if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory) {
1154bb0738eSEd Maste             ret = LLDB_INVALID_ADDRESS;
1164bb0738eSEd Maste             break;
117435933ddSDimitry Andric           } else {
1184bb0738eSEd Maste             ret = region_info.GetRange().GetRangeEnd();
1194bb0738eSEd Maste           }
120435933ddSDimitry Andric         } else if (ret + size < region_info.GetRange().GetRangeEnd()) {
1214bb0738eSEd Maste           return ret;
122435933ddSDimitry Andric         } else {
1234bb0738eSEd Maste           // ret stays the same.  We just need to walk a bit further.
1244bb0738eSEd Maste         }
1254bb0738eSEd Maste 
126435933ddSDimitry Andric         err = process_sp->GetMemoryRegionInfo(
127435933ddSDimitry Andric             region_info.GetRange().GetRangeEnd(), region_info);
128435933ddSDimitry Andric         if (err.Fail()) {
12995ec533aSDimitry Andric           lldbassert(0 && "GetMemoryRegionInfo() succeeded, then failed");
1304bb0738eSEd Maste           ret = LLDB_INVALID_ADDRESS;
1314bb0738eSEd Maste           break;
1324bb0738eSEd Maste         }
1334bb0738eSEd Maste       }
1344bb0738eSEd Maste     }
1354bb0738eSEd Maste   }
1364bb0738eSEd Maste 
1374bb0738eSEd Maste   // We've tried our algorithm, and it didn't work.  Now we have to reset back
1384bb0738eSEd Maste   // to the end of the allocations we've already reported, or use a 'sensible'
1394bb0738eSEd Maste   // default if this is our first allocation.
1404bb0738eSEd Maste 
141435933ddSDimitry Andric   if (m_allocations.empty()) {
1424bb0738eSEd Maste     uint32_t address_byte_size = GetAddressByteSize();
143435933ddSDimitry Andric     if (address_byte_size != UINT32_MAX) {
144435933ddSDimitry Andric       switch (address_byte_size) {
1454bb0738eSEd Maste       case 8:
1464bb0738eSEd Maste         ret = 0xffffffff00000000ull;
1474bb0738eSEd Maste         break;
1484bb0738eSEd Maste       case 4:
1494bb0738eSEd Maste         ret = 0xee000000ull;
1504bb0738eSEd Maste         break;
1514bb0738eSEd Maste       default:
1524bb0738eSEd Maste         break;
1534bb0738eSEd Maste       }
1544bb0738eSEd Maste     }
155435933ddSDimitry Andric   } else {
1564bb0738eSEd Maste     auto back = m_allocations.rbegin();
1574bb0738eSEd Maste     lldb::addr_t addr = back->first;
1584bb0738eSEd Maste     size_t alloc_size = back->second.m_size;
1594bb0738eSEd Maste     ret = llvm::alignTo(addr + alloc_size, 4096);
160ac7ddfbfSEd Maste   }
161ac7ddfbfSEd Maste 
162ac7ddfbfSEd Maste   return ret;
163ac7ddfbfSEd Maste }
164ac7ddfbfSEd Maste 
165ac7ddfbfSEd Maste IRMemoryMap::AllocationMap::iterator
FindAllocation(lldb::addr_t addr,size_t size)166435933ddSDimitry Andric IRMemoryMap::FindAllocation(lldb::addr_t addr, size_t size) {
167ac7ddfbfSEd Maste   if (addr == LLDB_INVALID_ADDRESS)
168ac7ddfbfSEd Maste     return m_allocations.end();
169ac7ddfbfSEd Maste 
170ac7ddfbfSEd Maste   AllocationMap::iterator iter = m_allocations.lower_bound(addr);
171ac7ddfbfSEd Maste 
172435933ddSDimitry Andric   if (iter == m_allocations.end() || iter->first > addr) {
173ac7ddfbfSEd Maste     if (iter == m_allocations.begin())
174ac7ddfbfSEd Maste       return m_allocations.end();
175ac7ddfbfSEd Maste     iter--;
176ac7ddfbfSEd Maste   }
177ac7ddfbfSEd Maste 
178ac7ddfbfSEd Maste   if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
179ac7ddfbfSEd Maste     return iter;
180ac7ddfbfSEd Maste 
181ac7ddfbfSEd Maste   return m_allocations.end();
182ac7ddfbfSEd Maste }
183ac7ddfbfSEd Maste 
IntersectsAllocation(lldb::addr_t addr,size_t size) const184435933ddSDimitry Andric bool IRMemoryMap::IntersectsAllocation(lldb::addr_t addr, size_t size) const {
185ac7ddfbfSEd Maste   if (addr == LLDB_INVALID_ADDRESS)
186ac7ddfbfSEd Maste     return false;
187ac7ddfbfSEd Maste 
1880127ef0fSEd Maste   AllocationMap::const_iterator iter = m_allocations.lower_bound(addr);
189ac7ddfbfSEd Maste 
190435933ddSDimitry Andric   // Since we only know that the returned interval begins at a location greater
1914ba319b5SDimitry Andric   // than or equal to where the given interval begins, it's possible that the
1924ba319b5SDimitry Andric   // given interval intersects either the returned interval or the previous
1934ba319b5SDimitry Andric   // interval.  Thus, we need to check both. Note that we only need to check
1944ba319b5SDimitry Andric   // these two intervals.  Since all intervals are disjoint it is not possible
1954ba319b5SDimitry Andric   // that an adjacent interval does not intersect, but a non-adjacent interval
1964ba319b5SDimitry Andric   // does intersect.
1970127ef0fSEd Maste   if (iter != m_allocations.end()) {
198435933ddSDimitry Andric     if (AllocationsIntersect(addr, size, iter->second.m_process_start,
199435933ddSDimitry Andric                              iter->second.m_size))
200ac7ddfbfSEd Maste       return true;
2010127ef0fSEd Maste   }
202ac7ddfbfSEd Maste 
2030127ef0fSEd Maste   if (iter != m_allocations.begin()) {
2040127ef0fSEd Maste     --iter;
205435933ddSDimitry Andric     if (AllocationsIntersect(addr, size, iter->second.m_process_start,
206435933ddSDimitry Andric                              iter->second.m_size))
2070127ef0fSEd Maste       return true;
208ac7ddfbfSEd Maste   }
209ac7ddfbfSEd Maste 
210ac7ddfbfSEd Maste   return false;
211ac7ddfbfSEd Maste }
212ac7ddfbfSEd Maste 
AllocationsIntersect(lldb::addr_t addr1,size_t size1,lldb::addr_t addr2,size_t size2)213435933ddSDimitry Andric bool IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1,
214435933ddSDimitry Andric                                        lldb::addr_t addr2, size_t size2) {
215435933ddSDimitry Andric   // Given two half open intervals [A, B) and [X, Y), the only 6 permutations
2164ba319b5SDimitry Andric   // that satisfy A<B and X<Y are the following:
2170127ef0fSEd Maste   // A B X Y
2180127ef0fSEd Maste   // A X B Y  (intersects)
2190127ef0fSEd Maste   // A X Y B  (intersects)
2200127ef0fSEd Maste   // X A B Y  (intersects)
2210127ef0fSEd Maste   // X A Y B  (intersects)
2220127ef0fSEd Maste   // X Y A B
2234ba319b5SDimitry Andric   // The first is B <= X, and the last is Y <= A. So the condition is !(B <= X
2244ba319b5SDimitry Andric   // || Y <= A)), or (X < B && A < Y)
2250127ef0fSEd Maste   return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
2260127ef0fSEd Maste }
2270127ef0fSEd Maste 
GetByteOrder()228435933ddSDimitry Andric lldb::ByteOrder IRMemoryMap::GetByteOrder() {
229ac7ddfbfSEd Maste   lldb::ProcessSP process_sp = m_process_wp.lock();
230ac7ddfbfSEd Maste 
231ac7ddfbfSEd Maste   if (process_sp)
232ac7ddfbfSEd Maste     return process_sp->GetByteOrder();
233ac7ddfbfSEd Maste 
234ac7ddfbfSEd Maste   lldb::TargetSP target_sp = m_target_wp.lock();
235ac7ddfbfSEd Maste 
236ac7ddfbfSEd Maste   if (target_sp)
237ac7ddfbfSEd Maste     return target_sp->GetArchitecture().GetByteOrder();
238ac7ddfbfSEd Maste 
239ac7ddfbfSEd Maste   return lldb::eByteOrderInvalid;
240ac7ddfbfSEd Maste }
241ac7ddfbfSEd Maste 
GetAddressByteSize()242435933ddSDimitry Andric uint32_t IRMemoryMap::GetAddressByteSize() {
243ac7ddfbfSEd Maste   lldb::ProcessSP process_sp = m_process_wp.lock();
244ac7ddfbfSEd Maste 
245ac7ddfbfSEd Maste   if (process_sp)
246ac7ddfbfSEd Maste     return process_sp->GetAddressByteSize();
247ac7ddfbfSEd Maste 
248ac7ddfbfSEd Maste   lldb::TargetSP target_sp = m_target_wp.lock();
249ac7ddfbfSEd Maste 
250ac7ddfbfSEd Maste   if (target_sp)
251ac7ddfbfSEd Maste     return target_sp->GetArchitecture().GetAddressByteSize();
252ac7ddfbfSEd Maste 
253ac7ddfbfSEd Maste   return UINT32_MAX;
254ac7ddfbfSEd Maste }
255ac7ddfbfSEd Maste 
GetBestExecutionContextScope() const256435933ddSDimitry Andric ExecutionContextScope *IRMemoryMap::GetBestExecutionContextScope() const {
257ac7ddfbfSEd Maste   lldb::ProcessSP process_sp = m_process_wp.lock();
258ac7ddfbfSEd Maste 
259ac7ddfbfSEd Maste   if (process_sp)
260ac7ddfbfSEd Maste     return process_sp.get();
261ac7ddfbfSEd Maste 
262ac7ddfbfSEd Maste   lldb::TargetSP target_sp = m_target_wp.lock();
263ac7ddfbfSEd Maste 
264ac7ddfbfSEd Maste   if (target_sp)
265ac7ddfbfSEd Maste     return target_sp.get();
266ac7ddfbfSEd Maste 
267ac7ddfbfSEd Maste   return NULL;
268ac7ddfbfSEd Maste }
269ac7ddfbfSEd Maste 
Allocation(lldb::addr_t process_alloc,lldb::addr_t process_start,size_t size,uint32_t permissions,uint8_t alignment,AllocationPolicy policy)270ac7ddfbfSEd Maste IRMemoryMap::Allocation::Allocation(lldb::addr_t process_alloc,
271435933ddSDimitry Andric                                     lldb::addr_t process_start, size_t size,
272435933ddSDimitry Andric                                     uint32_t permissions, uint8_t alignment,
273435933ddSDimitry Andric                                     AllocationPolicy policy)
274435933ddSDimitry Andric     : m_process_alloc(process_alloc), m_process_start(process_start),
275*b5893f02SDimitry Andric       m_size(size), m_policy(policy), m_leak(false), m_permissions(permissions),
276*b5893f02SDimitry Andric       m_alignment(alignment) {
277435933ddSDimitry Andric   switch (policy) {
278ac7ddfbfSEd Maste   default:
279ac7ddfbfSEd Maste     assert(0 && "We cannot reach this!");
280ac7ddfbfSEd Maste   case eAllocationPolicyHostOnly:
281ac7ddfbfSEd Maste   case eAllocationPolicyMirror:
282ac7ddfbfSEd Maste     m_data.SetByteSize(size);
283*b5893f02SDimitry Andric     break;
284*b5893f02SDimitry Andric   case eAllocationPolicyProcessOnly:
285ac7ddfbfSEd Maste     break;
286ac7ddfbfSEd Maste   }
287ac7ddfbfSEd Maste }
288ac7ddfbfSEd Maste 
Malloc(size_t size,uint8_t alignment,uint32_t permissions,AllocationPolicy policy,bool zero_memory,Status & error)289435933ddSDimitry Andric lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment,
290435933ddSDimitry Andric                                  uint32_t permissions, AllocationPolicy policy,
2915517e702SDimitry Andric                                  bool zero_memory, Status &error) {
292435933ddSDimitry Andric   lldb_private::Log *log(
293435933ddSDimitry Andric       lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
294ac7ddfbfSEd Maste   error.Clear();
295ac7ddfbfSEd Maste 
296ac7ddfbfSEd Maste   lldb::ProcessSP process_sp;
297ac7ddfbfSEd Maste   lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
298ac7ddfbfSEd Maste   lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
299ac7ddfbfSEd Maste 
300ac7ddfbfSEd Maste   size_t allocation_size;
301ac7ddfbfSEd Maste 
3024ba319b5SDimitry Andric   if (size == 0) {
3034ba319b5SDimitry Andric     // FIXME: Malloc(0) should either return an invalid address or assert, in
3044ba319b5SDimitry Andric     // order to cut down on unnecessary allocations.
305ac7ddfbfSEd Maste     allocation_size = alignment;
3064ba319b5SDimitry Andric   } else {
3074ba319b5SDimitry Andric     // Round up the requested size to an aligned value.
3084ba319b5SDimitry Andric     allocation_size = llvm::alignTo(size, alignment);
3094ba319b5SDimitry Andric 
3104ba319b5SDimitry Andric     // The process page cache does not see the requested alignment. We can't
3114ba319b5SDimitry Andric     // assume its result will be any more than 1-byte aligned. To work around
3124ba319b5SDimitry Andric     // this, request `alignment - 1` additional bytes.
3134ba319b5SDimitry Andric     allocation_size += alignment - 1;
3144ba319b5SDimitry Andric   }
315ac7ddfbfSEd Maste 
316435933ddSDimitry Andric   switch (policy) {
317ac7ddfbfSEd Maste   default:
318ac7ddfbfSEd Maste     error.SetErrorToGenericError();
319ac7ddfbfSEd Maste     error.SetErrorString("Couldn't malloc: invalid allocation policy");
320ac7ddfbfSEd Maste     return LLDB_INVALID_ADDRESS;
321ac7ddfbfSEd Maste   case eAllocationPolicyHostOnly:
322ac7ddfbfSEd Maste     allocation_address = FindSpace(allocation_size);
323435933ddSDimitry Andric     if (allocation_address == LLDB_INVALID_ADDRESS) {
324ac7ddfbfSEd Maste       error.SetErrorToGenericError();
325ac7ddfbfSEd Maste       error.SetErrorString("Couldn't malloc: address space is full");
326ac7ddfbfSEd Maste       return LLDB_INVALID_ADDRESS;
327ac7ddfbfSEd Maste     }
328ac7ddfbfSEd Maste     break;
329ac7ddfbfSEd Maste   case eAllocationPolicyMirror:
330ac7ddfbfSEd Maste     process_sp = m_process_wp.lock();
3310127ef0fSEd Maste     if (log)
332435933ddSDimitry Andric       log->Printf("IRMemoryMap::%s process_sp=0x%" PRIx64
333435933ddSDimitry Andric                   ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s",
334435933ddSDimitry Andric                   __FUNCTION__, (lldb::addr_t)process_sp.get(),
335435933ddSDimitry Andric                   process_sp && process_sp->CanJIT() ? "true" : "false",
336435933ddSDimitry Andric                   process_sp && process_sp->IsAlive() ? "true" : "false");
337435933ddSDimitry Andric     if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) {
3389f2f44ceSEd Maste       if (!zero_memory)
339435933ddSDimitry Andric         allocation_address =
340435933ddSDimitry Andric             process_sp->AllocateMemory(allocation_size, permissions, error);
3419f2f44ceSEd Maste       else
342435933ddSDimitry Andric         allocation_address =
343435933ddSDimitry Andric             process_sp->CallocateMemory(allocation_size, permissions, error);
3449f2f44ceSEd Maste 
345ac7ddfbfSEd Maste       if (!error.Success())
346ac7ddfbfSEd Maste         return LLDB_INVALID_ADDRESS;
347435933ddSDimitry Andric     } else {
3480127ef0fSEd Maste       if (log)
349435933ddSDimitry Andric         log->Printf("IRMemoryMap::%s switching to eAllocationPolicyHostOnly "
350435933ddSDimitry Andric                     "due to failed condition (see previous expr log message)",
351435933ddSDimitry Andric                     __FUNCTION__);
352ac7ddfbfSEd Maste       policy = eAllocationPolicyHostOnly;
353ac7ddfbfSEd Maste       allocation_address = FindSpace(allocation_size);
354435933ddSDimitry Andric       if (allocation_address == LLDB_INVALID_ADDRESS) {
355ac7ddfbfSEd Maste         error.SetErrorToGenericError();
356ac7ddfbfSEd Maste         error.SetErrorString("Couldn't malloc: address space is full");
357ac7ddfbfSEd Maste         return LLDB_INVALID_ADDRESS;
358ac7ddfbfSEd Maste       }
359ac7ddfbfSEd Maste     }
360ac7ddfbfSEd Maste     break;
361ac7ddfbfSEd Maste   case eAllocationPolicyProcessOnly:
362ac7ddfbfSEd Maste     process_sp = m_process_wp.lock();
363435933ddSDimitry Andric     if (process_sp) {
364435933ddSDimitry Andric       if (process_sp->CanJIT() && process_sp->IsAlive()) {
3659f2f44ceSEd Maste         if (!zero_memory)
366435933ddSDimitry Andric           allocation_address =
367435933ddSDimitry Andric               process_sp->AllocateMemory(allocation_size, permissions, error);
3689f2f44ceSEd Maste         else
369435933ddSDimitry Andric           allocation_address =
370435933ddSDimitry Andric               process_sp->CallocateMemory(allocation_size, permissions, error);
3719f2f44ceSEd Maste 
372ac7ddfbfSEd Maste         if (!error.Success())
373ac7ddfbfSEd Maste           return LLDB_INVALID_ADDRESS;
374435933ddSDimitry Andric       } else {
375ac7ddfbfSEd Maste         error.SetErrorToGenericError();
376435933ddSDimitry Andric         error.SetErrorString(
377435933ddSDimitry Andric             "Couldn't malloc: process doesn't support allocating memory");
378ac7ddfbfSEd Maste         return LLDB_INVALID_ADDRESS;
379ac7ddfbfSEd Maste       }
380435933ddSDimitry Andric     } else {
381ac7ddfbfSEd Maste       error.SetErrorToGenericError();
382435933ddSDimitry Andric       error.SetErrorString("Couldn't malloc: process doesn't exist, and this "
383435933ddSDimitry Andric                            "memory must be in the process");
384ac7ddfbfSEd Maste       return LLDB_INVALID_ADDRESS;
385ac7ddfbfSEd Maste     }
386ac7ddfbfSEd Maste     break;
387ac7ddfbfSEd Maste   }
388ac7ddfbfSEd Maste 
389ac7ddfbfSEd Maste   lldb::addr_t mask = alignment - 1;
390ac7ddfbfSEd Maste   aligned_address = (allocation_address + mask) & (~mask);
391ac7ddfbfSEd Maste 
392*b5893f02SDimitry Andric   m_allocations.emplace(
393*b5893f02SDimitry Andric       std::piecewise_construct, std::forward_as_tuple(aligned_address),
394*b5893f02SDimitry Andric       std::forward_as_tuple(allocation_address, aligned_address,
395*b5893f02SDimitry Andric                             allocation_size, permissions, alignment, policy));
396ac7ddfbfSEd Maste 
397435933ddSDimitry Andric   if (zero_memory) {
3985517e702SDimitry Andric     Status write_error;
3994bb0738eSEd Maste     std::vector<uint8_t> zero_buf(size, 0);
4004bb0738eSEd Maste     WriteMemory(aligned_address, zero_buf.data(), size, write_error);
4014bb0738eSEd Maste   }
4024bb0738eSEd Maste 
403435933ddSDimitry Andric   if (log) {
404ac7ddfbfSEd Maste     const char *policy_string;
405ac7ddfbfSEd Maste 
406435933ddSDimitry Andric     switch (policy) {
407ac7ddfbfSEd Maste     default:
408ac7ddfbfSEd Maste       policy_string = "<invalid policy>";
409ac7ddfbfSEd Maste       break;
410ac7ddfbfSEd Maste     case eAllocationPolicyHostOnly:
411ac7ddfbfSEd Maste       policy_string = "eAllocationPolicyHostOnly";
412ac7ddfbfSEd Maste       break;
413ac7ddfbfSEd Maste     case eAllocationPolicyProcessOnly:
414ac7ddfbfSEd Maste       policy_string = "eAllocationPolicyProcessOnly";
415ac7ddfbfSEd Maste       break;
416ac7ddfbfSEd Maste     case eAllocationPolicyMirror:
417ac7ddfbfSEd Maste       policy_string = "eAllocationPolicyMirror";
418ac7ddfbfSEd Maste       break;
419ac7ddfbfSEd Maste     }
420ac7ddfbfSEd Maste 
421435933ddSDimitry Andric     log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64
422435933ddSDimitry Andric                 ", %s) -> 0x%" PRIx64,
423435933ddSDimitry Andric                 (uint64_t)allocation_size, (uint64_t)alignment,
424435933ddSDimitry Andric                 (uint64_t)permissions, policy_string, aligned_address);
425ac7ddfbfSEd Maste   }
426ac7ddfbfSEd Maste 
427ac7ddfbfSEd Maste   return aligned_address;
428ac7ddfbfSEd Maste }
429ac7ddfbfSEd Maste 
Leak(lldb::addr_t process_address,Status & error)4305517e702SDimitry Andric void IRMemoryMap::Leak(lldb::addr_t process_address, Status &error) {
431ac7ddfbfSEd Maste   error.Clear();
432ac7ddfbfSEd Maste 
433ac7ddfbfSEd Maste   AllocationMap::iterator iter = m_allocations.find(process_address);
434ac7ddfbfSEd Maste 
435435933ddSDimitry Andric   if (iter == m_allocations.end()) {
436ac7ddfbfSEd Maste     error.SetErrorToGenericError();
437ac7ddfbfSEd Maste     error.SetErrorString("Couldn't leak: allocation doesn't exist");
438ac7ddfbfSEd Maste     return;
439ac7ddfbfSEd Maste   }
440ac7ddfbfSEd Maste 
441ac7ddfbfSEd Maste   Allocation &allocation = iter->second;
442ac7ddfbfSEd Maste 
443ac7ddfbfSEd Maste   allocation.m_leak = true;
444ac7ddfbfSEd Maste }
445ac7ddfbfSEd Maste 
Free(lldb::addr_t process_address,Status & error)4465517e702SDimitry Andric void IRMemoryMap::Free(lldb::addr_t process_address, Status &error) {
447ac7ddfbfSEd Maste   error.Clear();
448ac7ddfbfSEd Maste 
449ac7ddfbfSEd Maste   AllocationMap::iterator iter = m_allocations.find(process_address);
450ac7ddfbfSEd Maste 
451435933ddSDimitry Andric   if (iter == m_allocations.end()) {
452ac7ddfbfSEd Maste     error.SetErrorToGenericError();
453ac7ddfbfSEd Maste     error.SetErrorString("Couldn't free: allocation doesn't exist");
454ac7ddfbfSEd Maste     return;
455ac7ddfbfSEd Maste   }
456ac7ddfbfSEd Maste 
457ac7ddfbfSEd Maste   Allocation &allocation = iter->second;
458ac7ddfbfSEd Maste 
459435933ddSDimitry Andric   switch (allocation.m_policy) {
460ac7ddfbfSEd Maste   default:
461435933ddSDimitry Andric   case eAllocationPolicyHostOnly: {
462ac7ddfbfSEd Maste     lldb::ProcessSP process_sp = m_process_wp.lock();
463435933ddSDimitry Andric     if (process_sp) {
464ac7ddfbfSEd Maste       if (process_sp->CanJIT() && process_sp->IsAlive())
465435933ddSDimitry Andric         process_sp->DeallocateMemory(
466435933ddSDimitry Andric             allocation.m_process_alloc); // FindSpace allocated this for real
467ac7ddfbfSEd Maste     }
468ac7ddfbfSEd Maste 
469ac7ddfbfSEd Maste     break;
470ac7ddfbfSEd Maste   }
471ac7ddfbfSEd Maste   case eAllocationPolicyMirror:
472435933ddSDimitry Andric   case eAllocationPolicyProcessOnly: {
473ac7ddfbfSEd Maste     lldb::ProcessSP process_sp = m_process_wp.lock();
474ac7ddfbfSEd Maste     if (process_sp)
475ac7ddfbfSEd Maste       process_sp->DeallocateMemory(allocation.m_process_alloc);
476ac7ddfbfSEd Maste   }
477ac7ddfbfSEd Maste   }
478ac7ddfbfSEd Maste 
479435933ddSDimitry Andric   if (lldb_private::Log *log =
480435933ddSDimitry Andric           lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
481435933ddSDimitry Andric     log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64
482435933ddSDimitry Andric                 "..0x%" PRIx64 ")",
483435933ddSDimitry Andric                 (uint64_t)process_address, iter->second.m_process_start,
484ac7ddfbfSEd Maste                 iter->second.m_process_start + iter->second.m_size);
485ac7ddfbfSEd Maste   }
486ac7ddfbfSEd Maste 
487ac7ddfbfSEd Maste   m_allocations.erase(iter);
488ac7ddfbfSEd Maste }
489ac7ddfbfSEd Maste 
GetAllocSize(lldb::addr_t address,size_t & size)490435933ddSDimitry Andric bool IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size) {
491b91a7dfcSDimitry Andric   AllocationMap::iterator iter = FindAllocation(address, size);
492b91a7dfcSDimitry Andric   if (iter == m_allocations.end())
493b91a7dfcSDimitry Andric     return false;
494b91a7dfcSDimitry Andric 
495b91a7dfcSDimitry Andric   Allocation &al = iter->second;
496b91a7dfcSDimitry Andric 
497435933ddSDimitry Andric   if (address > (al.m_process_start + al.m_size)) {
498b91a7dfcSDimitry Andric     size = 0;
499b91a7dfcSDimitry Andric     return false;
500b91a7dfcSDimitry Andric   }
501b91a7dfcSDimitry Andric 
502435933ddSDimitry Andric   if (address > al.m_process_start) {
503b91a7dfcSDimitry Andric     int dif = address - al.m_process_start;
504b91a7dfcSDimitry Andric     size = al.m_size - dif;
505b91a7dfcSDimitry Andric     return true;
506b91a7dfcSDimitry Andric   }
507b91a7dfcSDimitry Andric 
508b91a7dfcSDimitry Andric   size = al.m_size;
509b91a7dfcSDimitry Andric   return true;
510b91a7dfcSDimitry Andric }
511b91a7dfcSDimitry Andric 
WriteMemory(lldb::addr_t process_address,const uint8_t * bytes,size_t size,Status & error)512435933ddSDimitry Andric void IRMemoryMap::WriteMemory(lldb::addr_t process_address,
5135517e702SDimitry Andric                               const uint8_t *bytes, size_t size,
5145517e702SDimitry Andric                               Status &error) {
515ac7ddfbfSEd Maste   error.Clear();
516ac7ddfbfSEd Maste 
517ac7ddfbfSEd Maste   AllocationMap::iterator iter = FindAllocation(process_address, size);
518ac7ddfbfSEd Maste 
519435933ddSDimitry Andric   if (iter == m_allocations.end()) {
520ac7ddfbfSEd Maste     lldb::ProcessSP process_sp = m_process_wp.lock();
521ac7ddfbfSEd Maste 
522435933ddSDimitry Andric     if (process_sp) {
523ac7ddfbfSEd Maste       process_sp->WriteMemory(process_address, bytes, size, error);
524ac7ddfbfSEd Maste       return;
525ac7ddfbfSEd Maste     }
526ac7ddfbfSEd Maste 
527ac7ddfbfSEd Maste     error.SetErrorToGenericError();
528435933ddSDimitry Andric     error.SetErrorString("Couldn't write: no allocation contains the target "
529435933ddSDimitry Andric                          "range and the process doesn't exist");
530ac7ddfbfSEd Maste     return;
531ac7ddfbfSEd Maste   }
532ac7ddfbfSEd Maste 
533ac7ddfbfSEd Maste   Allocation &allocation = iter->second;
534ac7ddfbfSEd Maste 
535ac7ddfbfSEd Maste   uint64_t offset = process_address - allocation.m_process_start;
536ac7ddfbfSEd Maste 
537ac7ddfbfSEd Maste   lldb::ProcessSP process_sp;
538ac7ddfbfSEd Maste 
539435933ddSDimitry Andric   switch (allocation.m_policy) {
540ac7ddfbfSEd Maste   default:
541ac7ddfbfSEd Maste     error.SetErrorToGenericError();
542ac7ddfbfSEd Maste     error.SetErrorString("Couldn't write: invalid allocation policy");
543ac7ddfbfSEd Maste     return;
544ac7ddfbfSEd Maste   case eAllocationPolicyHostOnly:
545435933ddSDimitry Andric     if (!allocation.m_data.GetByteSize()) {
546ac7ddfbfSEd Maste       error.SetErrorToGenericError();
547ac7ddfbfSEd Maste       error.SetErrorString("Couldn't write: data buffer is empty");
548ac7ddfbfSEd Maste       return;
549ac7ddfbfSEd Maste     }
550ac7ddfbfSEd Maste     ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
551ac7ddfbfSEd Maste     break;
552ac7ddfbfSEd Maste   case eAllocationPolicyMirror:
553435933ddSDimitry Andric     if (!allocation.m_data.GetByteSize()) {
554ac7ddfbfSEd Maste       error.SetErrorToGenericError();
555ac7ddfbfSEd Maste       error.SetErrorString("Couldn't write: data buffer is empty");
556ac7ddfbfSEd Maste       return;
557ac7ddfbfSEd Maste     }
558ac7ddfbfSEd Maste     ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
559ac7ddfbfSEd Maste     process_sp = m_process_wp.lock();
560435933ddSDimitry Andric     if (process_sp) {
561ac7ddfbfSEd Maste       process_sp->WriteMemory(process_address, bytes, size, error);
562ac7ddfbfSEd Maste       if (!error.Success())
563ac7ddfbfSEd Maste         return;
564ac7ddfbfSEd Maste     }
565ac7ddfbfSEd Maste     break;
566ac7ddfbfSEd Maste   case eAllocationPolicyProcessOnly:
567ac7ddfbfSEd Maste     process_sp = m_process_wp.lock();
568435933ddSDimitry Andric     if (process_sp) {
569ac7ddfbfSEd Maste       process_sp->WriteMemory(process_address, bytes, size, error);
570ac7ddfbfSEd Maste       if (!error.Success())
571ac7ddfbfSEd Maste         return;
572ac7ddfbfSEd Maste     }
573ac7ddfbfSEd Maste     break;
574ac7ddfbfSEd Maste   }
575ac7ddfbfSEd Maste 
576435933ddSDimitry Andric   if (lldb_private::Log *log =
577435933ddSDimitry Andric           lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
578435933ddSDimitry Andric     log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64
579435933ddSDimitry Andric                 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
580435933ddSDimitry Andric                 (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size,
581ac7ddfbfSEd Maste                 (uint64_t)allocation.m_process_start,
582435933ddSDimitry Andric                 (uint64_t)allocation.m_process_start +
583435933ddSDimitry Andric                     (uint64_t)allocation.m_size);
584ac7ddfbfSEd Maste   }
585ac7ddfbfSEd Maste }
586ac7ddfbfSEd Maste 
WriteScalarToMemory(lldb::addr_t process_address,Scalar & scalar,size_t size,Status & error)587435933ddSDimitry Andric void IRMemoryMap::WriteScalarToMemory(lldb::addr_t process_address,
588435933ddSDimitry Andric                                       Scalar &scalar, size_t size,
5895517e702SDimitry Andric                                       Status &error) {
590ac7ddfbfSEd Maste   error.Clear();
591ac7ddfbfSEd Maste 
592ac7ddfbfSEd Maste   if (size == UINT32_MAX)
593ac7ddfbfSEd Maste     size = scalar.GetByteSize();
594ac7ddfbfSEd Maste 
595435933ddSDimitry Andric   if (size > 0) {
596ac7ddfbfSEd Maste     uint8_t buf[32];
597435933ddSDimitry Andric     const size_t mem_size =
598435933ddSDimitry Andric         scalar.GetAsMemoryData(buf, size, GetByteOrder(), error);
599435933ddSDimitry Andric     if (mem_size > 0) {
600ac7ddfbfSEd Maste       return WriteMemory(process_address, buf, mem_size, error);
601435933ddSDimitry Andric     } else {
602ac7ddfbfSEd Maste       error.SetErrorToGenericError();
603435933ddSDimitry Andric       error.SetErrorString(
604435933ddSDimitry Andric           "Couldn't write scalar: failed to get scalar as memory data");
605ac7ddfbfSEd Maste     }
606435933ddSDimitry Andric   } else {
607ac7ddfbfSEd Maste     error.SetErrorToGenericError();
608ac7ddfbfSEd Maste     error.SetErrorString("Couldn't write scalar: its size was zero");
609ac7ddfbfSEd Maste   }
610ac7ddfbfSEd Maste   return;
611ac7ddfbfSEd Maste }
612ac7ddfbfSEd Maste 
WritePointerToMemory(lldb::addr_t process_address,lldb::addr_t address,Status & error)613435933ddSDimitry Andric void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address,
6145517e702SDimitry Andric                                        lldb::addr_t address, Status &error) {
615ac7ddfbfSEd Maste   error.Clear();
616ac7ddfbfSEd Maste 
617ac7ddfbfSEd Maste   Scalar scalar(address);
618ac7ddfbfSEd Maste 
619ac7ddfbfSEd Maste   WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
620ac7ddfbfSEd Maste }
621ac7ddfbfSEd Maste 
ReadMemory(uint8_t * bytes,lldb::addr_t process_address,size_t size,Status & error)622435933ddSDimitry Andric void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address,
6235517e702SDimitry Andric                              size_t size, Status &error) {
624ac7ddfbfSEd Maste   error.Clear();
625ac7ddfbfSEd Maste 
626ac7ddfbfSEd Maste   AllocationMap::iterator iter = FindAllocation(process_address, size);
627ac7ddfbfSEd Maste 
628435933ddSDimitry Andric   if (iter == m_allocations.end()) {
629ac7ddfbfSEd Maste     lldb::ProcessSP process_sp = m_process_wp.lock();
630ac7ddfbfSEd Maste 
631435933ddSDimitry Andric     if (process_sp) {
632ac7ddfbfSEd Maste       process_sp->ReadMemory(process_address, bytes, size, error);
633ac7ddfbfSEd Maste       return;
634ac7ddfbfSEd Maste     }
635ac7ddfbfSEd Maste 
636ac7ddfbfSEd Maste     lldb::TargetSP target_sp = m_target_wp.lock();
637ac7ddfbfSEd Maste 
638435933ddSDimitry Andric     if (target_sp) {
639ac7ddfbfSEd Maste       Address absolute_address(process_address);
640ac7ddfbfSEd Maste       target_sp->ReadMemory(absolute_address, false, bytes, size, error);
641ac7ddfbfSEd Maste       return;
642ac7ddfbfSEd Maste     }
643ac7ddfbfSEd Maste 
644ac7ddfbfSEd Maste     error.SetErrorToGenericError();
645435933ddSDimitry Andric     error.SetErrorString("Couldn't read: no allocation contains the target "
646435933ddSDimitry Andric                          "range, and neither the process nor the target exist");
647ac7ddfbfSEd Maste     return;
648ac7ddfbfSEd Maste   }
649ac7ddfbfSEd Maste 
650ac7ddfbfSEd Maste   Allocation &allocation = iter->second;
651ac7ddfbfSEd Maste 
652ac7ddfbfSEd Maste   uint64_t offset = process_address - allocation.m_process_start;
653ac7ddfbfSEd Maste 
654435933ddSDimitry Andric   if (offset > allocation.m_size) {
6550127ef0fSEd Maste     error.SetErrorToGenericError();
6560127ef0fSEd Maste     error.SetErrorString("Couldn't read: data is not in the allocation");
6570127ef0fSEd Maste     return;
6580127ef0fSEd Maste   }
6590127ef0fSEd Maste 
660ac7ddfbfSEd Maste   lldb::ProcessSP process_sp;
661ac7ddfbfSEd Maste 
662435933ddSDimitry Andric   switch (allocation.m_policy) {
663ac7ddfbfSEd Maste   default:
664ac7ddfbfSEd Maste     error.SetErrorToGenericError();
665ac7ddfbfSEd Maste     error.SetErrorString("Couldn't read: invalid allocation policy");
666ac7ddfbfSEd Maste     return;
667ac7ddfbfSEd Maste   case eAllocationPolicyHostOnly:
668435933ddSDimitry Andric     if (!allocation.m_data.GetByteSize()) {
669ac7ddfbfSEd Maste       error.SetErrorToGenericError();
670ac7ddfbfSEd Maste       error.SetErrorString("Couldn't read: data buffer is empty");
671ac7ddfbfSEd Maste       return;
672ac7ddfbfSEd Maste     }
673435933ddSDimitry Andric     if (allocation.m_data.GetByteSize() < offset + size) {
6740127ef0fSEd Maste       error.SetErrorToGenericError();
6750127ef0fSEd Maste       error.SetErrorString("Couldn't read: not enough underlying data");
6760127ef0fSEd Maste       return;
6770127ef0fSEd Maste     }
6780127ef0fSEd Maste 
679ac7ddfbfSEd Maste     ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
680ac7ddfbfSEd Maste     break;
681ac7ddfbfSEd Maste   case eAllocationPolicyMirror:
682ac7ddfbfSEd Maste     process_sp = m_process_wp.lock();
683435933ddSDimitry Andric     if (process_sp) {
684ac7ddfbfSEd Maste       process_sp->ReadMemory(process_address, bytes, size, error);
685ac7ddfbfSEd Maste       if (!error.Success())
686ac7ddfbfSEd Maste         return;
687435933ddSDimitry Andric     } else {
688435933ddSDimitry Andric       if (!allocation.m_data.GetByteSize()) {
689ac7ddfbfSEd Maste         error.SetErrorToGenericError();
690ac7ddfbfSEd Maste         error.SetErrorString("Couldn't read: data buffer is empty");
691ac7ddfbfSEd Maste         return;
692ac7ddfbfSEd Maste       }
693ac7ddfbfSEd Maste       ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
694ac7ddfbfSEd Maste     }
695ac7ddfbfSEd Maste     break;
696ac7ddfbfSEd Maste   case eAllocationPolicyProcessOnly:
697ac7ddfbfSEd Maste     process_sp = m_process_wp.lock();
698435933ddSDimitry Andric     if (process_sp) {
699ac7ddfbfSEd Maste       process_sp->ReadMemory(process_address, bytes, size, error);
700ac7ddfbfSEd Maste       if (!error.Success())
701ac7ddfbfSEd Maste         return;
702ac7ddfbfSEd Maste     }
703ac7ddfbfSEd Maste     break;
704ac7ddfbfSEd Maste   }
705ac7ddfbfSEd Maste 
706435933ddSDimitry Andric   if (lldb_private::Log *log =
707435933ddSDimitry Andric           lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
708435933ddSDimitry Andric     log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64
709435933ddSDimitry Andric                 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
710435933ddSDimitry Andric                 (uint64_t)process_address, (uint64_t)bytes, (uint64_t)size,
711ac7ddfbfSEd Maste                 (uint64_t)allocation.m_process_start,
712435933ddSDimitry Andric                 (uint64_t)allocation.m_process_start +
713435933ddSDimitry Andric                     (uint64_t)allocation.m_size);
714ac7ddfbfSEd Maste   }
715ac7ddfbfSEd Maste }
716ac7ddfbfSEd Maste 
ReadScalarFromMemory(Scalar & scalar,lldb::addr_t process_address,size_t size,Status & error)717435933ddSDimitry Andric void IRMemoryMap::ReadScalarFromMemory(Scalar &scalar,
718435933ddSDimitry Andric                                        lldb::addr_t process_address,
7195517e702SDimitry Andric                                        size_t size, Status &error) {
720ac7ddfbfSEd Maste   error.Clear();
721ac7ddfbfSEd Maste 
722435933ddSDimitry Andric   if (size > 0) {
723ac7ddfbfSEd Maste     DataBufferHeap buf(size, 0);
724ac7ddfbfSEd Maste     ReadMemory(buf.GetBytes(), process_address, size, error);
725ac7ddfbfSEd Maste 
726ac7ddfbfSEd Maste     if (!error.Success())
727ac7ddfbfSEd Maste       return;
728ac7ddfbfSEd Maste 
729435933ddSDimitry Andric     DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(),
730435933ddSDimitry Andric                             GetAddressByteSize());
731ac7ddfbfSEd Maste 
732ac7ddfbfSEd Maste     lldb::offset_t offset = 0;
733ac7ddfbfSEd Maste 
734435933ddSDimitry Andric     switch (size) {
735ac7ddfbfSEd Maste     default:
736ac7ddfbfSEd Maste       error.SetErrorToGenericError();
737435933ddSDimitry Andric       error.SetErrorStringWithFormat(
738435933ddSDimitry Andric           "Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
739ac7ddfbfSEd Maste       return;
740435933ddSDimitry Andric     case 1:
741435933ddSDimitry Andric       scalar = extractor.GetU8(&offset);
742435933ddSDimitry Andric       break;
743435933ddSDimitry Andric     case 2:
744435933ddSDimitry Andric       scalar = extractor.GetU16(&offset);
745435933ddSDimitry Andric       break;
746435933ddSDimitry Andric     case 4:
747435933ddSDimitry Andric       scalar = extractor.GetU32(&offset);
748435933ddSDimitry Andric       break;
749435933ddSDimitry Andric     case 8:
750435933ddSDimitry Andric       scalar = extractor.GetU64(&offset);
751435933ddSDimitry Andric       break;
752ac7ddfbfSEd Maste     }
753435933ddSDimitry Andric   } else {
754ac7ddfbfSEd Maste     error.SetErrorToGenericError();
755ac7ddfbfSEd Maste     error.SetErrorString("Couldn't read scalar: its size was zero");
756ac7ddfbfSEd Maste   }
757ac7ddfbfSEd Maste   return;
758ac7ddfbfSEd Maste }
759ac7ddfbfSEd Maste 
ReadPointerFromMemory(lldb::addr_t * address,lldb::addr_t process_address,Status & error)760435933ddSDimitry Andric void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t *address,
761435933ddSDimitry Andric                                         lldb::addr_t process_address,
7625517e702SDimitry Andric                                         Status &error) {
763ac7ddfbfSEd Maste   error.Clear();
764ac7ddfbfSEd Maste 
765ac7ddfbfSEd Maste   Scalar pointer_scalar;
766435933ddSDimitry Andric   ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(),
767435933ddSDimitry Andric                        error);
768ac7ddfbfSEd Maste 
769ac7ddfbfSEd Maste   if (!error.Success())
770ac7ddfbfSEd Maste     return;
771ac7ddfbfSEd Maste 
772ac7ddfbfSEd Maste   *address = pointer_scalar.ULongLong();
773ac7ddfbfSEd Maste 
774ac7ddfbfSEd Maste   return;
775ac7ddfbfSEd Maste }
776ac7ddfbfSEd Maste 
GetMemoryData(DataExtractor & extractor,lldb::addr_t process_address,size_t size,Status & error)777435933ddSDimitry Andric void IRMemoryMap::GetMemoryData(DataExtractor &extractor,
778435933ddSDimitry Andric                                 lldb::addr_t process_address, size_t size,
7795517e702SDimitry Andric                                 Status &error) {
780ac7ddfbfSEd Maste   error.Clear();
781ac7ddfbfSEd Maste 
782435933ddSDimitry Andric   if (size > 0) {
783ac7ddfbfSEd Maste     AllocationMap::iterator iter = FindAllocation(process_address, size);
784ac7ddfbfSEd Maste 
785435933ddSDimitry Andric     if (iter == m_allocations.end()) {
786ac7ddfbfSEd Maste       error.SetErrorToGenericError();
787435933ddSDimitry Andric       error.SetErrorStringWithFormat(
788435933ddSDimitry Andric           "Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64
789435933ddSDimitry Andric           ")",
790435933ddSDimitry Andric           process_address, process_address + size);
791ac7ddfbfSEd Maste       return;
792ac7ddfbfSEd Maste     }
793ac7ddfbfSEd Maste 
794ac7ddfbfSEd Maste     Allocation &allocation = iter->second;
795ac7ddfbfSEd Maste 
796435933ddSDimitry Andric     switch (allocation.m_policy) {
797ac7ddfbfSEd Maste     default:
798ac7ddfbfSEd Maste       error.SetErrorToGenericError();
799435933ddSDimitry Andric       error.SetErrorString(
800435933ddSDimitry Andric           "Couldn't get memory data: invalid allocation policy");
801ac7ddfbfSEd Maste       return;
802ac7ddfbfSEd Maste     case eAllocationPolicyProcessOnly:
803ac7ddfbfSEd Maste       error.SetErrorToGenericError();
804435933ddSDimitry Andric       error.SetErrorString(
805435933ddSDimitry Andric           "Couldn't get memory data: memory is only in the target");
806ac7ddfbfSEd Maste       return;
807435933ddSDimitry Andric     case eAllocationPolicyMirror: {
808ac7ddfbfSEd Maste       lldb::ProcessSP process_sp = m_process_wp.lock();
809ac7ddfbfSEd Maste 
810435933ddSDimitry Andric       if (!allocation.m_data.GetByteSize()) {
811ac7ddfbfSEd Maste         error.SetErrorToGenericError();
812ac7ddfbfSEd Maste         error.SetErrorString("Couldn't get memory data: data buffer is empty");
813ac7ddfbfSEd Maste         return;
814ac7ddfbfSEd Maste       }
815435933ddSDimitry Andric       if (process_sp) {
816435933ddSDimitry Andric         process_sp->ReadMemory(allocation.m_process_start,
817435933ddSDimitry Andric                                allocation.m_data.GetBytes(),
818435933ddSDimitry Andric                                allocation.m_data.GetByteSize(), error);
819ac7ddfbfSEd Maste         if (!error.Success())
820ac7ddfbfSEd Maste           return;
821ac7ddfbfSEd Maste         uint64_t offset = process_address - allocation.m_process_start;
822435933ddSDimitry Andric         extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
823435933ddSDimitry Andric                                   GetByteOrder(), GetAddressByteSize());
824ac7ddfbfSEd Maste         return;
825ac7ddfbfSEd Maste       }
826435933ddSDimitry Andric     } break;
827ac7ddfbfSEd Maste     case eAllocationPolicyHostOnly:
828435933ddSDimitry Andric       if (!allocation.m_data.GetByteSize()) {
829ac7ddfbfSEd Maste         error.SetErrorToGenericError();
830ac7ddfbfSEd Maste         error.SetErrorString("Couldn't get memory data: data buffer is empty");
831ac7ddfbfSEd Maste         return;
832ac7ddfbfSEd Maste       }
833ac7ddfbfSEd Maste       uint64_t offset = process_address - allocation.m_process_start;
834435933ddSDimitry Andric       extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
835435933ddSDimitry Andric                                 GetByteOrder(), GetAddressByteSize());
836ac7ddfbfSEd Maste       return;
837ac7ddfbfSEd Maste     }
838435933ddSDimitry Andric   } else {
839ac7ddfbfSEd Maste     error.SetErrorToGenericError();
840ac7ddfbfSEd Maste     error.SetErrorString("Couldn't get memory data: its size was zero");
841ac7ddfbfSEd Maste     return;
842ac7ddfbfSEd Maste   }
843ac7ddfbfSEd Maste }
844