[project @ 2001-08-21 15:22:09 by sewardj]
[ghc-hetmet.git] / ghc / rts / Linker.c
index 6589c2d..e4d2d07 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: Linker.c,v 1.39 2001/04/24 15:49:19 qrczak Exp $
+ * $Id: Linker.c,v 1.59 2001/08/21 15:22:09 sewardj Exp $
  *
  * (c) The GHC Team, 2000
  *
@@ -7,6 +7,7 @@
  *
  * ---------------------------------------------------------------------------*/
 
+#include "PosixSource.h"
 #include "Rts.h"
 #include "RtsFlags.h"
 #include "HsFFI.h"
@@ -32,6 +33,7 @@
 #  define OBJFORMAT_ELF
 #elif defined(cygwin32_TARGET_OS) || defined (mingw32_TARGET_OS)
 #  define OBJFORMAT_PEi386
+#  include <windows.h>
 #endif
 
 /* Hash table mapping symbol names to Symbol */
@@ -70,13 +72,94 @@ typedef struct _RtsSymbolVal {
 #endif
 
 #if !defined (mingw32_TARGET_OS)
+
 #define RTS_POSIX_ONLY_SYMBOLS                  \
       SymX(stg_sig_install)                    \
       Sym(nocldstop)
+#define RTS_MINGW_ONLY_SYMBOLS /**/
+
 #else
+
 #define RTS_POSIX_ONLY_SYMBOLS
+
+/* These are statically linked from the mingw libraries into the ghc
+   executable, so we have to employ this hack. */
+#define RTS_MINGW_ONLY_SYMBOLS                  \
+      SymX(memset)                              \
+      SymX(inet_ntoa)                           \
+      SymX(inet_addr)                           \
+      SymX(htonl)                               \
+      SymX(recvfrom)                            \
+      SymX(listen)                              \
+      SymX(bind)                                \
+      SymX(shutdown)                            \
+      SymX(connect)                             \
+      SymX(htons)                               \
+      SymX(ntohs)                               \
+      SymX(getservbyname)                       \
+      SymX(getservbyport)                       \
+      SymX(getprotobynumber)                    \
+      SymX(getprotobyname)                      \
+      SymX(gethostbyname)                       \
+      SymX(gethostbyaddr)                       \
+      SymX(gethostname)                         \
+      SymX(strcpy)                              \
+      SymX(strncpy)                             \
+      SymX(abort)                               \
+      Sym(_alloca)                              \
+      Sym(isxdigit)                             \
+      Sym(isupper)                              \
+      Sym(ispunct)                              \
+      Sym(islower)                              \
+      Sym(isspace)                              \
+      Sym(isprint)                              \
+      Sym(isdigit)                              \
+      Sym(iscntrl)                              \
+      Sym(isalpha)                              \
+      Sym(isalnum)                              \
+      SymX(strcmp)                              \
+      SymX(memmove)                             \
+      SymX(realloc)                             \
+      SymX(malloc)                              \
+      SymX(pow)                                 \
+      SymX(tanh)                                \
+      SymX(cosh)                                \
+      SymX(sinh)                                \
+      SymX(atan)                                \
+      SymX(acos)                                \
+      SymX(asin)                                \
+      SymX(tan)                                 \
+      SymX(cos)                                 \
+      SymX(sin)                                 \
+      SymX(exp)                                 \
+      SymX(log)                                 \
+      SymX(sqrt)                                \
+      SymX(memcpy)                              \
+      Sym(mktime)                               \
+      Sym(_imp___timezone)                      \
+      Sym(_imp___tzname)                        \
+      Sym(localtime)                            \
+      Sym(gmtime)                               \
+      SymX(getenv)                              \
+      SymX(free)                                \
+      SymX(rename)                              \
+      Sym(opendir)                              \
+      Sym(readdir)                              \
+      Sym(closedir)                             \
+      SymX(GetCurrentProcess)                   \
+      SymX(GetProcessTimes)                     \
+      SymX(CloseHandle)                         \
+      SymX(GetExitCodeProcess)                  \
+      SymX(WaitForSingleObject)                 \
+      SymX(CreateProcessA)                      \
+      Sym(__divdi3)                             \
+      Sym(__udivdi3)                            \
+      Sym(__moddi3)                             \
+      Sym(__umoddi3)                            \
+      SymX(_errno)
 #endif
 
+
 #define RTS_SYMBOLS                            \
       SymX(MainRegTable)                       \
       Sym(stg_gc_enter_1)                      \
@@ -86,6 +169,7 @@ typedef struct _RtsSymbolVal {
       Sym(stg_gc_f1)                           \
       Sym(stg_gc_ut_1_0)                       \
       Sym(stg_gc_ut_0_1)                       \
+      Sym(stg_gc_unpt_r1)                      \
       Sym(stg_gc_unbx_r1)                      \
       Sym(stg_chk_0)                           \
       Sym(stg_chk_1)                           \
@@ -154,6 +238,7 @@ typedef struct _RtsSymbolVal {
       SymX(newArrayzh_fast)                    \
       SymX(unsafeThawArrayzh_fast)             \
       SymX(newByteArrayzh_fast)                        \
+      SymX(newPinnedByteArrayzh_fast)          \
       SymX(newMutVarzh_fast)                   \
       SymX(quotRemIntegerzh_fast)              \
       SymX(quotIntegerzh_fast)                 \
@@ -189,6 +274,8 @@ typedef struct _RtsSymbolVal {
       SymX(__gmpz_get_ui)                      \
       SymX(prog_argv)                          \
       SymX(prog_argc)                          \
+      SymX(getProgArgv)                                \
+      SymX(setProgArgv)                                \
       SymX(resetNonBlockingFd)                 \
       SymX(performGC)                          \
       SymX(getStablePtr)                       \
@@ -252,41 +339,6 @@ typedef struct _RtsSymbolVal {
 #define RTS_LONG_LONG_SYMS /* nothing */
 #else
 #define RTS_LONG_LONG_SYMS                     \
-      SymX(stg_gtWord64)                       \
-      SymX(stg_geWord64)                       \
-      SymX(stg_eqWord64)                       \
-      SymX(stg_neWord64)                       \
-      SymX(stg_ltWord64)                       \
-      SymX(stg_leWord64)                       \
-      SymX(stg_gtInt64)                                \
-      SymX(stg_geInt64)                                \
-      SymX(stg_eqInt64)                                \
-      SymX(stg_neInt64)                                \
-      SymX(stg_ltInt64)                                \
-      SymX(stg_leInt64)                                \
-      SymX(stg_remWord64)                      \
-      SymX(stg_quotWord64)                     \
-      SymX(stg_remInt64)                       \
-      SymX(stg_quotInt64)                      \
-      SymX(stg_negateInt64)                    \
-      SymX(stg_plusInt64)                      \
-      SymX(stg_minusInt64)                     \
-      SymX(stg_timesInt64)                     \
-      SymX(stg_and64)                          \
-      SymX(stg_or64)                           \
-      SymX(stg_xor64)                          \
-      SymX(stg_not64)                          \
-      SymX(stg_shiftL64)                       \
-      SymX(stg_shiftRL64)                      \
-      SymX(stg_iShiftL64)                      \
-      SymX(stg_iShiftRL64)                     \
-      SymX(stg_iShiftRA64)                     \
-      SymX(stg_intToInt64)                     \
-      SymX(stg_int64ToInt)                     \
-      SymX(stg_int64ToWord64)                  \
-      SymX(stg_wordToWord64)                   \
-      SymX(stg_word64ToWord)                   \
-      SymX(stg_word64ToInt64)                  \
       SymX(int64ToIntegerzh_fast)              \
       SymX(word64ToIntegerzh_fast)
 #endif /* SUPPORT_LONG_LONGS */
@@ -295,7 +347,9 @@ typedef struct _RtsSymbolVal {
 #define Sym(vvv)  extern void (vvv);
 #define SymX(vvv) /**/
 RTS_SYMBOLS
+RTS_LONG_LONG_SYMS
 RTS_POSIX_ONLY_SYMBOLS
+RTS_MINGW_ONLY_SYMBOLS
 #undef Sym
 #undef SymX
 
@@ -313,6 +367,7 @@ static RtsSymbolVal rtsSyms[] = {
       RTS_SYMBOLS
       RTS_LONG_LONG_SYMS
       RTS_POSIX_ONLY_SYMBOLS
+      RTS_MINGW_ONLY_SYMBOLS
       { 0, 0 } /* sentinel */
 };
 
@@ -344,18 +399,45 @@ initLinker( void )
  * do RTLD_GLOBAL-style add, so no further messing around needs to
  * happen in order that symbols in the loaded .so are findable --
  * lookupSymbol() will subsequently see them by dlsym on the program's
- * dl-handle.  Returns 0 if fail, 1 if success.
+ * 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 
+ * linked list.  When looking for a symbol, try all handles in the
+ * list.
  */
+
+#if defined(OBJFORMAT_PEi386)
+/* A record for storing handles into DLLs. */
+
+typedef
+   struct _OpenedDLL {
+      char*              name;
+      struct _OpenedDLL* next;
+      HINSTANCE instance;
+   } 
+   OpenedDLL;
+
+/* A list thereof. */
+static OpenedDLL* opened_dlls = NULL;
+#endif
+
+
+
 char*
-addDLL ( char* dll_name )
+addDLL ( char* path, char* dll_name )
 {
 #  if defined(OBJFORMAT_ELF)
    void *hdl;
    char *buf;
    char *errmsg;
 
-   buf = stgMallocBytes(strlen(dll_name) + 10, "addDll");
-   sprintf(buf, "lib%s.so", dll_name);
+   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);
    if (hdl == NULL) {
@@ -366,10 +448,41 @@ addDLL ( char* dll_name )
    } else {
       return NULL;
    }
-   ASSERT(0); /*NOTREACHED*/
+   /*NOTREACHED*/
+
 #  elif defined(OBJFORMAT_PEi386)
-   barf("addDLL: not implemented on PEi386 yet");
-   return 0;
+
+   /* Add this DLL to the list of DLLs in which to search for symbols.
+      The path argument is ignored. */
+   char*      buf;
+   OpenedDLL* o_dll;
+   HINSTANCE  instance;
+
+   /* fprintf(stderr, "\naddDLL; path=`%s', dll_name = `%s'\n", path, dll_name); */
+
+   /* See if we've already got it, and ignore if so. */
+   for (o_dll = opened_dlls; o_dll != NULL; o_dll = o_dll->next) {
+      if (0 == strcmp(o_dll->name, dll_name))
+         return NULL;
+   }
+
+   buf = stgMallocBytes(strlen(dll_name) + 10, "addDLL");
+   sprintf(buf, "%s.DLL", dll_name);
+   instance = LoadLibrary(buf);
+   free(buf);
+   if (instance == NULL) {
+     /* LoadLibrary failed; return a ptr to the error msg. */
+     return "addDLL: unknown error";
+   }
+
+   o_dll = stgMallocBytes( sizeof(OpenedDLL), "addDLL" );
+   o_dll->name     = stgMallocBytes(1+strlen(dll_name), "addDLL");
+   strcpy(o_dll->name, dll_name);
+   o_dll->instance = instance;
+   o_dll->next     = opened_dlls;
+   opened_dlls     = o_dll;
+
+   return NULL;
 #  else
    barf("addDLL: not implemented on this platform");
 #  endif
@@ -389,6 +502,24 @@ lookupSymbol( char *lbl )
 #       if defined(OBJFORMAT_ELF)
        return dlsym(dl_prog_handle, lbl);
 #       elif defined(OBJFORMAT_PEi386)
+        OpenedDLL* o_dll;
+        void* sym;
+        for (o_dll = opened_dlls; o_dll != NULL; o_dll = o_dll->next) {
+           /* fprintf(stderr, "look in %s for %s\n", o_dll->name, lbl); */
+          if (lbl[0] == '_') {
+            /* HACK: if the name has an initial underscore, try stripping
+               it off & look that up first. I've yet to verify whether there's
+               a Rule that governs whether an initial '_' *should always* be
+               stripped off when mapping from import lib name to the DLL name.
+            */
+            sym = GetProcAddress(o_dll->instance, (lbl+1));
+            if (sym != NULL) return sym;
+          }
+           sym = GetProcAddress(o_dll->instance, lbl);
+           if (sym != NULL) return sym;
+        }
+        return NULL;
+#       else
         ASSERT(2+2 == 5);
         return NULL;
 #       endif
@@ -425,6 +556,7 @@ loadObj( char *path )
    int r, n;
    FILE *f;
 
+   /* fprintf(stderr, "loadObj %s\n", path ); */
 #  ifdef DEBUG
    /* assert that we haven't already loaded this object */
    { 
@@ -658,26 +790,29 @@ typedef
 
 
 /* From PE spec doc, section 3.3.2 */
-#define IMAGE_FILE_RELOCS_STRIPPED     0x0001
-#define IMAGE_FILE_EXECUTABLE_IMAGE    0x0002
-#define IMAGE_FILE_DLL                 0x2000
-#define IMAGE_FILE_SYSTEM              0x1000
-#define IMAGE_FILE_BYTES_REVERSED_HI   0x8000
-#define IMAGE_FILE_BYTES_REVERSED_LO   0x0080
-#define IMAGE_FILE_32BIT_MACHINE       0x0100
+/* Note use of MYIMAGE_* since IMAGE_* are already defined in
+   windows.h -- for the same purpose, but I want to know what I'm
+   getting, here. */
+#define MYIMAGE_FILE_RELOCS_STRIPPED     0x0001
+#define MYIMAGE_FILE_EXECUTABLE_IMAGE    0x0002
+#define MYIMAGE_FILE_DLL                 0x2000
+#define MYIMAGE_FILE_SYSTEM              0x1000
+#define MYIMAGE_FILE_BYTES_REVERSED_HI   0x8000
+#define MYIMAGE_FILE_BYTES_REVERSED_LO   0x0080
+#define MYIMAGE_FILE_32BIT_MACHINE       0x0100
 
 /* From PE spec doc, section 5.4.2 and 5.4.4 */
-#define IMAGE_SYM_CLASS_EXTERNAL       2
-#define IMAGE_SYM_CLASS_STATIC         3
-#define IMAGE_SYM_UNDEFINED            0
+#define MYIMAGE_SYM_CLASS_EXTERNAL       2
+#define MYIMAGE_SYM_CLASS_STATIC         3
+#define MYIMAGE_SYM_UNDEFINED            0
 
 /* From PE spec doc, section 4.1 */
-#define IMAGE_SCN_CNT_CODE             0x00000020
-#define IMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
+#define MYIMAGE_SCN_CNT_CODE             0x00000020
+#define MYIMAGE_SCN_CNT_INITIALIZED_DATA 0x00000040
 
 /* From PE spec doc, section 5.2.1 */
-#define IMAGE_REL_I386_DIR32           0x0006
-#define IMAGE_REL_I386_REL32           0x0014
+#define MYIMAGE_REL_I386_DIR32           0x0006
+#define MYIMAGE_REL_I386_REL32           0x0014
 
 
 /* We use myindex to calculate array addresses, rather than
@@ -812,7 +947,7 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
    COFF_section* sectab;
    COFF_symbol*  symtab;
    UChar*        strtab;
-
+   /* fprintf(stderr, "\nLOADING %s\n", oc->fileName); */
    hdr = (COFF_header*)(oc->image);
    sectab = (COFF_section*) (
                ((UChar*)(oc->image)) 
@@ -822,8 +957,7 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
                ((UChar*)(oc->image))
                + hdr->PointerToSymbolTable 
             );
-   strtab = ((UChar*)(oc->image))
-            + hdr->PointerToSymbolTable
+   strtab = ((UChar*)symtab)
             + hdr->NumberOfSymbols * sizeof_COFF_symbol;
 
    if (hdr->Machine != 0x14c) {
@@ -834,16 +968,22 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
       belch("PEi386 with nonempty optional header");
       return 0;
    }
-   if ( /* (hdr->Characteristics & IMAGE_FILE_RELOCS_STRIPPED) || */
-        (hdr->Characteristics & IMAGE_FILE_EXECUTABLE_IMAGE) ||
-        (hdr->Characteristics & IMAGE_FILE_DLL) ||
-        (hdr->Characteristics & IMAGE_FILE_SYSTEM) ) {
+   if ( /* (hdr->Characteristics & MYIMAGE_FILE_RELOCS_STRIPPED) || */
+        (hdr->Characteristics & MYIMAGE_FILE_EXECUTABLE_IMAGE) ||
+        (hdr->Characteristics & MYIMAGE_FILE_DLL) ||
+        (hdr->Characteristics & MYIMAGE_FILE_SYSTEM) ) {
       belch("Not a PEi386 object file");
       return 0;
    }
-   if ( (hdr->Characteristics & IMAGE_FILE_BYTES_REVERSED_HI) ||
-        !(hdr->Characteristics & IMAGE_FILE_32BIT_MACHINE) ) {
-      belch("Invalid PEi386 word size or endiannness");
+   if ( (hdr->Characteristics & MYIMAGE_FILE_BYTES_REVERSED_HI)
+        /* || !(hdr->Characteristics & MYIMAGE_FILE_32BIT_MACHINE) */ ) {
+      belch("Invalid PEi386 word size or endiannness: %d", 
+            (int)(hdr->Characteristics));
+      return 0;
+   }
+   /* fprintf(stderr, "strtab size %d\n", * (UInt32*)strtab); */
+   if (* (UInt32*)strtab > 510000) {
+      belch("PEi386 object has suspiciously large string table; > 64k relocs?");
       return 0;
    }
 
@@ -875,16 +1015,7 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
    fprintf ( stderr,
              "characteristics:   0x%x\n", (UInt32)(hdr->Characteristics) );
 
-   fprintf ( stderr, "\n" );
-   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 
-         fprintf( stderr, "%c", strtab[i] );
-   }
-   fprintf ( stderr, "--- END  of string table---\n");
-
+   /* Print the section table. */
    fprintf ( stderr, "\n" );
    for (i = 0; i < hdr->NumberOfSections; i++) {
       COFF_reloc* reltab;
@@ -916,6 +1047,7 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
       reltab = (COFF_reloc*) (
                   ((UChar*)(oc->image)) + sectab_i->PointerToRelocations
                );
+
       for (j = 0; j < sectab_i->NumberOfRelocations; j++) {
          COFF_symbol* sym;
          COFF_reloc* rel = (COFF_reloc*)
@@ -926,12 +1058,21 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
                    rel->VirtualAddress );
          sym = (COFF_symbol*)
                myindex ( sizeof_COFF_symbol, symtab, rel->SymbolTableIndex );
-         printName ( sym->Name, strtab );
+         printName ( sym->Name, strtab -10 );
          fprintf ( stderr, "'\n" );
       }
       fprintf ( stderr, "\n" );
    }
 
+   fprintf ( stderr, "\n" );
+   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 
+         fprintf( stderr, "%c", strtab[i] );
+   }
+   fprintf ( stderr, "--- END  of string table---\n");
 
    fprintf ( stderr, "\n" );
    i = 0;
@@ -964,7 +1105,6 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
    }
 
    fprintf ( stderr, "\n" );
-
    return 1;
 }
 
@@ -1010,8 +1150,8 @@ ocGetNames_PEi386 ( ObjectCode* oc )
       symtab_i = (COFF_symbol*)
                  myindex ( sizeof_COFF_symbol, symtab, i );
 
-      if (symtab_i->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
-          symtab_i->SectionNumber != IMAGE_SYM_UNDEFINED) {
+      if (symtab_i->StorageClass == MYIMAGE_SYM_CLASS_EXTERNAL &&
+          symtab_i->SectionNumber != MYIMAGE_SYM_UNDEFINED) {
 
          /* This symbol is global and defined, viz, exported */
          COFF_section* sectabent;
@@ -1019,8 +1159,8 @@ ocGetNames_PEi386 ( ObjectCode* oc )
          /* cstring_from_COFF_symbol_name always succeeds. */
          sname = cstring_from_COFF_symbol_name ( symtab_i->Name, strtab );
 
-         /* for IMAGE_SYMCLASS_EXTERNAL 
-                && !IMAGE_SYM_UNDEFINED,
+         /* for MYIMAGE_SYMCLASS_EXTERNAL 
+                && !MYIMAGE_SYM_UNDEFINED,
             the address of the symbol is: 
                 address of relevant section + offset in section
          */
@@ -1031,6 +1171,7 @@ ocGetNames_PEi386 ( ObjectCode* oc )
          addr = ((UChar*)(oc->image))
                 + (sectabent->PointerToRawData
                    + symtab_i->Value);
+         /* fprintf(stderr,"addSymbol %p `%s'\n", addr,sname); */
          IF_DEBUG(linker, belch("addSymbol %p `%s'\n", addr,sname);)
          ASSERT(i >= 0 && i < oc->n_symbols);
          oc->symbols[i] = sname;
@@ -1055,19 +1196,20 @@ ocGetNames_PEi386 ( ObjectCode* oc )
       COFF_section* sectab_i
          = (COFF_section*)
            myindex ( sizeof_COFF_section, sectab, i );
-      IF_DEBUG(linker, belchf("section name = %s\n", sectab_i->Name ));
+      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 
          alternative of testing the sectab_i->Name field seems to
          work ok with Cygwin.
       */
-      if (sectab_i->Characteristics & IMAGE_SCN_CNT_CODE || 
-          sectab_i->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
+      if (sectab_i->Characteristics & MYIMAGE_SCN_CNT_CODE || 
+          sectab_i->Characteristics & MYIMAGE_SCN_CNT_INITIALIZED_DATA)
          kind = SECTIONKIND_CODE_OR_RODATA;
 #endif
 
-      if (0==strcmp(".text",sectab_i->Name))
+      if (0==strcmp(".text",sectab_i->Name) ||
+          0==strcmp(".rodata",sectab_i->Name))
          kind = SECTIONKIND_CODE_OR_RODATA;
       if (0==strcmp(".data",sectab_i->Name) ||
           0==strcmp(".bss",sectab_i->Name))
@@ -1109,7 +1251,8 @@ ocResolve_PEi386 ( ObjectCode* oc )
    /* ToDo: should be variable-sized?  But is at least safe in the
       sense of buffer-overrun-proof. */
    char symbol[1000];
-   
+   /* fprintf(stderr, "resolving for %s\n", oc->fileName); */
+
    hdr = (COFF_header*)(oc->image);
    sectab = (COFF_section*) (
                ((UChar*)(oc->image)) 
@@ -1141,7 +1284,8 @@ ocResolve_PEi386 ( ObjectCode* oc )
          pP = (UInt32*)(
                  ((UChar*)(oc->image)) 
                  + (sectab_i->PointerToRawData 
-                    + reltab_j->VirtualAddress)
+                    + reltab_j->VirtualAddress
+                    - sectab_i->VirtualAddress )
               );
          /* the existing contents of pP */
          A = *pP;
@@ -1159,35 +1303,33 @@ ocResolve_PEi386 ( ObjectCode* oc )
                             printName ( sym->Name, strtab );
                             fprintf ( stderr, "'\n" ));
 
-         if (sym->StorageClass == IMAGE_SYM_CLASS_STATIC) {
+         if (sym->StorageClass == MYIMAGE_SYM_CLASS_STATIC) {
             COFF_section* section_sym 
                = findPEi386SectionCalled ( oc, sym->Name );
             if (!section_sym) {
-               fprintf ( stderr, "bad section = `%s'\n", sym->Name );
-               barf("Can't find abovementioned PEi386 section");
+               belch("%s: can't find section `%s'", oc->fileName, sym->Name);
                return 0;
             }
             S = ((UInt32)(oc->image))
                 + (section_sym->PointerToRawData
                    + sym->Value);
          } else {
-            copyName ( sym->Name, strtab, symbol, 1000 );
+            copyName ( sym->Name, strtab, symbol, 1000-1 );
             zapTrailingAtSign ( symbol );
             (void*)S = lookupLocalSymbol( oc, symbol );
             if ((void*)S == NULL)
                (void*)S = lookupSymbol( symbol );
             if (S == 0) {
-               belch("ocResolve_PEi386: %s: unknown symbol `%s'", 
-                      oc->fileName, symbol);
+               belch("%s: unknown symbol `%s'", oc->fileName, symbol);
                return 0;
             }
          }
 
          switch (reltab_j->Type) {
-            case IMAGE_REL_I386_DIR32: 
+            case MYIMAGE_REL_I386_DIR32: 
                *pP = A + S; 
                break;
-            case IMAGE_REL_I386_REL32:
+            case MYIMAGE_REL_I386_REL32:
                /* Tricky.  We have to insert a displacement at
                   pP which, when added to the PC for the _next_
                   insn, gives the address of the target (S).
@@ -1203,16 +1345,15 @@ ocResolve_PEi386 ( ObjectCode* oc )
                *pP = S - ((UInt32)pP) - 4;
                break;
             default: 
-               fprintf(stderr, 
-                       "unhandled PEi386 relocation type %d\n",
-                       reltab_j->Type);
-               barf("unhandled PEi386 relocation type");
+               belch("%s: unhandled PEi386 relocation type %d", 
+                    oc->fileName, reltab_j->Type);
                return 0;
          }
 
       }
    }
    
+   IF_DEBUG(linker, belch("completed %s", oc->fileName));
    return 1;
 }
 
@@ -1230,7 +1371,12 @@ ocResolve_PEi386 ( ObjectCode* oc )
 
 #if defined(sparc_TARGET_ARCH)
 #  define ELF_TARGET_SPARC  /* Used inside <elf.h> */
+#elif defined(i386_TARGET_ARCH)
+#  define ELF_TARGET_386    /* Used inside <elf.h> */
 #endif
+/* There is a similar case for IA64 in the Solaris2 headers if this
+ * ever becomes relevant.
+ */
 
 #include <elf.h>
 
@@ -1269,13 +1415,13 @@ ocVerifyImage_ELF ( ObjectCode* oc )
        ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
        ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
        ehdr->e_ident[EI_MAG3] != ELFMAG3) {
-      belch("ocVerifyImage_ELF: not an ELF header");
+      belch("%s: not an ELF header", oc->fileName);
       return 0;
    }
    IF_DEBUG(linker,belch( "Is an ELF header" ));
 
    if (ehdr->e_ident[EI_CLASS] != ELFCLASS32) {
-      belch("ocVerifyImage_ELF: not 32 bit ELF" );
+      belch("%s: not 32 bit ELF", oc->fileName);
       return 0;
    }
 
@@ -1287,12 +1433,12 @@ ocVerifyImage_ELF ( ObjectCode* oc )
    if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) {
        IF_DEBUG(linker,belch( "Is big-endian" ));
    } else {
-       belch("ocVerifyImage_ELF: unknown endiannness");
+       belch("%s: unknown endiannness", oc->fileName);
        return 0;
    }
 
    if (ehdr->e_type != ET_REL) {
-      belch("ocVerifyImage_ELF: not a relocatable object (.o) file");
+      belch("%s: not a relocatable object (.o) file", oc->fileName);
       return 0;
    }
    IF_DEBUG(linker, belch( "Is a relocatable object (.o) file" ));
@@ -1302,7 +1448,7 @@ ocVerifyImage_ELF ( ObjectCode* oc )
       case EM_386:   IF_DEBUG(linker,belch( "x86" )); break;
       case EM_SPARC: IF_DEBUG(linker,belch( "sparc" )); break;
       default:       IF_DEBUG(linker,belch( "unknown" )); 
-                     belch("ocVerifyImage_ELF: unknown architecture");
+                     belch("%s: unknown architecture", oc->fileName);
                      return 0;
    }
 
@@ -1315,7 +1461,7 @@ ocVerifyImage_ELF ( ObjectCode* oc )
    shdr = (Elf32_Shdr*) (ehdrC + ehdr->e_shoff);
 
    if (ehdr->e_shstrndx == SHN_UNDEF) {
-      belch("ocVerifyImage_ELF: no section header string table");
+      belch("%s: no section header string table", oc->fileName);
       return 0;
    } else {
       IF_DEBUG(linker,belch( "Section header string table is section %d", 
@@ -1356,7 +1502,7 @@ ocVerifyImage_ELF ( ObjectCode* oc )
       }
    }  
    if (nstrtab != 1) {
-      belch("ocVerifyImage_ELF: no string tables, or too many");
+      belch("%s: no string tables, or too many", oc->fileName);
       return 0;
    }
 
@@ -1373,7 +1519,7 @@ ocVerifyImage_ELF ( ObjectCode* oc )
                shdr[i].sh_size % sizeof(Elf32_Sym)
              ));
       if (0 != shdr[i].sh_size % sizeof(Elf32_Sym)) {
-         belch("ocVerifyImage_ELF: non-integral number of symbol table entries");
+         belch("%s: non-integral number of symbol table entries", oc->fileName);
          return 0;
       }
       for (j = 0; j < nent; j++) {
@@ -1408,7 +1554,7 @@ ocVerifyImage_ELF ( ObjectCode* oc )
    }
 
    if (nsymtabs == 0) {
-      belch("ocVerifyImage_ELF: didn't find any symbol tables");
+      belch("%s: didn't find any symbol tables", oc->fileName);
       return 0;
    }
 
@@ -1431,7 +1577,7 @@ ocGetNames_ELF ( ObjectCode* oc )
    ASSERT(symhash != NULL);
 
    if (!strtab) {
-      belch("ocGetNames_ELF: no strtab");
+      belch("%s: no strtab", oc->fileName);
       return 0;
    }
 
@@ -1522,9 +1668,10 @@ ocGetNames_ELF ( ObjectCode* oc )
 
 /* Do ELF relocations which lack an explicit addend.  All x86-linux
    relocations appear to be of this form. */
-static int do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC,
-                                      Elf32_Shdr* shdr, int shnum, 
-                                      Elf32_Sym*  stab, char* strtab )
+static int
+do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC,
+                           Elf32_Shdr* shdr, int shnum, 
+                           Elf32_Sym*  stab, char* strtab )
 {
    int j;
    char *symbol;
@@ -1567,8 +1714,8 @@ static int do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC,
                (void*)S = lookupSymbol( symbol );
          }
          if (!S) {
-            barf("do_Elf32_Rel_relocations:  %s: unknown symbol `%s'", 
-                 oc->fileName, symbol);
+            belch("%s: unknown symbol `%s'", oc->fileName, symbol);
+           return 0;
          }
          IF_DEBUG(linker,belch( "`%s' resolves to %p", symbol, (void*)S ));
       }
@@ -1580,9 +1727,8 @@ static int do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC,
          case R_386_PC32: *pP = S + A - P; break;
 #        endif
          default: 
-            fprintf(stderr, "unhandled ELF relocation(Rel) type %d\n",
-                            ELF32_R_TYPE(info));
-            barf("do_Elf32_Rel_relocations: unhandled ELF relocation type");
+            belch("%s: unhandled ELF relocation(Rel) type %d\n",
+                 oc->fileName, ELF32_R_TYPE(info));
             return 0;
       }
 
