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 ||
37df56540aSSean Callanan                 allocation.second.m_policy == eAllocationPolicyProcessOnly ||
38df56540aSSean Callanan                 (allocation.second.m_policy == eAllocationPolicyHostOnly && process_sp->CanJIT()))
395a1af4e6SSean Callanan                 process_sp->DeallocateMemory(allocation.second.m_process_alloc);
405a1af4e6SSean Callanan 
415a1af4e6SSean Callanan             if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
425a1af4e6SSean Callanan             {
435a1af4e6SSean Callanan                 log->Printf("IRMemoryMap::~IRMemoryMap deallocated [0x%llx..0x%llx)",
445a1af4e6SSean Callanan                             (uint64_t)allocation.second.m_process_start,
455a1af4e6SSean Callanan                             (uint64_t)allocation.second.m_process_start + (uint64_t)allocation.second.m_size);
465a1af4e6SSean Callanan             }
475a1af4e6SSean Callanan         }
485a1af4e6SSean Callanan     }
495a1af4e6SSean Callanan }
505a1af4e6SSean Callanan 
515a1af4e6SSean Callanan lldb::addr_t
525a1af4e6SSean Callanan IRMemoryMap::FindSpace (size_t size)
535a1af4e6SSean Callanan {
54bb9945f4SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
55bb9945f4SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
565a1af4e6SSean Callanan 
57bb9945f4SSean Callanan     lldb::addr_t ret = LLDB_INVALID_ADDRESS;
585a1af4e6SSean Callanan 
59df56540aSSean Callanan     if (process_sp && process_sp->CanJIT())
60df56540aSSean Callanan     {
61df56540aSSean Callanan         Error alloc_error;
62df56540aSSean Callanan 
63df56540aSSean Callanan         ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
64df56540aSSean Callanan 
65df56540aSSean Callanan         if (!alloc_error.Success())
66df56540aSSean Callanan             return LLDB_INVALID_ADDRESS;
67df56540aSSean Callanan         else
68df56540aSSean Callanan             return ret;
69df56540aSSean Callanan     }
70df56540aSSean Callanan 
71bb9945f4SSean Callanan     for (int iterations = 0; iterations < 16; ++iterations)
725a1af4e6SSean Callanan     {
73*5c42d8a8SJim Ingham         lldb::addr_t candidate = LLDB_INVALID_ADDRESS;
745a1af4e6SSean Callanan 
75bb9945f4SSean Callanan         switch (target_sp->GetArchitecture().GetAddressByteSize())
76bb9945f4SSean Callanan         {
77bb9945f4SSean Callanan         case 4:
78bb9945f4SSean Callanan             {
79bb9945f4SSean Callanan                 uint32_t random_data = random();
80bb9945f4SSean Callanan                 candidate = random_data;
81bb9945f4SSean Callanan                 candidate &= ~0xfffull;
82bb9945f4SSean Callanan                 break;
83bb9945f4SSean Callanan             }
84bb9945f4SSean Callanan         case 8:
85bb9945f4SSean Callanan             {
86bb9945f4SSean Callanan                 uint32_t random_low = random();
87bb9945f4SSean Callanan                 uint32_t random_high = random();
88bb9945f4SSean Callanan                 candidate = random_high;
89bb9945f4SSean Callanan                 candidate <<= 32ull;
90bb9945f4SSean Callanan                 candidate |= random_low;
91bb9945f4SSean Callanan                 candidate &= ~0xfffull;
92bb9945f4SSean Callanan                 break;
93bb9945f4SSean Callanan             }
945a1af4e6SSean Callanan         }
955a1af4e6SSean Callanan 
96bb9945f4SSean Callanan         if (IntersectsAllocation(candidate, size))
97bb9945f4SSean Callanan             continue;
985a1af4e6SSean Callanan 
99bb9945f4SSean Callanan         char buf[1];
100bb9945f4SSean Callanan 
101bb9945f4SSean Callanan         Error err;
102bb9945f4SSean Callanan 
103bb9945f4SSean Callanan         if (process_sp &&
104bb9945f4SSean Callanan             (process_sp->ReadMemory(candidate, buf, 1, err) == 1 ||
105bb9945f4SSean Callanan              process_sp->ReadMemory(candidate + size, buf, 1, err) == 1))
106bb9945f4SSean Callanan             continue;
107bb9945f4SSean Callanan 
108bb9945f4SSean Callanan         ret = candidate;
1095a1af4e6SSean Callanan     }
1105a1af4e6SSean Callanan 
111bb9945f4SSean Callanan     return ret;
1125a1af4e6SSean Callanan }
1135a1af4e6SSean Callanan 
1145a1af4e6SSean Callanan IRMemoryMap::AllocationMap::iterator
1155a1af4e6SSean Callanan IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
1165a1af4e6SSean Callanan {
1171582ee68SSean Callanan     if (addr == LLDB_INVALID_ADDRESS)
1181582ee68SSean Callanan         return m_allocations.end();
1191582ee68SSean Callanan 
1205a1af4e6SSean Callanan     AllocationMap::iterator iter = m_allocations.lower_bound (addr);
1215a1af4e6SSean Callanan 
12214b1bae5SSean Callanan     if (iter == m_allocations.end() ||
12314b1bae5SSean Callanan         iter->first > addr)
1245a1af4e6SSean Callanan     {
1255a1af4e6SSean Callanan         if (iter == m_allocations.begin())
1265a1af4e6SSean Callanan             return m_allocations.end();
1275a1af4e6SSean Callanan         iter--;
1285a1af4e6SSean Callanan     }
1295a1af4e6SSean Callanan 
1305a1af4e6SSean Callanan     if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
1315a1af4e6SSean Callanan         return iter;
1325a1af4e6SSean Callanan 
1335a1af4e6SSean Callanan     return m_allocations.end();
1345a1af4e6SSean Callanan }
1355a1af4e6SSean Callanan 
136bb9945f4SSean Callanan bool
137bb9945f4SSean Callanan IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size)
138bb9945f4SSean Callanan {
139bb9945f4SSean Callanan     if (addr == LLDB_INVALID_ADDRESS)
140bb9945f4SSean Callanan         return false;
141bb9945f4SSean Callanan 
142bb9945f4SSean Callanan     AllocationMap::iterator iter = m_allocations.lower_bound (addr);
143bb9945f4SSean Callanan 
144bb9945f4SSean Callanan     if (iter == m_allocations.end() ||
145bb9945f4SSean Callanan         iter->first > addr)
146bb9945f4SSean Callanan     {
147bb9945f4SSean Callanan         if (iter == m_allocations.begin())
148bb9945f4SSean Callanan             return false;
149bb9945f4SSean Callanan 
150bb9945f4SSean Callanan         iter--;
151bb9945f4SSean Callanan     }
152bb9945f4SSean Callanan 
153bb9945f4SSean Callanan     while (iter != m_allocations.end() && iter->second.m_process_alloc < addr + size)
154bb9945f4SSean Callanan     {
155bb9945f4SSean Callanan         if (iter->second.m_process_start + iter->second.m_size > addr)
156bb9945f4SSean Callanan             return true;
157bb9945f4SSean Callanan 
158bb9945f4SSean Callanan         ++iter;
159bb9945f4SSean Callanan     }
160bb9945f4SSean Callanan 
161bb9945f4SSean Callanan     return false;
162bb9945f4SSean Callanan }
163bb9945f4SSean Callanan 
16435005f76SSean Callanan lldb::ByteOrder
16535005f76SSean Callanan IRMemoryMap::GetByteOrder()
16635005f76SSean Callanan {
16735005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
16835005f76SSean Callanan 
16935005f76SSean Callanan     if (process_sp)
17035005f76SSean Callanan         return process_sp->GetByteOrder();
17135005f76SSean Callanan 
17235005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
17335005f76SSean Callanan 
17435005f76SSean Callanan     if (target_sp)
17508052afaSSean Callanan         return target_sp->GetArchitecture().GetByteOrder();
17635005f76SSean Callanan 
17735005f76SSean Callanan     return lldb::eByteOrderInvalid;
17835005f76SSean Callanan }
17935005f76SSean Callanan 
18035005f76SSean Callanan uint32_t
18135005f76SSean Callanan IRMemoryMap::GetAddressByteSize()
18235005f76SSean Callanan {
18335005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
18435005f76SSean Callanan 
18535005f76SSean Callanan     if (process_sp)
18635005f76SSean Callanan         return process_sp->GetAddressByteSize();
18735005f76SSean Callanan 
18835005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
18935005f76SSean Callanan 
19035005f76SSean Callanan     if (target_sp)
19108052afaSSean Callanan         return target_sp->GetArchitecture().GetAddressByteSize();
19235005f76SSean Callanan 
19335005f76SSean Callanan     return UINT32_MAX;
19435005f76SSean Callanan }
19535005f76SSean Callanan 
19635005f76SSean Callanan ExecutionContextScope *
19735005f76SSean Callanan IRMemoryMap::GetBestExecutionContextScope()
19835005f76SSean Callanan {
19935005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
20035005f76SSean Callanan 
20135005f76SSean Callanan     if (process_sp)
20235005f76SSean Callanan         return process_sp.get();
20335005f76SSean Callanan 
20435005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
20535005f76SSean Callanan 
20635005f76SSean Callanan     if (target_sp)
20735005f76SSean Callanan         return target_sp.get();
20835005f76SSean Callanan 
20935005f76SSean Callanan     return NULL;
21035005f76SSean Callanan }
21135005f76SSean Callanan 
212d2562509SSean Callanan IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
213d2562509SSean Callanan                                      lldb::addr_t process_start,
214d2562509SSean Callanan                                      size_t size,
215d2562509SSean Callanan                                      uint32_t permissions,
216d2562509SSean Callanan                                      uint8_t alignment,
217d2562509SSean Callanan                                      AllocationPolicy policy)
218d2562509SSean Callanan {
219d2562509SSean Callanan     m_process_alloc = process_alloc;
220d2562509SSean Callanan     m_process_start = process_start;
221d2562509SSean Callanan     m_size = size;
222d2562509SSean Callanan     m_permissions = permissions;
223d2562509SSean Callanan     m_alignment = alignment;
224d2562509SSean Callanan     m_policy = policy;
225d2562509SSean Callanan 
226d2562509SSean Callanan     switch (policy)
227d2562509SSean Callanan     {
228d2562509SSean Callanan         default:
229d2562509SSean Callanan             assert (0 && "We cannot reach this!");
230d2562509SSean Callanan         case eAllocationPolicyHostOnly:
231d2562509SSean Callanan             m_data.SetByteSize(size);
232d2562509SSean Callanan             memset(m_data.GetBytes(), 0, size);
233d2562509SSean Callanan             break;
234d2562509SSean Callanan         case eAllocationPolicyProcessOnly:
235d2562509SSean Callanan             break;
236d2562509SSean Callanan         case eAllocationPolicyMirror:
237d2562509SSean Callanan             m_data.SetByteSize(size);
238d2562509SSean Callanan             memset(m_data.GetBytes(), 0, size);
239d2562509SSean Callanan             break;
240d2562509SSean Callanan     }
241d2562509SSean Callanan }
242d2562509SSean Callanan 
2435a1af4e6SSean Callanan lldb::addr_t
2445a1af4e6SSean Callanan IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
2455a1af4e6SSean Callanan {
24608052afaSSean Callanan     error.Clear();
24708052afaSSean Callanan 
2485a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
2495a1af4e6SSean Callanan     lldb::addr_t    allocation_address  = LLDB_INVALID_ADDRESS;
2505a1af4e6SSean Callanan     lldb::addr_t    aligned_address     = LLDB_INVALID_ADDRESS;
2515a1af4e6SSean Callanan 
252750dcc33SMatt Kopec     size_t          alignment_mask = alignment - 1;
253750dcc33SMatt Kopec     size_t          allocation_size;
254750dcc33SMatt Kopec 
255750dcc33SMatt Kopec     if (size == 0)
256750dcc33SMatt Kopec         allocation_size = alignment;
257750dcc33SMatt Kopec     else
258750dcc33SMatt Kopec         allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size;
2595a1af4e6SSean Callanan 
2605a1af4e6SSean Callanan     switch (policy)
2615a1af4e6SSean Callanan     {
2625a1af4e6SSean Callanan     default:
2635a1af4e6SSean Callanan         error.SetErrorToGenericError();
2645a1af4e6SSean Callanan         error.SetErrorString("Couldn't malloc: invalid allocation policy");
2655a1af4e6SSean Callanan         return LLDB_INVALID_ADDRESS;
2665a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
2675a1af4e6SSean Callanan         allocation_address = FindSpace(allocation_size);
2685a1af4e6SSean Callanan         if (allocation_address == LLDB_INVALID_ADDRESS)
2695a1af4e6SSean Callanan         {
2705a1af4e6SSean Callanan             error.SetErrorToGenericError();
2715a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: address space is full");
2725a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
2735a1af4e6SSean Callanan         }
2745a1af4e6SSean Callanan         break;
2755a1af4e6SSean Callanan     case eAllocationPolicyMirror:
2765a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
277bb9945f4SSean Callanan         if (process_sp && process_sp->CanJIT())
2785a1af4e6SSean Callanan         {
2795a1af4e6SSean Callanan             allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
2805a1af4e6SSean Callanan             if (!error.Success())
2815a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
2825a1af4e6SSean Callanan         }
2835a1af4e6SSean Callanan         else
2845a1af4e6SSean Callanan         {
285bb9945f4SSean Callanan             policy = eAllocationPolicyHostOnly;
2865a1af4e6SSean Callanan             allocation_address = FindSpace(allocation_size);
2875a1af4e6SSean Callanan             if (allocation_address == LLDB_INVALID_ADDRESS)
2885a1af4e6SSean Callanan             {
2895a1af4e6SSean Callanan                 error.SetErrorToGenericError();
2905a1af4e6SSean Callanan                 error.SetErrorString("Couldn't malloc: address space is full");
2915a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
2925a1af4e6SSean Callanan             }
2935a1af4e6SSean Callanan         }
2945a1af4e6SSean Callanan         break;
2955a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
2965a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
2975a1af4e6SSean Callanan         if (process_sp)
2985a1af4e6SSean Callanan         {
299bb9945f4SSean Callanan             if (process_sp->CanJIT())
300bb9945f4SSean Callanan             {
3015a1af4e6SSean Callanan                 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
3025a1af4e6SSean Callanan                 if (!error.Success())
3035a1af4e6SSean Callanan                     return LLDB_INVALID_ADDRESS;
3045a1af4e6SSean Callanan             }
3055a1af4e6SSean Callanan             else
3065a1af4e6SSean Callanan             {
3075a1af4e6SSean Callanan                 error.SetErrorToGenericError();
308bb9945f4SSean Callanan                 error.SetErrorString("Couldn't malloc: process doesn't support allocating memory");
309bb9945f4SSean Callanan                 return LLDB_INVALID_ADDRESS;
310bb9945f4SSean Callanan             }
311bb9945f4SSean Callanan         }
312bb9945f4SSean Callanan         else
313bb9945f4SSean Callanan         {
314bb9945f4SSean Callanan             error.SetErrorToGenericError();
3155a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
3165a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
3175a1af4e6SSean Callanan         }
3185a1af4e6SSean Callanan         break;
3195a1af4e6SSean Callanan     }
3205a1af4e6SSean Callanan 
3215a1af4e6SSean Callanan 
3225a1af4e6SSean Callanan     lldb::addr_t mask = alignment - 1;
3235a1af4e6SSean Callanan     aligned_address = (allocation_address + mask) & (~mask);
3245a1af4e6SSean Callanan 
325d2562509SSean Callanan     m_allocations[aligned_address] = Allocation(allocation_address,
326d2562509SSean Callanan                                                 aligned_address,
327750dcc33SMatt Kopec                                                 allocation_size,
328d2562509SSean Callanan                                                 permissions,
329d2562509SSean Callanan                                                 alignment,
330d2562509SSean Callanan                                                 policy);
3315a1af4e6SSean Callanan 
3325a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
3335a1af4e6SSean Callanan     {
3345a1af4e6SSean Callanan         const char * policy_string;
3355a1af4e6SSean Callanan 
3365a1af4e6SSean Callanan         switch (policy)
3375a1af4e6SSean Callanan         {
3385a1af4e6SSean Callanan         default:
3395a1af4e6SSean Callanan             policy_string = "<invalid policy>";
3405a1af4e6SSean Callanan             break;
3415a1af4e6SSean Callanan         case eAllocationPolicyHostOnly:
3425a1af4e6SSean Callanan             policy_string = "eAllocationPolicyHostOnly";
3435a1af4e6SSean Callanan             break;
3445a1af4e6SSean Callanan         case eAllocationPolicyProcessOnly:
3455a1af4e6SSean Callanan             policy_string = "eAllocationPolicyProcessOnly";
3465a1af4e6SSean Callanan             break;
3475a1af4e6SSean Callanan         case eAllocationPolicyMirror:
3485a1af4e6SSean Callanan             policy_string = "eAllocationPolicyMirror";
3495a1af4e6SSean Callanan             break;
3505a1af4e6SSean Callanan         }
3515a1af4e6SSean Callanan 
3525a1af4e6SSean Callanan         log->Printf("IRMemoryMap::Malloc (%llu, 0x%llx, 0x%llx, %s) -> 0x%llx",
353750dcc33SMatt Kopec                     (uint64_t)allocation_size,
3545a1af4e6SSean Callanan                     (uint64_t)alignment,
3555a1af4e6SSean Callanan                     (uint64_t)permissions,
3565a1af4e6SSean Callanan                     policy_string,
3575a1af4e6SSean Callanan                     aligned_address);
3585a1af4e6SSean Callanan     }
3595a1af4e6SSean Callanan 
3605a1af4e6SSean Callanan     return aligned_address;
3615a1af4e6SSean Callanan }
3625a1af4e6SSean Callanan 
3635a1af4e6SSean Callanan void
3645a1af4e6SSean Callanan IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
3655a1af4e6SSean Callanan {
36608052afaSSean Callanan     error.Clear();
36708052afaSSean Callanan 
3685a1af4e6SSean Callanan     AllocationMap::iterator iter = m_allocations.find(process_address);
3695a1af4e6SSean Callanan 
3705a1af4e6SSean Callanan     if (iter == m_allocations.end())
3715a1af4e6SSean Callanan     {
3725a1af4e6SSean Callanan         error.SetErrorToGenericError();
3735a1af4e6SSean Callanan         error.SetErrorString("Couldn't free: allocation doesn't exist");
3745a1af4e6SSean Callanan         return;
3755a1af4e6SSean Callanan     }
3765a1af4e6SSean Callanan 
3775a1af4e6SSean Callanan     Allocation &allocation = iter->second;
3785a1af4e6SSean Callanan 
3795a1af4e6SSean Callanan     switch (allocation.m_policy)
3805a1af4e6SSean Callanan     {
3815a1af4e6SSean Callanan     default:
3825a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
383df56540aSSean Callanan         {
384df56540aSSean Callanan             lldb::ProcessSP process_sp = m_process_wp.lock();
385df56540aSSean Callanan             if (process_sp && process_sp->CanJIT())
386df56540aSSean Callanan                 process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
387df56540aSSean Callanan 
3885a1af4e6SSean Callanan             break;
389df56540aSSean Callanan         }
3905a1af4e6SSean Callanan     case eAllocationPolicyMirror:
3915a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
392df56540aSSean Callanan         {
3935a1af4e6SSean Callanan             lldb::ProcessSP process_sp = m_process_wp.lock();
3945a1af4e6SSean Callanan             if (process_sp)
3955a1af4e6SSean Callanan                 process_sp->DeallocateMemory(allocation.m_process_alloc);
3965a1af4e6SSean Callanan         }
397df56540aSSean Callanan     }
3985a1af4e6SSean Callanan 
3995a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
4005a1af4e6SSean Callanan     {
4015a1af4e6SSean Callanan         log->Printf("IRMemoryMap::Free (0x%llx) freed [0x%llx..0x%llx)",
4025a1af4e6SSean Callanan                     (uint64_t)process_address,
4035a1af4e6SSean Callanan                     iter->second.m_process_start,
4045a1af4e6SSean Callanan                     iter->second.m_process_start + iter->second.m_size);
4055a1af4e6SSean Callanan     }
4065a1af4e6SSean Callanan 
4075a1af4e6SSean Callanan     m_allocations.erase(iter);
4085a1af4e6SSean Callanan }
4095a1af4e6SSean Callanan 
4105a1af4e6SSean Callanan void
4115a1af4e6SSean Callanan IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
4125a1af4e6SSean Callanan {
41308052afaSSean Callanan     error.Clear();
41408052afaSSean Callanan 
4155a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
4165a1af4e6SSean Callanan 
4175a1af4e6SSean Callanan     if (iter == m_allocations.end())
4185a1af4e6SSean Callanan     {
419c8c5b8dcSSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
420c8c5b8dcSSean Callanan 
421c8c5b8dcSSean Callanan         if (process_sp)
422c8c5b8dcSSean Callanan         {
423c8c5b8dcSSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
424c8c5b8dcSSean Callanan             return;
425c8c5b8dcSSean Callanan         }
426c8c5b8dcSSean Callanan 
4275a1af4e6SSean Callanan         error.SetErrorToGenericError();
428c8c5b8dcSSean Callanan         error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
4295a1af4e6SSean Callanan         return;
4305a1af4e6SSean Callanan     }
4315a1af4e6SSean Callanan 
4325a1af4e6SSean Callanan     Allocation &allocation = iter->second;
4335a1af4e6SSean Callanan 
4345a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
4355a1af4e6SSean Callanan 
4365a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
4375a1af4e6SSean Callanan 
4385a1af4e6SSean Callanan     switch (allocation.m_policy)
4395a1af4e6SSean Callanan     {
4405a1af4e6SSean Callanan     default:
4415a1af4e6SSean Callanan         error.SetErrorToGenericError();
4425a1af4e6SSean Callanan         error.SetErrorString("Couldn't write: invalid allocation policy");
4435a1af4e6SSean Callanan         return;
4445a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
445d2562509SSean Callanan         if (!allocation.m_data.GetByteSize())
4465a1af4e6SSean Callanan         {
4475a1af4e6SSean Callanan             error.SetErrorToGenericError();
4485a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
4495a1af4e6SSean Callanan             return;
4505a1af4e6SSean Callanan         }
451d2562509SSean Callanan         ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
4525a1af4e6SSean Callanan         break;
4535a1af4e6SSean Callanan     case eAllocationPolicyMirror:
454d2562509SSean Callanan         if (!allocation.m_data.GetByteSize())
4555a1af4e6SSean Callanan         {
4565a1af4e6SSean Callanan             error.SetErrorToGenericError();
4575a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
4585a1af4e6SSean Callanan             return;
4595a1af4e6SSean Callanan         }
460d2562509SSean Callanan         ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
4615a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
4625a1af4e6SSean Callanan         if (process_sp)
4635a1af4e6SSean Callanan         {
4645a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
4655a1af4e6SSean Callanan             if (!error.Success())
4665a1af4e6SSean Callanan                 return;
4675a1af4e6SSean Callanan         }
4685a1af4e6SSean Callanan         break;
4695a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
4705a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
4715a1af4e6SSean Callanan         if (process_sp)
4725a1af4e6SSean Callanan         {
4735a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
4745a1af4e6SSean Callanan             if (!error.Success())
4755a1af4e6SSean Callanan                 return;
4765a1af4e6SSean Callanan         }
4775a1af4e6SSean Callanan         break;
4785a1af4e6SSean Callanan     }
4795a1af4e6SSean Callanan 
4805a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
4815a1af4e6SSean Callanan     {
4825a1af4e6SSean Callanan         log->Printf("IRMemoryMap::WriteMemory (0x%llx, 0x%llx, 0x%lld) went to [0x%llx..0x%llx)",
4835a1af4e6SSean Callanan                     (uint64_t)process_address,
4845a1af4e6SSean Callanan                     (uint64_t)bytes,
4855a1af4e6SSean Callanan                     (uint64_t)size,
4865a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
4875a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
4885a1af4e6SSean Callanan     }
4895a1af4e6SSean Callanan }
4905a1af4e6SSean Callanan 
4915a1af4e6SSean Callanan void
49235005f76SSean Callanan IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
49335005f76SSean Callanan {
49408052afaSSean Callanan     error.Clear();
49508052afaSSean Callanan 
49635005f76SSean Callanan     if (size == UINT32_MAX)
49735005f76SSean Callanan         size = scalar.GetByteSize();
49835005f76SSean Callanan 
49935005f76SSean Callanan     if (size > 0)
50035005f76SSean Callanan     {
50135005f76SSean Callanan         uint8_t buf[32];
50235005f76SSean Callanan         const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
50335005f76SSean Callanan         if (mem_size > 0)
50435005f76SSean Callanan         {
50535005f76SSean Callanan             return WriteMemory(process_address, buf, mem_size, error);
50635005f76SSean Callanan         }
50735005f76SSean Callanan         else
50835005f76SSean Callanan         {
50935005f76SSean Callanan             error.SetErrorToGenericError();
51035005f76SSean Callanan             error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
51135005f76SSean Callanan         }
51235005f76SSean Callanan     }
51335005f76SSean Callanan     else
51435005f76SSean Callanan     {
51535005f76SSean Callanan         error.SetErrorToGenericError();
51635005f76SSean Callanan         error.SetErrorString ("Couldn't write scalar: its size was zero");
51735005f76SSean Callanan     }
51835005f76SSean Callanan     return;
51935005f76SSean Callanan }
52035005f76SSean Callanan 
52135005f76SSean Callanan void
522f8043fa5SSean Callanan IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
523f8043fa5SSean Callanan {
52408052afaSSean Callanan     error.Clear();
52508052afaSSean Callanan 
526f8043fa5SSean Callanan     Scalar scalar(address);
527f8043fa5SSean Callanan 
528f8043fa5SSean Callanan     WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
529f8043fa5SSean Callanan }
530f8043fa5SSean Callanan 
531f8043fa5SSean Callanan void
5325a1af4e6SSean Callanan IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
5335a1af4e6SSean Callanan {
53408052afaSSean Callanan     error.Clear();
53508052afaSSean Callanan 
5365a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
5375a1af4e6SSean Callanan 
5385a1af4e6SSean Callanan     if (iter == m_allocations.end())
5395a1af4e6SSean Callanan     {
540c8c5b8dcSSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
541c8c5b8dcSSean Callanan 
542c8c5b8dcSSean Callanan         if (process_sp)
543c8c5b8dcSSean Callanan         {
544c8c5b8dcSSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
545c8c5b8dcSSean Callanan             return;
546c8c5b8dcSSean Callanan         }
547c8c5b8dcSSean Callanan 
548c8c5b8dcSSean Callanan         lldb::TargetSP target_sp = m_target_wp.lock();
549c8c5b8dcSSean Callanan 
550c8c5b8dcSSean Callanan         if (target_sp)
551c8c5b8dcSSean Callanan         {
552c8c5b8dcSSean Callanan             Address absolute_address(process_address);
553c8c5b8dcSSean Callanan             target_sp->ReadMemory(absolute_address, false, bytes, size, error);
554c8c5b8dcSSean Callanan             return;
555c8c5b8dcSSean Callanan         }
556c8c5b8dcSSean Callanan 
5575a1af4e6SSean Callanan         error.SetErrorToGenericError();
558c8c5b8dcSSean Callanan         error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist");
5595a1af4e6SSean Callanan         return;
5605a1af4e6SSean Callanan     }
5615a1af4e6SSean Callanan 
5625a1af4e6SSean Callanan     Allocation &allocation = iter->second;
5635a1af4e6SSean Callanan 
5645a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
5655a1af4e6SSean Callanan 
5665a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
5675a1af4e6SSean Callanan 
5685a1af4e6SSean Callanan     switch (allocation.m_policy)
5695a1af4e6SSean Callanan     {
5705a1af4e6SSean Callanan     default:
5715a1af4e6SSean Callanan         error.SetErrorToGenericError();
5725a1af4e6SSean Callanan         error.SetErrorString("Couldn't read: invalid allocation policy");
5735a1af4e6SSean Callanan         return;
5745a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
575d2562509SSean Callanan         if (!allocation.m_data.GetByteSize())
5765a1af4e6SSean Callanan         {
5775a1af4e6SSean Callanan             error.SetErrorToGenericError();
5785a1af4e6SSean Callanan             error.SetErrorString("Couldn't read: data buffer is empty");
5795a1af4e6SSean Callanan             return;
5805a1af4e6SSean Callanan         }
581d2562509SSean Callanan         ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
5825a1af4e6SSean Callanan         break;
5835a1af4e6SSean Callanan     case eAllocationPolicyMirror:
5845a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
5855a1af4e6SSean Callanan         if (process_sp)
5865a1af4e6SSean Callanan         {
5875a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
5885a1af4e6SSean Callanan             if (!error.Success())
5895a1af4e6SSean Callanan                 return;
5905a1af4e6SSean Callanan         }
5915a1af4e6SSean Callanan         else
5925a1af4e6SSean Callanan         {
593d2562509SSean Callanan             if (!allocation.m_data.GetByteSize())
5945a1af4e6SSean Callanan             {
5955a1af4e6SSean Callanan                 error.SetErrorToGenericError();
5965a1af4e6SSean Callanan                 error.SetErrorString("Couldn't read: data buffer is empty");
5975a1af4e6SSean Callanan                 return;
5985a1af4e6SSean Callanan             }
599d2562509SSean Callanan             ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
6005a1af4e6SSean Callanan         }
6015a1af4e6SSean Callanan         break;
6025a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
6035a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
6045a1af4e6SSean Callanan         if (process_sp)
6055a1af4e6SSean Callanan         {
6065a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
6075a1af4e6SSean Callanan             if (!error.Success())
6085a1af4e6SSean Callanan                 return;
6095a1af4e6SSean Callanan         }
6105a1af4e6SSean Callanan         break;
6115a1af4e6SSean Callanan     }
6125a1af4e6SSean Callanan 
6135a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
6145a1af4e6SSean Callanan     {
6155a1af4e6SSean Callanan         log->Printf("IRMemoryMap::ReadMemory (0x%llx, 0x%llx, 0x%lld) came from [0x%llx..0x%llx)",
6165a1af4e6SSean Callanan                     (uint64_t)process_address,
6175a1af4e6SSean Callanan                     (uint64_t)bytes,
6185a1af4e6SSean Callanan                     (uint64_t)size,
6195a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
6205a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
6215a1af4e6SSean Callanan     }
6225a1af4e6SSean Callanan }
62335005f76SSean Callanan 
62435005f76SSean Callanan void
62535005f76SSean Callanan IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
62635005f76SSean Callanan {
62708052afaSSean Callanan     error.Clear();
62808052afaSSean Callanan 
62935005f76SSean Callanan     if (size > 0)
63035005f76SSean Callanan     {
63135005f76SSean Callanan         DataBufferHeap buf(size, 0);
63235005f76SSean Callanan         ReadMemory(buf.GetBytes(), process_address, size, error);
63335005f76SSean Callanan 
63435005f76SSean Callanan         if (!error.Success())
63535005f76SSean Callanan             return;
63635005f76SSean Callanan 
63735005f76SSean Callanan         DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
63835005f76SSean Callanan 
63935005f76SSean Callanan         lldb::offset_t offset = 0;
64035005f76SSean Callanan 
64135005f76SSean Callanan         switch (size)
64235005f76SSean Callanan         {
64335005f76SSean Callanan         default:
64435005f76SSean Callanan             error.SetErrorToGenericError();
64535005f76SSean Callanan             error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %lld", (unsigned long long)size);
64635005f76SSean Callanan             return;
64735005f76SSean Callanan         case 1: scalar = extractor.GetU8(&offset);  break;
64835005f76SSean Callanan         case 2: scalar = extractor.GetU16(&offset); break;
64935005f76SSean Callanan         case 4: scalar = extractor.GetU32(&offset); break;
65035005f76SSean Callanan         case 8: scalar = extractor.GetU64(&offset); break;
65135005f76SSean Callanan         }
65235005f76SSean Callanan     }
65335005f76SSean Callanan     else
65435005f76SSean Callanan     {
65535005f76SSean Callanan         error.SetErrorToGenericError();
656458ae1c6SSean Callanan         error.SetErrorString ("Couldn't read scalar: its size was zero");
65735005f76SSean Callanan     }
65835005f76SSean Callanan     return;
65935005f76SSean Callanan }
66035005f76SSean Callanan 
661458ae1c6SSean Callanan void
6622d37e5a5SSean Callanan IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
6632d37e5a5SSean Callanan {
66408052afaSSean Callanan     error.Clear();
66508052afaSSean Callanan 
6662d37e5a5SSean Callanan     Scalar pointer_scalar;
6672d37e5a5SSean Callanan     ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
6682d37e5a5SSean Callanan 
6692d37e5a5SSean Callanan     if (!error.Success())
6702d37e5a5SSean Callanan         return;
6712d37e5a5SSean Callanan 
6722d37e5a5SSean Callanan     *address = pointer_scalar.ULongLong();
6732d37e5a5SSean Callanan 
6742d37e5a5SSean Callanan     return;
6752d37e5a5SSean Callanan }
6762d37e5a5SSean Callanan 
6772d37e5a5SSean Callanan void
678458ae1c6SSean Callanan IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
679458ae1c6SSean Callanan {
68008052afaSSean Callanan     error.Clear();
68108052afaSSean Callanan 
682458ae1c6SSean Callanan     if (size > 0)
683458ae1c6SSean Callanan     {
684458ae1c6SSean Callanan         AllocationMap::iterator iter = FindAllocation(process_address, size);
685458ae1c6SSean Callanan 
686458ae1c6SSean Callanan         if (iter == m_allocations.end())
687458ae1c6SSean Callanan         {
688458ae1c6SSean Callanan             error.SetErrorToGenericError();
689458ae1c6SSean Callanan             error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%llx..0x%llx)", (unsigned long long)process_address, (unsigned long long)(process_address + size));
690458ae1c6SSean Callanan             return;
691458ae1c6SSean Callanan         }
692458ae1c6SSean Callanan 
693458ae1c6SSean Callanan         Allocation &allocation = iter->second;
694458ae1c6SSean Callanan 
695458ae1c6SSean Callanan         switch (allocation.m_policy)
696458ae1c6SSean Callanan         {
697458ae1c6SSean Callanan         default:
698458ae1c6SSean Callanan             error.SetErrorToGenericError();
699458ae1c6SSean Callanan             error.SetErrorString("Couldn't get memory data: invalid allocation policy");
700458ae1c6SSean Callanan             return;
701458ae1c6SSean Callanan         case eAllocationPolicyProcessOnly:
702458ae1c6SSean Callanan             error.SetErrorToGenericError();
703458ae1c6SSean Callanan             error.SetErrorString("Couldn't get memory data: memory is only in the target");
704458ae1c6SSean Callanan             return;
705458ae1c6SSean Callanan         case eAllocationPolicyMirror:
706c8c5b8dcSSean Callanan             {
707c8c5b8dcSSean Callanan                 lldb::ProcessSP process_sp = m_process_wp.lock();
708c8c5b8dcSSean Callanan 
709d2562509SSean Callanan                 if (!allocation.m_data.GetByteSize())
710c8c5b8dcSSean Callanan                 {
711c8c5b8dcSSean Callanan                     error.SetErrorToGenericError();
712c8c5b8dcSSean Callanan                     error.SetErrorString("Couldn't get memory data: data buffer is empty");
713c8c5b8dcSSean Callanan                     return;
714c8c5b8dcSSean Callanan                 }
715c8c5b8dcSSean Callanan                 if (process_sp)
716c8c5b8dcSSean Callanan                 {
717d2562509SSean Callanan                     process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error);
718c8c5b8dcSSean Callanan                     if (!error.Success())
719c8c5b8dcSSean Callanan                         return;
720c8c5b8dcSSean Callanan                     uint64_t offset = process_address - allocation.m_process_start;
721d2562509SSean Callanan                     extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
722c8c5b8dcSSean Callanan                     return;
723c8c5b8dcSSean Callanan                 }
724c8c5b8dcSSean Callanan             }
725c8c5b8dcSSean Callanan         case eAllocationPolicyHostOnly:
726d2562509SSean Callanan             if (!allocation.m_data.GetByteSize())
727458ae1c6SSean Callanan             {
728458ae1c6SSean Callanan                 error.SetErrorToGenericError();
729458ae1c6SSean Callanan                 error.SetErrorString("Couldn't get memory data: data buffer is empty");
730458ae1c6SSean Callanan                 return;
731458ae1c6SSean Callanan             }
732458ae1c6SSean Callanan             uint64_t offset = process_address - allocation.m_process_start;
733d2562509SSean Callanan             extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
734458ae1c6SSean Callanan             return;
735458ae1c6SSean Callanan         }
736458ae1c6SSean Callanan     }
737458ae1c6SSean Callanan     else
738458ae1c6SSean Callanan     {
739458ae1c6SSean Callanan         error.SetErrorToGenericError();
740458ae1c6SSean Callanan         error.SetErrorString ("Couldn't get memory data: its size was zero");
741458ae1c6SSean Callanan         return;
742458ae1c6SSean Callanan     }
743458ae1c6SSean Callanan }
744458ae1c6SSean Callanan 
745458ae1c6SSean Callanan 
746