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 lldb::DataBufferSP GetL2CacheLine(lldb::addr_t addr, Status &error); 66 }; 67 68 69 70 class AllocatedBlock { 71 public: 72 AllocatedBlock(lldb::addr_t addr, uint32_t byte_size, uint32_t permissions, 73 uint32_t chunk_size); 74 75 ~AllocatedBlock(); 76 77 lldb::addr_t ReserveBlock(uint32_t size); 78 79 bool FreeBlock(lldb::addr_t addr); 80 GetBaseAddress()81 lldb::addr_t GetBaseAddress() const { return m_range.GetRangeBase(); } 82 GetByteSize()83 uint32_t GetByteSize() const { return m_range.GetByteSize(); } 84 GetPermissions()85 uint32_t GetPermissions() const { return m_permissions; } 86 GetChunkSize()87 uint32_t GetChunkSize() const { return m_chunk_size; } 88 Contains(lldb::addr_t addr)89 bool Contains(lldb::addr_t addr) const { 90 return m_range.Contains(addr); 91 } 92 93 protected: TotalChunks()94 uint32_t TotalChunks() const { return GetByteSize() / GetChunkSize(); } 95 CalculateChunksNeededForSize(uint32_t size)96 uint32_t CalculateChunksNeededForSize(uint32_t size) const { 97 return (size + m_chunk_size - 1) / m_chunk_size; 98 } 99 // Base address of this block of memory 4GB of chunk should be enough. 100 Range<lldb::addr_t, uint32_t> m_range; 101 // Permissions for this memory (logical OR of lldb::Permissions bits) 102 const uint32_t m_permissions; 103 // The size of chunks that the memory at m_addr is divied up into. 104 const uint32_t m_chunk_size; 105 // A sorted list of free address ranges. 106 RangeVector<lldb::addr_t, uint32_t> m_free_blocks; 107 // A sorted list of reserved address. 108 RangeVector<lldb::addr_t, uint32_t> m_reserved_blocks; 109 }; 110 111 // A class that can track allocated memory and give out allocated memory 112 // without us having to make an allocate/deallocate call every time we need 113 // some memory in a process that is being debugged. 114 class AllocatedMemoryCache { 115 public: 116 // Constructors and Destructors 117 AllocatedMemoryCache(Process &process); 118 119 ~AllocatedMemoryCache(); 120 121 void Clear(bool deallocate_memory); 122 123 lldb::addr_t AllocateMemory(size_t byte_size, uint32_t permissions, 124 Status &error); 125 126 bool DeallocateMemory(lldb::addr_t ptr); 127 128 protected: 129 typedef std::shared_ptr<AllocatedBlock> AllocatedBlockSP; 130 131 AllocatedBlockSP AllocatePage(uint32_t byte_size, uint32_t permissions, 132 uint32_t chunk_size, Status &error); 133 134 // Classes that inherit from MemoryCache can see and modify these 135 Process &m_process; 136 std::recursive_mutex m_mutex; 137 typedef std::multimap<uint32_t, AllocatedBlockSP> PermissionsToBlockMap; 138 PermissionsToBlockMap m_memory_map; 139 140 private: 141 AllocatedMemoryCache(const AllocatedMemoryCache &) = delete; 142 const AllocatedMemoryCache &operator=(const AllocatedMemoryCache &) = delete; 143 }; 144 145 } // namespace lldb_private 146 147 #endif // LLDB_TARGET_MEMORY_H 148