blob: 9239e087b6eb5c68e3f2bb897ad14152ea291fa5 [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
50IRMemoryMap::FindSpace (size_t size)
51{
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;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000056
Sean Callananad7cc462013-06-17 21:19:31 +000057 if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
Sean Callanandf565402013-04-27 02:19:33 +000058 {
59 Error alloc_error;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000060
Sean Callanandf565402013-04-27 02:19:33 +000061 ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000062
Sean Callanandf565402013-04-27 02:19:33 +000063 if (!alloc_error.Success())
64 return LLDB_INVALID_ADDRESS;
65 else
66 return ret;
67 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000068
Sean Callananbb9945f2013-04-19 01:51:24 +000069 for (int iterations = 0; iterations < 16; ++iterations)
Sean Callanan5a1af4e2013-04-05 02:22:57 +000070 {
Jim Ingham5c42d8a2013-05-15 18:27:08 +000071 lldb::addr_t candidate = LLDB_INVALID_ADDRESS;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000072
Sean Callananbb9945f2013-04-19 01:51:24 +000073 switch (target_sp->GetArchitecture().GetAddressByteSize())
74 {
75 case 4:
76 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +000077 uint32_t random_data = rand();
Sean Callananbb9945f2013-04-19 01:51:24 +000078 candidate = random_data;
79 candidate &= ~0xfffull;
80 break;
81 }
82 case 8:
83 {
Virgile Bellob2f1fb22013-08-23 12:44:05 +000084 uint32_t random_low = rand();
85 uint32_t random_high = rand();
Sean Callananbb9945f2013-04-19 01:51:24 +000086 candidate = random_high;
87 candidate <<= 32ull;
88 candidate |= random_low;
89 candidate &= ~0xfffull;
90 break;
91 }
92 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000093
Sean Callananbb9945f2013-04-19 01:51:24 +000094 if (IntersectsAllocation(candidate, size))
95 continue;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000096
Sean Callananbb9945f2013-04-19 01:51:24 +000097 ret = candidate;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +000098
Sean Callananbb777042013-05-16 17:30:37 +000099 return ret;
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000100 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000101
Sean Callananbb9945f2013-04-19 01:51:24 +0000102 return ret;
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000103}
104
105IRMemoryMap::AllocationMap::iterator
106IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
107{
Sean Callanan1582ee62013-04-18 22:06:33 +0000108 if (addr == LLDB_INVALID_ADDRESS)
109 return m_allocations.end();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000110
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000111 AllocationMap::iterator iter = m_allocations.lower_bound (addr);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000112
Sean Callanan14b1bae2013-04-16 23:25:35 +0000113 if (iter == m_allocations.end() ||
114 iter->first > addr)
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000115 {
116 if (iter == m_allocations.begin())
117 return m_allocations.end();
118 iter--;
119 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000120
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000121 if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
122 return iter;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000123
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000124 return m_allocations.end();
125}
126
Sean Callananbb9945f2013-04-19 01:51:24 +0000127bool
Zachary Turner15362442014-06-25 18:37:19 +0000128IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size) const
Sean Callananbb9945f2013-04-19 01:51:24 +0000129{
130 if (addr == LLDB_INVALID_ADDRESS)
131 return false;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000132
Zachary Turner15362442014-06-25 18:37:19 +0000133 AllocationMap::const_iterator iter = m_allocations.lower_bound (addr);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000134
Zachary Turner15362442014-06-25 18:37:19 +0000135 // Since we only know that the returned interval begins at a location greater than or
136 // equal to where the given interval begins, it's possible that the given interval
137 // intersects either the returned interval or the previous interval. Thus, we need to
138 // check both. Note that we only need to check these two intervals. Since all intervals
139 // are disjoint it is not possible that an adjacent interval does not intersect, but a
140 // non-adjacent interval does intersect.
141 if (iter != m_allocations.end()) {
Zachary Turnercfcd7912014-06-25 18:40:58 +0000142 if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
Sean Callananbb9945f2013-04-19 01:51:24 +0000143 return true;
Sean Callananbb9945f2013-04-19 01:51:24 +0000144 }
Zachary Turner15362442014-06-25 18:37:19 +0000145
146 if (iter != m_allocations.begin()) {
147 --iter;
Zachary Turnercfcd7912014-06-25 18:40:58 +0000148 if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
Zachary Turner15362442014-06-25 18:37:19 +0000149 return true;
150 }
151
Sean Callananbb9945f2013-04-19 01:51:24 +0000152 return false;
153}
154
Zachary Turner15362442014-06-25 18:37:19 +0000155bool
156IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1, lldb::addr_t addr2, size_t size2) {
157 // Given two half open intervals [A, B) and [X, Y), the only 6 permutations that satisfy
158 // A<B and X<Y are the following:
159 // A B X Y
160 // A X B Y (intersects)
161 // A X Y B (intersects)
162 // X A B Y (intersects)
163 // X A Y B (intersects)
164 // X Y A B
165 // The first is B <= X, and the last is Y <= A.
166 // So the condition is !(B <= X || Y <= A)), or (X < B && A < Y)
167 return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
168}
169
Sean Callanan35005f72013-04-12 18:10:34 +0000170lldb::ByteOrder
171IRMemoryMap::GetByteOrder()
172{
173 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000174
Sean Callanan35005f72013-04-12 18:10:34 +0000175 if (process_sp)
176 return process_sp->GetByteOrder();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000177
Sean Callanan35005f72013-04-12 18:10:34 +0000178 lldb::TargetSP target_sp = m_target_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000179
Sean Callanan35005f72013-04-12 18:10:34 +0000180 if (target_sp)
Sean Callanan08052af2013-04-17 07:50:58 +0000181 return target_sp->GetArchitecture().GetByteOrder();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000182
Sean Callanan35005f72013-04-12 18:10:34 +0000183 return lldb::eByteOrderInvalid;
184}
185
186uint32_t
187IRMemoryMap::GetAddressByteSize()
188{
189 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000190
Sean Callanan35005f72013-04-12 18:10:34 +0000191 if (process_sp)
192 return process_sp->GetAddressByteSize();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000193
Sean Callanan35005f72013-04-12 18:10:34 +0000194 lldb::TargetSP target_sp = m_target_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000195
Sean Callanan35005f72013-04-12 18:10:34 +0000196 if (target_sp)
Sean Callanan08052af2013-04-17 07:50:58 +0000197 return target_sp->GetArchitecture().GetAddressByteSize();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000198
Sean Callanan35005f72013-04-12 18:10:34 +0000199 return UINT32_MAX;
200}
201
202ExecutionContextScope *
Greg Clayton23f8c952014-03-24 23:10:19 +0000203IRMemoryMap::GetBestExecutionContextScope() const
Sean Callanan35005f72013-04-12 18:10:34 +0000204{
205 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000206
Sean Callanan35005f72013-04-12 18:10:34 +0000207 if (process_sp)
208 return process_sp.get();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000209
Sean Callanan35005f72013-04-12 18:10:34 +0000210 lldb::TargetSP target_sp = m_target_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000211
Sean Callanan35005f72013-04-12 18:10:34 +0000212 if (target_sp)
213 return target_sp.get();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000214
Sean Callanan35005f72013-04-12 18:10:34 +0000215 return NULL;
216}
217
Sean Callanand2562502013-04-19 17:44:40 +0000218IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
219 lldb::addr_t process_start,
220 size_t size,
221 uint32_t permissions,
222 uint8_t alignment,
Michael Sartain6fea7792013-08-06 22:21:08 +0000223 AllocationPolicy policy) :
224 m_process_alloc (process_alloc),
225 m_process_start (process_start),
226 m_size (size),
227 m_permissions (permissions),
228 m_alignment (alignment),
229 m_policy (policy),
230 m_leak (false)
Sean Callanand2562502013-04-19 17:44:40 +0000231{
Sean Callanand2562502013-04-19 17:44:40 +0000232 switch (policy)
233 {
234 default:
235 assert (0 && "We cannot reach this!");
236 case eAllocationPolicyHostOnly:
237 m_data.SetByteSize(size);
238 memset(m_data.GetBytes(), 0, size);
239 break;
240 case eAllocationPolicyProcessOnly:
241 break;
242 case eAllocationPolicyMirror:
243 m_data.SetByteSize(size);
244 memset(m_data.GetBytes(), 0, size);
245 break;
246 }
247}
248
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000249lldb::addr_t
250IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
251{
Todd Fialaaf245d12014-06-30 21:05:18 +0000252 lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan08052af2013-04-17 07:50:58 +0000253 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000254
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000255 lldb::ProcessSP process_sp;
256 lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
257 lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
Matt Kopec750dcc32013-04-26 17:48:01 +0000258
259 size_t alignment_mask = alignment - 1;
260 size_t allocation_size;
261
262 if (size == 0)
263 allocation_size = alignment;
264 else
265 allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000266
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000267 switch (policy)
268 {
269 default:
270 error.SetErrorToGenericError();
271 error.SetErrorString("Couldn't malloc: invalid allocation policy");
272 return LLDB_INVALID_ADDRESS;
273 case eAllocationPolicyHostOnly:
274 allocation_address = FindSpace(allocation_size);
275 if (allocation_address == LLDB_INVALID_ADDRESS)
276 {
277 error.SetErrorToGenericError();
278 error.SetErrorString("Couldn't malloc: address space is full");
279 return LLDB_INVALID_ADDRESS;
280 }
281 break;
282 case eAllocationPolicyMirror:
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000283 process_sp = m_process_wp.lock();
Todd Fialaaf245d12014-06-30 21:05:18 +0000284 if (log)
285 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 +0000286 if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000287 {
288 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
289 if (!error.Success())
290 return LLDB_INVALID_ADDRESS;
291 }
292 else
293 {
Todd Fialaaf245d12014-06-30 21:05:18 +0000294 if (log)
295 log->Printf ("IRMemoryMap::%s switching to eAllocationPolicyHostOnly due to failed condition (see previous expr log message)", __FUNCTION__);
Sean Callananbb9945f2013-04-19 01:51:24 +0000296 policy = eAllocationPolicyHostOnly;
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000297 allocation_address = FindSpace(allocation_size);
298 if (allocation_address == LLDB_INVALID_ADDRESS)
299 {
300 error.SetErrorToGenericError();
301 error.SetErrorString("Couldn't malloc: address space is full");
302 return LLDB_INVALID_ADDRESS;
303 }
304 }
305 break;
306 case eAllocationPolicyProcessOnly:
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000307 process_sp = m_process_wp.lock();
308 if (process_sp)
309 {
Sean Callananad7cc462013-06-17 21:19:31 +0000310 if (process_sp->CanJIT() && process_sp->IsAlive())
Sean Callananbb9945f2013-04-19 01:51:24 +0000311 {
312 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
313 if (!error.Success())
314 return LLDB_INVALID_ADDRESS;
315 }
316 else
317 {
318 error.SetErrorToGenericError();
319 error.SetErrorString("Couldn't malloc: process doesn't support allocating memory");
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000320 return LLDB_INVALID_ADDRESS;
Sean Callananbb9945f2013-04-19 01:51:24 +0000321 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000322 }
323 else
324 {
325 error.SetErrorToGenericError();
326 error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
327 return LLDB_INVALID_ADDRESS;
328 }
329 break;
330 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000331
332
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000333 lldb::addr_t mask = alignment - 1;
334 aligned_address = (allocation_address + mask) & (~mask);
335
Sean Callanand2562502013-04-19 17:44:40 +0000336 m_allocations[aligned_address] = Allocation(allocation_address,
337 aligned_address,
Matt Kopec750dcc32013-04-26 17:48:01 +0000338 allocation_size,
Sean Callanand2562502013-04-19 17:44:40 +0000339 permissions,
340 alignment,
341 policy);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000342
Todd Fialaaf245d12014-06-30 21:05:18 +0000343 if (log)
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000344 {
345 const char * policy_string;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000346
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000347 switch (policy)
348 {
349 default:
350 policy_string = "<invalid policy>";
351 break;
352 case eAllocationPolicyHostOnly:
353 policy_string = "eAllocationPolicyHostOnly";
354 break;
355 case eAllocationPolicyProcessOnly:
356 policy_string = "eAllocationPolicyProcessOnly";
357 break;
358 case eAllocationPolicyMirror:
359 policy_string = "eAllocationPolicyMirror";
360 break;
361 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000362
Matt Kopecef143712013-06-03 18:00:07 +0000363 log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64,
Matt Kopec750dcc32013-04-26 17:48:01 +0000364 (uint64_t)allocation_size,
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000365 (uint64_t)alignment,
366 (uint64_t)permissions,
367 policy_string,
368 aligned_address);
369 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000370
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000371 return aligned_address;
372}
373
374void
Sean Callananfbf5c682013-05-22 22:49:06 +0000375IRMemoryMap::Leak (lldb::addr_t process_address, Error &error)
376{
377 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000378
Sean Callananfbf5c682013-05-22 22:49:06 +0000379 AllocationMap::iterator iter = m_allocations.find(process_address);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000380
Sean Callananfbf5c682013-05-22 22:49:06 +0000381 if (iter == m_allocations.end())
382 {
383 error.SetErrorToGenericError();
384 error.SetErrorString("Couldn't leak: allocation doesn't exist");
385 return;
386 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000387
Sean Callananfbf5c682013-05-22 22:49:06 +0000388 Allocation &allocation = iter->second;
389
390 allocation.m_leak = true;
391}
392
393void
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000394IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
395{
Sean Callanan08052af2013-04-17 07:50:58 +0000396 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000397
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000398 AllocationMap::iterator iter = m_allocations.find(process_address);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000399
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000400 if (iter == m_allocations.end())
401 {
402 error.SetErrorToGenericError();
403 error.SetErrorString("Couldn't free: allocation doesn't exist");
404 return;
405 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000406
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000407 Allocation &allocation = iter->second;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000408
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000409 switch (allocation.m_policy)
410 {
411 default:
412 case eAllocationPolicyHostOnly:
Sean Callanandf565402013-04-27 02:19:33 +0000413 {
414 lldb::ProcessSP process_sp = m_process_wp.lock();
Sean Callananbb777042013-05-16 17:30:37 +0000415 if (process_sp)
416 {
Sean Callananad7cc462013-06-17 21:19:31 +0000417 if (process_sp->CanJIT() && process_sp->IsAlive())
Sean Callananbb777042013-05-16 17:30:37 +0000418 process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
Sean Callananbb777042013-05-16 17:30:37 +0000419 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000420
Sean Callanandf565402013-04-27 02:19:33 +0000421 break;
422 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000423 case eAllocationPolicyMirror:
424 case eAllocationPolicyProcessOnly:
Sean Callanandf565402013-04-27 02:19:33 +0000425 {
426 lldb::ProcessSP process_sp = m_process_wp.lock();
427 if (process_sp)
428 process_sp->DeallocateMemory(allocation.m_process_alloc);
429 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000430 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000431
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000432 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000433 {
Matt Kopecef143712013-06-03 18:00:07 +0000434 log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")",
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000435 (uint64_t)process_address,
436 iter->second.m_process_start,
437 iter->second.m_process_start + iter->second.m_size);
438 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000439
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000440 m_allocations.erase(iter);
441}
442
443void
444IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
445{
Sean Callanan08052af2013-04-17 07:50:58 +0000446 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000447
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000448 AllocationMap::iterator iter = FindAllocation(process_address, size);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000449
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000450 if (iter == m_allocations.end())
451 {
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000452 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000453
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000454 if (process_sp)
455 {
456 process_sp->WriteMemory(process_address, bytes, size, error);
457 return;
458 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000459
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000460 error.SetErrorToGenericError();
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000461 error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000462 return;
463 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000464
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000465 Allocation &allocation = iter->second;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000466
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000467 uint64_t offset = process_address - allocation.m_process_start;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000468
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000469 lldb::ProcessSP process_sp;
470
471 switch (allocation.m_policy)
472 {
473 default:
474 error.SetErrorToGenericError();
475 error.SetErrorString("Couldn't write: invalid allocation policy");
476 return;
477 case eAllocationPolicyHostOnly:
Sean Callanand2562502013-04-19 17:44:40 +0000478 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000479 {
480 error.SetErrorToGenericError();
481 error.SetErrorString("Couldn't write: data buffer is empty");
482 return;
483 }
Sean Callanand2562502013-04-19 17:44:40 +0000484 ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000485 break;
486 case eAllocationPolicyMirror:
Sean Callanand2562502013-04-19 17:44:40 +0000487 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000488 {
489 error.SetErrorToGenericError();
490 error.SetErrorString("Couldn't write: data buffer is empty");
491 return;
492 }
Sean Callanand2562502013-04-19 17:44:40 +0000493 ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000494 process_sp = m_process_wp.lock();
495 if (process_sp)
496 {
497 process_sp->WriteMemory(process_address, bytes, size, error);
498 if (!error.Success())
499 return;
500 }
501 break;
502 case eAllocationPolicyProcessOnly:
503 process_sp = m_process_wp.lock();
504 if (process_sp)
505 {
506 process_sp->WriteMemory(process_address, bytes, size, error);
507 if (!error.Success())
508 return;
509 }
510 break;
511 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000512
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000513 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000514 {
Matt Kopecef143712013-06-03 18:00:07 +0000515 log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000516 (uint64_t)process_address,
517 (uint64_t)bytes,
518 (uint64_t)size,
519 (uint64_t)allocation.m_process_start,
520 (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
521 }
522}
523
524void
Sean Callanan35005f72013-04-12 18:10:34 +0000525IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
Sean Callanan08052af2013-04-17 07:50:58 +0000526{
527 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000528
Sean Callanan35005f72013-04-12 18:10:34 +0000529 if (size == UINT32_MAX)
530 size = scalar.GetByteSize();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000531
Sean Callanan35005f72013-04-12 18:10:34 +0000532 if (size > 0)
533 {
534 uint8_t buf[32];
535 const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
536 if (mem_size > 0)
537 {
538 return WriteMemory(process_address, buf, mem_size, error);
539 }
540 else
541 {
542 error.SetErrorToGenericError();
543 error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
544 }
545 }
546 else
547 {
548 error.SetErrorToGenericError();
549 error.SetErrorString ("Couldn't write scalar: its size was zero");
550 }
551 return;
552}
553
554void
Sean Callananf8043fa2013-04-12 21:40:34 +0000555IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
556{
Sean Callanan08052af2013-04-17 07:50:58 +0000557 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000558
Sean Callananf8043fa2013-04-12 21:40:34 +0000559 Scalar scalar(address);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000560
Sean Callananf8043fa2013-04-12 21:40:34 +0000561 WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
562}
563
Sean Callananf8043fa2013-04-12 21:40:34 +0000564void
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000565IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
566{
Sean Callanan08052af2013-04-17 07:50:58 +0000567 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000568
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000569 AllocationMap::iterator iter = FindAllocation(process_address, size);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000570
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000571 if (iter == m_allocations.end())
572 {
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000573 lldb::ProcessSP process_sp = m_process_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000574
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000575 if (process_sp)
576 {
577 process_sp->ReadMemory(process_address, bytes, size, error);
578 return;
579 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000580
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000581 lldb::TargetSP target_sp = m_target_wp.lock();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000582
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000583 if (target_sp)
584 {
585 Address absolute_address(process_address);
586 target_sp->ReadMemory(absolute_address, false, bytes, size, error);
587 return;
588 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000589
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000590 error.SetErrorToGenericError();
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000591 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 +0000592 return;
593 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000594
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000595 Allocation &allocation = iter->second;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000596
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000597 uint64_t offset = process_address - allocation.m_process_start;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000598
Sean Callanan9bbf3cd2014-03-04 21:56:11 +0000599 if (offset > allocation.m_size)
600 {
601 error.SetErrorToGenericError();
602 error.SetErrorString("Couldn't read: data is not in the allocation");
603 return;
604 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000605
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000606 lldb::ProcessSP process_sp;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000607
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000608 switch (allocation.m_policy)
609 {
610 default:
611 error.SetErrorToGenericError();
612 error.SetErrorString("Couldn't read: invalid allocation policy");
613 return;
614 case eAllocationPolicyHostOnly:
Sean Callanand2562502013-04-19 17:44:40 +0000615 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000616 {
617 error.SetErrorToGenericError();
618 error.SetErrorString("Couldn't read: data buffer is empty");
619 return;
620 }
Sean Callanan9bbf3cd2014-03-04 21:56:11 +0000621 if (allocation.m_data.GetByteSize() < offset + size)
622 {
623 error.SetErrorToGenericError();
624 error.SetErrorString("Couldn't read: not enough underlying data");
625 return;
626 }
627
Sean Callanand2562502013-04-19 17:44:40 +0000628 ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000629 break;
630 case eAllocationPolicyMirror:
631 process_sp = m_process_wp.lock();
632 if (process_sp)
633 {
634 process_sp->ReadMemory(process_address, bytes, size, error);
635 if (!error.Success())
636 return;
637 }
638 else
639 {
Sean Callanand2562502013-04-19 17:44:40 +0000640 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000641 {
642 error.SetErrorToGenericError();
643 error.SetErrorString("Couldn't read: data buffer is empty");
644 return;
645 }
Sean Callanand2562502013-04-19 17:44:40 +0000646 ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000647 }
648 break;
649 case eAllocationPolicyProcessOnly:
650 process_sp = m_process_wp.lock();
651 if (process_sp)
652 {
653 process_sp->ReadMemory(process_address, bytes, size, error);
654 if (!error.Success())
655 return;
656 }
657 break;
658 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000659
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000660 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
661 {
Matt Kopecef143712013-06-03 18:00:07 +0000662 log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000663 (uint64_t)process_address,
664 (uint64_t)bytes,
665 (uint64_t)size,
666 (uint64_t)allocation.m_process_start,
667 (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
668 }
669}
Sean Callanan35005f72013-04-12 18:10:34 +0000670
671void
672IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
Sean Callanan08052af2013-04-17 07:50:58 +0000673{
674 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000675
Sean Callanan35005f72013-04-12 18:10:34 +0000676 if (size > 0)
677 {
678 DataBufferHeap buf(size, 0);
679 ReadMemory(buf.GetBytes(), process_address, size, error);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000680
Sean Callanan35005f72013-04-12 18:10:34 +0000681 if (!error.Success())
682 return;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000683
Sean Callanan35005f72013-04-12 18:10:34 +0000684 DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000685
Sean Callanan35005f72013-04-12 18:10:34 +0000686 lldb::offset_t offset = 0;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000687
Sean Callanan35005f72013-04-12 18:10:34 +0000688 switch (size)
689 {
690 default:
691 error.SetErrorToGenericError();
Greg Claytone86cef62013-06-04 21:30:42 +0000692 error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
Sean Callanan35005f72013-04-12 18:10:34 +0000693 return;
694 case 1: scalar = extractor.GetU8(&offset); break;
695 case 2: scalar = extractor.GetU16(&offset); break;
696 case 4: scalar = extractor.GetU32(&offset); break;
697 case 8: scalar = extractor.GetU64(&offset); break;
698 }
699 }
700 else
701 {
702 error.SetErrorToGenericError();
Sean Callanan458ae1c2013-04-13 02:06:42 +0000703 error.SetErrorString ("Couldn't read scalar: its size was zero");
Sean Callanan35005f72013-04-12 18:10:34 +0000704 }
705 return;
706}
707
Sean Callanan458ae1c2013-04-13 02:06:42 +0000708void
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000709IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
710{
Sean Callanan08052af2013-04-17 07:50:58 +0000711 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000712
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000713 Scalar pointer_scalar;
714 ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000715
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000716 if (!error.Success())
717 return;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000718
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000719 *address = pointer_scalar.ULongLong();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000720
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000721 return;
722}
723
724void
Sean Callanan458ae1c2013-04-13 02:06:42 +0000725IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
726{
Sean Callanan08052af2013-04-17 07:50:58 +0000727 error.Clear();
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000728
Sean Callanan458ae1c2013-04-13 02:06:42 +0000729 if (size > 0)
730 {
731 AllocationMap::iterator iter = FindAllocation(process_address, size);
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000732
Sean Callanan458ae1c2013-04-13 02:06:42 +0000733 if (iter == m_allocations.end())
734 {
735 error.SetErrorToGenericError();
Matt Kopecef143712013-06-03 18:00:07 +0000736 error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size);
Sean Callanan458ae1c2013-04-13 02:06:42 +0000737 return;
738 }
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000739
Sean Callanan458ae1c2013-04-13 02:06:42 +0000740 Allocation &allocation = iter->second;
Sylvestre Ledruceab3ac2014-07-06 17:54:58 +0000741
Sean Callanan458ae1c2013-04-13 02:06:42 +0000742 switch (allocation.m_policy)
743 {
744 default:
745 error.SetErrorToGenericError();
746 error.SetErrorString("Couldn't get memory data: invalid allocation policy");
747 return;
748 case eAllocationPolicyProcessOnly:
749 error.SetErrorToGenericError();
750 error.SetErrorString("Couldn't get memory data: memory is only in the target");
751 return;
Sean Callanan458ae1c2013-04-13 02:06:42 +0000752 case eAllocationPolicyMirror:
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000753 {
754 lldb::ProcessSP process_sp = m_process_wp.lock();
755
Sean Callanand2562502013-04-19 17:44:40 +0000756 if (!allocation.m_data.GetByteSize())
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000757 {
758 error.SetErrorToGenericError();
759 error.SetErrorString("Couldn't get memory data: data buffer is empty");
760 return;
761 }
762 if (process_sp)
763 {
Sean Callanand2562502013-04-19 17:44:40 +0000764 process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error);
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000765 if (!error.Success())
766 return;
767 uint64_t offset = process_address - allocation.m_process_start;
Sean Callanand2562502013-04-19 17:44:40 +0000768 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000769 return;
770 }
771 }
772 case eAllocationPolicyHostOnly:
Sean Callanand2562502013-04-19 17:44:40 +0000773 if (!allocation.m_data.GetByteSize())
Sean Callanan458ae1c2013-04-13 02:06:42 +0000774 {
775 error.SetErrorToGenericError();
776 error.SetErrorString("Couldn't get memory data: data buffer is empty");
777 return;
778 }
779 uint64_t offset = process_address - allocation.m_process_start;
Sean Callanand2562502013-04-19 17:44:40 +0000780 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
Sean Callanan458ae1c2013-04-13 02:06:42 +0000781 return;
782 }
783 }
784 else
785 {
786 error.SetErrorToGenericError();
787 error.SetErrorString ("Couldn't get memory data: its size was zero");
788 return;
789 }
790}