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 {
53*bb9945f4SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
54*bb9945f4SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
555a1af4e6SSean Callanan 
56*bb9945f4SSean Callanan     lldb::addr_t ret = LLDB_INVALID_ADDRESS;
575a1af4e6SSean Callanan 
58*bb9945f4SSean Callanan     for (int iterations = 0; iterations < 16; ++iterations)
595a1af4e6SSean Callanan     {
60*bb9945f4SSean Callanan         lldb::addr_t candidate;
615a1af4e6SSean Callanan 
62*bb9945f4SSean Callanan         switch (target_sp->GetArchitecture().GetAddressByteSize())
63*bb9945f4SSean Callanan         {
64*bb9945f4SSean Callanan         case 4:
65*bb9945f4SSean Callanan             {
66*bb9945f4SSean Callanan                 uint32_t random_data = random();
67*bb9945f4SSean Callanan                 candidate = random_data;
68*bb9945f4SSean Callanan                 candidate &= ~0xfffull;
69*bb9945f4SSean Callanan                 break;
70*bb9945f4SSean Callanan             }
71*bb9945f4SSean Callanan         case 8:
72*bb9945f4SSean Callanan             {
73*bb9945f4SSean Callanan                 uint32_t random_low = random();
74*bb9945f4SSean Callanan                 uint32_t random_high = random();
75*bb9945f4SSean Callanan                 candidate = random_high;
76*bb9945f4SSean Callanan                 candidate <<= 32ull;
77*bb9945f4SSean Callanan                 candidate |= random_low;
78*bb9945f4SSean Callanan                 candidate &= ~0xfffull;
79*bb9945f4SSean Callanan                 break;
80*bb9945f4SSean Callanan             }
815a1af4e6SSean Callanan         }
825a1af4e6SSean Callanan 
83*bb9945f4SSean Callanan         if (IntersectsAllocation(candidate, size))
84*bb9945f4SSean Callanan             continue;
855a1af4e6SSean Callanan 
86*bb9945f4SSean Callanan         char buf[1];
87*bb9945f4SSean Callanan 
88*bb9945f4SSean Callanan         Error err;
89*bb9945f4SSean Callanan 
90*bb9945f4SSean Callanan         if (process_sp &&
91*bb9945f4SSean Callanan             (process_sp->ReadMemory(candidate, buf, 1, err) == 1 ||
92*bb9945f4SSean Callanan              process_sp->ReadMemory(candidate + size, buf, 1, err) == 1))
93*bb9945f4SSean Callanan             continue;
94*bb9945f4SSean Callanan 
95*bb9945f4SSean Callanan         ret = candidate;
965a1af4e6SSean Callanan     }
975a1af4e6SSean Callanan 
98*bb9945f4SSean Callanan     return ret;
995a1af4e6SSean Callanan }
1005a1af4e6SSean Callanan 
1015a1af4e6SSean Callanan IRMemoryMap::AllocationMap::iterator
1025a1af4e6SSean Callanan IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
1035a1af4e6SSean Callanan {
1041582ee68SSean Callanan     if (addr == LLDB_INVALID_ADDRESS)
1051582ee68SSean Callanan         return m_allocations.end();
1061582ee68SSean Callanan 
1075a1af4e6SSean Callanan     AllocationMap::iterator iter = m_allocations.lower_bound (addr);
1085a1af4e6SSean Callanan 
10914b1bae5SSean Callanan     if (iter == m_allocations.end() ||
11014b1bae5SSean Callanan         iter->first > addr)
1115a1af4e6SSean Callanan     {
1125a1af4e6SSean Callanan         if (iter == m_allocations.begin())
1135a1af4e6SSean Callanan             return m_allocations.end();
1145a1af4e6SSean Callanan         iter--;
1155a1af4e6SSean Callanan     }
1165a1af4e6SSean Callanan 
1175a1af4e6SSean Callanan     if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
1185a1af4e6SSean Callanan         return iter;
1195a1af4e6SSean Callanan 
1205a1af4e6SSean Callanan     return m_allocations.end();
1215a1af4e6SSean Callanan }
1225a1af4e6SSean Callanan 
123*bb9945f4SSean Callanan bool
124*bb9945f4SSean Callanan IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size)
125*bb9945f4SSean Callanan {
126*bb9945f4SSean Callanan     if (addr == LLDB_INVALID_ADDRESS)
127*bb9945f4SSean Callanan         return false;
128*bb9945f4SSean Callanan 
129*bb9945f4SSean Callanan     AllocationMap::iterator iter = m_allocations.lower_bound (addr);
130*bb9945f4SSean Callanan 
131*bb9945f4SSean Callanan     if (iter == m_allocations.end() ||
132*bb9945f4SSean Callanan         iter->first > addr)
133*bb9945f4SSean Callanan     {
134*bb9945f4SSean Callanan         if (iter == m_allocations.begin())
135*bb9945f4SSean Callanan             return false;
136*bb9945f4SSean Callanan 
137*bb9945f4SSean Callanan         iter--;
138*bb9945f4SSean Callanan     }
139*bb9945f4SSean Callanan 
140*bb9945f4SSean Callanan     while (iter != m_allocations.end() && iter->second.m_process_alloc < addr + size)
141*bb9945f4SSean Callanan     {
142*bb9945f4SSean Callanan         if (iter->second.m_process_start + iter->second.m_size > addr)
143*bb9945f4SSean Callanan             return true;
144*bb9945f4SSean Callanan 
145*bb9945f4SSean Callanan         ++iter;
146*bb9945f4SSean Callanan     }
147*bb9945f4SSean Callanan 
148*bb9945f4SSean Callanan     return false;
149*bb9945f4SSean Callanan }
150*bb9945f4SSean Callanan 
15135005f76SSean Callanan lldb::ByteOrder
15235005f76SSean Callanan IRMemoryMap::GetByteOrder()
15335005f76SSean Callanan {
15435005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
15535005f76SSean Callanan 
15635005f76SSean Callanan     if (process_sp)
15735005f76SSean Callanan         return process_sp->GetByteOrder();
15835005f76SSean Callanan 
15935005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
16035005f76SSean Callanan 
16135005f76SSean Callanan     if (target_sp)
16208052afaSSean Callanan         return target_sp->GetArchitecture().GetByteOrder();
16335005f76SSean Callanan 
16435005f76SSean Callanan     return lldb::eByteOrderInvalid;
16535005f76SSean Callanan }
16635005f76SSean Callanan 
16735005f76SSean Callanan uint32_t
16835005f76SSean Callanan IRMemoryMap::GetAddressByteSize()
16935005f76SSean Callanan {
17035005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
17135005f76SSean Callanan 
17235005f76SSean Callanan     if (process_sp)
17335005f76SSean Callanan         return process_sp->GetAddressByteSize();
17435005f76SSean Callanan 
17535005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
17635005f76SSean Callanan 
17735005f76SSean Callanan     if (target_sp)
17808052afaSSean Callanan         return target_sp->GetArchitecture().GetAddressByteSize();
17935005f76SSean Callanan 
18035005f76SSean Callanan     return UINT32_MAX;
18135005f76SSean Callanan }
18235005f76SSean Callanan 
18335005f76SSean Callanan ExecutionContextScope *
18435005f76SSean Callanan IRMemoryMap::GetBestExecutionContextScope()
18535005f76SSean Callanan {
18635005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
18735005f76SSean Callanan 
18835005f76SSean Callanan     if (process_sp)
18935005f76SSean Callanan         return process_sp.get();
19035005f76SSean Callanan 
19135005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
19235005f76SSean Callanan 
19335005f76SSean Callanan     if (target_sp)
19435005f76SSean Callanan         return target_sp.get();
19535005f76SSean Callanan 
19635005f76SSean Callanan     return NULL;
19735005f76SSean Callanan }
19835005f76SSean Callanan 
1995a1af4e6SSean Callanan lldb::addr_t
2005a1af4e6SSean Callanan IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
2015a1af4e6SSean Callanan {
20208052afaSSean Callanan     error.Clear();
20308052afaSSean Callanan 
2045a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
2055a1af4e6SSean Callanan     lldb::addr_t    allocation_address  = LLDB_INVALID_ADDRESS;
2065a1af4e6SSean Callanan     lldb::addr_t    aligned_address     = LLDB_INVALID_ADDRESS;
2075a1af4e6SSean Callanan 
2085a1af4e6SSean Callanan     size_t          allocation_size = (size ? size : 1) + alignment - 1;
2095a1af4e6SSean Callanan 
2105a1af4e6SSean Callanan     switch (policy)
2115a1af4e6SSean Callanan     {
2125a1af4e6SSean Callanan     default:
2135a1af4e6SSean Callanan         error.SetErrorToGenericError();
2145a1af4e6SSean Callanan         error.SetErrorString("Couldn't malloc: invalid allocation policy");
2155a1af4e6SSean Callanan         return LLDB_INVALID_ADDRESS;
2165a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
2175a1af4e6SSean Callanan         allocation_address = FindSpace(allocation_size);
2185a1af4e6SSean Callanan         if (allocation_address == LLDB_INVALID_ADDRESS)
2195a1af4e6SSean Callanan         {
2205a1af4e6SSean Callanan             error.SetErrorToGenericError();
2215a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: address space is full");
2225a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
2235a1af4e6SSean Callanan         }
2245a1af4e6SSean Callanan         break;
2255a1af4e6SSean Callanan     case eAllocationPolicyMirror:
2265a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
227*bb9945f4SSean Callanan         if (process_sp && process_sp->CanJIT())
2285a1af4e6SSean Callanan         {
2295a1af4e6SSean Callanan             allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
2305a1af4e6SSean Callanan             if (!error.Success())
2315a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
2325a1af4e6SSean Callanan         }
2335a1af4e6SSean Callanan         else
2345a1af4e6SSean Callanan         {
235*bb9945f4SSean Callanan             policy = eAllocationPolicyHostOnly;
2365a1af4e6SSean Callanan             allocation_address = FindSpace(allocation_size);
2375a1af4e6SSean Callanan             if (allocation_address == LLDB_INVALID_ADDRESS)
2385a1af4e6SSean Callanan             {
2395a1af4e6SSean Callanan                 error.SetErrorToGenericError();
2405a1af4e6SSean Callanan                 error.SetErrorString("Couldn't malloc: address space is full");
2415a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
2425a1af4e6SSean Callanan             }
2435a1af4e6SSean Callanan         }
2445a1af4e6SSean Callanan         break;
2455a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
2465a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
2475a1af4e6SSean Callanan         if (process_sp)
2485a1af4e6SSean Callanan         {
249*bb9945f4SSean Callanan             if (process_sp->CanJIT())
250*bb9945f4SSean Callanan             {
2515a1af4e6SSean Callanan                 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
2525a1af4e6SSean Callanan                 if (!error.Success())
2535a1af4e6SSean Callanan                     return LLDB_INVALID_ADDRESS;
2545a1af4e6SSean Callanan             }
2555a1af4e6SSean Callanan             else
2565a1af4e6SSean Callanan             {
2575a1af4e6SSean Callanan                 error.SetErrorToGenericError();
258*bb9945f4SSean Callanan                 error.SetErrorString("Couldn't malloc: process doesn't support allocating memory");
259*bb9945f4SSean Callanan                 return LLDB_INVALID_ADDRESS;
260*bb9945f4SSean Callanan             }
261*bb9945f4SSean Callanan         }
262*bb9945f4SSean Callanan         else
263*bb9945f4SSean Callanan         {
264*bb9945f4SSean Callanan             error.SetErrorToGenericError();
2655a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
2665a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
2675a1af4e6SSean Callanan         }
2685a1af4e6SSean Callanan         break;
2695a1af4e6SSean Callanan     }
2705a1af4e6SSean Callanan 
2715a1af4e6SSean Callanan 
2725a1af4e6SSean Callanan     lldb::addr_t mask = alignment - 1;
2735a1af4e6SSean Callanan     aligned_address = (allocation_address + mask) & (~mask);
2745a1af4e6SSean Callanan 
275d850685eSGreg Clayton     Allocation allocation;
2765a1af4e6SSean Callanan 
2775a1af4e6SSean Callanan     allocation.m_process_alloc = allocation_address;
2785a1af4e6SSean Callanan     allocation.m_process_start = aligned_address;
2795a1af4e6SSean Callanan     allocation.m_size = size;
2805a1af4e6SSean Callanan     allocation.m_permissions = permissions;
2815a1af4e6SSean Callanan     allocation.m_alignment = alignment;
2825a1af4e6SSean Callanan     allocation.m_policy = policy;
2835a1af4e6SSean Callanan 
284d850685eSGreg Clayton     m_allocations[aligned_address] = std::move(allocation);
285d850685eSGreg Clayton 
2865a1af4e6SSean Callanan     switch (policy)
2875a1af4e6SSean Callanan     {
2885a1af4e6SSean Callanan     default:
2895a1af4e6SSean Callanan         assert (0 && "We cannot reach this!");
2905a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
291e0c64e15SGreg Clayton         allocation.m_data_ap.reset(new DataBufferHeap(size, 0));
2925a1af4e6SSean Callanan         break;
2935a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
2945a1af4e6SSean Callanan         break;
2955a1af4e6SSean Callanan     case eAllocationPolicyMirror:
296e0c64e15SGreg Clayton         allocation.m_data_ap.reset(new DataBufferHeap(size, 0));
2975a1af4e6SSean Callanan         break;
2985a1af4e6SSean Callanan     }
2995a1af4e6SSean Callanan 
3005a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
3015a1af4e6SSean Callanan     {
3025a1af4e6SSean Callanan         const char * policy_string;
3035a1af4e6SSean Callanan 
3045a1af4e6SSean Callanan         switch (policy)
3055a1af4e6SSean Callanan         {
3065a1af4e6SSean Callanan         default:
3075a1af4e6SSean Callanan             policy_string = "<invalid policy>";
3085a1af4e6SSean Callanan             break;
3095a1af4e6SSean Callanan         case eAllocationPolicyHostOnly:
3105a1af4e6SSean Callanan             policy_string = "eAllocationPolicyHostOnly";
3115a1af4e6SSean Callanan             break;
3125a1af4e6SSean Callanan         case eAllocationPolicyProcessOnly:
3135a1af4e6SSean Callanan             policy_string = "eAllocationPolicyProcessOnly";
3145a1af4e6SSean Callanan             break;
3155a1af4e6SSean Callanan         case eAllocationPolicyMirror:
3165a1af4e6SSean Callanan             policy_string = "eAllocationPolicyMirror";
3175a1af4e6SSean Callanan             break;
3185a1af4e6SSean Callanan         }
3195a1af4e6SSean Callanan 
3205a1af4e6SSean Callanan         log->Printf("IRMemoryMap::Malloc (%llu, 0x%llx, 0x%llx, %s) -> 0x%llx",
3215a1af4e6SSean Callanan                     (uint64_t)size,
3225a1af4e6SSean Callanan                     (uint64_t)alignment,
3235a1af4e6SSean Callanan                     (uint64_t)permissions,
3245a1af4e6SSean Callanan                     policy_string,
3255a1af4e6SSean Callanan                     aligned_address);
3265a1af4e6SSean Callanan     }
3275a1af4e6SSean Callanan 
3285a1af4e6SSean Callanan     return aligned_address;
3295a1af4e6SSean Callanan }
3305a1af4e6SSean Callanan 
3315a1af4e6SSean Callanan void
3325a1af4e6SSean Callanan IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
3335a1af4e6SSean Callanan {
33408052afaSSean Callanan     error.Clear();
33508052afaSSean Callanan 
3365a1af4e6SSean Callanan     AllocationMap::iterator iter = m_allocations.find(process_address);
3375a1af4e6SSean Callanan 
3385a1af4e6SSean Callanan     if (iter == m_allocations.end())
3395a1af4e6SSean Callanan     {
3405a1af4e6SSean Callanan         error.SetErrorToGenericError();
3415a1af4e6SSean Callanan         error.SetErrorString("Couldn't free: allocation doesn't exist");
3425a1af4e6SSean Callanan         return;
3435a1af4e6SSean Callanan     }
3445a1af4e6SSean Callanan 
3455a1af4e6SSean Callanan     Allocation &allocation = iter->second;
3465a1af4e6SSean Callanan 
3475a1af4e6SSean Callanan     switch (allocation.m_policy)
3485a1af4e6SSean Callanan     {
3495a1af4e6SSean Callanan     default:
3505a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
3515a1af4e6SSean Callanan         break;
3525a1af4e6SSean Callanan     case eAllocationPolicyMirror:
3535a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
3545a1af4e6SSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
3555a1af4e6SSean Callanan         if (process_sp)
3565a1af4e6SSean Callanan             process_sp->DeallocateMemory(allocation.m_process_alloc);
3575a1af4e6SSean Callanan     }
3585a1af4e6SSean Callanan 
3595a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
3605a1af4e6SSean Callanan     {
3615a1af4e6SSean Callanan         log->Printf("IRMemoryMap::Free (0x%llx) freed [0x%llx..0x%llx)",
3625a1af4e6SSean Callanan                     (uint64_t)process_address,
3635a1af4e6SSean Callanan                     iter->second.m_process_start,
3645a1af4e6SSean Callanan                     iter->second.m_process_start + iter->second.m_size);
3655a1af4e6SSean Callanan     }
3665a1af4e6SSean Callanan 
3675a1af4e6SSean Callanan     m_allocations.erase(iter);
3685a1af4e6SSean Callanan }
3695a1af4e6SSean Callanan 
3705a1af4e6SSean Callanan void
3715a1af4e6SSean Callanan IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
3725a1af4e6SSean Callanan {
37308052afaSSean Callanan     error.Clear();
37408052afaSSean Callanan 
3755a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
3765a1af4e6SSean Callanan 
3775a1af4e6SSean Callanan     if (iter == m_allocations.end())
3785a1af4e6SSean Callanan     {
379c8c5b8dcSSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
380c8c5b8dcSSean Callanan 
381c8c5b8dcSSean Callanan         if (process_sp)
382c8c5b8dcSSean Callanan         {
383c8c5b8dcSSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
384c8c5b8dcSSean Callanan             return;
385c8c5b8dcSSean Callanan         }
386c8c5b8dcSSean Callanan 
3875a1af4e6SSean Callanan         error.SetErrorToGenericError();
388c8c5b8dcSSean Callanan         error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
3895a1af4e6SSean Callanan         return;
3905a1af4e6SSean Callanan     }
3915a1af4e6SSean Callanan 
3925a1af4e6SSean Callanan     Allocation &allocation = iter->second;
3935a1af4e6SSean Callanan 
3945a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
3955a1af4e6SSean Callanan 
3965a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
3975a1af4e6SSean Callanan 
3985a1af4e6SSean Callanan     switch (allocation.m_policy)
3995a1af4e6SSean Callanan     {
4005a1af4e6SSean Callanan     default:
4015a1af4e6SSean Callanan         error.SetErrorToGenericError();
4025a1af4e6SSean Callanan         error.SetErrorString("Couldn't write: invalid allocation policy");
4035a1af4e6SSean Callanan         return;
4045a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
405e0c64e15SGreg Clayton         if (!allocation.m_data_ap.get())
4065a1af4e6SSean Callanan         {
4075a1af4e6SSean Callanan             error.SetErrorToGenericError();
4085a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
4095a1af4e6SSean Callanan             return;
4105a1af4e6SSean Callanan         }
411e0c64e15SGreg Clayton         ::memcpy (allocation.m_data_ap->GetBytes() + offset, bytes, size);
4125a1af4e6SSean Callanan         break;
4135a1af4e6SSean Callanan     case eAllocationPolicyMirror:
414e0c64e15SGreg Clayton         if (!allocation.m_data_ap.get())
4155a1af4e6SSean Callanan         {
4165a1af4e6SSean Callanan             error.SetErrorToGenericError();
4175a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
4185a1af4e6SSean Callanan             return;
4195a1af4e6SSean Callanan         }
420e0c64e15SGreg Clayton         ::memcpy (allocation.m_data_ap->GetBytes() + offset, bytes, size);
4215a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
4225a1af4e6SSean Callanan         if (process_sp)
4235a1af4e6SSean Callanan         {
4245a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
4255a1af4e6SSean Callanan             if (!error.Success())
4265a1af4e6SSean Callanan                 return;
4275a1af4e6SSean Callanan         }
4285a1af4e6SSean Callanan         break;
4295a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
4305a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
4315a1af4e6SSean Callanan         if (process_sp)
4325a1af4e6SSean Callanan         {
4335a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
4345a1af4e6SSean Callanan             if (!error.Success())
4355a1af4e6SSean Callanan                 return;
4365a1af4e6SSean Callanan         }
4375a1af4e6SSean Callanan         break;
4385a1af4e6SSean Callanan     }
4395a1af4e6SSean Callanan 
4405a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
4415a1af4e6SSean Callanan     {
4425a1af4e6SSean Callanan         log->Printf("IRMemoryMap::WriteMemory (0x%llx, 0x%llx, 0x%lld) went to [0x%llx..0x%llx)",
4435a1af4e6SSean Callanan                     (uint64_t)process_address,
4445a1af4e6SSean Callanan                     (uint64_t)bytes,
4455a1af4e6SSean Callanan                     (uint64_t)size,
4465a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
4475a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
4485a1af4e6SSean Callanan     }
4495a1af4e6SSean Callanan }
4505a1af4e6SSean Callanan 
4515a1af4e6SSean Callanan void
45235005f76SSean Callanan IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
45335005f76SSean Callanan {
45408052afaSSean Callanan     error.Clear();
45508052afaSSean Callanan 
45635005f76SSean Callanan     if (size == UINT32_MAX)
45735005f76SSean Callanan         size = scalar.GetByteSize();
45835005f76SSean Callanan 
45935005f76SSean Callanan     if (size > 0)
46035005f76SSean Callanan     {
46135005f76SSean Callanan         uint8_t buf[32];
46235005f76SSean Callanan         const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
46335005f76SSean Callanan         if (mem_size > 0)
46435005f76SSean Callanan         {
46535005f76SSean Callanan             return WriteMemory(process_address, buf, mem_size, error);
46635005f76SSean Callanan         }
46735005f76SSean Callanan         else
46835005f76SSean Callanan         {
46935005f76SSean Callanan             error.SetErrorToGenericError();
47035005f76SSean Callanan             error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
47135005f76SSean Callanan         }
47235005f76SSean Callanan     }
47335005f76SSean Callanan     else
47435005f76SSean Callanan     {
47535005f76SSean Callanan         error.SetErrorToGenericError();
47635005f76SSean Callanan         error.SetErrorString ("Couldn't write scalar: its size was zero");
47735005f76SSean Callanan     }
47835005f76SSean Callanan     return;
47935005f76SSean Callanan }
48035005f76SSean Callanan 
48135005f76SSean Callanan void
482f8043fa5SSean Callanan IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
483f8043fa5SSean Callanan {
48408052afaSSean Callanan     error.Clear();
48508052afaSSean Callanan 
486f8043fa5SSean Callanan     Scalar scalar(address);
487f8043fa5SSean Callanan 
488f8043fa5SSean Callanan     WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
489f8043fa5SSean Callanan }
490f8043fa5SSean Callanan 
491f8043fa5SSean Callanan void
4925a1af4e6SSean Callanan IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
4935a1af4e6SSean Callanan {
49408052afaSSean Callanan     error.Clear();
49508052afaSSean Callanan 
4965a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
4975a1af4e6SSean Callanan 
4985a1af4e6SSean Callanan     if (iter == m_allocations.end())
4995a1af4e6SSean Callanan     {
500c8c5b8dcSSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
501c8c5b8dcSSean Callanan 
502c8c5b8dcSSean Callanan         if (process_sp)
503c8c5b8dcSSean Callanan         {
504c8c5b8dcSSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
505c8c5b8dcSSean Callanan             return;
506c8c5b8dcSSean Callanan         }
507c8c5b8dcSSean Callanan 
508c8c5b8dcSSean Callanan         lldb::TargetSP target_sp = m_target_wp.lock();
509c8c5b8dcSSean Callanan 
510c8c5b8dcSSean Callanan         if (target_sp)
511c8c5b8dcSSean Callanan         {
512c8c5b8dcSSean Callanan             Address absolute_address(process_address);
513c8c5b8dcSSean Callanan             target_sp->ReadMemory(absolute_address, false, bytes, size, error);
514c8c5b8dcSSean Callanan             return;
515c8c5b8dcSSean Callanan         }
516c8c5b8dcSSean Callanan 
5175a1af4e6SSean Callanan         error.SetErrorToGenericError();
518c8c5b8dcSSean Callanan         error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist");
5195a1af4e6SSean Callanan         return;
5205a1af4e6SSean Callanan     }
5215a1af4e6SSean Callanan 
5225a1af4e6SSean Callanan     Allocation &allocation = iter->second;
5235a1af4e6SSean Callanan 
5245a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
5255a1af4e6SSean Callanan 
5265a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
5275a1af4e6SSean Callanan 
5285a1af4e6SSean Callanan     switch (allocation.m_policy)
5295a1af4e6SSean Callanan     {
5305a1af4e6SSean Callanan     default:
5315a1af4e6SSean Callanan         error.SetErrorToGenericError();
5325a1af4e6SSean Callanan         error.SetErrorString("Couldn't read: invalid allocation policy");
5335a1af4e6SSean Callanan         return;
5345a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
535e0c64e15SGreg Clayton         if (!allocation.m_data_ap.get())
5365a1af4e6SSean Callanan         {
5375a1af4e6SSean Callanan             error.SetErrorToGenericError();
5385a1af4e6SSean Callanan             error.SetErrorString("Couldn't read: data buffer is empty");
5395a1af4e6SSean Callanan             return;
5405a1af4e6SSean Callanan         }
541e0c64e15SGreg Clayton         ::memcpy (bytes, allocation.m_data_ap->GetBytes() + offset, size);
5425a1af4e6SSean Callanan         break;
5435a1af4e6SSean Callanan     case eAllocationPolicyMirror:
5445a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
5455a1af4e6SSean Callanan         if (process_sp)
5465a1af4e6SSean Callanan         {
5475a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
5485a1af4e6SSean Callanan             if (!error.Success())
5495a1af4e6SSean Callanan                 return;
5505a1af4e6SSean Callanan         }
5515a1af4e6SSean Callanan         else
5525a1af4e6SSean Callanan         {
553e0c64e15SGreg Clayton             if (!allocation.m_data_ap.get())
5545a1af4e6SSean Callanan             {
5555a1af4e6SSean Callanan                 error.SetErrorToGenericError();
5565a1af4e6SSean Callanan                 error.SetErrorString("Couldn't read: data buffer is empty");
5575a1af4e6SSean Callanan                 return;
5585a1af4e6SSean Callanan             }
559e0c64e15SGreg Clayton             ::memcpy (bytes, allocation.m_data_ap->GetBytes() + offset, size);
5605a1af4e6SSean Callanan         }
5615a1af4e6SSean Callanan         break;
5625a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
5635a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
5645a1af4e6SSean Callanan         if (process_sp)
5655a1af4e6SSean Callanan         {
5665a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
5675a1af4e6SSean Callanan             if (!error.Success())
5685a1af4e6SSean Callanan                 return;
5695a1af4e6SSean Callanan         }
5705a1af4e6SSean Callanan         break;
5715a1af4e6SSean Callanan     }
5725a1af4e6SSean Callanan 
5735a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
5745a1af4e6SSean Callanan     {
5755a1af4e6SSean Callanan         log->Printf("IRMemoryMap::ReadMemory (0x%llx, 0x%llx, 0x%lld) came from [0x%llx..0x%llx)",
5765a1af4e6SSean Callanan                     (uint64_t)process_address,
5775a1af4e6SSean Callanan                     (uint64_t)bytes,
5785a1af4e6SSean Callanan                     (uint64_t)size,
5795a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
5805a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
5815a1af4e6SSean Callanan     }
5825a1af4e6SSean Callanan }
58335005f76SSean Callanan 
58435005f76SSean Callanan void
58535005f76SSean Callanan IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
58635005f76SSean Callanan {
58708052afaSSean Callanan     error.Clear();
58808052afaSSean Callanan 
58935005f76SSean Callanan     if (size > 0)
59035005f76SSean Callanan     {
59135005f76SSean Callanan         DataBufferHeap buf(size, 0);
59235005f76SSean Callanan         ReadMemory(buf.GetBytes(), process_address, size, error);
59335005f76SSean Callanan 
59435005f76SSean Callanan         if (!error.Success())
59535005f76SSean Callanan             return;
59635005f76SSean Callanan 
59735005f76SSean Callanan         DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
59835005f76SSean Callanan 
59935005f76SSean Callanan         lldb::offset_t offset = 0;
60035005f76SSean Callanan 
60135005f76SSean Callanan         switch (size)
60235005f76SSean Callanan         {
60335005f76SSean Callanan         default:
60435005f76SSean Callanan             error.SetErrorToGenericError();
60535005f76SSean Callanan             error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %lld", (unsigned long long)size);
60635005f76SSean Callanan             return;
60735005f76SSean Callanan         case 1: scalar = extractor.GetU8(&offset);  break;
60835005f76SSean Callanan         case 2: scalar = extractor.GetU16(&offset); break;
60935005f76SSean Callanan         case 4: scalar = extractor.GetU32(&offset); break;
61035005f76SSean Callanan         case 8: scalar = extractor.GetU64(&offset); break;
61135005f76SSean Callanan         }
61235005f76SSean Callanan     }
61335005f76SSean Callanan     else
61435005f76SSean Callanan     {
61535005f76SSean Callanan         error.SetErrorToGenericError();
616458ae1c6SSean Callanan         error.SetErrorString ("Couldn't read scalar: its size was zero");
61735005f76SSean Callanan     }
61835005f76SSean Callanan     return;
61935005f76SSean Callanan }
62035005f76SSean Callanan 
621458ae1c6SSean Callanan void
6222d37e5a5SSean Callanan IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
6232d37e5a5SSean Callanan {
62408052afaSSean Callanan     error.Clear();
62508052afaSSean Callanan 
6262d37e5a5SSean Callanan     Scalar pointer_scalar;
6272d37e5a5SSean Callanan     ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
6282d37e5a5SSean Callanan 
6292d37e5a5SSean Callanan     if (!error.Success())
6302d37e5a5SSean Callanan         return;
6312d37e5a5SSean Callanan 
6322d37e5a5SSean Callanan     *address = pointer_scalar.ULongLong();
6332d37e5a5SSean Callanan 
6342d37e5a5SSean Callanan     return;
6352d37e5a5SSean Callanan }
6362d37e5a5SSean Callanan 
6372d37e5a5SSean Callanan void
638458ae1c6SSean Callanan IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
639458ae1c6SSean Callanan {
64008052afaSSean Callanan     error.Clear();
64108052afaSSean Callanan 
642458ae1c6SSean Callanan     if (size > 0)
643458ae1c6SSean Callanan     {
644458ae1c6SSean Callanan         AllocationMap::iterator iter = FindAllocation(process_address, size);
645458ae1c6SSean Callanan 
646458ae1c6SSean Callanan         if (iter == m_allocations.end())
647458ae1c6SSean Callanan         {
648458ae1c6SSean Callanan             error.SetErrorToGenericError();
649458ae1c6SSean Callanan             error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%llx..0x%llx)", (unsigned long long)process_address, (unsigned long long)(process_address + size));
650458ae1c6SSean Callanan             return;
651458ae1c6SSean Callanan         }
652458ae1c6SSean Callanan 
653458ae1c6SSean Callanan         Allocation &allocation = iter->second;
654458ae1c6SSean Callanan 
655458ae1c6SSean Callanan         switch (allocation.m_policy)
656458ae1c6SSean Callanan         {
657458ae1c6SSean Callanan         default:
658458ae1c6SSean Callanan             error.SetErrorToGenericError();
659458ae1c6SSean Callanan             error.SetErrorString("Couldn't get memory data: invalid allocation policy");
660458ae1c6SSean Callanan             return;
661458ae1c6SSean Callanan         case eAllocationPolicyProcessOnly:
662458ae1c6SSean Callanan             error.SetErrorToGenericError();
663458ae1c6SSean Callanan             error.SetErrorString("Couldn't get memory data: memory is only in the target");
664458ae1c6SSean Callanan             return;
665458ae1c6SSean Callanan         case eAllocationPolicyMirror:
666c8c5b8dcSSean Callanan             {
667c8c5b8dcSSean Callanan                 lldb::ProcessSP process_sp = m_process_wp.lock();
668c8c5b8dcSSean Callanan 
669e0c64e15SGreg Clayton                 if (!allocation.m_data_ap.get())
670c8c5b8dcSSean Callanan                 {
671c8c5b8dcSSean Callanan                     error.SetErrorToGenericError();
672c8c5b8dcSSean Callanan                     error.SetErrorString("Couldn't get memory data: data buffer is empty");
673c8c5b8dcSSean Callanan                     return;
674c8c5b8dcSSean Callanan                 }
675c8c5b8dcSSean Callanan                 if (process_sp)
676c8c5b8dcSSean Callanan                 {
677e0c64e15SGreg Clayton                     process_sp->ReadMemory(allocation.m_process_start, allocation.m_data_ap->GetBytes(), allocation.m_data_ap->GetByteSize(), error);
678c8c5b8dcSSean Callanan                     if (!error.Success())
679c8c5b8dcSSean Callanan                         return;
680c8c5b8dcSSean Callanan                     uint64_t offset = process_address - allocation.m_process_start;
681e0c64e15SGreg Clayton                     extractor = DataExtractor(allocation.m_data_ap->GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
682c8c5b8dcSSean Callanan                     return;
683c8c5b8dcSSean Callanan                 }
684c8c5b8dcSSean Callanan             }
685c8c5b8dcSSean Callanan         case eAllocationPolicyHostOnly:
686e0c64e15SGreg Clayton             if (!allocation.m_data_ap.get())
687458ae1c6SSean Callanan             {
688458ae1c6SSean Callanan                 error.SetErrorToGenericError();
689458ae1c6SSean Callanan                 error.SetErrorString("Couldn't get memory data: data buffer is empty");
690458ae1c6SSean Callanan                 return;
691458ae1c6SSean Callanan             }
692458ae1c6SSean Callanan             uint64_t offset = process_address - allocation.m_process_start;
693e0c64e15SGreg Clayton             extractor = DataExtractor(allocation.m_data_ap->GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
694458ae1c6SSean Callanan             return;
695458ae1c6SSean Callanan         }
696458ae1c6SSean Callanan     }
697458ae1c6SSean Callanan     else
698458ae1c6SSean Callanan     {
699458ae1c6SSean Callanan         error.SetErrorToGenericError();
700458ae1c6SSean Callanan         error.SetErrorString ("Couldn't get memory data: its size was zero");
701458ae1c6SSean Callanan         return;
702458ae1c6SSean Callanan     }
703458ae1c6SSean Callanan }
704458ae1c6SSean Callanan 
705458ae1c6SSean Callanan 
706