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"
16*f3df7e86SSean Callanan #include "lldb/Target/MemoryRegionInfo.h"
175a1af4e6SSean Callanan #include "lldb/Target/Process.h"
1835005f76SSean Callanan #include "lldb/Target/Target.h"
19*f3df7e86SSean Callanan #include "lldb/Utility/LLDBAssert.h"
205a1af4e6SSean Callanan 
215a1af4e6SSean Callanan using namespace lldb_private;
225a1af4e6SSean Callanan 
2335005f76SSean Callanan IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) :
2435005f76SSean Callanan     m_target_wp(target_sp)
255a1af4e6SSean Callanan {
26b024d878SSean Callanan     if (target_sp)
27b024d878SSean Callanan         m_process_wp = target_sp->GetProcessSP();
285a1af4e6SSean Callanan }
295a1af4e6SSean Callanan 
305a1af4e6SSean Callanan IRMemoryMap::~IRMemoryMap ()
315a1af4e6SSean Callanan {
325a1af4e6SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
335a1af4e6SSean Callanan 
345a1af4e6SSean Callanan     if (process_sp)
355a1af4e6SSean Callanan     {
36bb77704cSSean Callanan         AllocationMap::iterator iter;
375a1af4e6SSean Callanan 
38bb77704cSSean Callanan         Error err;
39bb77704cSSean Callanan 
40bb77704cSSean Callanan         while ((iter = m_allocations.begin()) != m_allocations.end())
415a1af4e6SSean Callanan         {
42bb77704cSSean Callanan             err.Clear();
43fbf5c682SSean Callanan             if (iter->second.m_leak)
44fbf5c682SSean Callanan                 m_allocations.erase(iter);
45fbf5c682SSean Callanan             else
46bb77704cSSean Callanan                 Free(iter->first, err);
475a1af4e6SSean Callanan         }
485a1af4e6SSean Callanan     }
495a1af4e6SSean Callanan }
505a1af4e6SSean Callanan 
515a1af4e6SSean Callanan lldb::addr_t
52*f3df7e86SSean Callanan IRMemoryMap::FindSpace (size_t size)
535a1af4e6SSean Callanan {
54*f3df7e86SSean Callanan     // The FindSpace algorithm's job is to find a region of memory that the
55*f3df7e86SSean Callanan     // underlying process is unlikely to be using.
56*f3df7e86SSean Callanan     //
57*f3df7e86SSean Callanan     // The memory returned by this function will never be written to.  The only
58*f3df7e86SSean Callanan     // point is that it should not shadow process memory if possible, so that
59*f3df7e86SSean Callanan     // expressions processing real values from the process do not use the
60*f3df7e86SSean Callanan     // wrong data.
61*f3df7e86SSean Callanan     //
62*f3df7e86SSean Callanan     // If the process can in fact allocate memory (CanJIT() lets us know this)
63*f3df7e86SSean Callanan     // then this can be accomplished just be allocating memory in the inferior.
64*f3df7e86SSean Callanan     // Then no guessing is required.
65*f3df7e86SSean Callanan 
66bb9945f4SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
67bb9945f4SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
685a1af4e6SSean Callanan 
69*f3df7e86SSean Callanan     const bool process_is_alive = process_sp && process_sp->IsAlive();
70*f3df7e86SSean Callanan 
71bb9945f4SSean Callanan     lldb::addr_t ret = LLDB_INVALID_ADDRESS;
723ddcd314SZachary Turner     if (size == 0)
733ddcd314SZachary Turner         return ret;
745a1af4e6SSean Callanan 
75*f3df7e86SSean Callanan     if (process_is_alive && process_sp->CanJIT())
76df56540aSSean Callanan     {
77df56540aSSean Callanan         Error alloc_error;
78df56540aSSean Callanan 
79df56540aSSean Callanan         ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
80df56540aSSean Callanan 
81df56540aSSean Callanan         if (!alloc_error.Success())
82df56540aSSean Callanan             return LLDB_INVALID_ADDRESS;
83df56540aSSean Callanan         else
84df56540aSSean Callanan             return ret;
85df56540aSSean Callanan     }
86df56540aSSean Callanan 
87*f3df7e86SSean Callanan     // At this point we know that we need to hunt.
88*f3df7e86SSean Callanan     //
89*f3df7e86SSean Callanan     // First, go to the end of the existing allocations we've made if there are
90*f3df7e86SSean Callanan     // any allocations.  Otherwise start at the beginning of memory.
91*f3df7e86SSean Callanan 
92*f3df7e86SSean Callanan     if (m_allocations.empty())
93*f3df7e86SSean Callanan     {
94*f3df7e86SSean Callanan         ret = 0x0;
95*f3df7e86SSean Callanan     }
96*f3df7e86SSean Callanan     else
97*f3df7e86SSean Callanan     {
98*f3df7e86SSean Callanan         auto back = m_allocations.rbegin();
99*f3df7e86SSean Callanan         lldb::addr_t addr = back->first;
100*f3df7e86SSean Callanan         size_t alloc_size = back->second.m_size;
101*f3df7e86SSean Callanan         ret = llvm::alignTo(addr+alloc_size, 4096);
102*f3df7e86SSean Callanan     }
103*f3df7e86SSean Callanan 
104*f3df7e86SSean Callanan     // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped
105*f3df7e86SSean Callanan     // regions, walk forward through memory until a region is found that
106*f3df7e86SSean Callanan     // has adequate space for our allocation.
107*f3df7e86SSean Callanan     if (process_is_alive)
108*f3df7e86SSean Callanan     {
109*f3df7e86SSean Callanan         const uint64_t end_of_memory = process_sp->GetAddressByteSize() == 8 ?
110*f3df7e86SSean Callanan             0xffffffffffffffffull : 0xffffffffull;
111*f3df7e86SSean Callanan 
112*f3df7e86SSean Callanan         lldbassert(process_sp->GetAddressByteSize() == 4 || end_of_memory != 0xffffffffull);
113*f3df7e86SSean Callanan 
114*f3df7e86SSean Callanan         MemoryRegionInfo region_info;
115*f3df7e86SSean Callanan         Error err = process_sp->GetMemoryRegionInfo(ret, region_info);
116*f3df7e86SSean Callanan         if (err.Success())
117*f3df7e86SSean Callanan         {
118*f3df7e86SSean Callanan             while (true)
119*f3df7e86SSean Callanan             {
120*f3df7e86SSean Callanan                 if (region_info.GetReadable() != MemoryRegionInfo::OptionalBool::eNo ||
121*f3df7e86SSean Callanan                     region_info.GetWritable() != MemoryRegionInfo::OptionalBool::eNo ||
122*f3df7e86SSean Callanan                     region_info.GetExecutable() != MemoryRegionInfo::OptionalBool::eNo)
123*f3df7e86SSean Callanan                 {
124*f3df7e86SSean Callanan                     if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory)
125*f3df7e86SSean Callanan                     {
126*f3df7e86SSean Callanan                         ret = LLDB_INVALID_ADDRESS;
127*f3df7e86SSean Callanan                         break;
128*f3df7e86SSean Callanan                     }
129*f3df7e86SSean Callanan                     else
130*f3df7e86SSean Callanan                     {
131*f3df7e86SSean Callanan                         ret = region_info.GetRange().GetRangeEnd();
132*f3df7e86SSean Callanan                     }
133*f3df7e86SSean Callanan                 }
134*f3df7e86SSean Callanan                 else if (ret + size < region_info.GetRange().GetRangeEnd())
135*f3df7e86SSean Callanan                 {
136*f3df7e86SSean Callanan                     return ret;
137*f3df7e86SSean Callanan                 }
138*f3df7e86SSean Callanan                 else
139*f3df7e86SSean Callanan                 {
140*f3df7e86SSean Callanan                     // ret stays the same.  We just need to walk a bit further.
141*f3df7e86SSean Callanan                 }
142*f3df7e86SSean Callanan 
143*f3df7e86SSean Callanan                 err = process_sp->GetMemoryRegionInfo(region_info.GetRange().GetRangeEnd(), region_info);
144*f3df7e86SSean Callanan                 if (err.Fail())
145*f3df7e86SSean Callanan                 {
146*f3df7e86SSean Callanan                     lldbassert(!"GetMemoryRegionInfo() succeeded, then failed");
147*f3df7e86SSean Callanan                     ret = LLDB_INVALID_ADDRESS;
148*f3df7e86SSean Callanan                     break;
149*f3df7e86SSean Callanan                 }
150*f3df7e86SSean Callanan             }
151*f3df7e86SSean Callanan         }
152*f3df7e86SSean Callanan     }
153*f3df7e86SSean Callanan 
154*f3df7e86SSean Callanan     // We've tried our algorithm, and it didn't work.  Now we have to reset back
155*f3df7e86SSean Callanan     // to the end of the allocations we've already reported, or use a 'sensible'
156*f3df7e86SSean Callanan     // default if this is our first allocation.
157*f3df7e86SSean Callanan 
158*f3df7e86SSean Callanan     if (m_allocations.empty())
159*f3df7e86SSean Callanan     {
160*f3df7e86SSean Callanan         uint32_t address_byte_size = GetAddressByteSize();
161*f3df7e86SSean Callanan         if (address_byte_size != UINT32_MAX)
162*f3df7e86SSean Callanan         {
163*f3df7e86SSean Callanan             switch (address_byte_size)
164*f3df7e86SSean Callanan             {
165*f3df7e86SSean Callanan                 case 8:
166*f3df7e86SSean Callanan                     ret = 0xffffffff00000000ull;
167*f3df7e86SSean Callanan                     break;
168*f3df7e86SSean Callanan                 case 4:
169*f3df7e86SSean Callanan                     ret = 0xee000000ull;
170*f3df7e86SSean Callanan                     break;
171*f3df7e86SSean Callanan                 default:
172*f3df7e86SSean Callanan                     break;
173*f3df7e86SSean Callanan             }
174*f3df7e86SSean Callanan         }
175*f3df7e86SSean Callanan     }
176*f3df7e86SSean Callanan     else
1775a1af4e6SSean Callanan     {
1783ddcd314SZachary Turner         auto back = m_allocations.rbegin();
1793ddcd314SZachary Turner         lldb::addr_t addr = back->first;
1803ddcd314SZachary Turner         size_t alloc_size = back->second.m_size;
181a94ae1e0SRafael Espindola         ret = llvm::alignTo(addr+alloc_size, 4096);
1825a1af4e6SSean Callanan     }
1835a1af4e6SSean Callanan 
184bb9945f4SSean Callanan     return ret;
1855a1af4e6SSean Callanan }
1865a1af4e6SSean Callanan 
1875a1af4e6SSean Callanan IRMemoryMap::AllocationMap::iterator
1885a1af4e6SSean Callanan IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
1895a1af4e6SSean Callanan {
1901582ee68SSean Callanan     if (addr == LLDB_INVALID_ADDRESS)
1911582ee68SSean Callanan         return m_allocations.end();
1921582ee68SSean Callanan 
1935a1af4e6SSean Callanan     AllocationMap::iterator iter = m_allocations.lower_bound (addr);
1945a1af4e6SSean Callanan 
19514b1bae5SSean Callanan     if (iter == m_allocations.end() ||
19614b1bae5SSean Callanan         iter->first > addr)
1975a1af4e6SSean Callanan     {
1985a1af4e6SSean Callanan         if (iter == m_allocations.begin())
1995a1af4e6SSean Callanan             return m_allocations.end();
2005a1af4e6SSean Callanan         iter--;
2015a1af4e6SSean Callanan     }
2025a1af4e6SSean Callanan 
2035a1af4e6SSean Callanan     if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
2045a1af4e6SSean Callanan         return iter;
2055a1af4e6SSean Callanan 
2065a1af4e6SSean Callanan     return m_allocations.end();
2075a1af4e6SSean Callanan }
2085a1af4e6SSean Callanan 
209bb9945f4SSean Callanan bool
21015362445SZachary Turner IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size) const
211bb9945f4SSean Callanan {
212bb9945f4SSean Callanan     if (addr == LLDB_INVALID_ADDRESS)
213bb9945f4SSean Callanan         return false;
214bb9945f4SSean Callanan 
21515362445SZachary Turner     AllocationMap::const_iterator iter = m_allocations.lower_bound (addr);
216bb9945f4SSean Callanan 
21715362445SZachary Turner     // Since we only know that the returned interval begins at a location greater than or
21815362445SZachary Turner     // equal to where the given interval begins, it's possible that the given interval
21915362445SZachary Turner     // intersects either the returned interval or the previous interval.  Thus, we need to
22015362445SZachary Turner     // check both. Note that we only need to check these two intervals.  Since all intervals
22115362445SZachary Turner     // are disjoint it is not possible that an adjacent interval does not intersect, but a
22215362445SZachary Turner     // non-adjacent interval does intersect.
22315362445SZachary Turner     if (iter != m_allocations.end()) {
224cfcd7914SZachary Turner         if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
225bb9945f4SSean Callanan             return true;
22615362445SZachary Turner     }
227bb9945f4SSean Callanan 
22815362445SZachary Turner     if (iter != m_allocations.begin()) {
22915362445SZachary Turner         --iter;
230cfcd7914SZachary Turner         if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
23115362445SZachary Turner             return true;
232bb9945f4SSean Callanan     }
233bb9945f4SSean Callanan 
234bb9945f4SSean Callanan     return false;
235bb9945f4SSean Callanan }
236bb9945f4SSean Callanan 
23715362445SZachary Turner bool
23815362445SZachary Turner IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1, lldb::addr_t addr2, size_t size2) {
23915362445SZachary Turner   // Given two half open intervals [A, B) and [X, Y), the only 6 permutations that satisfy
24015362445SZachary Turner   // A<B and X<Y are the following:
24115362445SZachary Turner   // A B X Y
24215362445SZachary Turner   // A X B Y  (intersects)
24315362445SZachary Turner   // A X Y B  (intersects)
24415362445SZachary Turner   // X A B Y  (intersects)
24515362445SZachary Turner   // X A Y B  (intersects)
24615362445SZachary Turner   // X Y A B
24715362445SZachary Turner   // The first is B <= X, and the last is Y <= A.
24815362445SZachary Turner   // So the condition is !(B <= X || Y <= A)), or (X < B && A < Y)
24915362445SZachary Turner   return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
25015362445SZachary Turner }
25115362445SZachary Turner 
25235005f76SSean Callanan lldb::ByteOrder
25335005f76SSean Callanan IRMemoryMap::GetByteOrder()
25435005f76SSean Callanan {
25535005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
25635005f76SSean Callanan 
25735005f76SSean Callanan     if (process_sp)
25835005f76SSean Callanan         return process_sp->GetByteOrder();
25935005f76SSean Callanan 
26035005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
26135005f76SSean Callanan 
26235005f76SSean Callanan     if (target_sp)
26308052afaSSean Callanan         return target_sp->GetArchitecture().GetByteOrder();
26435005f76SSean Callanan 
26535005f76SSean Callanan     return lldb::eByteOrderInvalid;
26635005f76SSean Callanan }
26735005f76SSean Callanan 
26835005f76SSean Callanan uint32_t
26935005f76SSean Callanan IRMemoryMap::GetAddressByteSize()
27035005f76SSean Callanan {
27135005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
27235005f76SSean Callanan 
27335005f76SSean Callanan     if (process_sp)
27435005f76SSean Callanan         return process_sp->GetAddressByteSize();
27535005f76SSean Callanan 
27635005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
27735005f76SSean Callanan 
27835005f76SSean Callanan     if (target_sp)
27908052afaSSean Callanan         return target_sp->GetArchitecture().GetAddressByteSize();
28035005f76SSean Callanan 
28135005f76SSean Callanan     return UINT32_MAX;
28235005f76SSean Callanan }
28335005f76SSean Callanan 
28435005f76SSean Callanan ExecutionContextScope *
28523f8c95aSGreg Clayton IRMemoryMap::GetBestExecutionContextScope() const
28635005f76SSean Callanan {
28735005f76SSean Callanan     lldb::ProcessSP process_sp = m_process_wp.lock();
28835005f76SSean Callanan 
28935005f76SSean Callanan     if (process_sp)
29035005f76SSean Callanan         return process_sp.get();
29135005f76SSean Callanan 
29235005f76SSean Callanan     lldb::TargetSP target_sp = m_target_wp.lock();
29335005f76SSean Callanan 
29435005f76SSean Callanan     if (target_sp)
29535005f76SSean Callanan         return target_sp.get();
29635005f76SSean Callanan 
29735005f76SSean Callanan     return NULL;
29835005f76SSean Callanan }
29935005f76SSean Callanan 
300d2562509SSean Callanan IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
301d2562509SSean Callanan                                      lldb::addr_t process_start,
302d2562509SSean Callanan                                      size_t size,
303d2562509SSean Callanan                                      uint32_t permissions,
304d2562509SSean Callanan                                      uint8_t alignment,
3056fea779cSMichael Sartain                                      AllocationPolicy policy) :
3066fea779cSMichael Sartain     m_process_alloc (process_alloc),
3076fea779cSMichael Sartain     m_process_start (process_start),
3086fea779cSMichael Sartain     m_size (size),
3096fea779cSMichael Sartain     m_permissions (permissions),
3106fea779cSMichael Sartain     m_alignment (alignment),
3116fea779cSMichael Sartain     m_policy (policy),
3126fea779cSMichael Sartain     m_leak (false)
313d2562509SSean Callanan {
314d2562509SSean Callanan     switch (policy)
315d2562509SSean Callanan     {
316d2562509SSean Callanan         default:
317d2562509SSean Callanan             assert (0 && "We cannot reach this!");
318d2562509SSean Callanan         case eAllocationPolicyHostOnly:
319d2562509SSean Callanan             m_data.SetByteSize(size);
320d2562509SSean Callanan             memset(m_data.GetBytes(), 0, size);
321d2562509SSean Callanan             break;
322d2562509SSean Callanan         case eAllocationPolicyProcessOnly:
323d2562509SSean Callanan             break;
324d2562509SSean Callanan         case eAllocationPolicyMirror:
325d2562509SSean Callanan             m_data.SetByteSize(size);
326d2562509SSean Callanan             memset(m_data.GetBytes(), 0, size);
327d2562509SSean Callanan             break;
328d2562509SSean Callanan     }
329d2562509SSean Callanan }
330d2562509SSean Callanan 
3315a1af4e6SSean Callanan lldb::addr_t
3322c381414SJim Ingham IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, bool zero_memory, Error &error)
3335a1af4e6SSean Callanan {
334af245d11STodd Fiala     lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
33508052afaSSean Callanan     error.Clear();
33608052afaSSean Callanan 
3375a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
3385a1af4e6SSean Callanan     lldb::addr_t    allocation_address  = LLDB_INVALID_ADDRESS;
3395a1af4e6SSean Callanan     lldb::addr_t    aligned_address     = LLDB_INVALID_ADDRESS;
3405a1af4e6SSean Callanan 
341750dcc33SMatt Kopec     size_t          alignment_mask = alignment - 1;
342750dcc33SMatt Kopec     size_t          allocation_size;
343750dcc33SMatt Kopec 
344750dcc33SMatt Kopec     if (size == 0)
345750dcc33SMatt Kopec         allocation_size = alignment;
346750dcc33SMatt Kopec     else
347750dcc33SMatt Kopec         allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size;
3485a1af4e6SSean Callanan 
3495a1af4e6SSean Callanan     switch (policy)
3505a1af4e6SSean Callanan     {
3515a1af4e6SSean Callanan     default:
3525a1af4e6SSean Callanan         error.SetErrorToGenericError();
3535a1af4e6SSean Callanan         error.SetErrorString("Couldn't malloc: invalid allocation policy");
3545a1af4e6SSean Callanan         return LLDB_INVALID_ADDRESS;
3555a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
3565a1af4e6SSean Callanan         allocation_address = FindSpace(allocation_size);
3575a1af4e6SSean Callanan         if (allocation_address == LLDB_INVALID_ADDRESS)
3585a1af4e6SSean Callanan         {
3595a1af4e6SSean Callanan             error.SetErrorToGenericError();
3605a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: address space is full");
3615a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
3625a1af4e6SSean Callanan         }
3635a1af4e6SSean Callanan         break;
3645a1af4e6SSean Callanan     case eAllocationPolicyMirror:
3655a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
366af245d11STodd Fiala         if (log)
367af245d11STodd 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");
368ad7cc466SSean Callanan         if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
3695a1af4e6SSean Callanan         {
3702c381414SJim Ingham             if (!zero_memory)
3715a1af4e6SSean Callanan               allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
3722c381414SJim Ingham             else
3732c381414SJim Ingham               allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error);
3742c381414SJim Ingham 
3755a1af4e6SSean Callanan             if (!error.Success())
3765a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
3775a1af4e6SSean Callanan         }
3785a1af4e6SSean Callanan         else
3795a1af4e6SSean Callanan         {
380af245d11STodd Fiala             if (log)
381af245d11STodd Fiala                 log->Printf ("IRMemoryMap::%s switching to eAllocationPolicyHostOnly due to failed condition (see previous expr log message)", __FUNCTION__);
382bb9945f4SSean Callanan             policy = eAllocationPolicyHostOnly;
3835a1af4e6SSean Callanan             allocation_address = FindSpace(allocation_size);
3845a1af4e6SSean Callanan             if (allocation_address == LLDB_INVALID_ADDRESS)
3855a1af4e6SSean Callanan             {
3865a1af4e6SSean Callanan                 error.SetErrorToGenericError();
3875a1af4e6SSean Callanan                 error.SetErrorString("Couldn't malloc: address space is full");
3885a1af4e6SSean Callanan                 return LLDB_INVALID_ADDRESS;
3895a1af4e6SSean Callanan             }
3905a1af4e6SSean Callanan         }
3915a1af4e6SSean Callanan         break;
3925a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
3935a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
3945a1af4e6SSean Callanan         if (process_sp)
3955a1af4e6SSean Callanan         {
396ad7cc466SSean Callanan             if (process_sp->CanJIT() && process_sp->IsAlive())
397bb9945f4SSean Callanan             {
3982c381414SJim Ingham                 if (!zero_memory)
3995a1af4e6SSean Callanan                   allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
4002c381414SJim Ingham                 else
4012c381414SJim Ingham                   allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error);
4022c381414SJim Ingham 
4035a1af4e6SSean Callanan                 if (!error.Success())
4045a1af4e6SSean Callanan                     return LLDB_INVALID_ADDRESS;
4055a1af4e6SSean Callanan             }
4065a1af4e6SSean Callanan             else
4075a1af4e6SSean Callanan             {
4085a1af4e6SSean Callanan                 error.SetErrorToGenericError();
409bb9945f4SSean Callanan                 error.SetErrorString("Couldn't malloc: process doesn't support allocating memory");
410bb9945f4SSean Callanan                 return LLDB_INVALID_ADDRESS;
411bb9945f4SSean Callanan             }
412bb9945f4SSean Callanan         }
413bb9945f4SSean Callanan         else
414bb9945f4SSean Callanan         {
415bb9945f4SSean Callanan             error.SetErrorToGenericError();
4165a1af4e6SSean Callanan             error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
4175a1af4e6SSean Callanan             return LLDB_INVALID_ADDRESS;
4185a1af4e6SSean Callanan         }
4195a1af4e6SSean Callanan         break;
4205a1af4e6SSean Callanan     }
4215a1af4e6SSean Callanan 
4225a1af4e6SSean Callanan 
4235a1af4e6SSean Callanan     lldb::addr_t mask = alignment - 1;
4245a1af4e6SSean Callanan     aligned_address = (allocation_address + mask) & (~mask);
4255a1af4e6SSean Callanan 
426d2562509SSean Callanan     m_allocations[aligned_address] = Allocation(allocation_address,
427d2562509SSean Callanan                                                 aligned_address,
428750dcc33SMatt Kopec                                                 allocation_size,
429d2562509SSean Callanan                                                 permissions,
430d2562509SSean Callanan                                                 alignment,
431d2562509SSean Callanan                                                 policy);
4325a1af4e6SSean Callanan 
433af245d11STodd Fiala     if (log)
4345a1af4e6SSean Callanan     {
4355a1af4e6SSean Callanan         const char * policy_string;
4365a1af4e6SSean Callanan 
4375a1af4e6SSean Callanan         switch (policy)
4385a1af4e6SSean Callanan         {
4395a1af4e6SSean Callanan         default:
4405a1af4e6SSean Callanan             policy_string = "<invalid policy>";
4415a1af4e6SSean Callanan             break;
4425a1af4e6SSean Callanan         case eAllocationPolicyHostOnly:
4435a1af4e6SSean Callanan             policy_string = "eAllocationPolicyHostOnly";
4445a1af4e6SSean Callanan             break;
4455a1af4e6SSean Callanan         case eAllocationPolicyProcessOnly:
4465a1af4e6SSean Callanan             policy_string = "eAllocationPolicyProcessOnly";
4475a1af4e6SSean Callanan             break;
4485a1af4e6SSean Callanan         case eAllocationPolicyMirror:
4495a1af4e6SSean Callanan             policy_string = "eAllocationPolicyMirror";
4505a1af4e6SSean Callanan             break;
4515a1af4e6SSean Callanan         }
4525a1af4e6SSean Callanan 
453ef14371dSMatt Kopec         log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64,
454750dcc33SMatt Kopec                     (uint64_t)allocation_size,
4555a1af4e6SSean Callanan                     (uint64_t)alignment,
4565a1af4e6SSean Callanan                     (uint64_t)permissions,
4575a1af4e6SSean Callanan                     policy_string,
4585a1af4e6SSean Callanan                     aligned_address);
4595a1af4e6SSean Callanan     }
4605a1af4e6SSean Callanan 
4615a1af4e6SSean Callanan     return aligned_address;
4625a1af4e6SSean Callanan }
4635a1af4e6SSean Callanan 
4645a1af4e6SSean Callanan void
465fbf5c682SSean Callanan IRMemoryMap::Leak (lldb::addr_t process_address, Error &error)
466fbf5c682SSean Callanan {
467fbf5c682SSean Callanan     error.Clear();
468fbf5c682SSean Callanan 
469fbf5c682SSean Callanan     AllocationMap::iterator iter = m_allocations.find(process_address);
470fbf5c682SSean Callanan 
471fbf5c682SSean Callanan     if (iter == m_allocations.end())
472fbf5c682SSean Callanan     {
473fbf5c682SSean Callanan         error.SetErrorToGenericError();
474fbf5c682SSean Callanan         error.SetErrorString("Couldn't leak: allocation doesn't exist");
475fbf5c682SSean Callanan         return;
476fbf5c682SSean Callanan     }
477fbf5c682SSean Callanan 
478fbf5c682SSean Callanan     Allocation &allocation = iter->second;
479fbf5c682SSean Callanan 
480fbf5c682SSean Callanan     allocation.m_leak = true;
481fbf5c682SSean Callanan }
482fbf5c682SSean Callanan 
483fbf5c682SSean Callanan void
4845a1af4e6SSean Callanan IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
4855a1af4e6SSean Callanan {
48608052afaSSean Callanan     error.Clear();
48708052afaSSean Callanan 
4885a1af4e6SSean Callanan     AllocationMap::iterator iter = m_allocations.find(process_address);
4895a1af4e6SSean Callanan 
4905a1af4e6SSean Callanan     if (iter == m_allocations.end())
4915a1af4e6SSean Callanan     {
4925a1af4e6SSean Callanan         error.SetErrorToGenericError();
4935a1af4e6SSean Callanan         error.SetErrorString("Couldn't free: allocation doesn't exist");
4945a1af4e6SSean Callanan         return;
4955a1af4e6SSean Callanan     }
4965a1af4e6SSean Callanan 
4975a1af4e6SSean Callanan     Allocation &allocation = iter->second;
4985a1af4e6SSean Callanan 
4995a1af4e6SSean Callanan     switch (allocation.m_policy)
5005a1af4e6SSean Callanan     {
5015a1af4e6SSean Callanan     default:
5025a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
503df56540aSSean Callanan         {
504df56540aSSean Callanan             lldb::ProcessSP process_sp = m_process_wp.lock();
505bb77704cSSean Callanan             if (process_sp)
506bb77704cSSean Callanan             {
507ad7cc466SSean Callanan                 if (process_sp->CanJIT() && process_sp->IsAlive())
508df56540aSSean Callanan                     process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
509bb77704cSSean Callanan             }
510df56540aSSean Callanan 
5115a1af4e6SSean Callanan             break;
512df56540aSSean Callanan         }
5135a1af4e6SSean Callanan     case eAllocationPolicyMirror:
5145a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
515df56540aSSean Callanan         {
5165a1af4e6SSean Callanan             lldb::ProcessSP process_sp = m_process_wp.lock();
5175a1af4e6SSean Callanan             if (process_sp)
5185a1af4e6SSean Callanan                 process_sp->DeallocateMemory(allocation.m_process_alloc);
5195a1af4e6SSean Callanan         }
520df56540aSSean Callanan     }
5215a1af4e6SSean Callanan 
5225a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
5235a1af4e6SSean Callanan     {
524ef14371dSMatt Kopec         log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")",
5255a1af4e6SSean Callanan                     (uint64_t)process_address,
5265a1af4e6SSean Callanan                     iter->second.m_process_start,
5275a1af4e6SSean Callanan                     iter->second.m_process_start + iter->second.m_size);
5285a1af4e6SSean Callanan     }
5295a1af4e6SSean Callanan 
5305a1af4e6SSean Callanan     m_allocations.erase(iter);
5315a1af4e6SSean Callanan }
5325a1af4e6SSean Callanan 
53390ff7911SEwan Crawford bool
53490ff7911SEwan Crawford IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size)
53590ff7911SEwan Crawford {
53690ff7911SEwan Crawford     AllocationMap::iterator iter = FindAllocation(address, size);
53790ff7911SEwan Crawford     if (iter == m_allocations.end())
53890ff7911SEwan Crawford         return false;
53990ff7911SEwan Crawford 
54090ff7911SEwan Crawford     Allocation &al = iter->second;
54190ff7911SEwan Crawford 
54290ff7911SEwan Crawford     if (address > (al.m_process_start + al.m_size))
54390ff7911SEwan Crawford     {
54490ff7911SEwan Crawford         size = 0;
54590ff7911SEwan Crawford         return false;
54690ff7911SEwan Crawford     }
54790ff7911SEwan Crawford 
54890ff7911SEwan Crawford     if (address > al.m_process_start)
54990ff7911SEwan Crawford     {
55090ff7911SEwan Crawford         int dif = address - al.m_process_start;
55190ff7911SEwan Crawford         size = al.m_size - dif;
55290ff7911SEwan Crawford         return true;
55390ff7911SEwan Crawford     }
55490ff7911SEwan Crawford 
55590ff7911SEwan Crawford     size = al.m_size;
55690ff7911SEwan Crawford     return true;
55790ff7911SEwan Crawford }
55890ff7911SEwan Crawford 
5595a1af4e6SSean Callanan void
5605a1af4e6SSean Callanan IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
5615a1af4e6SSean Callanan {
56208052afaSSean Callanan     error.Clear();
56308052afaSSean Callanan 
5645a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
5655a1af4e6SSean Callanan 
5665a1af4e6SSean Callanan     if (iter == m_allocations.end())
5675a1af4e6SSean Callanan     {
568c8c5b8dcSSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
569c8c5b8dcSSean Callanan 
570c8c5b8dcSSean Callanan         if (process_sp)
571c8c5b8dcSSean Callanan         {
572c8c5b8dcSSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
573c8c5b8dcSSean Callanan             return;
574c8c5b8dcSSean Callanan         }
575c8c5b8dcSSean Callanan 
5765a1af4e6SSean Callanan         error.SetErrorToGenericError();
577c8c5b8dcSSean Callanan         error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
5785a1af4e6SSean Callanan         return;
5795a1af4e6SSean Callanan     }
5805a1af4e6SSean Callanan 
5815a1af4e6SSean Callanan     Allocation &allocation = iter->second;
5825a1af4e6SSean Callanan 
5835a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
5845a1af4e6SSean Callanan 
5855a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
5865a1af4e6SSean Callanan 
5875a1af4e6SSean Callanan     switch (allocation.m_policy)
5885a1af4e6SSean Callanan     {
5895a1af4e6SSean Callanan     default:
5905a1af4e6SSean Callanan         error.SetErrorToGenericError();
5915a1af4e6SSean Callanan         error.SetErrorString("Couldn't write: invalid allocation policy");
5925a1af4e6SSean Callanan         return;
5935a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
594d2562509SSean Callanan         if (!allocation.m_data.GetByteSize())
5955a1af4e6SSean Callanan         {
5965a1af4e6SSean Callanan             error.SetErrorToGenericError();
5975a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
5985a1af4e6SSean Callanan             return;
5995a1af4e6SSean Callanan         }
600d2562509SSean Callanan         ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
6015a1af4e6SSean Callanan         break;
6025a1af4e6SSean Callanan     case eAllocationPolicyMirror:
603d2562509SSean Callanan         if (!allocation.m_data.GetByteSize())
6045a1af4e6SSean Callanan         {
6055a1af4e6SSean Callanan             error.SetErrorToGenericError();
6065a1af4e6SSean Callanan             error.SetErrorString("Couldn't write: data buffer is empty");
6075a1af4e6SSean Callanan             return;
6085a1af4e6SSean Callanan         }
609d2562509SSean Callanan         ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
6105a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
6115a1af4e6SSean Callanan         if (process_sp)
6125a1af4e6SSean Callanan         {
6135a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
6145a1af4e6SSean Callanan             if (!error.Success())
6155a1af4e6SSean Callanan                 return;
6165a1af4e6SSean Callanan         }
6175a1af4e6SSean Callanan         break;
6185a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
6195a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
6205a1af4e6SSean Callanan         if (process_sp)
6215a1af4e6SSean Callanan         {
6225a1af4e6SSean Callanan             process_sp->WriteMemory(process_address, bytes, size, error);
6235a1af4e6SSean Callanan             if (!error.Success())
6245a1af4e6SSean Callanan                 return;
6255a1af4e6SSean Callanan         }
6265a1af4e6SSean Callanan         break;
6275a1af4e6SSean Callanan     }
6285a1af4e6SSean Callanan 
6295a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
6305a1af4e6SSean Callanan     {
631ef14371dSMatt Kopec         log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
6325a1af4e6SSean Callanan                     (uint64_t)process_address,
6335a1af4e6SSean Callanan                     (uint64_t)bytes,
6345a1af4e6SSean Callanan                     (uint64_t)size,
6355a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
6365a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
6375a1af4e6SSean Callanan     }
6385a1af4e6SSean Callanan }
6395a1af4e6SSean Callanan 
6405a1af4e6SSean Callanan void
64135005f76SSean Callanan IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
64235005f76SSean Callanan {
64308052afaSSean Callanan     error.Clear();
64408052afaSSean Callanan 
64535005f76SSean Callanan     if (size == UINT32_MAX)
64635005f76SSean Callanan         size = scalar.GetByteSize();
64735005f76SSean Callanan 
64835005f76SSean Callanan     if (size > 0)
64935005f76SSean Callanan     {
65035005f76SSean Callanan         uint8_t buf[32];
65135005f76SSean Callanan         const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
65235005f76SSean Callanan         if (mem_size > 0)
65335005f76SSean Callanan         {
65435005f76SSean Callanan             return WriteMemory(process_address, buf, mem_size, error);
65535005f76SSean Callanan         }
65635005f76SSean Callanan         else
65735005f76SSean Callanan         {
65835005f76SSean Callanan             error.SetErrorToGenericError();
65935005f76SSean Callanan             error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
66035005f76SSean Callanan         }
66135005f76SSean Callanan     }
66235005f76SSean Callanan     else
66335005f76SSean Callanan     {
66435005f76SSean Callanan         error.SetErrorToGenericError();
66535005f76SSean Callanan         error.SetErrorString ("Couldn't write scalar: its size was zero");
66635005f76SSean Callanan     }
66735005f76SSean Callanan     return;
66835005f76SSean Callanan }
66935005f76SSean Callanan 
67035005f76SSean Callanan void
671f8043fa5SSean Callanan IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
672f8043fa5SSean Callanan {
67308052afaSSean Callanan     error.Clear();
67408052afaSSean Callanan 
675f8043fa5SSean Callanan     Scalar scalar(address);
676f8043fa5SSean Callanan 
677f8043fa5SSean Callanan     WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
678f8043fa5SSean Callanan }
679f8043fa5SSean Callanan 
680f8043fa5SSean Callanan void
6815a1af4e6SSean Callanan IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
6825a1af4e6SSean Callanan {
68308052afaSSean Callanan     error.Clear();
68408052afaSSean Callanan 
6855a1af4e6SSean Callanan     AllocationMap::iterator iter = FindAllocation(process_address, size);
6865a1af4e6SSean Callanan 
6875a1af4e6SSean Callanan     if (iter == m_allocations.end())
6885a1af4e6SSean Callanan     {
689c8c5b8dcSSean Callanan         lldb::ProcessSP process_sp = m_process_wp.lock();
690c8c5b8dcSSean Callanan 
691c8c5b8dcSSean Callanan         if (process_sp)
692c8c5b8dcSSean Callanan         {
693c8c5b8dcSSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
694c8c5b8dcSSean Callanan             return;
695c8c5b8dcSSean Callanan         }
696c8c5b8dcSSean Callanan 
697c8c5b8dcSSean Callanan         lldb::TargetSP target_sp = m_target_wp.lock();
698c8c5b8dcSSean Callanan 
699c8c5b8dcSSean Callanan         if (target_sp)
700c8c5b8dcSSean Callanan         {
701c8c5b8dcSSean Callanan             Address absolute_address(process_address);
702c8c5b8dcSSean Callanan             target_sp->ReadMemory(absolute_address, false, bytes, size, error);
703c8c5b8dcSSean Callanan             return;
704c8c5b8dcSSean Callanan         }
705c8c5b8dcSSean Callanan 
7065a1af4e6SSean Callanan         error.SetErrorToGenericError();
707c8c5b8dcSSean Callanan         error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist");
7085a1af4e6SSean Callanan         return;
7095a1af4e6SSean Callanan     }
7105a1af4e6SSean Callanan 
7115a1af4e6SSean Callanan     Allocation &allocation = iter->second;
7125a1af4e6SSean Callanan 
7135a1af4e6SSean Callanan     uint64_t offset = process_address - allocation.m_process_start;
7145a1af4e6SSean Callanan 
7159bbf3cd3SSean Callanan     if (offset > allocation.m_size)
7169bbf3cd3SSean Callanan     {
7179bbf3cd3SSean Callanan         error.SetErrorToGenericError();
7189bbf3cd3SSean Callanan         error.SetErrorString("Couldn't read: data is not in the allocation");
7199bbf3cd3SSean Callanan         return;
7209bbf3cd3SSean Callanan     }
7219bbf3cd3SSean Callanan 
7225a1af4e6SSean Callanan     lldb::ProcessSP process_sp;
7235a1af4e6SSean Callanan 
7245a1af4e6SSean Callanan     switch (allocation.m_policy)
7255a1af4e6SSean Callanan     {
7265a1af4e6SSean Callanan     default:
7275a1af4e6SSean Callanan         error.SetErrorToGenericError();
7285a1af4e6SSean Callanan         error.SetErrorString("Couldn't read: invalid allocation policy");
7295a1af4e6SSean Callanan         return;
7305a1af4e6SSean Callanan     case eAllocationPolicyHostOnly:
731d2562509SSean Callanan         if (!allocation.m_data.GetByteSize())
7325a1af4e6SSean Callanan         {
7335a1af4e6SSean Callanan             error.SetErrorToGenericError();
7345a1af4e6SSean Callanan             error.SetErrorString("Couldn't read: data buffer is empty");
7355a1af4e6SSean Callanan             return;
7365a1af4e6SSean Callanan         }
7379bbf3cd3SSean Callanan         if (allocation.m_data.GetByteSize() < offset + size)
7389bbf3cd3SSean Callanan         {
7399bbf3cd3SSean Callanan             error.SetErrorToGenericError();
7409bbf3cd3SSean Callanan             error.SetErrorString("Couldn't read: not enough underlying data");
7419bbf3cd3SSean Callanan             return;
7429bbf3cd3SSean Callanan         }
7439bbf3cd3SSean Callanan 
744d2562509SSean Callanan         ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
7455a1af4e6SSean Callanan         break;
7465a1af4e6SSean Callanan     case eAllocationPolicyMirror:
7475a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
7485a1af4e6SSean Callanan         if (process_sp)
7495a1af4e6SSean Callanan         {
7505a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
7515a1af4e6SSean Callanan             if (!error.Success())
7525a1af4e6SSean Callanan                 return;
7535a1af4e6SSean Callanan         }
7545a1af4e6SSean Callanan         else
7555a1af4e6SSean Callanan         {
756d2562509SSean Callanan             if (!allocation.m_data.GetByteSize())
7575a1af4e6SSean Callanan             {
7585a1af4e6SSean Callanan                 error.SetErrorToGenericError();
7595a1af4e6SSean Callanan                 error.SetErrorString("Couldn't read: data buffer is empty");
7605a1af4e6SSean Callanan                 return;
7615a1af4e6SSean Callanan             }
762d2562509SSean Callanan             ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
7635a1af4e6SSean Callanan         }
7645a1af4e6SSean Callanan         break;
7655a1af4e6SSean Callanan     case eAllocationPolicyProcessOnly:
7665a1af4e6SSean Callanan         process_sp = m_process_wp.lock();
7675a1af4e6SSean Callanan         if (process_sp)
7685a1af4e6SSean Callanan         {
7695a1af4e6SSean Callanan             process_sp->ReadMemory(process_address, bytes, size, error);
7705a1af4e6SSean Callanan             if (!error.Success())
7715a1af4e6SSean Callanan                 return;
7725a1af4e6SSean Callanan         }
7735a1af4e6SSean Callanan         break;
7745a1af4e6SSean Callanan     }
7755a1af4e6SSean Callanan 
7765a1af4e6SSean Callanan     if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
7775a1af4e6SSean Callanan     {
778ef14371dSMatt Kopec         log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
7795a1af4e6SSean Callanan                     (uint64_t)process_address,
7805a1af4e6SSean Callanan                     (uint64_t)bytes,
7815a1af4e6SSean Callanan                     (uint64_t)size,
7825a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start,
7835a1af4e6SSean Callanan                     (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
7845a1af4e6SSean Callanan     }
7855a1af4e6SSean Callanan }
78635005f76SSean Callanan 
78735005f76SSean Callanan void
78835005f76SSean Callanan IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
78935005f76SSean Callanan {
79008052afaSSean Callanan     error.Clear();
79108052afaSSean Callanan 
79235005f76SSean Callanan     if (size > 0)
79335005f76SSean Callanan     {
79435005f76SSean Callanan         DataBufferHeap buf(size, 0);
79535005f76SSean Callanan         ReadMemory(buf.GetBytes(), process_address, size, error);
79635005f76SSean Callanan 
79735005f76SSean Callanan         if (!error.Success())
79835005f76SSean Callanan             return;
79935005f76SSean Callanan 
80035005f76SSean Callanan         DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
80135005f76SSean Callanan 
80235005f76SSean Callanan         lldb::offset_t offset = 0;
80335005f76SSean Callanan 
80435005f76SSean Callanan         switch (size)
80535005f76SSean Callanan         {
80635005f76SSean Callanan         default:
80735005f76SSean Callanan             error.SetErrorToGenericError();
808e86cef63SGreg Clayton             error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
80935005f76SSean Callanan             return;
81035005f76SSean Callanan         case 1: scalar = extractor.GetU8(&offset);  break;
81135005f76SSean Callanan         case 2: scalar = extractor.GetU16(&offset); break;
81235005f76SSean Callanan         case 4: scalar = extractor.GetU32(&offset); break;
81335005f76SSean Callanan         case 8: scalar = extractor.GetU64(&offset); break;
81435005f76SSean Callanan         }
81535005f76SSean Callanan     }
81635005f76SSean Callanan     else
81735005f76SSean Callanan     {
81835005f76SSean Callanan         error.SetErrorToGenericError();
819458ae1c6SSean Callanan         error.SetErrorString ("Couldn't read scalar: its size was zero");
82035005f76SSean Callanan     }
82135005f76SSean Callanan     return;
82235005f76SSean Callanan }
82335005f76SSean Callanan 
824458ae1c6SSean Callanan void
8252d37e5a5SSean Callanan IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
8262d37e5a5SSean Callanan {
82708052afaSSean Callanan     error.Clear();
82808052afaSSean Callanan 
8292d37e5a5SSean Callanan     Scalar pointer_scalar;
8302d37e5a5SSean Callanan     ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
8312d37e5a5SSean Callanan 
8322d37e5a5SSean Callanan     if (!error.Success())
8332d37e5a5SSean Callanan         return;
8342d37e5a5SSean Callanan 
8352d37e5a5SSean Callanan     *address = pointer_scalar.ULongLong();
8362d37e5a5SSean Callanan 
8372d37e5a5SSean Callanan     return;
8382d37e5a5SSean Callanan }
8392d37e5a5SSean Callanan 
8402d37e5a5SSean Callanan void
841458ae1c6SSean Callanan IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
842458ae1c6SSean Callanan {
84308052afaSSean Callanan     error.Clear();
84408052afaSSean Callanan 
845458ae1c6SSean Callanan     if (size > 0)
846458ae1c6SSean Callanan     {
847458ae1c6SSean Callanan         AllocationMap::iterator iter = FindAllocation(process_address, size);
848458ae1c6SSean Callanan 
849458ae1c6SSean Callanan         if (iter == m_allocations.end())
850458ae1c6SSean Callanan         {
851458ae1c6SSean Callanan             error.SetErrorToGenericError();
852ef14371dSMatt Kopec             error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size);
853458ae1c6SSean Callanan             return;
854458ae1c6SSean Callanan         }
855458ae1c6SSean Callanan 
856458ae1c6SSean Callanan         Allocation &allocation = iter->second;
857458ae1c6SSean Callanan 
858458ae1c6SSean Callanan         switch (allocation.m_policy)
859458ae1c6SSean Callanan         {
860458ae1c6SSean Callanan         default:
861458ae1c6SSean Callanan             error.SetErrorToGenericError();
862458ae1c6SSean Callanan             error.SetErrorString("Couldn't get memory data: invalid allocation policy");
863458ae1c6SSean Callanan             return;
864458ae1c6SSean Callanan         case eAllocationPolicyProcessOnly:
865458ae1c6SSean Callanan             error.SetErrorToGenericError();
866458ae1c6SSean Callanan             error.SetErrorString("Couldn't get memory data: memory is only in the target");
867458ae1c6SSean Callanan             return;
868458ae1c6SSean Callanan         case eAllocationPolicyMirror:
869c8c5b8dcSSean Callanan             {
870c8c5b8dcSSean Callanan                 lldb::ProcessSP process_sp = m_process_wp.lock();
871c8c5b8dcSSean Callanan 
872d2562509SSean Callanan                 if (!allocation.m_data.GetByteSize())
873c8c5b8dcSSean Callanan                 {
874c8c5b8dcSSean Callanan                     error.SetErrorToGenericError();
875c8c5b8dcSSean Callanan                     error.SetErrorString("Couldn't get memory data: data buffer is empty");
876c8c5b8dcSSean Callanan                     return;
877c8c5b8dcSSean Callanan                 }
878c8c5b8dcSSean Callanan                 if (process_sp)
879c8c5b8dcSSean Callanan                 {
880d2562509SSean Callanan                     process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error);
881c8c5b8dcSSean Callanan                     if (!error.Success())
882c8c5b8dcSSean Callanan                         return;
883c8c5b8dcSSean Callanan                     uint64_t offset = process_address - allocation.m_process_start;
884d2562509SSean Callanan                     extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
885c8c5b8dcSSean Callanan                     return;
886c8c5b8dcSSean Callanan                 }
887c8c5b8dcSSean Callanan             }
888cec91ef9SGreg Clayton             break;
889c8c5b8dcSSean Callanan         case eAllocationPolicyHostOnly:
890d2562509SSean Callanan             if (!allocation.m_data.GetByteSize())
891458ae1c6SSean Callanan             {
892458ae1c6SSean Callanan                 error.SetErrorToGenericError();
893458ae1c6SSean Callanan                 error.SetErrorString("Couldn't get memory data: data buffer is empty");
894458ae1c6SSean Callanan                 return;
895458ae1c6SSean Callanan             }
896458ae1c6SSean Callanan             uint64_t offset = process_address - allocation.m_process_start;
897d2562509SSean Callanan             extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
898458ae1c6SSean Callanan             return;
899458ae1c6SSean Callanan         }
900458ae1c6SSean Callanan     }
901458ae1c6SSean Callanan     else
902458ae1c6SSean Callanan     {
903458ae1c6SSean Callanan         error.SetErrorToGenericError();
904458ae1c6SSean Callanan         error.SetErrorString ("Couldn't get memory data: its size was zero");
905458ae1c6SSean Callanan         return;
906458ae1c6SSean Callanan     }
907458ae1c6SSean Callanan }
908