15a1af4e6SSean Callanan //===-- IRMemoryMap.cpp -----------------------------------------*- C++ -*-===//
25a1af4e6SSean Callanan //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65a1af4e6SSean Callanan //
75a1af4e6SSean Callanan //===----------------------------------------------------------------------===//
85a1af4e6SSean Callanan 
9b9c1b51eSKate Stone #include "lldb/Expression/IRMemoryMap.h"
10f3df7e86SSean Callanan #include "lldb/Target/MemoryRegionInfo.h"
115a1af4e6SSean Callanan #include "lldb/Target/Process.h"
1235005f76SSean Callanan #include "lldb/Target/Target.h"
13666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
14666cc0b2SZachary Turner #include "lldb/Utility/DataExtractor.h"
15f3df7e86SSean Callanan #include "lldb/Utility/LLDBAssert.h"
166f9e6901SZachary Turner #include "lldb/Utility/Log.h"
17d821c997SPavel Labath #include "lldb/Utility/Scalar.h"
1897206d57SZachary Turner #include "lldb/Utility/Status.h"
195a1af4e6SSean Callanan 
205a1af4e6SSean Callanan using namespace lldb_private;
215a1af4e6SSean Callanan 
22b9c1b51eSKate Stone IRMemoryMap::IRMemoryMap(lldb::TargetSP target_sp) : m_target_wp(target_sp) {
23b024d878SSean Callanan   if (target_sp)
24b024d878SSean Callanan     m_process_wp = target_sp->GetProcessSP();
255a1af4e6SSean Callanan }
265a1af4e6SSean Callanan 
27b9c1b51eSKate Stone IRMemoryMap::~IRMemoryMap() {
285a1af4e6SSean Callanan   lldb::ProcessSP process_sp = m_process_wp.lock();
295a1af4e6SSean Callanan 
30b9c1b51eSKate Stone   if (process_sp) {
31bb77704cSSean Callanan     AllocationMap::iterator iter;
325a1af4e6SSean Callanan 
3397206d57SZachary Turner     Status err;
34bb77704cSSean Callanan 
35b9c1b51eSKate Stone     while ((iter = m_allocations.begin()) != m_allocations.end()) {
36bb77704cSSean Callanan       err.Clear();
37fbf5c682SSean Callanan       if (iter->second.m_leak)
38fbf5c682SSean Callanan         m_allocations.erase(iter);
39fbf5c682SSean Callanan       else
40bb77704cSSean Callanan         Free(iter->first, err);
415a1af4e6SSean Callanan     }
425a1af4e6SSean Callanan   }
435a1af4e6SSean Callanan }
445a1af4e6SSean Callanan 
45b9c1b51eSKate Stone lldb::addr_t IRMemoryMap::FindSpace(size_t size) {
46f3df7e86SSean Callanan   // The FindSpace algorithm's job is to find a region of memory that the
47f3df7e86SSean Callanan   // underlying process is unlikely to be using.
48f3df7e86SSean Callanan   //
49f3df7e86SSean Callanan   // The memory returned by this function will never be written to.  The only
50f3df7e86SSean Callanan   // point is that it should not shadow process memory if possible, so that
5105097246SAdrian Prantl   // expressions processing real values from the process do not use the wrong
5205097246SAdrian Prantl   // data.
53f3df7e86SSean Callanan   //
54f3df7e86SSean Callanan   // If the process can in fact allocate memory (CanJIT() lets us know this)
55f3df7e86SSean Callanan   // then this can be accomplished just be allocating memory in the inferior.
56f3df7e86SSean Callanan   // Then no guessing is required.
57f3df7e86SSean Callanan 
58bb9945f4SSean Callanan   lldb::TargetSP target_sp = m_target_wp.lock();
59bb9945f4SSean Callanan   lldb::ProcessSP process_sp = m_process_wp.lock();
605a1af4e6SSean Callanan 
61f3df7e86SSean Callanan   const bool process_is_alive = process_sp && process_sp->IsAlive();
62f3df7e86SSean Callanan 
63bb9945f4SSean Callanan   lldb::addr_t ret = LLDB_INVALID_ADDRESS;
643ddcd314SZachary Turner   if (size == 0)
653ddcd314SZachary Turner     return ret;
665a1af4e6SSean Callanan 
67b9c1b51eSKate Stone   if (process_is_alive && process_sp->CanJIT()) {
6897206d57SZachary Turner     Status alloc_error;
69df56540aSSean Callanan 
70b9c1b51eSKate Stone     ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable |
71b9c1b51eSKate Stone                                                lldb::ePermissionsWritable,
72b9c1b51eSKate Stone                                      alloc_error);
73df56540aSSean Callanan 
74df56540aSSean Callanan     if (!alloc_error.Success())
75df56540aSSean Callanan       return LLDB_INVALID_ADDRESS;
76df56540aSSean Callanan     else
77df56540aSSean Callanan       return ret;
78df56540aSSean Callanan   }
79df56540aSSean Callanan 
80f3df7e86SSean Callanan   // At this point we know that we need to hunt.
81f3df7e86SSean Callanan   //
82f3df7e86SSean Callanan   // First, go to the end of the existing allocations we've made if there are
83f3df7e86SSean Callanan   // any allocations.  Otherwise start at the beginning of memory.
84f3df7e86SSean Callanan 
85b9c1b51eSKate Stone   if (m_allocations.empty()) {
86f3df7e86SSean Callanan     ret = 0x0;
87b9c1b51eSKate Stone   } else {
88f3df7e86SSean Callanan     auto back = m_allocations.rbegin();
89f3df7e86SSean Callanan     lldb::addr_t addr = back->first;
90f3df7e86SSean Callanan     size_t alloc_size = back->second.m_size;
91f3df7e86SSean Callanan     ret = llvm::alignTo(addr + alloc_size, 4096);
92f3df7e86SSean Callanan   }
93f3df7e86SSean Callanan 
94f3df7e86SSean Callanan   // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped
9505097246SAdrian Prantl   // regions, walk forward through memory until a region is found that has
9605097246SAdrian Prantl   // adequate space for our allocation.
97b9c1b51eSKate Stone   if (process_is_alive) {
98b9c1b51eSKate Stone     const uint64_t end_of_memory = process_sp->GetAddressByteSize() == 8
99b9c1b51eSKate Stone                                        ? 0xffffffffffffffffull
100b9c1b51eSKate Stone                                        : 0xffffffffull;
101f3df7e86SSean Callanan 
102b9c1b51eSKate Stone     lldbassert(process_sp->GetAddressByteSize() == 4 ||
103b9c1b51eSKate Stone                end_of_memory != 0xffffffffull);
104f3df7e86SSean Callanan 
105f3df7e86SSean Callanan     MemoryRegionInfo region_info;
10697206d57SZachary Turner     Status err = process_sp->GetMemoryRegionInfo(ret, region_info);
107b9c1b51eSKate Stone     if (err.Success()) {
108b9c1b51eSKate Stone       while (true) {
109f3df7e86SSean Callanan         if (region_info.GetReadable() != MemoryRegionInfo::OptionalBool::eNo ||
110f3df7e86SSean Callanan             region_info.GetWritable() != MemoryRegionInfo::OptionalBool::eNo ||
111b9c1b51eSKate Stone             region_info.GetExecutable() !=
112b9c1b51eSKate Stone                 MemoryRegionInfo::OptionalBool::eNo) {
113b9c1b51eSKate Stone           if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory) {
114f3df7e86SSean Callanan             ret = LLDB_INVALID_ADDRESS;
115f3df7e86SSean Callanan             break;
116b9c1b51eSKate Stone           } else {
117f3df7e86SSean Callanan             ret = region_info.GetRange().GetRangeEnd();
118f3df7e86SSean Callanan           }
119b9c1b51eSKate Stone         } else if (ret + size < region_info.GetRange().GetRangeEnd()) {
120f3df7e86SSean Callanan           return ret;
121b9c1b51eSKate Stone         } else {
122f3df7e86SSean Callanan           // ret stays the same.  We just need to walk a bit further.
123f3df7e86SSean Callanan         }
124f3df7e86SSean Callanan 
125b9c1b51eSKate Stone         err = process_sp->GetMemoryRegionInfo(
126b9c1b51eSKate Stone             region_info.GetRange().GetRangeEnd(), region_info);
127b9c1b51eSKate Stone         if (err.Fail()) {
128f31c9d27SPavel Labath           lldbassert(0 && "GetMemoryRegionInfo() succeeded, then failed");
129f3df7e86SSean Callanan           ret = LLDB_INVALID_ADDRESS;
130f3df7e86SSean Callanan           break;
131f3df7e86SSean Callanan         }
132f3df7e86SSean Callanan       }
133f3df7e86SSean Callanan     }
134f3df7e86SSean Callanan   }
135f3df7e86SSean Callanan 
136f3df7e86SSean Callanan   // We've tried our algorithm, and it didn't work.  Now we have to reset back
137f3df7e86SSean Callanan   // to the end of the allocations we've already reported, or use a 'sensible'
138f3df7e86SSean Callanan   // default if this is our first allocation.
139f3df7e86SSean Callanan 
140b9c1b51eSKate Stone   if (m_allocations.empty()) {
141f3df7e86SSean Callanan     uint32_t address_byte_size = GetAddressByteSize();
142b9c1b51eSKate Stone     if (address_byte_size != UINT32_MAX) {
143b9c1b51eSKate Stone       switch (address_byte_size) {
144f3df7e86SSean Callanan       case 8:
145f3df7e86SSean Callanan         ret = 0xffffffff00000000ull;
146f3df7e86SSean Callanan         break;
147f3df7e86SSean Callanan       case 4:
148f3df7e86SSean Callanan         ret = 0xee000000ull;
149f3df7e86SSean Callanan         break;
150f3df7e86SSean Callanan       default:
151f3df7e86SSean Callanan         break;
152f3df7e86SSean Callanan       }
153f3df7e86SSean Callanan     }
154b9c1b51eSKate Stone   } else {
1553ddcd314SZachary Turner     auto back = m_allocations.rbegin();
1563ddcd314SZachary Turner     lldb::addr_t addr = back->first;
1573ddcd314SZachary Turner     size_t alloc_size = back->second.m_size;
158a94ae1e0SRafael Espindola     ret = llvm::alignTo(addr + alloc_size, 4096);
1595a1af4e6SSean Callanan   }
1605a1af4e6SSean Callanan 
161bb9945f4SSean Callanan   return ret;
1625a1af4e6SSean Callanan }
1635a1af4e6SSean Callanan 
1645a1af4e6SSean Callanan IRMemoryMap::AllocationMap::iterator
165b9c1b51eSKate Stone IRMemoryMap::FindAllocation(lldb::addr_t addr, size_t size) {
1661582ee68SSean Callanan   if (addr == LLDB_INVALID_ADDRESS)
1671582ee68SSean Callanan     return m_allocations.end();
1681582ee68SSean Callanan 
1695a1af4e6SSean Callanan   AllocationMap::iterator iter = m_allocations.lower_bound(addr);
1705a1af4e6SSean Callanan 
171b9c1b51eSKate Stone   if (iter == m_allocations.end() || iter->first > addr) {
1725a1af4e6SSean Callanan     if (iter == m_allocations.begin())
1735a1af4e6SSean Callanan       return m_allocations.end();
1745a1af4e6SSean Callanan     iter--;
1755a1af4e6SSean Callanan   }
1765a1af4e6SSean Callanan 
1775a1af4e6SSean Callanan   if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
1785a1af4e6SSean Callanan     return iter;
1795a1af4e6SSean Callanan 
1805a1af4e6SSean Callanan   return m_allocations.end();
1815a1af4e6SSean Callanan }
1825a1af4e6SSean Callanan 
183b9c1b51eSKate Stone bool IRMemoryMap::IntersectsAllocation(lldb::addr_t addr, size_t size) const {
184bb9945f4SSean Callanan   if (addr == LLDB_INVALID_ADDRESS)
185bb9945f4SSean Callanan     return false;
186bb9945f4SSean Callanan 
18715362445SZachary Turner   AllocationMap::const_iterator iter = m_allocations.lower_bound(addr);
188bb9945f4SSean Callanan 
189b9c1b51eSKate Stone   // Since we only know that the returned interval begins at a location greater
19005097246SAdrian Prantl   // than or equal to where the given interval begins, it's possible that the
19105097246SAdrian Prantl   // given interval intersects either the returned interval or the previous
19205097246SAdrian Prantl   // interval.  Thus, we need to check both. Note that we only need to check
19305097246SAdrian Prantl   // these two intervals.  Since all intervals are disjoint it is not possible
19405097246SAdrian Prantl   // that an adjacent interval does not intersect, but a non-adjacent interval
19505097246SAdrian Prantl   // does intersect.
19615362445SZachary Turner   if (iter != m_allocations.end()) {
197b9c1b51eSKate Stone     if (AllocationsIntersect(addr, size, iter->second.m_process_start,
198b9c1b51eSKate Stone                              iter->second.m_size))
199bb9945f4SSean Callanan       return true;
20015362445SZachary Turner   }
201bb9945f4SSean Callanan 
20215362445SZachary Turner   if (iter != m_allocations.begin()) {
20315362445SZachary Turner     --iter;
204b9c1b51eSKate Stone     if (AllocationsIntersect(addr, size, iter->second.m_process_start,
205b9c1b51eSKate Stone                              iter->second.m_size))
20615362445SZachary Turner       return true;
207bb9945f4SSean Callanan   }
208bb9945f4SSean Callanan 
209bb9945f4SSean Callanan   return false;
210bb9945f4SSean Callanan }
211bb9945f4SSean Callanan 
212b9c1b51eSKate Stone bool IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1,
213b9c1b51eSKate Stone                                        lldb::addr_t addr2, size_t size2) {
214b9c1b51eSKate Stone   // Given two half open intervals [A, B) and [X, Y), the only 6 permutations
21505097246SAdrian Prantl   // that satisfy A<B and X<Y are the following:
21615362445SZachary Turner   // A B X Y
21715362445SZachary Turner   // A X B Y  (intersects)
21815362445SZachary Turner   // A X Y B  (intersects)
21915362445SZachary Turner   // X A B Y  (intersects)
22015362445SZachary Turner   // X A Y B  (intersects)
22115362445SZachary Turner   // X Y A B
22205097246SAdrian Prantl   // The first is B <= X, and the last is Y <= A. So the condition is !(B <= X
22305097246SAdrian Prantl   // || Y <= A)), or (X < B && A < Y)
22415362445SZachary Turner   return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
22515362445SZachary Turner }
22615362445SZachary Turner 
227b9c1b51eSKate Stone lldb::ByteOrder IRMemoryMap::GetByteOrder() {
22835005f76SSean Callanan   lldb::ProcessSP process_sp = m_process_wp.lock();
22935005f76SSean Callanan 
23035005f76SSean Callanan   if (process_sp)
23135005f76SSean Callanan     return process_sp->GetByteOrder();
23235005f76SSean Callanan 
23335005f76SSean Callanan   lldb::TargetSP target_sp = m_target_wp.lock();
23435005f76SSean Callanan 
23535005f76SSean Callanan   if (target_sp)
23608052afaSSean Callanan     return target_sp->GetArchitecture().GetByteOrder();
23735005f76SSean Callanan 
23835005f76SSean Callanan   return lldb::eByteOrderInvalid;
23935005f76SSean Callanan }
24035005f76SSean Callanan 
241b9c1b51eSKate Stone uint32_t IRMemoryMap::GetAddressByteSize() {
24235005f76SSean Callanan   lldb::ProcessSP process_sp = m_process_wp.lock();
24335005f76SSean Callanan 
24435005f76SSean Callanan   if (process_sp)
24535005f76SSean Callanan     return process_sp->GetAddressByteSize();
24635005f76SSean Callanan 
24735005f76SSean Callanan   lldb::TargetSP target_sp = m_target_wp.lock();
24835005f76SSean Callanan 
24935005f76SSean Callanan   if (target_sp)
25008052afaSSean Callanan     return target_sp->GetArchitecture().GetAddressByteSize();
25135005f76SSean Callanan 
25235005f76SSean Callanan   return UINT32_MAX;
25335005f76SSean Callanan }
25435005f76SSean Callanan 
255b9c1b51eSKate Stone ExecutionContextScope *IRMemoryMap::GetBestExecutionContextScope() const {
25635005f76SSean Callanan   lldb::ProcessSP process_sp = m_process_wp.lock();
25735005f76SSean Callanan 
25835005f76SSean Callanan   if (process_sp)
25935005f76SSean Callanan     return process_sp.get();
26035005f76SSean Callanan 
26135005f76SSean Callanan   lldb::TargetSP target_sp = m_target_wp.lock();
26235005f76SSean Callanan 
26335005f76SSean Callanan   if (target_sp)
26435005f76SSean Callanan     return target_sp.get();
26535005f76SSean Callanan 
266248a1305SKonrad Kleine   return nullptr;
26735005f76SSean Callanan }
26835005f76SSean Callanan 
269d2562509SSean Callanan IRMemoryMap::Allocation::Allocation(lldb::addr_t process_alloc,
270b9c1b51eSKate Stone                                     lldb::addr_t process_start, size_t size,
271b9c1b51eSKate Stone                                     uint32_t permissions, uint8_t alignment,
272b9c1b51eSKate Stone                                     AllocationPolicy policy)
273b9c1b51eSKate Stone     : m_process_alloc(process_alloc), m_process_start(process_start),
274f71dd344SVedant Kumar       m_size(size), m_policy(policy), m_leak(false), m_permissions(permissions),
275f71dd344SVedant Kumar       m_alignment(alignment) {
276b9c1b51eSKate Stone   switch (policy) {
277d2562509SSean Callanan   default:
27835861f21SFangrui Song     llvm_unreachable("Invalid AllocationPolicy");
279d2562509SSean Callanan   case eAllocationPolicyHostOnly:
280d2562509SSean Callanan   case eAllocationPolicyMirror:
281d2562509SSean Callanan     m_data.SetByteSize(size);
28294523598SVedant Kumar     break;
28394523598SVedant Kumar   case eAllocationPolicyProcessOnly:
284d2562509SSean Callanan     break;
285d2562509SSean Callanan   }
286d2562509SSean Callanan }
287d2562509SSean Callanan 
288b9c1b51eSKate Stone lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment,
289b9c1b51eSKate Stone                                  uint32_t permissions, AllocationPolicy policy,
29097206d57SZachary Turner                                  bool zero_memory, Status &error) {
291b9c1b51eSKate Stone   lldb_private::Log *log(
292b9c1b51eSKate Stone       lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
29308052afaSSean Callanan   error.Clear();
29408052afaSSean Callanan 
2955a1af4e6SSean Callanan   lldb::ProcessSP process_sp;
2965a1af4e6SSean Callanan   lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
2975a1af4e6SSean Callanan   lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
2985a1af4e6SSean Callanan 
299750dcc33SMatt Kopec   size_t allocation_size;
300750dcc33SMatt Kopec 
3015b71e75eSVedant Kumar   if (size == 0) {
3025b71e75eSVedant Kumar     // FIXME: Malloc(0) should either return an invalid address or assert, in
3035b71e75eSVedant Kumar     // order to cut down on unnecessary allocations.
304750dcc33SMatt Kopec     allocation_size = alignment;
3055b71e75eSVedant Kumar   } else {
3065b71e75eSVedant Kumar     // Round up the requested size to an aligned value.
3075b71e75eSVedant Kumar     allocation_size = llvm::alignTo(size, alignment);
3085b71e75eSVedant Kumar 
3095b71e75eSVedant Kumar     // The process page cache does not see the requested alignment. We can't
3105b71e75eSVedant Kumar     // assume its result will be any more than 1-byte aligned. To work around
3115b71e75eSVedant Kumar     // this, request `alignment - 1` additional bytes.
3125b71e75eSVedant Kumar     allocation_size += alignment - 1;
3135b71e75eSVedant Kumar   }
3145a1af4e6SSean Callanan 
315b9c1b51eSKate Stone   switch (policy) {
3165a1af4e6SSean Callanan   default:
3175a1af4e6SSean Callanan     error.SetErrorToGenericError();
3185a1af4e6SSean Callanan     error.SetErrorString("Couldn't malloc: invalid allocation policy");
3195a1af4e6SSean Callanan     return LLDB_INVALID_ADDRESS;
3205a1af4e6SSean Callanan   case eAllocationPolicyHostOnly:
3215a1af4e6SSean Callanan     allocation_address = FindSpace(allocation_size);
322b9c1b51eSKate Stone     if (allocation_address == LLDB_INVALID_ADDRESS) {
3235a1af4e6SSean Callanan       error.SetErrorToGenericError();
3245a1af4e6SSean Callanan       error.SetErrorString("Couldn't malloc: address space is full");
3255a1af4e6SSean Callanan       return LLDB_INVALID_ADDRESS;
3265a1af4e6SSean Callanan     }
3275a1af4e6SSean Callanan     break;
3285a1af4e6SSean Callanan   case eAllocationPolicyMirror:
3295a1af4e6SSean Callanan     process_sp = m_process_wp.lock();
33063e5fb76SJonas Devlieghere     LLDB_LOGF(log,
331*df6879ecSJan Kratochvil               "IRMemoryMap::%s process_sp=0x%" PRIxPTR
332b9c1b51eSKate Stone               ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s",
333*df6879ecSJan Kratochvil               __FUNCTION__, reinterpret_cast<uintptr_t>(process_sp.get()),
334b9c1b51eSKate Stone               process_sp && process_sp->CanJIT() ? "true" : "false",
335b9c1b51eSKate Stone               process_sp && process_sp->IsAlive() ? "true" : "false");
336b9c1b51eSKate Stone     if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) {
3372c381414SJim Ingham       if (!zero_memory)
338b9c1b51eSKate Stone         allocation_address =
339b9c1b51eSKate Stone             process_sp->AllocateMemory(allocation_size, permissions, error);
3402c381414SJim Ingham       else
341b9c1b51eSKate Stone         allocation_address =
342b9c1b51eSKate Stone             process_sp->CallocateMemory(allocation_size, permissions, error);
3432c381414SJim Ingham 
3445a1af4e6SSean Callanan       if (!error.Success())
3455a1af4e6SSean Callanan         return LLDB_INVALID_ADDRESS;
346b9c1b51eSKate Stone     } else {
34763e5fb76SJonas Devlieghere       LLDB_LOGF(log,
34863e5fb76SJonas Devlieghere                 "IRMemoryMap::%s switching to eAllocationPolicyHostOnly "
349b9c1b51eSKate Stone                 "due to failed condition (see previous expr log message)",
350b9c1b51eSKate Stone                 __FUNCTION__);
351bb9945f4SSean Callanan       policy = eAllocationPolicyHostOnly;
3525a1af4e6SSean Callanan       allocation_address = FindSpace(allocation_size);
353b9c1b51eSKate Stone       if (allocation_address == LLDB_INVALID_ADDRESS) {
3545a1af4e6SSean Callanan         error.SetErrorToGenericError();
3555a1af4e6SSean Callanan         error.SetErrorString("Couldn't malloc: address space is full");
3565a1af4e6SSean Callanan         return LLDB_INVALID_ADDRESS;
3575a1af4e6SSean Callanan       }
3585a1af4e6SSean Callanan     }
3595a1af4e6SSean Callanan     break;
3605a1af4e6SSean Callanan   case eAllocationPolicyProcessOnly:
3615a1af4e6SSean Callanan     process_sp = m_process_wp.lock();
362b9c1b51eSKate Stone     if (process_sp) {
363b9c1b51eSKate Stone       if (process_sp->CanJIT() && process_sp->IsAlive()) {
3642c381414SJim Ingham         if (!zero_memory)
365b9c1b51eSKate Stone           allocation_address =
366b9c1b51eSKate Stone               process_sp->AllocateMemory(allocation_size, permissions, error);
3672c381414SJim Ingham         else
368b9c1b51eSKate Stone           allocation_address =
369b9c1b51eSKate Stone               process_sp->CallocateMemory(allocation_size, permissions, error);
3702c381414SJim Ingham 
3715a1af4e6SSean Callanan         if (!error.Success())
3725a1af4e6SSean Callanan           return LLDB_INVALID_ADDRESS;
373b9c1b51eSKate Stone       } else {
3745a1af4e6SSean Callanan         error.SetErrorToGenericError();
375b9c1b51eSKate Stone         error.SetErrorString(
376b9c1b51eSKate Stone             "Couldn't malloc: process doesn't support allocating memory");
377bb9945f4SSean Callanan         return LLDB_INVALID_ADDRESS;
378bb9945f4SSean Callanan       }
379b9c1b51eSKate Stone     } else {
380bb9945f4SSean Callanan       error.SetErrorToGenericError();
381b9c1b51eSKate Stone       error.SetErrorString("Couldn't malloc: process doesn't exist, and this "
382b9c1b51eSKate Stone                            "memory must be in the process");
3835a1af4e6SSean Callanan       return LLDB_INVALID_ADDRESS;
3845a1af4e6SSean Callanan     }
3855a1af4e6SSean Callanan     break;
3865a1af4e6SSean Callanan   }
3875a1af4e6SSean Callanan 
3885a1af4e6SSean Callanan   lldb::addr_t mask = alignment - 1;
3895a1af4e6SSean Callanan   aligned_address = (allocation_address + mask) & (~mask);
3905a1af4e6SSean Callanan 
391f71dd344SVedant Kumar   m_allocations.emplace(
392f71dd344SVedant Kumar       std::piecewise_construct, std::forward_as_tuple(aligned_address),
393f71dd344SVedant Kumar       std::forward_as_tuple(allocation_address, aligned_address,
394f71dd344SVedant Kumar                             allocation_size, permissions, alignment, policy));
3955a1af4e6SSean Callanan 
396b9c1b51eSKate Stone   if (zero_memory) {
39797206d57SZachary Turner     Status write_error;
398b37674dcSSean Callanan     std::vector<uint8_t> zero_buf(size, 0);
399b37674dcSSean Callanan     WriteMemory(aligned_address, zero_buf.data(), size, write_error);
400b37674dcSSean Callanan   }
401b37674dcSSean Callanan 
402b9c1b51eSKate Stone   if (log) {
4035a1af4e6SSean Callanan     const char *policy_string;
4045a1af4e6SSean Callanan 
405b9c1b51eSKate Stone     switch (policy) {
4065a1af4e6SSean Callanan     default:
4075a1af4e6SSean Callanan       policy_string = "<invalid policy>";
4085a1af4e6SSean Callanan       break;
4095a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
4105a1af4e6SSean Callanan       policy_string = "eAllocationPolicyHostOnly";
4115a1af4e6SSean Callanan       break;
4125a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
4135a1af4e6SSean Callanan       policy_string = "eAllocationPolicyProcessOnly";
4145a1af4e6SSean Callanan       break;
4155a1af4e6SSean Callanan     case eAllocationPolicyMirror:
4165a1af4e6SSean Callanan       policy_string = "eAllocationPolicyMirror";
4175a1af4e6SSean Callanan       break;
4185a1af4e6SSean Callanan     }
4195a1af4e6SSean Callanan 
42063e5fb76SJonas Devlieghere     LLDB_LOGF(log,
42163e5fb76SJonas Devlieghere               "IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64
422b9c1b51eSKate Stone               ", %s) -> 0x%" PRIx64,
423b9c1b51eSKate Stone               (uint64_t)allocation_size, (uint64_t)alignment,
424b9c1b51eSKate Stone               (uint64_t)permissions, policy_string, aligned_address);
4255a1af4e6SSean Callanan   }
4265a1af4e6SSean Callanan 
4275a1af4e6SSean Callanan   return aligned_address;
4285a1af4e6SSean Callanan }
4295a1af4e6SSean Callanan 
43097206d57SZachary Turner void IRMemoryMap::Leak(lldb::addr_t process_address, Status &error) {
431fbf5c682SSean Callanan   error.Clear();
432fbf5c682SSean Callanan 
433fbf5c682SSean Callanan   AllocationMap::iterator iter = m_allocations.find(process_address);
434fbf5c682SSean Callanan 
435b9c1b51eSKate Stone   if (iter == m_allocations.end()) {
436fbf5c682SSean Callanan     error.SetErrorToGenericError();
437fbf5c682SSean Callanan     error.SetErrorString("Couldn't leak: allocation doesn't exist");
438fbf5c682SSean Callanan     return;
439fbf5c682SSean Callanan   }
440fbf5c682SSean Callanan 
441fbf5c682SSean Callanan   Allocation &allocation = iter->second;
442fbf5c682SSean Callanan 
443fbf5c682SSean Callanan   allocation.m_leak = true;
444fbf5c682SSean Callanan }
445fbf5c682SSean Callanan 
44697206d57SZachary Turner void IRMemoryMap::Free(lldb::addr_t process_address, Status &error) {
44708052afaSSean Callanan   error.Clear();
44808052afaSSean Callanan 
4495a1af4e6SSean Callanan   AllocationMap::iterator iter = m_allocations.find(process_address);
4505a1af4e6SSean Callanan 
451b9c1b51eSKate Stone   if (iter == m_allocations.end()) {
4525a1af4e6SSean Callanan     error.SetErrorToGenericError();
4535a1af4e6SSean Callanan     error.SetErrorString("Couldn't free: allocation doesn't exist");
4545a1af4e6SSean Callanan     return;
4555a1af4e6SSean Callanan   }
4565a1af4e6SSean Callanan 
4575a1af4e6SSean Callanan   Allocation &allocation = iter->second;
4585a1af4e6SSean Callanan 
459b9c1b51eSKate Stone   switch (allocation.m_policy) {
4605a1af4e6SSean Callanan   default:
461b9c1b51eSKate Stone   case eAllocationPolicyHostOnly: {
462df56540aSSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
463b9c1b51eSKate Stone     if (process_sp) {
464ad7cc466SSean Callanan       if (process_sp->CanJIT() && process_sp->IsAlive())
465b9c1b51eSKate Stone         process_sp->DeallocateMemory(
466b9c1b51eSKate Stone             allocation.m_process_alloc); // FindSpace allocated this for real
467bb77704cSSean Callanan     }
468df56540aSSean Callanan 
4695a1af4e6SSean Callanan     break;
470df56540aSSean Callanan   }
4715a1af4e6SSean Callanan   case eAllocationPolicyMirror:
472b9c1b51eSKate Stone   case eAllocationPolicyProcessOnly: {
4735a1af4e6SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
4745a1af4e6SSean Callanan     if (process_sp)
4755a1af4e6SSean Callanan       process_sp->DeallocateMemory(allocation.m_process_alloc);
4765a1af4e6SSean Callanan   }
477df56540aSSean Callanan   }
4785a1af4e6SSean Callanan 
479b9c1b51eSKate Stone   if (lldb_private::Log *log =
480b9c1b51eSKate Stone           lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
48163e5fb76SJonas Devlieghere     LLDB_LOGF(log,
48263e5fb76SJonas Devlieghere               "IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64
483b9c1b51eSKate Stone               "..0x%" PRIx64 ")",
484b9c1b51eSKate Stone               (uint64_t)process_address, iter->second.m_process_start,
4855a1af4e6SSean Callanan               iter->second.m_process_start + iter->second.m_size);
4865a1af4e6SSean Callanan   }
4875a1af4e6SSean Callanan 
4885a1af4e6SSean Callanan   m_allocations.erase(iter);
4895a1af4e6SSean Callanan }
4905a1af4e6SSean Callanan 
491b9c1b51eSKate Stone bool IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size) {
49290ff7911SEwan Crawford   AllocationMap::iterator iter = FindAllocation(address, size);
49390ff7911SEwan Crawford   if (iter == m_allocations.end())
49490ff7911SEwan Crawford     return false;
49590ff7911SEwan Crawford 
49690ff7911SEwan Crawford   Allocation &al = iter->second;
49790ff7911SEwan Crawford 
498b9c1b51eSKate Stone   if (address > (al.m_process_start + al.m_size)) {
49990ff7911SEwan Crawford     size = 0;
50090ff7911SEwan Crawford     return false;
50190ff7911SEwan Crawford   }
50290ff7911SEwan Crawford 
503b9c1b51eSKate Stone   if (address > al.m_process_start) {
50490ff7911SEwan Crawford     int dif = address - al.m_process_start;
50590ff7911SEwan Crawford     size = al.m_size - dif;
50690ff7911SEwan Crawford     return true;
50790ff7911SEwan Crawford   }
50890ff7911SEwan Crawford 
50990ff7911SEwan Crawford   size = al.m_size;
51090ff7911SEwan Crawford   return true;
51190ff7911SEwan Crawford }
51290ff7911SEwan Crawford 
513b9c1b51eSKate Stone void IRMemoryMap::WriteMemory(lldb::addr_t process_address,
51497206d57SZachary Turner                               const uint8_t *bytes, size_t size,
51597206d57SZachary Turner                               Status &error) {
51608052afaSSean Callanan   error.Clear();
51708052afaSSean Callanan 
5185a1af4e6SSean Callanan   AllocationMap::iterator iter = FindAllocation(process_address, size);
5195a1af4e6SSean Callanan 
520b9c1b51eSKate Stone   if (iter == m_allocations.end()) {
521c8c5b8dcSSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
522c8c5b8dcSSean Callanan 
523b9c1b51eSKate Stone     if (process_sp) {
524c8c5b8dcSSean Callanan       process_sp->WriteMemory(process_address, bytes, size, error);
525c8c5b8dcSSean Callanan       return;
526c8c5b8dcSSean Callanan     }
527c8c5b8dcSSean Callanan 
5285a1af4e6SSean Callanan     error.SetErrorToGenericError();
529b9c1b51eSKate Stone     error.SetErrorString("Couldn't write: no allocation contains the target "
530b9c1b51eSKate Stone                          "range and the process doesn't exist");
5315a1af4e6SSean Callanan     return;
5325a1af4e6SSean Callanan   }
5335a1af4e6SSean Callanan 
5345a1af4e6SSean Callanan   Allocation &allocation = iter->second;
5355a1af4e6SSean Callanan 
5365a1af4e6SSean Callanan   uint64_t offset = process_address - allocation.m_process_start;
5375a1af4e6SSean Callanan 
5385a1af4e6SSean Callanan   lldb::ProcessSP process_sp;
5395a1af4e6SSean Callanan 
540b9c1b51eSKate Stone   switch (allocation.m_policy) {
5415a1af4e6SSean Callanan   default:
5425a1af4e6SSean Callanan     error.SetErrorToGenericError();
5435a1af4e6SSean Callanan     error.SetErrorString("Couldn't write: invalid allocation policy");
5445a1af4e6SSean Callanan     return;
5455a1af4e6SSean Callanan   case eAllocationPolicyHostOnly:
546b9c1b51eSKate Stone     if (!allocation.m_data.GetByteSize()) {
5475a1af4e6SSean Callanan       error.SetErrorToGenericError();
5485a1af4e6SSean Callanan       error.SetErrorString("Couldn't write: data buffer is empty");
5495a1af4e6SSean Callanan       return;
5505a1af4e6SSean Callanan     }
551d2562509SSean Callanan     ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
5525a1af4e6SSean Callanan     break;
5535a1af4e6SSean Callanan   case eAllocationPolicyMirror:
554b9c1b51eSKate Stone     if (!allocation.m_data.GetByteSize()) {
5555a1af4e6SSean Callanan       error.SetErrorToGenericError();
5565a1af4e6SSean Callanan       error.SetErrorString("Couldn't write: data buffer is empty");
5575a1af4e6SSean Callanan       return;
5585a1af4e6SSean Callanan     }
559d2562509SSean Callanan     ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
5605a1af4e6SSean Callanan     process_sp = m_process_wp.lock();
561b9c1b51eSKate Stone     if (process_sp) {
5625a1af4e6SSean Callanan       process_sp->WriteMemory(process_address, bytes, size, error);
5635a1af4e6SSean Callanan       if (!error.Success())
5645a1af4e6SSean Callanan         return;
5655a1af4e6SSean Callanan     }
5665a1af4e6SSean Callanan     break;
5675a1af4e6SSean Callanan   case eAllocationPolicyProcessOnly:
5685a1af4e6SSean Callanan     process_sp = m_process_wp.lock();
569b9c1b51eSKate Stone     if (process_sp) {
5705a1af4e6SSean Callanan       process_sp->WriteMemory(process_address, bytes, size, error);
5715a1af4e6SSean Callanan       if (!error.Success())
5725a1af4e6SSean Callanan         return;
5735a1af4e6SSean Callanan     }
5745a1af4e6SSean Callanan     break;
5755a1af4e6SSean Callanan   }
5765a1af4e6SSean Callanan 
577b9c1b51eSKate Stone   if (lldb_private::Log *log =
578b9c1b51eSKate Stone           lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
57963e5fb76SJonas Devlieghere     LLDB_LOGF(log,
580*df6879ecSJan Kratochvil               "IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIxPTR
581b9c1b51eSKate Stone               ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
582*df6879ecSJan Kratochvil               (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,
5835a1af4e6SSean Callanan               (uint64_t)allocation.m_process_start,
584b9c1b51eSKate Stone               (uint64_t)allocation.m_process_start +
585b9c1b51eSKate Stone                   (uint64_t)allocation.m_size);
5865a1af4e6SSean Callanan   }
5875a1af4e6SSean Callanan }
5885a1af4e6SSean Callanan 
589b9c1b51eSKate Stone void IRMemoryMap::WriteScalarToMemory(lldb::addr_t process_address,
590b9c1b51eSKate Stone                                       Scalar &scalar, size_t size,
59197206d57SZachary Turner                                       Status &error) {
59208052afaSSean Callanan   error.Clear();
59308052afaSSean Callanan 
59435005f76SSean Callanan   if (size == UINT32_MAX)
59535005f76SSean Callanan     size = scalar.GetByteSize();
59635005f76SSean Callanan 
597b9c1b51eSKate Stone   if (size > 0) {
59835005f76SSean Callanan     uint8_t buf[32];
599b9c1b51eSKate Stone     const size_t mem_size =
600b9c1b51eSKate Stone         scalar.GetAsMemoryData(buf, size, GetByteOrder(), error);
601b9c1b51eSKate Stone     if (mem_size > 0) {
60235005f76SSean Callanan       return WriteMemory(process_address, buf, mem_size, error);
603b9c1b51eSKate Stone     } else {
60435005f76SSean Callanan       error.SetErrorToGenericError();
605b9c1b51eSKate Stone       error.SetErrorString(
606b9c1b51eSKate Stone           "Couldn't write scalar: failed to get scalar as memory data");
60735005f76SSean Callanan     }
608b9c1b51eSKate Stone   } else {
60935005f76SSean Callanan     error.SetErrorToGenericError();
61035005f76SSean Callanan     error.SetErrorString("Couldn't write scalar: its size was zero");
61135005f76SSean Callanan   }
61235005f76SSean Callanan   return;
61335005f76SSean Callanan }
61435005f76SSean Callanan 
615b9c1b51eSKate Stone void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address,
61697206d57SZachary Turner                                        lldb::addr_t address, Status &error) {
61708052afaSSean Callanan   error.Clear();
61808052afaSSean Callanan 
619f8043fa5SSean Callanan   Scalar scalar(address);
620f8043fa5SSean Callanan 
621f8043fa5SSean Callanan   WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
622f8043fa5SSean Callanan }
623f8043fa5SSean Callanan 
624b9c1b51eSKate Stone void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address,
62597206d57SZachary Turner                              size_t size, Status &error) {
62608052afaSSean Callanan   error.Clear();
62708052afaSSean Callanan 
6285a1af4e6SSean Callanan   AllocationMap::iterator iter = FindAllocation(process_address, size);
6295a1af4e6SSean Callanan 
630b9c1b51eSKate Stone   if (iter == m_allocations.end()) {
631c8c5b8dcSSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
632c8c5b8dcSSean Callanan 
633b9c1b51eSKate Stone     if (process_sp) {
634c8c5b8dcSSean Callanan       process_sp->ReadMemory(process_address, bytes, size, error);
635c8c5b8dcSSean Callanan       return;
636c8c5b8dcSSean Callanan     }
637c8c5b8dcSSean Callanan 
638c8c5b8dcSSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
639c8c5b8dcSSean Callanan 
640b9c1b51eSKate Stone     if (target_sp) {
641c8c5b8dcSSean Callanan       Address absolute_address(process_address);
642c8c5b8dcSSean Callanan       target_sp->ReadMemory(absolute_address, false, bytes, size, error);
643c8c5b8dcSSean Callanan       return;
644c8c5b8dcSSean Callanan     }
645c8c5b8dcSSean Callanan 
6465a1af4e6SSean Callanan     error.SetErrorToGenericError();
647b9c1b51eSKate Stone     error.SetErrorString("Couldn't read: no allocation contains the target "
648b9c1b51eSKate Stone                          "range, and neither the process nor the target exist");
6495a1af4e6SSean Callanan     return;
6505a1af4e6SSean Callanan   }
6515a1af4e6SSean Callanan 
6525a1af4e6SSean Callanan   Allocation &allocation = iter->second;
6535a1af4e6SSean Callanan 
6545a1af4e6SSean Callanan   uint64_t offset = process_address - allocation.m_process_start;
6555a1af4e6SSean Callanan 
656b9c1b51eSKate Stone   if (offset > allocation.m_size) {
6579bbf3cd3SSean Callanan     error.SetErrorToGenericError();
6589bbf3cd3SSean Callanan     error.SetErrorString("Couldn't read: data is not in the allocation");
6599bbf3cd3SSean Callanan     return;
6609bbf3cd3SSean Callanan   }
6619bbf3cd3SSean Callanan 
6625a1af4e6SSean Callanan   lldb::ProcessSP process_sp;
6635a1af4e6SSean Callanan 
664b9c1b51eSKate Stone   switch (allocation.m_policy) {
6655a1af4e6SSean Callanan   default:
6665a1af4e6SSean Callanan     error.SetErrorToGenericError();
6675a1af4e6SSean Callanan     error.SetErrorString("Couldn't read: invalid allocation policy");
6685a1af4e6SSean Callanan     return;
6695a1af4e6SSean Callanan   case eAllocationPolicyHostOnly:
670b9c1b51eSKate Stone     if (!allocation.m_data.GetByteSize()) {
6715a1af4e6SSean Callanan       error.SetErrorToGenericError();
6725a1af4e6SSean Callanan       error.SetErrorString("Couldn't read: data buffer is empty");
6735a1af4e6SSean Callanan       return;
6745a1af4e6SSean Callanan     }
675b9c1b51eSKate Stone     if (allocation.m_data.GetByteSize() < offset + size) {
6769bbf3cd3SSean Callanan       error.SetErrorToGenericError();
6779bbf3cd3SSean Callanan       error.SetErrorString("Couldn't read: not enough underlying data");
6789bbf3cd3SSean Callanan       return;
6799bbf3cd3SSean Callanan     }
6809bbf3cd3SSean Callanan 
681d2562509SSean Callanan     ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
6825a1af4e6SSean Callanan     break;
6835a1af4e6SSean Callanan   case eAllocationPolicyMirror:
6845a1af4e6SSean Callanan     process_sp = m_process_wp.lock();
685b9c1b51eSKate Stone     if (process_sp) {
6865a1af4e6SSean Callanan       process_sp->ReadMemory(process_address, bytes, size, error);
6875a1af4e6SSean Callanan       if (!error.Success())
6885a1af4e6SSean Callanan         return;
689b9c1b51eSKate Stone     } else {
690b9c1b51eSKate Stone       if (!allocation.m_data.GetByteSize()) {
6915a1af4e6SSean Callanan         error.SetErrorToGenericError();
6925a1af4e6SSean Callanan         error.SetErrorString("Couldn't read: data buffer is empty");
6935a1af4e6SSean Callanan         return;
6945a1af4e6SSean Callanan       }
695d2562509SSean Callanan       ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
6965a1af4e6SSean Callanan     }
6975a1af4e6SSean Callanan     break;
6985a1af4e6SSean Callanan   case eAllocationPolicyProcessOnly:
6995a1af4e6SSean Callanan     process_sp = m_process_wp.lock();
700b9c1b51eSKate Stone     if (process_sp) {
7015a1af4e6SSean Callanan       process_sp->ReadMemory(process_address, bytes, size, error);
7025a1af4e6SSean Callanan       if (!error.Success())
7035a1af4e6SSean Callanan         return;
7045a1af4e6SSean Callanan     }
7055a1af4e6SSean Callanan     break;
7065a1af4e6SSean Callanan   }
7075a1af4e6SSean Callanan 
708b9c1b51eSKate Stone   if (lldb_private::Log *log =
709b9c1b51eSKate Stone           lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS)) {
71063e5fb76SJonas Devlieghere     LLDB_LOGF(log,
711*df6879ecSJan Kratochvil               "IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIxPTR
712b9c1b51eSKate Stone               ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
713*df6879ecSJan Kratochvil               (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,
7145a1af4e6SSean Callanan               (uint64_t)allocation.m_process_start,
715b9c1b51eSKate Stone               (uint64_t)allocation.m_process_start +
716b9c1b51eSKate Stone                   (uint64_t)allocation.m_size);
7175a1af4e6SSean Callanan   }
7185a1af4e6SSean Callanan }
71935005f76SSean Callanan 
720b9c1b51eSKate Stone void IRMemoryMap::ReadScalarFromMemory(Scalar &scalar,
721b9c1b51eSKate Stone                                        lldb::addr_t process_address,
72297206d57SZachary Turner                                        size_t size, Status &error) {
72308052afaSSean Callanan   error.Clear();
72408052afaSSean Callanan 
725b9c1b51eSKate Stone   if (size > 0) {
72635005f76SSean Callanan     DataBufferHeap buf(size, 0);
72735005f76SSean Callanan     ReadMemory(buf.GetBytes(), process_address, size, error);
72835005f76SSean Callanan 
72935005f76SSean Callanan     if (!error.Success())
73035005f76SSean Callanan       return;
73135005f76SSean Callanan 
732b9c1b51eSKate Stone     DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(),
733b9c1b51eSKate Stone                             GetAddressByteSize());
73435005f76SSean Callanan 
73535005f76SSean Callanan     lldb::offset_t offset = 0;
73635005f76SSean Callanan 
737b9c1b51eSKate Stone     switch (size) {
73835005f76SSean Callanan     default:
73935005f76SSean Callanan       error.SetErrorToGenericError();
740b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
741b9c1b51eSKate Stone           "Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
74235005f76SSean Callanan       return;
743b9c1b51eSKate Stone     case 1:
744b9c1b51eSKate Stone       scalar = extractor.GetU8(&offset);
745b9c1b51eSKate Stone       break;
746b9c1b51eSKate Stone     case 2:
747b9c1b51eSKate Stone       scalar = extractor.GetU16(&offset);
748b9c1b51eSKate Stone       break;
749b9c1b51eSKate Stone     case 4:
750b9c1b51eSKate Stone       scalar = extractor.GetU32(&offset);
751b9c1b51eSKate Stone       break;
752b9c1b51eSKate Stone     case 8:
753b9c1b51eSKate Stone       scalar = extractor.GetU64(&offset);
754b9c1b51eSKate Stone       break;
75535005f76SSean Callanan     }
756b9c1b51eSKate Stone   } else {
75735005f76SSean Callanan     error.SetErrorToGenericError();
758458ae1c6SSean Callanan     error.SetErrorString("Couldn't read scalar: its size was zero");
75935005f76SSean Callanan   }
76035005f76SSean Callanan   return;
76135005f76SSean Callanan }
76235005f76SSean Callanan 
763b9c1b51eSKate Stone void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t *address,
764b9c1b51eSKate Stone                                         lldb::addr_t process_address,
76597206d57SZachary Turner                                         Status &error) {
76608052afaSSean Callanan   error.Clear();
76708052afaSSean Callanan 
7682d37e5a5SSean Callanan   Scalar pointer_scalar;
769b9c1b51eSKate Stone   ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(),
770b9c1b51eSKate Stone                        error);
7712d37e5a5SSean Callanan 
7722d37e5a5SSean Callanan   if (!error.Success())
7732d37e5a5SSean Callanan     return;
7742d37e5a5SSean Callanan 
7752d37e5a5SSean Callanan   *address = pointer_scalar.ULongLong();
7762d37e5a5SSean Callanan 
7772d37e5a5SSean Callanan   return;
7782d37e5a5SSean Callanan }
7792d37e5a5SSean Callanan 
780b9c1b51eSKate Stone void IRMemoryMap::GetMemoryData(DataExtractor &extractor,
781b9c1b51eSKate Stone                                 lldb::addr_t process_address, size_t size,
78297206d57SZachary Turner                                 Status &error) {
78308052afaSSean Callanan   error.Clear();
78408052afaSSean Callanan 
785b9c1b51eSKate Stone   if (size > 0) {
786458ae1c6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
787458ae1c6SSean Callanan 
788b9c1b51eSKate Stone     if (iter == m_allocations.end()) {
789458ae1c6SSean Callanan       error.SetErrorToGenericError();
790b9c1b51eSKate Stone       error.SetErrorStringWithFormat(
791b9c1b51eSKate Stone           "Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64
792b9c1b51eSKate Stone           ")",
793b9c1b51eSKate Stone           process_address, process_address + size);
794458ae1c6SSean Callanan       return;
795458ae1c6SSean Callanan     }
796458ae1c6SSean Callanan 
797458ae1c6SSean Callanan     Allocation &allocation = iter->second;
798458ae1c6SSean Callanan 
799b9c1b51eSKate Stone     switch (allocation.m_policy) {
800458ae1c6SSean Callanan     default:
801458ae1c6SSean Callanan       error.SetErrorToGenericError();
802b9c1b51eSKate Stone       error.SetErrorString(
803b9c1b51eSKate Stone           "Couldn't get memory data: invalid allocation policy");
804458ae1c6SSean Callanan       return;
805458ae1c6SSean Callanan     case eAllocationPolicyProcessOnly:
806458ae1c6SSean Callanan       error.SetErrorToGenericError();
807b9c1b51eSKate Stone       error.SetErrorString(
808b9c1b51eSKate Stone           "Couldn't get memory data: memory is only in the target");
809458ae1c6SSean Callanan       return;
810b9c1b51eSKate Stone     case eAllocationPolicyMirror: {
811c8c5b8dcSSean Callanan       lldb::ProcessSP process_sp = m_process_wp.lock();
812c8c5b8dcSSean Callanan 
813b9c1b51eSKate Stone       if (!allocation.m_data.GetByteSize()) {
814c8c5b8dcSSean Callanan         error.SetErrorToGenericError();
815c8c5b8dcSSean Callanan         error.SetErrorString("Couldn't get memory data: data buffer is empty");
816c8c5b8dcSSean Callanan         return;
817c8c5b8dcSSean Callanan       }
818b9c1b51eSKate Stone       if (process_sp) {
819b9c1b51eSKate Stone         process_sp->ReadMemory(allocation.m_process_start,
820b9c1b51eSKate Stone                                allocation.m_data.GetBytes(),
821b9c1b51eSKate Stone                                allocation.m_data.GetByteSize(), error);
822c8c5b8dcSSean Callanan         if (!error.Success())
823c8c5b8dcSSean Callanan           return;
824c8c5b8dcSSean Callanan         uint64_t offset = process_address - allocation.m_process_start;
825b9c1b51eSKate Stone         extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
826b9c1b51eSKate Stone                                   GetByteOrder(), GetAddressByteSize());
827c8c5b8dcSSean Callanan         return;
828c8c5b8dcSSean Callanan       }
829b9c1b51eSKate Stone     } break;
830c8c5b8dcSSean Callanan     case eAllocationPolicyHostOnly:
831b9c1b51eSKate Stone       if (!allocation.m_data.GetByteSize()) {
832458ae1c6SSean Callanan         error.SetErrorToGenericError();
833458ae1c6SSean Callanan         error.SetErrorString("Couldn't get memory data: data buffer is empty");
834458ae1c6SSean Callanan         return;
835458ae1c6SSean Callanan       }
836458ae1c6SSean Callanan       uint64_t offset = process_address - allocation.m_process_start;
837b9c1b51eSKate Stone       extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
838b9c1b51eSKate Stone                                 GetByteOrder(), GetAddressByteSize());
839458ae1c6SSean Callanan       return;
840458ae1c6SSean Callanan     }
841b9c1b51eSKate Stone   } else {
842458ae1c6SSean Callanan     error.SetErrorToGenericError();
843458ae1c6SSean Callanan     error.SetErrorString("Couldn't get memory data: its size was zero");
844458ae1c6SSean Callanan     return;
845458ae1c6SSean Callanan   }
846458ae1c6SSean Callanan }
847