home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / binutils-2.2.1 / ld / ldsym.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-03  |  16.1 KB  |  676 lines

  1. /* All symbol handling for the linker
  2.    Copyright (C) 1991 Free Software Foundation, Inc.
  3.    Written by Steve Chamberlain steve@cygnus.com
  4.  
  5. This file is part of GLD, the Gnu Linker.
  6.  
  7. This program is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2 of the License, or
  10. (at your option) any later version.
  11.  
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /*
  22.    We keep a hash table of global symbols. Each entry in a hash table
  23.    is called an ldsym_type. Each has three chains; a pointer to a
  24.    chain of definitions for the symbol (hopefully one long), a pointer
  25.    to a chain of references to the symbol, and a pointer to a chain of
  26.    common symbols. Each pointer points into the canonical symbol table
  27.    provided by bfd, each one of which points to an asymbol. During
  28.    linkage, the linker uses the udata field to point to the next entry
  29.    in a canonical table....
  30.  
  31.  
  32.    ld_sym
  33.             |          |
  34.    +----------+        +----------+
  35.    | defs     |      a canonical symbol table
  36.    +----------+         +----------+
  37.    | refs     | ----->  | one entry|  -----> asymbol
  38.    +----------+        +----------+       |            |
  39.    | coms     |        |          |       +---------+
  40.    +----------+        +----------+       | udata   |-----> another canonical
  41.                        +---------+        symbol
  42.  
  43.  
  44.  
  45.    It is very simple to make all the symbol pointers point to the same
  46.    definition - just run down the chain and make the asymbols pointers
  47.    within the canonical table point to the asymbol attacthed to the
  48.    definition of the symbol.
  49.  
  50. */
  51.  
  52. #include "bfd.h"
  53. #include "sysdep.h"
  54.  
  55. #include "ld.h"
  56. #include "ldsym.h"
  57. #include "ldmisc.h"
  58. #include "ldlang.h"
  59. /* IMPORT */
  60. extern int symbol_truncate;
  61. extern bfd *output_bfd;
  62. extern strip_symbols_type strip_symbols;
  63. extern discard_locals_type discard_locals;
  64. /* Head and tail of global symbol table chronological list */
  65.  
  66. ldsym_type *symbol_head = (ldsym_type *) NULL;
  67. ldsym_type **symbol_tail_ptr = &symbol_head;
  68. CONST char *keepsyms_file;
  69. int kept_syms;
  70.  
  71. extern ld_config_type config;
  72.  
  73. struct obstack global_sym_obstack;
  74. #define obstack_chunk_alloc ldmalloc
  75. #define obstack_chunk_free  free
  76.  
  77. /*
  78.   incremented for each symbol in the ldsym_type table
  79.   no matter what flavour it is
  80. */
  81. unsigned int global_symbol_count;
  82.  
  83. /* IMPORTS */
  84.  
  85. extern boolean option_longmap;
  86.  
  87. /* LOCALS */
  88. #define    TABSIZE    1009
  89. static ldsym_type *global_symbol_hash_table[TABSIZE];
  90.  
  91. /* Compute the hash code for symbol name KEY.  */
  92. static
  93. #ifdef __GNUC__
  94.   __inline
  95. #endif
  96.  
  97. int
  98. DEFUN (hash_string, (key),
  99.        CONST char *key)
  100. {
  101.   register CONST char *cp;
  102.   register int k;
  103.   register int l = 0;
  104.   cp = key;
  105.   k = 0;
  106.   while (*cp && l < symbol_truncate)
  107.     {
  108.       k = (((k << 1) + (k >> 14)) ^ (*cp++)) & 0x3fff;
  109.       l++;
  110.     }
  111.   return k;
  112. }
  113.  
  114. static
  115. #ifdef __GNUC__
  116.   __inline
  117. #endif
  118.   ldsym_type *
  119. DEFUN (search, (key, hashval),
  120.        CONST char *key AND
  121.        int hashval)
  122. {
  123.   ldsym_type *bp;
  124.   for (bp = global_symbol_hash_table[hashval]; bp; bp = bp->link)
  125.     if (!strncmp (key, bp->name, symbol_truncate))
  126.       {
  127.     if (bp->flags & SYM_INDIRECT)
  128.       {
  129.         /* Use the symbol we're aliased to instead */
  130.         return (ldsym_type *) (bp->sdefs_chain);
  131.       }
  132.     return bp;
  133.       }
  134.   return 0;
  135. }
  136.  
  137.  
  138. /* Get the symbol table entry for the global symbol named KEY.
  139.    Create one if there is none.  */
  140. ldsym_type *
  141. DEFUN (ldsym_get, (key),
  142.        CONST char *key)
  143. {
  144.   register int hashval;
  145.   register ldsym_type *bp;
  146.  
  147.   /* Determine the proper bucket.  */
  148.  
  149.   hashval = hash_string (key) % TABSIZE;
  150.  
  151.   /* Search the bucket.  */
  152.   bp = search (key, hashval);
  153.   if (bp)
  154.     {
  155.       return bp;
  156.     }
  157.  
  158.   /* Nothing was found; create a new symbol table entry.  */
  159.  
  160.   bp = (ldsym_type *) obstack_alloc (&global_sym_obstack, (bfd_size_type) (sizeof (ldsym_type)));
  161.   bp->srefs_chain = (asymbol **) NULL;
  162.   bp->sdefs_chain = (asymbol **) NULL;
  163.   bp->scoms_chain = (asymbol **) NULL;
  164.   bp->name = obstack_copy (&global_sym_obstack, key, strlen (key) + 1);
  165.   bp->flags = 0;
  166.   /* Add the entry to the bucket.  */
  167.  
  168.   bp->link = global_symbol_hash_table[hashval];
  169.   global_symbol_hash_table[hashval] = bp;
  170.  
  171.   /* Keep the chronological list up to date too */
  172.   *symbol_tail_ptr = bp;
  173.   symbol_tail_ptr = &bp->next;
  174.   bp->next = 0;
  175.   global_symbol_count++;
  176.  
  177.   return bp;
  178. }
  179.  
  180. /* Like `ldsym_get' but return 0 if the symbol is not already known.  */
  181.  
  182. ldsym_type *
  183. DEFUN (ldsym_get_soft, (key),
  184.        CONST char *key)
  185. {
  186.   register int hashval;
  187.   /* Determine which bucket.  */
  188.  
  189.   hashval = hash_string (key) % TABSIZE;
  190.  
  191.   /* Search the bucket.  */
  192.   return search (key, hashval);
  193. }
  194.  
  195. static asymbol **
  196. process_keepsyms (table, size)
  197.      asymbol **table;
  198.      int size;
  199. {
  200.   struct obstack obstack;
  201.   char *start_of_obstack;
  202.   FILE *ks_file = 0;
  203.   asymbol **out = table;
  204.   asymbol **end = table + size;
  205.   asymbol **sym;
  206.  
  207.   if (!keepsyms_file || size == 0)
  208.     return end;
  209.   obstack_init (&obstack);
  210.   obstack_alloc (&obstack, 1);
  211.   obstack_finish (&obstack);
  212.   start_of_obstack = obstack_alloc (&obstack, 1);
  213.   ks_file = fopen (keepsyms_file, "r");
  214.   if (!ks_file)
  215.     {
  216.       info ("%X%P: can't open keep-symbols file `%s'\n", keepsyms_file);
  217.       goto egress;
  218.     }
  219.   errno = 0;
  220.  
  221. #define KEEP(S) \
  222.   do { asymbol **p = (S), *tmp = *out; *out = *p; *p = tmp; out++; } while (0)
  223.  
  224.   while (!feof (ks_file) && !ferror (ks_file))
  225.     {
  226.       int c;
  227.       char *ptr;
  228.       int found = 0;
  229.  
  230.       obstack_free (&obstack, start_of_obstack);
  231.       do
  232.     {
  233.       c = getc (ks_file);
  234.       if (c == '\n')
  235.         c = 0;
  236.       obstack_1grow (&obstack, c);
  237.     }
  238.       while (c > 0);
  239.       if (c == EOF)
  240.     {
  241.       if (!feof (ks_file))
  242.         /* error occurred */
  243.         {
  244.           info ("%X%P: error reading keep-symbols file `%s': %E\n",
  245.             keepsyms_file);
  246.           out = end;
  247.           goto egress;
  248.         }
  249.       if (obstack_next_free (&obstack) != obstack_base (&obstack) + 1)
  250.         /* eof in middle of symbol */
  251.         {
  252.           info ("%X%P: eof reached mid-line while reading keep-symbols file `%s'\n",
  253.             keepsyms_file);
  254.           out = end;
  255.           goto egress;
  256.         }
  257.       /* All okay -- no incomplete lines, EOF reached.  */
  258.       break;
  259.     }
  260.       ptr = obstack_next_free (&obstack) - 2;
  261.       /* discard trailing trash */
  262.       while (*ptr == ' '
  263.          || *ptr == '\t')
  264.     *ptr-- = 0;
  265.       ptr = obstack_base (&obstack);
  266.       for (sym = out; sym < end; sym++)
  267.     if (!strncmp ((*sym)->name, ptr, symbol_truncate))
  268.       {
  269.         KEEP (sym);
  270.         found = 1;
  271.       }
  272.       if (!found)
  273.     info ("%P: symbol `%s' (requested to be kept) not found\n", ptr);
  274.     }
  275.   /* It'd be slightly faster to move this pass above the previous one,
  276.      but that'd mean any symbols preserved in this pass would generate
  277.      warnings if they were also listed in the keepsyms file.  */
  278.   for (sym = out; sym < end; sym++)
  279.     {
  280.       asymbol *s = *sym;
  281.       if (s->section == &bfd_und_section
  282.       || bfd_is_com_section (s->section)
  283.       || s->flags & BSF_KEEP_G)
  284.     KEEP (sym);
  285.     }
  286. egress:
  287.   obstack_free (&obstack, start_of_obstack);
  288.   if (ks_file)
  289.     fclose (ks_file);
  290.   return out;
  291. }
  292.  
  293. static void
  294. list_file_locals (entry)
  295.      lang_input_statement_type *entry;
  296. {
  297.   asymbol **q;
  298.   fprintf (config.map_file, "\nLocal symbols of ");
  299.   minfo ("%I", entry);
  300.   fprintf (config.map_file, ":\n\n");
  301.   if (entry->asymbols)
  302.     {
  303.       for (q = entry->asymbols; *q; q++)
  304.     {
  305.       asymbol *p = *q;
  306.       /* If this is a definition,
  307.        update it if necessary by this file's start address.  */
  308.       if (p->flags & BSF_LOCAL)
  309.         info ("  %V %s\n", p->value, p->name);
  310.     }
  311.     }
  312. }
  313.  
  314.  
  315. static void
  316. DEFUN (print_file_stuff, (f),
  317.        lang_input_statement_type * f)
  318. {
  319.   fprintf (config.map_file, "  %s\n", f->filename);
  320.   if (f->just_syms_flag)
  321.     {
  322.       fprintf (config.map_file, " symbols only\n");
  323.     }
  324.   else
  325.     {
  326.       asection *s;
  327.       if (true || option_longmap)
  328.     {
  329.       for (s = f->the_bfd->sections;
  330.            s != (asection *) NULL;
  331.            s = s->next)
  332.         {
  333.           print_address (s->output_offset);
  334.           if (s->reloc_done)
  335.         {
  336.           fprintf (config.map_file, " %08x 2**%2ud %s\n",
  337.                (unsigned) bfd_get_section_size_after_reloc (s),
  338.                s->alignment_power, s->name);
  339.         }
  340.  
  341.           else
  342.         {
  343.           fprintf (config.map_file, " %08x 2**%2ud %s\n",
  344.                (unsigned) bfd_get_section_size_before_reloc (s),
  345.                s->alignment_power, s->name);
  346.         }
  347.         }
  348.     }
  349.       else
  350.     {
  351.       for (s = f->the_bfd->sections;
  352.            s != (asection *) NULL;
  353.            s = s->next)
  354.         {
  355.           fprintf (config.map_file, "%s ", s->name);
  356.           print_address (s->output_offset);
  357.           fprintf (config.map_file, "(%x)", (unsigned) bfd_get_section_size_after_reloc (s));
  358.         }
  359.       fprintf (config.map_file, "hex \n");
  360.     }
  361.     }
  362.   fprintf (config.map_file, "\n");
  363. }
  364.  
  365. void
  366. ldsym_print_symbol_table ()
  367. {
  368.   fprintf (config.map_file, "**FILES**\n\n");
  369.  
  370.   lang_for_each_file (print_file_stuff);
  371.  
  372.   fprintf (config.map_file, "**GLOBAL SYMBOLS**\n\n");
  373.   fprintf (config.map_file, "offset    section    offset   symbol\n");
  374.   {
  375.     register ldsym_type *sp;
  376.  
  377.     for (sp = symbol_head; sp; sp = sp->next)
  378.       {
  379.     if (sp->flags & SYM_INDIRECT)
  380.       {
  381.         fprintf (config.map_file, "indirect %s to %s\n",
  382.              sp->name, (((ldsym_type *) (sp->sdefs_chain))->name));
  383.       }
  384.     else
  385.       {
  386.         if (sp->sdefs_chain)
  387.           {
  388.         asymbol *defsym = *(sp->sdefs_chain);
  389.         asection *defsec = bfd_get_section (defsym);
  390.         print_address (defsym->value);
  391.         if (defsec)
  392.           {
  393.             fprintf (config.map_file, "  %-10s",
  394.                  bfd_section_name (output_bfd,
  395.                            defsec));
  396.             print_space ();
  397.             print_address (defsym->value + defsec->vma);
  398.  
  399.           }
  400.         else
  401.           {
  402.             fprintf (config.map_file, "         .......");
  403.           }
  404.  
  405.           }
  406.  
  407.  
  408.         if (sp->scoms_chain)
  409.           {
  410.         fprintf (config.map_file, "common               ");
  411.         print_address ((*(sp->scoms_chain))->value);
  412.         fprintf (config.map_file, " %s ", sp->name);
  413.           }
  414.         else if (sp->sdefs_chain)
  415.           {
  416.         fprintf (config.map_file, " %s ", sp->name);
  417.           }
  418.         else
  419.           {
  420.         fprintf (config.map_file, "undefined                     ");
  421.         fprintf (config.map_file, "%s ", sp->name);
  422.  
  423.           }
  424.       }
  425.     print_nl ();
  426.  
  427.       }
  428.   }
  429.   if (option_longmap)
  430.     {
  431.       lang_for_each_file (list_file_locals);
  432.     }
  433. }
  434.  
  435. extern lang_output_section_statement_type *create_object_symbols;
  436. extern char lprefix;
  437. static asymbol **
  438. write_file_locals (output_buffer)
  439.      asymbol **output_buffer;
  440. {
  441.   LANG_FOR_EACH_INPUT_STATEMENT (entry)
  442.   {
  443.     /* Run trough the symbols and work out what to do with them */
  444.     unsigned int i;
  445.  
  446.     /* Add one for the filename symbol if needed */
  447.     if (create_object_symbols
  448.     != (lang_output_section_statement_type *) NULL)
  449.       {
  450.     asection *s;
  451.     for (s = entry->the_bfd->sections;
  452.          s != (asection *) NULL;
  453.          s = s->next)
  454.       {
  455.         if (s->output_section == create_object_symbols->bfd_section)
  456.           {
  457.         /* Add symbol to this section */
  458.         asymbol *newsym =
  459.         (asymbol *) bfd_make_empty_symbol (entry->the_bfd);
  460.         newsym->name = entry->local_sym_name;
  461.         /* The symbol belongs to the output file's text section */
  462.  
  463.         /* The value is the start of this section in the output file*/
  464.         newsym->value = 0;
  465.         /* FIXME: Usurping BSF_KEEP_G flag, since it's defined as
  466.          "used by the linker" and I can't find any other code that
  467.          uses it.  Should be a cleaner way of doing this (like an
  468.          "application flags" field in the symbol structure?).  */
  469.         newsym->flags = BSF_LOCAL | BSF_KEEP_G;
  470.         newsym->section = s;
  471.         *output_buffer++ = newsym;
  472.         break;
  473.           }
  474.       }
  475.       }
  476.     for (i = 0; i < entry->symbol_count; i++)
  477.       {
  478.     asymbol *p = entry->asymbols[i];
  479.     /* FIXME, temporary hack, since not all of ld knows about the new abs section convention */
  480.  
  481.     if (p->section == 0)
  482.       p->section = &bfd_abs_section;
  483.     if (flag_is_global (p->flags))
  484.       {
  485.         /* We are only interested in outputting
  486.        globals at this stage in special circumstances */
  487.         if (bfd_asymbol_bfd (p) == entry->the_bfd
  488.         && flag_is_not_at_end (p->flags))
  489.           {
  490.         /* And this is one of them */
  491.         *(output_buffer++) = p;
  492.         p->flags |= BSF_KEEP;
  493.           }
  494.       }
  495.     else
  496.       {
  497.         if (p->section == &bfd_ind_section)
  498.           {
  499.         /* Dont think about indirect symbols */
  500.           }
  501.         else if (flag_is_debugger (p->flags))
  502.           {
  503.         /* Only keep the debugger symbols if no stripping required */
  504.         if (strip_symbols == STRIP_NONE)
  505.           {
  506.             *output_buffer++ = p;
  507.           }
  508.           }
  509.         else if (p->section == &bfd_und_section
  510.              || bfd_is_com_section (p->section))
  511.           {
  512.         /* These must be global.  */
  513.           }
  514.         else if (flag_is_ordinary_local (p->flags))
  515.           {
  516.         if (discard_locals == DISCARD_ALL)
  517.           {
  518.           }
  519.         else if (discard_locals == DISCARD_L &&
  520.              (p->name[0] == lprefix))
  521.           {
  522.           }
  523.         else if (p->flags == BSF_WARNING)
  524.           {
  525.           }
  526.         else
  527.           {
  528.             *output_buffer++ = p;
  529.           }
  530.           }
  531.         else if (p->flags & BSF_CTOR)
  532.           {
  533.         /* Throw it away */
  534.           }
  535.         else
  536.           {
  537.         FAIL ();
  538.           }
  539.       }
  540.       }
  541.  
  542.  
  543.   }
  544.   return output_buffer;
  545. }
  546.  
  547.  
  548. static asymbol **
  549. write_file_globals (symbol_table)
  550.      asymbol **symbol_table;
  551. {
  552.   FOR_EACH_LDSYM (sp)
  553.   {
  554.     if (sp->flags & SYM_INDIRECT)
  555.       {
  556.     asymbol *bufp = (*(sp->srefs_chain));
  557.     ldsym_type *aliased_to = (ldsym_type *) (sp->sdefs_chain);
  558.     if (aliased_to->sdefs_chain)
  559.       {
  560.         asymbol *p = aliased_to->sdefs_chain[0];
  561.         bufp->value = p->value;
  562.         bufp->section = p->section;
  563.         bufp->flags = p->flags;
  564.       }
  565.     else
  566.       {
  567.         bufp->value = 0;
  568.         bufp->flags = 0;
  569.         bufp->section = &bfd_und_section;
  570.       }
  571.     *symbol_table++ = bufp;
  572.       }
  573.     else if ((sp->flags & SYM_INDIRECT) == 0 && sp->sdefs_chain != (asymbol **) NULL)
  574.       {
  575.     asymbol *bufp = (*(sp->sdefs_chain));
  576.  
  577.     if ((bufp->flags & BSF_KEEP) == 0)
  578.       {
  579.         ASSERT (bufp != (asymbol *) NULL);
  580.  
  581.         bufp->name = sp->name;
  582.  
  583.         if (sp->scoms_chain != (asymbol **) NULL)
  584.  
  585.           {
  586.         /*
  587.          defined as common but not allocated, this happens
  588.          only with -r and not -d, write out a common
  589.          definition
  590.          */
  591.         bufp = *(sp->scoms_chain);
  592.           }
  593.         *symbol_table++ = bufp;
  594.       }
  595.       }
  596.     else if (sp->scoms_chain != (asymbol **) NULL)
  597.       {
  598.     /* This symbol is a common - just output */
  599.     asymbol *bufp = (*(sp->scoms_chain));
  600.     *symbol_table++ = bufp;
  601.       }
  602.     else if (sp->srefs_chain != (asymbol **) NULL)
  603.       {
  604.     /* This symbol is undefined but has a reference */
  605.     asymbol *bufp = (*(sp->srefs_chain));
  606.     *symbol_table++ = bufp;
  607.       }
  608.     else
  609.       {
  610.     /*
  611.        This symbol has neither defs nor refs, it must have come
  612.        from the command line, since noone has used it it has no
  613.        data attatched, so we'll ignore it
  614.        */
  615.       }
  616.   }
  617.   return symbol_table;
  618. }
  619.  
  620. void
  621. ldsym_write ()
  622. {
  623.   if (keepsyms_file != 0
  624.       && strip_symbols != STRIP_SOME)
  625.     {
  626.       info ("%P `-retain-symbols-file' overrides `-s' and `-S'\n");
  627.       strip_symbols = STRIP_SOME;
  628.     }
  629.   if (strip_symbols != STRIP_ALL)
  630.     {
  631.       /* We know the maximum size of the symbol table -
  632.        it's the size of all the global symbols ever seen +
  633.        the size of all the symbols from all the files +
  634.        the number of files (for the per file symbols)
  635.        +1 (for the null at the end)
  636.        */
  637.       extern unsigned int total_files_seen;
  638.       extern unsigned int total_symbols_seen;
  639.  
  640.       asymbol **symbol_table = (asymbol **)
  641.       ldmalloc ((bfd_size_type) (global_symbol_count +
  642.                  total_files_seen +
  643.                   total_symbols_seen + 1) * sizeof (asymbol *));
  644.       asymbol **tablep = write_file_locals (symbol_table);
  645.  
  646.       tablep = write_file_globals (tablep);
  647.       tablep = process_keepsyms (symbol_table, tablep - symbol_table);
  648.  
  649.       *tablep = (asymbol *) NULL;
  650.       bfd_set_symtab (output_bfd, symbol_table, (unsigned) (tablep - symbol_table));
  651.     }
  652. }
  653.  
  654. /*
  655. return true if the supplied symbol name is not in the
  656. linker symbol table
  657. */
  658. boolean
  659. DEFUN (ldsym_undefined, (sym),
  660.        CONST char *sym)
  661. {
  662.   ldsym_type *from_table = ldsym_get_soft (sym);
  663.   if (from_table != (ldsym_type *) NULL)
  664.     {
  665.       if (from_table->sdefs_chain != (asymbol **) NULL)
  666.     return false;
  667.     }
  668.   return true;
  669. }
  670.  
  671. void
  672. DEFUN_VOID (ldsym_init)
  673. {
  674.   obstack_begin (&global_sym_obstack, 20000);
  675. }
  676.