Skip to content

Commit 6742dc1

Browse files
committed
Update Minidump file builder to use new API
1 parent 4220f93 commit 6742dc1

File tree

3 files changed

+59
-50
lines changed

3 files changed

+59
-50
lines changed

lldb/include/lldb/Target/Process.h

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1589,10 +1589,21 @@ class Process : public std::enable_shared_from_this<Process>,
15891589
size_t ReadMemoryFromInferior(lldb::addr_t vm_addr, void *buf, size_t size,
15901590
Status &error);
15911591

1592-
typedef lldb::IterationAction(ReadMemoryChunkCallback)(lldb::Status &,
1593-
DataBufferHeap &, lldb
1594-
: addr_t,
1595-
lldb::offset_t);
1592+
// Callback definition for read Memory in chunks
1593+
//
1594+
// Status, the status returned from ReadMemoryFromInferior
1595+
// DataBufferHeap, buffer with bytes potentially written to it
1596+
// addr_t, the current_addr, start + bytes read so far.
1597+
// uint64_t bytes_to_read, the expected bytes read, this
1598+
// is important if it's a partial read
1599+
// uint64_t bytes_read_for_chunk, the actual count of bytes read for this
1600+
// chunk
1601+
typedef std::function<IterationAction(lldb_private::Status&,
1602+
lldb_private::DataBufferHeap&,
1603+
lldb::addr_t,
1604+
uint64_t,
1605+
uint64_t)> ReadMemoryChunkCallback;
1606+
15961607
/// Read of memory from a process in discrete chunks, terminating
15971608
/// either when all bytes are read, or the supplied callback returns
15981609
/// IterationAction::Stop
@@ -1610,9 +1621,6 @@ class Process : public std::enable_shared_from_this<Process>,
16101621
///
16111622
/// \param[in] callback
16121623
/// The callback to invoke when a chunk is read from memory.
1613-
/// \param[in] cacheReads
1614-
/// Whether to use the ReadMemory instead of ReadMemory inferior, defaults
1615-
/// to false.
16161624
///
16171625
/// \return
16181626
/// The number of bytes that were actually read into \a buf and
@@ -1622,8 +1630,7 @@ class Process : public std::enable_shared_from_this<Process>,
16221630
/// vm_addr, \a buf, and \a size updated appropriately. Zero is
16231631
/// returned in the case of an error.
16241632
size_t ReadMemoryInChunks(lldb::addr_t vm_addr, DataBufferHeap &data,
1625-
size_t size, ReadMemoryChunkCallback callback,
1626-
bool cacheReads = false);
1633+
size_t size, ReadMemoryChunkCallback callback);
16271634

16281635
/// Read a NULL terminated C string from memory
16291636
///

lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp

