diff options
-rw-r--r-- | ld/.Sanitize | 6 | ||||
-rw-r--r-- | ld/ldindr.c | 73 | ||||
-rw-r--r-- | ld/ldsym.c | 90 |
3 files changed, 119 insertions, 50 deletions
diff --git a/ld/.Sanitize b/ld/.Sanitize index 8c309b6..cd507e6 100644 --- a/ld/.Sanitize +++ b/ld/.Sanitize @@ -80,7 +80,6 @@ ldsym.h ldvanilla.c ldver.c ldver.h -ldversion.c ldwarn.h ldwrite.c ldwrite.h @@ -93,7 +92,10 @@ echo Done in `pwd`. # # # $Log$ -# Revision 1.3 1991/08/01 23:59:06 steve +# Revision 1.4 1991/08/06 21:28:21 steve +# Patches to fix bugs reported by roland McGrath +# +# Revision 1.3 1991/08/01 23:59:06 steve # *** empty log message *** # # Revision 1.2 1991/07/16 00:31:15 steve diff --git a/ld/ldindr.c b/ld/ldindr.c index 8e19842..7770e8d 100644 --- a/ld/ldindr.c +++ b/ld/ldindr.c @@ -3,13 +3,11 @@ BFD supplies symbols to be indirected with the BFD_INDIRECT bit set. Whenever the linker gets one of these, it calls add_indirect - with the symbol. We create an entry into the ldsym hash table as if it - were a normal symbol, but with the SYM_INDIRECT bit set in the - flags. - - When it comes time to tie up the symbols at a later date, the flag - will be seen and a call made to do the right thing (tm) - + with the symbol. We look up the symbol which this one dereferneces, + and stop if they are the same. If they are not the same, copy all + the information from the current to the dereffed symbol. Set the + indirect bit in the flag. From now on the ldsym_get stuff will + perform the indirection for us, at no charge. */ @@ -18,41 +16,52 @@ #include "bfd.h" #include "ld.h" #include "ldsym.h" +#include "ldmisc.h" -extern ld_config_type config; -void -DEFUN(add_indirect,(ptr), -asymbol **ptr) + + +static asymbol ** +DEFUN(move_it,(a_list, b_list), +asymbol **a_list AND +asymbol **b_list) { - if (config.relocateable_output == false) { - ldsym_type *sp = ldsym_get((*ptr)->name); - sp->flags |= SYM_INDIRECT; - sp->sdefs_chain = ptr; + asymbol **head = a_list; + asymbol **cursor = head; + + if (a_list == 0) return b_list; + if (b_list == 0) return a_list; + + while (1) { + asymbol *ptr = cursor[0]; + asymbol **next = (asymbol **)(ptr->udata); + if (next == 0) { + ptr->udata = (PTR) b_list; + return head; + } + cursor = next; } } - - void -DEFUN(do_indirect,(ptr), -ldsym_type *ptr) +DEFUN(add_indirect,(ptr), +asymbol **ptr) { -if (config.relocateable_output == false) { - /* Dig out the symbol were indirecting to. It's held in the value - field. - */ + ldsym_type *lgs = ldsym_get((*ptr)->name); + ldsym_type *new = ldsym_get(((asymbol *)((*ptr)->value))->name); + /* If the mapping has already been done, stop now */ + if (lgs == new) return; + lgs->flags |= SYM_INDIRECT; - CONST char *name = ((asymbol *)(*(ptr->sdefs_chain))->value)->name; + new->scoms_chain = move_it(new->scoms_chain, lgs->scoms_chain); + lgs->scoms_chain = 0; + new->srefs_chain = move_it(new->srefs_chain, lgs->srefs_chain); + lgs->srefs_chain = 0; + new->sdefs_chain = move_it(new->sdefs_chain, lgs->sdefs_chain); + lgs->sdefs_chain = 0; - ldsym_type *new = ldsym_get(name); + lgs->sdefs_chain = (asymbol **)new; +} - /* We have to make a copy of the sdefs_chain item name, since - symbols will be clobbered on writing, and we want to write the - same string twice */ - ptr->sdefs_chain[0][0] = new->sdefs_chain[0][0]; - ptr->sdefs_chain[0][0].name = name; -} -} @@ -26,9 +26,40 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ Written by Steve Chamberlain steve@cygnus.com All symbol handling for the linker - */ + + + We keep a hash table of global symbols. Each entry in a hash table + is called an ldsym_type. Each has three chains; a pointer to a + chain of definitions for the symbol (hopefully one long), a pointer + to a chain of references to the symbol, and a pointer to a chain of + common symbols. Each pointer points into the canonical symbol table + provided by bfd, each one of which points to an asymbol. Duringing + linkage, the linker uses the udata field to point to the next entry + in a canonical table.... + + + ld_sym + | | + +----------+ +----------+ + | defs | a canonical symbol table + +----------+ +----------+ + | refs | -----> | one entry| -----> asymbol + +----------+ +----------+ | | + | coms | | | +---------+ + +----------+ +----------+ | udata |-----> another canonical symbol + +---------+ + + + + It is very simple to make all the symbol pointers point to the same + definition - just run down the chain and make the asymbols pointers + within the canonical table point to the asymbol attacthed to the + definition of the symbol. + +*/ + #include "sysdep.h" #include "bfd.h" @@ -61,12 +92,15 @@ extern boolean option_longmap ; static ldsym_type *global_symbol_hash_table[TABSIZE]; /* Compute the hash code for symbol name KEY. */ - +static +#ifdef __GNUC__ +inline +#endif int -hash_string (key) - char *key; +DEFUN(hash_string,(key), + CONST char *key) { - register char *cp; + register CONST char *cp; register int k; cp = key; @@ -77,6 +111,28 @@ hash_string (key) return k; } +static +#ifdef __GNUC__ +inline +#endif ldsym_type *bp; +ldsym_type * +DEFUN(search,(key,hashval) , + CONST char *key AND + int hashval) +{ + ldsym_type *bp; + for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link) + if (! strcmp (key, bp->name)) { + if (bp->flags & SYM_INDIRECT) { + /* Use the symbol we're aliased to instead */ + return (ldsym_type *)(bp->sdefs_chain); + } + return bp; + } + return 0; +} + + /* Get the symbol table entry for the global symbol named KEY. Create one if there is none. */ ldsym_type * @@ -91,10 +147,10 @@ DEFUN(ldsym_get,(key), hashval = hash_string (key) % TABSIZE; /* Search the bucket. */ - - for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link) - if (! strcmp (key, bp->name)) - return bp; + bp = search(key, hashval); + if(bp) { + return bp; + } /* Nothing was found; create a new symbol table entry. */ @@ -132,12 +188,7 @@ DEFUN(ldsym_get_soft,(key), hashval = hash_string (key) % TABSIZE; /* Search the bucket. */ - - for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link) - if (! strcmp (key, bp->name)) - return bp; - - return 0; +return search(key, hashval); } @@ -214,6 +265,11 @@ ldsym_print_symbol_table () for (sp = symbol_head; sp; sp = sp->next) { + if (sp->flags & SYM_INDIRECT) { + fprintf(stdout,"indirect %s to %s\n", + sp->name, (((ldsym_type *)(sp->sdefs_chain))->name)); + } + else { if (sp->sdefs_chain) { asymbol *defsym = *(sp->sdefs_chain); @@ -247,7 +303,9 @@ ldsym_print_symbol_table () else { printf("undefined "); printf("%s ",sp->name); + } + } print_nl(); } @@ -352,7 +410,7 @@ asymbol **symbol_table; { FOR_EACH_LDSYM(sp) { - if (sp->sdefs_chain != (asymbol **)NULL) { + if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **)NULL) { asymbol *bufp = (*(sp->sdefs_chain)); if ((bufp->flags & BSF_KEEP) ==0) { |