1061da546Spatrick //===-- IRMemoryMap.h -------------------------------------------*- C++ -*-===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9*dda28197Spatrick #ifndef LLDB_EXPRESSION_IRMEMORYMAP_H 10*dda28197Spatrick #define LLDB_EXPRESSION_IRMEMORYMAP_H 11061da546Spatrick 12061da546Spatrick #include "lldb/Utility/DataBufferHeap.h" 13061da546Spatrick #include "lldb/Utility/UserID.h" 14061da546Spatrick #include "lldb/lldb-public.h" 15061da546Spatrick 16061da546Spatrick #include <map> 17061da546Spatrick 18061da546Spatrick namespace lldb_private { 19061da546Spatrick 20061da546Spatrick /// \class IRMemoryMap IRMemoryMap.h "lldb/Expression/IRMemoryMap.h" 21061da546Spatrick /// Encapsulates memory that may exist in the process but must 22061da546Spatrick /// also be available in the host process. 23061da546Spatrick /// 24061da546Spatrick /// This class encapsulates a group of memory objects that must be readable or 25061da546Spatrick /// writable from the host process regardless of whether the process exists. 26061da546Spatrick /// This allows the IR interpreter as well as JITted code to access the same 27061da546Spatrick /// memory. All allocations made by this class are represented as disjoint 28061da546Spatrick /// intervals. 29061da546Spatrick /// 30061da546Spatrick /// Point queries against this group of memory objects can be made by the 31061da546Spatrick /// address in the tar at which they reside. If the inferior does not exist, 32061da546Spatrick /// allocations still get made-up addresses. If an inferior appears at some 33061da546Spatrick /// point, then those addresses need to be re-mapped. 34061da546Spatrick class IRMemoryMap { 35061da546Spatrick public: 36061da546Spatrick IRMemoryMap(lldb::TargetSP target_sp); 37061da546Spatrick ~IRMemoryMap(); 38061da546Spatrick 39061da546Spatrick enum AllocationPolicy : uint8_t { 40061da546Spatrick eAllocationPolicyInvalid = 41061da546Spatrick 0, ///< It is an error for an allocation to have this policy. 42061da546Spatrick eAllocationPolicyHostOnly, ///< This allocation was created in the host and 43061da546Spatrick ///will never make it into the process. 44061da546Spatrick ///< It is an error to create other types of allocations while such 45061da546Spatrick ///allocations exist. 46061da546Spatrick eAllocationPolicyMirror, ///< The intent is that this allocation exist both 47061da546Spatrick ///in the host and the process and have 48061da546Spatrick ///< the same content in both. 49061da546Spatrick eAllocationPolicyProcessOnly ///< The intent is that this allocation exist 50061da546Spatrick ///only in the process. 51061da546Spatrick }; 52061da546Spatrick 53061da546Spatrick lldb::addr_t Malloc(size_t size, uint8_t alignment, uint32_t permissions, 54061da546Spatrick AllocationPolicy policy, bool zero_memory, Status &error); 55061da546Spatrick void Leak(lldb::addr_t process_address, Status &error); 56061da546Spatrick void Free(lldb::addr_t process_address, Status &error); 57061da546Spatrick 58061da546Spatrick void WriteMemory(lldb::addr_t process_address, const uint8_t *bytes, 59061da546Spatrick size_t size, Status &error); 60061da546Spatrick void WriteScalarToMemory(lldb::addr_t process_address, Scalar &scalar, 61061da546Spatrick size_t size, Status &error); 62061da546Spatrick void WritePointerToMemory(lldb::addr_t process_address, lldb::addr_t address, 63061da546Spatrick Status &error); 64061da546Spatrick void ReadMemory(uint8_t *bytes, lldb::addr_t process_address, size_t size, 65061da546Spatrick Status &error); 66061da546Spatrick void ReadScalarFromMemory(Scalar &scalar, lldb::addr_t process_address, 67061da546Spatrick size_t size, Status &error); 68061da546Spatrick void ReadPointerFromMemory(lldb::addr_t *address, 69061da546Spatrick lldb::addr_t process_address, Status &error); 70061da546Spatrick bool GetAllocSize(lldb::addr_t address, size_t &size); 71061da546Spatrick void GetMemoryData(DataExtractor &extractor, lldb::addr_t process_address, 72061da546Spatrick size_t size, Status &error); 73061da546Spatrick 74061da546Spatrick lldb::ByteOrder GetByteOrder(); 75061da546Spatrick uint32_t GetAddressByteSize(); 76061da546Spatrick 77061da546Spatrick // This function can return NULL. 78061da546Spatrick ExecutionContextScope *GetBestExecutionContextScope() const; 79061da546Spatrick GetTarget()80061da546Spatrick lldb::TargetSP GetTarget() { return m_target_wp.lock(); } 81061da546Spatrick 82061da546Spatrick protected: 83061da546Spatrick // This function should only be used if you know you are using the JIT. Any 84061da546Spatrick // other cases should use GetBestExecutionContextScope(). 85061da546Spatrick GetProcessWP()86061da546Spatrick lldb::ProcessWP &GetProcessWP() { return m_process_wp; } 87061da546Spatrick 88061da546Spatrick private: 89061da546Spatrick struct Allocation { 90061da546Spatrick lldb::addr_t 91061da546Spatrick m_process_alloc; ///< The (unaligned) base for the remote allocation. 92061da546Spatrick lldb::addr_t 93061da546Spatrick m_process_start; ///< The base address of the allocation in the process. 94061da546Spatrick size_t m_size; ///< The size of the requested allocation. 95061da546Spatrick DataBufferHeap m_data; 96061da546Spatrick 97061da546Spatrick /// Flags. Keep these grouped together to avoid structure padding. 98061da546Spatrick AllocationPolicy m_policy; 99061da546Spatrick bool m_leak; 100061da546Spatrick uint8_t m_permissions; ///< The access permissions on the memory in the 101061da546Spatrick /// process. In the host, the memory is always 102061da546Spatrick /// read/write. 103061da546Spatrick uint8_t m_alignment; ///< The alignment of the requested allocation. 104061da546Spatrick 105061da546Spatrick public: 106061da546Spatrick Allocation(lldb::addr_t process_alloc, lldb::addr_t process_start, 107061da546Spatrick size_t size, uint32_t permissions, uint8_t alignment, 108061da546Spatrick AllocationPolicy m_policy); 109061da546Spatrick 110*dda28197Spatrick Allocation(const Allocation &) = delete; 111*dda28197Spatrick const Allocation &operator=(const Allocation &) = delete; 112061da546Spatrick }; 113061da546Spatrick 114061da546Spatrick static_assert(sizeof(Allocation) <= 115061da546Spatrick (4 * sizeof(lldb::addr_t)) + sizeof(DataBufferHeap), 116061da546Spatrick "IRMemoryMap::Allocation is larger than expected"); 117061da546Spatrick 118061da546Spatrick lldb::ProcessWP m_process_wp; 119061da546Spatrick lldb::TargetWP m_target_wp; 120061da546Spatrick typedef std::map<lldb::addr_t, Allocation> AllocationMap; 121061da546Spatrick AllocationMap m_allocations; 122061da546Spatrick 123061da546Spatrick lldb::addr_t FindSpace(size_t size); 124061da546Spatrick bool ContainsHostOnlyAllocations(); 125061da546Spatrick AllocationMap::iterator FindAllocation(lldb::addr_t addr, size_t size); 126061da546Spatrick 127061da546Spatrick // Returns true if the given allocation intersects any allocation in the 128061da546Spatrick // memory map. 129061da546Spatrick bool IntersectsAllocation(lldb::addr_t addr, size_t size) const; 130061da546Spatrick 131061da546Spatrick // Returns true if the two given allocations intersect each other. 132061da546Spatrick static bool AllocationsIntersect(lldb::addr_t addr1, size_t size1, 133061da546Spatrick lldb::addr_t addr2, size_t size2); 134061da546Spatrick }; 135061da546Spatrick } 136061da546Spatrick 137061da546Spatrick #endif 138