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     {
34bb77704cSSean Callanan         AllocationMap::iterator iter;
355a1af4e6SSean Callanan 
36bb77704cSSean Callanan         Error err;
37bb77704cSSean Callanan 
38bb77704cSSean Callanan         while ((iter = m_allocations.begin()) != m_allocations.end())
395a1af4e6SSean Callanan         {
40bb77704cSSean Callanan             err.Clear();
41fbf5c682SSean Callanan             if (iter->second.m_leak)
42fbf5c682SSean Callanan                 m_allocations.erase(iter);
43fbf5c682SSean Callanan             else
44bb77704cSSean Callanan                 Free(iter->first, err);
455a1af4e6SSean Callanan         }
465a1af4e6SSean Callanan     }
475a1af4e6SSean Callanan }
485a1af4e6SSean Callanan 
495a1af4e6SSean Callanan lldb::addr_t
505a1af4e6SSean Callanan IRMemoryMap::FindSpace (size_t size)
515a1af4e6SSean Callanan {
52bb9945f4SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
53bb9945f4SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
545a1af4e6SSean Callanan 
55bb9945f4SSean Callanan     lldb::addr_t ret = LLDB_INVALID_ADDRESS;
56*3ddcd314SZachary Turner     if (size == 0)
57*3ddcd314SZachary Turner         return ret;
585a1af4e6SSean Callanan 
59ad7cc466SSean Callanan     if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
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 
71*3ddcd314SZachary Turner     ret = 0;
72*3ddcd314SZachary Turner     if (!m_allocations.empty())
735a1af4e6SSean Callanan     {
74*3ddcd314SZachary Turner         auto back = m_allocations.rbegin();
75*3ddcd314SZachary Turner         lldb::addr_t addr = back->first;
76*3ddcd314SZachary Turner         size_t alloc_size = back->second.m_size;
77*3ddcd314SZachary Turner         ret = llvm::RoundUpToAlignment(addr+alloc_size, 4096);
785a1af4e6SSean Callanan     }
795a1af4e6SSean Callanan 
80bb9945f4SSean Callanan     return ret;
815a1af4e6SSean Callanan }
825a1af4e6SSean Callanan 
835a1af4e6SSean Callanan IRMemoryMap::AllocationMap::iterator
845a1af4e6SSean Callanan IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
855a1af4e6SSean Callanan {
861582ee68SSean Callanan     if (addr == LLDB_INVALID_ADDRESS)
871582ee68SSean Callanan         return m_allocations.end();
881582ee68SSean Callanan 
895a1af4e6SSean Callanan     AllocationMap::iterator iter = m_allocations.lower_bound (addr);
905a1af4e6SSean Callanan 
9114b1bae5SSean Callanan     if (iter == m_allocations.end() ||
9214b1bae5SSean Callanan         iter->first > addr)
935a1af4e6SSean Callanan     {
945a1af4e6SSean Callanan         if (iter == m_allocations.begin())
955a1af4e6SSean Callanan             return m_allocations.end();
965a1af4e6SSean Callanan         iter--;
975a1af4e6SSean Callanan     }
985a1af4e6SSean Callanan 
995a1af4e6SSean Callanan     if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
1005a1af4e6SSean Callanan         return iter;
1015a1af4e6SSean Callanan 
1025a1af4e6SSean Callanan     return m_allocations.end();
1035a1af4e6SSean Callanan }
1045a1af4e6SSean Callanan 
105bb9945f4SSean Callanan bool
10615362445SZachary Turner IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size) const
107bb9945f4SSean Callanan {
108bb9945f4SSean Callanan     if (addr == LLDB_INVALID_ADDRESS)
109bb9945f4SSean Callanan         return false;
110bb9945f4SSean Callanan 
11115362445SZachary Turner     AllocationMap::const_iterator iter = m_allocations.lower_bound (addr);
112bb9945f4SSean Callanan 
11315362445SZachary Turner     // Since we only know that the returned interval begins at a location greater than or
11415362445SZachary Turner     // equal to where the given interval begins, it's possible that the given interval
11515362445SZachary Turner     // intersects either the returned interval or the previous interval.  Thus, we need to
11615362445SZachary Turner     // check both. Note that we only need to check these two intervals.  Since all intervals
11715362445SZachary Turner     // are disjoint it is not possible that an adjacent interval does not intersect, but a
11815362445SZachary Turner     // non-adjacent interval does intersect.
11915362445SZachary Turner     if (iter != m_allocations.end()) {
120cfcd7914SZachary Turner         if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
121bb9945f4SSean Callanan             return true;
12215362445SZachary Turner     }
123bb9945f4SSean Callanan 
12415362445SZachary Turner     if (iter != m_allocations.begin()) {
12515362445SZachary Turner         --iter;
126cfcd7914SZachary Turner         if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
12715362445SZachary Turner             return true;
128bb9945f4SSean Callanan     }
129bb9945f4SSean Callanan 
130bb9945f4SSean Callanan     return false;
131bb9945f4SSean Callanan }
132bb9945f4SSean Callanan 
13315362445SZachary Turner bool
13415362445SZachary Turner IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1, lldb::addr_t addr2, size_t size2) {
13515362445SZachary Turner   // Given two half open intervals [A, B) and [X, Y), the only 6 permutations that satisfy
13615362445SZachary Turner   // A<B and X<Y are the following:
13715362445SZachary Turner   // A B X Y
13815362445SZachary Turner   // A X B Y  (intersects)
13915362445SZachary Turner   // A X Y B  (intersects)
14015362445SZachary Turner   // X A B Y  (intersects)
14115362445SZachary Turner   // X A Y B  (intersects)
14215362445SZachary Turner   // X Y A B
14315362445SZachary Turner   // The first is B <= X, and the last is Y <= A.
14415362445SZachary Turner   // So the condition is !(B <= X || Y <= A)), or (X < B && A < Y)
14515362445SZachary Turner   return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
14615362445SZachary Turner }
14715362445SZachary Turner 
14835005f76SSean Callanan lldb::ByteOrder
14935005f76SSean Callanan IRMemoryMap::GetByteOrder()
15035005f76SSean Callanan {
15135005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
15235005f76SSean Callanan 
15335005f76SSean Callanan     if (process_sp)
15435005f76SSean Callanan         return process_sp->GetByteOrder();
15535005f76SSean Callanan 
15635005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
15735005f76SSean Callanan 
15835005f76SSean Callanan     if (target_sp)
15908052afaSSean Callanan         return target_sp->GetArchitecture().GetByteOrder();
16035005f76SSean Callanan 
16135005f76SSean Callanan     return lldb::eByteOrderInvalid;
16235005f76SSean Callanan }
16335005f76SSean Callanan 
16435005f76SSean Callanan uint32_t
16535005f76SSean Callanan IRMemoryMap::GetAddressByteSize()
16635005f76SSean Callanan {
16735005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
16835005f76SSean Callanan 
16935005f76SSean Callanan     if (process_sp)
17035005f76SSean Callanan         return process_sp->GetAddressByteSize();
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().GetAddressByteSize();
17635005f76SSean Callanan 
17735005f76SSean Callanan     return UINT32_MAX;
17835005f76SSean Callanan }
17935005f76SSean Callanan 
18035005f76SSean Callanan ExecutionContextScope *
18123f8c95aSGreg Clayton IRMemoryMap::GetBestExecutionContextScope() const
18235005f76SSean Callanan {
18335005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
18435005f76SSean Callanan 
18535005f76SSean Callanan     if (process_sp)
18635005f76SSean Callanan         return process_sp.get();
18735005f76SSean Callanan 
18835005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
18935005f76SSean Callanan 
19035005f76SSean Callanan     if (target_sp)
19135005f76SSean Callanan         return target_sp.get();
19235005f76SSean Callanan 
19335005f76SSean Callanan     return NULL;
19435005f76SSean Callanan }
19535005f76SSean Callanan 
196d2562509SSean Callanan IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
197d2562509SSean Callanan                                      lldb::addr_t process_start,
198d2562509SSean Callanan                                      size_t size,
199d2562509SSean Callanan                                      uint32_t permissions,
200d2562509SSean Callanan                                      uint8_t alignment,
2016fea779cSMichael Sartain                                      AllocationPolicy policy) :
2026fea779cSMichael Sartain     m_process_alloc (process_alloc),
2036fea779cSMichael Sartain     m_process_start (process_start),
2046fea779cSMichael Sartain     m_size (size),
2056fea779cSMichael Sartain     m_permissions (permissions),
2066fea779cSMichael Sartain     m_alignment (alignment),
2076fea779cSMichael Sartain     m_policy (policy),
2086fea779cSMichael Sartain     m_leak (false)
209d2562509SSean Callanan {
210d2562509SSean Callanan     switch (policy)
211d2562509SSean Callanan     {
212d2562509SSean Callanan         default:
213d2562509SSean Callanan             assert (0 && "We cannot reach this!");
214d2562509SSean Callanan         case eAllocationPolicyHostOnly:
215d2562509SSean Callanan             m_data.SetByteSize(size);
216d2562509SSean Callanan             memset(m_data.GetBytes(), 0, size);
217d2562509SSean Callanan             break;
218d2562509SSean Callanan         case eAllocationPolicyProcessOnly:
219d2562509SSean Callanan             break;
220d2562509SSean Callanan         case eAllocationPolicyMirror:
221d2562509SSean Callanan             m_data.SetByteSize(size);
222d2562509SSean Callanan             memset(m_data.GetBytes(), 0, size);
223d2562509SSean Callanan             break;
224d2562509SSean Callanan     }
225d2562509SSean Callanan }
226d2562509SSean Callanan 
2275a1af4e6SSean Callanan lldb::addr_t
2285a1af4e6SSean Callanan IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
2295a1af4e6SSean Callanan {
230af245d11STodd Fiala     lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
23108052afaSSean Callanan     error.Clear();
23208052afaSSean Callanan 
2335a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
2345a1af4e6SSean Callanan     lldb::addr_t    allocation_address  = LLDB_INVALID_ADDRESS;
2355a1af4e6SSean Callanan     lldb::addr_t    aligned_address     = LLDB_INVALID_ADDRESS;
2365a1af4e6SSean Callanan 
237750dcc33SMatt Kopec     size_t          alignment_mask = alignment - 1;
238750dcc33SMatt Kopec     size_t          allocation_size;
239750dcc33SMatt Kopec 
240750dcc33SMatt Kopec     if (size == 0)
241750dcc33SMatt Kopec         allocation_size = alignment;
242750dcc33SMatt Kopec     else
243750dcc33SMatt Kopec         allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size;
2445a1af4e6SSean Callanan 
2455a1af4e6SSean Callanan     switch (policy)
2465a1af4e6SSean Callanan     {
2475a1af4e6SSean Callanan     default:
2485a1af4e6SSean Callanan         error.SetErrorToGenericError();
2495a1af4e6SSean Callanan         error.SetErrorString("Couldn't malloc: invalid allocation policy");
2505a1af4e6SSean Callanan         return LLDB_INVALID_ADDRESS;
2515a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
2525a1af4e6SSean Callanan         allocation_address = FindSpace(allocation_size);
2535a1af4e6SSean Callanan         if (allocation_address == LLDB_INVALID_ADDRESS)
2545a1af4e6SSean Callanan         {
2555a1af4e6SSean Callanan             error.SetErrorToGenericError();
2565a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: address space is full");
2575a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
2585a1af4e6SSean Callanan         }
2595a1af4e6SSean Callanan         break;
2605a1af4e6SSean Callanan     case eAllocationPolicyMirror:
2615a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
262af245d11STodd Fiala         if (log)
263af245d11STodd Fiala             log->Printf ("IRMemoryMap::%s process_sp=0x%" PRIx64 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", __FUNCTION__, (lldb::addr_t) process_sp.get (), process_sp && process_sp->CanJIT () ? "true" : "false", process_sp && process_sp->IsAlive () ? "true" : "false");
264ad7cc466SSean Callanan         if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
2655a1af4e6SSean Callanan         {
2665a1af4e6SSean Callanan             allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
2675a1af4e6SSean Callanan             if (!error.Success())
2685a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
2695a1af4e6SSean Callanan         }
2705a1af4e6SSean Callanan         else
2715a1af4e6SSean Callanan         {
272af245d11STodd Fiala             if (log)
273af245d11STodd Fiala                 log->Printf ("IRMemoryMap::%s switching to eAllocationPolicyHostOnly due to failed condition (see previous expr log message)", __FUNCTION__);
274bb9945f4SSean Callanan             policy = eAllocationPolicyHostOnly;
2755a1af4e6SSean Callanan             allocation_address = FindSpace(allocation_size);
2765a1af4e6SSean Callanan             if (allocation_address == LLDB_INVALID_ADDRESS)
2775a1af4e6SSean Callanan             {
2785a1af4e6SSean Callanan                 error.SetErrorToGenericError();
2795a1af4e6SSean Callanan                 error.SetErrorString("Couldn't malloc: address space is full");
2805a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
2815a1af4e6SSean Callanan             }
2825a1af4e6SSean Callanan         }
2835a1af4e6SSean Callanan         break;
2845a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
2855a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
2865a1af4e6SSean Callanan         if (process_sp)
2875a1af4e6SSean Callanan         {
288ad7cc466SSean Callanan             if (process_sp->CanJIT() && process_sp->IsAlive())
289bb9945f4SSean Callanan             {
2905a1af4e6SSean Callanan                 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
2915a1af4e6SSean Callanan                 if (!error.Success())
2925a1af4e6SSean Callanan                     return LLDB_INVALID_ADDRESS;
2935a1af4e6SSean Callanan             }
2945a1af4e6SSean Callanan             else
2955a1af4e6SSean Callanan             {
2965a1af4e6SSean Callanan                 error.SetErrorToGenericError();
297bb9945f4SSean Callanan                 error.SetErrorString("Couldn't malloc: process doesn't support allocating memory");
298bb9945f4SSean Callanan                 return LLDB_INVALID_ADDRESS;
299bb9945f4SSean Callanan             }
300bb9945f4SSean Callanan         }
301bb9945f4SSean Callanan         else
302bb9945f4SSean Callanan         {
303bb9945f4SSean Callanan             error.SetErrorToGenericError();
3045a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
3055a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
3065a1af4e6SSean Callanan         }
3075a1af4e6SSean Callanan         break;
3085a1af4e6SSean Callanan     }
3095a1af4e6SSean Callanan 
3105a1af4e6SSean Callanan 
3115a1af4e6SSean Callanan     lldb::addr_t mask = alignment - 1;
3125a1af4e6SSean Callanan     aligned_address = (allocation_address + mask) & (~mask);
3135a1af4e6SSean Callanan 
314d2562509SSean Callanan     m_allocations[aligned_address] = Allocation(allocation_address,
315d2562509SSean Callanan                                                 aligned_address,
316750dcc33SMatt Kopec                                                 allocation_size,
317d2562509SSean Callanan                                                 permissions,
318d2562509SSean Callanan                                                 alignment,
319d2562509SSean Callanan                                                 policy);
3205a1af4e6SSean Callanan 
321af245d11STodd Fiala     if (log)
3225a1af4e6SSean Callanan     {
3235a1af4e6SSean Callanan         const char * policy_string;
3245a1af4e6SSean Callanan 
3255a1af4e6SSean Callanan         switch (policy)
3265a1af4e6SSean Callanan         {
3275a1af4e6SSean Callanan         default:
3285a1af4e6SSean Callanan             policy_string = "<invalid policy>";
3295a1af4e6SSean Callanan             break;
3305a1af4e6SSean Callanan         case eAllocationPolicyHostOnly:
3315a1af4e6SSean Callanan             policy_string = "eAllocationPolicyHostOnly";
3325a1af4e6SSean Callanan             break;
3335a1af4e6SSean Callanan         case eAllocationPolicyProcessOnly:
3345a1af4e6SSean Callanan             policy_string = "eAllocationPolicyProcessOnly";
3355a1af4e6SSean Callanan             break;
3365a1af4e6SSean Callanan         case eAllocationPolicyMirror:
3375a1af4e6SSean Callanan             policy_string = "eAllocationPolicyMirror";
3385a1af4e6SSean Callanan             break;
3395a1af4e6SSean Callanan         }
3405a1af4e6SSean Callanan 
341ef14371dSMatt Kopec         log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64,
342750dcc33SMatt Kopec                     (uint64_t)allocation_size,
3435a1af4e6SSean Callanan                     (uint64_t)alignment,
3445a1af4e6SSean Callanan                     (uint64_t)permissions,
3455a1af4e6SSean Callanan                     policy_string,
3465a1af4e6SSean Callanan                     aligned_address);
3475a1af4e6SSean Callanan     }
3485a1af4e6SSean Callanan 
3495a1af4e6SSean Callanan     return aligned_address;
3505a1af4e6SSean Callanan }
3515a1af4e6SSean Callanan 
3525a1af4e6SSean Callanan void
353fbf5c682SSean Callanan IRMemoryMap::Leak (lldb::addr_t process_address, Error &error)
354fbf5c682SSean Callanan {
355fbf5c682SSean Callanan     error.Clear();
356fbf5c682SSean Callanan 
357fbf5c682SSean Callanan     AllocationMap::iterator iter = m_allocations.find(process_address);
358fbf5c682SSean Callanan 
359fbf5c682SSean Callanan     if (iter == m_allocations.end())
360fbf5c682SSean Callanan     {
361fbf5c682SSean Callanan         error.SetErrorToGenericError();
362fbf5c682SSean Callanan         error.SetErrorString("Couldn't leak: allocation doesn't exist");
363fbf5c682SSean Callanan         return;
364fbf5c682SSean Callanan     }
365fbf5c682SSean Callanan 
366fbf5c682SSean Callanan     Allocation &allocation = iter->second;
367fbf5c682SSean Callanan 
368fbf5c682SSean Callanan     allocation.m_leak = true;
369fbf5c682SSean Callanan }
370fbf5c682SSean Callanan 
371fbf5c682SSean Callanan void
3725a1af4e6SSean Callanan IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
3735a1af4e6SSean Callanan {
37408052afaSSean Callanan     error.Clear();
37508052afaSSean Callanan 
3765a1af4e6SSean Callanan     AllocationMap::iterator iter = m_allocations.find(process_address);
3775a1af4e6SSean Callanan 
3785a1af4e6SSean Callanan     if (iter == m_allocations.end())
3795a1af4e6SSean Callanan     {
3805a1af4e6SSean Callanan         error.SetErrorToGenericError();
3815a1af4e6SSean Callanan         error.SetErrorString("Couldn't free: allocation doesn't exist");
3825a1af4e6SSean Callanan         return;
3835a1af4e6SSean Callanan     }
3845a1af4e6SSean Callanan 
3855a1af4e6SSean Callanan     Allocation &allocation = iter->second;
3865a1af4e6SSean Callanan 
3875a1af4e6SSean Callanan     switch (allocation.m_policy)
3885a1af4e6SSean Callanan     {
3895a1af4e6SSean Callanan     default:
3905a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
391df56540aSSean Callanan         {
392df56540aSSean Callanan             lldb::ProcessSP process_sp = m_process_wp.lock();
393bb77704cSSean Callanan             if (process_sp)
394bb77704cSSean Callanan             {
395ad7cc466SSean Callanan                 if (process_sp->CanJIT() && process_sp->IsAlive())
396df56540aSSean Callanan                     process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
397bb77704cSSean Callanan             }
398df56540aSSean Callanan 
3995a1af4e6SSean Callanan             break;
400df56540aSSean Callanan         }
4015a1af4e6SSean Callanan     case eAllocationPolicyMirror:
4025a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
403df56540aSSean Callanan         {
4045a1af4e6SSean Callanan             lldb::ProcessSP process_sp = m_process_wp.lock();
4055a1af4e6SSean Callanan             if (process_sp)
4065a1af4e6SSean Callanan                 process_sp->DeallocateMemory(allocation.m_process_alloc);
4075a1af4e6SSean Callanan         }
408df56540aSSean Callanan     }
4095a1af4e6SSean Callanan 
4105a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
4115a1af4e6SSean Callanan     {
412ef14371dSMatt Kopec         log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")",
4135a1af4e6SSean Callanan                     (uint64_t)process_address,
4145a1af4e6SSean Callanan                     iter->second.m_process_start,
4155a1af4e6SSean Callanan                     iter->second.m_process_start + iter->second.m_size);
4165a1af4e6SSean Callanan     }
4175a1af4e6SSean Callanan 
4185a1af4e6SSean Callanan     m_allocations.erase(iter);
4195a1af4e6SSean Callanan }
4205a1af4e6SSean Callanan 
4215a1af4e6SSean Callanan void
4225a1af4e6SSean Callanan IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
4235a1af4e6SSean Callanan {
42408052afaSSean Callanan     error.Clear();
42508052afaSSean Callanan 
4265a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
4275a1af4e6SSean Callanan 
4285a1af4e6SSean Callanan     if (iter == m_allocations.end())
4295a1af4e6SSean Callanan     {
430c8c5b8dcSSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
431c8c5b8dcSSean Callanan 
432c8c5b8dcSSean Callanan         if (process_sp)
433c8c5b8dcSSean Callanan         {
434c8c5b8dcSSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
435c8c5b8dcSSean Callanan             return;
436c8c5b8dcSSean Callanan         }
437c8c5b8dcSSean Callanan 
4385a1af4e6SSean Callanan         error.SetErrorToGenericError();
439c8c5b8dcSSean Callanan         error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
4405a1af4e6SSean Callanan         return;
4415a1af4e6SSean Callanan     }
4425a1af4e6SSean Callanan 
4435a1af4e6SSean Callanan     Allocation &allocation = iter->second;
4445a1af4e6SSean Callanan 
4455a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
4465a1af4e6SSean Callanan 
4475a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
4485a1af4e6SSean Callanan 
4495a1af4e6SSean Callanan     switch (allocation.m_policy)
4505a1af4e6SSean Callanan     {
4515a1af4e6SSean Callanan     default:
4525a1af4e6SSean Callanan         error.SetErrorToGenericError();
4535a1af4e6SSean Callanan         error.SetErrorString("Couldn't write: invalid allocation policy");
4545a1af4e6SSean Callanan         return;
4555a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
456d2562509SSean Callanan         if (!allocation.m_data.GetByteSize())
4575a1af4e6SSean Callanan         {
4585a1af4e6SSean Callanan             error.SetErrorToGenericError();
4595a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
4605a1af4e6SSean Callanan             return;
4615a1af4e6SSean Callanan         }
462d2562509SSean Callanan         ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
4635a1af4e6SSean Callanan         break;
4645a1af4e6SSean Callanan     case eAllocationPolicyMirror:
465d2562509SSean Callanan         if (!allocation.m_data.GetByteSize())
4665a1af4e6SSean Callanan         {
4675a1af4e6SSean Callanan             error.SetErrorToGenericError();
4685a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
4695a1af4e6SSean Callanan             return;
4705a1af4e6SSean Callanan         }
471d2562509SSean Callanan         ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
4725a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
4735a1af4e6SSean Callanan         if (process_sp)
4745a1af4e6SSean Callanan         {
4755a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
4765a1af4e6SSean Callanan             if (!error.Success())
4775a1af4e6SSean Callanan                 return;
4785a1af4e6SSean Callanan         }
4795a1af4e6SSean Callanan         break;
4805a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
4815a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
4825a1af4e6SSean Callanan         if (process_sp)
4835a1af4e6SSean Callanan         {
4845a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
4855a1af4e6SSean Callanan             if (!error.Success())
4865a1af4e6SSean Callanan                 return;
4875a1af4e6SSean Callanan         }
4885a1af4e6SSean Callanan         break;
4895a1af4e6SSean Callanan     }
4905a1af4e6SSean Callanan 
4915a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
4925a1af4e6SSean Callanan     {
493ef14371dSMatt Kopec         log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
4945a1af4e6SSean Callanan                     (uint64_t)process_address,
4955a1af4e6SSean Callanan                     (uint64_t)bytes,
4965a1af4e6SSean Callanan                     (uint64_t)size,
4975a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
4985a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
4995a1af4e6SSean Callanan     }
5005a1af4e6SSean Callanan }
5015a1af4e6SSean Callanan 
5025a1af4e6SSean Callanan void
50335005f76SSean Callanan IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
50435005f76SSean Callanan {
50508052afaSSean Callanan     error.Clear();
50608052afaSSean Callanan 
50735005f76SSean Callanan     if (size == UINT32_MAX)
50835005f76SSean Callanan         size = scalar.GetByteSize();
50935005f76SSean Callanan 
51035005f76SSean Callanan     if (size > 0)
51135005f76SSean Callanan     {
51235005f76SSean Callanan         uint8_t buf[32];
51335005f76SSean Callanan         const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
51435005f76SSean Callanan         if (mem_size > 0)
51535005f76SSean Callanan         {
51635005f76SSean Callanan             return WriteMemory(process_address, buf, mem_size, error);
51735005f76SSean Callanan         }
51835005f76SSean Callanan         else
51935005f76SSean Callanan         {
52035005f76SSean Callanan             error.SetErrorToGenericError();
52135005f76SSean Callanan             error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
52235005f76SSean Callanan         }
52335005f76SSean Callanan     }
52435005f76SSean Callanan     else
52535005f76SSean Callanan     {
52635005f76SSean Callanan         error.SetErrorToGenericError();
52735005f76SSean Callanan         error.SetErrorString ("Couldn't write scalar: its size was zero");
52835005f76SSean Callanan     }
52935005f76SSean Callanan     return;
53035005f76SSean Callanan }
53135005f76SSean Callanan 
53235005f76SSean Callanan void
533f8043fa5SSean Callanan IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
534f8043fa5SSean Callanan {
53508052afaSSean Callanan     error.Clear();
53608052afaSSean Callanan 
537f8043fa5SSean Callanan     Scalar scalar(address);
538f8043fa5SSean Callanan 
539f8043fa5SSean Callanan     WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
540f8043fa5SSean Callanan }
541f8043fa5SSean Callanan 
542f8043fa5SSean Callanan void
5435a1af4e6SSean Callanan IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
5445a1af4e6SSean Callanan {
54508052afaSSean Callanan     error.Clear();
54608052afaSSean Callanan 
5475a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
5485a1af4e6SSean Callanan 
5495a1af4e6SSean Callanan     if (iter == m_allocations.end())
5505a1af4e6SSean Callanan     {
551c8c5b8dcSSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
552c8c5b8dcSSean Callanan 
553c8c5b8dcSSean Callanan         if (process_sp)
554c8c5b8dcSSean Callanan         {
555c8c5b8dcSSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
556c8c5b8dcSSean Callanan             return;
557c8c5b8dcSSean Callanan         }
558c8c5b8dcSSean Callanan 
559c8c5b8dcSSean Callanan         lldb::TargetSP target_sp = m_target_wp.lock();
560c8c5b8dcSSean Callanan 
561c8c5b8dcSSean Callanan         if (target_sp)
562c8c5b8dcSSean Callanan         {
563c8c5b8dcSSean Callanan             Address absolute_address(process_address);
564c8c5b8dcSSean Callanan             target_sp->ReadMemory(absolute_address, false, bytes, size, error);
565c8c5b8dcSSean Callanan             return;
566c8c5b8dcSSean Callanan         }
567c8c5b8dcSSean Callanan 
5685a1af4e6SSean Callanan         error.SetErrorToGenericError();
569c8c5b8dcSSean Callanan         error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist");
5705a1af4e6SSean Callanan         return;
5715a1af4e6SSean Callanan     }
5725a1af4e6SSean Callanan 
5735a1af4e6SSean Callanan     Allocation &allocation = iter->second;
5745a1af4e6SSean Callanan 
5755a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
5765a1af4e6SSean Callanan 
5779bbf3cd3SSean Callanan     if (offset > allocation.m_size)
5789bbf3cd3SSean Callanan     {
5799bbf3cd3SSean Callanan         error.SetErrorToGenericError();
5809bbf3cd3SSean Callanan         error.SetErrorString("Couldn't read: data is not in the allocation");
5819bbf3cd3SSean Callanan         return;
5829bbf3cd3SSean Callanan     }
5839bbf3cd3SSean Callanan 
5845a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
5855a1af4e6SSean Callanan 
5865a1af4e6SSean Callanan     switch (allocation.m_policy)
5875a1af4e6SSean Callanan     {
5885a1af4e6SSean Callanan     default:
5895a1af4e6SSean Callanan         error.SetErrorToGenericError();
5905a1af4e6SSean Callanan         error.SetErrorString("Couldn't read: invalid allocation policy");
5915a1af4e6SSean Callanan         return;
5925a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
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         }
5999bbf3cd3SSean Callanan         if (allocation.m_data.GetByteSize() < offset + size)
6009bbf3cd3SSean Callanan         {
6019bbf3cd3SSean Callanan             error.SetErrorToGenericError();
6029bbf3cd3SSean Callanan             error.SetErrorString("Couldn't read: not enough underlying data");
6039bbf3cd3SSean Callanan             return;
6049bbf3cd3SSean Callanan         }
6059bbf3cd3SSean Callanan 
606d2562509SSean Callanan         ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
6075a1af4e6SSean Callanan         break;
6085a1af4e6SSean Callanan     case eAllocationPolicyMirror:
6095a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
6105a1af4e6SSean Callanan         if (process_sp)
6115a1af4e6SSean Callanan         {
6125a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
6135a1af4e6SSean Callanan             if (!error.Success())
6145a1af4e6SSean Callanan                 return;
6155a1af4e6SSean Callanan         }
6165a1af4e6SSean Callanan         else
6175a1af4e6SSean Callanan         {
618d2562509SSean Callanan             if (!allocation.m_data.GetByteSize())
6195a1af4e6SSean Callanan             {
6205a1af4e6SSean Callanan                 error.SetErrorToGenericError();
6215a1af4e6SSean Callanan                 error.SetErrorString("Couldn't read: data buffer is empty");
6225a1af4e6SSean Callanan                 return;
6235a1af4e6SSean Callanan             }
624d2562509SSean Callanan             ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
6255a1af4e6SSean Callanan         }
6265a1af4e6SSean Callanan         break;
6275a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
6285a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
6295a1af4e6SSean Callanan         if (process_sp)
6305a1af4e6SSean Callanan         {
6315a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
6325a1af4e6SSean Callanan             if (!error.Success())
6335a1af4e6SSean Callanan                 return;
6345a1af4e6SSean Callanan         }
6355a1af4e6SSean Callanan         break;
6365a1af4e6SSean Callanan     }
6375a1af4e6SSean Callanan 
6385a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
6395a1af4e6SSean Callanan     {
640ef14371dSMatt Kopec         log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
6415a1af4e6SSean Callanan                     (uint64_t)process_address,
6425a1af4e6SSean Callanan                     (uint64_t)bytes,
6435a1af4e6SSean Callanan                     (uint64_t)size,
6445a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
6455a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
6465a1af4e6SSean Callanan     }
6475a1af4e6SSean Callanan }
64835005f76SSean Callanan 
64935005f76SSean Callanan void
65035005f76SSean Callanan IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
65135005f76SSean Callanan {
65208052afaSSean Callanan     error.Clear();
65308052afaSSean Callanan 
65435005f76SSean Callanan     if (size > 0)
65535005f76SSean Callanan     {
65635005f76SSean Callanan         DataBufferHeap buf(size, 0);
65735005f76SSean Callanan         ReadMemory(buf.GetBytes(), process_address, size, error);
65835005f76SSean Callanan 
65935005f76SSean Callanan         if (!error.Success())
66035005f76SSean Callanan             return;
66135005f76SSean Callanan 
66235005f76SSean Callanan         DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
66335005f76SSean Callanan 
66435005f76SSean Callanan         lldb::offset_t offset = 0;
66535005f76SSean Callanan 
66635005f76SSean Callanan         switch (size)
66735005f76SSean Callanan         {
66835005f76SSean Callanan         default:
66935005f76SSean Callanan             error.SetErrorToGenericError();
670e86cef63SGreg Clayton             error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
67135005f76SSean Callanan             return;
67235005f76SSean Callanan         case 1: scalar = extractor.GetU8(&offset);  break;
67335005f76SSean Callanan         case 2: scalar = extractor.GetU16(&offset); break;
67435005f76SSean Callanan         case 4: scalar = extractor.GetU32(&offset); break;
67535005f76SSean Callanan         case 8: scalar = extractor.GetU64(&offset); break;
67635005f76SSean Callanan         }
67735005f76SSean Callanan     }
67835005f76SSean Callanan     else
67935005f76SSean Callanan     {
68035005f76SSean Callanan         error.SetErrorToGenericError();
681458ae1c6SSean Callanan         error.SetErrorString ("Couldn't read scalar: its size was zero");
68235005f76SSean Callanan     }
68335005f76SSean Callanan     return;
68435005f76SSean Callanan }
68535005f76SSean Callanan 
686458ae1c6SSean Callanan void
6872d37e5a5SSean Callanan IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
6882d37e5a5SSean Callanan {
68908052afaSSean Callanan     error.Clear();
69008052afaSSean Callanan 
6912d37e5a5SSean Callanan     Scalar pointer_scalar;
6922d37e5a5SSean Callanan     ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
6932d37e5a5SSean Callanan 
6942d37e5a5SSean Callanan     if (!error.Success())
6952d37e5a5SSean Callanan         return;
6962d37e5a5SSean Callanan 
6972d37e5a5SSean Callanan     *address = pointer_scalar.ULongLong();
6982d37e5a5SSean Callanan 
6992d37e5a5SSean Callanan     return;
7002d37e5a5SSean Callanan }
7012d37e5a5SSean Callanan 
7022d37e5a5SSean Callanan void
703458ae1c6SSean Callanan IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
704458ae1c6SSean Callanan {
70508052afaSSean Callanan     error.Clear();
70608052afaSSean Callanan 
707458ae1c6SSean Callanan     if (size > 0)
708458ae1c6SSean Callanan     {
709458ae1c6SSean Callanan         AllocationMap::iterator iter = FindAllocation(process_address, size);
710458ae1c6SSean Callanan 
711458ae1c6SSean Callanan         if (iter == m_allocations.end())
712458ae1c6SSean Callanan         {
713458ae1c6SSean Callanan             error.SetErrorToGenericError();
714ef14371dSMatt Kopec             error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size);
715458ae1c6SSean Callanan             return;
716458ae1c6SSean Callanan         }
717458ae1c6SSean Callanan 
718458ae1c6SSean Callanan         Allocation &allocation = iter->second;
719458ae1c6SSean Callanan 
720458ae1c6SSean Callanan         switch (allocation.m_policy)
721458ae1c6SSean Callanan         {
722458ae1c6SSean Callanan         default:
723458ae1c6SSean Callanan             error.SetErrorToGenericError();
724458ae1c6SSean Callanan             error.SetErrorString("Couldn't get memory data: invalid allocation policy");
725458ae1c6SSean Callanan             return;
726458ae1c6SSean Callanan         case eAllocationPolicyProcessOnly:
727458ae1c6SSean Callanan             error.SetErrorToGenericError();
728458ae1c6SSean Callanan             error.SetErrorString("Couldn't get memory data: memory is only in the target");
729458ae1c6SSean Callanan             return;
730458ae1c6SSean Callanan         case eAllocationPolicyMirror:
731c8c5b8dcSSean Callanan             {
732c8c5b8dcSSean Callanan                 lldb::ProcessSP process_sp = m_process_wp.lock();
733c8c5b8dcSSean Callanan 
734d2562509SSean Callanan                 if (!allocation.m_data.GetByteSize())
735c8c5b8dcSSean Callanan                 {
736c8c5b8dcSSean Callanan                     error.SetErrorToGenericError();
737c8c5b8dcSSean Callanan                     error.SetErrorString("Couldn't get memory data: data buffer is empty");
738c8c5b8dcSSean Callanan                     return;
739c8c5b8dcSSean Callanan                 }
740c8c5b8dcSSean Callanan                 if (process_sp)
741c8c5b8dcSSean Callanan                 {
742d2562509SSean Callanan                     process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error);
743c8c5b8dcSSean Callanan                     if (!error.Success())
744c8c5b8dcSSean Callanan                         return;
745c8c5b8dcSSean Callanan                     uint64_t offset = process_address - allocation.m_process_start;
746d2562509SSean Callanan                     extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
747c8c5b8dcSSean Callanan                     return;
748c8c5b8dcSSean Callanan                 }
749c8c5b8dcSSean Callanan             }
750c8c5b8dcSSean Callanan         case eAllocationPolicyHostOnly:
751d2562509SSean Callanan             if (!allocation.m_data.GetByteSize())
752458ae1c6SSean Callanan             {
753458ae1c6SSean Callanan                 error.SetErrorToGenericError();
754458ae1c6SSean Callanan                 error.SetErrorString("Couldn't get memory data: data buffer is empty");
755458ae1c6SSean Callanan                 return;
756458ae1c6SSean Callanan             }
757458ae1c6SSean Callanan             uint64_t offset = process_address - allocation.m_process_start;
758d2562509SSean Callanan             extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
759458ae1c6SSean Callanan             return;
760458ae1c6SSean Callanan         }
761458ae1c6SSean Callanan     }
762458ae1c6SSean Callanan     else
763458ae1c6SSean Callanan     {
764458ae1c6SSean Callanan         error.SetErrorToGenericError();
765458ae1c6SSean Callanan         error.SetErrorString ("Couldn't get memory data: its size was zero");
766458ae1c6SSean Callanan         return;
767458ae1c6SSean Callanan     }
768458ae1c6SSean Callanan }
769