xref: /openbsd-src/gnu/usr.bin/binutils/gprof/corefile.c (revision cf2f2c5620d6d9a4fd01930983c4b9a1f76d7aa3)
15f210c2aSfgsch /* corefile.c
25f210c2aSfgsch 
3d2201f2fSdrahn    Copyright 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
45f210c2aSfgsch 
55f210c2aSfgsch    This file is part of GNU Binutils.
65f210c2aSfgsch 
75f210c2aSfgsch    This program is free software; you can redistribute it and/or modify
85f210c2aSfgsch    it under the terms of the GNU General Public License as published by
95f210c2aSfgsch    the Free Software Foundation; either version 2 of the License, or
105f210c2aSfgsch    (at your option) any later version.
115f210c2aSfgsch 
125f210c2aSfgsch    This program is distributed in the hope that it will be useful,
135f210c2aSfgsch    but WITHOUT ANY WARRANTY; without even the implied warranty of
145f210c2aSfgsch    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
155f210c2aSfgsch    GNU General Public License for more details.
165f210c2aSfgsch 
175f210c2aSfgsch    You should have received a copy of the GNU General Public License
185f210c2aSfgsch    along with this program; if not, write to the Free Software
195f210c2aSfgsch    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
205f210c2aSfgsch    02111-1307, USA.  */
215f210c2aSfgsch 
22f7cc78ecSespie #include "libiberty.h"
23f7cc78ecSespie #include "gprof.h"
24d2201f2fSdrahn #include "search_list.h"
25d2201f2fSdrahn #include "source.h"
26f7cc78ecSespie #include "symtab.h"
27d2201f2fSdrahn #include "corefile.h"
28f7cc78ecSespie 
29f7cc78ecSespie bfd *core_bfd;
30f7cc78ecSespie int core_num_syms;
31f7cc78ecSespie asymbol **core_syms;
32f7cc78ecSespie asection *core_text_sect;
33f7cc78ecSespie PTR core_text_space;
34f7cc78ecSespie 
35f7cc78ecSespie int min_insn_size;
36f7cc78ecSespie int offset_to_code;
37f7cc78ecSespie 
38f7cc78ecSespie /* For mapping symbols to specific .o files during file ordering.  */
39f7cc78ecSespie struct function_map *symbol_map;
40f7cc78ecSespie unsigned int symbol_map_count;
41f7cc78ecSespie 
42d2201f2fSdrahn static void read_function_mappings PARAMS ((const char *));
43d2201f2fSdrahn static int core_sym_class PARAMS ((asymbol *));
44d2201f2fSdrahn static bfd_boolean get_src_info
45d2201f2fSdrahn   PARAMS ((bfd_vma, const char **, const char **, int *));
46d2201f2fSdrahn 
47f7cc78ecSespie extern void i386_find_call  PARAMS ((Sym *, bfd_vma, bfd_vma));
48f7cc78ecSespie extern void alpha_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
49f7cc78ecSespie extern void vax_find_call   PARAMS ((Sym *, bfd_vma, bfd_vma));
50f7cc78ecSespie extern void tahoe_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
51f7cc78ecSespie extern void sparc_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
52d2201f2fSdrahn extern void mips_find_call  PARAMS ((Sym *, bfd_vma, bfd_vma));
53f7cc78ecSespie 
54f7cc78ecSespie static void
read_function_mappings(filename)55d2201f2fSdrahn read_function_mappings (filename)
56d2201f2fSdrahn      const char *filename;
57f7cc78ecSespie {
58f7cc78ecSespie   FILE *file = fopen (filename, "r");
59f7cc78ecSespie   char dummy[1024];
60f7cc78ecSespie   int count = 0;
61f7cc78ecSespie 
62f7cc78ecSespie   if (!file)
63f7cc78ecSespie     {
64f7cc78ecSespie       fprintf (stderr, _("%s: could not open %s.\n"), whoami, filename);
65f7cc78ecSespie       done (1);
66f7cc78ecSespie     }
67f7cc78ecSespie 
68f7cc78ecSespie   /* First parse the mapping file so we know how big we need to
69f7cc78ecSespie      make our tables.  We also do some sanity checks at this
70f7cc78ecSespie      time.  */
71f7cc78ecSespie   while (!feof (file))
72f7cc78ecSespie     {
73f7cc78ecSespie       int matches;
74f7cc78ecSespie 
75f7cc78ecSespie       matches = fscanf (file, "%[^\n:]", dummy);
76f7cc78ecSespie       if (!matches)
77f7cc78ecSespie 	{
78f7cc78ecSespie 	  fprintf (stderr, _("%s: unable to parse mapping file %s.\n"),
79f7cc78ecSespie 		   whoami, filename);
80f7cc78ecSespie 	  done (1);
81f7cc78ecSespie 	}
82f7cc78ecSespie 
83f7cc78ecSespie       /* Just skip messages about files with no symbols.  */
84f7cc78ecSespie       if (!strncmp (dummy, "No symbols in ", 14))
85f7cc78ecSespie 	{
86f7cc78ecSespie 	  fscanf (file, "\n");
87f7cc78ecSespie 	  continue;
88f7cc78ecSespie 	}
89f7cc78ecSespie 
90f7cc78ecSespie       /* Don't care what else is on this line at this point.  */
91f7cc78ecSespie       fscanf (file, "%[^\n]\n", dummy);
92f7cc78ecSespie       count++;
93f7cc78ecSespie     }
94f7cc78ecSespie 
95f7cc78ecSespie   /* Now we know how big we need to make our table.  */
96f7cc78ecSespie   symbol_map = ((struct function_map *)
97f7cc78ecSespie 		xmalloc (count * sizeof (struct function_map)));
98f7cc78ecSespie 
99f7cc78ecSespie   /* Rewind the input file so we can read it again.  */
100f7cc78ecSespie   rewind (file);
101f7cc78ecSespie 
102f7cc78ecSespie   /* Read each entry and put it into the table.  */
103f7cc78ecSespie   count = 0;
104f7cc78ecSespie   while (!feof (file))
105f7cc78ecSespie     {
106f7cc78ecSespie       int matches;
107f7cc78ecSespie       char *tmp;
108f7cc78ecSespie 
109f7cc78ecSespie       matches = fscanf (file, "%[^\n:]", dummy);
110f7cc78ecSespie       if (!matches)
111f7cc78ecSespie 	{
112f7cc78ecSespie 	  fprintf (stderr, _("%s: unable to parse mapping file %s.\n"),
113f7cc78ecSespie 		   whoami, filename);
114f7cc78ecSespie 	  done (1);
115f7cc78ecSespie 	}
116f7cc78ecSespie 
117f7cc78ecSespie       /* Just skip messages about files with no symbols.  */
118f7cc78ecSespie       if (!strncmp (dummy, "No symbols in ", 14))
119f7cc78ecSespie 	{
120f7cc78ecSespie 	  fscanf (file, "\n");
121f7cc78ecSespie 	  continue;
122f7cc78ecSespie 	}
123f7cc78ecSespie 
124f7cc78ecSespie       /* dummy has the filename, go ahead and copy it.  */
125f7cc78ecSespie       symbol_map[count].file_name = xmalloc (strlen (dummy) + 1);
126f7cc78ecSespie       strcpy (symbol_map[count].file_name, dummy);
127f7cc78ecSespie 
128f7cc78ecSespie       /* Now we need the function name.  */
129f7cc78ecSespie       fscanf (file, "%[^\n]\n", dummy);
130f7cc78ecSespie       tmp = strrchr (dummy, ' ') + 1;
131f7cc78ecSespie       symbol_map[count].function_name = xmalloc (strlen (tmp) + 1);
132f7cc78ecSespie       strcpy (symbol_map[count].function_name, tmp);
133f7cc78ecSespie       count++;
134f7cc78ecSespie     }
135f7cc78ecSespie 
136f7cc78ecSespie   /* Record the size of the map table for future reference.  */
137f7cc78ecSespie   symbol_map_count = count;
138f7cc78ecSespie }
139f7cc78ecSespie 
1405f210c2aSfgsch 
141f7cc78ecSespie void
core_init(aout_name)142d2201f2fSdrahn core_init (aout_name)
143d2201f2fSdrahn      const char *aout_name;
144f7cc78ecSespie {
145d2201f2fSdrahn   core_bfd = bfd_openr (aout_name, 0);
146f7cc78ecSespie 
147f7cc78ecSespie   if (!core_bfd)
148f7cc78ecSespie     {
149d2201f2fSdrahn       perror (aout_name);
150f7cc78ecSespie       done (1);
151f7cc78ecSespie     }
152f7cc78ecSespie 
153f7cc78ecSespie   if (!bfd_check_format (core_bfd, bfd_object))
154f7cc78ecSespie     {
155d2201f2fSdrahn       fprintf (stderr, _("%s: %s: not in a.out format\n"), whoami, aout_name);
156f7cc78ecSespie       done (1);
157f7cc78ecSespie     }
158f7cc78ecSespie 
1595f210c2aSfgsch   /* Get core's text section.  */
160f7cc78ecSespie   core_text_sect = bfd_get_section_by_name (core_bfd, ".text");
161f7cc78ecSespie   if (!core_text_sect)
162f7cc78ecSespie     {
163f7cc78ecSespie       core_text_sect = bfd_get_section_by_name (core_bfd, "$CODE$");
164f7cc78ecSespie       if (!core_text_sect)
165f7cc78ecSespie 	{
166f7cc78ecSespie 	  fprintf (stderr, _("%s: can't find .text section in %s\n"),
167d2201f2fSdrahn 		   whoami, aout_name);
168f7cc78ecSespie 	  done (1);
169f7cc78ecSespie 	}
170f7cc78ecSespie     }
171f7cc78ecSespie 
1725f210c2aSfgsch   /* Read core's symbol table.  */
173f7cc78ecSespie 
1745f210c2aSfgsch   /* This will probably give us more than we need, but that's ok.  */
175f7cc78ecSespie   core_num_syms = bfd_get_symtab_upper_bound (core_bfd);
176f7cc78ecSespie   if (core_num_syms < 0)
177f7cc78ecSespie     {
178d2201f2fSdrahn       fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
179f7cc78ecSespie 	       bfd_errmsg (bfd_get_error ()));
180f7cc78ecSespie       done (1);
181f7cc78ecSespie     }
182f7cc78ecSespie 
183f7cc78ecSespie   core_syms = (asymbol **) xmalloc (core_num_syms);
184f7cc78ecSespie   core_num_syms = bfd_canonicalize_symtab (core_bfd, core_syms);
1855f210c2aSfgsch 
186f7cc78ecSespie   if (core_num_syms < 0)
187f7cc78ecSespie     {
188d2201f2fSdrahn       fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
189f7cc78ecSespie 	       bfd_errmsg (bfd_get_error ()));
190f7cc78ecSespie       done (1);
191f7cc78ecSespie     }
192f7cc78ecSespie 
193f7cc78ecSespie   min_insn_size = 1;
194f7cc78ecSespie   offset_to_code = 0;
195f7cc78ecSespie 
196f7cc78ecSespie   switch (bfd_get_arch (core_bfd))
197f7cc78ecSespie     {
198f7cc78ecSespie     case bfd_arch_vax:
199f7cc78ecSespie     case bfd_arch_tahoe:
200f7cc78ecSespie       offset_to_code = 2;
201f7cc78ecSespie       break;
202f7cc78ecSespie 
203f7cc78ecSespie     case bfd_arch_alpha:
204f7cc78ecSespie       min_insn_size = 4;
205f7cc78ecSespie       break;
206f7cc78ecSespie 
207f7cc78ecSespie     default:
208f7cc78ecSespie       break;
209f7cc78ecSespie     }
210f7cc78ecSespie 
211f7cc78ecSespie   if (function_mapping_file)
212f7cc78ecSespie     read_function_mappings (function_mapping_file);
213f7cc78ecSespie }
214f7cc78ecSespie 
2155f210c2aSfgsch /* Read in the text space of an a.out file.  */
216f7cc78ecSespie 
217f7cc78ecSespie void
core_get_text_space(cbfd)218d2201f2fSdrahn core_get_text_space (cbfd)
219d2201f2fSdrahn      bfd *cbfd;
220f7cc78ecSespie {
221d2201f2fSdrahn   core_text_space = (PTR) malloc ((unsigned int) core_text_sect->_raw_size);
222f7cc78ecSespie 
223f7cc78ecSespie   if (!core_text_space)
224f7cc78ecSespie     {
225f7cc78ecSespie       fprintf (stderr, _("%s: ran out room for %lu bytes of text space\n"),
226f7cc78ecSespie 	       whoami, (unsigned long) core_text_sect->_raw_size);
227f7cc78ecSespie       done (1);
228f7cc78ecSespie     }
2295f210c2aSfgsch 
230d2201f2fSdrahn   if (!bfd_get_section_contents (cbfd, core_text_sect, core_text_space,
231d2201f2fSdrahn 				 (bfd_vma) 0, core_text_sect->_raw_size))
232f7cc78ecSespie     {
233f7cc78ecSespie       bfd_perror ("bfd_get_section_contents");
234f7cc78ecSespie       free (core_text_space);
235f7cc78ecSespie       core_text_space = 0;
236f7cc78ecSespie     }
2375f210c2aSfgsch 
238f7cc78ecSespie   if (!core_text_space)
239f7cc78ecSespie     fprintf (stderr, _("%s: can't do -c\n"), whoami);
240f7cc78ecSespie }
241f7cc78ecSespie 
242f7cc78ecSespie 
243f7cc78ecSespie void
find_call(parent,p_lowpc,p_highpc)244d2201f2fSdrahn find_call (parent, p_lowpc, p_highpc)
245d2201f2fSdrahn      Sym *parent;
246d2201f2fSdrahn      bfd_vma p_lowpc;
247d2201f2fSdrahn      bfd_vma p_highpc;
248f7cc78ecSespie {
249f7cc78ecSespie   switch (bfd_get_arch (core_bfd))
250f7cc78ecSespie     {
251f7cc78ecSespie     case bfd_arch_i386:
252f7cc78ecSespie       i386_find_call (parent, p_lowpc, p_highpc);
253f7cc78ecSespie       break;
254f7cc78ecSespie 
255f7cc78ecSespie     case bfd_arch_alpha:
256f7cc78ecSespie       alpha_find_call (parent, p_lowpc, p_highpc);
257f7cc78ecSespie       break;
258f7cc78ecSespie 
259f7cc78ecSespie     case bfd_arch_vax:
260f7cc78ecSespie       vax_find_call (parent, p_lowpc, p_highpc);
261f7cc78ecSespie       break;
262f7cc78ecSespie 
263f7cc78ecSespie     case bfd_arch_sparc:
264f7cc78ecSespie       sparc_find_call (parent, p_lowpc, p_highpc);
265f7cc78ecSespie       break;
266f7cc78ecSespie 
267f7cc78ecSespie     case bfd_arch_tahoe:
268f7cc78ecSespie       tahoe_find_call (parent, p_lowpc, p_highpc);
269f7cc78ecSespie       break;
270f7cc78ecSespie 
271d2201f2fSdrahn     case bfd_arch_mips:
272d2201f2fSdrahn       mips_find_call (parent, p_lowpc, p_highpc);
273d2201f2fSdrahn       break;
274d2201f2fSdrahn 
275f7cc78ecSespie     default:
276f7cc78ecSespie       fprintf (stderr, _("%s: -c not supported on architecture %s\n"),
277f7cc78ecSespie 	       whoami, bfd_printable_name(core_bfd));
278f7cc78ecSespie 
279f7cc78ecSespie       /* Don't give the error more than once.  */
280f7cc78ecSespie       ignore_direct_calls = FALSE;
281f7cc78ecSespie     }
282f7cc78ecSespie }
283f7cc78ecSespie 
2845f210c2aSfgsch /* Return class of symbol SYM.  The returned class can be any of:
2855f210c2aSfgsch 	0   -> symbol is not interesting to us
2865f210c2aSfgsch 	'T' -> symbol is a global name
2875f210c2aSfgsch 	't' -> symbol is a local (static) name.  */
2885f210c2aSfgsch 
289f7cc78ecSespie static int
core_sym_class(sym)290d2201f2fSdrahn core_sym_class (sym)
291d2201f2fSdrahn      asymbol *sym;
292f7cc78ecSespie {
293f7cc78ecSespie   symbol_info syminfo;
294f7cc78ecSespie   const char *name;
295f7cc78ecSespie   char sym_prefix;
296f7cc78ecSespie   int i;
297f7cc78ecSespie 
298f7cc78ecSespie   if (sym->section == NULL || (sym->flags & BSF_DEBUGGING) != 0)
299f7cc78ecSespie     return 0;
300f7cc78ecSespie 
3015f210c2aSfgsch   /* Must be a text symbol, and static text symbols
3025f210c2aSfgsch      don't qualify if ignore_static_funcs set.   */
303f7cc78ecSespie   if (ignore_static_funcs && (sym->flags & BSF_LOCAL))
304f7cc78ecSespie     {
305f7cc78ecSespie       DBG (AOUTDEBUG, printf ("[core_sym_class] %s: not a function\n",
306f7cc78ecSespie 			      sym->name));
307f7cc78ecSespie       return 0;
308f7cc78ecSespie     }
309f7cc78ecSespie 
310f7cc78ecSespie   bfd_get_symbol_info (core_bfd, sym, &syminfo);
311f7cc78ecSespie   i = syminfo.type;
312f7cc78ecSespie 
313f7cc78ecSespie   if (i == 'T')
3145f210c2aSfgsch     return i;			/* It's a global symbol.  */
315f7cc78ecSespie 
316f7cc78ecSespie   if (i == 'W')
317f7cc78ecSespie     /* Treat weak symbols as text symbols.  FIXME: a weak symbol may
318f7cc78ecSespie        also be a data symbol.  */
319f7cc78ecSespie     return 'T';
320f7cc78ecSespie 
321f7cc78ecSespie   if (i != 't')
322f7cc78ecSespie     {
3235f210c2aSfgsch       /* Not a static text symbol.  */
324f7cc78ecSespie       DBG (AOUTDEBUG, printf ("[core_sym_class] %s is of class %c\n",
325f7cc78ecSespie 			      sym->name, i));
326f7cc78ecSespie       return 0;
327f7cc78ecSespie     }
328f7cc78ecSespie 
3295f210c2aSfgsch   /* Do some more filtering on static function-names.  */
330f7cc78ecSespie   if (ignore_static_funcs)
331f7cc78ecSespie     return 0;
3325f210c2aSfgsch 
3335f210c2aSfgsch   /* Can't zero-length name or funny characters in name, where
3345f210c2aSfgsch      `funny' includes: `.' (.o file names) and `$' (Pascal labels).  */
335f7cc78ecSespie   if (!sym->name || sym->name[0] == '\0')
336f7cc78ecSespie     return 0;
337f7cc78ecSespie 
338f7cc78ecSespie   for (name = sym->name; *name; ++name)
339f7cc78ecSespie     {
340f7cc78ecSespie       if (*name == '.' || *name == '$')
341f7cc78ecSespie 	return 0;
342f7cc78ecSespie     }
3435f210c2aSfgsch 
3445f210c2aSfgsch   /* On systems where the C compiler adds an underscore to all
3455f210c2aSfgsch      names, static names without underscores seem usually to be
3465f210c2aSfgsch      labels in hand written assembler in the library.  We don't want
3475f210c2aSfgsch      these names.  This is certainly necessary on a Sparc running
3485f210c2aSfgsch      SunOS 4.1 (try profiling a program that does a lot of
3495f210c2aSfgsch      division). I don't know whether it has harmful side effects on
3505f210c2aSfgsch      other systems.  Perhaps it should be made configurable.  */
351f7cc78ecSespie   sym_prefix = bfd_get_symbol_leading_char (core_bfd);
3525f210c2aSfgsch 
353f7cc78ecSespie   if ((sym_prefix && sym_prefix != sym->name[0])
3545f210c2aSfgsch       /* GCC may add special symbols to help gdb figure out the file
3555f210c2aSfgsch 	language.  We want to ignore these, since sometimes they mask
3565f210c2aSfgsch 	the real function.  (dj@ctron)  */
357f7cc78ecSespie       || !strncmp (sym->name, "__gnu_compiled", 14)
358f7cc78ecSespie       || !strncmp (sym->name, "___gnu_compiled", 15))
359f7cc78ecSespie     {
360f7cc78ecSespie       return 0;
361f7cc78ecSespie     }
362f7cc78ecSespie 
3635f210c2aSfgsch   /* If the object file supports marking of function symbols, then
3645f210c2aSfgsch      we can zap anything that doesn't have BSF_FUNCTION set.  */
365f7cc78ecSespie   if (ignore_non_functions && (sym->flags & BSF_FUNCTION) == 0)
366f7cc78ecSespie     return 0;
367f7cc78ecSespie 
3685f210c2aSfgsch   return 't';			/* It's a static text symbol.  */
369f7cc78ecSespie }
370f7cc78ecSespie 
3715f210c2aSfgsch /* Get whatever source info we can get regarding address ADDR.  */
372f7cc78ecSespie 
373d2201f2fSdrahn static bfd_boolean
get_src_info(addr,filename,name,line_num)374d2201f2fSdrahn get_src_info (addr, filename, name, line_num)
375d2201f2fSdrahn      bfd_vma addr;
376d2201f2fSdrahn      const char **filename;
377d2201f2fSdrahn      const char **name;
378d2201f2fSdrahn      int *line_num;
379f7cc78ecSespie {
380f7cc78ecSespie   const char *fname = 0, *func_name = 0;
381f7cc78ecSespie   int l = 0;
382f7cc78ecSespie 
383f7cc78ecSespie   if (bfd_find_nearest_line (core_bfd, core_text_sect, core_syms,
384f7cc78ecSespie 			     addr - core_text_sect->vma,
385f7cc78ecSespie 			     &fname, &func_name, (unsigned int *) &l)
386f7cc78ecSespie       && fname && func_name && l)
387f7cc78ecSespie     {
388f7cc78ecSespie       DBG (AOUTDEBUG, printf ("[get_src_info] 0x%lx -> %s:%d (%s)\n",
389f7cc78ecSespie 			      (unsigned long) addr, fname, l, func_name));
390f7cc78ecSespie       *filename = fname;
391f7cc78ecSespie       *name = func_name;
392f7cc78ecSespie       *line_num = l;
393f7cc78ecSespie       return TRUE;
394f7cc78ecSespie     }
395f7cc78ecSespie   else
396f7cc78ecSespie     {
397f7cc78ecSespie       DBG (AOUTDEBUG, printf ("[get_src_info] no info for 0x%lx (%s:%d,%s)\n",
398f7cc78ecSespie 			      (long) addr, fname ? fname : "<unknown>", l,
399f7cc78ecSespie 			      func_name ? func_name : "<unknown>"));
400f7cc78ecSespie       return FALSE;
401f7cc78ecSespie     }
402f7cc78ecSespie }
403f7cc78ecSespie 
4045f210c2aSfgsch /* Read in symbol table from core.
4055f210c2aSfgsch    One symbol per function is entered.  */
406f7cc78ecSespie 
407f7cc78ecSespie void
core_create_function_syms(cbfd)408d2201f2fSdrahn core_create_function_syms (cbfd)
409d2201f2fSdrahn      bfd *cbfd ATTRIBUTE_UNUSED;
410f7cc78ecSespie {
411d2201f2fSdrahn   bfd_vma min_vma = ~(bfd_vma) 0;
412d2201f2fSdrahn   bfd_vma max_vma = 0;
413f7cc78ecSespie   int class;
414f7cc78ecSespie   long i, found, skip;
415f7cc78ecSespie   unsigned int j;
416f7cc78ecSespie 
4175f210c2aSfgsch   /* Pass 1 - determine upper bound on number of function names.  */
418f7cc78ecSespie   symtab.len = 0;
4195f210c2aSfgsch 
420f7cc78ecSespie   for (i = 0; i < core_num_syms; ++i)
421f7cc78ecSespie     {
422f7cc78ecSespie       if (!core_sym_class (core_syms[i]))
423f7cc78ecSespie 	continue;
424f7cc78ecSespie 
425f7cc78ecSespie       /* This should be replaced with a binary search or hashed
426f7cc78ecSespie 	 search.  Gross.
427f7cc78ecSespie 
428f7cc78ecSespie 	 Don't create a symtab entry for a function that has
429f7cc78ecSespie 	 a mapping to a file, unless it's the first function
430f7cc78ecSespie 	 in the file.  */
431f7cc78ecSespie       skip = 0;
432f7cc78ecSespie       for (j = 0; j < symbol_map_count; j++)
433f7cc78ecSespie 	if (!strcmp (core_syms[i]->name, symbol_map[j].function_name))
434f7cc78ecSespie 	  {
435f7cc78ecSespie 	    if (j > 0 && ! strcmp (symbol_map [j].file_name,
436f7cc78ecSespie 				   symbol_map [j - 1].file_name))
437f7cc78ecSespie 	      skip = 1;
438f7cc78ecSespie 	    break;
439f7cc78ecSespie 	  }
4405f210c2aSfgsch 
441f7cc78ecSespie       if (!skip)
442f7cc78ecSespie 	++symtab.len;
443f7cc78ecSespie     }
444f7cc78ecSespie 
445f7cc78ecSespie   if (symtab.len == 0)
446f7cc78ecSespie     {
447f7cc78ecSespie       fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, a_out_name);
448f7cc78ecSespie       done (1);
449f7cc78ecSespie     }
450f7cc78ecSespie 
4515f210c2aSfgsch   /* The "+ 2" is for the sentinels.  */
452f7cc78ecSespie   symtab.base = (Sym *) xmalloc ((symtab.len + 2) * sizeof (Sym));
453f7cc78ecSespie 
4545f210c2aSfgsch   /* Pass 2 - create symbols.  */
455f7cc78ecSespie   symtab.limit = symtab.base;
4565f210c2aSfgsch 
457f7cc78ecSespie   for (i = 0; i < core_num_syms; ++i)
458f7cc78ecSespie     {
459*cf2f2c56Smiod       asection *sym_sec;
460*cf2f2c56Smiod 
461f7cc78ecSespie       class = core_sym_class (core_syms[i]);
4625f210c2aSfgsch 
463f7cc78ecSespie       if (!class)
464f7cc78ecSespie 	{
465f7cc78ecSespie 	  DBG (AOUTDEBUG,
466f7cc78ecSespie 	       printf ("[core_create_function_syms] rejecting: 0x%lx %s\n",
467f7cc78ecSespie 		       (unsigned long) core_syms[i]->value,
468f7cc78ecSespie 		       core_syms[i]->name));
469f7cc78ecSespie 	  continue;
470f7cc78ecSespie 	}
4715f210c2aSfgsch 
472f7cc78ecSespie       /* This should be replaced with a binary search or hashed
473f7cc78ecSespie 	 search.  Gross.   */
474f7cc78ecSespie       skip = 0;
475f7cc78ecSespie       found = 0;
4765f210c2aSfgsch 
477f7cc78ecSespie       for (j = 0; j < symbol_map_count; j++)
478f7cc78ecSespie 	if (!strcmp (core_syms[i]->name, symbol_map[j].function_name))
479f7cc78ecSespie 	  {
480f7cc78ecSespie 	    if (j > 0 && ! strcmp (symbol_map [j].file_name,
481f7cc78ecSespie 				   symbol_map [j - 1].file_name))
482f7cc78ecSespie 	      skip = 1;
483f7cc78ecSespie 	    else
484f7cc78ecSespie 	      found = j;
485f7cc78ecSespie 	    break;
486f7cc78ecSespie 	  }
487f7cc78ecSespie 
488f7cc78ecSespie       if (skip)
489f7cc78ecSespie 	continue;
490f7cc78ecSespie 
491f7cc78ecSespie       sym_init (symtab.limit);
492f7cc78ecSespie 
4935f210c2aSfgsch       /* Symbol offsets are always section-relative.  */
494*cf2f2c56Smiod       sym_sec = core_syms[i]->section;
495*cf2f2c56Smiod       symtab.limit->addr = core_syms[i]->value;
496*cf2f2c56Smiod       if (sym_sec)
497*cf2f2c56Smiod 	symtab.limit->addr += bfd_get_section_vma (sym_sec->owner, sym_sec);
4985f210c2aSfgsch 
499f7cc78ecSespie       if (symbol_map_count
500f7cc78ecSespie 	  && !strcmp (core_syms[i]->name, symbol_map[found].function_name))
501f7cc78ecSespie 	{
502f7cc78ecSespie 	  symtab.limit->name = symbol_map[found].file_name;
503f7cc78ecSespie 	  symtab.limit->mapped = 1;
504f7cc78ecSespie 	}
505f7cc78ecSespie       else
506f7cc78ecSespie 	{
507f7cc78ecSespie 	  symtab.limit->name = core_syms[i]->name;
508f7cc78ecSespie 	  symtab.limit->mapped = 0;
509f7cc78ecSespie 	}
510f7cc78ecSespie 
5115f210c2aSfgsch       /* Lookup filename and line number, if we can.  */
512f7cc78ecSespie       {
513f7cc78ecSespie 	const char *filename, *func_name;
514f7cc78ecSespie 
515f7cc78ecSespie 	if (get_src_info (symtab.limit->addr, &filename, &func_name,
516f7cc78ecSespie 			  &symtab.limit->line_num))
517f7cc78ecSespie 	  {
518f7cc78ecSespie 	    symtab.limit->file = source_file_lookup_path (filename);
519f7cc78ecSespie 
520f7cc78ecSespie 	    /* FIXME: Checking __osf__ here does not work with a cross
521f7cc78ecSespie 	       gprof.  */
522f7cc78ecSespie #ifdef __osf__
5235f210c2aSfgsch 	    /* Suppress symbols that are not function names.  This is
5245f210c2aSfgsch 	       useful to suppress code-labels and aliases.
5255f210c2aSfgsch 
5265f210c2aSfgsch 	       This is known to be useful under DEC's OSF/1.  Under SunOS 4.x,
5275f210c2aSfgsch 	       labels do not appear in the symbol table info, so this isn't
5285f210c2aSfgsch 	       necessary.  */
529f7cc78ecSespie 
530f7cc78ecSespie 	    if (strcmp (symtab.limit->name, func_name) != 0)
531f7cc78ecSespie 	      {
5325f210c2aSfgsch 		/* The symbol's address maps to a different name, so
5335f210c2aSfgsch 		   it can't be a function-entry point.  This happens
5345f210c2aSfgsch 		   for labels, for example.  */
535f7cc78ecSespie 		DBG (AOUTDEBUG,
536f7cc78ecSespie 		     printf ("[core_create_function_syms: rej %s (maps to %s)\n",
537f7cc78ecSespie 			     symtab.limit->name, func_name));
538f7cc78ecSespie 		continue;
539f7cc78ecSespie 	      }
540f7cc78ecSespie #endif
541f7cc78ecSespie 	  }
542f7cc78ecSespie       }
543f7cc78ecSespie 
544f7cc78ecSespie       symtab.limit->is_func = TRUE;
545f7cc78ecSespie       symtab.limit->is_bb_head = TRUE;
5465f210c2aSfgsch 
547f7cc78ecSespie       if (class == 't')
548f7cc78ecSespie 	symtab.limit->is_static = TRUE;
549f7cc78ecSespie 
550d2201f2fSdrahn       /* Keep track of the minimum and maximum vma addresses used by all
551d2201f2fSdrahn 	 symbols.  When computing the max_vma, use the ending address of the
552d2201f2fSdrahn 	 section containing the symbol, if available.  */
553f7cc78ecSespie       min_vma = MIN (symtab.limit->addr, min_vma);
554*cf2f2c56Smiod       if (sym_sec)
555*cf2f2c56Smiod 	max_vma = MAX (bfd_get_section_vma (sym_sec->owner, sym_sec)
556*cf2f2c56Smiod 		       + bfd_section_size (sym_sec->owner, sym_sec) - 1,
557*cf2f2c56Smiod 		       max_vma);
558d2201f2fSdrahn       else
559f7cc78ecSespie 	max_vma = MAX (symtab.limit->addr, max_vma);
560f7cc78ecSespie 
5615f210c2aSfgsch       /* If we see "main" without an initial '_', we assume names
5625f210c2aSfgsch 	 are *not* prefixed by '_'.  */
563f7cc78ecSespie       if (symtab.limit->name[0] == 'm' && discard_underscores
564f7cc78ecSespie 	  && strcmp (symtab.limit->name, "main") == 0)
565f7cc78ecSespie 	discard_underscores = 0;
566f7cc78ecSespie 
567f7cc78ecSespie       DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n",
568f7cc78ecSespie 			      (long) (symtab.limit - symtab.base),
569f7cc78ecSespie 			      symtab.limit->name,
570f7cc78ecSespie 			      (unsigned long) symtab.limit->addr));
571f7cc78ecSespie       ++symtab.limit;
572f7cc78ecSespie     }
573f7cc78ecSespie 
5745f210c2aSfgsch   /* Create sentinels.  */
575f7cc78ecSespie   sym_init (symtab.limit);
576f7cc78ecSespie   symtab.limit->name = "<locore>";
577f7cc78ecSespie   symtab.limit->addr = 0;
578f7cc78ecSespie   symtab.limit->end_addr = min_vma - 1;
579f7cc78ecSespie   ++symtab.limit;
580f7cc78ecSespie 
581f7cc78ecSespie   sym_init (symtab.limit);
582f7cc78ecSespie   symtab.limit->name = "<hicore>";
583f7cc78ecSespie   symtab.limit->addr = max_vma + 1;
584d2201f2fSdrahn   symtab.limit->end_addr = ~(bfd_vma) 0;
585f7cc78ecSespie   ++symtab.limit;
586f7cc78ecSespie 
587f7cc78ecSespie   symtab.len = symtab.limit - symtab.base;
588f7cc78ecSespie   symtab_finalize (&symtab);
589f7cc78ecSespie }
590f7cc78ecSespie 
5915f210c2aSfgsch /* Read in symbol table from core.
5925f210c2aSfgsch    One symbol per line of source code is entered.  */
593f7cc78ecSespie 
594f7cc78ecSespie void
core_create_line_syms(cbfd)595d2201f2fSdrahn core_create_line_syms (cbfd)
596d2201f2fSdrahn      bfd *cbfd;
597f7cc78ecSespie {
598f7cc78ecSespie   char *prev_name, *prev_filename;
599d2201f2fSdrahn   unsigned int prev_name_len, prev_filename_len;
600d2201f2fSdrahn   bfd_vma vma, min_vma = ~(bfd_vma) 0, max_vma = 0;
601f7cc78ecSespie   bfd_vma offset;
602f7cc78ecSespie   Sym *prev, dummy, *sentinel, *sym;
603f7cc78ecSespie   const char *filename;
604f7cc78ecSespie   int prev_line_num;
605f7cc78ecSespie   Sym_Table ltab;
6065f210c2aSfgsch 
6075f210c2aSfgsch   /* Create symbols for functions as usual.  This is necessary in
6085f210c2aSfgsch      cases where parts of a program were not compiled with -g.  For
6095f210c2aSfgsch      those parts we still want to get info at the function level.  */
610d2201f2fSdrahn   core_create_function_syms (cbfd);
611f7cc78ecSespie 
6125f210c2aSfgsch   /* Pass 1 - counter number of symbols.  */
613f7cc78ecSespie 
6145f210c2aSfgsch   /* To find all line information, walk through all possible
6155f210c2aSfgsch      text-space addresses (one by one!) and get the debugging
6165f210c2aSfgsch      info for each address.  When the debugging info changes,
6175f210c2aSfgsch      it is time to create a new symbol.
6185f210c2aSfgsch 
6195f210c2aSfgsch      Of course, this is rather slow and it would be better if
6205f210c2aSfgsch      bfd would provide an iterator for enumerating all line infos.  */
621f7cc78ecSespie   prev_name_len = PATH_MAX;
622f7cc78ecSespie   prev_filename_len = PATH_MAX;
623f7cc78ecSespie   prev_name = xmalloc (prev_name_len);
624f7cc78ecSespie   prev_filename = xmalloc (prev_filename_len);
625f7cc78ecSespie   ltab.len = 0;
626f7cc78ecSespie   prev_line_num = 0;
6275f210c2aSfgsch 
628f7cc78ecSespie   for (offset = 0; offset < core_text_sect->_raw_size; offset += min_insn_size)
629f7cc78ecSespie     {
630d2201f2fSdrahn       unsigned int len;
631f7cc78ecSespie 
632f7cc78ecSespie       vma = core_text_sect->vma + offset;
6335f210c2aSfgsch 
634f7cc78ecSespie       if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num)
635f7cc78ecSespie 	  || (prev_line_num == dummy.line_num
636f7cc78ecSespie 	      && prev_name != NULL
637f7cc78ecSespie 	      && strcmp (prev_name, dummy.name) == 0
638f7cc78ecSespie 	      && strcmp (prev_filename, filename) == 0))
639f7cc78ecSespie 	continue;
640f7cc78ecSespie 
641f7cc78ecSespie       ++ltab.len;
642f7cc78ecSespie       prev_line_num = dummy.line_num;
643f7cc78ecSespie 
644f7cc78ecSespie       len = strlen (dummy.name);
645f7cc78ecSespie       if (len >= prev_name_len)
646f7cc78ecSespie 	{
647f7cc78ecSespie 	  prev_name_len = len + 1024;
648f7cc78ecSespie 	  free (prev_name);
649f7cc78ecSespie 	  prev_name = xmalloc (prev_name_len);
650f7cc78ecSespie 	}
651f7cc78ecSespie 
6525f210c2aSfgsch       strcpy (prev_name, dummy.name);
653f7cc78ecSespie       len = strlen (filename);
6545f210c2aSfgsch 
655f7cc78ecSespie       if (len >= prev_filename_len)
656f7cc78ecSespie 	{
657f7cc78ecSespie 	  prev_filename_len = len + 1024;
658f7cc78ecSespie 	  free (prev_filename);
659f7cc78ecSespie 	  prev_filename = xmalloc (prev_filename_len);
660f7cc78ecSespie 	}
6615f210c2aSfgsch 
662f7cc78ecSespie       strcpy (prev_filename, filename);
663f7cc78ecSespie 
664f7cc78ecSespie       min_vma = MIN (vma, min_vma);
665f7cc78ecSespie       max_vma = MAX (vma, max_vma);
666f7cc78ecSespie     }
667f7cc78ecSespie 
668f7cc78ecSespie   free (prev_name);
669f7cc78ecSespie   free (prev_filename);
670f7cc78ecSespie 
6715f210c2aSfgsch   /* Make room for function symbols, too.  */
672f7cc78ecSespie   ltab.len += symtab.len;
673f7cc78ecSespie   ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym));
674f7cc78ecSespie   ltab.limit = ltab.base;
675f7cc78ecSespie 
6765f210c2aSfgsch   /* Pass 2 - create symbols.  */
677f7cc78ecSespie 
678f7cc78ecSespie   /* We now set is_static as we go along, rather than by running
679f7cc78ecSespie      through the symbol table at the end.
680f7cc78ecSespie 
681f7cc78ecSespie      The old way called symtab_finalize before the is_static pass,
682f7cc78ecSespie      causing a problem since symtab_finalize uses is_static as part of
683f7cc78ecSespie      its address conflict resolution algorithm.  Since global symbols
684f7cc78ecSespie      were prefered over static symbols, and all line symbols were
685f7cc78ecSespie      global at that point, static function names that conflicted with
686f7cc78ecSespie      their own line numbers (static, but labeled as global) were
687f7cc78ecSespie      rejected in favor of the line num.
688f7cc78ecSespie 
689f7cc78ecSespie      This was not the desired functionality.  We always want to keep
690f7cc78ecSespie      our function symbols and discard any conflicting line symbols.
691f7cc78ecSespie      Perhaps symtab_finalize should be modified to make this
692f7cc78ecSespie      distinction as well, but the current fix works and the code is a
693f7cc78ecSespie      lot cleaner now.  */
694f7cc78ecSespie   prev = 0;
6955f210c2aSfgsch 
696f7cc78ecSespie   for (offset = 0; offset < core_text_sect->_raw_size; offset += min_insn_size)
697f7cc78ecSespie     {
698f7cc78ecSespie       sym_init (ltab.limit);
6995f210c2aSfgsch 
700f7cc78ecSespie       if (!get_src_info (core_text_sect->vma + offset, &filename,
701f7cc78ecSespie 			 &ltab.limit->name, &ltab.limit->line_num)
702f7cc78ecSespie 	  || (prev && prev->line_num == ltab.limit->line_num
703f7cc78ecSespie 	      && strcmp (prev->name, ltab.limit->name) == 0
704f7cc78ecSespie 	      && strcmp (prev->file->name, filename) == 0))
705f7cc78ecSespie 	continue;
706f7cc78ecSespie 
7075f210c2aSfgsch       /* Make name pointer a malloc'ed string.  */
708f7cc78ecSespie       ltab.limit->name = xstrdup (ltab.limit->name);
709f7cc78ecSespie       ltab.limit->file = source_file_lookup_path (filename);
710f7cc78ecSespie 
711f7cc78ecSespie       ltab.limit->addr = core_text_sect->vma + offset;
712f7cc78ecSespie 
713f7cc78ecSespie       /* Set is_static based on the enclosing function, using either:
7145f210c2aSfgsch 	 1) the previous symbol, if it's from the same function, or
7155f210c2aSfgsch 	 2) a symtab lookup.  */
716f7cc78ecSespie       if (prev && ltab.limit->file == prev->file &&
717f7cc78ecSespie 	  strcmp (ltab.limit->name, prev->name) == 0)
718f7cc78ecSespie 	{
719f7cc78ecSespie 	  ltab.limit->is_static = prev->is_static;
720f7cc78ecSespie 	}
721f7cc78ecSespie       else
722f7cc78ecSespie 	{
723f7cc78ecSespie 	  sym = sym_lookup(&symtab, ltab.limit->addr);
724f7cc78ecSespie 	  ltab.limit->is_static = sym->is_static;
725f7cc78ecSespie 	}
726f7cc78ecSespie 
727f7cc78ecSespie       prev = ltab.limit;
728f7cc78ecSespie 
7295f210c2aSfgsch       /* If we see "main" without an initial '_', we assume names
7305f210c2aSfgsch 	 are *not* prefixed by '_'.  */
731f7cc78ecSespie       if (ltab.limit->name[0] == 'm' && discard_underscores
732f7cc78ecSespie 	  && strcmp (ltab.limit->name, "main") == 0)
733f7cc78ecSespie 	discard_underscores = 0;
734f7cc78ecSespie 
735f7cc78ecSespie       DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n",
736f7cc78ecSespie 			      (unsigned long) (ltab.limit - ltab.base),
737f7cc78ecSespie 			      ltab.limit->name,
738f7cc78ecSespie 			      (unsigned long) ltab.limit->addr));
739f7cc78ecSespie       ++ltab.limit;
740f7cc78ecSespie     }
741f7cc78ecSespie 
7425f210c2aSfgsch   /* Update sentinels.  */
743d2201f2fSdrahn   sentinel = sym_lookup (&symtab, (bfd_vma) 0);
7445f210c2aSfgsch 
745d2201f2fSdrahn   if (sentinel
746d2201f2fSdrahn       && strcmp (sentinel->name, "<locore>") == 0
747f7cc78ecSespie       && min_vma <= sentinel->end_addr)
748f7cc78ecSespie     sentinel->end_addr = min_vma - 1;
749f7cc78ecSespie 
750d2201f2fSdrahn   sentinel = sym_lookup (&symtab, ~(bfd_vma) 0);
751f7cc78ecSespie 
752d2201f2fSdrahn   if (sentinel
753d2201f2fSdrahn       && strcmp (sentinel->name, "<hicore>") == 0
754d2201f2fSdrahn       && max_vma >= sentinel->addr)
7555f210c2aSfgsch     sentinel->addr = max_vma + 1;
7565f210c2aSfgsch 
7575f210c2aSfgsch   /* Copy in function symbols.  */
758f7cc78ecSespie   memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym));
759f7cc78ecSespie   ltab.limit += symtab.len;
760f7cc78ecSespie 
761f7cc78ecSespie   if ((unsigned int) (ltab.limit - ltab.base) != ltab.len)
762f7cc78ecSespie     {
763f7cc78ecSespie       fprintf (stderr,
764f7cc78ecSespie 	       _("%s: somebody miscounted: ltab.len=%d instead of %ld\n"),
765f7cc78ecSespie 	       whoami, ltab.len, (long) (ltab.limit - ltab.base));
766f7cc78ecSespie       done (1);
767f7cc78ecSespie     }
768f7cc78ecSespie 
7695f210c2aSfgsch   /* Finalize ltab and make it symbol table.  */
770f7cc78ecSespie   symtab_finalize (&ltab);
771f7cc78ecSespie   free (symtab.base);
772f7cc78ecSespie   symtab = ltab;
773f7cc78ecSespie }
774