blob: 3dbdc5af6dc128a564849bdfb21f29e36ab4ba4c [file] [log] [blame]
Sean Callanan5a1af4e2013-04-05 02:22:57 +00001//===-- IRMemoryMap.cpp -----------------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Sean Callanan35005f72013-04-12 18:10:34 +000010#include "lldb/Core/DataBufferHeap.h"
11#include "lldb/Core/DataExtractor.h"
Sean Callanan5a1af4e2013-04-05 02:22:57 +000012#include "lldb/Core/Error.h"
13#include "lldb/Core/Log.h"
Sean Callanan35005f72013-04-12 18:10:34 +000014#include "lldb/Core/Scalar.h"
Sean Callanan5a1af4e2013-04-05 02:22:57 +000015#include "lldb/Expression/IRMemoryMap.h"
16#include "lldb/Target/Process.h"
Sean Callanan35005f72013-04-12 18:10:34 +000017#include "lldb/Target/Target.h"
Sean Callanan5a1af4e2013-04-05 02:22:57 +000018
19using namespace lldb_private;
20
Sean Callanan35005f72013-04-12 18:10:34 +000021IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) :
Sean Callanan35005f72013-04-12 18:10:34 +000022 m_target_wp(target_sp)
Sean Callanan5a1af4e2013-04-05 02:22:57 +000023{
Sean Callananb024d872013-04-15 17:12:47 +000024 if (target_sp)
25 m_process_wp = target_sp->GetProcessSP();
Sean Callanan5a1af4e2013-04-05 02:22:57 +000026}
27
28IRMemoryMap::~IRMemoryMap ()
29{
30 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000031
Sean Callanan5a1af4e2013-04-05 02:22:57 +000032 if (process_sp)
33 {
Sean Callananbb777042013-05-16 17:30:37 +000034 AllocationMap::iterator iter;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000035
Sean Callananbb777042013-05-16 17:30:37 +000036 Error err;
37
38 while ((iter = m_allocations.begin()) != m_allocations.end())
Sean Callanan5a1af4e2013-04-05 02:22:57 +000039 {
Sean Callananbb777042013-05-16 17:30:37 +000040 err.Clear();
Sean Callananfbf5c682013-05-22 22:49:06 +000041 if (iter->second.m_leak)
42 m_allocations.erase(iter);
43 else
44 Free(iter->first, err);
Sean Callanan5a1af4e2013-04-05 02:22:57 +000045 }
46 }
47}
48
49lldb::addr_t
Jim Ingham2c381412015-11-04 20:32:27 +000050IRMemoryMap::FindSpace (size_t size, bool zero_memory)
Sean Callanan5a1af4e2013-04-05 02:22:57 +000051{
Sean Callananbb9945f2013-04-19 01:51:24 +000052 lldb::TargetSP target_sp = m_target_wp.lock();
53 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000054
Sean Callananbb9945f2013-04-19 01:51:24 +000055 lldb::addr_t ret = LLDB_INVALID_ADDRESS;
Zachary Turner3ddcd312014-07-09 16:42:27 +000056 if (size == 0)
57 return ret;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000058
Sean Callananad7cc462013-06-17 21:19:31 +000059 if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
Sean Callanandf565402013-04-27 02:19:33 +000060 {
61 Error alloc_error;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000062
Jim Ingham2c381412015-11-04 20:32:27 +000063 if (!zero_memory)
64 ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
65 else
66 ret = process_sp->CallocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000067
Sean Callanandf565402013-04-27 02:19:33 +000068 if (!alloc_error.Success())
69 return LLDB_INVALID_ADDRESS;
70 else
71 return ret;
72 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000073
Zachary Turner3ddcd312014-07-09 16:42:27 +000074 ret = 0;
75 if (!m_allocations.empty())
Sean Callanan5a1af4e2013-04-05 02:22:57 +000076 {
Zachary Turner3ddcd312014-07-09 16:42:27 +000077 auto back = m_allocations.rbegin();
78 lldb::addr_t addr = back->first;
79 size_t alloc_size = back->second.m_size;
Rafael Espindolaa94ae1e2016-01-18 20:57:54 +000080 ret = llvm::alignTo(addr+alloc_size, 4096);
Sean Callanan5a1af4e2013-04-05 02:22:57 +000081 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000082
Sean Callananbb9945f2013-04-19 01:51:24 +000083 return ret;
Sean Callanan5a1af4e2013-04-05 02:22:57 +000084}
85
86IRMemoryMap::AllocationMap::iterator
87IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
88{
Sean Callanan1582ee62013-04-18 22:06:33 +000089 if (addr == LLDB_INVALID_ADDRESS)
90 return m_allocations.end();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000091
Sean Callanan5a1af4e2013-04-05 02:22:57 +000092 AllocationMap::iterator iter = m_allocations.lower_bound (addr);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000093
Sean Callanan14b1bae2013-04-16 23:25:35 +000094 if (iter == m_allocations.end() ||
95 iter->first > addr)
Sean Callanan5a1af4e2013-04-05 02:22:57 +000096 {
97 if (iter == m_allocations.begin())
98 return m_allocations.end();
99 iter--;
100 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000101
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000102 if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
103 return iter;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000104
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000105 return m_allocations.end();
106}
107
Sean Callananbb9945f2013-04-19 01:51:24 +0000108bool
Zachary Turner15362442014-06-25 18:37:19 +0000109IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size) const
Sean Callananbb9945f2013-04-19 01:51:24 +0000110{
111 if (addr == LLDB_INVALID_ADDRESS)
112 return false;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000113
Zachary Turner15362442014-06-25 18:37:19 +0000114 AllocationMap::const_iterator iter = m_allocations.lower_bound (addr);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000115
Zachary Turner15362442014-06-25 18:37:19 +0000116 // Since we only know that the returned interval begins at a location greater than or
117 // equal to where the given interval begins, it's possible that the given interval
118 // intersects either the returned interval or the previous interval. Thus, we need to
119 // check both. Note that we only need to check these two intervals. Since all intervals
120 // are disjoint it is not possible that an adjacent interval does not intersect, but a
121 // non-adjacent interval does intersect.
122 if (iter != m_allocations.end()) {
Zachary Turnercfcd7912014-06-25 18:40:58 +0000123 if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
Sean Callananbb9945f2013-04-19 01:51:24 +0000124 return true;
Sean Callananbb9945f2013-04-19 01:51:24 +0000125 }
Zachary Turner15362442014-06-25 18:37:19 +0000126
127 if (iter != m_allocations.begin()) {
128 --iter;
Zachary Turnercfcd7912014-06-25 18:40:58 +0000129 if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
Zachary Turner15362442014-06-25 18:37:19 +0000130 return true;
131 }
132
Sean Callananbb9945f2013-04-19 01:51:24 +0000133 return false;
134}
135
Zachary Turner15362442014-06-25 18:37:19 +0000136bool
137IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1, lldb::addr_t addr2, size_t size2) {
138 // Given two half open intervals [A, B) and [X, Y), the only 6 permutations that satisfy
139 // A<B and X<Y are the following:
140 // A B X Y
141 // A X B Y (intersects)
142 // A X Y B (intersects)
143 // X A B Y (intersects)
144 // X A Y B (intersects)
145 // X Y A B
146 // The first is B <= X, and the last is Y <= A.
147 // So the condition is !(B <= X || Y <= A)), or (X < B && A < Y)
148 return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
149}
150
Sean Callanan35005f72013-04-12 18:10:34 +0000151lldb::ByteOrder
152IRMemoryMap::GetByteOrder()
153{
154 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000155
Sean Callanan35005f72013-04-12 18:10:34 +0000156 if (process_sp)
157 return process_sp->GetByteOrder();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000158
Sean Callanan35005f72013-04-12 18:10:34 +0000159 lldb::TargetSP target_sp = m_target_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000160
Sean Callanan35005f72013-04-12 18:10:34 +0000161 if (target_sp)
Sean Callanan08052af2013-04-17 07:50:58 +0000162 return target_sp->GetArchitecture().GetByteOrder();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000163
Sean Callanan35005f72013-04-12 18:10:34 +0000164 return lldb::eByteOrderInvalid;
165}
166
167uint32_t
168IRMemoryMap::GetAddressByteSize()
169{
170 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000171
Sean Callanan35005f72013-04-12 18:10:34 +0000172 if (process_sp)
173 return process_sp->GetAddressByteSize();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000174
Sean Callanan35005f72013-04-12 18:10:34 +0000175 lldb::TargetSP target_sp = m_target_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000176
Sean Callanan35005f72013-04-12 18:10:34 +0000177 if (target_sp)
Sean Callanan08052af2013-04-17 07:50:58 +0000178 return target_sp->GetArchitecture().GetAddressByteSize();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000179
Sean Callanan35005f72013-04-12 18:10:34 +0000180 return UINT32_MAX;
181}
182
183ExecutionContextScope *
Greg Clayton23f8c952014-03-24 23:10:19 +0000184IRMemoryMap::GetBestExecutionContextScope() const
Sean Callanan35005f72013-04-12 18:10:34 +0000185{
186 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000187
Sean Callanan35005f72013-04-12 18:10:34 +0000188 if (process_sp)
189 return process_sp.get();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000190
Sean Callanan35005f72013-04-12 18:10:34 +0000191 lldb::TargetSP target_sp = m_target_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000192
Sean Callanan35005f72013-04-12 18:10:34 +0000193 if (target_sp)
194 return target_sp.get();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000195
Sean Callanan35005f72013-04-12 18:10:34 +0000196 return NULL;
197}
198
Sean Callanand2562502013-04-19 17:44:40 +0000199IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
200 lldb::addr_t process_start,
201 size_t size,
202 uint32_t permissions,
203 uint8_t alignment,
Michael Sartain6fea7792013-08-06 22:21:08 +0000204 AllocationPolicy policy) :
205 m_process_alloc (process_alloc),
206 m_process_start (process_start),
207 m_size (size),
208 m_permissions (permissions),
209 m_alignment (alignment),
210 m_policy (policy),
211 m_leak (false)
Sean Callanand2562502013-04-19 17:44:40 +0000212{
Sean Callanand2562502013-04-19 17:44:40 +0000213 switch (policy)
214 {
215 default:
216 assert (0 && "We cannot reach this!");
217 case eAllocationPolicyHostOnly:
218 m_data.SetByteSize(size);
219 memset(m_data.GetBytes(), 0, size);
220 break;
221 case eAllocationPolicyProcessOnly:
222 break;
223 case eAllocationPolicyMirror:
224 m_data.SetByteSize(size);
225 memset(m_data.GetBytes(), 0, size);
226 break;
227 }
228}
229
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000230lldb::addr_t
Jim Ingham2c381412015-11-04 20:32:27 +0000231IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, bool zero_memory, Error &error)
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000232{
Todd Fialaaf245d12014-06-30 21:05:18 +0000233 lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan08052af2013-04-17 07:50:58 +0000234 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000235
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000236 lldb::ProcessSP process_sp;
237 lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
238 lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
Matt Kopec750dcc32013-04-26 17:48:01 +0000239
240 size_t alignment_mask = alignment - 1;
241 size_t allocation_size;
242
243 if (size == 0)
244 allocation_size = alignment;
245 else
246 allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000247
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000248 switch (policy)
249 {
250 default:
251 error.SetErrorToGenericError();
252 error.SetErrorString("Couldn't malloc: invalid allocation policy");
253 return LLDB_INVALID_ADDRESS;
254 case eAllocationPolicyHostOnly:
255 allocation_address = FindSpace(allocation_size);
256 if (allocation_address == LLDB_INVALID_ADDRESS)
257 {
258 error.SetErrorToGenericError();
259 error.SetErrorString("Couldn't malloc: address space is full");
260 return LLDB_INVALID_ADDRESS;
261 }
262 break;
263 case eAllocationPolicyMirror:
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000264 process_sp = m_process_wp.lock();
Todd Fialaaf245d12014-06-30 21:05:18 +0000265 if (log)
266 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");
Sean Callananad7cc462013-06-17 21:19:31 +0000267 if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000268 {
Jim Ingham2c381412015-11-04 20:32:27 +0000269 if (!zero_memory)
270 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
271 else
272 allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error);
273
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000274 if (!error.Success())
275 return LLDB_INVALID_ADDRESS;
276 }
277 else
278 {
Todd Fialaaf245d12014-06-30 21:05:18 +0000279 if (log)
280 log->Printf ("IRMemoryMap::%s switching to eAllocationPolicyHostOnly due to failed condition (see previous expr log message)", __FUNCTION__);
Sean Callananbb9945f2013-04-19 01:51:24 +0000281 policy = eAllocationPolicyHostOnly;
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000282 allocation_address = FindSpace(allocation_size);
283 if (allocation_address == LLDB_INVALID_ADDRESS)
284 {
285 error.SetErrorToGenericError();
286 error.SetErrorString("Couldn't malloc: address space is full");
287 return LLDB_INVALID_ADDRESS;
288 }
289 }
290 break;
291 case eAllocationPolicyProcessOnly:
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000292 process_sp = m_process_wp.lock();
293 if (process_sp)
294 {
Sean Callananad7cc462013-06-17 21:19:31 +0000295 if (process_sp->CanJIT() && process_sp->IsAlive())
Sean Callananbb9945f2013-04-19 01:51:24 +0000296 {
Jim Ingham2c381412015-11-04 20:32:27 +0000297 if (!zero_memory)
298 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
299 else
300 allocation_address = process_sp->CallocateMemory(allocation_size, permissions, error);
301
Sean Callananbb9945f2013-04-19 01:51:24 +0000302 if (!error.Success())
303 return LLDB_INVALID_ADDRESS;
304 }
305 else
306 {
307 error.SetErrorToGenericError();
308 error.SetErrorString("Couldn't malloc: process doesn't support allocating memory");
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000309 return LLDB_INVALID_ADDRESS;
Sean Callananbb9945f2013-04-19 01:51:24 +0000310 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000311 }
312 else
313 {
314 error.SetErrorToGenericError();
315 error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
316 return LLDB_INVALID_ADDRESS;
317 }
318 break;
319 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000320
321
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000322 lldb::addr_t mask = alignment - 1;
323 aligned_address = (allocation_address + mask) & (~mask);
324
Sean Callanand2562502013-04-19 17:44:40 +0000325 m_allocations[aligned_address] = Allocation(allocation_address,
326 aligned_address,
Matt Kopec750dcc32013-04-26 17:48:01 +0000327 allocation_size,
Sean Callanand2562502013-04-19 17:44:40 +0000328 permissions,
329 alignment,
330 policy);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000331
Todd Fialaaf245d12014-06-30 21:05:18 +0000332 if (log)
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000333 {
334 const char * policy_string;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000335
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000336 switch (policy)
337 {
338 default:
339 policy_string = "<invalid policy>";
340 break;
341 case eAllocationPolicyHostOnly:
342 policy_string = "eAllocationPolicyHostOnly";
343 break;
344 case eAllocationPolicyProcessOnly:
345 policy_string = "eAllocationPolicyProcessOnly";
346 break;
347 case eAllocationPolicyMirror:
348 policy_string = "eAllocationPolicyMirror";
349 break;
350 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000351
Matt Kopecef143712013-06-03 18:00:07 +0000352 log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64,
Matt Kopec750dcc32013-04-26 17:48:01 +0000353 (uint64_t)allocation_size,
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000354 (uint64_t)alignment,
355 (uint64_t)permissions,
356 policy_string,
357 aligned_address);
358 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000359
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000360 return aligned_address;
361}
362
363void
Sean Callananfbf5c682013-05-22 22:49:06 +0000364IRMemoryMap::Leak (lldb::addr_t process_address, Error &error)
365{
366 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000367
Sean Callananfbf5c682013-05-22 22:49:06 +0000368 AllocationMap::iterator iter = m_allocations.find(process_address);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000369
Sean Callananfbf5c682013-05-22 22:49:06 +0000370 if (iter == m_allocations.end())
371 {
372 error.SetErrorToGenericError();
373 error.SetErrorString("Couldn't leak: allocation doesn't exist");
374 return;
375 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000376
Sean Callananfbf5c682013-05-22 22:49:06 +0000377 Allocation &allocation = iter->second;
378
379 allocation.m_leak = true;
380}
381
382void
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000383IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
384{
Sean Callanan08052af2013-04-17 07:50:58 +0000385 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000386
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000387 AllocationMap::iterator iter = m_allocations.find(process_address);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000388
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000389 if (iter == m_allocations.end())
390 {
391 error.SetErrorToGenericError();
392 error.SetErrorString("Couldn't free: allocation doesn't exist");
393 return;
394 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000395
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000396 Allocation &allocation = iter->second;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000397
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000398 switch (allocation.m_policy)
399 {
400 default:
401 case eAllocationPolicyHostOnly:
Sean Callanandf565402013-04-27 02:19:33 +0000402 {
403 lldb::ProcessSP process_sp = m_process_wp.lock();
Sean Callananbb777042013-05-16 17:30:37 +0000404 if (process_sp)
405 {
Sean Callananad7cc462013-06-17 21:19:31 +0000406 if (process_sp->CanJIT() && process_sp->IsAlive())
Sean Callananbb777042013-05-16 17:30:37 +0000407 process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
Sean Callananbb777042013-05-16 17:30:37 +0000408 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000409
Sean Callanandf565402013-04-27 02:19:33 +0000410 break;
411 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000412 case eAllocationPolicyMirror:
413 case eAllocationPolicyProcessOnly:
Sean Callanandf565402013-04-27 02:19:33 +0000414 {
415 lldb::ProcessSP process_sp = m_process_wp.lock();
416 if (process_sp)
417 process_sp->DeallocateMemory(allocation.m_process_alloc);
418 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000419 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000420
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000421 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000422 {
Matt Kopecef143712013-06-03 18:00:07 +0000423 log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")",
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000424 (uint64_t)process_address,
425 iter->second.m_process_start,
426 iter->second.m_process_start + iter->second.m_size);
427 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000428
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000429 m_allocations.erase(iter);
430}
431
Ewan Crawford90ff7912015-07-14 10:56:58 +0000432bool
433IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size)
434{
435 AllocationMap::iterator iter = FindAllocation(address, size);
436 if (iter == m_allocations.end())
437 return false;
438
439 Allocation &al = iter->second;
440
441 if (address > (al.m_process_start + al.m_size))
442 {
443 size = 0;
444 return false;
445 }
446
447 if (address > al.m_process_start)
448 {
449 int dif = address - al.m_process_start;
450 size = al.m_size - dif;
451 return true;
452 }
453
454 size = al.m_size;
455 return true;
456}
457
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000458void
459IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
460{
Sean Callanan08052af2013-04-17 07:50:58 +0000461 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000462
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000463 AllocationMap::iterator iter = FindAllocation(process_address, size);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000464
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000465 if (iter == m_allocations.end())
466 {
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000467 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000468
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000469 if (process_sp)
470 {
471 process_sp->WriteMemory(process_address, bytes, size, error);
472 return;
473 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000474
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000475 error.SetErrorToGenericError();
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000476 error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000477 return;
478 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000479
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000480 Allocation &allocation = iter->second;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000481
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000482 uint64_t offset = process_address - allocation.m_process_start;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000483
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000484 lldb::ProcessSP process_sp;
485
486 switch (allocation.m_policy)
487 {
488 default:
489 error.SetErrorToGenericError();
490 error.SetErrorString("Couldn't write: invalid allocation policy");
491 return;
492 case eAllocationPolicyHostOnly:
Sean Callanand2562502013-04-19 17:44:40 +0000493 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000494 {
495 error.SetErrorToGenericError();
496 error.SetErrorString("Couldn't write: data buffer is empty");
497 return;
498 }
Sean Callanand2562502013-04-19 17:44:40 +0000499 ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000500 break;
501 case eAllocationPolicyMirror:
Sean Callanand2562502013-04-19 17:44:40 +0000502 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000503 {
504 error.SetErrorToGenericError();
505 error.SetErrorString("Couldn't write: data buffer is empty");
506 return;
507 }
Sean Callanand2562502013-04-19 17:44:40 +0000508 ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000509 process_sp = m_process_wp.lock();
510 if (process_sp)
511 {
512 process_sp->WriteMemory(process_address, bytes, size, error);
513 if (!error.Success())
514 return;
515 }
516 break;
517 case eAllocationPolicyProcessOnly:
518 process_sp = m_process_wp.lock();
519 if (process_sp)
520 {
521 process_sp->WriteMemory(process_address, bytes, size, error);
522 if (!error.Success())
523 return;
524 }
525 break;
526 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000527
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000528 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000529 {
Matt Kopecef143712013-06-03 18:00:07 +0000530 log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000531 (uint64_t)process_address,
532 (uint64_t)bytes,
533 (uint64_t)size,
534 (uint64_t)allocation.m_process_start,
535 (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
536 }
537}
538
539void
Sean Callanan35005f72013-04-12 18:10:34 +0000540IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
Sean Callanan08052af2013-04-17 07:50:58 +0000541{
542 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000543
Sean Callanan35005f72013-04-12 18:10:34 +0000544 if (size == UINT32_MAX)
545 size = scalar.GetByteSize();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000546
Sean Callanan35005f72013-04-12 18:10:34 +0000547 if (size > 0)
548 {
549 uint8_t buf[32];
550 const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
551 if (mem_size > 0)
552 {
553 return WriteMemory(process_address, buf, mem_size, error);
554 }
555 else
556 {
557 error.SetErrorToGenericError();
558 error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
559 }
560 }
561 else
562 {
563 error.SetErrorToGenericError();
564 error.SetErrorString ("Couldn't write scalar: its size was zero");
565 }
566 return;
567}
568
569void
Sean Callananf8043fa2013-04-12 21:40:34 +0000570IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
571{
Sean Callanan08052af2013-04-17 07:50:58 +0000572 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000573
Sean Callananf8043fa2013-04-12 21:40:34 +0000574 Scalar scalar(address);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000575
Sean Callananf8043fa2013-04-12 21:40:34 +0000576 WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
577}
578
Sean Callananf8043fa2013-04-12 21:40:34 +0000579void
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000580IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
581{
Sean Callanan08052af2013-04-17 07:50:58 +0000582 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000583
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000584 AllocationMap::iterator iter = FindAllocation(process_address, size);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000585
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000586 if (iter == m_allocations.end())
587 {
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000588 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000589
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000590 if (process_sp)
591 {
592 process_sp->ReadMemory(process_address, bytes, size, error);
593 return;
594 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000595
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000596 lldb::TargetSP target_sp = m_target_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000597
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000598 if (target_sp)
599 {
600 Address absolute_address(process_address);
601 target_sp->ReadMemory(absolute_address, false, bytes, size, error);
602 return;
603 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000604
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000605 error.SetErrorToGenericError();
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000606 error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist");
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000607 return;
608 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000609
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000610 Allocation &allocation = iter->second;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000611
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000612 uint64_t offset = process_address - allocation.m_process_start;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000613
Sean Callanan9bbf3cd2014-03-04 21:56:11 +0000614 if (offset > allocation.m_size)
615 {
616 error.SetErrorToGenericError();
617 error.SetErrorString("Couldn't read: data is not in the allocation");
618 return;
619 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000620
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000621 lldb::ProcessSP process_sp;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000622
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000623 switch (allocation.m_policy)
624 {
625 default:
626 error.SetErrorToGenericError();
627 error.SetErrorString("Couldn't read: invalid allocation policy");
628 return;
629 case eAllocationPolicyHostOnly:
Sean Callanand2562502013-04-19 17:44:40 +0000630 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000631 {
632 error.SetErrorToGenericError();
633 error.SetErrorString("Couldn't read: data buffer is empty");
634 return;
635 }
Sean Callanan9bbf3cd2014-03-04 21:56:11 +0000636 if (allocation.m_data.GetByteSize() < offset + size)
637 {
638 error.SetErrorToGenericError();
639 error.SetErrorString("Couldn't read: not enough underlying data");
640 return;
641 }
642
Sean Callanand2562502013-04-19 17:44:40 +0000643 ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000644 break;
645 case eAllocationPolicyMirror:
646 process_sp = m_process_wp.lock();
647 if (process_sp)
648 {
649 process_sp->ReadMemory(process_address, bytes, size, error);
650 if (!error.Success())
651 return;
652 }
653 else
654 {
Sean Callanand2562502013-04-19 17:44:40 +0000655 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000656 {
657 error.SetErrorToGenericError();
658 error.SetErrorString("Couldn't read: data buffer is empty");
659 return;
660 }
Sean Callanand2562502013-04-19 17:44:40 +0000661 ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000662 }
663 break;
664 case eAllocationPolicyProcessOnly:
665 process_sp = m_process_wp.lock();
666 if (process_sp)
667 {
668 process_sp->ReadMemory(process_address, bytes, size, error);
669 if (!error.Success())
670 return;
671 }
672 break;
673 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000674
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000675 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
676 {
Matt Kopecef143712013-06-03 18:00:07 +0000677 log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000678 (uint64_t)process_address,
679 (uint64_t)bytes,
680 (uint64_t)size,
681 (uint64_t)allocation.m_process_start,
682 (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
683 }
684}
Sean Callanan35005f72013-04-12 18:10:34 +0000685
686void
687IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
Sean Callanan08052af2013-04-17 07:50:58 +0000688{
689 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000690
Sean Callanan35005f72013-04-12 18:10:34 +0000691 if (size > 0)
692 {
693 DataBufferHeap buf(size, 0);
694 ReadMemory(buf.GetBytes(), process_address, size, error);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000695
Sean Callanan35005f72013-04-12 18:10:34 +0000696 if (!error.Success())
697 return;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000698
Sean Callanan35005f72013-04-12 18:10:34 +0000699 DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000700
Sean Callanan35005f72013-04-12 18:10:34 +0000701 lldb::offset_t offset = 0;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000702
Sean Callanan35005f72013-04-12 18:10:34 +0000703 switch (size)
704 {
705 default:
706 error.SetErrorToGenericError();
Greg Claytone86cef62013-06-04 21:30:42 +0000707 error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
Sean Callanan35005f72013-04-12 18:10:34 +0000708 return;
709 case 1: scalar = extractor.GetU8(&offset); break;
710 case 2: scalar = extractor.GetU16(&offset); break;
711 case 4: scalar = extractor.GetU32(&offset); break;
712 case 8: scalar = extractor.GetU64(&offset); break;
713 }
714 }
715 else
716 {
717 error.SetErrorToGenericError();
Sean Callanan458ae1c2013-04-13 02:06:42 +0000718 error.SetErrorString ("Couldn't read scalar: its size was zero");
Sean Callanan35005f72013-04-12 18:10:34 +0000719 }
720 return;
721}
722
Sean Callanan458ae1c2013-04-13 02:06:42 +0000723void
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000724IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
725{
Sean Callanan08052af2013-04-17 07:50:58 +0000726 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000727
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000728 Scalar pointer_scalar;
729 ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000730
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000731 if (!error.Success())
732 return;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000733
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000734 *address = pointer_scalar.ULongLong();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000735
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000736 return;
737}
738
739void
Sean Callanan458ae1c2013-04-13 02:06:42 +0000740IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
741{
Sean Callanan08052af2013-04-17 07:50:58 +0000742 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000743
Sean Callanan458ae1c2013-04-13 02:06:42 +0000744 if (size > 0)
745 {
746 AllocationMap::iterator iter = FindAllocation(process_address, size);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000747
Sean Callanan458ae1c2013-04-13 02:06:42 +0000748 if (iter == m_allocations.end())
749 {
750 error.SetErrorToGenericError();
Matt Kopecef143712013-06-03 18:00:07 +0000751 error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size);
Sean Callanan458ae1c2013-04-13 02:06:42 +0000752 return;
753 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000754
Sean Callanan458ae1c2013-04-13 02:06:42 +0000755 Allocation &allocation = iter->second;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000756
Sean Callanan458ae1c2013-04-13 02:06:42 +0000757 switch (allocation.m_policy)
758 {
759 default:
760 error.SetErrorToGenericError();
761 error.SetErrorString("Couldn't get memory data: invalid allocation policy");
762 return;
763 case eAllocationPolicyProcessOnly:
764 error.SetErrorToGenericError();
765 error.SetErrorString("Couldn't get memory data: memory is only in the target");
766 return;
Sean Callanan458ae1c2013-04-13 02:06:42 +0000767 case eAllocationPolicyMirror:
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000768 {
769 lldb::ProcessSP process_sp = m_process_wp.lock();
770
Sean Callanand2562502013-04-19 17:44:40 +0000771 if (!allocation.m_data.GetByteSize())
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000772 {
773 error.SetErrorToGenericError();
774 error.SetErrorString("Couldn't get memory data: data buffer is empty");
775 return;
776 }
777 if (process_sp)
778 {
Sean Callanand2562502013-04-19 17:44:40 +0000779 process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error);
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000780 if (!error.Success())
781 return;
782 uint64_t offset = process_address - allocation.m_process_start;
Sean Callanand2562502013-04-19 17:44:40 +0000783 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000784 return;
785 }
786 }
787 case eAllocationPolicyHostOnly:
Sean Callanand2562502013-04-19 17:44:40 +0000788 if (!allocation.m_data.GetByteSize())
Sean Callanan458ae1c2013-04-13 02:06:42 +0000789 {
790 error.SetErrorToGenericError();
791 error.SetErrorString("Couldn't get memory data: data buffer is empty");
792 return;
793 }
794 uint64_t offset = process_address - allocation.m_process_start;
Sean Callanand2562502013-04-19 17:44:40 +0000795 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
Sean Callanan458ae1c2013-04-13 02:06:42 +0000796 return;
797 }
798 }
799 else
800 {
801 error.SetErrorToGenericError();
802 error.SetErrorString ("Couldn't get memory data: its size was zero");
803 return;
804 }
805}