[GHC] #12523: Constructor info tables generated by GHCi don't return tagged pointers

GHC ghc-devs at haskell.org
Mon Aug 22 23:54:33 UTC 2016


#12523: Constructor info tables generated by GHCi don't return tagged pointers
-------------------------------------+-------------------------------------
           Reporter:  mniip          |             Owner:
               Type:  bug            |            Status:  new
           Priority:  normal         |         Milestone:
          Component:  GHCi           |           Version:  8.1
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  GHCi crash
  Unknown/Multiple                   |
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 If we have in a file:
 {{{#!hs
 data X = X String
 unX (X s) = s
 }}}
 And then load the file in ghci with `-fobject-code` and
 {{{
 > data Y = Y String
 > unX (Unsafe.Coerce.unsafeCoerce (Y "foo"))
 "Segmentation fault (core dumped)
 }}}

 Even though we are shooting ourselves in the foot there, the constructors
 `X` and `Y` are represented identically internally, so the code is
 supposed to work. And it does work if we either move `unX` into ghci'd
 code, or `Y` into compiled code.

 After a legthy debugging session with @rwbarton over IRC, we've identified
 the culprit of this. As [[Commentary/Rts/HaskellExecution/PointerTagging]]
 states, "In the continuation of an algebraic case, R1 is assumed tagged".
 And all compiled constructors tag the pointer when entered, e.g:
 {{{
 Dump of assembler code for function
 ghczmprim_GHCziTypes_False_static_info:
    0x00007fffef8dd018 <+0>:     48 ff c3        inc    %rbx
    0x00007fffef8dd01b <+3>:     ff 65 00        jmpq   *0x0(%rbp)
 Dump of assembler code for function base_GHCziBase_Just_static_info:
    0x00007ffff03eb780 <+0>:     48 83 c3 02     add    $0x2,%rbx
    0x00007ffff03eb784 <+4>:     ff 65 00        jmpq   *0x0(%rbp)
 Dump of assembler code for function ghczmprim_GHCziTypes_GT_static_info:
    0x00007fffef8dd1f8 <+0>:     48 83 c3 03     add    $0x3,%rbx
    0x00007fffef8dd1fc <+4>:     ff 65 00        jmpq   *0x0(%rbp)
 Dump of assembler code for function
 base_GHCziRTSziFlags_HeapByClosureType_static_info:
    0x00007ffff057e768 <+0>:     48 ff c3        inc    %rbx // more than 7
 constructors so all tags are '1'
    0x00007ffff057e76b <+3>:     ff 65 00        jmpq   *0x0(%rbp)
 }}}

 Whereas all ghci-bound data constructors share the
 `stg_interp_constr_entry` entry code (with an optional trampoline leading
 there):
 {{{
 Dump of assembler code from 0x7ffff7ff3080 to 0x7ffff7ff3090:
 => 0x00007ffff7ff3080:  jmpq   *0x2(%rip)        # 0x7ffff7ff3088
    0x00007ffff7ff3088:  0x00007fffef4c9388
 Dump of assembler code for function stg_interp_constr_entry:
    0x00007fffef4c9388 <+0>:     ff 65 00        jmpq   *0x0(%rbp)
 }}}

 Relevant code: source:libraries/ghci/GHCi/InfoTable.hsc#L32

 So in the end, compiled code relies on the assumption that the pointer is
 tagged, and ghci constructors produce untagged pointers. Even though it is
 currently impossible to have compiled code pattern match on a ghci
 constructor, I think this shouldn't happen.

--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/12523>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list