X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FLinker.c;h=a4854e130ee8731534528f00264e8ed6bbee6fe1;hb=0e6a76a1182be8336cfaaa6bf482c57a89193372;hp=532765dab777f60f616baeff02d4d2d8b12b5e33;hpb=f55855f29f7610bf7e3a2feb4f3d43e098498772;p=ghc-hetmet.git diff --git a/ghc/rts/Linker.c b/ghc/rts/Linker.c index 532765d..a4854e1 100644 --- a/ghc/rts/Linker.c +++ b/ghc/rts/Linker.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Linker.c,v 1.95 2002/06/12 22:29:43 wolfgang Exp $ + * $Id: Linker.c,v 1.106 2002/10/23 08:52:26 simonmar Exp $ * * (c) The GHC Team, 2000, 2001 * @@ -24,11 +24,16 @@ #include #endif +#include +#include + #ifdef HAVE_SYS_STAT_H #include #endif -#ifdef HAVE_DLFCN_H +#if defined(HAVE_FRAMEWORK_HASKELLSUPPORT) +#include +#elif defined(HAVE_DLFCN_H) #include #endif @@ -59,7 +64,9 @@ #elif defined(cygwin32_TARGET_OS) || defined (mingw32_TARGET_OS) # define OBJFORMAT_PEi386 # include +# include #elif defined(darwin_TARGET_OS) +# include # define OBJFORMAT_MACHO # include # include @@ -67,7 +74,7 @@ #endif /* Hash table mapping symbol names to Symbol */ -/*Str*/HashTable *symhash; +static /*Str*/HashTable *symhash; #if defined(OBJFORMAT_ELF) static int ocVerifyImage_ELF ( ObjectCode* oc ); @@ -210,7 +217,6 @@ typedef struct _RtsSymbolVal { executable, so we have to employ this hack. */ #define RTS_MINGW_ONLY_SYMBOLS \ SymX(memset) \ - SymX(memset) \ SymX(inet_ntoa) \ SymX(inet_addr) \ SymX(htonl) \ @@ -276,34 +282,6 @@ typedef struct _RtsSymbolVal { Sym(__umoddi3) #endif -#ifdef darwin_TARGET_OS -#define RTS_DARWIN_ONLY_SYMBOLS \ - Sym(__divdi3) \ - Sym(__udivdi3) \ - Sym(__moddi3) \ - Sym(__umoddi3) \ - Sym(__ashldi3) \ - Sym(__ashrdi3) \ - Sym(__lshrdi3) \ - SymX(stg_gc_enter_2) \ - SymX(stg_gc_enter_3) \ - SymX(stg_gc_enter_4) \ - SymX(stg_gc_enter_5) \ - SymX(stg_gc_enter_6) \ - SymX(stg_gc_enter_7) \ - SymX(stg_gc_enter_8) \ - SymX(stg_chk_2) \ - SymX(stg_chk_3) \ - SymX(stg_chk_4) \ - SymX(stg_chk_5) \ - SymX(stg_chk_6) \ - SymX(stg_chk_7) \ - SymX(stg_chk_8) \ - -#else -#define RTS_DARWIN_ONLY_SYMBOLS -#endif - #ifndef SMP # define MAIN_CAP_SYM SymX(MainCapability) #else @@ -314,7 +292,6 @@ typedef struct _RtsSymbolVal { Maybe_ForeignObj \ Maybe_Stable_Names \ Sym(StgReturn) \ - Sym(__stginit_GHCziPrim) \ Sym(init_stack) \ SymX(__stg_chk_0) \ SymX(__stg_chk_1) \ @@ -414,6 +391,7 @@ typedef struct _RtsSymbolVal { SymX(newCAF) \ SymX(newMVarzh_fast) \ SymX(newMutVarzh_fast) \ + SymX(atomicModifyMutVarzh_fast) \ SymX(newPinnedByteArrayzh_fast) \ SymX(orIntegerzh_fast) \ SymX(performGC) \ @@ -433,7 +411,6 @@ typedef struct _RtsSymbolVal { SymX(rts_evalIO) \ SymX(rts_evalLazyIO) \ SymX(rts_eval_) \ - SymX(rts_getAddr) \ SymX(rts_getBool) \ SymX(rts_getChar) \ SymX(rts_getDouble) \ @@ -445,7 +422,6 @@ typedef struct _RtsSymbolVal { SymX(rts_getThreadId) \ SymX(rts_getWord) \ SymX(rts_getWord32) \ - SymX(rts_mkAddr) \ SymX(rts_mkBool) \ SymX(rts_mkChar) \ SymX(rts_mkDouble) \ @@ -528,6 +504,16 @@ typedef struct _RtsSymbolVal { /* force these symbols to be present */ #define RTS_EXTRA_SYMBOLS \ Sym(__divsf3) +#elif defined(powerpc_TARGET_ARCH) +#define RTS_EXTRA_SYMBOLS \ + Sym(__divdi3) \ + Sym(__udivdi3) \ + Sym(__moddi3) \ + Sym(__umoddi3) \ + Sym(__ashldi3) \ + Sym(__ashrdi3) \ + Sym(__lshrdi3) \ + Sym(__eprintf) #else #define RTS_EXTRA_SYMBOLS /* nothing */ #endif @@ -541,7 +527,6 @@ RTS_EXTRA_SYMBOLS RTS_POSIX_ONLY_SYMBOLS RTS_MINGW_ONLY_SYMBOLS RTS_CYGWIN_ONLY_SYMBOLS -RTS_DARWIN_ONLY_SYMBOLS #undef Sym #undef SymX @@ -562,7 +547,6 @@ static RtsSymbolVal rtsSyms[] = { RTS_POSIX_ONLY_SYMBOLS RTS_MINGW_ONLY_SYMBOLS RTS_CYGWIN_ONLY_SYMBOLS - RTS_DARWIN_ONLY_SYMBOLS { 0, 0 } /* sentinel */ }; @@ -603,6 +587,10 @@ static void ghciInsertStrHashTable ( char* obj_name, /* ----------------------------------------------------------------------------- * initialize the object linker */ + + +static int linker_init_done = 0 ; + #if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO) static void *dl_prog_handle; #endif @@ -612,6 +600,13 @@ initLinker( void ) { RtsSymbolVal *sym; + /* Make initLinker idempotent, so we can call it + before evey relevant operation; that means we + don't need to initialise the linker separately */ + if (linker_init_done == 1) { return; } else { + linker_init_done = 1; + } + symhash = allocStrHashTable(); /* populate the symbol table with stuff from the RTS */ @@ -625,6 +620,9 @@ initLinker( void ) } /* ----------------------------------------------------------------------------- + * Loading DLL or .so dynamic libraries + * ----------------------------------------------------------------------------- + * * Add a DLL from which symbols may be found. In the ELF case, just * do RTLD_GLOBAL-style add, so no further messing around needs to * happen in order that symbols in the loaded .so are findable -- @@ -633,7 +631,12 @@ initLinker( void ) * * 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. + * list. This means that we need to load even DLLs that are guaranteed + * to be in the ghc.exe image already, just so we can get a handle + * to give to loadSymbol, so that we can find the symbols. For such + * libraries, the LoadLibrary call should be a no-op except for returning + * the handle. + * */ #if defined(OBJFORMAT_PEi386) @@ -651,15 +654,16 @@ typedef static OpenedDLL* opened_dlls = NULL; #endif - - char * addDLL( char *dll_name ) { # if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO) + /* ------------------- ELF DLL loader ------------------- */ void *hdl; char *errmsg; + initLinker(); + hdl= dlopen(dll_name, RTLD_NOW | RTLD_GLOBAL); if (hdl == NULL) { /* dlopen failed; return a ptr to the error msg. */ @@ -672,14 +676,15 @@ addDLL( char *dll_name ) /*NOTREACHED*/ # elif defined(OBJFORMAT_PEi386) + /* ------------------- Win32 DLL loader ------------------- */ - /* 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); */ + initLinker(); + + /* fprintf(stderr, "\naddDLL; dll_name = `%s'\n", 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) { @@ -687,11 +692,21 @@ addDLL( char *dll_name ) return NULL; } + /* The file name has no suffix (yet) so that we can try + both foo.dll and foo.drv + + The documentation for LoadLibrary says: + If no file name extension is specified in the lpFileName + parameter, the default library extension .dll is + appended. However, the file name string can include a trailing + point character (.) to indicate that the module name has no + extension. */ + buf = stgMallocBytes(strlen(dll_name) + 10, "addDLL"); sprintf(buf, "%s.DLL", dll_name); instance = LoadLibrary(buf); if (instance == NULL) { - sprintf(buf, "%s.DRV", dll_name); // KAA: allow loading of drivers (like winspool.drv) + sprintf(buf, "%s.DRV", dll_name); // KAA: allow loading of drivers (like winspool.drv) instance = LoadLibrary(buf); if (instance == NULL) { free(buf); @@ -702,6 +717,7 @@ addDLL( char *dll_name ) } free(buf); + /* Add this DLL to the list of DLLs in which to search for symbols. */ o_dll = stgMallocBytes( sizeof(OpenedDLL), "addDLL" ); o_dll->name = stgMallocBytes(1+strlen(dll_name), "addDLL"); strcpy(o_dll->name, dll_name); @@ -722,6 +738,7 @@ void * lookupSymbol( char *lbl ) { void *val; + initLinker() ; ASSERT(symhash != NULL); val = lookupStrHashTable(symhash, lbl); @@ -767,6 +784,7 @@ void * lookupLocalSymbol( ObjectCode* oc, char *lbl ) { void *val; + initLinker() ; val = lookupStrHashTable(oc->lochash, lbl); if (val == NULL) { @@ -791,6 +809,9 @@ void ghci_enquire ( char* addr ) char* a; const int DELTA = 64; ObjectCode* oc; + + initLinker(); + for (oc = objects; oc; oc = oc->next) { for (i = 0; i < oc->n_symbols; i++) { sym = oc->symbols[i]; @@ -834,6 +855,8 @@ loadObj( char *path ) FILE *f; #endif + initLinker(); + /* fprintf(stderr, "loadObj %s\n", path ); */ /* Check that we haven't already loaded this object. Don't give up @@ -974,6 +997,8 @@ resolveObjs( void ) ObjectCode *oc; int r; + initLinker(); + for (oc = objects; oc; oc = oc->next) { if (oc->status != OBJECT_RESOLVED) { # if defined(OBJFORMAT_ELF) @@ -1003,6 +1028,8 @@ unloadObj( char *path ) ASSERT(symhash != NULL); ASSERT(objects != NULL); + initLinker(); + prev = NULL; for (oc = objects; oc; prev = oc, oc = oc->next) { if (!strcmp(oc->fileName,path)) { @@ -1850,7 +1877,8 @@ ocResolve_PEi386 ( ObjectCode* oc ) if ((void*)S != NULL) goto foundit; (void*)S = lookupSymbol( symbol ); if ((void*)S != NULL) goto foundit; - belch("%s: unknown symbol `%s'", oc->fileName, symbol); + /* Newline first because the interactive linker has printed "linking..." */ + belch("\n%s: unknown symbol `%s'", oc->fileName, symbol); return 0; foundit: } @@ -2866,6 +2894,7 @@ static int ocVerifyImage_MachO(ObjectCode* oc) } static void resolveImports( + ObjectCode* oc, char *image, struct symtab_command *symLC, struct section *sect, // ptr to lazy or non-lazy symbol pointer section @@ -2884,6 +2913,8 @@ static void resolveImports( if((symbol->n_type & N_TYPE) == N_UNDF && (symbol->n_type & N_EXT) && (symbol->n_value != 0)) addr = (void*) (symbol->n_value); + else if((addr = lookupLocalSymbol(oc,nm)) != NULL) + ; else addr = lookupSymbol(nm); if(!addr) @@ -2936,12 +2967,32 @@ static void relocateSection(char *image, if(reloc->r_pcrel && !reloc->r_extern) continue; - if(!reloc->r_pcrel - && reloc->r_length == 2 - && reloc->r_type == GENERIC_RELOC_VANILLA) + if(!reloc->r_pcrel && reloc->r_length == 2) { - unsigned long* word = (unsigned long*) (image + sect->offset + reloc->r_address); + unsigned long word; + + unsigned long* wordPtr = (unsigned long*) (image + sect->offset + reloc->r_address); + if(reloc->r_type == GENERIC_RELOC_VANILLA) + { + word = *wordPtr; + } + else if(reloc->r_type == PPC_RELOC_LO16) + { + word = ((unsigned short*) wordPtr)[1]; + word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF) << 16; + } + else if(reloc->r_type == PPC_RELOC_HI16) + { + word = ((unsigned short*) wordPtr)[1] << 16; + word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF); + } + else if(reloc->r_type == PPC_RELOC_HA16) + { + word = ((unsigned short*) wordPtr)[1] << 16; + word += ((short)relocs[i+1].r_address & (short)0xFFFF); + } + if(!reloc->r_extern) { long delta = @@ -2949,14 +3000,36 @@ static void relocateSection(char *image, - sections[reloc->r_symbolnum-1].addr + ((long) image); - *word += delta; + word += delta; } else { struct nlist *symbol = &nlist[reloc->r_symbolnum]; char *nm = image + symLC->stroff + symbol->n_un.n_strx; - *word = lookupSymbol(nm); - ASSERT(*word); + word = (unsigned long) (lookupSymbol(nm)); + ASSERT(word); + } + + if(reloc->r_type == GENERIC_RELOC_VANILLA) + { + *wordPtr = word; + continue; + } + else if(reloc->r_type == PPC_RELOC_LO16) + { + ((unsigned short*) wordPtr)[1] = word & 0xFFFF; + i++; continue; + } + else if(reloc->r_type == PPC_RELOC_HI16) + { + ((unsigned short*) wordPtr)[1] = (word >> 16) & 0xFFFF; + i++; continue; + } + else if(reloc->r_type == PPC_RELOC_HA16) + { + ((unsigned short*) wordPtr)[1] = ((word >> 16) & 0xFFFF) + + ((word & (1<<15)) ? 1 : 0); + i++; continue; } continue; } @@ -2972,7 +3045,7 @@ static int ocGetNames_MachO(ObjectCode* oc) char *image = (char*) oc->image; struct mach_header *header = (struct mach_header*) image; struct load_command *lc = (struct load_command*) (image + sizeof(struct mach_header)); - int i,curSymbol; + unsigned i,curSymbol; struct segment_command *segLC = NULL; struct section *sections, *la_ptrs = NULL, *nl_ptrs = NULL; struct symtab_command *symLC = NULL; @@ -3051,6 +3124,20 @@ static int ocGetNames_MachO(ObjectCode* oc) } } + // insert local symbols into lochash + for(i=dsymLC->ilocalsym;iilocalsym+dsymLC->nlocalsym;i++) + { + if((nlist[i].n_type & N_TYPE) == N_SECT) + { + char *nm = image + symLC->stroff + nlist[i].n_un.n_strx; + ghciInsertStrHashTable(oc->fileName, oc->lochash, nm, image + + sections[nlist[i].n_sect-1].offset + - sections[nlist[i].n_sect-1].addr + + nlist[i].n_value); + } + } + + commonStorage = stgCallocBytes(1,commonSize,"ocGetNames_MachO(common symbols)"); commonCounter = (unsigned long)commonStorage; for(i=0;insyms;i++) @@ -3063,7 +3150,7 @@ static int ocGetNames_MachO(ObjectCode* oc) nlist[i].n_value = commonCounter; - ghciInsertStrHashTable(oc->fileName, symhash, nm, nlist[i].n_value); + ghciInsertStrHashTable(oc->fileName, symhash, nm, (void*)commonCounter); oc->symbols[curSymbol++] = nm; commonCounter += sz; @@ -3077,7 +3164,7 @@ static int ocResolve_MachO(ObjectCode* oc) char *image = (char*) oc->image; struct mach_header *header = (struct mach_header*) image; struct load_command *lc = (struct load_command*) (image + sizeof(struct mach_header)); - int i; + unsigned i; struct segment_command *segLC = NULL; struct section *sections, *la_ptrs = NULL, *nl_ptrs = NULL; struct symtab_command *symLC = NULL; @@ -3110,9 +3197,9 @@ static int ocResolve_MachO(ObjectCode* oc) indirectSyms = (unsigned long*) (image + dsymLC->indirectsymoff); if(la_ptrs) - resolveImports(image,symLC,la_ptrs,indirectSyms,nlist); + resolveImports(oc,image,symLC,la_ptrs,indirectSyms,nlist); if(nl_ptrs) - resolveImports(image,symLC,nl_ptrs,indirectSyms,nlist); + resolveImports(oc,image,symLC,nl_ptrs,indirectSyms,nlist); for(i=0;insects;i++) {