15a1af4e6SSean Callanan //===-- IRMemoryMap.cpp -----------------------------------------*- C++ -*-===//
25a1af4e6SSean Callanan //
35a1af4e6SSean Callanan //                     The LLVM Compiler Infrastructure
45a1af4e6SSean Callanan //
55a1af4e6SSean Callanan // This file is distributed under the University of Illinois Open Source
65a1af4e6SSean Callanan // License. See LICENSE.TXT for details.
75a1af4e6SSean Callanan //
85a1af4e6SSean Callanan //===----------------------------------------------------------------------===//
95a1af4e6SSean Callanan 
1035005f76SSean Callanan #include "lldb/Core/DataBufferHeap.h"
1135005f76SSean Callanan #include "lldb/Core/DataExtractor.h"
125a1af4e6SSean Callanan #include "lldb/Core/Error.h"
135a1af4e6SSean Callanan #include "lldb/Core/Log.h"
1435005f76SSean Callanan #include "lldb/Core/Scalar.h"
155a1af4e6SSean Callanan #include "lldb/Expression/IRMemoryMap.h"
165a1af4e6SSean Callanan #include "lldb/Target/Process.h"
1735005f76SSean Callanan #include "lldb/Target/Target.h"
185a1af4e6SSean Callanan 
195a1af4e6SSean Callanan using namespace lldb_private;
205a1af4e6SSean Callanan 
215a1af4e6SSean Callanan IRMemoryMap::IRMemoryMap (lldb::ProcessSP process_sp) :
2235005f76SSean Callanan     m_process_wp(process_sp),
2335005f76SSean Callanan     m_target_wp(process_sp->GetTarget().shared_from_this())
2435005f76SSean Callanan {
2535005f76SSean Callanan }
2635005f76SSean Callanan 
2735005f76SSean Callanan IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) :
2835005f76SSean Callanan     m_process_wp(),
2935005f76SSean Callanan     m_target_wp(target_sp)
305a1af4e6SSean Callanan {
315a1af4e6SSean Callanan }
325a1af4e6SSean Callanan 
335a1af4e6SSean Callanan IRMemoryMap::~IRMemoryMap ()
345a1af4e6SSean Callanan {
355a1af4e6SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
365a1af4e6SSean Callanan 
375a1af4e6SSean Callanan     if (process_sp)
385a1af4e6SSean Callanan     {
395a1af4e6SSean Callanan         for (AllocationMap::value_type &allocation : m_allocations)
405a1af4e6SSean Callanan         {
415a1af4e6SSean Callanan             if (allocation.second.m_policy == eAllocationPolicyMirror ||
425a1af4e6SSean Callanan                 allocation.second.m_policy == eAllocationPolicyHostOnly)
435a1af4e6SSean Callanan                 process_sp->DeallocateMemory(allocation.second.m_process_alloc);
445a1af4e6SSean Callanan 
455a1af4e6SSean Callanan             if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
465a1af4e6SSean Callanan             {
475a1af4e6SSean Callanan                 log->Printf("IRMemoryMap::~IRMemoryMap deallocated [0x%llx..0x%llx)",
485a1af4e6SSean Callanan                             (uint64_t)allocation.second.m_process_start,
495a1af4e6SSean Callanan                             (uint64_t)allocation.second.m_process_start + (uint64_t)allocation.second.m_size);
505a1af4e6SSean Callanan             }
515a1af4e6SSean Callanan         }
525a1af4e6SSean Callanan     }
535a1af4e6SSean Callanan }
545a1af4e6SSean Callanan 
555a1af4e6SSean Callanan lldb::addr_t
565a1af4e6SSean Callanan IRMemoryMap::FindSpace (size_t size)
575a1af4e6SSean Callanan {
585a1af4e6SSean Callanan     // Yup, this is just plain O(n) insertion.  We'll use a range tree if we
595a1af4e6SSean Callanan     // start caring.
605a1af4e6SSean Callanan 
615a1af4e6SSean Callanan     lldb::addr_t remote_address = 0x1000; // skip first page of memory
625a1af4e6SSean Callanan 
635a1af4e6SSean Callanan     for (AllocationMap::value_type &allocation : m_allocations)
645a1af4e6SSean Callanan     {
655a1af4e6SSean Callanan         if (remote_address < allocation.second.m_process_start &&
665a1af4e6SSean Callanan             remote_address + size <= allocation.second.m_process_start)
675a1af4e6SSean Callanan             return remote_address;
685a1af4e6SSean Callanan 
695a1af4e6SSean Callanan         remote_address = allocation.second.m_process_start = allocation.second.m_size;
705a1af4e6SSean Callanan     }
715a1af4e6SSean Callanan 
725a1af4e6SSean Callanan     if (remote_address + size < remote_address)
735a1af4e6SSean Callanan         return LLDB_INVALID_ADDRESS; // massively unlikely
745a1af4e6SSean Callanan 
755a1af4e6SSean Callanan     return remote_address;
765a1af4e6SSean Callanan }
775a1af4e6SSean Callanan 
785a1af4e6SSean Callanan bool
795a1af4e6SSean Callanan IRMemoryMap::ContainsHostOnlyAllocations ()
805a1af4e6SSean Callanan {
815a1af4e6SSean Callanan     for (AllocationMap::value_type &allocation : m_allocations)
825a1af4e6SSean Callanan     {
835a1af4e6SSean Callanan         if (allocation.second.m_policy == eAllocationPolicyHostOnly)
845a1af4e6SSean Callanan             return true;
855a1af4e6SSean Callanan     }
865a1af4e6SSean Callanan 
875a1af4e6SSean Callanan     return false;
885a1af4e6SSean Callanan }
895a1af4e6SSean Callanan 
905a1af4e6SSean Callanan IRMemoryMap::AllocationMap::iterator
915a1af4e6SSean Callanan IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
925a1af4e6SSean Callanan {
935a1af4e6SSean Callanan     AllocationMap::iterator iter = m_allocations.lower_bound (addr);
945a1af4e6SSean Callanan 
955a1af4e6SSean Callanan     if (iter == m_allocations.end())
965a1af4e6SSean Callanan         return iter;
975a1af4e6SSean Callanan 
985a1af4e6SSean Callanan     if (iter->first > addr)
995a1af4e6SSean Callanan     {
1005a1af4e6SSean Callanan         if (iter == m_allocations.begin())
1015a1af4e6SSean Callanan             return m_allocations.end();
1025a1af4e6SSean Callanan         iter--;
1035a1af4e6SSean Callanan     }
1045a1af4e6SSean Callanan 
1055a1af4e6SSean Callanan     if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
1065a1af4e6SSean Callanan         return iter;
1075a1af4e6SSean Callanan 
1085a1af4e6SSean Callanan     return m_allocations.end();
1095a1af4e6SSean Callanan }
1105a1af4e6SSean Callanan 
11135005f76SSean Callanan lldb::ByteOrder
11235005f76SSean Callanan IRMemoryMap::GetByteOrder()
11335005f76SSean Callanan {
11435005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
11535005f76SSean Callanan 
11635005f76SSean Callanan     if (process_sp)
11735005f76SSean Callanan         return process_sp->GetByteOrder();
11835005f76SSean Callanan 
11935005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
12035005f76SSean Callanan 
12135005f76SSean Callanan     if (target_sp)
12235005f76SSean Callanan         return target_sp->GetDefaultArchitecture().GetByteOrder();
12335005f76SSean Callanan 
12435005f76SSean Callanan     return lldb::eByteOrderInvalid;
12535005f76SSean Callanan }
12635005f76SSean Callanan 
12735005f76SSean Callanan uint32_t
12835005f76SSean Callanan IRMemoryMap::GetAddressByteSize()
12935005f76SSean Callanan {
13035005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
13135005f76SSean Callanan 
13235005f76SSean Callanan     if (process_sp)
13335005f76SSean Callanan         return process_sp->GetAddressByteSize();
13435005f76SSean Callanan 
13535005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
13635005f76SSean Callanan 
13735005f76SSean Callanan     if (target_sp)
13835005f76SSean Callanan         return target_sp->GetDefaultArchitecture().GetAddressByteSize();
13935005f76SSean Callanan 
14035005f76SSean Callanan     return UINT32_MAX;
14135005f76SSean Callanan }
14235005f76SSean Callanan 
14335005f76SSean Callanan ExecutionContextScope *
14435005f76SSean Callanan IRMemoryMap::GetBestExecutionContextScope()
14535005f76SSean Callanan {
14635005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
14735005f76SSean Callanan 
14835005f76SSean Callanan     if (process_sp)
14935005f76SSean Callanan         return process_sp.get();
15035005f76SSean Callanan 
15135005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
15235005f76SSean Callanan 
15335005f76SSean Callanan     if (target_sp)
15435005f76SSean Callanan         return target_sp.get();
15535005f76SSean Callanan 
15635005f76SSean Callanan     return NULL;
15735005f76SSean Callanan }
15835005f76SSean Callanan 
1595a1af4e6SSean Callanan lldb::addr_t
1605a1af4e6SSean Callanan IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
1615a1af4e6SSean Callanan {
1625a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
1635a1af4e6SSean Callanan     lldb::addr_t    allocation_address  = LLDB_INVALID_ADDRESS;
1645a1af4e6SSean Callanan     lldb::addr_t    aligned_address     = LLDB_INVALID_ADDRESS;
1655a1af4e6SSean Callanan 
1665a1af4e6SSean Callanan     size_t          allocation_size = (size ? size : 1) + alignment - 1;
1675a1af4e6SSean Callanan 
1685a1af4e6SSean Callanan     switch (policy)
1695a1af4e6SSean Callanan     {
1705a1af4e6SSean Callanan     default:
1715a1af4e6SSean Callanan         error.SetErrorToGenericError();
1725a1af4e6SSean Callanan         error.SetErrorString("Couldn't malloc: invalid allocation policy");
1735a1af4e6SSean Callanan         return LLDB_INVALID_ADDRESS;
1745a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
1755a1af4e6SSean Callanan         allocation_address = FindSpace(allocation_size);
1765a1af4e6SSean Callanan         if (allocation_address == LLDB_INVALID_ADDRESS)
1775a1af4e6SSean Callanan         {
1785a1af4e6SSean Callanan             error.SetErrorToGenericError();
1795a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: address space is full");
1805a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
1815a1af4e6SSean Callanan         }
1825a1af4e6SSean Callanan         break;
1835a1af4e6SSean Callanan     case eAllocationPolicyMirror:
1845a1af4e6SSean Callanan         if (ContainsHostOnlyAllocations())
1855a1af4e6SSean Callanan         {
1865a1af4e6SSean Callanan             error.SetErrorToGenericError();
1875a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: host-only allocations are polluting the address space");
1885a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
1895a1af4e6SSean Callanan         }
1905a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
1915a1af4e6SSean Callanan         if (process_sp)
1925a1af4e6SSean Callanan         {
1935a1af4e6SSean Callanan             allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
1945a1af4e6SSean Callanan             if (!error.Success())
1955a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
1965a1af4e6SSean Callanan         }
1975a1af4e6SSean Callanan         else
1985a1af4e6SSean Callanan         {
1995a1af4e6SSean Callanan             allocation_address = FindSpace(allocation_size);
2005a1af4e6SSean Callanan             if (allocation_address == LLDB_INVALID_ADDRESS)
2015a1af4e6SSean Callanan             {
2025a1af4e6SSean Callanan                 error.SetErrorToGenericError();
2035a1af4e6SSean Callanan                 error.SetErrorString("Couldn't malloc: address space is full");
2045a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
2055a1af4e6SSean Callanan             }
2065a1af4e6SSean Callanan         }
2075a1af4e6SSean Callanan         break;
2085a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
2095a1af4e6SSean Callanan         if (ContainsHostOnlyAllocations())
2105a1af4e6SSean Callanan         {
2115a1af4e6SSean Callanan             error.SetErrorToGenericError();
2125a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: host-only allocations are polluting the address space");
2135a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
2145a1af4e6SSean Callanan         }
2155a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
2165a1af4e6SSean Callanan         if (process_sp)
2175a1af4e6SSean Callanan         {
2185a1af4e6SSean Callanan             allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
2195a1af4e6SSean Callanan             if (!error.Success())
2205a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
2215a1af4e6SSean Callanan         }
2225a1af4e6SSean Callanan         else
2235a1af4e6SSean Callanan         {
2245a1af4e6SSean Callanan             error.SetErrorToGenericError();
2255a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
2265a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
2275a1af4e6SSean Callanan         }
2285a1af4e6SSean Callanan         break;
2295a1af4e6SSean Callanan     }
2305a1af4e6SSean Callanan 
2315a1af4e6SSean Callanan 
2325a1af4e6SSean Callanan     lldb::addr_t mask = alignment - 1;
2335a1af4e6SSean Callanan     aligned_address = (allocation_address + mask) & (~mask);
2345a1af4e6SSean Callanan 
2355a1af4e6SSean Callanan     Allocation &allocation(m_allocations[aligned_address]);
2365a1af4e6SSean Callanan 
2375a1af4e6SSean Callanan     allocation.m_process_alloc = allocation_address;
2385a1af4e6SSean Callanan     allocation.m_process_start = aligned_address;
2395a1af4e6SSean Callanan     allocation.m_size = size;
2405a1af4e6SSean Callanan     allocation.m_permissions = permissions;
2415a1af4e6SSean Callanan     allocation.m_alignment = alignment;
2425a1af4e6SSean Callanan     allocation.m_policy = policy;
2435a1af4e6SSean Callanan 
2445a1af4e6SSean Callanan     switch (policy)
2455a1af4e6SSean Callanan     {
2465a1af4e6SSean Callanan     default:
2475a1af4e6SSean Callanan         assert (0 && "We cannot reach this!");
2485a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
2495a1af4e6SSean Callanan         allocation.m_data.reset(new DataBufferHeap(size, 0));
2505a1af4e6SSean Callanan         break;
2515a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
2525a1af4e6SSean Callanan         break;
2535a1af4e6SSean Callanan     case eAllocationPolicyMirror:
2545a1af4e6SSean Callanan         allocation.m_data.reset(new DataBufferHeap(size, 0));
2555a1af4e6SSean Callanan         break;
2565a1af4e6SSean Callanan     }
2575a1af4e6SSean Callanan 
2585a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
2595a1af4e6SSean Callanan     {
2605a1af4e6SSean Callanan         const char * policy_string;
2615a1af4e6SSean Callanan 
2625a1af4e6SSean Callanan         switch (policy)
2635a1af4e6SSean Callanan         {
2645a1af4e6SSean Callanan         default:
2655a1af4e6SSean Callanan             policy_string = "<invalid policy>";
2665a1af4e6SSean Callanan             break;
2675a1af4e6SSean Callanan         case eAllocationPolicyHostOnly:
2685a1af4e6SSean Callanan             policy_string = "eAllocationPolicyHostOnly";
2695a1af4e6SSean Callanan             break;
2705a1af4e6SSean Callanan         case eAllocationPolicyProcessOnly:
2715a1af4e6SSean Callanan             policy_string = "eAllocationPolicyProcessOnly";
2725a1af4e6SSean Callanan             break;
2735a1af4e6SSean Callanan         case eAllocationPolicyMirror:
2745a1af4e6SSean Callanan             policy_string = "eAllocationPolicyMirror";
2755a1af4e6SSean Callanan             break;
2765a1af4e6SSean Callanan         }
2775a1af4e6SSean Callanan 
2785a1af4e6SSean Callanan         log->Printf("IRMemoryMap::Malloc (%llu, 0x%llx, 0x%llx, %s) -> 0x%llx",
2795a1af4e6SSean Callanan                     (uint64_t)size,
2805a1af4e6SSean Callanan                     (uint64_t)alignment,
2815a1af4e6SSean Callanan                     (uint64_t)permissions,
2825a1af4e6SSean Callanan                     policy_string,
2835a1af4e6SSean Callanan                     aligned_address);
2845a1af4e6SSean Callanan     }
2855a1af4e6SSean Callanan 
2865a1af4e6SSean Callanan     return aligned_address;
2875a1af4e6SSean Callanan }
2885a1af4e6SSean Callanan 
2895a1af4e6SSean Callanan void
2905a1af4e6SSean Callanan IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
2915a1af4e6SSean Callanan {
2925a1af4e6SSean Callanan     AllocationMap::iterator iter = m_allocations.find(process_address);
2935a1af4e6SSean Callanan 
2945a1af4e6SSean Callanan     if (iter == m_allocations.end())
2955a1af4e6SSean Callanan     {
2965a1af4e6SSean Callanan         error.SetErrorToGenericError();
2975a1af4e6SSean Callanan         error.SetErrorString("Couldn't free: allocation doesn't exist");
2985a1af4e6SSean Callanan         return;
2995a1af4e6SSean Callanan     }
3005a1af4e6SSean Callanan 
3015a1af4e6SSean Callanan     Allocation &allocation = iter->second;
3025a1af4e6SSean Callanan 
3035a1af4e6SSean Callanan     switch (allocation.m_policy)
3045a1af4e6SSean Callanan     {
3055a1af4e6SSean Callanan     default:
3065a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
3075a1af4e6SSean Callanan         break;
3085a1af4e6SSean Callanan     case eAllocationPolicyMirror:
3095a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
3105a1af4e6SSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
3115a1af4e6SSean Callanan         if (process_sp)
3125a1af4e6SSean Callanan             process_sp->DeallocateMemory(allocation.m_process_alloc);
3135a1af4e6SSean Callanan     }
3145a1af4e6SSean Callanan 
3155a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
3165a1af4e6SSean Callanan     {
3175a1af4e6SSean Callanan         log->Printf("IRMemoryMap::Free (0x%llx) freed [0x%llx..0x%llx)",
3185a1af4e6SSean Callanan                     (uint64_t)process_address,
3195a1af4e6SSean Callanan                     iter->second.m_process_start,
3205a1af4e6SSean Callanan                     iter->second.m_process_start + iter->second.m_size);
3215a1af4e6SSean Callanan     }
3225a1af4e6SSean Callanan 
3235a1af4e6SSean Callanan     m_allocations.erase(iter);
3245a1af4e6SSean Callanan }
3255a1af4e6SSean Callanan 
3265a1af4e6SSean Callanan void
3275a1af4e6SSean Callanan IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
3285a1af4e6SSean Callanan {
3295a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
3305a1af4e6SSean Callanan 
3315a1af4e6SSean Callanan     if (iter == m_allocations.end())
3325a1af4e6SSean Callanan     {
3335a1af4e6SSean Callanan         error.SetErrorToGenericError();
3345a1af4e6SSean Callanan         error.SetErrorString("Couldn't write: no allocation contains the target range");
3355a1af4e6SSean Callanan         return;
3365a1af4e6SSean Callanan     }
3375a1af4e6SSean Callanan 
3385a1af4e6SSean Callanan     Allocation &allocation = iter->second;
3395a1af4e6SSean Callanan 
3405a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
3415a1af4e6SSean Callanan 
3425a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
3435a1af4e6SSean Callanan 
3445a1af4e6SSean Callanan     switch (allocation.m_policy)
3455a1af4e6SSean Callanan     {
3465a1af4e6SSean Callanan     default:
3475a1af4e6SSean Callanan         error.SetErrorToGenericError();
3485a1af4e6SSean Callanan         error.SetErrorString("Couldn't write: invalid allocation policy");
3495a1af4e6SSean Callanan         return;
3505a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
3515a1af4e6SSean Callanan         if (!allocation.m_data)
3525a1af4e6SSean Callanan         {
3535a1af4e6SSean Callanan             error.SetErrorToGenericError();
3545a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
3555a1af4e6SSean Callanan             return;
3565a1af4e6SSean Callanan         }
3575a1af4e6SSean Callanan         ::memcpy (allocation.m_data->GetBytes() + offset, bytes, size);
3585a1af4e6SSean Callanan         break;
3595a1af4e6SSean Callanan     case eAllocationPolicyMirror:
3605a1af4e6SSean Callanan         if (!allocation.m_data)
3615a1af4e6SSean Callanan         {
3625a1af4e6SSean Callanan             error.SetErrorToGenericError();
3635a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
3645a1af4e6SSean Callanan             return;
3655a1af4e6SSean Callanan         }
3665a1af4e6SSean Callanan         ::memcpy (allocation.m_data->GetBytes() + offset, bytes, size);
3675a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
3685a1af4e6SSean Callanan         if (process_sp)
3695a1af4e6SSean Callanan         {
3705a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
3715a1af4e6SSean Callanan             if (!error.Success())
3725a1af4e6SSean Callanan                 return;
3735a1af4e6SSean Callanan         }
3745a1af4e6SSean Callanan         break;
3755a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
3765a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
3775a1af4e6SSean Callanan         if (process_sp)
3785a1af4e6SSean Callanan         {
3795a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
3805a1af4e6SSean Callanan             if (!error.Success())
3815a1af4e6SSean Callanan                 return;
3825a1af4e6SSean Callanan         }
3835a1af4e6SSean Callanan         break;
3845a1af4e6SSean Callanan     }
3855a1af4e6SSean Callanan 
3865a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
3875a1af4e6SSean Callanan     {
3885a1af4e6SSean Callanan         log->Printf("IRMemoryMap::WriteMemory (0x%llx, 0x%llx, 0x%lld) went to [0x%llx..0x%llx)",
3895a1af4e6SSean Callanan                     (uint64_t)process_address,
3905a1af4e6SSean Callanan                     (uint64_t)bytes,
3915a1af4e6SSean Callanan                     (uint64_t)size,
3925a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
3935a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
3945a1af4e6SSean Callanan     }
3955a1af4e6SSean Callanan }
3965a1af4e6SSean Callanan 
3975a1af4e6SSean Callanan void
39835005f76SSean Callanan IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
39935005f76SSean Callanan {
40035005f76SSean Callanan     if (size == UINT32_MAX)
40135005f76SSean Callanan         size = scalar.GetByteSize();
40235005f76SSean Callanan 
40335005f76SSean Callanan     if (size > 0)
40435005f76SSean Callanan     {
40535005f76SSean Callanan         uint8_t buf[32];
40635005f76SSean Callanan         const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
40735005f76SSean Callanan         if (mem_size > 0)
40835005f76SSean Callanan         {
40935005f76SSean Callanan             return WriteMemory(process_address, buf, mem_size, error);
41035005f76SSean Callanan         }
41135005f76SSean Callanan         else
41235005f76SSean Callanan         {
41335005f76SSean Callanan             error.SetErrorToGenericError();
41435005f76SSean Callanan             error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
41535005f76SSean Callanan         }
41635005f76SSean Callanan     }
41735005f76SSean Callanan     else
41835005f76SSean Callanan     {
41935005f76SSean Callanan         error.SetErrorToGenericError();
42035005f76SSean Callanan         error.SetErrorString ("Couldn't write scalar: its size was zero");
42135005f76SSean Callanan     }
42235005f76SSean Callanan     return;
42335005f76SSean Callanan }
42435005f76SSean Callanan 
42535005f76SSean Callanan void
426*f8043fa5SSean Callanan IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
427*f8043fa5SSean Callanan {
428*f8043fa5SSean Callanan     Scalar scalar(address);
429*f8043fa5SSean Callanan 
430*f8043fa5SSean Callanan     WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
431*f8043fa5SSean Callanan }
432*f8043fa5SSean Callanan 
433*f8043fa5SSean Callanan 
434*f8043fa5SSean Callanan void
4355a1af4e6SSean Callanan IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
4365a1af4e6SSean Callanan {
4375a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
4385a1af4e6SSean Callanan 
4395a1af4e6SSean Callanan     if (iter == m_allocations.end())
4405a1af4e6SSean Callanan     {
4415a1af4e6SSean Callanan         error.SetErrorToGenericError();
4425a1af4e6SSean Callanan         error.SetErrorString("Couldn't read: no allocation contains the target range");
4435a1af4e6SSean Callanan         return;
4445a1af4e6SSean Callanan     }
4455a1af4e6SSean Callanan 
4465a1af4e6SSean Callanan     Allocation &allocation = iter->second;
4475a1af4e6SSean Callanan 
4485a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
4495a1af4e6SSean Callanan 
4505a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
4515a1af4e6SSean Callanan 
4525a1af4e6SSean Callanan     switch (allocation.m_policy)
4535a1af4e6SSean Callanan     {
4545a1af4e6SSean Callanan     default:
4555a1af4e6SSean Callanan         error.SetErrorToGenericError();
4565a1af4e6SSean Callanan         error.SetErrorString("Couldn't read: invalid allocation policy");
4575a1af4e6SSean Callanan         return;
4585a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
4595a1af4e6SSean Callanan         if (!allocation.m_data)
4605a1af4e6SSean Callanan         {
4615a1af4e6SSean Callanan             error.SetErrorToGenericError();
4625a1af4e6SSean Callanan             error.SetErrorString("Couldn't read: data buffer is empty");
4635a1af4e6SSean Callanan             return;
4645a1af4e6SSean Callanan         }
4655a1af4e6SSean Callanan         ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
4665a1af4e6SSean Callanan         break;
4675a1af4e6SSean Callanan     case eAllocationPolicyMirror:
4685a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
4695a1af4e6SSean Callanan         if (process_sp)
4705a1af4e6SSean Callanan         {
4715a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
4725a1af4e6SSean Callanan             if (!error.Success())
4735a1af4e6SSean Callanan                 return;
4745a1af4e6SSean Callanan         }
4755a1af4e6SSean Callanan         else
4765a1af4e6SSean Callanan         {
4775a1af4e6SSean Callanan             if (!allocation.m_data)
4785a1af4e6SSean Callanan             {
4795a1af4e6SSean Callanan                 error.SetErrorToGenericError();
4805a1af4e6SSean Callanan                 error.SetErrorString("Couldn't read: data buffer is empty");
4815a1af4e6SSean Callanan                 return;
4825a1af4e6SSean Callanan             }
4835a1af4e6SSean Callanan             ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
4845a1af4e6SSean Callanan         }
4855a1af4e6SSean Callanan         break;
4865a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
4875a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
4885a1af4e6SSean Callanan         if (process_sp)
4895a1af4e6SSean Callanan         {
4905a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
4915a1af4e6SSean Callanan             if (!error.Success())
4925a1af4e6SSean Callanan                 return;
4935a1af4e6SSean Callanan         }
4945a1af4e6SSean Callanan         break;
4955a1af4e6SSean Callanan     }
4965a1af4e6SSean Callanan 
4975a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
4985a1af4e6SSean Callanan     {
4995a1af4e6SSean Callanan         log->Printf("IRMemoryMap::ReadMemory (0x%llx, 0x%llx, 0x%lld) came from [0x%llx..0x%llx)",
5005a1af4e6SSean Callanan                     (uint64_t)process_address,
5015a1af4e6SSean Callanan                     (uint64_t)bytes,
5025a1af4e6SSean Callanan                     (uint64_t)size,
5035a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
5045a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
5055a1af4e6SSean Callanan     }
5065a1af4e6SSean Callanan }
50735005f76SSean Callanan 
50835005f76SSean Callanan void
50935005f76SSean Callanan IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
51035005f76SSean Callanan {
51135005f76SSean Callanan     if (size > 0)
51235005f76SSean Callanan     {
51335005f76SSean Callanan         DataBufferHeap buf(size, 0);
51435005f76SSean Callanan         ReadMemory(buf.GetBytes(), process_address, size, error);
51535005f76SSean Callanan 
51635005f76SSean Callanan         if (!error.Success())
51735005f76SSean Callanan             return;
51835005f76SSean Callanan 
51935005f76SSean Callanan         DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
52035005f76SSean Callanan 
52135005f76SSean Callanan         lldb::offset_t offset = 0;
52235005f76SSean Callanan 
52335005f76SSean Callanan         switch (size)
52435005f76SSean Callanan         {
52535005f76SSean Callanan         default:
52635005f76SSean Callanan             error.SetErrorToGenericError();
52735005f76SSean Callanan             error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %lld", (unsigned long long)size);
52835005f76SSean Callanan             return;
52935005f76SSean Callanan         case 1: scalar = extractor.GetU8(&offset);  break;
53035005f76SSean Callanan         case 2: scalar = extractor.GetU16(&offset); break;
53135005f76SSean Callanan         case 4: scalar = extractor.GetU32(&offset); break;
53235005f76SSean Callanan         case 8: scalar = extractor.GetU64(&offset); break;
53335005f76SSean Callanan         }
53435005f76SSean Callanan     }
53535005f76SSean Callanan     else
53635005f76SSean Callanan     {
53735005f76SSean Callanan         error.SetErrorToGenericError();
53835005f76SSean Callanan         error.SetErrorString ("Couldn't write scalar: its size was zero");
53935005f76SSean Callanan     }
54035005f76SSean Callanan     return;
54135005f76SSean Callanan }
54235005f76SSean Callanan 
543