diff options
Diffstat (limited to 'rts/linker/Elf.c')
-rw-r--r-- | rts/linker/Elf.c | 112 |
1 files changed, 55 insertions, 57 deletions
diff --git a/rts/linker/Elf.c b/rts/linker/Elf.c index 9ea10d443f..b647d207cb 100644 --- a/rts/linker/Elf.c +++ b/rts/linker/Elf.c @@ -53,11 +53,13 @@ * SILENTLY generate crashing code for data references. This hack is * enabled by X86_64_ELF_NONPIC_HACK. * - * One workaround is to use shared Haskell libraries. This is - * coming. Another workaround is to keep the static libraries but - * compile them with -fPIC, because that will generate PIC references - * to data which can be relocated. The PIC code is still too green to - * do this systematically, though. + * One workaround is to use shared Haskell libraries. This is the case + * when dynamically-linked GHCi is used. + * + * Another workaround is to keep the static libraries but compile them + * with -fPIC -fexternal-dynamic-refs, because that will generate PIC + * references to data which can be relocated. This is the case when + * +RTS -xp is passed. * * See bug #781 * See thread http://www.haskell.org/pipermail/cvs-ghc/2007-September/038458.html @@ -74,7 +76,7 @@ * Sym*_NeedsProto: the symbol is undefined and we add a dummy * default proto extern void sym(void); */ -#define X86_64_ELF_NONPIC_HACK 1 +#define X86_64_ELF_NONPIC_HACK (!RtsFlags.MiscFlags.linkerAlwaysPic) #if defined(sparc_HOST_ARCH) # define ELF_TARGET_SPARC /* Used inside <elf.h> */ @@ -169,6 +171,8 @@ get_shndx_table(Elf_Ehdr* ehdr) void ocInit_ELF(ObjectCode * oc) { + ocDeinit_ELF(oc); + oc->info = (struct ObjectCodeFormatInfo*)stgCallocBytes( 1, sizeof *oc->info, "ocInit_Elf(ObjectCodeFormatInfo)"); @@ -318,6 +322,7 @@ ocDeinit_ELF(ObjectCode * oc) } stgFree(oc->info); + oc->info = NULL; } } @@ -576,7 +581,7 @@ ocVerifyImage_ELF ( ObjectCode* oc ) /* Figure out what kind of section it is. Logic derived from Figure 1.14 ("Special Sections") of the ELF document ("Portable Formats Specification, Version 1.1"). */ -static int getSectionKind_ELF( Elf_Shdr *hdr, int *is_bss ) +static SectionKind getSectionKind_ELF( Elf_Shdr *hdr, int *is_bss ) { *is_bss = false; @@ -678,23 +683,31 @@ ocGetNames_ELF ( ObjectCode* oc ) StgWord mapped_size = 0, mapped_offset = 0; StgWord size = shdr[i].sh_size; StgWord offset = shdr[i].sh_offset; + StgWord align = shdr[i].sh_addralign; if (is_bss && size > 0) { /* This is a non-empty .bss section. Allocate zeroed space for it, and set its .sh_offset field such that ehdrC + .sh_offset == addr_of_zeroed_space. */ -#if defined(NEED_GOT) - /* always use mmap if we use GOT slots. Otherwise the malloced - * address might be out of range for sections that are mmaped. - */ - alloc = SECTION_MMAP; - start = mmap(NULL, size, - PROT_READ | PROT_WRITE | PROT_EXEC, - MAP_ANON | MAP_PRIVATE, - -1, 0); - mapped_start = start; - mapped_offset = 0; - mapped_size = roundUpToPage(size); +#if defined(NEED_GOT) || RTS_LINKER_USE_MMAP + if (USE_CONTIGUOUS_MMAP || RtsFlags.MiscFlags.linkerAlwaysPic) { + /* The space for bss sections is already preallocated */ + ASSERT(oc->bssBegin != NULL); + alloc = SECTION_NOMEM; + start = + oc->image + roundUpToAlign(oc->bssBegin - oc->image, align); + oc->bssBegin = (char*)start + size; + ASSERT(oc->bssBegin <= oc->bssEnd); + } else { + /* Use mmapForLinker to allocate .bss, otherwise the malloced + * address might be out of range for sections that are mmaped. + */ + alloc = SECTION_MMAP; + start = mmapForLinker(size, MAP_ANONYMOUS, -1, 0); + mapped_start = start; + mapped_offset = 0; + mapped_size = roundUpToPage(size); + } #else alloc = SECTION_MALLOC; start = stgCallocBytes(1, size, "ocGetNames_ELF(BSS)"); @@ -754,7 +767,7 @@ ocGetNames_ELF ( ObjectCode* oc ) start = mem; mapped_start = mem; #else - if (USE_CONTIGUOUS_MMAP) { + if (USE_CONTIGUOUS_MMAP || RtsFlags.MiscFlags.linkerAlwaysPic) { // already mapped. start = oc->image + offset; alloc = SECTION_NOMEM; @@ -1585,9 +1598,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, case COMPAT_R_X86_64_PC32: { -#if defined(ALWAYS_PIC) - barf("R_X86_64_PC32 relocation, but ALWAYS_PIC."); -#else StgInt64 off = value - P; if (off != (Elf64_Sword)off && X86_64_ELF_NONPIC_HACK) { StgInt64 pltAddress = @@ -1604,7 +1614,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, } Elf64_Sword payload = off; memcpy((void*)P, &payload, sizeof(payload)); -#endif break; } @@ -1617,9 +1626,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, case COMPAT_R_X86_64_32: { -#if defined(ALWAYS_PIC) - barf("R_X86_64_32 relocation, but ALWAYS_PIC."); -#else if (value != (Elf64_Word)value && X86_64_ELF_NONPIC_HACK) { StgInt64 pltAddress = (StgInt64) &makeSymbolExtra(oc, ELF_R_SYM(info), S) @@ -1635,15 +1641,11 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, } Elf64_Word payload = value; memcpy((void*)P, &payload, sizeof(payload)); -#endif break; } case COMPAT_R_X86_64_32S: { -#if defined(ALWAYS_PIC) - barf("R_X86_64_32S relocation, but ALWAYS_PIC."); -#else if ((StgInt64)value != (Elf64_Sword)value && X86_64_ELF_NONPIC_HACK) { StgInt64 pltAddress = (StgInt64) &makeSymbolExtra(oc, ELF_R_SYM(info), S) @@ -1659,7 +1661,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, } Elf64_Sword payload = value; memcpy((void*)P, &payload, sizeof(payload)); -#endif break; } case COMPAT_R_X86_64_REX_GOTPCRELX: @@ -1681,9 +1682,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, #if defined(dragonfly_HOST_OS) case COMPAT_R_X86_64_GOTTPOFF: { -#if defined(ALWAYS_PIC) - barf("R_X86_64_GOTTPOFF relocation, but ALWAYS_PIC."); -#else /* determine the offset of S to the current thread's tls area XXX: Move this to the beginning of function */ @@ -1701,16 +1699,12 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, } Elf64_SWord payload = off; memcpy((void*)P, &payload, sizeof(payload)); -#endif break; } #endif case COMPAT_R_X86_64_PLT32: { -#if defined(ALWAYS_PIC) - barf("R_X86_64_PLT32 relocation, but ALWAYS_PIC."); -#else StgInt64 off = value - P; if (off != (Elf64_Sword)off) { StgInt64 pltAddress = (StgInt64) &makeSymbolExtra(oc, ELF_R_SYM(info), S) @@ -1725,7 +1719,6 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, } Elf64_Sword payload = off; memcpy((void*)P, &payload, sizeof(payload)); -#endif break; } #endif @@ -1891,22 +1884,27 @@ int ocRunInit_ELF( ObjectCode *oc ) #if defined(NEED_SYMBOL_EXTRAS) -int ocAllocateSymbolExtras_ELF( ObjectCode *oc ) +int ocAllocateExtras_ELF( ObjectCode *oc ) { - Elf_Ehdr *ehdr; - Elf_Shdr* shdr; - Elf_Word i, shnum; - - ehdr = (Elf_Ehdr *) oc->image; - shdr = (Elf_Shdr *) ( ((char *)oc->image) + ehdr->e_shoff ); - - shnum = elf_shnum(ehdr); - - for( i = 0; i < shnum; i++ ) - if( shdr[i].sh_type == SHT_SYMTAB ) - break; + Elf_Ehdr *ehdr = (Elf_Ehdr *) oc->image; + Elf_Shdr* shdr = (Elf_Shdr *) ( ((char *)oc->image) + ehdr->e_shoff ); + Elf_Shdr* symtab = NULL; + Elf_Word shnum = elf_shnum(ehdr); + int bssSize = 0; + + for (Elf_Word i = 0; i < shnum; ++i) { + if(shdr[i].sh_type == SHT_SYMTAB) { + symtab = &shdr[i]; + } else { + int isBss = 0; + getSectionKind_ELF(&shdr[i], &isBss); + if (isBss && shdr[i].sh_size > 0) { + bssSize += roundUpToAlign(shdr[i].sh_size, shdr[i].sh_addralign); + } + } + } - if( i == shnum ) + if (symtab == NULL) { // Not having a symbol table is not in principle a problem. // When an object file has no symbols then the 'strip' program @@ -1916,15 +1914,15 @@ int ocAllocateSymbolExtras_ELF( ObjectCode *oc ) return 1; } - if( shdr[i].sh_entsize != sizeof( Elf_Sym ) ) + if( symtab->sh_entsize != sizeof( Elf_Sym ) ) { errorBelch( "The entry size (%d) of the symtab isn't %d\n", - (int) shdr[i].sh_entsize, (int) sizeof( Elf_Sym ) ); + (int) symtab->sh_entsize, (int) sizeof( Elf_Sym ) ); return 0; } - return ocAllocateSymbolExtras( oc, shdr[i].sh_size / sizeof( Elf_Sym ), 0 ); + return ocAllocateExtras(oc, symtab->sh_size / sizeof( Elf_Sym ), 0, bssSize); } #endif /* NEED_SYMBOL_EXTRAS */ |