Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assertion `nwritten == buf_size' failed to hold (Again) #3779

Closed
KJTsanaktsidis opened this issue Jul 10, 2024 · 19 comments · Fixed by #3800
Closed

Assertion `nwritten == buf_size' failed to hold (Again) #3779

KJTsanaktsidis opened this issue Jul 10, 2024 · 19 comments · Fixed by #3800
Assignees

Comments

@KJTsanaktsidis
Copy link
Contributor

KJTsanaktsidis commented Jul 10, 2024

This appears to be a regression of #3325 in just about every way, but I figured I'd open a new issue since that was 2 years old.

I've got a recording that crashes during replay 100% of the time with this exception. I can also semi-reproducibly re-record it and obtain a crashing replay again.

[FATAL src/Task.cc:3267:write_bytes_helper_no_notifications() errno: EIO] 
 (task 34287 (rec:20517) at time 66790)
 -> Assertion `nwritten == buf_size' failed to hold. Should have written 3976 bytes to 0x7ff8cbdff0f8, but only wrote 3848
Tail of trace dump:
{
  real_time:1839.720144 global_time:66770, event:`SYSCALL: munmap' (state:ENTERING_SYSCALL) tid:20516, ticks:27355246
rax:0xffffffffffffffda rbx:0x681fffa0 rcx:0xffffffffffffffff rdx:0x0 rsi:0x10000 rdi:0x7f5797b30000 rbp:0x7fffc6a5aa10 rsp:0x681ffde0 r8:0x40 r9:0x0 r10:0x30 r11:0x246 r12:0x11 r13:0x16 r14:0x5601fe0a82b0 r15:0x7f5797b30020 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0xb fs_base:0x7f5797cf7780 gs_base:0x0
}
{
  real_time:1839.720167 global_time:66771, event:`SYSCALL: munmap' (state:EXITING_SYSCALL) tid:20516, ticks:27355246
rax:0x0 rbx:0x681fffa0 rcx:0xffffffffffffffff rdx:0x0 rsi:0x10000 rdi:0x7f5797b30000 rbp:0x7fffc6a5aa10 rsp:0x681ffde0 r8:0x40 r9:0x0 r10:0x30 r11:0x246 r12:0x11 r13:0x16 r14:0x5601fe0a82b0 r15:0x7f5797b30020 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0xb fs_base:0x7f5797cf7780 gs_base:0x0
}
{
  real_time:1839.720184 global_time:66772, event:`SYSCALL: munmap' (state:ENTERING_SYSCALL) tid:20516, ticks:27355304
rax:0xffffffffffffffda rbx:0x681fffa0 rcx:0xffffffffffffffff rdx:0x0 rsi:0x10000 rdi:0x7f5797b40000 rbp:0x7fffc6a5aa10 rsp:0x681ffde0 r8:0x20 r9:0x0 r10:0x30 r11:0x246 r12:0x12 r13:0x16 r14:0x5601fe0a3cd0 r15:0x7f5797b40010 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0xb fs_base:0x7f5797cf7780 gs_base:0x0
}
{
  real_time:1839.720206 global_time:66773, event:`SYSCALL: munmap' (state:EXITING_SYSCALL) tid:20516, ticks:27355304
rax:0x0 rbx:0x681fffa0 rcx:0xffffffffffffffff rdx:0x0 rsi:0x10000 rdi:0x7f5797b40000 rbp:0x7fffc6a5aa10 rsp:0x681ffde0 r8:0x20 r9:0x0 r10:0x30 r11:0x246 r12:0x12 r13:0x16 r14:0x5601fe0a3cd0 r15:0x7f5797b40010 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0xb fs_base:0x7f5797cf7780 gs_base:0x0
}
{
  real_time:1839.720224 global_time:66774, event:`SYSCALL: munmap' (state:ENTERING_SYSCALL) tid:20516, ticks:27355362
rax:0xffffffffffffffda rbx:0x681fffa0 rcx:0xffffffffffffffff rdx:0x0 rsi:0x10000 rdi:0x7f5797b50000 rbp:0x7fffc6a5aa10 rsp:0x681ffde0 r8:0x20 r9:0x0 r10:0x30 r11:0x246 r12:0x13 r13:0x16 r14:0x5601fe07fae0 r15:0x7f5797b50030 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0xb fs_base:0x7f5797cf7780 gs_base:0x0
}
{
  real_time:1839.720243 global_time:66775, event:`SYSCALL: munmap' (state:EXITING_SYSCALL) tid:20516, ticks:27355362
rax:0x0 rbx:0x681fffa0 rcx:0xffffffffffffffff rdx:0x0 rsi:0x10000 rdi:0x7f5797b50000 rbp:0x7fffc6a5aa10 rsp:0x681ffde0 r8:0x20 r9:0x0 r10:0x30 r11:0x246 r12:0x13 r13:0x16 r14:0x5601fe07fae0 r15:0x7f5797b50030 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0xb fs_base:0x7f5797cf7780 gs_base:0x0
}
{
  real_time:1839.720261 global_time:66776, event:`SYSCALL: munmap' (state:ENTERING_SYSCALL) tid:20516, ticks:27355420
rax:0xffffffffffffffda rbx:0x681fffa0 rcx:0xffffffffffffffff rdx:0x0 rsi:0x10000 rdi:0x7f5797b60000 rbp:0x7fffc6a5aa10 rsp:0x681ffde0 r8:0x2010 r9:0x0 r10:0x30 r11:0x246 r12:0x14 r13:0x16 r14:0x5601fe078440 r15:0x7f5797b60020 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0xb fs_base:0x7f5797cf7780 gs_base:0x0
}
{
  real_time:1839.720285 global_time:66777, event:`SYSCALL: munmap' (state:EXITING_SYSCALL) tid:20516, ticks:27355420
rax:0x0 rbx:0x681fffa0 rcx:0xffffffffffffffff rdx:0x0 rsi:0x10000 rdi:0x7f5797b60000 rbp:0x7fffc6a5aa10 rsp:0x681ffde0 r8:0x2010 r9:0x0 r10:0x30 r11:0x246 r12:0x14 r13:0x16 r14:0x5601fe078440 r15:0x7f5797b60020 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0xb fs_base:0x7f5797cf7780 gs_base:0x0
}
{
  real_time:1839.720303 global_time:66778, event:`SYSCALL: munmap' (state:ENTERING_SYSCALL) tid:20516, ticks:27355478
rax:0xffffffffffffffda rbx:0x681fffa0 rcx:0xffffffffffffffff rdx:0x0 rsi:0x10000 rdi:0x7f5797be0000 rbp:0x7fffc6a5aa10 rsp:0x681ffde0 r8:0x70 r9:0x0 r10:0x30 r11:0x246 r12:0x15 r13:0x16 r14:0x5601fe060330 r15:0x7f5797be0060 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0xb fs_base:0x7f5797cf7780 gs_base:0x0
}
{
  real_time:1839.720323 global_time:66779, event:`SYSCALL: munmap' (state:EXITING_SYSCALL) tid:20516, ticks:27355478
rax:0x0 rbx:0x681fffa0 rcx:0xffffffffffffffff rdx:0x0 rsi:0x10000 rdi:0x7f5797be0000 rbp:0x7fffc6a5aa10 rsp:0x681ffde0 r8:0x70 r9:0x0 r10:0x30 r11:0x246 r12:0x15 r13:0x16 r14:0x5601fe060330 r15:0x7f5797be0060 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0xb fs_base:0x7f5797cf7780 gs_base:0x0
}
{
  real_time:1839.720423 global_time:66780, event:`PATCH_SYSCALL' tid:20516, ticks:27356439
rax:0xe7 rbx:0x7f5797ee2fa8 rcx:0xffffffffffffffff rdx:0xe7 rsi:0xffffffffffffff10 rdi:0x0 rbp:0x7fffc6a5ab80 rsp:0x7fffc6a5ab28 r8:0x7fffc6a5aad0 r9:0x7fffc6a5aa2f r10:0x0 r11:0x246 r12:0x1 r13:0x0 r14:0x7f5797ee1680 r15:0x7f5797ee2fc0 rip:0x7f5797ddeeab eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0xffffffffffffffff fs_base:0x7f5797cf7780 gs_base:0x0
  { map_file:"<ZERO>", addr:0x7f5798060000, length:0x1000, prot_flags:"r-xp", file_offset:0x0, device:0, inode:0, data_file:"", data_offset:0x0, file_size:0x1000 }
  { tid:20516, addr:0x7f5798060000, length:0x5e }
  { tid:20516, addr:0x7f5797ddeeab, length:0x8 }
}
{
  real_time:1839.720443 global_time:66781, event:`SYSCALL: exit_group' (state:ENTERING_SYSCALL) tid:20516, ticks:27356449
rax:0xffffffffffffffda rbx:0x681fffa0 rcx:0xffffffffffffffff rdx:0xe7 rsi:0xffffffffffffff10 rdi:0x0 rbp:0x7fffc6a5ab80 rsp:0x681ffde0 r8:0x7fffc6a5aad0 r9:0x7fffc6a5aa2f r10:0x0 r11:0x246 r12:0x1 r13:0x0 r14:0x7f5797ee1680 r15:0x7f5797ee2fc0 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0xe7 fs_base:0x7f5797cf7780 gs_base:0x0
}
{
  real_time:1839.720466 global_time:66782, event:`EXIT' tid:20516, ticks:27356449
  { tid:20516, addr:0x7f5797cf7a50, length:0x4 }
}
{
  real_time:1839.720534 global_time:66783, event:`EXIT' tid:20519, ticks:8660
}
{
  real_time:1839.721236 global_time:66784, event:`SYSCALL: poll' (state:EXITING_SYSCALL) tid:20517, ticks:1371
rax:0x1 rbx:0x7ff8cbdfffa0 rcx:0xffffffffffffffff rdx:0xffffffff rsi:0x1 rdi:0x7ff8d0dfe430 rbp:0x7ff8d0dfe420 rsp:0x7ff8cbdffde0 r8:0x0 r9:0x0 r10:0x4 r11:0x246 r12:0x7ff8d0dfe430 r13:0x20c49ba5e353f7cf r14:0xd1a8aa0 r15:0x0 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0x7 fs_base:0x7ff8d0dff6c0 gs_base:0x0
  { tid:20517, addr:0x7ff8d0dfe430, length:0x8 }
}
{
  real_time:1839.721289 global_time:66785, event:`SYSCALLBUF_FLUSH' tid:20517, ticks:1849
  { syscall:'read', ret:0x0, size:0x10, desched:1 }
}
{
  real_time:1839.721294 global_time:66786, event:`SYSCALL: wait4' (state:ENTERING_SYSCALL) tid:20517, ticks:1849
rax:0xffffffffffffffda rbx:0x7ff8cbdfffa0 rcx:0xffffffffffffffff rdx:0x0 rsi:0x7ff8d0dfe8f8 rdi:0x5024 rbp:0x7ff8d0dfe800 rsp:0x7ff8cbdffde0 r8:0x0 r9:0x0 r10:0x0 r11:0x246 r12:0xd18f920 r13:0xd0840f0 r14:0xd18f800 r15:0x7ff8ec877980 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0x3d fs_base:0x7ff8d0dff6c0 gs_base:0x0
}
{
  real_time:1839.721297 global_time:66787, event:`SYSCALLBUF_RESET' tid:20517, ticks:1849
}
{
  real_time:1839.721428 global_time:66788, event:`SYSCALL: wait4' (state:EXITING_SYSCALL) tid:20517, ticks:1849
rax:0x5024 rbx:0x7ff8cbdfffa0 rcx:0xffffffffffffffff rdx:0x0 rsi:0x7ff8d0dfe8f8 rdi:0x5024 rbp:0x7ff8d0dfe800 rsp:0x7ff8cbdffde0 r8:0x0 r9:0x0 r10:0x0 r11:0x246 r12:0xd18f920 r13:0xd0840f0 r14:0xd18f800 r15:0x7ff8ec877980 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0x3d fs_base:0x7ff8d0dff6c0 gs_base:0x0
  { tid:20517, addr:0x7ff8d0dfe8f8, length:0x4 }
}
{
  real_time:1839.721469 global_time:66789, event:`SIGNAL: SIGCHLD(async)' tid:20517, ticks:1849
rax:0x5024 rbx:0x7ff8cbdfffa0 rcx:0xffffffffffffffff rdx:0x0 rsi:0x7ff8d0dfe8f8 rdi:0x5024 rbp:0x7ff8d0dfe800 rsp:0x7ff8cbdffde0 r8:0x0 r9:0x0 r10:0x0 r11:0x246 r12:0xd18f920 r13:0xd0840f0 r14:0xd18f800 r15:0x7ff8ec877980 rip:0x70000002 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0x3d fs_base:0x7ff8d0dff6c0 gs_base:0x0 st0:0x0 st1:0x0 st2:0x0 st3:0x0 st4:0x0 st5:0x0 st6:0x0 st7:0x0 ymm0:0xd18f868000000000d18f868 ymm1:0x7ff8ec877980 ymm2:0xd40b9e0 ymm3:0x7ff8fa712b20 ymm4:0x7ff8c4000090 ymm5:0x4024000000000000 ymm6:0x0 ymm7:0x3fb2b940d826360e ymm8:0x0 ymm9:0x0 ymm10:0x0 ymm11:0x0 ymm12:0x0 ymm13:0x0 ymm14:0x0 ymm15:0x0
}
{
  real_time:1839.721514 global_time:66790, event:`SIGNAL_HANDLER: SIGCHLD(async)' tid:20517, ticks:1849
rax:0x0 rbx:0x7ff8cbdfffa0 rcx:0xffffffffffffffff rdx:0x7ff8cbdff100 rsi:0x7ff8cbdff230 rdi:0x11 rbp:0x7ff8d0dfe800 rsp:0x7ff8cbdff0f8 r8:0x0 r9:0x0 r10:0x0 r11:0x246 r12:0xd18f920 r13:0xd0840f0 r14:0xd18f800 r15:0x7ff8ec877980 rip:0x7ff8faa594d0 eflags:0x246 cs:0x33 ss:0x2b ds:0x0 es:0x0 fs:0x0 gs:0x0 orig_rax:0x3d fs_base:0x7ff8d0dff6c0 gs_base:0x0 st0:0x0 st1:0x0 st2:0x0 st3:0x0 st4:0x0 st5:0x0 st6:0x0 st7:0x0 ymm0:0x0 ymm1:0x0 ymm2:0x0 ymm3:0x0 ymm4:0x0 ymm5:0x0 ymm6:0x0 ymm7:0x0 ymm8:0x0 ymm9:0x0 ymm10:0x0 ymm11:0x0 ymm12:0x0 ymm13:0x0 ymm14:0x0 ymm15:0x0
  { tid:20517, addr:0x7ff8cbdff0f8, length:0xf88 }
}
{
  real_time:1839.721609 global_time:66791, event:`SYSCALLBUF_FLUSH' tid:20517, ticks:1891
  { syscall:'write', ret:0x8, size:0x10, desched:1 }
}

The program is the Ruby test suite. If you want to download 500MB of build product, I tar'd up the directory here: https://1drv.ms/u/s!AjbrX5Fo8lg8jZ4N9tW3fEUTFPd-JA?e=zFApbp

There's a packed trace exhibiting this behaviour in ruby/build/rr_trace. You can record another one with cd build; rr record --output-trace-dir rr_trace -- make TESTOPTS="-v --tty=no $(realpath ../bootstraptest/test_ractor.rb)" btest

Like in #3325, the captured write seems to be past the end of a scratch area. I ran info proc mappings from the emergency gdbserver and saw that the mapping it was writing into was rwx which I guess probably means it's a scratch mapping from RR itself?

info proc mappings
(gdb) info proc mappings
process 20235
Mapped address spaces:

          Start Addr           End Addr       Size     Offset  Perms  objfile
            0x400000           0x401000     0x1000        0x0  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/bin/ruby
            0x401000           0x402000     0x1000     0x1000  r-xp   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/bin/ruby
            0x402000           0x403000     0x1000     0x2000  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/bin/ruby
            0x403000           0x404000     0x1000     0x2000  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/bin/ruby
            0x404000           0x405000     0x1000     0x3000  rw-p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/bin/ruby
           0xd080000          0xf32c000  0x22ac000        0x0  rw-p   [heap]
          0x68000000         0x68200000   0x200000        0x0  rwxp   
          0x6fffd000         0x70001000     0x4000        0x0  r-xp   /usr/local/lib64/rr/librrpage.so
          0x70001000         0x70002000     0x1000        0x0  rw-s   /tmp/rr-shared-preload_thread_locals-33882-54
          0x70002000         0x70102000   0x100000        0x0  rw-s   /tmp/rr-shared-syscallbuf.20235-33882-57
          0x70103000         0x70104000     0x1000        0x0  r-xp   
          0x70104000         0x70204000   0x100000        0x0  rw-s   /tmp/rr-shared-syscallbuf.20236-33939-58
          0x70304000         0x70404000   0x100000        0x0  rw-s   /tmp/rr-shared-syscallbuf.20515-34285-460
          0x70704000         0x70804000   0x100000        0x0  rw-s   /tmp/rr-shared-syscallbuf.20517-34287-463
      0x7ff8c4000000     0x7ff8c4021000    0x21000        0x0  rw-p   
      0x7ff8c4021000     0x7ff8c8000000  0x3fdf000        0x0  ---p   
      0x7ff8cbc00000     0x7ff8cbe00000   0x200000        0x0  rwxp   
      0x7ff8cc000000     0x7ff8cc021000    0x21000        0x0  rw-p   
      0x7ff8cc021000     0x7ff8d0000000  0x3fdf000        0x0  ---p   
      0x7ff8d0200000     0x7ff8d0400000   0x200000        0x0  rwxp   
      0x7ff8d0cff000     0x7ff8d0d00000     0x1000        0x0  ---p   
      0x7ff8d0d00000     0x7ff8d0e00000   0x100000        0x0  rw-p   [stack]
      0x7ff8d1200000     0x7ff8d1201000     0x1000        0x0  ---p   
      0x7ff8d1201000     0x7ff8d12a2000    0xa1000        0x0  rw-p   
      0x7ff8d12a2000     0x7ff8d12a3000     0x1000        0x0  ---p   
      0x7ff8d12a3000     0x7ff8d1344000    0xa1000        0x0  rw-p   
      0x7ff8d1344000     0x7ff8d1345000     0x1000        0x0  ---p   
      0x7ff8d1345000     0x7ff8d13e6000    0xa1000        0x0  rw-p   
      0x7ff8d13e6000     0x7ff8d13e7000     0x1000        0x0  ---p   
      0x7ff8d13e7000     0x7ff8d1488000    0xa1000        0x0  rw-p   
      0x7ff8d1488000     0x7ff8d1489000     0x1000        0x0  ---p   
      0x7ff8d1489000     0x7ff8d152a000    0xa1000        0x0  rw-p   
      0x7ff8d152a000     0x7ff8d152b000     0x1000        0x0  ---p   
      0x7ff8d152b000     0x7ff8d15cc000    0xa1000        0x0  rw-p   
      0x7ff8d15cc000     0x7ff8d15cd000     0x1000        0x0  ---p   
      0x7ff8d15cd000     0x7ff8d166e000    0xa1000        0x0  rw-p   
      0x7ff8d166e000     0x7ff8d166f000     0x1000        0x0  ---p   
      0x7ff8d166f000     0x7ff8d1710000    0xa1000        0x0  rw-p   
      0x7ff8d1710000     0x7ff8d1711000     0x1000        0x0  ---p   
      0x7ff8d1711000     0x7ff8d17b2000    0xa1000        0x0  rw-p   
      0x7ff8d17b2000     0x7ff8d17b3000     0x1000        0x0  ---p   
      0x7ff8d17b3000     0x7ff8d1854000    0xa1000        0x0  rw-p   
      0x7ff8d1854000     0x7ff8d1855000     0x1000        0x0  ---p   
      0x7ff8d1855000     0x7ff8d18f6000    0xa1000        0x0  rw-p   
      0x7ff8d18f6000     0x7ff8d18f7000     0x1000        0x0  ---p   
      0x7ff8d18f7000     0x7ff8d1998000    0xa1000        0x0  rw-p   
      0x7ff8d1998000     0x7ff8d1999000     0x1000        0x0  ---p   
      0x7ff8d1999000     0x7ff8d1a3a000    0xa1000        0x0  rw-p   
      0x7ff8d1a3a000     0x7ff8d1a3b000     0x1000        0x0  ---p   
      0x7ff8d1a3b000     0x7ff8d1adc000    0xa1000        0x0  rw-p   
      0x7ff8d1adc000     0x7ff8d1add000     0x1000        0x0  ---p   
      0x7ff8d1add000     0x7ff8d1b7e000    0xa1000        0x0  rw-p   
      0x7ff8d1b7e000     0x7ff8d1b7f000     0x1000        0x0  ---p   
      0x7ff8d1b7f000     0x7ff8d1c20000    0xa1000        0x0  rw-p   
      0x7ff8d1c20000     0x7ff8d1c21000     0x1000        0x0  ---p   
      0x7ff8d1c21000     0x7ff8d1cc2000    0xa1000        0x0  rw-p   
      0x7ff8d1cc2000     0x7ff8d1cc3000     0x1000        0x0  ---p   
      0x7ff8d1cc3000     0x7ff8d1d64000    0xa1000        0x0  rw-p   
      0x7ff8d1d64000     0x7ff8d1d65000     0x1000        0x0  ---p   
      0x7ff8d1d65000     0x7ff8d1e06000    0xa1000        0x0  rw-p   
      0x7ff8d1e06000     0x7ff8d1e07000     0x1000        0x0  ---p   
      0x7ff8d1e07000     0x7ff8d1ea8000    0xa1000        0x0  rw-p   
      0x7ff8d1ea8000     0x7ff8d1ea9000     0x1000        0x0  ---p   
      0x7ff8d1ea9000     0x7ff8d1f4a000    0xa1000        0x0  rw-p   
      0x7ff8d1f4a000     0x7ff8d1f4b000     0x1000        0x0  ---p   
      0x7ff8d1f4b000     0x7ff8d1fec000    0xa1000        0x0  rw-p   
      0x7ff8d1fec000     0x7ff8d1fed000     0x1000        0x0  ---p   
      0x7ff8d1fed000     0x7ff8d208e000    0xa1000        0x0  rw-p   
      0x7ff8d208e000     0x7ff8d208f000     0x1000        0x0  ---p   
      0x7ff8d208f000     0x7ff8d2130000    0xa1000        0x0  rw-p   
      0x7ff8d2130000     0x7ff8d2131000     0x1000        0x0  ---p   
      0x7ff8d2131000     0x7ff8d21d2000    0xa1000        0x0  rw-p   
      0x7ff8d21d2000     0x7ff8d21d3000     0x1000        0x0  ---p   
      0x7ff8d21d3000     0x7ff8d2274000    0xa1000        0x0  rw-p   
      0x7ff8d2274000     0x7ff8d2275000     0x1000        0x0  ---p   
      0x7ff8d2275000     0x7ff8d2316000    0xa1000        0x0  rw-p   
      0x7ff8d2316000     0x7ff8d2317000     0x1000        0x0  ---p   
      0x7ff8d2317000     0x7ff8d23b8000    0xa1000        0x0  rw-p   
      0x7ff8d23b8000     0x7ff8d23b9000     0x1000        0x0  ---p   
      0x7ff8d23b9000     0x7ff8d245a000    0xa1000        0x0  rw-p   
      0x7ff8d245a000     0x7ff8d245b000     0x1000        0x0  ---p   
      0x7ff8d245b000     0x7ff8d24fc000    0xa1000        0x0  rw-p   
      0x7ff8d24fc000     0x7ff8d24fd000     0x1000        0x0  ---p   
      0x7ff8d24fd000     0x7ff8d259e000    0xa1000        0x0  rw-p   
      0x7ff8d259e000     0x7ff8d259f000     0x1000        0x0  ---p   
      0x7ff8d259f000     0x7ff8d2640000    0xa1000        0x0  rw-p   
      0x7ff8d26ff000     0x7ff8d2700000     0x1000        0x0  ---p   
      0x7ff8d2700000     0x7ff8d2800000   0x100000        0x0  rw-p   [stack]
      0x7ff8d2800000     0x7ff8d2a00000   0x200000        0x0  rwxp   
      0x7ff8d2a00000     0x7ff8d2a01000     0x1000        0x0  ---p   
      0x7ff8d2a01000     0x7ff8d3201000   0x800000        0x0  rw-p   [stack]
      0x7ff8d32c0000     0x7ff8d32d0000    0x10000        0x0  rw-p   
      0x7ff8d3300000     0x7ff8d3310000    0x10000        0x0  rw-p   
      0x7ff8d33d0000     0x7ff8ec800000 0x19430000        0x0  rw-p   
      0x7ff8ec810000     0x7ff8ec890000    0x80000        0x0  rw-p   
      0x7ff8ec89e000     0x7ff8eca00000   0x162000        0x0  rw-p   
      0x7ff8eca00000     0x7ff8fa51d000  0xdb1d000        0x0  r--p   /usr/lib/locale/locale-archive
      0x7ff8fa52b000     0x7ff8fa553000    0x28000        0x0  r--p   /usr/lib64/libc.so.6
      0x7ff8fa553000     0x7ff8fa6c0000   0x16d000    0x28000  r-xp   /usr/lib64/libc.so.6
      0x7ff8fa6c0000     0x7ff8fa70e000    0x4e000   0x195000  r--p   /usr/lib64/libc.so.6
      0x7ff8fa70e000     0x7ff8fa712000     0x4000   0x1e2000  r--p   /usr/lib64/libc.so.6
      0x7ff8fa712000     0x7ff8fa714000     0x2000   0x1e6000  rw-p   /usr/lib64/libc.so.6
      0x7ff8fa714000     0x7ff8fa71c000     0x8000        0x0  rw-p   
      0x7ff8fa71c000     0x7ff8fa72c000    0x10000        0x0  r--p   /usr/lib64/libm.so.6
      0x7ff8fa72c000     0x7ff8fa7a4000    0x78000    0x10000  r-xp   /usr/lib64/libm.so.6
      0x7ff8fa7a4000     0x7ff8fa7fe000    0x5a000    0x88000  r--p   /usr/lib64/libm.so.6
      0x7ff8fa7fe000     0x7ff8fa7ff000     0x1000    0xe1000  r--p   /usr/lib64/libm.so.6
      0x7ff8fa7ff000     0x7ff8fa800000     0x1000    0xe2000  rw-p   /usr/lib64/libm.so.6
      0x7ff8fa800000     0x7ff8fa83e000    0x3e000        0x0  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/libruby.so.3.3.2
      0x7ff8fa83e000     0x7ff8fab83000   0x345000    0x3e000  r-xp   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/libruby.so.3.3.2
      0x7ff8fab83000     0x7ff8facd6000   0x153000   0x383000  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/libruby.so.3.3.2
      0x7ff8facd6000     0x7ff8face3000     0xd000   0x4d5000  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/libruby.so.3.3.2
      0x7ff8face3000     0x7ff8face7000     0x4000   0x4e2000  rw-p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/libruby.so.3.3.2
      0x7ff8face7000     0x7ff8facfb000    0x14000        0x0  rw-p   
      0x7ff8facfc000     0x7ff8facfd000     0x1000        0x0  r-xp   
      0x7ff8facfe000     0x7ff8facff000     0x1000        0x0  r-xp   
      0x7ff8fad10000     0x7ff8fad55000    0x45000        0x0  rw-p   
      0x7ff8fad55000     0x7ff8fad56000     0x1000        0x0  r--p   /usr/lib64/libcrypt.so.2.0.0
      0x7ff8fad56000     0x7ff8fad6a000    0x14000     0x1000  r-xp   /usr/lib64/libcrypt.so.2.0.0
      0x7ff8fad6a000     0x7ff8fad83000    0x19000    0x15000  r--p   /usr/lib64/libcrypt.so.2.0.0
      0x7ff8fad83000     0x7ff8fad84000     0x1000    0x2d000  r--p   /usr/lib64/libcrypt.so.2.0.0
      0x7ff8fad84000     0x7ff8fad8d000     0x9000        0x0  rw-p   
      0x7ff8fad8d000     0x7ff8fad8f000     0x2000        0x0  r--p   /usr/lib64/libz.so.1.3.1.zlib-ng
      0x7ff8fad8f000     0x7ff8fada5000    0x16000     0x2000  r-xp   /usr/lib64/libz.so.1.3.1.zlib-ng
      0x7ff8fada5000     0x7ff8fadac000     0x7000    0x18000  r--p   /usr/lib64/libz.so.1.3.1.zlib-ng
      0x7ff8fadac000     0x7ff8fadad000     0x1000    0x1f000  r--p   /usr/lib64/libz.so.1.3.1.zlib-ng
      0x7ff8fadad000     0x7ff8fadae000     0x1000    0x20000  rw-p   /usr/lib64/libz.so.1.3.1.zlib-ng
      0x7ff8fadae000     0x7ff8fadaf000     0x1000        0x0  r--p   /usr/lib64/libdl.so.2
      0x7ff8fadaf000     0x7ff8fadb0000     0x1000     0x1000  r-xp   /usr/lib64/libdl.so.2
      0x7ff8fadb0000     0x7ff8fadb1000     0x1000     0x2000  r--p   /usr/lib64/libdl.so.2
      0x7ff8fadb1000     0x7ff8fadb2000     0x1000     0x2000  r--p   /usr/lib64/libdl.so.2
      0x7ff8fadb2000     0x7ff8fadb3000     0x1000        0x0  rw-p   
      0x7ff8fadb5000     0x7ff8fadb7000     0x2000        0x0  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/etc.so
      0x7ff8fadb7000     0x7ff8fadba000     0x3000     0x2000  r-xp   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/etc.so
      0x7ff8fadba000     0x7ff8fadbc000     0x2000     0x5000  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/etc.so
      0x7ff8fadbc000     0x7ff8fadbd000     0x1000     0x6000  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/etc.so
      0x7ff8fadbd000     0x7ff8fadbe000     0x1000     0x7000  rw-p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/etc.so
      0x7ff8fadbe000     0x7ff8fadbf000     0x1000        0x0  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/enc/trans/transdb.so
      0x7ff8fadbf000     0x7ff8fadc0000     0x1000     0x1000  r-xp   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/enc/trans/transdb.so
      0x7ff8fadc0000     0x7ff8fadc1000     0x1000     0x2000  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/enc/trans/transdb.so
      0x7ff8fadc1000     0x7ff8fadc2000     0x1000     0x2000  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/enc/trans/transdb.so
      0x7ff8fadc2000     0x7ff8fadc3000     0x1000     0x3000  rw-p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/enc/trans/transdb.so
      0x7ff8fadc3000     0x7ff8fadc4000     0x1000        0x0  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/enc/encdb.so
      0x7ff8fadc4000     0x7ff8fadc5000     0x1000     0x1000  r-xp   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/enc/encdb.so
      0x7ff8fadc5000     0x7ff8fadc6000     0x1000     0x2000  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/enc/encdb.so
      0x7ff8fadc6000     0x7ff8fadc7000     0x1000     0x2000  r--p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/enc/encdb.so
      0x7ff8fadc7000     0x7ff8fadc8000     0x1000     0x3000  rw-p   /home/kjtsanaktsidis/.rbenv/versions/3.3.2/lib/ruby/3.3.0/x86_64-linux/enc/encdb.so
      0x7ff8fadc8000     0x7ff8fadc9000     0x1000        0x0  r--p   /usr/local/lib64/rr/librrpreload.so
      0x7ff8fadc9000     0x7ff8fadd1000     0x8000     0x1000  r-xp   /usr/local/lib64/rr/librrpreload.so
      0x7ff8fadd1000     0x7ff8fadd4000     0x3000     0x9000  r--p   /usr/local/lib64/rr/librrpreload.so
      0x7ff8fadd4000     0x7ff8fadd5000     0x1000     0xb000  r--p   /usr/local/lib64/rr/librrpreload.so
      0x7ff8fadd5000     0x7ff8fadd6000     0x1000     0xc000  rw-p   /usr/local/lib64/rr/librrpreload.so
      0x7ff8fadd6000     0x7ff8fade2000     0xc000        0x0  rw-p   
      0x7ff8fade2000     0x7ff8fade4000     0x2000        0x0  r-xp   [vdso]
      0x7ff8fade4000     0x7ff8fade5000     0x1000        0x0  r--p   /usr/lib64/ld-linux-x86-64.so.2
      0x7ff8fade5000     0x7ff8fae0d000    0x28000     0x1000  r-xp   /usr/lib64/ld-linux-x86-64.so.2
      0x7ff8fae0d000     0x7ff8fae17000     0xa000    0x29000  r--p   /usr/lib64/ld-linux-x86-64.so.2
      0x7ff8fae17000     0x7ff8fae19000     0x2000    0x33000  r--p   /usr/lib64/ld-linux-x86-64.so.2
      0x7ff8fae19000     0x7ff8fae1b000     0x2000    0x35000  rw-p   /usr/lib64/ld-linux-x86-64.so.2
      0x7ffc1e7ab000     0x7ffc1ef87000   0x7dc000        0x0  rw-p   
      0x7ffc1ef87000     0x7ffc1efaa000    0x23000        0x0  rw-p   [stack]
      0xffffffffff600000 0xffffffffff601000     0x1000        0x0  --xp   [vsyscall]

Also, based on the steps in #3325 (comment), I also applied a similar patch to my rr:

diff --git a/src/RecordTask.cc b/src/RecordTask.cc
index fdbe2ee0..26cba395 100644
--- a/src/RecordTask.cc
+++ b/src/RecordTask.cc
@@ -1751,6 +1751,7 @@ void RecordTask::record_remote_writable(remote_ptr<void> addr,
   remote_ptr<void> p = addr;
   bool seen_rr_mapping = false;
   int mapping_count = 0;
+  cerr << "record_remote_writable params " << addr << " " << num_bytes << "\n";
   while (p < addr + num_bytes) {
     if (!as->has_mapping(p)) {
       break;
@@ -1760,6 +1761,8 @@ void RecordTask::record_remote_writable(remote_ptr<void> addr,
     if (m.flags) {
       seen_rr_mapping = true;
     }
+    cerr << "record_remote_writable " << m.map << "\n";
+    cerr << "record_remote_writable seen_rr_mapping " << seen_rr_mapping << "\n";
     if (!(m.map.prot() & PROT_WRITE) ||
         (seen_rr_mapping && mapping_count > 1)) {
       break;
@@ -1768,6 +1771,7 @@ void RecordTask::record_remote_writable(remote_ptr<void> addr,
   }
   num_bytes = min(num_bytes, p - addr);
 
+  cerr << "record_remote_writable num_bytes " << num_bytes << "\n";
   record_remote(addr, num_bytes);
 }

This is the output I get with it (both record and replay): https://gist.github.com/KJTsanaktsidis/24cf028f25e7c511b5deee3e62643dd4 (n.b. ignore the crashing Ruby process/stack trace it prints out; that's the issue I wanted to debug, but I got distracted by this instead!).

Also, my machine:

/proc/cpuinfo
processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 140
model name	: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
stepping	: 1
microcode	: 0xb4
cpu MHz		: 1090.595
cache size	: 12288 KB
physical id	: 0
siblings	: 8
core id		: 0
cpu cores	: 4
apicid		: 0
initial apicid	: 0
fpu		: yes
fpu_exception	: yes
cpuid level	: 27
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l2 cdp_l2 ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb intel_pt avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves split_lock_detect user_shstk dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req vnmi avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid movdiri movdir64b fsrm avx512_vp2intersect md_clear ibt flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple pml ept_mode_based_exec tsc_scaling
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb gds bhi
bogomips	: 5606.40
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 1
vendor_id	: GenuineIntel
cpu family	: 6
model		: 140
model name	: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
stepping	: 1
microcode	: 0xb4
cpu MHz		: 712.230
cache size	: 12288 KB
physical id	: 0
siblings	: 8
core id		: 1
cpu cores	: 4
apicid		: 2
initial apicid	: 2
fpu		: yes
fpu_exception	: yes
cpuid level	: 27
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l2 cdp_l2 ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb intel_pt avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves split_lock_detect user_shstk dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req vnmi avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid movdiri movdir64b fsrm avx512_vp2intersect md_clear ibt flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple pml ept_mode_based_exec tsc_scaling
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb gds bhi
bogomips	: 5606.40
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 2
vendor_id	: GenuineIntel
cpu family	: 6
model		: 140
model name	: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
stepping	: 1
microcode	: 0xb4
cpu MHz		: 1100.011
cache size	: 12288 KB
physical id	: 0
siblings	: 8
core id		: 2
cpu cores	: 4
apicid		: 4
initial apicid	: 4
fpu		: yes
fpu_exception	: yes
cpuid level	: 27
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l2 cdp_l2 ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb intel_pt avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves split_lock_detect user_shstk dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req vnmi avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid movdiri movdir64b fsrm avx512_vp2intersect md_clear ibt flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple pml ept_mode_based_exec tsc_scaling
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb gds bhi
bogomips	: 5606.40
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 3
vendor_id	: GenuineIntel
cpu family	: 6
model		: 140
model name	: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
stepping	: 1
microcode	: 0xb4
cpu MHz		: 1100.022
cache size	: 12288 KB
physical id	: 0
siblings	: 8
core id		: 3
cpu cores	: 4
apicid		: 6
initial apicid	: 6
fpu		: yes
fpu_exception	: yes
cpuid level	: 27
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l2 cdp_l2 ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb intel_pt avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves split_lock_detect user_shstk dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req vnmi avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid movdiri movdir64b fsrm avx512_vp2intersect md_clear ibt flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple pml ept_mode_based_exec tsc_scaling
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb gds bhi
bogomips	: 5606.40
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 4
vendor_id	: GenuineIntel
cpu family	: 6
model		: 140
model name	: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
stepping	: 1
microcode	: 0xb4
cpu MHz		: 1100.000
cache size	: 12288 KB
physical id	: 0
siblings	: 8
core id		: 0
cpu cores	: 4
apicid		: 1
initial apicid	: 1
fpu		: yes
fpu_exception	: yes
cpuid level	: 27
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l2 cdp_l2 ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb intel_pt avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves split_lock_detect user_shstk dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req vnmi avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid movdiri movdir64b fsrm avx512_vp2intersect md_clear ibt flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple pml ept_mode_based_exec tsc_scaling
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb gds bhi
bogomips	: 5606.40
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 5
vendor_id	: GenuineIntel
cpu family	: 6
model		: 140
model name	: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
stepping	: 1
microcode	: 0xb4
cpu MHz		: 1100.000
cache size	: 12288 KB
physical id	: 0
siblings	: 8
core id		: 1
cpu cores	: 4
apicid		: 3
initial apicid	: 3
fpu		: yes
fpu_exception	: yes
cpuid level	: 27
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l2 cdp_l2 ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb intel_pt avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves split_lock_detect user_shstk dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req vnmi avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid movdiri movdir64b fsrm avx512_vp2intersect md_clear ibt flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple pml ept_mode_based_exec tsc_scaling
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb gds bhi
bogomips	: 5606.40
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 6
vendor_id	: GenuineIntel
cpu family	: 6
model		: 140
model name	: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
stepping	: 1
microcode	: 0xb4
cpu MHz		: 400.000
cache size	: 12288 KB
physical id	: 0
siblings	: 8
core id		: 2
cpu cores	: 4
apicid		: 5
initial apicid	: 5
fpu		: yes
fpu_exception	: yes
cpuid level	: 27
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l2 cdp_l2 ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb intel_pt avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves split_lock_detect user_shstk dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req vnmi avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid movdiri movdir64b fsrm avx512_vp2intersect md_clear ibt flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple pml ept_mode_based_exec tsc_scaling
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb gds bhi
bogomips	: 5606.40
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

processor	: 7
vendor_id	: GenuineIntel
cpu family	: 6
model		: 140
model name	: 11th Gen Intel(R) Core(TM) i7-1165G7 @ 2.80GHz
stepping	: 1
microcode	: 0xb4
cpu MHz		: 1054.382
cache size	: 12288 KB
physical id	: 0
siblings	: 8
core id		: 3
cpu cores	: 4
apicid		: 7
initial apicid	: 7
fpu		: yes
fpu_exception	: yes
cpuid level	: 27
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx pdpe1gb rdtscp lm constant_tsc art arch_perfmon pebs bts rep_good nopl xtopology nonstop_tsc cpuid aperfmperf tsc_known_freq pni pclmulqdq dtes64 monitor ds_cpl vmx est tm2 ssse3 sdbg fma cx16 xtpr pdcm pcid sse4_1 sse4_2 x2apic movbe popcnt tsc_deadline_timer aes xsave avx f16c rdrand lahf_lm abm 3dnowprefetch cpuid_fault epb cat_l2 cdp_l2 ssbd ibrs ibpb stibp ibrs_enhanced tpr_shadow flexpriority ept vpid ept_ad fsgsbase tsc_adjust bmi1 avx2 smep bmi2 erms invpcid rdt_a avx512f avx512dq rdseed adx smap avx512ifma clflushopt clwb intel_pt avx512cd sha_ni avx512bw avx512vl xsaveopt xsavec xgetbv1 xsaves split_lock_detect user_shstk dtherm ida arat pln pts hwp hwp_notify hwp_act_window hwp_epp hwp_pkg_req vnmi avx512vbmi umip pku ospke avx512_vbmi2 gfni vaes vpclmulqdq avx512_vnni avx512_bitalg avx512_vpopcntdq rdpid movdiri movdir64b fsrm avx512_vp2intersect md_clear ibt flush_l1d arch_capabilities
vmx flags	: vnmi preemption_timer posted_intr invvpid ept_x_only ept_ad ept_1gb flexpriority apicv tsc_offset vtpr mtf vapic ept vpid unrestricted_guest vapic_reg vid ple pml ept_mode_based_exec tsc_scaling
bugs		: spectre_v1 spectre_v2 spec_store_bypass swapgs eibrs_pbrsb gds bhi
bogomips	: 5606.40
clflush size	: 64
cache_alignment	: 64
address sizes	: 39 bits physical, 48 bits virtual
power management:

Thanks for taking a look at this :) If I can do anything to debug this further please let me know!

@KJTsanaktsidis
Copy link
Contributor Author

KJTsanaktsidis commented Jul 11, 2024

So, I did a bit more digging - the problem seems to be that two threads have their rr scratch mappings right next to each other. From my output gist:

#2 test_ractor.rb:7 record_remote_writable params 0x7fc98f7ff0f8 3976
record_remote_writable 0x7fc98f600000-0x7fc98fa00000 rwxp 00000000 00:00 0          
record_remote_writable seen_rr_mapping 0
record_remote_writable num_bytes 3976
. 0.047
#3 test_ractor.rb:12 record_remote_writable params 0x7fc98f5ff0f8 3976
record_remote_writable 0x7fc98f400000-0x7fc98fa00000 rwxp 00000000 00:00 0          
record_remote_writable seen_rr_mapping 0
record_remote_writable num_bytes 3976

the mapping is an RR scratch mapping (it's rwxp) but it's gown from 0x7fc98f600000-0x7fc98fa00000 (0x400000 bytes) to 0x7fc98f400000-0x7fc98fa00000 (0x600000 bytes). So I guess the kernel merged the VMA's for RR's scratch regions together and so writes off the end of it don't actually get stopped.

I actually managed to fix this I think, with this patch, which whacks an extra guard page at the end of the scratch mapping. This was actually discussed in #3325 -

@khuey: Can we stick a PROT_NONE guard page before the syscallbuf?
@rocallahan: Yeah we could but we don't need to, I think

diff --git a/src/Task.cc b/src/Task.cc
index ea3ec348..0676ce94 100644
--- a/src/Task.cc
+++ b/src/Task.cc
@@ -455,9 +455,11 @@ void Task::unmap_buffers_for(
     AutoRemoteSyscalls& remote, Task* other,
     remote_ptr<struct syscallbuf_hdr> saved_syscallbuf_child) {
   if (other->scratch_ptr) {
+    // Unmap one more page at the end of scratch_ptr, which is a guard page
     if (remote.infallible_munmap_syscall_if_alive(
-          other->scratch_ptr, other->scratch_size)) {
+          other->scratch_ptr, other->scratch_size + page_size())) {
       vm()->unmap(this, other->scratch_ptr, other->scratch_size);
+      vm()->unmap(this, other->scratch_ptr + other->scratch_size, page_size());
     }
   }
   if (!saved_syscallbuf_child.is_null()) {
diff --git a/src/record_syscall.cc b/src/record_syscall.cc
index 4817818e..e4300009 100644
--- a/src/record_syscall.cc
+++ b/src/record_syscall.cc
@@ -3343,7 +3343,8 @@ static const uintptr_t FIXED_SCRATCH_PTR = 0x68000000;
 static void init_scratch_memory(RecordTask* t,
                                 ScratchAddrType addr_type = DYNAMIC_ADDRESS) {
   const int scratch_size = 512 * page_size();
-  size_t sz = scratch_size;
+  // Allocate one more page off the end of the scratch as a guard page
+  size_t sz = scratch_size + page_size();
   // The PROT_EXEC looks scary, and it is, but it's to prevent
   // this region from being coalesced with another anonymous
   // segment mapped just after this one.  If we named this
@@ -3363,6 +3364,10 @@ static void init_scratch_memory(RecordTask* t,
                                                   sz, prot, flags | MAP_FIXED, -1, 0);
     }
     t->scratch_size = scratch_size;
+
+    // mprotect the extra page we allocated as a guard page
+    remote.infallible_syscall_if_alive(syscall_number_for_mprotect(remote.arch()),
+                                       t->scratch_ptr + t->scratch_size, page_size(), PROT_NONE);
   }
 
   t->setup_preload_thread_locals();
@@ -3373,11 +3378,20 @@ static void init_scratch_memory(RecordTask* t,
   r.set_syscall_result(t->scratch_ptr);
   t->set_regs(r);
 
-  KernelMapping km =
-      t->vm()->map(t, t->scratch_ptr, sz, prot, flags, 0, string());
   struct stat stat;
   memset(&stat, 0, sizeof(stat));
+
+  // Important that the guard page goes first into the recording; lots of things (e.g.
+  // prepare_clone and process_execve) depend on this order
+  KernelMapping km_guard =
+      t->vm()->map(t, t->scratch_ptr + t->scratch_size, page_size(), PROT_NONE, flags, 0, string());
   auto record_in_trace = t->trace_writer().write_mapped_region(t,
+    km_guard, stat, km_guard.fsname(), vector<TraceRemoteFd>());
+  ASSERT(t, record_in_trace == TraceWriter::DONT_RECORD_IN_TRACE);
+
+  KernelMapping km =
+      t->vm()->map(t, t->scratch_ptr, t->scratch_size, prot, flags, 0, string());
+  record_in_trace = t->trace_writer().write_mapped_region(t,
     km, stat, km.fsname(), vector<TraceRemoteFd>());
   ASSERT(t, record_in_trace == TraceWriter::DONT_RECORD_IN_TRACE);
 
diff --git a/src/replay_syscall.cc b/src/replay_syscall.cc
index 6a102497..9d324bb3 100644
--- a/src/replay_syscall.cc
+++ b/src/replay_syscall.cc
@@ -312,6 +312,13 @@ template <typename Arch> static void prepare_clone(ReplayTask* t) {
 
   TraceReader::MappedData data;
   KernelMapping km = t->trace_reader().read_mapped_region(&data);
+  // Skip past guard page
+  if (km.prot() == 0) {
+    bool found;
+    km = t->trace_reader().read_mapped_region(&data, &found);
+    ASSERT(t, found) << "Could not find scratch memory mapping after clone";
+  }
+
   init_scratch_memory(new_task, km, data);
 }

I'm hesitant to open up a PR with this because I don't really understand why the signal handler frame is running 80 bytes past the end of the syscallbuffer, but this patch does seem to fix my problem so hopefully that's instructive to people who do get how this all works?

KJTsanaktsidis added a commit to KJTsanaktsidis/rr that referenced this issue Jul 11, 2024
@khuey
Copy link
Collaborator

khuey commented Jul 11, 2024

Hmm, so the issue here is that we read/write off the end of the buffer (because our signal handler stack frame size is a conservative estimate), and then the mapping beyond exists during recording but doesn't during replay?

@KJTsanaktsidis
Copy link
Contributor Author

Yes, that’s what is implied by the logs printed during recording by the couts I added, I think

@khuey khuey self-assigned this Jul 11, 2024
@khuey
Copy link
Collaborator

khuey commented Jul 11, 2024

In the original trace at the top of the issue the scratch buffer of tid 20517 (cloned from 20235) is placed at 0x7ff8cbc00000 at event 66034. Earlier at event 65800 tid 20235 vforks to tid 20516 and it's scratch buffer is placed at 0x7ff8cbe00000. 20516 then execves at 65952. The vfork returns at event 66032 (i.e. immediately before tid 20517 is created). I suspect the vfork/execve is relevant here.

@khuey
Copy link
Collaborator

khuey commented Jul 12, 2024

I don't see why the scratch buffer at 0x7ff8cbe00000 would be hanging around though. I can't reproduce this in a simple example, and I would expect that this code

rr/src/Task.cc

Lines 1062 to 1070 in 77f88f4

for (Task* t : as->task_set()) {
if (t != this) {
other_task_in_address_space = true;
if (t->is_stopped_) {
stopped_task_in_address_space = t;
break;
}
}
}
always finds a stopped task to use for unmapping buffers, namely the task that called vfork(2).

@khuey
Copy link
Collaborator

khuey commented Jul 12, 2024

I don't think we actually want a PROT_NONE guard page here. It would mean consuming an additional VMA per thread increasing our overhead for large processes.

@KJTsanaktsidis
Copy link
Contributor Author

I suspect the vfork/execve is relevant here.

I changed Ruby (the program under test) to call fork instead of vfork and the problem went away, so I think you're onto something.

I don't think we actually want a PROT_NONE guard page here. It would mean consuming an additional VMA per thread increasing our overhead for large processes.

I agree. What I actually wanted to do first was name the VMA with PR_SET_VMA_ANON_NAME, but my distro's kernel (Fedora) doesn't have CONFIG_ANON_VMA_NAME. It would be nice if distros enabled this though.

I would expect that this code always finds a stopped task to use for unmapping buffers, namely the task that called vfork(2).

I don't think I'm seeing the warnings that prints, but I'll add some extra logging around there and see if anything interesting turns up.

@KJTsanaktsidis
Copy link
Contributor Author

Oh no, I spoke to soon. When recording with --log=all:warn, I see quite a lot of this:

#89 test_ractor.rb:1444 [WARN post_exec()] Intentionally leaking syscallbuf after exec for task 52530
. 0.061
#90 test_ractor.rb:1452 [WARN post_exec()] Intentionally leaking syscallbuf after exec for task 52535
. 0.074
#91 test_ractor.rb:1470 [WARN post_exec()] Intentionally leaking syscallbuf after exec for task 52540
. 0.573

So this is happening.

@KJTsanaktsidis
Copy link
Contributor Author

KJTsanaktsidis commented Jul 12, 2024

I would expect that this code always finds a stopped task to use for unmapping buffers, namely the task that called vfork(2).

That task seems to be explicitly excluded because of if (t != this) right?

EDIT: Sorry, you mean the task that called vfork; this is the task that was created because of it.

@khuey
Copy link
Collaborator

khuey commented Jul 12, 2024

Right. this is the vfork()ee and the vfork()er should be around (and stopped in the vfork syscall) to be used to unmap the buffers.

@khuey
Copy link
Collaborator

khuey commented Jul 12, 2024

Does this fix your issue?

diff --git a/src/AddressSpace.h b/src/AddressSpace.h
index 2eae98a3..cb095623 100644
--- a/src/AddressSpace.h
+++ b/src/AddressSpace.h
@@ -315,6 +315,8 @@ public:
       IS_RR_PAGE = 0x8,
       // This mapping is the rr vdso page
       IS_RR_VDSO_PAGE = 0x10,
+      // This mapping is the per-thread scratch space.
+      IS_SCRATCH = 0x20,
     };
     uint32_t flags;
   };
diff --git a/src/record_syscall.cc b/src/record_syscall.cc
index 4817818e..a74b24fd 100644
--- a/src/record_syscall.cc
+++ b/src/record_syscall.cc
@@ -3375,6 +3375,7 @@ static void init_scratch_memory(RecordTask* t,

   KernelMapping km =
       t->vm()->map(t, t->scratch_ptr, sz, prot, flags, 0, string());
+  t->vm()->mapping_flags_of(t->scratch_ptr) |= AddressSpace::Mapping::IS_SCRATCH;
   struct stat stat;
   memset(&stat, 0, sizeof(stat));
   auto record_in_trace = t->trace_writer().write_mapped_region(t,

@KJTsanaktsidis
Copy link
Contributor Author

I have no idea how, but yes that does fix my issue!

KJTsanaktsidis added a commit to KJTsanaktsidis/rr that referenced this issue Jul 12, 2024
@khuey
Copy link
Collaborator

khuey commented Jul 12, 2024

I have no idea how

Setting the IS_SCRATCH flag causes seen_rr_mapping in RecordTask::record_remote_writable to get set which limits it to that first mapping and doesn't allow it to run off into the next one.

but yes that does fix my issue!

Cool.

I still don't understand why the scratch buffer is leaked in this particular case but given that there are certainly general cases where they can leak I think we need to take something like this.

@KJTsanaktsidis
Copy link
Contributor Author

Ah - I see, this check becomes true -

if (m.flags) {
. Thanks for fixing this, and thanks also for explaining it to me!

@rocallahan
Copy link
Collaborator

One way to fix this would be for the callers of record_remote_writable() --- or at least the signal_state_changed() caller --- to compare the contents of the tail of the potentially-written memory region before and after the kernel writes to the memory. We could limit the memory range that we record to exclude the tail of unchanged bytes. The problem with this is that due to sigaltstack() it's not trivial to predict before we enter a signal handler where the sigframe is actually going to be written :-(.

(Also, in the absence of sigaltstack() we could compare SP before and after enter the signal handler to get a bound on the sigframe size.)

I'd really prefer to avoid having to track sigaltstack() state, partly because currently sigaltstack() is syscall-buffered so that would require additional complexity.

@rocallahan
Copy link
Collaborator

One thing that might work well enough is to add a flag to MemWrite to indicate that we didn't know the correct size. Then when we replay those writes, if the write extends into unmapped memory, don't treat that as fatal, just drop the extra data.

@KJTsanaktsidis
Copy link
Contributor Author

It sounds like you're proposing:

  • Add a new flag to the MemWrite capn proto struct
  • Set that flag on the sigframe write which is recorded here:
    t->record_remote_writable(t->regs().sp(), sigframe_size);
  • When replaying memory writes, make this assertion non-fatal if that flag is set:

    rr/src/Task.cc

    Lines 3267 to 3269 in 03f6446

    ASSERT(this, nwritten == buf_size)
    << "Should have written " << buf_size << " bytes to " << addr
    << ", but only wrote " << nwritten;

However, if the only place we think this can happen is in the EV_SIGNAL event, what if we just made the replay skip the assertion, if the write comes through here:

t->apply_data_record_from_trace();
?

I'm happy to have a go at implementing either of these. I'm definitely not very knowledgeable about all this stuff though, so apologies if I've said something dumb!

@rocallahan
Copy link
Collaborator

However, if the only place we think this can happen is in the EV_SIGNAL event, what if we just made the replay skip the assertion, if the write comes through here:

Yes, that should work. There is another use of record_remote_writable though where that won't work. But maybe that's not worth worrying about in practice. We can do what you're suggesting and then do the more general fix later if we need to. Thanks!

@KJTsanaktsidis
Copy link
Contributor Author

I opened a PR for this #3800. Let me know what you think - I don't write much C++ so some of my taste is pretty awful!.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
3 participants