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 
10*35005f76SSean Callanan #include "lldb/Core/DataBufferHeap.h"
11*35005f76SSean Callanan #include "lldb/Core/DataExtractor.h"
125a1af4e6SSean Callanan #include "lldb/Core/Error.h"
135a1af4e6SSean Callanan #include "lldb/Core/Log.h"
14*35005f76SSean Callanan #include "lldb/Core/Scalar.h"
155a1af4e6SSean Callanan #include "lldb/Expression/IRMemoryMap.h"
165a1af4e6SSean Callanan #include "lldb/Target/Process.h"
17*35005f76SSean Callanan #include "lldb/Target/Target.h"
185a1af4e6SSean Callanan 
195a1af4e6SSean Callanan using namespace lldb_private;
205a1af4e6SSean Callanan 
215a1af4e6SSean Callanan IRMemoryMap::IRMemoryMap (lldb::ProcessSP process_sp) :
22*35005f76SSean Callanan     m_process_wp(process_sp),
23*35005f76SSean Callanan     m_target_wp(process_sp->GetTarget().shared_from_this())
24*35005f76SSean Callanan {
25*35005f76SSean Callanan }
26*35005f76SSean Callanan 
27*35005f76SSean Callanan IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) :
28*35005f76SSean Callanan     m_process_wp(),
29*35005f76SSean 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 
111*35005f76SSean Callanan lldb::ByteOrder
112*35005f76SSean Callanan IRMemoryMap::GetByteOrder()
113*35005f76SSean Callanan {
114*35005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
115*35005f76SSean Callanan 
116*35005f76SSean Callanan     if (process_sp)
117*35005f76SSean Callanan         return process_sp->GetByteOrder();
118*35005f76SSean Callanan 
119*35005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
120*35005f76SSean Callanan 
121*35005f76SSean Callanan     if (target_sp)
122*35005f76SSean Callanan         return target_sp->GetDefaultArchitecture().GetByteOrder();
123*35005f76SSean Callanan 
124*35005f76SSean Callanan     return lldb::eByteOrderInvalid;
125*35005f76SSean Callanan }
126*35005f76SSean Callanan 
127*35005f76SSean Callanan uint32_t
128*35005f76SSean Callanan IRMemoryMap::GetAddressByteSize()
129*35005f76SSean Callanan {
130*35005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
131*35005f76SSean Callanan 
132*35005f76SSean Callanan     if (process_sp)
133*35005f76SSean Callanan         return process_sp->GetAddressByteSize();
134*35005f76SSean Callanan 
135*35005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
136*35005f76SSean Callanan 
137*35005f76SSean Callanan     if (target_sp)
138*35005f76SSean Callanan         return target_sp->GetDefaultArchitecture().GetAddressByteSize();
139*35005f76SSean Callanan 
140*35005f76SSean Callanan     return UINT32_MAX;
141*35005f76SSean Callanan }
142*35005f76SSean Callanan 
143*35005f76SSean Callanan ExecutionContextScope *
144*35005f76SSean Callanan IRMemoryMap::GetBestExecutionContextScope()
145*35005f76SSean Callanan {
146*35005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
147*35005f76SSean Callanan 
148*35005f76SSean Callanan     if (process_sp)
149*35005f76SSean Callanan         return process_sp.get();
150*35005f76SSean Callanan 
151*35005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
152*35005f76SSean Callanan 
153*35005f76SSean Callanan     if (target_sp)
154*35005f76SSean Callanan         return target_sp.get();
155*35005f76SSean Callanan 
156*35005f76SSean Callanan     return NULL;
157*35005f76SSean Callanan }
158*35005f76SSean 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
398*35005f76SSean Callanan IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
399*35005f76SSean Callanan {
400*35005f76SSean Callanan     if (size == UINT32_MAX)
401*35005f76SSean Callanan         size = scalar.GetByteSize();
402*35005f76SSean Callanan 
403*35005f76SSean Callanan     if (size > 0)
404*35005f76SSean Callanan     {
405*35005f76SSean Callanan         uint8_t buf[32];
406*35005f76SSean Callanan         const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
407*35005f76SSean Callanan         if (mem_size > 0)
408*35005f76SSean Callanan         {
409*35005f76SSean Callanan             return WriteMemory(process_address, buf, mem_size, error);
410*35005f76SSean Callanan         }
411*35005f76SSean Callanan         else
412*35005f76SSean Callanan         {
413*35005f76SSean Callanan             error.SetErrorToGenericError();
414*35005f76SSean Callanan             error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
415*35005f76SSean Callanan         }
416*35005f76SSean Callanan     }
417*35005f76SSean Callanan     else
418*35005f76SSean Callanan     {
419*35005f76SSean Callanan         error.SetErrorToGenericError();
420*35005f76SSean Callanan         error.SetErrorString ("Couldn't write scalar: its size was zero");
421*35005f76SSean Callanan     }
422*35005f76SSean Callanan     return;
423*35005f76SSean Callanan }
424*35005f76SSean Callanan 
425*35005f76SSean Callanan void
4265a1af4e6SSean Callanan IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
4275a1af4e6SSean Callanan {
4285a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
4295a1af4e6SSean Callanan 
4305a1af4e6SSean Callanan     if (iter == m_allocations.end())
4315a1af4e6SSean Callanan     {
4325a1af4e6SSean Callanan         error.SetErrorToGenericError();
4335a1af4e6SSean Callanan         error.SetErrorString("Couldn't read: no allocation contains the target range");
4345a1af4e6SSean Callanan         return;
4355a1af4e6SSean Callanan     }
4365a1af4e6SSean Callanan 
4375a1af4e6SSean Callanan     Allocation &allocation = iter->second;
4385a1af4e6SSean Callanan 
4395a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
4405a1af4e6SSean Callanan 
4415a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
4425a1af4e6SSean Callanan 
4435a1af4e6SSean Callanan     switch (allocation.m_policy)
4445a1af4e6SSean Callanan     {
4455a1af4e6SSean Callanan     default:
4465a1af4e6SSean Callanan         error.SetErrorToGenericError();
4475a1af4e6SSean Callanan         error.SetErrorString("Couldn't read: invalid allocation policy");
4485a1af4e6SSean Callanan         return;
4495a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
4505a1af4e6SSean Callanan         if (!allocation.m_data)
4515a1af4e6SSean Callanan         {
4525a1af4e6SSean Callanan             error.SetErrorToGenericError();
4535a1af4e6SSean Callanan             error.SetErrorString("Couldn't read: data buffer is empty");
4545a1af4e6SSean Callanan             return;
4555a1af4e6SSean Callanan         }
4565a1af4e6SSean Callanan         ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
4575a1af4e6SSean Callanan         break;
4585a1af4e6SSean Callanan     case eAllocationPolicyMirror:
4595a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
4605a1af4e6SSean Callanan         if (process_sp)
4615a1af4e6SSean Callanan         {
4625a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
4635a1af4e6SSean Callanan             if (!error.Success())
4645a1af4e6SSean Callanan                 return;
4655a1af4e6SSean Callanan         }
4665a1af4e6SSean Callanan         else
4675a1af4e6SSean Callanan         {
4685a1af4e6SSean Callanan             if (!allocation.m_data)
4695a1af4e6SSean Callanan             {
4705a1af4e6SSean Callanan                 error.SetErrorToGenericError();
4715a1af4e6SSean Callanan                 error.SetErrorString("Couldn't read: data buffer is empty");
4725a1af4e6SSean Callanan                 return;
4735a1af4e6SSean Callanan             }
4745a1af4e6SSean Callanan             ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
4755a1af4e6SSean Callanan         }
4765a1af4e6SSean Callanan         break;
4775a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
4785a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
4795a1af4e6SSean Callanan         if (process_sp)
4805a1af4e6SSean Callanan         {
4815a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
4825a1af4e6SSean Callanan             if (!error.Success())
4835a1af4e6SSean Callanan                 return;
4845a1af4e6SSean Callanan         }
4855a1af4e6SSean Callanan         break;
4865a1af4e6SSean Callanan     }
4875a1af4e6SSean Callanan 
4885a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
4895a1af4e6SSean Callanan     {
4905a1af4e6SSean Callanan         log->Printf("IRMemoryMap::ReadMemory (0x%llx, 0x%llx, 0x%lld) came from [0x%llx..0x%llx)",
4915a1af4e6SSean Callanan                     (uint64_t)process_address,
4925a1af4e6SSean Callanan                     (uint64_t)bytes,
4935a1af4e6SSean Callanan                     (uint64_t)size,
4945a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
4955a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
4965a1af4e6SSean Callanan     }
4975a1af4e6SSean Callanan }
498*35005f76SSean Callanan 
499*35005f76SSean Callanan void
500*35005f76SSean Callanan IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
501*35005f76SSean Callanan {
502*35005f76SSean Callanan     if (size > 0)
503*35005f76SSean Callanan     {
504*35005f76SSean Callanan         DataBufferHeap buf(size, 0);
505*35005f76SSean Callanan         ReadMemory(buf.GetBytes(), process_address, size, error);
506*35005f76SSean Callanan 
507*35005f76SSean Callanan         if (!error.Success())
508*35005f76SSean Callanan             return;
509*35005f76SSean Callanan 
510*35005f76SSean Callanan         DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
511*35005f76SSean Callanan 
512*35005f76SSean Callanan         lldb::offset_t offset = 0;
513*35005f76SSean Callanan 
514*35005f76SSean Callanan         switch (size)
515*35005f76SSean Callanan         {
516*35005f76SSean Callanan         default:
517*35005f76SSean Callanan             error.SetErrorToGenericError();
518*35005f76SSean Callanan             error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %lld", (unsigned long long)size);
519*35005f76SSean Callanan             return;
520*35005f76SSean Callanan         case 1: scalar = extractor.GetU8(&offset);  break;
521*35005f76SSean Callanan         case 2: scalar = extractor.GetU16(&offset); break;
522*35005f76SSean Callanan         case 4: scalar = extractor.GetU32(&offset); break;
523*35005f76SSean Callanan         case 8: scalar = extractor.GetU64(&offset); break;
524*35005f76SSean Callanan         }
525*35005f76SSean Callanan     }
526*35005f76SSean Callanan     else
527*35005f76SSean Callanan     {
528*35005f76SSean Callanan         error.SetErrorToGenericError();
529*35005f76SSean Callanan         error.SetErrorString ("Couldn't write scalar: its size was zero");
530*35005f76SSean Callanan     }
531*35005f76SSean Callanan     return;
532*35005f76SSean Callanan }
533*35005f76SSean Callanan 
534