X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FLinker.c;h=9ee1858f4c267f5a7b4c16e3d5f794d1db8223e7;hb=f97dcf9fc2ea2a419087bca53f2fea811c5181a9;hp=b8969d838f29427903d2c326ec2cf61e9665145c;hpb=a98dfa6e445bdf6a5ac24b9496b51a21fd8113db;p=ghc-hetmet.git diff --git a/ghc/rts/Linker.c b/ghc/rts/Linker.c index b8969d8..9ee1858 100644 --- a/ghc/rts/Linker.c +++ b/ghc/rts/Linker.c @@ -10,7 +10,9 @@ #include "PosixSource.h" #endif -// Linux needs _GNU_SOURCE to get RTLD_DEFAULT from . +/* Linux needs _GNU_SOURCE to get RTLD_DEFAULT from and + MREMAP_MAYMOVE from . + */ #ifdef __linux__ #define _GNU_SOURCE #endif @@ -36,13 +38,11 @@ #include #endif -#if defined(HAVE_FRAMEWORK_HASKELLSUPPORT) -#include -#elif defined(HAVE_DLFCN_H) +#if defined(HAVE_DLFCN_H) #include #endif -#if defined(cygwin32_TARGET_OS) +#if defined(cygwin32_HOST_OS) #ifdef HAVE_DIRENT_H #include #endif @@ -58,12 +58,12 @@ #include #endif -#if defined(ia64_TARGET_ARCH) || defined(openbsd_TARGET_OS) +#if defined(ia64_HOST_ARCH) || defined(openbsd_HOST_OS) || defined(linux_HOST_OS) || defined(freebsd_HOST_OS) #define USE_MMAP #include #include -#if defined(openbsd_TARGET_OS) +#if defined(openbsd_HOST_OS) || defined(linux_HOST_OS) || defined(freebsd_HOST_OS) #ifdef HAVE_UNISTD_H #include #endif @@ -71,13 +71,13 @@ #endif -#if defined(linux_TARGET_OS) || defined(solaris2_TARGET_OS) || defined(freebsd_TARGET_OS) || defined(netbsd_TARGET_OS) || defined(openbsd_TARGET_OS) +#if defined(linux_HOST_OS) || defined(solaris2_HOST_OS) || defined(freebsd_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS) # define OBJFORMAT_ELF -#elif defined(cygwin32_TARGET_OS) || defined (mingw32_TARGET_OS) +#elif defined(cygwin32_HOST_OS) || defined (mingw32_HOST_OS) # define OBJFORMAT_PEi386 # include # include -#elif defined(darwin_TARGET_OS) +#elif defined(darwin_HOST_OS) # include # define OBJFORMAT_MACHO # include @@ -96,7 +96,7 @@ ObjectCode *objects = NULL; /* initially empty */ static int ocVerifyImage_ELF ( ObjectCode* oc ); static int ocGetNames_ELF ( ObjectCode* oc ); static int ocResolve_ELF ( ObjectCode* oc ); -#if defined(powerpc_TARGET_ARCH) +#if defined(powerpc_HOST_ARCH) static int ocAllocateJumpIslands_ELF ( ObjectCode* oc ); #endif #elif defined(OBJFORMAT_PEi386) @@ -134,13 +134,13 @@ typedef struct _RtsSymbolVal { #define Maybe_Stable_Names #endif -#if !defined (mingw32_TARGET_OS) +#if !defined (mingw32_HOST_OS) #define RTS_POSIX_ONLY_SYMBOLS \ SymX(stg_sig_install) \ Sym(nocldstop) #endif -#if defined (cygwin32_TARGET_OS) +#if defined (cygwin32_HOST_OS) #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 @@ -224,10 +224,10 @@ typedef struct _RtsSymbolVal { SymX(utime) \ SymX(waitpid) -#elif !defined(mingw32_TARGET_OS) +#elif !defined(mingw32_HOST_OS) #define RTS_MINGW_ONLY_SYMBOLS /**/ #define RTS_CYGWIN_ONLY_SYMBOLS /**/ -#else /* defined(mingw32_TARGET_OS) */ +#else /* defined(mingw32_HOST_OS) */ #define RTS_POSIX_ONLY_SYMBOLS /**/ #define RTS_CYGWIN_ONLY_SYMBOLS /**/ @@ -391,6 +391,8 @@ typedef struct _RtsSymbolVal { SymX(andIntegerzh_fast) \ SymX(atomicallyzh_fast) \ SymX(barf) \ + SymX(debugBelch) \ + SymX(errorBelch) \ SymX(blockAsyncExceptionszh_fast) \ SymX(catchzh_fast) \ SymX(catchRetryzh_fast) \ @@ -421,7 +423,14 @@ typedef struct _RtsSymbolVal { SymX(genericRaise) \ SymX(getProgArgv) \ SymX(getStablePtr) \ - SymX(initLinker) \ + SymX(hs_init) \ + SymX(hs_exit) \ + SymX(hs_set_argv) \ + SymX(hs_add_root) \ + SymX(hs_perform_gc) \ + SymX(hs_free_stable_ptr) \ + SymX(hs_free_fun_ptr) \ + SymX(initLinker) \ SymX(int2Integerzh_fast) \ SymX(integer2Intzh_fast) \ SymX(integer2Wordzh_fast) \ @@ -526,6 +535,7 @@ typedef struct _RtsSymbolVal { SymX(stg_IND_STATIC_info) \ SymX(stg_INTLIKE_closure) \ SymX(stg_MUT_ARR_PTRS_FROZEN_info) \ + SymX(stg_MUT_ARR_PTRS_FROZEN0_info) \ SymX(stg_WEAK_info) \ SymX(stg_ap_0_info) \ SymX(stg_ap_v_info) \ @@ -602,7 +612,7 @@ typedef struct _RtsSymbolVal { Sym(__ashrdi3) \ Sym(__lshrdi3) \ Sym(__eprintf) -#elif defined(ia64_TARGET_ARCH) +#elif defined(ia64_HOST_ARCH) #define RTS_LIBGCC_SYMBOLS \ Sym(__divdi3) \ Sym(__udivdi3) \ @@ -614,7 +624,7 @@ typedef struct _RtsSymbolVal { #define RTS_LIBGCC_SYMBOLS #endif -#ifdef darwin_TARGET_OS +#ifdef darwin_HOST_OS // Symbols that don't have a leading underscore // on Mac OS X. They have to receive special treatment, // see machoInitSymbolsWithoutUnderscore() @@ -711,7 +721,7 @@ static void *dl_prog_handle; #endif /* dlopen(NULL,..) doesn't work so we grab libc explicitly */ -#if defined(openbsd_TARGET_OS) +#if defined(openbsd_HOST_OS) static void *dl_libc_handle; #endif @@ -743,7 +753,7 @@ initLinker( void ) dl_prog_handle = RTLD_DEFAULT; # else dl_prog_handle = dlopen(NULL, RTLD_LAZY); -# if defined(openbsd_TARGET_OS) +# if defined(openbsd_HOST_OS) dl_libc_handle = dlopen("libc.so", RTLD_LAZY); # endif # endif // RTLD_DEFAULT @@ -876,7 +886,7 @@ lookupSymbol( char *lbl ) if (val == NULL) { # if defined(OBJFORMAT_ELF) -# if defined(openbsd_TARGET_OS) +# if defined(openbsd_HOST_OS) val = dlsym(dl_prog_handle, lbl); return (val != NULL) ? val : dlsym(dl_libc_handle,lbl); # else /* not openbsd */ @@ -979,7 +989,7 @@ void ghci_enquire ( char* addr ) } #endif -#ifdef ia64_TARGET_ARCH +#ifdef ia64_HOST_ARCH static unsigned int PLTSize(void); #endif @@ -1062,7 +1072,7 @@ loadObj( char *path ) /* On many architectures malloc'd memory isn't executable, so we need to use mmap. */ -#if defined(openbsd_TARGET_OS) +#if defined(openbsd_HOST_OS) fd = open(path, O_RDONLY, S_IRUSR); #else fd = open(path, O_RDONLY); @@ -1072,7 +1082,7 @@ loadObj( char *path ) pagesize = getpagesize(); -#ifdef ia64_TARGET_ARCH +#ifdef ia64_HOST_ARCH /* The PLT needs to be right before the object */ n = ROUND_UP(PLTSize(), pagesize); oc->plt = mmap(NULL, n, PROT_EXEC|PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); @@ -1110,7 +1120,7 @@ loadObj( char *path ) # if defined(OBJFORMAT_MACHO) r = ocAllocateJumpIslands_MachO ( oc ); if (!r) { return r; } -# elif defined(OBJFORMAT_ELF) && defined(powerpc_TARGET_ARCH) +# elif defined(OBJFORMAT_ELF) && defined(powerpc_HOST_ARCH) r = ocAllocateJumpIslands_ELF ( oc ); if (!r) { return r; } #endif @@ -1284,7 +1294,7 @@ static void addSection ( ObjectCode* oc, SectionKind kind, * PowerPC specifics (jump islands) * ------------------------------------------------------------------------*/ -#if defined(powerpc_TARGET_ARCH) +#if defined(powerpc_HOST_ARCH) /* ocAllocateJumpIslands @@ -1304,21 +1314,51 @@ static void addSection ( ObjectCode* oc, SectionKind kind, static int ocAllocateJumpIslands( ObjectCode* oc, int count, int first ) { +#ifdef USE_MMAP + int pagesize, n, m; +#endif int aligned; if( count > 0 ) { -#ifdef USE_MMAP - #error ocAllocateJumpIslands doesnt want USE_MMAP to be defined -#endif // round up to the nearest 4 aligned = (oc->fileSize + 3) & ~3; +#ifdef USE_MMAP + #ifndef linux_HOST_OS /* mremap is a linux extension */ + #error ocAllocateJumpIslands doesnt want USE_MMAP to be defined + #endif + + pagesize = getpagesize(); + n = ROUND_UP( oc->fileSize, pagesize ); + m = ROUND_UP( aligned + sizeof (ppcJumpIsland) * count, pagesize ); + + /* The effect of this mremap() call is only the ensure that we have + * a sufficient number of virtually contiguous pages. As returned from + * mremap, the pages past the end of the file are not backed. We give + * them a backing by using MAP_FIXED to map in anonymous pages. + */ + if( (oc->image = mremap( oc->image, n, m, MREMAP_MAYMOVE )) == MAP_FAILED ) + { + errorBelch( "Unable to mremap for Jump Islands\n" ); + return 0; + } + + if( mmap( oc->image + n, m - n, PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, 0, 0 ) == MAP_FAILED ) + { + errorBelch( "Unable to mmap( MAP_FIXED ) for Jump Islands\n" ); + return 0; + } + +#else oc->image = stgReallocBytes( oc->image, - aligned + sizeof( ppcJumpIsland ) * count, + aligned + sizeof (ppcJumpIsland) * count, "ocAllocateJumpIslands" ); - oc->jump_islands = (ppcJumpIsland *) (((char *) oc->image) + aligned); - memset( oc->jump_islands, 0, sizeof( ppcJumpIsland ) * count ); +#endif /* USE_MMAP */ + + oc->jump_islands = (ppcJumpIsland *) (oc->image + aligned); + memset( oc->jump_islands, 0, sizeof (ppcJumpIsland) * count ); } else oc->jump_islands = NULL; @@ -2188,14 +2228,14 @@ ocResolve_PEi386 ( ObjectCode* oc ) #define FALSE 0 #define TRUE 1 -#if defined(sparc_TARGET_ARCH) +#if defined(sparc_HOST_ARCH) # define ELF_TARGET_SPARC /* Used inside */ -#elif defined(i386_TARGET_ARCH) +#elif defined(i386_HOST_ARCH) # define ELF_TARGET_386 /* Used inside */ -#elif defined(x86_64_TARGET_ARCH) +#elif defined(x86_64_HOST_ARCH) # define ELF_TARGET_X64_64 # define ELF_64BIT -#elif defined (ia64_TARGET_ARCH) +#elif defined (ia64_HOST_ARCH) # define ELF_TARGET_IA64 /* Used inside */ # define ELF_64BIT # define ELF_FUNCTION_DESC /* calling convention uses function descriptors */ @@ -2203,7 +2243,7 @@ ocResolve_PEi386 ( ObjectCode* oc ) # define ELF_NEED_PLT /* needs Procedure Linkage Tables */ #endif -#if !defined(openbsd_TARGET_OS) +#if !defined(openbsd_HOST_OS) #include #else /* openbsd elf has things in different places, with diff names */ @@ -2325,7 +2365,7 @@ copyFunctionDesc(Elf_Addr target) #endif #ifdef ELF_NEED_PLT -#ifdef ia64_TARGET_ARCH +#ifdef ia64_HOST_ARCH static void ia64_reloc_gprel22(Elf_Addr target, Elf_Addr value); static void ia64_reloc_pcrel21(Elf_Addr target, Elf_Addr value, ObjectCode *oc); @@ -2406,7 +2446,7 @@ findElfSection ( void* objImage, Elf_Word sh_type ) return ptr; } -#if defined(ia64_TARGET_ARCH) +#if defined(ia64_HOST_ARCH) static Elf_Addr findElfSegment ( void* objImage, Elf_Addr vaddr ) { @@ -2852,7 +2892,7 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC, value = S + A; switch (ELF_R_TYPE(info)) { -# ifdef i386_TARGET_ARCH +# ifdef i386_HOST_ARCH case R_386_32: *pP = value; break; case R_386_PC32: *pP = value - P; break; # endif @@ -2887,7 +2927,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, target_shndx, symtab_shndx )); for (j = 0; j < nent; j++) { -#if defined(DEBUG) || defined(sparc_TARGET_ARCH) || defined(ia64_TARGET_ARCH) || defined(powerpc_TARGET_ARCH) +#if defined(DEBUG) || defined(sparc_HOST_ARCH) || defined(ia64_HOST_ARCH) || defined(powerpc_HOST_ARCH) /* This #ifdef only serves to avoid unused-var warnings. */ Elf_Addr offset = rtab[j].r_offset; Elf_Addr P = targ + offset; @@ -2897,13 +2937,13 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, Elf_Addr S; void* S_tmp; Elf_Addr value; -# if defined(sparc_TARGET_ARCH) +# if defined(sparc_HOST_ARCH) Elf_Word* pP = (Elf_Word*)P; Elf_Word w1, w2; -# elif defined(ia64_TARGET_ARCH) +# elif defined(ia64_HOST_ARCH) Elf64_Xword *pP = (Elf64_Xword *)P; Elf_Addr addr; -# elif defined(powerpc_TARGET_ARCH) +# elif defined(powerpc_HOST_ARCH) Elf_Sword delta; # endif @@ -2957,7 +2997,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, value = S + A; switch (ELF_R_TYPE(info)) { -# if defined(sparc_TARGET_ARCH) +# if defined(sparc_HOST_ARCH) case R_SPARC_WDISP30: w1 = *pP & 0xC0000000; w2 = (Elf_Word)((value - P) >> 2); @@ -2994,7 +3034,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, w2 = (Elf_Word)value; *pP = w2; break; -# elif defined(ia64_TARGET_ARCH) +# elif defined(ia64_HOST_ARCH) case R_IA64_DIR64LSB: case R_IA64_FPTR64LSB: *pP = value; @@ -3022,7 +3062,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, /* This goes with R_IA64_LTOFF22X and points to the load to * convert into a move. We don't implement relaxation. */ break; -# elif defined(powerpc_TARGET_ARCH) +# elif defined(powerpc_HOST_ARCH) case R_PPC_ADDR16_LO: *(Elf32_Half*) P = value; break; @@ -3113,7 +3153,7 @@ ocResolve_ELF ( ObjectCode* oc ) freeHashTable(oc->lochash, NULL); oc->lochash = NULL; -#if defined(powerpc_TARGET_ARCH) +#if defined(powerpc_HOST_ARCH) ocFlushInstructionCache( oc ); #endif @@ -3127,7 +3167,7 @@ ocResolve_ELF ( ObjectCode* oc ) * take care of the most common relocations. */ -#ifdef ia64_TARGET_ARCH +#ifdef ia64_HOST_ARCH static Elf64_Xword ia64_extract_instruction(Elf64_Xword *target) @@ -3216,7 +3256,7 @@ ia64_reloc_pcrel21(Elf_Addr target, Elf_Addr value, ObjectCode *oc) * PowerPC ELF specifics */ -#ifdef powerpc_TARGET_ARCH +#ifdef powerpc_HOST_ARCH static int ocAllocateJumpIslands_ELF( ObjectCode *oc ) { @@ -3282,7 +3322,7 @@ static int ocAllocateJumpIslands_MachO(ObjectCode* oc) // symbol, so we don't have to allocate too many // jump islands. struct symtab_command *symLC = (struct symtab_command *) lc; - int min = symLC->nsyms, max = 0; + unsigned min = symLC->nsyms, max = 0; struct nlist *nlist = symLC ? (struct nlist*) ((char*) oc->image + symLC->symoff) : NULL; @@ -3313,7 +3353,7 @@ static int ocAllocateJumpIslands_MachO(ObjectCode* oc) return ocAllocateJumpIslands(oc,0,0); } -static int ocVerifyImage_MachO(ObjectCode* oc) +static int ocVerifyImage_MachO(ObjectCode* oc STG_UNUSED) { // FIXME: do some verifying here return 1; @@ -3356,7 +3396,7 @@ static int resolveImports( return 1; } -static char* relocateAddress( +static unsigned long relocateAddress( ObjectCode* oc, int nSections, struct section* sections, @@ -3368,12 +3408,13 @@ static char* relocateAddress( if(sections[i].addr <= address && address < sections[i].addr + sections[i].size) { - return oc->image + sections[i].offset + address - sections[i].addr; + return (unsigned long)oc->image + + sections[i].offset + address - sections[i].addr; } } barf("Invalid Mach-O file:" "Address out of bounds while relocating object file"); - return NULL; + return 0; } static int relocateSection( @@ -3509,7 +3550,9 @@ static int relocateSection( { unsigned long word = 0; unsigned long jumpIsland = 0; - long offsetToJumpIsland; + long offsetToJumpIsland = 0xBADBAD42; // initialise to bad value + // to avoid warning and to catch + // bugs. unsigned long* wordPtr = (unsigned long*) (image + sect->offset + reloc->r_address); checkProddableBlock(oc,wordPtr); @@ -3553,7 +3596,7 @@ static int relocateSection( { struct nlist *symbol = &nlist[reloc->r_symbolnum]; char *nm = image + symLC->stroff + symbol->n_un.n_strx; - unsigned long symbolAddress = (unsigned long) (lookupSymbol(nm)); + void *symbolAddress = lookupSymbol(nm); if(!symbolAddress) { errorBelch("\nunknown symbol `%s'", nm); @@ -3565,7 +3608,7 @@ static int relocateSection( // In the .o file, this should be a relative jump to NULL // and we'll change it to a jump to a relative jump to the symbol ASSERT(-word == reloc->r_address); - word = symbolAddress; + word = (unsigned long) symbolAddress; jumpIsland = makeJumpIsland(oc,reloc->r_symbolnum,word); word -= ((long)image) + sect->offset + reloc->r_address; if(jumpIsland != 0) @@ -3576,7 +3619,7 @@ static int relocateSection( } else { - word += symbolAddress; + word += (unsigned long) symbolAddress; } } @@ -3634,7 +3677,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)); - unsigned i,curSymbol; + unsigned i,curSymbol = 0; struct segment_command *segLC = NULL; struct section *sections; struct symtab_command *symLC = NULL; @@ -3716,7 +3759,6 @@ static int ocGetNames_MachO(ObjectCode* oc) if(symLC) { - curSymbol = 0; for(i=0;insyms;i++) { if(nlist[i].n_type & N_STAB) @@ -3829,7 +3871,7 @@ static int ocResolve_MachO(ObjectCode* oc) freeHashTable(oc->lochash, NULL); oc->lochash = NULL; -#if defined (powerpc_TARGET_ARCH) +#if defined (powerpc_HOST_ARCH) ocFlushInstructionCache( oc ); #endif