[project @ 2003-09-23 17:07:39 by sof]
[ghc-hetmet.git] / ghc / rts / Linker.c
index 13cdf3a..6753876 100644 (file)
@@ -1,7 +1,7 @@
 /* -----------------------------------------------------------------------------
- * $Id: Linker.c,v 1.116 2003/03/25 17:58:47 sof Exp $
+ * $Id: Linker.c,v 1.130 2003/09/21 22:20:54 wolfgang Exp $
  *
- * (c) The GHC Team, 2000, 2001
+ * (c) The GHC Team, 2000-2003
  *
  * RTS Object Linker
  *
@@ -59,7 +59,7 @@
 #include <sys/mman.h>
 #endif
 
-#if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS) || defined(freebsd_TARGET_OS)
+#if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS) || defined(freebsd_TARGET_OS) || defined(netbsd_TARGET_OS) || defined(openbsd_TARGET_OS)
 #  define OBJFORMAT_ELF
 #elif defined(cygwin32_TARGET_OS) || defined (mingw32_TARGET_OS)
 #  define OBJFORMAT_PEi386
@@ -71,6 +71,7 @@
 #  include <mach-o/loader.h>
 #  include <mach-o/nlist.h>
 #  include <mach-o/reloc.h>
+#  include <mach-o/dyld.h>
 #endif
 
 /* Hash table mapping symbol names to Symbol */
@@ -92,7 +93,7 @@ static int ocVerifyImage_MachO    ( ObjectCode* oc );
 static int ocGetNames_MachO       ( ObjectCode* oc );
 static int ocResolve_MachO        ( ObjectCode* oc );
 
-static void machoInitSymbolsWithoutUnderscore();
+static void machoInitSymbolsWithoutUnderscore( void );
 #endif
 
 /* -----------------------------------------------------------------------------
@@ -205,11 +206,7 @@ typedef struct _RtsSymbolVal {
       SymX(uname)                               \
       SymX(unlink)                              \
       SymX(utime)                               \
-      SymX(waitpid)                             \
-      Sym(__divdi3)                             \
-      Sym(__udivdi3)                            \
-      Sym(__moddi3)                             \
-      Sym(__umoddi3)
+      SymX(waitpid)
 
 #elif !defined(mingw32_TARGET_OS)
 #define RTS_MINGW_ONLY_SYMBOLS /**/
