Skip to content

Commit 566eb2b

Browse files
[lldb] Respect max packet size limits for MultiMemRead in ProcessGDBRemote (#172022)
(ignore the first commit, it is the dependency of this PR) Servers advertise what their maximum packet size is, MultiMemRead needs to respect that. Depends on: * #172020
1 parent d68afde commit 566eb2b

File tree

1 file changed

+50
-15
lines changed

1 file changed

+50
-15
lines changed

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

Lines changed: 50 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2790,29 +2790,64 @@ 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 (up to 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+
if (idx == 0)
2806+
LLDB_LOG(GetLog(GDBRLog::Process),
2807+
"MultiMemRead input has a range (base = {0:x}, size = {1}) "
2808+
"bigger than the maximum allowed by remote",
2809+
range.base, range.size);
2810+
return idx;
2811+
}
2812+
}
2813+
return ranges.size();
2814+
}
2815+
27932816
llvm::SmallVector<llvm::MutableArrayRef<uint8_t>>
27942817
ProcessGDBRemote::ReadMemoryRanges(
27952818
llvm::ArrayRef<Range<lldb::addr_t, size_t>> ranges,
27962819
llvm::MutableArrayRef<uint8_t> buffer) {
27972820
if (!m_gdb_comm.GetMultiMemReadSupported())
27982821
return Process::ReadMemoryRanges(ranges, buffer);
27992822

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();
2823+
const llvm::ArrayRef<Range<lldb::addr_t, size_t>> original_ranges = ranges;
28102824
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);
2825+
2826+
while (!ranges.empty()) {
2827+
uint64_t num_ranges =
2828+
ComputeNumRangesMultiMemRead(m_max_memory_size, ranges);
2829+
if (num_ranges == 0)
2830+
return Process::ReadMemoryRanges(original_ranges, buffer);
2831+
2832+
auto ranges_for_request = ranges.take_front(num_ranges);
2833+
ranges = ranges.drop_front(num_ranges);
2834+
2835+
llvm::Expected<StringExtractorGDBRemote> response =
2836+
SendMultiMemReadPacket(ranges_for_request);
2837+
if (!response) {
2838+
LLDB_LOG_ERROR(GetLog(GDBRLog::Process), response.takeError(),
2839+
"MultiMemRead error response: {0}");
2840+
return Process::ReadMemoryRanges(original_ranges, buffer);
2841+
}
2842+
2843+
llvm::StringRef response_str = response->GetStringRef();
2844+
const unsigned expected_num_ranges = ranges_for_request.size();
2845+
if (llvm::Error error = ParseMultiMemReadPacket(
2846+
response_str, buffer, expected_num_ranges, memory_regions)) {
2847+
LLDB_LOG_ERROR(GetLog(GDBRLog::Process), std::move(error),
2848+
"MultiMemRead error parsing response: {0}");
2849+
return Process::ReadMemoryRanges(original_ranges, buffer);
2850+
}
28162851
}
28172852
return memory_regions;
28182853
}

0 commit comments

Comments
 (0)