Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 1 | //===-- IRMemoryMap.h -------------------------------------------*- C++ -*-===// |
| 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 | |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 9 | #ifndef LLDB_EXPRESSION_IRMEMORYMAP_H |
| 10 | #define LLDB_EXPRESSION_IRMEMORYMAP_H |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 11 | |
| 12 | #include "lldb/Utility/DataBufferHeap.h" |
| 13 | #include "lldb/Utility/UserID.h" |
| 14 | #include "lldb/lldb-public.h" |
| 15 | |
| 16 | #include <map> |
| 17 | |
| 18 | namespace lldb_private { |
| 19 | |
| 20 | /// \class IRMemoryMap IRMemoryMap.h "lldb/Expression/IRMemoryMap.h" |
| 21 | /// Encapsulates memory that may exist in the process but must |
| 22 | /// also be available in the host process. |
| 23 | /// |
| 24 | /// This class encapsulates a group of memory objects that must be readable or |
| 25 | /// writable from the host process regardless of whether the process exists. |
| 26 | /// This allows the IR interpreter as well as JITted code to access the same |
| 27 | /// memory. All allocations made by this class are represented as disjoint |
| 28 | /// intervals. |
| 29 | /// |
| 30 | /// Point queries against this group of memory objects can be made by the |
| 31 | /// address in the tar at which they reside. If the inferior does not exist, |
| 32 | /// allocations still get made-up addresses. If an inferior appears at some |
| 33 | /// point, then those addresses need to be re-mapped. |
| 34 | class IRMemoryMap { |
| 35 | public: |
| 36 | IRMemoryMap(lldb::TargetSP target_sp); |
| 37 | ~IRMemoryMap(); |
| 38 | |
| 39 | enum AllocationPolicy : uint8_t { |
| 40 | eAllocationPolicyInvalid = |
| 41 | 0, ///< It is an error for an allocation to have this policy. |
| 42 | eAllocationPolicyHostOnly, ///< This allocation was created in the host and |
| 43 | ///will never make it into the process. |
| 44 | ///< It is an error to create other types of allocations while such |
| 45 | ///allocations exist. |
| 46 | eAllocationPolicyMirror, ///< The intent is that this allocation exist both |
| 47 | ///in the host and the process and have |
| 48 | ///< the same content in both. |
| 49 | eAllocationPolicyProcessOnly ///< The intent is that this allocation exist |
| 50 | ///only in the process. |
| 51 | }; |
| 52 | |
| 53 | lldb::addr_t Malloc(size_t size, uint8_t alignment, uint32_t permissions, |
| 54 | AllocationPolicy policy, bool zero_memory, Status &error); |
| 55 | void Leak(lldb::addr_t process_address, Status &error); |
| 56 | void Free(lldb::addr_t process_address, Status &error); |
| 57 | |
| 58 | void WriteMemory(lldb::addr_t process_address, const uint8_t *bytes, |
| 59 | size_t size, Status &error); |
| 60 | void WriteScalarToMemory(lldb::addr_t process_address, Scalar &scalar, |
| 61 | size_t size, Status &error); |
| 62 | void WritePointerToMemory(lldb::addr_t process_address, lldb::addr_t address, |
| 63 | Status &error); |
| 64 | void ReadMemory(uint8_t *bytes, lldb::addr_t process_address, size_t size, |
| 65 | Status &error); |
| 66 | void ReadScalarFromMemory(Scalar &scalar, lldb::addr_t process_address, |
| 67 | size_t size, Status &error); |
| 68 | void ReadPointerFromMemory(lldb::addr_t *address, |
| 69 | lldb::addr_t process_address, Status &error); |
| 70 | bool GetAllocSize(lldb::addr_t address, size_t &size); |
| 71 | void GetMemoryData(DataExtractor &extractor, lldb::addr_t process_address, |
| 72 | size_t size, Status &error); |
| 73 | |
| 74 | lldb::ByteOrder GetByteOrder(); |
| 75 | uint32_t GetAddressByteSize(); |
| 76 | |
| 77 | // This function can return NULL. |
| 78 | ExecutionContextScope *GetBestExecutionContextScope() const; |
| 79 | |
| 80 | lldb::TargetSP GetTarget() { return m_target_wp.lock(); } |
| 81 | |
| 82 | protected: |
| 83 | // This function should only be used if you know you are using the JIT. Any |
| 84 | // other cases should use GetBestExecutionContextScope(). |
| 85 | |
| 86 | lldb::ProcessWP &GetProcessWP() { return m_process_wp; } |
| 87 | |
| 88 | private: |
| 89 | struct Allocation { |
| 90 | lldb::addr_t |
| 91 | m_process_alloc; ///< The (unaligned) base for the remote allocation. |
| 92 | lldb::addr_t |
| 93 | m_process_start; ///< The base address of the allocation in the process. |
| 94 | size_t m_size; ///< The size of the requested allocation. |
| 95 | DataBufferHeap m_data; |
| 96 | |
| 97 | /// Flags. Keep these grouped together to avoid structure padding. |
| 98 | AllocationPolicy m_policy; |
| 99 | bool m_leak; |
| 100 | uint8_t m_permissions; ///< The access permissions on the memory in the |
| 101 | /// process. In the host, the memory is always |
| 102 | /// read/write. |
| 103 | uint8_t m_alignment; ///< The alignment of the requested allocation. |
| 104 | |
| 105 | public: |
| 106 | Allocation(lldb::addr_t process_alloc, lldb::addr_t process_start, |
| 107 | size_t size, uint32_t permissions, uint8_t alignment, |
| 108 | AllocationPolicy m_policy); |
| 109 | |
Olivier Deprez | f4ef2d0 | 2021-04-20 13:36:24 +0200 | [diff] [blame] | 110 | Allocation(const Allocation &) = delete; |
| 111 | const Allocation &operator=(const Allocation &) = delete; |
Andrew Walbran | 3d2c197 | 2020-04-07 12:24:26 +0100 | [diff] [blame] | 112 | }; |
| 113 | |
| 114 | static_assert(sizeof(Allocation) <= |
| 115 | (4 * sizeof(lldb::addr_t)) + sizeof(DataBufferHeap), |
| 116 | "IRMemoryMap::Allocation is larger than expected"); |
| 117 | |
| 118 | lldb::ProcessWP m_process_wp; |
| 119 | lldb::TargetWP m_target_wp; |
| 120 | typedef std::map<lldb::addr_t, Allocation> AllocationMap; |
| 121 | AllocationMap m_allocations; |
| 122 | |
| 123 | lldb::addr_t FindSpace(size_t size); |
| 124 | bool ContainsHostOnlyAllocations(); |
| 125 | AllocationMap::iterator FindAllocation(lldb::addr_t addr, size_t size); |
| 126 | |
| 127 | // Returns true if the given allocation intersects any allocation in the |
| 128 | // memory map. |
| 129 | bool IntersectsAllocation(lldb::addr_t addr, size_t size) const; |
| 130 | |
| 131 | // Returns true if the two given allocations intersect each other. |
| 132 | static bool AllocationsIntersect(lldb::addr_t addr1, size_t size1, |
| 133 | lldb::addr_t addr2, size_t size2); |
| 134 | }; |
| 135 | } |
| 136 | |
| 137 | #endif |