@@ -218,6 +215,15 @@ typedef struct _RtsSymbolVal {
 #define RTS_POSIX_ONLY_SYMBOLS  /**/
 #define RTS_CYGWIN_ONLY_SYMBOLS /**/
 
+/* Extra syms gen'ed by mingw-2's gcc-3.2: */
+#if __GNUC__>=3
+#define RTS_MINGW_EXTRA_SYMS                    \
+      Sym(_imp____mb_cur_max)                   \
+      Sym(_imp___pctype)            
+#else
+#define RTS_MINGW_EXTRA_SYMS
+#endif
+
 /* These are statically linked from the mingw libraries into the ghc
    executable, so we have to employ this hack. */
 #define RTS_MINGW_ONLY_SYMBOLS                  \
@@ -282,11 +288,8 @@ typedef struct _RtsSymbolVal {
       Sym(opendir)                              \
       Sym(readdir)                              \
       Sym(rewinddir)                            \
-      Sym(closedir)                             \
-      Sym(__divdi3)                             \
-      Sym(__udivdi3)                            \
-      Sym(__moddi3)                             \
-      Sym(__umoddi3)
+      RTS_MINGW_EXTRA_SYMS                      \
+      Sym(closedir)
 #endif
 
 #ifndef SMP
@@ -372,11 +375,13 @@ typedef struct _RtsSymbolVal {
       SymX(gcdIntegerzh_fast)                  \
       SymX(gcdIntegerIntzh_fast)               \
       SymX(gcdIntzh_fast)                      \
+      SymX(genSymZh)                           \
       SymX(getProgArgv)                                \
       SymX(getStablePtr)                       \
       SymX(int2Integerzh_fast)                 \
       SymX(integer2Intzh_fast)                 \
       SymX(integer2Wordzh_fast)                        \
+      SymX(isCurrentThreadBoundzh_fast)                \
       SymX(isDoubleDenormalized)               \
       SymX(isDoubleInfinite)                   \
       SymX(isDoubleNaN)                                \
@@ -409,6 +414,7 @@ typedef struct _RtsSymbolVal {
       SymX(quotIntegerzh_fast)                 \
       SymX(quotRemIntegerzh_fast)              \
       SymX(raisezh_fast)                       \
+      SymX(raiseIOzh_fast)                     \
       SymX(remIntegerzh_fast)                  \
       SymX(resetNonBlockingFd)                 \
       SymX(resumeThread)                       \
@@ -417,6 +423,7 @@ typedef struct _RtsSymbolVal {
       SymX(rts_eval)                           \
       SymX(rts_evalIO)                         \
       SymX(rts_evalLazyIO)                     \
+      SymX(rts_evalStableIO)                   \
       SymX(rts_eval_)                          \
       SymX(rts_getBool)                                \
       SymX(rts_getChar)                                \
@@ -450,6 +457,7 @@ typedef struct _RtsSymbolVal {
       SymX(rts_mkWord64)                       \
       SymX(rts_mkWord8)                                \
       SymX(rts_unlock)                         \
+      SymX(rtsSupportsBoundThreads)            \
       SymX(run_queue_hd)                       \
       SymX(setProgArgv)                                \
       SymX(startupHaskell)                     \
@@ -458,6 +466,8 @@ typedef struct _RtsSymbolVal {
       SymX(stable_ptr_table)                   \
       SymX(stackOverflow)                      \
       SymX(stg_CAF_BLACKHOLE_info)             \
+      SymX(stg_BLACKHOLE_BQ_info)              \
+      SymX(awakenBlockedQueue)                 \
       SymX(stg_CHARLIKE_closure)               \
       SymX(stg_EMPTY_MVAR_info)                        \
       SymX(stg_IND_STATIC_info)                        \
@@ -540,12 +550,9 @@ typedef struct _RtsSymbolVal {
 #define RTS_LONG_LONG_SYMS /* nothing */
 #endif
 
-#ifdef ia64_TARGET_ARCH
-/* force these symbols to be present */
-#define RTS_EXTRA_SYMBOLS                      \
-      Sym(__divsf3)
-#elif defined(powerpc_TARGET_ARCH)
-#define RTS_EXTRA_SYMBOLS                      \
+// 64-bit support functions in libgcc.a
+#if defined(__GNUC__) && SIZEOF_VOID_P <= 4
+#define RTS_LIBGCC_SYMBOLS                     \
       Sym(__divdi3)                             \
       Sym(__udivdi3)                            \
       Sym(__moddi3)                             \
@@ -554,27 +561,37 @@ typedef struct _RtsSymbolVal {
       Sym(__ashrdi3)                           \
       Sym(__lshrdi3)                           \
       Sym(__eprintf)
-      
+#elif defined(ia64_TARGET_ARCH)
+#define RTS_LIBGCC_SYMBOLS                     \
+      Sym(__divdi3)                            \
+      Sym(__udivdi3)                            \
+      Sym(__moddi3)                            \
+      Sym(__umoddi3)                           \
+      Sym(__divsf3)                            \
+      Sym(__divdf3)
+#else
+#define RTS_LIBGCC_SYMBOLS
+#endif
+
+#ifdef darwin_TARGET_OS
       // Symbols that don't have a leading underscore
       // on Mac OS X. They have to receive special treatment,
       // see machoInitSymbolsWithoutUnderscore()
 #define RTS_MACHO_NOUNDERLINE_SYMBOLS          \
       Sym(saveFP)                              \
       Sym(restFP)
-#else
-#define RTS_EXTRA_SYMBOLS /* nothing */
 #endif
 
 /* entirely bogus claims about types of these symbols */
-#define Sym(vvv)  extern void (vvv);
+#define Sym(vvv)  extern void vvv(void);
 #define SymX(vvv) /**/
 #define SymX_redirect(vvv,xxx) /**/
 RTS_SYMBOLS
 RTS_LONG_LONG_SYMS
-RTS_EXTRA_SYMBOLS
 RTS_POSIX_ONLY_SYMBOLS
 RTS_MINGW_ONLY_SYMBOLS
 RTS_CYGWIN_ONLY_SYMBOLS
+RTS_LIBGCC_SYMBOLS
 #undef Sym
 #undef SymX
 #undef SymX_redirect
@@ -598,10 +615,10 @@ RTS_CYGWIN_ONLY_SYMBOLS
 static RtsSymbolVal rtsSyms[] = {
       RTS_SYMBOLS
       RTS_LONG_LONG_SYMS
-      RTS_EXTRA_SYMBOLS
       RTS_POSIX_ONLY_SYMBOLS
       RTS_MINGW_ONLY_SYMBOLS
       RTS_CYGWIN_ONLY_SYMBOLS
+      RTS_LIBGCC_SYMBOLS
       { 0, 0 } /* sentinel */
 };
 
@@ -723,7 +740,11 @@ addDLL( char *dll_name )
 
    initLinker();
 
+#if !defined(openbsd_TARGET_OS)
    hdl= dlopen(dll_name, RTLD_NOW | RTLD_GLOBAL);
+#else
+   hdl= dlopen(dll_name, RTLD_LAZY);
+#endif
    if (hdl == NULL) {
       /* dlopen failed; return a ptr to the error msg. */
       errmsg = dlerror();
@@ -802,8 +823,15 @@ lookupSymbol( char *lbl )
     val = lookupStrHashTable(symhash, lbl);
 
     if (val == NULL) {
-#       if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
+#       if defined(OBJFORMAT_ELF)
        return dlsym(dl_prog_handle, lbl);
+#       elif defined(OBJFORMAT_MACHO)
+       if(NSIsSymbolNameDefined(lbl)) {
+           NSSymbol symbol = NSLookupAndBindSymbol(lbl);
+           return NSAddressOfSymbol(symbol);
+       } else {
+           return NULL;
+       }
 #       elif defined(OBJFORMAT_PEi386)
         OpenedDLL* o_dll;
         void* sym;
@@ -1992,6 +2020,9 @@ ocResolve_PEi386 ( ObjectCode* oc )
 #  define ELF_TARGET_SPARC  /* Used inside <elf.h> */
 #elif defined(i386_TARGET_ARCH)
 #  define ELF_TARGET_386    /* Used inside <elf.h> */
+#elif defined(x86_64_TARGET_ARCH)
+#  define ELF_TARGET_X64_64
+#  define ELF_64BIT
 #elif defined (ia64_TARGET_ARCH)
 #  define ELF_TARGET_IA64   /* Used inside <elf.h> */
 #  define ELF_64BIT
@@ -2000,7 +2031,15 @@ ocResolve_PEi386 ( ObjectCode* oc )
 #  define ELF_NEED_PLT      /* needs Procedure Linkage Tables */
 #endif
 
+#if !defined(openbsd_TARGET_OS)
 #include <elf.h>
+#else
+/* openbsd elf has things in different places, with diff names */
+#include <elf_abi.h>
+#include <machine/reloc.h>
+#define R_386_32    RELOC_32
+#define R_386_PC32  RELOC_PC32
+#endif
 
 /*
  * Define a set of types which can be used for both ELF32 and ELF64
@@ -2032,11 +2071,19 @@ ocResolve_PEi386 ( ObjectCode* oc )
 #define Elf_Sym     Elf32_Sym
 #define Elf_Rel     Elf32_Rel
 #define Elf_Rela    Elf32_Rela
+#ifndef ELF_ST_TYPE
 #define ELF_ST_TYPE ELF32_ST_TYPE
+#endif
+#ifndef ELF_ST_BIND
 #define ELF_ST_BIND ELF32_ST_BIND
+#endif
+#ifndef ELF_R_TYPE
 #define ELF_R_TYPE  ELF32_R_TYPE
+#endif
+#ifndef ELF_R_SYM
 #define ELF_R_SYM   ELF32_R_SYM
 #endif
+#endif
 
 
 /*
@@ -2697,8 +2744,8 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
 #ifdef ELF_FUNCTION_DESC
            /* If a function, already a function descriptor - we would
               have to copy it to add an offset. */
-            if (S && ELF_ST_TYPE(sym.st_info) == STT_FUNC)
-               assert(A == 0);
+            if (S && (ELF_ST_TYPE(sym.st_info) == STT_FUNC) && (A != 0))
+               belch("%s: function %s with addend %p", oc->fileName, symbol, (void *)A);
 #endif
         }
          if (!S) {
@@ -2757,6 +2804,9 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
         case R_IA64_FPTR64LSB:
            *pP = value;
            break;
+        case R_IA64_PCREL64LSB:
+           *pP = value - P;
+           break;
         case R_IA64_SEGREL64LSB:
            addr = findElfSegment(ehdrC, value);
            *pP = value - addr;
@@ -2765,6 +2815,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
            ia64_reloc_gprel22(P, value);
            break;
         case R_IA64_LTOFF22:
+        case R_IA64_LTOFF22X:
         case R_IA64_LTOFF_FPTR22:
            addr = allocateGOTEntry(value);
            ia64_reloc_gprel22(P, addr);
@@ -2772,6 +2823,10 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC,
         case R_IA64_PCREL21B:
            ia64_reloc_pcrel21(P, S, oc);
            break;
+        case R_IA64_LDXMOV:
+           /* This goes with R_IA64_LTOFF22X and points to the load to
+            * convert into a move.  We don't implement relaxation. */
+           break;
 #        endif
          default:
             belch("%s: unhandled ELF relocation(RelA) type %d\n",
@@ -2984,13 +3039,16 @@ static int resolveImports(
            return 0;
        }
        ASSERT(addr);
+       checkProddableBlock(oc,((void**)(image + sect->offset)) + i);
        ((void**)(image + sect->offset))[i] = addr;
     }
     
     return 1;
 }
 
-static int relocateSection(char *image, 
+static int relocateSection(
+    ObjectCode* oc,
+    char *image, 
     struct symtab_command *symLC, struct nlist *nlist,
     struct section* sections, struct section *sect)
 {
@@ -3018,6 +3076,7 @@ static int relocateSection(char *image,
                {
                    unsigned long* word = (unsigned long*) (image + sect->offset + scat->r_address);
                    
+                   checkProddableBlock(oc,word);
                    *word = scat->r_value + sect->offset + ((long) image);
                }
            }
@@ -3035,6 +3094,7 @@ static int relocateSection(char *image,
                unsigned long word = 0;
 
                unsigned long* wordPtr = (unsigned long*) (image + sect->offset + reloc->r_address);
+               checkProddableBlock(oc,wordPtr);
                
                if(reloc->r_type == GENERIC_RELOC_VANILLA)
                {
@@ -3169,6 +3229,10 @@ static int ocGetNames_MachO(ObjectCode* oc)
            addSection(oc, SECTIONKIND_RWDATA, 
                (void*) (image + sections[i].offset),
                (void*) (image + sections[i].offset + sections[i].size));
+               
+       if(sections[i].size > 0)    // size 0 segments do exist
+           addProddableBlock(oc, (void*) (image + sections[i].offset),
+                                           sections[i].size);
     }
 
        // count external symbols defined here
@@ -3285,7 +3349,7 @@ static int ocResolve_MachO(ObjectCode* oc)
     
     for(i=0;i<segLC->nsects;i++)
     {
-       if(!relocateSection(image,symLC,nlist,sections,&sections[i]))
+       if(!relocateSection(oc,image,symLC,nlist,sections,&sections[i]))
            return 0;
     }