X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Frts%2FLinker.c;h=3cd337fca9a88f41a4df10ab257381c1b92fb654;hb=9cb75205a0ffb89d9996ba8500493ba35d4b712f;hp=d8f1e435a5585d74dfdc1ab69124d446bf2cc61b;hpb=067e49d16fc85ff490d26baa7e17affcce4daf40;p=ghc-hetmet.git diff --git a/ghc/rts/Linker.c b/ghc/rts/Linker.c index d8f1e43..3cd337f 100644 --- a/ghc/rts/Linker.c +++ b/ghc/rts/Linker.c @@ -58,12 +58,12 @@ #include #endif -#if defined(ia64_TARGET_ARCH) || defined(openbsd_TARGET_OS) +#if defined(ia64_TARGET_ARCH) || defined(openbsd_TARGET_OS) || defined(linux_TARGET_OS) #define USE_MMAP #include #include -#if defined(openbsd_TARGET_OS) +#if defined(openbsd_TARGET_OS) || defined(linux_TARGET_OS) #ifdef HAVE_UNISTD_H #include #endif @@ -597,6 +597,7 @@ typedef struct _RtsSymbolVal { Sym(__udivdi3) \ Sym(__moddi3) \ Sym(__umoddi3) \ + Sym(__muldi3) \ Sym(__ashldi3) \ Sym(__ashrdi3) \ Sym(__lshrdi3) \ @@ -2450,10 +2451,10 @@ ocVerifyImage_ELF ( ObjectCode* oc ) } if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) { - IF_DEBUG(linker,debugBelch( "Is little-endian" )); + IF_DEBUG(linker,debugBelch( "Is little-endian\n" )); } else if (ehdr->e_ident[EI_DATA] == ELFDATA2MSB) { - IF_DEBUG(linker,debugBelch( "Is big-endian" )); + IF_DEBUG(linker,debugBelch( "Is big-endian\n" )); } else { errorBelch("%s: unknown endiannness", oc->fileName); return 0; @@ -2463,7 +2464,7 @@ ocVerifyImage_ELF ( ObjectCode* oc ) errorBelch("%s: not a relocatable object (.o) file", oc->fileName); return 0; } - IF_DEBUG(linker, debugBelch( "Is a relocatable object (.o) file" )); + IF_DEBUG(linker, debugBelch( "Is a relocatable object (.o) file\n" )); IF_DEBUG(linker,debugBelch( "Architecture is " )); switch (ehdr->e_machine) { @@ -2479,7 +2480,7 @@ ocVerifyImage_ELF ( ObjectCode* oc ) } IF_DEBUG(linker,debugBelch( - "\nSection header table: start %d, n_entries %d, ent_size %d", + "\nSection header table: start %d, n_entries %d, ent_size %d\n", ehdr->e_shoff, ehdr->e_shnum, ehdr->e_shentsize )); ASSERT (ehdr->e_shentsize == sizeof(Elf_Shdr)); @@ -2490,7 +2491,7 @@ ocVerifyImage_ELF ( ObjectCode* oc ) errorBelch("%s: no section header string table", oc->fileName); return 0; } else { - IF_DEBUG(linker,debugBelch( "Section header string table is section %d", + IF_DEBUG(linker,debugBelch( "Section header string table is section %d\n", ehdr->e_shstrndx)); sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset; } @@ -2541,11 +2542,11 @@ ocVerifyImage_ELF ( ObjectCode* oc ) IF_DEBUG(linker,debugBelch( "\nSymbol tables" )); for (i = 0; i < ehdr->e_shnum; i++) { if (shdr[i].sh_type != SHT_SYMTAB) continue; - IF_DEBUG(linker,debugBelch( "section %d is a symbol table", i )); + IF_DEBUG(linker,debugBelch( "section %d is a symbol table\n", i )); nsymtabs++; stab = (Elf_Sym*) (ehdrC + shdr[i].sh_offset); nent = shdr[i].sh_size / sizeof(Elf_Sym); - IF_DEBUG(linker,debugBelch( " number of entries is apparently %d (%d rem)", + IF_DEBUG(linker,debugBelch( " number of entries is apparently %d (%d rem)\n", nent, shdr[i].sh_size % sizeof(Elf_Sym) )); @@ -2592,6 +2593,38 @@ ocVerifyImage_ELF ( ObjectCode* oc ) return 1; } +static int getSectionKind_ELF( Elf_Shdr *hdr, int *is_bss ) +{ + *is_bss = FALSE; + + if (hdr->sh_type == SHT_PROGBITS + && (hdr->sh_flags & SHF_ALLOC) && (hdr->sh_flags & SHF_EXECINSTR)) { + /* .text-style section */ + return SECTIONKIND_CODE_OR_RODATA; + } + + if (hdr->sh_type == SHT_PROGBITS + && (hdr->sh_flags & SHF_ALLOC) && (hdr->sh_flags & SHF_WRITE)) { + /* .data-style section */ + return SECTIONKIND_RWDATA; + } + + if (hdr->sh_type == SHT_PROGBITS + && (hdr->sh_flags & SHF_ALLOC) && !(hdr->sh_flags & SHF_WRITE)) { + /* .rodata-style section */ + return SECTIONKIND_CODE_OR_RODATA; + } + + if (hdr->sh_type == SHT_NOBITS + && (hdr->sh_flags & SHF_ALLOC) && (hdr->sh_flags & SHF_WRITE)) { + /* .bss-style section */ + *is_bss = TRUE; + return SECTIONKIND_RWDATA; + } + + return SECTIONKIND_OTHER; +} + static int ocGetNames_ELF ( ObjectCode* oc ) @@ -2616,34 +2649,8 @@ ocGetNames_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"). */ - Elf_Shdr hdr = shdr[i]; - SectionKind kind = SECTIONKIND_OTHER; int is_bss = FALSE; - - if (hdr.sh_type == SHT_PROGBITS - && (hdr.sh_flags & SHF_ALLOC) && (hdr.sh_flags & SHF_EXECINSTR)) { - /* .text-style section */ - kind = SECTIONKIND_CODE_OR_RODATA; - } - else - if (hdr.sh_type == SHT_PROGBITS - && (hdr.sh_flags & SHF_ALLOC) && (hdr.sh_flags & SHF_WRITE)) { - /* .data-style section */ - kind = SECTIONKIND_RWDATA; - } - else - if (hdr.sh_type == SHT_PROGBITS - && (hdr.sh_flags & SHF_ALLOC) && !(hdr.sh_flags & SHF_WRITE)) { - /* .rodata-style section */ - kind = SECTIONKIND_CODE_OR_RODATA; - } - else - if (hdr.sh_type == SHT_NOBITS - && (hdr.sh_flags & SHF_ALLOC) && (hdr.sh_flags & SHF_WRITE)) { - /* .bss-style section */ - kind = SECTIONKIND_RWDATA; - is_bss = TRUE; - } + SectionKind kind = getSectionKind_ELF(&shdr[i], &is_bss); if (is_bss && shdr[i].sh_size > 0) { /* This is a non-empty .bss section. Allocate zeroed space for @@ -2748,7 +2755,7 @@ ocGetNames_ELF ( ObjectCode* oc ) } } else { /* Skip. */ - IF_DEBUG(linker,debugBelch( "skipping `%s'", + IF_DEBUG(linker,debugBelch( "skipping `%s'\n", strtab + stab[j].st_name )); /* debugBelch( @@ -2785,9 +2792,19 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC, stab = (Elf_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset); targ = (Elf_Word*)(ehdrC + shdr[ target_shndx ].sh_offset); - IF_DEBUG(linker,debugBelch( "relocations for section %d using symtab %d", + IF_DEBUG(linker,debugBelch( "relocations for section %d using symtab %d\n", target_shndx, symtab_shndx )); + /* Skip sections that we're not interested in. */ + { + int is_bss; + SectionKind kind = getSectionKind_ELF(&shdr[target_shndx], &is_bss); + if (kind == SECTIONKIND_OTHER) { + IF_DEBUG(linker,debugBelch( "skipping (target section not loaded)")); + return 1; + } + } + for (j = 0; j < nent; j++) { Elf_Addr offset = rtab[j].r_offset; Elf_Addr info = rtab[j].r_info; @@ -2825,10 +2842,10 @@ do_Elf_Rel_relocations ( ObjectCode* oc, char* ehdrC, errorBelch("%s: unknown symbol `%s'", oc->fileName, symbol); return 0; } - IF_DEBUG(linker,debugBelch( "`%s' resolves to %p", symbol, (void*)S )); + IF_DEBUG(linker,debugBelch( "`%s' resolves to %p\n", symbol, (void*)S )); } - IF_DEBUG(linker,debugBelch( "Reloc: P = %p S = %p A = %p", + IF_DEBUG(linker,debugBelch( "Reloc: P = %p S = %p A = %p\n", (void*)P, (void*)S, (void*)A )); checkProddableBlock ( oc, pP ); @@ -2866,7 +2883,7 @@ do_Elf_Rela_relocations ( ObjectCode* oc, char* ehdrC, stab = (Elf_Sym*) (ehdrC + shdr[ symtab_shndx ].sh_offset); targ = (Elf_Addr) (ehdrC + shdr[ target_shndx ].sh_offset); - IF_DEBUG(linker,debugBelch( "relocations for section %d using symtab %d", + IF_DEBUG(linker,debugBelch( "relocations for section %d using symtab %d\n", target_shndx, symtab_shndx )); for (j = 0; j < nent; j++) { @@ -3065,7 +3082,6 @@ ocResolve_ELF ( ObjectCode* oc ) char* ehdrC = (char*)(oc->image); Elf_Ehdr* ehdr = (Elf_Ehdr*) ehdrC; Elf_Shdr* shdr = (Elf_Shdr*) (ehdrC + ehdr->e_shoff); - char* sh_strtab = ehdrC + shdr[ehdr->e_shstrndx].sh_offset; /* first find "the" symbol table */ stab = (Elf_Sym*) findElfSection ( ehdrC, SHT_SYMTAB ); @@ -3080,15 +3096,7 @@ ocResolve_ELF ( ObjectCode* oc ) /* Process the relocation sections. */ for (shnum = 0; shnum < ehdr->e_shnum; shnum++) { - - /* Skip sections called ".rel.stab". These appear to contain - relocation entries that, when done, make the stabs debugging - info point at the right places. We ain't interested in all - dat jazz, mun. */ - if (0 == memcmp(".rel.stab", sh_strtab + shdr[shnum].sh_name, 9)) - continue; - - if (shdr[shnum].sh_type == SHT_REL ) { + if (shdr[shnum].sh_type == SHT_REL) { ok = do_Elf_Rel_relocations ( oc, ehdrC, shdr, shnum, stab, strtab ); if (!ok) return ok; @@ -3267,20 +3275,42 @@ static int ocAllocateJumpIslands_MachO(ObjectCode* oc) unsigned i; for( i = 0; i < header->ncmds; i++ ) - { - if( lc->cmd == LC_DYSYMTAB ) + { + if( lc->cmd == LC_SYMTAB ) { - struct dysymtab_command *dsymLC = (struct dysymtab_command *) lc; - - if( !ocAllocateJumpIslands( oc, dsymLC->nundefsym, - dsymLC->iundefsym ) ) - return 0; + // Find out the first and last undefined external + // 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; + struct nlist *nlist = + symLC ? (struct nlist*) ((char*) oc->image + symLC->symoff) + : NULL; + for(i=0;insyms;i++) + { + if(nlist[i].n_type & N_STAB) + ; + else if(nlist[i].n_type & N_EXT) + { + if((nlist[i].n_type & N_TYPE) == N_UNDF + && (nlist[i].n_value == 0)) + { + if(i < min) + min = i; + if(i > max) + max = i; + } + } + } + if(max >= min) + return ocAllocateJumpIslands(oc, max - min + 1, min); - break; // there can be only one LC_DSYMTAB + break; } + lc = (struct load_command *) ( ((char *)lc) + lc->cmdsize ); } - return 1; + return ocAllocateJumpIslands(oc,0,0); } static int ocVerifyImage_MachO(ObjectCode* oc) @@ -3578,9 +3608,11 @@ static int relocateSection( // The branch offset is too large. // Therefore, we try to use a jump island. 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: " @@ -3606,7 +3638,6 @@ static int ocGetNames_MachO(ObjectCode* oc) struct segment_command *segLC = NULL; struct section *sections; struct symtab_command *symLC = NULL; - struct dysymtab_command *dsymLC = NULL; struct nlist *nlist; unsigned long commonSize = 0; char *commonStorage = NULL; @@ -3618,13 +3649,12 @@ static int ocGetNames_MachO(ObjectCode* oc) segLC = (struct segment_command*) lc; else if(lc->cmd == LC_SYMTAB) symLC = (struct symtab_command*) lc; - else if(lc->cmd == LC_DYSYMTAB) - dsymLC = (struct dysymtab_command*) lc; lc = (struct load_command *) ( ((char*)lc) + lc->cmdsize ); } sections = (struct section*) (segLC+1); - nlist = (struct nlist*) (image + symLC->symoff); + nlist = symLC ? (struct nlist*) (image + symLC->symoff) + : NULL; for(i=0;insects;i++) { @@ -3662,61 +3692,56 @@ static int ocGetNames_MachO(ObjectCode* oc) // count external symbols defined here oc->n_symbols = 0; - if(dsymLC) - { - for(i = dsymLC->iextdefsym; - i < dsymLC->iextdefsym + dsymLC->nextdefsym; - i++) - { - if((nlist[i].n_type & N_TYPE) == N_SECT) - oc->n_symbols++; - } - } if(symLC) { for(i=0;insyms;i++) { - if((nlist[i].n_type & N_TYPE) == N_UNDF - && (nlist[i].n_type & N_EXT) && (nlist[i].n_value != 0)) - { - commonSize += nlist[i].n_value; - oc->n_symbols++; - } + if(nlist[i].n_type & N_STAB) + ; + else if(nlist[i].n_type & N_EXT) + { + if((nlist[i].n_type & N_TYPE) == N_UNDF + && (nlist[i].n_value != 0)) + { + commonSize += nlist[i].n_value; + oc->n_symbols++; + } + else if((nlist[i].n_type & N_TYPE) == N_SECT) + oc->n_symbols++; + } } } oc->symbols = stgMallocBytes(oc->n_symbols * sizeof(char*), "ocGetNames_MachO(oc->symbols)"); - if(dsymLC) + if(symLC) { - // insert symbols into hash table - for(i = dsymLC->iextdefsym, curSymbol = 0; - i < dsymLC->iextdefsym + 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 - + 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++) + curSymbol = 0; + for(i=0;insyms;i++) { - if((nlist[i].n_type & N_TYPE) == N_SECT) + if(nlist[i].n_type & N_STAB) + ; + else 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); + if(nlist[i].n_type & N_EXT) + { + char *nm = image + symLC->stroff + nlist[i].n_un.n_strx; + 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; + } + else + { + 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); + } } } }