@@ -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+
27932810llvm::SmallVector<llvm::MutableArrayRef<uint8_t >>
27942811ProcessGDBRemote::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