Add a proper write barrier for MVars
[ghc-hetmet.git] / rts / Linker.c
index 4ab84ed..e86efd3 100644 (file)
@@ -83,7 +83,9 @@
 #  include <mach-o/loader.h>
 #  include <mach-o/nlist.h>
 #  include <mach-o/reloc.h>
+#if !defined(HAVE_DLFCN_H)
 #  include <mach-o/dyld.h>
+#endif
 #if defined(powerpc_HOST_ARCH)
 #  include <mach-o/ppc/reloc.h>
 #endif
@@ -256,6 +258,12 @@ typedef struct _RtsSymbolVal {
 #define RTS_MINGW_EXTRA_SYMS
 #endif
 
+#if HAVE_GETTIMEOFDAY
+#define RTS_MINGW_GETTIMEOFDAY_SYM Sym(gettimeofday)
+#else
+#define RTS_MINGW_GETTIMEOFDAY_SYM /**/
+#endif
+
 /* These are statically linked from the mingw libraries into the ghc
    executable, so we have to employ this hack. */
 #define RTS_MINGW_ONLY_SYMBOLS                  \
@@ -339,6 +347,7 @@ typedef struct _RtsSymbolVal {
       Sym(readdir)                              \
       Sym(rewinddir)                            \
       RTS_MINGW_EXTRA_SYMS                      \
+      RTS_MINGW_GETTIMEOFDAY_SYM               \
       Sym(closedir)
 #endif
 
@@ -470,12 +479,12 @@ typedef struct _RtsSymbolVal {
       SymX(__encodeDouble)                     \
       SymX(__encodeFloat)                      \
       SymX(addDLL)                             \
-      SymX(__gmpn_gcd_1)                       \
-      SymX(__gmpz_cmp)                         \
-      SymX(__gmpz_cmp_si)                      \
-      SymX(__gmpz_cmp_ui)                      \
-      SymX(__gmpz_get_si)                      \
-      SymX(__gmpz_get_ui)                      \
+      SymExtern(__gmpn_gcd_1)                  \
+      SymExtern(__gmpz_cmp)                    \
+      SymExtern(__gmpz_cmp_si)                 \
+      SymExtern(__gmpz_cmp_ui)                 \
+      SymExtern(__gmpz_get_si)                 \
+      SymExtern(__gmpz_get_ui)                 \
       SymX(__int_encodeDouble)                 \
       SymX(__int_encodeFloat)                  \
       SymX(andIntegerzh_fast)                  \
@@ -516,6 +525,7 @@ typedef struct _RtsSymbolVal {
       SymX(genSymZh)                           \
       SymX(genericRaise)                       \
       SymX(getProgArgv)                                \
+      SymX(getFullProgArgv)                            \
       SymX(getStablePtr)                       \
       SymX(hs_init)                            \
       SymX(hs_exit)                            \
@@ -524,9 +534,10 @@ typedef struct _RtsSymbolVal {
       SymX(hs_perform_gc)                      \
       SymX(hs_free_stable_ptr)                 \
       SymX(hs_free_fun_ptr)                    \
+      SymX(hs_hpc_rootModule)                  \
       SymX(initLinker)                         \
-      SymX(infoPtrzh_fast)                      \
-      SymX(closurePayloadzh_fast)               \
+      SymX(unpackClosurezh_fast)                \
+      SymX(getApStackValzh_fast)                \
       SymX(int2Integerzh_fast)                 \
       SymX(integer2Intzh_fast)                 \
       SymX(integer2Wordzh_fast)                        \
@@ -590,32 +601,38 @@ typedef struct _RtsSymbolVal {
       SymX(rts_getDouble)                      \
       SymX(rts_getFloat)                       \
       SymX(rts_getInt)                         \
+      SymX(rts_getInt8)                                \
+      SymX(rts_getInt16)                       \
       SymX(rts_getInt32)                       \
+      SymX(rts_getInt64)                       \
       SymX(rts_getPtr)                         \
       SymX(rts_getFunPtr)                      \
       SymX(rts_getStablePtr)                   \
       SymX(rts_getThreadId)                    \
       SymX(rts_getWord)                                \
+      SymX(rts_getWord8)                       \
+      SymX(rts_getWord16)                      \
       SymX(rts_getWord32)                      \
+      SymX(rts_getWord64)                      \
       SymX(rts_lock)                           \
       SymX(rts_mkBool)                         \
       SymX(rts_mkChar)                         \
       SymX(rts_mkDouble)                       \
       SymX(rts_mkFloat)                                \
       SymX(rts_mkInt)                          \
+      SymX(rts_mkInt8)                         \
       SymX(rts_mkInt16)                                \
       SymX(rts_mkInt32)                                \
       SymX(rts_mkInt64)                                \
-      SymX(rts_mkInt8)                         \
       SymX(rts_mkPtr)                          \
       SymX(rts_mkFunPtr)                       \
       SymX(rts_mkStablePtr)                    \
       SymX(rts_mkString)                       \
       SymX(rts_mkWord)                         \
+      SymX(rts_mkWord8)                                \
       SymX(rts_mkWord16)                       \
       SymX(rts_mkWord32)                       \
       SymX(rts_mkWord64)                       \
-      SymX(rts_mkWord8)                                \
       SymX(rts_unlock)                         \
       SymX(rtsSupportsBoundThreads)            \
       SymX(__hscore_get_saved_termios)         \
@@ -629,7 +646,8 @@ typedef struct _RtsSymbolVal {
       SymX(stg_CAF_BLACKHOLE_info)             \
       SymX(awakenBlockedQueue)                 \
       SymX(stg_CHARLIKE_closure)               \
-      SymX(stg_EMPTY_MVAR_info)                        \
+      SymX(stg_MVAR_CLEAN_info)                        \
+      SymX(stg_MVAR_DIRTY_info)                        \
       SymX(stg_IND_STATIC_info)                        \
       SymX(stg_INTLIKE_closure)                        \
       SymX(stg_MUT_ARR_PTRS_DIRTY_info)                \
@@ -710,6 +728,11 @@ typedef struct _RtsSymbolVal {
       SymX(getAllocations)                      \
       SymX(revertCAFs)                          \
       SymX(RtsFlags)                            \
+      SymX(rts_breakpoint_io_action)           \
+      SymX(rts_stop_next_breakpoint)           \
+      SymX(rts_stop_on_exception)              \
+      SymX(stopTimer)                          \
+      SymX(n_capabilities)                     \
       RTS_USER_SIGNALS_SYMBOLS
 
 #ifdef SUPPORT_LONG_LONGS
@@ -755,6 +778,11 @@ typedef struct _RtsSymbolVal {
 
 /* entirely bogus claims about types of these symbols */
 #define Sym(vvv)  extern void vvv(void);
+#if defined(__PIC__) && defined(mingw32_TARGET_OS)
+#define SymExtern(vvv)  extern void _imp__ ## vvv (void);
+#else
+#define SymExtern(vvv)  SymX(vvv)
+#endif
 #define SymX(vvv) /**/
 #define SymX_redirect(vvv,xxx) /**/
 RTS_SYMBOLS
@@ -768,6 +796,7 @@ RTS_LIBGCC_SYMBOLS
 #undef Sym
 #undef SymX
 #undef SymX_redirect
+#undef SymExtern
 
 #ifdef LEADING_UNDERSCORE
 #define MAYBE_LEADING_UNDERSCORE_STR(s) ("_" s)
@@ -778,6 +807,8 @@ RTS_LIBGCC_SYMBOLS
 #define Sym(vvv) { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
                     (void*)(&(vvv)) },
 #define SymX(vvv) Sym(vvv)
+#define SymExtern(vvv) { MAYBE_LEADING_UNDERSCORE_STR(#vvv), \
+           (void*)DLL_IMPORT_DATA_REF(vvv) },
 
 // SymX_redirect allows us to redirect references to one symbol to
 // another symbol.  See newCAF/newDynCAF for an example.
@@ -917,13 +948,13 @@ typedef
 static OpenedDLL* opened_dlls = NULL;
 #endif
 
-char *
+const char *
 addDLL( char *dll_name )
 {
 #  if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
    /* ------------------- ELF DLL loader ------------------- */
    void *hdl;
-   char *errmsg;
+   const char *errmsg;
 
    initLinker();
 
@@ -1042,12 +1073,25 @@ lookupSymbol( char *lbl )
        return dlsym(dl_prog_handle, lbl);
 #      endif
 #       elif defined(OBJFORMAT_MACHO)
+#       if HAVE_DLFCN_H
+        /* On OS X 10.3 and later, we use dlsym instead of the old legacy
+           interface.
+
+           HACK: On OS X, global symbols are prefixed with an underscore.
+                 However, dlsym wants us to omit the leading underscore from the
+                 symbol name. For now, we simply strip it off here (and ONLY
+                 here).
+        */
+        ASSERT(lbl[0] == '_');
+        return dlsym(dl_prog_handle, lbl+1);
+#       else
        if(NSIsSymbolNameDefined(lbl)) {
            NSSymbol symbol = NSLookupAndBindSymbol(lbl);
            return NSAddressOfSymbol(symbol);
        } else {
            return NULL;
        }
+#       endif /* HAVE_DLFCN_H */
 #       elif defined(OBJFORMAT_PEi386)
         OpenedDLL* o_dll;
         void* sym;
@@ -1246,13 +1290,20 @@ loadObj( char *path )
    /* Link objects into the lower 2Gb on x86_64.  GHC assumes the
     * small memory model on this architecture (see gcc docs,
     * -mcmodel=small).
+    *
+    * MAP_32BIT not available on OpenBSD/amd64
     */
-#ifdef x86_64_HOST_ARCH
+#if defined(x86_64_HOST_ARCH) && defined(MAP_32BIT)
 #define EXTRA_MAP_FLAGS MAP_32BIT
 #else
 #define EXTRA_MAP_FLAGS 0
 #endif
 
+   /* MAP_ANONYMOUS is MAP_ANON on some systems, e.g. OpenBSD */
+#if !defined(MAP_ANONYMOUS) && defined(MAP_ANON)
+#define MAP_ANONYMOUS MAP_ANON
+#endif
+
    oc->image = mmap(map_addr, n, PROT_EXEC|PROT_READ|PROT_WRITE,
                    MAP_PRIVATE|EXTRA_MAP_FLAGS, fd, 0);
    if (oc->image == MAP_FAILED)
@@ -2515,15 +2566,20 @@ ocResolve_PEi386 ( ObjectCode* oc )
 #endif
 
 #if !defined(openbsd_HOST_OS)
-#include <elf.h>
+#  include <elf.h>
 #else
 /* openbsd elf has things in different places, with diff names */
-#include <elf_abi.h>
-#include <machine/reloc.h>
-#define R_386_32    RELOC_32
-#define R_386_PC32  RELOC_PC32
+#  include <elf_abi.h>
+#  include <machine/reloc.h>
+#  define R_386_32    RELOC_32
+#  define R_386_PC32  RELOC_PC32
 #endif
 
+/* If elf.h doesn't define it */
+#  ifndef R_X86_64_PC64     
+#    define R_X86_64_PC64 24
+#  endif
+
 /*
  * Define a set of types which can be used for both ELF32 and ELF64
  */
@@ -2721,7 +2777,7 @@ x86_64_high_symbol( char *lbl, void *addr )
        x86_64_bounce_buffer = 
            mmap(NULL, X86_64_BB_SIZE * sizeof(x86_64_bounce), 
                 PROT_EXEC|PROT_READ|PROT_WRITE, 
-                MAP_PRIVATE|MAP_32BIT|MAP_ANONYMOUS, -1, 0);
+                MAP_PRIVATE|EXTRA_MAP_FLAGS|MAP_ANONYMOUS, -1, 0);
        if (x86_64_bounce_buffer == MAP_FAILED) {
            barf("x86_64_high_symbol: mmap failed");
        }
@@ -2849,8 +2905,12 @@ ocVerifyImage_ELF ( ObjectCode* oc )
 #ifdef EM_X86_64
       case EM_X86_64: IF_DEBUG(linker,debugBelch( "x86_64" )); break;
 #endif
+#ifdef EM_AMD64
+      case EM_AMD64: IF_DEBUG(linker,debugBelch( "amd64" )); break;
+#endif
       default:       IF_DEBUG(linker,debugBelch( "unknown" ));
-                     errorBelch("%s: unknown architecture", oc->fileName);
+                     errorBelch("%s: unknown architecture (e_machine == %d)"
+                                , oc->fileName, ehdr->e_machine);
                      return 0;
    }
 
@@ -3465,6 +3525,13 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
          break;
       }
 
+      case R_X86_64_PC64:
+      {
+         StgInt64 off = value - P;
+         *(Elf64_Word *)P = (Elf64_Word)off;
+         break;
+      }
+
       case R_X86_64_32:
          if (value >= 0x7fffffffL) {
              barf("R_X86_64_32 relocation out of range: %s = %p\n",
@@ -4184,7 +4251,7 @@ static int relocateSection(
 #ifdef powerpc_HOST_ARCH
                             // In the .o file, this should be a relative jump to NULL
                             // and we'll change it to a relative jump to the symbol
-                        ASSERT(-word == reloc->r_address);
+                        ASSERT(word + reloc->r_address == 0);
                         jumpIsland = (unsigned long)
                                         &makeSymbolExtra(oc,
                                                          reloc->r_symbolnum,