1 //===-- Memory.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 9 #ifndef LLDB_TARGET_MEMORY_H 10 #define LLDB_TARGET_MEMORY_H 11 12 #include "lldb/Utility/RangeMap.h" 13 #include "lldb/lldb-private.h" 14 #include <map> 15 #include <mutex> 16 #include <vector> 17 18 namespace lldb_private { 19 // A class to track memory that was read from a live process between 20 // runs. 21 class MemoryCache { 22 public: 23 // Constructors and Destructors 24 MemoryCache(Process &process); 25 26 ~MemoryCache(); 27 28 void Clear(bool clear_invalid_ranges = false); 29 30 void Flush(lldb::addr_t addr, size_t size); 31 32 size_t Read(lldb::addr_t addr, void *dst, size_t dst_len, Status &error); 33 GetMemoryCacheLineSize()34 uint32_t GetMemoryCacheLineSize() const { return m_L2_cache_line_byte_size; } 35 36 void AddInvalidRange(lldb::addr_t base_addr, lldb::addr_t byte_size); 37 38 bool RemoveInvalidRange(lldb::addr_t base_addr, lldb::addr_t byte_size); 39 40 // Allow external sources to populate data into the L1 memory cache 41 void AddL1CacheData(lldb::addr_t addr, const void *src, size_t src_len); 42 43 void AddL1CacheData(lldb::addr_t addr, 44 const lldb::DataBufferSP &data_buffer_sp); 45 46 protected: 47 typedef std::map<lldb::addr_t, lldb::DataBufferSP> BlockMap; 48 typedef RangeVector<lldb::addr_t, lldb::addr_t, 4> InvalidRanges; 49 typedef Range<lldb::addr_t, lldb::addr_t> AddrRange; 50 // Classes that inherit from MemoryCache can see and modify these 51 std::recursive_mutex m_mutex; 52 BlockMap m_L1_cache; // A first level memory cache whose chunk sizes vary that 53 // will be used only if the memory read fits entirely in 54 // a chunk 55 BlockMap m_L2_cache; // A memory cache of fixed size chinks 56 // (m_L2_cache_line_byte_size bytes in size each) 57 InvalidRanges m_invalid_ranges; 58 Process &m_process; 59 uint32_t m_L2_cache_line_byte_size; 60 61 private: 62 MemoryCache(const MemoryCache &) = delete; 63 const MemoryCache &operator=(const MemoryCache &) = delete; 64 }; 65 66 67 68 class AllocatedBlock { 69 public: 70 AllocatedBlock(lldb::addr_t addr, uint32_t byte_size, uint32_t permissions, 71 uint32_t chunk_size); 72 73 ~AllocatedBlock(); 74 75 lldb::addr_t ReserveBlock(uint32_t size); 76 77 bool FreeBlock(lldb::addr_t addr); 78 GetBaseAddress()79 lldb::addr_t GetBaseAddress() const { return m_range.GetRangeBase(); } 80 GetByteSize()81 uint32_t GetByteSize() const { return m_range.GetByteSize(); } 82 GetPermissions()83 uint32_t GetPermissions() const { return m_permissions; } 84 GetChunkSize()85 uint32_t GetChunkSize() const { return m_chunk_size; } 86 Contains(lldb::addr_t addr)87 bool Contains(lldb::addr_t addr) const { 88 return m_range.Contains(addr); 89 } 90 91 protected: TotalChunks()92 uint32_t TotalChunks() const { return GetByteSize() / GetChunkSize(); } 93 CalculateChunksNeededForSize(uint32_t size)94 uint32_t CalculateChunksNeededForSize(uint32_t size) const { 95 return (size + m_chunk_size - 1) / m_chunk_size; 96 } 97 // Base address of this block of memory 4GB of chunk should be enough. 98 Range<lldb::addr_t, uint32_t> m_range; 99 // Permissions for this memory (logical OR of lldb::Permissions bits) 100 const uint32_t m_permissions; 101 // The size of chunks that the memory at m_addr is divied up into. 102 const uint32_t m_chunk_size; 103 // A sorted list of free address ranges. 104 RangeVector<lldb::addr_t, uint32_t> m_free_blocks; 105 // A sorted list of reserved address. 106 RangeVector<lldb::addr_t, uint32_t> m_reserved_blocks; 107 }; 108 109 // A class that can track allocated memory and give out allocated memory 110 // without us having to make an allocate/deallocate call every time we need 111 // some memory in a process that is being debugged. 112 class AllocatedMemoryCache { 113 public: 114 // Constructors and Destructors 115 AllocatedMemoryCache(Process &process); 116 117 ~AllocatedMemoryCache(); 118 119 void Clear(); 120 121 lldb::addr_t AllocateMemory(size_t byte_size, uint32_t permissions, 122 Status &error); 123 124 bool DeallocateMemory(lldb::addr_t ptr); 125 126 protected: 127 typedef std::shared_ptr<AllocatedBlock> AllocatedBlockSP; 128 129 AllocatedBlockSP AllocatePage(uint32_t byte_size, uint32_t permissions, 130 uint32_t chunk_size, Status &error); 131 132 // Classes that inherit from MemoryCache can see and modify these 133 Process &m_process; 134 std::recursive_mutex m_mutex; 135 typedef std::multimap<uint32_t, AllocatedBlockSP> PermissionsToBlockMap; 136 PermissionsToBlockMap m_memory_map; 137 138 private: 139 AllocatedMemoryCache(const AllocatedMemoryCache &) = delete; 140 const AllocatedMemoryCache &operator=(const AllocatedMemoryCache &) = delete; 141 }; 142 143 } // namespace lldb_private 144 145 #endif // LLDB_TARGET_MEMORY_H 146