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 {
24b024d878SSean Callanan     if (target_sp)
25b024d878SSean 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 
64*08052afaSSean 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 
9014b1bae5SSean Callanan     if (iter == m_allocations.end() ||
9114b1bae5SSean Callanan         iter->first > addr)
925a1af4e6SSean Callanan     {
935a1af4e6SSean Callanan         if (iter == m_allocations.begin())
945a1af4e6SSean Callanan             return m_allocations.end();
955a1af4e6SSean Callanan         iter--;
965a1af4e6SSean Callanan     }
975a1af4e6SSean Callanan 
985a1af4e6SSean Callanan     if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
995a1af4e6SSean Callanan         return iter;
1005a1af4e6SSean Callanan 
1015a1af4e6SSean Callanan     return m_allocations.end();
1025a1af4e6SSean Callanan }
1035a1af4e6SSean Callanan 
10435005f76SSean Callanan lldb::ByteOrder
10535005f76SSean Callanan IRMemoryMap::GetByteOrder()
10635005f76SSean Callanan {
10735005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
10835005f76SSean Callanan 
10935005f76SSean Callanan     if (process_sp)
11035005f76SSean Callanan         return process_sp->GetByteOrder();
11135005f76SSean Callanan 
11235005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
11335005f76SSean Callanan 
11435005f76SSean Callanan     if (target_sp)
115*08052afaSSean Callanan         return target_sp->GetArchitecture().GetByteOrder();
11635005f76SSean Callanan 
11735005f76SSean Callanan     return lldb::eByteOrderInvalid;
11835005f76SSean Callanan }
11935005f76SSean Callanan 
12035005f76SSean Callanan uint32_t
12135005f76SSean Callanan IRMemoryMap::GetAddressByteSize()
12235005f76SSean Callanan {
12335005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
12435005f76SSean Callanan 
12535005f76SSean Callanan     if (process_sp)
12635005f76SSean Callanan         return process_sp->GetAddressByteSize();
12735005f76SSean Callanan 
12835005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
12935005f76SSean Callanan 
13035005f76SSean Callanan     if (target_sp)
131*08052afaSSean Callanan         return target_sp->GetArchitecture().GetAddressByteSize();
13235005f76SSean Callanan 
13335005f76SSean Callanan     return UINT32_MAX;
13435005f76SSean Callanan }
13535005f76SSean Callanan 
13635005f76SSean Callanan ExecutionContextScope *
13735005f76SSean Callanan IRMemoryMap::GetBestExecutionContextScope()
13835005f76SSean Callanan {
13935005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
14035005f76SSean Callanan 
14135005f76SSean Callanan     if (process_sp)
14235005f76SSean Callanan         return process_sp.get();
14335005f76SSean Callanan 
14435005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
14535005f76SSean Callanan 
14635005f76SSean Callanan     if (target_sp)
14735005f76SSean Callanan         return target_sp.get();
14835005f76SSean Callanan 
14935005f76SSean Callanan     return NULL;
15035005f76SSean Callanan }
15135005f76SSean Callanan 
1525a1af4e6SSean Callanan lldb::addr_t
1535a1af4e6SSean Callanan IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
1545a1af4e6SSean Callanan {
155*08052afaSSean Callanan     error.Clear();
156*08052afaSSean 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 {
287*08052afaSSean Callanan     error.Clear();
288*08052afaSSean Callanan 
2895a1af4e6SSean Callanan     AllocationMap::iterator iter = m_allocations.find(process_address);
2905a1af4e6SSean Callanan 
2915a1af4e6SSean Callanan     if (iter == m_allocations.end())
2925a1af4e6SSean Callanan     {
2935a1af4e6SSean Callanan         error.SetErrorToGenericError();
2945a1af4e6SSean Callanan         error.SetErrorString("Couldn't free: allocation doesn't exist");
2955a1af4e6SSean Callanan         return;
2965a1af4e6SSean Callanan     }
2975a1af4e6SSean Callanan 
2985a1af4e6SSean Callanan     Allocation &allocation = iter->second;
2995a1af4e6SSean Callanan 
3005a1af4e6SSean Callanan     switch (allocation.m_policy)
3015a1af4e6SSean Callanan     {
3025a1af4e6SSean Callanan     default:
3035a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
3045a1af4e6SSean Callanan         break;
3055a1af4e6SSean Callanan     case eAllocationPolicyMirror:
3065a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
3075a1af4e6SSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
3085a1af4e6SSean Callanan         if (process_sp)
3095a1af4e6SSean Callanan             process_sp->DeallocateMemory(allocation.m_process_alloc);
3105a1af4e6SSean Callanan     }
3115a1af4e6SSean Callanan 
3125a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
3135a1af4e6SSean Callanan     {
3145a1af4e6SSean Callanan         log->Printf("IRMemoryMap::Free (0x%llx) freed [0x%llx..0x%llx)",
3155a1af4e6SSean Callanan                     (uint64_t)process_address,
3165a1af4e6SSean Callanan                     iter->second.m_process_start,
3175a1af4e6SSean Callanan                     iter->second.m_process_start + iter->second.m_size);
3185a1af4e6SSean Callanan     }
3195a1af4e6SSean Callanan 
3205a1af4e6SSean Callanan     m_allocations.erase(iter);
3215a1af4e6SSean Callanan }
3225a1af4e6SSean Callanan 
3235a1af4e6SSean Callanan void
3245a1af4e6SSean Callanan IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
3255a1af4e6SSean Callanan {
326*08052afaSSean Callanan     error.Clear();
327*08052afaSSean Callanan 
3285a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
3295a1af4e6SSean Callanan 
3305a1af4e6SSean Callanan     if (iter == m_allocations.end())
3315a1af4e6SSean Callanan     {
332c8c5b8dcSSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
333c8c5b8dcSSean Callanan 
334c8c5b8dcSSean Callanan         if (process_sp)
335c8c5b8dcSSean Callanan         {
336c8c5b8dcSSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
337c8c5b8dcSSean Callanan             return;
338c8c5b8dcSSean Callanan         }
339c8c5b8dcSSean Callanan 
3405a1af4e6SSean Callanan         error.SetErrorToGenericError();
341c8c5b8dcSSean Callanan         error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
3425a1af4e6SSean Callanan         return;
3435a1af4e6SSean Callanan     }
3445a1af4e6SSean Callanan 
3455a1af4e6SSean Callanan     Allocation &allocation = iter->second;
3465a1af4e6SSean Callanan 
3475a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
3485a1af4e6SSean Callanan 
3495a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
3505a1af4e6SSean Callanan 
3515a1af4e6SSean Callanan     switch (allocation.m_policy)
3525a1af4e6SSean Callanan     {
3535a1af4e6SSean Callanan     default:
3545a1af4e6SSean Callanan         error.SetErrorToGenericError();
3555a1af4e6SSean Callanan         error.SetErrorString("Couldn't write: invalid allocation policy");
3565a1af4e6SSean Callanan         return;
3575a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
3585a1af4e6SSean Callanan         if (!allocation.m_data)
3595a1af4e6SSean Callanan         {
3605a1af4e6SSean Callanan             error.SetErrorToGenericError();
3615a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
3625a1af4e6SSean Callanan             return;
3635a1af4e6SSean Callanan         }
3645a1af4e6SSean Callanan         ::memcpy (allocation.m_data->GetBytes() + offset, bytes, size);
3655a1af4e6SSean Callanan         break;
3665a1af4e6SSean Callanan     case eAllocationPolicyMirror:
3675a1af4e6SSean Callanan         if (!allocation.m_data)
3685a1af4e6SSean Callanan         {
3695a1af4e6SSean Callanan             error.SetErrorToGenericError();
3705a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
3715a1af4e6SSean Callanan             return;
3725a1af4e6SSean Callanan         }
3735a1af4e6SSean Callanan         ::memcpy (allocation.m_data->GetBytes() + offset, bytes, size);
3745a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
3755a1af4e6SSean Callanan         if (process_sp)
3765a1af4e6SSean Callanan         {
3775a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
3785a1af4e6SSean Callanan             if (!error.Success())
3795a1af4e6SSean Callanan                 return;
3805a1af4e6SSean Callanan         }
3815a1af4e6SSean Callanan         break;
3825a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
3835a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
3845a1af4e6SSean Callanan         if (process_sp)
3855a1af4e6SSean Callanan         {
3865a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
3875a1af4e6SSean Callanan             if (!error.Success())
3885a1af4e6SSean Callanan                 return;
3895a1af4e6SSean Callanan         }
3905a1af4e6SSean Callanan         break;
3915a1af4e6SSean Callanan     }
3925a1af4e6SSean Callanan 
3935a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
3945a1af4e6SSean Callanan     {
3955a1af4e6SSean Callanan         log->Printf("IRMemoryMap::WriteMemory (0x%llx, 0x%llx, 0x%lld) went to [0x%llx..0x%llx)",
3965a1af4e6SSean Callanan                     (uint64_t)process_address,
3975a1af4e6SSean Callanan                     (uint64_t)bytes,
3985a1af4e6SSean Callanan                     (uint64_t)size,
3995a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
4005a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
4015a1af4e6SSean Callanan     }
4025a1af4e6SSean Callanan }
4035a1af4e6SSean Callanan 
4045a1af4e6SSean Callanan void
40535005f76SSean Callanan IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
40635005f76SSean Callanan {
407*08052afaSSean Callanan     error.Clear();
408*08052afaSSean Callanan 
40935005f76SSean Callanan     if (size == UINT32_MAX)
41035005f76SSean Callanan         size = scalar.GetByteSize();
41135005f76SSean Callanan 
41235005f76SSean Callanan     if (size > 0)
41335005f76SSean Callanan     {
41435005f76SSean Callanan         uint8_t buf[32];
41535005f76SSean Callanan         const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
41635005f76SSean Callanan         if (mem_size > 0)
41735005f76SSean Callanan         {
41835005f76SSean Callanan             return WriteMemory(process_address, buf, mem_size, error);
41935005f76SSean Callanan         }
42035005f76SSean Callanan         else
42135005f76SSean Callanan         {
42235005f76SSean Callanan             error.SetErrorToGenericError();
42335005f76SSean Callanan             error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
42435005f76SSean Callanan         }
42535005f76SSean Callanan     }
42635005f76SSean Callanan     else
42735005f76SSean Callanan     {
42835005f76SSean Callanan         error.SetErrorToGenericError();
42935005f76SSean Callanan         error.SetErrorString ("Couldn't write scalar: its size was zero");
43035005f76SSean Callanan     }
43135005f76SSean Callanan     return;
43235005f76SSean Callanan }
43335005f76SSean Callanan 
43435005f76SSean Callanan void
435f8043fa5SSean Callanan IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
436f8043fa5SSean Callanan {
437*08052afaSSean Callanan     error.Clear();
438*08052afaSSean Callanan 
439f8043fa5SSean Callanan     Scalar scalar(address);
440f8043fa5SSean Callanan 
441f8043fa5SSean Callanan     WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
442f8043fa5SSean Callanan }
443f8043fa5SSean Callanan 
444f8043fa5SSean Callanan void
4455a1af4e6SSean Callanan IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
4465a1af4e6SSean Callanan {
447*08052afaSSean Callanan     error.Clear();
448*08052afaSSean Callanan 
4495a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
4505a1af4e6SSean Callanan 
4515a1af4e6SSean Callanan     if (iter == m_allocations.end())
4525a1af4e6SSean Callanan     {
453c8c5b8dcSSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
454c8c5b8dcSSean Callanan 
455c8c5b8dcSSean Callanan         if (process_sp)
456c8c5b8dcSSean Callanan         {
457c8c5b8dcSSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
458c8c5b8dcSSean Callanan             return;
459c8c5b8dcSSean Callanan         }
460c8c5b8dcSSean Callanan 
461c8c5b8dcSSean Callanan         lldb::TargetSP target_sp = m_target_wp.lock();
462c8c5b8dcSSean Callanan 
463c8c5b8dcSSean Callanan         if (target_sp)
464c8c5b8dcSSean Callanan         {
465c8c5b8dcSSean Callanan             Address absolute_address(process_address);
466c8c5b8dcSSean Callanan             target_sp->ReadMemory(absolute_address, false, bytes, size, error);
467c8c5b8dcSSean Callanan             return;
468c8c5b8dcSSean Callanan         }
469c8c5b8dcSSean Callanan 
4705a1af4e6SSean Callanan         error.SetErrorToGenericError();
471c8c5b8dcSSean Callanan         error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist");
4725a1af4e6SSean Callanan         return;
4735a1af4e6SSean Callanan     }
4745a1af4e6SSean Callanan 
4755a1af4e6SSean Callanan     Allocation &allocation = iter->second;
4765a1af4e6SSean Callanan 
4775a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
4785a1af4e6SSean Callanan 
4795a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
4805a1af4e6SSean Callanan 
4815a1af4e6SSean Callanan     switch (allocation.m_policy)
4825a1af4e6SSean Callanan     {
4835a1af4e6SSean Callanan     default:
4845a1af4e6SSean Callanan         error.SetErrorToGenericError();
4855a1af4e6SSean Callanan         error.SetErrorString("Couldn't read: invalid allocation policy");
4865a1af4e6SSean Callanan         return;
4875a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
4885a1af4e6SSean Callanan         if (!allocation.m_data)
4895a1af4e6SSean Callanan         {
4905a1af4e6SSean Callanan             error.SetErrorToGenericError();
4915a1af4e6SSean Callanan             error.SetErrorString("Couldn't read: data buffer is empty");
4925a1af4e6SSean Callanan             return;
4935a1af4e6SSean Callanan         }
4945a1af4e6SSean Callanan         ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
4955a1af4e6SSean Callanan         break;
4965a1af4e6SSean Callanan     case eAllocationPolicyMirror:
4975a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
4985a1af4e6SSean Callanan         if (process_sp)
4995a1af4e6SSean Callanan         {
5005a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
5015a1af4e6SSean Callanan             if (!error.Success())
5025a1af4e6SSean Callanan                 return;
5035a1af4e6SSean Callanan         }
5045a1af4e6SSean Callanan         else
5055a1af4e6SSean Callanan         {
5065a1af4e6SSean Callanan             if (!allocation.m_data)
5075a1af4e6SSean Callanan             {
5085a1af4e6SSean Callanan                 error.SetErrorToGenericError();
5095a1af4e6SSean Callanan                 error.SetErrorString("Couldn't read: data buffer is empty");
5105a1af4e6SSean Callanan                 return;
5115a1af4e6SSean Callanan             }
5125a1af4e6SSean Callanan             ::memcpy (bytes, allocation.m_data->GetBytes() + offset, size);
5135a1af4e6SSean Callanan         }
5145a1af4e6SSean Callanan         break;
5155a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
5165a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
5175a1af4e6SSean Callanan         if (process_sp)
5185a1af4e6SSean Callanan         {
5195a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
5205a1af4e6SSean Callanan             if (!error.Success())
5215a1af4e6SSean Callanan                 return;
5225a1af4e6SSean Callanan         }
5235a1af4e6SSean Callanan         break;
5245a1af4e6SSean Callanan     }
5255a1af4e6SSean Callanan 
5265a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
5275a1af4e6SSean Callanan     {
5285a1af4e6SSean Callanan         log->Printf("IRMemoryMap::ReadMemory (0x%llx, 0x%llx, 0x%lld) came from [0x%llx..0x%llx)",
5295a1af4e6SSean Callanan                     (uint64_t)process_address,
5305a1af4e6SSean Callanan                     (uint64_t)bytes,
5315a1af4e6SSean Callanan                     (uint64_t)size,
5325a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
5335a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
5345a1af4e6SSean Callanan     }
5355a1af4e6SSean Callanan }
53635005f76SSean Callanan 
53735005f76SSean Callanan void
53835005f76SSean Callanan IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
53935005f76SSean Callanan {
540*08052afaSSean Callanan     error.Clear();
541*08052afaSSean Callanan 
54235005f76SSean Callanan     if (size > 0)
54335005f76SSean Callanan     {
54435005f76SSean Callanan         DataBufferHeap buf(size, 0);
54535005f76SSean Callanan         ReadMemory(buf.GetBytes(), process_address, size, error);
54635005f76SSean Callanan 
54735005f76SSean Callanan         if (!error.Success())
54835005f76SSean Callanan             return;
54935005f76SSean Callanan 
55035005f76SSean Callanan         DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
55135005f76SSean Callanan 
55235005f76SSean Callanan         lldb::offset_t offset = 0;
55335005f76SSean Callanan 
55435005f76SSean Callanan         switch (size)
55535005f76SSean Callanan         {
55635005f76SSean Callanan         default:
55735005f76SSean Callanan             error.SetErrorToGenericError();
55835005f76SSean Callanan             error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %lld", (unsigned long long)size);
55935005f76SSean Callanan             return;
56035005f76SSean Callanan         case 1: scalar = extractor.GetU8(&offset);  break;
56135005f76SSean Callanan         case 2: scalar = extractor.GetU16(&offset); break;
56235005f76SSean Callanan         case 4: scalar = extractor.GetU32(&offset); break;
56335005f76SSean Callanan         case 8: scalar = extractor.GetU64(&offset); break;
56435005f76SSean Callanan         }
56535005f76SSean Callanan     }
56635005f76SSean Callanan     else
56735005f76SSean Callanan     {
56835005f76SSean Callanan         error.SetErrorToGenericError();
569458ae1c6SSean Callanan         error.SetErrorString ("Couldn't read scalar: its size was zero");
57035005f76SSean Callanan     }
57135005f76SSean Callanan     return;
57235005f76SSean Callanan }
57335005f76SSean Callanan 
574458ae1c6SSean Callanan void
5752d37e5a5SSean Callanan IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
5762d37e5a5SSean Callanan {
577*08052afaSSean Callanan     error.Clear();
578*08052afaSSean Callanan 
5792d37e5a5SSean Callanan     Scalar pointer_scalar;
5802d37e5a5SSean Callanan     ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
5812d37e5a5SSean Callanan 
5822d37e5a5SSean Callanan     if (!error.Success())
5832d37e5a5SSean Callanan         return;
5842d37e5a5SSean Callanan 
5852d37e5a5SSean Callanan     *address = pointer_scalar.ULongLong();
5862d37e5a5SSean Callanan 
5872d37e5a5SSean Callanan     return;
5882d37e5a5SSean Callanan }
5892d37e5a5SSean Callanan 
5902d37e5a5SSean Callanan void
591458ae1c6SSean Callanan IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
592458ae1c6SSean Callanan {
593*08052afaSSean Callanan     error.Clear();
594*08052afaSSean Callanan 
595458ae1c6SSean Callanan     if (size > 0)
596458ae1c6SSean Callanan     {
597458ae1c6SSean Callanan         AllocationMap::iterator iter = FindAllocation(process_address, size);
598458ae1c6SSean Callanan 
599458ae1c6SSean Callanan         if (iter == m_allocations.end())
600458ae1c6SSean Callanan         {
601458ae1c6SSean Callanan             error.SetErrorToGenericError();
602458ae1c6SSean Callanan             error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%llx..0x%llx)", (unsigned long long)process_address, (unsigned long long)(process_address + size));
603458ae1c6SSean Callanan             return;
604458ae1c6SSean Callanan         }
605458ae1c6SSean Callanan 
606458ae1c6SSean Callanan         Allocation &allocation = iter->second;
607458ae1c6SSean Callanan 
608458ae1c6SSean Callanan         switch (allocation.m_policy)
609458ae1c6SSean Callanan         {
610458ae1c6SSean Callanan         default:
611458ae1c6SSean Callanan             error.SetErrorToGenericError();
612458ae1c6SSean Callanan             error.SetErrorString("Couldn't get memory data: invalid allocation policy");
613458ae1c6SSean Callanan             return;
614458ae1c6SSean Callanan         case eAllocationPolicyProcessOnly:
615458ae1c6SSean Callanan             error.SetErrorToGenericError();
616458ae1c6SSean Callanan             error.SetErrorString("Couldn't get memory data: memory is only in the target");
617458ae1c6SSean Callanan             return;
618458ae1c6SSean Callanan         case eAllocationPolicyMirror:
619c8c5b8dcSSean Callanan             {
620c8c5b8dcSSean Callanan                 lldb::ProcessSP process_sp = m_process_wp.lock();
621c8c5b8dcSSean Callanan 
622c8c5b8dcSSean Callanan                 if (!allocation.m_data.get())
623c8c5b8dcSSean Callanan                 {
624c8c5b8dcSSean Callanan                     error.SetErrorToGenericError();
625c8c5b8dcSSean Callanan                     error.SetErrorString("Couldn't get memory data: data buffer is empty");
626c8c5b8dcSSean Callanan                     return;
627c8c5b8dcSSean Callanan                 }
628c8c5b8dcSSean Callanan                 if (process_sp)
629c8c5b8dcSSean Callanan                 {
630c8c5b8dcSSean Callanan                     process_sp->ReadMemory(allocation.m_process_start, allocation.m_data->GetBytes(), allocation.m_data->GetByteSize(), error);
631c8c5b8dcSSean Callanan                     if (!error.Success())
632c8c5b8dcSSean Callanan                         return;
633c8c5b8dcSSean Callanan                     uint64_t offset = process_address - allocation.m_process_start;
634c8c5b8dcSSean Callanan                     extractor = DataExtractor(allocation.m_data->GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
635c8c5b8dcSSean Callanan                     return;
636c8c5b8dcSSean Callanan                 }
637c8c5b8dcSSean Callanan             }
638c8c5b8dcSSean Callanan         case eAllocationPolicyHostOnly:
639458ae1c6SSean Callanan             if (!allocation.m_data.get())
640458ae1c6SSean Callanan             {
641458ae1c6SSean Callanan                 error.SetErrorToGenericError();
642458ae1c6SSean Callanan                 error.SetErrorString("Couldn't get memory data: data buffer is empty");
643458ae1c6SSean Callanan                 return;
644458ae1c6SSean Callanan             }
645458ae1c6SSean Callanan             uint64_t offset = process_address - allocation.m_process_start;
646458ae1c6SSean Callanan             extractor = DataExtractor(allocation.m_data->GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
647458ae1c6SSean Callanan             return;
648458ae1c6SSean Callanan         }
649458ae1c6SSean Callanan     }
650458ae1c6SSean Callanan     else
651458ae1c6SSean Callanan     {
652458ae1c6SSean Callanan         error.SetErrorToGenericError();
653458ae1c6SSean Callanan         error.SetErrorString ("Couldn't get memory data: its size was zero");
654458ae1c6SSean Callanan         return;
655458ae1c6SSean Callanan     }
656458ae1c6SSean Callanan }
657458ae1c6SSean Callanan 
658458ae1c6SSean Callanan 
659