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