1 //===-- 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
10 #include "lldb/Core/DataBufferHeap.h"
11 #include "lldb/Core/DataExtractor.h"
12 #include "lldb/Core/Error.h"
13 #include "lldb/Core/Log.h"
14 #include "lldb/Core/Scalar.h"
15 #include "lldb/Expression/IRMemoryMap.h"
16 #include "lldb/Target/Process.h"
17 #include "lldb/Target/Target.h"
18
19 using namespace lldb_private;
20
IRMemoryMap(lldb::TargetSP target_sp)21 IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) :
22 m_target_wp(target_sp)
23 {
24 if (target_sp)
25 m_process_wp = target_sp->GetProcessSP();
26 }
27
~IRMemoryMap()28 IRMemoryMap::~IRMemoryMap ()
29 {
30 lldb::ProcessSP process_sp = m_process_wp.lock();
31
32 if (process_sp)
33 {
34 AllocationMap::iterator iter;
35
36 Error err;
37
38 while ((iter = m_allocations.begin()) != m_allocations.end())
39 {
40 err.Clear();
41 if (iter->second.m_leak)
42 m_allocations.erase(iter);
43 else
44 Free(iter->first, err);
45 }
46 }
47 }
48
49 lldb::addr_t
FindSpace(size_t size)50 IRMemoryMap::FindSpace (size_t size)
51 {
52 lldb::TargetSP target_sp = m_target_wp.lock();
53 lldb::ProcessSP process_sp = m_process_wp.lock();
54
55 lldb::addr_t ret = LLDB_INVALID_ADDRESS;
56 if (size == 0)
57 return ret;
58
59 if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
60 {
61 Error alloc_error;
62
63 ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable | lldb::ePermissionsWritable, alloc_error);
64
65 if (!alloc_error.Success())
66 return LLDB_INVALID_ADDRESS;
67 else
68 return ret;
69 }
70
71 ret = 0;
72 if (!m_allocations.empty())
73 {
74 auto back = m_allocations.rbegin();
75 lldb::addr_t addr = back->first;
76 size_t alloc_size = back->second.m_size;
77 ret = llvm::RoundUpToAlignment(addr+alloc_size, 4096);
78 }
79
80 return ret;
81 }
82
83 IRMemoryMap::AllocationMap::iterator
FindAllocation(lldb::addr_t addr,size_t size)84 IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
85 {
86 if (addr == LLDB_INVALID_ADDRESS)
87 return m_allocations.end();
88
89 AllocationMap::iterator iter = m_allocations.lower_bound (addr);
90
91 if (iter == m_allocations.end() ||
92 iter->first > addr)
93 {
94 if (iter == m_allocations.begin())
95 return m_allocations.end();
96 iter--;
97 }
98
99 if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
100 return iter;
101
102 return m_allocations.end();
103 }
104
105 bool
IntersectsAllocation(lldb::addr_t addr,size_t size) const106 IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size) const
107 {
108 if (addr == LLDB_INVALID_ADDRESS)
109 return false;
110
111 AllocationMap::const_iterator iter = m_allocations.lower_bound (addr);
112
113 // Since we only know that the returned interval begins at a location greater than or
114 // equal to where the given interval begins, it's possible that the given interval
115 // intersects either the returned interval or the previous interval. Thus, we need to
116 // check both. Note that we only need to check these two intervals. Since all intervals
117 // are disjoint it is not possible that an adjacent interval does not intersect, but a
118 // non-adjacent interval does intersect.
119 if (iter != m_allocations.end()) {
120 if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
121 return true;
122 }
123
124 if (iter != m_allocations.begin()) {
125 --iter;
126 if (AllocationsIntersect(addr, size, iter->second.m_process_start, iter->second.m_size))
127 return true;
128 }
129
130 return false;
131 }
132
133 bool
AllocationsIntersect(lldb::addr_t addr1,size_t size1,lldb::addr_t addr2,size_t size2)134 IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1, lldb::addr_t addr2, size_t size2) {
135 // Given two half open intervals [A, B) and [X, Y), the only 6 permutations that satisfy
136 // A<B and X<Y are the following:
137 // A B X Y
138 // A X B Y (intersects)
139 // A X Y B (intersects)
140 // X A B Y (intersects)
141 // X A Y B (intersects)
142 // X Y A B
143 // The first is B <= X, and the last is Y <= A.
144 // So the condition is !(B <= X || Y <= A)), or (X < B && A < Y)
145 return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
146 }
147
148 lldb::ByteOrder
GetByteOrder()149 IRMemoryMap::GetByteOrder()
150 {
151 lldb::ProcessSP process_sp = m_process_wp.lock();
152
153 if (process_sp)
154 return process_sp->GetByteOrder();
155
156 lldb::TargetSP target_sp = m_target_wp.lock();
157
158 if (target_sp)
159 return target_sp->GetArchitecture().GetByteOrder();
160
161 return lldb::eByteOrderInvalid;
162 }
163
164 uint32_t
GetAddressByteSize()165 IRMemoryMap::GetAddressByteSize()
166 {
167 lldb::ProcessSP process_sp = m_process_wp.lock();
168
169 if (process_sp)
170 return process_sp->GetAddressByteSize();
171
172 lldb::TargetSP target_sp = m_target_wp.lock();
173
174 if (target_sp)
175 return target_sp->GetArchitecture().GetAddressByteSize();
176
177 return UINT32_MAX;
178 }
179
180 ExecutionContextScope *
GetBestExecutionContextScope() const181 IRMemoryMap::GetBestExecutionContextScope() const
182 {
183 lldb::ProcessSP process_sp = m_process_wp.lock();
184
185 if (process_sp)
186 return process_sp.get();
187
188 lldb::TargetSP target_sp = m_target_wp.lock();
189
190 if (target_sp)
191 return target_sp.get();
192
193 return NULL;
194 }
195
Allocation(lldb::addr_t process_alloc,lldb::addr_t process_start,size_t size,uint32_t permissions,uint8_t alignment,AllocationPolicy policy)196 IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
197 lldb::addr_t process_start,
198 size_t size,
199 uint32_t permissions,
200 uint8_t alignment,
201 AllocationPolicy policy) :
202 m_process_alloc (process_alloc),
203 m_process_start (process_start),
204 m_size (size),
205 m_permissions (permissions),
206 m_alignment (alignment),
207 m_policy (policy),
208 m_leak (false)
209 {
210 switch (policy)
211 {
212 default:
213 assert (0 && "We cannot reach this!");
214 case eAllocationPolicyHostOnly:
215 m_data.SetByteSize(size);
216 memset(m_data.GetBytes(), 0, size);
217 break;
218 case eAllocationPolicyProcessOnly:
219 break;
220 case eAllocationPolicyMirror:
221 m_data.SetByteSize(size);
222 memset(m_data.GetBytes(), 0, size);
223 break;
224 }
225 }
226
227 lldb::addr_t
Malloc(size_t size,uint8_t alignment,uint32_t permissions,AllocationPolicy policy,Error & error)228 IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
229 {
230 lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
231 error.Clear();
232
233 lldb::ProcessSP process_sp;
234 lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
235 lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
236
237 size_t alignment_mask = alignment - 1;
238 size_t allocation_size;
239
240 if (size == 0)
241 allocation_size = alignment;
242 else
243 allocation_size = (size & alignment_mask) ? ((size + alignment) & (~alignment_mask)) : size;
244
245 switch (policy)
246 {
247 default:
248 error.SetErrorToGenericError();
249 error.SetErrorString("Couldn't malloc: invalid allocation policy");
250 return LLDB_INVALID_ADDRESS;
251 case eAllocationPolicyHostOnly:
252 allocation_address = FindSpace(allocation_size);
253 if (allocation_address == LLDB_INVALID_ADDRESS)
254 {
255 error.SetErrorToGenericError();
256 error.SetErrorString("Couldn't malloc: address space is full");
257 return LLDB_INVALID_ADDRESS;
258 }
259 break;
260 case eAllocationPolicyMirror:
261 process_sp = m_process_wp.lock();
262 if (log)
263 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");
264 if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
265 {
266 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
267 if (!error.Success())
268 return LLDB_INVALID_ADDRESS;
269 }
270 else
271 {
272 if (log)
273 log->Printf ("IRMemoryMap::%s switching to eAllocationPolicyHostOnly due to failed condition (see previous expr log message)", __FUNCTION__);
274 policy = eAllocationPolicyHostOnly;
275 allocation_address = FindSpace(allocation_size);
276 if (allocation_address == LLDB_INVALID_ADDRESS)
277 {
278 error.SetErrorToGenericError();
279 error.SetErrorString("Couldn't malloc: address space is full");
280 return LLDB_INVALID_ADDRESS;
281 }
282 }
283 break;
284 case eAllocationPolicyProcessOnly:
285 process_sp = m_process_wp.lock();
286 if (process_sp)
287 {
288 if (process_sp->CanJIT() && process_sp->IsAlive())
289 {
290 allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
291 if (!error.Success())
292 return LLDB_INVALID_ADDRESS;
293 }
294 else
295 {
296 error.SetErrorToGenericError();
297 error.SetErrorString("Couldn't malloc: process doesn't support allocating memory");
298 return LLDB_INVALID_ADDRESS;
299 }
300 }
301 else
302 {
303 error.SetErrorToGenericError();
304 error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process");
305 return LLDB_INVALID_ADDRESS;
306 }
307 break;
308 }
309
310
311 lldb::addr_t mask = alignment - 1;
312 aligned_address = (allocation_address + mask) & (~mask);
313
314 m_allocations[aligned_address] = Allocation(allocation_address,
315 aligned_address,
316 allocation_size,
317 permissions,
318 alignment,
319 policy);
320
321 if (log)
322 {
323 const char * policy_string;
324
325 switch (policy)
326 {
327 default:
328 policy_string = "<invalid policy>";
329 break;
330 case eAllocationPolicyHostOnly:
331 policy_string = "eAllocationPolicyHostOnly";
332 break;
333 case eAllocationPolicyProcessOnly:
334 policy_string = "eAllocationPolicyProcessOnly";
335 break;
336 case eAllocationPolicyMirror:
337 policy_string = "eAllocationPolicyMirror";
338 break;
339 }
340
341 log->Printf("IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", %s) -> 0x%" PRIx64,
342 (uint64_t)allocation_size,
343 (uint64_t)alignment,
344 (uint64_t)permissions,
345 policy_string,
346 aligned_address);
347 }
348
349 return aligned_address;
350 }
351
352 void
Leak(lldb::addr_t process_address,Error & error)353 IRMemoryMap::Leak (lldb::addr_t process_address, Error &error)
354 {
355 error.Clear();
356
357 AllocationMap::iterator iter = m_allocations.find(process_address);
358
359 if (iter == m_allocations.end())
360 {
361 error.SetErrorToGenericError();
362 error.SetErrorString("Couldn't leak: allocation doesn't exist");
363 return;
364 }
365
366 Allocation &allocation = iter->second;
367
368 allocation.m_leak = true;
369 }
370
371 void
Free(lldb::addr_t process_address,Error & error)372 IRMemoryMap::Free (lldb::addr_t process_address, Error &error)
373 {
374 error.Clear();
375
376 AllocationMap::iterator iter = m_allocations.find(process_address);
377
378 if (iter == m_allocations.end())
379 {
380 error.SetErrorToGenericError();
381 error.SetErrorString("Couldn't free: allocation doesn't exist");
382 return;
383 }
384
385 Allocation &allocation = iter->second;
386
387 switch (allocation.m_policy)
388 {
389 default:
390 case eAllocationPolicyHostOnly:
391 {
392 lldb::ProcessSP process_sp = m_process_wp.lock();
393 if (process_sp)
394 {
395 if (process_sp->CanJIT() && process_sp->IsAlive())
396 process_sp->DeallocateMemory(allocation.m_process_alloc); // FindSpace allocated this for real
397 }
398
399 break;
400 }
401 case eAllocationPolicyMirror:
402 case eAllocationPolicyProcessOnly:
403 {
404 lldb::ProcessSP process_sp = m_process_wp.lock();
405 if (process_sp)
406 process_sp->DeallocateMemory(allocation.m_process_alloc);
407 }
408 }
409
410 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
411 {
412 log->Printf("IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64 "..0x%" PRIx64 ")",
413 (uint64_t)process_address,
414 iter->second.m_process_start,
415 iter->second.m_process_start + iter->second.m_size);
416 }
417
418 m_allocations.erase(iter);
419 }
420
421 bool
GetAllocSize(lldb::addr_t address,size_t & size)422 IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size)
423 {
424 AllocationMap::iterator iter = FindAllocation(address, size);
425 if (iter == m_allocations.end())
426 return false;
427
428 Allocation &al = iter->second;
429
430 if (address > (al.m_process_start + al.m_size))
431 {
432 size = 0;
433 return false;
434 }
435
436 if (address > al.m_process_start)
437 {
438 int dif = address - al.m_process_start;
439 size = al.m_size - dif;
440 return true;
441 }
442
443 size = al.m_size;
444 return true;
445 }
446
447 void
WriteMemory(lldb::addr_t process_address,const uint8_t * bytes,size_t size,Error & error)448 IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error)
449 {
450 error.Clear();
451
452 AllocationMap::iterator iter = FindAllocation(process_address, size);
453
454 if (iter == m_allocations.end())
455 {
456 lldb::ProcessSP process_sp = m_process_wp.lock();
457
458 if (process_sp)
459 {
460 process_sp->WriteMemory(process_address, bytes, size, error);
461 return;
462 }
463
464 error.SetErrorToGenericError();
465 error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist");
466 return;
467 }
468
469 Allocation &allocation = iter->second;
470
471 uint64_t offset = process_address - allocation.m_process_start;
472
473 lldb::ProcessSP process_sp;
474
475 switch (allocation.m_policy)
476 {
477 default:
478 error.SetErrorToGenericError();
479 error.SetErrorString("Couldn't write: invalid allocation policy");
480 return;
481 case eAllocationPolicyHostOnly:
482 if (!allocation.m_data.GetByteSize())
483 {
484 error.SetErrorToGenericError();
485 error.SetErrorString("Couldn't write: data buffer is empty");
486 return;
487 }
488 ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
489 break;
490 case eAllocationPolicyMirror:
491 if (!allocation.m_data.GetByteSize())
492 {
493 error.SetErrorToGenericError();
494 error.SetErrorString("Couldn't write: data buffer is empty");
495 return;
496 }
497 ::memcpy (allocation.m_data.GetBytes() + offset, bytes, size);
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 case eAllocationPolicyProcessOnly:
507 process_sp = m_process_wp.lock();
508 if (process_sp)
509 {
510 process_sp->WriteMemory(process_address, bytes, size, error);
511 if (!error.Success())
512 return;
513 }
514 break;
515 }
516
517 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
518 {
519 log->Printf("IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
520 (uint64_t)process_address,
521 (uint64_t)bytes,
522 (uint64_t)size,
523 (uint64_t)allocation.m_process_start,
524 (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
525 }
526 }
527
528 void
WriteScalarToMemory(lldb::addr_t process_address,Scalar & scalar,size_t size,Error & error)529 IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
530 {
531 error.Clear();
532
533 if (size == UINT32_MAX)
534 size = scalar.GetByteSize();
535
536 if (size > 0)
537 {
538 uint8_t buf[32];
539 const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
540 if (mem_size > 0)
541 {
542 return WriteMemory(process_address, buf, mem_size, error);
543 }
544 else
545 {
546 error.SetErrorToGenericError();
547 error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
548 }
549 }
550 else
551 {
552 error.SetErrorToGenericError();
553 error.SetErrorString ("Couldn't write scalar: its size was zero");
554 }
555 return;
556 }
557
558 void
WritePointerToMemory(lldb::addr_t process_address,lldb::addr_t address,Error & error)559 IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error)
560 {
561 error.Clear();
562
563 Scalar scalar(address);
564
565 WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
566 }
567
568 void
ReadMemory(uint8_t * bytes,lldb::addr_t process_address,size_t size,Error & error)569 IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
570 {
571 error.Clear();
572
573 AllocationMap::iterator iter = FindAllocation(process_address, size);
574
575 if (iter == m_allocations.end())
576 {
577 lldb::ProcessSP process_sp = m_process_wp.lock();
578
579 if (process_sp)
580 {
581 process_sp->ReadMemory(process_address, bytes, size, error);
582 return;
583 }
584
585 lldb::TargetSP target_sp = m_target_wp.lock();
586
587 if (target_sp)
588 {
589 Address absolute_address(process_address);
590 target_sp->ReadMemory(absolute_address, false, bytes, size, error);
591 return;
592 }
593
594 error.SetErrorToGenericError();
595 error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist");
596 return;
597 }
598
599 Allocation &allocation = iter->second;
600
601 uint64_t offset = process_address - allocation.m_process_start;
602
603 if (offset > allocation.m_size)
604 {
605 error.SetErrorToGenericError();
606 error.SetErrorString("Couldn't read: data is not in the allocation");
607 return;
608 }
609
610 lldb::ProcessSP process_sp;
611
612 switch (allocation.m_policy)
613 {
614 default:
615 error.SetErrorToGenericError();
616 error.SetErrorString("Couldn't read: invalid allocation policy");
617 return;
618 case eAllocationPolicyHostOnly:
619 if (!allocation.m_data.GetByteSize())
620 {
621 error.SetErrorToGenericError();
622 error.SetErrorString("Couldn't read: data buffer is empty");
623 return;
624 }
625 if (allocation.m_data.GetByteSize() < offset + size)
626 {
627 error.SetErrorToGenericError();
628 error.SetErrorString("Couldn't read: not enough underlying data");
629 return;
630 }
631
632 ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
633 break;
634 case eAllocationPolicyMirror:
635 process_sp = m_process_wp.lock();
636 if (process_sp)
637 {
638 process_sp->ReadMemory(process_address, bytes, size, error);
639 if (!error.Success())
640 return;
641 }
642 else
643 {
644 if (!allocation.m_data.GetByteSize())
645 {
646 error.SetErrorToGenericError();
647 error.SetErrorString("Couldn't read: data buffer is empty");
648 return;
649 }
650 ::memcpy (bytes, allocation.m_data.GetBytes() + offset, size);
651 }
652 break;
653 case eAllocationPolicyProcessOnly:
654 process_sp = m_process_wp.lock();
655 if (process_sp)
656 {
657 process_sp->ReadMemory(process_address, bytes, size, error);
658 if (!error.Success())
659 return;
660 }
661 break;
662 }
663
664 if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
665 {
666 log->Printf("IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
667 (uint64_t)process_address,
668 (uint64_t)bytes,
669 (uint64_t)size,
670 (uint64_t)allocation.m_process_start,
671 (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
672 }
673 }
674
675 void
ReadScalarFromMemory(Scalar & scalar,lldb::addr_t process_address,size_t size,Error & error)676 IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
677 {
678 error.Clear();
679
680 if (size > 0)
681 {
682 DataBufferHeap buf(size, 0);
683 ReadMemory(buf.GetBytes(), process_address, size, error);
684
685 if (!error.Success())
686 return;
687
688 DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
689
690 lldb::offset_t offset = 0;
691
692 switch (size)
693 {
694 default:
695 error.SetErrorToGenericError();
696 error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
697 return;
698 case 1: scalar = extractor.GetU8(&offset); break;
699 case 2: scalar = extractor.GetU16(&offset); break;
700 case 4: scalar = extractor.GetU32(&offset); break;
701 case 8: scalar = extractor.GetU64(&offset); break;
702 }
703 }
704 else
705 {
706 error.SetErrorToGenericError();
707 error.SetErrorString ("Couldn't read scalar: its size was zero");
708 }
709 return;
710 }
711
712 void
ReadPointerFromMemory(lldb::addr_t * address,lldb::addr_t process_address,Error & error)713 IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error)
714 {
715 error.Clear();
716
717 Scalar pointer_scalar;
718 ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error);
719
720 if (!error.Success())
721 return;
722
723 *address = pointer_scalar.ULongLong();
724
725 return;
726 }
727
728 void
GetMemoryData(DataExtractor & extractor,lldb::addr_t process_address,size_t size,Error & error)729 IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error)
730 {
731 error.Clear();
732
733 if (size > 0)
734 {
735 AllocationMap::iterator iter = FindAllocation(process_address, size);
736
737 if (iter == m_allocations.end())
738 {
739 error.SetErrorToGenericError();
740 error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64 ")", process_address, process_address + size);
741 return;
742 }
743
744 Allocation &allocation = iter->second;
745
746 switch (allocation.m_policy)
747 {
748 default:
749 error.SetErrorToGenericError();
750 error.SetErrorString("Couldn't get memory data: invalid allocation policy");
751 return;
752 case eAllocationPolicyProcessOnly:
753 error.SetErrorToGenericError();
754 error.SetErrorString("Couldn't get memory data: memory is only in the target");
755 return;
756 case eAllocationPolicyMirror:
757 {
758 lldb::ProcessSP process_sp = m_process_wp.lock();
759
760 if (!allocation.m_data.GetByteSize())
761 {
762 error.SetErrorToGenericError();
763 error.SetErrorString("Couldn't get memory data: data buffer is empty");
764 return;
765 }
766 if (process_sp)
767 {
768 process_sp->ReadMemory(allocation.m_process_start, allocation.m_data.GetBytes(), allocation.m_data.GetByteSize(), error);
769 if (!error.Success())
770 return;
771 uint64_t offset = process_address - allocation.m_process_start;
772 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
773 return;
774 }
775 }
776 case eAllocationPolicyHostOnly:
777 if (!allocation.m_data.GetByteSize())
778 {
779 error.SetErrorToGenericError();
780 error.SetErrorString("Couldn't get memory data: data buffer is empty");
781 return;
782 }
783 uint64_t offset = process_address - allocation.m_process_start;
784 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize());
785 return;
786 }
787 }
788 else
789 {
790 error.SetErrorToGenericError();
791 error.SetErrorString ("Couldn't get memory data: its size was zero");
792 return;
793 }
794 }
795