Porting to DragonFly BSD

Goetz Isenmann info at goetz-isenmann.de
Sun Nov 15 07:42:46 EST 2009


On Sat, Nov 14, 2009 at 04:16:58PM +0000, Colin Paul Adams wrote:
>     Goetz> Until now I had no time and energie to dig deeper into the
>     Goetz> problem [1], that looks to me, like rts/Linker cannot load
>     Goetz> any object file that references errno.

Seems to be worse when I try to build snapshot ghc-6.13.20091111. I
get a relocation error much earlier during the stage2 build.

>     Goetz> My guess is, that for dragonflys "extern __thread int
>     Goetz> errno;" we do not only need to add a new case in
>     Goetz> rts/Linker.c but also need to generate different code for
>     Goetz> this thread local storage access.

I am still not sure, but the generated code might be ok

001e5565 <__hscore_get_errno>:
  1e5565:       55                      push   %ebp
  1e5566:       89 e5                   mov    %esp,%ebp
  1e5568:       65 a1 00 00 00 00       mov    %gs:0x0,%eax
  1e556e:       8b 15 00 00 00 00       mov    0x0,%edx
  1e5574:       8b 04 10                mov    (%eax,%edx,1),%eax
  1e5577:       c9                      leave  
  1e5578:       c3                      ret    

The corresponding relocation info is

001e5570 R_386_TLS_IE      errno

