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