X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FLinker.c;h=a9d3089382c489b77a1c78bd06a6cee1d327d274;hb=e1c4a20eb3545e0ac5c67099e487d1f26d4a655c;hp=85d5809210524e1540380b85c3a5129bd699d6ef;hpb=920a3de7d913f9f369ffb8e5f0892ef7c9aeacde;p=ghc-hetmet.git diff --git a/ghc/rts/Linker.c b/ghc/rts/Linker.c index 85d5809..a9d3089 100644 --- a/ghc/rts/Linker.c +++ b/ghc/rts/Linker.c @@ -1,6 +1,6 @@ /* ----------------------------------------------------------------------------- * - * (c) The GHC Team, 2000-2003 + * (c) The GHC Team, 2000-2004 * * RTS Object Linker * @@ -9,6 +9,12 @@ #if 0 #include "PosixSource.h" #endif + +// Linux needs _GNU_SOURCE to get RTLD_DEFAULT from . +#ifdef __linux__ +#define _GNU_SOURCE +#endif + #include "Rts.h" #include "RtsFlags.h" #include "HsFFI.h" @@ -52,10 +58,17 @@ #include #endif -#if defined(ia64_TARGET_ARCH) +#if defined(ia64_TARGET_ARCH) || defined(openbsd_TARGET_OS) #define USE_MMAP #include #include + +#if defined(openbsd_TARGET_OS) +#ifdef HAVE_UNISTD_H +#include +#endif +#endif + #endif #if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS) || defined(freebsd_TARGET_OS) || defined(netbsd_TARGET_OS) || defined(openbsd_TARGET_OS) @@ -128,7 +141,7 @@ typedef struct _RtsSymbolVal { #define RTS_MINGW_ONLY_SYMBOLS /**/ /* Don't have the ability to read import libs / archives, so * we have to stupidly list a lot of what libcygwin.a - * exports; sigh. + * exports; sigh. */ #define RTS_CYGWIN_ONLY_SYMBOLS \ SymX(regfree) \ @@ -219,7 +232,7 @@ typedef struct _RtsSymbolVal { #if __GNUC__>=3 #define RTS_MINGW_EXTRA_SYMS \ Sym(_imp____mb_cur_max) \ - Sym(_imp___pctype) + Sym(_imp___pctype) #else #define RTS_MINGW_EXTRA_SYMS #endif @@ -334,17 +347,14 @@ typedef struct _RtsSymbolVal { SymX(stg_block_takemvar) \ SymX(stg_block_putmvar) \ SymX(stg_seq_frame_info) \ - SymX(ErrorHdrHook) \ MAIN_CAP_SYM \ SymX(MallocFailHook) \ SymX(OnExitHook) \ SymX(OutOfHeapHook) \ - SymX(PatErrorHdrHook) \ - SymX(PostTraceHook) \ - SymX(PreTraceHook) \ SymX(StackOverflowHook) \ SymX(__encodeDouble) \ SymX(__encodeFloat) \ + SymX(addDLL) \ SymX(__gmpn_gcd_1) \ SymX(__gmpz_cmp) \ SymX(__gmpz_cmp_si) \ @@ -354,6 +364,7 @@ typedef struct _RtsSymbolVal { SymX(__int_encodeDouble) \ SymX(__int_encodeFloat) \ SymX(andIntegerzh_fast) \ + SymX(barf) \ SymX(blockAsyncExceptionszh_fast) \ SymX(catchzh_fast) \ SymX(cmp_thread) \ @@ -380,6 +391,7 @@ typedef struct _RtsSymbolVal { SymX(genSymZh) \ SymX(getProgArgv) \ SymX(getStablePtr) \ + SymX(initLinker) \ SymX(int2Integerzh_fast) \ SymX(integer2Intzh_fast) \ SymX(integer2Wordzh_fast) \ @@ -394,6 +406,8 @@ typedef struct _RtsSymbolVal { SymX(isFloatNaN) \ SymX(isFloatNegativeZero) \ SymX(killThreadzh_fast) \ + SymX(loadObj) \ + SymX(lookupSymbol) \ SymX(makeStablePtrzh_fast) \ SymX(minusIntegerzh_fast) \ SymX(mkApUpd0zh_fast) \ @@ -409,6 +423,7 @@ typedef struct _RtsSymbolVal { SymX(newPinnedByteArrayzh_fast) \ SymX(orIntegerzh_fast) \ SymX(performGC) \ + SymX(performMajorGC) \ SymX(plusIntegerzh_fast) \ SymX(prog_argc) \ SymX(prog_argv) \ @@ -420,6 +435,7 @@ typedef struct _RtsSymbolVal { SymX(remIntegerzh_fast) \ SymX(resetNonBlockingFd) \ SymX(resumeThread) \ + SymX(resolveObjs) \ SymX(rts_apply) \ SymX(rts_checkSchedStatus) \ SymX(rts_eval) \ @@ -539,6 +555,7 @@ typedef struct _RtsSymbolVal { SymX(tryPutMVarzh_fast) \ SymX(tryTakeMVarzh_fast) \ SymX(unblockAsyncExceptionszh_fast) \ + SymX(unloadObj) \ SymX(unsafeThawArrayzh_fast) \ SymX(waitReadzh_fast) \ SymX(waitWritezh_fast) \ @@ -554,13 +571,6 @@ typedef struct _RtsSymbolVal { #define RTS_LONG_LONG_SYMS /* nothing */ #endif -#ifdef HAVE_TERMIOS_H -#define RTS_TERMIOS_SYMS \ - Sym(saved_termios) -#else -#define RTS_TERMIOS_SYMS /* nothing */ -#endif - // 64-bit support functions in libgcc.a #if defined(__GNUC__) && SIZEOF_VOID_P <= 4 #define RTS_LIBGCC_SYMBOLS \ @@ -602,7 +612,6 @@ RTS_LONG_LONG_SYMS RTS_POSIX_ONLY_SYMBOLS RTS_MINGW_ONLY_SYMBOLS RTS_CYGWIN_ONLY_SYMBOLS -RTS_TERMIOS_SYMS RTS_LIBGCC_SYMBOLS #undef Sym #undef SymX @@ -679,6 +688,11 @@ static int linker_init_done = 0 ; static void *dl_prog_handle; #endif +/* dlopen(NULL,..) doesn't work so we grab libc explicitly */ +#if defined(openbsd_TARGET_OS) +static void *dl_libc_handle; +#endif + void initLinker( void ) { @@ -703,7 +717,14 @@ initLinker( void ) # endif # if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO) +# if defined(RTLD_DEFAULT) + dl_prog_handle = RTLD_DEFAULT; +# else dl_prog_handle = dlopen(NULL, RTLD_LAZY); +# if defined(openbsd_TARGET_OS) + dl_libc_handle = dlopen("libc.so", RTLD_LAZY); +# endif +# endif // RTLD_DEFAULT # endif } @@ -724,7 +745,7 @@ initLinker( void ) * 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) @@ -833,7 +854,12 @@ lookupSymbol( char *lbl ) if (val == NULL) { # if defined(OBJFORMAT_ELF) +# if defined(openbsd_TARGET_OS) + val = dlsym(dl_prog_handle, lbl); + return (val != NULL) ? val : dlsym(dl_libc_handle,lbl); +# else /* not openbsd */ return dlsym(dl_prog_handle, lbl); +# endif # elif defined(OBJFORMAT_MACHO) if(NSIsSymbolNameDefined(lbl)) { NSSymbol symbol = NSLookupAndBindSymbol(lbl); @@ -948,7 +974,7 @@ loadObj( char *path ) int r, n; #ifdef USE_MMAP int fd, pagesize; - void *map_addr; + void *map_addr = NULL; #else FILE *f; #endif @@ -957,24 +983,25 @@ loadObj( char *path ) /* fprintf(stderr, "loadObj %s\n", path ); */ - /* Check that we haven't already loaded this object. Don't give up - at this stage; ocGetNames_* will barf later. */ + /* Check that we haven't already loaded this object. + Ignore requests to load multiple times */ { ObjectCode *o; int is_dup = 0; for (o = objects; o; o = o->next) { - if (0 == strcmp(o->fileName, path)) + if (0 == strcmp(o->fileName, path)) { is_dup = 1; + break; /* don't need to search further */ + } } if (is_dup) { - fprintf(stderr, - "\n\n" + IF_DEBUG(linker, belch( "GHCi runtime linker: warning: looks like you're trying to load the\n" "same object file twice:\n" " %s\n" - "GHCi will continue, but a duplicate-symbol error may shortly follow.\n" - "\n" - , path); + "GHCi will ignore this, but be warned.\n" + , path)); + return 1; /* success */ } } @@ -1013,7 +1040,11 @@ loadObj( char *path ) /* On many architectures malloc'd memory isn't executable, so we need to use mmap. */ +#if defined(openbsd_TARGET_OS) + fd = open(path, O_RDONLY, S_IRUSR); +#else fd = open(path, O_RDONLY); +#endif if (fd == -1) barf("loadObj: can't open `%s'", path); @@ -1131,7 +1162,7 @@ unloadObj( char *path ) ASSERT(symhash != NULL); ASSERT(objects != NULL); - initLinker(); + initLinker(); prev = NULL; for (oc = objects; oc; prev = oc, oc = oc->next) { @@ -1919,9 +1950,9 @@ ocResolve_PEi386 ( ObjectCode* oc ) * * See Section 4.1 (last para) of the PE spec (rev6.0). * - * Nov2003 update: the GNU linker still doesn't correctly - * handle the generation of relocatable object files with - * overflown relocations. Hence the output to warn of potential + * Nov2003 update: the GNU linker still doesn't correctly + * handle the generation of relocatable object files with + * overflown relocations. Hence the output to warn of potential * troubles. */ COFF_reloc* rel = (COFF_reloc*) @@ -3012,7 +3043,7 @@ ia64_reloc_pcrel21(Elf_Addr target, Elf_Addr value, ObjectCode *oc) /* Support for MachO linking on Darwin/MacOS X on PowerPC chips by Wolfgang Thaller (wolfgang.thaller@gmx.net) - + I hereby formally apologize for the hackish nature of this code. Things that need to be done: *) implement ocVerifyImage_MachO @@ -3022,10 +3053,10 @@ ia64_reloc_pcrel21(Elf_Addr target, Elf_Addr value, ObjectCode *oc) /* ocAllocateJumpIslands_MachO - + Allocate additional space at the end of the object file image to make room for jump islands. - + PowerPC relative branch instructions have a 24 bit displacement field. As PPC code is always 4-byte-aligned, this yields a +-32MB range. If a particular imported symbol is outside this range, we have to redirect @@ -3053,7 +3084,7 @@ static int ocAllocateJumpIslands_MachO(ObjectCode* oc) unsigned long nundefsym = dsymLC->nundefsym; oc->island_start_symbol = dsymLC->iundefsym; oc->n_islands = nundefsym; - + if(nundefsym > 0) { #ifdef USE_MMAP @@ -3062,11 +3093,11 @@ static int ocAllocateJumpIslands_MachO(ObjectCode* oc) oc->image = stgReallocBytes( image, oc->fileSize + islandSize * nundefsym, "ocAllocateJumpIslands_MachO"); -#endif +#endif oc->jump_islands = oc->image + oc->fileSize; memset(oc->jump_islands, 0, islandSize * nundefsym); } - + break; // there can be only one LC_DSYMTAB } lc = (struct load_command *) ( ((char*)lc) + lc->cmdsize ); @@ -3089,14 +3120,14 @@ static int resolveImports( struct nlist *nlist) { unsigned i; - + for(i=0;i*4size;i++) { // according to otool, reserved1 contains the first index into the indirect symbol table struct nlist *symbol = &nlist[indirectSyms[sect->reserved1+i]]; char *nm = image + symLC->stroff + symbol->n_un.n_strx; void *addr = NULL; - + if((symbol->n_type & N_TYPE) == N_UNDF && (symbol->n_type & N_EXT) && (symbol->n_value != 0)) addr = (void*) (symbol->n_value); @@ -3113,7 +3144,7 @@ static int resolveImports( checkProddableBlock(oc,((void**)(image + sect->offset)) + i); ((void**)(image + sect->offset))[i] = addr; } - + return 1; } @@ -3126,19 +3157,19 @@ static void* makeJumpIsland( symbolNumber - oc->island_start_symbol > oc->n_islands) return NULL; symbolNumber -= oc->island_start_symbol; - + void *island = (void*) ((char*)oc->jump_islands + islandSize * symbolNumber); unsigned long *p = (unsigned long*) island; - + // lis r12, hi16(target) *p++ = 0x3d800000 | ( ((unsigned long) target) >> 16 ); // ori r12, r12, lo16(target) - *p++ = 0x618c0000 | ( ((unsigned long) target) & 0xFFFF ); + *p++ = 0x618c0000 | ( ((unsigned long) target) & 0xFFFF ); // mtctr r12 *p++ = 0x7d8903a6; // bctr *p++ = 0x4e800420; - + return (void*) island; } @@ -3147,7 +3178,7 @@ static char* relocateAddress( int nSections, struct section* sections, unsigned long address) -{ +{ int i; for(i = 0; i < nSections; i++) { @@ -3164,13 +3195,13 @@ static char* relocateAddress( static int relocateSection( ObjectCode* oc, - char *image, + char *image, struct symtab_command *symLC, struct nlist *nlist, int nSections, struct section* sections, struct section *sect) { struct relocation_info *relocs; int i,n; - + if(!strcmp(sect->sectname,"__la_symbol_ptr")) return 1; else if(!strcmp(sect->sectname,"__nl_symbol_ptr")) @@ -3178,14 +3209,14 @@ static int relocateSection( n = sect->nreloc; relocs = (struct relocation_info*) (image + sect->reloff); - + for(i=0;ir_pcrel) { if(scat->r_length == 2) @@ -3193,7 +3224,7 @@ static int relocateSection( unsigned long word = 0; unsigned long* wordPtr = (unsigned long*) (image + sect->offset + scat->r_address); checkProddableBlock(oc,wordPtr); - + // Step 1: Figure out what the relocated value should be if(scat->r_type == GENERIC_RELOC_VANILLA) { @@ -3206,11 +3237,11 @@ static int relocateSection( { struct scattered_relocation_info *pair = (struct scattered_relocation_info*) &relocs[i+1]; - + if(!pair->r_scattered || pair->r_type != PPC_RELOC_PAIR) barf("Invalid Mach-O file: " "PPC_RELOC_*_SECTDIFF not followed by PPC_RELOC_PAIR"); - + word = (unsigned long) (relocateAddress(oc, nSections, sections, scat->r_value) - relocateAddress(oc, nSections, sections, pair->r_value)); @@ -3239,7 +3270,7 @@ static int relocateSection( } } } - + continue; // FIXME: I hope it's OK to ignore all the others. } else @@ -3247,16 +3278,16 @@ static int relocateSection( struct relocation_info *reloc = &relocs[i]; if(reloc->r_pcrel && !reloc->r_extern) continue; - + if(reloc->r_length == 2) { unsigned long word = 0; unsigned long jumpIsland = 0; long offsetToJumpIsland; - + unsigned long* wordPtr = (unsigned long*) (image + sect->offset + reloc->r_address); checkProddableBlock(oc,wordPtr); - + if(reloc->r_type == GENERIC_RELOC_VANILLA) { word = *wordPtr; @@ -3285,11 +3316,11 @@ static int relocateSection( if(!reloc->r_extern) { - long delta = + long delta = sections[reloc->r_symbolnum-1].offset - sections[reloc->r_symbolnum-1].addr + ((long) image); - + word += delta; } else @@ -3302,7 +3333,7 @@ static int relocateSection( belch("\nunknown symbol `%s'", nm); return 0; } - + if(reloc->r_pcrel) { jumpIsland = (long) makeJumpIsland(oc,reloc->r_symbolnum,(void*)word); @@ -3314,7 +3345,7 @@ static int relocateSection( } } } - + if(reloc->r_type == GENERIC_RELOC_VANILLA) { *wordPtr = word; @@ -3345,7 +3376,7 @@ static int relocateSection( if(jumpIsland == 0) barf("unconditional relative branch out of range: " "no jump island available"); - + word = offsetToJumpIsland; if((long)word > (long)0x01FFFFFF || (long)word < (long)0xFFE00000) barf("unconditional relative branch out of range: " @@ -3388,36 +3419,36 @@ static int ocGetNames_MachO(ObjectCode* oc) lc = (struct load_command *) ( ((char*)lc) + lc->cmdsize ); } - sections = (struct section*) (segLC+1); + sections = (struct section*) (segLC+1); nlist = (struct nlist*) (image + symLC->symoff); for(i=0;insects;i++) { if(sections[i].size == 0) continue; - + if((sections[i].flags & SECTION_TYPE) == S_ZEROFILL) { char * zeroFillArea = stgCallocBytes(1,sections[i].size, "ocGetNames_MachO(common symbols)"); sections[i].offset = zeroFillArea - image; } - + if(!strcmp(sections[i].sectname,"__text")) - addSection(oc, SECTIONKIND_CODE_OR_RODATA, + addSection(oc, SECTIONKIND_CODE_OR_RODATA, (void*) (image + sections[i].offset), (void*) (image + sections[i].offset + sections[i].size)); else if(!strcmp(sections[i].sectname,"__const")) - addSection(oc, SECTIONKIND_RWDATA, + addSection(oc, SECTIONKIND_RWDATA, (void*) (image + sections[i].offset), (void*) (image + sections[i].offset + sections[i].size)); else if(!strcmp(sections[i].sectname,"__data")) - addSection(oc, SECTIONKIND_RWDATA, + addSection(oc, SECTIONKIND_RWDATA, (void*) (image + sections[i].offset), (void*) (image + sections[i].offset + sections[i].size)); else if(!strcmp(sections[i].sectname,"__bss") || !strcmp(sections[i].sectname,"__common")) - addSection(oc, SECTIONKIND_RWDATA, + addSection(oc, SECTIONKIND_RWDATA, (void*) (image + sections[i].offset), (void*) (image + sections[i].offset + sections[i].size)); @@ -3443,35 +3474,35 @@ static int ocGetNames_MachO(ObjectCode* oc) } oc->symbols = stgMallocBytes(oc->n_symbols * sizeof(char*), "ocGetNames_MachO(oc->symbols)"); - + // insert symbols into hash table for(i=dsymLC->iextdefsym,curSymbol=0;iiextdefsym+dsymLC->nextdefsym;i++) { if((nlist[i].n_type & N_TYPE) == N_SECT) { char *nm = image + symLC->stroff + nlist[i].n_un.n_strx; - ghciInsertStrHashTable(oc->fileName, symhash, nm, image + + ghciInsertStrHashTable(oc->fileName, symhash, nm, image + sections[nlist[i].n_sect-1].offset - sections[nlist[i].n_sect-1].addr + nlist[i].n_value); oc->symbols[curSymbol++] = nm; } } - + // 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 + + 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++) @@ -3481,12 +3512,12 @@ static int ocGetNames_MachO(ObjectCode* oc) { char *nm = image + symLC->stroff + nlist[i].n_un.n_strx; unsigned long sz = nlist[i].n_value; - + nlist[i].n_value = commonCounter; - + ghciInsertStrHashTable(oc->fileName, symhash, nm, (void*)commonCounter); oc->symbols[curSymbol++] = nm; - + commonCounter += sz; } } @@ -3516,8 +3547,8 @@ static int ocResolve_MachO(ObjectCode* oc) dsymLC = (struct dysymtab_command*) lc; lc = (struct load_command *) ( ((char*)lc) + lc->cmdsize ); } - - sections = (struct section*) (segLC+1); + + sections = (struct section*) (segLC+1); nlist = (struct nlist*) (image + symLC->symoff); for(i=0;insects;i++) @@ -3527,7 +3558,7 @@ static int ocResolve_MachO(ObjectCode* oc) else if(!strcmp(sections[i].sectname,"__nl_symbol_ptr")) nl_ptrs = §ions[i]; } - + indirectSyms = (unsigned long*) (image + dsymLC->indirectsymoff); if(la_ptrs) @@ -3536,7 +3567,7 @@ static int ocResolve_MachO(ObjectCode* oc) if(nl_ptrs) if(!resolveImports(oc,image,symLC,nl_ptrs,indirectSyms,nlist)) return 0; - + for(i=0;insects;i++) { if(!relocateSection(oc,image,symLC,nlist,segLC->nsects,sections,§ions[i])) @@ -3546,7 +3577,7 @@ static int ocResolve_MachO(ObjectCode* oc) /* Free the local symbol table; we won't need it again. */ freeHashTable(oc->lochash, NULL); oc->lochash = NULL; - + /* Flush the data & instruction caches. Because the PPC has split data/instruction caches, we have to @@ -3579,11 +3610,11 @@ static void machoInitSymbolsWithoutUnderscore() { void *p; -#undef Sym +#undef Sym #define Sym(x) \ __asm__ ("lis %0,hi16(" #x ")\n\tori %0,%0,lo16(" #x ")" : "=r" (p)); \ ghciInsertStrHashTable("(GHCi built-in symbols)", symhash, #x, p); - + RTS_MACHO_NOUNDERLINE_SYMBOLS }