X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FLinker.c;h=6387ee1fdf707f9cc044226fef635d54ae08111e;hb=73855b2d99dfb60b89c057f43ab313b243cfc574;hp=9833b310fa70ecb8b2dfed05770d5aec285c1fbe;hpb=3d982281f91ee40e20d03bd5c9607f032d9215a6;p=ghc-hetmet.git diff --git a/rts/Linker.c b/rts/Linker.c index 9833b31..6387ee1 100644 --- a/rts/Linker.c +++ b/rts/Linker.c @@ -71,16 +71,14 @@ #include #endif -#if defined(ia64_HOST_ARCH) || defined(linux_HOST_OS) || defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS) +#if defined(linux_HOST_OS) || defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS) || defined(darwin_HOST_OS) #define USE_MMAP #include #include -#if defined(linux_HOST_OS) || defined(freebsd_HOST_OS) || defined(dragonfly_HOST_OS) || defined(netbsd_HOST_OS) || defined(openbsd_HOST_OS) #ifdef HAVE_UNISTD_H #include #endif -#endif #endif @@ -109,6 +107,10 @@ #endif #endif +#if defined(x86_64_HOST_ARCH) && defined(darwin_HOST_OS) +#define ALWAYS_PIC +#endif + /* Hash table mapping symbol names to Symbol */ static /*Str*/HashTable *symhash; @@ -136,7 +138,9 @@ static int ocVerifyImage_MachO ( ObjectCode* oc ); static int ocGetNames_MachO ( ObjectCode* oc ); static int ocResolve_MachO ( ObjectCode* oc ); +#ifndef USE_MMAP static int machoGetMisalignment( FILE * ); +#endif #if defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH) static int ocAllocateSymbolExtras_MachO ( ObjectCode* oc ); #endif @@ -208,7 +212,7 @@ static void machoInitSymbolsWithoutUnderscore( void ); * We pick a default address based on the OS, but also make this * configurable via an RTS flag (+RTS -xm) */ -#if defined(x86_64_HOST_ARCH) +#if !defined(ALWAYS_PIC) && defined(x86_64_HOST_ARCH) #if defined(MAP_32BIT) // Try to use MAP_32BIT @@ -457,7 +461,7 @@ typedef struct _RtsSymbolVal { SymI_NeedsProto(closedir) #endif -#if defined(darwin_TARGET_OS) && HAVE_PRINTF_LDBLSTUB +#if defined(darwin_HOST_OS) && HAVE_PRINTF_LDBLSTUB #define RTS_DARWIN_ONLY_SYMBOLS \ SymI_NeedsProto(asprintf$LDBLStub) \ SymI_NeedsProto(err$LDBLStub) \ @@ -515,9 +519,9 @@ typedef struct _RtsSymbolVal { #if !defined(mingw32_HOST_OS) #define RTS_USER_SIGNALS_SYMBOLS \ - SymI_HasProto(setIOManagerPipe) \ + SymI_HasProto(setIOManagerControlFd) \ + SymI_HasProto(setIOManagerWakeupFd) \ SymI_HasProto(ioManagerWakeup) \ - SymI_HasProto(ioManagerSync) \ SymI_HasProto(blockUserSignals) \ SymI_HasProto(unblockUserSignals) #else @@ -743,8 +747,9 @@ typedef struct _RtsSymbolVal { SymI_HasProto(debugBelch) \ SymI_HasProto(errorBelch) \ SymI_HasProto(sysErrorBelch) \ - SymI_HasProto(stg_asyncExceptionsBlockedzh) \ - SymI_HasProto(stg_blockAsyncExceptionszh) \ + SymI_HasProto(stg_getMaskingStatezh) \ + SymI_HasProto(stg_maskAsyncExceptionszh) \ + SymI_HasProto(stg_maskUninterruptiblezh) \ SymI_HasProto(stg_catchzh) \ SymI_HasProto(stg_catchRetryzh) \ SymI_HasProto(stg_catchSTMzh) \ @@ -765,11 +770,12 @@ typedef struct _RtsSymbolVal { SymI_HasProto(forkOS_createThread) \ SymI_HasProto(freeHaskellFunctionPtr) \ SymI_HasProto(getOrSetTypeableStore) \ - SymI_HasProto(getOrSetGHCConcSignalHandlerStore) \ - SymI_HasProto(getOrSetGHCConcPendingEventsStore) \ - SymI_HasProto(getOrSetGHCConcPendingDelaysStore) \ - SymI_HasProto(getOrSetGHCConcIOManagerThreadStore) \ - SymI_HasProto(getOrSetGHCConcProddingStore) \ + SymI_HasProto(getOrSetGHCConcSignalSignalHandlerStore) \ + SymI_HasProto(getOrSetGHCConcWindowsPendingDelaysStore) \ + SymI_HasProto(getOrSetGHCConcWindowsIOManagerThreadStore) \ + SymI_HasProto(getOrSetGHCConcWindowsProddingStore) \ + SymI_HasProto(getOrSetSystemEventThreadEventManagerStore) \ + SymI_HasProto(getOrSetSystemEventThreadIOManagerThreadStore) \ SymI_HasProto(genSymZh) \ SymI_HasProto(genericRaise) \ SymI_HasProto(getProgArgv) \ @@ -788,6 +794,7 @@ typedef struct _RtsSymbolVal { SymI_HasProto(stg_unpackClosurezh) \ SymI_HasProto(stg_getApStackValzh) \ SymI_HasProto(stg_getSparkzh) \ + SymI_HasProto(stg_numSparkszh) \ SymI_HasProto(stg_isCurrentThreadBoundzh) \ SymI_HasProto(stg_isEmptyMVarzh) \ SymI_HasProto(stg_killThreadzh) \ @@ -870,6 +877,7 @@ typedef struct _RtsSymbolVal { SymI_HasProto(rts_unlock) \ SymI_HasProto(rts_unsafeGetMyCapability) \ SymI_HasProto(rtsSupportsBoundThreads) \ + SymI_HasProto(rts_isProfiled) \ SymI_HasProto(setProgArgv) \ SymI_HasProto(startupHaskell) \ SymI_HasProto(shutdownHaskell) \ @@ -950,7 +958,7 @@ typedef struct _RtsSymbolVal { SymI_HasProto(stg_threadStatuszh) \ SymI_HasProto(stg_tryPutMVarzh) \ SymI_HasProto(stg_tryTakeMVarzh) \ - SymI_HasProto(stg_unblockAsyncExceptionszh) \ + SymI_HasProto(stg_unmaskAsyncExceptionszh) \ SymI_HasProto(unloadObj) \ SymI_HasProto(stg_unsafeThawArrayzh) \ SymI_HasProto(stg_waitReadzh) \ @@ -958,6 +966,7 @@ typedef struct _RtsSymbolVal { SymI_HasProto(stg_writeTVarzh) \ SymI_HasProto(stg_yieldzh) \ SymI_NeedsProto(stg_interp_constr_entry) \ + SymI_HasProto(stg_arg_bitmaps) \ SymI_HasProto(alloc_blocks_lim) \ SymI_HasProto(g0) \ SymI_HasProto(allocate) \ @@ -1003,7 +1012,7 @@ typedef struct _RtsSymbolVal { /* entirely bogus claims about types of these symbols */ #define SymI_NeedsProto(vvv) extern void vvv(void); -#if defined(__PIC__) && defined(mingw32_TARGET_OS) +#if defined(__PIC__) && defined(mingw32_HOST_OS) #define SymE_HasProto(vvv) SymE_HasProto(vvv); #define SymE_NeedsProto(vvv) extern void _imp__ ## vvv (void); #else @@ -1162,7 +1171,7 @@ initLinker( void ) ASSERT( compileResult == 0 ); # endif -#if defined(x86_64_HOST_ARCH) +#if !defined(ALWAYS_PIC) && defined(x86_64_HOST_ARCH) if (RtsFlags.MiscFlags.linkerMemBase != 0) { // User-override for mmap_32bit_base mmap_32bit_base = (void*)RtsFlags.MiscFlags.linkerMemBase; @@ -1531,7 +1540,7 @@ mmapForLinker (size_t bytes, nat flags, int fd) pagesize = getpagesize(); size = ROUND_UP(bytes, pagesize); -#if defined(x86_64_HOST_ARCH) +#if !defined(ALWAYS_PIC) && defined(x86_64_HOST_ARCH) mmap_again: if (mmap_32bit_base != 0) { @@ -1548,7 +1557,7 @@ mmap_again: stg_exit(EXIT_FAILURE); } -#if defined(x86_64_HOST_ARCH) +#if !defined(ALWAYS_PIC) && defined(x86_64_HOST_ARCH) if (mmap_32bit_base != 0) { if (result == map_addr) { mmap_32bit_base = (StgWord8*)map_addr + size; @@ -1606,6 +1615,7 @@ loadObj( char *path ) #else FILE *f; #endif + IF_DEBUG(linker, debugBelch("loadObj %s\n", path)); initLinker(); /* debugBelch("loadObj %s\n", path ); */ @@ -1646,7 +1656,10 @@ loadObj( char *path ) # endif r = stat(path, &st); - if (r == -1) { return 0; } + if (r == -1) { + IF_DEBUG(linker, debugBelch("File doesn't exist\n")); + return 0; + } /* sigh, strdup() isn't a POSIX function, so do it the long way */ oc->fileName = stgMallocBytes( strlen(path)+1, "loadObj" ); @@ -1715,10 +1728,16 @@ loadObj( char *path ) # if defined(OBJFORMAT_MACHO) && (defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH)) r = ocAllocateSymbolExtras_MachO ( oc ); - if (!r) { return r; } + if (!r) { + IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO failed\n")); + return r; + } # elif defined(OBJFORMAT_ELF) && (defined(powerpc_HOST_ARCH) || defined(x86_64_HOST_ARCH)) r = ocAllocateSymbolExtras_ELF ( oc ); - if (!r) { return r; } + if (!r) { + IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_ELF failed\n")); + return r; + } #endif /* verify the in-memory image */ @@ -1731,7 +1750,10 @@ loadObj( char *path ) # else barf("loadObj: no verify method"); # endif - if (!r) { return r; } + if (!r) { + IF_DEBUG(linker, debugBelch("ocVerifyImage_* failed\n")); + return r; + } /* build the symbol list for this image */ # if defined(OBJFORMAT_ELF) @@ -1743,7 +1765,10 @@ loadObj( char *path ) # else barf("loadObj: no getNames method"); # endif - if (!r) { return r; } + if (!r) { + IF_DEBUG(linker, debugBelch("ocGetNames_* failed\n")); + return r; + } /* loaded, but not resolved yet */ oc->status = OBJECT_LOADED; @@ -2016,7 +2041,7 @@ static SymbolExtra* makeSymbolExtra( ObjectCode* oc, * PowerPC specifics (instruction cache flushing) * ------------------------------------------------------------------------*/ -#ifdef powerpc_TARGET_ARCH +#ifdef powerpc_HOST_ARCH /* ocFlushInstructionCache @@ -2248,7 +2273,7 @@ cstring_from_COFF_symbol_name ( UChar* name, UChar* strtab ) */ if (name[7]==0) return name; /* The annoying case: 8 bytes. Copy into a temporary - (which is never freed ...) + (XXX which is never freed ...) */ newstr = stgMallocBytes(9, "cstring_from_COFF_symbol_name"); ASSERT(newstr); @@ -2257,6 +2282,33 @@ cstring_from_COFF_symbol_name ( UChar* name, UChar* strtab ) return newstr; } +/* Getting the name of a section is mildly tricky, so we make a + function for it. Sadly, in one case we have to copy the string + (when it is exactly 8 bytes long there's no trailing '\0'), so for + consistency we *always* copy the string; the caller must free it +*/ +static char * +cstring_from_section_name (UChar* name, UChar* strtab) +{ + char *newstr; + + if (name[0]=='/') { + int strtab_offset = strtol((char*)name+1,NULL,10); + int len = strlen(((char*)strtab) + strtab_offset); + + newstr = stgMallocBytes(len, "cstring_from_section_symbol_name"); + strcpy((char*)newstr, (char*)((UChar*)strtab) + strtab_offset); + return newstr; + } + else + { + newstr = stgMallocBytes(9, "cstring_from_section_symbol_name"); + ASSERT(newstr); + strncpy((char*)newstr,(char*)name,8); + newstr[8] = 0; + return newstr; + } +} /* Just compares the short names (first 8 chars) */ static COFF_section * @@ -2555,7 +2607,16 @@ ocGetNames_PEi386 ( ObjectCode* oc ) COFF_section* sectab_i = (COFF_section*) myindex ( sizeof_COFF_section, sectab, i ); - if (0 != strcmp((char*)sectab_i->Name, ".bss")) continue; + + char *secname = cstring_from_section_name(sectab_i->Name, strtab); + + if (0 != strcmp(secname, ".bss")) { + stgFree(secname); + continue; + } + + stgFree(secname); + /* sof 10/05: the PE spec text isn't too clear regarding what * the SizeOfRawData field is supposed to hold for object * file sections containing just uninitialized data -- for executables, @@ -2596,7 +2657,10 @@ ocGetNames_PEi386 ( ObjectCode* oc ) COFF_section* sectab_i = (COFF_section*) myindex ( sizeof_COFF_section, sectab, i ); - IF_DEBUG(linker, debugBelch("section name = %s\n", sectab_i->Name )); + + char *secname = cstring_from_section_name(sectab_i->Name, strtab); + + IF_DEBUG(linker, debugBelch("section name = %s\n", secname )); # if 0 /* I'm sure this is the Right Way to do it. However, the @@ -2608,12 +2672,12 @@ ocGetNames_PEi386 ( ObjectCode* oc ) kind = SECTIONKIND_CODE_OR_RODATA; # endif - if (0==strcmp(".text",(char*)sectab_i->Name) || - 0==strcmp(".rdata",(char*)sectab_i->Name)|| - 0==strcmp(".rodata",(char*)sectab_i->Name)) + if (0==strcmp(".text",(char*)secname) || + 0==strcmp(".rdata",(char*)secname)|| + 0==strcmp(".rodata",(char*)secname)) kind = SECTIONKIND_CODE_OR_RODATA; - if (0==strcmp(".data",(char*)sectab_i->Name) || - 0==strcmp(".bss",(char*)sectab_i->Name)) + if (0==strcmp(".data",(char*)secname) || + 0==strcmp(".bss",(char*)secname)) kind = SECTIONKIND_RWDATA; ASSERT(sectab_i->SizeOfRawData == 0 || sectab_i->VirtualSize == 0); @@ -2626,16 +2690,18 @@ ocGetNames_PEi386 ( ObjectCode* oc ) if (kind == SECTIONKIND_OTHER /* Ignore sections called which contain stabs debugging information. */ - && 0 != strcmp(".stab", (char*)sectab_i->Name) - && 0 != strcmp(".stabstr", (char*)sectab_i->Name) + && 0 != strcmp(".stab", (char*)secname) + && 0 != strcmp(".stabstr", (char*)secname) /* ignore constructor section for now */ - && 0 != strcmp(".ctors", (char*)sectab_i->Name) + && 0 != strcmp(".ctors", (char*)secname) /* ignore section generated from .ident */ - && 0!= strcmp("/4", (char*)sectab_i->Name) + && 0!= strncmp(".debug", (char*)secname, 6) /* ignore unknown section that appeared in gcc 3.4.5(?) */ - && 0!= strcmp(".reloc", (char*)sectab_i->Name) + && 0!= strcmp(".reloc", (char*)secname) + && 0 != strcmp(".rdata$zzz", (char*)secname) ) { - errorBelch("Unknown PEi386 section name `%s' (while processing: %s)", sectab_i->Name, oc->fileName); + errorBelch("Unknown PEi386 section name `%s' (while processing: %s)", secname, oc->fileName); + stgFree(secname); return 0; } @@ -2643,6 +2709,8 @@ ocGetNames_PEi386 ( ObjectCode* oc ) addSection(oc, kind, start, end); addProddableBlock(oc, start, end - start + 1); } + + stgFree(secname); } /* Copy exported symbols into the ObjectCode. */ @@ -2774,12 +2842,20 @@ ocResolve_PEi386 ( ObjectCode* oc ) ((UChar*)(oc->image)) + sectab_i->PointerToRelocations ); + char *secname = cstring_from_section_name(sectab_i->Name, strtab); + /* Ignore sections called which contain stabs debugging information. */ - if (0 == strcmp(".stab", (char*)sectab_i->Name) - || 0 == strcmp(".stabstr", (char*)sectab_i->Name) - || 0 == strcmp(".ctors", (char*)sectab_i->Name)) - continue; + if (0 == strcmp(".stab", (char*)secname) + || 0 == strcmp(".stabstr", (char*)secname) + || 0 == strcmp(".ctors", (char*)secname) + || 0 == strncmp(".debug", (char*)secname, 6) + || 0 == strcmp(".rdata$zzz", (char*)secname)) { + stgFree(secname); + continue; + } + + stgFree(secname); if ( sectab_i->Characteristics & MYIMAGE_SCN_LNK_NRELOC_OVFL ) { /* If the relocation field (a short) has overflowed, the @@ -3759,6 +3835,9 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, case R_X86_64_PC32: { +#if defined(ALWAYS_PIC) + barf("R_X86_64_PC32 relocation, but ALWAYS_PIC."); +#else StgInt64 off = value - P; if (off >= 0x7fffffffL || off < -0x80000000L) { #if X86_64_ELF_NONPIC_HACK @@ -3771,6 +3850,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, #endif } *(Elf64_Word *)P = (Elf64_Word)off; +#endif break; } @@ -3782,6 +3862,9 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, } case R_X86_64_32: +#if defined(ALWAYS_PIC) + barf("R_X86_64_32 relocation, but ALWAYS_PIC."); +#else if (value >= 0x7fffffffL) { #if X86_64_ELF_NONPIC_HACK StgInt64 pltAddress = (StgInt64) &makeSymbolExtra(oc, ELF_R_SYM(info), S) @@ -3793,9 +3876,13 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, #endif } *(Elf64_Word *)P = (Elf64_Word)value; +#endif break; case R_X86_64_32S: +#if defined(ALWAYS_PIC) + barf("R_X86_64_32S relocation, but ALWAYS_PIC."); +#else if ((StgInt64)value > 0x7fffffffL || (StgInt64)value < -0x80000000L) { #if X86_64_ELF_NONPIC_HACK StgInt64 pltAddress = (StgInt64) &makeSymbolExtra(oc, ELF_R_SYM(info), S) @@ -3807,6 +3894,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, #endif } *(Elf64_Sword *)P = (Elf64_Sword)value; +#endif break; case R_X86_64_GOTPCREL: @@ -3819,6 +3907,9 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, case R_X86_64_PLT32: { +#if defined(ALWAYS_PIC) + barf("R_X86_64_PLT32 relocation, but ALWAYS_PIC."); +#else StgInt64 off = value - P; if (off >= 0x7fffffffL || off < -0x80000000L) { StgInt64 pltAddress = (StgInt64) &makeSymbolExtra(oc, ELF_R_SYM(info), S) @@ -3826,6 +3917,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, off = pltAddress + A - P; } *(Elf64_Word *)P = (Elf64_Word)off; +#endif break; } #endif @@ -4020,12 +4112,18 @@ static int ocVerifyImage_MachO(ObjectCode* oc) char *image = (char*) oc->image; struct mach_header *header = (struct mach_header*) image; -#if x86_64_TARGET_ARCH || powerpc64_TARGET_ARCH - if(header->magic != MH_MAGIC_64) +#if x86_64_HOST_ARCH || powerpc64_HOST_ARCH + if(header->magic != MH_MAGIC_64) { + errorBelch("%s: Bad magic. Expected: %08x, got: %08x.\n", + oc->fileName, MH_MAGIC_64, header->magic); return 0; + } #else - if(header->magic != MH_MAGIC) + if(header->magic != MH_MAGIC) { + errorBelch("%s: Bad magic. Expected: %08x, got: %08x.\n", + oc->fileName, MH_MAGIC, header->magic); return 0; + } #endif // FIXME: do some more verifying here return 1; @@ -4212,6 +4310,9 @@ static int relocateSection( thing += value; break; case X86_64_RELOC_SIGNED: + case X86_64_RELOC_SIGNED_1: + case X86_64_RELOC_SIGNED_2: + case X86_64_RELOC_SIGNED_4: ASSERT(reloc->r_pcrel); thing += value - baseValue; break; @@ -4275,7 +4376,8 @@ static int relocateSection( else if(scat->r_type == PPC_RELOC_SECTDIFF || scat->r_type == PPC_RELOC_LO16_SECTDIFF || scat->r_type == PPC_RELOC_HI16_SECTDIFF - || scat->r_type == PPC_RELOC_HA16_SECTDIFF) + || scat->r_type == PPC_RELOC_HA16_SECTDIFF + || scat->r_type == PPC_RELOC_LOCAL_SECTDIFF) #else else if(scat->r_type == GENERIC_RELOC_SECTDIFF || scat->r_type == GENERIC_RELOC_LOCAL_SECTDIFF) @@ -4794,6 +4896,7 @@ static void machoInitSymbolsWithoutUnderscore() } #endif +#ifndef USE_MMAP /* * Figure out by how much to shift the entire Mach-O file in memory * when loading so that its single segment ends up 16-byte-aligned @@ -4806,12 +4909,18 @@ static int machoGetMisalignment( FILE * f ) fread(&header, sizeof(header), 1, f); rewind(f); -#if x86_64_TARGET_ARCH || powerpc64_TARGET_ARCH - if(header.magic != MH_MAGIC_64) +#if x86_64_HOST_ARCH || powerpc64_HOST_ARCH + if(header.magic != MH_MAGIC_64) { + errorBelch("Bad magic. Expected: %08x, got: %08x.\n", + MH_MAGIC_64, header->magic); return 0; + } #else - if(header.magic != MH_MAGIC) + if(header.magic != MH_MAGIC) { + errorBelch("Bad magic. Expected: %08x, got: %08x.\n", + MH_MAGIC, header->magic); return 0; + } #endif misalignment = (header.sizeofcmds + sizeof(header)) @@ -4819,6 +4928,6 @@ static int machoGetMisalignment( FILE * f ) return misalignment ? (16 - misalignment) : 0; } - #endif +#endif