>     Goetz> [1] $ ghci GHCi, version 6.10.4:
>     Goetz> http://www.haskell.org/ghc/ :? for help Loading package
>     Goetz> ghc-prim ... linking ... done.  Loading package integer
>     Goetz> ... linking ... done.  ghc:
>     Goetz> /var/tmp/isenmann/ghc-6.10.4-3/lib/ghc-6.10.4/base-4.1.0.0/HSbase-4.1.0.0.o:
>     Goetz> unhandled ELF relocation(Rel) type 15
> 
>     Goetz> Loading package base ... linking ... ghc: unable to load
>     Goetz> package `base'
> 
> After some googling, and learning very little, I speclated that simply
> adding a third line for R_386_TLS_IE with the same action as the first
> line - just storing value, might work: 
> 
> case R_386_TLS_IE: *pP = value; break;
> 
> This seems to work up to a point. That is I get no crashes in ghci.

I have also tried this, but I do not believe, that something that
simple will work. At least it should pass this test: When you try to
open a file that does not exist

Prelude> System.IO.openFile "xxx" System.IO.ReadMode

you should get

*** Exception: xxx: openFile: does not exist (No such file or directory)

and not (Unknown error: ...).


My current strategie is, to avoid the problem in a first step.

With the attached errno_ptr.{h,c} I create a shared library, that
encapsulates the errno access, install the header file as
/usr/pkg/include/errno_ptr.h and the shared lib as
/usr/pkg/lib/liberrno_ptr.so

Building ghc-6.10.4 with the attached patch (only a quick hack, to
check the idea) I get a result, that looks much better. 

@Colin: Maybe you can test and use this hack.

@Simon: I am not sure, in which direction I should look for solving
this problem:

 1. Avoid the tls problem
    a) Try to convince the dragonfly people, that it might be useful,
       to have something like the errno access wrapper in libc.
    b) If (1a) fails, try to create a patch for netbsd pkgsrc and/or
       ghc, so that an access wrapper will be created and installed
       as part of a ghc installation on dragonfly.
 2. Fix the problem
    a) Try to add the necessary logic into the ghc runtime.
    b) Try to use the platforms loader.
    Have no clue, if and how (2a) or (2b) are possible, where to get
    some help or at least the necessary information.

Goetz
-------------- next part --------------
int *errno_ptr(void);
-------------- next part --------------
#include <errno.h>
#include <errno_ptr.h>

int *errno_ptr(void) {
  return (&errno);
}

-------------- next part --------------
#! /bin/sh
gcc -shared -o liberrno_ptr.so -I. -fPIC -O2 errno_ptr.c
-------------- next part --------------
A non-text attachment was scrubbed...
Name: liberrno_ptr.so
Type: application/octet-stream
Size: 4209 bytes
Desc: not available
Url : http://www.haskell.org/pipermail/glasgow-haskell-users/attachments/20091115/d6e1e43d/liberrno_ptr-0001.so
-------------- next part --------------
diff -ru ghc-6.10.4/compiler/nativeGen/NCG.h ghc-6.10.4-dfly-5/compiler/nativeGen/NCG.h
--- ghc-6.10.4/compiler/nativeGen/NCG.h	2009-07-14 19:10:51 +0200
+++ ghc-6.10.4-dfly-5/compiler/nativeGen/NCG.h	2009-11-11 17:53:20 +0100
@@ -38,6 +38,12 @@
 # define IF_OS_freebsd(x,y) y
 #endif
 -- - - - - - - - - - - - - - - - - - - - - - 
+#if dragonfly_TARGET_OS
+# define IF_OS_dragonfly(x,y) x
+#else
+# define IF_OS_dragonfly(x,y) y
+#endif
+-- - - - - - - - - - - - - - - - - - - - - - 
 #if netbsd_TARGET_OS
 # define IF_OS_netbsd(x,y) x
 #else
diff -ru ghc-6.10.4/configure ghc-6.10.4-dfly-5/configure
--- ghc-6.10.4/configure	2009-07-14 19:24:26 +0200
+++ ghc-6.10.4-dfly-5/configure	2009-11-11 17:53:20 +0100
@@ -2307,6 +2307,15 @@
         HostVendor_CPP='unknown'
         HostOS_CPP='freebsd'
         ;;
+i[3456]86-*-dragonfly*)
+        HostPlatform=i386-unknown-dragonfly # hack again
+        TargetPlatform=i386-unknown-dragonfly
+        BuildPlatform=i386-unknown-dragonfly
+        HostPlatform_CPP='i386_unknown_dragonfly'
+        HostArch_CPP='i386'
+        HostVendor_CPP='unknown'
+        HostOS_CPP='dragonfly'
+        ;;
 i[3456]86-*-freebsd2*) # Older FreeBSDs are a.out
         HostPlatform=i386-unknown-freebsd2 # hack again
         TargetPlatform=i386-unknown-freebsd2
diff -ru ghc-6.10.4/configure.ac ghc-6.10.4-dfly-5/configure.ac
--- ghc-6.10.4/configure.ac	2009-07-14 19:10:53 +0200
+++ ghc-6.10.4-dfly-5/configure.ac	2009-11-11 17:53:20 +0100
@@ -260,6 +260,15 @@
         HostVendor_CPP='unknown'
         HostOS_CPP='freebsd'
         ;;
+i[[3456]]86-*-dragonfly*)
+        HostPlatform=i386-unknown-dragonfly # hack again
+        TargetPlatform=i386-unknown-dragonfly
+        BuildPlatform=i386-unknown-dragonfly
+        HostPlatform_CPP='i386_unknown_dragonfly'
+        HostArch_CPP='i386'
+        HostVendor_CPP='unknown'
+        HostOS_CPP='dragonfly'
+        ;;
 i[[3456]]86-*-freebsd2*) # Older FreeBSDs are a.out
         HostPlatform=i386-unknown-freebsd2 # hack again
         TargetPlatform=i386-unknown-freebsd2
diff -ru ghc-6.10.4/distrib/configure-bin.ac ghc-6.10.4-dfly-5/distrib/configure-bin.ac
--- ghc-6.10.4/distrib/configure-bin.ac	2009-07-14 19:10:52 +0200
+++ ghc-6.10.4-dfly-5/distrib/configure-bin.ac	2009-11-11 17:53:20 +0100
@@ -42,6 +42,8 @@
 	TargetPlatform=i386-unknown-freebsd2;;
 i[[3456]]86-*-freebsd[[3-9]]*)
 	TargetPlatform=i386-unknown-freebsd;;
+i[[3456]]86-*-dragonfly*)
+	TargetPlatform=i386-unknown-dragonfly;;
 i[[3456]]86-*-netbsd*)
 	TargetPlatform=i386-unknown-netbsd;;
 i[[3456]]86-*-openbsd*)
diff -ru ghc-6.10.4/driver/mangler/ghc-asm.lprl ghc-6.10.4-dfly-5/driver/mangler/ghc-asm.lprl
--- ghc-6.10.4/driver/mangler/ghc-asm.lprl	2009-07-14 19:10:52 +0200
+++ ghc-6.10.4-dfly-5/driver/mangler/ghc-asm.lprl	2009-11-11 17:53:20 +0100
@@ -160,12 +160,12 @@
     $T_HDR_vector   = "\.text\n\t\.align 4\n"; # NB: requires padding
 
     #--------------------------------------------------------#
-    } elsif ( $TargetPlatform =~ /^i386-.*-(solaris2|linux|gnu|freebsd|netbsd|openbsd|kfreebsdgnu)$/m ) {
+    } elsif ( $TargetPlatform =~ /^i386-.*-(solaris2|linux|gnu|freebsd|dragonfly|netbsd|openbsd|kfreebsdgnu)$/m ) {
 
     $T_STABBY	    = 0; # 1 iff .stab things (usually if a.out format)
     $T_US	    = ''; # _ if symbols have an underscore on the front
     $T_PRE_APP	    = # regexp that says what comes before APP/NO_APP
-		      ($TargetPlatform =~ /-(linux|gnu|freebsd|netbsd|openbsd)$/m) ? '#' : '/' ;
+		      ($TargetPlatform =~ /-(linux|gnu|freebsd|dragonfly|netbsd|openbsd)$/m) ? '#' : '/' ;
     $T_CONST_LBL    = '^\.LC(\d+):$'; # regexp for what such a lbl looks like
     $T_POST_LBL	    = ':';
     $T_X86_PRE_LLBL_PAT = '\.L';
@@ -216,7 +216,7 @@
     $T_HDR_vector   = "\.text\n\t\.align 8\n";
 
     #--------------------------------------------------------#
-    } elsif ( $TargetPlatform =~ /^x86_64-.*-(linux|openbsd|freebsd|netbsd)$/m ) {
+    } elsif ( $TargetPlatform =~ /^x86_64-.*-(linux|openbsd|freebsd|dragonfly|netbsd)$/m ) {
 
     $T_STABBY       = 0; # 1 iff .stab things (usually if a.out format)
     $T_US           = ''; # _ if symbols have an underscore on the front
diff -ru ghc-6.10.4/libraries/base/base.cabal ghc-6.10.4-dfly-5/libraries/base/base.cabal
--- ghc-6.10.4/libraries/base/base.cabal	2009-07-14 19:13:10 +0200
+++ ghc-6.10.4-dfly-5/libraries/base/base.cabal	2009-11-14 22:40:17 +0100
@@ -164,12 +164,14 @@
         cbits/dirUtils.c
         cbits/inputReady.c
         cbits/selectUtils.c
-    include-dirs: include
+    include-dirs: include /usr/pkg/include
     includes:    HsBase.h
     install-includes:    HsBase.h HsBaseConfig.h WCsubst.h dirUtils.h consUtils.h Typeable.h
     if os(windows) {
         extra-libraries: wsock32, user32, shell32
     }
+    extra-lib-dirs: /usr/pkg/lib
+    extra-libraries: errno_ptr
     extensions: CPP
     -- We need to set the package name to base (without a version number)
     -- as it's magic.
diff -ru ghc-6.10.4/libraries/base/include/HsBase.h ghc-6.10.4-dfly-5/libraries/base/include/HsBase.h
--- ghc-6.10.4/libraries/base/include/HsBase.h	2009-07-14 19:13:10 +0200
+++ ghc-6.10.4-dfly-5/libraries/base/include/HsBase.h	2009-11-14 22:41:12 +0100
@@ -53,7 +53,7 @@
 #endif
 #endif
 #if HAVE_ERRNO_H
-#include <errno.h>
+#include <errno_ptr.h>
 #endif
 #if HAVE_STRING_H
 #include <string.h>
@@ -220,8 +220,8 @@
 # endif
 #endif
 
-INLINE int __hscore_get_errno(void) { return errno; }
-INLINE void __hscore_set_errno(int e) { errno = e; }
+INLINE int __hscore_get_errno(void) { return *errno_ptr(); }
+INLINE void __hscore_set_errno(int e) { *errno_ptr() = e; }
 
 #if !defined(_MSC_VER)
 INLINE int __hscore_s_isreg(mode_t m)  { return S_ISREG(m);  }
diff -ru ghc-6.10.4/libraries/process/cbits/runProcess.c ghc-6.10.4-dfly-5/libraries/process/cbits/runProcess.c
--- ghc-6.10.4/libraries/process/cbits/runProcess.c	2009-07-14 19:19:22 +0200
+++ ghc-6.10.4-dfly-5/libraries/process/cbits/runProcess.c	2009-11-14 22:43:20 +0100
@@ -13,6 +13,7 @@
 #if !(defined(_MSC_VER) || defined(__MINGW32__) || defined(_WIN32))
 
 #include "execvpe.h"
+#include <errno_ptr.h>
 
 /* ----------------------------------------------------------------------------
    UNIX versions
@@ -215,7 +216,7 @@
 	else
 	    if (WIFSIGNALED(wstat))
 	    {
-		errno = EINTR;
+		*errno_ptr() = EINTR;
 		return -1;
 	    }
 	    else
@@ -226,7 +227,7 @@
     
     if (res == 0) return 0;
 
-    if (errno == ECHILD) 
+    if (*errno_ptr() == ECHILD) 
     {
 	    *pExitCode = 0;
 	    return 1;
@@ -241,7 +242,7 @@
     
     while (waitpid(handle, &wstat, 0) < 0)
     {
-	if (errno != EINTR)
+	if (*errno_ptr() != EINTR)
 	{
 	    return -1;
 	}
diff -ru ghc-6.10.4/libraries/unix/System/Posix/Signals.hsc ghc-6.10.4-dfly-5/libraries/unix/System/Posix/Signals.hsc
--- ghc-6.10.4/libraries/unix/System/Posix/Signals.hsc	2009-07-14 19:20:42 +0200
+++ ghc-6.10.4-dfly-5/libraries/unix/System/Posix/Signals.hsc	2009-11-11 17:53:20 +0100
@@ -292,7 +292,7 @@
 raiseSignal :: Signal -> IO ()
 raiseSignal sig = throwErrnoIfMinus1_ "raiseSignal" (c_raise sig)
 
-#if defined(__GLASGOW_HASKELL__) && (defined(openbsd_HOST_OS) || defined(freebsd_HOST_OS))
+#if defined(__GLASGOW_HASKELL__) && (defined(openbsd_HOST_OS) || defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS))
 foreign import ccall unsafe "genericRaise"
   c_raise :: CInt -> IO CInt
 #else
diff -ru ghc-6.10.4/libraries/unix/cbits/execvpe.c ghc-6.10.4-dfly-5/libraries/unix/cbits/execvpe.c
--- ghc-6.10.4/libraries/unix/cbits/execvpe.c	2009-07-14 19:20:42 +0200
+++ ghc-6.10.4-dfly-5/libraries/unix/cbits/execvpe.c	2009-11-14 22:42:15 +0100
@@ -18,7 +18,7 @@
 #include <sys/time.h>
 #include <stdlib.h>
 #include <string.h>
-#include <errno.h>
+#include <errno_ptr.h>
 
 /*
  * We want the search semantics of execvp, but we want to provide our
@@ -115,7 +115,7 @@
 
       retry:
         (void) execve(bp, argv, envp);
-	switch (errno) {
+	switch (*errno_ptr()) {
 	case EACCES:
 	    eacces = 1;
 	    break;
@@ -147,9 +147,9 @@
 	}
     }
     if (eacces)
-	errno = EACCES;
-    else if (!errno)
-	errno = ENOENT;
+	*errno_ptr() = EACCES;
+    else if (!*errno_ptr())
+	*errno_ptr() = ENOENT;
   done:
     if (path)
 	free(path);
diff -ru ghc-6.10.4/mk/config.mk.in ghc-6.10.4-dfly-5/mk/config.mk.in
--- ghc-6.10.4/mk/config.mk.in	2009-07-14 19:10:53 +0200
+++ ghc-6.10.4-dfly-5/mk/config.mk.in	2009-11-11 17:53:20 +0100
@@ -298,7 +298,7 @@
 # Whether to include GHCi in the compiler.  Depends on whether the RTS linker
 # has support for this OS/ARCH combination.
 
-OsSupportsGHCi=$(strip $(patsubst $(HostOS_CPP), YES, $(findstring $(HostOS_CPP), mingw32 cygwin32 linux solaris2 freebsd netbsd openbsd darwin)))
+OsSupportsGHCi=$(strip $(patsubst $(HostOS_CPP), YES, $(findstring $(HostOS_CPP), mingw32 cygwin32 linux solaris2 freebsd dragonfly netbsd openbsd darwin)))
 ArchSupportsGHCi=$(strip $(patsubst $(HostArch_CPP), YES, $(findstring $(HostArch_CPP), i386 x86_64 powerpc sparc sparc64)))
 
 ifeq "$(OsSupportsGHCi)$(ArchSupportsGHCi)" "YESYES"
diff -ruN ghc-6.10.4-orig/rts/Linker.c ghc-6.10.4/rts/Linker.c
--- ghc-6.10.4-orig/rts/Linker.c	2009-07-14 19:10:53 +0200
+++ ghc-6.10.4/rts/Linker.c	2009-11-27 09:49:16 +0100
@@ -61,12 +61,12 @@
 #include <sys/wait.h>
 #endif
 
-#if defined(ia64_HOST_ARCH) || defined(linux_HOST_OS) || defined(freebsd_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS)
+#if defined(ia64_HOST_ARCH) || defined(linux_HOST_OS) || defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS)
 #define USE_MMAP
 #include <fcntl.h>
 #include <sys/mman.h>
 
-#if defined(linux_HOST_OS) || defined(freebsd_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS)
+#if defined(linux_HOST_OS) || defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS)
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -74,7 +74,7 @@
 
 #endif
 
-#if defined(linux_HOST_OS) || defined(solaris2_HOST_OS) || defined(freebsd_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS)
+#if defined(linux_HOST_OS) || defined(solaris2_HOST_OS) || defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS)
 #  define OBJFORMAT_ELF
 #elif defined(cygwin32_HOST_OS) || defined (mingw32_HOST_OS)
 #  define OBJFORMAT_PEi386
@@ -1327,7 +1327,7 @@
        } else {
            if ((W_)result > 0x80000000) {
                // oops, we were given memory over 2Gb
-#if defined(freebsd_HOST_OS)
+#if defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS)
                // Some platforms require MAP_FIXED.  This is normally
                // a bad idea, because MAP_FIXED will overwrite
                // existing mappings.
diff -ru ghc-6.10.4/rts/RtsUtils.c ghc-6.10.4-dfly-5/rts/RtsUtils.c
--- ghc-6.10.4/rts/RtsUtils.c	2009-07-14 19:10:52 +0200
+++ ghc-6.10.4-dfly-5/rts/RtsUtils.c	2009-11-11 17:53:20 +0100
@@ -461,7 +461,7 @@
  * genericRaise(), rather than raise(3).
  */
 int genericRaise(int sig) {
-#if defined(THREADED_RTS) && (defined(openbsd_HOST_OS) || defined(freebsd_HOST_OS))
+#if defined(THREADED_RTS) && (defined(openbsd_HOST_OS) || defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS))
         return pthread_kill(pthread_self(), sig);
 #else
         return raise(sig);
--- ghc-6.10.4/libraries/base/cbits/inputReady.c-orig	2009-07-14 19:13:10 +0200
+++ ghc-6.10.4/libraries/base/cbits/inputReady.c	2009-11-14 23:24:53 +0100
@@ -7,6 +7,8 @@
 /* select and supporting types is not Posix */
 /* #include "PosixSource.h" */
 #include "HsBase.h"
+#include <errno.h>
+#include <errno_ptr.h>
 
 /*
  * inputReady(fd) checks to see whether input is available on the file
@@ -42,7 +44,7 @@
 	tv.tv_usec = (msecs % 1000) * 1000;
 	
 	while ((ready = select(maxfd, &rfd, &wfd, NULL, &tv)) < 0 ) {
-	    if (errno != EINTR ) {
+	    if (*errno_ptr() != EINTR ) {
 		return -1;
 	    }
 	}


More information about the Glasgow-haskell-users mailing list