xref: /freebsd-src/contrib/llvm-project/lldb/source/Expression/IRMemoryMap.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
15ffd83dbSDimitry Andric //===-- IRMemoryMap.cpp ---------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Expression/IRMemoryMap.h"
100b57cec5SDimitry Andric #include "lldb/Target/MemoryRegionInfo.h"
110b57cec5SDimitry Andric #include "lldb/Target/Process.h"
120b57cec5SDimitry Andric #include "lldb/Target/Target.h"
130b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
140b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
150b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
1681ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
170b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
180b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h"
190b57cec5SDimitry Andric #include "lldb/Utility/Status.h"
200b57cec5SDimitry Andric 
210b57cec5SDimitry Andric using namespace lldb_private;
220b57cec5SDimitry Andric 
IRMemoryMap(lldb::TargetSP target_sp)230b57cec5SDimitry Andric IRMemoryMap::IRMemoryMap(lldb::TargetSP target_sp) : m_target_wp(target_sp) {
240b57cec5SDimitry Andric   if (target_sp)
250b57cec5SDimitry Andric     m_process_wp = target_sp->GetProcessSP();
260b57cec5SDimitry Andric }
270b57cec5SDimitry Andric 
~IRMemoryMap()280b57cec5SDimitry Andric IRMemoryMap::~IRMemoryMap() {
290b57cec5SDimitry Andric   lldb::ProcessSP process_sp = m_process_wp.lock();
300b57cec5SDimitry Andric 
310b57cec5SDimitry Andric   if (process_sp) {
320b57cec5SDimitry Andric     AllocationMap::iterator iter;
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric     Status err;
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric     while ((iter = m_allocations.begin()) != m_allocations.end()) {
370b57cec5SDimitry Andric       err.Clear();
380b57cec5SDimitry Andric       if (iter->second.m_leak)
390b57cec5SDimitry Andric         m_allocations.erase(iter);
400b57cec5SDimitry Andric       else
410b57cec5SDimitry Andric         Free(iter->first, err);
420b57cec5SDimitry Andric     }
430b57cec5SDimitry Andric   }
440b57cec5SDimitry Andric }
450b57cec5SDimitry Andric 
FindSpace(size_t size)460b57cec5SDimitry Andric lldb::addr_t IRMemoryMap::FindSpace(size_t size) {
470b57cec5SDimitry Andric   // The FindSpace algorithm's job is to find a region of memory that the
480b57cec5SDimitry Andric   // underlying process is unlikely to be using.
490b57cec5SDimitry Andric   //
500b57cec5SDimitry Andric   // The memory returned by this function will never be written to.  The only
510b57cec5SDimitry Andric   // point is that it should not shadow process memory if possible, so that
520b57cec5SDimitry Andric   // expressions processing real values from the process do not use the wrong
530b57cec5SDimitry Andric   // data.
540b57cec5SDimitry Andric   //
550b57cec5SDimitry Andric   // If the process can in fact allocate memory (CanJIT() lets us know this)
560b57cec5SDimitry Andric   // then this can be accomplished just be allocating memory in the inferior.
570b57cec5SDimitry Andric   // Then no guessing is required.
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric   lldb::TargetSP target_sp = m_target_wp.lock();
600b57cec5SDimitry Andric   lldb::ProcessSP process_sp = m_process_wp.lock();
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   const bool process_is_alive = process_sp && process_sp->IsAlive();
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   lldb::addr_t ret = LLDB_INVALID_ADDRESS;
650b57cec5SDimitry Andric   if (size == 0)
660b57cec5SDimitry Andric     return ret;
670b57cec5SDimitry Andric 
680b57cec5SDimitry Andric   if (process_is_alive && process_sp->CanJIT()) {
690b57cec5SDimitry Andric     Status alloc_error;
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric     ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable |
720b57cec5SDimitry Andric                                                lldb::ePermissionsWritable,
730b57cec5SDimitry Andric                                      alloc_error);
740b57cec5SDimitry Andric 
750b57cec5SDimitry Andric     if (!alloc_error.Success())
760b57cec5SDimitry Andric       return LLDB_INVALID_ADDRESS;
770b57cec5SDimitry Andric     else
780b57cec5SDimitry Andric       return ret;
790b57cec5SDimitry Andric   }
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric   // At this point we know that we need to hunt.
820b57cec5SDimitry Andric   //
830b57cec5SDimitry Andric   // First, go to the end of the existing allocations we've made if there are
840b57cec5SDimitry Andric   // any allocations.  Otherwise start at the beginning of memory.
850b57cec5SDimitry Andric 
860b57cec5SDimitry Andric   if (m_allocations.empty()) {
870b57cec5SDimitry Andric     ret = 0x0;
880b57cec5SDimitry Andric   } else {
890b57cec5SDimitry Andric     auto back = m_allocations.rbegin();
900b57cec5SDimitry Andric     lldb::addr_t addr = back->first;
910b57cec5SDimitry Andric     size_t alloc_size = back->second.m_size;
920b57cec5SDimitry Andric     ret = llvm::alignTo(addr + alloc_size, 4096);
930b57cec5SDimitry Andric   }
940b57cec5SDimitry Andric 
95*06c3fb27SDimitry Andric   uint64_t end_of_memory;
96*06c3fb27SDimitry Andric   switch (GetAddressByteSize()) {
97*06c3fb27SDimitry Andric   case 2:
98*06c3fb27SDimitry Andric     end_of_memory = 0xffffull;
99*06c3fb27SDimitry Andric     break;
100*06c3fb27SDimitry Andric   case 4:
101*06c3fb27SDimitry Andric     end_of_memory = 0xffffffffull;
102*06c3fb27SDimitry Andric     break;
103*06c3fb27SDimitry Andric   case 8:
104*06c3fb27SDimitry Andric     end_of_memory = 0xffffffffffffffffull;
105*06c3fb27SDimitry Andric     break;
106*06c3fb27SDimitry Andric   default:
107*06c3fb27SDimitry Andric     lldbassert(false && "Invalid address size.");
108*06c3fb27SDimitry Andric     return LLDB_INVALID_ADDRESS;
109*06c3fb27SDimitry Andric   }
110*06c3fb27SDimitry Andric 
1110b57cec5SDimitry Andric   // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped
1120b57cec5SDimitry Andric   // regions, walk forward through memory until a region is found that has
1130b57cec5SDimitry Andric   // adequate space for our allocation.
1140b57cec5SDimitry Andric   if (process_is_alive) {
1150b57cec5SDimitry Andric     MemoryRegionInfo region_info;
1160b57cec5SDimitry Andric     Status err = process_sp->GetMemoryRegionInfo(ret, region_info);
1170b57cec5SDimitry Andric     if (err.Success()) {
1180b57cec5SDimitry Andric       while (true) {
1190b57cec5SDimitry Andric         if (region_info.GetReadable() != MemoryRegionInfo::OptionalBool::eNo ||
1200b57cec5SDimitry Andric             region_info.GetWritable() != MemoryRegionInfo::OptionalBool::eNo ||
1210b57cec5SDimitry Andric             region_info.GetExecutable() !=
1220b57cec5SDimitry Andric                 MemoryRegionInfo::OptionalBool::eNo) {
1230b57cec5SDimitry Andric           if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory) {
1240b57cec5SDimitry Andric             ret = LLDB_INVALID_ADDRESS;
1250b57cec5SDimitry Andric             break;
1260b57cec5SDimitry Andric           } else {
1270b57cec5SDimitry Andric             ret = region_info.GetRange().GetRangeEnd();
1280b57cec5SDimitry Andric           }
1290b57cec5SDimitry Andric         } else if (ret + size < region_info.GetRange().GetRangeEnd()) {
1300b57cec5SDimitry Andric           return ret;
1310b57cec5SDimitry Andric         } else {
1320b57cec5SDimitry Andric           // ret stays the same.  We just need to walk a bit further.
1330b57cec5SDimitry Andric         }
1340b57cec5SDimitry Andric 
1350b57cec5SDimitry Andric         err = process_sp->GetMemoryRegionInfo(
1360b57cec5SDimitry Andric             region_info.GetRange().GetRangeEnd(), region_info);
1370b57cec5SDimitry Andric         if (err.Fail()) {
1380b57cec5SDimitry Andric           lldbassert(0 && "GetMemoryRegionInfo() succeeded, then failed");
1390b57cec5SDimitry Andric           ret = LLDB_INVALID_ADDRESS;
1400b57cec5SDimitry Andric           break;
1410b57cec5SDimitry Andric         }
1420b57cec5SDimitry Andric       }
1430b57cec5SDimitry Andric     }
1440b57cec5SDimitry Andric   }
1450b57cec5SDimitry Andric 
1460b57cec5SDimitry Andric   // We've tried our algorithm, and it didn't work.  Now we have to reset back
1470b57cec5SDimitry Andric   // to the end of the allocations we've already reported, or use a 'sensible'
1480b57cec5SDimitry Andric   // default if this is our first allocation.
1490b57cec5SDimitry Andric   if (m_allocations.empty()) {
150*06c3fb27SDimitry Andric     uint64_t alloc_address = target_sp->GetExprAllocAddress();
151*06c3fb27SDimitry Andric     if (alloc_address > 0) {
152*06c3fb27SDimitry Andric       if (alloc_address >= end_of_memory) {
153*06c3fb27SDimitry Andric         lldbassert(0 && "The allocation address for expression evaluation must "
154*06c3fb27SDimitry Andric                         "be within process address space");
155*06c3fb27SDimitry Andric         return LLDB_INVALID_ADDRESS;
156*06c3fb27SDimitry Andric       }
157*06c3fb27SDimitry Andric       ret = alloc_address;
158*06c3fb27SDimitry Andric     } else {
1590b57cec5SDimitry Andric       uint32_t address_byte_size = GetAddressByteSize();
1600b57cec5SDimitry Andric       if (address_byte_size != UINT32_MAX) {
1610b57cec5SDimitry Andric         switch (address_byte_size) {
162*06c3fb27SDimitry Andric         case 2:
163*06c3fb27SDimitry Andric           ret = 0x8000ull;
1640b57cec5SDimitry Andric           break;
1650b57cec5SDimitry Andric         case 4:
1660b57cec5SDimitry Andric           ret = 0xee000000ull;
1670b57cec5SDimitry Andric           break;
168*06c3fb27SDimitry Andric         case 8:
169*06c3fb27SDimitry Andric           ret = 0xdead0fff00000000ull;
1700b57cec5SDimitry Andric           break;
171*06c3fb27SDimitry Andric         default:
172*06c3fb27SDimitry Andric           lldbassert(false && "Invalid address size.");
173*06c3fb27SDimitry Andric           return LLDB_INVALID_ADDRESS;
174*06c3fb27SDimitry Andric         }
1750b57cec5SDimitry Andric       }
1760b57cec5SDimitry Andric     }
1770b57cec5SDimitry Andric   } else {
1780b57cec5SDimitry Andric     auto back = m_allocations.rbegin();
1790b57cec5SDimitry Andric     lldb::addr_t addr = back->first;
1800b57cec5SDimitry Andric     size_t alloc_size = back->second.m_size;
181*06c3fb27SDimitry Andric     uint64_t align = target_sp->GetExprAllocAlign();
182*06c3fb27SDimitry Andric     if (align == 0)
183*06c3fb27SDimitry Andric       align = 4096;
184*06c3fb27SDimitry Andric     ret = llvm::alignTo(addr + alloc_size, align);
1850b57cec5SDimitry Andric   }
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   return ret;
1880b57cec5SDimitry Andric }
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric IRMemoryMap::AllocationMap::iterator
FindAllocation(lldb::addr_t addr,size_t size)1910b57cec5SDimitry Andric IRMemoryMap::FindAllocation(lldb::addr_t addr, size_t size) {
1920b57cec5SDimitry Andric   if (addr == LLDB_INVALID_ADDRESS)
1930b57cec5SDimitry Andric     return m_allocations.end();
1940b57cec5SDimitry Andric 
1950b57cec5SDimitry Andric   AllocationMap::iterator iter = m_allocations.lower_bound(addr);
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   if (iter == m_allocations.end() || iter->first > addr) {
1980b57cec5SDimitry Andric     if (iter == m_allocations.begin())
1990b57cec5SDimitry Andric       return m_allocations.end();
2000b57cec5SDimitry Andric     iter--;
2010b57cec5SDimitry Andric   }
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
2040b57cec5SDimitry Andric     return iter;
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric   return m_allocations.end();
2070b57cec5SDimitry Andric }
2080b57cec5SDimitry Andric 
IntersectsAllocation(lldb::addr_t addr,size_t size) const2090b57cec5SDimitry Andric bool IRMemoryMap::IntersectsAllocation(lldb::addr_t addr, size_t size) const {
2100b57cec5SDimitry Andric   if (addr == LLDB_INVALID_ADDRESS)
2110b57cec5SDimitry Andric     return false;
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   AllocationMap::const_iterator iter = m_allocations.lower_bound(addr);
2140b57cec5SDimitry Andric 
2150b57cec5SDimitry Andric   // Since we only know that the returned interval begins at a location greater
2160b57cec5SDimitry Andric   // than or equal to where the given interval begins, it's possible that the
2170b57cec5SDimitry Andric   // given interval intersects either the returned interval or the previous
2180b57cec5SDimitry Andric   // interval.  Thus, we need to check both. Note that we only need to check
2190b57cec5SDimitry Andric   // these two intervals.  Since all intervals are disjoint it is not possible
2200b57cec5SDimitry Andric   // that an adjacent interval does not intersect, but a non-adjacent interval
2210b57cec5SDimitry Andric   // does intersect.
2220b57cec5SDimitry Andric   if (iter != m_allocations.end()) {
2230b57cec5SDimitry Andric     if (AllocationsIntersect(addr, size, iter->second.m_process_start,
2240b57cec5SDimitry Andric                              iter->second.m_size))
2250b57cec5SDimitry Andric       return true;
2260b57cec5SDimitry Andric   }
2270b57cec5SDimitry Andric 
2280b57cec5SDimitry Andric   if (iter != m_allocations.begin()) {
2290b57cec5SDimitry Andric     --iter;
2300b57cec5SDimitry Andric     if (AllocationsIntersect(addr, size, iter->second.m_process_start,
2310b57cec5SDimitry Andric                              iter->second.m_size))
2320b57cec5SDimitry Andric       return true;
2330b57cec5SDimitry Andric   }
2340b57cec5SDimitry Andric 
2350b57cec5SDimitry Andric   return false;
2360b57cec5SDimitry Andric }
2370b57cec5SDimitry Andric 
AllocationsIntersect(lldb::addr_t addr1,size_t size1,lldb::addr_t addr2,size_t size2)2380b57cec5SDimitry Andric bool IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1,
2390b57cec5SDimitry Andric                                        lldb::addr_t addr2, size_t size2) {
2400b57cec5SDimitry Andric   // Given two half open intervals [A, B) and [X, Y), the only 6 permutations
2410b57cec5SDimitry Andric   // that satisfy A<B and X<Y are the following:
2420b57cec5SDimitry Andric   // A B X Y
2430b57cec5SDimitry Andric   // A X B Y  (intersects)
2440b57cec5SDimitry Andric   // A X Y B  (intersects)
2450b57cec5SDimitry Andric   // X A B Y  (intersects)
2460b57cec5SDimitry Andric   // X A Y B  (intersects)
2470b57cec5SDimitry Andric   // X Y A B
2480b57cec5SDimitry Andric   // The first is B <= X, and the last is Y <= A. So the condition is !(B <= X
2490b57cec5SDimitry Andric   // || Y <= A)), or (X < B && A < Y)
2500b57cec5SDimitry Andric   return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
2510b57cec5SDimitry Andric }
2520b57cec5SDimitry Andric 
GetByteOrder()2530b57cec5SDimitry Andric lldb::ByteOrder IRMemoryMap::GetByteOrder() {
2540b57cec5SDimitry Andric   lldb::ProcessSP process_sp = m_process_wp.lock();
2550b57cec5SDimitry Andric 
2560b57cec5SDimitry Andric   if (process_sp)
2570b57cec5SDimitry Andric     return process_sp->GetByteOrder();
2580b57cec5SDimitry Andric 
2590b57cec5SDimitry Andric   lldb::TargetSP target_sp = m_target_wp.lock();
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   if (target_sp)
2620b57cec5SDimitry Andric     return target_sp->GetArchitecture().GetByteOrder();
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   return lldb::eByteOrderInvalid;
2650b57cec5SDimitry Andric }
2660b57cec5SDimitry Andric 
GetAddressByteSize()2670b57cec5SDimitry Andric uint32_t IRMemoryMap::GetAddressByteSize() {
2680b57cec5SDimitry Andric   lldb::ProcessSP process_sp = m_process_wp.lock();
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric   if (process_sp)
2710b57cec5SDimitry Andric     return process_sp->GetAddressByteSize();
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric   lldb::TargetSP target_sp = m_target_wp.lock();
2740b57cec5SDimitry Andric 
2750b57cec5SDimitry Andric   if (target_sp)
2760b57cec5SDimitry Andric     return target_sp->GetArchitecture().GetAddressByteSize();
2770b57cec5SDimitry Andric 
2780b57cec5SDimitry Andric   return UINT32_MAX;
2790b57cec5SDimitry Andric }
2800b57cec5SDimitry Andric 
GetBestExecutionContextScope() const2810b57cec5SDimitry Andric ExecutionContextScope *IRMemoryMap::GetBestExecutionContextScope() const {
2820b57cec5SDimitry Andric   lldb::ProcessSP process_sp = m_process_wp.lock();
2830b57cec5SDimitry Andric 
2840b57cec5SDimitry Andric   if (process_sp)
2850b57cec5SDimitry Andric     return process_sp.get();
2860b57cec5SDimitry Andric 
2870b57cec5SDimitry Andric   lldb::TargetSP target_sp = m_target_wp.lock();
2880b57cec5SDimitry Andric 
2890b57cec5SDimitry Andric   if (target_sp)
2900b57cec5SDimitry Andric     return target_sp.get();
2910b57cec5SDimitry Andric 
2920b57cec5SDimitry Andric   return nullptr;
2930b57cec5SDimitry Andric }
2940b57cec5SDimitry Andric 
Allocation(lldb::addr_t process_alloc,lldb::addr_t process_start,size_t size,uint32_t permissions,uint8_t alignment,AllocationPolicy policy)2950b57cec5SDimitry Andric IRMemoryMap::Allocation::Allocation(lldb::addr_t process_alloc,
2960b57cec5SDimitry Andric                                     lldb::addr_t process_start, size_t size,
2970b57cec5SDimitry Andric                                     uint32_t permissions, uint8_t alignment,
2980b57cec5SDimitry Andric                                     AllocationPolicy policy)
2990b57cec5SDimitry Andric     : m_process_alloc(process_alloc), m_process_start(process_start),
3000b57cec5SDimitry Andric       m_size(size), m_policy(policy), m_leak(false), m_permissions(permissions),
3010b57cec5SDimitry Andric       m_alignment(alignment) {
3020b57cec5SDimitry Andric   switch (policy) {
3030b57cec5SDimitry Andric   default:
3040b57cec5SDimitry Andric     llvm_unreachable("Invalid AllocationPolicy");
3050b57cec5SDimitry Andric   case eAllocationPolicyHostOnly:
3060b57cec5SDimitry Andric   case eAllocationPolicyMirror:
3070b57cec5SDimitry Andric     m_data.SetByteSize(size);
3080b57cec5SDimitry Andric     break;
3090b57cec5SDimitry Andric   case eAllocationPolicyProcessOnly:
3100b57cec5SDimitry Andric     break;
3110b57cec5SDimitry Andric   }
3120b57cec5SDimitry Andric }
3130b57cec5SDimitry Andric 
Malloc(size_t size,uint8_t alignment,uint32_t permissions,AllocationPolicy policy,bool zero_memory,Status & error)3140b57cec5SDimitry Andric lldb::addr_t IRMemoryMap::Malloc(size_t size, uint8_t alignment,
3150b57cec5SDimitry Andric                                  uint32_t permissions, AllocationPolicy policy,
3160b57cec5SDimitry Andric                                  bool zero_memory, Status &error) {
31781ad6265SDimitry Andric   lldb_private::Log *log(GetLog(LLDBLog::Expressions));
3180b57cec5SDimitry Andric   error.Clear();
3190b57cec5SDimitry Andric 
3200b57cec5SDimitry Andric   lldb::ProcessSP process_sp;
3210b57cec5SDimitry Andric   lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
3220b57cec5SDimitry Andric   lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
3230b57cec5SDimitry Andric 
3240b57cec5SDimitry Andric   size_t allocation_size;
3250b57cec5SDimitry Andric 
3260b57cec5SDimitry Andric   if (size == 0) {
3270b57cec5SDimitry Andric     // FIXME: Malloc(0) should either return an invalid address or assert, in
3280b57cec5SDimitry Andric     // order to cut down on unnecessary allocations.
3290b57cec5SDimitry Andric     allocation_size = alignment;
3300b57cec5SDimitry Andric   } else {
3310b57cec5SDimitry Andric     // Round up the requested size to an aligned value.
3320b57cec5SDimitry Andric     allocation_size = llvm::alignTo(size, alignment);
3330b57cec5SDimitry Andric 
3340b57cec5SDimitry Andric     // The process page cache does not see the requested alignment. We can't
3350b57cec5SDimitry Andric     // assume its result will be any more than 1-byte aligned. To work around
3360b57cec5SDimitry Andric     // this, request `alignment - 1` additional bytes.
3370b57cec5SDimitry Andric     allocation_size += alignment - 1;
3380b57cec5SDimitry Andric   }
3390b57cec5SDimitry Andric 
3400b57cec5SDimitry Andric   switch (policy) {
3410b57cec5SDimitry Andric   default:
3420b57cec5SDimitry Andric     error.SetErrorToGenericError();
3430b57cec5SDimitry Andric     error.SetErrorString("Couldn't malloc: invalid allocation policy");
3440b57cec5SDimitry Andric     return LLDB_INVALID_ADDRESS;
3450b57cec5SDimitry Andric   case eAllocationPolicyHostOnly:
3460b57cec5SDimitry Andric     allocation_address = FindSpace(allocation_size);
3470b57cec5SDimitry Andric     if (allocation_address == LLDB_INVALID_ADDRESS) {
3480b57cec5SDimitry Andric       error.SetErrorToGenericError();
3490b57cec5SDimitry Andric       error.SetErrorString("Couldn't malloc: address space is full");
3500b57cec5SDimitry Andric       return LLDB_INVALID_ADDRESS;
3510b57cec5SDimitry Andric     }
3520b57cec5SDimitry Andric     break;
3530b57cec5SDimitry Andric   case eAllocationPolicyMirror:
3540b57cec5SDimitry Andric     process_sp = m_process_wp.lock();
3559dba64beSDimitry Andric     LLDB_LOGF(log,
356480093f4SDimitry Andric               "IRMemoryMap::%s process_sp=0x%" PRIxPTR
3570b57cec5SDimitry Andric               ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s",
358480093f4SDimitry Andric               __FUNCTION__, reinterpret_cast<uintptr_t>(process_sp.get()),
3590b57cec5SDimitry Andric               process_sp && process_sp->CanJIT() ? "true" : "false",
3600b57cec5SDimitry Andric               process_sp && process_sp->IsAlive() ? "true" : "false");
3610b57cec5SDimitry Andric     if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) {
3620b57cec5SDimitry Andric       if (!zero_memory)
3630b57cec5SDimitry Andric         allocation_address =
3640b57cec5SDimitry Andric             process_sp->AllocateMemory(allocation_size, permissions, error);
3650b57cec5SDimitry Andric       else
3660b57cec5SDimitry Andric         allocation_address =
3670b57cec5SDimitry Andric             process_sp->CallocateMemory(allocation_size, permissions, error);
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric       if (!error.Success())
3700b57cec5SDimitry Andric         return LLDB_INVALID_ADDRESS;
3710b57cec5SDimitry Andric     } else {
3729dba64beSDimitry Andric       LLDB_LOGF(log,
3739dba64beSDimitry Andric                 "IRMemoryMap::%s switching to eAllocationPolicyHostOnly "
3740b57cec5SDimitry Andric                 "due to failed condition (see previous expr log message)",
3750b57cec5SDimitry Andric                 __FUNCTION__);
3760b57cec5SDimitry Andric       policy = eAllocationPolicyHostOnly;
3770b57cec5SDimitry Andric       allocation_address = FindSpace(allocation_size);
3780b57cec5SDimitry Andric       if (allocation_address == LLDB_INVALID_ADDRESS) {
3790b57cec5SDimitry Andric         error.SetErrorToGenericError();
3800b57cec5SDimitry Andric         error.SetErrorString("Couldn't malloc: address space is full");
3810b57cec5SDimitry Andric         return LLDB_INVALID_ADDRESS;
3820b57cec5SDimitry Andric       }
3830b57cec5SDimitry Andric     }
3840b57cec5SDimitry Andric     break;
3850b57cec5SDimitry Andric   case eAllocationPolicyProcessOnly:
3860b57cec5SDimitry Andric     process_sp = m_process_wp.lock();
3870b57cec5SDimitry Andric     if (process_sp) {
3880b57cec5SDimitry Andric       if (process_sp->CanJIT() && process_sp->IsAlive()) {
3890b57cec5SDimitry Andric         if (!zero_memory)
3900b57cec5SDimitry Andric           allocation_address =
3910b57cec5SDimitry Andric               process_sp->AllocateMemory(allocation_size, permissions, error);
3920b57cec5SDimitry Andric         else
3930b57cec5SDimitry Andric           allocation_address =
3940b57cec5SDimitry Andric               process_sp->CallocateMemory(allocation_size, permissions, error);
3950b57cec5SDimitry Andric 
3960b57cec5SDimitry Andric         if (!error.Success())
3970b57cec5SDimitry Andric           return LLDB_INVALID_ADDRESS;
3980b57cec5SDimitry Andric       } else {
3990b57cec5SDimitry Andric         error.SetErrorToGenericError();
4000b57cec5SDimitry Andric         error.SetErrorString(
4010b57cec5SDimitry Andric             "Couldn't malloc: process doesn't support allocating memory");
4020b57cec5SDimitry Andric         return LLDB_INVALID_ADDRESS;
4030b57cec5SDimitry Andric       }
4040b57cec5SDimitry Andric     } else {
4050b57cec5SDimitry Andric       error.SetErrorToGenericError();
4060b57cec5SDimitry Andric       error.SetErrorString("Couldn't malloc: process doesn't exist, and this "
4070b57cec5SDimitry Andric                            "memory must be in the process");
4080b57cec5SDimitry Andric       return LLDB_INVALID_ADDRESS;
4090b57cec5SDimitry Andric     }
4100b57cec5SDimitry Andric     break;
4110b57cec5SDimitry Andric   }
4120b57cec5SDimitry Andric 
4130b57cec5SDimitry Andric   lldb::addr_t mask = alignment - 1;
4140b57cec5SDimitry Andric   aligned_address = (allocation_address + mask) & (~mask);
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   m_allocations.emplace(
4170b57cec5SDimitry Andric       std::piecewise_construct, std::forward_as_tuple(aligned_address),
4180b57cec5SDimitry Andric       std::forward_as_tuple(allocation_address, aligned_address,
4190b57cec5SDimitry Andric                             allocation_size, permissions, alignment, policy));
4200b57cec5SDimitry Andric 
4210b57cec5SDimitry Andric   if (zero_memory) {
4220b57cec5SDimitry Andric     Status write_error;
4230b57cec5SDimitry Andric     std::vector<uint8_t> zero_buf(size, 0);
4240b57cec5SDimitry Andric     WriteMemory(aligned_address, zero_buf.data(), size, write_error);
4250b57cec5SDimitry Andric   }
4260b57cec5SDimitry Andric 
4270b57cec5SDimitry Andric   if (log) {
4280b57cec5SDimitry Andric     const char *policy_string;
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric     switch (policy) {
4310b57cec5SDimitry Andric     default:
4320b57cec5SDimitry Andric       policy_string = "<invalid policy>";
4330b57cec5SDimitry Andric       break;
4340b57cec5SDimitry Andric     case eAllocationPolicyHostOnly:
4350b57cec5SDimitry Andric       policy_string = "eAllocationPolicyHostOnly";
4360b57cec5SDimitry Andric       break;
4370b57cec5SDimitry Andric     case eAllocationPolicyProcessOnly:
4380b57cec5SDimitry Andric       policy_string = "eAllocationPolicyProcessOnly";
4390b57cec5SDimitry Andric       break;
4400b57cec5SDimitry Andric     case eAllocationPolicyMirror:
4410b57cec5SDimitry Andric       policy_string = "eAllocationPolicyMirror";
4420b57cec5SDimitry Andric       break;
4430b57cec5SDimitry Andric     }
4440b57cec5SDimitry Andric 
4459dba64beSDimitry Andric     LLDB_LOGF(log,
4469dba64beSDimitry Andric               "IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64
4470b57cec5SDimitry Andric               ", %s) -> 0x%" PRIx64,
4480b57cec5SDimitry Andric               (uint64_t)allocation_size, (uint64_t)alignment,
4490b57cec5SDimitry Andric               (uint64_t)permissions, policy_string, aligned_address);
4500b57cec5SDimitry Andric   }
4510b57cec5SDimitry Andric 
4520b57cec5SDimitry Andric   return aligned_address;
4530b57cec5SDimitry Andric }
4540b57cec5SDimitry Andric 
Leak(lldb::addr_t process_address,Status & error)4550b57cec5SDimitry Andric void IRMemoryMap::Leak(lldb::addr_t process_address, Status &error) {
4560b57cec5SDimitry Andric   error.Clear();
4570b57cec5SDimitry Andric 
4580b57cec5SDimitry Andric   AllocationMap::iterator iter = m_allocations.find(process_address);
4590b57cec5SDimitry Andric 
4600b57cec5SDimitry Andric   if (iter == m_allocations.end()) {
4610b57cec5SDimitry Andric     error.SetErrorToGenericError();
4620b57cec5SDimitry Andric     error.SetErrorString("Couldn't leak: allocation doesn't exist");
4630b57cec5SDimitry Andric     return;
4640b57cec5SDimitry Andric   }
4650b57cec5SDimitry Andric 
4660b57cec5SDimitry Andric   Allocation &allocation = iter->second;
4670b57cec5SDimitry Andric 
4680b57cec5SDimitry Andric   allocation.m_leak = true;
4690b57cec5SDimitry Andric }
4700b57cec5SDimitry Andric 
Free(lldb::addr_t process_address,Status & error)4710b57cec5SDimitry Andric void IRMemoryMap::Free(lldb::addr_t process_address, Status &error) {
4720b57cec5SDimitry Andric   error.Clear();
4730b57cec5SDimitry Andric 
4740b57cec5SDimitry Andric   AllocationMap::iterator iter = m_allocations.find(process_address);
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric   if (iter == m_allocations.end()) {
4770b57cec5SDimitry Andric     error.SetErrorToGenericError();
4780b57cec5SDimitry Andric     error.SetErrorString("Couldn't free: allocation doesn't exist");
4790b57cec5SDimitry Andric     return;
4800b57cec5SDimitry Andric   }
4810b57cec5SDimitry Andric 
4820b57cec5SDimitry Andric   Allocation &allocation = iter->second;
4830b57cec5SDimitry Andric 
4840b57cec5SDimitry Andric   switch (allocation.m_policy) {
4850b57cec5SDimitry Andric   default:
4860b57cec5SDimitry Andric   case eAllocationPolicyHostOnly: {
4870b57cec5SDimitry Andric     lldb::ProcessSP process_sp = m_process_wp.lock();
4880b57cec5SDimitry Andric     if (process_sp) {
4890b57cec5SDimitry Andric       if (process_sp->CanJIT() && process_sp->IsAlive())
4900b57cec5SDimitry Andric         process_sp->DeallocateMemory(
4910b57cec5SDimitry Andric             allocation.m_process_alloc); // FindSpace allocated this for real
4920b57cec5SDimitry Andric     }
4930b57cec5SDimitry Andric 
4940b57cec5SDimitry Andric     break;
4950b57cec5SDimitry Andric   }
4960b57cec5SDimitry Andric   case eAllocationPolicyMirror:
4970b57cec5SDimitry Andric   case eAllocationPolicyProcessOnly: {
4980b57cec5SDimitry Andric     lldb::ProcessSP process_sp = m_process_wp.lock();
4990b57cec5SDimitry Andric     if (process_sp)
5000b57cec5SDimitry Andric       process_sp->DeallocateMemory(allocation.m_process_alloc);
5010b57cec5SDimitry Andric   }
5020b57cec5SDimitry Andric   }
5030b57cec5SDimitry Andric 
50481ad6265SDimitry Andric   if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {
5059dba64beSDimitry Andric     LLDB_LOGF(log,
5069dba64beSDimitry Andric               "IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64
5070b57cec5SDimitry Andric               "..0x%" PRIx64 ")",
5080b57cec5SDimitry Andric               (uint64_t)process_address, iter->second.m_process_start,
5090b57cec5SDimitry Andric               iter->second.m_process_start + iter->second.m_size);
5100b57cec5SDimitry Andric   }
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric   m_allocations.erase(iter);
5130b57cec5SDimitry Andric }
5140b57cec5SDimitry Andric 
GetAllocSize(lldb::addr_t address,size_t & size)5150b57cec5SDimitry Andric bool IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size) {
5160b57cec5SDimitry Andric   AllocationMap::iterator iter = FindAllocation(address, size);
5170b57cec5SDimitry Andric   if (iter == m_allocations.end())
5180b57cec5SDimitry Andric     return false;
5190b57cec5SDimitry Andric 
5200b57cec5SDimitry Andric   Allocation &al = iter->second;
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric   if (address > (al.m_process_start + al.m_size)) {
5230b57cec5SDimitry Andric     size = 0;
5240b57cec5SDimitry Andric     return false;
5250b57cec5SDimitry Andric   }
5260b57cec5SDimitry Andric 
5270b57cec5SDimitry Andric   if (address > al.m_process_start) {
5280b57cec5SDimitry Andric     int dif = address - al.m_process_start;
5290b57cec5SDimitry Andric     size = al.m_size - dif;
5300b57cec5SDimitry Andric     return true;
5310b57cec5SDimitry Andric   }
5320b57cec5SDimitry Andric 
5330b57cec5SDimitry Andric   size = al.m_size;
5340b57cec5SDimitry Andric   return true;
5350b57cec5SDimitry Andric }
5360b57cec5SDimitry Andric 
WriteMemory(lldb::addr_t process_address,const uint8_t * bytes,size_t size,Status & error)5370b57cec5SDimitry Andric void IRMemoryMap::WriteMemory(lldb::addr_t process_address,
5380b57cec5SDimitry Andric                               const uint8_t *bytes, size_t size,
5390b57cec5SDimitry Andric                               Status &error) {
5400b57cec5SDimitry Andric   error.Clear();
5410b57cec5SDimitry Andric 
5420b57cec5SDimitry Andric   AllocationMap::iterator iter = FindAllocation(process_address, size);
5430b57cec5SDimitry Andric 
5440b57cec5SDimitry Andric   if (iter == m_allocations.end()) {
5450b57cec5SDimitry Andric     lldb::ProcessSP process_sp = m_process_wp.lock();
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric     if (process_sp) {
5480b57cec5SDimitry Andric       process_sp->WriteMemory(process_address, bytes, size, error);
5490b57cec5SDimitry Andric       return;
5500b57cec5SDimitry Andric     }
5510b57cec5SDimitry Andric 
5520b57cec5SDimitry Andric     error.SetErrorToGenericError();
5530b57cec5SDimitry Andric     error.SetErrorString("Couldn't write: no allocation contains the target "
5540b57cec5SDimitry Andric                          "range and the process doesn't exist");
5550b57cec5SDimitry Andric     return;
5560b57cec5SDimitry Andric   }
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric   Allocation &allocation = iter->second;
5590b57cec5SDimitry Andric 
5600b57cec5SDimitry Andric   uint64_t offset = process_address - allocation.m_process_start;
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric   lldb::ProcessSP process_sp;
5630b57cec5SDimitry Andric 
5640b57cec5SDimitry Andric   switch (allocation.m_policy) {
5650b57cec5SDimitry Andric   default:
5660b57cec5SDimitry Andric     error.SetErrorToGenericError();
5670b57cec5SDimitry Andric     error.SetErrorString("Couldn't write: invalid allocation policy");
5680b57cec5SDimitry Andric     return;
5690b57cec5SDimitry Andric   case eAllocationPolicyHostOnly:
5700b57cec5SDimitry Andric     if (!allocation.m_data.GetByteSize()) {
5710b57cec5SDimitry Andric       error.SetErrorToGenericError();
5720b57cec5SDimitry Andric       error.SetErrorString("Couldn't write: data buffer is empty");
5730b57cec5SDimitry Andric       return;
5740b57cec5SDimitry Andric     }
5750b57cec5SDimitry Andric     ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
5760b57cec5SDimitry Andric     break;
5770b57cec5SDimitry Andric   case eAllocationPolicyMirror:
5780b57cec5SDimitry Andric     if (!allocation.m_data.GetByteSize()) {
5790b57cec5SDimitry Andric       error.SetErrorToGenericError();
5800b57cec5SDimitry Andric       error.SetErrorString("Couldn't write: data buffer is empty");
5810b57cec5SDimitry Andric       return;
5820b57cec5SDimitry Andric     }
5830b57cec5SDimitry Andric     ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
5840b57cec5SDimitry Andric     process_sp = m_process_wp.lock();
5850b57cec5SDimitry Andric     if (process_sp) {
5860b57cec5SDimitry Andric       process_sp->WriteMemory(process_address, bytes, size, error);
5870b57cec5SDimitry Andric       if (!error.Success())
5880b57cec5SDimitry Andric         return;
5890b57cec5SDimitry Andric     }
5900b57cec5SDimitry Andric     break;
5910b57cec5SDimitry Andric   case eAllocationPolicyProcessOnly:
5920b57cec5SDimitry Andric     process_sp = m_process_wp.lock();
5930b57cec5SDimitry Andric     if (process_sp) {
5940b57cec5SDimitry Andric       process_sp->WriteMemory(process_address, bytes, size, error);
5950b57cec5SDimitry Andric       if (!error.Success())
5960b57cec5SDimitry Andric         return;
5970b57cec5SDimitry Andric     }
5980b57cec5SDimitry Andric     break;
5990b57cec5SDimitry Andric   }
6000b57cec5SDimitry Andric 
60181ad6265SDimitry Andric   if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {
6029dba64beSDimitry Andric     LLDB_LOGF(log,
603480093f4SDimitry Andric               "IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIxPTR
6040b57cec5SDimitry Andric               ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
605480093f4SDimitry Andric               (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,
6060b57cec5SDimitry Andric               (uint64_t)allocation.m_process_start,
6070b57cec5SDimitry Andric               (uint64_t)allocation.m_process_start +
6080b57cec5SDimitry Andric                   (uint64_t)allocation.m_size);
6090b57cec5SDimitry Andric   }
6100b57cec5SDimitry Andric }
6110b57cec5SDimitry Andric 
WriteScalarToMemory(lldb::addr_t process_address,Scalar & scalar,size_t size,Status & error)6120b57cec5SDimitry Andric void IRMemoryMap::WriteScalarToMemory(lldb::addr_t process_address,
6130b57cec5SDimitry Andric                                       Scalar &scalar, size_t size,
6140b57cec5SDimitry Andric                                       Status &error) {
6150b57cec5SDimitry Andric   error.Clear();
6160b57cec5SDimitry Andric 
6170b57cec5SDimitry Andric   if (size == UINT32_MAX)
6180b57cec5SDimitry Andric     size = scalar.GetByteSize();
6190b57cec5SDimitry Andric 
6200b57cec5SDimitry Andric   if (size > 0) {
6210b57cec5SDimitry Andric     uint8_t buf[32];
6220b57cec5SDimitry Andric     const size_t mem_size =
6230b57cec5SDimitry Andric         scalar.GetAsMemoryData(buf, size, GetByteOrder(), error);
6240b57cec5SDimitry Andric     if (mem_size > 0) {
6250b57cec5SDimitry Andric       return WriteMemory(process_address, buf, mem_size, error);
6260b57cec5SDimitry Andric     } else {
6270b57cec5SDimitry Andric       error.SetErrorToGenericError();
6280b57cec5SDimitry Andric       error.SetErrorString(
6290b57cec5SDimitry Andric           "Couldn't write scalar: failed to get scalar as memory data");
6300b57cec5SDimitry Andric     }
6310b57cec5SDimitry Andric   } else {
6320b57cec5SDimitry Andric     error.SetErrorToGenericError();
6330b57cec5SDimitry Andric     error.SetErrorString("Couldn't write scalar: its size was zero");
6340b57cec5SDimitry Andric   }
6350b57cec5SDimitry Andric }
6360b57cec5SDimitry Andric 
WritePointerToMemory(lldb::addr_t process_address,lldb::addr_t address,Status & error)6370b57cec5SDimitry Andric void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address,
6380b57cec5SDimitry Andric                                        lldb::addr_t address, Status &error) {
6390b57cec5SDimitry Andric   error.Clear();
6400b57cec5SDimitry Andric 
6410b57cec5SDimitry Andric   Scalar scalar(address);
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric   WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
6440b57cec5SDimitry Andric }
6450b57cec5SDimitry Andric 
ReadMemory(uint8_t * bytes,lldb::addr_t process_address,size_t size,Status & error)6460b57cec5SDimitry Andric void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address,
6470b57cec5SDimitry Andric                              size_t size, Status &error) {
6480b57cec5SDimitry Andric   error.Clear();
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric   AllocationMap::iterator iter = FindAllocation(process_address, size);
6510b57cec5SDimitry Andric 
6520b57cec5SDimitry Andric   if (iter == m_allocations.end()) {
6530b57cec5SDimitry Andric     lldb::ProcessSP process_sp = m_process_wp.lock();
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric     if (process_sp) {
6560b57cec5SDimitry Andric       process_sp->ReadMemory(process_address, bytes, size, error);
6570b57cec5SDimitry Andric       return;
6580b57cec5SDimitry Andric     }
6590b57cec5SDimitry Andric 
6600b57cec5SDimitry Andric     lldb::TargetSP target_sp = m_target_wp.lock();
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric     if (target_sp) {
6630b57cec5SDimitry Andric       Address absolute_address(process_address);
664fe6060f1SDimitry Andric       target_sp->ReadMemory(absolute_address, bytes, size, error, true);
6650b57cec5SDimitry Andric       return;
6660b57cec5SDimitry Andric     }
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric     error.SetErrorToGenericError();
6690b57cec5SDimitry Andric     error.SetErrorString("Couldn't read: no allocation contains the target "
6700b57cec5SDimitry Andric                          "range, and neither the process nor the target exist");
6710b57cec5SDimitry Andric     return;
6720b57cec5SDimitry Andric   }
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric   Allocation &allocation = iter->second;
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric   uint64_t offset = process_address - allocation.m_process_start;
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric   if (offset > allocation.m_size) {
6790b57cec5SDimitry Andric     error.SetErrorToGenericError();
6800b57cec5SDimitry Andric     error.SetErrorString("Couldn't read: data is not in the allocation");
6810b57cec5SDimitry Andric     return;
6820b57cec5SDimitry Andric   }
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric   lldb::ProcessSP process_sp;
6850b57cec5SDimitry Andric 
6860b57cec5SDimitry Andric   switch (allocation.m_policy) {
6870b57cec5SDimitry Andric   default:
6880b57cec5SDimitry Andric     error.SetErrorToGenericError();
6890b57cec5SDimitry Andric     error.SetErrorString("Couldn't read: invalid allocation policy");
6900b57cec5SDimitry Andric     return;
6910b57cec5SDimitry Andric   case eAllocationPolicyHostOnly:
6920b57cec5SDimitry Andric     if (!allocation.m_data.GetByteSize()) {
6930b57cec5SDimitry Andric       error.SetErrorToGenericError();
6940b57cec5SDimitry Andric       error.SetErrorString("Couldn't read: data buffer is empty");
6950b57cec5SDimitry Andric       return;
6960b57cec5SDimitry Andric     }
6970b57cec5SDimitry Andric     if (allocation.m_data.GetByteSize() < offset + size) {
6980b57cec5SDimitry Andric       error.SetErrorToGenericError();
6990b57cec5SDimitry Andric       error.SetErrorString("Couldn't read: not enough underlying data");
7000b57cec5SDimitry Andric       return;
7010b57cec5SDimitry Andric     }
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric     ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
7040b57cec5SDimitry Andric     break;
7050b57cec5SDimitry Andric   case eAllocationPolicyMirror:
7060b57cec5SDimitry Andric     process_sp = m_process_wp.lock();
7070b57cec5SDimitry Andric     if (process_sp) {
7080b57cec5SDimitry Andric       process_sp->ReadMemory(process_address, bytes, size, error);
7090b57cec5SDimitry Andric       if (!error.Success())
7100b57cec5SDimitry Andric         return;
7110b57cec5SDimitry Andric     } else {
7120b57cec5SDimitry Andric       if (!allocation.m_data.GetByteSize()) {
7130b57cec5SDimitry Andric         error.SetErrorToGenericError();
7140b57cec5SDimitry Andric         error.SetErrorString("Couldn't read: data buffer is empty");
7150b57cec5SDimitry Andric         return;
7160b57cec5SDimitry Andric       }
7170b57cec5SDimitry Andric       ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
7180b57cec5SDimitry Andric     }
7190b57cec5SDimitry Andric     break;
7200b57cec5SDimitry Andric   case eAllocationPolicyProcessOnly:
7210b57cec5SDimitry Andric     process_sp = m_process_wp.lock();
7220b57cec5SDimitry Andric     if (process_sp) {
7230b57cec5SDimitry Andric       process_sp->ReadMemory(process_address, bytes, size, error);
7240b57cec5SDimitry Andric       if (!error.Success())
7250b57cec5SDimitry Andric         return;
7260b57cec5SDimitry Andric     }
7270b57cec5SDimitry Andric     break;
7280b57cec5SDimitry Andric   }
7290b57cec5SDimitry Andric 
73081ad6265SDimitry Andric   if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {
7319dba64beSDimitry Andric     LLDB_LOGF(log,
732480093f4SDimitry Andric               "IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIxPTR
7330b57cec5SDimitry Andric               ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
734480093f4SDimitry Andric               (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,
7350b57cec5SDimitry Andric               (uint64_t)allocation.m_process_start,
7360b57cec5SDimitry Andric               (uint64_t)allocation.m_process_start +
7370b57cec5SDimitry Andric                   (uint64_t)allocation.m_size);
7380b57cec5SDimitry Andric   }
7390b57cec5SDimitry Andric }
7400b57cec5SDimitry Andric 
ReadScalarFromMemory(Scalar & scalar,lldb::addr_t process_address,size_t size,Status & error)7410b57cec5SDimitry Andric void IRMemoryMap::ReadScalarFromMemory(Scalar &scalar,
7420b57cec5SDimitry Andric                                        lldb::addr_t process_address,
7430b57cec5SDimitry Andric                                        size_t size, Status &error) {
7440b57cec5SDimitry Andric   error.Clear();
7450b57cec5SDimitry Andric 
7460b57cec5SDimitry Andric   if (size > 0) {
7470b57cec5SDimitry Andric     DataBufferHeap buf(size, 0);
7480b57cec5SDimitry Andric     ReadMemory(buf.GetBytes(), process_address, size, error);
7490b57cec5SDimitry Andric 
7500b57cec5SDimitry Andric     if (!error.Success())
7510b57cec5SDimitry Andric       return;
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric     DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(),
7540b57cec5SDimitry Andric                             GetAddressByteSize());
7550b57cec5SDimitry Andric 
7560b57cec5SDimitry Andric     lldb::offset_t offset = 0;
7570b57cec5SDimitry Andric 
7580b57cec5SDimitry Andric     switch (size) {
7590b57cec5SDimitry Andric     default:
7600b57cec5SDimitry Andric       error.SetErrorToGenericError();
7610b57cec5SDimitry Andric       error.SetErrorStringWithFormat(
7620b57cec5SDimitry Andric           "Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
7630b57cec5SDimitry Andric       return;
7640b57cec5SDimitry Andric     case 1:
7650b57cec5SDimitry Andric       scalar = extractor.GetU8(&offset);
7660b57cec5SDimitry Andric       break;
7670b57cec5SDimitry Andric     case 2:
7680b57cec5SDimitry Andric       scalar = extractor.GetU16(&offset);
7690b57cec5SDimitry Andric       break;
7700b57cec5SDimitry Andric     case 4:
7710b57cec5SDimitry Andric       scalar = extractor.GetU32(&offset);
7720b57cec5SDimitry Andric       break;
7730b57cec5SDimitry Andric     case 8:
7740b57cec5SDimitry Andric       scalar = extractor.GetU64(&offset);
7750b57cec5SDimitry Andric       break;
7760b57cec5SDimitry Andric     }
7770b57cec5SDimitry Andric   } else {
7780b57cec5SDimitry Andric     error.SetErrorToGenericError();
7790b57cec5SDimitry Andric     error.SetErrorString("Couldn't read scalar: its size was zero");
7800b57cec5SDimitry Andric   }
7810b57cec5SDimitry Andric }
7820b57cec5SDimitry Andric 
ReadPointerFromMemory(lldb::addr_t * address,lldb::addr_t process_address,Status & error)7830b57cec5SDimitry Andric void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t *address,
7840b57cec5SDimitry Andric                                         lldb::addr_t process_address,
7850b57cec5SDimitry Andric                                         Status &error) {
7860b57cec5SDimitry Andric   error.Clear();
7870b57cec5SDimitry Andric 
7880b57cec5SDimitry Andric   Scalar pointer_scalar;
7890b57cec5SDimitry Andric   ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(),
7900b57cec5SDimitry Andric                        error);
7910b57cec5SDimitry Andric 
7920b57cec5SDimitry Andric   if (!error.Success())
7930b57cec5SDimitry Andric     return;
7940b57cec5SDimitry Andric 
7950b57cec5SDimitry Andric   *address = pointer_scalar.ULongLong();
7960b57cec5SDimitry Andric }
7970b57cec5SDimitry Andric 
GetMemoryData(DataExtractor & extractor,lldb::addr_t process_address,size_t size,Status & error)7980b57cec5SDimitry Andric void IRMemoryMap::GetMemoryData(DataExtractor &extractor,
7990b57cec5SDimitry Andric                                 lldb::addr_t process_address, size_t size,
8000b57cec5SDimitry Andric                                 Status &error) {
8010b57cec5SDimitry Andric   error.Clear();
8020b57cec5SDimitry Andric 
8030b57cec5SDimitry Andric   if (size > 0) {
8040b57cec5SDimitry Andric     AllocationMap::iterator iter = FindAllocation(process_address, size);
8050b57cec5SDimitry Andric 
8060b57cec5SDimitry Andric     if (iter == m_allocations.end()) {
8070b57cec5SDimitry Andric       error.SetErrorToGenericError();
8080b57cec5SDimitry Andric       error.SetErrorStringWithFormat(
8090b57cec5SDimitry Andric           "Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64
8100b57cec5SDimitry Andric           ")",
8110b57cec5SDimitry Andric           process_address, process_address + size);
8120b57cec5SDimitry Andric       return;
8130b57cec5SDimitry Andric     }
8140b57cec5SDimitry Andric 
8150b57cec5SDimitry Andric     Allocation &allocation = iter->second;
8160b57cec5SDimitry Andric 
8170b57cec5SDimitry Andric     switch (allocation.m_policy) {
8180b57cec5SDimitry Andric     default:
8190b57cec5SDimitry Andric       error.SetErrorToGenericError();
8200b57cec5SDimitry Andric       error.SetErrorString(
8210b57cec5SDimitry Andric           "Couldn't get memory data: invalid allocation policy");
8220b57cec5SDimitry Andric       return;
8230b57cec5SDimitry Andric     case eAllocationPolicyProcessOnly:
8240b57cec5SDimitry Andric       error.SetErrorToGenericError();
8250b57cec5SDimitry Andric       error.SetErrorString(
8260b57cec5SDimitry Andric           "Couldn't get memory data: memory is only in the target");
8270b57cec5SDimitry Andric       return;
8280b57cec5SDimitry Andric     case eAllocationPolicyMirror: {
8290b57cec5SDimitry Andric       lldb::ProcessSP process_sp = m_process_wp.lock();
8300b57cec5SDimitry Andric 
8310b57cec5SDimitry Andric       if (!allocation.m_data.GetByteSize()) {
8320b57cec5SDimitry Andric         error.SetErrorToGenericError();
8330b57cec5SDimitry Andric         error.SetErrorString("Couldn't get memory data: data buffer is empty");
8340b57cec5SDimitry Andric         return;
8350b57cec5SDimitry Andric       }
8360b57cec5SDimitry Andric       if (process_sp) {
8370b57cec5SDimitry Andric         process_sp->ReadMemory(allocation.m_process_start,
8380b57cec5SDimitry Andric                                allocation.m_data.GetBytes(),
8390b57cec5SDimitry Andric                                allocation.m_data.GetByteSize(), error);
8400b57cec5SDimitry Andric         if (!error.Success())
8410b57cec5SDimitry Andric           return;
8420b57cec5SDimitry Andric         uint64_t offset = process_address - allocation.m_process_start;
8430b57cec5SDimitry Andric         extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
8440b57cec5SDimitry Andric                                   GetByteOrder(), GetAddressByteSize());
8450b57cec5SDimitry Andric         return;
8460b57cec5SDimitry Andric       }
8470b57cec5SDimitry Andric     } break;
8480b57cec5SDimitry Andric     case eAllocationPolicyHostOnly:
8490b57cec5SDimitry Andric       if (!allocation.m_data.GetByteSize()) {
8500b57cec5SDimitry Andric         error.SetErrorToGenericError();
8510b57cec5SDimitry Andric         error.SetErrorString("Couldn't get memory data: data buffer is empty");
8520b57cec5SDimitry Andric         return;
8530b57cec5SDimitry Andric       }
8540b57cec5SDimitry Andric       uint64_t offset = process_address - allocation.m_process_start;
8550b57cec5SDimitry Andric       extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
8560b57cec5SDimitry Andric                                 GetByteOrder(), GetAddressByteSize());
8570b57cec5SDimitry Andric       return;
8580b57cec5SDimitry Andric     }
8590b57cec5SDimitry Andric   } else {
8600b57cec5SDimitry Andric     error.SetErrorToGenericError();
8610b57cec5SDimitry Andric     error.SetErrorString("Couldn't get memory data: its size was zero");
8620b57cec5SDimitry Andric     return;
8630b57cec5SDimitry Andric   }
8640b57cec5SDimitry Andric }
865