56 RELOCO_BEGIN_UNSAFE_BUFFER_USAGE;
59 const size_t row_size = (diff.bytes_per_row > 0) ?
size_t{diff.bytes_per_row} :
size_t{16};
60 if (diff.scratch.size() < row_size * 2) {
61 out.write(string_view(
"[ERROR: Scratch buffer too small for remote_memory_diff]"));
65 std::byte *old_chunk_buf = diff.scratch.data();
66 std::byte *new_chunk_buf = diff.scratch.data() + row_size;
68 size_t identical_rows_streak = 0;
71 while (offset < diff.size) {
72 const size_t current_chunk_size = std::min(row_size, diff.size - offset);
75 const auto old_read = diff.old_space.read_bytes(diff.old_address + offset, old_chunk_buf, current_chunk_size);
76 const auto new_read = diff.new_space.read_bytes(diff.new_address + offset, new_chunk_buf, current_chunk_size);
78 if (!old_read || !new_read) {
80 if (identical_rows_streak > 0) {
81 flush_streak(out, identical_rows_streak);
82 identical_rows_streak = 0;
84 out.write(string_view(
" 0x"));
85 detail::format_unsigned<detail::radix::hex>(out, diff.new_address + offset,
false, 8);
86 out.write(string_view(
": [REMOTE READ FAULT]\n"));
91 const span<const std::byte> old_chunk(old_chunk_buf, current_chunk_size);
92 const span<const std::byte> new_chunk(new_chunk_buf, current_chunk_size);
95 bool rows_match =
true;
96 for (
size_t i = 0; i < current_chunk_size; ++i) {
97 if (old_chunk[i] != new_chunk[i]) {
104 identical_rows_streak++;
106 if (identical_rows_streak > 0) {
107 flush_streak(out, identical_rows_streak);
108 identical_rows_streak = 0;
112 out.write(string_view(
" 0x"));
113 detail::format_unsigned<detail::radix::hex>(out, diff.new_address + offset,
false, 8);
114 out.write(string_view(
": "));
116 format_row_bytes(out, old_chunk);
117 out.write(string_view(
" -> "));
118 format_row_bytes(out, new_chunk);
119 out.write(string_view(
"\n"));
125 if (identical_rows_streak > 0) {
126 flush_streak(out, identical_rows_streak);
129 RELOCO_END_UNSAFE_BUFFER_USAGE;