15a1af4e6SSean Callanan //===-- IRMemoryMap.cpp -----------------------------------------*- C++ -*-===// 25a1af4e6SSean Callanan // 35a1af4e6SSean Callanan // The LLVM Compiler Infrastructure 45a1af4e6SSean Callanan // 55a1af4e6SSean Callanan // This file is distributed under the University of Illinois Open Source 65a1af4e6SSean Callanan // License. See LICENSE.TXT for details. 75a1af4e6SSean Callanan // 85a1af4e6SSean Callanan //===----------------------------------------------------------------------===// 95a1af4e6SSean Callanan 1035005f76SSean Callanan #include "lldb/Core/DataBufferHeap.h" 1135005f76SSean Callanan #include "lldb/Core/DataExtractor.h" 125a1af4e6SSean Callanan #include "lldb/Core/Error.h" 135a1af4e6SSean Callanan #include "lldb/Core/Log.h" 1435005f76SSean Callanan #include "lldb/Core/Scalar.h" 155a1af4e6SSean Callanan #include "lldb/Expression/IRMemoryMap.h" 165a1af4e6SSean Callanan #include "lldb/Target/Process.h" 1735005f76SSean Callanan #include "lldb/Target/Target.h" 185a1af4e6SSean Callanan 195a1af4e6SSean Callanan using namespace lldb_private; 205a1af4e6SSean Callanan 2135005f76SSean Callanan IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) : 2235005f76SSean Callanan m_target_wp(target_sp) 235a1af4e6SSean Callanan { 24b024d878SSean Callanan if (target_sp) 25b024d878SSean Callanan m_process_wp = target_sp->GetProcessSP(); 265a1af4e6SSean Callanan } 275a1af4e6SSean Callanan 285a1af4e6SSean Callanan IRMemoryMap::~IRMemoryMap () 295a1af4e6SSean Callanan { 305a1af4e6SSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock(); 315a1af4e6SSean Callanan 325a1af4e6SSean Callanan if (process_sp) 335a1af4e6SSean Callanan { 345a1af4e6SSean Callanan for (AllocationMap::value_type &allocation : m_allocations) 355a1af4e6SSean Callanan { 365a1af4e6SSean Callanan if (allocation.second.m_policy == eAllocationPolicyMirror || 375a1af4e6SSean Callanan allocation.second.m_policy == eAllocationPolicyHostOnly) 385a1af4e6SSean Callanan process_sp->DeallocateMemory(allocation.second.m_process_alloc); 395a1af4e6SSean Callanan 405a1af4e6SSean Callanan if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) 415a1af4e6SSean Callanan { 425a1af4e6SSean Callanan log->Printf("IRMemoryMap::~IRMemoryMap deallocated [0x%llx..0x%llx)", 435a1af4e6SSean Callanan (uint64_t)allocation.second.m_process_start, 445a1af4e6SSean Callanan (uint64_t)allocation.second.m_process_start + (uint64_t)allocation.second.m_size); 455a1af4e6SSean Callanan } 465a1af4e6SSean Callanan } 475a1af4e6SSean Callanan } 485a1af4e6SSean Callanan } 495a1af4e6SSean Callanan 505a1af4e6SSean Callanan lldb::addr_t 515a1af4e6SSean Callanan IRMemoryMap::FindSpace (size_t size) 525a1af4e6SSean Callanan { 53*bb9945f4SSean Callanan lldb::TargetSP target_sp = m_target_wp.lock(); 54*bb9945f4SSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock(); 555a1af4e6SSean Callanan 56*bb9945f4SSean Callanan lldb::addr_t ret = LLDB_INVALID_ADDRESS; 575a1af4e6SSean Callanan 58*bb9945f4SSean Callanan for (int iterations = 0; iterations < 16; ++iterations) 595a1af4e6SSean Callanan { 60*bb9945f4SSean Callanan lldb::addr_t candidate; 615a1af4e6SSean Callanan 62*bb9945f4SSean Callanan switch (target_sp->GetArchitecture().GetAddressByteSize()) 63*bb9945f4SSean Callanan { 64*bb9945f4SSean Callanan case 4: 65*bb9945f4SSean Callanan { 66*bb9945f4SSean Callanan uint32_t random_data = random(); 67*bb9945f4SSean Callanan candidate = random_data; 68*bb9945f4SSean Callanan candidate &= ~0xfffull; 69*bb9945f4SSean Callanan break; 70*bb9945f4SSean Callanan } 71*bb9945f4SSean Callanan case 8: 72*bb9945f4SSean Callanan { 73*bb9945f4SSean Callanan uint32_t random_low = random(); 74*bb9945f4SSean Callanan uint32_t random_high = random(); 75*bb9945f4SSean Callanan candidate = random_high; 76*bb9945f4SSean Callanan candidate <<= 32ull; 77*bb9945f4SSean Callanan candidate |= random_low; 78*bb9945f4SSean Callanan candidate &= ~0xfffull; 79*bb9945f4SSean Callanan break; 80*bb9945f4SSean Callanan } 815a1af4e6SSean Callanan } 825a1af4e6SSean Callanan 83*bb9945f4SSean Callanan if (IntersectsAllocation(candidate, size)) 84*bb9945f4SSean Callanan continue; 855a1af4e6SSean Callanan 86*bb9945f4SSean Callanan char buf[1]; 87*bb9945f4SSean Callanan 88*bb9945f4SSean Callanan Error err; 89*bb9945f4SSean Callanan 90*bb9945f4SSean Callanan if (process_sp && 91*bb9945f4SSean Callanan (process_sp->ReadMemory(candidate, buf, 1, err) == 1 || 92*bb9945f4SSean Callanan process_sp->ReadMemory(candidate + size, buf, 1, err) == 1)) 93*bb9945f4SSean Callanan continue; 94*bb9945f4SSean Callanan 95*bb9945f4SSean Callanan ret = candidate; 965a1af4e6SSean Callanan } 975a1af4e6SSean Callanan 98*bb9945f4SSean Callanan return ret; 995a1af4e6SSean Callanan } 1005a1af4e6SSean Callanan 1015a1af4e6SSean Callanan IRMemoryMap::AllocationMap::iterator 1025a1af4e6SSean Callanan IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size) 1035a1af4e6SSean Callanan { 1041582ee68SSean Callanan if (addr == LLDB_INVALID_ADDRESS) 1051582ee68SSean Callanan return m_allocations.end(); 1061582ee68SSean Callanan 1075a1af4e6SSean Callanan AllocationMap::iterator iter = m_allocations.lower_bound (addr); 1085a1af4e6SSean Callanan 10914b1bae5SSean Callanan if (iter == m_allocations.end() || 11014b1bae5SSean Callanan iter->first > addr) 1115a1af4e6SSean Callanan { 1125a1af4e6SSean Callanan if (iter == m_allocations.begin()) 1135a1af4e6SSean Callanan return m_allocations.end(); 1145a1af4e6SSean Callanan iter--; 1155a1af4e6SSean Callanan } 1165a1af4e6SSean Callanan 1175a1af4e6SSean Callanan if (iter->first <= addr && iter->first + iter->second.m_size >= addr + size) 1185a1af4e6SSean Callanan return iter; 1195a1af4e6SSean Callanan 1205a1af4e6SSean Callanan return m_allocations.end(); 1215a1af4e6SSean Callanan } 1225a1af4e6SSean Callanan 123*bb9945f4SSean Callanan bool 124*bb9945f4SSean Callanan IRMemoryMap::IntersectsAllocation (lldb::addr_t addr, size_t size) 125*bb9945f4SSean Callanan { 126*bb9945f4SSean Callanan if (addr == LLDB_INVALID_ADDRESS) 127*bb9945f4SSean Callanan return false; 128*bb9945f4SSean Callanan 129*bb9945f4SSean Callanan AllocationMap::iterator iter = m_allocations.lower_bound (addr); 130*bb9945f4SSean Callanan 131*bb9945f4SSean Callanan if (iter == m_allocations.end() || 132*bb9945f4SSean Callanan iter->first > addr) 133*bb9945f4SSean Callanan { 134*bb9945f4SSean Callanan if (iter == m_allocations.begin()) 135*bb9945f4SSean Callanan return false; 136*bb9945f4SSean Callanan 137*bb9945f4SSean Callanan iter--; 138*bb9945f4SSean Callanan } 139*bb9945f4SSean Callanan 140*bb9945f4SSean Callanan while (iter != m_allocations.end() && iter->second.m_process_alloc < addr + size) 141*bb9945f4SSean Callanan { 142*bb9945f4SSean Callanan if (iter->second.m_process_start + iter->second.m_size > addr) 143*bb9945f4SSean Callanan return true; 144*bb9945f4SSean Callanan 145*bb9945f4SSean Callanan ++iter; 146*bb9945f4SSean Callanan } 147*bb9945f4SSean Callanan 148*bb9945f4SSean Callanan return false; 149*bb9945f4SSean Callanan } 150*bb9945f4SSean Callanan 15135005f76SSean Callanan lldb::ByteOrder 15235005f76SSean Callanan IRMemoryMap::GetByteOrder() 15335005f76SSean Callanan { 15435005f76SSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock(); 15535005f76SSean Callanan 15635005f76SSean Callanan if (process_sp) 15735005f76SSean Callanan return process_sp->GetByteOrder(); 15835005f76SSean Callanan 15935005f76SSean Callanan lldb::TargetSP target_sp = m_target_wp.lock(); 16035005f76SSean Callanan 16135005f76SSean Callanan if (target_sp) 16208052afaSSean Callanan return target_sp->GetArchitecture().GetByteOrder(); 16335005f76SSean Callanan 16435005f76SSean Callanan return lldb::eByteOrderInvalid; 16535005f76SSean Callanan } 16635005f76SSean Callanan 16735005f76SSean Callanan uint32_t 16835005f76SSean Callanan IRMemoryMap::GetAddressByteSize() 16935005f76SSean Callanan { 17035005f76SSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock(); 17135005f76SSean Callanan 17235005f76SSean Callanan if (process_sp) 17335005f76SSean Callanan return process_sp->GetAddressByteSize(); 17435005f76SSean Callanan 17535005f76SSean Callanan lldb::TargetSP target_sp = m_target_wp.lock(); 17635005f76SSean Callanan 17735005f76SSean Callanan if (target_sp) 17808052afaSSean Callanan return target_sp->GetArchitecture().GetAddressByteSize(); 17935005f76SSean Callanan 18035005f76SSean Callanan return UINT32_MAX; 18135005f76SSean Callanan } 18235005f76SSean Callanan 18335005f76SSean Callanan ExecutionContextScope * 18435005f76SSean Callanan IRMemoryMap::GetBestExecutionContextScope() 18535005f76SSean Callanan { 18635005f76SSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock(); 18735005f76SSean Callanan 18835005f76SSean Callanan if (process_sp) 18935005f76SSean Callanan return process_sp.get(); 19035005f76SSean Callanan 19135005f76SSean Callanan lldb::TargetSP target_sp = m_target_wp.lock(); 19235005f76SSean Callanan 19335005f76SSean Callanan if (target_sp) 19435005f76SSean Callanan return target_sp.get(); 19535005f76SSean Callanan 19635005f76SSean Callanan return NULL; 19735005f76SSean Callanan } 19835005f76SSean Callanan 1995a1af4e6SSean Callanan lldb::addr_t 2005a1af4e6SSean Callanan IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error) 2015a1af4e6SSean Callanan { 20208052afaSSean Callanan error.Clear(); 20308052afaSSean Callanan 2045a1af4e6SSean Callanan lldb::ProcessSP process_sp; 2055a1af4e6SSean Callanan lldb::addr_t allocation_address = LLDB_INVALID_ADDRESS; 2065a1af4e6SSean Callanan lldb::addr_t aligned_address = LLDB_INVALID_ADDRESS; 2075a1af4e6SSean Callanan 2085a1af4e6SSean Callanan size_t allocation_size = (size ? size : 1) + alignment - 1; 2095a1af4e6SSean Callanan 2105a1af4e6SSean Callanan switch (policy) 2115a1af4e6SSean Callanan { 2125a1af4e6SSean Callanan default: 2135a1af4e6SSean Callanan error.SetErrorToGenericError(); 2145a1af4e6SSean Callanan error.SetErrorString("Couldn't malloc: invalid allocation policy"); 2155a1af4e6SSean Callanan return LLDB_INVALID_ADDRESS; 2165a1af4e6SSean Callanan case eAllocationPolicyHostOnly: 2175a1af4e6SSean Callanan allocation_address = FindSpace(allocation_size); 2185a1af4e6SSean Callanan if (allocation_address == LLDB_INVALID_ADDRESS) 2195a1af4e6SSean Callanan { 2205a1af4e6SSean Callanan error.SetErrorToGenericError(); 2215a1af4e6SSean Callanan error.SetErrorString("Couldn't malloc: address space is full"); 2225a1af4e6SSean Callanan return LLDB_INVALID_ADDRESS; 2235a1af4e6SSean Callanan } 2245a1af4e6SSean Callanan break; 2255a1af4e6SSean Callanan case eAllocationPolicyMirror: 2265a1af4e6SSean Callanan process_sp = m_process_wp.lock(); 227*bb9945f4SSean Callanan if (process_sp && process_sp->CanJIT()) 2285a1af4e6SSean Callanan { 2295a1af4e6SSean Callanan allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error); 2305a1af4e6SSean Callanan if (!error.Success()) 2315a1af4e6SSean Callanan return LLDB_INVALID_ADDRESS; 2325a1af4e6SSean Callanan } 2335a1af4e6SSean Callanan else 2345a1af4e6SSean Callanan { 235*bb9945f4SSean Callanan policy = eAllocationPolicyHostOnly; 2365a1af4e6SSean Callanan allocation_address = FindSpace(allocation_size); 2375a1af4e6SSean Callanan if (allocation_address == LLDB_INVALID_ADDRESS) 2385a1af4e6SSean Callanan { 2395a1af4e6SSean Callanan error.SetErrorToGenericError(); 2405a1af4e6SSean Callanan error.SetErrorString("Couldn't malloc: address space is full"); 2415a1af4e6SSean Callanan return LLDB_INVALID_ADDRESS; 2425a1af4e6SSean Callanan } 2435a1af4e6SSean Callanan } 2445a1af4e6SSean Callanan break; 2455a1af4e6SSean Callanan case eAllocationPolicyProcessOnly: 2465a1af4e6SSean Callanan process_sp = m_process_wp.lock(); 2475a1af4e6SSean Callanan if (process_sp) 2485a1af4e6SSean Callanan { 249*bb9945f4SSean Callanan if (process_sp->CanJIT()) 250*bb9945f4SSean Callanan { 2515a1af4e6SSean Callanan allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error); 2525a1af4e6SSean Callanan if (!error.Success()) 2535a1af4e6SSean Callanan return LLDB_INVALID_ADDRESS; 2545a1af4e6SSean Callanan } 2555a1af4e6SSean Callanan else 2565a1af4e6SSean Callanan { 2575a1af4e6SSean Callanan error.SetErrorToGenericError(); 258*bb9945f4SSean Callanan error.SetErrorString("Couldn't malloc: process doesn't support allocating memory"); 259*bb9945f4SSean Callanan return LLDB_INVALID_ADDRESS; 260*bb9945f4SSean Callanan } 261*bb9945f4SSean Callanan } 262*bb9945f4SSean Callanan else 263*bb9945f4SSean Callanan { 264*bb9945f4SSean Callanan error.SetErrorToGenericError(); 2655a1af4e6SSean Callanan error.SetErrorString("Couldn't malloc: process doesn't exist, and this memory must be in the process"); 2665a1af4e6SSean Callanan return LLDB_INVALID_ADDRESS; 2675a1af4e6SSean Callanan } 2685a1af4e6SSean Callanan break; 2695a1af4e6SSean Callanan } 2705a1af4e6SSean Callanan 2715a1af4e6SSean Callanan 2725a1af4e6SSean Callanan lldb::addr_t mask = alignment - 1; 2735a1af4e6SSean Callanan aligned_address = (allocation_address + mask) & (~mask); 2745a1af4e6SSean Callanan 275d850685eSGreg Clayton Allocation allocation; 2765a1af4e6SSean Callanan 2775a1af4e6SSean Callanan allocation.m_process_alloc = allocation_address; 2785a1af4e6SSean Callanan allocation.m_process_start = aligned_address; 2795a1af4e6SSean Callanan allocation.m_size = size; 2805a1af4e6SSean Callanan allocation.m_permissions = permissions; 2815a1af4e6SSean Callanan allocation.m_alignment = alignment; 2825a1af4e6SSean Callanan allocation.m_policy = policy; 2835a1af4e6SSean Callanan 284d850685eSGreg Clayton m_allocations[aligned_address] = std::move(allocation); 285d850685eSGreg Clayton 2865a1af4e6SSean Callanan switch (policy) 2875a1af4e6SSean Callanan { 2885a1af4e6SSean Callanan default: 2895a1af4e6SSean Callanan assert (0 && "We cannot reach this!"); 2905a1af4e6SSean Callanan case eAllocationPolicyHostOnly: 291e0c64e15SGreg Clayton allocation.m_data_ap.reset(new DataBufferHeap(size, 0)); 2925a1af4e6SSean Callanan break; 2935a1af4e6SSean Callanan case eAllocationPolicyProcessOnly: 2945a1af4e6SSean Callanan break; 2955a1af4e6SSean Callanan case eAllocationPolicyMirror: 296e0c64e15SGreg Clayton allocation.m_data_ap.reset(new DataBufferHeap(size, 0)); 2975a1af4e6SSean Callanan break; 2985a1af4e6SSean Callanan } 2995a1af4e6SSean Callanan 3005a1af4e6SSean Callanan if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) 3015a1af4e6SSean Callanan { 3025a1af4e6SSean Callanan const char * policy_string; 3035a1af4e6SSean Callanan 3045a1af4e6SSean Callanan switch (policy) 3055a1af4e6SSean Callanan { 3065a1af4e6SSean Callanan default: 3075a1af4e6SSean Callanan policy_string = "<invalid policy>"; 3085a1af4e6SSean Callanan break; 3095a1af4e6SSean Callanan case eAllocationPolicyHostOnly: 3105a1af4e6SSean Callanan policy_string = "eAllocationPolicyHostOnly"; 3115a1af4e6SSean Callanan break; 3125a1af4e6SSean Callanan case eAllocationPolicyProcessOnly: 3135a1af4e6SSean Callanan policy_string = "eAllocationPolicyProcessOnly"; 3145a1af4e6SSean Callanan break; 3155a1af4e6SSean Callanan case eAllocationPolicyMirror: 3165a1af4e6SSean Callanan policy_string = "eAllocationPolicyMirror"; 3175a1af4e6SSean Callanan break; 3185a1af4e6SSean Callanan } 3195a1af4e6SSean Callanan 3205a1af4e6SSean Callanan log->Printf("IRMemoryMap::Malloc (%llu, 0x%llx, 0x%llx, %s) -> 0x%llx", 3215a1af4e6SSean Callanan (uint64_t)size, 3225a1af4e6SSean Callanan (uint64_t)alignment, 3235a1af4e6SSean Callanan (uint64_t)permissions, 3245a1af4e6SSean Callanan policy_string, 3255a1af4e6SSean Callanan aligned_address); 3265a1af4e6SSean Callanan } 3275a1af4e6SSean Callanan 3285a1af4e6SSean Callanan return aligned_address; 3295a1af4e6SSean Callanan } 3305a1af4e6SSean Callanan 3315a1af4e6SSean Callanan void 3325a1af4e6SSean Callanan IRMemoryMap::Free (lldb::addr_t process_address, Error &error) 3335a1af4e6SSean Callanan { 33408052afaSSean Callanan error.Clear(); 33508052afaSSean Callanan 3365a1af4e6SSean Callanan AllocationMap::iterator iter = m_allocations.find(process_address); 3375a1af4e6SSean Callanan 3385a1af4e6SSean Callanan if (iter == m_allocations.end()) 3395a1af4e6SSean Callanan { 3405a1af4e6SSean Callanan error.SetErrorToGenericError(); 3415a1af4e6SSean Callanan error.SetErrorString("Couldn't free: allocation doesn't exist"); 3425a1af4e6SSean Callanan return; 3435a1af4e6SSean Callanan } 3445a1af4e6SSean Callanan 3455a1af4e6SSean Callanan Allocation &allocation = iter->second; 3465a1af4e6SSean Callanan 3475a1af4e6SSean Callanan switch (allocation.m_policy) 3485a1af4e6SSean Callanan { 3495a1af4e6SSean Callanan default: 3505a1af4e6SSean Callanan case eAllocationPolicyHostOnly: 3515a1af4e6SSean Callanan break; 3525a1af4e6SSean Callanan case eAllocationPolicyMirror: 3535a1af4e6SSean Callanan case eAllocationPolicyProcessOnly: 3545a1af4e6SSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock(); 3555a1af4e6SSean Callanan if (process_sp) 3565a1af4e6SSean Callanan process_sp->DeallocateMemory(allocation.m_process_alloc); 3575a1af4e6SSean Callanan } 3585a1af4e6SSean Callanan 3595a1af4e6SSean Callanan if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) 3605a1af4e6SSean Callanan { 3615a1af4e6SSean Callanan log->Printf("IRMemoryMap::Free (0x%llx) freed [0x%llx..0x%llx)", 3625a1af4e6SSean Callanan (uint64_t)process_address, 3635a1af4e6SSean Callanan iter->second.m_process_start, 3645a1af4e6SSean Callanan iter->second.m_process_start + iter->second.m_size); 3655a1af4e6SSean Callanan } 3665a1af4e6SSean Callanan 3675a1af4e6SSean Callanan m_allocations.erase(iter); 3685a1af4e6SSean Callanan } 3695a1af4e6SSean Callanan 3705a1af4e6SSean Callanan void 3715a1af4e6SSean Callanan IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error) 3725a1af4e6SSean Callanan { 37308052afaSSean Callanan error.Clear(); 37408052afaSSean Callanan 3755a1af4e6SSean Callanan AllocationMap::iterator iter = FindAllocation(process_address, size); 3765a1af4e6SSean Callanan 3775a1af4e6SSean Callanan if (iter == m_allocations.end()) 3785a1af4e6SSean Callanan { 379c8c5b8dcSSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock(); 380c8c5b8dcSSean Callanan 381c8c5b8dcSSean Callanan if (process_sp) 382c8c5b8dcSSean Callanan { 383c8c5b8dcSSean Callanan process_sp->WriteMemory(process_address, bytes, size, error); 384c8c5b8dcSSean Callanan return; 385c8c5b8dcSSean Callanan } 386c8c5b8dcSSean Callanan 3875a1af4e6SSean Callanan error.SetErrorToGenericError(); 388c8c5b8dcSSean Callanan error.SetErrorString("Couldn't write: no allocation contains the target range and the process doesn't exist"); 3895a1af4e6SSean Callanan return; 3905a1af4e6SSean Callanan } 3915a1af4e6SSean Callanan 3925a1af4e6SSean Callanan Allocation &allocation = iter->second; 3935a1af4e6SSean Callanan 3945a1af4e6SSean Callanan uint64_t offset = process_address - allocation.m_process_start; 3955a1af4e6SSean Callanan 3965a1af4e6SSean Callanan lldb::ProcessSP process_sp; 3975a1af4e6SSean Callanan 3985a1af4e6SSean Callanan switch (allocation.m_policy) 3995a1af4e6SSean Callanan { 4005a1af4e6SSean Callanan default: 4015a1af4e6SSean Callanan error.SetErrorToGenericError(); 4025a1af4e6SSean Callanan error.SetErrorString("Couldn't write: invalid allocation policy"); 4035a1af4e6SSean Callanan return; 4045a1af4e6SSean Callanan case eAllocationPolicyHostOnly: 405e0c64e15SGreg Clayton if (!allocation.m_data_ap.get()) 4065a1af4e6SSean Callanan { 4075a1af4e6SSean Callanan error.SetErrorToGenericError(); 4085a1af4e6SSean Callanan error.SetErrorString("Couldn't write: data buffer is empty"); 4095a1af4e6SSean Callanan return; 4105a1af4e6SSean Callanan } 411e0c64e15SGreg Clayton ::memcpy (allocation.m_data_ap->GetBytes() + offset, bytes, size); 4125a1af4e6SSean Callanan break; 4135a1af4e6SSean Callanan case eAllocationPolicyMirror: 414e0c64e15SGreg Clayton if (!allocation.m_data_ap.get()) 4155a1af4e6SSean Callanan { 4165a1af4e6SSean Callanan error.SetErrorToGenericError(); 4175a1af4e6SSean Callanan error.SetErrorString("Couldn't write: data buffer is empty"); 4185a1af4e6SSean Callanan return; 4195a1af4e6SSean Callanan } 420e0c64e15SGreg Clayton ::memcpy (allocation.m_data_ap->GetBytes() + offset, bytes, size); 4215a1af4e6SSean Callanan process_sp = m_process_wp.lock(); 4225a1af4e6SSean Callanan if (process_sp) 4235a1af4e6SSean Callanan { 4245a1af4e6SSean Callanan process_sp->WriteMemory(process_address, bytes, size, error); 4255a1af4e6SSean Callanan if (!error.Success()) 4265a1af4e6SSean Callanan return; 4275a1af4e6SSean Callanan } 4285a1af4e6SSean Callanan break; 4295a1af4e6SSean Callanan case eAllocationPolicyProcessOnly: 4305a1af4e6SSean Callanan process_sp = m_process_wp.lock(); 4315a1af4e6SSean Callanan if (process_sp) 4325a1af4e6SSean Callanan { 4335a1af4e6SSean Callanan process_sp->WriteMemory(process_address, bytes, size, error); 4345a1af4e6SSean Callanan if (!error.Success()) 4355a1af4e6SSean Callanan return; 4365a1af4e6SSean Callanan } 4375a1af4e6SSean Callanan break; 4385a1af4e6SSean Callanan } 4395a1af4e6SSean Callanan 4405a1af4e6SSean Callanan if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) 4415a1af4e6SSean Callanan { 4425a1af4e6SSean Callanan log->Printf("IRMemoryMap::WriteMemory (0x%llx, 0x%llx, 0x%lld) went to [0x%llx..0x%llx)", 4435a1af4e6SSean Callanan (uint64_t)process_address, 4445a1af4e6SSean Callanan (uint64_t)bytes, 4455a1af4e6SSean Callanan (uint64_t)size, 4465a1af4e6SSean Callanan (uint64_t)allocation.m_process_start, 4475a1af4e6SSean Callanan (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size); 4485a1af4e6SSean Callanan } 4495a1af4e6SSean Callanan } 4505a1af4e6SSean Callanan 4515a1af4e6SSean Callanan void 45235005f76SSean Callanan IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error) 45335005f76SSean Callanan { 45408052afaSSean Callanan error.Clear(); 45508052afaSSean Callanan 45635005f76SSean Callanan if (size == UINT32_MAX) 45735005f76SSean Callanan size = scalar.GetByteSize(); 45835005f76SSean Callanan 45935005f76SSean Callanan if (size > 0) 46035005f76SSean Callanan { 46135005f76SSean Callanan uint8_t buf[32]; 46235005f76SSean Callanan const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error); 46335005f76SSean Callanan if (mem_size > 0) 46435005f76SSean Callanan { 46535005f76SSean Callanan return WriteMemory(process_address, buf, mem_size, error); 46635005f76SSean Callanan } 46735005f76SSean Callanan else 46835005f76SSean Callanan { 46935005f76SSean Callanan error.SetErrorToGenericError(); 47035005f76SSean Callanan error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data"); 47135005f76SSean Callanan } 47235005f76SSean Callanan } 47335005f76SSean Callanan else 47435005f76SSean Callanan { 47535005f76SSean Callanan error.SetErrorToGenericError(); 47635005f76SSean Callanan error.SetErrorString ("Couldn't write scalar: its size was zero"); 47735005f76SSean Callanan } 47835005f76SSean Callanan return; 47935005f76SSean Callanan } 48035005f76SSean Callanan 48135005f76SSean Callanan void 482f8043fa5SSean Callanan IRMemoryMap::WritePointerToMemory (lldb::addr_t process_address, lldb::addr_t address, Error &error) 483f8043fa5SSean Callanan { 48408052afaSSean Callanan error.Clear(); 48508052afaSSean Callanan 486f8043fa5SSean Callanan Scalar scalar(address); 487f8043fa5SSean Callanan 488f8043fa5SSean Callanan WriteScalarToMemory(process_address, scalar, GetAddressByteSize(), error); 489f8043fa5SSean Callanan } 490f8043fa5SSean Callanan 491f8043fa5SSean Callanan void 4925a1af4e6SSean Callanan IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error) 4935a1af4e6SSean Callanan { 49408052afaSSean Callanan error.Clear(); 49508052afaSSean Callanan 4965a1af4e6SSean Callanan AllocationMap::iterator iter = FindAllocation(process_address, size); 4975a1af4e6SSean Callanan 4985a1af4e6SSean Callanan if (iter == m_allocations.end()) 4995a1af4e6SSean Callanan { 500c8c5b8dcSSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock(); 501c8c5b8dcSSean Callanan 502c8c5b8dcSSean Callanan if (process_sp) 503c8c5b8dcSSean Callanan { 504c8c5b8dcSSean Callanan process_sp->ReadMemory(process_address, bytes, size, error); 505c8c5b8dcSSean Callanan return; 506c8c5b8dcSSean Callanan } 507c8c5b8dcSSean Callanan 508c8c5b8dcSSean Callanan lldb::TargetSP target_sp = m_target_wp.lock(); 509c8c5b8dcSSean Callanan 510c8c5b8dcSSean Callanan if (target_sp) 511c8c5b8dcSSean Callanan { 512c8c5b8dcSSean Callanan Address absolute_address(process_address); 513c8c5b8dcSSean Callanan target_sp->ReadMemory(absolute_address, false, bytes, size, error); 514c8c5b8dcSSean Callanan return; 515c8c5b8dcSSean Callanan } 516c8c5b8dcSSean Callanan 5175a1af4e6SSean Callanan error.SetErrorToGenericError(); 518c8c5b8dcSSean Callanan error.SetErrorString("Couldn't read: no allocation contains the target range, and neither the process nor the target exist"); 5195a1af4e6SSean Callanan return; 5205a1af4e6SSean Callanan } 5215a1af4e6SSean Callanan 5225a1af4e6SSean Callanan Allocation &allocation = iter->second; 5235a1af4e6SSean Callanan 5245a1af4e6SSean Callanan uint64_t offset = process_address - allocation.m_process_start; 5255a1af4e6SSean Callanan 5265a1af4e6SSean Callanan lldb::ProcessSP process_sp; 5275a1af4e6SSean Callanan 5285a1af4e6SSean Callanan switch (allocation.m_policy) 5295a1af4e6SSean Callanan { 5305a1af4e6SSean Callanan default: 5315a1af4e6SSean Callanan error.SetErrorToGenericError(); 5325a1af4e6SSean Callanan error.SetErrorString("Couldn't read: invalid allocation policy"); 5335a1af4e6SSean Callanan return; 5345a1af4e6SSean Callanan case eAllocationPolicyHostOnly: 535e0c64e15SGreg Clayton if (!allocation.m_data_ap.get()) 5365a1af4e6SSean Callanan { 5375a1af4e6SSean Callanan error.SetErrorToGenericError(); 5385a1af4e6SSean Callanan error.SetErrorString("Couldn't read: data buffer is empty"); 5395a1af4e6SSean Callanan return; 5405a1af4e6SSean Callanan } 541e0c64e15SGreg Clayton ::memcpy (bytes, allocation.m_data_ap->GetBytes() + offset, size); 5425a1af4e6SSean Callanan break; 5435a1af4e6SSean Callanan case eAllocationPolicyMirror: 5445a1af4e6SSean Callanan process_sp = m_process_wp.lock(); 5455a1af4e6SSean Callanan if (process_sp) 5465a1af4e6SSean Callanan { 5475a1af4e6SSean Callanan process_sp->ReadMemory(process_address, bytes, size, error); 5485a1af4e6SSean Callanan if (!error.Success()) 5495a1af4e6SSean Callanan return; 5505a1af4e6SSean Callanan } 5515a1af4e6SSean Callanan else 5525a1af4e6SSean Callanan { 553e0c64e15SGreg Clayton if (!allocation.m_data_ap.get()) 5545a1af4e6SSean Callanan { 5555a1af4e6SSean Callanan error.SetErrorToGenericError(); 5565a1af4e6SSean Callanan error.SetErrorString("Couldn't read: data buffer is empty"); 5575a1af4e6SSean Callanan return; 5585a1af4e6SSean Callanan } 559e0c64e15SGreg Clayton ::memcpy (bytes, allocation.m_data_ap->GetBytes() + offset, size); 5605a1af4e6SSean Callanan } 5615a1af4e6SSean Callanan break; 5625a1af4e6SSean Callanan case eAllocationPolicyProcessOnly: 5635a1af4e6SSean Callanan process_sp = m_process_wp.lock(); 5645a1af4e6SSean Callanan if (process_sp) 5655a1af4e6SSean Callanan { 5665a1af4e6SSean Callanan process_sp->ReadMemory(process_address, bytes, size, error); 5675a1af4e6SSean Callanan if (!error.Success()) 5685a1af4e6SSean Callanan return; 5695a1af4e6SSean Callanan } 5705a1af4e6SSean Callanan break; 5715a1af4e6SSean Callanan } 5725a1af4e6SSean Callanan 5735a1af4e6SSean Callanan if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) 5745a1af4e6SSean Callanan { 5755a1af4e6SSean Callanan log->Printf("IRMemoryMap::ReadMemory (0x%llx, 0x%llx, 0x%lld) came from [0x%llx..0x%llx)", 5765a1af4e6SSean Callanan (uint64_t)process_address, 5775a1af4e6SSean Callanan (uint64_t)bytes, 5785a1af4e6SSean Callanan (uint64_t)size, 5795a1af4e6SSean Callanan (uint64_t)allocation.m_process_start, 5805a1af4e6SSean Callanan (uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size); 5815a1af4e6SSean Callanan } 5825a1af4e6SSean Callanan } 58335005f76SSean Callanan 58435005f76SSean Callanan void 58535005f76SSean Callanan IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error) 58635005f76SSean Callanan { 58708052afaSSean Callanan error.Clear(); 58808052afaSSean Callanan 58935005f76SSean Callanan if (size > 0) 59035005f76SSean Callanan { 59135005f76SSean Callanan DataBufferHeap buf(size, 0); 59235005f76SSean Callanan ReadMemory(buf.GetBytes(), process_address, size, error); 59335005f76SSean Callanan 59435005f76SSean Callanan if (!error.Success()) 59535005f76SSean Callanan return; 59635005f76SSean Callanan 59735005f76SSean Callanan DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize()); 59835005f76SSean Callanan 59935005f76SSean Callanan lldb::offset_t offset = 0; 60035005f76SSean Callanan 60135005f76SSean Callanan switch (size) 60235005f76SSean Callanan { 60335005f76SSean Callanan default: 60435005f76SSean Callanan error.SetErrorToGenericError(); 60535005f76SSean Callanan error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %lld", (unsigned long long)size); 60635005f76SSean Callanan return; 60735005f76SSean Callanan case 1: scalar = extractor.GetU8(&offset); break; 60835005f76SSean Callanan case 2: scalar = extractor.GetU16(&offset); break; 60935005f76SSean Callanan case 4: scalar = extractor.GetU32(&offset); break; 61035005f76SSean Callanan case 8: scalar = extractor.GetU64(&offset); break; 61135005f76SSean Callanan } 61235005f76SSean Callanan } 61335005f76SSean Callanan else 61435005f76SSean Callanan { 61535005f76SSean Callanan error.SetErrorToGenericError(); 616458ae1c6SSean Callanan error.SetErrorString ("Couldn't read scalar: its size was zero"); 61735005f76SSean Callanan } 61835005f76SSean Callanan return; 61935005f76SSean Callanan } 62035005f76SSean Callanan 621458ae1c6SSean Callanan void 6222d37e5a5SSean Callanan IRMemoryMap::ReadPointerFromMemory (lldb::addr_t *address, lldb::addr_t process_address, Error &error) 6232d37e5a5SSean Callanan { 62408052afaSSean Callanan error.Clear(); 62508052afaSSean Callanan 6262d37e5a5SSean Callanan Scalar pointer_scalar; 6272d37e5a5SSean Callanan ReadScalarFromMemory(pointer_scalar, process_address, GetAddressByteSize(), error); 6282d37e5a5SSean Callanan 6292d37e5a5SSean Callanan if (!error.Success()) 6302d37e5a5SSean Callanan return; 6312d37e5a5SSean Callanan 6322d37e5a5SSean Callanan *address = pointer_scalar.ULongLong(); 6332d37e5a5SSean Callanan 6342d37e5a5SSean Callanan return; 6352d37e5a5SSean Callanan } 6362d37e5a5SSean Callanan 6372d37e5a5SSean Callanan void 638458ae1c6SSean Callanan IRMemoryMap::GetMemoryData (DataExtractor &extractor, lldb::addr_t process_address, size_t size, Error &error) 639458ae1c6SSean Callanan { 64008052afaSSean Callanan error.Clear(); 64108052afaSSean Callanan 642458ae1c6SSean Callanan if (size > 0) 643458ae1c6SSean Callanan { 644458ae1c6SSean Callanan AllocationMap::iterator iter = FindAllocation(process_address, size); 645458ae1c6SSean Callanan 646458ae1c6SSean Callanan if (iter == m_allocations.end()) 647458ae1c6SSean Callanan { 648458ae1c6SSean Callanan error.SetErrorToGenericError(); 649458ae1c6SSean Callanan error.SetErrorStringWithFormat("Couldn't find an allocation containing [0x%llx..0x%llx)", (unsigned long long)process_address, (unsigned long long)(process_address + size)); 650458ae1c6SSean Callanan return; 651458ae1c6SSean Callanan } 652458ae1c6SSean Callanan 653458ae1c6SSean Callanan Allocation &allocation = iter->second; 654458ae1c6SSean Callanan 655458ae1c6SSean Callanan switch (allocation.m_policy) 656458ae1c6SSean Callanan { 657458ae1c6SSean Callanan default: 658458ae1c6SSean Callanan error.SetErrorToGenericError(); 659458ae1c6SSean Callanan error.SetErrorString("Couldn't get memory data: invalid allocation policy"); 660458ae1c6SSean Callanan return; 661458ae1c6SSean Callanan case eAllocationPolicyProcessOnly: 662458ae1c6SSean Callanan error.SetErrorToGenericError(); 663458ae1c6SSean Callanan error.SetErrorString("Couldn't get memory data: memory is only in the target"); 664458ae1c6SSean Callanan return; 665458ae1c6SSean Callanan case eAllocationPolicyMirror: 666c8c5b8dcSSean Callanan { 667c8c5b8dcSSean Callanan lldb::ProcessSP process_sp = m_process_wp.lock(); 668c8c5b8dcSSean Callanan 669e0c64e15SGreg Clayton if (!allocation.m_data_ap.get()) 670c8c5b8dcSSean Callanan { 671c8c5b8dcSSean Callanan error.SetErrorToGenericError(); 672c8c5b8dcSSean Callanan error.SetErrorString("Couldn't get memory data: data buffer is empty"); 673c8c5b8dcSSean Callanan return; 674c8c5b8dcSSean Callanan } 675c8c5b8dcSSean Callanan if (process_sp) 676c8c5b8dcSSean Callanan { 677e0c64e15SGreg Clayton process_sp->ReadMemory(allocation.m_process_start, allocation.m_data_ap->GetBytes(), allocation.m_data_ap->GetByteSize(), error); 678c8c5b8dcSSean Callanan if (!error.Success()) 679c8c5b8dcSSean Callanan return; 680c8c5b8dcSSean Callanan uint64_t offset = process_address - allocation.m_process_start; 681e0c64e15SGreg Clayton extractor = DataExtractor(allocation.m_data_ap->GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize()); 682c8c5b8dcSSean Callanan return; 683c8c5b8dcSSean Callanan } 684c8c5b8dcSSean Callanan } 685c8c5b8dcSSean Callanan case eAllocationPolicyHostOnly: 686e0c64e15SGreg Clayton if (!allocation.m_data_ap.get()) 687458ae1c6SSean Callanan { 688458ae1c6SSean Callanan error.SetErrorToGenericError(); 689458ae1c6SSean Callanan error.SetErrorString("Couldn't get memory data: data buffer is empty"); 690458ae1c6SSean Callanan return; 691458ae1c6SSean Callanan } 692458ae1c6SSean Callanan uint64_t offset = process_address - allocation.m_process_start; 693e0c64e15SGreg Clayton extractor = DataExtractor(allocation.m_data_ap->GetBytes() + offset, size, GetByteOrder(), GetAddressByteSize()); 694458ae1c6SSean Callanan return; 695458ae1c6SSean Callanan } 696458ae1c6SSean Callanan } 697458ae1c6SSean Callanan else 698458ae1c6SSean Callanan { 699458ae1c6SSean Callanan error.SetErrorToGenericError(); 700458ae1c6SSean Callanan error.SetErrorString ("Couldn't get memory data: its size was zero"); 701458ae1c6SSean Callanan return; 702458ae1c6SSean Callanan } 703458ae1c6SSean Callanan } 704458ae1c6SSean Callanan 705458ae1c6SSean Callanan 706