Skip to content

Commit 58d7eda

Browse files
fixup! Address review comments
1 parent 5b143dd commit 58d7eda

File tree

3 files changed

+32
-20
lines changed

3 files changed

+32
-20
lines changed

lldb/include/lldb/Target/Process.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1572,6 +1572,9 @@ class Process : public std::enable_shared_from_this<Process>,
15721572
Status &error);
15731573

15741574
/// Read from multiple memory ranges and write the results into buffer.
1575+
/// This calls ReadMemoryFromInferior multiple times, once per range,
1576+
/// bypassing the read cache. Process implementations that can perform this
1577+
/// operation more efficiently should override this.
15751578
///
15761579
/// \param[in] ranges
15771580
/// A collection of ranges (base address + size) to read from.

lldb/source/Target/Process.cpp

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1974,25 +1974,36 @@ size_t Process::ReadMemory(addr_t addr, void *buf, size_t size, Status &error) {
19741974
llvm::SmallVector<llvm::MutableArrayRef<uint8_t>>
19751975
Process::ReadMemoryRanges(llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges,
19761976
llvm::MutableArrayRef<uint8_t> buffer) {
1977-
llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> results;
1977+
auto total_ranges_len = llvm::sum_of(
1978+
llvm::map_range(ranges, [](auto range) { return range.size; }));
1979+
// If the buffer is not large enough, this is a programmer error.
1980+
// In production builds, gracefully fail by returning empty chunks.
1981+
assert(buffer.size() >= total_ranges_len);
1982+
if (buffer.size() < total_ranges_len)
1983+
return llvm::SmallVector<llvm::MutableArrayRef<uint8_t>>(ranges.size());
19781984

1979-
for (auto [addr, len] : ranges) {
1980-
// This is either a programmer error, or a protocol violation.
1981-
// In production builds, gracefully fail.
1982-
assert(buffer.size() >= len);
1983-
if (buffer.size() < len) {
1984-
results.push_back(buffer.take_front(0));
1985-
continue;
1986-
}
1985+
llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> results;
19871986

1987+
// While `buffer` has space, take the next requested range and read
1988+
// memory into a `buffer` chunk, then slice it to remove the used chunk.
1989+
for (auto [addr, range_len] : ranges) {
19881990
Status status;
19891991
size_t num_bytes_read =
1990-
ReadMemoryFromInferior(addr, buffer.data(), len, status);
1992+
ReadMemoryFromInferior(addr, buffer.data(), range_len, status);
19911993
// FIXME: ReadMemoryFromInferior promises to return 0 in case of errors, but
19921994
// it doesn't; it never checks for errors.
19931995
if (status.Fail())
19941996
num_bytes_read = 0;
1997+
1998+
assert(num_bytes_read <= range_len && "read more than requested bytes");
1999+
if (num_bytes_read > range_len) {
2000+
// In production builds, gracefully fail by returning an empty chunk.
2001+
results.emplace_back();
2002+
continue;
2003+
}
2004+
19952005
results.push_back(buffer.take_front(num_bytes_read));
2006+
// Slice buffer to remove the used chunk.
19962007
buffer = buffer.drop_front(num_bytes_read);
19972008
}
19982009

lldb/unittests/Target/MemoryTest.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#include "lldb/Utility/DataBufferHeap.h"
1919
#include "gtest/gtest.h"
2020
#include <cstdint>
21-
#include <random>
2221

2322
using namespace lldb_private;
2423
using namespace lldb;
@@ -228,15 +227,15 @@ TEST_F(MemoryTest, TesetMemoryCacheRead) {
228227
// old cache
229228
}
230229

231-
/// A process class that reads `lower_byte(address)` for each `address` it
232-
/// reads.
230+
/// A process class that, when asked to read memory from some address X, returns
231+
/// the least significant byte of X.
233232
class DummyReaderProcess : public Process {
234233
public:
235234
size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
236235
Status &error) override {
237236
uint8_t *buffer = static_cast<uint8_t *>(buf);
238237
for (size_t addr = vm_addr; addr < vm_addr + size; addr++)
239-
buffer[addr - vm_addr] = addr;
238+
buffer[addr - vm_addr] = static_cast<uint8_t>(addr); // LSB of addr.
240239
return size;
241240
}
242241
// Boilerplate, nothing interesting below.
@@ -270,12 +269,11 @@ TEST_F(MemoryTest, TestReadMemoryRanges) {
270269

271270
llvm::SmallVector<uint8_t, 0> buffer(1024, 0);
272271

273-
// Read 8 ranges of 128 bytes, starting at random addresses
274-
std::mt19937 rng(42);
275-
std::uniform_int_distribution<addr_t> distribution(1, 100000);
276-
llvm::SmallVector<Range<addr_t, size_t>> ranges;
277-
for (unsigned i = 0; i < 1024; i += 128)
278-
ranges.emplace_back(distribution(rng), 128);
272+
// Read 8 ranges of 128 bytes with arbitrary base addresses.
273+
llvm::SmallVector<Range<addr_t, size_t>> ranges = {
274+
{0x12345, 128}, {0x11112222, 128}, {0x77777777, 128},
275+
{0xffaabbccdd, 128}, {0x0, 128}, {0x4242424242, 128},
276+
{0x17171717, 128}, {0x99999, 128}};
279277

280278
llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> read_results =
281279
process->ReadMemoryRanges(ranges, buffer);

0 commit comments

Comments
 (0)