]> Git Repo - binutils.git/blobdiff - ld/ldsym.c
* ldgram.y, ldlex.l: parse ABSOLUTE
[binutils.git] / ld / ldsym.c
index 24272a926c5c54630ebd674daa8ba3267ed84434..02faf351a3023cde7e539582b97488b8aeb3070e 100644 (file)
@@ -1,59 +1,56 @@
-/* Copyright (C) 1991 Free Software Foundation, Inc.
-
+/* All symbol handling for the linker
+   Copyright (C) 1991 Free Software Foundation, Inc.
+   Written by Steve Chamberlain [email protected]
 This file is part of GLD, the Gnu Linker.
 
-GLD is free software; you can redistribute it and/or modify
+This program is free software; you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 1, or (at your option)
-any later version.
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
 
-GLD is distributed in the hope that it will be useful,
+This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
-along with GLD; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
-
-/*
- *  $Id$ 
- *
- *  $Log$
- *  Revision 1.2  1991/03/22 23:02:38  steve
- *  Brought up to sync with Intel again.
- *
- * Revision 1.1  1991/03/13  00:48:32  chrisb
- * Initial revision
- *
- * Revision 1.4  1991/03/10  09:31:36  rich
- *  Modified Files:
- *     Makefile config.h ld-emul.c ld-emul.h ld-gld.c ld-gld960.c
- *     ld-lnk960.c ld.h lddigest.c ldexp.c ldexp.h ldfile.c ldfile.h
- *     ldgram.y ldinfo.h ldlang.c ldlang.h ldlex.h ldlex.l ldmain.c
- *     ldmain.h ldmisc.c ldmisc.h ldsym.c ldsym.h ldversion.c
- *     ldversion.h ldwarn.h ldwrite.c ldwrite.h y.tab.h
- *
- * As of this round of changes, ld now builds on all hosts of (Intel960)
- * interest and copy passes my copy test on big endian hosts again.
- *
- * Revision 1.3  1991/03/06  02:28:56  sac
- * Cleaned up
- *
- * Revision 1.2  1991/02/22  17:15:06  sac
- * Added RCS keywords and copyrights
- *
-*/
+along with this program; if not, write to the Free Software
+Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 /* 
-   Written by Steve Chamberlain [email protected]
-   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. During
+   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"
+#include "sysdep.h"
 
 #include "ld.h"
 #include "ldsym.h"
@@ -62,11 +59,19 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* IMPORT */
 
 extern bfd *output_bfd;
+extern strip_symbols_type strip_symbols;
+extern discard_locals_type discard_locals;
 /* Head and tail of global symbol table chronological list */
 
 ldsym_type *symbol_head = (ldsym_type *)NULL;
 ldsym_type **symbol_tail_ptr = &symbol_head;
 
+extern ld_config_type config;
+
+struct obstack global_sym_obstack;
+#define obstack_chunk_alloc ldmalloc
+#define obstack_chunk_free  free
+
 /*
   incremented for each symbol in the ldsym_type table
   no matter what flavour it is 
@@ -82,12 +87,16 @@ 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;
@@ -98,11 +107,33 @@ 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 *
-ldsym_get (key)
-     char *key;
+DEFUN(ldsym_get,(key),
+      CONST     char *key)
 {
   register int hashval;
   register ldsym_type *bp;
@@ -112,23 +143,19 @@ 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.  */
 
-  bp = (ldsym_type *) ldmalloc (sizeof (ldsym_type));
+  bp = (ldsym_type *) obstack_alloc (&global_sym_obstack, (bfd_size_type)(sizeof (ldsym_type)));
   bp->srefs_chain = (asymbol **)NULL;
   bp->sdefs_chain = (asymbol **)NULL;
   bp->scoms_chain = (asymbol **)NULL;
-  bp->name = (char *) ldmalloc (strlen (key) + 1);
-  strcpy (bp->name, key);
-
-
-
-
+  bp->name = obstack_copy(&global_sym_obstack,  key, strlen(key)+1);
+  bp->flags = 0;
   /* Add the entry to the bucket.  */
 
   bp->link = global_symbol_hash_table[hashval];
@@ -146,23 +173,16 @@ ldsym_get (key)
 /* Like `ldsym_get' but return 0 if the symbol is not already known.  */
 
 ldsym_type *
