Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions lldb/include/lldb/Target/Memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@

#include "lldb/Utility/RangeMap.h"
#include "lldb/lldb-private.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/SmallVector.h"
#include <map>
#include <mutex>
#include <vector>
Expand All @@ -31,6 +33,13 @@ class MemoryCache {

size_t Read(lldb::addr_t addr, void *dst, size_t dst_len, Status &error);

/// Reads multiple memory ranges, serving cache hits from L1 and batching all
/// misses through Process::DoReadMemoryRanges. The semantics of the return
/// value match Process::ReadMemoryRanges.
llvm::SmallVector<llvm::MutableArrayRef<uint8_t>>
ReadRanges(llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges,
llvm::MutableArrayRef<uint8_t> buffer);

uint32_t GetMemoryCacheLineSize() const { return m_L2_cache_line_byte_size; }

void AddInvalidRange(lldb::addr_t base_addr, lldb::addr_t byte_size);
Expand All @@ -40,6 +49,11 @@ class MemoryCache {
// Allow external sources to populate data into the L1 memory cache
void AddL1CacheData(lldb::addr_t addr, const void *src, size_t src_len);

void AddL1CacheData(lldb::addr_t addr, llvm::ArrayRef<uint8_t> src) {
if (!src.empty())
AddL1CacheData(addr, src.data(), src.size());
}

void AddL1CacheData(lldb::addr_t addr,
const lldb::DataBufferSP &data_buffer_sp);

Expand Down
1 change: 1 addition & 0 deletions lldb/include/lldb/Target/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,7 @@ class Process : public std::enable_shared_from_this<Process>,
friend class StopInfo;
friend class Target;
friend class ThreadList;
friend class MemoryCache;

public:
/// Broadcaster event bits definitions.
Expand Down
51 changes: 51 additions & 0 deletions lldb/source/Target/Memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
#include "lldb/Utility/RangeMap.h"
#include "lldb/Utility/State.h"

#include "llvm/ADT/STLExtras.h"

#include <cinttypes>
#include <memory>

Expand Down Expand Up @@ -270,6 +272,55 @@ size_t MemoryCache::Read(addr_t addr, void *dst, size_t dst_len,
return dst_len;
}

llvm::SmallVector<llvm::MutableArrayRef<uint8_t>>
MemoryCache::ReadRanges(llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges,
llvm::MutableArrayRef<uint8_t> buffer) {
std::lock_guard<std::recursive_mutex> guard(m_mutex);

llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> results;
results.reserve(ranges.size());
llvm::SmallVector<Range<lldb::addr_t, size_t>> missed_ranges;

// Iterate once serving requests from L1.
for (auto range : ranges) {
const lldb::addr_t addr = range.GetRangeBase();
const size_t len = range.GetByteSize();

if (m_invalid_ranges.FindEntryThatContains(addr)) {
results.push_back(buffer.take_front(0));
continue;
}

if (const uint8_t *l1_data = FindL1CacheEntry(addr, len)) {
results.push_back(buffer.take_front(len));
buffer = buffer.drop_front(len);
memcpy(results.back().data(), l1_data, len);
continue;
}

// Use a nullptr to denote this needs fetching.
results.emplace_back(nullptr, nullptr);
missed_ranges.push_back(range);
}

if (missed_ranges.empty())
return results;

llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> fetched_buffers_vec =
m_process.DoReadMemoryRanges(missed_ranges, buffer);
auto fetched_buffers = llvm::ArrayRef(fetched_buffers_vec);

for (auto [missed_range, fetched] : llvm::zip(missed_ranges, fetched_buffers))
AddL1CacheData(missed_range.GetRangeBase(), fetched);

// Use the just-fetched memory to fill in the gaps left by the cache.
for (auto &result : results)
if (result.data() == nullptr)
result = fetched_buffers.consume_front();

return results;
}

AllocatedBlock::AllocatedBlock(lldb::addr_t addr, uint32_t byte_size,
uint32_t permissions, uint32_t chunk_size)
: m_range(addr, byte_size), m_permissions(permissions),
Expand Down
2 changes: 2 additions & 0 deletions lldb/source/Target/Process.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2077,6 +2077,8 @@ Process::ReadMemoryRanges(llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges,
for (const Range<lldb::addr_t, size_t> &range : ranges)
fixed_ranges.emplace_back(FixAnyAddress(range.GetRangeBase()),
range.GetByteSize());
if (!GetDisableMemoryCache())
return m_memory_cache.ReadRanges(fixed_ranges, buffer);
return DoReadMemoryRanges(fixed_ranges, buffer);
}

Expand Down
2 changes: 1 addition & 1 deletion lldb/unittests/Target/MemoryTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ TEST_F(MemoryTest, TestReadMemoryRanges) {
{
llvm::SmallVector<uint8_t, 0> buffer(1024, 0);
llvm::SmallVector<Range<addr_t, size_t>> ranges = {
{0x12345, 128}, {0x11112222, 128}, {0x77777777, 128}};
{0x6789, 128}, {0x333344444, 128}, {0x99999999, 128}};
llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> read_results =
dummy_process.ReadMemoryRanges(ranges, buffer);
for (auto [range, memory] : llvm::zip(ranges, read_results)) {
Expand Down