1d495c534SGreg Clayton //===-- Memory.cpp ----------------------------------------------*- C++ -*-===// 2d495c534SGreg Clayton // 3d495c534SGreg Clayton // The LLVM Compiler Infrastructure 4d495c534SGreg Clayton // 5d495c534SGreg Clayton // This file is distributed under the University of Illinois Open Source 6d495c534SGreg Clayton // License. See LICENSE.TXT for details. 7d495c534SGreg Clayton // 8d495c534SGreg Clayton //===----------------------------------------------------------------------===// 9d495c534SGreg Clayton 10d495c534SGreg Clayton #include "lldb/Target/Memory.h" 11d495c534SGreg Clayton // C Includes 12ffeba256SVirgile Bello #include <inttypes.h> 13d495c534SGreg Clayton // C++ Includes 14d495c534SGreg Clayton // Other libraries and framework includes 15d495c534SGreg Clayton // Project includes 16d495c534SGreg Clayton #include "lldb/Core/DataBufferHeap.h" 17d495c534SGreg Clayton #include "lldb/Core/State.h" 18d495c534SGreg Clayton #include "lldb/Core/Log.h" 19d495c534SGreg Clayton #include "lldb/Target/Process.h" 20d495c534SGreg Clayton 21d495c534SGreg Clayton using namespace lldb; 22d495c534SGreg Clayton using namespace lldb_private; 23d495c534SGreg Clayton 24d495c534SGreg Clayton //---------------------------------------------------------------------- 25d495c534SGreg Clayton // MemoryCache constructor 26d495c534SGreg Clayton //---------------------------------------------------------------------- 27d495c534SGreg Clayton MemoryCache::MemoryCache(Process &process) : 28d495c534SGreg Clayton m_process (process), 29d495c534SGreg Clayton m_cache_line_byte_size (512), 30a9f40ad8SGreg Clayton m_mutex (Mutex::eMutexTypeRecursive), 31a9f40ad8SGreg Clayton m_cache (), 32a9f40ad8SGreg Clayton m_invalid_ranges () 33d495c534SGreg Clayton { 34d495c534SGreg Clayton } 35d495c534SGreg Clayton 36d495c534SGreg Clayton //---------------------------------------------------------------------- 37d495c534SGreg Clayton // Destructor 38d495c534SGreg Clayton //---------------------------------------------------------------------- 39d495c534SGreg Clayton MemoryCache::~MemoryCache() 40d495c534SGreg Clayton { 41d495c534SGreg Clayton } 42d495c534SGreg Clayton 43d495c534SGreg Clayton void 4415fc2be7SGreg Clayton MemoryCache::Clear(bool clear_invalid_ranges) 45d495c534SGreg Clayton { 46a9f40ad8SGreg Clayton Mutex::Locker locker (m_mutex); 47d495c534SGreg Clayton m_cache.clear(); 4815fc2be7SGreg Clayton if (clear_invalid_ranges) 4915fc2be7SGreg Clayton m_invalid_ranges.Clear(); 50d495c534SGreg Clayton } 51d495c534SGreg Clayton 52d495c534SGreg Clayton void 53d495c534SGreg Clayton MemoryCache::Flush (addr_t addr, size_t size) 54d495c534SGreg Clayton { 55d495c534SGreg Clayton if (size == 0) 56d495c534SGreg Clayton return; 57d495c534SGreg Clayton 58a9f40ad8SGreg Clayton Mutex::Locker locker (m_mutex); 59d495c534SGreg Clayton if (m_cache.empty()) 60d495c534SGreg Clayton return; 61d495c534SGreg Clayton 62de0e9d04SGreg Clayton const uint32_t cache_line_byte_size = m_cache_line_byte_size; 63de0e9d04SGreg Clayton const addr_t end_addr = (addr + size - 1); 64de0e9d04SGreg Clayton const addr_t first_cache_line_addr = addr - (addr % cache_line_byte_size); 65de0e9d04SGreg Clayton const addr_t last_cache_line_addr = end_addr - (end_addr % cache_line_byte_size); 66de0e9d04SGreg Clayton // Watch for overflow where size will cause us to go off the end of the 67de0e9d04SGreg Clayton // 64 bit address space 68de0e9d04SGreg Clayton uint32_t num_cache_lines; 69de0e9d04SGreg Clayton if (last_cache_line_addr >= first_cache_line_addr) 70de0e9d04SGreg Clayton num_cache_lines = ((last_cache_line_addr - first_cache_line_addr)/cache_line_byte_size) + 1; 71de0e9d04SGreg Clayton else 72de0e9d04SGreg Clayton num_cache_lines = (UINT64_MAX - first_cache_line_addr + 1)/cache_line_byte_size; 73d495c534SGreg Clayton 74de0e9d04SGreg Clayton uint32_t cache_idx = 0; 75de0e9d04SGreg Clayton for (addr_t curr_addr = first_cache_line_addr; 76de0e9d04SGreg Clayton cache_idx < num_cache_lines; 77de0e9d04SGreg Clayton curr_addr += cache_line_byte_size, ++cache_idx) 78d495c534SGreg Clayton { 79a9f40ad8SGreg Clayton BlockMap::iterator pos = m_cache.find (curr_addr); 80d495c534SGreg Clayton if (pos != m_cache.end()) 81d495c534SGreg Clayton m_cache.erase(pos); 82d495c534SGreg Clayton } 83d495c534SGreg Clayton } 84d495c534SGreg Clayton 85a9f40ad8SGreg Clayton void 86a9f40ad8SGreg Clayton MemoryCache::AddInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size) 87a9f40ad8SGreg Clayton { 88a9f40ad8SGreg Clayton if (byte_size > 0) 89a9f40ad8SGreg Clayton { 90a9f40ad8SGreg Clayton Mutex::Locker locker (m_mutex); 91a9f40ad8SGreg Clayton InvalidRanges::Entry range (base_addr, byte_size); 92a9f40ad8SGreg Clayton m_invalid_ranges.Append(range); 93a9f40ad8SGreg Clayton m_invalid_ranges.Sort(); 94a9f40ad8SGreg Clayton } 95a9f40ad8SGreg Clayton } 96a9f40ad8SGreg Clayton 97a9f40ad8SGreg Clayton bool 98a9f40ad8SGreg Clayton MemoryCache::RemoveInvalidRange (lldb::addr_t base_addr, lldb::addr_t byte_size) 99a9f40ad8SGreg Clayton { 100a9f40ad8SGreg Clayton if (byte_size > 0) 101a9f40ad8SGreg Clayton { 102a9f40ad8SGreg Clayton Mutex::Locker locker (m_mutex); 103a9f40ad8SGreg Clayton const uint32_t idx = m_invalid_ranges.FindEntryIndexThatContains(base_addr); 104a9f40ad8SGreg Clayton if (idx != UINT32_MAX) 105a9f40ad8SGreg Clayton { 106a9f40ad8SGreg Clayton const InvalidRanges::Entry *entry = m_invalid_ranges.GetEntryAtIndex (idx); 107a9f40ad8SGreg Clayton if (entry->GetRangeBase() == base_addr && entry->GetByteSize() == byte_size) 108a9f40ad8SGreg Clayton return m_invalid_ranges.RemoveEntrtAtIndex (idx); 109a9f40ad8SGreg Clayton } 110a9f40ad8SGreg Clayton } 111a9f40ad8SGreg Clayton return false; 112a9f40ad8SGreg Clayton } 113a9f40ad8SGreg Clayton 114a9f40ad8SGreg Clayton 115a9f40ad8SGreg Clayton 116d495c534SGreg Clayton size_t 117d495c534SGreg Clayton MemoryCache::Read (addr_t addr, 118d495c534SGreg Clayton void *dst, 119d495c534SGreg Clayton size_t dst_len, 120d495c534SGreg Clayton Error &error) 121d495c534SGreg Clayton { 122d495c534SGreg Clayton size_t bytes_left = dst_len; 123*6076bf4eSJason Molenda 124*6076bf4eSJason Molenda // If this memory read request is larger than the cache line size, then 125*6076bf4eSJason Molenda // we (1) try to read as much of it at once as possible, and (2) don't 126*6076bf4eSJason Molenda // add the data to the memory cache. We don't want to split a big read 127*6076bf4eSJason Molenda // up into more separate reads than necessary, and with a large memory read 128*6076bf4eSJason Molenda // request, it is unlikely that the caller function will ask for the next 129*6076bf4eSJason Molenda // 4 bytes after the large memory read - so there's little benefit to saving 130*6076bf4eSJason Molenda // it in the cache. 131*6076bf4eSJason Molenda if (dst && dst_len > m_cache_line_byte_size) 132*6076bf4eSJason Molenda { 133*6076bf4eSJason Molenda return m_process.ReadMemoryFromInferior (addr, dst, dst_len, error); 134*6076bf4eSJason Molenda } 135*6076bf4eSJason Molenda 136d495c534SGreg Clayton if (dst && bytes_left > 0) 137d495c534SGreg Clayton { 138d495c534SGreg Clayton const uint32_t cache_line_byte_size = m_cache_line_byte_size; 139d495c534SGreg Clayton uint8_t *dst_buf = (uint8_t *)dst; 140d495c534SGreg Clayton addr_t curr_addr = addr - (addr % cache_line_byte_size); 141d495c534SGreg Clayton addr_t cache_offset = addr - curr_addr; 142a9f40ad8SGreg Clayton Mutex::Locker locker (m_mutex); 143d495c534SGreg Clayton 144d495c534SGreg Clayton while (bytes_left > 0) 145d495c534SGreg Clayton { 146a9f40ad8SGreg Clayton if (m_invalid_ranges.FindEntryThatContains(curr_addr)) 14755d24311SJim Ingham { 14855d24311SJim Ingham error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, curr_addr); 149a9f40ad8SGreg Clayton return dst_len - bytes_left; 15055d24311SJim Ingham } 151a9f40ad8SGreg Clayton 152a9f40ad8SGreg Clayton BlockMap::const_iterator pos = m_cache.find (curr_addr); 153a9f40ad8SGreg Clayton BlockMap::const_iterator end = m_cache.end (); 154d495c534SGreg Clayton 155d495c534SGreg Clayton if (pos != end) 156d495c534SGreg Clayton { 157d495c534SGreg Clayton size_t curr_read_size = cache_line_byte_size - cache_offset; 158d495c534SGreg Clayton if (curr_read_size > bytes_left) 159d495c534SGreg Clayton curr_read_size = bytes_left; 160d495c534SGreg Clayton 161d495c534SGreg Clayton memcpy (dst_buf + dst_len - bytes_left, pos->second->GetBytes() + cache_offset, curr_read_size); 162d495c534SGreg Clayton 163d495c534SGreg Clayton bytes_left -= curr_read_size; 164d495c534SGreg Clayton curr_addr += curr_read_size + cache_offset; 165d495c534SGreg Clayton cache_offset = 0; 166d495c534SGreg Clayton 167d495c534SGreg Clayton if (bytes_left > 0) 168d495c534SGreg Clayton { 169d495c534SGreg Clayton // Get sequential cache page hits 170d495c534SGreg Clayton for (++pos; (pos != end) && (bytes_left > 0); ++pos) 171d495c534SGreg Clayton { 172d495c534SGreg Clayton assert ((curr_addr % cache_line_byte_size) == 0); 173d495c534SGreg Clayton 174d495c534SGreg Clayton if (pos->first != curr_addr) 175d495c534SGreg Clayton break; 176d495c534SGreg Clayton 177d495c534SGreg Clayton curr_read_size = pos->second->GetByteSize(); 178d495c534SGreg Clayton if (curr_read_size > bytes_left) 179d495c534SGreg Clayton curr_read_size = bytes_left; 180d495c534SGreg Clayton 181d495c534SGreg Clayton memcpy (dst_buf + dst_len - bytes_left, pos->second->GetBytes(), curr_read_size); 182d495c534SGreg Clayton 183d495c534SGreg Clayton bytes_left -= curr_read_size; 184d495c534SGreg Clayton curr_addr += curr_read_size; 185d495c534SGreg Clayton 186d495c534SGreg Clayton // We have a cache page that succeeded to read some bytes 187d495c534SGreg Clayton // but not an entire page. If this happens, we must cap 188d495c534SGreg Clayton // off how much data we are able to read... 189d495c534SGreg Clayton if (pos->second->GetByteSize() != cache_line_byte_size) 190d495c534SGreg Clayton return dst_len - bytes_left; 191d495c534SGreg Clayton } 192d495c534SGreg Clayton } 193d495c534SGreg Clayton } 194d495c534SGreg Clayton 195d495c534SGreg Clayton // We need to read from the process 196d495c534SGreg Clayton 197d495c534SGreg Clayton if (bytes_left > 0) 198d495c534SGreg Clayton { 199d495c534SGreg Clayton assert ((curr_addr % cache_line_byte_size) == 0); 2007b0992d9SGreg Clayton std::unique_ptr<DataBufferHeap> data_buffer_heap_ap(new DataBufferHeap (cache_line_byte_size, 0)); 201d495c534SGreg Clayton size_t process_bytes_read = m_process.ReadMemoryFromInferior (curr_addr, 202d495c534SGreg Clayton data_buffer_heap_ap->GetBytes(), 203d495c534SGreg Clayton data_buffer_heap_ap->GetByteSize(), 204d495c534SGreg Clayton error); 205d495c534SGreg Clayton if (process_bytes_read == 0) 206d495c534SGreg Clayton return dst_len - bytes_left; 207d495c534SGreg Clayton 208d495c534SGreg Clayton if (process_bytes_read != cache_line_byte_size) 209d495c534SGreg Clayton data_buffer_heap_ap->SetByteSize (process_bytes_read); 210d495c534SGreg Clayton m_cache[curr_addr] = DataBufferSP (data_buffer_heap_ap.release()); 211d495c534SGreg Clayton // We have read data and put it into the cache, continue through the 212d495c534SGreg Clayton // loop again to get the data out of the cache... 213d495c534SGreg Clayton } 214d495c534SGreg Clayton } 215d495c534SGreg Clayton } 216d495c534SGreg Clayton 217d495c534SGreg Clayton return dst_len - bytes_left; 218d495c534SGreg Clayton } 219d495c534SGreg Clayton 220d495c534SGreg Clayton 221d495c534SGreg Clayton 222d495c534SGreg Clayton AllocatedBlock::AllocatedBlock (lldb::addr_t addr, 223d495c534SGreg Clayton uint32_t byte_size, 224d495c534SGreg Clayton uint32_t permissions, 225d495c534SGreg Clayton uint32_t chunk_size) : 226d495c534SGreg Clayton m_addr (addr), 227d495c534SGreg Clayton m_byte_size (byte_size), 228d495c534SGreg Clayton m_permissions (permissions), 229d495c534SGreg Clayton m_chunk_size (chunk_size), 230d495c534SGreg Clayton m_offset_to_chunk_size () 231d495c534SGreg Clayton // m_allocated (byte_size / chunk_size) 232d495c534SGreg Clayton { 233d495c534SGreg Clayton assert (byte_size > chunk_size); 234d495c534SGreg Clayton } 235d495c534SGreg Clayton 236d495c534SGreg Clayton AllocatedBlock::~AllocatedBlock () 237d495c534SGreg Clayton { 238d495c534SGreg Clayton } 239d495c534SGreg Clayton 240d495c534SGreg Clayton lldb::addr_t 241d495c534SGreg Clayton AllocatedBlock::ReserveBlock (uint32_t size) 242d495c534SGreg Clayton { 243d495c534SGreg Clayton addr_t addr = LLDB_INVALID_ADDRESS; 244d495c534SGreg Clayton if (size <= m_byte_size) 245d495c534SGreg Clayton { 246d495c534SGreg Clayton const uint32_t needed_chunks = CalculateChunksNeededForSize (size); 2475160ce5cSGreg Clayton Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); 248d495c534SGreg Clayton 249d495c534SGreg Clayton if (m_offset_to_chunk_size.empty()) 250d495c534SGreg Clayton { 251d495c534SGreg Clayton m_offset_to_chunk_size[0] = needed_chunks; 252d495c534SGreg Clayton if (log) 253d495c534SGreg Clayton log->Printf ("[1] AllocatedBlock::ReserveBlock (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks", size, size, 0, needed_chunks, m_chunk_size); 254d495c534SGreg Clayton addr = m_addr; 255d495c534SGreg Clayton } 256d495c534SGreg Clayton else 257d495c534SGreg Clayton { 258d495c534SGreg Clayton uint32_t last_offset = 0; 259d495c534SGreg Clayton OffsetToChunkSize::const_iterator pos = m_offset_to_chunk_size.begin(); 260d495c534SGreg Clayton OffsetToChunkSize::const_iterator end = m_offset_to_chunk_size.end(); 261d495c534SGreg Clayton while (pos != end) 262d495c534SGreg Clayton { 263d495c534SGreg Clayton if (pos->first > last_offset) 264d495c534SGreg Clayton { 265d495c534SGreg Clayton const uint32_t bytes_available = pos->first - last_offset; 266d495c534SGreg Clayton const uint32_t num_chunks = CalculateChunksNeededForSize (bytes_available); 267d495c534SGreg Clayton if (num_chunks >= needed_chunks) 268d495c534SGreg Clayton { 269d495c534SGreg Clayton m_offset_to_chunk_size[last_offset] = needed_chunks; 270d495c534SGreg Clayton if (log) 271d495c534SGreg Clayton log->Printf ("[2] AllocatedBlock::ReserveBlock (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks", size, size, last_offset, needed_chunks, m_chunk_size); 272d495c534SGreg Clayton addr = m_addr + last_offset; 273d495c534SGreg Clayton break; 274d495c534SGreg Clayton } 275d495c534SGreg Clayton } 276d495c534SGreg Clayton 277d495c534SGreg Clayton last_offset = pos->first + pos->second * m_chunk_size; 278d495c534SGreg Clayton 279d495c534SGreg Clayton if (++pos == end) 280d495c534SGreg Clayton { 281d495c534SGreg Clayton // Last entry... 282d495c534SGreg Clayton const uint32_t chunks_left = CalculateChunksNeededForSize (m_byte_size - last_offset); 283d495c534SGreg Clayton if (chunks_left >= needed_chunks) 284d495c534SGreg Clayton { 285d495c534SGreg Clayton m_offset_to_chunk_size[last_offset] = needed_chunks; 286d495c534SGreg Clayton if (log) 287d495c534SGreg Clayton log->Printf ("[3] AllocatedBlock::ReserveBlock (size = %u (0x%x)) => offset = 0x%x, %u %u bit chunks", size, size, last_offset, needed_chunks, m_chunk_size); 288d495c534SGreg Clayton addr = m_addr + last_offset; 289d495c534SGreg Clayton break; 290d495c534SGreg Clayton } 291d495c534SGreg Clayton } 292d495c534SGreg Clayton } 293d495c534SGreg Clayton } 294d495c534SGreg Clayton // const uint32_t total_chunks = m_allocated.size (); 295d495c534SGreg Clayton // uint32_t unallocated_idx = 0; 296d495c534SGreg Clayton // uint32_t allocated_idx = m_allocated.find_first(); 297d495c534SGreg Clayton // uint32_t first_chunk_idx = UINT32_MAX; 298d495c534SGreg Clayton // uint32_t num_chunks; 299d495c534SGreg Clayton // while (1) 300d495c534SGreg Clayton // { 301d495c534SGreg Clayton // if (allocated_idx == UINT32_MAX) 302d495c534SGreg Clayton // { 303d495c534SGreg Clayton // // No more bits are set starting from unallocated_idx, so we 304d495c534SGreg Clayton // // either have enough chunks for the request, or we don't. 305d495c534SGreg Clayton // // Eiter way we break out of the while loop... 306d495c534SGreg Clayton // num_chunks = total_chunks - unallocated_idx; 307d495c534SGreg Clayton // if (needed_chunks <= num_chunks) 308d495c534SGreg Clayton // first_chunk_idx = unallocated_idx; 309d495c534SGreg Clayton // break; 310d495c534SGreg Clayton // } 311d495c534SGreg Clayton // else if (allocated_idx > unallocated_idx) 312d495c534SGreg Clayton // { 313d495c534SGreg Clayton // // We have some allocated chunks, check if there are enough 314d495c534SGreg Clayton // // free chunks to satisfy the request? 315d495c534SGreg Clayton // num_chunks = allocated_idx - unallocated_idx; 316d495c534SGreg Clayton // if (needed_chunks <= num_chunks) 317d495c534SGreg Clayton // { 318d495c534SGreg Clayton // // Yep, we have enough! 319d495c534SGreg Clayton // first_chunk_idx = unallocated_idx; 320d495c534SGreg Clayton // break; 321d495c534SGreg Clayton // } 322d495c534SGreg Clayton // } 323d495c534SGreg Clayton // 324d495c534SGreg Clayton // while (unallocated_idx < total_chunks) 325d495c534SGreg Clayton // { 326d495c534SGreg Clayton // if (m_allocated[unallocated_idx]) 327d495c534SGreg Clayton // ++unallocated_idx; 328d495c534SGreg Clayton // else 329d495c534SGreg Clayton // break; 330d495c534SGreg Clayton // } 331d495c534SGreg Clayton // 332d495c534SGreg Clayton // if (unallocated_idx >= total_chunks) 333d495c534SGreg Clayton // break; 334d495c534SGreg Clayton // 335d495c534SGreg Clayton // allocated_idx = m_allocated.find_next(unallocated_idx); 336d495c534SGreg Clayton // } 337d495c534SGreg Clayton // 338d495c534SGreg Clayton // if (first_chunk_idx != UINT32_MAX) 339d495c534SGreg Clayton // { 340d495c534SGreg Clayton // const uint32_t end_bit_idx = unallocated_idx + needed_chunks; 341d495c534SGreg Clayton // for (uint32_t idx = first_chunk_idx; idx < end_bit_idx; ++idx) 342d495c534SGreg Clayton // m_allocated.set(idx); 343d495c534SGreg Clayton // return m_addr + m_chunk_size * first_chunk_idx; 344d495c534SGreg Clayton // } 345d495c534SGreg Clayton } 3465160ce5cSGreg Clayton Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); 347d495c534SGreg Clayton if (log) 348d01b2953SDaniel Malea log->Printf ("AllocatedBlock::ReserveBlock (size = %u (0x%x)) => 0x%16.16" PRIx64, size, size, (uint64_t)addr); 349d495c534SGreg Clayton return addr; 350d495c534SGreg Clayton } 351d495c534SGreg Clayton 352d495c534SGreg Clayton bool 353d495c534SGreg Clayton AllocatedBlock::FreeBlock (addr_t addr) 354d495c534SGreg Clayton { 355d495c534SGreg Clayton uint32_t offset = addr - m_addr; 356d495c534SGreg Clayton OffsetToChunkSize::iterator pos = m_offset_to_chunk_size.find (offset); 357d495c534SGreg Clayton bool success = false; 358d495c534SGreg Clayton if (pos != m_offset_to_chunk_size.end()) 359d495c534SGreg Clayton { 360d495c534SGreg Clayton m_offset_to_chunk_size.erase (pos); 361d495c534SGreg Clayton success = true; 362d495c534SGreg Clayton } 3635160ce5cSGreg Clayton Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_VERBOSE)); 364d495c534SGreg Clayton if (log) 365d01b2953SDaniel Malea log->Printf ("AllocatedBlock::FreeBlock (addr = 0x%16.16" PRIx64 ") => %i", (uint64_t)addr, success); 366d495c534SGreg Clayton return success; 367d495c534SGreg Clayton } 368d495c534SGreg Clayton 369d495c534SGreg Clayton 370d495c534SGreg Clayton AllocatedMemoryCache::AllocatedMemoryCache (Process &process) : 371d495c534SGreg Clayton m_process (process), 372d495c534SGreg Clayton m_mutex (Mutex::eMutexTypeRecursive), 373d495c534SGreg Clayton m_memory_map() 374d495c534SGreg Clayton { 375d495c534SGreg Clayton } 376d495c534SGreg Clayton 377d495c534SGreg Clayton AllocatedMemoryCache::~AllocatedMemoryCache () 378d495c534SGreg Clayton { 379d495c534SGreg Clayton } 380d495c534SGreg Clayton 381d495c534SGreg Clayton 382d495c534SGreg Clayton void 383d495c534SGreg Clayton AllocatedMemoryCache::Clear() 384d495c534SGreg Clayton { 385d495c534SGreg Clayton Mutex::Locker locker (m_mutex); 386d495c534SGreg Clayton if (m_process.IsAlive()) 387d495c534SGreg Clayton { 388d495c534SGreg Clayton PermissionsToBlockMap::iterator pos, end = m_memory_map.end(); 389d495c534SGreg Clayton for (pos = m_memory_map.begin(); pos != end; ++pos) 390d495c534SGreg Clayton m_process.DoDeallocateMemory(pos->second->GetBaseAddress()); 391d495c534SGreg Clayton } 392d495c534SGreg Clayton m_memory_map.clear(); 393d495c534SGreg Clayton } 394d495c534SGreg Clayton 395d495c534SGreg Clayton 396d495c534SGreg Clayton AllocatedMemoryCache::AllocatedBlockSP 397d495c534SGreg Clayton AllocatedMemoryCache::AllocatePage (uint32_t byte_size, 398d495c534SGreg Clayton uint32_t permissions, 399d495c534SGreg Clayton uint32_t chunk_size, 400d495c534SGreg Clayton Error &error) 401d495c534SGreg Clayton { 402d495c534SGreg Clayton AllocatedBlockSP block_sp; 403d495c534SGreg Clayton const size_t page_size = 4096; 404d495c534SGreg Clayton const size_t num_pages = (byte_size + page_size - 1) / page_size; 405d495c534SGreg Clayton const size_t page_byte_size = num_pages * page_size; 406d495c534SGreg Clayton 407d495c534SGreg Clayton addr_t addr = m_process.DoAllocateMemory(page_byte_size, permissions, error); 408d495c534SGreg Clayton 4095160ce5cSGreg Clayton Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 410d495c534SGreg Clayton if (log) 411d495c534SGreg Clayton { 412ffeba256SVirgile Bello log->Printf ("Process::DoAllocateMemory (byte_size = 0x%8.8" PRIx32 ", permissions = %s) => 0x%16.16" PRIx64, 413ffeba256SVirgile Bello (uint32_t)page_byte_size, 414d495c534SGreg Clayton GetPermissionsAsCString(permissions), 415d495c534SGreg Clayton (uint64_t)addr); 416d495c534SGreg Clayton } 417d495c534SGreg Clayton 418d495c534SGreg Clayton if (addr != LLDB_INVALID_ADDRESS) 419d495c534SGreg Clayton { 420d495c534SGreg Clayton block_sp.reset (new AllocatedBlock (addr, page_byte_size, permissions, chunk_size)); 421d495c534SGreg Clayton m_memory_map.insert (std::make_pair (permissions, block_sp)); 422d495c534SGreg Clayton } 423d495c534SGreg Clayton return block_sp; 424d495c534SGreg Clayton } 425d495c534SGreg Clayton 426d495c534SGreg Clayton lldb::addr_t 427d495c534SGreg Clayton AllocatedMemoryCache::AllocateMemory (size_t byte_size, 428d495c534SGreg Clayton uint32_t permissions, 429d495c534SGreg Clayton Error &error) 430d495c534SGreg Clayton { 431d495c534SGreg Clayton Mutex::Locker locker (m_mutex); 432d495c534SGreg Clayton 433d495c534SGreg Clayton addr_t addr = LLDB_INVALID_ADDRESS; 434d495c534SGreg Clayton std::pair<PermissionsToBlockMap::iterator, PermissionsToBlockMap::iterator> range = m_memory_map.equal_range (permissions); 435d495c534SGreg Clayton 436d495c534SGreg Clayton for (PermissionsToBlockMap::iterator pos = range.first; pos != range.second; ++pos) 437d495c534SGreg Clayton { 438d495c534SGreg Clayton addr = (*pos).second->ReserveBlock (byte_size); 439d495c534SGreg Clayton } 440d495c534SGreg Clayton 441d495c534SGreg Clayton if (addr == LLDB_INVALID_ADDRESS) 442d495c534SGreg Clayton { 443d495c534SGreg Clayton AllocatedBlockSP block_sp (AllocatePage (byte_size, permissions, 16, error)); 444d495c534SGreg Clayton 445d495c534SGreg Clayton if (block_sp) 446d495c534SGreg Clayton addr = block_sp->ReserveBlock (byte_size); 447d495c534SGreg Clayton } 4485160ce5cSGreg Clayton Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 449d495c534SGreg Clayton if (log) 450ffeba256SVirgile Bello log->Printf ("AllocatedMemoryCache::AllocateMemory (byte_size = 0x%8.8" PRIx32 ", permissions = %s) => 0x%16.16" PRIx64, (uint32_t)byte_size, GetPermissionsAsCString(permissions), (uint64_t)addr); 451d495c534SGreg Clayton return addr; 452d495c534SGreg Clayton } 453d495c534SGreg Clayton 454d495c534SGreg Clayton bool 455d495c534SGreg Clayton AllocatedMemoryCache::DeallocateMemory (lldb::addr_t addr) 456d495c534SGreg Clayton { 457d495c534SGreg Clayton Mutex::Locker locker (m_mutex); 458d495c534SGreg Clayton 459d495c534SGreg Clayton PermissionsToBlockMap::iterator pos, end = m_memory_map.end(); 460d495c534SGreg Clayton bool success = false; 461d495c534SGreg Clayton for (pos = m_memory_map.begin(); pos != end; ++pos) 462d495c534SGreg Clayton { 463d495c534SGreg Clayton if (pos->second->Contains (addr)) 464d495c534SGreg Clayton { 465d495c534SGreg Clayton success = pos->second->FreeBlock (addr); 466d495c534SGreg Clayton break; 467d495c534SGreg Clayton } 468d495c534SGreg Clayton } 4695160ce5cSGreg Clayton Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); 470d495c534SGreg Clayton if (log) 471d01b2953SDaniel Malea log->Printf("AllocatedMemoryCache::DeallocateMemory (addr = 0x%16.16" PRIx64 ") => %i", (uint64_t)addr, success); 472d495c534SGreg Clayton return success; 473d495c534SGreg Clayton } 474d495c534SGreg Clayton 475d495c534SGreg Clayton 476