pass arguments to unknown function calls in registers
[ghc-hetmet.git] / ghc / rts / Linker.c
index 7768c0b..a9faab5 100644 (file)
@@ -10,7 +10,9 @@
 #include "PosixSource.h"
 #endif
 
-//  Linux needs _GNU_SOURCE to get RTLD_DEFAULT from <dlfcn.h>.
+/* Linux needs _GNU_SOURCE to get RTLD_DEFAULT from <dlfcn.h> and 
+   MREMAP_MAYMOVE from <sys/mman.h>.
+ */
 #ifdef __linux__
 #define _GNU_SOURCE
 #endif
@@ -24,6 +26,7 @@
 #include "RtsUtils.h"
 #include "Schedule.h"
 #include "Storage.h"
+#include "Sparks.h"
 
 #ifdef HAVE_SYS_TYPES_H
 #include <sys/types.h>
 #include <sys/stat.h>
 #endif
 
-#if defined(HAVE_FRAMEWORK_HASKELLSUPPORT)
-#include <HaskellSupport/dlfcn.h>
-#elif defined(HAVE_DLFCN_H)
+#if defined(HAVE_DLFCN_H)
 #include <dlfcn.h>
 #endif
 
-#if defined(cygwin32_TARGET_OS)
+#if defined(cygwin32_HOST_OS)
 #ifdef HAVE_DIRENT_H
 #include <dirent.h>
 #endif
 #include <sys/wait.h>
 #endif
 
-#if defined(ia64_TARGET_ARCH) || defined(openbsd_TARGET_OS)
+#if defined(ia64_HOST_ARCH) || defined(openbsd_HOST_OS) || defined(linux_HOST_OS) || defined(freebsd_HOST_OS)
 #define USE_MMAP
 #include <fcntl.h>
 #include <sys/mman.h>
 
-#if defined(openbsd_TARGET_OS) 
+#if defined(openbsd_HOST_OS) || defined(linux_HOST_OS) || defined(freebsd_HOST_OS)
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
 
 #endif
 
-#if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS) || defined(freebsd_TARGET_OS) || defined(netbsd_TARGET_OS) || defined(openbsd_TARGET_OS)
+#if defined(linux_HOST_OS) || defined(solaris2_HOST_OS) || defined(freebsd_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS)
 #  define OBJFORMAT_ELF
-#elif defined(cygwin32_TARGET_OS) || defined (mingw32_TARGET_OS)
+#elif defined(cygwin32_HOST_OS) || defined (mingw32_HOST_OS)
 #  define OBJFORMAT_PEi386
 #  include <windows.h>
 #  include <math.h>
-#elif defined(darwin_TARGET_OS)
-#  include <mach-o/ppc/reloc.h>
+#elif defined(darwin_HOST_OS)
 #  define OBJFORMAT_MACHO
 #  include <mach-o/loader.h>
 #  include <mach-o/nlist.h>
 #  include <mach-o/reloc.h>
 #  include <mach-o/dyld.h>
+#if defined(powerpc_HOST_ARCH)
+#  include <mach-o/ppc/reloc.h>
+#endif
 #endif
 
 /* Hash table mapping symbol names to Symbol */
@@ -96,7 +99,7 @@ ObjectCode *objects = NULL;   /* initially empty */
 static int ocVerifyImage_ELF    ( ObjectCode* oc );
 static int ocGetNames_ELF       ( ObjectCode* oc );
 static int ocResolve_ELF        ( ObjectCode* oc );
-#if defined(powerpc_TARGET_ARCH)
+#if defined(powerpc_HOST_ARCH)
 static int ocAllocateJumpIslands_ELF ( ObjectCode* oc );
 #endif
 #elif defined(OBJFORMAT_PEi386)
@@ -104,13 +107,20 @@ static int ocVerifyImage_PEi386 ( ObjectCode* oc );
 static int ocGetNames_PEi386    ( ObjectCode* oc );
 static int ocResolve_PEi386     ( ObjectCode* oc );
 #elif defined(OBJFORMAT_MACHO)
-static int ocAllocateJumpIslands_MachO ( ObjectCode* oc );
 static int ocVerifyImage_MachO    ( ObjectCode* oc );
 static int ocGetNames_MachO       ( ObjectCode* oc );
 static int ocResolve_MachO        ( ObjectCode* oc );
 
+static int machoGetMisalignment( FILE * );
+#ifdef powerpc_HOST_ARCH
+static int ocAllocateJumpIslands_MachO ( ObjectCode* oc );
 static void machoInitSymbolsWithoutUnderscore( void );
 #endif
+#endif
+
+#if defined(x86_64_HOST_ARCH)
+static void*x86_64_high_symbol( char *lbl, void *addr );
+#endif
 
 /* -----------------------------------------------------------------------------
  * Built-in symbols from the RTS
@@ -123,24 +133,22 @@ typedef struct _RtsSymbolVal {
 
 
 #if !defined(PAR)
-#define Maybe_ForeignObj        SymX(mkForeignObjzh_fast)
-
 #define Maybe_Stable_Names      SymX(mkWeakzh_fast)                    \
                                SymX(makeStableNamezh_fast)             \
                                SymX(finalizzeWeakzh_fast)
 #else
 /* These are not available in GUM!!! -- HWL */
-#define Maybe_ForeignObj
 #define Maybe_Stable_Names
 #endif
 
-#if !defined (mingw32_TARGET_OS)
+#if !defined (mingw32_HOST_OS)
 #define RTS_POSIX_ONLY_SYMBOLS                  \
+      SymX(signal_handlers)                    \
       SymX(stg_sig_install)                    \
       Sym(nocldstop)
 #endif
 
-#if defined (cygwin32_TARGET_OS)
+#if defined (cygwin32_HOST_OS)
 #define RTS_MINGW_ONLY_SYMBOLS /**/
 /* Don't have the ability to read import libs / archives, so
  * we have to stupidly list a lot of what libcygwin.a
@@ -224,10 +232,10 @@ typedef struct _RtsSymbolVal {
       SymX(utime)                               \
       SymX(waitpid)
 
-#elif !defined(mingw32_TARGET_OS)
+#elif !defined(mingw32_HOST_OS)
 #define RTS_MINGW_ONLY_SYMBOLS /**/
 #define RTS_CYGWIN_ONLY_SYMBOLS /**/
-#else /* defined(mingw32_TARGET_OS) */
+#else /* defined(mingw32_HOST_OS) */
 #define RTS_POSIX_ONLY_SYMBOLS  /**/
 #define RTS_CYGWIN_ONLY_SYMBOLS /**/
 
