Skip to content

WIP: Export continuation symbols in x86 binaries in -g4 and above

Ömer Sinan Ağacan requested to merge osa1/ghc:global_cont_symbols into master

With this patch we can see names of continuations in stack when debugging x86 executables in gdb. For example, in a crash I previously couldn't see what's on the stack:

(gdb) print *(StgClosure*)$rbp
$1 = {
  header = {
    info = 0x24c9b8
  },
  payload = 0x42000d3648
}

It's not clear which continuation is 0x24c9b8.

Or with ghc-gdb 1:

(gdb) ghc backtrace
Sp = 0x42000d3640
0: RET_SMALL
  return=0x24c9b8 (Main.hs:79)
  field 0: Ptr  0x420000b322  : CONSTR_2_0
  field 1: Ptr  0x420000600000: off-heap(0x420000600000)
  field 2: Ptr  0x42000d37b0  : FUN_1_0
1: RET_SMALL
  return=0x24cad8 (Main.hs:24)
2: UPDATE_FRAME(0x42000d4c30: BLACKHOLE)
3: RET_SMALL
  return=0x380200 (libraries/base/GHC/IO/Handle/Text.hs:583)
  field 0: Ptr  0x5be5d8      : off-heap(0x5be5d8)
  field 1: Ptr  0x6ce48a      : off-heap(0x6ce488)
  field 2: Ptr  0x5ce841      : off-heap(0x5ce840)
  field 3: Word 283468840976
  field 4: Word 1
  field 5: Ptr  0x42000d37c0  : THUNK_1_0
  field 6: Ptr  0x42000d37da  : CONSTR_2_0
  field 7: Word 2048
  field 8: Ptr  0x42000d37f1  : CONSTR_1_1
4: CATCH_FRAME
5: STOP_FRAME

With this patch:

(gdb) print *(StgClosure*)$rbp
$1 = {
  header = {
    info = 0x24c9b8 <.Lc5Dv>
  },
  payload = 0x42000d3648
}

It's now clear that the continuation is c5Dv, which can be easily seen in Cmm and asm dumps:

go_s5vj_entry() {
        { info_tbls: [...
                      (c5Dv,
                       label: block_c5Dv_info
                       rep: StackRep [False, False, False]
                       srt: Nothing),
                      ...]
          ...
        }
    {offset
      ...
      c5Dv:
          unwind Sp = Just Sp + 32;
          //tick src<Main.hs:41:5-38>
          //tick src<Main.hs:41:13-38>
          //tick src<Main.hs:79:32-35>
          //tick src<Main.hs:38:7-28>
          //tick src<Main.hs:42:5-38>
          //tick src<Main.hs:42:13-38>
          _s5vp::P64 = P64[R1 + 7];
          _s5vq::I64 = I64[_s5vp::P64 + 8];
          if (_s5vq::I64 == I64[P64[Sp + 16] + 8]) goto c5Ef; else goto c5EG;
      ...
    }
}

Or with ghc-gdb we can see symbols of all of the frames in the stack easily:

(gdb) ghc backtrace
Sp = 0x42000d3640
0: RET_SMALL
  return=0x24c9b8 <.Lc5Dv> (Main.hs:79)
  field 0: Ptr  0x420000b322  : CONSTR_2_0
  field 1: Ptr  0x420000600000: off-heap(0x420000600000)
  field 2: Ptr  0x42000d37b0  : FUN_1_0
1: RET_SMALL
  return=0x24cad8 <.Lc5EX> (Main.hs:24)
2: UPDATE_FRAME(0x42000d4c30: BLACKHOLE)
3: RET_SMALL
  return=0x380200 (libraries/base/GHC/IO/Handle/Text.hs:583)
  field 0: Ptr  0x5be5d8      : off-heap(0x5be5d8)
  field 1: Ptr  0x6ce48a      : off-heap(0x6ce488)
  field 2: Ptr  0x5ce841      : off-heap(0x5ce840)
  field 3: Word 283468840976
  field 4: Word 1
  field 5: Ptr  0x42000d37c0  : THUNK_1_0
  field 6: Ptr  0x42000d37da  : CONSTR_2_0
  field 7: Word 2048
  field 8: Ptr  0x42000d37f1  : CONSTR_1_1
4: CATCH_FRAME
5: STOP_FRAME

This is incredibly helpful when debugging runtime issues.

Fixes #16286.

Note: these symbols are only made visible in x86 backend and when debug level is greater than 3 (-g4 and above).

Edited by Ben Gamari

Merge request reports