Skip to content

Commit a0a13a6

Browse files
[lldb] Respect max packet size limits for MultiMemRead in ProcessGDBRemote
Servers advertise what their maximum packet size is, MultiMemRead needs to respect that. Depends on #172020
1 parent f785ca0 commit a0a13a6

File tree

1 file changed

+48
-15
lines changed

1 file changed

+48
-15
lines changed

lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2790,29 +2790,62 @@ size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
27902790
return 0;
27912791
}
27922792

2793+
/// Returns the number of ranges that is safe to request using MultiMemRead
2794+
/// while respecting max_packet_size.
2795+
static uint64_t ComputeNumRangesMultiMemRead(
2796+
uint64_t max_packet_size,
2797+
llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges) {
2798+
// Each range is specified by two numbers (~16 ASCII characters) and one
2799+
// comma.
2800+
constexpr uint64_t range_overhead = 33;
2801+
uint64_t current_size = 0;
2802+
for (auto [idx, range] : llvm::enumerate(ranges)) {
2803+
uint64_t potential_size = current_size + range.size + range_overhead;
2804+
if (potential_size > max_packet_size)
2805+
return idx;
2806+
}
2807+
return ranges.size();
2808+
}
2809+
27932810
llvm::SmallVector<llvm::MutableArrayRef<uint8_t>>
27942811
ProcessGDBRemote::ReadMemoryRanges(
27952812
llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges,
27962813
llvm::MutableArrayRef<uint8_t> buffer) {
27972814
if (!m_gdb_comm.GetMultiMemReadSupported())
27982815
return Process::ReadMemoryRanges(ranges, buffer);
27992816

2800-
llvm::Expected<StringExtractorGDBRemote> response =
2801-
SendMultiMemReadPacket(ranges);
2802-
if (!response) {
2803-
LLDB_LOG_ERROR(GetLog(GDBRLog::Process), response.takeError(),
2804-
"MultiMemRead error response: {0}");
2805-
return Process::ReadMemoryRanges(ranges, buffer);
2806-
}
2807-
2808-
llvm::StringRef response_str = response->GetStringRef();
2809-
const unsigned expected_num_ranges = ranges.size();
2817+
const llvm::ArrayRef<Range<lldb::addr_t, size_t>> original_ranges = ranges;
28102818
llvm::SmallVector<llvm::MutableArrayRef<uint8_t>> memory_regions;
2811-
if (llvm::Error error = ParseMultiMemReadPacket(
2812-
response_str, buffer, expected_num_ranges, memory_regions)) {
2813-
LLDB_LOG_ERROR(GetLog(GDBRLog::Process), std::move(error),
2814-
"MultiMemRead error parsing response: {0}");
2815-
return Process::ReadMemoryRanges(ranges, buffer);
2819+
2820+
while (!ranges.empty()) {
2821+
uint64_t num_ranges =
2822+
ComputeNumRangesMultiMemRead(m_max_memory_size, ranges);
2823+
if (num_ranges == 0) {
2824+
LLDB_LOG(
2825+
GetLog(GDBRLog::Process),
2826+
"MultiMemRead has a range bigger than maximum allowed by remote");
2827+
return Process::ReadMemoryRanges(original_ranges, buffer);
2828+
}
2829+
2830+
auto ranges_for_request = ranges.take_front(num_ranges);
2831+
ranges = ranges.drop_front(num_ranges);
2832+
2833+
llvm::Expected<StringExtractorGDBRemote> response =
2834+
SendMultiMemReadPacket(ranges_for_request);
2835+
if (!response) {
2836+
LLDB_LOG_ERROR(GetLog(GDBRLog::Process), response.takeError(),
2837+
"MultiMemRead error response: {0}");
2838+
return Process::ReadMemoryRanges(original_ranges, buffer);
2839+
}
2840+
2841+
llvm::StringRef response_str = response->GetStringRef();
2842+
const unsigned expected_num_ranges = ranges_for_request.size();
2843+
if (llvm::Error error = ParseMultiMemReadPacket(
2844+
response_str, buffer, expected_num_ranges, memory_regions)) {
2845+
LLDB_LOG_ERROR(GetLog(GDBRLog::Process), std::move(error),
2846+
"MultiMemRead error parsing response: {0}");
2847+
return Process::ReadMemoryRanges(original_ranges, buffer);
2848+
}
28162849
}
28172850
return memory_regions;
28182851
}

0 commit comments

Comments
 (0)