868 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Expression/IRMemoryMap.h"10#include "lldb/Target/MemoryRegionInfo.h"11#include "lldb/Target/Process.h"12#include "lldb/Target/Target.h"13#include "lldb/Utility/DataBufferHeap.h"14#include "lldb/Utility/DataExtractor.h"15#include "lldb/Utility/LLDBAssert.h"16#include "lldb/Utility/LLDBLog.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 23IRMemoryMap::IRMemoryMap(lldb::TargetSP target_sp) : m_target_wp(target_sp) {24 if (target_sp)25 m_process_wp = target_sp->GetProcessSP();26}27 28IRMemoryMap::~IRMemoryMap() {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 else41 Free(iter->first, err);42 }43 }44}45 46lldb::addr_t IRMemoryMap::FindSpace(size_t size) {47 // The FindSpace algorithm's job is to find a region of memory that the48 // underlying process is unlikely to be using.49 //50 // The memory returned by this function will never be written to. The only51 // point is that it should not shadow process memory if possible, so that52 // expressions processing real values from the process do not use the wrong53 // 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 64 lldb::addr_t ret = LLDB_INVALID_ADDRESS;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())76 return LLDB_INVALID_ADDRESS;77 else78 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 are84 // 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.");108 return LLDB_INVALID_ADDRESS;109 }110 111 // Now, if it's possible to use the GetMemoryRegionInfo API to detect mapped112 // regions, walk forward through memory until a region is found that has113 // 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 crashes123 // in the inferior.124 ret = region_info.GetRange().GetRangeEnd();125 } else if (region_info.GetReadable() !=126 MemoryRegionInfo::OptionalBool::eNo ||127 region_info.GetWritable() !=128 MemoryRegionInfo::OptionalBool::eNo ||129 region_info.GetExecutable() !=130 MemoryRegionInfo::OptionalBool::eNo) {131 if (region_info.GetRange().GetRangeEnd() - 1 >= end_of_memory) {132 ret = LLDB_INVALID_ADDRESS;133 break;134 } else {135 ret = region_info.GetRange().GetRangeEnd();136 }137 } else if (ret + size < region_info.GetRange().GetRangeEnd()) {138 return ret;139 } else {140 // ret stays the same. We just need to walk a bit further.141 }142 143 err = process_sp->GetMemoryRegionInfo(144 region_info.GetRange().GetRangeEnd(), region_info);145 if (err.Fail()) {146 lldbassert(0 && "GetMemoryRegionInfo() succeeded, then failed");147 ret = LLDB_INVALID_ADDRESS;148 break;149 }150 }151 }152 }153 154 // We've tried our algorithm, and it didn't work. Now we have to reset back155 // to the end of the allocations we've already reported, or use a 'sensible'156 // default if this is our first allocation.157 if (m_allocations.empty()) {158 uint64_t alloc_address = target_sp->GetExprAllocAddress();159 if (alloc_address > 0) {160 if (alloc_address >= end_of_memory) {161 lldbassert(0 && "The allocation address for expression evaluation must "162 "be within process address space");163 return LLDB_INVALID_ADDRESS;164 }165 ret = alloc_address;166 } else {167 uint32_t address_byte_size = GetAddressByteSize();168 if (address_byte_size != UINT32_MAX) {169 switch (address_byte_size) {170 case 2:171 ret = 0x8000ull;172 break;173 case 4:174 ret = 0xee000000ull;175 break;176 case 8:177 ret = 0xdead0fff00000000ull;178 break;179 default:180 lldbassert(false && "Invalid address size.");181 return LLDB_INVALID_ADDRESS;182 }183 }184 }185 } else {186 auto back = m_allocations.rbegin();187 lldb::addr_t addr = back->first;188 size_t alloc_size = back->second.m_size;189 uint64_t align = target_sp->GetExprAllocAlign();190 if (align == 0)191 align = 4096;192 ret = llvm::alignTo(addr + alloc_size, align);193 }194 195 return ret;196}197 198IRMemoryMap::AllocationMap::iterator199IRMemoryMap::FindAllocation(lldb::addr_t addr, size_t size) {200 if (addr == LLDB_INVALID_ADDRESS)201 return m_allocations.end();202 203 AllocationMap::iterator iter = m_allocations.lower_bound(addr);204 205 if (iter == m_allocations.end() || iter->first > addr) {206 if (iter == m_allocations.begin())207 return m_allocations.end();208 iter--;209 }210 211 if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size)212 return iter;213 214 return m_allocations.end();215}216 217bool IRMemoryMap::IntersectsAllocation(lldb::addr_t addr, size_t size) const {218 if (addr == LLDB_INVALID_ADDRESS)219 return false;220 221 AllocationMap::const_iterator iter = m_allocations.lower_bound(addr);222 223 // Since we only know that the returned interval begins at a location greater224 // than or equal to where the given interval begins, it's possible that the225 // given interval intersects either the returned interval or the previous226 // interval. Thus, we need to check both. Note that we only need to check227 // these two intervals. Since all intervals are disjoint it is not possible228 // that an adjacent interval does not intersect, but a non-adjacent interval229 // does intersect.230 if (iter != m_allocations.end()) {231 if (AllocationsIntersect(addr, size, iter->second.m_process_start,232 iter->second.m_size))233 return true;234 }235 236 if (iter != m_allocations.begin()) {237 --iter;238 if (AllocationsIntersect(addr, size, iter->second.m_process_start,239 iter->second.m_size))240 return true;241 }242 243 return false;244}245 246bool IRMemoryMap::AllocationsIntersect(lldb::addr_t addr1, size_t size1,247 lldb::addr_t addr2, size_t size2) {248 // Given two half open intervals [A, B) and [X, Y), the only 6 permutations249 // that satisfy A<B and X<Y are the following:250 // A B X Y251 // A X B Y (intersects)252 // A X Y B (intersects)253 // X A B Y (intersects)254 // X A Y B (intersects)255 // X Y A B256 // The first is B <= X, and the last is Y <= A. So the condition is !(B <= X257 // || Y <= A)), or (X < B && A < Y)258 return (addr2 < (addr1 + size1)) && (addr1 < (addr2 + size2));259}260 261lldb::ByteOrder IRMemoryMap::GetByteOrder() {262 lldb::ProcessSP process_sp = m_process_wp.lock();263 264 if (process_sp)265 return process_sp->GetByteOrder();266 267 lldb::TargetSP target_sp = m_target_wp.lock();268 269 if (target_sp)270 return target_sp->GetArchitecture().GetByteOrder();271 272 return lldb::eByteOrderInvalid;273}274 275uint32_t IRMemoryMap::GetAddressByteSize() {276 lldb::ProcessSP process_sp = m_process_wp.lock();277 278 if (process_sp)279 return process_sp->GetAddressByteSize();280 281 lldb::TargetSP target_sp = m_target_wp.lock();282 283 if (target_sp)284 return target_sp->GetArchitecture().GetAddressByteSize();285 286 return UINT32_MAX;287}288 289ExecutionContextScope *IRMemoryMap::GetBestExecutionContextScope() const {290 lldb::ProcessSP process_sp = m_process_wp.lock();291 292 if (process_sp)293 return process_sp.get();294 295 lldb::TargetSP target_sp = m_target_wp.lock();296 297 if (target_sp)298 return target_sp.get();299 300 return nullptr;301}302 303IRMemoryMap::Allocation::Allocation(lldb::addr_t process_alloc,304 lldb::addr_t process_start, size_t size,305 uint32_t permissions, uint8_t alignment,306 AllocationPolicy policy)307 : m_process_alloc(process_alloc), m_process_start(process_start),308 m_size(size), m_policy(policy), m_leak(false), m_permissions(permissions),309 m_alignment(alignment) {310 switch (policy) {311 default:312 llvm_unreachable("Invalid AllocationPolicy");313 case eAllocationPolicyHostOnly:314 case eAllocationPolicyMirror:315 m_data.SetByteSize(size);316 break;317 case eAllocationPolicyProcessOnly:318 break;319 }320}321 322llvm::Expected<lldb::addr_t>323IRMemoryMap::Malloc(size_t size, uint8_t alignment, uint32_t permissions,324 AllocationPolicy policy, bool zero_memory,325 AllocationPolicy *used_policy) {326 lldb_private::Log *log(GetLog(LLDBLog::Expressions));327 328 lldb::ProcessSP process_sp;329 lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS;330 lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS;331 332 size_t allocation_size;333 334 if (size == 0) {335 // FIXME: Malloc(0) should either return an invalid address or assert, in336 // order to cut down on unnecessary allocations.337 allocation_size = alignment;338 } else {339 // Round up the requested size to an aligned value.340 allocation_size = llvm::alignTo(size, alignment);341 342 // The process page cache does not see the requested alignment. We can't343 // assume its result will be any more than 1-byte aligned. To work around344 // this, request `alignment - 1` additional bytes.345 allocation_size += alignment - 1;346 }347 348 switch (policy) {349 default:350 return llvm::createStringError(351 llvm::inconvertibleErrorCode(),352 "Couldn't malloc: invalid allocation policy");353 case eAllocationPolicyHostOnly:354 allocation_address = FindSpace(allocation_size);355 if (allocation_address == LLDB_INVALID_ADDRESS)356 return llvm::createStringError(llvm::inconvertibleErrorCode(),357 "Couldn't malloc: address space is full");358 break;359 case eAllocationPolicyMirror:360 process_sp = m_process_wp.lock();361 LLDB_LOGF(log,362 "IRMemoryMap::%s process_sp=0x%" PRIxPTR363 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s",364 __FUNCTION__, reinterpret_cast<uintptr_t>(process_sp.get()),365 process_sp && process_sp->CanJIT() ? "true" : "false",366 process_sp && process_sp->IsAlive() ? "true" : "false");367 if (process_sp && process_sp->CanJIT() && process_sp->IsAlive()) {368 Status error;369 if (!zero_memory)370 allocation_address =371 process_sp->AllocateMemory(allocation_size, permissions, error);372 else373 allocation_address =374 process_sp->CallocateMemory(allocation_size, permissions, error);375 376 if (!error.Success())377 return error.takeError();378 } else {379 LLDB_LOGF(log,380 "IRMemoryMap::%s switching to eAllocationPolicyHostOnly "381 "due to failed condition (see previous expr log message)",382 __FUNCTION__);383 policy = eAllocationPolicyHostOnly;384 allocation_address = FindSpace(allocation_size);385 if (allocation_address == LLDB_INVALID_ADDRESS)386 return llvm::createStringError(387 llvm::inconvertibleErrorCode(),388 "Couldn't malloc: address space is full");389 }390 break;391 case eAllocationPolicyProcessOnly:392 process_sp = m_process_wp.lock();393 if (process_sp) {394 if (process_sp->CanJIT() && process_sp->IsAlive()) {395 Status error;396 if (!zero_memory)397 allocation_address =398 process_sp->AllocateMemory(allocation_size, permissions, error);399 else400 allocation_address =401 process_sp->CallocateMemory(allocation_size, permissions, error);402 403 if (!error.Success())404 return error.takeError();405 } else {406 return llvm::createStringError(407 llvm::inconvertibleErrorCode(),408 "Couldn't malloc: process doesn't support allocating memory");409 }410 } else {411 return llvm::createStringError(llvm::inconvertibleErrorCode(),412 "Couldn't malloc: process doesn't exist, "413 "and this memory must be in the process");414 }415 break;416 }417 418 lldb::addr_t mask = alignment - 1;419 aligned_address = (allocation_address + mask) & (~mask);420 421 m_allocations.emplace(422 std::piecewise_construct, std::forward_as_tuple(aligned_address),423 std::forward_as_tuple(allocation_address, aligned_address,424 allocation_size, permissions, alignment, policy));425 426 if (zero_memory) {427 Status write_error;428 std::vector<uint8_t> zero_buf(size, 0);429 WriteMemory(aligned_address, zero_buf.data(), size, write_error);430 }431 432 if (log) {433 const char *policy_string;434 435 switch (policy) {436 default:437 policy_string = "<invalid policy>";438 break;439 case eAllocationPolicyHostOnly:440 policy_string = "eAllocationPolicyHostOnly";441 break;442 case eAllocationPolicyProcessOnly:443 policy_string = "eAllocationPolicyProcessOnly";444 break;445 case eAllocationPolicyMirror:446 policy_string = "eAllocationPolicyMirror";447 break;448 }449 450 LLDB_LOGF(log,451 "IRMemoryMap::Malloc (%" PRIu64 ", 0x%" PRIx64 ", 0x%" PRIx64452 ", %s) -> 0x%" PRIx64,453 (uint64_t)allocation_size, (uint64_t)alignment,454 (uint64_t)permissions, policy_string, aligned_address);455 }456 457 if (used_policy)458 *used_policy = policy;459 460 return aligned_address;461}462 463void IRMemoryMap::Leak(lldb::addr_t process_address, Status &error) {464 error.Clear();465 466 AllocationMap::iterator iter = m_allocations.find(process_address);467 468 if (iter == m_allocations.end()) {469 error = Status::FromErrorString("Couldn't leak: allocation doesn't exist");470 return;471 }472 473 Allocation &allocation = iter->second;474 475 allocation.m_leak = true;476}477 478void IRMemoryMap::Free(lldb::addr_t process_address, Status &error) {479 error.Clear();480 481 AllocationMap::iterator iter = m_allocations.find(process_address);482 483 if (iter == m_allocations.end()) {484 error = Status::FromErrorString("Couldn't free: allocation doesn't exist");485 return;486 }487 488 Allocation &allocation = iter->second;489 490 switch (allocation.m_policy) {491 default:492 case eAllocationPolicyHostOnly: {493 lldb::ProcessSP process_sp = m_process_wp.lock();494 if (process_sp) {495 if (process_sp->CanJIT() && process_sp->IsAlive())496 process_sp->DeallocateMemory(497 allocation.m_process_alloc); // FindSpace allocated this for real498 }499 500 break;501 }502 case eAllocationPolicyMirror:503 case eAllocationPolicyProcessOnly: {504 lldb::ProcessSP process_sp = m_process_wp.lock();505 if (process_sp)506 process_sp->DeallocateMemory(allocation.m_process_alloc);507 }508 }509 510 if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {511 LLDB_LOGF(log,512 "IRMemoryMap::Free (0x%" PRIx64 ") freed [0x%" PRIx64513 "..0x%" PRIx64 ")",514 (uint64_t)process_address, iter->second.m_process_start,515 iter->second.m_process_start + iter->second.m_size);516 }517 518 m_allocations.erase(iter);519}520 521bool IRMemoryMap::GetAllocSize(lldb::addr_t address, size_t &size) {522 AllocationMap::iterator iter = FindAllocation(address, size);523 if (iter == m_allocations.end())524 return false;525 526 Allocation &al = iter->second;527 528 if (address > (al.m_process_start + al.m_size)) {529 size = 0;530 return false;531 }532 533 if (address > al.m_process_start) {534 int dif = address - al.m_process_start;535 size = al.m_size - dif;536 return true;537 }538 539 size = al.m_size;540 return true;541}542 543void IRMemoryMap::WriteMemory(lldb::addr_t process_address,544 const uint8_t *bytes, size_t size,545 Status &error) {546 error.Clear();547 548 AllocationMap::iterator iter = FindAllocation(process_address, size);549 550 if (iter == m_allocations.end()) {551 lldb::ProcessSP process_sp = m_process_wp.lock();552 553 if (process_sp) {554 process_sp->WriteMemory(process_address, bytes, size, error);555 return;556 }557 558 error = Status::FromErrorString(559 "Couldn't write: no allocation contains the target "560 "range and the process doesn't exist");561 return;562 }563 564 Allocation &allocation = iter->second;565 566 uint64_t offset = process_address - allocation.m_process_start;567 568 lldb::ProcessSP process_sp;569 570 switch (allocation.m_policy) {571 default:572 error =573 Status::FromErrorString("Couldn't write: invalid allocation policy");574 return;575 case eAllocationPolicyHostOnly:576 if (!allocation.m_data.GetByteSize()) {577 error = Status::FromErrorString("Couldn't write: data buffer is empty");578 return;579 }580 ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);581 break;582 case eAllocationPolicyMirror:583 if (!allocation.m_data.GetByteSize()) {584 error = Status::FromErrorString("Couldn't write: data buffer is empty");585 return;586 }587 ::memcpy(allocation.m_data.GetBytes() + offset, bytes, size);588 process_sp = m_process_wp.lock();589 if (process_sp) {590 process_sp->WriteMemory(process_address, bytes, size, error);591 if (!error.Success())592 return;593 }594 break;595 case eAllocationPolicyProcessOnly:596 process_sp = m_process_wp.lock();597 if (process_sp) {598 process_sp->WriteMemory(process_address, bytes, size, error);599 if (!error.Success())600 return;601 }602 break;603 }604 605 if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {606 LLDB_LOGF(log,607 "IRMemoryMap::WriteMemory (0x%" PRIx64 ", 0x%" PRIxPTR608 ", 0x%" PRId64 ") went to [0x%" PRIx64 "..0x%" PRIx64 ")",609 (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,610 (uint64_t)allocation.m_process_start,611 (uint64_t)allocation.m_process_start +612 (uint64_t)allocation.m_size);613 }614}615 616void IRMemoryMap::WriteScalarToMemory(lldb::addr_t process_address,617 Scalar &scalar, size_t size,618 Status &error) {619 error.Clear();620 621 if (size == UINT32_MAX)622 size = scalar.GetByteSize();623 624 if (size > 0) {625 uint8_t buf[32];626 const size_t mem_size =627 scalar.GetAsMemoryData(buf, size, GetByteOrder(), error);628 if (mem_size > 0) {629 return WriteMemory(process_address, buf, mem_size, error);630 } else {631 error = Status::FromErrorString(632 "Couldn't write scalar: failed to get scalar as memory data");633 }634 } else {635 error = Status::FromErrorString("Couldn't write scalar: its size was zero");636 }637}638 639void IRMemoryMap::WritePointerToMemory(lldb::addr_t process_address,640 lldb::addr_t pointer, Status &error) {641 error.Clear();642 643 /// Only ask the Process to fix `pointer` if the address belongs to the644 /// process. An address belongs to the process if the Allocation policy is not645 /// eAllocationPolicyHostOnly.646 auto it = FindAllocation(pointer, 1);647 if (it == m_allocations.end() ||648 it->second.m_policy != AllocationPolicy::eAllocationPolicyHostOnly)649 if (auto process_sp = GetProcessWP().lock())650 pointer = process_sp->FixAnyAddress(pointer);651 652 Scalar scalar(pointer);653 654 WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error);655}656 657void IRMemoryMap::ReadMemory(uint8_t *bytes, lldb::addr_t process_address,658 size_t size, Status &error) {659 error.Clear();660 661 AllocationMap::iterator iter = FindAllocation(process_address, size);662 663 if (iter == m_allocations.end()) {664 lldb::ProcessSP process_sp = m_process_wp.lock();665 666 if (process_sp) {667 process_sp->ReadMemory(process_address, bytes, size, error);668 return;669 }670 671 lldb::TargetSP target_sp = m_target_wp.lock();672 673 if (target_sp) {674 Address absolute_address(process_address);675 target_sp->ReadMemory(absolute_address, bytes, size, error, true);676 return;677 }678 679 error = Status::FromErrorString(680 "Couldn't read: no allocation contains the target "681 "range, and neither the process nor the target exist");682 return;683 }684 685 Allocation &allocation = iter->second;686 687 uint64_t offset = process_address - allocation.m_process_start;688 689 if (offset > allocation.m_size) {690 error =691 Status::FromErrorString("Couldn't read: data is not in the allocation");692 return;693 }694 695 lldb::ProcessSP process_sp;696 697 switch (allocation.m_policy) {698 default:699 error = Status::FromErrorString("Couldn't read: invalid allocation policy");700 return;701 case eAllocationPolicyHostOnly:702 if (!allocation.m_data.GetByteSize()) {703 error = Status::FromErrorString("Couldn't read: data buffer is empty");704 return;705 }706 if (allocation.m_data.GetByteSize() < offset + size) {707 error =708 Status::FromErrorString("Couldn't read: not enough underlying data");709 return;710 }711 712 ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);713 break;714 case eAllocationPolicyMirror:715 process_sp = m_process_wp.lock();716 if (process_sp) {717 process_sp->ReadMemory(process_address, bytes, size, error);718 if (!error.Success())719 return;720 } else {721 if (!allocation.m_data.GetByteSize()) {722 error = Status::FromErrorString("Couldn't read: data buffer is empty");723 return;724 }725 ::memcpy(bytes, allocation.m_data.GetBytes() + offset, size);726 }727 break;728 case eAllocationPolicyProcessOnly:729 process_sp = m_process_wp.lock();730 if (process_sp) {731 process_sp->ReadMemory(process_address, bytes, size, error);732 if (!error.Success())733 return;734 }735 break;736 }737 738 if (lldb_private::Log *log = GetLog(LLDBLog::Expressions)) {739 LLDB_LOGF(log,740 "IRMemoryMap::ReadMemory (0x%" PRIx64 ", 0x%" PRIxPTR741 ", 0x%" PRId64 ") came from [0x%" PRIx64 "..0x%" PRIx64 ")",742 (uint64_t)process_address, reinterpret_cast<uintptr_t>(bytes), (uint64_t)size,743 (uint64_t)allocation.m_process_start,744 (uint64_t)allocation.m_process_start +745 (uint64_t)allocation.m_size);746 }747}748 749void IRMemoryMap::ReadScalarFromMemory(Scalar &scalar,750 lldb::addr_t process_address,751 size_t size, Status &error) {752 error.Clear();753 754 if (size > 0) {755 DataBufferHeap buf(size, 0);756 ReadMemory(buf.GetBytes(), process_address, size, error);757 758 if (!error.Success())759 return;760 761 DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(),762 GetAddressByteSize());763 764 lldb::offset_t offset = 0;765 766 switch (size) {767 default:768 error = Status::FromErrorStringWithFormat(769 "Couldn't read scalar: unsupported size %" PRIu64, (uint64_t)size);770 return;771 case 1:772 scalar = extractor.GetU8(&offset);773 break;774 case 2:775 scalar = extractor.GetU16(&offset);776 break;777 case 4:778 scalar = extractor.GetU32(&offset);779 break;780 case 8:781 scalar = extractor.GetU64(&offset);782 break;783 }784 } else {785 error = Status::FromErrorString("Couldn't read scalar: its size was zero");786 }787}788 789void IRMemoryMap::ReadPointerFromMemory(lldb::addr_t *address,790 lldb::addr_t process_address,791 Status &error) {792 error.Clear();793 794 Scalar pointer_scalar;795 ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(),796 error);797 798 if (!error.Success())799 return;800 801 *address = pointer_scalar.ULongLong();802}803 804void IRMemoryMap::GetMemoryData(DataExtractor &extractor,805 lldb::addr_t process_address, size_t size,806 Status &error) {807 error.Clear();808 809 if (size > 0) {810 AllocationMap::iterator iter = FindAllocation(process_address, size);811 812 if (iter == m_allocations.end()) {813 error = Status::FromErrorStringWithFormat(814 "Couldn't find an allocation containing [0x%" PRIx64 "..0x%" PRIx64815 ")",816 process_address, process_address + size);817 return;818 }819 820 Allocation &allocation = iter->second;821 822 switch (allocation.m_policy) {823 default:824 error = Status::FromErrorString(825 "Couldn't get memory data: invalid allocation policy");826 return;827 case eAllocationPolicyProcessOnly:828 error = Status::FromErrorString(829 "Couldn't get memory data: memory is only in the target");830 return;831 case eAllocationPolicyMirror: {832 lldb::ProcessSP process_sp = m_process_wp.lock();833 834 if (!allocation.m_data.GetByteSize()) {835 error = Status::FromErrorString(836 "Couldn't get memory data: data buffer is empty");837 return;838 }839 if (process_sp) {840 process_sp->ReadMemory(allocation.m_process_start,841 allocation.m_data.GetBytes(),842 allocation.m_data.GetByteSize(), error);843 if (!error.Success())844 return;845 uint64_t offset = process_address - allocation.m_process_start;846 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,847 GetByteOrder(), GetAddressByteSize());848 return;849 }850 } break;851 case eAllocationPolicyHostOnly:852 if (!allocation.m_data.GetByteSize()) {853 error = Status::FromErrorString(854 "Couldn't get memory data: data buffer is empty");855 return;856 }857 uint64_t offset = process_address - allocation.m_process_start;858 extractor = DataExtractor(allocation.m_data.GetBytes() + offset, size,859 GetByteOrder(), GetAddressByteSize());860 return;861 }862 } else {863 error =864 Status::FromErrorString("Couldn't get memory data: its size was zero");865 return;866 }867}868