
#11337: Unwind information incorrect between Sp adjustment and end of block -------------------------------------+------------------------------------- Reporter: bgamari | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.3 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Description changed by bgamari: Old description:
As pointed out in Phab: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.
New description: As pointed out in Phab: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. -- -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/11337#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler