drbbdup shifts drreg restore before non-cti block end, breaking rseq mangling
I hit this when using drbbdup for more things in drmemtrace and running larger apps that use rseq. These app reliably crash with SIGSEGV due to register corruption because drreg-reserved registers are not restored prior to the copy of the natively-executed app rseq sequence.
rseq mangling says:
/* We assume that by making this a block end, clients will restore app state
* before this native invocation.
* TODO i#2350: Take some further action to better guarantee this in the face
* of future drreg optimizations, etc. Do we need new interface features, or
* do we live with a fake app jump or sthg?
*/
rseq truncates blocks after stores, so there is no cti or syscall at the end. drbbdup disables drreg restore before the last instr:
drreg_set_bb_properties(drcontext, DRREG_USER_RESTORES_AT_BB_END);
In a non-drbbdup block, drreg inserts before the last app instr, while bbdup inserts before the inserted jump or exit label for the end of the bb copy: so after the last app instr, when there's no ending cti/syscall.
How to solve? Have DR insert a label "DR_NOTE_SPILL_BARRIER" that drreg looks for? We already do this for DR_NOTE_ANNOTATION so this type of solution has precedence. Xref #5160 on potential refactoring to put drreg into the core.