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 
2135005f76SSean Callanan IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) :
2235005f76SSean Callanan     m_target_wp(target_sp)
235a1af4e6SSean Callanan {
24*b024d878SSean Callanan     if (target_sp)
25*b024d878SSean Callanan         m_process_wp = target_sp->GetProcessSP();
265a1af4e6SSean Callanan }
275a1af4e6SSean Callanan 
285a1af4e6SSean Callanan IRMemoryMap::~IRMemoryMap ()
295a1af4e6SSean Callanan {
305a1af4e6SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
315a1af4e6SSean Callanan 
325a1af4e6SSean Callanan     if (process_sp)
335a1af4e6SSean Callanan     {
345a1af4e6SSean Callanan         for (AllocationMap::value_type &allocation : m_allocations)
355a1af4e6SSean Callanan         {
365a1af4e6SSean Callanan             if (allocation.second.m_policy == eAllocationPolicyMirror ||
375a1af4e6SSean Callanan                 allocation.second.m_policy == eAllocationPolicyHostOnly)
385a1af4e6SSean Callanan                 process_sp->DeallocateMemory(allocation.second.m_process_alloc);
395a1af4e6SSean Callanan 
405a1af4e6SSean Callanan             if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
415a1af4e6SSean Callanan             {
425a1af4e6SSean Callanan                 log->Printf("IRMemoryMap::~IRMemoryMap deallocated [0x%llx..0x%llx)",
435a1af4e6SSean Callanan                             (uint64_t)allocation.second.m_process_start,
445a1af4e6SSean Callanan                             (uint64_t)allocation.second.m_process_start + (uint64_t)allocation.second.m_size);
455a1af4e6SSean Callanan             }
465a1af4e6SSean Callanan         }
475a1af4e6SSean Callanan     }
485a1af4e6SSean Callanan }
495a1af4e6SSean Callanan 
505a1af4e6SSean Callanan lldb::addr_t
515a1af4e6SSean Callanan IRMemoryMap::FindSpace (size_t size)
525a1af4e6SSean Callanan {
535a1af4e6SSean Callanan     // Yup, this is just plain O(n) insertion.  We'll use a range tree if we
545a1af4e6SSean Callanan     // start caring.
555a1af4e6SSean Callanan 
565a1af4e6SSean Callanan     lldb::addr_t remote_address = 0x1000; // skip first page of memory
575a1af4e6SSean Callanan 
585a1af4e6SSean Callanan     for (AllocationMap::value_type &allocation : m_allocations)
595a1af4e6SSean Callanan     {
605a1af4e6SSean Callanan         if (remote_address < allocation.second.m_process_start &&
615a1af4e6SSean Callanan             remote_address + size <= allocation.second.m_process_start)
625a1af4e6SSean Callanan             return remote_address;
635a1af4e6SSean Callanan 
645a1af4e6SSean Callanan         remote_address = allocation.second.m_process_start = allocation.second.m_size;
655a1af4e6SSean Callanan     }
665a1af4e6SSean Callanan 
675a1af4e6SSean Callanan     if (remote_address + size < remote_address)
685a1af4e6SSean Callanan         return LLDB_INVALID_ADDRESS; // massively unlikely
695a1af4e6SSean Callanan 
705a1af4e6SSean Callanan     return remote_address;
715a1af4e6SSean Callanan }
725a1af4e6SSean Callanan 
735a1af4e6SSean Callanan bool
745a1af4e6SSean Callanan IRMemoryMap::ContainsHostOnlyAllocations ()
755a1af4e6SSean Callanan {
765a1af4e6SSean Callanan     for (AllocationMap::value_type &allocation : m_allocations)
775a1af4e6SSean Callanan     {
785a1af4e6SSean Callanan         if (allocation.second.m_policy == eAllocationPolicyHostOnly)
795a1af4e6SSean Callanan             return true;
805a1af4e6SSean Callanan     }
815a1af4e6SSean Callanan 
825a1af4e6SSean Callanan     return false;
835a1af4e6SSean Callanan }
845a1af4e6SSean Callanan 
855a1af4e6SSean Callanan IRMemoryMap::AllocationMap::iterator
865a1af4e6SSean Callanan IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
875a1af4e6SSean Callanan {
885a1af4e6SSean Callanan     AllocationMap::iterator iter = m_allocations.lower_bound (addr);
895a1af4e6SSean Callanan 
905a1af4e6SSean Callanan     if (iter == m_allocations.end())
915a1af4e6SSean Callanan         return iter;
925a1af4e6SSean Callanan 
935a1af4e6SSean Callanan     if (iter->first > addr)
945a1af4e6SSean Callanan     {
955a1af4e6SSean Callanan         if (iter == m_allocations.begin())
965a1af4e6SSean Callanan             return m_allocations.end();
975a1af4e6SSean Callanan         iter--;
985a1af4e6SSean Callanan     }
995a1af4e6SSean Callanan 
1005a1af4e6SSean Callanan     if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
1015a1af4e6SSean Callanan         return iter;
1025a1af4e6SSean Callanan 
1035a1af4e6SSean Callanan     return m_allocations.end();
1045a1af4e6SSean Callanan }
1055a1af4e6SSean Callanan 
10635005f76SSean Callanan lldb::ByteOrder
10735005f76SSean Callanan IRMemoryMap::GetByteOrder()
10835005f76SSean Callanan {
10935005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
11035005f76SSean Callanan 
11135005f76SSean Callanan     if (process_sp)
11235005f76SSean Callanan         return process_sp->GetByteOrder();
11335005f76SSean Callanan 
11435005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
11535005f76SSean Callanan 
11635005f76SSean Callanan     if (target_sp)
11735005f76SSean Callanan         return target_sp->GetDefaultArchitecture().GetByteOrder();
11835005f76SSean Callanan 
11935005f76SSean Callanan     return lldb::eByteOrderInvalid;
12035005f76SSean Callanan }
12135005f76SSean Callanan 
12235005f76SSean Callanan uint32_t
12335005f76SSean Callanan IRMemoryMap::GetAddressByteSize()
12435005f76SSean Callanan {
12535005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
12635005f76SSean Callanan 
12735005f76SSean Callanan     if (process_sp)
12835005f76SSean Callanan         return process_sp->GetAddressByteSize();
12935005f76SSean Callanan 
13035005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
13135005f76SSean Callanan 
13235005f76SSean Callanan     if (target_sp)
13335005f76SSean Callanan         return target_sp->GetDefaultArchitecture().GetAddressByteSize();
13435005f76SSean Callanan 
13535005f76SSean Callanan     return UINT32_MAX;
13635005f76SSean Callanan }
13735005f76SSean Callanan 
13835005f76SSean Callanan ExecutionContextScope *
13935005f76SSean Callanan IRMemoryMap::GetBestExecutionContextScope()
14035005f76SSean Callanan {
14135005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
14235005f76SSean Callanan 
14335005f76SSean Callanan     if (process_sp)
14435005f76SSean Callanan         return process_sp.get();
14535005f76SSean Callanan 
14635005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
14735005f76SSean Callanan 
14835005f76SSean Callanan     if (target_sp)
14935005f76SSean Callanan         return target_sp.get();
15035005f76SSean Callanan 
15135005f76SSean Callanan     return NULL;
15235005f76SSean Callanan }
15335005f76SSean Callanan 
1545a1af4e6SSean Callanan lldb::addr_t
1555a1af4e6SSean Callanan IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
1565a1af4e6SSean Callanan {
1575a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
1585a1af4e6SSean Callanan     lldb::addr_t    allocation_address  = LLDB_INVALID_ADDRESS;
1595a1af4e6SSean Callanan     lldb::addr_t    aligned_address     = LLDB_INVALID_ADDRESS;
1605a1af4e6SSean Callanan 
1615a1af4e6SSean Callanan     size_t          allocation_size = (size ? size : 1) + alignment - 1;
1625a1af4e6SSean Callanan 
1635a1af4e6SSean Callanan     switch (policy)
1645a1af4e6SSean Callanan     {
1655a1af4e6SSean Callanan     default:
1665a1af4e6SSean Callanan         error.SetErrorToGenericError();
1675a1af4e6SSean Callanan         error.SetErrorString("Couldn't malloc: invalid allocation policy");
1685a1af4e6SSean Callanan         return LLDB_INVALID_ADDRESS;
1695a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
1705a1af4e6SSean Callanan         allocation_address = FindSpace(allocation_size);
1715a1af4e6SSean Callanan         if (allocation_address == LLDB_INVALID_ADDRESS)
1725a1af4e6SSean Callanan         {
1735a1af4e6SSean Callanan             error.SetErrorToGenericError();
1745a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: address space is full");
1755a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
1765a1af4e6SSean Callanan         }
1775a1af4e6SSean Callanan         break;
1785a1af4e6SSean Callanan     case eAllocationPolicyMirror:
1795a1af4e6SSean Callanan         if (ContainsHostOnlyAllocations())
1805a1af4e6SSean Callanan         {
1815a1af4e6SSean Callanan             error.SetErrorToGenericError();
1825a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: host-only allocations are polluting the address space");
1835a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
1845a1af4e6SSean Callanan         }
1855a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
1865a1af4e6SSean Callanan         if (process_sp)
1875a1af4e6SSean Callanan         {
1885a1af4e6SSean Callanan             allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
1895a1af4e6SSean Callanan             if (!error.Success())
1905a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
1915a1af4e6SSean Callanan         }
1925a1af4e6SSean Callanan         else
1935a1af4e6SSean Callanan         {
1945a1af4e6SSean Callanan             allocation_address = FindSpace(allocation_size);
1955a1af4e6SSean Callanan             if (allocation_address == LLDB_INVALID_ADDRESS)
1965a1af4e6SSean Callanan             {
1975a1af4e6SSean Callanan                 error.SetErrorToGenericError();
1985a1af4e6SSean Callanan                 error.SetErrorString("Couldn't malloc: address space is full");
1995a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
2005a1af4e6SSean Callanan             }
2015a1af4e6SSean Callanan         }
2025a1af4e6SSean Callanan         break;
2035a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
2045a1af4e6SSean Callanan         if (ContainsHostOnlyAllocations())
2055a1af4e6SSean Callanan         {
2065a1af4e6SSean Callanan             error.SetErrorToGenericError();
2075a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: host-only allocations are polluting the address space");
2085a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
2095a1af4e6SSean Callanan         }
2105a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
2115a1af4e6SSean Callanan         if (process_sp)
2125a1af4e6SSean Callanan         {
2135a1af4e6SSean Callanan             allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
2145a1af4e6SSean Callanan             if (!error.Success())
2155a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
2165a1af4e6SSean Callanan         }
2175a1af4e6SSean Callanan         else
2185a1af4e6SSean Callanan         {
2195a1af4e6SSean Callanan             error.SetErrorToGenericError();
2205a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
2215a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
2225a1af4e6SSean Callanan         }
2235a1af4e6SSean Callanan         break;
2245a1af4e6SSean Callanan     }
2255a1af4e6SSean Callanan 
2265a1af4e6SSean Callanan 
2275a1af4e6SSean Callanan     lldb::addr_t mask = alignment - 1;
2285a1af4e6SSean Callanan     aligned_address = (allocation_address + mask) & (~mask);
2295a1af4e6SSean Callanan 
2305a1af4e6SSean Callanan     Allocation &allocation(m_allocations[aligned_address]);
2315a1af4e6SSean Callanan 
2325a1af4e6SSean Callanan     allocation.m_process_alloc = allocation_address;
2335a1af4e6SSean Callanan     allocation.m_process_start = aligned_address;
2345a1af4e6SSean Callanan     allocation.m_size = size;
2355a1af4e6SSean Callanan     allocation.m_permissions = permissions;
2365a1af4e6SSean Callanan     allocation.m_alignment = alignment;
2375a1af4e6SSean Callanan     allocation.m_policy = policy;
2385a1af4e6SSean Callanan 
2395a1af4e6SSean Callanan     switch (policy)
2405a1af4e6SSean Callanan     {
2415a1af4e6SSean Callanan     default:
2425a1af4e6SSean Callanan         assert (0 && "We cannot reach this!");
2435a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
2445a1af4e6SSean Callanan         allocation.m_data.reset(new DataBufferHeap(size, 0));
2455a1af4e6SSean Callanan         break;
2465a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
2475a1af4e6SSean Callanan         break;
2485a1af4e6SSean Callanan     case eAllocationPolicyMirror:
2495a1af4e6SSean Callanan         allocation.m_data.reset(new DataBufferHeap(size, 0));
2505a1af4e6SSean Callanan         break;
2515a1af4e6SSean Callanan     }
2525a1af4e6SSean Callanan 
2535a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
2545a1af4e6SSean Callanan     {
2555a1af4e6SSean Callanan         const char * policy_string;
2565a1af4e6SSean Callanan 
2575a1af4e6SSean Callanan         switch (policy)
2585a1af4e6SSean Callanan         {
2595a1af4e6SSean Callanan         default:
2605a1af4e6SSean Callanan             policy_string = "<invalid policy>";
2615a1af4e6SSean Callanan             break;
2625a1af4e6SSean Callanan         case eAllocationPolicyHostOnly:
2635a1af4e6SSean Callanan             policy_string = "eAllocationPolicyHostOnly";
2645a1af4e6SSean Callanan             break;
2655a1af4e6SSean Callanan         case eAllocationPolicyProcessOnly:
2665a1af4e6SSean Callanan             policy_string = "eAllocationPolicyProcessOnly";
2675a1af4e6SSean Callanan             break;
2685a1af4e6SSean Callanan         case eAllocationPolicyMirror:
2695a1af4e6SSean Callanan             policy_string = "eAllocationPolicyMirror";
2705a1af4e6SSean Callanan             break;
2715a1af4e6SSean Callanan         }
2725a1af4e6SSean Callanan 
2735a1af4e6SSean Callanan         log->Printf("IRMemoryMap::Malloc (%llu, 0x%llx, 0x%llx, %s) -> 0x%llx",
2745a1af4e6SSean Callanan                     (uint64_t)size,
2755a1af4e6SSean Callanan                     (uint64_t)alignment,
2765a1af4e6SSean Callanan                     (uint64_t)permissions,
2775a1af4e6SSean Callanan                     policy_string,
2785a1af4e6SSean Callanan                     aligned_address);
2795a1af4e6SSean Callanan     }
2805a1af4e6SSean Callanan 
2815a1af4e6SSean Callanan     return aligned_address;
2825a1af4e6SSean Callanan }
2835a1af4e6SSean Callanan 
2845a1af4e6SSean Callanan void
2855a1af4e6SSean Callanan IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
2865a1af4e6SSean Callanan {
2875a1af4e6SSean Callanan     AllocationMap::iterator iter = m_allocations.find(process_address);
2885a1af4e6SSean Callanan 
2895a1af4e6SSean Callanan     if (iter == m_allocations.end())
2905a1af4e6SSean Callanan     {
2915a1af4e6SSean Callanan         error.SetErrorToGenericError();
2925a1af4e6SSean Callanan         error.SetErrorString("Couldn't free: allocation doesn't exist");
2935a1af4e6SSean Callanan         return;
2945a1af4e6SSean Callanan     }
2955a1af4e6SSean Callanan 
2965a1af4e6SSean Callanan     Allocation &allocation = iter->second;
2975a1af4e6SSean Callanan 
2985a1af4e6SSean Callanan     switch (allocation.m_policy)
2995a1af4e6SSean Callanan     {
3005a1af4e6SSean Callanan     default:
3015a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
3025a1af4e6SSean Callanan         break;
3035a1af4e6SSean Callanan     case eAllocationPolicyMirror:
3045a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
3055a1af4e6SSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
3065a1af4e6SSean Callanan         if (process_sp)
3075a1af4e6SSean Callanan             process_sp->DeallocateMemory(allocation.m_process_alloc);
3085a1af4e6SSean Callanan     }
3095a1af4e6SSean Callanan 
3105a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
3115a1af4e6SSean Callanan     {
3125a1af4e6SSean Callanan         log->Printf("IRMemoryMap::Free (0x%llx) freed [0x%llx..0x%llx)",
3135a1af4e6SSean Callanan                     (uint64_t)process_address,
3145a1af4e6SSean Callanan                     iter->second.m_process_start,
3155a1af4e6SSean Callanan                     iter->second.m_process_start + iter->second.m_size);
3165a1af4e6SSean Callanan     }
3175a1af4e6SSean Callanan 
3185a1af4e6SSean Callanan     m_allocations.erase(iter);
3195a1af4e6SSean Callanan }
3205a1af4e6SSean Callanan 
3215a1af4e6SSean Callanan void
3225a1af4e6SSean Callanan IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
3235a1af4e6SSean Callanan {
3245a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
3255a1af4e6SSean Callanan 
3265a1af4e6SSean Callanan     if (iter == m_allocations.end())
3275a1af4e6SSean Callanan     {
3285a1af4e6SSean Callanan         error.SetErrorToGenericError();
3295a1af4e6SSean Callanan         error.SetErrorString("Couldn't write: no allocation contains the target range");
3305a1af4e6SSean Callanan         return;
3315a1af4e6SSean Callanan     }
3325a1af4e6SSean Callanan 
3335a1af4e6SSean Callanan     Allocation &allocation = iter->second;
3345a1af4e6SSean Callanan 
3355a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
3365a1af4e6SSean Callanan 
3375a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
3385a1af4e6SSean Callanan 
3395a1af4e6SSean Callanan     switch (allocation.m_policy)
3405a1af4e6SSean Callanan     {
3415a1af4e6SSean Callanan     default:
3425a1af4e6SSean Callanan         error.SetErrorToGenericError();
3435a1af4e6SSean Callanan         error.SetErrorString("Couldn't write: invalid allocation policy");
3445a1af4e6SSean Callanan         return;
3455a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
3465a1af4e6SSean Callanan         if (!allocation.m_data)
3475a1af4e6SSean Callanan         {
3485a1af4e6SSean Callanan             error.SetErrorToGenericError();
3495a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
3505a1af4e6SSean Callanan             return;
3515a1af4e6SSean Callanan         }
3525a1af4e6SSean Callanan         ::memcpy (allocation.m_data->GetBytes() + offset, bytes, size);
3535a1af4e6SSean Callanan         break;
3545a1af4e6SSean Callanan     case eAllocationPolicyMirror:
3555a1af4e6SSean Callanan         if (!allocation.m_data)
3565a1af4e6SSean Callanan         {
3575a1af4e6SSean Callanan             error.SetErrorToGenericError();
3585a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
3595a1af4e6SSean Callanan             return;
3605a1af4e6SSean Callanan         }
3615a1af4e6SSean Callanan         ::memcpy (allocation.m_data->GetBytes() + offset, bytes, size);
3625a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
3635a1af4e6SSean Callanan         if (process_sp)
3645a1af4e6SSean Callanan         {
3655a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
3665a1af4e6SSean Callanan             if (!error.Success())
3675a1af4e6SSean Callanan                 return;
3685a1af4e6SSean Callanan         }
3695a1af4e6SSean Callanan         break;
3705a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
3715a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
3725a1af4e6SSean Callanan         if (process_sp)
3735a1af4e6SSean Callanan         {
3745a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
3755a1af4e6SSean Callanan             if (!error.Success())
3765a1af4e6SSean Callanan                 return;
3775a1af4e6SSean Callanan         }
3785a1af4e6SSean Callanan         break;
3795a1af4e6SSean Callanan     }
3805a1af4e6SSean Callanan 
3815a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
3825a1af4e6SSean Callanan     {
3835a1af4e6SSean Callanan         log->Printf("IRMemoryMap::WriteMemory (0x%llx, 0x%llx, 0x%lld) went to [0x%llx..0x%llx)",
3845a1af4e6SSean Callanan                     (uint64_t)process_address,
3855a1af4e6SSean Callanan                     (uint64_t)bytes,
3865a1af4e6SSean Callanan                     (uint64_t)size,
3875a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
3885a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
3895a1af4e6SSean Callanan     }
3905a1af4e6SSean Callanan }
3915a1af4e6SSean Callanan 
3925a1af4e6SSean Callanan void
39335005f76SSean Callanan IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
39435005f76SSean Callanan {
39535005f76SSean Callanan     if (size == UINT32_MAX)
39635005f76SSean Callanan         size = scalar.GetByteSize();
39735005f76SSean Callanan 
39835005f76SSean Callanan     if (size > 0)
39935005f76SSean Callanan     {
40035005f76SSean Callanan         uint8_t buf[32];
40135005f76SSean Callanan         const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
40235005f76SSean Callanan         if (mem_size > 0)
40335005f76SSean Callanan         {
40435005f76SSean Callanan             return WriteMemory(process_address, buf, mem_size, error);
40535005f76SSean Callanan         }
40635005f76SSean Callanan         else
40735005f76SSean Callanan         {
40835005f76SSean Callanan             error.SetErrorToGenericError();
40935005f76SSean Callanan             error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
41035005f76SSean Callanan         }
41135005f76SSean Callanan     }
41235005f76SSean Callanan     else
41335005f76SSean Callanan     {
41435005f76SSean Callanan         error.SetErrorToGenericError();
41535005f76SSean Callanan         error.SetErrorString ("Couldn't write scalar: its size was zero");
41635005f76SSean Callanan     }
41735005f76SSean Callanan     return;
41835005f76SSean Callanan }
41935005f76SSean Callanan 
42035005f76SSean Callanan void
421f8043fa5SSean Callanan IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
422f8043fa5SSean Callanan {
423f8043fa5SSean Callanan     Scalar scalar(address);
424f8043fa5SSean Callanan 
425f8043fa5SSean Callanan     WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
426f8043fa5SSean Callanan }
427f8043fa5SSean Callanan 
428f8043fa5SSean Callanan 
429f8043fa5SSean Callanan void
4305a1af4e6SSean Callanan IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
4315a1af4e6SSean Callanan {
4325a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
4335a1af4e6SSean Callanan 
4345a1af4e6SSean Callanan     if (iter == m_allocations.end())
4355a1af4e6SSean Callanan     {
4365a1af4e6SSean Callanan         error.SetErrorToGenericError();
4375a1af4e6SSean Callanan         error.SetErrorString("Couldn't read: no allocation contains the target range");
4385a1af4e6SSean Callanan         return;
4395a1af4e6SSean Callanan     }
4405a1af4e6SSean Callanan 
4415a1af4e6SSean Callanan     Allocation &allocation = iter->second;
4425a1af4e6SSean Callanan 
4435a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
4445a1af4e6SSean Callanan 
4455a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
4465a1af4e6SSean Callanan 
4475a1af4e6SSean Callanan     switch (allocation.m_policy)
4485a1af4e6SSean Callanan     {
4495a1af4e6SSean Callanan     default:
4505a1af4e6SSean Callanan         error.SetErrorToGenericError();
4515a1af4e6SSean Callanan         error.SetErrorString("Couldn't read: invalid allocation policy");
4525a1af4e6SSean Callanan         return;
4535a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
4545a1af4e6SSean Callanan         if (!allocation.m_data)
4555a1af4e6SSean Callanan         {
4565a1af4e6SSean Callanan             error.SetErrorToGenericError();
4575a1af4e6SSean Callanan             error.SetErrorString("Couldn't read: data buffer is empty");
4585a1af4e6SSean Callanan             return;
4595a1af4e6SSean Callanan         }
4605a1af4e6SSean Callanan         ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
4615a1af4e6SSean Callanan         break;
4625a1af4e6SSean Callanan     case eAllocationPolicyMirror:
4635a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
4645a1af4e6SSean Callanan         if (process_sp)
4655a1af4e6SSean Callanan         {
4665a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
4675a1af4e6SSean Callanan             if (!error.Success())
4685a1af4e6SSean Callanan                 return;
4695a1af4e6SSean Callanan         }
4705a1af4e6SSean Callanan         else
4715a1af4e6SSean Callanan         {
4725a1af4e6SSean Callanan             if (!allocation.m_data)
4735a1af4e6SSean Callanan             {
4745a1af4e6SSean Callanan                 error.SetErrorToGenericError();
4755a1af4e6SSean Callanan                 error.SetErrorString("Couldn't read: data buffer is empty");
4765a1af4e6SSean Callanan                 return;
4775a1af4e6SSean Callanan             }
4785a1af4e6SSean Callanan             ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
4795a1af4e6SSean Callanan         }
4805a1af4e6SSean Callanan         break;
4815a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
4825a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
4835a1af4e6SSean Callanan         if (process_sp)
4845a1af4e6SSean Callanan         {
4855a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
4865a1af4e6SSean Callanan             if (!error.Success())
4875a1af4e6SSean Callanan                 return;
4885a1af4e6SSean Callanan         }
4895a1af4e6SSean Callanan         break;
4905a1af4e6SSean Callanan     }
4915a1af4e6SSean Callanan 
4925a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
4935a1af4e6SSean Callanan     {
4945a1af4e6SSean Callanan         log->Printf("IRMemoryMap::ReadMemory (0x%llx, 0x%llx, 0x%lld) came from [0x%llx..0x%llx)",
4955a1af4e6SSean Callanan                     (uint64_t)process_address,
4965a1af4e6SSean Callanan                     (uint64_t)bytes,
4975a1af4e6SSean Callanan                     (uint64_t)size,
4985a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
4995a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
5005a1af4e6SSean Callanan     }
5015a1af4e6SSean Callanan }
50235005f76SSean Callanan 
50335005f76SSean Callanan void
50435005f76SSean Callanan IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
50535005f76SSean Callanan {
50635005f76SSean Callanan     if (size > 0)
50735005f76SSean Callanan     {
50835005f76SSean Callanan         DataBufferHeap buf(size, 0);
50935005f76SSean Callanan         ReadMemory(buf.GetBytes(), process_address, size, error);
51035005f76SSean Callanan 
51135005f76SSean Callanan         if (!error.Success())
51235005f76SSean Callanan             return;
51335005f76SSean Callanan 
51435005f76SSean Callanan         DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
51535005f76SSean Callanan 
51635005f76SSean Callanan         lldb::offset_t offset = 0;
51735005f76SSean Callanan 
51835005f76SSean Callanan         switch (size)
51935005f76SSean Callanan         {
52035005f76SSean Callanan         default:
52135005f76SSean Callanan             error.SetErrorToGenericError();
52235005f76SSean Callanan             error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %lld", (unsigned long long)size);
52335005f76SSean Callanan             return;
52435005f76SSean Callanan         case 1: scalar = extractor.GetU8(&offset);  break;
52535005f76SSean Callanan         case 2: scalar = extractor.GetU16(&offset); break;
52635005f76SSean Callanan         case 4: scalar = extractor.GetU32(&offset); break;
52735005f76SSean Callanan         case 8: scalar = extractor.GetU64(&offset); break;
52835005f76SSean Callanan         }
52935005f76SSean Callanan     }
53035005f76SSean Callanan     else
53135005f76SSean Callanan     {
53235005f76SSean Callanan         error.SetErrorToGenericError();
533458ae1c6SSean Callanan         error.SetErrorString ("Couldn't read scalar: its size was zero");
53435005f76SSean Callanan     }
53535005f76SSean Callanan     return;
53635005f76SSean Callanan }
53735005f76SSean Callanan 
538458ae1c6SSean Callanan void
539458ae1c6SSean Callanan IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
540458ae1c6SSean Callanan {
541458ae1c6SSean Callanan     if (size > 0)
542458ae1c6SSean Callanan     {
543458ae1c6SSean Callanan         AllocationMap::iterator iter = FindAllocation(process_address, size);
544458ae1c6SSean Callanan 
545458ae1c6SSean Callanan         if (iter == m_allocations.end())
546458ae1c6SSean Callanan         {
547458ae1c6SSean Callanan             error.SetErrorToGenericError();
548458ae1c6SSean Callanan             error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%llx..0x%llx)", (unsigned long long)process_address, (unsigned long long)(process_address + size));
549458ae1c6SSean Callanan             return;
550458ae1c6SSean Callanan         }
551458ae1c6SSean Callanan 
552458ae1c6SSean Callanan         Allocation &allocation = iter->second;
553458ae1c6SSean Callanan 
554458ae1c6SSean Callanan         switch (allocation.m_policy)
555458ae1c6SSean Callanan         {
556458ae1c6SSean Callanan         default:
557458ae1c6SSean Callanan             error.SetErrorToGenericError();
558458ae1c6SSean Callanan             error.SetErrorString("Couldn't get memory data: invalid allocation policy");
559458ae1c6SSean Callanan             return;
560458ae1c6SSean Callanan         case eAllocationPolicyProcessOnly:
561458ae1c6SSean Callanan             error.SetErrorToGenericError();
562458ae1c6SSean Callanan             error.SetErrorString("Couldn't get memory data: memory is only in the target");
563458ae1c6SSean Callanan             return;
564458ae1c6SSean Callanan         case eAllocationPolicyHostOnly:
565458ae1c6SSean Callanan         case eAllocationPolicyMirror:
566458ae1c6SSean Callanan             if (!allocation.m_data.get())
567458ae1c6SSean Callanan             {
568458ae1c6SSean Callanan                 error.SetErrorToGenericError();
569458ae1c6SSean Callanan                 error.SetErrorString("Couldn't get memory data: data buffer is empty");
570458ae1c6SSean Callanan                 return;
571458ae1c6SSean Callanan             }
572458ae1c6SSean Callanan             uint64_t offset = process_address - allocation.m_process_start;
573458ae1c6SSean Callanan             extractor = DataExtractor(allocation.m_data->GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
574458ae1c6SSean Callanan             return;
575458ae1c6SSean Callanan         }
576458ae1c6SSean Callanan     }
577458ae1c6SSean Callanan     else
578458ae1c6SSean Callanan     {
579458ae1c6SSean Callanan         error.SetErrorToGenericError();
580458ae1c6SSean Callanan         error.SetErrorString ("Couldn't get memory data: its size was zero");
581458ae1c6SSean Callanan         return;
582458ae1c6SSean Callanan     }
583458ae1c6SSean Callanan }
584458ae1c6SSean Callanan 
585458ae1c6SSean Callanan 
586