Patches to fix bugs reported by roland McGrath
authorSteve Chamberlain <steve@cygnus>
Tue, 6 Aug 1991 21:28:21 +0000 (21:28 +0000)
committerSteve Chamberlain <steve@cygnus>
Tue, 6 Aug 1991 21:28:21 +0000 (21:28 +0000)
ld/.Sanitize
ld/ldindr.c
ld/ldsym.c

index 8c309b6d8ecc0d4bc80b31005aabf0410388bc05..cd507e6e4229c7104ae49e935aebfff2fc9ba716 100644 (file)
@@ -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
index 8e198427035830aee26f06a71d3585453945f25c..7770e8dc42648effe6ce96cde0b00d47df1537be 100644 (file)
@@ -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.
 */
 
 
 #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;
-}
-}
index bffa80e3665d6e79eb8d8e107c5e76633bdf0f70..98a1b8b5f73d1d002965071929c82194fdaa7552 100644 (file)
@@ -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) {