Deterministic crash in compiled program
I have program which crashes reliably with both GHC 8.4 & 8.6: coin-node.hs
Steps to reproduce
- To compile use:
ghc --make -O1 -debug -rtsopts ./exe/coin-node.hsCrash happens if
-O1/-O2is specified. With
-O0program finish normally
- Run with
./coin-node +RTS -c -V0 -i0 -DS -A256k. Both
-Aflags are necessary. Either removing
-Amakes crash go away so it's clearly related to GC somehow.
-dcore-lintshows no errors
Low level code comes from
memory package. Crash itself is deterministic and always happens in the same place. However test case is fragile and depends on forcing values in particular order. For example removing bang from
pubK makes crash go away
I expect programs compiled by GHC to not crash unless one gets way too playful with bits.
Core dump analysis
Crash happens in comparing two MutableByteArray# wrappers for equality:
0x00000000004041ac <+316>: mov rsi,QWORD PTR [rdx+0x8] 0x00000000004041b0 <+320>: mov rdi,QWORD PTR [rbp+0x10] => 0x00000000004041b4 <+324>: cmp rsi,QWORD PTR [rdi+0x8]
rdi's content is
0x0000420000700000 which is not valid address. However:
(rr) x/* ($rdi >> 8) 0x490680 <stg_ARR_WORDS_info>: 0x4657bfb8 (rr) x/g ($rdi >> 8) + 8 0x4200007008: 0x0000000000000001 (rr) x/8b ($rdi >> 8) + 8 +8 0x4200007010: 0x01 0xaa 0xaa 0xaa 0xaa 0xaa 0xaa 0xaa
So it does point to correct byte array except it got shifted by 8 bits somehow. Using rr one could find how that value gets stored onto stack(?):
0x000000000040412c <+188>: mov rcx,QWORD PTR [rax+0x7] => 0x0000000000404130 <+192>: mov QWORD PTR [rbp-0x10],rcx
Very suspicious thing is load from
rax+7. Indeed if we load from
rax + 8 we'll get correct value. My only hypothesis is that
rax expected to contain tagged pointer but that tag got lost somehow.
rax = 0x42000bf708 so all tag bits are clear.
- GHC version used: 8.4.4, 8.6.4, 8.6.5
- Operating System: Linux
- System Architecture: x64