| 619 | |
| 620 | |
| 621 | DataBuffer DebuggerMemory::ReadMemory(uint64_t offset, size_t len) |
| 622 | { |
| 623 | std::unique_lock<std::recursive_mutex> memoryLock(m_memoryMutex); |
| 624 | |
| 625 | DataBuffer result; |
| 626 | |
| 627 | // ProcessView implements read caching in a manner inspired by CPU cache: |
| 628 | // Reads are aligned on 256-byte boundaries and 256 bytes long |
| 629 | |
| 630 | // Cache read start: round down addr to nearest 256 byte boundary |
| 631 | size_t cacheStart = offset & (~0xffLL); |
| 632 | // Cache read end: round up addr+length to nearest 256 byte boundary |
| 633 | size_t cacheEnd = (offset + len + 0xFF) & (~0xffLL); |
| 634 | // List of 256-byte block addresses to read into the cache to fully cover this region |
| 635 | for (uint64_t block = cacheStart; block < cacheEnd; block += 0x100) |
| 636 | { |
| 637 | // If any block cannot be read, then return false |
| 638 | if (m_errorCache.find(block) != m_errorCache.end()) |
| 639 | { |
| 640 | return result; |
| 641 | } |
| 642 | |
| 643 | auto iter = m_valueCache.find(block); |
| 644 | if (iter == m_valueCache.end()) |
| 645 | { |
| 646 | // The ReadMemory() function should return the number of bytes read |
| 647 | DataBuffer buffer = m_state->GetAdapter()->ReadMemory(block, 0x100); |
| 648 | // TODO: what if the buffer's size is smaller than 0x100 |
| 649 | if (buffer.GetLength() > 0) |
| 650 | { |
| 651 | m_valueCache[block] = buffer; |
| 652 | } |
| 653 | else |
| 654 | { |
| 655 | m_errorCache.insert(block); |
| 656 | return result; |
| 657 | } |
| 658 | } |
| 659 | |
| 660 | DataBuffer cached = m_valueCache[block]; |
| 661 | if (offset + len < block + cached.GetLength()) |
| 662 | { |
| 663 | // Last block |
| 664 | cached = cached.GetSlice(0, offset + len - block); |
| 665 | } |
| 666 | // Note a block can be both the fist and the last block, so we should not put an else here |
| 667 | if (offset > block) |
| 668 | { |
| 669 | // First block |
| 670 | cached = cached.GetSlice(offset - block, cached.GetLength() - (offset - block)); |
| 671 | } |
| 672 | result.Append(cached); |
| 673 | } |
| 674 | return result; |
| 675 | } |
| 676 | |
| 677 | |
| 678 | bool DebuggerMemory::WriteMemory(std::uintptr_t address, const DataBuffer& buffer) |
no test coverage detected