X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;ds=sidebyside;f=ghc%2Frts%2FLinker.c;h=85d5809210524e1540380b85c3a5129bd699d6ef;hb=920a3de7d913f9f369ffb8e5f0892ef7c9aeacde;hp=093a791fcb7d224ca5132bd93a6be0bf7317e0e1;hpb=2203c0cef25db52714de9bb33a5f3cde2d18b0f3;p=ghc-hetmet.git diff --git a/ghc/rts/Linker.c b/ghc/rts/Linker.c index 093a791..85d5809 100644 --- a/ghc/rts/Linker.c +++ b/ghc/rts/Linker.c @@ -1,5 +1,4 @@ /* ----------------------------------------------------------------------------- - * $Id: Linker.c,v 1.136 2003/10/08 09:42:34 wolfgang Exp $ * * (c) The GHC Team, 2000-2003 * @@ -230,6 +229,7 @@ typedef struct _RtsSymbolVal { #define RTS_MINGW_ONLY_SYMBOLS \ SymX(asyncReadzh_fast) \ SymX(asyncWritezh_fast) \ + SymX(asyncDoProczh_fast) \ SymX(memset) \ SymX(inet_ntoa) \ SymX(inet_addr) \ @@ -554,6 +554,13 @@ 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 \ @@ -595,6 +602,7 @@ 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 @@ -744,11 +752,8 @@ addDLL( char *dll_name ) initLinker(); -#if !defined(openbsd_TARGET_OS) hdl= dlopen(dll_name, RTLD_NOW | RTLD_GLOBAL); -#else - hdl= dlopen(dll_name, RTLD_LAZY); -#endif + if (hdl == NULL) { /* dlopen failed; return a ptr to the error msg. */ errmsg = dlerror(); @@ -1913,11 +1918,16 @@ ocResolve_PEi386 ( ObjectCode* oc ) * real count can be found in the first reloc entry. * * 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 + * troubles. */ COFF_reloc* rel = (COFF_reloc*) myindex ( sizeof_COFF_reloc, reltab, 0 ); noRelocs = rel->VirtualAddress; - fprintf(stderr, "Overflown relocs: %u\n", noRelocs); + fprintf(stderr, "WARNING: Overflown relocation field (# relocs found: %u)\n", noRelocs); fflush(stderr); j = 1; } else { noRelocs = sectab_i->NumberOfRelocations; @@ -3000,13 +3010,11 @@ ia64_reloc_pcrel21(Elf_Addr target, Elf_Addr value, ObjectCode *oc) #if defined(OBJFORMAT_MACHO) /* - Initial support for MachO linking on Darwin/MacOS X on PowerPC chips + 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: - *) handle uninitialized data sections ("__common"). - Normal common definitions work, but beware if you pass -fno-common to gcc. *) implement ocVerifyImage_MachO *) add still more sanity checks. */ @@ -3049,7 +3057,7 @@ static int ocAllocateJumpIslands_MachO(ObjectCode* oc) if(nundefsym > 0) { #ifdef USE_MMAP - #error ocAllocateJumpIslands_MachO doesn't want USE_MMAP to be defined + #error ocAllocateJumpIslands_MachO doesnt want USE_MMAP to be defined #else oc->image = stgReallocBytes( image, oc->fileSize + islandSize * nundefsym, @@ -3134,11 +3142,31 @@ static void* makeJumpIsland( return (void*) island; } +static char* relocateAddress( + ObjectCode* oc, + int nSections, + struct section* sections, + unsigned long address) +{ + int i; + for(i = 0; i < nSections; i++) + { + if(sections[i].addr <= address + && address < sections[i].addr + sections[i].size) + { + return oc->image + sections[i].offset + address - sections[i].addr; + } + } + barf("Invalid Mach-O file:" + "Address out of bounds while relocating object file"); + return NULL; +} + static int relocateSection( ObjectCode* oc, char *image, struct symtab_command *symLC, struct nlist *nlist, - struct section* sections, struct section *sect) + int nSections, struct section* sections, struct section *sect) { struct relocation_info *relocs; int i,n; @@ -3160,12 +3188,55 @@ static int relocateSection( if(!scat->r_pcrel) { - if(scat->r_length == 2 && scat->r_type == GENERIC_RELOC_VANILLA) + if(scat->r_length == 2) { - unsigned long* word = (unsigned long*) (image + sect->offset + scat->r_address); + unsigned long word = 0; + unsigned long* wordPtr = (unsigned long*) (image + sect->offset + scat->r_address); + checkProddableBlock(oc,wordPtr); - checkProddableBlock(oc,word); - *word = scat->r_value + sect->offset + ((long) image); + // Step 1: Figure out what the relocated value should be + if(scat->r_type == GENERIC_RELOC_VANILLA) + { + word = scat->r_value + sect->offset + ((long) image); + } + 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) + { + 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)); + i++; + } + else + continue; // ignore the others + + if(scat->r_type == GENERIC_RELOC_VANILLA + || scat->r_type == PPC_RELOC_SECTDIFF) + { + *wordPtr = word; + } + else if(scat->r_type == PPC_RELOC_LO16_SECTDIFF) + { + ((unsigned short*) wordPtr)[1] = word & 0xFFFF; + } + else if(scat->r_type == PPC_RELOC_HI16_SECTDIFF) + { + ((unsigned short*) wordPtr)[1] = (word >> 16) & 0xFFFF; + } + else if(scat->r_type == PPC_RELOC_HA16_SECTDIFF) + { + ((unsigned short*) wordPtr)[1] = ((word >> 16) & 0xFFFF) + + ((word & (1<<15)) ? 1 : 0); + } } } @@ -3298,7 +3369,7 @@ static int ocGetNames_MachO(ObjectCode* oc) struct load_command *lc = (struct load_command*) (image + sizeof(struct mach_header)); unsigned i,curSymbol; struct segment_command *segLC = NULL; - struct section *sections, *la_ptrs = NULL, *nl_ptrs = NULL; + struct section *sections; struct symtab_command *symLC = NULL; struct dysymtab_command *dsymLC = NULL; struct nlist *nlist; @@ -3322,13 +3393,17 @@ static int ocGetNames_MachO(ObjectCode* oc) for(i=0;insects;i++) { - if(!strcmp(sections[i].sectname,"__la_symbol_ptr")) - la_ptrs = §ions[i]; - else if(!strcmp(sections[i].sectname,"__nl_symbol_ptr")) - nl_ptrs = §ions[i]; - - // for now, only add __text and __const to the sections table - else if(!strcmp(sections[i].sectname,"__text")) + 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, (void*) (image + sections[i].offset), (void*) (image + sections[i].offset + sections[i].size)); @@ -3340,10 +3415,14 @@ static int ocGetNames_MachO(ObjectCode* oc) addSection(oc, SECTIONKIND_RWDATA, (void*) (image + sections[i].offset), (void*) (image + sections[i].offset + sections[i].size)); - - if(sections[i].size > 0) // size 0 segments do exist - addProddableBlock(oc, (void*) (image + sections[i].offset), - sections[i].size); + else if(!strcmp(sections[i].sectname,"__bss") + || !strcmp(sections[i].sectname,"__common")) + addSection(oc, SECTIONKIND_RWDATA, + (void*) (image + sections[i].offset), + (void*) (image + sections[i].offset + sections[i].size)); + + addProddableBlock(oc, (void*) (image + sections[i].offset), + sections[i].size); } // count external symbols defined here @@ -3460,13 +3539,30 @@ static int ocResolve_MachO(ObjectCode* oc) for(i=0;insects;i++) { - if(!relocateSection(oc,image,symLC,nlist,sections,§ions[i])) + if(!relocateSection(oc,image,symLC,nlist,segLC->nsects,sections,§ions[i])) return 0; } /* 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 + do that whenever we modify code at runtime. + */ + { + int n = (oc->fileSize + islandSize * oc->n_islands) / 4; + unsigned long *p = (unsigned long*)oc->image; + while(n--) + { + __asm__ volatile ("dcbf 0,%0\n\tsync\n\ticbi 0,%0" + : : "r" (p)); + p++; + } + __asm__ volatile ("sync\n\tisync"); + } return 1; }