LLDB mainline
Memory.h
Go to the documentation of this file.
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
13#include "lldb/lldb-private.h"
14#include "llvm/ADT/ArrayRef.h"
15#include "llvm/ADT/DenseMap.h"
16#include "llvm/ADT/SmallVector.h"
17#include <map>
18#include <memory>
19#include <mutex>
20#include <vector>
21
22namespace lldb_private {
23
24/// A set of cache entries, all of which are aligned and have the same size.
25/// Entries cannot be partially filled.
26class LineCache {
27 /// Keyed by line index, so a key names a whole line.
28 using Collection = llvm::DenseMap<uint64_t, std::unique_ptr<uint8_t[]>>;
29
30public:
31 explicit LineCache(uint32_t line_byte_size)
32 : m_line_byte_size(line_byte_size) {}
33
34 uint32_t GetLineByteSize() const { return m_line_byte_size; }
35
36 /// The cached bytes from \a addr to the end of the line holding it, empty if
37 /// that line is not resident.
38 llvm::ArrayRef<uint8_t> Lookup(lldb::addr_t addr) const;
39
40 bool Holds(lldb::addr_t addr) const {
41 return m_lines.contains(IndexOf(addr));
42 }
43
44 /// Add one whole line. \a addr must be line aligned and \a src must hold a
45 /// whole line.
46 void Insert(lldb::addr_t addr, llvm::ArrayRef<uint8_t> src);
47
48 /// Drop every line that intersects [addr, addr+size).
49 void EraseRange(lldb::addr_t addr, lldb::addr_t size);
50
51 void Clear(uint32_t new_line_byte_size) {
52 m_lines.clear();
53 m_line_byte_size = new_line_byte_size;
54 }
55
56 size_t GetSize() const { return m_lines.size(); }
57
58 /// Iteration yields a line index and its bytes, in unspecified order.
59 using const_iterator = Collection::const_iterator;
60 const_iterator begin() const { return m_lines.begin(); }
61 const_iterator end() const { return m_lines.end(); }
62
63private:
64 uint64_t IndexOf(lldb::addr_t addr) const { return addr / m_line_byte_size; }
65
68};
69
70/// A set of non-overlapping byte ranges at arbitrary addresses. Lengths vary,
71/// so every chunk carries its own.
73 using Collection = std::map<lldb::addr_t, std::vector<uint8_t>>;
74
75public:
76 /// The cached bytes from \a addr to the end of the chunk holding it, empty
77 /// if no chunk holds it.
78 llvm::ArrayRef<uint8_t> Lookup(lldb::addr_t addr) const;
79
80 bool Holds(lldb::addr_t addr) const { return !Lookup(addr).empty(); }
81
82 /// Add the bytes of [addr, addr+src.size()) that no chunk holds yet. Bytes
83 /// already held are kept: which read produced a byte does not matter.
84 void InsertMissing(lldb::addr_t addr, llvm::ArrayRef<uint8_t> src);
85
86 /// Drop every chunk that intersects [addr, addr+size).
87 void EraseRange(lldb::addr_t addr, lldb::addr_t size);
88
89 void Clear() { m_chunks.clear(); }
90
91 size_t GetSize() const { return m_chunks.size(); }
92
93 /// Iteration yields a chunk's start address and its bytes, in address order.
94 using const_iterator = Collection::const_iterator;
95 const_iterator begin() const { return m_chunks.begin(); }
96 const_iterator end() const { return m_chunks.end(); }
97
98private:
99 /// The chunk holding \a addr, or end(). Chunks never overlap, so only the
100 /// one starting at or below \a addr can hold it.
101 Collection::const_iterator FindChunkContaining(lldb::addr_t addr) const;
102
104};
105
106// A class to track memory that was read from a live process between
107// runs.
109public:
110 // Constructors and Destructors
111 MemoryCache(Process &process);
112
114
115 void Clear(bool clear_invalid_ranges = false);
116
117 void Flush(lldb::addr_t addr, size_t size);
118
119 size_t Read(lldb::addr_t addr, void *dst, size_t dst_len, Status &error);
120
121 /// Reads memory ranges, serving hits from the cache and batching misses
122 /// through Process::DoReadMemoryRanges. Matches Process::ReadMemoryRanges.
123 llvm::SmallVector<llvm::MutableArrayRef<uint8_t>>
124 ReadRanges(llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges,
125 llvm::MutableArrayRef<uint8_t> buffer);
126
127 uint32_t GetMemoryCacheLineSize() const {
128 return m_L2_cache.GetLineByteSize();
129 }
130
131 void AddInvalidRange(lldb::addr_t base_addr, lldb::addr_t byte_size);
132
133 bool RemoveInvalidRange(lldb::addr_t base_addr, lldb::addr_t byte_size);
134
135 /// Allow external sources to populate data into the memory cache.
136 void AddCacheData(lldb::addr_t addr, const void *src, size_t src_len);
137
138 void AddCacheData(lldb::addr_t addr, llvm::ArrayRef<uint8_t> src) {
139 if (!src.empty())
140 AddCacheData(addr, src.data(), src.size());
141 }
142
143 void AddCacheData(lldb::addr_t addr,
144 const lldb::DataBufferSP &data_buffer_sp);
145
146protected:
149 // Classes that inherit from MemoryCache can see and modify these
150 std::recursive_mutex m_mutex;
151 // L1 and L2 partition the cache. An address is held by at most one. L2
152 // holds whole, aligned lines; L1 holds smaller, non-overlapping pieces.
153 ChunkCache m_L1_cache; // Chunks smaller than a cache line.
154 LineCache m_L2_cache; // Whole cache lines.
157
158private:
159 MemoryCache(const MemoryCache &) = delete;
160 const MemoryCache &operator=(const MemoryCache &) = delete;
161
162 // Add a whole cache line to L2 and drop the L1 entries it supersedes.
163 // Caller must hold m_mutex.
164 void InsertWholeLine(lldb::addr_t line_base_addr,
165 llvm::ArrayRef<uint8_t> src);
166
167 // Add the bytes of [addr, addr+src.size()) that no entry holds yet to L1.
168 // The range must lie within one cache line. Caller must hold m_mutex.
169 void InsertPartialLine(lldb::addr_t addr, llvm::ArrayRef<uint8_t> src);
170
171 // Split [addr, addr+src.size()) at cache line boundaries: whole lines to L2,
172 // shorter pieces to L1. Takes m_mutex.
173 void InsertData(lldb::addr_t addr, llvm::ArrayRef<uint8_t> src);
174
175 // Copy the cached bytes of [addr, addr+len), stopping at the first miss,
176 // and return the count. Never reads from the inferior; caller holds m_mutex.
177 size_t ReadFromCaches(lldb::addr_t addr, void *dst, size_t len) const;
178
179 // Returns the range to fetch from the inferior for a read of
180 // [read_addr, caller_end), where the caches already supplied bytes_filled
181 // bytes immediately below read_addr. Caller must hold m_mutex.
182 AddrRange GrowReadRange(lldb::addr_t read_addr, lldb::addr_t caller_end,
183 size_t bytes_filled) const;
184};
185
186
187
189public:
190 AllocatedBlock(lldb::addr_t addr, uint32_t byte_size, uint32_t permissions,
191 uint32_t chunk_size);
192
194
195 lldb::addr_t ReserveBlock(uint32_t size);
196
197 bool FreeBlock(lldb::addr_t addr);
198
199 lldb::addr_t GetBaseAddress() const { return m_range.GetRangeBase(); }
200
201 uint32_t GetByteSize() const { return m_range.GetByteSize(); }
202
203 uint32_t GetPermissions() const { return m_permissions; }
204
205 uint32_t GetChunkSize() const { return m_chunk_size; }
206
207 bool Contains(lldb::addr_t addr) const {
208 return m_range.Contains(addr);
209 }
210
211protected:
212 uint32_t TotalChunks() const { return GetByteSize() / GetChunkSize(); }
213
214 uint32_t CalculateChunksNeededForSize(uint32_t size) const {
215 return (size + m_chunk_size - 1) / m_chunk_size;
216 }
217 // Base address of this block of memory 4GB of chunk should be enough.
219 // Permissions for this memory (logical OR of lldb::Permissions bits)
220 const uint32_t m_permissions;
221 // The size of chunks that the memory at m_addr is divied up into.
222 const uint32_t m_chunk_size;
223 // A sorted list of free address ranges.
225 // A sorted list of reserved address.
227};
228
229// A class that can track allocated memory and give out allocated memory
230// without us having to make an allocate/deallocate call every time we need
231// some memory in a process that is being debugged.
233public:
234 // Constructors and Destructors
236
238
239 void Clear(bool deallocate_memory);
240
241 lldb::addr_t AllocateMemory(size_t byte_size, uint32_t permissions,
242 Status &error);
243
245
246 bool IsInCache(lldb::addr_t addr) const;
247
248protected:
249 typedef std::shared_ptr<AllocatedBlock> AllocatedBlockSP;
250
251 AllocatedBlockSP AllocatePage(uint32_t byte_size, uint32_t permissions,
252 uint32_t chunk_size, Status &error);
253
254 // Classes that inherit from MemoryCache can see and modify these
256 mutable std::recursive_mutex m_mutex;
257 typedef std::multimap<uint32_t, AllocatedBlockSP> PermissionsToBlockMap;
259
260private:
263};
264
265} // namespace lldb_private
266
267#endif // LLDB_TARGET_MEMORY_H
static llvm::raw_ostream & error(Stream &strm)
uint32_t CalculateChunksNeededForSize(uint32_t size) const
Definition Memory.h:214
bool FreeBlock(lldb::addr_t addr)
Definition Memory.cpp:460
uint32_t GetPermissions() const
Definition Memory.h:203
lldb::addr_t GetBaseAddress() const
Definition Memory.h:199
lldb::addr_t ReserveBlock(uint32_t size)
Definition Memory.cpp:408
const uint32_t m_permissions
Definition Memory.h:220
Range< lldb::addr_t, uint32_t > m_range
Definition Memory.h:218
AllocatedBlock(lldb::addr_t addr, uint32_t byte_size, uint32_t permissions, uint32_t chunk_size)
Definition Memory.cpp:396
RangeVector< lldb::addr_t, uint32_t > m_free_blocks
Definition Memory.h:224
uint32_t TotalChunks() const
Definition Memory.h:212
RangeVector< lldb::addr_t, uint32_t > m_reserved_blocks
Definition Memory.h:226
uint32_t GetChunkSize() const
Definition Memory.h:205
const uint32_t m_chunk_size
Definition Memory.h:222
uint32_t GetByteSize() const
Definition Memory.h:201
bool Contains(lldb::addr_t addr) const
Definition Memory.h:207
lldb::addr_t AllocateMemory(size_t byte_size, uint32_t permissions, Status &error)
Definition Memory.cpp:514
bool IsInCache(lldb::addr_t addr) const
Definition Memory.cpp:564
std::multimap< uint32_t, AllocatedBlockSP > PermissionsToBlockMap
Definition Memory.h:257
const AllocatedMemoryCache & operator=(const AllocatedMemoryCache &)=delete
AllocatedMemoryCache(Process &process)
Definition Memory.cpp:474
std::recursive_mutex m_mutex
Definition Memory.h:256
void Clear(bool deallocate_memory)
Definition Memory.cpp:479
bool DeallocateMemory(lldb::addr_t ptr)
Definition Memory.cpp:545
std::shared_ptr< AllocatedBlock > AllocatedBlockSP
Definition Memory.h:249
PermissionsToBlockMap m_memory_map
Definition Memory.h:258
AllocatedMemoryCache(const AllocatedMemoryCache &)=delete
AllocatedBlockSP AllocatePage(uint32_t byte_size, uint32_t permissions, uint32_t chunk_size, Status &error)
Definition Memory.cpp:490
A set of non-overlapping byte ranges at arbitrary addresses.
Definition Memory.h:72
const_iterator begin() const
Definition Memory.h:95
llvm::ArrayRef< uint8_t > Lookup(lldb::addr_t addr) const
The cached bytes from addr to the end of the chunk holding it, empty if no chunk holds it.
Definition Memory.cpp:68
size_t GetSize() const
Definition Memory.h:91
Collection::const_iterator FindChunkContaining(lldb::addr_t addr) const
The chunk holding addr, or end().
Definition Memory.cpp:58
std::map< lldb::addr_t, std::vector< uint8_t > > Collection
Definition Memory.h:73
Collection::const_iterator const_iterator
Iteration yields a chunk's start address and its bytes, in address order.
Definition Memory.h:94
const_iterator end() const
Definition Memory.h:96
bool Holds(lldb::addr_t addr) const
Definition Memory.h:80
void EraseRange(lldb::addr_t addr, lldb::addr_t size)
Drop every chunk that intersects [addr, addr+size).
Definition Memory.cpp:99
void InsertMissing(lldb::addr_t addr, llvm::ArrayRef< uint8_t > src)
Add the bytes of [addr, addr+src.size()) that no chunk holds yet.
Definition Memory.cpp:75
A set of cache entries, all of which are aligned and have the same size.
Definition Memory.h:26
const_iterator end() const
Definition Memory.h:61
uint64_t IndexOf(lldb::addr_t addr) const
Definition Memory.h:64
void Clear(uint32_t new_line_byte_size)
Definition Memory.h:51
llvm::DenseMap< uint64_t, std::unique_ptr< uint8_t[]> > Collection
Keyed by line index, so a key names a whole line.
Definition Memory.h:28
Collection::const_iterator const_iterator
Iteration yields a line index and its bytes, in unspecified order.
Definition Memory.h:59
uint32_t GetLineByteSize() const
Definition Memory.h:34
uint32_t m_line_byte_size
Definition Memory.h:67
llvm::ArrayRef< uint8_t > Lookup(lldb::addr_t addr) const
The cached bytes from addr to the end of the line holding it, empty if that line is not resident.
Definition Memory.cpp:27
void Insert(lldb::addr_t addr, llvm::ArrayRef< uint8_t > src)
Add one whole line.
Definition Memory.cpp:36
Collection m_lines
Definition Memory.h:66
size_t GetSize() const
Definition Memory.h:56
const_iterator begin() const
Definition Memory.h:60
void EraseRange(lldb::addr_t addr, lldb::addr_t size)
Drop every line that intersects [addr, addr+size).
Definition Memory.cpp:46
LineCache(uint32_t line_byte_size)
Definition Memory.h:31
bool Holds(lldb::addr_t addr) const
Definition Memory.h:40
uint32_t GetMemoryCacheLineSize() const
Definition Memory.h:127
MemoryCache(Process &process)
Definition Memory.cpp:116
std::recursive_mutex m_mutex
Definition Memory.h:150
void AddCacheData(lldb::addr_t addr, const void *src, size_t src_len)
Allow external sources to populate data into the memory cache.
Definition Memory.cpp:131
bool RemoveInvalidRange(lldb::addr_t base_addr, lldb::addr_t byte_size)
Definition Memory.cpp:210
void Flush(lldb::addr_t addr, size_t size)
Definition Memory.cpp:190
void InsertWholeLine(lldb::addr_t line_base_addr, llvm::ArrayRef< uint8_t > src)
Definition Memory.cpp:136
llvm::SmallVector< llvm::MutableArrayRef< uint8_t > > ReadRanges(llvm::ArrayRef< Range< lldb::addr_t, size_t > > ranges, llvm::MutableArrayRef< uint8_t > buffer)
Reads memory ranges, serving hits from the cache and batching misses through Process::DoReadMemoryRan...
Definition Memory.cpp:338
InvalidRanges m_invalid_ranges
Definition Memory.h:155
void InsertPartialLine(lldb::addr_t addr, llvm::ArrayRef< uint8_t > src)
Definition Memory.cpp:143
void Clear(bool clear_invalid_ranges=false)
Definition Memory.cpp:123
RangeVector< lldb::addr_t, lldb::addr_t, 4 > InvalidRanges
Definition Memory.h:147
size_t ReadFromCaches(lldb::addr_t addr, void *dst, size_t len) const
Definition Memory.cpp:225
void InsertData(lldb::addr_t addr, llvm::ArrayRef< uint8_t > src)
Definition Memory.cpp:155
MemoryCache(const MemoryCache &)=delete
void AddCacheData(lldb::addr_t addr, llvm::ArrayRef< uint8_t > src)
Definition Memory.h:138
AddrRange GrowReadRange(lldb::addr_t read_addr, lldb::addr_t caller_end, size_t bytes_filled) const
Definition Memory.cpp:250
size_t Read(lldb::addr_t addr, void *dst, size_t dst_len, Status &error)
Definition Memory.cpp:290
void AddInvalidRange(lldb::addr_t base_addr, lldb::addr_t byte_size)
Definition Memory.cpp:200
const MemoryCache & operator=(const MemoryCache &)=delete
Range< lldb::addr_t, lldb::addr_t > AddrRange
Definition Memory.h:148
A plug-in interface definition class for debugging a process.
Definition Process.h:368
An error handling class.
Definition Status.h:118
A class that represents a running process on the host machine.
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
uint64_t addr_t
Definition lldb-types.h:80