25 : m_mutex(), m_L1_cache(), m_L2_cache(), m_invalid_ranges(),
27 m_L2_cache_line_byte_size(process.GetMemoryCacheLineSize()) {}
33 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
36 if (clear_invalid_ranges)
49 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
57 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
62 BlockMap::iterator pos =
m_L1_cache.upper_bound(addr);
67 AddrRange chunk_range(pos->first, pos->second->GetByteSize());
76 const addr_t end_addr = (addr + size - 1);
77 const addr_t first_cache_line_addr = addr - (addr % cache_line_byte_size);
78 const addr_t last_cache_line_addr =
79 end_addr - (end_addr % cache_line_byte_size);
82 uint32_t num_cache_lines;
83 if (last_cache_line_addr >= first_cache_line_addr)
84 num_cache_lines = ((last_cache_line_addr - first_cache_line_addr) /
85 cache_line_byte_size) +
89 (
UINT64_MAX - first_cache_line_addr + 1) / cache_line_byte_size;
91 uint32_t cache_idx = 0;
92 for (
addr_t curr_addr = first_cache_line_addr; cache_idx < num_cache_lines;
93 curr_addr += cache_line_byte_size, ++cache_idx) {
94 BlockMap::iterator pos =
m_L2_cache.find(curr_addr);
104 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
114 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
131 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
136 auto data_buffer_heap_sp =
139 line_base_addr, data_buffer_heap_sp->GetBytes(),
140 data_buffer_heap_sp->GetByteSize(),
error);
143 if (process_bytes_read == 0)
148 data_buffer_heap_sp->SetByteSize(process_bytes_read);
150 m_L2_cache[line_base_addr] = data_buffer_heap_sp;
151 return data_buffer_heap_sp;
156 if (!dst || dst_len == 0)
159 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
168 "memory read failed for 0x%" PRIx64, addr);
178 BlockMap::iterator pos =
m_L1_cache.upper_bound(addr);
182 AddrRange chunk_range(pos->first, pos->second->GetByteSize());
183 if (chunk_range.
Contains(read_range)) {
184 memcpy(dst, pos->second->GetBytes() + (addr - chunk_range.
GetRangeBase()),
208 addr_t cache_line_base_addr = addr - cache_line_offset;
212 if (!first_cache_line)
217 if (cache_line_offset >= first_cache_line->GetByteSize())
220 uint8_t *dst_buf = (uint8_t *)dst;
221 size_t bytes_left = dst_len;
222 size_t read_size = first_cache_line->GetByteSize() - cache_line_offset;
223 if (read_size > bytes_left)
224 read_size = bytes_left;
226 memcpy(dst_buf + dst_len - bytes_left,
227 first_cache_line->GetBytes() + cache_line_offset, read_size);
228 bytes_left -= read_size;
234 return dst_len - bytes_left;
237 if (bytes_left > 0) {
245 "memory read failed for 0x%" PRIx64, cache_line_base_addr);
246 return dst_len - bytes_left;
251 if (!second_cache_line)
252 return dst_len - bytes_left;
254 read_size = bytes_left;
255 if (read_size > second_cache_line->GetByteSize())
256 read_size = second_cache_line->GetByteSize();
258 memcpy(dst_buf + dst_len - bytes_left, second_cache_line->GetBytes(),
260 bytes_left -= read_size;
262 return dst_len - bytes_left;
269 uint32_t permissions, uint32_t chunk_size)
270 : m_range(addr, byte_size), m_permissions(permissions),
271 m_chunk_size(chunk_size)
275 assert(byte_size > chunk_size);
287 for (
size_t i=0; i<free_count; ++i)
291 if (range_size >= size)
296 addr_t addr = free_block.GetRangeBase();
318 free_block.SetRangeBase(reserved_block.
GetRangeEnd());
319 free_block.SetByteSize(bytes_left);
321 LLDB_LOGV(log,
"({0}) (size = {1} ({1:x})) => {2:x}",
this, size, addr);
326 LLDB_LOGV(log,
"({0}) (size = {1} ({1:x})) => {2:x}",
this, size,
332 bool success =
false;
341 LLDB_LOGV(log,
"({0}) (addr = {1:x}) => {2}",
this, addr, success);
346 : m_process(process), m_mutex(), m_memory_map() {}
351 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
353 PermissionsToBlockMap::iterator pos, end =
m_memory_map.end();
364 const size_t page_size = 4096;
365 const size_t num_pages = (byte_size + page_size - 1) / page_size;
366 const size_t page_byte_size = num_pages * page_size;
373 "Process::DoAllocateMemory (byte_size = 0x%8.8" PRIx32
374 ", permissions = %s) => 0x%16.16" PRIx64,
380 block_sp = std::make_shared<AllocatedBlock>(addr, page_byte_size,
381 permissions, chunk_size);
382 m_memory_map.insert(std::make_pair(permissions, block_sp));
388 uint32_t permissions,
390 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
393 std::pair<PermissionsToBlockMap::iterator, PermissionsToBlockMap::iterator>
396 for (PermissionsToBlockMap::iterator pos = range.first; pos != range.second;
398 addr = (*pos).second->ReserveBlock(byte_size);
407 addr = block_sp->ReserveBlock(byte_size);
411 "AllocatedMemoryCache::AllocateMemory (byte_size = 0x%8.8" PRIx32
412 ", permissions = %s) => 0x%16.16" PRIx64,
419 std::lock_guard<std::recursive_mutex> guard(
m_mutex);
421 PermissionsToBlockMap::iterator pos, end =
m_memory_map.end();
422 bool success =
false;
424 if (pos->second->Contains(addr)) {
425 success = pos->second->FreeBlock(addr);
431 "AllocatedMemoryCache::DeallocateMemory (addr = 0x%16.16" PRIx64
433 (uint64_t)addr, success);
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
#define LLDB_LOGV(log,...)
uint32_t CalculateChunksNeededForSize(uint32_t size) const
bool FreeBlock(lldb::addr_t addr)
lldb::addr_t ReserveBlock(uint32_t size)
Range< lldb::addr_t, uint32_t > m_range
AllocatedBlock(lldb::addr_t addr, uint32_t byte_size, uint32_t permissions, uint32_t chunk_size)
RangeVector< lldb::addr_t, uint32_t > m_free_blocks
RangeVector< lldb::addr_t, uint32_t > m_reserved_blocks
const uint32_t m_chunk_size
lldb::addr_t AllocateMemory(size_t byte_size, uint32_t permissions, Status &error)
AllocatedMemoryCache(Process &process)
std::recursive_mutex m_mutex
void Clear(bool deallocate_memory)
bool DeallocateMemory(lldb::addr_t ptr)
std::shared_ptr< AllocatedBlock > AllocatedBlockSP
PermissionsToBlockMap m_memory_map
AllocatedBlockSP AllocatePage(uint32_t byte_size, uint32_t permissions, uint32_t chunk_size, Status &error)
A subclass of DataBuffer that stores a data buffer on the heap.
MemoryCache(Process &process)
std::recursive_mutex m_mutex
bool RemoveInvalidRange(lldb::addr_t base_addr, lldb::addr_t byte_size)
void Flush(lldb::addr_t addr, size_t size)
void AddL1CacheData(lldb::addr_t addr, const void *src, size_t src_len)
InvalidRanges m_invalid_ranges
void Clear(bool clear_invalid_ranges=false)
size_t Read(lldb::addr_t addr, void *dst, size_t dst_len, Status &error)
void AddInvalidRange(lldb::addr_t base_addr, lldb::addr_t byte_size)
lldb::DataBufferSP GetL2CacheLine(lldb::addr_t addr, Status &error)
uint32_t m_L2_cache_line_byte_size
uint64_t GetMemoryCacheLineSize() const
A plug-in interface definition class for debugging a process.
size_t ReadMemoryFromInferior(lldb::addr_t vm_addr, void *buf, size_t size, Status &error)
Read of memory from a process.
virtual bool IsAlive()
Check if a process is still alive.
virtual Status DoDeallocateMemory(lldb::addr_t ptr)
Actually deallocate memory in the process.
virtual lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions, Status &error)
Actually allocate memory in the process.
const Entry * FindEntryThatContains(B addr) const
uint32_t FindEntryIndexThatContains(B addr) const
const Entry * GetEntryAtIndex(size_t i) const
Entry & GetEntryRef(size_t i)
bool RemoveEntryAtIndex(uint32_t idx)
void Append(const Entry &entry)
void Insert(const Entry &entry, bool combine)
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
#define LLDB_INVALID_ADDRESS
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
const char * GetPermissionsAsCString(uint32_t permissions)
std::shared_ptr< lldb_private::DataBuffer > DataBufferSP
bool Contains(BaseType r) const
BaseType GetRangeBase() const
SizeType GetByteSize() const
BaseType GetRangeEnd() const
bool DoesIntersect(const Range &rhs) const
void SetByteSize(SizeType s)