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

  1. #include "gprof.h"
  2. #include "cg_arcs.h"
  3. #include "core.h"
  4. #include "symtab.h"
  5.  
  6. Sym_Table symtab;
  7.  
  8.  
  9. /*
  10.  * Initialize a symbol (so it's empty).
  11.  */
  12. void
  13. DEFUN (sym_init, (sym), Sym * sym)
  14. {
  15.   memset (sym, 0, sizeof (*sym));
  16.   /*
  17.    * It is not safe to assume that a binary zero corresponds to
  18.    * a floating-point 0.0, so initialize floats explicitly:
  19.    */
  20.   sym->hist.time = 0.0;
  21.   sym->cg.child_time = 0.0;
  22.   sym->cg.prop.fract = 0.0;
  23.   sym->cg.prop.self = 0.0;
  24.   sym->cg.prop.child = 0.0;
  25. }
  26.  
  27.  
  28. /*
  29.  * Compare the function entry-point of two symbols and return <0, =0,
  30.  * or >0 depending on whether the left value is smaller than, equal
  31.  * to, or greater than the right value.  If two symbols are equal
  32.  * but one has is_func set and the other doesn't, we make the
  33.  * non-function symbol one "bigger" so that the function symbol will
  34.  * survive duplicate removal.  Finally, if both symbols have the
  35.  * same is_func value, we discriminate against is_static such that
  36.  * the global symbol survives.
  37.  */
  38. static int
  39. DEFUN (cmp_addr, (lp, rp), const PTR lp AND const PTR rp)
  40. {
  41.   Sym *left = (Sym *) lp;
  42.   Sym *right = (Sym *) rp;
  43.  
  44.   if (left->addr > right->addr)
  45.     {
  46.       return 1;
  47.     }
  48.   else if (left->addr < right->addr)
  49.     {
  50.       return -1;
  51.     }
  52.  
  53.   if (left->is_func != right->is_func)
  54.     {
  55.       return right->is_func - left->is_func;
  56.     }
  57.  
  58.   return left->is_static - right->is_static;
  59. }
  60.  
  61.  
  62. void
  63. DEFUN (symtab_finalize, (tab), Sym_Table * tab)
  64. {
  65.   Sym *src, *dst;
  66.   bfd_vma prev_addr;
  67.  
  68.   if (!tab->len)
  69.     {
  70.       return;
  71.     }
  72.  
  73.   /*
  74.    * Sort symbol table in order of increasing function addresses:
  75.    */
  76.   qsort (tab->base, tab->len, sizeof (Sym), cmp_addr);
  77.  
  78.   /*
  79.    * Remove duplicate entries to speed-up later processing and
  80.    * set end_addr if its not set yet:
  81.    */
  82.   prev_addr = tab->base[0].addr + 1;
  83.   for (src = dst = tab->base; src < tab->limit; ++src)
  84.     {
  85.       if (src->addr == prev_addr)
  86.     {
  87.       /*
  88.        * If same address, favor global symbol over static one.
  89.        * If both symbols are either static or global, check
  90.        * whether one has name beginning with underscore while
  91.        * the other doesn't.  In such cases, keep sym without
  92.        * underscore.  This takes cares of compiler generated
  93.        * symbols (such as __gnu_compiled, __c89_used, etc.).
  94.        */
  95.       if ((!src->is_static && dst[-1].is_static)
  96.           || ((src->is_static == dst[-1].is_static)
  97.           && ((src->name[0] != '_' && dst[-1].name[0] == '_')
  98.               || (src->name[0]
  99.               && src->name[1] != '_' && dst[-1].name[1] == '_'))))
  100.         {
  101.           DBG (AOUTDEBUG | IDDEBUG,
  102.            printf ("[symtab_finalize] favor %s@%c%c over %s@%c%c",
  103.                src->name, src->is_static ? 't' : 'T',
  104.                src->is_func ? 'F' : 'f',
  105.                dst[-1].name, dst[-1].is_static ? 't' : 'T',
  106.                dst[-1].is_func ? 'F' : 'f');
  107.            printf (" (addr=%lx)\n", src->addr));
  108.           dst[-1] = *src;
  109.         }
  110.       else
  111.         {
  112.           DBG (AOUTDEBUG | IDDEBUG,
  113.            printf ("[symtab_finalize] favor %s@%c%c over %s@%c%c",
  114.                dst[-1].name, dst[-1].is_static ? 't' : 'T',
  115.                dst[-1].is_func ? 'F' : 'f',
  116.                src->name, src->is_static ? 't' : 'T',
  117.                src->is_func ? 'F' : 'f');
  118.            printf (" (addr=%lx)\n", src->addr));
  119.         }
  120.     }
  121.       else
  122.     {
  123.       if (dst > tab->base && dst[-1].end_addr == 0)
  124.         {
  125.           dst[-1].end_addr = src->addr - 1;
  126.         }
  127.  
  128.       /* retain sym only if it has a non-empty address range: */
  129.       if (!src->end_addr || src->addr <= src->end_addr)
  130.         {
  131.           *dst++ = *src;
  132.           prev_addr = src->addr;
  133.         }
  134.     }
  135.     }
  136.   if (tab->len > 0 && dst[-1].end_addr == 0)
  137.     {
  138.       dst[-1].end_addr = core_text_sect->vma + core_text_sect->_raw_size - 1;
  139.     }
  140.  
  141.   DBG (AOUTDEBUG | IDDEBUG,
  142.        printf ("[symtab_finalize]: removed %d duplicate entries\n",
  143.            tab->len - (int) (dst - tab->base)));
  144.  
  145.   tab->limit = dst;
  146.   tab->len = tab->limit - tab->base;
  147.  
  148.   DBG (AOUTDEBUG | IDDEBUG,
  149.        int j;
  150.  
  151.        for (j = 0; j < tab->len; ++j)
  152.        {
  153.        printf ("[symtab_finalize] 0x%lx-0x%lx\t%s\n",
  154.            (long) tab->base[j].addr, (long) tab->base[j].end_addr,
  155.            tab->base[j].name);
  156.        }
  157.   );
  158. }
  159.  
  160.  
  161. #ifdef DEBUG
  162.  
  163. Sym *
  164. DEFUN (dbg_sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address)
  165. {
  166.   long low, mid, high;
  167.   Sym *sym;
  168.  
  169.   fprintf (stderr, "[sym_lookup] address 0x%lx\n", address);
  170.  
  171.   sym = symtab->base;
  172.   for (low = 0, high = symtab->len - 1; low != high;)
  173.     {
  174.       mid = (high + low) >> 1;
  175.       fprintf (stderr, "[dbg_sym_lookup] low=0x%lx, mid=0x%lx, high=0x%lx\n",
  176.            low, mid, high);
  177.       fprintf (stderr, "[dbg_sym_lookup] sym[m]=0x%lx sym[m + 1]=0x%lx\n",
  178.            sym[mid].addr, sym[mid + 1].addr);
  179.       if (sym[mid].addr <= address && sym[mid + 1].addr > address)
  180.     {
  181.       return &sym[mid];
  182.     }
  183.       if (sym[mid].addr > address)
  184.     {
  185.       high = mid;
  186.     }
  187.       else
  188.     {
  189.       low = mid + 1;
  190.     }
  191.     }
  192.   fprintf (stderr, "[sym_lookup] binary search fails???\n");
  193.   return 0;
  194. }
  195.  
  196. #endif    /* DEBUG */
  197.  
  198.  
  199. /*
  200.  * Look up an address in the symbol-table that is sorted by address.
  201.  * If address does not hit any symbol, 0 is returned.
  202.  */
  203. Sym *
  204. DEFUN (sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address)
  205. {
  206.   long low, high;
  207.   long mid = -1;
  208.   Sym *sym;
  209. #ifdef DEBUG
  210.   int probes = 0;
  211. #endif /* DEBUG */
  212.  
  213.   if (!symtab->len)
  214.     {
  215.       return 0;
  216.     }
  217.  
  218.   sym = symtab->base;
  219.   for (low = 0, high = symtab->len - 1; low != high;)
  220.     {
  221.       DBG (LOOKUPDEBUG, ++probes);
  222.       mid = (high + low) / 2;
  223.       if (sym[mid].addr <= address && sym[mid + 1].addr > address)
  224.     {
  225.       if (address > sym[mid].end_addr)
  226.         {
  227.           /*
  228.            * Address falls into gap between sym[mid] and
  229.            * sym[mid + 1]:
  230.            */
  231.           return 0;
  232.         }
  233.       else
  234.         {
  235.           DBG (LOOKUPDEBUG,
  236.            printf ("[sym_lookup] %d probes (symtab->len=%d)\n",
  237.                probes, symtab->len - 1));
  238.           return &sym[mid];
  239.         }
  240.     }
  241.       if (sym[mid].addr > address)
  242.     {
  243.       high = mid;
  244.     }
  245.       else
  246.     {
  247.       low = mid + 1;
  248.     }
  249.     }
  250.   if (sym[mid + 1].addr <= address)
  251.     {
  252.       if (address > sym[mid + 1].end_addr)
  253.     {
  254.       /* address is beyond end of sym[mid + 1]: */
  255.       return 0;
  256.     }
  257.       else
  258.     {
  259.       DBG (LOOKUPDEBUG, printf ("[sym_lookup] %d (%d) probes, fall off\n",
  260.                     probes, symtab->len - 1));
  261.       return &sym[mid + 1];
  262.     }
  263.     }
  264.   return 0;
  265. }
  266.