[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