merge upstream HEAD
[ghc-hetmet.git] / rts / Linker.c
index edad92e..c840857 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 ) && !defined(powerpc_HOST_ARCH) ) || \
-    defined(kfreebsdgnu_HOST_OS)
-/* Don't use mmap on powerpc-apple-darwin as mmap doesn't support
+#if !defined(powerpc_HOST_ARCH) && \
+    (   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(kfreebsdgnu_HOST_OS) )
+/* Don't use mmap on powerpc_HOST_ARCH 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.
 #elif defined(darwin_HOST_OS)
 #  define OBJFORMAT_MACHO
 #  include <regex.h>
+#  include <mach/machine.h>
+#  include <mach-o/fat.h>
 #  include <mach-o/loader.h>
 #  include <mach-o/nlist.h>
 #  include <mach-o/reloc.h>
@@ -830,6 +832,7 @@ typedef struct _RtsSymbolVal {
       SymI_HasProto(stg_newTVarzh)                      \
       SymI_HasProto(stg_noDuplicatezh)                  \
       SymI_HasProto(stg_atomicModifyMutVarzh)           \
+      SymI_HasProto(stg_casMutVarzh)                    \
       SymI_HasProto(stg_newPinnedByteArrayzh)           \
       SymI_HasProto(stg_newAlignedPinnedByteArrayzh)    \
       SymI_HasProto(newSpark)                           \
@@ -1565,6 +1568,7 @@ mmapForLinker (size_t bytes, nat flags, int fd)
    int pagesize, size;
    static nat fixed = 0;
 
+   IF_DEBUG(linker, debugBelch("mmapForLinker: start\n"));
    pagesize = getpagesize();
    size = ROUND_UP(bytes, pagesize);
 
@@ -1576,6 +1580,8 @@ mmap_again:
    }
 #endif
 
+   IF_DEBUG(linker, debugBelch("mmapForLinker: \tprotection %#0x\n", PROT_EXEC | PROT_READ | PROT_WRITE));
+   IF_DEBUG(linker, debugBelch("mmapForLinker: \tflags      %#0x\n", MAP_PRIVATE | TRY_MAP_32BIT | fixed | flags));
    result = mmap(map_addr, size, PROT_EXEC|PROT_READ|PROT_WRITE,
                     MAP_PRIVATE|TRY_MAP_32BIT|fixed|flags, fd, 0);
 
@@ -1623,6 +1629,8 @@ mmap_again:
    }
 #endif
 
+   IF_DEBUG(linker, debugBelch("mmapForLinker: mapped %lu bytes starting at %p\n", (lnat)size, result));
+   IF_DEBUG(linker, debugBelch("mmapForLinker: done\n"));
    return result;
 }
 #endif // USE_MMAP
@@ -1638,6 +1646,7 @@ mkOc( char *path, char *image, int imageSize,
     ) {
    ObjectCode* oc;
 
+   IF_DEBUG(linker, debugBelch("mkOc: start\n"));
    oc = stgMallocBytes(sizeof(ObjectCode), "loadArchive(oc)");
 
 #  if defined(OBJFORMAT_ELF)
@@ -1679,6 +1688,7 @@ mkOc( char *path, char *image, int imageSize,
    oc->next              = objects;
    objects               = oc;
 
+   IF_DEBUG(linker, debugBelch("mkOc: done\n"));
    return oc;
 }
 
@@ -1694,13 +1704,33 @@ loadArchive( char *path )
     char *fileName;
     size_t fileNameSize;
     int isObject, isGnuIndex;
-    char tmp[12];
+    char tmp[20];
     char *gnuFileIndex;
     int gnuFileIndexSize;
-#if !defined(USE_MMAP) && defined(darwin_HOST_OS)
+#if defined(darwin_HOST_OS)
+    int i;
+    uint32_t nfat_arch, nfat_offset, cputype, cpusubtype;
+#if defined(i386_HOST_ARCH)
+    const uint32_t mycputype = CPU_TYPE_X86;
+    const uint32_t mycpusubtype = CPU_SUBTYPE_X86_ALL;
+#elif defined(x86_64_HOST_ARCH)
+    const uint32_t mycputype = CPU_TYPE_X86_64;
+    const uint32_t mycpusubtype = CPU_SUBTYPE_X86_64_ALL;
+#elif defined(powerpc_HOST_ARCH)
+    const uint32_t mycputype = CPU_TYPE_POWERPC;
+    const uint32_t mycpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+#elif defined(powerpc64_HOST_ARCH)
+    const uint32_t mycputype = CPU_TYPE_POWERPC64;
+    const uint32_t mycpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+#else
+#error Unknown Darwin architecture
+#endif
+#if !defined(USE_MMAP)
     int misalignment;
 #endif
+#endif
 
+    IF_DEBUG(linker, debugBelch("loadArchive: start\n"));
     IF_DEBUG(linker, debugBelch("loadArchive: Loading archive `%s'\n", path));
 
     gnuFileIndex = NULL;
@@ -1713,20 +1743,97 @@ loadArchive( char *path )
     if (!f)
         barf("loadObj: can't read `%s'", path);
 
+    /* Check if this is an archive by looking for the magic "!<arch>\n"
+     * string.  Usually, if this fails, we barf and quit.  On Darwin however,
+     * we may have a fat archive, which contains archives for more than
+     * one architecture.  Fat archives start with the magic number 0xcafebabe,
+     * always stored big endian.  If we find a fat_header, we scan through
+     * the fat_arch structs, searching through for one for our host
+     * architecture.  If a matching struct is found, we read the offset
+     * of our archive data (nfat_offset) and seek forward nfat_offset bytes
+     * from the start of the file.
+     *
+     * A subtlety is that all of the members of the fat_header and fat_arch
+     * structs are stored big endian, so we need to call byte order
+     * conversion functions.
+     *
+     * If we find the appropriate architecture in a fat archive, we gobble
+     * its magic "!<arch>\n" string and continue processing just as if
+     * we had a single architecture archive.
+     */
+
     n = fread ( tmp, 1, 8, f );
