From: sewardj Date: Mon, 12 Feb 2001 12:46:23 +0000 (+0000) Subject: [project @ 2001-02-12 12:46:23 by sewardj] X-Git-Tag: Approximately_9120_patches~2670 X-Git-Url: http://git.megacz.com/?a=commitdiff_plain;h=4b6c8c65c1eb579e93a4554e29041a554d7a479b;p=ghc-hetmet.git [project @ 2001-02-12 12:46:23 by sewardj] Teach the runtime linker about local symbols, so that we don't have to rely on batch linkers to resolve local symbols in libraries at library-build-time. --- diff --git a/ghc/rts/Linker.c b/ghc/rts/Linker.c index 4f2a456..b4d682e 100644 --- a/ghc/rts/Linker.c +++ b/ghc/rts/Linker.c @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: Linker.c,v 1.23 2001/02/12 12:22:01 simonmar Exp $ + * $Id: Linker.c,v 1.24 2001/02/12 12:46:23 sewardj Exp $ * * (c) The GHC Team, 2000 * @@ -295,6 +295,21 @@ lookupSymbol( char *lbl ) } } +static +void * +lookupLocalSymbol( ObjectCode* oc, char *lbl ) +{ + SymbolVal *val; + val = lookupStrHashTable(oc->lochash, lbl); + + if (val == NULL) { + return NULL; + } else { + return val->addr; + } +} + + /* ----------------------------------------------------------------------------- * Load an obj (populate the global symbol table, but don't resolve yet) * @@ -308,14 +323,14 @@ loadObj( char *path ) int r, n; FILE *f; -#ifdef DEBUG +# ifdef DEBUG /* assert that we haven't already loaded this object */ { ObjectCode *o; for (o = objects; o; o = o->next) ASSERT(strcmp(o->fileName, path)); } -#endif /* DEBUG */ +# endif /* DEBUG */ oc = stgMallocBytes(sizeof(ObjectCode), "loadObj(oc)"); @@ -331,7 +346,7 @@ loadObj( char *path ) r = stat(path, &st); if (r == -1) { return 0; } - /* sigh, stdup() isn't a POSIX function, so do it the long way */ + /* sigh, strdup() isn't a POSIX function, so do it the long way */ oc->fileName = stgMallocBytes( strlen(path)+1, "loadObj" ); strcpy(oc->fileName, path); @@ -339,6 +354,7 @@ loadObj( char *path ) oc->image = stgMallocBytes( st.st_size, "loadObj(image)" ); oc->symbols = NULL; oc->sections = NULL; + oc->lochash = allocStrHashTable(); /* chain it onto the list of objects */ oc->next = objects; @@ -394,13 +410,13 @@ resolveObjs( void ) for (oc = objects; oc; oc = oc->next) { if (oc->status != OBJECT_RESOLVED) { -# if defined(OBJFORMAT_ELF) +# if defined(OBJFORMAT_ELF) r = ocResolve_ELF ( oc ); -# elif defined(OBJFORMAT_PEi386) +# elif defined(OBJFORMAT_PEi386) r = ocResolve_PEi386 ( oc ); -# else +# else barf("link: not implemented on this platform"); -# endif +# endif if (!r) { return r; } oc->status = OBJECT_RESOLVED; } @@ -447,6 +463,7 @@ unloadObj( char *path ) free(oc->fileName); free(oc->symbols); free(oc->sections); + freeHashTable(oc->lochash, NULL); free(oc); return 1; } @@ -1332,27 +1349,34 @@ ocGetNames_ELF ( ObjectCode* oc ) oc->n_symbols = nent; for (j = 0; j < nent; j++) { if ( ( ELF32_ST_BIND(stab[j].st_info)==STB_GLOBAL - /* || ELF32_ST_BIND(stab[j].st_info)==STB_LOCAL */ + || ELF32_ST_BIND(stab[j].st_info)==STB_LOCAL ) - /* and not an undefined symbol */ - && stab[j].st_shndx != SHN_UNDEF - && + /* and not an undefined symbol */ + && stab[j].st_shndx != SHN_UNDEF + && /* and it's a not a section or string table or anything silly */ ( ELF32_ST_TYPE(stab[j].st_info)==STT_FUNC || ELF32_ST_TYPE(stab[j].st_info)==STT_OBJECT || - ELF32_ST_TYPE(stab[j].st_info)==STT_NOTYPE ) - ) { + ELF32_ST_TYPE(stab[j].st_info)==STT_NOTYPE + ) + ) { char* nm = strtab + stab[j].st_name; char* ad = ehdrC + shdr[ stab[j].st_shndx ].sh_offset + stab[j].st_value; ASSERT(nm != NULL); ASSERT(ad != NULL); - IF_DEBUG(linker,belch( "addOTabName: %10p %s %s", - ad, oc->fileName, nm )); oc->symbols[j].lbl = nm; oc->symbols[j].addr = ad; - insertStrHashTable(symhash, nm, &(oc->symbols[j])); + if (ELF32_ST_BIND(stab[j].st_info)==STB_LOCAL) { + IF_DEBUG(linker,belch( "addOTabName(LOCL): %10p %s %s", + ad, oc->fileName, nm )); + insertStrHashTable(oc->lochash, nm, &(oc->symbols[j])); + } else { + IF_DEBUG(linker,belch( "addOTabName(GLOB): %10p %s %s", + ad, oc->fileName, nm )); + insertStrHashTable(symhash, nm, &(oc->symbols[j])); + } } else { IF_DEBUG(linker,belch( "skipping `%s'", @@ -1415,9 +1439,12 @@ static int do_Elf32_Rel_relocations ( ObjectCode* oc, char* ehdrC, (ehdrC + shdr[stab[ELF32_R_SYM(info)].st_shndx ].sh_offset + stab[ELF32_R_SYM(info)].st_value); } else { - /* No? Should be in the symbol table then. */ + /* No? Should be in a symbol table then; first try the + local one. */ symbol = strtab+stab[ ELF32_R_SYM(info)].st_name; - (void *)S = lookupSymbol( symbol ); + (void*)S = lookupLocalSymbol( oc, symbol ); + if ((void*)S == NULL) + (void*)S = lookupSymbol( symbol ); } if (!S) { barf("do_Elf32_Rel_relocations: %s: unknown symbol `%s'", @@ -1487,9 +1514,12 @@ static int do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC, (ehdrC + shdr[stab[ELF32_R_SYM(info)].st_shndx ].sh_offset + stab[ELF32_R_SYM(info)].st_value); } else { - /* No? Should be in the symbol table then. */ + /* No? Should be in a symbol table then; first try the + local one. */ symbol = strtab+stab[ ELF32_R_SYM(info)].st_name; - (void *)S = lookupSymbol( symbol ); + (void*)S = lookupLocalSymbol( oc, symbol ); + if ((void*)S == NULL) + (void*)S = lookupSymbol( symbol ); } if (!S) { barf("ocResolve_ELF: %s: unknown symbol `%s'", @@ -1530,9 +1560,6 @@ static int do_Elf32_Rela_relocations ( ObjectCode* oc, char* ehdrC, w2 = (Elf32_Word)(S + A); *pP = w2; break; - case R_SPARC_NONE: belch("R_SPARC_NONE"); - break; - # endif default: fprintf(stderr, "unhandled ELF relocation(RelA) type %d\n", diff --git a/ghc/rts/LinkerInternals.h b/ghc/rts/LinkerInternals.h index d124979..9cf3317 100644 --- a/ghc/rts/LinkerInternals.h +++ b/ghc/rts/LinkerInternals.h @@ -1,5 +1,5 @@ /* ----------------------------------------------------------------------------- - * $Id: LinkerInternals.h,v 1.1 2001/02/11 17:51:07 simonmar Exp $ + * $Id: LinkerInternals.h,v 1.2 2001/02/12 12:46:23 sewardj Exp $ * * (c) The GHC Team, 2000 * @@ -36,20 +36,23 @@ typedef struct { void* start; void* end; SectionKind kind; } * for each object file in use. */ typedef struct _ObjectCode { - OStatus status; - char* fileName; - int fileSize; - char* formatName; /* eg "ELF32", "DLL", "COFF", etc. */ + OStatus status; + char* fileName; + int fileSize; + char* formatName; /* eg "ELF32", "DLL", "COFF", etc. */ - SymbolVal *symbols; - int n_symbols; + SymbolVal *symbols; + int n_symbols; /* ptr to malloc'd lump of memory holding the obj file */ - void* image; + void* image; /* The section-kind entries for this object module. Dynamically expands. */ - Section* sections; - int n_sections; + Section* sections; + int n_sections; + + /* A private hash table for local symbols. */ + HashTable* lochash; /* Allow a chain of these things */ struct _ObjectCode * next;