[GHC] #11337: Unwind information incorrect between Sp adjustment and end of block
#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) | Keywords: | Operating System: Unknown/Multiple Architecture: | Type of failure: None/Unknown Unknown/Multiple | Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- 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 works reasonably well in most cases since we most Cmm blocks have the form, {{{ 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> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#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 works reasonably well in most cases since we most Cmm blocks have the form, {{{ 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:1> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#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
#11337: Unwind information incorrect between Sp adjustment and end of block -------------------------------------+------------------------------------- Reporter: bgamari | Owner: bgamari 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: | -------------------------------------+------------------------------------- Changes (by bgamari): * owner: => bgamari -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11337#comment:3> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#11337: Unwind information incorrect between Sp adjustment and end of block -------------------------------------+------------------------------------- Reporter: bgamari | Owner: bgamari 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: | -------------------------------------+------------------------------------- Comment (by bgamari): In principle this ought not to be too hard to fix: 1. Fix `CmmLayoutStack.maybeAddSpAdj` to add a `CmmUnwind` node after the `CmmAssign`. 2. Fix `Debug.extractUnwind` to properly emit tables for all unwind nodes in a block. -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11337#comment:4> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#11337: Unwind information incorrect between Sp adjustment and end of block -------------------------------------+------------------------------------- Reporter: bgamari | Owner: bgamari Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.3 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Debugging | Unknown/Multiple information is incorrect | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * failure: None/Unknown => Debugging information is incorrect -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11337#comment:5> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#11337: Unwind information incorrect between Sp adjustment and end of block -------------------------------------+------------------------------------- Reporter: bgamari | Owner: bgamari Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.3 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Debugging | Unknown/Multiple information is incorrect | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by simonmar): * cc: simonmar (added) -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11337#comment:6> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#11337: Unwind information incorrect between Sp adjustment and end of block -------------------------------------+------------------------------------- Reporter: bgamari | Owner: bgamari Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 7.10.3 (CodeGen) | Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Debugging | Unknown/Multiple information is incorrect | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Ben Gamari <ben@…>): In [changeset:"3eb737ee3f900f256a7474b199a4ab40178a8cac/ghc" 3eb737e/ghc]: {{{ #!CommitTicketReference repository="ghc" revision="3eb737ee3f900f256a7474b199a4ab40178a8cac" Generalize CmmUnwind and pass unwind information through NCG As discussed in D1532, Trac Trac #11337, and Trac Trac #11338, the stack unwinding information produced by GHC is currently quite approximate. Essentially we assume that register values do not change at all within a basic block. While this is somewhat true in normal Haskell code, blocks containing foreign calls often break this assumption. This results in unreliable call stacks, especially in the code containing foreign calls. This is worse than it sounds as unreliable unwinding information can at times result in segmentation faults. This patch set attempts to improve this situation by tracking unwinding information with finer granularity. By dispensing with the assumption of one unwinding table per block, we allow the compiler to accurately represent the areas surrounding foreign calls. Towards this end we generalize the representation of unwind information in the backend in three ways, * Multiple CmmUnwind nodes can occur per block * CmmUnwind nodes can now carry unwind information for multiple registers (while not strictly necessary; this makes emitting unwinding information a bit more convenient in the compiler) * The NCG backend is given an opportunity to modify the unwinding records since it may need to make adjustments due to, for instance, native calling convention requirements for foreign calls (see #11353). This sets the stage for resolving #11337 and #11338. Test Plan: Validate Reviewers: scpmw, simonmar, austin, erikd Subscribers: qnikst, thomie Differential Revision: https://phabricator.haskell.org/D2741 }}} -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11337#comment:7> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#11337: Unwind information incorrect between Sp adjustment and end of block -------------------------------------+------------------------------------- Reporter: bgamari | Owner: bgamari Type: bug | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 7.10.3 (CodeGen) | Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Debugging | Unknown/Multiple information is incorrect | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * status: new => closed * resolution: => fixed -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11337#comment:8> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#11337: Unwind information incorrect between Sp adjustment and end of block -------------------------------------+------------------------------------- Reporter: bgamari | Owner: bgamari Type: bug | Status: closed Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 7.10.3 (CodeGen) | Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Debugging | Unknown/Multiple information is incorrect | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * milestone: => 8.2.1 -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11337#comment:9> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
#11337: Unwind information incorrect between Sp adjustment and end of block -------------------------------------+------------------------------------- Reporter: bgamari | Owner: bgamari Type: bug | Status: closed Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 7.10.3 (CodeGen) | Resolution: fixed | Keywords: DWARF Operating System: Unknown/Multiple | Architecture: Type of failure: Debugging | Unknown/Multiple information is incorrect | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by bgamari): * keywords: => DWARF -- Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/11337#comment:10> GHC <http://www.haskell.org/ghc/> The Glasgow Haskell Compiler
participants (1)
-
GHC