-    if (strncmp(tmp, "!<arch>\n", 8) != 0)
+    if (n != 8)
+        barf("loadArchive: Failed reading header from `%s'", path);
+    if (strncmp(tmp, "!<arch>\n", 8) != 0) {
+
+#if defined(darwin_HOST_OS)
+        /* Not a standard archive, look for a fat archive magic number: */
+        if (ntohl(*(uint32_t *)tmp) == FAT_MAGIC) {
+            nfat_arch = ntohl(*(uint32_t *)(tmp + 4));
+            IF_DEBUG(linker, debugBelch("loadArchive: found a fat archive containing %d architectures\n", nfat_arch));
+            nfat_offset = 0;
+
+            for (i = 0; i < (int)nfat_arch; i++) {
+                /* search for the right arch */
+                n = fread( tmp, 1, 20, f );
+                if (n != 8)
+                    barf("loadArchive: Failed reading arch from `%s'", path);
+                cputype = ntohl(*(uint32_t *)tmp);
+                cpusubtype = ntohl(*(uint32_t *)(tmp + 4));
+
+                if (cputype == mycputype && cpusubtype == mycpusubtype) {
+                    IF_DEBUG(linker, debugBelch("loadArchive: found my archive in a fat archive\n"));
+                    nfat_offset = ntohl(*(uint32_t *)(tmp + 8));
+                    break;
+                }
+            }
+
+            if (nfat_offset == 0) {
+               barf ("loadArchive: searched %d architectures, but no host arch found", (int)nfat_arch);
+            }
+            else {
+                n = fseek( f, nfat_offset, SEEK_SET );
+                if (n != 0)
+                    barf("loadArchive: Failed to seek to arch in `%s'", path);
+                n = fread ( tmp, 1, 8, f );
+                if (n != 8)
+                    barf("loadArchive: Failed reading header from `%s'", path);
+                if (strncmp(tmp, "!<arch>\n", 8) != 0) {
+                    barf("loadArchive: couldn't find archive in `%s' at offset %d", path, nfat_offset);
+                }
+            }
+        }
+        else {
+            barf("loadArchive: Neither an archive, nor a fat archive: `%s'", path);
+        }
+
+#else
         barf("loadArchive: Not an archive: `%s'", path);
+#endif
+    }
+
+    IF_DEBUG(linker, debugBelch("loadArchive: loading archive contents\n"));
 
     while(1) {
         n = fread ( fileName, 1, 16, f );
         if (n != 16) {
             if (feof(f)) {
+                IF_DEBUG(linker, debugBelch("loadArchive: EOF while reading from '%s'\n", path));
                 break;
             }
             else {
                 barf("loadArchive: Failed reading file name from `%s'", path);
             }
         }
+
+#if defined(darwin_HOST_OS)
+        if (strncmp(fileName, "!<arch>\n", 8) == 0) {
+            IF_DEBUG(linker, debugBelch("loadArchive: found the start of another archive, breaking\n"));
+            break;
+        }
+#endif
+
         n = fread ( tmp, 1, 12, f );
         if (n != 12)
             barf("loadArchive: Failed reading mod time from `%s'", path);
@@ -1746,7 +1853,11 @@ loadArchive( char *path )
         for (n = 0; isdigit(tmp[n]); n++);
         tmp[n] = '\0';
         memberSize = atoi(tmp);
+
+        IF_DEBUG(linker, debugBelch("loadArchive: size of this archive member is %d\n", memberSize));
         n = fread ( tmp, 1, 2, f );
+        if (n != 2)
+            barf("loadArchive: Failed reading magic from `%s'", path);
         if (strncmp(tmp, "\x60\x0A", 2) != 0)
             barf("loadArchive: Failed reading magic from `%s' at %ld. Got %c%c",
                  path, ftell(f), tmp[0], tmp[1]);
@@ -1772,6 +1883,11 @@ loadArchive( char *path )
                          path);
                 }
                 fileName[thisFileNameSize] = 0;
+
+                /* On OS X at least, thisFileNameSize is the size of the
+                   fileName field, not the length of the fileName
+                   itself. */
+                thisFileNameSize = strlen(fileName);
             }
             else {
                 barf("loadArchive: BSD-variant filename size not found while reading filename from `%s'", path);
@@ -1857,6 +1973,9 @@ loadArchive( char *path )
                 && fileName[thisFileNameSize - 2] == '.'
                 && fileName[thisFileNameSize - 1] == 'o';
 
+        IF_DEBUG(linker, debugBelch("loadArchive: \tthisFileNameSize = %d\n", (int)thisFileNameSize));
+        IF_DEBUG(linker, debugBelch("loadArchive: \tisObject = %d\n", isObject));
+
         if (isObject) {
             char *archiveMemberName;
 
@@ -1922,23 +2041,29 @@ loadArchive( char *path )
             gnuFileIndexSize = memberSize;
         }
         else {
+            IF_DEBUG(linker, debugBelch("loadArchive: '%s' does not appear to be an object file\n", fileName));
             n = fseek(f, memberSize, SEEK_CUR);
             if (n != 0)
                 barf("loadArchive: error whilst seeking by %d in `%s'",
                      memberSize, path);
         }
+
         /* .ar files are 2-byte aligned */
         if (memberSize % 2) {
+            IF_DEBUG(linker, debugBelch("loadArchive: trying to read one pad byte\n"));
             n = fread ( tmp, 1, 1, f );
             if (n != 1) {
                 if (feof(f)) {
+                    IF_DEBUG(linker, debugBelch("loadArchive: found EOF while reading one pad byte\n"));
                     break;
                 }
                 else {
                     barf("loadArchive: Failed reading padding from `%s'", path);
                 }
             }
+            IF_DEBUG(linker, debugBelch("loadArchive: successfully read one pad byte\n"));
         }
+        IF_DEBUG(linker, debugBelch("loadArchive: reached end of archive loading while loop\n"));
     }
 
     fclose(f);
@@ -1952,6 +2077,7 @@ loadArchive( char *path )
 #endif
     }
 
+    IF_DEBUG(linker, debugBelch("loadArchive: done\n"));
     return 1;
 }
 
@@ -2079,18 +2205,18 @@ static HsInt
 loadOc( ObjectCode* oc ) {
    int r;
 
-   IF_DEBUG(linker, debugBelch("loadOc\n"));
+   IF_DEBUG(linker, debugBelch("loadOc: start\n"));
 
 #  if defined(OBJFORMAT_MACHO) && (defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH))
    r = ocAllocateSymbolExtras_MachO ( oc );
    if (!r) {
-       IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO failed\n"));
+       IF_DEBUG(linker, debugBelch("loadOc: ocAllocateSymbolExtras_MachO failed\n"));
        return r;
    }
 #  elif defined(OBJFORMAT_ELF) && (defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH))
    r = ocAllocateSymbolExtras_ELF ( oc );
    if (!r) {
-       IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_ELF failed\n"));
+       IF_DEBUG(linker, debugBelch("loadOc: ocAllocateSymbolExtras_ELF failed\n"));
        return r;
    }
 #endif
@@ -2106,7 +2232,7 @@ loadOc( ObjectCode* oc ) {
    barf("loadObj: no verify method");
 #  endif
    if (!r) {
-       IF_DEBUG(linker, debugBelch("ocVerifyImage_* failed\n"));
+       IF_DEBUG(linker, debugBelch("loadOc: ocVerifyImage_* failed\n"));
        return r;
    }
 
@@ -2121,13 +2247,13 @@ loadOc( ObjectCode* oc ) {
    barf("loadObj: no getNames method");
 #  endif
    if (!r) {
-       IF_DEBUG(linker, debugBelch("ocGetNames_* failed\n"));
+       IF_DEBUG(linker, debugBelch("loadOc: ocGetNames_* failed\n"));
        return r;
    }
 
    /* loaded, but not resolved yet */
    oc->status = OBJECT_LOADED;
-   IF_DEBUG(linker, debugBelch("loadObj done.\n"));
+   IF_DEBUG(linker, debugBelch("loadOc: done.\n"));
 
    return 1;
 }
@@ -2233,11 +2359,13 @@ unloadObj( char *path )
  * which may be prodded during relocation, and abort if we try and write
  * outside any of these.
  */
-static void addProddableBlock ( ObjectCode* oc, void* start, int size )
+static void
+addProddableBlock ( ObjectCode* oc, void* start, int size )
 {
    ProddableBlock* pb
       = stgMallocBytes(sizeof(ProddableBlock), "addProddableBlock");
-   IF_DEBUG(linker, debugBelch("addProddableBlock %p %p %d\n", oc, start, size));
+
+   IF_DEBUG(linker, debugBelch("addProddableBlock: %p %p %d\n", oc, start, size));
    ASSERT(size > 0);
    pb->start      = start;
    pb->size       = size;
@@ -2245,9 +2373,11 @@ static void addProddableBlock ( ObjectCode* oc, void* start, int size )
    oc->proddables = pb;
 }
 
-static void checkProddableBlock ( ObjectCode* oc, void* addr )
+static void
+checkProddableBlock (ObjectCode *oc, void *addr )
 {
    ProddableBlock* pb;
+
    for (pb = oc->proddables; pb != NULL; pb = pb->next) {
       char* s = (char*)(pb->start);
       char* e = s + pb->size - 1;
@@ -2263,7 +2393,8 @@ static void checkProddableBlock ( ObjectCode* oc, void* addr )
 /* -----------------------------------------------------------------------------
  * Section management.
  */
-static void addSection ( ObjectCode* oc, SectionKind kind,
+static void
+addSection ( ObjectCode* oc, SectionKind kind,
                          void* start, void* end )
 {
    Section* s   = stgMallocBytes(sizeof(Section), "addSection");
@@ -2272,10 +2403,9 @@ static void addSection ( ObjectCode* oc, SectionKind kind,
    s->kind      = kind;
    s->next      = oc->sections;
    oc->sections = s;
-   /*
-   debugBelch("addSection: %p-%p (size %d), kind %d\n",
-                   start, ((char*)end)-1, end - start + 1, kind );
-   */
+
+   IF_DEBUG(linker, debugBelch("addSection: %p-%p (size %ld), kind %d\n",
+                               start, ((char*)end)-1, (long)end - (long)start + 1, kind ));
 }
 
 
@@ -2416,7 +2546,9 @@ static SymbolExtra* makeSymbolExtra( ObjectCode* oc,
    Because the PPC has split data/instruction caches, we have to
    do that whenever we modify code at runtime.
  */
-static void ocFlushInstructionCacheFrom(void* begin, size_t length)
+
+static void
+ocFlushInstructionCacheFrom(void* begin, size_t length)
 {
     size_t         n = (length + 3) / 4;
     unsigned long* p = begin;
@@ -2435,15 +2567,22 @@ static void ocFlushInstructionCacheFrom(void* begin, size_t length)
                        "isync"
                      );
 }
-static void ocFlushInstructionCache( ObjectCode *oc )
+
+static void
+ocFlushInstructionCache( ObjectCode *oc )
 {
     /* The main object code */
-    ocFlushInstructionCacheFrom(oc->image + oc->misalignment, oc->fileSize);
+    ocFlushInstructionCacheFrom(oc->image
+#ifdef darwin_HOST_OS
+            + oc->misalignment
+#endif
+            , oc->fileSize);
 
     /* Jump Islands */
     ocFlushInstructionCacheFrom(oc->symbol_extras, sizeof(SymbolExtra) * oc->n_symbol_extras);
 }
-#endif
+#endif /* powerpc_HOST_ARCH */
+
 
 /* --------------------------------------------------------------------------
  * PEi386 specifics (Win32 targets)
@@ -4413,79 +4552,100 @@ static int ocAllocateSymbolExtras_ELF( ObjectCode *oc )
 #endif
 
 #ifdef powerpc_HOST_ARCH
-static int ocAllocateSymbolExtras_MachO(ObjectCode* oc)
+static int
+ocAllocateSymbolExtras_MachO(ObjectCode* oc)
 {
     struct mach_header *header = (struct mach_header *) oc->image;
     struct load_command *lc = (struct load_command *) (header + 1);
     unsigned i;
 
-    for( i = 0; i < header->ncmds; i++ )
-    {
-        if( lc->cmd == LC_SYMTAB )
-        {
+    IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: start\n"));
+
+    for (i = 0; i < header->ncmds; i++) {   
+        if (lc->cmd == LC_SYMTAB) {
+
                 // Find out the first and last undefined external
                 // symbol, so we don't have to allocate too many
-                // jump islands.
+            // jump islands/GOT entries.
+
             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)
+
+            for (i = 0; i < symLC->nsyms; i++) {
+
+                if (nlist[i].n_type & N_STAB) {
                     ;
-                else if(nlist[i].n_type & N_EXT)
-                {
+                } 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)
+                        && (nlist[i].n_value == 0)) {
+
+                        if (i < min) {
                             min = i;
-                        if(i > max)
+                        }
+
+                        if (i > max) {
                             max = i;
                     }
                 }
             }
-            if(max >= min)
+            }
+
+            if (max >= min) {
                 return ocAllocateSymbolExtras(oc, max - min + 1, min);
+            }
 
             break;
         }
 
         lc = (struct load_command *) ( ((char *)lc) + lc->cmdsize );
     }
+
     return ocAllocateSymbolExtras(oc,0,0);
 }
+
 #endif
 #ifdef x86_64_HOST_ARCH
-static int ocAllocateSymbolExtras_MachO(ObjectCode* oc)
+static int
+ocAllocateSymbolExtras_MachO(ObjectCode* oc)
 {
     struct mach_header *header = (struct mach_header *) oc->image;
     struct load_command *lc = (struct load_command *) (header + 1);
     unsigned i;
 
-    for( i = 0; i < header->ncmds; i++ )
-    {
-        if( lc->cmd == LC_SYMTAB )
-        {
+    IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: start\n"));
+
+    for (i = 0; i < header->ncmds; i++) {   
+        if (lc->cmd == LC_SYMTAB) {
+
                 // Just allocate one entry for every symbol
             struct symtab_command *symLC = (struct symtab_command *) lc;
 
+            IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: allocate %d symbols\n", symLC->nsyms));
+            IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: done\n"));
             return ocAllocateSymbolExtras(oc, symLC->nsyms, 0);
         }
 
         lc = (struct load_command *) ( ((char *)lc) + lc->cmdsize );
     }
+
+    IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: allocated no symbols\n"));
+    IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: done\n"));
     return ocAllocateSymbolExtras(oc,0,0);
 }
 #endif
 
-static int ocVerifyImage_MachO(ObjectCode* oc)
+static int
+ocVerifyImage_MachO(ObjectCode * oc)
 {
     char *image = (char*) oc->image;
     struct mach_header *header = (struct mach_header*) image;
 
+    IF_DEBUG(linker, debugBelch("ocVerifyImage_MachO: start\n"));
+
 #if x86_64_HOST_ARCH || powerpc64_HOST_ARCH
     if(header->magic != MH_MAGIC_64) {
         errorBelch("%s: Bad magic. Expected: %08x, got: %08x.\n",
@@ -4499,11 +4659,14 @@ static int ocVerifyImage_MachO(ObjectCode* oc)
         return 0;
     }
 #endif
+
     // FIXME: do some more verifying here
+    IF_DEBUG(linker, debugBelch("ocVerifyImage_MachO: done\n"));
     return 1;
 }
 
-static int resolveImports(
+static int
+resolveImports(
     ObjectCode* oc,
     char *image,
     struct symtab_command *symLC,
@@ -4518,12 +4681,13 @@ static int resolveImports(
 
 #if i386_HOST_ARCH
     int isJumpTable = 0;
-    if(!strcmp(sect->sectname,"__jump_table"))
-    {
+
+    if (strcmp(sect->sectname,"__jump_table") == 0) {
         isJumpTable = 1;
         itemSize = 5;
         ASSERT(sect->reserved2 == itemSize);
     }
+
 #endif
 
     for(i=0; i*itemSize < sect->size;i++)
@@ -4534,6 +4698,7 @@ static int resolveImports(
         void *addr = NULL;
 
         IF_DEBUG(linker, debugBelch("resolveImports: resolving %s\n", nm));
+
         if ((symbol->n_type & N_TYPE) == N_UNDF
             && (symbol->n_type & N_EXT) && (symbol->n_value != 0)) {
             addr = (void*) (symbol->n_value);
@@ -4550,10 +4715,10 @@ static int resolveImports(
         ASSERT(addr);
 
 #if i386_HOST_ARCH
-        if(isJumpTable)
-        {
+        if (isJumpTable) {
             checkProddableBlock(oc,image + sect->offset + i*itemSize);
-            *(image + sect->offset + i*itemSize) = 0xe9; // jmp
+
+            *(image + sect->offset + i * itemSize) = 0xe9; // jmp opcode
             *(unsigned*)(image + sect->offset + i*itemSize + 1)
                 = (char*)addr - (image + sect->offset + i*itemSize + 5);
         }
@@ -4773,10 +4938,9 @@ static int relocateSection(
                     // and use #ifdefs for the other types.
 
                     // Step 1: Figure out what the relocated value should be
-                    if(scat->r_type == GENERIC_RELOC_VANILLA)
-                    {
-                        word = *wordPtr + (unsigned long) relocateAddress(
-                                                                oc,
+                    if (scat->r_type == GENERIC_RELOC_VANILLA) {
+                        word = *wordPtr
+                             + (unsigned long) relocateAddress(oc,
                                                                 nSections,
                                                                 sections,
                                                                 scat->r_value)
@@ -4796,9 +4960,10 @@ static int relocateSection(
                         struct scattered_relocation_info *pair =
                                 (struct scattered_relocation_info*) &relocs[i+1];
 
-                        if(!pair->r_scattered || pair->r_type != GENERIC_RELOC_PAIR)
+                        if (!pair->r_scattered || pair->r_type != GENERIC_RELOC_PAIR) {
                             barf("Invalid Mach-O file: "
                                  "RELOC_*_SECTDIFF not followed by RELOC_PAIR");
+                        }
 
                         word = (unsigned long)
                                (relocateAddress(oc, nSections, sections, scat->r_value)
@@ -4812,9 +4977,11 @@ static int relocateSection(
                          || scat->r_type == PPC_RELOC_LO14)
                     {   // these are generated by label+offset things
                         struct relocation_info *pair = &relocs[i+1];
-                        if((pair->r_address & R_SCATTERED) || pair->r_type != PPC_RELOC_PAIR)
+
+                        if ((pair->r_address & R_SCATTERED) || pair->r_type != PPC_RELOC_PAIR) {
                             barf("Invalid Mach-O file: "
                                  "PPC_RELOC_* not followed by PPC_RELOC_PAIR");
+                        }
 
                         if(scat->r_type == PPC_RELOC_LO16)
                         {
@@ -4845,8 +5012,7 @@ static int relocateSection(
                         i++;
                     }
  #endif
-                    else
-                    {
+                    else {
                         barf ("Don't know how to handle this Mach-O "
                               "scattered relocation entry: "
                               "object file %s; entry type %ld; "
@@ -4869,15 +5035,18 @@ static int relocateSection(
                         *wordPtr = word;
                     }
 #ifdef powerpc_HOST_ARCH
-                    else if(scat->r_type == PPC_RELOC_LO16_SECTDIFF || scat->r_type == PPC_RELOC_LO16)
+                    else if (scat->r_type == PPC_RELOC_LO16_SECTDIFF
+                          || scat->r_type == PPC_RELOC_LO16)
                     {
                         ((unsigned short*) wordPtr)[1] = word & 0xFFFF;
                     }
-                    else if(scat->r_type == PPC_RELOC_HI16_SECTDIFF || scat->r_type == PPC_RELOC_HI16)
+                    else if (scat->r_type == PPC_RELOC_HI16_SECTDIFF
+                          || scat->r_type == PPC_RELOC_HI16)
                     {
                         ((unsigned short*) wordPtr)[1] = (word >> 16) & 0xFFFF;
                     }
-                    else if(scat->r_type == PPC_RELOC_HA16_SECTDIFF || scat->r_type == PPC_RELOC_HA16)
+                    else if (scat->r_type == PPC_RELOC_HA16_SECTDIFF
+                          || scat->r_type == PPC_RELOC_HA16)
                     {
                         ((unsigned short*) wordPtr)[1] = ((word >> 16) & 0xFFFF)
                             + ((word & (1<<15)) ? 1 : 0);
@@ -4912,11 +5081,12 @@ static int relocateSection(
         else /* !(relocs[i].r_address & R_SCATTERED) */
         {
             struct relocation_info *reloc = &relocs[i];
-            if(reloc->r_pcrel && !reloc->r_extern)
+            if (reloc->r_pcrel && !reloc->r_extern) {
+                IF_DEBUG(linker, debugBelch("relocateSection: pc relative but not external, skipping\n"));
                 continue;
+            }
 
-            if(reloc->r_length == 2)
-            {
+            if (reloc->r_length == 2) {
                 unsigned long word = 0;
 #ifdef powerpc_HOST_ARCH
                 unsigned long jumpIsland = 0;
@@ -4928,34 +5098,28 @@ static int relocateSection(
                 unsigned long* wordPtr = (unsigned long*) (image + sect->offset + reloc->r_address);
                 checkProddableBlock(oc,wordPtr);
 
-                if(reloc->r_type == GENERIC_RELOC_VANILLA)
-                {
+                if (reloc->r_type == GENERIC_RELOC_VANILLA) {
                     word = *wordPtr;
                 }
 #ifdef powerpc_HOST_ARCH
-                else if(reloc->r_type == PPC_RELOC_LO16)
-                {
+                else if (reloc->r_type == PPC_RELOC_LO16) {
                     word = ((unsigned short*) wordPtr)[1];
                     word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF) << 16;
                 }
-                else if(reloc->r_type == PPC_RELOC_HI16)
-                {
+                else if (reloc->r_type == PPC_RELOC_HI16) {
                     word = ((unsigned short*) wordPtr)[1] << 16;
                     word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF);
                 }
-                else if(reloc->r_type == PPC_RELOC_HA16)
-                {
+                else if (reloc->r_type == PPC_RELOC_HA16) {
                     word = ((unsigned short*) wordPtr)[1] << 16;
                     word += ((short)relocs[i+1].r_address & (short)0xFFFF);
                 }
-                else if(reloc->r_type == PPC_RELOC_BR24)
-                {
+                else if (reloc->r_type == PPC_RELOC_BR24) {
                     word = *wordPtr;
                     word = (word & 0x03FFFFFC) | ((word & 0x02000000) ? 0xFC000000 : 0);
                 }
 #endif
-                else
-                {
+                else {
                     barf("Can't handle this Mach-O relocation entry "
                          "(not scattered): "
                          "object file %s; entry type %ld; address %#lx\n",
@@ -4965,28 +5129,24 @@ static int relocateSection(
                     return 0;
                 }
 
-                if(!reloc->r_extern)
-                {
-                    long delta =
-                        sections[reloc->r_symbolnum-1].offset
+                if (!reloc->r_extern) {
+                    long delta = sections[reloc->r_symbolnum-1].offset
                         - sections[reloc->r_symbolnum-1].addr
                         + ((long) image);
 
                     word += delta;
                 }
-                else
-                {
+                else {
                     struct nlist *symbol = &nlist[reloc->r_symbolnum];
                     char *nm = image + symLC->stroff + symbol->n_un.n_strx;
                     void *symbolAddress = lookupSymbol(nm);
-                    if(!symbolAddress)
-                    {
+
+                    if (!symbolAddress) {
                         errorBelch("\nunknown symbol `%s'", nm);
                         return 0;
                     }
 
-                    if(reloc->r_pcrel)
-                    {
+                    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 relative jump to the symbol
@@ -4996,8 +5156,7 @@ static int relocateSection(
                                                          reloc->r_symbolnum,
                                                          (unsigned long) symbolAddress)
                                          -> jumpIsland;
-                        if(jumpIsland != 0)
-                        {
+                        if (jumpIsland != 0) {
                             offsetToJumpIsland = word + jumpIsland
                                 - (((long)image) + sect->offset - sect->addr);
                         }
@@ -5005,14 +5164,12 @@ static int relocateSection(
                         word += (unsigned long) symbolAddress
                                 - (((long)image) + sect->offset - sect->addr);
                     }
-                    else
-                    {
+                    else {
                         word += (unsigned long) symbolAddress;
                     }
                 }
 
-                if(reloc->r_type == GENERIC_RELOC_VANILLA)
-                {
+                if (reloc->r_type == GENERIC_RELOC_VANILLA) {
                     *wordPtr = word;
                     continue;
                 }
@@ -5020,34 +5177,36 @@ static int relocateSection(
                 else if(reloc->r_type == PPC_RELOC_LO16)
                 {
                     ((unsigned short*) wordPtr)[1] = word & 0xFFFF;
-                    i++; continue;
+                    i++;
+                    continue;
                 }
                 else if(reloc->r_type == PPC_RELOC_HI16)
                 {
                     ((unsigned short*) wordPtr)[1] = (word >> 16) & 0xFFFF;
-                    i++; continue;
+                    i++;
+                    continue;
                 }
                 else if(reloc->r_type == PPC_RELOC_HA16)
                 {
                     ((unsigned short*) wordPtr)[1] = ((word >> 16) & 0xFFFF)
                         + ((word & (1<<15)) ? 1 : 0);
-                    i++; continue;
+                    i++;
+                    continue;
                 }
                 else if(reloc->r_type == PPC_RELOC_BR24)
                 {
-                    if((word & 0x03) != 0)
+                    if ((word & 0x03) != 0) {
                         barf("%s: unconditional relative branch with a displacement "
                              "which isn't a multiple of 4 bytes: %#lx",
                              OC_INFORMATIVE_FILENAME(oc),
                              word);
+                    }
 
                     if((word & 0xFE000000) != 0xFE000000 &&
-                       (word & 0xFE000000) != 0x00000000)
-                    {
+                        (word & 0xFE000000) != 0x00000000) {
                         // The branch offset is too large.
                         // Therefore, we try to use a jump island.
-                        if(jumpIsland == 0)
-                        {
+                        if (jumpIsland == 0) {
                             barf("%s: unconditional relative branch out of range: "
                                  "no jump island available: %#lx",
                                  OC_INFORMATIVE_FILENAME(oc),
@@ -5055,13 +5214,15 @@ static int relocateSection(
                         }
 
                         word = offsetToJumpIsland;
+
                         if((word & 0xFE000000) != 0xFE000000 &&
-                           (word & 0xFE000000) != 0x00000000)
+                            (word & 0xFE000000) != 0x00000000) {
                             barf("%s: unconditional relative branch out of range: "
                                  "jump island out of range: %#lx",
                                  OC_INFORMATIVE_FILENAME(oc),
                                  word);
                     }
+                    }
                     *wordPtr = (*wordPtr & 0xFC000003) | (word & 0x03FFFFFC);
                     continue;
                 }
@@ -5082,11 +5243,13 @@ static int relocateSection(
         }
 #endif
     }
+
     IF_DEBUG(linker, debugBelch("relocateSection: done\n"));
     return 1;
 }
 
-static int ocGetNames_MachO(ObjectCode* oc)
+static int
+ocGetNames_MachO(ObjectCode* oc)
 {
     char *image = (char*) oc->image;
     struct mach_header *header = (struct mach_header*) image;
@@ -5104,10 +5267,13 @@ static int ocGetNames_MachO(ObjectCode* oc)
 
     for(i=0;i<header->ncmds;i++)
     {
-        if(lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64)
+        if (lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64) {
             segLC = (struct segment_command*) lc;
-        else if(lc->cmd == LC_SYMTAB)
+        }
+        else if (lc->cmd == LC_SYMTAB) {
             symLC = (struct symtab_command*) lc;
+        }
+
         lc = (struct load_command *) ( ((char*)lc) + lc->cmdsize );
     }
 
@@ -5115,14 +5281,19 @@ static int ocGetNames_MachO(ObjectCode* oc)
     nlist = symLC ? (struct nlist*) (image + symLC->symoff)
                   : NULL;
 
-    if(!segLC)
+    if (!segLC) {
         barf("ocGetNames_MachO: no segment load command");
+    }
 
+    IF_DEBUG(linker, debugBelch("ocGetNames_MachO: will load %d sections\n", segLC->nsects));
     for(i=0;i<segLC->nsects;i++)
     {
-        IF_DEBUG(linker, debugBelch("ocGetNames_MachO: segment %d\n", i));
-        if (sections[i].size == 0)
+        IF_DEBUG(linker, debugBelch("ocGetNames_MachO: section %d\n", i));
+
+        if (sections[i].size == 0) {
+            IF_DEBUG(linker, debugBelch("ocGetNames_MachO: found a zero length section, skipping\n"));
             continue;
+        }
 
         if((sections[i].flags & SECTION_TYPE) == S_ZEROFILL)
         {
@@ -5131,36 +5302,47 @@ static int ocGetNames_MachO(ObjectCode* oc)
             sections[i].offset = zeroFillArea - image;
         }
 
-        if(!strcmp(sections[i].sectname,"__text"))
+        if (!strcmp(sections[i].sectname,"__text")) {
+
+            IF_DEBUG(linker, debugBelch("ocGetNames_MachO: adding __text section\n"));
             addSection(oc, SECTIONKIND_CODE_OR_RODATA,
                 (void*) (image + sections[i].offset),
                 (void*) (image + sections[i].offset + sections[i].size));
-        else if(!strcmp(sections[i].sectname,"__const"))
+        }
+        else if (!strcmp(sections[i].sectname,"__const")) {
+
+            IF_DEBUG(linker, debugBelch("ocGetNames_MachO: adding __const section\n"));
             addSection(oc, SECTIONKIND_RWDATA,
                 (void*) (image + sections[i].offset),
                 (void*) (image + sections[i].offset + sections[i].size));
-        else if(!strcmp(sections[i].sectname,"__data"))
+        }    
+        else if (!strcmp(sections[i].sectname,"__data")) {
+
+            IF_DEBUG(linker, debugBelch("ocGetNames_MachO: adding __data section\n"));
             addSection(oc, SECTIONKIND_RWDATA,
                 (void*) (image + sections[i].offset),
                 (void*) (image + sections[i].offset + sections[i].size));
+        }
         else if(!strcmp(sections[i].sectname,"__bss")
-                || !strcmp(sections[i].sectname,"__common"))
+                || !strcmp(sections[i].sectname,"__common")) {
+
+            IF_DEBUG(linker, debugBelch("ocGetNames_MachO: adding __bss section\n"));
             addSection(oc, SECTIONKIND_RWDATA,
                 (void*) (image + sections[i].offset),
                 (void*) (image + sections[i].offset + sections[i].size));
-
-        addProddableBlock(oc, (void*) (image + sections[i].offset),
+        }
+        addProddableBlock(oc,
+                          (void *) (image + sections[i].offset),
                                         sections[i].size);
     }
 
         // count external symbols defined here
     oc->n_symbols = 0;
-    if(symLC)
-    {
-        for(i=0;i<symLC->nsyms;i++)
-        {
-            if(nlist[i].n_type & N_STAB)
+    if (symLC) {
+        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
@@ -5204,19 +5386,27 @@ static int ocGetNames_MachO(ObjectCode* oc)
                             oc->symbols[curSymbol++] = nm;
                     }
                 }
+                else
+                {
+                    IF_DEBUG(linker, debugBelch("ocGetNames_MachO: \t...not external, skipping\n"));
+                }
+            }
+            else
+            {
+                IF_DEBUG(linker, debugBelch("ocGetNames_MachO: \t...not defined in this section, skipping\n"));
             }
         }
     }
 
     commonStorage = stgCallocBytes(1,commonSize,"ocGetNames_MachO(common symbols)");
     commonCounter = (unsigned long)commonStorage;
-    if(symLC)
-    {
-        for(i=0;i<symLC->nsyms;i++)
-        {
+
+    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))
-            {
+             && (nlist[i].n_type & N_EXT)
+             && (nlist[i].n_value != 0)) {
+
                 char *nm = image + symLC->stroff + nlist[i].n_un.n_strx;
                 unsigned long sz = nlist[i].n_value;
 
@@ -5231,10 +5421,13 @@ static int ocGetNames_MachO(ObjectCode* oc)
             }
         }
     }
+
+    IF_DEBUG(linker, debugBelch("ocGetNames_MachO: done\n"));
     return 1;
 }
 
-static int ocResolve_MachO(ObjectCode* oc)
+static int
+ocResolve_MachO(ObjectCode* oc)
 {
     char *image = (char*) oc->image;
     struct mach_header *header = (struct mach_header*) image;
@@ -5249,12 +5442,19 @@ static int ocResolve_MachO(ObjectCode* oc)
     IF_DEBUG(linker, debugBelch("ocResolve_MachO: start\n"));
     for (i = 0; i < header->ncmds; i++)
     {
-        if(lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64)
+        if (lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64) {
             segLC = (struct segment_command*) lc;
-        else if(lc->cmd == LC_SYMTAB)
+            IF_DEBUG(linker, debugBelch("ocResolve_MachO: found a 32 or 64 bit segment load command\n"));
+        }
+        else if (lc->cmd == LC_SYMTAB) {
             symLC = (struct symtab_command*) lc;
-        else if(lc->cmd == LC_DYSYMTAB)
+            IF_DEBUG(linker, debugBelch("ocResolve_MachO: found a symbol table load command\n"));
+        }
+        else if (lc->cmd == LC_DYSYMTAB) {
             dsymLC = (struct dysymtab_command*) lc;
+            IF_DEBUG(linker, debugBelch("ocResolve_MachO: found a dynamic symbol table load command\n"));
+        }
+
         lc = (struct load_command *) ( ((char*)lc) + lc->cmdsize );
     }
 
@@ -5322,7 +5522,8 @@ static int ocResolve_MachO(ObjectCode* oc)
 
 extern void* symbolsWithoutUnderscore[];
 
-static void machoInitSymbolsWithoutUnderscore()
+static void
+machoInitSymbolsWithoutUnderscore(void)
 {
     void **p = symbolsWithoutUnderscore;
     __asm__ volatile(".globl _symbolsWithoutUnderscore\n.data\n_symbolsWithoutUnderscore:");
@@ -5350,7 +5551,8 @@ static void machoInitSymbolsWithoutUnderscore()
  * 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 )
+static int
+machoGetMisalignment( FILE * f )
 {
     struct mach_header header;
     int misalignment;