180814287SRaphael Isemann //===-- IRMemoryMap.cpp ---------------------------------------------------===//
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"
16*c34698a8SPavel Labath #include "lldb/Utility/LLDBLog.h"
176f9e6901SZachary Turner #include "lldb/Utility/Log.h"
18d821c997SPavel Labath #include "lldb/Utility/Scalar.h"
1997206d57SZachary Turner #include "lldb/Utility/Status.h"
205a1af4e6SSean Callanan
215a1af4e6SSean Callanan using namespace lldb_private;
225a1af4e6SSean Callanan
IRMemoryMap(lldb::TargetSP target_sp)23b9c1b51eSKate Stone IRMemoryMap::IRMemoryMap(lldb::TargetSP target_sp) : m_target_wp(target_sp) {
24b024d878SSean Callanan if (target_sp)
25b024d878SSean Callanan m_process_wp = target_sp->GetProcessSP();
265a1af4e6SSean Callanan }
275a1af4e6SSean Callanan
~IRMemoryMap()28b9c1b51eSKate Stone IRMemoryMap::~IRMemoryMap() {
295a1af4e6SSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock();
305a1af4e6SSean Callanan
31b9c1b51eSKate Stone if (process_sp) {
32bb77704cSSean Callanan AllocationMap::iterator iter;
335a1af4e6SSean Callanan
3497206d57SZachary Turner Status err;
35bb77704cSSean Callanan
36b9c1b51eSKate Stone while ((iter = m_allocations.begin()) != m_allocations.end()) {
37bb77704cSSean Callanan err.Clear();
38fbf5c682SSean Callanan if (iter->second.m_leak)
39fbf5c682SSean Callanan m_allocations.erase(iter);
40fbf5c682SSean Callanan else
41bb77704cSSean Callanan Free(iter->first, err);
425a1af4e6SSean Callanan }
435a1af4e6SSean Callanan }
445a1af4e6SSean Callanan }
455a1af4e6SSean Callanan
FindSpace(size_t size)46b9c1b51eSKate Stone lldb::addr_t IRMemoryMap::FindSpace(size_t size) {
47f3df7e86SSean Callanan // The FindSpace algorithm's job is to find a region of memory that the
48f3df7e86SSean Callanan // underlying process is unlikely to be using.
49f3df7e86SSean Callanan //
50f3df7e86SSean Callanan // The memory returned by this function will never be written to. The only
51f3df7e86SSean Callanan // point is that it should not shadow process memory if possible, so that
5205097246SAdrian Prantl // expressions processing real values from the process do not use the wrong
5305097246SAdrian Prantl // data.
54f3df7e86SSean Callanan //
55f3df7e86SSean Callanan // If the process can in fact allocate memory (CanJIT() lets us know this)
56f3df7e86SSean Callanan // then this can be accomplished just be allocating memory in the inferior.
57f3df7e86SSean Callanan // Then no guessing is required.
58f3df7e86SSean Callanan
59bb9945f4SSean Callanan lldb::TargetSP target_sp = m_target_wp.lock();
60bb9945f4SSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock();
615a1af4e6SSean Callanan
62f3df7e86SSean Callanan const bool process_is_alive = process_sp && process_sp->IsAlive();
63f3df7e86SSean Callanan
64bb9945f4SSean Callanan lldb::addr_t ret = LLDB_INVALID_ADDRESS;
653ddcd314SZachary Turner if (size == 0)
663ddcd314SZachary Turner return ret;
675a1af4e6SSean Callanan
68b9c1b51eSKate Stone if (process_is_alive && process_sp->CanJIT()) {
6997206d57SZachary Turner Status alloc_error;
70df56540aSSean Callanan
71b9c1b51eSKate Stone ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable |
72b9c1b51eSKate Stone lldb::ePermissionsWritable,
73b9c1b51eSKate Stone alloc_error);
74df56540aSSean Callanan
75df56540aSSean Callanan if (!alloc_error.Success())
76df56540aSSean Callanan return LLDB_INVALID_ADDRESS;
77df56540aSSean Callanan else
78df56540aSSean Callanan return ret;
79df56540aSSean Callanan }
80df56540aSSean Callanan
81f3df7e86SSean Callanan // At this point we know that we need to hunt.
82f3df7e86SSean Callanan //
83f3df7e86SSean Callanan // First, go to the end of the existing allocations we've made if there are
84f3df7e86SSean Callanan // any allocations. Otherwise start at the beginning of memory.
85f3df7e86SSean Callanan
86b9c1b51eSKate Stone if (m_allocations.empty()) {
87f3df7e86SSean Callanan ret = 0x0;
88b9c1b51eSKate Stone } else {
89f3df7e86SSean Callanan auto back = m_allocations.rbegin();
90f3df7e86SSean Callanan lldb::addr_t addr = back->first;
91f3df7e86SSean Callanan size_t alloc_size = back->second.m_size;
92f3df7e86SSean Callanan ret = llvm::alignTo(addr + alloc_size, 4096);
93f3df7e86SSean Callanan }
94f3df7e86SSean Callanan
95f3df7e86SSean Callanan // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped
9605097246SAdrian Prantl // regions, walk forward through memory until a region is found that has
9705097246SAdrian Prantl // adequate space for our allocation.
98b9c1b51eSKate Stone if (process_is_alive) {
99b9c1b51eSKate Stone const uint64_t end_of_memory = process_sp->GetAddressByteSize() == 8
100b9c1b51eSKate Stone ? 0xffffffffffffffffull
101b9c1b51eSKate Stone : 0xffffffffull;
102f3df7e86SSean Callanan
103b9c1b51eSKate Stone lldbassert(process_sp->GetAddressByteSize() == 4 ||
104b9c1b51eSKate Stone end_of_memory != 0xffffffffull);
105f3df7e86SSean Callanan
106f3df7e86SSean Callanan MemoryRegionInfo region_info;
10797206d57SZachary Turner Status err = process_sp->GetMemoryRegionInfo(ret, region_info);
108b9c1b51eSKate Stone if (err.Success()) {
109b9c1b51eSKate Stone while (true) {
110f3df7e86SSean Callanan if (region_info.GetReadable() != MemoryRegionInfo::OptionalBool::eNo ||
111f3df7e86SSean Callanan region_info.GetWritable() != MemoryRegionInfo::OptionalBool::eNo ||
112b9c1b51eSKate Stone region_info.GetExecutable() !=
113b9c1b51eSKate Stone MemoryRegionInfo::OptionalBool::eNo) {
114b9c1b51eSKate Stone if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory) {
115f3df7e86SSean Callanan ret = LLDB_INVALID_ADDRESS;
116f3df7e86SSean Callanan break;
117b9c1b51eSKate Stone } else {
118f3df7e86SSean Callanan ret = region_info.GetRange().GetRangeEnd();
119f3df7e86SSean Callanan }
120b9c1b51eSKate Stone } else if (ret + size < region_info.GetRange().GetRangeEnd()) {
121f3df7e86SSean Callanan return ret;
122b9c1b51eSKate Stone } else {
123f3df7e86SSean Callanan // ret stays the same. We just need to walk a bit further.
124f3df7e86SSean Callanan }
125f3df7e86SSean Callanan
126b9c1b51eSKate Stone err = process_sp->GetMemoryRegionInfo(
127b9c1b51eSKate Stone region_info.GetRange().GetRangeEnd(), region_info);
128b9c1b51eSKate Stone if (err.Fail()) {
129f31c9d27SPavel Labath lldbassert(0 && "GetMemoryRegionInfo() succeeded, then failed");
130f3df7e86SSean Callanan ret = LLDB_INVALID_ADDRESS;
131f3df7e86SSean Callanan break;
132f3df7e86SSean Callanan }
133f3df7e86SSean Callanan }
134f3df7e86SSean Callanan }
135f3df7e86SSean Callanan }
136f3df7e86SSean Callanan
137f3df7e86SSean Callanan // We've tried our algorithm, and it didn't work. Now we have to reset back
138f3df7e86SSean Callanan // to the end of the allocations we've already reported, or use a 'sensible'
139f3df7e86SSean Callanan // default if this is our first allocation.
140f3df7e86SSean Callanan
141b9c1b51eSKate Stone if (m_allocations.empty()) {
142f3df7e86SSean Callanan uint32_t address_byte_size = GetAddressByteSize();
143b9c1b51eSKate Stone if (address_byte_size != UINT32_MAX) {
144b9c1b51eSKate Stone switch (address_byte_size) {
145f3df7e86SSean Callanan case 8:
146f3df7e86SSean Callanan ret = 0xffffffff00000000ull;
147f3df7e86SSean Callanan break;
148f3df7e86SSean Callanan case 4:
149f3df7e86SSean Callanan ret = 0xee000000ull;
150f3df7e86SSean Callanan break;
151f3df7e86SSean Callanan default:
152f3df7e86SSean Callanan break;
153f3df7e86SSean Callanan }
154f3df7e86SSean Callanan }
155b9c1b51eSKate Stone } else {
1563ddcd314SZachary Turner auto back = m_allocations.rbegin();
1573ddcd314SZachary Turner lldb::addr_t addr = back->first;
1583ddcd314SZachary Turner size_t alloc_size = back->second.m_size;
159a94ae1e0SRafael Espindola ret = llvm::alignTo(addr + alloc_size, 4096);
1605a1af4e6SSean Callanan }
1615a1af4e6SSean Callanan
162bb9945f4SSean Callanan return ret;
1635a1af4e6SSean Callanan }
1645a1af4e6SSean Callanan
1655a1af4e6SSean Callanan IRMemoryMap::AllocationMap::iterator
FindAllocation(lldb::addr_t addr,size_t size)166b9c1b51eSKate Stone IRMemoryMap::FindAllocation(lldb::addr_t addr, size_t size) {
1671582ee68SSean Callanan if (addr == LLDB_INVALID_ADDRESS)
1681582ee68SSean Callanan return m_allocations.end();
1691582ee68SSean Callanan
1705a1af4e6SSean Callanan AllocationMap::iterator iter = m_allocations.lower_bound(addr);
1715a1af4e6SSean Callanan
172b9c1b51eSKate Stone if (iter == m_allocations.end() || iter->first > addr) {
1735a1af4e6SSean Callanan if (iter == m_allocations.begin())
1745a1af4e6SSean Callanan return m_allocations.end();
1755a1af4e6SSean Callanan iter--;
1765a1af4e6SSean Callanan }
1775a1af4e6SSean Callanan
1785a1af4e6SSean Callanan if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
1795a1af4e6SSean Callanan return iter;
1805a1af4e6SSean Callanan
1815a1af4e6SSean Callanan return m_allocations.end();
1825a1af4e6SSean Callanan }
1835a1af4e6SSean Callanan
IntersectsAllocation(lldb::addr_t addr,size_t size) const184b9c1b51eSKate Stone bool IRMemoryMap::IntersectsAllocation(lldb::addr_t addr, size_t size) const {
185bb9945f4SSean Callanan if (addr == LLDB_INVALID_ADDRESS)
186bb9945f4SSean Callanan return false;
187bb9945f4SSean Callanan
18815362445SZachary Turner AllocationMap::const_iterator iter = m_allocations.lower_bound(addr);
189bb9945f4SSean Callanan
190b9c1b51eSKate Stone // Since we only know that the returned interval begins at a location greater
19105097246SAdrian Prantl // than or equal to where the given interval begins, it's possible that the
19205097246SAdrian Prantl // given interval intersects either the returned interval or the previous
19305097246SAdrian Prantl // interval. Thus, we need to check both. Note that we only need to check
19405097246SAdrian Prantl // these two intervals. Since all intervals are disjoint it is not possible
19505097246SAdrian Prantl // that an adjacent interval does not intersect, but a non-adjacent interval
19605097246SAdrian Prantl // does intersect.
19715362445SZachary Turner if (iter != m_allocations.end()) {
198b9c1b51eSKate Stone if (AllocationsIntersect(addr, size, iter->second.m_process_start,
199b9c1b51eSKate Stone iter->second.m_size))
200bb9945f4SSean Callanan return true;
20115362445SZachary Turner }
202bb9945f4SSean Callanan
20315362445SZachary Turner if (iter != m_allocations.begin()) {
20415362445SZachary Turner --iter;
205b9c1b51eSKate Stone if (AllocationsIntersect(addr, size, iter->second.m_process_start,
206b9c1b51eSKate Stone iter->second.m_size))
20715362445SZachary Turner return true;
208bb9945f4SSean Callanan }
209bb9945f4SSean Callanan
210bb9945f4SSean Callanan return false;
211bb9945f4SSean Callanan }
212bb9945f4SSean Callanan
AllocationsIntersect(lldb::addr_t addr1,size_t size1,lldb::addr_t addr2,size_t size2)213b9c1b51eSKate Stone bool IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1,
214b9c1b51eSKate Stone lldb::addr_t addr2, size_t size2) {
215b9c1b51eSKate Stone // Given two half open intervals [A, B) and [X, Y), the only 6 permutations
21605097246SAdrian Prantl // that satisfy A<B and X<Y are the following:
21715362445SZachary Turner // A B X Y
21815362445SZachary Turner // A X B Y (intersects)
21915362445SZachary Turner // A X Y B (intersects)
22015362445SZachary Turner // X A B Y (intersects)
22115362445SZachary Turner // X A Y B (intersects)
22215362445SZachary Turner // X Y A B
22305097246SAdrian Prantl // The first is B <= X, and the last is Y <= A. So the condition is !(B <= X
22405097246SAdrian Prantl // || Y <= A)), or (X < B && A < Y)
22515362445SZachary Turner return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
22615362445SZachary Turner }
22715362445SZachary Turner
GetByteOrder()228b9c1b51eSKate Stone lldb::ByteOrder IRMemoryMap::GetByteOrder() {
22935005f76SSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock();
23035005f76SSean Callanan
23135005f76SSean Callanan if (process_sp)
23235005f76SSean Callanan return process_sp->GetByteOrder();
23335005f76SSean Callanan
23435005f76SSean Callanan lldb::TargetSP target_sp = m_target_wp.lock();
23535005f76SSean Callanan
23635005f76SSean Callanan if (target_sp)
23708052afaSSean Callanan return target_sp->GetArchitecture().GetByteOrder();
23835005f76SSean Callanan
23935005f76SSean Callanan return lldb::eByteOrderInvalid;
24035005f76SSean Callanan }
24135005f76SSean Callanan
GetAddressByteSize()242b9c1b51eSKate Stone uint32_t IRMemoryMap::GetAddressByteSize() {
24335005f76SSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock();
24435005f76SSean Callanan
24535005f76SSean Callanan if (process_sp)
24635005f76SSean Callanan return process_sp->GetAddressByteSize();
24735005f76SSean Callanan
24835005f76SSean Callanan lldb::TargetSP target_sp = m_target_wp.lock();
24935005f76SSean Callanan
25035005f76SSean Callanan if (target_sp)
25108052afaSSean Callanan return target_sp->GetArchitecture().GetAddressByteSize();
25235005f76SSean Callanan
25335005f76SSean Callanan return UINT32_MAX;
25435005f76SSean Callanan }
25535005f76SSean Callanan
GetBestExecutionContextScope() const256b9c1b51eSKate Stone ExecutionContextScope *IRMemoryMap::GetBestExecutionContextScope() const {
25735005f76SSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock();
25835005f76SSean Callanan
25935005f76SSean Callanan if (process_sp)
26035005f76SSean Callanan return process_sp.get();
26135005f76SSean Callanan
26235005f76SSean Callanan lldb::TargetSP target_sp = m_target_wp.lock();
26335005f76SSean Callanan
26435005f76SSean Callanan if (target_sp)
26535005f76SSean Callanan return target_sp.get();
26635005f76SSean Callanan
267248a1305SKonrad Kleine return nullptr;
26835005f76SSean Callanan }
26935005f76SSean Callanan
Allocation(lldb::addr_t process_alloc,lldb::addr_t process_start,size_t size,uint32_t permissions,uint8_t alignment,AllocationPolicy policy)270d2562509SSean Callanan IRMemoryMap::Allocation::Allocation(lldb::addr_t process_alloc,
271b9c1b51eSKate Stone lldb::addr_t process_start, size_t size,
272b9c1b51eSKate Stone uint32_t permissions, uint8_t alignment,
273b9c1b51eSKate Stone AllocationPolicy policy)
274b9c1b51eSKate Stone : m_process_alloc(process_alloc), m_process_start(process_start),
275f71dd344SVedant Kumar m_size(size), m_policy(policy), m_leak(false), m_permissions(permissions),
276f71dd344SVedant Kumar m_alignment(alignment) {
277b9c1b51eSKate Stone switch (policy) {
278d2562509SSean Callanan default:
27935861f21SFangrui Song llvm_unreachable("Invalid AllocationPolicy");
280d2562509SSean Callanan case eAllocationPolicyHostOnly:
281d2562509SSean Callanan case eAllocationPolicyMirror:
282d2562509SSean Callanan m_data.SetByteSize(size);
28394523598SVedant Kumar break;
28494523598SVedant Kumar case eAllocationPolicyProcessOnly:
285d2562509SSean Callanan break;
286d2562509SSean Callanan }
287d2562509SSean Callanan }
288d2562509SSean Callanan
Malloc(size_t size,uint8_t alignment,uint32_t permissions,AllocationPolicy policy,bool zero_memory,Status & error)289b9c1b51eSKate Stone lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment,
290b9c1b51eSKate Stone uint32_t permissions, AllocationPolicy policy,
29197206d57SZachary Turner bool zero_memory, Status &error) {
292a007a6d8SPavel Labath lldb_private::Log *log(GetLog(LLDBLog::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,
331df6879ecSJan Kratochvil "IRMemoryMap::%s process_sp=0x%" PRIxPTR
332b9c1b51eSKate Stone ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s",
333df6879ecSJan 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
Leak(lldb::addr_t process_address,Status & error)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
Free(lldb::addr_t process_address,Status & error)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
479a007a6d8SPavel Labath if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {
48063e5fb76SJonas Devlieghere LLDB_LOGF(log,
48163e5fb76SJonas Devlieghere "IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64
482b9c1b51eSKate Stone "..0x%" PRIx64 ")",
483b9c1b51eSKate Stone (uint64_t)process_address, iter->second.m_process_start,
4845a1af4e6SSean Callanan iter->second.m_process_start + iter->second.m_size);
4855a1af4e6SSean Callanan }
4865a1af4e6SSean Callanan
4875a1af4e6SSean Callanan m_allocations.erase(iter);
4885a1af4e6SSean Callanan }
4895a1af4e6SSean Callanan
GetAllocSize(lldb::addr_t address,size_t & size)490b9c1b51eSKate Stone bool IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size) {
49190ff7911SEwan Crawford AllocationMap::iterator iter = FindAllocation(address, size);
49290ff7911SEwan Crawford if (iter == m_allocations.end())
49390ff7911SEwan Crawford return false;
49490ff7911SEwan Crawford
49590ff7911SEwan Crawford Allocation &al = iter->second;
49690ff7911SEwan Crawford
497b9c1b51eSKate Stone if (address > (al.m_process_start + al.m_size)) {
49890ff7911SEwan Crawford size = 0;
49990ff7911SEwan Crawford return false;
50090ff7911SEwan Crawford }
50190ff7911SEwan Crawford
502b9c1b51eSKate Stone if (address > al.m_process_start) {
50390ff7911SEwan Crawford int dif = address - al.m_process_start;
50490ff7911SEwan Crawford size = al.m_size - dif;
50590ff7911SEwan Crawford return true;
50690ff7911SEwan Crawford }
50790ff7911SEwan Crawford
50890ff7911SEwan Crawford size = al.m_size;
50990ff7911SEwan Crawford return true;
51090ff7911SEwan Crawford }
51190ff7911SEwan Crawford
WriteMemory(lldb::addr_t process_address,const uint8_t * bytes,size_t size,Status & error)512b9c1b51eSKate Stone void IRMemoryMap::WriteMemory(lldb::addr_t process_address,
51397206d57SZachary Turner const uint8_t *bytes, size_t size,
51497206d57SZachary Turner Status &error) {
51508052afaSSean Callanan error.Clear();
51608052afaSSean Callanan
5175a1af4e6SSean Callanan AllocationMap::iterator iter = FindAllocation(process_address, size);
5185a1af4e6SSean Callanan
519b9c1b51eSKate Stone if (iter == m_allocations.end()) {
520c8c5b8dcSSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock();
521c8c5b8dcSSean Callanan
522b9c1b51eSKate Stone if (process_sp) {
523c8c5b8dcSSean Callanan process_sp->WriteMemory(process_address, bytes, size, error);
524c8c5b8dcSSean Callanan return;
525c8c5b8dcSSean Callanan }
526c8c5b8dcSSean Callanan
5275a1af4e6SSean Callanan error.SetErrorToGenericError();
528b9c1b51eSKate Stone error.SetErrorString("Couldn't write: no allocation contains the target "
529b9c1b51eSKate Stone "range and the process doesn't exist");
5305a1af4e6SSean Callanan return;
5315a1af4e6SSean Callanan }
5325a1af4e6SSean Callanan
5335a1af4e6SSean Callanan Allocation &allocation = iter->second;
5345a1af4e6SSean Callanan
5355a1af4e6SSean Callanan uint64_t offset = process_address - allocation.m_process_start;
5365a1af4e6SSean Callanan
5375a1af4e6SSean Callanan lldb::ProcessSP process_sp;
5385a1af4e6SSean Callanan
539b9c1b51eSKate Stone switch (allocation.m_policy) {
5405a1af4e6SSean Callanan default:
5415a1af4e6SSean Callanan error.SetErrorToGenericError();
5425a1af4e6SSean Callanan error.SetErrorString("Couldn't write: invalid allocation policy");
5435a1af4e6SSean Callanan return;
5445a1af4e6SSean Callanan case eAllocationPolicyHostOnly:
545b9c1b51eSKate Stone if (!allocation.m_data.GetByteSize()) {
5465a1af4e6SSean Callanan error.SetErrorToGenericError();
5475a1af4e6SSean Callanan error.SetErrorString("Couldn't write: data buffer is empty");
5485a1af4e6SSean Callanan return;
5495a1af4e6SSean Callanan }
550d2562509SSean Callanan ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
5515a1af4e6SSean Callanan break;
5525a1af4e6SSean Callanan case eAllocationPolicyMirror:
553b9c1b51eSKate Stone if (!allocation.m_data.GetByteSize()) {
5545a1af4e6SSean Callanan error.SetErrorToGenericError();
5555a1af4e6SSean Callanan error.SetErrorString("Couldn't write: data buffer is empty");
5565a1af4e6SSean Callanan return;
5575a1af4e6SSean Callanan }
558d2562509SSean Callanan ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
5595a1af4e6SSean Callanan process_sp = m_process_wp.lock();
560b9c1b51eSKate Stone if (process_sp) {
5615a1af4e6SSean Callanan process_sp->WriteMemory(process_address, bytes, size, error);
5625a1af4e6SSean Callanan if (!error.Success())
5635a1af4e6SSean Callanan return;
5645a1af4e6SSean Callanan }
5655a1af4e6SSean Callanan break;
5665a1af4e6SSean Callanan case eAllocationPolicyProcessOnly:
5675a1af4e6SSean Callanan process_sp = m_process_wp.lock();
568b9c1b51eSKate Stone if (process_sp) {
5695a1af4e6SSean Callanan process_sp->WriteMemory(process_address, bytes, size, error);
5705a1af4e6SSean Callanan if (!error.Success())
5715a1af4e6SSean Callanan return;
5725a1af4e6SSean Callanan }
5735a1af4e6SSean Callanan break;
5745a1af4e6SSean Callanan }
5755a1af4e6SSean Callanan
576a007a6d8SPavel Labath if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {
57763e5fb76SJonas Devlieghere LLDB_LOGF(log,
578df6879ecSJan Kratochvil "IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIxPTR
579b9c1b51eSKate Stone ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
580df6879ecSJan Kratochvil (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,
5815a1af4e6SSean Callanan (uint64_t)allocation.m_process_start,
582b9c1b51eSKate Stone (uint64_t)allocation.m_process_start +
583b9c1b51eSKate Stone (uint64_t)allocation.m_size);
5845a1af4e6SSean Callanan }
5855a1af4e6SSean Callanan }
5865a1af4e6SSean Callanan
WriteScalarToMemory(lldb::addr_t process_address,Scalar & scalar,size_t size,Status & error)587b9c1b51eSKate Stone void IRMemoryMap::WriteScalarToMemory(lldb::addr_t process_address,
588b9c1b51eSKate Stone Scalar &scalar, size_t size,
58997206d57SZachary Turner Status &error) {
59008052afaSSean Callanan error.Clear();
59108052afaSSean Callanan
59235005f76SSean Callanan if (size == UINT32_MAX)
59335005f76SSean Callanan size = scalar.GetByteSize();
59435005f76SSean Callanan
595b9c1b51eSKate Stone if (size > 0) {
59635005f76SSean Callanan uint8_t buf[32];
597b9c1b51eSKate Stone const size_t mem_size =
598b9c1b51eSKate Stone scalar.GetAsMemoryData(buf, size, GetByteOrder(), error);
599b9c1b51eSKate Stone if (mem_size > 0) {
60035005f76SSean Callanan return WriteMemory(process_address, buf, mem_size, error);
601b9c1b51eSKate Stone } else {
60235005f76SSean Callanan error.SetErrorToGenericError();
603b9c1b51eSKate Stone error.SetErrorString(
604b9c1b51eSKate Stone "Couldn't write scalar: failed to get scalar as memory data");
60535005f76SSean Callanan }
606b9c1b51eSKate Stone } else {
60735005f76SSean Callanan error.SetErrorToGenericError();
60835005f76SSean Callanan error.SetErrorString("Couldn't write scalar: its size was zero");
60935005f76SSean Callanan }
61035005f76SSean Callanan }
61135005f76SSean Callanan
WritePointerToMemory(lldb::addr_t process_address,lldb::addr_t address,Status & error)612b9c1b51eSKate Stone void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address,
61397206d57SZachary Turner lldb::addr_t address, Status &error) {
61408052afaSSean Callanan error.Clear();
61508052afaSSean Callanan
616f8043fa5SSean Callanan Scalar scalar(address);
617f8043fa5SSean Callanan
618f8043fa5SSean Callanan WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
619f8043fa5SSean Callanan }
620f8043fa5SSean Callanan
ReadMemory(uint8_t * bytes,lldb::addr_t process_address,size_t size,Status & error)621b9c1b51eSKate Stone void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address,
62297206d57SZachary Turner size_t size, Status &error) {
62308052afaSSean Callanan error.Clear();
62408052afaSSean Callanan
6255a1af4e6SSean Callanan AllocationMap::iterator iter = FindAllocation(process_address, size);
6265a1af4e6SSean Callanan
627b9c1b51eSKate Stone if (iter == m_allocations.end()) {
628c8c5b8dcSSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock();
629c8c5b8dcSSean Callanan
630b9c1b51eSKate Stone if (process_sp) {
631c8c5b8dcSSean Callanan process_sp->ReadMemory(process_address, bytes, size, error);
632c8c5b8dcSSean Callanan return;
633c8c5b8dcSSean Callanan }
634c8c5b8dcSSean Callanan
635c8c5b8dcSSean Callanan lldb::TargetSP target_sp = m_target_wp.lock();
636c8c5b8dcSSean Callanan
637b9c1b51eSKate Stone if (target_sp) {
638c8c5b8dcSSean Callanan Address absolute_address(process_address);
639e9fe788dSJason Molenda target_sp->ReadMemory(absolute_address, bytes, size, error, true);
640c8c5b8dcSSean Callanan return;
641c8c5b8dcSSean Callanan }
642c8c5b8dcSSean Callanan
6435a1af4e6SSean Callanan error.SetErrorToGenericError();
644b9c1b51eSKate Stone error.SetErrorString("Couldn't read: no allocation contains the target "
645b9c1b51eSKate Stone "range, and neither the process nor the target exist");
6465a1af4e6SSean Callanan return;
6475a1af4e6SSean Callanan }
6485a1af4e6SSean Callanan
6495a1af4e6SSean Callanan Allocation &allocation = iter->second;
6505a1af4e6SSean Callanan
6515a1af4e6SSean Callanan uint64_t offset = process_address - allocation.m_process_start;
6525a1af4e6SSean Callanan
653b9c1b51eSKate Stone if (offset > allocation.m_size) {
6549bbf3cd3SSean Callanan error.SetErrorToGenericError();
6559bbf3cd3SSean Callanan error.SetErrorString("Couldn't read: data is not in the allocation");
6569bbf3cd3SSean Callanan return;
6579bbf3cd3SSean Callanan }
6589bbf3cd3SSean Callanan
6595a1af4e6SSean Callanan lldb::ProcessSP process_sp;
6605a1af4e6SSean Callanan
661b9c1b51eSKate Stone switch (allocation.m_policy) {
6625a1af4e6SSean Callanan default:
6635a1af4e6SSean Callanan error.SetErrorToGenericError();
6645a1af4e6SSean Callanan error.SetErrorString("Couldn't read: invalid allocation policy");
6655a1af4e6SSean Callanan return;
6665a1af4e6SSean Callanan case eAllocationPolicyHostOnly:
667b9c1b51eSKate Stone if (!allocation.m_data.GetByteSize()) {
6685a1af4e6SSean Callanan error.SetErrorToGenericError();
6695a1af4e6SSean Callanan error.SetErrorString("Couldn't read: data buffer is empty");
6705a1af4e6SSean Callanan return;
6715a1af4e6SSean Callanan }
672b9c1b51eSKate Stone if (allocation.m_data.GetByteSize() < offset + size) {
6739bbf3cd3SSean Callanan error.SetErrorToGenericError();
6749bbf3cd3SSean Callanan error.SetErrorString("Couldn't read: not enough underlying data");
6759bbf3cd3SSean Callanan return;
6769bbf3cd3SSean Callanan }
6779bbf3cd3SSean Callanan
678d2562509SSean Callanan ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
6795a1af4e6SSean Callanan break;
6805a1af4e6SSean Callanan case eAllocationPolicyMirror:
6815a1af4e6SSean Callanan process_sp = m_process_wp.lock();
682b9c1b51eSKate Stone if (process_sp) {
6835a1af4e6SSean Callanan process_sp->ReadMemory(process_address, bytes, size, error);
6845a1af4e6SSean Callanan if (!error.Success())
6855a1af4e6SSean Callanan return;
686b9c1b51eSKate Stone } else {
687b9c1b51eSKate Stone if (!allocation.m_data.GetByteSize()) {
6885a1af4e6SSean Callanan error.SetErrorToGenericError();
6895a1af4e6SSean Callanan error.SetErrorString("Couldn't read: data buffer is empty");
6905a1af4e6SSean Callanan return;
6915a1af4e6SSean Callanan }
692d2562509SSean Callanan ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
6935a1af4e6SSean Callanan }
6945a1af4e6SSean Callanan break;
6955a1af4e6SSean Callanan case eAllocationPolicyProcessOnly:
6965a1af4e6SSean Callanan process_sp = m_process_wp.lock();
697b9c1b51eSKate Stone if (process_sp) {
6985a1af4e6SSean Callanan process_sp->ReadMemory(process_address, bytes, size, error);
6995a1af4e6SSean Callanan if (!error.Success())
7005a1af4e6SSean Callanan return;
7015a1af4e6SSean Callanan }
7025a1af4e6SSean Callanan break;
7035a1af4e6SSean Callanan }
7045a1af4e6SSean Callanan
705a007a6d8SPavel Labath if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {
70663e5fb76SJonas Devlieghere LLDB_LOGF(log,
707df6879ecSJan Kratochvil "IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIxPTR
708b9c1b51eSKate Stone ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
709df6879ecSJan Kratochvil (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,
7105a1af4e6SSean Callanan (uint64_t)allocation.m_process_start,
711b9c1b51eSKate Stone (uint64_t)allocation.m_process_start +
712b9c1b51eSKate Stone (uint64_t)allocation.m_size);
7135a1af4e6SSean Callanan }
7145a1af4e6SSean Callanan }
71535005f76SSean Callanan
ReadScalarFromMemory(Scalar & scalar,lldb::addr_t process_address,size_t size,Status & error)716b9c1b51eSKate Stone void IRMemoryMap::ReadScalarFromMemory(Scalar &scalar,
717b9c1b51eSKate Stone lldb::addr_t process_address,
71897206d57SZachary Turner size_t size, Status &error) {
71908052afaSSean Callanan error.Clear();
72008052afaSSean Callanan
721b9c1b51eSKate Stone if (size > 0) {
72235005f76SSean Callanan DataBufferHeap buf(size, 0);
72335005f76SSean Callanan ReadMemory(buf.GetBytes(), process_address, size, error);
72435005f76SSean Callanan
72535005f76SSean Callanan if (!error.Success())
72635005f76SSean Callanan return;
72735005f76SSean Callanan
728b9c1b51eSKate Stone DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(),
729b9c1b51eSKate Stone GetAddressByteSize());
73035005f76SSean Callanan
73135005f76SSean Callanan lldb::offset_t offset = 0;
73235005f76SSean Callanan
733b9c1b51eSKate Stone switch (size) {
73435005f76SSean Callanan default:
73535005f76SSean Callanan error.SetErrorToGenericError();
736b9c1b51eSKate Stone error.SetErrorStringWithFormat(
737b9c1b51eSKate Stone "Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
73835005f76SSean Callanan return;
739b9c1b51eSKate Stone case 1:
740b9c1b51eSKate Stone scalar = extractor.GetU8(&offset);
741b9c1b51eSKate Stone break;
742b9c1b51eSKate Stone case 2:
743b9c1b51eSKate Stone scalar = extractor.GetU16(&offset);
744b9c1b51eSKate Stone break;
745b9c1b51eSKate Stone case 4:
746b9c1b51eSKate Stone scalar = extractor.GetU32(&offset);
747b9c1b51eSKate Stone break;
748b9c1b51eSKate Stone case 8:
749b9c1b51eSKate Stone scalar = extractor.GetU64(&offset);
750b9c1b51eSKate Stone break;
75135005f76SSean Callanan }
752b9c1b51eSKate Stone } else {
75335005f76SSean Callanan error.SetErrorToGenericError();
754458ae1c6SSean Callanan error.SetErrorString("Couldn't read scalar: its size was zero");
75535005f76SSean Callanan }
75635005f76SSean Callanan }
75735005f76SSean Callanan
ReadPointerFromMemory(lldb::addr_t * address,lldb::addr_t process_address,Status & error)758b9c1b51eSKate Stone void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t *address,
759b9c1b51eSKate Stone lldb::addr_t process_address,
76097206d57SZachary Turner Status &error) {
76108052afaSSean Callanan error.Clear();
76208052afaSSean Callanan
7632d37e5a5SSean Callanan Scalar pointer_scalar;
764b9c1b51eSKate Stone ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(),
765b9c1b51eSKate Stone error);
7662d37e5a5SSean Callanan
7672d37e5a5SSean Callanan if (!error.Success())
7682d37e5a5SSean Callanan return;
7692d37e5a5SSean Callanan
7702d37e5a5SSean Callanan *address = pointer_scalar.ULongLong();
7712d37e5a5SSean Callanan }
7722d37e5a5SSean Callanan
GetMemoryData(DataExtractor & extractor,lldb::addr_t process_address,size_t size,Status & error)773b9c1b51eSKate Stone void IRMemoryMap::GetMemoryData(DataExtractor &extractor,
774b9c1b51eSKate Stone lldb::addr_t process_address, size_t size,
77597206d57SZachary Turner Status &error) {
77608052afaSSean Callanan error.Clear();
77708052afaSSean Callanan
778b9c1b51eSKate Stone if (size > 0) {
779458ae1c6SSean Callanan AllocationMap::iterator iter = FindAllocation(process_address, size);
780458ae1c6SSean Callanan
781b9c1b51eSKate Stone if (iter == m_allocations.end()) {
782458ae1c6SSean Callanan error.SetErrorToGenericError();
783b9c1b51eSKate Stone error.SetErrorStringWithFormat(
784b9c1b51eSKate Stone "Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64
785b9c1b51eSKate Stone ")",
786b9c1b51eSKate Stone process_address, process_address + size);
787458ae1c6SSean Callanan return;
788458ae1c6SSean Callanan }
789458ae1c6SSean Callanan
790458ae1c6SSean Callanan Allocation &allocation = iter->second;
791458ae1c6SSean Callanan
792b9c1b51eSKate Stone switch (allocation.m_policy) {
793458ae1c6SSean Callanan default:
794458ae1c6SSean Callanan error.SetErrorToGenericError();
795b9c1b51eSKate Stone error.SetErrorString(
796b9c1b51eSKate Stone "Couldn't get memory data: invalid allocation policy");
797458ae1c6SSean Callanan return;
798458ae1c6SSean Callanan case eAllocationPolicyProcessOnly:
799458ae1c6SSean Callanan error.SetErrorToGenericError();
800b9c1b51eSKate Stone error.SetErrorString(
801b9c1b51eSKate Stone "Couldn't get memory data: memory is only in the target");
802458ae1c6SSean Callanan return;
803b9c1b51eSKate Stone case eAllocationPolicyMirror: {
804c8c5b8dcSSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock();
805c8c5b8dcSSean Callanan
806b9c1b51eSKate Stone if (!allocation.m_data.GetByteSize()) {
807c8c5b8dcSSean Callanan error.SetErrorToGenericError();
808c8c5b8dcSSean Callanan error.SetErrorString("Couldn't get memory data: data buffer is empty");
809c8c5b8dcSSean Callanan return;
810c8c5b8dcSSean Callanan }
811b9c1b51eSKate Stone if (process_sp) {
812b9c1b51eSKate Stone process_sp->ReadMemory(allocation.m_process_start,
813b9c1b51eSKate Stone allocation.m_data.GetBytes(),
814b9c1b51eSKate Stone allocation.m_data.GetByteSize(), error);
815c8c5b8dcSSean Callanan if (!error.Success())
816c8c5b8dcSSean Callanan return;
817c8c5b8dcSSean Callanan uint64_t offset = process_address - allocation.m_process_start;
818b9c1b51eSKate Stone extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
819b9c1b51eSKate Stone GetByteOrder(), GetAddressByteSize());
820c8c5b8dcSSean Callanan return;
821c8c5b8dcSSean Callanan }
822b9c1b51eSKate Stone } break;
823c8c5b8dcSSean Callanan case eAllocationPolicyHostOnly:
824b9c1b51eSKate Stone if (!allocation.m_data.GetByteSize()) {
825458ae1c6SSean Callanan error.SetErrorToGenericError();
826458ae1c6SSean Callanan error.SetErrorString("Couldn't get memory data: data buffer is empty");
827458ae1c6SSean Callanan return;
828458ae1c6SSean Callanan }
829458ae1c6SSean Callanan uint64_t offset = process_address - allocation.m_process_start;
830b9c1b51eSKate Stone extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
831b9c1b51eSKate Stone GetByteOrder(), GetAddressByteSize());
832458ae1c6SSean Callanan return;
833458ae1c6SSean Callanan }
834b9c1b51eSKate Stone } else {
835458ae1c6SSean Callanan error.SetErrorToGenericError();
836458ae1c6SSean Callanan error.SetErrorString("Couldn't get memory data: its size was zero");
837458ae1c6SSean Callanan return;
838458ae1c6SSean Callanan }
839458ae1c6SSean Callanan }
840