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 <ab.limit->name, <ab.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 (<ab);
771f7cc78ecSespie free (symtab.base);
772f7cc78ecSespie symtab = ltab;
773f7cc78ecSespie }
774