[project @ 2001-08-14 13:40:07 by sewardj]
[ghc-hetmet.git] / ghc / rts / Linker.c
index 308df05..a4f85e1 100644 (file)
@@ -1,5 +1,5 @@
 /* -----------------------------------------------------------------------------
- * $Id: Linker.c,v 1.32 2001/02/28 10:03:42 sewardj Exp $
+ * $Id: Linker.c,v 1.57 2001/08/14 13:40: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 */
@@ -57,6 +59,107 @@ typedef struct _RtsSymbolVal {
 } RtsSymbolVal;
 
 
+#if !defined(PAR)
+#define Maybe_ForeignObj        SymX(mkForeignObjzh_fast)
+
+#define Maybe_Stable_Names      SymX(mkWeakzh_fast)                    \
+                               SymX(makeStableNamezh_fast)             \
+                               SymX(finalizzeWeakzh_fast)
+#else
+/* These are not available in GUM!!! -- HWL */
+#define Maybe_ForeignObj
+#define Maybe_Stable_Names
+#endif
+
+#if !defined (mingw32_TARGET_OS)
+
+#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)                      \
@@ -66,12 +169,14 @@ 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)                           \
       Sym(stg_gen_chk)                         \
       SymX(stg_exit)                           \
       SymX(stg_update_PAP)                     \
+      SymX(stg_ap_1_upd_info)                  \
       SymX(stg_ap_2_upd_info)                  \
       SymX(stg_ap_3_upd_info)                  \
       SymX(stg_ap_4_upd_info)                  \
