LLDB mainline
IRMemoryMap.cpp
Go to the documentation of this file.
1//===-- IRMemoryMap.cpp ---------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
11#include "lldb/Target/Process.h"
12#include "lldb/Target/Target.h"
17#include "lldb/Utility/Log.h"
18#include "lldb/Utility/Scalar.h"
19#include "lldb/Utility/Status.h"
20
21using namespace lldb_private;
22
24 if (target_sp)
25 m_process_wp = target_sp->GetProcessSP();
26}
27
29 lldb::ProcessSP process_sp = m_process_wp.lock();
30
31 if (process_sp) {
32 AllocationMap::iterator iter;
33
34 Status err;
35
36 while ((iter = m_allocations.begin()) != m_allocations.end()) {
37 err.Clear();
38 if (iter->second.m_leak)
39 m_allocations.erase(iter);
40 else
41 Free(iter->first, err);
42 }
43 }
44}
45
47 // The FindSpace algorithm's job is to find a region of memory that the
48 // underlying process is unlikely to be using.
49 //
50 // The memory returned by this function will never be written to. The only
51 // point is that it should not shadow process memory if possible, so that
52 // expressions processing real values from the process do not use the wrong
53 // data.
54 //
55 // If the process can in fact allocate memory (CanJIT() lets us know this)
56 // then this can be accomplished just be allocating memory in the inferior.
57 // Then no guessing is required.
58
59 lldb::TargetSP target_sp = m_target_wp.lock();
60 lldb::ProcessSP process_sp = m_process_wp.lock();
61
62 const bool process_is_alive = process_sp && process_sp->IsAlive();
63
65 if (size == 0)
66 return ret;
67
68 if (process_is_alive && process_sp->CanJIT()) {
69 Status alloc_error;
70
71 ret = process_sp->AllocateMemory(size, lldb::ePermissionsReadable |
72 lldb::ePermissionsWritable,
73 alloc_error);
74
75 if (!alloc_error.Success())
77 else
78 return ret;
79 }
80
81 // At this point we know that we need to hunt.
82 //
83 // First, go to the end of the existing allocations we've made if there are
84 // any allocations. Otherwise start at the beginning of memory.
85
86 if (m_allocations.empty()) {
87 ret = 0;
88 } else {
89 auto back = m_allocations.rbegin();
90 lldb::addr_t addr = back->first;
91 size_t alloc_size = back->second.m_size;
92 ret = llvm::alignTo(addr + alloc_size, 4096);
93 }
94
95 uint64_t end_of_memory;
96 switch (GetAddressByteSize()) {
97 case 2:
98 end_of_memory = 0xffffull;
99 break;
100 case 4:
101 end_of_memory = 0xffffffffull;
102 break;
103 case 8:
104 end_of_memory = 0xffffffffffffffffull;
105 break;
106 default:
107 lldbassert(false && "Invalid address size.");
109 }
110
111 // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped
112 // regions, walk forward through memory until a region is found that has
113 // adequate space for our allocation.
114 if (process_is_alive) {
115 MemoryRegionInfo region_info;
116 Status err = process_sp->GetMemoryRegionInfo(ret, region_info);
117 if (err.Success()) {
118 while (true) {
119 if (region_info.GetRange().GetRangeBase() == 0 &&
120 region_info.GetRange().GetRangeEnd() < end_of_memory) {
121 // Don't use a region that starts at address 0,
122 // it can make it harder to debug null dereference crashes
123 // in the inferior.
124 ret = region_info.GetRange().GetRangeEnd();
125 } else if (region_info.GetReadable() != eLazyBoolNo ||
126 region_info.GetWritable() != eLazyBoolNo ||
127 region_info.GetExecutable() != eLazyBoolNo) {
128 if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory) {
130 break;
131 } else {
132 ret = region_info.GetRange().GetRangeEnd();
133 }
134 } else if (ret + size < region_info.GetRange().GetRangeEnd()) {
135 return ret;
136 } else {
137 // ret stays the same. We just need to walk a bit further.
138 }
139
140 err = process_sp->GetMemoryRegionInfo(
141 region_info.GetRange().GetRangeEnd(), region_info);
142 if (err.Fail()) {
143 // The target can't describe memory beyond this point (e.g.
144 // WebAssembly linear memory). Treat the remaining address space
145 // as unmapped.
146 if (ret + size < end_of_memory)
147 return ret;
149 break;
150 }
151 }
152 }
153 }
154
155 // We've tried our algorithm, and it didn't work. Now we have to reset back
156 // to the end of the allocations we've already reported, or use a 'sensible'
157 // default if this is our first allocation.
158 if (m_allocations.empty()) {
159 uint64_t alloc_address = target_sp->GetExprAllocAddress();
160 if (alloc_address > 0) {
161 if (alloc_address >= end_of_memory) {
162 lldbassert(0 && "The allocation address for expression evaluation must "
163 "be within process address space");
165 }
166 ret = alloc_address;
167 } else {
168 uint32_t address_byte_size = GetAddressByteSize();
169 if (address_byte_size != UINT32_MAX) {
170 switch (address_byte_size) {
171 case 2:
172 ret = 0x8000ull;
173 break;
174 case 4:
175 ret = 0xee000000ull;
176 break;
177 case 8:
178 ret = 0xdead0fff00000000ull;
179 break;
180 default:
181 lldbassert(false && "Invalid address size.");
183 }
184 }
185 }
186 } else {
187 auto back = m_allocations.rbegin();
188 lldb::addr_t addr = back->first;
189 size_t alloc_size = back->second.m_size;
190 uint64_t align = target_sp->GetExprAllocAlign();
191 if (align == 0)
192 align = 4096;
193 ret = llvm::alignTo(addr + alloc_size, align);
194 }
195
196 return ret;
197}
198
199IRMemoryMap::AllocationMap::iterator
201 if (addr == LLDB_INVALID_ADDRESS)
202 return m_allocations.end();
203
204 AllocationMap::iterator iter = m_allocations.lower_bound(addr);
205
206 if (iter == m_allocations.end() || iter->first > addr) {
207 if (iter == m_allocations.begin())
208 return m_allocations.end();
209 iter--;
210 }
211
212 if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)
213 return iter;
214
215 return m_allocations.end();
216}
217
218bool IRMemoryMap::IntersectsAllocation(lldb::addr_t addr, size_t size) const {
219 if (addr == LLDB_INVALID_ADDRESS)
220 return false;
221
222 AllocationMap::const_iterator iter = m_allocations.lower_bound(addr);
223
224 // Since we only know that the returned interval begins at a location greater
225 // than or equal to where the given interval begins, it's possible that the
226 // given interval intersects either the returned interval or the previous
227 // interval. Thus, we need to check both. Note that we only need to check
228 // these two intervals. Since all intervals are disjoint it is not possible
229 // that an adjacent interval does not intersect, but a non-adjacent interval
230 // does intersect.
231 if (iter != m_allocations.end()) {
232 if (AllocationsIntersect(addr, size, iter->second.m_process_start,
233 iter->second.m_size))
234 return true;
235 }
236
237 if (iter != m_allocations.begin()) {
238 --iter;
239 if (AllocationsIntersect(addr, size, iter->second.m_process_start,
240 iter->second.m_size))
241 return true;
242 }
243
244 return false;
245}
246
248 lldb::addr_t addr2, size_t size2) {
249 // Given two half open intervals [A, B) and [X, Y), the only 6 permutations
250 // that satisfy A<B and X<Y are the following:
251 // A B X Y
252 // A X B Y (intersects)
253 // A X Y B (intersects)
254 // X A B Y (intersects)
255 // X A Y B (intersects)
256 // X Y A B
257 // The first is B <= X, and the last is Y <= A. So the condition is !(B <= X
258 // || Y <= A)), or (X < B && A < Y)
259 return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));
260}
261
263 lldb::ProcessSP process_sp = m_process_wp.lock();
264
265 if (process_sp)
266 return process_sp->GetByteOrder();
267
268 lldb::TargetSP target_sp = m_target_wp.lock();
269
270 if (target_sp)
271 return target_sp->GetArchitecture().GetByteOrder();
272
274}
275
277 lldb::ProcessSP process_sp = m_process_wp.lock();
278
279 if (process_sp)
280 return process_sp->GetAddressByteSize();
281
282 lldb::TargetSP target_sp = m_target_wp.lock();
283
284 if (target_sp)
285 return target_sp->GetArchitecture().GetAddressByteSize();
286
287 return UINT32_MAX;
288}
289
291 lldb::ProcessSP process_sp = m_process_wp.lock();
292
293 if (process_sp)
294 return process_sp.get();
295
296 lldb::TargetSP target_sp = m_target_wp.lock();
297
298 if (target_sp)
299 return target_sp.get();
300
301 return nullptr;
302}
303
305 lldb::addr_t process_start, size_t size,
306 uint32_t permissions, uint8_t alignment,
307 AllocationPolicy policy)
308 : m_process_alloc(process_alloc), m_process_start(process_start),
309 m_size(size), m_policy(policy), m_leak(false), m_permissions(permissions),
310 m_alignment(alignment) {
311 switch (policy) {
312 default:
313 llvm_unreachable("Invalid AllocationPolicy");
316 m_data.SetByteSize(size);
317 break;
319 break;
320 }
321}
322
323llvm::Expected<lldb::addr_t>
324IRMemoryMap::Malloc(size_t size, uint8_t alignment, uint32_t permissions,
325 AllocationPolicy policy, bool zero_memory,
326 AllocationPolicy *used_policy) {
328
329 lldb::ProcessSP process_sp;
330 lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;
331 lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;
332
333 size_t allocation_size;
334
335 if (size == 0) {
336 // FIXME: Malloc(0) should either return an invalid address or assert, in
337 // order to cut down on unnecessary allocations.
338 allocation_size = alignment;
339 } else {
340 // Round up the requested size to an aligned value.
341 allocation_size = llvm::alignTo(size, alignment);
342
343 // The process page cache does not see the requested alignment. We can't
344 // assume its result will be any more than 1-byte aligned. To work around
345 // this, request `alignment - 1` additional bytes.
346 allocation_size += alignment - 1;
347 }
348
349 switch (policy) {
350 default:
351 return llvm::createStringError(
352 llvm::inconvertibleErrorCode(),
353 "Couldn't malloc: invalid allocation policy");
355 allocation_address = FindSpace(allocation_size);
356 if (allocation_address == LLDB_INVALID_ADDRESS)
357 return llvm::createStringError(llvm::inconvertibleErrorCode(),
358 "Couldn't malloc: address space is full");
359 break;
361 process_sp = m_process_wp.lock();
362 LLDB_LOGF(log,
363 "IRMemoryMap::%s process_sp=0x%" PRIxPTR
364 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s",
365 __FUNCTION__, reinterpret_cast<uintptr_t>(process_sp.get()),
366 process_sp && process_sp->CanJIT() ? "true" : "false",
367 process_sp && process_sp->IsAlive() ? "true" : "false");
368 if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) {
370 if (!zero_memory)
371 allocation_address =
372 process_sp->AllocateMemory(allocation_size, permissions, error);
373 else
374 allocation_address =
375 process_sp->CallocateMemory(allocation_size, permissions, error);
376
377 if (!error.Success())
378 return error.takeError();
379 } else {
380 LLDB_LOGF(log,
381 "IRMemoryMap::%s switching to eAllocationPolicyHostOnly "
382 "due to failed condition (see previous expr log message)",
383 __FUNCTION__);
385 allocation_address = FindSpace(allocation_size);
386 if (allocation_address == LLDB_INVALID_ADDRESS)
387 return llvm::createStringError(
388 llvm::inconvertibleErrorCode(),
389 "Couldn't malloc: address space is full");
390 }
391 break;
393 process_sp = m_process_wp.lock();
394 if (process_sp) {
395 if (process_sp->CanJIT() && process_sp->IsAlive()) {
397 if (!zero_memory)
398 allocation_address =
399 process_sp->AllocateMemory(allocation_size, permissions, error);
400 else
401 allocation_address =
402 process_sp->CallocateMemory(allocation_size, permissions, error);
403
404 if (!error.Success())
405 return error.takeError();
406 } else {
407 return llvm::createStringError(
408 llvm::inconvertibleErrorCode(),
409 "Couldn't malloc: process doesn't support allocating memory");
410 }
411 } else {
412 return llvm::createStringError(llvm::inconvertibleErrorCode(),
413 "Couldn't malloc: process doesn't exist, "
414 "and this memory must be in the process");
415 }
416 break;
417 }
418
419 lldb::addr_t mask = alignment - 1;
420 aligned_address = (allocation_address + mask) & (~mask);
421
422 m_allocations.emplace(
423 std::piecewise_construct, std::forward_as_tuple(aligned_address),
424 std::forward_as_tuple(allocation_address, aligned_address,
425 allocation_size, permissions, alignment, policy));
426
427 if (zero_memory) {
428 Status write_error;
429 std::vector<uint8_t> zero_buf(size, 0);
430 WriteMemory(aligned_address, zero_buf.data(), size, write_error);
431 }
432
433 if (log) {
434 const char *policy_string;
435
436 switch (policy) {
437 default:
438 policy_string = "<invalid policy>";
439 break;
441 policy_string = "eAllocationPolicyHostOnly";
442 break;
444 policy_string = "eAllocationPolicyProcessOnly";
445 break;
447 policy_string = "eAllocationPolicyMirror";
448 break;
449 }
450
451 LLDB_LOGF(log,
452 "IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64
453 ", %s) -> 0x%" PRIx64,
454 (uint64_t)allocation_size, (uint64_t)alignment,
455 (uint64_t)permissions, policy_string, aligned_address);
456 }
457
458 if (used_policy)
459 *used_policy = policy;
460
461 return aligned_address;
462}
463
465 error.Clear();
466
467 AllocationMap::iterator iter = m_allocations.find(process_address);
468
469 if (iter == m_allocations.end()) {
470 error = Status::FromErrorString("Couldn't leak: allocation doesn't exist");
471 return;
472 }
473
474 Allocation &allocation = iter->second;
475
476 allocation.m_leak = true;
477}
478
480 error.Clear();
481
482 AllocationMap::iterator iter = m_allocations.find(process_address);
483
484 if (iter == m_allocations.end()) {
485 error = Status::FromErrorString("Couldn't free: allocation doesn't exist");
486 return;
487 }
488
489 Allocation &allocation = iter->second;
490
491 switch (allocation.m_policy) {
492 default:
494 lldb::ProcessSP process_sp = m_process_wp.lock();
495 if (process_sp) {
496 if (process_sp->CanJIT() && process_sp->IsAlive())
497 process_sp->DeallocateMemory(
498 allocation.m_process_alloc); // FindSpace allocated this for real
499 }
500
501 break;
502 }
505 lldb::ProcessSP process_sp = m_process_wp.lock();
506 if (process_sp)
507 process_sp->DeallocateMemory(allocation.m_process_alloc);
508 }
509 }
510
512 LLDB_LOGF(log,
513 "IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64
514 "..0x%" PRIx64 ")",
515 (uint64_t)process_address, iter->second.m_process_start,
516 iter->second.m_process_start + iter->second.m_size);
517 }
518
519 m_allocations.erase(iter);
520}
521
522bool IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size) {
523 AllocationMap::iterator iter = FindAllocation(address, size);
524 if (iter == m_allocations.end())
525 return false;
526
527 Allocation &al = iter->second;
528
529 if (address > (al.m_process_start + al.m_size)) {
530 size = 0;
531 return false;
532 }
533
534 if (address > al.m_process_start) {
535 int dif = address - al.m_process_start;
536 size = al.m_size - dif;
537 return true;
538 }
539
540 size = al.m_size;
541 return true;
542}
543
545 const uint8_t *bytes, size_t size,
546 Status &error) {
547 error.Clear();
548
549 AllocationMap::iterator iter = FindAllocation(process_address, size);
550
551 if (iter == m_allocations.end()) {
552 lldb::ProcessSP process_sp = m_process_wp.lock();
553
554 if (process_sp) {
555 process_sp->WriteMemory(process_address, bytes, size, error);
556 return;
557 }
558
560 "Couldn't write: no allocation contains the target "
561 "range and the process doesn't exist");
562 return;
563 }
564
565 Allocation &allocation = iter->second;
566
567 uint64_t offset = process_address - allocation.m_process_start;
568
569 lldb::ProcessSP process_sp;
570
571 switch (allocation.m_policy) {
572 default:
573 error =
574 Status::FromErrorString("Couldn't write: invalid allocation policy");
575 return;
577 if (!allocation.m_data.GetByteSize()) {
578 error = Status::FromErrorString("Couldn't write: data buffer is empty");
579 return;
580 }
581 ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
582 break;
584 if (!allocation.m_data.GetByteSize()) {
585 error = Status::FromErrorString("Couldn't write: data buffer is empty");
586 return;
587 }
588 ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);
589 process_sp = m_process_wp.lock();
590 if (process_sp) {
591 process_sp->WriteMemory(process_address, bytes, size, error);
592 if (!error.Success())
593 return;
594 }
595 break;
597 process_sp = m_process_wp.lock();
598 if (process_sp) {
599 process_sp->WriteMemory(process_address, bytes, size, error);
600 if (!error.Success())
601 return;
602 }
603 break;
604 }
605
607 LLDB_LOGF(log,
608 "IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIxPTR
609 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",
610 (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,
611 (uint64_t)allocation.m_process_start,
612 (uint64_t)allocation.m_process_start +
613 (uint64_t)allocation.m_size);
614 }
615}
616
618 Scalar &scalar, size_t size,
619 Status &error) {
620 error.Clear();
621
622 if (size == UINT32_MAX)
623 size = scalar.GetByteSize();
624
625 if (size > 0) {
626 uint8_t buf[32];
627 const size_t mem_size =
628 scalar.GetAsMemoryData(buf, size, GetByteOrder(), error);
629 if (mem_size > 0) {
630 return WriteMemory(process_address, buf, mem_size, error);
631 } else {
633 "Couldn't write scalar: failed to get scalar as memory data");
634 }
635 } else {
636 error = Status::FromErrorString("Couldn't write scalar: its size was zero");
637 }
638}
639
641 lldb::addr_t pointer, Status &error) {
642 error.Clear();
643
644 /// Only ask the Process to fix `pointer` if the address belongs to the
645 /// process. An address belongs to the process if the Allocation policy is not
646 /// eAllocationPolicyHostOnly.
647 auto it = FindAllocation(pointer, 1);
648 if (it == m_allocations.end() ||
649 it->second.m_policy != AllocationPolicy::eAllocationPolicyHostOnly)
650 if (auto process_sp = GetProcessWP().lock())
651 pointer = process_sp->FixAnyAddress(pointer);
652
653 Scalar scalar(pointer);
654
655 WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);
656}
657
658void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address,
659 size_t size, Status &error) {
660 error.Clear();
661
662 AllocationMap::iterator iter = FindAllocation(process_address, size);
663
664 if (iter == m_allocations.end()) {
665 lldb::ProcessSP process_sp = m_process_wp.lock();
666
667 if (process_sp) {
668 process_sp->ReadMemory(process_address, bytes, size, error);
669 return;
670 }
671
672 lldb::TargetSP target_sp = m_target_wp.lock();
673
674 if (target_sp) {
675 Address absolute_address(process_address);
676 target_sp->ReadMemory(absolute_address, bytes, size, error, true);
677 return;
678 }
679
681 "Couldn't read: no allocation contains the target "
682 "range, and neither the process nor the target exist");
683 return;
684 }
685
686 Allocation &allocation = iter->second;
687
688 uint64_t offset = process_address - allocation.m_process_start;
689
690 if (offset > allocation.m_size) {
691 error =
692 Status::FromErrorString("Couldn't read: data is not in the allocation");
693 return;
694 }
695
696 lldb::ProcessSP process_sp;
697
698 switch (allocation.m_policy) {
699 default:
700 error = Status::FromErrorString("Couldn't read: invalid allocation policy");
701 return;
703 if (!allocation.m_data.GetByteSize()) {
704 error = Status::FromErrorString("Couldn't read: data buffer is empty");
705 return;
706 }
707 if (allocation.m_data.GetByteSize() < offset + size) {
708 error =
709 Status::FromErrorString("Couldn't read: not enough underlying data");
710 return;
711 }
712
713 ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
714 break;
716 process_sp = m_process_wp.lock();
717 if (process_sp) {
718 process_sp->ReadMemory(process_address, bytes, size, error);
719 if (!error.Success())
720 return;
721 } else {
722 if (!allocation.m_data.GetByteSize()) {
723 error = Status::FromErrorString("Couldn't read: data buffer is empty");
724 return;
725 }
726 ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);
727 }
728 break;
730 process_sp = m_process_wp.lock();
731 if (process_sp) {
732 process_sp->ReadMemory(process_address, bytes, size, error);
733 if (!error.Success())
734 return;
735 }
736 break;
737 }
738
740 LLDB_LOGF(log,
741 "IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIxPTR
742 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",
743 (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,
744 (uint64_t)allocation.m_process_start,
745 (uint64_t)allocation.m_process_start +
746 (uint64_t)allocation.m_size);
747 }
748}
749
751 lldb::addr_t process_address,
752 size_t size, Status &error) {
753 error.Clear();
754
755 if (size > 0) {
756 DataBufferHeap buf(size, 0);
757 ReadMemory(buf.GetBytes(), process_address, size, error);
758
759 if (!error.Success())
760 return;
761
762 DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(),
764
765 lldb::offset_t offset = 0;
766
767 switch (size) {
768 default:
770 "Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);
771 return;
772 case 1:
773 scalar = extractor.GetU8(&offset);
774 break;
775 case 2:
776 scalar = extractor.GetU16(&offset);
777 break;
778 case 4:
779 scalar = extractor.GetU32(&offset);
780 break;
781 case 8:
782 scalar = extractor.GetU64(&offset);
783 break;
784 }
785 } else {
786 error = Status::FromErrorString("Couldn't read scalar: its size was zero");
787 }
788}
789
791 lldb::addr_t process_address,
792 Status &error) {
793 error.Clear();
794
795 Scalar pointer_scalar;
796 ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(),
797 error);
798
799 if (!error.Success())
800 return;
801
802 *address = pointer_scalar.ULongLong();
803}
804
806 lldb::addr_t process_address, size_t size,
807 Status &error) {
808 error.Clear();
809
810 if (size > 0) {
811 AllocationMap::iterator iter = FindAllocation(process_address, size);
812
813 if (iter == m_allocations.end()) {
815 "Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64
816 ")",
817 process_address, process_address + size);
818 return;
819 }
820
821 Allocation &allocation = iter->second;
822
823 switch (allocation.m_policy) {
824 default:
826 "Couldn't get memory data: invalid allocation policy");
827 return;
830 "Couldn't get memory data: memory is only in the target");
831 return;
833 lldb::ProcessSP process_sp = m_process_wp.lock();
834
835 if (!allocation.m_data.GetByteSize()) {
837 "Couldn't get memory data: data buffer is empty");
838 return;
839 }
840 if (process_sp) {
841 process_sp->ReadMemory(allocation.m_process_start,
842 allocation.m_data.GetBytes(),
843 allocation.m_data.GetByteSize(), error);
844 if (!error.Success())
845 return;
846 uint64_t offset = process_address - allocation.m_process_start;
847 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
849 return;
850 }
851 } break;
853 if (!allocation.m_data.GetByteSize()) {
855 "Couldn't get memory data: data buffer is empty");
856 return;
857 }
858 uint64_t offset = process_address - allocation.m_process_start;
859 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,
861 return;
862 }
863 } else {
864 error =
865 Status::FromErrorString("Couldn't get memory data: its size was zero");
866 return;
867 }
868}
static llvm::raw_ostream & error(Stream &strm)
#define lldbassert(x)
Definition LLDBAssert.h:16
#define LLDB_LOGF(log,...)
Definition Log.h:378
A section + offset based address class.
Definition Address.h:62
A subclass of DataBuffer that stores a data buffer on the heap.
lldb::offset_t GetByteSize() const override
Get the number of bytes in the data buffer.
An data extractor class.
uint64_t GetU64(lldb::offset_t *offset_ptr) const
Extract a uint64_t value from *offset_ptr.
uint32_t GetU32(lldb::offset_t *offset_ptr) const
Extract a uint32_t value from *offset_ptr.
uint16_t GetU16(lldb::offset_t *offset_ptr) const
Extract a uint16_t value from *offset_ptr.
uint8_t GetU8(lldb::offset_t *offset_ptr) const
Extract a uint8_t value from *offset_ptr.
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
lldb::TargetWP m_target_wp
void Free(lldb::addr_t process_address, Status &error)
lldb::ByteOrder GetByteOrder()
llvm::Expected< lldb::addr_t > Malloc(size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, bool zero_memory, AllocationPolicy *used_policy=nullptr)
void ReadPointerFromMemory(lldb::addr_t *address, lldb::addr_t process_address, Status &error)
lldb::ProcessWP m_process_wp
AllocationMap m_allocations
bool IntersectsAllocation(lldb::addr_t addr, size_t size) const
ExecutionContextScope * GetBestExecutionContextScope() const
static bool AllocationsIntersect(lldb::addr_t addr1, size_t size1, lldb::addr_t addr2, size_t size2)
void GetMemoryData(DataExtractor &extractor, lldb::addr_t process_address, size_t size, Status &error)
lldb::ProcessWP & GetProcessWP()
Definition IRMemoryMap.h:92
AllocationMap::iterator FindAllocation(lldb::addr_t addr, size_t size)
void WritePointerToMemory(lldb::addr_t process_address, lldb::addr_t pointer, Status &error)
IRMemoryMap(lldb::TargetSP target_sp)
void ReadScalarFromMemory(Scalar &scalar, lldb::addr_t process_address, size_t size, Status &error)
lldb::addr_t FindSpace(size_t size)
void WriteScalarToMemory(lldb::addr_t process_address, Scalar &scalar, size_t size, Status &error)
bool GetAllocSize(lldb::addr_t address, size_t &size)
void Leak(lldb::addr_t process_address, Status &error)
void WriteMemory(lldb::addr_t process_address, const uint8_t *bytes, size_t size, Status &error)
void ReadMemory(uint8_t *bytes, lldb::addr_t process_address, size_t size, Status &error)
@ eAllocationPolicyProcessOnly
The intent is that this allocation exist only in the process.
Definition IRMemoryMap.h:50
@ eAllocationPolicyHostOnly
This allocation was created in the host and will never make it into the process.
Definition IRMemoryMap.h:43
@ eAllocationPolicyMirror
The intent is that this allocation exist both in the host and the process and have the same content i...
Definition IRMemoryMap.h:47
size_t GetByteSize() const
Definition Scalar.cpp:162
unsigned long long ULongLong(unsigned long long fail_value=0) const
Definition Scalar.cpp:365
size_t GetAsMemoryData(void *dst, size_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const
Definition Scalar.cpp:788
An error handling class.
Definition Status.h:118
void Clear()
Clear the object state.
Definition Status.cpp:214
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
Definition Status.cpp:106
static Status FromErrorString(const char *str)
Definition Status.h:141
bool Fail() const
Test for error condition.
Definition Status.cpp:293
bool Success() const
Test for success condition.
Definition Status.cpp:303
uint8_t * GetBytes()
Get a pointer to the data.
Definition DataBuffer.h:108
#define LLDB_INVALID_ADDRESS
#define UINT32_MAX
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:327
uint64_t offset_t
Definition lldb-types.h:85
std::shared_ptr< lldb_private::Process > ProcessSP
ByteOrder
Byte ordering definitions.
uint64_t addr_t
Definition lldb-types.h:80
std::shared_ptr< lldb_private::Target > TargetSP
size_t m_size
The size of the requested allocation.
lldb::addr_t m_process_alloc
The (unaligned) base for the remote allocation.
Definition IRMemoryMap.h:97
AllocationPolicy m_policy
Flags. Keep these grouped together to avoid structure padding.
uint8_t m_permissions
The access permissions on the memory in the process.
Allocation(lldb::addr_t process_alloc, lldb::addr_t process_start, size_t size, uint32_t permissions, uint8_t alignment, AllocationPolicy m_policy)
lldb::addr_t m_process_start
The base address of the allocation in the process.
Definition IRMemoryMap.h:99
uint8_t m_alignment
The alignment of the requested allocation.
BaseType GetRangeBase() const
Definition RangeMap.h:45
BaseType GetRangeEnd() const
Definition RangeMap.h:78