-ldsym_get_soft (key)
-     char *key;
+DEFUN(ldsym_get_soft,(key),
+      CONST char *key)
 {
   register int hashval;
-  register ldsym_type *bp;
-
   /* Determine which bucket.  */
 
   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);
 }
 
 
@@ -174,9 +194,9 @@ list_file_locals (entry)
 lang_input_statement_type *entry;
 {
   asymbol **q;
-  fprintf (stderr, "\nLocal symbols of ");
-  info("%I", entry);
-  fprintf (stderr, ":\n\n");
+  fprintf (config.map_file, "\nLocal symbols of ");
+  minfo("%I", entry);
+  fprintf (config.map_file, ":\n\n");
   if (entry->asymbols) {
     for (q = entry->asymbols; *q; q++) 
       {
@@ -191,97 +211,114 @@ lang_input_statement_type *entry;
 
 
 static void
-print_file_stuff(f)
-lang_input_statement_type *f;
+DEFUN(print_file_stuff,(f),
+      lang_input_statement_type *f)
 {
-  fprintf (stderr, "  %s", f->filename);
-  fprintf (stderr, " ");
+  fprintf (config.map_file,"  %s\n", f->filename);
   if (f->just_syms_flag) 
-    {
-      fprintf (stderr, " symbols only\n");
-    }
+  {
+    fprintf (config.map_file, " symbols only\n");
+  }
   else 
-    {
-      asection *s;
-      if (option_longmap) {
-       for (s = f->the_bfd->sections;
-            s != (asection *)NULL;
-            s = s->next) {
-         fprintf (stderr, "%08lx %08x 2**%2ud %s\n",
-                  s->output_offset,
-                  (unsigned)s->size, s->alignment_power, s->name);
+  {
+    asection *s;
+    if (true || option_longmap) {
+      for (s = f->the_bfd->sections;
+          s != (asection *)NULL;
+          s = s->next) {
+       print_address(s->output_offset);
+       if (s->reloc_done)
+       {
+         fprintf (config.map_file, " %08x 2**%2ud %s\n",
+                  (unsigned)bfd_get_section_size_after_reloc(s),
+                  s->alignment_power, s->name);
        }
-      }
-      else {         
-       for (s = f->the_bfd->sections;
-            s != (asection *)NULL;
-            s = s->next) {
-         fprintf (stderr, "%s %lx(%x) ",
-                  s->name,
-                  s->output_offset,
-                  (unsigned)   s->size);
+           
+       else 
+       {
+         fprintf (config.map_file, " %08x 2**%2ud %s\n",
+                  (unsigned)bfd_get_section_size_before_reloc(s),
+                  s->alignment_power, s->name);
        }
-       fprintf (stderr, "hex \n");
       }
     }
+    else
+    {        
+      for (s = f->the_bfd->sections;
+          s != (asection *)NULL;
+          s = s->next) {
+       fprintf(config.map_file, "%s ", s->name);
+       print_address(s->output_offset);
+       fprintf(config.map_file, "(%x)", (unsigned)bfd_get_section_size_after_reloc(s));
+      }
+      fprintf(config.map_file, "hex \n");
+    }
+  }
+  fprintf (config.map_file, "\n");
 }
 
 void
 ldsym_print_symbol_table ()
 {
-  fprintf (stderr, "\nFiles:\n\n");
+  fprintf (config.map_file, "**FILES**\n\n");
 
   lang_for_each_file(print_file_stuff);
 
-  fprintf (stderr, "\nGlobal symbols:\n\n");
+  fprintf(config.map_file, "**GLOBAL SYMBOLS**\n\n");
+  fprintf(config.map_file, "offset    section    offset   symbol\n");
   {
     register ldsym_type *sp;
 
     for (sp = symbol_head; sp; sp = sp->next)
       {
-       if (sp->sdefs_chain) 
-         {
-           asymbol *defsym = *(sp->sdefs_chain);
-           asection *defsec = bfd_get_section(defsym);
-           fprintf(stderr,"%08lx ",defsym->value);
-           if (defsec)
-             {
-               fprintf(stderr,"%08lx ",defsym->value+defsec->vma);
-               fprintf(stderr,
-                       "%7s",
-                       bfd_section_name(output_bfd,
-                                        defsec));
-
-             }
-           else 
-             {
-               fprintf(stderr,"         .......");
-             }
-
-         }     
-       else {
-         fprintf(stderr,"undefined");
+       if (sp->flags & SYM_INDIRECT) {
+         fprintf(config.map_file,"indirect %s to %s\n",
+                 sp->name, (((ldsym_type *)(sp->sdefs_chain))->name));
        }
+       else {
+         if (sp->sdefs_chain) 
+           {
+             asymbol *defsym = *(sp->sdefs_chain);
+             asection *defsec = bfd_get_section(defsym);
+             print_address(defsym->value);
+             if (defsec)
+               {
+                 fprintf(config.map_file, "  %-10s",
+                        bfd_section_name(output_bfd,
+                                         defsec));
+                 print_space();
+                 print_address(defsym->value+defsec->vma);
 
+               }
+             else 
+               {
+                 fprintf(config.map_file, "         .......");
+               }
 
-       if (sp->scoms_chain) {
-         fprintf(stderr, " common size %5lu    %s",
-                 (*(sp->scoms_chain))->value, sp->name);
-       }
-       if (sp->sdefs_chain) {
-         fprintf(stderr, " symbol def %08lx    %s",
-                 (*(sp->sdefs_chain))->value,
-                 sp->name);
-       }
-       else {
-         fprintf(stderr, " undefined    %s",
-                 sp->name);
+           }   
+
+
+         if (sp->scoms_chain) {
+           fprintf(config.map_file, "common               ");
+           print_address((*(sp->scoms_chain))->value);
+           fprintf(config.map_file, " %s ",sp->name);
+         }
+         else if (sp->sdefs_chain) {
+           fprintf(config.map_file, " %s ",sp->name);
+         }
+         else {
+           fprintf(config.map_file, "undefined                     ");
+           fprintf(config.map_file, "%s ",sp->name);
+
+         }
        }
-       fprintf(stderr, "\n");
+       print_nl();
 
       }
   }
-  lang_for_each_file(list_file_locals);
+  if (option_longmap) {
+    lang_for_each_file(list_file_locals);
+  }
 }
 
 extern lang_output_section_statement_type *create_object_symbols;
@@ -290,87 +327,90 @@ static asymbol **
 write_file_locals(output_buffer)
 asymbol **output_buffer;
 {
-LANG_FOR_EACH_INPUT_STATEMENT(entry)
+  LANG_FOR_EACH_INPUT_STATEMENT(entry)
+  {
+    /* Run trough the symbols and work out what to do with them */
+    unsigned int i;
+
+    /* Add one for the filename symbol if needed */
+    if (create_object_symbols 
+       != (lang_output_section_statement_type *)NULL) {
+      asection *s;
+      for (s = entry->the_bfd->sections;
+          s != (asection *)NULL;
+          s = s->next) {
+       if (s->output_section == create_object_symbols->bfd_section) {
+         /* Add symbol to this section */
+         asymbol * newsym  =
+          (asymbol *)bfd_make_empty_symbol(entry->the_bfd);
+         newsym->name = entry->local_sym_name;
+         /* The symbol belongs to the output file's text section */
+
+         /* The value is the start of this section in the output file*/
+         newsym->value  = 0;
+         newsym->flags = BSF_LOCAL;
+         newsym->section = s;
+         *output_buffer++ = newsym;
+         break;
+       }
+      }
+    }
+    for (i = 0; i < entry->symbol_count; i++) 
     {
-      /* Run trough the symbols and work out what to do with them */
-      unsigned int i;
-
-      /* Add one for the filename symbol if needed */
-      if (create_object_symbols 
-         != (lang_output_section_statement_type *)NULL) {
-       asection *s;
-       for (s = entry->the_bfd->sections;
-            s != (asection *)NULL;
-            s = s->next) {
-         if (s->output_section == create_object_symbols->bfd_section) {
-           /* Add symbol to this section */
-           asymbol * newsym  =
-             (asymbol *)bfd_make_empty_symbol(entry->the_bfd);
-           newsym->name = entry->local_sym_name;
-           /* The symbol belongs to the output file's text section */
-
-           /* The value is the start of this section in the output file*/
-           newsym->value  = 0;
-           newsym->flags = BSF_LOCAL;
-           newsym->section = s;
-           *output_buffer++ = newsym;
-           break;
-         }
+      asymbol *p = entry->asymbols[i];
+      /* FIXME, temporary hack, since not all of ld knows about the new abs section convention */
+
+      if (p->section == 0)
+       p->section = &bfd_abs_section;
+      if (flag_is_global(p->flags) )
+      {
+       /* We are only interested in outputting 
+          globals at this stage in special circumstances */
+       if (p->the_bfd == entry->the_bfd 
+           && flag_is_not_at_end(p->flags)) {
+         /* And this is one of them */
+         *(output_buffer++) = p;
+         p->flags |= BSF_KEEP;
        }
       }
-      for (i = 0; i < entry->symbol_count; i++) 
+      else {
+       if (flag_is_ordinary_local(p->flags)) 
        {
-         asymbol *p = entry->asymbols[i];
-
-         if (flag_is_global(p->flags) || flag_is_absolute(p->flags))
-           {
-             /* We are only interested in outputting 
-                globals at this stage in special circumstances */
-             if (p->the_bfd == entry->the_bfd 
-                 && flag_is_not_at_end(p->flags)) {
-               /* And this is one of them */
-               *(output_buffer++) = p;
-               p->flags |= BSF_KEEP;
-             }
-           }
-         else {
-           if (flag_is_ordinary_local(p->flags)) 
-             {
-               if (discard_locals == DISCARD_ALL)
-                 {  }
-               else if (discard_locals == DISCARD_L &&
-                        (p->name[0] == lprefix)) 
-                 {  }
-               else if (p->flags ==  BSF_WARNING) 
-                 {  }
-               else 
-                 { *output_buffer++ = p; }
-             }
-           else if (flag_is_debugger(p->flags)) 
-             {
-               /* Only keep the debugger symbols if no stripping required */
-               if (strip_symbols == STRIP_NONE) {
-                 *output_buffer++ = p;
-               }
-             }
-           else if (flag_is_undefined(p->flags)) 
-             { /* This must be global */
-             }
-           else if (flag_is_common(p->flags)) {
-          /* And so must this */
-           } 
-           else if (p->flags & BSF_CTOR) {
-             /* Throw it away */
-           }
-else
-             {
-               FAIL();
-             }
+         if (discard_locals == DISCARD_ALL)
+         {  }
+         else if (discard_locals == DISCARD_L &&
+                  (p->name[0] == lprefix)) 
+         {  }
+         else if (p->flags ==  BSF_WARNING) 
+         {  }
+         else 
+         { *output_buffer++ = p; }
+       }
+       else if (flag_is_debugger(p->flags)) 
+       {
+         /* Only keep the debugger symbols if no stripping required */
+         if (strip_symbols == STRIP_NONE) {
+           *output_buffer++ = p;
          }
        }
+       else if (p->section == &bfd_und_section)
+       {                       /* This must be global */
+       }
+       else if (p->section == &bfd_com_section) {
+         /* And so must this */
+       } 
+       else if (p->flags & BSF_CTOR) {
+         /* Throw it away */
+       }
+       else
+       {
+         FAIL();
+       }
+      }
+    }
 
 
-    }
+  }
   return output_buffer;
 }
 
@@ -381,7 +421,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) {
@@ -439,7 +479,7 @@ ldsym_write()
     extern unsigned int total_symbols_seen;
 
     asymbol **  symbol_table =  (asymbol **) 
-      ldmalloc ((size_t)(global_symbol_count +
+      ldmalloc ((bfd_size_type)(global_symbol_count +
                         total_files_seen +
                         total_symbols_seen + 1) *     sizeof (asymbol *));
     asymbol ** tablep = write_file_locals(symbol_table);
@@ -450,3 +490,25 @@ ldsym_write()
     bfd_set_symtab(output_bfd, symbol_table, (unsigned)( tablep - symbol_table));
   }
 }
+
+/*
+return true if the supplied symbol name is not in the 
+linker symbol table
+*/
+boolean 
+DEFUN(ldsym_undefined,(sym),
+      CONST char *sym)
+{
+  ldsym_type *from_table = ldsym_get_soft(sym);
+  if (from_table != (ldsym_type *)NULL) 
+  {
+    if (from_table->sdefs_chain != (asymbol **)NULL) return false;
+  }
+  return true;
+}
+
+void
+DEFUN_VOID(ldsym_init)
+{
+  obstack_begin(&global_sym_obstack, 20000);
+}
This page took 0.039371 seconds and 4 git commands to generate.