@@ -1593,9 +1739,10 @@ static int do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC,
 
 /* Do ELF relocations for which explicit addends are supplied.
    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_Sym*  stab, char* strtab )
+static int
+do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC,
+                            Elf32_Shdr* shdr, int shnum, 
+                            Elf32_Sym*  stab, char* strtab )
 {
    int j;
    char *symbol;
@@ -1644,8 +1791,8 @@ static int do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC,
                (void*)S = lookupSymbol( symbol );
          }
          if (!S) {
-          barf("do_Elf32_Rela_relocations: %s: unknown symbol `%s'", 
-                   oc->fileName, symbol);
+          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);
@@ -1678,15 +1825,25 @@ static int do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC,
             w1 |= w2;
             *pP = w1;
             break;
+         /* According to the Sun documentation:
+            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
+            is probably wrong, but hey ...)  
+         */
+         case R_SPARC_UA32:
          case R_SPARC_32:
             w2 = (Elf32_Word)(S + A);
             *pP = w2;
             break;
 #        endif
          default: 
-            fprintf(stderr, "unhandled ELF relocation(RelA) type %d\n",
-                            ELF32_R_TYPE(info));
-            barf("do_Elf32_Rela_relocations: unhandled ELF relocation type");
+            belch("%s: unhandled ELF relocation(RelA) type %d\n",
+                 oc->fileName, ELF32_R_TYPE(info));
             return 0;
       }
 
@@ -1712,7 +1869,7 @@ ocResolve_ELF ( ObjectCode* oc )
    strtab = findElfSection ( ehdrC, SHT_STRTAB );
 
    if (stab == NULL || strtab == NULL) {
-      belch("ocResolve_ELF: can't find string or symbol table");
+      belch("%s: can't find string or symbol table", oc->fileName);
       return 0; 
    }