home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / binutils-2.7-src.tgz / tar.out / fsf / binutils / ld / ldcref.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  8KB  |  327 lines

  1. /* ldcref.c -- output a cross reference table
  2.    Copyright (C) 1996 Free Software Foundation, Inc.
  3.    Written by Ian Lance Taylor <ian@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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  20.  
  21. /* This file holds routines that manage the cross reference table.  */
  22.  
  23. #include "bfd.h"
  24. #include "sysdep.h"
  25. #include "bfdlink.h"
  26. #include "libiberty.h"
  27.  
  28. #include "ld.h"
  29. #include "ldmain.h"
  30. #include "ldmisc.h"
  31.  
  32. /* We keep an instance of this structure for each reference to a
  33.    symbol from a given object.  */
  34.  
  35. struct cref_ref
  36. {
  37.   /* The next reference.  */
  38.   struct cref_ref *next;
  39.   /* The object.  */
  40.   bfd *abfd;
  41.   /* True if the symbol is defined.  */
  42.   unsigned int def : 1;
  43.   /* True if the symbol is common.  */
  44.   unsigned int common : 1;
  45.   /* True if the symbol is undefined.  */
  46.   unsigned int undef : 1;
  47. };
  48.  
  49. /* We keep a hash table of symbols.  Each entry looks like this.  */
  50.  
  51. struct cref_hash_entry
  52. {
  53.   struct bfd_hash_entry root;
  54.   /* The demangled name.  */
  55.   char *demangled;
  56.   /* References to and definitions of this symbol.  */
  57.   struct cref_ref *refs;
  58. };
  59.  
  60. /* This is what the hash table looks like.  */
  61.  
  62. struct cref_hash_table
  63. {
  64.   struct bfd_hash_table root;
  65. };
  66.  
  67. /* Local functions.  */
  68.  
  69. static struct bfd_hash_entry *cref_hash_newfunc
  70.   PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
  71. static boolean cref_fill_array PARAMS ((struct cref_hash_entry *, PTR));
  72. static int cref_sort_array PARAMS ((const PTR, const PTR));
  73. static void output_one_cref PARAMS ((FILE *, struct cref_hash_entry *));
  74.  
  75. /* Look up an entry in the cref hash table.  */
  76.  
  77. #define cref_hash_lookup(table, string, create, copy)        \
  78.   ((struct cref_hash_entry *)                    \
  79.    bfd_hash_lookup (&(table)->root, (string), (create), (copy)))
  80.  
  81. /* Traverse the cref hash table.  */
  82.  
  83. #define cref_hash_traverse(table, func, info)                \
  84.   (bfd_hash_traverse                            \
  85.    (&(table)->root,                            \
  86.     (boolean (*) PARAMS ((struct bfd_hash_entry *, PTR))) (func),    \
  87.     (info)))
  88.  
  89. /* The cref hash table.  */
  90.  
  91. static struct cref_hash_table cref_table;
  92.  
  93. /* Whether the cref hash table has been initialized.  */
  94.  
  95. static boolean cref_initialized;
  96.  
  97. /* The number of symbols seen so far.  */
  98.  
  99. static size_t cref_symcount;
  100.  
  101. /* Create an entry in a cref hash table.  */
  102.  
  103. static struct bfd_hash_entry *
  104. cref_hash_newfunc (entry, table, string)
  105.      struct bfd_hash_entry *entry;
  106.      struct bfd_hash_table *table;
  107.      const char *string;
  108. {
  109.   struct cref_hash_entry *ret = (struct cref_hash_entry *) entry;
  110.  
  111.   /* Allocate the structure if it has not already been allocated by a
  112.      subclass.  */
  113.   if (ret == NULL)
  114.     ret = ((struct cref_hash_entry *)
  115.        bfd_hash_allocate (table, sizeof (struct cref_hash_entry)));
  116.   if (ret == NULL)
  117.     return (struct bfd_hash_entry *) ret;
  118.  
  119.   /* Call the allocation method of the superclass.  */
  120.   ret = ((struct cref_hash_entry *)
  121.      bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
  122.   if (ret != NULL)
  123.     {
  124.       /* Set local fields.  */
  125.       ret->demangled = NULL;
  126.       ret->refs = NULL;
  127.  
  128.       /* Keep a count of the number of entries created in the hash
  129.          table.  */
  130.       ++cref_symcount;
  131.     }
  132.  
  133.   return (struct bfd_hash_entry *) ret;
  134. }
  135.  
  136. /* Add a symbol to the cref hash table.  This is called for every
  137.    symbol that is seen during the link.  */
  138.  
  139. /*ARGSUSED*/
  140. void
  141. add_cref (name, abfd, section, value)
  142.      const char *name;
  143.      bfd *abfd;
  144.      asection *section;
  145.      bfd_vma value;
  146. {
  147.   struct cref_hash_entry *h;
  148.   struct cref_ref *r;
  149.  
  150.   if (! cref_initialized)
  151.     {
  152.       if (! bfd_hash_table_init (&cref_table.root, cref_hash_newfunc))
  153.     einfo ("%X%P: bfd_hash_table_init of cref table failed: %E\n");
  154.       cref_initialized = true;
  155.     }
  156.  
  157.   h = cref_hash_lookup (&cref_table, name, true, false);
  158.   if (h == NULL)
  159.     einfo ("%X%P: cref_hash_lookup failed: %E\n");
  160.  
  161.   for (r = h->refs; r != NULL; r = r->next)
  162.     if (r->abfd == abfd)
  163.       break;
  164.  
  165.   if (r == NULL)
  166.     {
  167.       r = (struct cref_ref *) xmalloc (sizeof *r);
  168.       r->next = h->refs;
  169.       h->refs = r;
  170.       r->abfd = abfd;
  171.       r->def = false;
  172.       r->common = false;
  173.       r->undef = false;
  174.     }
  175.  
  176.   if (bfd_is_und_section (section))
  177.     r->undef = true;
  178.   else if (bfd_is_com_section (section))
  179.     r->common = true;
  180.   else
  181.     r->def = true;
  182. }
  183.  
  184. /* Copy the addresses of the hash table entries into an array.  This
  185.    is called via cref_hash_traverse.  We also fill in the demangled
  186.    name.  */
  187.  
  188. static boolean
  189. cref_fill_array (h, data)
  190.      struct cref_hash_entry *h;
  191.      PTR data;
  192. {
  193.   struct cref_hash_entry ***pph = (struct cref_hash_entry ***) data;
  194.  
  195.   ASSERT (h->demangled == NULL);
  196.   h->demangled = demangle (h->root.string);
  197.  
  198.   **pph = h;
  199.  
  200.   ++*pph;
  201.  
  202.   return true;
  203. }
  204.  
  205. /* Sort an array of cref hash table entries by name.  */
  206.  
  207. static int
  208. cref_sort_array (a1, a2)
  209.      const PTR a1;
  210.      const PTR a2;
  211. {
  212.   const struct cref_hash_entry **p1 = (const struct cref_hash_entry **) a1;
  213.   const struct cref_hash_entry **p2 = (const struct cref_hash_entry **) a2;
  214.  
  215.   return strcmp ((*p1)->demangled, (*p2)->demangled);
  216. }
  217.  
  218. /* Write out the cref table.  */
  219.  
  220. #define FILECOL (50)
  221.  
  222. void
  223. output_cref (fp)
  224.      FILE *fp;
  225. {
  226.   int len;
  227.   struct cref_hash_entry **csyms, **csym_fill, **csym, **csym_end;
  228.  
  229.   fprintf (fp, "\nCross Reference Table\n\n");
  230.   fprintf (fp, "Symbol");
  231.   len = sizeof "Symbol" - 1;
  232.   while (len < FILECOL)
  233.     {
  234.       putc (' ' , fp);
  235.       ++len;
  236.     }
  237.   fprintf (fp, "File\n");
  238.  
  239.   if (! cref_initialized)
  240.     {
  241.       fprintf (fp, "No symbols\n");
  242.       return;
  243.     }
  244.  
  245.   csyms = ((struct cref_hash_entry **)
  246.        xmalloc (cref_symcount * sizeof (*csyms)));
  247.  
  248.   csym_fill = csyms;
  249.   cref_hash_traverse (&cref_table, cref_fill_array, &csym_fill);
  250.   ASSERT (csym_fill - csyms == cref_symcount);
  251.  
  252.   qsort (csyms, cref_symcount, sizeof (*csyms), cref_sort_array);
  253.  
  254.   csym_end = csyms + cref_symcount;
  255.   for (csym = csyms; csym < csym_end; csym++)
  256.     output_one_cref (fp, *csym);
  257. }
  258.  
  259. /* Output one entry in the cross reference table.  */
  260.  
  261. static void
  262. output_one_cref (fp, h)
  263.      FILE *fp;
  264.      struct cref_hash_entry *h;
  265. {
  266.   int len;
  267.   struct bfd_link_hash_entry *hl;
  268.   struct cref_ref *r;
  269.  
  270.   hl = bfd_link_hash_lookup (link_info.hash, h->root.string, false,
  271.                  false, true);
  272.   if (hl == NULL)
  273.     einfo ("%P: symbol `%T' missing from main hash table\n",
  274.        h->root.string);
  275.   else
  276.     {
  277.       /* If this symbol is defined in a dynamic object but never
  278.      referenced by a normal object, then don't print it.  */
  279.       if (hl->type == bfd_link_hash_defined)
  280.     {
  281.       if (hl->u.def.section->output_section == NULL)
  282.         return;
  283.       if ((hl->u.def.section->owner->flags & DYNAMIC) != 0)
  284.         {
  285.           for (r = h->refs; r != NULL; r = r->next)
  286.         if ((r->abfd->flags & DYNAMIC) == 0)
  287.           break;
  288.           if (r == NULL)
  289.         return;
  290.         }
  291.     }
  292.     }
  293.  
  294.   fprintf (fp, "%s ", h->demangled);
  295.   len = strlen (h->demangled) + 1;
  296.  
  297.   for (r = h->refs; r != NULL; r = r->next)
  298.     {
  299.       if (r->def)
  300.     {
  301.       while (len < FILECOL)
  302.         {
  303.           putc (' ', fp);
  304.           ++len;
  305.         }
  306.       finfo (fp, "%B\n", r->abfd);
  307.       len = 0;
  308.     }
  309.     }
  310.  
  311.   for (r = h->refs; r != NULL; r = r->next)
  312.     {
  313.       if (! r->def)
  314.     {
  315.       while (len < FILECOL)
  316.         {
  317.           putc (' ', fp);
  318.           ++len;
  319.         }
  320.       finfo (fp, "%B\n", r->abfd);
  321.       len = 0;
  322.     }
  323.     }
  324.  
  325.   ASSERT (len == 0);
  326. }
  327.