xref: /netbsd-src/external/gpl3/binutils.old/dist/gprof/corefile.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
175fd0b74Schristos /* corefile.c
275fd0b74Schristos 
3*e992f068Schristos    Copyright (C) 1999-2022 Free Software Foundation, Inc.
475fd0b74Schristos 
575fd0b74Schristos    This file is part of GNU Binutils.
675fd0b74Schristos 
775fd0b74Schristos    This program is free software; you can redistribute it and/or modify
875fd0b74Schristos    it under the terms of the GNU General Public License as published by
975fd0b74Schristos    the Free Software Foundation; either version 3 of the License, or
1075fd0b74Schristos    (at your option) any later version.
1175fd0b74Schristos 
1275fd0b74Schristos    This program is distributed in the hope that it will be useful,
1375fd0b74Schristos    but WITHOUT ANY WARRANTY; without even the implied warranty of
1475fd0b74Schristos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1575fd0b74Schristos    GNU General Public License for more details.
1675fd0b74Schristos 
1775fd0b74Schristos    You should have received a copy of the GNU General Public License
1875fd0b74Schristos    along with this program; if not, write to the Free Software
1975fd0b74Schristos    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
2075fd0b74Schristos    02110-1301, USA.  */
2175fd0b74Schristos 
2275fd0b74Schristos #include "gprof.h"
2375fd0b74Schristos #include "libiberty.h"
2475fd0b74Schristos #include "filenames.h"
2575fd0b74Schristos #include "search_list.h"
2675fd0b74Schristos #include "source.h"
2775fd0b74Schristos #include "symtab.h"
2875fd0b74Schristos #include "hist.h"
2975fd0b74Schristos #include "corefile.h"
3075fd0b74Schristos #include "safe-ctype.h"
31ede78133Schristos #include <limits.h>    /* For UINT_MAX.  */
3275fd0b74Schristos 
3375fd0b74Schristos #include <stdlib.h>
3475fd0b74Schristos 
3575fd0b74Schristos bfd *core_bfd;
3675fd0b74Schristos static int core_num_syms;
3775fd0b74Schristos static asymbol **core_syms;
3875fd0b74Schristos asection *core_text_sect;
3975fd0b74Schristos void * core_text_space;
4075fd0b74Schristos 
4175fd0b74Schristos static int min_insn_size;
4275fd0b74Schristos int offset_to_code;
4375fd0b74Schristos 
4475fd0b74Schristos /* For mapping symbols to specific .o files during file ordering.  */
4575fd0b74Schristos struct function_map * symbol_map;
4675fd0b74Schristos unsigned int symbol_map_count;
4775fd0b74Schristos 
4875fd0b74Schristos static void read_function_mappings (const char *);
4975fd0b74Schristos static int core_sym_class (asymbol *);
50*e992f068Schristos static bool get_src_info
5175fd0b74Schristos   (bfd_vma, const char **, const char **, int *);
5275fd0b74Schristos 
5375fd0b74Schristos extern void i386_find_call  (Sym *, bfd_vma, bfd_vma);
5475fd0b74Schristos extern void alpha_find_call (Sym *, bfd_vma, bfd_vma);
5575fd0b74Schristos extern void vax_find_call   (Sym *, bfd_vma, bfd_vma);
5675fd0b74Schristos extern void sparc_find_call (Sym *, bfd_vma, bfd_vma);
5775fd0b74Schristos extern void mips_find_call  (Sym *, bfd_vma, bfd_vma);
5875fd0b74Schristos extern void aarch64_find_call (Sym *, bfd_vma, bfd_vma);
5975fd0b74Schristos 
6075fd0b74Schristos static void
parse_error(const char * filename)6175fd0b74Schristos parse_error (const char *filename)
6275fd0b74Schristos {
6375fd0b74Schristos   fprintf (stderr, _("%s: unable to parse mapping file %s.\n"), whoami, filename);
6475fd0b74Schristos   done (1);
6575fd0b74Schristos }
6675fd0b74Schristos 
6775fd0b74Schristos /* Compare two function_map structs based on function name.
6875fd0b74Schristos    We want to sort in ascending order.  */
6975fd0b74Schristos 
7075fd0b74Schristos static int
cmp_symbol_map(const void * l,const void * r)7175fd0b74Schristos cmp_symbol_map (const void * l, const void * r)
7275fd0b74Schristos {
7375fd0b74Schristos   return strcmp (((struct function_map *) l)->function_name,
7475fd0b74Schristos 		 ((struct function_map *) r)->function_name);
7575fd0b74Schristos }
7675fd0b74Schristos 
77ede78133Schristos #define BUFSIZE      (1024)
78ede78133Schristos /* This is BUFSIZE - 1 as a string.  Suitable for use in fprintf/sscanf format strings.  */
79ede78133Schristos #define STR_BUFSIZE  "1023"
80ede78133Schristos 
8175fd0b74Schristos static void
read_function_mappings(const char * filename)8275fd0b74Schristos read_function_mappings (const char *filename)
8375fd0b74Schristos {
8475fd0b74Schristos   FILE * file = fopen (filename, "r");
85ede78133Schristos   char dummy[BUFSIZE];
8675fd0b74Schristos   int count = 0;
8775fd0b74Schristos   unsigned int i;
8875fd0b74Schristos 
8975fd0b74Schristos   if (!file)
9075fd0b74Schristos     {
9175fd0b74Schristos       fprintf (stderr, _("%s: could not open %s.\n"), whoami, filename);
9275fd0b74Schristos       done (1);
9375fd0b74Schristos     }
9475fd0b74Schristos 
9575fd0b74Schristos   /* First parse the mapping file so we know how big we need to
9675fd0b74Schristos      make our tables.  We also do some sanity checks at this
9775fd0b74Schristos      time.  */
9875fd0b74Schristos   while (!feof (file))
9975fd0b74Schristos     {
10075fd0b74Schristos       int matches;
10175fd0b74Schristos 
102ede78133Schristos       matches = fscanf (file, "%" STR_BUFSIZE "[^\n:]", dummy);
10375fd0b74Schristos       if (!matches)
10475fd0b74Schristos 	parse_error (filename);
10575fd0b74Schristos 
10675fd0b74Schristos       /* Just skip messages about files with no symbols.  */
10775fd0b74Schristos       if (!strncmp (dummy, "No symbols in ", 14))
10875fd0b74Schristos 	{
10975fd0b74Schristos 	  matches = fscanf (file, "\n");
11075fd0b74Schristos 	  if (matches == EOF)
11175fd0b74Schristos 	    parse_error (filename);
11275fd0b74Schristos 	  continue;
11375fd0b74Schristos 	}
11475fd0b74Schristos 
11575fd0b74Schristos       /* Don't care what else is on this line at this point.  */
116ede78133Schristos       matches = fscanf (file, "%" STR_BUFSIZE "[^\n]\n", dummy);
11775fd0b74Schristos       if (!matches)
11875fd0b74Schristos 	parse_error (filename);
11975fd0b74Schristos       count++;
12075fd0b74Schristos     }
12175fd0b74Schristos 
12275fd0b74Schristos   /* Now we know how big we need to make our table.  */
12375fd0b74Schristos   symbol_map = ((struct function_map *)
12475fd0b74Schristos 		xmalloc (count * sizeof (struct function_map)));
12575fd0b74Schristos 
12675fd0b74Schristos   /* Rewind the input file so we can read it again.  */
12775fd0b74Schristos   rewind (file);
12875fd0b74Schristos 
12975fd0b74Schristos   /* Read each entry and put it into the table.  */
13075fd0b74Schristos   count = 0;
13175fd0b74Schristos   while (!feof (file))
13275fd0b74Schristos     {
13375fd0b74Schristos       int matches;
13475fd0b74Schristos       char *tmp;
13575fd0b74Schristos 
136ede78133Schristos       matches = fscanf (file, "%" STR_BUFSIZE "[^\n:]", dummy);
13775fd0b74Schristos       if (!matches)
13875fd0b74Schristos 	parse_error (filename);
13975fd0b74Schristos 
14075fd0b74Schristos       /* Just skip messages about files with no symbols.  */
14175fd0b74Schristos       if (!strncmp (dummy, "No symbols in ", 14))
14275fd0b74Schristos 	{
14375fd0b74Schristos 	  matches = fscanf (file, "\n");
14475fd0b74Schristos 	  if (matches == EOF)
14575fd0b74Schristos 	    parse_error (filename);
14675fd0b74Schristos 	  continue;
14775fd0b74Schristos 	}
14875fd0b74Schristos 
14975fd0b74Schristos       /* dummy has the filename, go ahead and copy it.  */
15075fd0b74Schristos       symbol_map[count].file_name = (char *) xmalloc (strlen (dummy) + 1);
15175fd0b74Schristos       strcpy (symbol_map[count].file_name, dummy);
15275fd0b74Schristos 
15375fd0b74Schristos       /* Now we need the function name.  */
154ede78133Schristos       matches = fscanf (file, "%" STR_BUFSIZE "[^\n]\n", dummy);
15575fd0b74Schristos       if (!matches)
15675fd0b74Schristos 	parse_error (filename);
15775fd0b74Schristos       tmp = strrchr (dummy, ' ') + 1;
15875fd0b74Schristos       symbol_map[count].function_name = (char *) xmalloc (strlen (tmp) + 1);
15975fd0b74Schristos       strcpy (symbol_map[count].function_name, tmp);
16075fd0b74Schristos       count++;
16175fd0b74Schristos     }
16275fd0b74Schristos 
16375fd0b74Schristos   /* Record the size of the map table for future reference.  */
16475fd0b74Schristos   symbol_map_count = count;
16575fd0b74Schristos 
16675fd0b74Schristos   for (i = 0; i < symbol_map_count; ++i)
16775fd0b74Schristos     if (i == 0
16875fd0b74Schristos         || filename_cmp (symbol_map[i].file_name, symbol_map[i - 1].file_name))
16975fd0b74Schristos       symbol_map[i].is_first = 1;
17075fd0b74Schristos 
17175fd0b74Schristos   qsort (symbol_map, symbol_map_count, sizeof (struct function_map), cmp_symbol_map);
17275fd0b74Schristos 
17375fd0b74Schristos   fclose (file);
17475fd0b74Schristos }
17575fd0b74Schristos 
17675fd0b74Schristos void
core_init(const char * aout_name)17775fd0b74Schristos core_init (const char * aout_name)
17875fd0b74Schristos {
17975fd0b74Schristos   int core_sym_bytes;
18075fd0b74Schristos   asymbol *synthsyms;
18175fd0b74Schristos   long synth_count;
18275fd0b74Schristos 
18375fd0b74Schristos   core_bfd = bfd_openr (aout_name, 0);
18475fd0b74Schristos 
18575fd0b74Schristos   if (!core_bfd)
18675fd0b74Schristos     {
18775fd0b74Schristos       perror (aout_name);
18875fd0b74Schristos       done (1);
18975fd0b74Schristos     }
19075fd0b74Schristos 
191012573ebSchristos   core_bfd->flags |= BFD_DECOMPRESS;
192012573ebSchristos 
19375fd0b74Schristos   if (!bfd_check_format (core_bfd, bfd_object))
19475fd0b74Schristos     {
19575fd0b74Schristos       fprintf (stderr, _("%s: %s: not in executable format\n"), whoami, aout_name);
19675fd0b74Schristos       done (1);
19775fd0b74Schristos     }
19875fd0b74Schristos 
19975fd0b74Schristos   /* Get core's text section.  */
20075fd0b74Schristos   core_text_sect = bfd_get_section_by_name (core_bfd, ".text");
20175fd0b74Schristos   if (!core_text_sect)
20275fd0b74Schristos     {
20375fd0b74Schristos       core_text_sect = bfd_get_section_by_name (core_bfd, "$CODE$");
20475fd0b74Schristos       if (!core_text_sect)
20575fd0b74Schristos 	{
20675fd0b74Schristos 	  fprintf (stderr, _("%s: can't find .text section in %s\n"),
20775fd0b74Schristos 		   whoami, aout_name);
20875fd0b74Schristos 	  done (1);
20975fd0b74Schristos 	}
21075fd0b74Schristos     }
21175fd0b74Schristos 
21275fd0b74Schristos   /* Read core's symbol table.  */
21375fd0b74Schristos 
21475fd0b74Schristos   /* This will probably give us more than we need, but that's ok.  */
21575fd0b74Schristos   core_sym_bytes = bfd_get_symtab_upper_bound (core_bfd);
21675fd0b74Schristos   if (core_sym_bytes < 0)
21775fd0b74Schristos     {
21875fd0b74Schristos       fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
21975fd0b74Schristos 	       bfd_errmsg (bfd_get_error ()));
22075fd0b74Schristos       done (1);
22175fd0b74Schristos     }
22275fd0b74Schristos 
22375fd0b74Schristos   core_syms = (asymbol **) xmalloc (core_sym_bytes);
22475fd0b74Schristos   core_num_syms = bfd_canonicalize_symtab (core_bfd, core_syms);
22575fd0b74Schristos 
22675fd0b74Schristos   if (core_num_syms < 0)
22775fd0b74Schristos     {
22875fd0b74Schristos       fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
22975fd0b74Schristos 	       bfd_errmsg (bfd_get_error ()));
23075fd0b74Schristos       done (1);
23175fd0b74Schristos     }
23275fd0b74Schristos 
23375fd0b74Schristos   synth_count = bfd_get_synthetic_symtab (core_bfd, core_num_syms, core_syms,
23475fd0b74Schristos 					  0, NULL, &synthsyms);
23575fd0b74Schristos   if (synth_count > 0)
23675fd0b74Schristos     {
23775fd0b74Schristos       asymbol **symp;
23875fd0b74Schristos       long new_size;
23975fd0b74Schristos       long i;
24075fd0b74Schristos 
24175fd0b74Schristos       new_size = (core_num_syms + synth_count + 1) * sizeof (*core_syms);
24275fd0b74Schristos       core_syms = (asymbol **) xrealloc (core_syms, new_size);
24375fd0b74Schristos       symp = core_syms + core_num_syms;
24475fd0b74Schristos       core_num_syms += synth_count;
24575fd0b74Schristos       for (i = 0; i < synth_count; i++)
24675fd0b74Schristos 	*symp++ = synthsyms + i;
24775fd0b74Schristos       *symp = 0;
24875fd0b74Schristos     }
24975fd0b74Schristos 
25075fd0b74Schristos   min_insn_size = 1;
25175fd0b74Schristos   offset_to_code = 0;
25275fd0b74Schristos 
25375fd0b74Schristos   switch (bfd_get_arch (core_bfd))
25475fd0b74Schristos     {
25575fd0b74Schristos     case bfd_arch_vax:
25675fd0b74Schristos       offset_to_code = 2;
25775fd0b74Schristos       break;
25875fd0b74Schristos 
25975fd0b74Schristos     case bfd_arch_alpha:
26075fd0b74Schristos       min_insn_size = 4;
26175fd0b74Schristos       break;
26275fd0b74Schristos 
26375fd0b74Schristos     default:
26475fd0b74Schristos       break;
26575fd0b74Schristos     }
26675fd0b74Schristos 
26775fd0b74Schristos   if (function_mapping_file)
26875fd0b74Schristos     read_function_mappings (function_mapping_file);
26975fd0b74Schristos }
27075fd0b74Schristos 
27175fd0b74Schristos /* Read in the text space of an a.out file.  */
27275fd0b74Schristos 
27375fd0b74Schristos void
core_get_text_space(bfd * cbfd)27475fd0b74Schristos core_get_text_space (bfd *cbfd)
27575fd0b74Schristos {
276012573ebSchristos   core_text_space = malloc (bfd_section_size (core_text_sect));
27775fd0b74Schristos 
27875fd0b74Schristos   if (!core_text_space)
27975fd0b74Schristos     {
28075fd0b74Schristos       fprintf (stderr, _("%s: ran out room for %lu bytes of text space\n"),
281012573ebSchristos 	       whoami, (unsigned long) bfd_section_size (core_text_sect));
28275fd0b74Schristos       done (1);
28375fd0b74Schristos     }
28475fd0b74Schristos 
28575fd0b74Schristos   if (!bfd_get_section_contents (cbfd, core_text_sect, core_text_space,
286012573ebSchristos 				 0, bfd_section_size (core_text_sect)))
28775fd0b74Schristos     {
28875fd0b74Schristos       bfd_perror ("bfd_get_section_contents");
28975fd0b74Schristos       free (core_text_space);
29075fd0b74Schristos       core_text_space = 0;
29175fd0b74Schristos     }
29275fd0b74Schristos 
29375fd0b74Schristos   if (!core_text_space)
29475fd0b74Schristos     fprintf (stderr, _("%s: can't do -c\n"), whoami);
29575fd0b74Schristos }
29675fd0b74Schristos 
29775fd0b74Schristos 
29875fd0b74Schristos void
find_call(Sym * parent,bfd_vma p_lowpc,bfd_vma p_highpc)29975fd0b74Schristos find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
30075fd0b74Schristos {
30175fd0b74Schristos   if (core_text_space == 0)
30275fd0b74Schristos     return;
30375fd0b74Schristos 
30475fd0b74Schristos   hist_clip_symbol_address (&p_lowpc, &p_highpc);
30575fd0b74Schristos 
30675fd0b74Schristos   switch (bfd_get_arch (core_bfd))
30775fd0b74Schristos     {
30875fd0b74Schristos     case bfd_arch_i386:
30975fd0b74Schristos       i386_find_call (parent, p_lowpc, p_highpc);
31075fd0b74Schristos       break;
31175fd0b74Schristos 
31275fd0b74Schristos     case bfd_arch_alpha:
31375fd0b74Schristos       alpha_find_call (parent, p_lowpc, p_highpc);
31475fd0b74Schristos       break;
31575fd0b74Schristos 
31675fd0b74Schristos     case bfd_arch_vax:
31775fd0b74Schristos       vax_find_call (parent, p_lowpc, p_highpc);
31875fd0b74Schristos       break;
31975fd0b74Schristos 
32075fd0b74Schristos     case bfd_arch_sparc:
32175fd0b74Schristos       sparc_find_call (parent, p_lowpc, p_highpc);
32275fd0b74Schristos       break;
32375fd0b74Schristos 
32475fd0b74Schristos     case bfd_arch_mips:
32575fd0b74Schristos       mips_find_call (parent, p_lowpc, p_highpc);
32675fd0b74Schristos       break;
32775fd0b74Schristos 
32875fd0b74Schristos     case bfd_arch_aarch64:
32975fd0b74Schristos       aarch64_find_call (parent, p_lowpc, p_highpc);
33075fd0b74Schristos       break;
33175fd0b74Schristos 
33275fd0b74Schristos     default:
33375fd0b74Schristos       fprintf (stderr, _("%s: -c not supported on architecture %s\n"),
33475fd0b74Schristos 	       whoami, bfd_printable_name(core_bfd));
33575fd0b74Schristos 
33675fd0b74Schristos       /* Don't give the error more than once.  */
337*e992f068Schristos       ignore_direct_calls = false;
33875fd0b74Schristos     }
33975fd0b74Schristos }
34075fd0b74Schristos 
34175fd0b74Schristos /* Return class of symbol SYM.  The returned class can be any of:
34275fd0b74Schristos 	0   -> symbol is not interesting to us
34375fd0b74Schristos 	'T' -> symbol is a global name
34475fd0b74Schristos 	't' -> symbol is a local (static) name.  */
34575fd0b74Schristos 
34675fd0b74Schristos static int
core_sym_class(asymbol * sym)34775fd0b74Schristos core_sym_class (asymbol *sym)
34875fd0b74Schristos {
34975fd0b74Schristos   symbol_info syminfo;
35075fd0b74Schristos   const char *name;
35175fd0b74Schristos   char sym_prefix;
35275fd0b74Schristos   int i;
35375fd0b74Schristos 
35475fd0b74Schristos   if (sym->section == NULL || (sym->flags & BSF_DEBUGGING) != 0)
35575fd0b74Schristos     return 0;
35675fd0b74Schristos 
35775fd0b74Schristos   /* Must be a text symbol, and static text symbols
35875fd0b74Schristos      don't qualify if ignore_static_funcs set.   */
35975fd0b74Schristos   if (ignore_static_funcs && (sym->flags & BSF_LOCAL))
36075fd0b74Schristos     {
36175fd0b74Schristos       DBG (AOUTDEBUG, printf ("[core_sym_class] %s: not a function\n",
36275fd0b74Schristos 			      sym->name));
36375fd0b74Schristos       return 0;
36475fd0b74Schristos     }
36575fd0b74Schristos 
36675fd0b74Schristos   bfd_get_symbol_info (core_bfd, sym, &syminfo);
36775fd0b74Schristos   i = syminfo.type;
36875fd0b74Schristos 
36975fd0b74Schristos   if (i == 'T')
37075fd0b74Schristos     return i;			/* It's a global symbol.  */
37175fd0b74Schristos 
37275fd0b74Schristos   if (i == 'W')
37375fd0b74Schristos     /* Treat weak symbols as text symbols.  FIXME: a weak symbol may
37475fd0b74Schristos        also be a data symbol.  */
37575fd0b74Schristos     return 'T';
37675fd0b74Schristos 
37775fd0b74Schristos   if (i != 't')
37875fd0b74Schristos     {
37975fd0b74Schristos       /* Not a static text symbol.  */
38075fd0b74Schristos       DBG (AOUTDEBUG, printf ("[core_sym_class] %s is of class %c\n",
38175fd0b74Schristos 			      sym->name, i));
38275fd0b74Schristos       return 0;
38375fd0b74Schristos     }
38475fd0b74Schristos 
38575fd0b74Schristos   /* Do some more filtering on static function-names.  */
38675fd0b74Schristos   if (ignore_static_funcs)
38775fd0b74Schristos     return 0;
38875fd0b74Schristos 
38975fd0b74Schristos   /* Can't zero-length name or funny characters in name, where
39075fd0b74Schristos      `funny' includes: `.' (.o file names) and `$' (Pascal labels).  */
39175fd0b74Schristos   if (!sym->name || sym->name[0] == '\0')
39275fd0b74Schristos     return 0;
39375fd0b74Schristos 
39475fd0b74Schristos   for (name = sym->name; *name; ++name)
39575fd0b74Schristos     {
39675fd0b74Schristos       if (*name == '$')
39775fd0b74Schristos         return 0;
39875fd0b74Schristos 
39975fd0b74Schristos       while (*name == '.')
40075fd0b74Schristos 	{
40175fd0b74Schristos 	  /* Allow both nested subprograms (which end with ".NNN", where N is
40275fd0b74Schristos 	     a digit) and GCC cloned functions (which contain ".clone").
40375fd0b74Schristos 	     Allow for multiple iterations of both - apparently GCC can clone
40475fd0b74Schristos 	     clones and subprograms.  */
40575fd0b74Schristos 	  int digit_seen = 0;
40675fd0b74Schristos #define CLONE_NAME	    ".clone."
40775fd0b74Schristos #define CLONE_NAME_LEN	    strlen (CLONE_NAME)
40875fd0b74Schristos #define CONSTPROP_NAME	    ".constprop."
40975fd0b74Schristos #define CONSTPROP_NAME_LEN  strlen (CONSTPROP_NAME)
41075fd0b74Schristos 
41175fd0b74Schristos 	  if (strlen (name) > CLONE_NAME_LEN
41275fd0b74Schristos 	      && strncmp (name, CLONE_NAME, CLONE_NAME_LEN) == 0)
41375fd0b74Schristos 	    name += CLONE_NAME_LEN - 1;
41475fd0b74Schristos 
41575fd0b74Schristos 	  else if (strlen (name) > CONSTPROP_NAME_LEN
41675fd0b74Schristos 	      && strncmp (name, CONSTPROP_NAME, CONSTPROP_NAME_LEN) == 0)
41775fd0b74Schristos 	    name += CONSTPROP_NAME_LEN - 1;
41875fd0b74Schristos 
41975fd0b74Schristos 	  for (name++; *name; name++)
42075fd0b74Schristos 	    if (digit_seen && *name == '.')
42175fd0b74Schristos 	      break;
42275fd0b74Schristos 	    else if (ISDIGIT (*name))
42375fd0b74Schristos 	      digit_seen = 1;
42475fd0b74Schristos 	    else
42575fd0b74Schristos 	      return 0;
42675fd0b74Schristos 	}
42775fd0b74Schristos     }
42875fd0b74Schristos 
42975fd0b74Schristos   /* On systems where the C compiler adds an underscore to all
43075fd0b74Schristos      names, static names without underscores seem usually to be
43175fd0b74Schristos      labels in hand written assembler in the library.  We don't want
43275fd0b74Schristos      these names.  This is certainly necessary on a Sparc running
43375fd0b74Schristos      SunOS 4.1 (try profiling a program that does a lot of
43475fd0b74Schristos      division). I don't know whether it has harmful side effects on
43575fd0b74Schristos      other systems.  Perhaps it should be made configurable.  */
43675fd0b74Schristos   sym_prefix = bfd_get_symbol_leading_char (core_bfd);
43775fd0b74Schristos 
43875fd0b74Schristos   if ((sym_prefix && sym_prefix != sym->name[0])
43975fd0b74Schristos       /* GCC may add special symbols to help gdb figure out the file
44075fd0b74Schristos 	language.  We want to ignore these, since sometimes they mask
44175fd0b74Schristos 	the real function.  (dj@ctron)  */
44275fd0b74Schristos       || !strncmp (sym->name, "__gnu_compiled", 14)
44375fd0b74Schristos       || !strncmp (sym->name, "___gnu_compiled", 15))
44475fd0b74Schristos     {
44575fd0b74Schristos       return 0;
44675fd0b74Schristos     }
44775fd0b74Schristos 
44875fd0b74Schristos   /* If the object file supports marking of function symbols, then
44975fd0b74Schristos      we can zap anything that doesn't have BSF_FUNCTION set.  */
45075fd0b74Schristos   if (ignore_non_functions && (sym->flags & BSF_FUNCTION) == 0)
45175fd0b74Schristos     return 0;
45275fd0b74Schristos 
45375fd0b74Schristos   return 't';			/* It's a static text symbol.  */
45475fd0b74Schristos }
45575fd0b74Schristos 
45675fd0b74Schristos /* Get whatever source info we can get regarding address ADDR.  */
45775fd0b74Schristos 
458*e992f068Schristos static bool
get_src_info(bfd_vma addr,const char ** filename,const char ** name,int * line_num)459*e992f068Schristos get_src_info (bfd_vma addr, const char **filename, const char **name,
460*e992f068Schristos 	      int *line_num)
46175fd0b74Schristos {
46275fd0b74Schristos   const char *fname = 0, *func_name = 0;
46375fd0b74Schristos   int l = 0;
46475fd0b74Schristos 
46575fd0b74Schristos   if (bfd_find_nearest_line (core_bfd, core_text_sect, core_syms,
46675fd0b74Schristos 			     addr - core_text_sect->vma,
46775fd0b74Schristos 			     &fname, &func_name, (unsigned int *) &l)
46875fd0b74Schristos       && fname && func_name && l)
46975fd0b74Schristos     {
47075fd0b74Schristos       DBG (AOUTDEBUG, printf ("[get_src_info] 0x%lx -> %s:%d (%s)\n",
47175fd0b74Schristos 			      (unsigned long) addr, fname, l, func_name));
47275fd0b74Schristos       *filename = fname;
47375fd0b74Schristos       *name = func_name;
47475fd0b74Schristos       *line_num = l;
475*e992f068Schristos       return true;
47675fd0b74Schristos     }
47775fd0b74Schristos   else
47875fd0b74Schristos     {
47975fd0b74Schristos       DBG (AOUTDEBUG, printf ("[get_src_info] no info for 0x%lx (%s:%d,%s)\n",
48075fd0b74Schristos 			      (unsigned long) addr,
48175fd0b74Schristos 			      fname ? fname : "<unknown>", l,
48275fd0b74Schristos 			      func_name ? func_name : "<unknown>"));
483*e992f068Schristos       return false;
48475fd0b74Schristos     }
48575fd0b74Schristos }
48675fd0b74Schristos 
487ede78133Schristos static char buf[BUFSIZE];
488ede78133Schristos static char address[BUFSIZE];
489ede78133Schristos static char name[BUFSIZE];
490ede78133Schristos 
49175fd0b74Schristos /* Return number of symbols in a symbol-table file.  */
49275fd0b74Schristos 
493ede78133Schristos static unsigned int
num_of_syms_in(FILE * f)49475fd0b74Schristos num_of_syms_in (FILE * f)
49575fd0b74Schristos {
49675fd0b74Schristos   char   type;
497ede78133Schristos   unsigned int num = 0;
49875fd0b74Schristos 
49975fd0b74Schristos   while (!feof (f) && fgets (buf, BUFSIZE - 1, f))
50075fd0b74Schristos     {
501ede78133Schristos       if (sscanf (buf, "%" STR_BUFSIZE "s %c %" STR_BUFSIZE "s", address, &type, name) == 3)
50275fd0b74Schristos         if (type == 't' || type == 'T')
503ede78133Schristos 	  {
504ede78133Schristos 	    /* PR 20499 - prevent integer overflow computing argument to xmalloc.  */
505ede78133Schristos 	    if (++num >= UINT_MAX / sizeof (Sym))
506ede78133Schristos 	      return -1U;
50775fd0b74Schristos 	  }
508ede78133Schristos     }
50975fd0b74Schristos 
51075fd0b74Schristos   return num;
51175fd0b74Schristos }
51275fd0b74Schristos 
51375fd0b74Schristos /* Read symbol table from a file.  */
51475fd0b74Schristos 
51575fd0b74Schristos void
core_create_syms_from(const char * sym_table_file)51675fd0b74Schristos core_create_syms_from (const char * sym_table_file)
51775fd0b74Schristos {
51875fd0b74Schristos   char type;
51975fd0b74Schristos   bfd_vma min_vma = ~(bfd_vma) 0;
52075fd0b74Schristos   bfd_vma max_vma = 0;
52175fd0b74Schristos   FILE * f;
52275fd0b74Schristos 
52375fd0b74Schristos   f = fopen (sym_table_file, "r");
52475fd0b74Schristos   if (!f)
52575fd0b74Schristos     {
52675fd0b74Schristos       fprintf (stderr, _("%s: could not open %s.\n"), whoami, sym_table_file);
52775fd0b74Schristos       done (1);
52875fd0b74Schristos     }
52975fd0b74Schristos 
53075fd0b74Schristos   /* Pass 1 - determine upper bound on number of function names.  */
53175fd0b74Schristos   symtab.len = num_of_syms_in (f);
53275fd0b74Schristos 
53375fd0b74Schristos   if (symtab.len == 0)
53475fd0b74Schristos     {
53575fd0b74Schristos       fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, sym_table_file);
53675fd0b74Schristos       done (1);
53775fd0b74Schristos     }
538ede78133Schristos   else if (symtab.len == -1U)
539ede78133Schristos     {
540ede78133Schristos       fprintf (stderr, _("%s: file `%s' has too many symbols\n"),
541ede78133Schristos 	       whoami, sym_table_file);
542ede78133Schristos       done (1);
543ede78133Schristos     }
54475fd0b74Schristos 
54575fd0b74Schristos   symtab.base = (Sym *) xmalloc (symtab.len * sizeof (Sym));
54675fd0b74Schristos 
54775fd0b74Schristos   /* Pass 2 - create symbols.  */
54875fd0b74Schristos   symtab.limit = symtab.base;
54975fd0b74Schristos 
55075fd0b74Schristos   if (fseek (f, 0, SEEK_SET) != 0)
55175fd0b74Schristos     {
55275fd0b74Schristos       perror (sym_table_file);
55375fd0b74Schristos       done (1);
55475fd0b74Schristos     }
55575fd0b74Schristos 
55675fd0b74Schristos   while (!feof (f) && fgets (buf, BUFSIZE - 1, f))
55775fd0b74Schristos     {
558ede78133Schristos       if (sscanf (buf, "%" STR_BUFSIZE "s %c %" STR_BUFSIZE "s", address, &type, name) != 3)
559ede78133Schristos 	continue;
56075fd0b74Schristos       if (type != 't' && type != 'T')
56175fd0b74Schristos 	continue;
56275fd0b74Schristos 
56375fd0b74Schristos       sym_init (symtab.limit);
56475fd0b74Schristos 
56575fd0b74Schristos       sscanf (address, "%" BFD_VMA_FMT "x", &(symtab.limit->addr) );
56675fd0b74Schristos 
56775fd0b74Schristos       symtab.limit->name = (char *) xmalloc (strlen (name) + 1);
56875fd0b74Schristos       strcpy ((char *) symtab.limit->name, name);
56975fd0b74Schristos       symtab.limit->mapped = 0;
570*e992f068Schristos       symtab.limit->is_func = true;
571*e992f068Schristos       symtab.limit->is_bb_head = true;
57275fd0b74Schristos       symtab.limit->is_static = (type == 't');
57375fd0b74Schristos       min_vma = MIN (symtab.limit->addr, min_vma);
57475fd0b74Schristos       max_vma = MAX (symtab.limit->addr, max_vma);
57575fd0b74Schristos 
57675fd0b74Schristos       ++symtab.limit;
57775fd0b74Schristos     }
57875fd0b74Schristos   fclose (f);
57975fd0b74Schristos 
58075fd0b74Schristos   symtab.len = symtab.limit - symtab.base;
58175fd0b74Schristos   symtab_finalize (&symtab);
58275fd0b74Schristos }
58375fd0b74Schristos 
58475fd0b74Schristos static int
search_mapped_symbol(const void * l,const void * r)58575fd0b74Schristos search_mapped_symbol (const void * l, const void * r)
58675fd0b74Schristos {
58775fd0b74Schristos     return strcmp ((const char *) l, ((const struct function_map *) r)->function_name);
58875fd0b74Schristos }
58975fd0b74Schristos 
59075fd0b74Schristos /* Read in symbol table from core.
59175fd0b74Schristos    One symbol per function is entered.  */
59275fd0b74Schristos 
59375fd0b74Schristos void
core_create_function_syms(void)59475fd0b74Schristos core_create_function_syms (void)
59575fd0b74Schristos {
59675fd0b74Schristos   bfd_vma min_vma = ~ (bfd_vma) 0;
59775fd0b74Schristos   bfd_vma max_vma = 0;
59875fd0b74Schristos   int cxxclass;
59975fd0b74Schristos   long i;
60075fd0b74Schristos   struct function_map * found = NULL;
60175fd0b74Schristos   int core_has_func_syms = 0;
60275fd0b74Schristos 
60375fd0b74Schristos   switch (core_bfd->xvec->flavour)
60475fd0b74Schristos     {
60575fd0b74Schristos     default:
60675fd0b74Schristos       break;
60775fd0b74Schristos     case bfd_target_coff_flavour:
60875fd0b74Schristos     case bfd_target_ecoff_flavour:
60975fd0b74Schristos     case bfd_target_xcoff_flavour:
61075fd0b74Schristos     case bfd_target_elf_flavour:
61175fd0b74Schristos     case bfd_target_som_flavour:
61275fd0b74Schristos       core_has_func_syms = 1;
61375fd0b74Schristos     }
61475fd0b74Schristos 
61575fd0b74Schristos   /* Pass 1 - determine upper bound on number of function names.  */
61675fd0b74Schristos   symtab.len = 0;
61775fd0b74Schristos 
61875fd0b74Schristos   for (i = 0; i < core_num_syms; ++i)
61975fd0b74Schristos     {
62075fd0b74Schristos       if (!core_sym_class (core_syms[i]))
62175fd0b74Schristos 	continue;
62275fd0b74Schristos 
62375fd0b74Schristos       /* Don't create a symtab entry for a function that has
62475fd0b74Schristos 	 a mapping to a file, unless it's the first function
62575fd0b74Schristos 	 in the file.  */
62675fd0b74Schristos       if (symbol_map_count != 0)
62775fd0b74Schristos 	{
62875fd0b74Schristos 	  /* Note: some systems (SunOS 5.8) crash if bsearch base argument
62975fd0b74Schristos 	     is NULL.  */
63075fd0b74Schristos 	  found = (struct function_map *) bsearch
63175fd0b74Schristos 	    (core_syms[i]->name, symbol_map, symbol_map_count,
63275fd0b74Schristos 	     sizeof (struct function_map), search_mapped_symbol);
63375fd0b74Schristos 	}
63475fd0b74Schristos       if (found == NULL || found->is_first)
63575fd0b74Schristos 	++symtab.len;
63675fd0b74Schristos     }
63775fd0b74Schristos 
63875fd0b74Schristos   if (symtab.len == 0)
63975fd0b74Schristos     {
64075fd0b74Schristos       fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, a_out_name);
64175fd0b74Schristos       done (1);
64275fd0b74Schristos     }
64375fd0b74Schristos 
64475fd0b74Schristos   symtab.base = (Sym *) xmalloc (symtab.len * sizeof (Sym));
64575fd0b74Schristos 
64675fd0b74Schristos   /* Pass 2 - create symbols.  */
64775fd0b74Schristos   symtab.limit = symtab.base;
64875fd0b74Schristos 
64975fd0b74Schristos   for (i = 0; i < core_num_syms; ++i)
65075fd0b74Schristos     {
65175fd0b74Schristos       asection *sym_sec;
65275fd0b74Schristos 
65375fd0b74Schristos       cxxclass = core_sym_class (core_syms[i]);
65475fd0b74Schristos 
65575fd0b74Schristos       if (!cxxclass)
65675fd0b74Schristos 	{
65775fd0b74Schristos 	  DBG (AOUTDEBUG,
65875fd0b74Schristos 	       printf ("[core_create_function_syms] rejecting: 0x%lx %s\n",
65975fd0b74Schristos 		       (unsigned long) core_syms[i]->value,
66075fd0b74Schristos 		       core_syms[i]->name));
66175fd0b74Schristos 	  continue;
66275fd0b74Schristos 	}
66375fd0b74Schristos 
66475fd0b74Schristos       if (symbol_map_count != 0)
66575fd0b74Schristos 	{
66675fd0b74Schristos 	  /* Note: some systems (SunOS 5.8) crash if bsearch base argument
66775fd0b74Schristos 	     is NULL.  */
66875fd0b74Schristos 	  found = (struct function_map *) bsearch
66975fd0b74Schristos 	    (core_syms[i]->name, symbol_map, symbol_map_count,
67075fd0b74Schristos 	     sizeof (struct function_map), search_mapped_symbol);
67175fd0b74Schristos 	}
67275fd0b74Schristos       if (found && ! found->is_first)
67375fd0b74Schristos 	continue;
67475fd0b74Schristos 
67575fd0b74Schristos       sym_init (symtab.limit);
67675fd0b74Schristos 
67775fd0b74Schristos       /* Symbol offsets are always section-relative.  */
67875fd0b74Schristos       sym_sec = core_syms[i]->section;
67975fd0b74Schristos       symtab.limit->addr = core_syms[i]->value;
68075fd0b74Schristos       if (sym_sec)
681012573ebSchristos 	symtab.limit->addr += bfd_section_vma (sym_sec);
68275fd0b74Schristos 
68375fd0b74Schristos       if (found)
68475fd0b74Schristos 	{
68575fd0b74Schristos 	  symtab.limit->name = found->file_name;
68675fd0b74Schristos 	  symtab.limit->mapped = 1;
68775fd0b74Schristos 	}
68875fd0b74Schristos       else
68975fd0b74Schristos 	{
69075fd0b74Schristos 	  symtab.limit->name = core_syms[i]->name;
69175fd0b74Schristos 	  symtab.limit->mapped = 0;
69275fd0b74Schristos 	}
69375fd0b74Schristos 
69475fd0b74Schristos       /* Lookup filename and line number, if we can.  */
69575fd0b74Schristos       {
69675fd0b74Schristos 	const char * filename;
69775fd0b74Schristos 	const char * func_name;
69875fd0b74Schristos 
69975fd0b74Schristos 	if (get_src_info (symtab.limit->addr, & filename, & func_name,
70075fd0b74Schristos 			  & symtab.limit->line_num))
70175fd0b74Schristos 	  {
70275fd0b74Schristos 	    symtab.limit->file = source_file_lookup_path (filename);
70375fd0b74Schristos 
70475fd0b74Schristos 	    /* FIXME: Checking __osf__ here does not work with a cross
70575fd0b74Schristos 	       gprof.  */
70675fd0b74Schristos #ifdef __osf__
70775fd0b74Schristos 	    /* Suppress symbols that are not function names.  This is
70875fd0b74Schristos 	       useful to suppress code-labels and aliases.
70975fd0b74Schristos 
71075fd0b74Schristos 	       This is known to be useful under DEC's OSF/1.  Under SunOS 4.x,
71175fd0b74Schristos 	       labels do not appear in the symbol table info, so this isn't
71275fd0b74Schristos 	       necessary.  */
71375fd0b74Schristos 
71475fd0b74Schristos 	    if (strcmp (symtab.limit->name, func_name) != 0)
71575fd0b74Schristos 	      {
71675fd0b74Schristos 		/* The symbol's address maps to a different name, so
71775fd0b74Schristos 		   it can't be a function-entry point.  This happens
71875fd0b74Schristos 		   for labels, for example.  */
71975fd0b74Schristos 		DBG (AOUTDEBUG,
72075fd0b74Schristos 		     printf ("[core_create_function_syms: rej %s (maps to %s)\n",
72175fd0b74Schristos 			     symtab.limit->name, func_name));
72275fd0b74Schristos 		continue;
72375fd0b74Schristos 	      }
72475fd0b74Schristos #endif
72575fd0b74Schristos 	  }
72675fd0b74Schristos       }
72775fd0b74Schristos 
72875fd0b74Schristos       symtab.limit->is_func = (!core_has_func_syms
72975fd0b74Schristos 			       || (core_syms[i]->flags & BSF_FUNCTION) != 0);
730*e992f068Schristos       symtab.limit->is_bb_head = true;
73175fd0b74Schristos 
73275fd0b74Schristos       if (cxxclass == 't')
733*e992f068Schristos 	symtab.limit->is_static = true;
73475fd0b74Schristos 
73575fd0b74Schristos       /* Keep track of the minimum and maximum vma addresses used by all
73675fd0b74Schristos 	 symbols.  When computing the max_vma, use the ending address of the
73775fd0b74Schristos 	 section containing the symbol, if available.  */
73875fd0b74Schristos       min_vma = MIN (symtab.limit->addr, min_vma);
73975fd0b74Schristos       if (sym_sec)
740012573ebSchristos 	max_vma = MAX (bfd_section_vma (sym_sec)
741012573ebSchristos 		       + bfd_section_size (sym_sec) - 1,
74275fd0b74Schristos 		       max_vma);
74375fd0b74Schristos       else
74475fd0b74Schristos 	max_vma = MAX (symtab.limit->addr, max_vma);
74575fd0b74Schristos 
74675fd0b74Schristos       DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n",
74775fd0b74Schristos 			      (long) (symtab.limit - symtab.base),
74875fd0b74Schristos 			      symtab.limit->name,
74975fd0b74Schristos 			      (unsigned long) symtab.limit->addr));
75075fd0b74Schristos       ++symtab.limit;
75175fd0b74Schristos     }
75275fd0b74Schristos 
75375fd0b74Schristos   symtab.len = symtab.limit - symtab.base;
75475fd0b74Schristos   symtab_finalize (&symtab);
75575fd0b74Schristos }
75675fd0b74Schristos 
75775fd0b74Schristos /* Read in symbol table from core.
75875fd0b74Schristos    One symbol per line of source code is entered.  */
75975fd0b74Schristos 
76075fd0b74Schristos void
core_create_line_syms(void)76175fd0b74Schristos core_create_line_syms (void)
76275fd0b74Schristos {
76375fd0b74Schristos   char *prev_name, *prev_filename;
76475fd0b74Schristos   unsigned int prev_name_len, prev_filename_len;
76575fd0b74Schristos   bfd_vma vma, min_vma = ~(bfd_vma) 0, max_vma = 0;
76675fd0b74Schristos   Sym *prev, dummy, *sym;
76775fd0b74Schristos   const char *filename;
76875fd0b74Schristos   int prev_line_num;
76975fd0b74Schristos   Sym_Table ltab;
77075fd0b74Schristos   bfd_vma vma_high;
77175fd0b74Schristos 
77275fd0b74Schristos   /* Create symbols for functions as usual.  This is necessary in
77375fd0b74Schristos      cases where parts of a program were not compiled with -g.  For
77475fd0b74Schristos      those parts we still want to get info at the function level.  */
77575fd0b74Schristos   core_create_function_syms ();
77675fd0b74Schristos 
77775fd0b74Schristos   /* Pass 1: count the number of symbols.  */
77875fd0b74Schristos 
77975fd0b74Schristos   /* To find all line information, walk through all possible
78075fd0b74Schristos      text-space addresses (one by one!) and get the debugging
78175fd0b74Schristos      info for each address.  When the debugging info changes,
78275fd0b74Schristos      it is time to create a new symbol.
78375fd0b74Schristos 
78475fd0b74Schristos      Of course, this is rather slow and it would be better if
78575fd0b74Schristos      BFD would provide an iterator for enumerating all line infos.  */
786*e992f068Schristos   prev_name_len = 1024;
787*e992f068Schristos   prev_filename_len = 1024;
78875fd0b74Schristos   prev_name = (char *) xmalloc (prev_name_len);
78975fd0b74Schristos   prev_filename = (char *) xmalloc (prev_filename_len);
79075fd0b74Schristos   ltab.len = 0;
79175fd0b74Schristos   prev_line_num = 0;
79275fd0b74Schristos 
793012573ebSchristos   vma_high = core_text_sect->vma + bfd_section_size (core_text_sect);
79475fd0b74Schristos   for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size)
79575fd0b74Schristos     {
79675fd0b74Schristos       unsigned int len;
79775fd0b74Schristos 
79875fd0b74Schristos       if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num)
79975fd0b74Schristos 	  || (prev_line_num == dummy.line_num
80075fd0b74Schristos 	      && prev_name != NULL
80175fd0b74Schristos 	      && strcmp (prev_name, dummy.name) == 0
80275fd0b74Schristos 	      && filename_cmp (prev_filename, filename) == 0))
80375fd0b74Schristos 	continue;
80475fd0b74Schristos 
80575fd0b74Schristos       ++ltab.len;
80675fd0b74Schristos       prev_line_num = dummy.line_num;
80775fd0b74Schristos 
80875fd0b74Schristos       len = strlen (dummy.name);
80975fd0b74Schristos       if (len >= prev_name_len)
81075fd0b74Schristos 	{
81175fd0b74Schristos 	  prev_name_len = len + 1024;
81275fd0b74Schristos 	  free (prev_name);
81375fd0b74Schristos 	  prev_name = (char *) xmalloc (prev_name_len);
81475fd0b74Schristos 	}
81575fd0b74Schristos 
81675fd0b74Schristos       strcpy (prev_name, dummy.name);
81775fd0b74Schristos       len = strlen (filename);
81875fd0b74Schristos 
81975fd0b74Schristos       if (len >= prev_filename_len)
82075fd0b74Schristos 	{
82175fd0b74Schristos 	  prev_filename_len = len + 1024;
82275fd0b74Schristos 	  free (prev_filename);
82375fd0b74Schristos 	  prev_filename = (char *) xmalloc (prev_filename_len);
82475fd0b74Schristos 	}
82575fd0b74Schristos 
82675fd0b74Schristos       strcpy (prev_filename, filename);
82775fd0b74Schristos 
82875fd0b74Schristos       min_vma = MIN (vma, min_vma);
82975fd0b74Schristos       max_vma = MAX (vma, max_vma);
83075fd0b74Schristos     }
83175fd0b74Schristos 
83275fd0b74Schristos   free (prev_name);
83375fd0b74Schristos   free (prev_filename);
83475fd0b74Schristos 
83575fd0b74Schristos   /* Make room for function symbols, too.  */
83675fd0b74Schristos   ltab.len += symtab.len;
83775fd0b74Schristos   ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym));
83875fd0b74Schristos   ltab.limit = ltab.base;
83975fd0b74Schristos 
84075fd0b74Schristos   /* Pass 2 - create symbols.  */
84175fd0b74Schristos 
84275fd0b74Schristos   /* We now set is_static as we go along, rather than by running
84375fd0b74Schristos      through the symbol table at the end.
84475fd0b74Schristos 
84575fd0b74Schristos      The old way called symtab_finalize before the is_static pass,
84675fd0b74Schristos      causing a problem since symtab_finalize uses is_static as part of
84775fd0b74Schristos      its address conflict resolution algorithm.  Since global symbols
848ede78133Schristos      were preferred over static symbols, and all line symbols were
84975fd0b74Schristos      global at that point, static function names that conflicted with
85075fd0b74Schristos      their own line numbers (static, but labeled as global) were
85175fd0b74Schristos      rejected in favor of the line num.
85275fd0b74Schristos 
85375fd0b74Schristos      This was not the desired functionality.  We always want to keep
85475fd0b74Schristos      our function symbols and discard any conflicting line symbols.
85575fd0b74Schristos      Perhaps symtab_finalize should be modified to make this
85675fd0b74Schristos      distinction as well, but the current fix works and the code is a
85775fd0b74Schristos      lot cleaner now.  */
85875fd0b74Schristos   prev = 0;
85975fd0b74Schristos 
86075fd0b74Schristos   for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size)
86175fd0b74Schristos     {
86275fd0b74Schristos       sym_init (ltab.limit);
86375fd0b74Schristos 
86475fd0b74Schristos       if (!get_src_info (vma, &filename, &ltab.limit->name, &ltab.limit->line_num)
86575fd0b74Schristos 	  || (prev && prev->line_num == ltab.limit->line_num
86675fd0b74Schristos 	      && strcmp (prev->name, ltab.limit->name) == 0
86775fd0b74Schristos 	      && filename_cmp (prev->file->name, filename) == 0))
86875fd0b74Schristos 	continue;
86975fd0b74Schristos 
87075fd0b74Schristos       /* Make name pointer a malloc'ed string.  */
87175fd0b74Schristos       ltab.limit->name = xstrdup (ltab.limit->name);
87275fd0b74Schristos       ltab.limit->file = source_file_lookup_path (filename);
87375fd0b74Schristos 
87475fd0b74Schristos       ltab.limit->addr = vma;
87575fd0b74Schristos 
87675fd0b74Schristos       /* Set is_static based on the enclosing function, using either:
87775fd0b74Schristos 	 1) the previous symbol, if it's from the same function, or
87875fd0b74Schristos 	 2) a symtab lookup.  */
87975fd0b74Schristos       if (prev && ltab.limit->file == prev->file &&
88075fd0b74Schristos 	  strcmp (ltab.limit->name, prev->name) == 0)
88175fd0b74Schristos 	{
88275fd0b74Schristos 	  ltab.limit->is_static = prev->is_static;
88375fd0b74Schristos 	}
88475fd0b74Schristos       else
88575fd0b74Schristos 	{
88675fd0b74Schristos 	  sym = sym_lookup(&symtab, ltab.limit->addr);
88775fd0b74Schristos           if (sym)
88875fd0b74Schristos 	    ltab.limit->is_static = sym->is_static;
88975fd0b74Schristos 	}
89075fd0b74Schristos 
89175fd0b74Schristos       prev = ltab.limit;
89275fd0b74Schristos 
89375fd0b74Schristos       DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n",
89475fd0b74Schristos 			      (unsigned long) (ltab.limit - ltab.base),
89575fd0b74Schristos 			      ltab.limit->name,
89675fd0b74Schristos 			      (unsigned long) ltab.limit->addr));
89775fd0b74Schristos       ++ltab.limit;
89875fd0b74Schristos     }
89975fd0b74Schristos 
90075fd0b74Schristos   /* Copy in function symbols.  */
90175fd0b74Schristos   memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym));
90275fd0b74Schristos   ltab.limit += symtab.len;
90375fd0b74Schristos 
90475fd0b74Schristos   if ((unsigned int) (ltab.limit - ltab.base) != ltab.len)
90575fd0b74Schristos     {
90675fd0b74Schristos       fprintf (stderr,
90775fd0b74Schristos 	       _("%s: somebody miscounted: ltab.len=%d instead of %ld\n"),
90875fd0b74Schristos 	       whoami, ltab.len, (long) (ltab.limit - ltab.base));
90975fd0b74Schristos       done (1);
91075fd0b74Schristos     }
91175fd0b74Schristos 
91275fd0b74Schristos   /* Finalize ltab and make it symbol table.  */
91375fd0b74Schristos   symtab_finalize (&ltab);
91475fd0b74Schristos   free (symtab.base);
91575fd0b74Schristos   symtab = ltab;
91675fd0b74Schristos }
917