FIX #1845 (unconditional relative branch out of range)
[ghc-hetmet.git] / rts / Linker.c
index a0e578e..2894b1e 100644 (file)
 #include <sys/wait.h>
 #endif
 
-#if defined(linux_HOST_OS) || defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS) || defined(darwin_HOST_OS)
+#if defined(linux_HOST_OS    ) || defined(freebsd_HOST_OS) || \
+    defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS ) || \
+    defined(openbsd_HOST_OS  ) || \
+    ( defined(darwin_HOST_OS ) && !defined(powerpc_HOST_ARCH) )
+/* Don't use mmap on powerpc-apple-darwin as mmap doesn't support
+ * reallocating but we need to allocate jump islands just after each
+ * object images. Otherwise relative branches to jump islands can fail
+ * due to 24-bits displacement overflow.
+ */
 #define USE_MMAP
 #include <fcntl.h>
 #include <sys/mman.h>
@@ -1685,6 +1693,9 @@ loadArchive( char *path )
     char tmp[12];
     char *gnuFileIndex;
     int gnuFileIndexSize;
+#if !defined(USE_MMAP) && defined(darwin_HOST_OS)
+    int misalignment;
+#endif
 
     IF_DEBUG(linker, debugBelch("loadArchive: Loading archive `%s'\n", path));
 
@@ -1854,8 +1865,13 @@ loadArchive( char *path )
                we use malloc then we can be given memory above 2^32.
                In the mmap case we're probably wasting lots of space;
                we could do better. */
-#ifdef USE_MMAP
+#if defined(USE_MMAP)
             image = mmapForLinker(memberSize, MAP_ANONYMOUS, -1);
+#elif defined(darwin_HOST_OS)
+            /* See loadObj() */
+            misalignment = machoGetMisalignment(f);
+            image = stgMallocBytes(memberSize + misalignment, "loadArchive(image)");
+            image += misalignment;
 #else
             image = stgMallocBytes(memberSize, "loadArchive(image)");
 #endif
@@ -1872,7 +1888,7 @@ loadArchive( char *path )
             oc = mkOc(path, image, memberSize, archiveMemberName
 #ifndef USE_MMAP
 #ifdef darwin_HOST_OS
-                     , 0
+                     , misalignment
 #endif
 #endif
                      );
@@ -1952,6 +1968,9 @@ loadObj( char *path )
    int fd;
 #else
    FILE *f;
+#  if defined(darwin_HOST_OS)
+   int misalignment;
+#  endif
 #endif
    IF_DEBUG(linker, debugBelch("loadObj %s\n", path));