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 18namespace lldb_private { 19// A class to track memory that was read from a live process between 20// runs. 21class MemoryCache { 22public: 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 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 46protected: 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 61private: 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 70class AllocatedBlock { 71public: 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 81 lldb::addr_t GetBaseAddress() const { return m_range.GetRangeBase(); } 82 83 uint32_t GetByteSize() const { return m_range.GetByteSize(); } 84 85 uint32_t GetPermissions() const { return m_permissions; } 86 87 uint32_t GetChunkSize() const { return m_chunk_size; } 88 89 bool Contains(lldb::addr_t addr) const { 90 return m_range.Contains(addr); 91 } 92 93protected: 94 uint32_t TotalChunks() const { return GetByteSize() / GetChunkSize(); } 95 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. 114class AllocatedMemoryCache { 115public: 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 128protected: 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 140private: 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