blob: f7d4a428c35855319660479dd1f1844f95882d7e [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();
31
32 if (process_sp)
33 {
Sean Callananbb777042013-05-16 17:30:37 +000034 AllocationMap::iterator iter;
35
36 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();
Sean Callanan5a1af4e2013-04-05 02:22:57 +000054
Sean Callananbb9945f2013-04-19 01:51:24 +000055 lldb::addr_t ret = LLDB_INVALID_ADDRESS;
Sean Callanan5a1af4e2013-04-05 02:22:57 +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;
60
61 ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
62
63 if (!alloc_error.Success())
64 return LLDB_INVALID_ADDRESS;
65 else
66 return ret;
67 }
68
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;
Sean Callananbb9945f2013-04-19 01:51:24 +000072
73 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 }
93
94 if (IntersectsAllocation(candidate, size))
95 continue;
Sean Callanan70cac8f2013-06-27 00:10:26 +000096
Sean Callananbb9945f2013-04-19 01:51:24 +000097 ret = candidate;
Sean Callanan70cac8f2013-06-27 00:10:26 +000098
Sean Callananbb777042013-05-16 17:30:37 +000099 return ret;
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000100 }
101
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();
110
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000111 AllocationMap::iterator iter = m_allocations.lower_bound (addr);
112
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 }
120
121 if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
122 return iter;
123
124 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;
132
Zachary Turner15362442014-06-25 18:37:19 +0000133 AllocationMap::const_iterator iter = m_allocations.lower_bound (addr);
Sean Callananbb9945f2013-04-19 01:51:24 +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();
174
175 if (process_sp)
176 return process_sp->GetByteOrder();
177
178 lldb::TargetSP target_sp = m_target_wp.lock();
179
180 if (target_sp)
Sean Callanan08052af2013-04-17 07:50:58 +0000181 return target_sp->GetArchitecture().GetByteOrder();
Sean Callanan35005f72013-04-12 18:10:34 +0000182
183 return lldb::eByteOrderInvalid;
184}
185
186uint32_t
187IRMemoryMap::GetAddressByteSize()
188{
189 lldb::ProcessSP process_sp = m_process_wp.lock();
190
191 if (process_sp)
192 return process_sp->GetAddressByteSize();
193
194 lldb::TargetSP target_sp = m_target_wp.lock();
195
196 if (target_sp)
Sean Callanan08052af2013-04-17 07:50:58 +0000197 return target_sp->GetArchitecture().GetAddressByteSize();
Sean Callanan35005f72013-04-12 18:10:34 +0000198
199 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();
206
207 if (process_sp)
208 return process_sp.get();
209
210 lldb::TargetSP target_sp = m_target_wp.lock();
211
212 if (target_sp)
213 return target_sp.get();
214
215 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{
Sean Callanan08052af2013-04-17 07:50:58 +0000252 error.Clear();
253
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000254 lldb::ProcessSP process_sp;
255 lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
256 lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
Matt Kopec750dcc32013-04-26 17:48:01 +0000257
258 size_t alignment_mask = alignment - 1;
259 size_t allocation_size;
260
261 if (size == 0)
262 allocation_size = alignment;
263 else
264 allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size;
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000265
266 switch (policy)
267 {
268 default:
269 error.SetErrorToGenericError();
270 error.SetErrorString("Couldn't malloc: invalid allocation policy");
271 return LLDB_INVALID_ADDRESS;
272 case eAllocationPolicyHostOnly:
273 allocation_address = FindSpace(allocation_size);
274 if (allocation_address == LLDB_INVALID_ADDRESS)
275 {
276 error.SetErrorToGenericError();
277 error.SetErrorString("Couldn't malloc: address space is full");
278 return LLDB_INVALID_ADDRESS;
279 }
280 break;
281 case eAllocationPolicyMirror:
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000282 process_sp = m_process_wp.lock();
Sean Callananad7cc462013-06-17 21:19:31 +0000283 if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000284 {
285 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
286 if (!error.Success())
287 return LLDB_INVALID_ADDRESS;
288 }
289 else
290 {
Sean Callananbb9945f2013-04-19 01:51:24 +0000291 policy = eAllocationPolicyHostOnly;
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000292 allocation_address = FindSpace(allocation_size);
293 if (allocation_address == LLDB_INVALID_ADDRESS)
294 {
295 error.SetErrorToGenericError();
296 error.SetErrorString("Couldn't malloc: address space is full");
297 return LLDB_INVALID_ADDRESS;
298 }
299 }
300 break;
301 case eAllocationPolicyProcessOnly:
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000302 process_sp = m_process_wp.lock();
303 if (process_sp)
304 {
Sean Callananad7cc462013-06-17 21:19:31 +0000305 if (process_sp->CanJIT() && process_sp->IsAlive())
Sean Callananbb9945f2013-04-19 01:51:24 +0000306 {
307 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
308 if (!error.Success())
309 return LLDB_INVALID_ADDRESS;
310 }
311 else
312 {
313 error.SetErrorToGenericError();
314 error.SetErrorString("Couldn't malloc: process doesn't support allocating memory");
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000315 return LLDB_INVALID_ADDRESS;
Sean Callananbb9945f2013-04-19 01:51:24 +0000316 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000317 }
318 else
319 {
320 error.SetErrorToGenericError();
321 error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
322 return LLDB_INVALID_ADDRESS;
323 }
324 break;
325 }
326
327
328 lldb::addr_t mask = alignment - 1;
329 aligned_address = (allocation_address + mask) & (~mask);
330
Sean Callanand2562502013-04-19 17:44:40 +0000331 m_allocations[aligned_address] = Allocation(allocation_address,
332 aligned_address,
Matt Kopec750dcc32013-04-26 17:48:01 +0000333 allocation_size,
Sean Callanand2562502013-04-19 17:44:40 +0000334 permissions,
335 alignment,
336 policy);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000337
338 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
339 {
340 const char * policy_string;
341
342 switch (policy)
343 {
344 default:
345 policy_string = "<invalid policy>";
346 break;
347 case eAllocationPolicyHostOnly:
348 policy_string = "eAllocationPolicyHostOnly";
349 break;
350 case eAllocationPolicyProcessOnly:
351 policy_string = "eAllocationPolicyProcessOnly";
352 break;
353 case eAllocationPolicyMirror:
354 policy_string = "eAllocationPolicyMirror";
355 break;
356 }
357
Matt Kopecef143712013-06-03 18:00:07 +0000358 log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64,
Matt Kopec750dcc32013-04-26 17:48:01 +0000359 (uint64_t)allocation_size,
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000360 (uint64_t)alignment,
361 (uint64_t)permissions,
362 policy_string,
363 aligned_address);
364 }
365
366 return aligned_address;
367}
368
369void
Sean Callananfbf5c682013-05-22 22:49:06 +0000370IRMemoryMap::Leak (lldb::addr_t process_address, Error &error)
371{
372 error.Clear();
373
374 AllocationMap::iterator iter = m_allocations.find(process_address);
375
376 if (iter == m_allocations.end())
377 {
378 error.SetErrorToGenericError();
379 error.SetErrorString("Couldn't leak: allocation doesn't exist");
380 return;
381 }
382
383 Allocation &allocation = iter->second;
384
385 allocation.m_leak = true;
386}
387
388void
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000389IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
390{
Sean Callanan08052af2013-04-17 07:50:58 +0000391 error.Clear();
392
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000393 AllocationMap::iterator iter = m_allocations.find(process_address);
394
395 if (iter == m_allocations.end())
396 {
397 error.SetErrorToGenericError();
398 error.SetErrorString("Couldn't free: allocation doesn't exist");
399 return;
400 }
401
402 Allocation &allocation = iter->second;
403
404 switch (allocation.m_policy)
405 {
406 default:
407 case eAllocationPolicyHostOnly:
Sean Callanandf565402013-04-27 02:19:33 +0000408 {
409 lldb::ProcessSP process_sp = m_process_wp.lock();
Sean Callananbb777042013-05-16 17:30:37 +0000410 if (process_sp)
411 {
Sean Callananad7cc462013-06-17 21:19:31 +0000412 if (process_sp->CanJIT() && process_sp->IsAlive())
Sean Callananbb777042013-05-16 17:30:37 +0000413 process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
Sean Callananbb777042013-05-16 17:30:37 +0000414 }
415
Sean Callanandf565402013-04-27 02:19:33 +0000416 break;
417 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000418 case eAllocationPolicyMirror:
419 case eAllocationPolicyProcessOnly:
Sean Callanandf565402013-04-27 02:19:33 +0000420 {
421 lldb::ProcessSP process_sp = m_process_wp.lock();
422 if (process_sp)
423 process_sp->DeallocateMemory(allocation.m_process_alloc);
424 }
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000425 }
426
427 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
428 {
Matt Kopecef143712013-06-03 18:00:07 +0000429 log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")",
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000430 (uint64_t)process_address,
431 iter->second.m_process_start,
432 iter->second.m_process_start + iter->second.m_size);
433 }
434
435 m_allocations.erase(iter);
436}
437
438void
439IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
440{
Sean Callanan08052af2013-04-17 07:50:58 +0000441 error.Clear();
442
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000443 AllocationMap::iterator iter = FindAllocation(process_address, size);
444
445 if (iter == m_allocations.end())
446 {
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000447 lldb::ProcessSP process_sp = m_process_wp.lock();
448
449 if (process_sp)
450 {
451 process_sp->WriteMemory(process_address, bytes, size, error);
452 return;
453 }
454
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000455 error.SetErrorToGenericError();
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000456 error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000457 return;
458 }
459
460 Allocation &allocation = iter->second;
461
462 uint64_t offset = process_address - allocation.m_process_start;
463
464 lldb::ProcessSP process_sp;
465
466 switch (allocation.m_policy)
467 {
468 default:
469 error.SetErrorToGenericError();
470 error.SetErrorString("Couldn't write: invalid allocation policy");
471 return;
472 case eAllocationPolicyHostOnly:
Sean Callanand2562502013-04-19 17:44:40 +0000473 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000474 {
475 error.SetErrorToGenericError();
476 error.SetErrorString("Couldn't write: data buffer is empty");
477 return;
478 }
Sean Callanand2562502013-04-19 17:44:40 +0000479 ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000480 break;
481 case eAllocationPolicyMirror:
Sean Callanand2562502013-04-19 17:44:40 +0000482 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000483 {
484 error.SetErrorToGenericError();
485 error.SetErrorString("Couldn't write: data buffer is empty");
486 return;
487 }
Sean Callanand2562502013-04-19 17:44:40 +0000488 ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000489 process_sp = m_process_wp.lock();
490 if (process_sp)
491 {
492 process_sp->WriteMemory(process_address, bytes, size, error);
493 if (!error.Success())
494 return;
495 }
496 break;
497 case eAllocationPolicyProcessOnly:
498 process_sp = m_process_wp.lock();
499 if (process_sp)
500 {
501 process_sp->WriteMemory(process_address, bytes, size, error);
502 if (!error.Success())
503 return;
504 }
505 break;
506 }
507
508 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
509 {
Matt Kopecef143712013-06-03 18:00:07 +0000510 log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000511 (uint64_t)process_address,
512 (uint64_t)bytes,
513 (uint64_t)size,
514 (uint64_t)allocation.m_process_start,
515 (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
516 }
517}
518
519void
Sean Callanan35005f72013-04-12 18:10:34 +0000520IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
Sean Callanan08052af2013-04-17 07:50:58 +0000521{
522 error.Clear();
523
Sean Callanan35005f72013-04-12 18:10:34 +0000524 if (size == UINT32_MAX)
525 size = scalar.GetByteSize();
526
527 if (size > 0)
528 {
529 uint8_t buf[32];
530 const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
531 if (mem_size > 0)
532 {
533 return WriteMemory(process_address, buf, mem_size, error);
534 }
535 else
536 {
537 error.SetErrorToGenericError();
538 error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
539 }
540 }
541 else
542 {
543 error.SetErrorToGenericError();
544 error.SetErrorString ("Couldn't write scalar: its size was zero");
545 }
546 return;
547}
548
549void
Sean Callananf8043fa2013-04-12 21:40:34 +0000550IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
551{
Sean Callanan08052af2013-04-17 07:50:58 +0000552 error.Clear();
553
Sean Callananf8043fa2013-04-12 21:40:34 +0000554 Scalar scalar(address);
555
556 WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
557}
558
Sean Callananf8043fa2013-04-12 21:40:34 +0000559void
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000560IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
561{
Sean Callanan08052af2013-04-17 07:50:58 +0000562 error.Clear();
563
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000564 AllocationMap::iterator iter = FindAllocation(process_address, size);
565
566 if (iter == m_allocations.end())
567 {
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000568 lldb::ProcessSP process_sp = m_process_wp.lock();
569
570 if (process_sp)
571 {
572 process_sp->ReadMemory(process_address, bytes, size, error);
573 return;
574 }
575
576 lldb::TargetSP target_sp = m_target_wp.lock();
577
578 if (target_sp)
579 {
580 Address absolute_address(process_address);
581 target_sp->ReadMemory(absolute_address, false, bytes, size, error);
582 return;
583 }
584
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000585 error.SetErrorToGenericError();
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000586 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 +0000587 return;
588 }
589
590 Allocation &allocation = iter->second;
591
592 uint64_t offset = process_address - allocation.m_process_start;
593
Sean Callanan9bbf3cd2014-03-04 21:56:11 +0000594 if (offset > allocation.m_size)
595 {
596 error.SetErrorToGenericError();
597 error.SetErrorString("Couldn't read: data is not in the allocation");
598 return;
599 }
600
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000601 lldb::ProcessSP process_sp;
602
603 switch (allocation.m_policy)
604 {
605 default:
606 error.SetErrorToGenericError();
607 error.SetErrorString("Couldn't read: invalid allocation policy");
608 return;
609 case eAllocationPolicyHostOnly:
Sean Callanand2562502013-04-19 17:44:40 +0000610 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000611 {
612 error.SetErrorToGenericError();
613 error.SetErrorString("Couldn't read: data buffer is empty");
614 return;
615 }
Sean Callanan9bbf3cd2014-03-04 21:56:11 +0000616 if (allocation.m_data.GetByteSize() < offset + size)
617 {
618 error.SetErrorToGenericError();
619 error.SetErrorString("Couldn't read: not enough underlying data");
620 return;
621 }
622
Sean Callanand2562502013-04-19 17:44:40 +0000623 ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000624 break;
625 case eAllocationPolicyMirror:
626 process_sp = m_process_wp.lock();
627 if (process_sp)
628 {
629 process_sp->ReadMemory(process_address, bytes, size, error);
630 if (!error.Success())
631 return;
632 }
633 else
634 {
Sean Callanand2562502013-04-19 17:44:40 +0000635 if (!allocation.m_data.GetByteSize())
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000636 {
637 error.SetErrorToGenericError();
638 error.SetErrorString("Couldn't read: data buffer is empty");
639 return;
640 }
Sean Callanand2562502013-04-19 17:44:40 +0000641 ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000642 }
643 break;
644 case eAllocationPolicyProcessOnly:
645 process_sp = m_process_wp.lock();
646 if (process_sp)
647 {
648 process_sp->ReadMemory(process_address, bytes, size, error);
649 if (!error.Success())
650 return;
651 }
652 break;
653 }
654
655 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
656 {
Matt Kopecef143712013-06-03 18:00:07 +0000657 log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
Sean Callanan5a1af4e2013-04-05 02:22:57 +0000658 (uint64_t)process_address,
659 (uint64_t)bytes,
660 (uint64_t)size,
661 (uint64_t)allocation.m_process_start,
662 (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
663 }
664}
Sean Callanan35005f72013-04-12 18:10:34 +0000665
666void
667IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
Sean Callanan08052af2013-04-17 07:50:58 +0000668{
669 error.Clear();
670
Sean Callanan35005f72013-04-12 18:10:34 +0000671 if (size > 0)
672 {
673 DataBufferHeap buf(size, 0);
674 ReadMemory(buf.GetBytes(), process_address, size, error);
675
676 if (!error.Success())
677 return;
678
679 DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
680
681 lldb::offset_t offset = 0;
682
683 switch (size)
684 {
685 default:
686 error.SetErrorToGenericError();
Greg Claytone86cef62013-06-04 21:30:42 +0000687 error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
Sean Callanan35005f72013-04-12 18:10:34 +0000688 return;
689 case 1: scalar = extractor.GetU8(&offset); break;
690 case 2: scalar = extractor.GetU16(&offset); break;
691 case 4: scalar = extractor.GetU32(&offset); break;
692 case 8: scalar = extractor.GetU64(&offset); break;
693 }
694 }
695 else
696 {
697 error.SetErrorToGenericError();
Sean Callanan458ae1c2013-04-13 02:06:42 +0000698 error.SetErrorString ("Couldn't read scalar: its size was zero");
Sean Callanan35005f72013-04-12 18:10:34 +0000699 }
700 return;
701}
702
Sean Callanan458ae1c2013-04-13 02:06:42 +0000703void
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000704IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
705{
Sean Callanan08052af2013-04-17 07:50:58 +0000706 error.Clear();
707
Sean Callanan2d37e5a2013-04-15 22:48:23 +0000708 Scalar pointer_scalar;
709 ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
710
711 if (!error.Success())
712 return;
713
714 *address = pointer_scalar.ULongLong();
715
716 return;
717}
718
719void
Sean Callanan458ae1c2013-04-13 02:06:42 +0000720IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
721{
Sean Callanan08052af2013-04-17 07:50:58 +0000722 error.Clear();
723
Sean Callanan458ae1c2013-04-13 02:06:42 +0000724 if (size > 0)
725 {
726 AllocationMap::iterator iter = FindAllocation(process_address, size);
727
728 if (iter == m_allocations.end())
729 {
730 error.SetErrorToGenericError();
Matt Kopecef143712013-06-03 18:00:07 +0000731 error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size);
Sean Callanan458ae1c2013-04-13 02:06:42 +0000732 return;
733 }
734
735 Allocation &allocation = iter->second;
736
737 switch (allocation.m_policy)
738 {
739 default:
740 error.SetErrorToGenericError();
741 error.SetErrorString("Couldn't get memory data: invalid allocation policy");
742 return;
743 case eAllocationPolicyProcessOnly:
744 error.SetErrorToGenericError();
745 error.SetErrorString("Couldn't get memory data: memory is only in the target");
746 return;
Sean Callanan458ae1c2013-04-13 02:06:42 +0000747 case eAllocationPolicyMirror:
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000748 {
749 lldb::ProcessSP process_sp = m_process_wp.lock();
750
Sean Callanand2562502013-04-19 17:44:40 +0000751 if (!allocation.m_data.GetByteSize())
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000752 {
753 error.SetErrorToGenericError();
754 error.SetErrorString("Couldn't get memory data: data buffer is empty");
755 return;
756 }
757 if (process_sp)
758 {
Sean Callanand2562502013-04-19 17:44:40 +0000759 process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error);
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000760 if (!error.Success())
761 return;
762 uint64_t offset = process_address - allocation.m_process_start;
Sean Callanand2562502013-04-19 17:44:40 +0000763 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
Sean Callananc8c5b8d2013-04-15 21:35:52 +0000764 return;
765 }
766 }
767 case eAllocationPolicyHostOnly:
Sean Callanand2562502013-04-19 17:44:40 +0000768 if (!allocation.m_data.GetByteSize())
Sean Callanan458ae1c2013-04-13 02:06:42 +0000769 {
770 error.SetErrorToGenericError();
771 error.SetErrorString("Couldn't get memory data: data buffer is empty");
772 return;
773 }
774 uint64_t offset = process_address - allocation.m_process_start;
Sean Callanand2562502013-04-19 17:44:40 +0000775 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
Sean Callanan458ae1c2013-04-13 02:06:42 +0000776 return;
777 }
778 }
779 else
780 {
781 error.SetErrorToGenericError();
782 error.SetErrorString ("Couldn't get memory data: its size was zero");
783 return;
784 }
785}
786
787