Skip to content

Unwind information incorrect between Sp adjustment and end of block

As pointed out in D1532, the DWARF unwinding information that we produce is currently a bit oversimplified. Namely, we produce exactly one unwind table per Cmm block. This, however, produces subtly incorrect debug information,

aProcedure() {
casl:
    -- we just entered the procedure, so the unwinding is trivial.
    unwind Sp = Sp
    -- we push some values onto the stack...
    I64[Sp - 16] = ...
    I64[Sp - 8] = ...
    -- and before leaving the block we update Sp.
    Sp = Sp - 16;
    -- technically our unwind information is now a lie
    call aFunction() returns to casd;

casd:
    -- we inherit the unwind information from the state of the stack when we
    -- left the preceding block (casl)
    unwind Sp = Sp + 16
    R2 = I64[Sp + 8];
    -- pop off that which we pushed
    Sp = Sp + 16;
    call GHC.List.$wunsafeTake_info(R3, R2) args: 8, res: 0, upd: 8;
}

Here there is a narrow window where our unwind information is technically wrong: between updating Sp in casl and calling into aFunction.

Note that after we arrive in aFunction we are safe, since our return address is casd, which has the correct unwinding information.

Edited by Ben Gamari
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information