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