@@ -295,11 +303,27 @@ typedef struct _RtsSymbolVal {
       SymX(exp)                                 \
       SymX(log)                                 \
       SymX(sqrt)                                \
+      SymX(powf)                                 \
+      SymX(tanhf)                                \
+      SymX(coshf)                                \
+      SymX(sinhf)                                \
+      SymX(atanf)                                \
+      SymX(acosf)                                \
+      SymX(asinf)                                \
+      SymX(tanf)                                 \
+      SymX(cosf)                                 \
+      SymX(sinf)                                 \
+      SymX(expf)                                 \
+      SymX(logf)                                 \
+      SymX(sqrtf)                                \
       SymX(memcpy)                              \
+      SymX(rts_InstallConsoleEvent)             \
+      SymX(rts_ConsoleHandlerDone)              \
       Sym(mktime)                               \
       Sym(_imp___timezone)                      \
       Sym(_imp___tzname)                        \
       Sym(_imp___iob)                           \
+      Sym(_imp___osver)                         \
       Sym(localtime)                            \
       Sym(gmtime)                               \
       Sym(opendir)                              \
@@ -309,19 +333,75 @@ typedef struct _RtsSymbolVal {
       Sym(closedir)
 #endif
 
+#if defined(darwin_TARGET_OS) && HAVE_PRINTF_LDBLSTUB
+#define RTS_DARWIN_ONLY_SYMBOLS                        \
+     Sym(asprintf$LDBLStub)                     \
+     Sym(err$LDBLStub)                          \
+     Sym(errc$LDBLStub)                         \
+     Sym(errx$LDBLStub)                         \
+     Sym(fprintf$LDBLStub)                      \
+     Sym(fscanf$LDBLStub)                       \
+     Sym(fwprintf$LDBLStub)                     \
+     Sym(fwscanf$LDBLStub)                      \
+     Sym(printf$LDBLStub)                       \
+     Sym(scanf$LDBLStub)                        \
+     Sym(snprintf$LDBLStub)                     \
+     Sym(sprintf$LDBLStub)                      \
+     Sym(sscanf$LDBLStub)                       \
+     Sym(strtold$LDBLStub)                      \
+     Sym(swprintf$LDBLStub)                     \
+     Sym(swscanf$LDBLStub)                      \
+     Sym(syslog$LDBLStub)                       \
+     Sym(vasprintf$LDBLStub)                    \
+     Sym(verr$LDBLStub)                         \
+     Sym(verrc$LDBLStub)                        \
+     Sym(verrx$LDBLStub)                        \
+     Sym(vfprintf$LDBLStub)                     \
+     Sym(vfscanf$LDBLStub)                      \
+     Sym(vfwprintf$LDBLStub)                    \
+     Sym(vfwscanf$LDBLStub)                     \
+     Sym(vprintf$LDBLStub)                      \
+     Sym(vscanf$LDBLStub)                       \
+     Sym(vsnprintf$LDBLStub)                    \
+     Sym(vsprintf$LDBLStub)                     \
+     Sym(vsscanf$LDBLStub)                      \
+     Sym(vswprintf$LDBLStub)                    \
+     Sym(vswscanf$LDBLStub)                     \
+     Sym(vsyslog$LDBLStub)                      \
+     Sym(vwarn$LDBLStub)                        \
+     Sym(vwarnc$LDBLStub)                       \
+     Sym(vwarnx$LDBLStub)                       \
+     Sym(vwprintf$LDBLStub)                     \
+     Sym(vwscanf$LDBLStub)                      \
+     Sym(warn$LDBLStub)                         \
+     Sym(warnc$LDBLStub)                        \
+     Sym(warnx$LDBLStub)                        \
+     Sym(wcstold$LDBLStub)                      \
+     Sym(wprintf$LDBLStub)                      \
+     Sym(wscanf$LDBLStub)
+#else
+#define RTS_DARWIN_ONLY_SYMBOLS
+#endif
+
 #ifndef SMP
 # define MAIN_CAP_SYM SymX(MainCapability)
 #else
 # define MAIN_CAP_SYM
 #endif
 
+#if !defined(mingw32_HOST_OS)
+#define RTS_USER_SIGNALS_SYMBOLS \
+   SymX(setIOManagerPipe)
+#else
+#define RTS_USER_SIGNALS_SYMBOLS /* nothing */
+#endif
+
 #ifdef TABLES_NEXT_TO_CODE
 #define RTS_RET_SYMBOLS /* nothing */
 #else
 #define RTS_RET_SYMBOLS                        \
       SymX(stg_enter_ret)                      \
       SymX(stg_gc_fun_ret)                     \
-      SymX(stg_ap_0_ret)                       \
       SymX(stg_ap_v_ret)                       \
       SymX(stg_ap_f_ret)                       \
       SymX(stg_ap_d_ret)                       \
@@ -339,7 +419,6 @@ typedef struct _RtsSymbolVal {
 #endif
 
 #define RTS_SYMBOLS                            \
-      Maybe_ForeignObj                         \
       Maybe_Stable_Names                       \
       Sym(StgReturn)                           \
       SymX(stg_enter_info)                     \
@@ -390,6 +469,8 @@ typedef struct _RtsSymbolVal {
       SymX(andIntegerzh_fast)                  \
       SymX(atomicallyzh_fast)                  \
       SymX(barf)                               \
+      SymX(debugBelch)                         \
+      SymX(errorBelch)                         \
       SymX(blockAsyncExceptionszh_fast)                \
       SymX(catchzh_fast)                       \
       SymX(catchRetryzh_fast)                  \
@@ -406,6 +487,7 @@ typedef struct _RtsSymbolVal {
       SymX(delayzh_fast)                       \
       SymX(deRefWeakzh_fast)                   \
       SymX(deRefStablePtrzh_fast)              \
+      SymX(dirty_MUT_VAR)                      \
       SymX(divExactIntegerzh_fast)             \
       SymX(divModIntegerzh_fast)               \
       SymX(forkzh_fast)                                \
@@ -420,7 +502,14 @@ typedef struct _RtsSymbolVal {
       SymX(genericRaise)                       \
       SymX(getProgArgv)                                \
       SymX(getStablePtr)                       \
-      SymX(initLinker)                         \
+      SymX(hs_init)                            \
+      SymX(hs_exit)                            \
+      SymX(hs_set_argv)                                \
+      SymX(hs_add_root)                                \
+      SymX(hs_perform_gc)                      \
+      SymX(hs_free_stable_ptr)                 \
+      SymX(hs_free_fun_ptr)                    \
+      SymX(initLinker)                         \
       SymX(int2Integerzh_fast)                 \
       SymX(integer2Intzh_fast)                 \
       SymX(integer2Wordzh_fast)                        \
@@ -451,6 +540,7 @@ typedef struct _RtsSymbolVal {
       SymX(newTVarzh_fast)                     \
       SymX(atomicModifyMutVarzh_fast)          \
       SymX(newPinnedByteArrayzh_fast)          \
+      SymX(newSpark)                           \
       SymX(orIntegerzh_fast)                   \
       SymX(performGC)                          \
       SymX(performMajorGC)                     \
@@ -508,7 +598,6 @@ typedef struct _RtsSymbolVal {
       SymX(rts_mkWord8)                                \
       SymX(rts_unlock)                         \
       SymX(rtsSupportsBoundThreads)            \
-      SymX(run_queue_hd)                       \
       SymX(__hscore_get_saved_termios)         \
       SymX(__hscore_set_saved_termios)         \
       SymX(setProgArgv)                                \
@@ -518,15 +607,15 @@ typedef struct _RtsSymbolVal {
       SymX(stable_ptr_table)                   \
       SymX(stackOverflow)                      \
       SymX(stg_CAF_BLACKHOLE_info)             \
-      SymX(stg_BLACKHOLE_BQ_info)              \
       SymX(awakenBlockedQueue)                 \
       SymX(stg_CHARLIKE_closure)               \
       SymX(stg_EMPTY_MVAR_info)                        \
       SymX(stg_IND_STATIC_info)                        \
       SymX(stg_INTLIKE_closure)                        \
+      SymX(stg_MUT_ARR_PTRS_DIRTY_info)                \
       SymX(stg_MUT_ARR_PTRS_FROZEN_info)       \
+      SymX(stg_MUT_ARR_PTRS_FROZEN0_info)      \
       SymX(stg_WEAK_info)                       \
-      SymX(stg_ap_0_info)                      \
       SymX(stg_ap_v_info)                      \
       SymX(stg_ap_f_info)                      \
       SymX(stg_ap_d_info)                      \
@@ -541,6 +630,21 @@ typedef struct _RtsSymbolVal {
       SymX(stg_ap_pppp_info)                   \
       SymX(stg_ap_ppppp_info)                  \
       SymX(stg_ap_pppppp_info)                 \
+      SymX(stg_ap_0_fast)                      \
+      SymX(stg_ap_v_fast)                      \
+      SymX(stg_ap_f_fast)                      \
+      SymX(stg_ap_d_fast)                      \
+      SymX(stg_ap_l_fast)                      \
+      SymX(stg_ap_n_fast)                      \
+      SymX(stg_ap_p_fast)                      \
+      SymX(stg_ap_pv_fast)                     \
+      SymX(stg_ap_pp_fast)                     \
+      SymX(stg_ap_ppv_fast)                    \
+      SymX(stg_ap_ppp_fast)                    \
+      SymX(stg_ap_pppv_fast)                   \
+      SymX(stg_ap_pppp_fast)                   \
+      SymX(stg_ap_ppppp_fast)                  \
+      SymX(stg_ap_pppppp_fast)                 \
       SymX(stg_ap_1_upd_info)                  \
       SymX(stg_ap_2_upd_info)                  \
       SymX(stg_ap_3_upd_info)                  \
@@ -579,7 +683,21 @@ typedef struct _RtsSymbolVal {
       SymX(word2Integerzh_fast)                        \
       SymX(writeTVarzh_fast)                   \
       SymX(xorIntegerzh_fast)                  \
-      SymX(yieldzh_fast)
+      SymX(yieldzh_fast)                        \
+      SymX(stg_interp_constr_entry)             \
+      SymX(stg_interp_constr1_entry)            \
+      SymX(stg_interp_constr2_entry)            \
+      SymX(stg_interp_constr3_entry)            \
+      SymX(stg_interp_constr4_entry)            \
+      SymX(stg_interp_constr5_entry)            \
+      SymX(stg_interp_constr6_entry)            \
+      SymX(stg_interp_constr7_entry)            \
+      SymX(stg_interp_constr8_entry)            \
+      SymX(stgMallocBytesRWX)                   \
+      SymX(getAllocations)                      \
+      SymX(revertCAFs)                          \
+      SymX(RtsFlags)                            \
+      RTS_USER_SIGNALS_SYMBOLS
 
 #ifdef SUPPORT_LONG_LONGS
 #define RTS_LONG_LONG_SYMS                     \
@@ -596,11 +714,12 @@ typedef struct _RtsSymbolVal {
       Sym(__udivdi3)                            \
       Sym(__moddi3)                             \
       Sym(__umoddi3)                           \
+      Sym(__muldi3)                            \
       Sym(__ashldi3)                           \
       Sym(__ashrdi3)                           \
       Sym(__lshrdi3)                           \
       Sym(__eprintf)
-#elif defined(ia64_TARGET_ARCH)
+#elif defined(ia64_HOST_ARCH)
 #define RTS_LIBGCC_SYMBOLS                     \
       Sym(__divdi3)                            \
       Sym(__udivdi3)                            \
@@ -612,7 +731,7 @@ typedef struct _RtsSymbolVal {
 #define RTS_LIBGCC_SYMBOLS
 #endif
 
-#ifdef darwin_TARGET_OS
+#if defined(darwin_HOST_OS) && defined(powerpc_HOST_ARCH)
       // Symbols that don't have a leading underscore
       // on Mac OS X. They have to receive special treatment,
       // see machoInitSymbolsWithoutUnderscore()
@@ -631,6 +750,7 @@ RTS_LONG_LONG_SYMS
 RTS_POSIX_ONLY_SYMBOLS
 RTS_MINGW_ONLY_SYMBOLS
 RTS_CYGWIN_ONLY_SYMBOLS
+RTS_DARWIN_ONLY_SYMBOLS
 RTS_LIBGCC_SYMBOLS
 #undef Sym
 #undef SymX
@@ -660,6 +780,12 @@ static RtsSymbolVal rtsSyms[] = {
       RTS_MINGW_ONLY_SYMBOLS
       RTS_CYGWIN_ONLY_SYMBOLS
       RTS_LIBGCC_SYMBOLS
+#if defined(darwin_HOST_OS) && defined(i386_HOST_ARCH)
+      // dyld stub code contains references to this,
+      // but it should never be called because we treat
+      // lazy pointers as nonlazy.
+      { "dyld_stub_binding_helper", (void*)0xDEADBEEF },
+#endif
       { 0, 0 } /* sentinel */
 };
 
@@ -709,7 +835,7 @@ static void *dl_prog_handle;
 #endif
 
 /* dlopen(NULL,..) doesn't work so we grab libc explicitly */
-#if defined(openbsd_TARGET_OS)
+#if defined(openbsd_HOST_OS)
 static void *dl_libc_handle;
 #endif
 
@@ -732,7 +858,7 @@ initLinker( void )
        ghciInsertStrHashTable("(GHCi built-in symbols)",
                                symhash, sym->lbl, sym->addr);
     }
-#   if defined(OBJFORMAT_MACHO)
+#   if defined(OBJFORMAT_MACHO) && defined(powerpc_HOST_ARCH)
     machoInitSymbolsWithoutUnderscore();
 #   endif
 
@@ -741,10 +867,10 @@ initLinker( void )
     dl_prog_handle = RTLD_DEFAULT;
 #   else
     dl_prog_handle = dlopen(NULL, RTLD_LAZY);
-#   if defined(openbsd_TARGET_OS)
+#   if defined(openbsd_HOST_OS)
     dl_libc_handle = dlopen("libc.so", RTLD_LAZY);
 #   endif
-#   endif // RTLD_DEFAULT
+#   endif /* RTLD_DEFAULT */
 #   endif
 }
 
@@ -874,9 +1000,19 @@ lookupSymbol( char *lbl )
 
     if (val == NULL) {
 #       if defined(OBJFORMAT_ELF)
-#      if defined(openbsd_TARGET_OS)
+#      if defined(openbsd_HOST_OS)
        val = dlsym(dl_prog_handle, lbl);
        return (val != NULL) ? val : dlsym(dl_libc_handle,lbl);
+#      elif defined(x86_64_HOST_ARCH)
+       val = dlsym(dl_prog_handle, lbl);
+       if (val >= (void *)0x80000000) {
+           void *new_val;
+           new_val = x86_64_high_symbol(lbl, val);
+           IF_DEBUG(linker,debugBelch("lookupSymbol: relocating out of range symbol: %s = %p, now %p\n", lbl, val, new_val));
+           return new_val;
+       } else {
+           return val;
+       }
 #      else /* not openbsd */
        return dlsym(dl_prog_handle, lbl);
 #      endif
@@ -970,14 +1106,14 @@ void ghci_enquire ( char* addr )
             // debugBelch("ghci_enquire: can't find %s\n", sym);
          }
          else if (addr-DELTA <= a && a <= addr+DELTA) {
-            debugBelch("%p + %3d  ==  `%s'\n", addr, a - addr, sym);
+            debugBelch("%p + %3d  ==  `%s'\n", addr, (int)(a - addr), sym);
          }
       }
    }
 }
 #endif
 
-#ifdef ia64_TARGET_ARCH
+#ifdef ia64_HOST_ARCH
 static unsigned int PLTSize(void);
 #endif
 
@@ -997,8 +1133,8 @@ loadObj( char *path )
    void *map_addr = NULL;
 #else
    FILE *f;
+   int misalignment;
 #endif
-
    initLinker();
 
    /* debugBelch("loadObj %s\n", path ); */
@@ -1060,7 +1196,7 @@ loadObj( char *path )
 
    /* On many architectures malloc'd memory isn't executable, so we need to use mmap. */
 
-#if defined(openbsd_TARGET_OS)
+#if defined(openbsd_HOST_OS)
    fd = open(path, O_RDONLY, S_IRUSR);
 #else
    fd = open(path, O_RDONLY);
@@ -1070,7 +1206,7 @@ loadObj( char *path )
 
    pagesize = getpagesize();
 
-#ifdef ia64_TARGET_ARCH
+#ifdef ia64_HOST_ARCH
    /* The PLT needs to be right before the object */
    n = ROUND_UP(PLTSize(), pagesize);
    oc->plt = mmap(NULL, n, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
@@ -1082,7 +1218,19 @@ loadObj( char *path )
 #endif
 
    n = ROUND_UP(oc->fileSize, pagesize);
-   oc->image = mmap(map_addr, n, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
+
+   /* Link objects into the lower 2Gb on x86_64.  GHC assumes the
+    * small memory model on this architecture (see gcc docs,
+    * -mcmodel=small).
+    */
+#ifdef x86_64_HOST_ARCH
+#define EXTRA_MAP_FLAGS MAP_32BIT
+#else
+#define EXTRA_MAP_FLAGS 0
+#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)
       barf("loadObj: can't map `%s'", path);
 
@@ -1090,13 +1238,30 @@ loadObj( char *path )
 
 #else /* !USE_MMAP */
 
-   oc->image = stgMallocBytes(oc->fileSize, "loadObj(image)");
-
    /* load the image into memory */
    f = fopen(path, "rb");
    if (!f)
        barf("loadObj: can't read `%s'", path);
 
+#ifdef darwin_HOST_OS
+    // In a Mach-O .o file, all sections can and will be misaligned
+    // if the total size of the headers is not a multiple of the
+    // desired alignment. This is fine for .o files that only serve
+    // as input for the static linker, but it's not fine for us,
+    // as SSE (used by gcc for floating point) and Altivec require
+    // 16-byte alignment.
+    // We calculate the correct alignment from the header before
+    // reading the file, and then we misalign oc->image on purpose so
+    // that the actual sections end up aligned again.
+   misalignment = machoGetMisalignment(f);
+   oc->misalignment = misalignment;
+#else
+   misalignment = 0;
+#endif
+
+   oc->image = stgMallocBytes(oc->fileSize + misalignment, "loadObj(image)");
+   oc->image += misalignment;
+   
    n = fread ( oc->image, 1, oc->fileSize, f );
    if (n != oc->fileSize)
       barf("loadObj: error whilst reading `%s'", path);
@@ -1105,10 +1270,10 @@ loadObj( char *path )
 
 #endif /* USE_MMAP */
 
-#  if defined(OBJFORMAT_MACHO)
+#  if defined(OBJFORMAT_MACHO) && defined(powerpc_HOST_ARCH)
    r = ocAllocateJumpIslands_MachO ( oc );
    if (!r) { return r; }
-#  elif defined(OBJFORMAT_ELF) && defined(powerpc_TARGET_ARCH)
+#  elif defined(OBJFORMAT_ELF) && defined(powerpc_HOST_ARCH)
    r = ocAllocateJumpIslands_ELF ( oc );
    if (!r) { return r; }
 #endif
@@ -1282,7 +1447,7 @@ static void addSection ( ObjectCode* oc, SectionKind kind,
  * PowerPC specifics (jump islands)
  * ------------------------------------------------------------------------*/
 
-#if defined(powerpc_TARGET_ARCH)
+#if defined(powerpc_HOST_ARCH)
 
 /*
   ocAllocateJumpIslands
@@ -1302,21 +1467,73 @@ static void addSection ( ObjectCode* oc, SectionKind kind,
 
 static int ocAllocateJumpIslands( ObjectCode* oc, int count, int first )
 {
+#ifdef USE_MMAP
+  int pagesize, n, m;
+#endif
   int aligned;
+  int misalignment = 0;
+#if darwin_HOST_OS
+  misalignment = oc->misalignment;
+#endif
 
   if( count > 0 )
   {
-#ifdef USE_MMAP
-    #error ocAllocateJumpIslands doesnt want USE_MMAP to be defined
-#endif
     // round up to the nearest 4
     aligned = (oc->fileSize + 3) & ~3;
 
+#ifdef USE_MMAP
+    #ifndef linux_HOST_OS /* mremap is a linux extension */
+        #error ocAllocateJumpIslands doesnt want USE_MMAP to be defined
+    #endif
+
+    pagesize = getpagesize();
+    n = ROUND_UP( oc->fileSize, pagesize );
+    m = ROUND_UP( aligned + sizeof (ppcJumpIsland) * count, pagesize );
+
+    /* If we have a half-page-size file and map one page of it then
+     * the part of the page after the size of the file remains accessible.
+     * If, however, we map in 2 pages, the 2nd page is not accessible
+     * and will give a "Bus Error" on access.  To get around this, we check
+     * if we need any extra pages for the jump islands and map them in
+     * anonymously.  We must check that we actually require extra pages
+     * otherwise the attempt to mmap 0 pages of anonymous memory will
+     * fail -EINVAL.
+     */
+
+    if( m > n )
+    {
+      /* The effect of this mremap() call is only the ensure that we have
+       * a sufficient number of virtually contiguous pages.  As returned from
+       * mremap, the pages past the end of the file are not backed.  We give
+       * them a backing by using MAP_FIXED to map in anonymous pages.
+       */
+      oc->image = mremap( oc->image, n, m, MREMAP_MAYMOVE );
+
+      if( oc->image == MAP_FAILED )
+      {
+        errorBelch( "Unable to mremap for Jump Islands\n" );
+        return 0;
+      }
+
+      if( mmap( oc->image + n, m - n, PROT_READ | PROT_WRITE | PROT_EXEC,
+                MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0 ) == MAP_FAILED )
+      {
+        errorBelch( "Unable to mmap( MAP_FIXED ) for Jump Islands\n" );
+        return 0;
+      }
+    }
+
+#else
+    oc->image -= misalignment;
     oc->image = stgReallocBytes( oc->image,
-                                 aligned + sizeof( ppcJumpIsland ) * count,
+                                 misalignment + 
+                                 aligned + sizeof (ppcJumpIsland) * count,
                                  "ocAllocateJumpIslands" );
-    oc->jump_islands = (ppcJumpIsland *) (((char *) oc->image) + aligned);
-    memset( oc->jump_islands, 0, sizeof( ppcJumpIsland ) * count );
+    oc->image += misalignment;
+#endif /* USE_MMAP */
+
+    oc->jump_islands = (ppcJumpIsland *) (oc->image + aligned);
+    memset( oc->jump_islands, 0, sizeof (ppcJumpIsland) * count );
   }
   else
     oc->jump_islands = NULL;
@@ -1666,24 +1883,25 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
             + hdr->NumberOfSymbols * sizeof_COFF_symbol;
 
    if (hdr->Machine != 0x14c) {
-      errorBelch("Not x86 PEi386");
+      errorBelch("%s: Not x86 PEi386", oc->fileName);
       return 0;
    }
    if (hdr->SizeOfOptionalHeader != 0) {
-      errorBelch("PEi386 with nonempty optional header");
+      errorBelch("%s: PEi386 with nonempty optional header", oc->fileName);
       return 0;
    }
    if ( /* (hdr->Characteristics & MYIMAGE_FILE_RELOCS_STRIPPED) || */
         (hdr->Characteristics & MYIMAGE_FILE_EXECUTABLE_IMAGE) ||
         (hdr->Characteristics & MYIMAGE_FILE_DLL) ||
         (hdr->Characteristics & MYIMAGE_FILE_SYSTEM) ) {
-      errorBelch("Not a PEi386 object file");
+      errorBelch("%s: Not a PEi386 object file", oc->fileName);
       return 0;
    }
    if ( (hdr->Characteristics & MYIMAGE_FILE_BYTES_REVERSED_HI)
         /* || !(hdr->Characteristics & MYIMAGE_FILE_32BIT_MACHINE) */ ) {
-      errorBelch("Invalid PEi386 word size or endiannness: %d",
-            (int)(hdr->Characteristics));
+      errorBelch("%s: Invalid PEi386 word size or endiannness: %d",
+                oc->fileName,
+                (int)(hdr->Characteristics));
       return 0;
    }
    /* If the string table size is way crazy, this might indicate that
@@ -1858,19 +2076,37 @@ ocGetNames_PEi386 ( ObjectCode* oc )
    /* Allocate space for any (local, anonymous) .bss sections. */
 
    for (i = 0; i < hdr->NumberOfSections; i++) {
+      UInt32 bss_sz;
       UChar* zspace;
       COFF_section* sectab_i
          = (COFF_section*)
            myindex ( sizeof_COFF_section, sectab, i );
       if (0 != strcmp(sectab_i->Name, ".bss")) continue;
-      if (sectab_i->VirtualSize == 0) continue;
+      /* sof 10/05: the PE spec text isn't too clear regarding what
+       * the SizeOfRawData field is supposed to hold for object
+       * file sections containing just uninitialized data -- for executables,
+       * it is supposed to be zero; unclear what it's supposed to be
+       * for object files. However, VirtualSize is guaranteed to be
+       * zero for object files, which definitely suggests that SizeOfRawData
+       * will be non-zero (where else would the size of this .bss section be
+       * stored?) Looking at the COFF_section info for incoming object files,
+       * this certainly appears to be the case.
+       *
+       * => I suspect we've been incorrectly handling .bss sections in (relocatable)
+       * object files up until now. This turned out to bite us with ghc-6.4.1's use
+       * of gcc-3.4.x, which has started to emit initially-zeroed-out local 'static'
+       * variable decls into to the .bss section. (The specific function in Q which
+       * triggered this is libraries/base/cbits/dirUtils.c:__hscore_getFolderPath())
+       */
+      if (sectab_i->VirtualSize == 0 && sectab_i->SizeOfRawData == 0) continue;
       /* This is a non-empty .bss section.  Allocate zeroed space for
          it, and set its PointerToRawData field such that oc->image +
          PointerToRawData == addr_of_zeroed_space.  */
-      zspace = stgCallocBytes(1, sectab_i->VirtualSize,
-                              "ocGetNames_PEi386(anonymous bss)");
+      bss_sz = sectab_i->VirtualSize;
+      if ( bss_sz < sectab_i->SizeOfRawData) { bss_sz = sectab_i->SizeOfRawData; }
+      zspace = stgCallocBytes(1, bss_sz, "ocGetNames_PEi386(anonymous bss)");
       sectab_i->PointerToRawData = ((UChar*)zspace) - ((UChar*)(oc->image));
-      addProddableBlock(oc, zspace, sectab_i->VirtualSize);
+      addProddableBlock(oc, zspace, bss_sz);
       /* debugBelch("BSS anon section at 0x%x\n", zspace); */
    }
 
@@ -1899,6 +2135,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
 #     endif
 
       if (0==strcmp(".text",sectab_i->Name) ||
+          0==strcmp(".rdata",sectab_i->Name)||
           0==strcmp(".rodata",sectab_i->Name))
          kind = SECTIONKIND_CODE_OR_RODATA;
       if (0==strcmp(".data",sectab_i->Name) ||
@@ -1917,8 +2154,10 @@ ocGetNames_PEi386 ( ObjectCode* oc )
              information. */
           && 0 != strcmp(".stab", sectab_i->Name)
           && 0 != strcmp(".stabstr", sectab_i->Name)
+          /* ignore constructor section for now */
+          && 0 != strcmp(".ctors", sectab_i->Name)
          ) {
-         errorBelch("Unknown PEi386 section name `%s'", sectab_i->Name);
+         errorBelch("Unknown PEi386 section name `%s' (while processing: %s)", sectab_i->Name, oc->fileName);
          return 0;
       }
 
@@ -2060,7 +2299,8 @@ ocResolve_PEi386 ( ObjectCode* oc )
       /* Ignore sections called which contain stabs debugging
          information. */
       if (0 == strcmp(".stab", sectab_i->Name)
-          || 0 == strcmp(".stabstr", sectab_i->Name))
+          || 0 == strcmp(".stabstr", sectab_i->Name)
+          || 0 == strcmp(".ctors", sectab_i->Name))
          continue;
 
       if ( sectab_i->Characteristics & MYIMAGE_SCN_LNK_NRELOC_OVFL ) {
@@ -2077,8 +2317,14 @@ ocResolve_PEi386 ( ObjectCode* oc )
         COFF_reloc* rel = (COFF_reloc*)
                            myindex ( sizeof_COFF_reloc, reltab, 0 );
        noRelocs = rel->VirtualAddress;
+
+       /* 10/05: we now assume (and check for) a GNU ld that is capable
+        * of handling object files with (>2^16) of relocs.
+        */
+#if 0
        debugBelch("WARNING: Overflown relocation field (# relocs found: %u)\n",
                   noRelocs);
+#endif
        j = 1;
       } else {
        noRelocs = sectab_i->NumberOfRelocations;
@@ -2139,7 +2385,7 @@ ocResolve_PEi386 ( ObjectCode* oc )
            /* Newline first because the interactive linker has printed "linking..." */
             errorBelch("\n%s: unknown symbol `%s'", oc->fileName, symbol);
             return 0;
-           foundit:
+           foundit:;
          }
          checkProddableBlock(oc, pP);
          switch (reltab_j->Type) {
@@ -2157,9 +2403,22 @@ ocResolve_PEi386 ( ObjectCode* oc )
                   -- hence the constant 4.
                   Also I don't know if A should be added, but so
                   far it has always been zero.
+
+                 SOF 05/2005: 'A' (old contents of *pP) have been observed
+                 to contain values other than zero (the 'wx' object file
+                 that came with wxhaskell-0.9.4; dunno how it was compiled..).
+                 So, add displacement to old value instead of asserting
+                 A to be zero. Fixes wxhaskell-related crashes, and no other
+                 ill effects have been observed.
+                 
+                 Update: the reason why we're seeing these more elaborate
+                 relocations is due to a switch in how the NCG compiles SRTs 
+                 and offsets to them from info tables. SRTs live in .(ro)data, 
+                 while info tables live in .text, causing GAS to emit REL32/DISP32 
+                 relocations with non-zero values. Adding the displacement is
+                 the right thing to do.
               */
-               ASSERT(A==0);
-               *pP = S - ((UInt32)pP) - 4;
+               *pP = S - ((UInt32)pP) - 4 + A;
                break;
             default:
                debugBelch("%s: unhandled PEi386 relocation type %d",
@@ -2186,14 +2445,14 @@ ocResolve_PEi386 ( ObjectCode* oc )
 #define FALSE 0
 #define TRUE  1
 
-#if defined(sparc_TARGET_ARCH)
+#if defined(sparc_HOST_ARCH)
 #  define ELF_TARGET_SPARC  /* Used inside <elf.h> */
-#elif defined(i386_TARGET_ARCH)
+#elif defined(i386_HOST_ARCH)
 #  define ELF_TARGET_386    /* Used inside <elf.h> */
-#elif defined(x86_64_TARGET_ARCH)
+#elif defined(x86_64_HOST_ARCH)
 #  define ELF_TARGET_X64_64
 #  define ELF_64BIT
-#elif defined (ia64_TARGET_ARCH)
+#elif defined (ia64_HOST_ARCH)
 #  define ELF_TARGET_IA64   /* Used inside <elf.h> */
 #  define ELF_64BIT
 #  define ELF_FUNCTION_DESC /* calling convention uses function descriptors */
@@ -2201,7 +2460,7 @@ ocResolve_PEi386 ( ObjectCode* oc )
 #  define ELF_NEED_PLT      /* needs Procedure Linkage Tables */
 #endif
 
-#if !defined(openbsd_TARGET_OS)
+#if !defined(openbsd_HOST_OS)
 #include <elf.h>
 #else
 /* openbsd elf has things in different places, with diff names */
@@ -2323,7 +2582,7 @@ copyFunctionDesc(Elf_Addr target)
 #endif
 
 #ifdef ELF_NEED_PLT
-#ifdef ia64_TARGET_ARCH
+#ifdef ia64_HOST_ARCH
 static void ia64_reloc_gprel22(Elf_Addr target, Elf_Addr value);
 static void ia64_reloc_pcrel21(Elf_Addr target, Elf_Addr value, ObjectCode *oc);
 
@@ -2375,6 +2634,64 @@ PLTSize(void)
 #endif
 
 
+#if x86_64_HOST_ARCH
+// On x86_64, 32-bit relocations are often used, which requires that
+// we can resolve a symbol to a 32-bit offset.  However, shared
+// libraries are placed outside the 2Gb area, which leaves us with a
+// problem when we need to give a 32-bit offset to a symbol in a
+// shared library.
+// 
+// For a function symbol, we can allocate a bounce sequence inside the
+// 2Gb area and resolve the symbol to this.  The bounce sequence is
+// simply a long jump instruction to the real location of the symbol.
+//
+// For data references, we're screwed.
+//
+typedef struct {
+    unsigned char jmp[8];  /* 6 byte instruction: jmpq *0x00000002(%rip) */
+    void *addr;
+} x86_64_bounce;
+
+#define X86_64_BB_SIZE 1024
+
+static x86_64_bounce *x86_64_bounce_buffer = NULL;
+static nat x86_64_bb_next_off;
+
+static void*
+x86_64_high_symbol( char *lbl, void *addr )
+{
+    x86_64_bounce *bounce;
+
+    if ( x86_64_bounce_buffer == NULL || 
+        x86_64_bb_next_off >= X86_64_BB_SIZE ) {
+       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);
+       if (x86_64_bounce_buffer == MAP_FAILED) {
+           barf("x86_64_high_symbol: mmap failed");
+       }
+       x86_64_bb_next_off = 0;
+    }
+    bounce = &x86_64_bounce_buffer[x86_64_bb_next_off];
+    bounce->jmp[0] = 0xff;
+    bounce->jmp[1] = 0x25;
+    bounce->jmp[2] = 0x02;
+    bounce->jmp[3] = 0x00;
+    bounce->jmp[4] = 0x00;
+    bounce->jmp[5] = 0x00;
+    bounce->addr = addr;
+    x86_64_bb_next_off++;
+
+    IF_DEBUG(linker, debugBelch("x86_64: allocated bounce entry for %s->%p at %p\n",
+                               lbl, addr, bounce));
+
+    insertStrHashTable(symhash, lbl, bounce);
+    return bounce;
+}
+#endif
+
+
 /*
  * Generic ELF functions
  */
@@ -2404,7 +2721,7 @@ findElfSection ( void* objImage, Elf_Word sh_type )
    return ptr;
 }
 
-#if defined(ia64_TARGET_ARCH)
+#if defined(ia64_HOST_ARCH)
 static Elf_Addr
 findElfSegment ( void* objImage, Elf_Addr vaddr )
 {
@@ -2449,10 +2766,10 @@ ocVerifyImage_ELF ( ObjectCode* oc )
    }
 
    if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
-       IF_DEBUG(linker,debugBelch( "Is little-endian" ));
+       IF_DEBUG(linker,debugBelch( "Is little-endian\n" ));
    } else
    if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
-       IF_DEBUG(linker,debugBelch( "Is big-endian" ));
+       IF_DEBUG(linker,debugBelch( "Is big-endian\n" ));
    } else {
        errorBelch("%s: unknown endiannness", oc->fileName);
        return 0;
@@ -2462,7 +2779,7 @@ ocVerifyImage_ELF ( ObjectCode* oc )
       errorBelch("%s: not a relocatable object (.o) file", oc->fileName);
       return 0;
    }
-   IF_DEBUG(linker, debugBelch( "Is a relocatable object (.o) file" ));
+   IF_DEBUG(linker, debugBelch( "Is a relocatable object (.o) file\n" ));
 
    IF_DEBUG(linker,debugBelch( "Architecture is " ));
    switch (ehdr->e_machine) {
@@ -2472,14 +2789,17 @@ ocVerifyImage_ELF ( ObjectCode* oc )
       case EM_IA_64: IF_DEBUG(linker,debugBelch( "ia64" )); break;
 #endif
       case EM_PPC:   IF_DEBUG(linker,debugBelch( "powerpc32" )); break;
+#ifdef EM_X86_64
+      case EM_X86_64: IF_DEBUG(linker,debugBelch( "x86_64" )); break;
+#endif
       default:       IF_DEBUG(linker,debugBelch( "unknown" ));
                      errorBelch("%s: unknown architecture", oc->fileName);
                      return 0;
    }
 
    IF_DEBUG(linker,debugBelch(
-             "\nSection header table: start %d, n_entries %d, ent_size %d",
-             ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize  ));
+             "\nSection header table: start %ld, n_entries %d, ent_size %d\n",
+             (long)ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize  ));
 
    ASSERT (ehdr->e_shentsize == sizeof(Elf_Shdr));
 
@@ -2489,7 +2809,7 @@ ocVerifyImage_ELF ( ObjectCode* oc )
       errorBelch("%s: no section header string table", oc->fileName);
       return 0;
    } else {
-      IF_DEBUG(linker,debugBelch( "Section header string table is section %d",
+      IF_DEBUG(linker,debugBelch( "Section header string table is section %d\n",
                           ehdr->e_shstrndx));
       sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
    }
@@ -2540,13 +2860,13 @@ ocVerifyImage_ELF ( ObjectCode* oc )
    IF_DEBUG(linker,debugBelch( "\nSymbol tables" ));
    for (i = 0; i < ehdr->e_shnum; i++) {
       if (shdr[i].sh_type != SHT_SYMTAB) continue;
-      IF_DEBUG(linker,debugBelch( "section %d is a symbol table", i ));
+      IF_DEBUG(linker,debugBelch( "section %d is a symbol table\n", i ));
       nsymtabs++;
       stab = (Elf_Sym*) (ehdrC + shdr[i].sh_offset);
       nent = shdr[i].sh_size / sizeof(Elf_Sym);
-      IF_DEBUG(linker,debugBelch( "   number of entries is apparently %d (%d rem)",
+      IF_DEBUG(linker,debugBelch( "   number of entries is apparently %d (%ld rem)\n",
                nent,
-               shdr[i].sh_size % sizeof(Elf_Sym)
+               (long)shdr[i].sh_size % sizeof(Elf_Sym)
              ));
       if (0 != shdr[i].sh_size % sizeof(Elf_Sym)) {
          errorBelch("%s: non-integral number of symbol table entries", oc->fileName);
@@ -2591,6 +2911,38 @@ ocVerifyImage_ELF ( ObjectCode* oc )
    return 1;
 }
 
+static int getSectionKind_ELF( Elf_Shdr *hdr, int *is_bss )
+{
+    *is_bss = FALSE;
+
+    if (hdr->sh_type == SHT_PROGBITS
+       && (hdr->sh_flags & SHF_ALLOC) && (hdr->sh_flags & SHF_EXECINSTR)) {
+       /* .text-style section */
+       return SECTIONKIND_CODE_OR_RODATA;
+    }
+
+    if (hdr->sh_type == SHT_PROGBITS
+           && (hdr->sh_flags & SHF_ALLOC) && (hdr->sh_flags & SHF_WRITE)) {
+           /* .data-style section */
+           return SECTIONKIND_RWDATA;
+    }
+
+    if (hdr->sh_type == SHT_PROGBITS
+       && (hdr->sh_flags & SHF_ALLOC) && !(hdr->sh_flags & SHF_WRITE)) {
+       /* .rodata-style section */
+       return SECTIONKIND_CODE_OR_RODATA;
+    }
+
+    if (hdr->sh_type == SHT_NOBITS
+       && (hdr->sh_flags & SHF_ALLOC) && (hdr->sh_flags & SHF_WRITE)) {
+       /* .bss-style section */
+       *is_bss = TRUE;
+       return SECTIONKIND_RWDATA;
+    }
+
+    return SECTIONKIND_OTHER;
+}
+
 
 static int
 ocGetNames_ELF ( ObjectCode* oc )
@@ -2615,34 +2967,8 @@ ocGetNames_ELF ( ObjectCode* oc )
       /* Figure out what kind of section it is.  Logic derived from
          Figure 1.14 ("Special Sections") of the ELF document
          ("Portable Formats Specification, Version 1.1"). */
-      Elf_Shdr    hdr    = shdr[i];
-      SectionKind kind   = SECTIONKIND_OTHER;
       int         is_bss = FALSE;
-
-      if (hdr.sh_type == SHT_PROGBITS
-          && (hdr.sh_flags & SHF_ALLOC) && (hdr.sh_flags & SHF_EXECINSTR)) {
-         /* .text-style section */
-         kind = SECTIONKIND_CODE_OR_RODATA;
-      }
-      else
-      if (hdr.sh_type == SHT_PROGBITS
-          && (hdr.sh_flags & SHF_ALLOC) && (hdr.sh_flags & SHF_WRITE)) {
-         /* .data-style section */
-         kind = SECTIONKIND_RWDATA;
-      }
-      else
-      if (hdr.sh_type == SHT_PROGBITS
-          && (hdr.sh_flags & SHF_ALLOC) && !(hdr.sh_flags & SHF_WRITE)) {
-         /* .rodata-style section */
-         kind = SECTIONKIND_CODE_OR_RODATA;
-      }
-      else
-      if (hdr.sh_type == SHT_NOBITS
-          && (hdr.sh_flags & SHF_ALLOC) && (hdr.sh_flags & SHF_WRITE)) {
-         /* .bss-style section */
-         kind = SECTIONKIND_RWDATA;
-         is_bss = TRUE;
-      }
+      SectionKind kind   = getSectionKind_ELF(&shdr[i], &is_bss);
 
       if (is_bss && shdr[i].sh_size > 0) {
          /* This is a non-empty .bss section.  Allocate zeroed space for
@@ -2747,7 +3073,7 @@ ocGetNames_ELF ( ObjectCode* oc )
             }
          } else {
             /* Skip. */
-            IF_DEBUG(linker,debugBelch( "skipping `%s'",
+            IF_DEBUG(linker,debugBelch( "skipping `%s'\n",
                                    strtab + stab[j].st_name ));
             /*
             debugBelch(
@@ -2784,9 +3110,19 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
 
    stab  = (Elf_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset);
    targ  = (Elf_Word*)(ehdrC + shdr[ target_shndx ].sh_offset);
-   IF_DEBUG(linker,debugBelch( "relocations for section %d using symtab %d",
+   IF_DEBUG(linker,debugBelch( "relocations for section %d using symtab %d\n",
                           target_shndx, symtab_shndx ));
 
+   /* Skip sections that we're not interested in. */
+   {
+       int is_bss;
+       SectionKind kind = getSectionKind_ELF(&shdr[target_shndx], &is_bss);
+       if (kind == SECTIONKIND_OTHER) {
+          IF_DEBUG(linker,debugBelch( "skipping (target section not loaded)"));
+          return 1;
+       }
+   }
+
    for (j = 0; j < nent; j++) {
       Elf_Addr offset = rtab[j].r_offset;
       Elf_Addr info   = rtab[j].r_info;
@@ -2824,23 +3160,23 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC,
             errorBelch("%s: unknown symbol `%s'", oc->fileName, symbol);
            return 0;
          }
-         IF_DEBUG(linker,debugBelch( "`%s' resolves to %p", symbol, (void*)S ));
+         IF_DEBUG(linker,debugBelch( "`%s' resolves to %p\n", symbol, (void*)S ));
       }
 
-      IF_DEBUG(linker,debugBelch( "Reloc: P = %p   S = %p   A = %p",
+      IF_DEBUG(linker,debugBelch( "Reloc: P = %p   S = %p   A = %p\n",
                             (void*)P, (void*)S, (void*)A ));
       checkProddableBlock ( oc, pP );
 
       value = S + A;
 
       switch (ELF_R_TYPE(info)) {
-#        ifdef i386_TARGET_ARCH
+#        ifdef i386_HOST_ARCH
          case R_386_32:   *pP = value;     break;
          case R_386_PC32: *pP = value - P; break;
 #        endif
          default:
-            errorBelch("%s: unhandled ELF relocation(Rel) type %d\n",
-                 oc->fileName, ELF_R_TYPE(info));
+            errorBelch("%s: unhandled ELF relocation(Rel) type %lu\n",
+                 oc->fileName, (lnat)ELF_R_TYPE(info));
             return 0;
       }
 
@@ -2856,7 +3192,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
                           Elf_Sym*  stab, char* strtab )
 {
    int j;
-   char *symbol;
+   char *symbol = NULL;
    Elf_Addr targ;
    Elf_Rela* rtab = (Elf_Rela*) (ehdrC + shdr[shnum].sh_offset);
    int         nent = shdr[shnum].sh_size / sizeof(Elf_Rela);
@@ -2865,11 +3201,11 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
 
    stab  = (Elf_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset);
    targ  = (Elf_Addr) (ehdrC + shdr[ target_shndx ].sh_offset);
-   IF_DEBUG(linker,debugBelch( "relocations for section %d using symtab %d",
+   IF_DEBUG(linker,debugBelch( "relocations for section %d using symtab %d\n",
                           target_shndx, symtab_shndx ));
 
    for (j = 0; j < nent; j++) {
-#if defined(DEBUG) || defined(sparc_TARGET_ARCH) || defined(ia64_TARGET_ARCH) || defined(powerpc_TARGET_ARCH)
+#if defined(DEBUG) || defined(sparc_HOST_ARCH) || defined(ia64_HOST_ARCH) || defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH)
       /* This #ifdef only serves to avoid unused-var warnings. */
       Elf_Addr  offset = rtab[j].r_offset;
       Elf_Addr  P      = targ + offset;
@@ -2879,13 +3215,13 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
       Elf_Addr  S;
       void*     S_tmp;
       Elf_Addr  value;
-#     if defined(sparc_TARGET_ARCH)
+#     if defined(sparc_HOST_ARCH)
       Elf_Word* pP = (Elf_Word*)P;
       Elf_Word  w1, w2;
-#     elif defined(ia64_TARGET_ARCH)
+#     elif defined(ia64_HOST_ARCH)
       Elf64_Xword *pP = (Elf64_Xword *)P;
       Elf_Addr addr;
-#     elif defined(powerpc_TARGET_ARCH)
+#     elif defined(powerpc_HOST_ARCH)
       Elf_Sword delta;
 #     endif
 
@@ -2939,7 +3275,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
       value = S + A;
 
       switch (ELF_R_TYPE(info)) {
-#        if defined(sparc_TARGET_ARCH)
+#        if defined(sparc_HOST_ARCH)
          case R_SPARC_WDISP30:
             w1 = *pP & 0xC0000000;
             w2 = (Elf_Word)((value - P) >> 2);
@@ -2976,7 +3312,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
             w2 = (Elf_Word)value;
             *pP = w2;
             break;
-#        elif defined(ia64_TARGET_ARCH)
+#        elif defined(ia64_HOST_ARCH)
         case R_IA64_DIR64LSB:
         case R_IA64_FPTR64LSB:
            *pP = value;
@@ -3004,7 +3340,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
            /* This goes with R_IA64_LTOFF22X and points to the load to
             * convert into a move.  We don't implement relaxation. */
            break;
-#        elif defined(powerpc_TARGET_ARCH)
+#        elif defined(powerpc_HOST_ARCH)
          case R_PPC_ADDR16_LO:
             *(Elf32_Half*) P = value;
             break;
@@ -3045,9 +3381,43 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
                                           | (delta & 0x3fffffc);
             break;
 #        endif
+
+#if x86_64_HOST_ARCH
+      case R_X86_64_64:
+         *(Elf64_Xword *)P = value;
+         break;
+
+      case R_X86_64_PC32:
+      {
+         StgInt64 off = value - P;
+         if (off >= 0x7fffffffL || off < -0x80000000L) {
+             barf("R_X86_64_PC32 relocation out of range: %s = %p",
+                  symbol, off);
+         }
+         *(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",
+                  symbol, value);
+         }
+         *(Elf64_Word *)P = (Elf64_Word)value;
+         break;
+
+      case R_X86_64_32S:
+         if ((StgInt64)value > 0x7fffffffL || (StgInt64)value < -0x80000000L) {
+             barf("R_X86_64_32S relocation out of range: %s = %p\n",
+                  symbol, value);
+         }
+         *(Elf64_Sword *)P = (Elf64_Sword)value;
+         break;
+#endif
+
          default:
-            errorBelch("%s: unhandled ELF relocation(RelA) type %d\n",
-                 oc->fileName, ELF_R_TYPE(info));
+            errorBelch("%s: unhandled ELF relocation(RelA) type %lu\n",
+                 oc->fileName, (lnat)ELF_R_TYPE(info));
             return 0;
       }
 
@@ -3064,7 +3434,6 @@ ocResolve_ELF ( ObjectCode* oc )
    char*     ehdrC = (char*)(oc->image);
    Elf_Ehdr* ehdr  = (Elf_Ehdr*) ehdrC;
    Elf_Shdr* shdr  = (Elf_Shdr*) (ehdrC + ehdr->e_shoff);
-   char* sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
 
    /* first find "the" symbol table */
    stab = (Elf_Sym*) findElfSection ( ehdrC, SHT_SYMTAB );
@@ -3079,15 +3448,7 @@ ocResolve_ELF ( ObjectCode* oc )
 
    /* Process the relocation sections. */
    for (shnum = 0; shnum < ehdr->e_shnum; shnum++) {
-
-      /* Skip sections called ".rel.stab".  These appear to contain
-         relocation entries that, when done, make the stabs debugging
-         info point at the right places.  We ain't interested in all
-         dat jazz, mun. */
-      if (0 == memcmp(".rel.stab", sh_strtab + shdr[shnum].sh_name, 9))
-         continue;
-
-      if (shdr[shnum].sh_type == SHT_REL ) {
+      if (shdr[shnum].sh_type == SHT_REL) {
          ok = do_Elf_Rel_relocations ( oc, ehdrC, shdr,
                                        shnum, stab, strtab );
          if (!ok) return ok;
@@ -3104,7 +3465,7 @@ ocResolve_ELF ( ObjectCode* oc )
    freeHashTable(oc->lochash, NULL);
    oc->lochash = NULL;
 
-#if defined(powerpc_TARGET_ARCH)
+#if defined(powerpc_HOST_ARCH)
    ocFlushInstructionCache( oc );
 #endif
 
@@ -3118,14 +3479,14 @@ ocResolve_ELF ( ObjectCode* oc )
  * take care of the most common relocations.
  */
 
-#ifdef ia64_TARGET_ARCH
+#ifdef ia64_HOST_ARCH
 
 static Elf64_Xword
 ia64_extract_instruction(Elf64_Xword *target)
 {
    Elf64_Xword w1, w2;
    int slot = (Elf_Addr)target & 3;
-   (Elf_Addr)target &= ~3;
+   target = (Elf_Addr)target & ~3;
 
    w1 = *target;
    w2 = *(target+1);
@@ -3147,7 +3508,7 @@ static void
 ia64_deposit_instruction(Elf64_Xword *target, Elf64_Xword value)
 {
    int slot = (Elf_Addr)target & 3;
-   (Elf_Addr)target &= ~3;
+   target = (Elf_Addr)target & ~3;
 
    switch (slot)
    {
@@ -3207,7 +3568,7 @@ ia64_reloc_pcrel21(Elf_Addr target, Elf_Addr value, ObjectCode *oc)
  * PowerPC ELF specifics
  */
 
-#ifdef powerpc_TARGET_ARCH
+#ifdef powerpc_HOST_ARCH
 
 static int ocAllocateJumpIslands_ELF( ObjectCode *oc )
 {
@@ -3250,7 +3611,7 @@ static int ocAllocateJumpIslands_ELF( ObjectCode *oc )
 #if defined(OBJFORMAT_MACHO)
 
 /*
-  Support for MachO linking on Darwin/MacOS X on PowerPC chips
+  Support for MachO linking on Darwin/MacOS X
   by Wolfgang Thaller (wolfgang.thaller@gmx.net)
 
   I hereby formally apologize for the hackish nature of this code.
@@ -3259,6 +3620,7 @@ static int ocAllocateJumpIslands_ELF( ObjectCode *oc )
   *) add still more sanity checks.
 */
 
+#ifdef powerpc_HOST_ARCH
 static int ocAllocateJumpIslands_MachO(ObjectCode* oc)
 {
     struct mach_header *header = (struct mach_header *) oc->image;
@@ -3266,23 +3628,46 @@ static int ocAllocateJumpIslands_MachO(ObjectCode* oc)
     unsigned i;
 
     for( i = 0; i < header->ncmds; i++ )
-    {
-        if( lc->cmd == LC_DYSYMTAB )
+    {   
+        if( lc->cmd == LC_SYMTAB )
         {
-            struct dysymtab_command *dsymLC = (struct dysymtab_command *) lc;
-
-            if( !ocAllocateJumpIslands( oc, dsymLC->nundefsym,
-                                            dsymLC->iundefsym ) )
-              return 0;
+                // Find out the first and last undefined external
+                // symbol, so we don't have to allocate too many
+                // jump islands.
+            struct symtab_command *symLC = (struct symtab_command *) lc;
+            unsigned min = symLC->nsyms, max = 0;
+            struct nlist *nlist =
+                symLC ? (struct nlist*) ((char*) oc->image + symLC->symoff)
+                      : NULL;
+            for(i=0;i<symLC->nsyms;i++)
+            {
+                if(nlist[i].n_type & N_STAB)
+                    ;
+                else if(nlist[i].n_type & N_EXT)
+                {
+                    if((nlist[i].n_type & N_TYPE) == N_UNDF
+                        && (nlist[i].n_value == 0))
+                    {
+                        if(i < min)
+                            min = i;
+                        if(i > max)
+                            max = i;
+                    }
+                }
+            }
+            if(max >= min)
+                return ocAllocateJumpIslands(oc, max - min + 1, min);
 
-            break;  // there can be only one LC_DSYMTAB
+            break;
         }
+        
         lc = (struct load_command *) ( ((char *)lc) + lc->cmdsize );
     }
-    return 1;
+    return ocAllocateJumpIslands(oc,0,0);
 }
+#endif
 
-static int ocVerifyImage_MachO(ObjectCode* oc)
+static int ocVerifyImage_MachO(ObjectCode* oc STG_UNUSED)
 {
     // FIXME: do some verifying here
     return 1;
@@ -3325,7 +3710,7 @@ static int resolveImports(
     return 1;
 }
 
-static char* relocateAddress(
+static unsigned long relocateAddress(
     ObjectCode* oc,
     int nSections,
     struct section* sections,
@@ -3337,12 +3722,13 @@ static char* relocateAddress(
         if(sections[i].addr <= address
             && address < sections[i].addr + sections[i].size)
         {
-            return oc->image + sections[i].offset + address - sections[i].addr;
+            return (unsigned long)oc->image
+                    + sections[i].offset + address - sections[i].addr;
         }
     }
     barf("Invalid Mach-O file:"
          "Address out of bounds while relocating object file");
-    return NULL;
+    return 0;
 }
 
 static int relocateSection(
@@ -3358,6 +3744,10 @@ static int relocateSection(
        return 1;
     else if(!strcmp(sect->sectname,"__nl_symbol_ptr"))
        return 1;
+    else if(!strcmp(sect->sectname,"__la_sym_ptr2"))
+       return 1;
+    else if(!strcmp(sect->sectname,"__la_sym_ptr3"))
+       return 1;
 
     n = sect->nreloc;
     relocs = (struct relocation_info*) (image + sect->reloff);
@@ -3377,6 +3767,15 @@ static int relocateSection(
                    unsigned long* wordPtr = (unsigned long*) (image + sect->offset + scat->r_address);
                    checkProddableBlock(oc,wordPtr);
 
+                    // Note on relocation types:
+                    // i386 uses the GENERIC_RELOC_* types,
+                    // while ppc uses special PPC_RELOC_* types.
+                    // *_RELOC_VANILLA and *_RELOC_PAIR have the same value
+                    // in both cases, all others are different.
+                    // Therefore, we use GENERIC_RELOC_VANILLA
+                    // and GENERIC_RELOC_PAIR instead of the PPC variants,
+                    // and use #ifdefs for the other types.
+                    
                    // Step 1: Figure out what the relocated value should be
                    if(scat->r_type == GENERIC_RELOC_VANILLA)
                    {
@@ -3387,23 +3786,28 @@ static int relocateSection(
                                                                 scat->r_value)
                                         - scat->r_value;
                    }
+#ifdef powerpc_HOST_ARCH
                    else if(scat->r_type == PPC_RELOC_SECTDIFF
                        || scat->r_type == PPC_RELOC_LO16_SECTDIFF
                        || scat->r_type == PPC_RELOC_HI16_SECTDIFF
                        || scat->r_type == PPC_RELOC_HA16_SECTDIFF)
+#else
+                    else if(scat->r_type == GENERIC_RELOC_SECTDIFF)
+#endif
                    {
                        struct scattered_relocation_info *pair =
                                (struct scattered_relocation_info*) &relocs[i+1];
 
-                       if(!pair->r_scattered || pair->r_type != PPC_RELOC_PAIR)
+                       if(!pair->r_scattered || pair->r_type != GENERIC_RELOC_PAIR)
                            barf("Invalid Mach-O file: "
-                                "PPC_RELOC_*_SECTDIFF not followed by PPC_RELOC_PAIR");
+                                "RELOC_*_SECTDIFF not followed by RELOC_PAIR");
 
                        word = (unsigned long)
                               (relocateAddress(oc, nSections, sections, scat->r_value)
                              - relocateAddress(oc, nSections, sections, pair->r_value));
                        i++;
                    }
+#ifdef powerpc_HOST_ARCH
                    else if(scat->r_type == PPC_RELOC_HI16
                          || scat->r_type == PPC_RELOC_LO16
                          || scat->r_type == PPC_RELOC_HA16
@@ -3442,14 +3846,21 @@ static int relocateSection(
                         
                         i++;
                     }
+ #endif
                     else
                        continue;  // ignore the others
 
+#ifdef powerpc_HOST_ARCH
                     if(scat->r_type == GENERIC_RELOC_VANILLA
                         || scat->r_type == PPC_RELOC_SECTDIFF)
+#else
+                    if(scat->r_type == GENERIC_RELOC_VANILLA
+                        || scat->r_type == GENERIC_RELOC_SECTDIFF)
+#endif
                     {
                         *wordPtr = word;
                     }
+#ifdef powerpc_HOST_ARCH
                     else if(scat->r_type == PPC_RELOC_LO16_SECTDIFF || scat->r_type == PPC_RELOC_LO16)
                     {
                         ((unsigned short*) wordPtr)[1] = word & 0xFFFF;
@@ -3463,6 +3874,7 @@ static int relocateSection(
                         ((unsigned short*) wordPtr)[1] = ((word >> 16) & 0xFFFF)
                             + ((word & (1<<15)) ? 1 : 0);
                     }
+#endif
                }
            }
 
@@ -3477,8 +3889,12 @@ static int relocateSection(
            if(reloc->r_length == 2)
            {
                unsigned long word = 0;
+#ifdef powerpc_HOST_ARCH
                 unsigned long jumpIsland = 0;
-                long offsetToJumpIsland;
+                long offsetToJumpIsland = 0xBADBAD42; // initialise to bad value
+                                                      // to avoid warning and to catch
+                                                      // bugs.
+#endif
 
                unsigned long* wordPtr = (unsigned long*) (image + sect->offset + reloc->r_address);
                checkProddableBlock(oc,wordPtr);
@@ -3487,6 +3903,7 @@ static int relocateSection(
                {
                    word = *wordPtr;
                }
+#ifdef powerpc_HOST_ARCH
                else if(reloc->r_type == PPC_RELOC_LO16)
                {
                    word = ((unsigned short*) wordPtr)[1];
@@ -3507,7 +3924,7 @@ static int relocateSection(
                    word = *wordPtr;
                    word = (word & 0x03FFFFFC) | ((word & 0x02000000) ? 0xFC000000 : 0);
                }
-
+#endif
 
                if(!reloc->r_extern)
                {
@@ -3522,7 +3939,7 @@ static int relocateSection(
                {
                    struct nlist *symbol = &nlist[reloc->r_symbolnum];
                    char *nm = image + symLC->stroff + symbol->n_un.n_strx;
-                   unsigned long symbolAddress = (unsigned long) (lookupSymbol(nm));
+                   void *symbolAddress = lookupSymbol(nm);
                    if(!symbolAddress)
                    {
                        errorBelch("\nunknown symbol `%s'", nm);
@@ -3531,21 +3948,23 @@ static int relocateSection(
 
                    if(reloc->r_pcrel)
                     {  
+#ifdef powerpc_HOST_ARCH
                             // In the .o file, this should be a relative jump to NULL
-                            // and we'll change it to a jump to a relative jump to the symbol
+                            // and we'll change it to a relative jump to the symbol
                         ASSERT(-word == reloc->r_address);
-                        word = symbolAddress;
-                        jumpIsland = makeJumpIsland(oc,reloc->r_symbolnum,word);
-                       word -= ((long)image) + sect->offset + reloc->r_address;
+                        jumpIsland = makeJumpIsland(oc,reloc->r_symbolnum,(unsigned long) symbolAddress);
                         if(jumpIsland != 0)
                         {
-                            offsetToJumpIsland = jumpIsland
-                                - (((long)image) + sect->offset + reloc->r_address);
+                            offsetToJumpIsland = word + jumpIsland
+                                - (((long)image) + sect->offset - sect->addr);
                         }
+#endif
+                       word += (unsigned long) symbolAddress
+                                - (((long)image) + sect->offset - sect->addr);
                     }
                     else
                     {
-                        word += symbolAddress;
+                        word += (unsigned long) symbolAddress;
                     }
                }
 
@@ -3554,6 +3973,7 @@ static int relocateSection(
                    *wordPtr = word;
                    continue;
                }
+#ifdef powerpc_HOST_ARCH
                else if(reloc->r_type == PPC_RELOC_LO16)
                {
                    ((unsigned short*) wordPtr)[1] = word & 0xFFFF;
@@ -3577,9 +3997,11 @@ static int relocateSection(
                         // The branch offset is too large.
                         // Therefore, we try to use a jump island.
                         if(jumpIsland == 0)
+                        {
                             barf("unconditional relative branch out of range: "
                                  "no jump island available");
-
+                        }
+                        
                         word = offsetToJumpIsland;
                         if((long)word > (long)0x01FFFFFF || (long)word < (long)0xFFE00000)
                             barf("unconditional relative branch out of range: "
@@ -3588,7 +4010,8 @@ static int relocateSection(
                    *wordPtr = (*wordPtr & 0xFC000003) | (word & 0x03FFFFFC);
                    continue;
                }
-           }
+#endif
+            }
            barf("\nunknown relocation %d",reloc->r_type);
            return 0;
        }
@@ -3601,11 +4024,10 @@ static int ocGetNames_MachO(ObjectCode* oc)
     char *image = (char*) oc->image;
     struct mach_header *header = (struct mach_header*) image;
     struct load_command *lc = (struct load_command*) (image + sizeof(struct mach_header));
-    unsigned i,curSymbol;
+    unsigned i,curSymbol = 0;
     struct segment_command *segLC = NULL;
     struct section *sections;
     struct symtab_command *symLC = NULL;
-    struct dysymtab_command *dsymLC = NULL;
     struct nlist *nlist;
     unsigned long commonSize = 0;
     char    *commonStorage = NULL;
@@ -3617,13 +4039,12 @@ static int ocGetNames_MachO(ObjectCode* oc)
            segLC = (struct segment_command*) lc;
        else if(lc->cmd == LC_SYMTAB)
            symLC = (struct symtab_command*) lc;
-       else if(lc->cmd == LC_DYSYMTAB)
-           dsymLC = (struct dysymtab_command*) lc;
        lc = (struct load_command *) ( ((char*)lc) + lc->cmdsize );
     }
 
     sections = (struct section*) (segLC+1);
-    nlist = (struct nlist*) (image + symLC->symoff);
+    nlist = symLC ? (struct nlist*) (image + symLC->symoff)
+                  : NULL;
 
     for(i=0;i<segLC->nsects;i++)
     {
@@ -3661,61 +4082,55 @@ static int ocGetNames_MachO(ObjectCode* oc)
 
        // count external symbols defined here
     oc->n_symbols = 0;
-    if(dsymLC)
-    {
-        for(i = dsymLC->iextdefsym;
-            i < dsymLC->iextdefsym + dsymLC->nextdefsym;
-            i++)
-        {
-            if((nlist[i].n_type & N_TYPE) == N_SECT)
-                oc->n_symbols++;
-        }
-    }
     if(symLC)
     {
         for(i=0;i<symLC->nsyms;i++)
         {
-           if((nlist[i].n_type & N_TYPE) == N_UNDF
-               && (nlist[i].n_type & N_EXT) && (nlist[i].n_value != 0))
-           {
-               commonSize += nlist[i].n_value;
-               oc->n_symbols++;
-           }
+            if(nlist[i].n_type & N_STAB)
+                ;
+            else if(nlist[i].n_type & N_EXT)
+            {
+                if((nlist[i].n_type & N_TYPE) == N_UNDF
+                    && (nlist[i].n_value != 0))
+                {
+                    commonSize += nlist[i].n_value;
+                    oc->n_symbols++;
+                }
+                else if((nlist[i].n_type & N_TYPE) == N_SECT)
+                    oc->n_symbols++;
+            }
         }
     }
     oc->symbols = stgMallocBytes(oc->n_symbols * sizeof(char*),
                                   "ocGetNames_MachO(oc->symbols)");
 
-    if(dsymLC)
+    if(symLC)
     {
-        // insert symbols into hash table
-        for(i = dsymLC->iextdefsym, curSymbol = 0;
-            i < dsymLC->iextdefsym + dsymLC->nextdefsym;
-            i++)
-        {
-            if((nlist[i].n_type & N_TYPE) == N_SECT)
-            {
-                char *nm = image + symLC->stroff + nlist[i].n_un.n_strx;
-                ghciInsertStrHashTable(oc->fileName, symhash, nm,
-                                        image
-                                        + sections[nlist[i].n_sect-1].offset
-                                        - sections[nlist[i].n_sect-1].addr
-                                        + nlist[i].n_value);
-                oc->symbols[curSymbol++] = nm;
-            }
-        }
-    
-        // insert local symbols into lochash
-        for(i=dsymLC->ilocalsym;i<dsymLC->ilocalsym+dsymLC->nlocalsym;i++)
+        for(i=0;i<symLC->nsyms;i++)
         {
-            if((nlist[i].n_type & N_TYPE) == N_SECT)
+            if(nlist[i].n_type & N_STAB)
+                ;
+            else if((nlist[i].n_type & N_TYPE) == N_SECT)
             {
-                char *nm = image + symLC->stroff + nlist[i].n_un.n_strx;
-                ghciInsertStrHashTable(oc->fileName, oc->lochash, nm,
-                                        image
-                                        + sections[nlist[i].n_sect-1].offset
-                                        - sections[nlist[i].n_sect-1].addr
-                                        + nlist[i].n_value);
+                if(nlist[i].n_type & N_EXT)
+                {
+                    char *nm = image + symLC->stroff + nlist[i].n_un.n_strx;
+                    ghciInsertStrHashTable(oc->fileName, symhash, nm,
+                                            image
+                                            + sections[nlist[i].n_sect-1].offset
+                                            - sections[nlist[i].n_sect-1].addr
+                                            + nlist[i].n_value);
+                    oc->symbols[curSymbol++] = nm;
+                }
+                else
+                {
+                    char *nm = image + symLC->stroff + nlist[i].n_un.n_strx;
+                    ghciInsertStrHashTable(oc->fileName, oc->lochash, nm,
+                                            image
+                                            + sections[nlist[i].n_sect-1].offset
+                                            - sections[nlist[i].n_sect-1].addr
+                                            + nlist[i].n_value);
+                }
             }
         }
     }
@@ -3778,6 +4193,10 @@ static int ocResolve_MachO(ObjectCode* oc)
            la_ptrs = &sections[i];
        else if(!strcmp(sections[i].sectname,"__nl_symbol_ptr"))
            nl_ptrs = &sections[i];
+        else if(!strcmp(sections[i].sectname,"__la_sym_ptr2"))
+           la_ptrs = &sections[i];
+        else if(!strcmp(sections[i].sectname,"__la_sym_ptr3"))
+           la_ptrs = &sections[i];
     }
 
     if(dsymLC)
@@ -3803,13 +4222,14 @@ static int ocResolve_MachO(ObjectCode* oc)
     freeHashTable(oc->lochash, NULL);
     oc->lochash = NULL;
 
-#if defined (powerpc_TARGET_ARCH)
+#if defined (powerpc_HOST_ARCH)
     ocFlushInstructionCache( oc );
 #endif
 
     return 1;
 }
 
+#ifdef powerpc_HOST_ARCH
 /*
  * The Mach-O object format uses leading underscores. But not everywhere.
  * There is a small number of runtime support functions defined in
@@ -3823,7 +4243,7 @@ static void machoInitSymbolsWithoutUnderscore()
 {
     extern void* symbolsWithoutUnderscore[];
     void **p = symbolsWithoutUnderscore;
-    __asm__ volatile(".data\n_symbolsWithoutUnderscore:");
+    __asm__ volatile(".globl _symbolsWithoutUnderscore\n.data\n_symbolsWithoutUnderscore:");
 
 #undef Sym
 #define Sym(x)  \
@@ -3842,3 +4262,26 @@ static void machoInitSymbolsWithoutUnderscore()
 #undef Sym
 }
 #endif
+
+/*
+ * Figure out by how much to shift the entire Mach-O file in memory
+ * when loading so that its single segment ends up 16-byte-aligned
+ */
+static int machoGetMisalignment( FILE * f )
+{
+    struct mach_header header;
+    int misalignment;
+    
+    fread(&header, sizeof(header), 1, f);
+    rewind(f);
+
+    if(header.magic != MH_MAGIC)
+        return 0;
+    
+    misalignment = (header.sizeofcmds + sizeof(header))
+                    & 0xF;
+
+    return misalignment ? (16 - misalignment) : 0;
+}
+
+#endif