Lines changed: 27 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -974,68 +974,57 @@ Status MinidumpFileBuilder::ReadWriteMemoryInChunks(
974974
const lldb_private::CoreFileMemoryRange &range, uint64_t &bytes_read) {
975975

976976
Log *log = GetLog(LLDBLog::Object);
977-
const lldb::addr_t addr = range.range.start();
978-
const lldb::addr_t size = range.range.size();
979-
980-
uint64_t bytes_remaining = size;
981-
Status error;
982-
while (bytes_remaining > 0) {
983-
// Get the next read chunk size as the minimum of the remaining bytes and
984-
// the write chunk max size.
985-
const size_t bytes_to_read =
986-
std::min(bytes_remaining, data_buffer.GetByteSize());
987-
const size_t bytes_read_for_chunk =
988-
m_process_sp->ReadMemory(range.range.start() + bytes_read,
989-
data_buffer.GetBytes(), bytes_to_read, error);
977+
Status addDataError;
978+
Process::ReadMemoryChunkCallback callback =
979+
[&](Status &error, DataBufferHeap &data, lldb::addr_t current_addr,
980+
uint64_t bytes_to_read,
981+
uint64_t bytes_read_for_chunk) -> lldb_private::IterationAction {
990982
if (error.Fail() || bytes_read_for_chunk == 0) {
991983
LLDB_LOGF(log,
992984
"Failed to read memory region at: %" PRIx64
993985
". Bytes read: %zu, error: %s",
994-
addr, bytes_read_for_chunk, error.AsCString());
986+
current_addr, bytes_read_for_chunk, error.AsCString());
995987

996988
// If we failed in a memory read, we would normally want to skip
997989
// this entire region, if we had already written to the minidump
998-
// file, we can't easily rewind the state.
990+
// file, we can't easily rewind that state.
999991
//
1000992
// So if we do encounter an error while reading, we just return
1001993
// immediately, any prior bytes read will still be included but
1002994
// any bytes partially read before the error are ignored.
1003-
return Status();
995+
return lldb_private::IterationAction::Stop;
1004996
}
1005997

1006-
// Write to the minidump file with the chunk potentially flushing to disk.
1007-
// this is the only place we want to return a true error, so that we can
1008-
// fail. If we get an error writing to disk we can't easily gaurauntee
1009-
// that we won't corrupt the minidump.
1010-
error = AddData(data_buffer.GetBytes(), bytes_read_for_chunk);
1011-
if (error.Fail())
1012-
return error;
1013-
1014-
// If the bytes read in this chunk would cause us to overflow, something
1015-
// went wrong and we should fail out of creating the Minidump.
1016-
if (bytes_read_for_chunk > bytes_remaining)
1017-
return Status::FromErrorString("Unexpected number of bytes read.");
1018-
else
1019-
bytes_remaining -= bytes_read_for_chunk;
1020-
1021-
// Update the caller with the number of bytes read, but also written to the
1022-
// underlying buffer.
1023-
bytes_read += bytes_read_for_chunk;
998+
// Write to the minidump file with the chunk potentially flushing to
999+
// disk.
1000+
// This error will be captured by the outer scope and is considered fatal.
1001+
// If we get an error writing to disk we can't easily guarauntee that we
1002+
// won't corrupt the minidump.
1003+
addDataError = AddData(data_buffer.GetBytes(), bytes_read_for_chunk);
1004+
if (addDataError.Fail())
1005+
return lldb_private::IterationAction::Stop;
10241006

10251007
if (bytes_read_for_chunk != bytes_to_read) {
10261008
LLDB_LOGF(log,
10271009
"Memory region at: %" PRIx64 " partiall read %" PRIx64
10281010
" bytes out of %" PRIx64 " bytes.",
1029-
addr, bytes_read_for_chunk,
1011+
current_addr, bytes_read_for_chunk,
10301012
bytes_to_read - bytes_read_for_chunk);
10311013

10321014
// If we've read some bytes, we stop trying to read more and return
10331015
// this best effort attempt
1034-
break;
1016+
return lldb_private::IterationAction::Stop;
10351017
}
1036-
}
10371018

1038-
return error;
1019+
// No problems, keep going!
1020+
return lldb_private::IterationAction::Continue;
1021+
};
1022+
1023+
const lldb::addr_t addr = range.range.start();
1024+
const lldb::addr_t size = range.range.size();
1025+
bytes_read =
1026+
m_process_sp->ReadMemoryInChunks(addr, data_buffer, size, callback);
1027+
return addDataError;
10391028
}
10401029

10411030
static uint64_t

lldb/source/Target/Process.cpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2235,6 +2235,10 @@ size_t Process::ReadMemoryFromInferior(addr_t addr, void *buf, size_t size,
22352235

22362236
size_t Process::ReadMemoryInChunks(lldb::addr_t vm_addr, DataBufferHeap &data,
22372237
size_t size, ReadMemoryChunkCallback callback) {
2238+
// Safety check to prevent an infinite loop.
2239+
if (data.GetByteSize() == 0)
2240+
return 0;
2241+
22382242
uint64_t bytes_remaining = size;
22392243
uint64_t bytes_read = 0;
22402244
Status error;
@@ -2243,12 +2247,21 @@ size_t Process::ReadMemoryInChunks(lldb::addr_t vm_addr, DataBufferHeap &data,
22432247
// the write chunk max size.
22442248
const size_t bytes_to_read =
22452249
std::min(bytes_remaining, data.GetByteSize());
2246-
const lldb::addr_t current_addr = vm_addr + bytes_read
2250+
const lldb::addr_t current_addr = vm_addr + bytes_read;
22472251
const size_t bytes_read_for_chunk =
2248-
m_process_sp->ReadMemory(current_addr,
2252+
ReadMemoryFromInferior(current_addr,
22492253
data.GetBytes(), bytes_to_read, error);
2250-
if (callback(error, data, current_addr, bytes_read_for_chunk) == lldb::IterationAction::Stop)
2254+
2255+
if (callback(error, data, current_addr, bytes_to_read, bytes_read_for_chunk) == IterationAction::Stop)
22512256
break;
2257+
2258+
bytes_read += bytes_read_for_chunk;
2259+
// If the bytes read in this chunk would cause us to overflow, something
2260+
// went wrong and we should fail fast.
2261+
if (bytes_read_for_chunk > bytes_remaining)
2262+
return 0;
2263+
else
2264+
bytes_remaining -= bytes_read_for_chunk;
22522265
}
22532266

22542267
return bytes_read;

0 commit comments

Comments
 (0)