[GHC] #13431: Linker error related to atan and ntdll on 32-bit Windows

#13431: Linker error related to atan and ntdll on 32-bit Windows -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Keywords: | Operating System: Windows Architecture: x86 | Type of failure: GHC rejects | valid program Test Case: | Blocked By: Blocking: | Related Tickets: Differential Rev(s): | Wiki Page: -------------------------------------+------------------------------------- That's a somewhat confusing title, so let me explain in more detail what I mean. I first noticed this issue when someone [https://github.com/idris-lang /Idris-dev/pull/3684 couldn't build Idris] on 32-bit Windows (using GHC 7.8, 7.10, or 8.0). Trying to link the Idris executable resulted in this cryptic linker error: {{{ Preprocessing executable 'idris' for idris-0.99.1... [1 of 1] Compiling Main ( main\Main.hs, dist\build\idris \idris-tmp\Main.o ) Linking dist\build\idris\idris.exe ... C:/Users/RyanGlScott/Software/ghc-8.0.1-x86/mingw/bin/../lib/gcc/i686-w64-mingw32/5.2.0/../../../../i686-w64-mingw32/lib/../lib/libmsvcrt.a(dohds01059.o):(.idata$5+0x0): multiple definition of `_imp__atan' C:/Users/RyanGlScott/Software/ghc-8.0.1-x86/mingw/bin/../lib/gcc/i686-w64-mingw32/5.2.0/../../../../i686-w64-mingw32/lib/../lib/libntdll.a(dgjjs01967.o):(.idata$5+0x0): first defined here collect2.exe: error: ld returned 1 exit status `gcc.exe' failed in phase `Linker'. (Exit code: 1) }}} The culprit was apparently Idris's dependency on the `mintty` package. The important bit was that `mintty` lists `ntdll` as in the `extra-libraries` stanza of its `.cabal` file. As it turns out, you can also reproduce this with a more recent version of `Win32`, which also depends on `ntdll`. First, run these steps: {{{ $ cabal get Win32 $ cd Win32-2.5.2.0/ $ cabal sandbox init $ cabal install . -w $(pwd)/../../../../Software/ghc-8.0.1-x86/bin/ghc }}} This will install the recent `Win32-2.5.2.0` in a sandbox (NB: I'm using 32-bit Windows GHC 8.0.1 here). Now create this file (which I named `Bug.hs`): {{{ module Main (main) where main :: IO () main = print (atan 0.5 :: Double) }}} And you can reproduce the linker error like so: {{{ $ ../../../../Software/ghc-8.0.1-x86/bin/ghc Bug.hs -package-db .cabal- sandbox/i386-windows-ghc-8.0.1-packages.conf.d/ -package Win32 -fforce- recomp [1 of 1] Compiling Main ( Bug.hs, Bug.o ) Linking Bug.exe ... C:/Users/RyanGlScott/Software/ghc-8.0.1-x86/mingw/bin/../lib/gcc/i686-w64-mingw32/5.2.0/../../../../i686-w64-mingw32/lib/../lib/libmsvcrt.a(dohds01059.o):(.idata$5+0x0): multiple definition of `_imp__atan' C:/Users/RyanGlScott/Software/ghc-8.0.1-x86/mingw/bin/../lib/gcc/i686-w64-mingw32/5.2.0/../../../../i686-w64-mingw32/lib/../lib/libntdll.a(dgjjs01967.o):(.idata$5+0x0): first defined here collect2.exe: error: ld returned 1 exit status `gcc.exe' failed in phase `Linker'. (Exit code: 1) }}} It's important to use 32-bit Windows GHC here, since I am unable to reproduce this with 64-bit Windows GHC. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13431 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13431: Linker error related to atan and ntdll on 32-bit Windows -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: (none) Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Windows | Architecture: x86 Type of failure: GHC rejects | Test Case: valid program | Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): The issue stems from the order in which `ntdll` and `msvcrt` are given to the linker when compiling the executable. If you compile with `-v3`, you'll discover this linker invocation: {{{ "gcc.exe" ... "-lntdll" ... "-lmsvcrt" ... }}} If you swap the order in which `msvcrt` and `ntdll` are linked: {{{ "gcc.exe" ... "-lmsvcrt" ... "-lntdll" ... }}} Then it works. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13431#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13431: Linker error related to atan and ntdll on 32-bit Windows -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: Phyx- Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Windows | Architecture: x86 Type of failure: GHC rejects | Test Case: valid program | Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by Phyx-): * owner: (none) => Phyx- -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13431#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13431: Linker error related to atan and ntdll on 32-bit Windows -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: Phyx- Type: bug | Status: upstream Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Windows | Architecture: x86 Type of failure: GHC rejects | Test Case: valid program | Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by Phyx-): * status: new => upstream * milestone: => 8.4.1 Comment: I believe this to be an upstream bug in `mingw-w64-crt`. It seems that `ntdll.dll` undocumented exports a few functions such as `atan`. The import libraries are created by default using a tool that scrapes the exports table of a dll and makes a `.def` file and then `dlltool` is called to generate the library. The problem is that this tool on the `x86` version seems to think these functions are `DATA` references (e.g. readonly data) instead of functions. And this it only exports `_imp__atan` instead of both `_atan` and `_imp__atan`. On `x64` the tool does get this correct. {{{ Tamar@Kino MINGW64 ~/MINGW-packages/mingw-w64-crt-git/src/mingw-w64 $ find -iname ntdll.def | xargs grep atan ./mingw-w64-crt/lib32/ntdll.def:atan DATA ./mingw-w64-crt/lib64/ntdll.def:atan ./mingw-w64-crt/libarm32/ntdll.def:atan }}} This will require some upstream patching because controlling the link order in all cases is very hard. In the meantime since it seems that `Win32` is the only one that's introducing this dependency, I think I can apply a patch locally there for `x86`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13431#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13431: Linker error related to atan and ntdll on 32-bit Windows -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: Phyx- Type: bug | Status: upstream Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Windows | Architecture: x86 Type of failure: GHC rejects | Test Case: valid program | Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by RyanGlScott): What is the patch you're referring to, out of curiosity? I'd also need to apply this patch to my `mintty` library as well. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13431#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13431: Linker error related to atan and ntdll on 32-bit Windows -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: Phyx- Type: bug | Status: upstream Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Windows | Architecture: x86 Type of failure: GHC rejects | Test Case: valid program | Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Phyx-): compiling and bundling a fixed `libntdll.a` -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13431#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13431: Linker error related to atan and ntdll on 32-bit Windows -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: Phyx- Type: bug | Status: upstream Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Windows | Architecture: x86 Type of failure: GHC rejects | Test Case: valid program | Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Phyx-): Or rather, depending on the amount of functions, I'll probably dynamically import them instead of statically linking. That way I can avoid `libntdll.a` completely. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13431#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13431: Linker error related to atan and ntdll on 32-bit Windows -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: Phyx- Type: bug | Status: upstream Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Windows | Architecture: x86 Type of failure: GHC rejects | Test Case: valid program | Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Phyx-): Upstream bug reported https://sourceforge.net/p/mingw-w64/bugs/596/ -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13431#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#13431: Linker error related to atan and ntdll on 32-bit Windows -------------------------------------+------------------------------------- Reporter: RyanGlScott | Owner: Phyx- Type: bug | Status: closed Priority: normal | Milestone: 8.4.1 Component: Compiler | Version: 8.0.1 Resolution: wontfix | Keywords: Operating System: Windows | Architecture: Type of failure: GHC rejects | Unknown/Multiple valid program | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Changes (by Phyx-): * status: upstream => closed * resolution: => wontfix * architecture: x86 => Unknown/Multiple Comment: Well, the long story short is this won't get fixed. The issue is that `mingw-w64` have their own version of the math functions. So depending on the link order you specify you get either the weird one exported in `ntdll` (which honestly I think is a mistake that Microsoft never could correct due to backwards compatibility.) Anyway, we debated three options, one of which I proposed was to remove these functions from `ntdll.a` entirely as MSDN does not document them. This lends more evidence to my theory that they were a mistake. But it seems this can't be done, so instead I suggested to also change the x64 version to break. The reason is that at least it's consistent and you won't end up with a different math function by accident. On the long term, this means that no haskell library should use `ntdll.a` as libraries don't have full control over the link ordering. This of course extends to other C code compiled by GHC. Those have to be linked to a shared library and then used by haskell code or dynamically load ntdll. Such is life. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13431#comment:8 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC