[project @ 2002-05-01 15:46:14 by simonmar]
[ghc-hetmet.git] / ghc / rts / Linker.c
index 8f259f3..6d8c71c 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
 /* -----------------------------------------------------------------------------
- * $Id: Linker.c,v 1.79 2002/01/29 02:41:21 sof Exp $
+ * $Id: Linker.c,v 1.89 2002/05/01 15:46:14 simonmar Exp $
  *
  * (c) The GHC Team, 2000, 2001
  *
  *
  * (c) The GHC Team, 2000, 2001
  *
@@ -144,6 +144,7 @@ typedef struct _RtsSymbolVal {
       Sym(gmtime)                               \
       Sym(opendir)                              \
       Sym(readdir)                              \
       Sym(gmtime)                               \
       Sym(opendir)                              \
       Sym(readdir)                              \
+      Sym(rewinddir)                            \
       Sym(closedir)                             \
       Sym(__divdi3)                             \
       Sym(__udivdi3)                            \
       Sym(closedir)                             \
       Sym(__divdi3)                             \
       Sym(__udivdi3)                            \
@@ -161,7 +162,7 @@ typedef struct _RtsSymbolVal {
       Maybe_ForeignObj                         \
       Maybe_Stable_Names                       \
       Sym(StgReturn)                           \
       Maybe_ForeignObj                         \
       Maybe_Stable_Names                       \
       Sym(StgReturn)                           \
-      Sym(__stginit_PrelGHC)                   \
+      Sym(__stginit_GHCziPrim)                 \
       Sym(init_stack)                          \
       SymX(__stg_chk_0)                                \
       SymX(__stg_chk_1)                                \
       Sym(init_stack)                          \
       SymX(__stg_chk_0)                                \
       SymX(__stg_chk_1)                                \
@@ -215,6 +216,7 @@ typedef struct _RtsSymbolVal {
       SymX(divExactIntegerzh_fast)             \
       SymX(divModIntegerzh_fast)               \
       SymX(forkzh_fast)                                \
       SymX(divExactIntegerzh_fast)             \
       SymX(divModIntegerzh_fast)               \
       SymX(forkzh_fast)                                \
+      SymX(forkProcesszh_fast)                  \
       SymX(freeHaskellFunctionPtr)             \
       SymX(freeStablePtr)                      \
       SymX(gcdIntegerzh_fast)                  \
       SymX(freeHaskellFunctionPtr)             \
       SymX(freeStablePtr)                      \
       SymX(gcdIntegerzh_fast)                  \
@@ -239,6 +241,7 @@ typedef struct _RtsSymbolVal {
       SymX(minusIntegerzh_fast)                        \
       SymX(mkApUpd0zh_fast)                    \
       SymX(myThreadIdzh_fast)                  \
       SymX(minusIntegerzh_fast)                        \
       SymX(mkApUpd0zh_fast)                    \
       SymX(myThreadIdzh_fast)                  \
+      SymX(labelThreadzh_fast)                  \
       SymX(newArrayzh_fast)                    \
       SymX(newBCOzh_fast)                      \
       SymX(newByteArrayzh_fast)                        \
       SymX(newArrayzh_fast)                    \
       SymX(newBCOzh_fast)                      \
       SymX(newByteArrayzh_fast)                        \
@@ -388,7 +391,7 @@ static RtsSymbolVal rtsSyms[] = {
  */
 static void ghciInsertStrHashTable ( char* obj_name,
                                      HashTable *table,
  */
 static void ghciInsertStrHashTable ( char* obj_name,
                                      HashTable *table,
-                                     char* key, 
+                                     char* key,
                                      void *data
                                   )
 {
                                      void *data
                                   )
 {
@@ -397,7 +400,7 @@ static void ghciInsertStrHashTable ( char* obj_name,
       insertStrHashTable(table, (StgWord)key, data);
       return;
    }
       insertStrHashTable(table, (StgWord)key, data);
       return;
    }
-   fprintf(stderr, 
+   fprintf(stderr,
       "\n\n"
       "GHCi runtime linker: fatal error: I found a duplicate definition for symbol\n"
       "   %s\n"
       "\n\n"
       "GHCi runtime linker: fatal error: I found a duplicate definition for symbol\n"
       "   %s\n"
@@ -448,7 +451,7 @@ initLinker( void )
  * lookupSymbol() will subsequently see them by dlsym on the program's
  * dl-handle.  Returns NULL if success, otherwise ptr to an err msg.
  *
  * lookupSymbol() will subsequently see them by dlsym on the program's
  * dl-handle.  Returns NULL if success, otherwise ptr to an err msg.
  *
- * In the PEi386 case, open the DLLs and put handles to them in a 
+ * In the PEi386 case, open the DLLs and put handles to them in a
  * linked list.  When looking for a symbol, try all handles in the
  * list.
  */
  * linked list.  When looking for a symbol, try all handles in the
  * list.
  */
@@ -461,7 +464,7 @@ typedef
       char*              name;
       struct _OpenedDLL* next;
       HINSTANCE instance;
       char*              name;
       struct _OpenedDLL* next;
       HINSTANCE instance;
-   } 
+   }
    OpenedDLL;
 
 /* A list thereof. */
    OpenedDLL;
 
 /* A list thereof. */
@@ -470,23 +473,14 @@ static OpenedDLL* opened_dlls = NULL;
 
 
 
 
 
 
-char*
-addDLL ( __attribute((unused)) char* path, char* dll_name )
+char *
+addDLL( char *dll_name )
 {
 #  if defined(OBJFORMAT_ELF)
    void *hdl;
 {
 #  if defined(OBJFORMAT_ELF)
    void *hdl;
-   char *buf;
    char *errmsg;
 
    char *errmsg;
 
-   if (path == NULL || strlen(path) == 0) {
-      buf = stgMallocBytes(strlen(dll_name) + 10, "addDll");
-      sprintf(buf, "lib%s.so", dll_name);
-   } else {
-      buf = stgMallocBytes(strlen(path) + 1 + strlen(dll_name) + 10, "addDll");
-      sprintf(buf, "%s/lib%s.so", path, dll_name);
-   }
-   hdl = dlopen(buf, RTLD_NOW | RTLD_GLOBAL );
-   free(buf);
+   hdl= dlopen(dll_name, RTLD_NOW | RTLD_GLOBAL);
    if (hdl == NULL) {
       /* dlopen failed; return a ptr to the error msg. */
       errmsg = dlerror();
    if (hdl == NULL) {
       /* dlopen failed; return a ptr to the error msg. */
       errmsg = dlerror();
@@ -516,11 +510,17 @@ addDLL ( __attribute((unused)) char* path, char* dll_name )
    buf = stgMallocBytes(strlen(dll_name) + 10, "addDLL");
    sprintf(buf, "%s.DLL", dll_name);
    instance = LoadLibrary(buf);
    buf = stgMallocBytes(strlen(dll_name) + 10, "addDLL");
    sprintf(buf, "%s.DLL", dll_name);
    instance = LoadLibrary(buf);
-   free(buf);
    if (instance == NULL) {
    if (instance == NULL) {
-     /* LoadLibrary failed; return a ptr to the error msg. */
-     return "addDLL: unknown error";
+        sprintf(buf, "%s.DRV", dll_name);              // KAA: allow loading of drivers (like winspool.drv)
+        instance = LoadLibrary(buf);
+        if (instance == NULL) {
+               free(buf);
+
+           /* LoadLibrary failed; return a ptr to the error msg. */
+           return "addDLL: unknown error";
+        }
    }
    }
+   free(buf);
 
    o_dll = stgMallocBytes( sizeof(OpenedDLL), "addDLL" );
    o_dll->name     = stgMallocBytes(1+strlen(dll_name), "addDLL");
 
    o_dll = stgMallocBytes( sizeof(OpenedDLL), "addDLL" );
    o_dll->name     = stgMallocBytes(1+strlen(dll_name), "addDLL");
@@ -537,7 +537,7 @@ addDLL ( __attribute((unused)) char* path, char* dll_name )
 
 /* -----------------------------------------------------------------------------
  * lookup a symbol in the hash table
 
 /* -----------------------------------------------------------------------------
  * lookup a symbol in the hash table
- */  
+ */
 void *
 lookupSymbol( char *lbl )
 {
 void *
 lookupSymbol( char *lbl )
 {
@@ -563,7 +563,7 @@ lookupSymbol( char *lbl )
               if (sym != NULL) {
                /*fprintf(stderr, "found %s in %s\n", lbl+1,o_dll->name); fflush(stderr);*/
                return sym;
               if (sym != NULL) {
                /*fprintf(stderr, "found %s in %s\n", lbl+1,o_dll->name); fflush(stderr);*/
                return sym;
-             } 
+             }
            }
            sym = GetProcAddress(o_dll->instance, lbl);
            if (sym != NULL) {
            }
            sym = GetProcAddress(o_dll->instance, lbl);
            if (sym != NULL) {
@@ -581,7 +581,7 @@ lookupSymbol( char *lbl )
     }
 }
 
     }
 }
 
-static 
+static
 __attribute((unused))
 void *
 lookupLocalSymbol( ObjectCode* oc, char *lbl )
 __attribute((unused))
 void *
 lookupLocalSymbol( ObjectCode* oc, char *lbl )
@@ -623,7 +623,7 @@ void ghci_enquire ( char* addr )
             a = lookupStrHashTable(symhash, sym);
          if (a == NULL) {
             /* fprintf(stderr, "ghci_enquire: can't find %s\n", sym); */
             a = lookupStrHashTable(symhash, sym);
          if (a == NULL) {
             /* fprintf(stderr, "ghci_enquire: can't find %s\n", sym); */
-         } 
+         }
          else if (addr-DELTA <= a && a <= addr+DELTA) {
             fprintf(stderr, "%p + %3d  ==  `%s'\n", addr, a - addr, sym);
          }
          else if (addr-DELTA <= a && a <= addr+DELTA) {
             fprintf(stderr, "%p + %3d  ==  `%s'\n", addr, a - addr, sym);
          }
@@ -650,7 +650,7 @@ loadObj( char *path )
 
    /* Check that we haven't already loaded this object.  Don't give up
       at this stage; ocGetNames_* will barf later. */
 
    /* Check that we haven't already loaded this object.  Don't give up
       at this stage; ocGetNames_* will barf later. */
-   { 
+   {
        ObjectCode *o;
        int is_dup = 0;
        for (o = objects; o; o = o->next) {
        ObjectCode *o;
        int is_dup = 0;
        for (o = objects; o; o = o->next) {
@@ -658,7 +658,7 @@ loadObj( char *path )
              is_dup = 1;
        }
        if (is_dup) {
              is_dup = 1;
        }
        if (is_dup) {
-        fprintf(stderr, 
+        fprintf(stderr,
             "\n\n"
             "GHCi runtime linker: warning: looks like you're trying to load the\n"
             "same object file twice:\n"
             "\n\n"
             "GHCi runtime linker: warning: looks like you're trying to load the\n"
             "same object file twice:\n"
@@ -740,7 +740,7 @@ loadObj( char *path )
  *
  * Returns: 1 if ok, 0 on error.
  */
  *
  * Returns: 1 if ok, 0 on error.
  */
-HsInt 
+HsInt
 resolveObjs( void )
 {
     ObjectCode *oc;
 resolveObjs( void )
 {
     ObjectCode *oc;
@@ -780,7 +780,7 @@ unloadObj( char *path )
            /* Remove all the mappings for the symbols within this
             * object..
             */
            /* Remove all the mappings for the symbols within this
             * object..
             */
-           { 
+           {
                 int i;
                 for (i = 0; i < oc->n_symbols; i++) {
                    if (oc->symbols[i] != NULL) {
                 int i;
                 for (i = 0; i < oc->n_symbols; i++) {
                    if (oc->symbols[i] != NULL) {
@@ -820,7 +820,7 @@ unloadObj( char *path )
  */
 static void addProddableBlock ( ObjectCode* oc, void* start, int size )
 {
  */
 static void addProddableBlock ( ObjectCode* oc, void* start, int size )
 {
-   ProddableBlock* pb 
+   ProddableBlock* pb
       = stgMallocBytes(sizeof(ProddableBlock), "addProddableBlock");
    /* fprintf(stderr, "aPB %p %p %d\n", oc, start, size); */
    ASSERT(size > 0);
       = stgMallocBytes(sizeof(ProddableBlock), "addProddableBlock");
    /* fprintf(stderr, "aPB %p %p %d\n", oc, start, size); */
    ASSERT(size > 0);
@@ -857,6 +857,10 @@ static void addSection ( ObjectCode* oc, SectionKind kind,
    s->kind      = kind;
    s->next      = oc->sections;
    oc->sections = s;
    s->kind      = kind;
    s->next      = oc->sections;
    oc->sections = s;
+   /*
+   fprintf(stderr, "addSection: %p-%p (size %d), kind %d\n",
+                   start, ((char*)end)-1, end - start + 1, kind );
+   */
 }
 
 
 }
 
 
@@ -865,13 +869,40 @@ static void addSection ( ObjectCode* oc, SectionKind kind,
  * PEi386 specifics (Win32 targets)
  * ------------------------------------------------------------------------*/
 
  * PEi386 specifics (Win32 targets)
  * ------------------------------------------------------------------------*/
 
-/* The information for this linker comes from 
-      Microsoft Portable Executable 
+/* The information for this linker comes from
+      Microsoft Portable Executable
       and Common Object File Format Specification
       revision 5.1 January 1998
    which SimonM says comes from the MS Developer Network CDs.
       and Common Object File Format Specification
       revision 5.1 January 1998
    which SimonM says comes from the MS Developer Network CDs.
+
+   It can be found there (on older CDs), but can also be found
+   online at:
+
+      http://www.microsoft.com/hwdev/hardware/PECOFF.asp
+
+   (this is Rev 6.0 from February 1999).
+
+   Things move, so if that fails, try searching for it via
+
+      http://www.google.com/search?q=PE+COFF+specification
+
+   The ultimate reference for the PE format is the Winnt.h
+   header file that comes with the Platform SDKs; as always,
+   implementations will drift wrt their documentation.
+
+   A good background article on the PE format is Matt Pietrek's
+   March 1994 article in Microsoft System Journal (MSJ)
+   (Vol.9, No. 3): "Peering Inside the PE: A Tour of the
+   Win32 Portable Executable File Format." The info in there
+   has recently been updated in a two part article in
+   MSDN magazine, issues Feb and March 2002,
+   "Inside Windows: An In-Depth Look into the Win32 Portable
+   Executable File Format"
+
+   John Levine's book "Linkers and Loaders" contains useful
+   info on PE too.
 */
 */
-      
+
 
 #if defined(OBJFORMAT_PEi386)
 
 
 #if defined(OBJFORMAT_PEi386)
 
@@ -883,7 +914,7 @@ typedef unsigned int   UInt32;
 typedef          int   Int32;
 
 
 typedef          int   Int32;
 
 
-typedef 
+typedef
    struct {
       UInt16 Machine;
       UInt16 NumberOfSections;
    struct {
       UInt16 Machine;
       UInt16 NumberOfSections;
@@ -898,7 +929,7 @@ typedef
 #define sizeof_COFF_header 20
 
 
 #define sizeof_COFF_header 20
 
 
-typedef 
+typedef
    struct {
       UChar  Name[8];
       UInt32 VirtualSize;
    struct {
       UChar  Name[8];
       UInt32 VirtualSize;
@@ -909,7 +940,7 @@ typedef
       UInt32 PointerToLinenumbers;
       UInt16 NumberOfRelocations;
       UInt16 NumberOfLineNumbers;
       UInt32 PointerToLinenumbers;
       UInt16 NumberOfRelocations;
       UInt16 NumberOfLineNumbers;
-      UInt32 Characteristics; 
+      UInt32 Characteristics;
    }
    COFF_section;
 
    }
    COFF_section;
 
@@ -970,7 +1001,7 @@ typedef
 
 /* We use myindex to calculate array addresses, rather than
    simply doing the normal subscript thing.  That's because
 
 /* We use myindex to calculate array addresses, rather than
    simply doing the normal subscript thing.  That's because
-   some of the above structs have sizes which are not 
+   some of the above structs have sizes which are not
    a whole number of words.  GCC rounds their sizes up to a
    whole number of words, which means that the address calcs
    arising from using normal C indexing or pointer arithmetic
    a whole number of words.  GCC rounds their sizes up to a
    whole number of words, which means that the address calcs
    arising from using normal C indexing or pointer arithmetic
@@ -1025,7 +1056,7 @@ cstring_from_COFF_symbol_name ( UChar* name, UChar* strtab )
 {
    UChar* newstr;
    /* If the string is longer than 8 bytes, look in the
 {
    UChar* newstr;
    /* If the string is longer than 8 bytes, look in the
-      string table for it -- this will be correctly zero terminated. 
+      string table for it -- this will be correctly zero terminated.
    */
    if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
       UInt32 strtab_offset = * (UInt32*)(name+4);
    */
    if (name[0]==0 && name[1]==0 && name[2]==0 && name[3]==0) {
       UInt32 strtab_offset = * (UInt32*)(name+4);
@@ -1051,23 +1082,23 @@ static COFF_section *
 findPEi386SectionCalled ( ObjectCode* oc,  char* name )
 {
    int i;
 findPEi386SectionCalled ( ObjectCode* oc,  char* name )
 {
    int i;
-   COFF_header* hdr 
+   COFF_header* hdr
       = (COFF_header*)(oc->image);
       = (COFF_header*)(oc->image);
-   COFF_section* sectab 
+   COFF_section* sectab
       = (COFF_section*) (
       = (COFF_section*) (
-           ((UChar*)(oc->image)) 
+           ((UChar*)(oc->image))
            + sizeof_COFF_header + hdr->SizeOfOptionalHeader
         );
    for (i = 0; i < hdr->NumberOfSections; i++) {
       UChar* n1;
       UChar* n2;
            + sizeof_COFF_header + hdr->SizeOfOptionalHeader
         );
    for (i = 0; i < hdr->NumberOfSections; i++) {
       UChar* n1;
       UChar* n2;
-      COFF_section* section_i 
+      COFF_section* section_i
          = (COFF_section*)
            myindex ( sizeof_COFF_section, sectab, i );
       n1 = (UChar*) &(section_i->Name);
       n2 = name;
          = (COFF_section*)
            myindex ( sizeof_COFF_section, sectab, i );
       n1 = (UChar*) &(section_i->Name);
       n2 = name;
-      if (n1[0]==n2[0] && n1[1]==n2[1] && n1[2]==n2[2] && 
-          n1[3]==n2[3] && n1[4]==n2[4] && n1[5]==n2[5] && 
+      if (n1[0]==n2[0] && n1[1]==n2[1] && n1[2]==n2[2] &&
+          n1[3]==n2[3] && n1[4]==n2[4] && n1[5]==n2[5] &&
           n1[6]==n2[6] && n1[7]==n2[7])
          return section_i;
    }
           n1[6]==n2[6] && n1[7]==n2[7])
          return section_i;
    }
@@ -1082,7 +1113,7 @@ zapTrailingAtSign ( UChar* sym )
 #  define my_isdigit(c) ((c) >= '0' && (c) <= '9')
    int i, j;
    if (sym[0] == 0) return;
 #  define my_isdigit(c) ((c) >= '0' && (c) <= '9')
    int i, j;
    if (sym[0] == 0) return;
-   i = 0; 
+   i = 0;
    while (sym[i] != 0) i++;
    i--;
    j = i;
    while (sym[i] != 0) i++;
    i--;
    j = i;
@@ -1104,12 +1135,12 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
    /* fprintf(stderr, "\nLOADING %s\n", oc->fileName); */
    hdr = (COFF_header*)(oc->image);
    sectab = (COFF_section*) (
    /* fprintf(stderr, "\nLOADING %s\n", oc->fileName); */
    hdr = (COFF_header*)(oc->image);
    sectab = (COFF_section*) (
-               ((UChar*)(oc->image)) 
+               ((UChar*)(oc->image))
                + sizeof_COFF_header + hdr->SizeOfOptionalHeader
             );
    symtab = (COFF_symbol*) (
                ((UChar*)(oc->image))
                + sizeof_COFF_header + hdr->SizeOfOptionalHeader
             );
    symtab = (COFF_symbol*) (
                ((UChar*)(oc->image))
-               + hdr->PointerToSymbolTable 
+               + hdr->PointerToSymbolTable
             );
    strtab = ((UChar*)symtab)
             + hdr->NumberOfSymbols * sizeof_COFF_symbol;
             );
    strtab = ((UChar*)symtab)
             + hdr->NumberOfSymbols * sizeof_COFF_symbol;
@@ -1131,7 +1162,7 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
    }
    if ( (hdr->Characteristics & MYIMAGE_FILE_BYTES_REVERSED_HI)
         /* || !(hdr->Characteristics & MYIMAGE_FILE_32BIT_MACHINE) */ ) {
    }
    if ( (hdr->Characteristics & MYIMAGE_FILE_BYTES_REVERSED_HI)
         /* || !(hdr->Characteristics & MYIMAGE_FILE_32BIT_MACHINE) */ ) {
-      belch("Invalid PEi386 word size or endiannness: %d", 
+      belch("Invalid PEi386 word size or endiannness: %d",
             (int)(hdr->Characteristics));
       return 0;
    }
             (int)(hdr->Characteristics));
       return 0;
    }
@@ -1154,25 +1185,25 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
    IF_DEBUG(linker, i=1);
    if (i == 0) return 1;
 
    IF_DEBUG(linker, i=1);
    if (i == 0) return 1;
 
-   fprintf ( stderr, 
+   fprintf ( stderr,
              "sectab offset = %d\n", ((UChar*)sectab) - ((UChar*)hdr) );
              "sectab offset = %d\n", ((UChar*)sectab) - ((UChar*)hdr) );
-   fprintf ( stderr, 
+   fprintf ( stderr,
              "symtab offset = %d\n", ((UChar*)symtab) - ((UChar*)hdr) );
              "symtab offset = %d\n", ((UChar*)symtab) - ((UChar*)hdr) );
-   fprintf ( stderr, 
+   fprintf ( stderr,
              "strtab offset = %d\n", ((UChar*)strtab) - ((UChar*)hdr) );
 
    fprintf ( stderr, "\n" );
              "strtab offset = %d\n", ((UChar*)strtab) - ((UChar*)hdr) );
 
    fprintf ( stderr, "\n" );
-   fprintf ( stderr, 
+   fprintf ( stderr,
              "Machine:           0x%x\n", (UInt32)(hdr->Machine) );
              "Machine:           0x%x\n", (UInt32)(hdr->Machine) );
-   fprintf ( stderr, 
+   fprintf ( stderr,
              "# sections:        %d\n",   (UInt32)(hdr->NumberOfSections) );
    fprintf ( stderr,
              "time/date:         0x%x\n", (UInt32)(hdr->TimeDateStamp) );
    fprintf ( stderr,
              "symtab offset:     %d\n",   (UInt32)(hdr->PointerToSymbolTable) );
              "# sections:        %d\n",   (UInt32)(hdr->NumberOfSections) );
    fprintf ( stderr,
              "time/date:         0x%x\n", (UInt32)(hdr->TimeDateStamp) );
    fprintf ( stderr,
              "symtab offset:     %d\n",   (UInt32)(hdr->PointerToSymbolTable) );
-   fprintf ( stderr, 
+   fprintf ( stderr,
              "# symbols:         %d\n",   (UInt32)(hdr->NumberOfSymbols) );
              "# symbols:         %d\n",   (UInt32)(hdr->NumberOfSymbols) );
-   fprintf ( stderr, 
+   fprintf ( stderr,
              "sz of opt hdr:     %d\n",   (UInt32)(hdr->SizeOfOptionalHeader) );
    fprintf ( stderr,
              "characteristics:   0x%x\n", (UInt32)(hdr->Characteristics) );
              "sz of opt hdr:     %d\n",   (UInt32)(hdr->SizeOfOptionalHeader) );
    fprintf ( stderr,
              "characteristics:   0x%x\n", (UInt32)(hdr->Characteristics) );
@@ -1184,14 +1215,14 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
       COFF_section* sectab_i
          = (COFF_section*)
            myindex ( sizeof_COFF_section, sectab, i );
       COFF_section* sectab_i
          = (COFF_section*)
            myindex ( sizeof_COFF_section, sectab, i );
-      fprintf ( stderr, 
+      fprintf ( stderr,
                 "\n"
                 "section %d\n"
                 "     name `",
                 "\n"
                 "section %d\n"
                 "     name `",
-                i 
+                i
               );
       printName ( sectab_i->Name, strtab );
               );
       printName ( sectab_i->Name, strtab );
-      fprintf ( stderr, 
+      fprintf ( stderr,
                 "'\n"
                 "    vsize %d\n"
                 "    vaddr %d\n"
                 "'\n"
                 "    vsize %d\n"
                 "    vaddr %d\n"
@@ -1211,13 +1242,12 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
       reltab = (COFF_reloc*) (
                   ((UChar*)(oc->image)) + sectab_i->PointerToRelocations
                );
       reltab = (COFF_reloc*) (
                   ((UChar*)(oc->image)) + sectab_i->PointerToRelocations
                );
-              
+
       if ( sectab_i->Characteristics & MYIMAGE_SCN_LNK_NRELOC_OVFL ) {
        /* If the relocation field (a short) has overflowed, the
         * real count can be found in the first reloc entry.
       if ( sectab_i->Characteristics & MYIMAGE_SCN_LNK_NRELOC_OVFL ) {
        /* If the relocation field (a short) has overflowed, the
         * real count can be found in the first reloc entry.
-        * The PE spec (Rev 6.0) doesn't really cover this,
-        * but as always header files provide the final word on
-        * details like this (cf. WinNT.h).
+        *
+        * See Section 4.1 (last para) of the PE spec (rev6.0).
         */
         COFF_reloc* rel = (COFF_reloc*)
                            myindex ( sizeof_COFF_reloc, reltab, 0 );
         */
         COFF_reloc* rel = (COFF_reloc*)
                            myindex ( sizeof_COFF_reloc, reltab, 0 );
@@ -1232,9 +1262,9 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
          COFF_symbol* sym;
          COFF_reloc* rel = (COFF_reloc*)
                            myindex ( sizeof_COFF_reloc, reltab, j );
          COFF_symbol* sym;
          COFF_reloc* rel = (COFF_reloc*)
                            myindex ( sizeof_COFF_reloc, reltab, j );
-         fprintf ( stderr, 
+         fprintf ( stderr,
                    "        type 0x%-4x   vaddr 0x%-8x   name `",
                    "        type 0x%-4x   vaddr 0x%-8x   name `",
-                   (UInt32)rel->Type, 
+                   (UInt32)rel->Type,
                    rel->VirtualAddress );
          sym = (COFF_symbol*)
                myindex ( sizeof_COFF_symbol, symtab, rel->SymbolTableIndex );
                    rel->VirtualAddress );
          sym = (COFF_symbol*)
                myindex ( sizeof_COFF_symbol, symtab, rel->SymbolTableIndex );
@@ -1249,8 +1279,8 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
    fprintf ( stderr, "string table has size 0x%x\n", * (UInt32*)strtab );
    fprintf ( stderr, "---START of string table---\n");
    for (i = 4; i < *(Int32*)strtab; i++) {
    fprintf ( stderr, "string table has size 0x%x\n", * (UInt32*)strtab );
    fprintf ( stderr, "---START of string table---\n");
    for (i = 4; i < *(Int32*)strtab; i++) {
-      if (strtab[i] == 0) 
-         fprintf ( stderr, "\n"); else 
+      if (strtab[i] == 0)
+         fprintf ( stderr, "\n"); else
          fprintf( stderr, "%c", strtab[i] );
    }
    fprintf ( stderr, "--- END  of string table---\n");
          fprintf( stderr, "%c", strtab[i] );
    }
    fprintf ( stderr, "--- END  of string table---\n");
@@ -1262,13 +1292,13 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
       if (i >= (Int32)(hdr->NumberOfSymbols)) break;
       symtab_i = (COFF_symbol*)
                  myindex ( sizeof_COFF_symbol, symtab, i );
       if (i >= (Int32)(hdr->NumberOfSymbols)) break;
       symtab_i = (COFF_symbol*)
                  myindex ( sizeof_COFF_symbol, symtab, i );
-      fprintf ( stderr, 
+      fprintf ( stderr,
                 "symbol %d\n"
                 "     name `",
                 "symbol %d\n"
                 "     name `",
-                i 
+                i
               );
       printName ( symtab_i->Name, strtab );
               );
       printName ( symtab_i->Name, strtab );
-      fprintf ( stderr, 
+      fprintf ( stderr,
                 "'\n"
                 "    value 0x%x\n"
                 "   1+sec# %d\n"
                 "'\n"
                 "    value 0x%x\n"
                 "   1+sec# %d\n"
@@ -1279,7 +1309,7 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
                 (Int32)(symtab_i->SectionNumber),
                 (UInt32)symtab_i->Type,
                 (UInt32)symtab_i->StorageClass,
                 (Int32)(symtab_i->SectionNumber),
                 (UInt32)symtab_i->Type,
                 (UInt32)symtab_i->StorageClass,
-                (UInt32)symtab_i->NumberOfAuxSymbols 
+                (UInt32)symtab_i->NumberOfAuxSymbols
               );
       i += symtab_i->NumberOfAuxSymbols;
       i++;
               );
       i += symtab_i->NumberOfAuxSymbols;
       i++;
@@ -1301,15 +1331,15 @@ ocGetNames_PEi386 ( ObjectCode* oc )
    UChar* sname;
    void*  addr;
    int    i;
    UChar* sname;
    void*  addr;
    int    i;
-   
+
    hdr = (COFF_header*)(oc->image);
    sectab = (COFF_section*) (
    hdr = (COFF_header*)(oc->image);
    sectab = (COFF_section*) (
-               ((UChar*)(oc->image)) 
+               ((UChar*)(oc->image))
                + sizeof_COFF_header + hdr->SizeOfOptionalHeader
             );
    symtab = (COFF_symbol*) (
                ((UChar*)(oc->image))
                + sizeof_COFF_header + hdr->SizeOfOptionalHeader
             );
    symtab = (COFF_symbol*) (
                ((UChar*)(oc->image))
-               + hdr->PointerToSymbolTable 
+               + hdr->PointerToSymbolTable
             );
    strtab = ((UChar*)(oc->image))
             + hdr->PointerToSymbolTable
             );
    strtab = ((UChar*)(oc->image))
             + hdr->PointerToSymbolTable
@@ -1327,7 +1357,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
       /* 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.  */
       /* 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, 
+      zspace = stgCallocBytes(1, sectab_i->VirtualSize,
                               "ocGetNames_PEi386(anonymous bss)");
       sectab_i->PointerToRawData = ((UChar*)zspace) - ((UChar*)(oc->image));
       addProddableBlock(oc, zspace, sectab_i->VirtualSize);
                               "ocGetNames_PEi386(anonymous bss)");
       sectab_i->PointerToRawData = ((UChar*)zspace) - ((UChar*)(oc->image));
       addProddableBlock(oc, zspace, sectab_i->VirtualSize);
@@ -1341,7 +1371,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
       UChar* end;
       UInt32 sz;
 
       UChar* end;
       UInt32 sz;
 
-      SectionKind kind 
+      SectionKind kind
          = SECTIONKIND_OTHER;
       COFF_section* sectab_i
          = (COFF_section*)
          = SECTIONKIND_OTHER;
       COFF_section* sectab_i
          = (COFF_section*)
@@ -1349,11 +1379,11 @@ ocGetNames_PEi386 ( ObjectCode* oc )
       IF_DEBUG(linker, belch("section name = %s\n", sectab_i->Name ));
 
 #     if 0
       IF_DEBUG(linker, belch("section name = %s\n", sectab_i->Name ));
 
 #     if 0
-      /* I'm sure this is the Right Way to do it.  However, the 
+      /* I'm sure this is the Right Way to do it.  However, the
          alternative of testing the sectab_i->Name field seems to
          work ok with Cygwin.
       */
          alternative of testing the sectab_i->Name field seems to
          work ok with Cygwin.
       */
-      if (sectab_i->Characteristics & MYIMAGE_SCN_CNT_CODE || 
+      if (sectab_i->Characteristics & MYIMAGE_SCN_CNT_CODE ||
           sectab_i->Characteristics & MYIMAGE_SCN_CNT_INITIALIZED_DATA)
          kind = SECTIONKIND_CODE_OR_RODATA;
 #     endif
           sectab_i->Characteristics & MYIMAGE_SCN_CNT_INITIALIZED_DATA)
          kind = SECTIONKIND_CODE_OR_RODATA;
 #     endif
@@ -1394,7 +1424,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
    oc->symbols   = stgMallocBytes(oc->n_symbols * sizeof(char*),
                                   "ocGetNames_PEi386(oc->symbols)");
    /* Call me paranoid; I don't care. */
    oc->symbols   = stgMallocBytes(oc->n_symbols * sizeof(char*),
                                   "ocGetNames_PEi386(oc->symbols)");
    /* Call me paranoid; I don't care. */
-   for (i = 0; i < oc->n_symbols; i++) 
+   for (i = 0; i < oc->n_symbols; i++)
       oc->symbols[i] = NULL;
 
    i = 0;
       oc->symbols[i] = NULL;
 
    i = 0;
@@ -1409,27 +1439,27 @@ ocGetNames_PEi386 ( ObjectCode* oc )
       if (symtab_i->StorageClass == MYIMAGE_SYM_CLASS_EXTERNAL
           && symtab_i->SectionNumber != MYIMAGE_SYM_UNDEFINED) {
          /* This symbol is global and defined, viz, exported */
       if (symtab_i->StorageClass == MYIMAGE_SYM_CLASS_EXTERNAL
           && symtab_i->SectionNumber != MYIMAGE_SYM_UNDEFINED) {
          /* This symbol is global and defined, viz, exported */
-         /* for MYIMAGE_SYMCLASS_EXTERNAL 
+         /* for MYIMAGE_SYMCLASS_EXTERNAL
                 && !MYIMAGE_SYM_UNDEFINED,
                 && !MYIMAGE_SYM_UNDEFINED,
-            the address of the symbol is: 
+            the address of the symbol is:
                 address of relevant section + offset in section
          */
                 address of relevant section + offset in section
          */
-         COFF_section* sectabent 
-            = (COFF_section*) myindex ( sizeof_COFF_section, 
+         COFF_section* sectabent
+            = (COFF_section*) myindex ( sizeof_COFF_section,
                                         sectab,
                                         symtab_i->SectionNumber-1 );
          addr = ((UChar*)(oc->image))
                 + (sectabent->PointerToRawData
                    + symtab_i->Value);
                                         sectab,
                                         symtab_i->SectionNumber-1 );
          addr = ((UChar*)(oc->image))
                 + (sectabent->PointerToRawData
                    + symtab_i->Value);
-      } 
+      }
       else
       if (symtab_i->SectionNumber == MYIMAGE_SYM_UNDEFINED
          && symtab_i->Value > 0) {
          /* This symbol isn't in any section at all, ie, global bss.
             Allocate zeroed space for it. */
       else
       if (symtab_i->SectionNumber == MYIMAGE_SYM_UNDEFINED
          && symtab_i->Value > 0) {
          /* This symbol isn't in any section at all, ie, global bss.
             Allocate zeroed space for it. */
-         addr = stgCallocBytes(1, symtab_i->Value, 
+         addr = stgCallocBytes(1, symtab_i->Value,
                                "ocGetNames_PEi386(non-anonymous bss)");
                                "ocGetNames_PEi386(non-anonymous bss)");
-         addSection(oc, SECTIONKIND_RWDATA, addr, 
+         addSection(oc, SECTIONKIND_RWDATA, addr,
                         ((UChar*)addr) + symtab_i->Value - 1);
          addProddableBlock(oc, addr, symtab_i->Value);
          /* fprintf(stderr, "BSS      section at 0x%x\n", addr); */
                         ((UChar*)addr) + symtab_i->Value - 1);
          addProddableBlock(oc, addr, symtab_i->Value);
          /* fprintf(stderr, "BSS      section at 0x%x\n", addr); */
@@ -1445,13 +1475,13 @@ ocGetNames_PEi386 ( ObjectCode* oc )
          ghciInsertStrHashTable(oc->fileName, symhash, sname, addr);
       } else {
 #        if 0
          ghciInsertStrHashTable(oc->fileName, symhash, sname, addr);
       } else {
 #        if 0
-         fprintf ( stderr, 
+         fprintf ( stderr,
                    "IGNORING symbol %d\n"
                    "     name `",
                    "IGNORING symbol %d\n"
                    "     name `",
-                   i 
+                   i
                  );
          printName ( symtab_i->Name, strtab );
                  );
          printName ( symtab_i->Name, strtab );
-         fprintf ( stderr, 
+         fprintf ( stderr,
                    "'\n"
                    "    value 0x%x\n"
                    "   1+sec# %d\n"
                    "'\n"
                    "    value 0x%x\n"
                    "   1+sec# %d\n"
@@ -1462,7 +1492,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
                    (Int32)(symtab_i->SectionNumber),
                    (UInt32)symtab_i->Type,
                    (UInt32)symtab_i->StorageClass,
                    (Int32)(symtab_i->SectionNumber),
                    (UInt32)symtab_i->Type,
                    (UInt32)symtab_i->StorageClass,
-                   (UInt32)symtab_i->NumberOfAuxSymbols 
+                   (UInt32)symtab_i->NumberOfAuxSymbols
                  );
 #        endif
       }
                  );
 #        endif
       }
@@ -1471,7 +1501,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
       i++;
    }
 
       i++;
    }
 
-   return 1;   
+   return 1;
 }
 
 
 }
 
 
@@ -1497,12 +1527,12 @@ ocResolve_PEi386 ( ObjectCode* oc )
 
    hdr = (COFF_header*)(oc->image);
    sectab = (COFF_section*) (
 
    hdr = (COFF_header*)(oc->image);
    sectab = (COFF_section*) (
-               ((UChar*)(oc->image)) 
+               ((UChar*)(oc->image))
                + sizeof_COFF_header + hdr->SizeOfOptionalHeader
             );
    symtab = (COFF_symbol*) (
                ((UChar*)(oc->image))
                + sizeof_COFF_header + hdr->SizeOfOptionalHeader
             );
    symtab = (COFF_symbol*) (
                ((UChar*)(oc->image))
-               + hdr->PointerToSymbolTable 
+               + hdr->PointerToSymbolTable
             );
    strtab = ((UChar*)(oc->image))
             + hdr->PointerToSymbolTable
             );
    strtab = ((UChar*)(oc->image))
             + hdr->PointerToSymbolTable
@@ -1526,9 +1556,8 @@ ocResolve_PEi386 ( ObjectCode* oc )
       if ( sectab_i->Characteristics & MYIMAGE_SCN_LNK_NRELOC_OVFL ) {
        /* If the relocation field (a short) has overflowed, the
         * real count can be found in the first reloc entry.
       if ( sectab_i->Characteristics & MYIMAGE_SCN_LNK_NRELOC_OVFL ) {
        /* If the relocation field (a short) has overflowed, the
         * real count can be found in the first reloc entry.
-        * The PE spec (Feb 99 version) doesn't really cover this,
-        * but as always header files provide the final word on
-        * details like this (cf. WinNT.h).
+         *
+        * See Section 4.1 (last para) of the PE spec (rev6.0).
         */
         COFF_reloc* rel = (COFF_reloc*)
                            myindex ( sizeof_COFF_reloc, reltab, 0 );
         */
         COFF_reloc* rel = (COFF_reloc*)
                            myindex ( sizeof_COFF_reloc, reltab, 0 );
@@ -1543,14 +1572,14 @@ ocResolve_PEi386 ( ObjectCode* oc )
 
       for (; j < noRelocs; j++) {
          COFF_symbol* sym;
 
       for (; j < noRelocs; j++) {
          COFF_symbol* sym;
-         COFF_reloc* reltab_j 
+         COFF_reloc* reltab_j
             = (COFF_reloc*)
               myindex ( sizeof_COFF_reloc, reltab, j );
 
          /* the location to patch */
          pP = (UInt32*)(
             = (COFF_reloc*)
               myindex ( sizeof_COFF_reloc, reltab, j );
 
          /* the location to patch */
          pP = (UInt32*)(
-                 ((UChar*)(oc->image)) 
-                 + (sectab_i->PointerToRawData 
+                 ((UChar*)(oc->image))
+                 + (sectab_i->PointerToRawData
                     + reltab_j->VirtualAddress
                     - sectab_i->VirtualAddress )
               );
                     + reltab_j->VirtualAddress
                     - sectab_i->VirtualAddress )
               );
@@ -1558,20 +1587,20 @@ ocResolve_PEi386 ( ObjectCode* oc )
          A = *pP;
          /* the symbol to connect to */
          sym = (COFF_symbol*)
          A = *pP;
          /* the symbol to connect to */
          sym = (COFF_symbol*)
-               myindex ( sizeof_COFF_symbol, 
+               myindex ( sizeof_COFF_symbol,
                          symtab, reltab_j->SymbolTableIndex );
          IF_DEBUG(linker,
                          symtab, reltab_j->SymbolTableIndex );
          IF_DEBUG(linker,
-                  fprintf ( stderr, 
+                  fprintf ( stderr,
                             "reloc sec %2d num %3d:  type 0x%-4x   "
                             "vaddr 0x%-8x   name `",
                             i, j,
                             "reloc sec %2d num %3d:  type 0x%-4x   "
                             "vaddr 0x%-8x   name `",
                             i, j,
-                            (UInt32)reltab_j->Type, 
+                            (UInt32)reltab_j->Type,
                             reltab_j->VirtualAddress );
                             printName ( sym->Name, strtab );
                             fprintf ( stderr, "'\n" ));
 
          if (sym->StorageClass == MYIMAGE_SYM_CLASS_STATIC) {
                             reltab_j->VirtualAddress );
                             printName ( sym->Name, strtab );
                             fprintf ( stderr, "'\n" ));
 
          if (sym->StorageClass == MYIMAGE_SYM_CLASS_STATIC) {
-            COFF_section* section_sym 
+            COFF_section* section_sym
                = findPEi386SectionCalled ( oc, sym->Name );
             if (!section_sym) {
                belch("%s: can't find section `%s'", oc->fileName, sym->Name);
                = findPEi386SectionCalled ( oc, sym->Name );
             if (!section_sym) {
                belch("%s: can't find section `%s'", oc->fileName, sym->Name);
@@ -1597,8 +1626,8 @@ ocResolve_PEi386 ( ObjectCode* oc )
          }
          checkProddableBlock(oc, pP);
          switch (reltab_j->Type) {
          }
          checkProddableBlock(oc, pP);
          switch (reltab_j->Type) {
-            case MYIMAGE_REL_I386_DIR32: 
-               *pP = A + S; 
+            case MYIMAGE_REL_I386_DIR32:
+               *pP = A + S;
                break;
             case MYIMAGE_REL_I386_REL32:
                /* Tricky.  We have to insert a displacement at
                break;
             case MYIMAGE_REL_I386_REL32:
                /* Tricky.  We have to insert a displacement at
@@ -1615,15 +1644,15 @@ ocResolve_PEi386 ( ObjectCode* oc )
                ASSERT(A==0);
                *pP = S - ((UInt32)pP) - 4;
                break;
                ASSERT(A==0);
                *pP = S - ((UInt32)pP) - 4;
                break;
-            default: 
-               belch("%s: unhandled PEi386 relocation type %d", 
+            default:
+               belch("%s: unhandled PEi386 relocation type %d",
                     oc->fileName, reltab_j->Type);
                return 0;
          }
 
       }
    }
                     oc->fileName, reltab_j->Type);
                return 0;
          }
 
       }
    }
-   
+
    IF_DEBUG(linker, belch("completed %s", oc->fileName));
    return 1;
 }
    IF_DEBUG(linker, belch("completed %s", oc->fileName));
    return 1;
 }
@@ -1667,7 +1696,7 @@ findElfSection ( void* objImage, Elf32_Word sh_type )
           && i != ehdr->e_shstrndx
          /* Ignore string tables named .stabstr, as they contain
              debugging info. */
           && i != ehdr->e_shstrndx
          /* Ignore string tables named .stabstr, as they contain
              debugging info. */
-          && 0 != strncmp(".stabstr", sh_strtab + shdr[i].sh_name, 8)
+          && 0 != memcmp(".stabstr", sh_strtab + shdr[i].sh_name, 8)
          ) {
          ptr = ehdrC + shdr[i].sh_offset;
          break;
          ) {
          ptr = ehdrC + shdr[i].sh_offset;
          break;
@@ -1725,13 +1754,13 @@ ocVerifyImage_ELF ( ObjectCode* oc )
    switch (ehdr->e_machine) {
       case EM_386:   IF_DEBUG(linker,belch( "x86" )); break;
       case EM_SPARC: IF_DEBUG(linker,belch( "sparc" )); break;
    switch (ehdr->e_machine) {
       case EM_386:   IF_DEBUG(linker,belch( "x86" )); break;
       case EM_SPARC: IF_DEBUG(linker,belch( "sparc" )); break;
-      default:       IF_DEBUG(linker,belch( "unknown" )); 
+      default:       IF_DEBUG(linker,belch( "unknown" ));
                      belch("%s: unknown architecture", oc->fileName);
                      return 0;
    }
 
    IF_DEBUG(linker,belch(
                      belch("%s: unknown architecture", oc->fileName);
                      return 0;
    }
 
    IF_DEBUG(linker,belch(
-             "\nSection header table: start %d, n_entries %d, ent_size %d", 
+             "\nSection header table: start %d, n_entries %d, ent_size %d",
              ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize  ));
 
    ASSERT (ehdr->e_shentsize == sizeof(Elf32_Shdr));
              ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize  ));
 
    ASSERT (ehdr->e_shentsize == sizeof(Elf32_Shdr));
@@ -1742,7 +1771,7 @@ ocVerifyImage_ELF ( ObjectCode* oc )
       belch("%s: no section header string table", oc->fileName);
       return 0;
    } else {
       belch("%s: no section header string table", oc->fileName);
       return 0;
    } else {
-      IF_DEBUG(linker,belch( "Section header string table is section %d", 
+      IF_DEBUG(linker,belch( "Section header string table is section %d",
                           ehdr->e_shstrndx));
       sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
    }
                           ehdr->e_shstrndx));
       sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset;
    }
@@ -1753,7 +1782,7 @@ ocVerifyImage_ELF ( ObjectCode* oc )
       IF_DEBUG(linker,fprintf(stderr, "size=%4d  ", (int)shdr[i].sh_size ));
       IF_DEBUG(linker,fprintf(stderr, "offs=%4d  ", (int)shdr[i].sh_offset ));
       IF_DEBUG(linker,fprintf(stderr, "  (%p .. %p)  ",
       IF_DEBUG(linker,fprintf(stderr, "size=%4d  ", (int)shdr[i].sh_size ));
       IF_DEBUG(linker,fprintf(stderr, "offs=%4d  ", (int)shdr[i].sh_offset ));
       IF_DEBUG(linker,fprintf(stderr, "  (%p .. %p)  ",
-               ehdrC + shdr[i].sh_offset, 
+               ehdrC + shdr[i].sh_offset,
                      ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1));
 
       if (shdr[i].sh_type == SHT_REL) {
                      ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1));
 
       if (shdr[i].sh_type == SHT_REL) {
@@ -1777,20 +1806,20 @@ ocVerifyImage_ELF ( ObjectCode* oc )
           && i != ehdr->e_shstrndx
          /* Ignore string tables named .stabstr, as they contain
              debugging info. */
           && i != ehdr->e_shstrndx
          /* Ignore string tables named .stabstr, as they contain
              debugging info. */
-          && 0 != strncmp(".stabstr", sh_strtab + shdr[i].sh_name, 8)
+          && 0 != memcmp(".stabstr", sh_strtab + shdr[i].sh_name, 8)
          ) {
          IF_DEBUG(linker,belch("   section %d is a normal string table", i ));
          strtab = ehdrC + shdr[i].sh_offset;
          nstrtab++;
       }
          ) {
          IF_DEBUG(linker,belch("   section %d is a normal string table", i ));
          strtab = ehdrC + shdr[i].sh_offset;
          nstrtab++;
       }
-   }  
+   }
    if (nstrtab != 1) {
       belch("%s: no string tables, or too many", oc->fileName);
       return 0;
    }
 
    nsymtabs = 0;
    if (nstrtab != 1) {
       belch("%s: no string tables, or too many", oc->fileName);
       return 0;
    }
 
    nsymtabs = 0;
-   IF_DEBUG(linker,belch( "\nSymbol tables" )); 
+   IF_DEBUG(linker,belch( "\nSymbol tables" ));
    for (i = 0; i < ehdr->e_shnum; i++) {
       if (shdr[i].sh_type != SHT_SYMTAB) continue;
       IF_DEBUG(linker,belch( "section %d is a symbol table", i ));
    for (i = 0; i < ehdr->e_shnum; i++) {
       if (shdr[i].sh_type != SHT_SYMTAB) continue;
       IF_DEBUG(linker,belch( "section %d is a symbol table", i ));
@@ -1807,7 +1836,7 @@ ocVerifyImage_ELF ( ObjectCode* oc )
       }
       for (j = 0; j < nent; j++) {
          IF_DEBUG(linker,fprintf(stderr, "   %2d  ", j ));
       }
       for (j = 0; j < nent; j++) {
          IF_DEBUG(linker,fprintf(stderr, "   %2d  ", j ));
-         IF_DEBUG(linker,fprintf(stderr, "  sec=%-5d  size=%-3d  val=%5p  ", 
+         IF_DEBUG(linker,fprintf(stderr, "  sec=%-5d  size=%-3d  val=%5p  ",
                              (int)stab[j].st_shndx,
                              (int)stab[j].st_size,
                              (char*)stab[j].st_value ));
                              (int)stab[j].st_shndx,
                              (int)stab[j].st_size,
                              (char*)stab[j].st_value ));
@@ -1872,25 +1901,25 @@ ocGetNames_ELF ( ObjectCode* oc )
       SectionKind kind   = SECTIONKIND_OTHER;
       int         is_bss = FALSE;
 
       SectionKind kind   = SECTIONKIND_OTHER;
       int         is_bss = FALSE;
 
-      if (hdr.sh_type == SHT_PROGBITS 
+      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
           && (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 
+      if (hdr.sh_type == SHT_PROGBITS
           && (hdr.sh_flags & SHF_ALLOC) && (hdr.sh_flags & SHF_WRITE)) {
          /* .data-style section */
          kind = SECTIONKIND_RWDATA;
       }
       else
           && (hdr.sh_flags & SHF_ALLOC) && (hdr.sh_flags & SHF_WRITE)) {
          /* .data-style section */
          kind = SECTIONKIND_RWDATA;
       }
       else
-      if (hdr.sh_type == SHT_PROGBITS 
+      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
           && (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 
+      if (hdr.sh_type == SHT_NOBITS
           && (hdr.sh_flags & SHF_ALLOC) && (hdr.sh_flags & SHF_WRITE)) {
          /* .bss-style section */
          kind = SECTIONKIND_RWDATA;
           && (hdr.sh_flags & SHF_ALLOC) && (hdr.sh_flags & SHF_WRITE)) {
          /* .bss-style section */
          kind = SECTIONKIND_RWDATA;
@@ -1899,22 +1928,23 @@ ocGetNames_ELF ( ObjectCode* oc )
 
       if (is_bss && shdr[i].sh_size > 0) {
          /* This is a non-empty .bss section.  Allocate zeroed space for
 
       if (is_bss && shdr[i].sh_size > 0) {
          /* This is a non-empty .bss section.  Allocate zeroed space for
-            it, and set its .sh_offset field such that 
+            it, and set its .sh_offset field such that
             ehdrC + .sh_offset == addr_of_zeroed_space.  */
             ehdrC + .sh_offset == addr_of_zeroed_space.  */
-         char* zspace = stgCallocBytes(1, shdr[i].sh_size, 
+         char* zspace = stgCallocBytes(1, shdr[i].sh_size,
                                        "ocGetNames_ELF(BSS)");
          shdr[i].sh_offset = ((char*)zspace) - ((char*)ehdrC);
                                        "ocGetNames_ELF(BSS)");
          shdr[i].sh_offset = ((char*)zspace) - ((char*)ehdrC);
-        /*         
-         fprintf(stderr, "BSS section at 0x%x, size %d\n", 
+        /*
+         fprintf(stderr, "BSS section at 0x%x, size %d\n",
                          zspace, shdr[i].sh_size);
         */
       }
 
       /* fill in the section info */
                          zspace, shdr[i].sh_size);
         */
       }
 
       /* fill in the section info */
-      addSection(oc, kind, ehdrC + shdr[i].sh_offset, 
-                     ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1);
-      if (kind != SECTIONKIND_OTHER && shdr[i].sh_size > 0)
+      if (kind != SECTIONKIND_OTHER && shdr[i].sh_size > 0) {
          addProddableBlock(oc, ehdrC + shdr[i].sh_offset, shdr[i].sh_size);
          addProddableBlock(oc, ehdrC + shdr[i].sh_offset, shdr[i].sh_size);
+         addSection(oc, kind, ehdrC + shdr[i].sh_offset,
+                        ehdrC + shdr[i].sh_offset + shdr[i].sh_size - 1);
+      }
 
       if (shdr[i].sh_type != SHT_SYMTAB) continue;
 
 
       if (shdr[i].sh_type != SHT_SYMTAB) continue;
 
@@ -1923,7 +1953,7 @@ ocGetNames_ELF ( ObjectCode* oc )
       nent = shdr[i].sh_size / sizeof(Elf32_Sym);
 
       oc->n_symbols = nent;
       nent = shdr[i].sh_size / sizeof(Elf32_Sym);
 
       oc->n_symbols = nent;
-      oc->symbols = stgMallocBytes(oc->n_symbols * sizeof(char*), 
+      oc->symbols = stgMallocBytes(oc->n_symbols * sizeof(char*),
                                    "ocGetNames_ELF(oc->symbols)");
 
       for (j = 0; j < nent; j++) {
                                    "ocGetNames_ELF(oc->symbols)");
 
       for (j = 0; j < nent; j++) {
@@ -1940,7 +1970,7 @@ ocGetNames_ELF ( ObjectCode* oc )
             isLocal = FALSE;
             ad = stgCallocBytes(1, stab[j].st_size, "ocGetNames_ELF(COMMON)");
            /*
             isLocal = FALSE;
             ad = stgCallocBytes(1, stab[j].st_size, "ocGetNames_ELF(COMMON)");
            /*
-            fprintf(stderr, "COMMON symbol, size %d name %s\n", 
+            fprintf(stderr, "COMMON symbol, size %d name %s\n",
                             stab[j].st_size, nm);
            */
            /* Pointless to do addProddableBlock() for this area,
                             stab[j].st_size, nm);
            */
            /* Pointless to do addProddableBlock() for this area,
@@ -1958,14 +1988,14 @@ ocGetNames_ELF ( ObjectCode* oc )
              /* and it's a not a section or string table or anything silly */
               ( ELF32_ST_TYPE(stab[j].st_info)==STT_FUNC ||
                 ELF32_ST_TYPE(stab[j].st_info)==STT_OBJECT ||
              /* and it's a not a section or string table or anything silly */
               ( ELF32_ST_TYPE(stab[j].st_info)==STT_FUNC ||
                 ELF32_ST_TYPE(stab[j].st_info)==STT_OBJECT ||
-                ELF32_ST_TYPE(stab[j].st_info)==STT_NOTYPE 
+                ELF32_ST_TYPE(stab[j].st_info)==STT_NOTYPE
               )
             ) {
            /* Section 0 is the undefined section, hence > and not >=. */
             ASSERT(secno > 0 && secno < ehdr->e_shnum);
               )
             ) {
            /* Section 0 is the undefined section, hence > and not >=. */
             ASSERT(secno > 0 && secno < ehdr->e_shnum);
-           /*            
+           /*
             if (shdr[secno].sh_type == SHT_NOBITS) {
             if (shdr[secno].sh_type == SHT_NOBITS) {
-               fprintf(stderr, "   BSS symbol, size %d off %d name %s\n", 
+               fprintf(stderr, "   BSS symbol, size %d off %d name %s\n",
                                stab[j].st_size, stab[j].st_value, nm);
             }
             */
                                stab[j].st_size, stab[j].st_value, nm);
             }
             */
@@ -1992,13 +2022,13 @@ ocGetNames_ELF ( ObjectCode* oc )
             }
          } else {
             /* Skip. */
             }
          } else {
             /* Skip. */
-            IF_DEBUG(linker,belch( "skipping `%s'", 
+            IF_DEBUG(linker,belch( "skipping `%s'",
                                    strtab + stab[j].st_name ));
             /*
                                    strtab + stab[j].st_name ));
             /*
-            fprintf(stderr, 
+            fprintf(stderr,
                     "skipping   bind = %d,  type = %d,  shndx = %d   `%s'\n",
                     "skipping   bind = %d,  type = %d,  shndx = %d   `%s'\n",
-                    (int)ELF32_ST_BIND(stab[j].st_info), 
-                    (int)ELF32_ST_TYPE(stab[j].st_info), 
+                    (int)ELF32_ST_BIND(stab[j].st_info),
+                    (int)ELF32_ST_TYPE(stab[j].st_info),
                     (int)stab[j].st_shndx,
                     strtab + stab[j].st_name
                    );
                     (int)stab[j].st_shndx,
                     strtab + stab[j].st_name
                    );
@@ -2017,7 +2047,7 @@ ocGetNames_ELF ( ObjectCode* oc )
    relocations appear to be of this form. */
 static int
 do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC,
    relocations appear to be of this form. */
 static int
 do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC,
-                           Elf32_Shdr* shdr, int shnum, 
+                           Elf32_Shdr* shdr, int shnum,
                            Elf32_Sym*  stab, char* strtab )
 {
    int j;
                            Elf32_Sym*  stab, char* strtab )
 {
    int j;
@@ -2040,7 +2070,7 @@ do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC,
       Elf32_Addr  A  = *pP;
       Elf32_Addr  S;
 
       Elf32_Addr  A  = *pP;
       Elf32_Addr  S;
 
-      IF_DEBUG(linker,belch( "Rel entry %3d is raw(%6p %6p)", 
+      IF_DEBUG(linker,belch( "Rel entry %3d is raw(%6p %6p)",
                              j, (void*)offset, (void*)info ));
       if (!info) {
          IF_DEBUG(linker,belch( " ZERO" ));
                              j, (void*)offset, (void*)info ));
       if (!info) {
          IF_DEBUG(linker,belch( " ZERO" ));
@@ -2068,14 +2098,14 @@ do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC,
          IF_DEBUG(linker,belch( "`%s' resolves to %p", symbol, (void*)S ));
       }
       IF_DEBUG(linker,belch( "Reloc: P = %p   S = %p   A = %p",
          IF_DEBUG(linker,belch( "`%s' resolves to %p", symbol, (void*)S ));
       }
       IF_DEBUG(linker,belch( "Reloc: P = %p   S = %p   A = %p",
-                            (void*)P, (void*)S, (void*)A )); 
+                            (void*)P, (void*)S, (void*)A ));
       checkProddableBlock ( oc, pP );
       switch (ELF32_R_TYPE(info)) {
 #        ifdef i386_TARGET_ARCH
          case R_386_32:   *pP = S + A;     break;
          case R_386_PC32: *pP = S + A - P; break;
 #        endif
       checkProddableBlock ( oc, pP );
       switch (ELF32_R_TYPE(info)) {
 #        ifdef i386_TARGET_ARCH
          case R_386_32:   *pP = S + A;     break;
          case R_386_PC32: *pP = S + A - P; break;
 #        endif
-         default: 
+         default:
             belch("%s: unhandled ELF relocation(Rel) type %d\n",
                  oc->fileName, ELF32_R_TYPE(info));
             return 0;
             belch("%s: unhandled ELF relocation(Rel) type %d\n",
                  oc->fileName, ELF32_R_TYPE(info));
             return 0;
@@ -2090,7 +2120,7 @@ do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC,
    sparc-solaris relocations appear to be of this form. */
 static int
 do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC,
    sparc-solaris relocations appear to be of this form. */
 static int
 do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC,
-                            Elf32_Shdr* shdr, int shnum, 
+                            Elf32_Shdr* shdr, int shnum,
                             Elf32_Sym*  stab, char* strtab )
 {
    int j;
                             Elf32_Sym*  stab, char* strtab )
 {
    int j;
@@ -2107,9 +2137,11 @@ do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC,
    for (j = 0; j < nent; j++) {
       Elf32_Addr  offset = rtab[j].r_offset;
       Elf32_Word  info   = rtab[j].r_info;
    for (j = 0; j < nent; j++) {
       Elf32_Addr  offset = rtab[j].r_offset;
       Elf32_Word  info   = rtab[j].r_info;
+#     if defined(sparc_TARGET_ARCH) || defined(DEBUG)
       Elf32_Sword addend = rtab[j].r_addend;
       Elf32_Sword addend = rtab[j].r_addend;
+      Elf32_Addr  A  = addend;
+#     endif
       Elf32_Addr  P  = ((Elf32_Addr)targ) + offset;
       Elf32_Addr  P  = ((Elf32_Addr)targ) + offset;
-      Elf32_Addr  A  = addend; /* Do not delete this; it is used on sparc. */
       Elf32_Addr  S;
 #     if defined(sparc_TARGET_ARCH)
       /* This #ifdef only serves to avoid unused-var warnings. */
       Elf32_Addr  S;
 #     if defined(sparc_TARGET_ARCH)
       /* This #ifdef only serves to avoid unused-var warnings. */
@@ -2117,8 +2149,8 @@ do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC,
       Elf32_Word  w1, w2;
 #     endif
 
       Elf32_Word  w1, w2;
 #     endif
 
-      IF_DEBUG(linker,belch( "Rel entry %3d is raw(%6p %6p %6p)   ", 
-                             j, (void*)offset, (void*)info, 
+      IF_DEBUG(linker,belch( "Rel entry %3d is raw(%6p %6p %6p)   ",
+                             j, (void*)offset, (void*)info,
                                 (void*)addend ));
       if (!info) {
          IF_DEBUG(linker,belch( " ZERO" ));
                                 (void*)addend ));
       if (!info) {
          IF_DEBUG(linker,belch( " ZERO" ));
@@ -2142,7 +2174,7 @@ do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC,
          if (!S) {
           belch("%s: unknown symbol `%s'", oc->fileName, symbol);
           return 0;
          if (!S) {
           belch("%s: unknown symbol `%s'", oc->fileName, symbol);
           return 0;
-          /* 
+          /*
           S = 0x11223344;
           fprintf ( stderr, "S %p A %p S+A %p S+A-P %p\n",S,A,S+A,S+A-P);
           */
           S = 0x11223344;
           fprintf ( stderr, "S %p A %p S+A %p S+A-P %p\n",S,A,S+A,S+A-P);
           */
@@ -2150,11 +2182,11 @@ do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC,
          IF_DEBUG(linker,belch( "`%s' resolves to %p", symbol, (void*)S ));
       }
       IF_DEBUG(linker,fprintf ( stderr, "Reloc: P = %p   S = %p   A = %p\n",
          IF_DEBUG(linker,belch( "`%s' resolves to %p", symbol, (void*)S ));
       }
       IF_DEBUG(linker,fprintf ( stderr, "Reloc: P = %p   S = %p   A = %p\n",
-                                        (void*)P, (void*)S, (void*)A )); 
+                                        (void*)P, (void*)S, (void*)A ));
       checkProddableBlock ( oc, (void*)P );
       switch (ELF32_R_TYPE(info)) {
 #        if defined(sparc_TARGET_ARCH)
       checkProddableBlock ( oc, (void*)P );
       switch (ELF32_R_TYPE(info)) {
 #        if defined(sparc_TARGET_ARCH)
-         case R_SPARC_WDISP30: 
+         case R_SPARC_WDISP30:
             w1 = *pP & 0xC0000000;
             w2 = (Elf32_Word)((S + A - P) >> 2);
             ASSERT((w2 & 0xC0000000) == 0);
             w1 = *pP & 0xC0000000;
             w2 = (Elf32_Word)((S + A - P) >> 2);
             ASSERT((w2 & 0xC0000000) == 0);
@@ -2176,14 +2208,14 @@ do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC,
             *pP = w1;
             break;
          /* According to the Sun documentation:
             *pP = w1;
             break;
          /* According to the Sun documentation:
-            R_SPARC_UA32 
+            R_SPARC_UA32
             This relocation type resembles R_SPARC_32, except it refers to an
             unaligned word. That is, the word to be relocated must be treated
             as four separate bytes with arbitrary alignment, not as a word
             aligned according to the architecture requirements.
 
             (JRS: which means that freeloading on the R_SPARC_32 case
             This relocation type resembles R_SPARC_32, except it refers to an
             unaligned word. That is, the word to be relocated must be treated
             as four separate bytes with arbitrary alignment, not as a word
             aligned according to the architecture requirements.
 
             (JRS: which means that freeloading on the R_SPARC_32 case
-            is probably wrong, but hey ...)  
+            is probably wrong, but hey ...)
          */
          case R_SPARC_UA32:
          case R_SPARC_32:
          */
          case R_SPARC_UA32:
          case R_SPARC_32:
@@ -2191,7 +2223,7 @@ do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC,
             *pP = w2;
             break;
 #        endif
             *pP = w2;
             break;
 #        endif
-         default: 
+         default:
             belch("%s: unhandled ELF relocation(RelA) type %d\n",
                  oc->fileName, ELF32_R_TYPE(info));
             return 0;
             belch("%s: unhandled ELF relocation(RelA) type %d\n",
                  oc->fileName, ELF32_R_TYPE(info));
             return 0;
@@ -2221,7 +2253,7 @@ ocResolve_ELF ( ObjectCode* oc )
 
    if (stab == NULL || strtab == NULL) {
       belch("%s: can't find string or symbol table", oc->fileName);
 
    if (stab == NULL || strtab == NULL) {
       belch("%s: can't find string or symbol table", oc->fileName);
-      return 0; 
+      return 0;
    }
 
    /* Process the relocation sections. */
    }
 
    /* Process the relocation sections. */
@@ -2231,17 +2263,17 @@ ocResolve_ELF ( ObjectCode* oc )
          relocation entries that, when done, make the stabs debugging
          info point at the right places.  We ain't interested in all
          dat jazz, mun. */
          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 == strncmp(".rel.stab", sh_strtab + shdr[shnum].sh_name, 9))
+      if (0 == memcmp(".rel.stab", sh_strtab + shdr[shnum].sh_name, 9))
          continue;
 
       if (shdr[shnum].sh_type == SHT_REL ) {
          continue;
 
       if (shdr[shnum].sh_type == SHT_REL ) {
-         ok = do_Elf32_Rel_relocations ( oc, ehdrC, shdr, 
+         ok = do_Elf32_Rel_relocations ( oc, ehdrC, shdr,
                                          shnum, stab, strtab );
          if (!ok) return ok;
       }
       else
       if (shdr[shnum].sh_type == SHT_RELA) {
                                          shnum, stab, strtab );
          if (!ok) return ok;
       }
       else
       if (shdr[shnum].sh_type == SHT_RELA) {
-         ok = do_Elf32_Rela_relocations ( oc, ehdrC, shdr, 
+         ok = do_Elf32_Rela_relocations ( oc, ehdrC, shdr,
                                           shnum, stab, strtab );
          if (!ok) return ok;
       }
                                           shnum, stab, strtab );
          if (!ok) return ok;
       }