trace signal placement in rseq region is wrong due to abort handler redirect
Gathering an offline drcachesim trace on the rseq test, for #4019 (closed), shows a signal marker too late -- it should be right after the ud2a:
$ bin64/drrun -t drcachesim -offline -- suite/tests/bin/linux.rseq
$ bin64/drrun -t drcachesim -simulator_type view -indir drmemtrace.linux.rseq.123467.3754.dir/
=>
0x00007f7a6c9e78f3 0f 0b ud2a
0x00007f7a6c9e78f5 83 05 4c 38 00 00 01 addl $0x01, <rel> 0x00007f7a6c9eb148
<marker: kernel xfer to handler>
<marker: timestamp 13223619762485105>
<marker: tid 123467 on core 0>
0x00007f7a6c9e785c 55 push %rbp
<...>
<marker: syscall xfer>
<marker: timestamp 13223619762492787>
<marker: tid 123467 on core 0>
0x00007f7a6c9e7901 83 05 44 38 00 00 01 addl $0x01, <rel> 0x00007f7a6c9eb14c
0x00007f7a6c9e7908 c6 05 41 38 00 00 00 movb $0x00, <rel> 0x00007f7a6c9eb150
This is caught by the invariants test, which I was hoping to add as a regression test for #4019 (closed):
$ bin64/drrun -t drcachesim -offline -- suite/tests/bin/linux.rseq
$ bin64/drrun -t drcachesim -test_mode -indir drmemtrace.linux.rseq.123467.3754.dir/
drcachesim: /home/bruening/dr/git/src/clients/drcachesim/tests/trace_invariants.cpp:143: virtual bool trace_invariants_t::process_memref(const memref_t&): Assertion `memref.instr.tid != pre_signal_instr.instr.tid || memref.instr.addr == pre_signal_instr.instr.addr || memref.instr.addr == pre_signal_instr.instr.addr + pre_signal_instr.instr.size || memref.instr.addr == app_handler_pc || type_is_instr_branch(pre_signal_instr.instr.type) || pre_signal_instr.instr.type == TRACE_TYPE_INSTR_SYSENTER' failed.
Aborted
Looks like the recorded offset is wrong:
[drmemtrace]: Appending 2 instrs in bb 0x7fcb228a48f3 in mod 5 +0x18f3 = /home/bruening/dr/git/build_x64_dbg_tests/suite/tests/bin/linux.rseq
0x00007fdb501da8f3 ud2a
[drmemtrace]: Checking whether reached signal/exception +0x1901 vs cur +0x18f3
0x00007fdb501da8f5 add $0x00000001 <rel> 0x00007fdb501de198[4byte] -> <rel> 0x00007fdb501de198[4byte]
[drmemtrace]: Checking whether reached signal/exception +0x1901 vs cur +0x18f5
[drmemtrace]: Filling in elided rip-rel addr with 0x7fdb501de198
[drmemtrace]: Appended memref type 0 size 4 to 0x7fdb501de198
[drmemtrace]: Checking whether reached signal/exception +0x1901 vs cur +0x18fc
[drmemtrace]: Filling in elided rip-rel addr with 0x7fdb501de198
[drmemtrace]: Appended memref type 1 size 4 to 0x7fdb501de198
[drmemtrace]: Checking whether reached signal/exception +0x1901 vs cur +0x18fc
[drmemtrace]: Signal/exception between bbs
[drmemtrace]: Appended marker type 0 value 0x1901
Ah here we go:
recreate_app : looking for 0x00007fdb103cf90b in frag @ 0x00007fdb103cf8d4 (tag 0x00007fdb501da8f3)
recreate_app -- found valid state pc 0x00007fdb501da8f3
translation 0x00007fdb501da8f3 is post-walk 0x0000000000000000 so not fixing xsp
recreate_app: moving 0x00007fdb501da8f3 inside rseq region to handler 0x00007fdb501da901
recreate_app -- found ok pc 0x00007fdb501da901
Hmm, how can we solve that? The kernel does not record the actual signal PC (unlike rseq v1), so DR does not either, and thus the tracer does not know when the signal was triggered.