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 / core.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  17KB  |  665 lines

  1. #include "libiberty.h"
  2. #include "gprof.h"
  3. #include "core.h"
  4. #include "symtab.h"
  5.  
  6. #ifndef MIN_INSN_SIZE
  7. /* If not defined in MACHINE_H, assume smallest instruction is 1 byte
  8.    long.  THis is safe but may be needlessly slow on machines where
  9.    all instructions are longer.  */
  10. #define MIN_INSN_SIZE 1
  11. #endif
  12.  
  13. bfd *core_bfd;
  14. int core_num_syms;
  15. asymbol **core_syms;
  16. asection *core_text_sect;
  17. PTR core_text_space;
  18.  
  19. /* For mapping symbols to specific .o files during file ordering.  */
  20. struct function_map {
  21.   char *function_name;
  22.   char *file_name;
  23. };
  24.  
  25. struct function_map *symbol_map;
  26. int symbol_map_count;
  27.  
  28. static void
  29. DEFUN (read_function_mappings, (filename), const char *filename)
  30. {
  31.   FILE *file = fopen (filename, "r");
  32.   char dummy[1024];
  33.   int count = 0;
  34.  
  35.   if (!file)
  36.     {
  37.       fprintf (stderr, "%s: could not open %s.\n", whoami, filename);
  38.       done (1);
  39.     }
  40.  
  41.   /* First parse the mapping file so we know how big we need to
  42.      make our tables.  We also do some sanity checks at this
  43.      time.  */
  44.   while (!feof (file))
  45.     {
  46.       int matches;
  47.  
  48.       matches = fscanf (file, "%[^\n:]", dummy);
  49.       if (!matches)
  50.     {
  51.       fprintf (stderr, "%s: unable to parse mapping file %s.\n",
  52.            whoami, filename);
  53.       done (1);
  54.     }
  55.  
  56.       /* Just skip messages about files with no symbols.  */
  57.       if (!strncmp (dummy, "No symbols in ", 14))
  58.     {
  59.       fscanf (file, "\n");
  60.       continue;
  61.     }
  62.  
  63.       /* Don't care what else is on this line at this point.  */
  64.       fscanf (file, "%[^\n]\n", dummy);
  65.       count++;
  66.     }
  67.  
  68.   /* Now we know how big we need to make our table.  */
  69.   symbol_map = xmalloc (count * sizeof (struct function_map));
  70.  
  71.   /* Rewind the input file so we can read it again.  */
  72.   rewind (file);
  73.  
  74.   /* Read each entry and put it into the table.  */
  75.   count = 0;
  76.   while (!feof (file))
  77.     {
  78.       int matches;
  79.       char *tmp;
  80.  
  81.       matches = fscanf (file, "%[^\n:]", dummy);
  82.       if (!matches)
  83.     {
  84.       fprintf (stderr, "%s: unable to parse mapping file %s.\n",
  85.            whoami, filename);
  86.       done (1);
  87.     }
  88.  
  89.       /* Just skip messages about files with no symbols.  */
  90.       if (!strncmp (dummy, "No symbols in ", 14))
  91.     {
  92.       fscanf (file, "\n");
  93.       continue;
  94.     }
  95.  
  96.       /* dummy has the filename, go ahead and copy it.  */
  97.       symbol_map[count].file_name = xmalloc (strlen (dummy) + 1);
  98.       strcpy (symbol_map[count].file_name, dummy);
  99.  
  100.       /* Now we need the function name.  */
  101.       fscanf (file, "%[^\n]\n", dummy);
  102.       tmp = strrchr (dummy, ' ') + 1;
  103.       symbol_map[count].function_name = xmalloc (strlen (tmp) + 1);
  104.       strcpy (symbol_map[count].function_name, tmp);
  105.       count++;
  106.     }
  107.  
  108.   /* Record the size of the map table for future reference.  */
  109.   symbol_map_count = count;
  110. }
  111.  
  112. void
  113. DEFUN (core_init, (a_out_name), const char *a_out_name)
  114. {
  115.   core_bfd = bfd_openr (a_out_name, 0);
  116.  
  117.   if (!core_bfd)
  118.     {
  119.       perror (a_out_name);
  120.       done (1);
  121.     }
  122.  
  123.   if (!bfd_check_format (core_bfd, bfd_object))
  124.     {
  125.       fprintf (stderr, "%s: %s: not in a.out format\n", whoami, a_out_name);
  126.       done (1);
  127.     }
  128.  
  129.   /* get core's text section: */
  130.   core_text_sect = bfd_get_section_by_name (core_bfd, ".text");
  131.   if (!core_text_sect)
  132.     {
  133.       core_text_sect = bfd_get_section_by_name (core_bfd, "$CODE$");
  134.       if (!core_text_sect)
  135.     {
  136.       fprintf (stderr, "%s: can't find .text section in %s\n",
  137.            whoami, a_out_name);
  138.       done (1);
  139.     }
  140.     }
  141.  
  142.   /* read core's symbol table: */
  143.  
  144.   /* this will probably give us more than we need, but that's ok:  */
  145.   core_num_syms = bfd_get_symtab_upper_bound (core_bfd);
  146.   if (core_num_syms < 0)
  147.     {
  148.       fprintf (stderr, "%s: %s: %s\n", whoami, a_out_name,
  149.            bfd_errmsg (bfd_get_error ()));
  150.       done (1);
  151.     }
  152.  
  153.   core_syms = (asymbol **) xmalloc (core_num_syms);
  154.   core_num_syms = bfd_canonicalize_symtab (core_bfd, core_syms);
  155.   if (core_num_syms < 0)
  156.     {
  157.       fprintf (stderr, "%s: %s: %s\n", whoami, a_out_name,
  158.            bfd_errmsg (bfd_get_error ()));
  159.       done (1);
  160.     }
  161.  
  162.   if (function_mapping_file)
  163.     read_function_mappings (function_mapping_file);
  164. }
  165.  
  166.  
  167. /*
  168.  * Read in the text space of an a.out file
  169.  */
  170. void
  171. DEFUN (core_get_text_space, (core_bfd), bfd * core_bfd)
  172. {
  173.   core_text_space = (PTR) malloc (core_text_sect->_raw_size);
  174.  
  175.   if (!core_text_space)
  176.     {
  177.       fprintf (stderr, "%s: ran out room for %ld bytes of text space\n",
  178.            whoami, core_text_sect->_raw_size);
  179.       done (1);
  180.     }
  181.   if (!bfd_get_section_contents (core_bfd, core_text_sect, core_text_space,
  182.                  0, core_text_sect->_raw_size))
  183.     {
  184.       bfd_perror ("bfd_get_section_contents");
  185.       free (core_text_space);
  186.       core_text_space = 0;
  187.     }
  188.   if (!core_text_space)
  189.     {
  190.       fprintf (stderr, "%s: can't do -c\n", whoami);
  191.     }
  192. }
  193.  
  194.  
  195. /*
  196.  * Return class of symbol SYM.  The returned class can be any of:
  197.  *      0   -> symbol is not interesting to us
  198.  *      'T' -> symbol is a global name
  199.  *      't' -> symbol is a local (static) name
  200.  */
  201. static int
  202. DEFUN (core_sym_class, (sym), asymbol * sym)
  203. {
  204.   symbol_info syminfo;
  205.   const char *name;
  206.   char sym_prefix;
  207.   int i;
  208.  
  209.   if (sym->section == NULL || (sym->flags & BSF_DEBUGGING) != 0)
  210.     {
  211.       return 0;
  212.     }
  213.  
  214.   /*
  215.    * Must be a text symbol, and static text symbols don't qualify if
  216.    * ignore_static_funcs set.
  217.    */
  218.   if (ignore_static_funcs && (sym->flags & BSF_LOCAL))
  219.     {
  220.       DBG (AOUTDEBUG, printf ("[core_sym_class] %s: not a function\n",
  221.                   sym->name));
  222.       return 0;
  223.     }
  224.  
  225.   bfd_get_symbol_info (core_bfd, sym, &syminfo);
  226.   i = syminfo.type;
  227.  
  228.   if (i == 'T')
  229.     {
  230.       return i;            /* it's a global symbol */
  231.     }
  232.  
  233.   if (i != 't')
  234.     {
  235.       /* not a static text symbol */
  236.       DBG (AOUTDEBUG, printf ("[core_sym_class] %s is of class %c\n",
  237.                   sym->name, i));
  238.       return 0;
  239.     }
  240.  
  241.   /* do some more filtering on static function-names: */
  242.  
  243.   if (ignore_static_funcs)
  244.     {
  245.       return 0;
  246.     }
  247.   /*
  248.    * Can't zero-length name or funny characters in name, where
  249.    * `funny' includes: `.' (.o file names) and `$' (Pascal labels).
  250.    */
  251.   if (!sym->name || sym->name[0] == '\0')
  252.     {
  253.       return 0;
  254.     }
  255.  
  256.   for (name = sym->name; *name; ++name)
  257.     {
  258.       if (*name == '.' || *name == '$')
  259.     {
  260.       return 0;
  261.     }
  262.     }
  263.   /*
  264.    * On systems where the C compiler adds an underscore to all
  265.    * names, static names without underscores seem usually to be
  266.    * labels in hand written assembler in the library.  We don't want
  267.    * these names.  This is certainly necessary on a Sparc running
  268.    * SunOS 4.1 (try profiling a program that does a lot of
  269.    * division). I don't know whether it has harmful side effects on
  270.    * other systems.  Perhaps it should be made configurable.
  271.    */
  272.   sym_prefix = bfd_get_symbol_leading_char (core_bfd);
  273.   if ((sym_prefix && sym_prefix != sym->name[0])
  274.   /*
  275.    * GCC may add special symbols to help gdb figure out the file
  276.    * language.  We want to ignore these, since sometimes they mask
  277.    * the real function.  (dj@ctron)
  278.    */
  279.       || !strncmp (sym->name, "__gnu_compiled", 14)
  280.       || !strncmp (sym->name, "___gnu_compiled", 15))
  281.     {
  282.       return 0;
  283.     }
  284.  
  285.   /* If the object file supports marking of function symbols, then we can
  286.      zap anything that doesn't have BSF_FUNCTION set.  */
  287.   if (ignore_non_functions && (sym->flags & BSF_FUNCTION) == 0)
  288.     return 0;
  289.  
  290.   return 't';            /* it's a static text symbol */
  291. }
  292.  
  293.  
  294. /*
  295.  * Get whatever source info we can get regarding address ADDR:
  296.  */
  297. static bool
  298. DEFUN (get_src_info, (addr, filename, name, line_num),
  299.        bfd_vma addr AND const char **filename AND const char **name
  300.        AND int *line_num)
  301. {
  302.   const char *fname = 0, *func_name = 0;
  303.   int l = 0;
  304.  
  305.   if (bfd_find_nearest_line (core_bfd, core_text_sect, core_syms,
  306.                  addr - core_text_sect->vma,
  307.                  &fname, &func_name, (unsigned int *) &l)
  308.       && fname && func_name && l)
  309.     {
  310.       DBG (AOUTDEBUG, printf ("[get_src_info] 0x%lx -> %s:%d (%s)\n",
  311.                   addr, fname, l, func_name));
  312.       *filename = fname;
  313.       *name = func_name;
  314.       *line_num = l;
  315.       return TRUE;
  316.     }
  317.   else
  318.     {
  319.       DBG (AOUTDEBUG, printf ("[get_src_info] no info for 0x%lx (%s:%d,%s)\n",
  320.                   (long) addr, fname ? fname : "<unknown>", l,
  321.                   func_name ? func_name : "<unknown>"));
  322.       return FALSE;
  323.     }
  324. }
  325.  
  326.  
  327. /*
  328.  * Read in symbol table from core.  One symbol per function is
  329.  * entered.
  330.  */
  331. void
  332. DEFUN (core_create_function_syms, (core_bfd), bfd * core_bfd)
  333. {
  334.   bfd_vma min_vma = ~0, max_vma = 0;
  335.   int class;
  336.   long i, j, found, skip;
  337.  
  338.   /* pass 1 - determine upper bound on number of function names: */
  339.   symtab.len = 0;
  340.   for (i = 0; i < core_num_syms; ++i)
  341.     {
  342.       if (!core_sym_class (core_syms[i]))
  343.     {
  344.       continue;
  345.     }
  346.  
  347.       /* This should be replaced with a binary search or hashed
  348.      search.  Gross. 
  349.  
  350.      Don't create a symtab entry for a function that has
  351.      a mapping to a file, unless it's the first function
  352.      in the file.  */
  353.       skip = 0;
  354.       for (j = 0; j < symbol_map_count; j++)
  355.     if (!strcmp (core_syms[i]->name, symbol_map[j].function_name))
  356.       {
  357.         if (j > 0 && ! strcmp (symbol_map [j].file_name,
  358.                     symbol_map [j - 1].file_name))
  359.           skip = 1;
  360.         break;
  361.       }
  362.       if (!skip)
  363.         ++symtab.len;
  364.     }
  365.  
  366.   if (symtab.len == 0)
  367.     {
  368.       fprintf (stderr, "%s: file `%s' has no symbols\n", whoami, a_out_name);
  369.       done (1);
  370.     }
  371.  
  372.   /* the "+ 2" is for the sentinels: */
  373.   symtab.base = (Sym *) xmalloc ((symtab.len + 2) * sizeof (Sym));
  374.  
  375.   /* pass 2 - create symbols: */
  376.  
  377.   symtab.limit = symtab.base;
  378.   for (i = 0; i < core_num_syms; ++i)
  379.     {
  380.       class = core_sym_class (core_syms[i]);
  381.       if (!class)
  382.     {
  383.       DBG (AOUTDEBUG,
  384.            printf ("[core_create_function_syms] rejecting: 0x%lx %s\n",
  385.                core_syms[i]->value, core_syms[i]->name));
  386.       continue;
  387.     }
  388.       /* This should be replaced with a binary search or hashed
  389.      search.  Gross.   */
  390.  
  391.       skip = 0;
  392.       found = 0;
  393.       for (j = 0; j < symbol_map_count; j++)
  394.     if (!strcmp (core_syms[i]->name, symbol_map[j].function_name))
  395.       {
  396.         if (j > 0 && ! strcmp (symbol_map [j].file_name,
  397.                     symbol_map [j - 1].file_name))
  398.           skip = 1;
  399.         else
  400.           found = j;
  401.         break;
  402.       }
  403.  
  404.       if (skip)
  405.     continue;
  406.  
  407.       sym_init (symtab.limit);
  408.  
  409.       /* symbol offsets are always section-relative: */
  410.  
  411.       symtab.limit->addr = core_syms[i]->value + core_syms[i]->section->vma;
  412.       if (symbol_map_count
  413.       && !strcmp (core_syms[i]->name, symbol_map[found].function_name))
  414.     {
  415.       symtab.limit->name = symbol_map[found].file_name;
  416.       symtab.limit->mapped = 1;
  417.     }
  418.       else
  419.     {
  420.       symtab.limit->name = core_syms[i]->name;
  421.       symtab.limit->mapped = 0;
  422.     }
  423.  
  424. #ifdef __osf__
  425.       /*
  426.        * Suppress symbols that are not function names.  This is
  427.        * useful to suppress code-labels and aliases.
  428.        *
  429.        * This is known to be useful under DEC's OSF/1.  Under SunOS 4.x,
  430.        * labels do not appear in the symbol table info, so this isn't
  431.        * necessary.
  432.        */
  433.       {
  434.     const char *filename, *func_name;
  435.     
  436.     if (get_src_info (symtab.limit->addr, &filename, &func_name,
  437.               &symtab.limit->line_num))
  438.       {
  439.         symtab.limit->file = source_file_lookup_path (filename);
  440.  
  441.         if (strcmp (symtab.limit->name, func_name) != 0)
  442.           {
  443.         /*
  444.          * The symbol's address maps to a different name, so
  445.          * it can't be a function-entry point.  This happens
  446.          * for labels, for example.
  447.          */
  448.         DBG (AOUTDEBUG,
  449.              printf ("[core_create_function_syms: rej %s (maps to %s)\n",
  450.                  symtab.limit->name, func_name));
  451.         continue;
  452.           }
  453.       }
  454.       }
  455. #endif
  456.  
  457.       symtab.limit->is_func = TRUE;
  458.       symtab.limit->is_bb_head = TRUE;
  459.       if (class == 't')
  460.     {
  461.       symtab.limit->is_static = TRUE;
  462.     }
  463.  
  464.       min_vma = MIN (symtab.limit->addr, min_vma);
  465.       max_vma = MAX (symtab.limit->addr, max_vma);
  466.  
  467.       /*
  468.        * If we see "main" without an initial '_', we assume names
  469.        * are *not* prefixed by '_'.
  470.        */
  471.       if (symtab.limit->name[0] == 'm' && discard_underscores
  472.       && strcmp (symtab.limit->name, "main") == 0)
  473.     {
  474.       discard_underscores = 0;
  475.     }
  476.  
  477.       DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n",
  478.                   (long) (symtab.limit - symtab.base),
  479.                   symtab.limit->name, symtab.limit->addr));
  480.       ++symtab.limit;
  481.     }
  482.  
  483.   /* create sentinels: */
  484.  
  485.   sym_init (symtab.limit);
  486.   symtab.limit->name = "<locore>";
  487.   symtab.limit->addr = 0;
  488.   symtab.limit->end_addr = min_vma - 1;
  489.   ++symtab.limit;
  490.  
  491.   sym_init (symtab.limit);
  492.   symtab.limit->name = "<hicore>";
  493.   symtab.limit->addr = max_vma + 1;
  494.   symtab.limit->end_addr = ~0;
  495.   ++symtab.limit;
  496.  
  497.   symtab.len = symtab.limit - symtab.base;
  498.   symtab_finalize (&symtab);
  499. }
  500.  
  501.  
  502. /*
  503.  * Read in symbol table from core.  One symbol per line of source code
  504.  * is entered.
  505.  */
  506. void
  507. DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd)
  508. {
  509.   char prev_name[PATH_MAX], prev_filename[PATH_MAX];
  510.   bfd_vma vma, min_vma = ~0, max_vma = 0;
  511.   bfd_vma offset, prev_offset, min_dist;
  512.   Sym *prev, dummy, *sentinel, *sym;
  513.   const char *filename;
  514.   int prev_line_num, i;
  515.   Sym_Table ltab;
  516.   /*
  517.    * Create symbols for functions as usual.  This is necessary in
  518.    * cases where parts of a program were not compiled with -g.  For
  519.    * those parts we still want to get info at the function level:
  520.    */
  521.   core_create_function_syms (core_bfd);
  522.  
  523.   /* pass 1 - counter number of symbols: */
  524.  
  525.   /*
  526.    * To find all line information, walk through all possible
  527.    * text-space addresses (one by one!) and get the debugging
  528.    * info for each address.  When the debugging info changes,
  529.    * it is time to create a new symbol.
  530.    *
  531.    * Of course, this is rather slow and it would be better if
  532.    * bfd would provide an iterator for enumerating all line
  533.    * infos, but for now, we try to speed up the second pass
  534.    * by determining what the minimum code distance between two
  535.    * lines is.
  536.    */
  537.   prev_name[0] = '\0';
  538.   ltab.len = 0;
  539.   min_dist = core_text_sect->_raw_size;
  540.   prev_offset = -min_dist;
  541.   prev_filename[0] = '\0';
  542.   prev_line_num = 0;
  543.   for (offset = 0; offset < core_text_sect->_raw_size; offset += MIN_INSN_SIZE)
  544.     {
  545.       vma = core_text_sect->vma + offset;
  546.       if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num)
  547.       || (prev_line_num == dummy.line_num &&
  548.           strcmp (prev_name, dummy.name) == 0
  549.           && strcmp (prev_filename, filename) == 0))
  550.     {
  551.       continue;
  552.     }
  553.  
  554.       ++ltab.len;
  555.       prev_line_num = dummy.line_num;
  556.       strcpy (prev_name, dummy.name);
  557.       strcpy (prev_filename, filename);
  558.  
  559.       if (offset - prev_offset < min_dist)
  560.     {
  561.       min_dist = offset - prev_offset;
  562.     }
  563.       prev_offset = offset;
  564.  
  565.       min_vma = MIN (vma, min_vma);
  566.       max_vma = MAX (vma, max_vma);
  567.     }
  568.  
  569.   DBG (AOUTDEBUG, printf ("[core_create_line_syms] min_dist=%lx\n", min_dist));
  570.  
  571.   /* make room for function symbols, too: */
  572.   ltab.len += symtab.len;
  573.   ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym));
  574.   ltab.limit = ltab.base;
  575.  
  576.   /* pass 2 - create symbols: */
  577.  
  578.   prev = 0;
  579.   for (offset = 0; offset < core_text_sect->_raw_size; offset += min_dist)
  580.     {
  581.       sym_init (ltab.limit);
  582.       if (!get_src_info (core_text_sect->vma + offset, &filename,
  583.              <ab.limit->name, <ab.limit->line_num)
  584.       || (prev && prev->line_num == ltab.limit->line_num
  585.           && strcmp (prev->name, ltab.limit->name) == 0
  586.           && strcmp (prev->file->name, filename) == 0))
  587.     {
  588.       continue;
  589.     }
  590.  
  591.       /* make name pointer a malloc'ed string: */
  592.       ltab.limit->name = xstrdup (ltab.limit->name);
  593.       ltab.limit->file = source_file_lookup_path (filename);
  594.  
  595.       ltab.limit->addr = core_text_sect->vma + offset;
  596.       prev = ltab.limit;
  597.  
  598.       /*
  599.        * If we see "main" without an initial '_', we assume names
  600.        * are *not* prefixed by '_'.
  601.        */
  602.       if (ltab.limit->name[0] == 'm' && discard_underscores
  603.       && strcmp (ltab.limit->name, "main") == 0)
  604.     {
  605.       discard_underscores = 0;
  606.     }
  607.  
  608.       DBG (AOUTDEBUG, printf ("[core_create_line_syms] %d %s 0x%lx\n",
  609.                   ltab.len, ltab.limit->name,
  610.                   ltab.limit->addr));
  611.       ++ltab.limit;
  612.     }
  613.  
  614.   /* update sentinels: */
  615.  
  616.   sentinel = sym_lookup (&symtab, 0);
  617.   if (strcmp (sentinel->name, "<locore>") == 0
  618.       && min_vma <= sentinel->end_addr)
  619.     {
  620.       sentinel->end_addr = min_vma - 1;
  621.     }
  622.  
  623.   sentinel = sym_lookup (&symtab, ~0);
  624.   if (strcmp (sentinel->name, "<hicore>") == 0 && max_vma >= sentinel->addr)
  625.     {
  626.       sentinel->addr = max_vma + 1;
  627.     }
  628.  
  629.   /* copy in function symbols: */
  630.   memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym));
  631.   ltab.limit += symtab.len;
  632.  
  633.   if (ltab.limit - ltab.base != ltab.len)
  634.     {
  635.       fprintf (stderr,
  636.            "%s: somebody miscounted: ltab.len=%ld instead of %d\n",
  637.            whoami, (long) (ltab.limit - ltab.base), ltab.len);
  638.       done (1);
  639.     }
  640.  
  641.   /* finalize ltab and make it symbol table: */
  642.  
  643.   symtab_finalize (<ab);
  644.   free (symtab.base);
  645.   symtab = ltab;
  646.  
  647.   /* now go through all core symbols and set is_static accordingly: */
  648.  
  649.   for (i = 0; i < core_num_syms; ++i)
  650.     {
  651.       if (core_sym_class (core_syms[i]) == 't')
  652.     {
  653.       sym = sym_lookup (&symtab, core_syms[i]->value
  654.                 + core_syms[i]->section->vma);
  655.       do
  656.         {
  657.           sym++->is_static = TRUE;
  658.         }
  659.       while (sym->file == sym[-1].file &&
  660.          strcmp (sym->name, sym[-1].name) == 0);
  661.     }
  662.     }
  663.  
  664. }
  665.