@@ -125,7 +230,7 @@ typedef struct _RtsSymbolVal {
       SymX(stackOverflow)                      \
       SymX(int2Integerzh_fast)                 \
       SymX(word2Integerzh_fast)                        \
-      SymX(mkForeignObjzh_fast)                        \
+      Maybe_ForeignObj                         \
       SymX(__encodeDouble)                     \
       SymX(decodeDoublezh_fast)                        \
       SymX(decodeFloatzh_fast)                 \
@@ -133,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)                 \
@@ -146,9 +252,7 @@ typedef struct _RtsSymbolVal {
       SymX(orIntegerzh_fast)                   \
       SymX(xorIntegerzh_fast)                  \
       SymX(complementIntegerzh_fast)           \
-      SymX(mkWeakzh_fast)                      \
-      SymX(makeStableNamezh_fast)              \
-      SymX(finalizzeWeakzh_fast)               \
+      Maybe_Stable_Names                       \
       SymX(blockAsyncExceptionszh_fast)                \
       SymX(unblockAsyncExceptionszh_fast)      \
       SymX(isDoubleNaN)                                \
@@ -166,9 +270,12 @@ typedef struct _RtsSymbolVal {
       SymX(__gmpz_cmp_ui)                      \
       SymX(__gmpz_cmp)                         \
       SymX(__gmpn_gcd_1)                       \
+      SymX(__gmpz_get_si)                      \
+      SymX(__gmpz_get_ui)                      \
       SymX(prog_argv)                          \
       SymX(prog_argc)                          \
       SymX(resetNonBlockingFd)                 \
+      SymX(performGC)                          \
       SymX(getStablePtr)                       \
       SymX(stable_ptr_table)                   \
       SymX(shutdownHaskellAndExit)             \
@@ -189,55 +296,47 @@ typedef struct _RtsSymbolVal {
       SymX(defaultsHook)                       \
       SymX(PreTraceHook)                       \
       SymX(PostTraceHook)                      \
-      SymX(stg_sig_install)                    \
-      Sym(nocldstop)                           \
       SymX(createAdjustor)                     \
+      SymX(rts_mkChar)                         \
       SymX(rts_mkInt)                          \
+      SymX(rts_mkInt8)                         \
+      SymX(rts_mkInt16)                                \
+      SymX(rts_mkInt32)                                \
+      SymX(rts_mkInt64)                                \
+      SymX(rts_mkWord)                         \
+      SymX(rts_mkWord8)                                \
+      SymX(rts_mkWord16)                       \
+      SymX(rts_mkWord32)                       \
+      SymX(rts_mkWord64)                       \
+      SymX(rts_mkPtr)                          \
+      SymX(rts_mkFloat)                                \
+      SymX(rts_mkDouble)                       \
       SymX(rts_mkStablePtr)                    \
+      SymX(rts_mkBool)                         \
+      SymX(rts_mkString)                       \
       SymX(rts_apply)                          \
+      SymX(rts_mkAddr)                         \
+      SymX(rts_getChar)                                \
+      SymX(rts_getInt)                         \
+      SymX(rts_getInt32)                       \
+      SymX(rts_getWord)                                \
+      SymX(rts_getWord32)                      \
+      SymX(rts_getPtr)                         \
+      SymX(rts_getFloat)                       \
+      SymX(rts_getDouble)                      \
+      SymX(rts_getStablePtr)                   \
+      SymX(rts_getBool)                                \
+      SymX(rts_getAddr)                                \
+      SymX(rts_eval)                           \
+      SymX(rts_eval_)                          \
       SymX(rts_evalIO)                         \
-      SymX(rts_checkSchedStatus)               \
-      SymX(rts_getInt)
+      SymX(rts_evalLazyIO)                     \
+      SymX(rts_checkSchedStatus)
 
 #ifndef SUPPORT_LONG_LONGS
 #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)                  \
+#define RTS_LONG_LONG_SYMS                     \
       SymX(int64ToIntegerzh_fast)              \
       SymX(word64ToIntegerzh_fast)
 #endif /* SUPPORT_LONG_LONGS */
@@ -246,6 +345,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
 
@@ -262,6 +364,8 @@ RTS_SYMBOLS
 static RtsSymbolVal rtsSyms[] = {
       RTS_SYMBOLS
       RTS_LONG_LONG_SYMS
+      RTS_POSIX_ONLY_SYMBOLS
+      RTS_MINGW_ONLY_SYMBOLS
       { 0, 0 } /* sentinel */
 };
 
@@ -293,18 +397,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) {
@@ -315,10 +446,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
@@ -338,6 +500,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
@@ -374,6 +554,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 */
    { 
@@ -607,26 +788,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
@@ -761,7 +945,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)) 
@@ -771,8 +955,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) {
@@ -783,16 +966,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;
    }
 
@@ -824,16 +1013,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;
@@ -865,6 +1045,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*)
@@ -875,12 +1056,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;
@@ -913,7 +1103,6 @@ ocVerifyImage_PEi386 ( ObjectCode* oc )
    }
 
    fprintf ( stderr, "\n" );
-
    return 1;
 }
 
@@ -959,8 +1148,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;
@@ -968,8 +1157,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
          */
@@ -980,6 +1169,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;
@@ -1004,19 +1194,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))
@@ -1058,7 +1249,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)) 
@@ -1090,7 +1282,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;
@@ -1108,35 +1301,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).
@@ -1152,16 +1343,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;
 }
 
@@ -1179,7 +1369,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>
 
@@ -1218,13 +1413,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;
    }
 
@@ -1236,12 +1431,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" ));
@@ -1251,7 +1446,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;
    }
 
@@ -1264,7 +1459,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", 
@@ -1305,7 +1500,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;
    }
 
@@ -1322,7 +1517,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++) {
@@ -1357,7 +1552,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;
    }
 
@@ -1380,7 +1575,7 @@ ocGetNames_ELF ( ObjectCode* oc )
    ASSERT(symhash != NULL);
 
    if (!strtab) {
-      belch("ocGetNames_ELF: no strtab");
+      belch("%s: no strtab", oc->fileName);
       return 0;
    }
 
@@ -1471,9 +1666,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;
@@ -1516,8 +1712,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 ));
       }
@@ -1529,9 +1725,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;
       }
 
@@ -1542,9 +1737,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;
@@ -1593,8 +1789,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);
@@ -1633,9 +1829,8 @@ static int do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC,
             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;
       }
 
@@ -1661,7 +1856,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; 
    }