12a6b7db3Sskrll /* corefile.c
22a6b7db3Sskrll
3*dd7241dfSchristos Copyright (C) 1999-2024 Free Software Foundation, Inc.
42a6b7db3Sskrll
52a6b7db3Sskrll This file is part of GNU Binutils.
62a6b7db3Sskrll
72a6b7db3Sskrll This program is free software; you can redistribute it and/or modify
82a6b7db3Sskrll it under the terms of the GNU General Public License as published by
92a6b7db3Sskrll the Free Software Foundation; either version 3 of the License, or
102a6b7db3Sskrll (at your option) any later version.
112a6b7db3Sskrll
122a6b7db3Sskrll This program is distributed in the hope that it will be useful,
132a6b7db3Sskrll but WITHOUT ANY WARRANTY; without even the implied warranty of
142a6b7db3Sskrll MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
152a6b7db3Sskrll GNU General Public License for more details.
162a6b7db3Sskrll
172a6b7db3Sskrll You should have received a copy of the GNU General Public License
182a6b7db3Sskrll along with this program; if not, write to the Free Software
192a6b7db3Sskrll Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
202a6b7db3Sskrll 02110-1301, USA. */
212a6b7db3Sskrll
222a6b7db3Sskrll #include "gprof.h"
232a6b7db3Sskrll #include "libiberty.h"
24b410d692Schristos #include "filenames.h"
252a6b7db3Sskrll #include "search_list.h"
262a6b7db3Sskrll #include "source.h"
272a6b7db3Sskrll #include "symtab.h"
282a6b7db3Sskrll #include "hist.h"
292a6b7db3Sskrll #include "corefile.h"
302a6b7db3Sskrll #include "safe-ctype.h"
316f226886Schristos #include <limits.h> /* For UINT_MAX. */
322a6b7db3Sskrll
33abf07352Sskrll #include <stdlib.h>
34abf07352Sskrll
352a6b7db3Sskrll bfd *core_bfd;
362a6b7db3Sskrll static int core_num_syms;
372a6b7db3Sskrll static asymbol **core_syms;
382a6b7db3Sskrll asection *core_text_sect;
3932998b1cSchristos void * core_text_space;
402a6b7db3Sskrll
412a6b7db3Sskrll static int min_insn_size;
422a6b7db3Sskrll int offset_to_code;
432a6b7db3Sskrll
442a6b7db3Sskrll /* For mapping symbols to specific .o files during file ordering. */
452a6b7db3Sskrll struct function_map * symbol_map;
462a6b7db3Sskrll unsigned int symbol_map_count;
472a6b7db3Sskrll
482a6b7db3Sskrll static void read_function_mappings (const char *);
492a6b7db3Sskrll static int core_sym_class (asymbol *);
5003f5171aSchristos static bool get_src_info
512a6b7db3Sskrll (bfd_vma, const char **, const char **, int *);
522a6b7db3Sskrll
532a6b7db3Sskrll extern void i386_find_call (Sym *, bfd_vma, bfd_vma);
542a6b7db3Sskrll extern void alpha_find_call (Sym *, bfd_vma, bfd_vma);
552a6b7db3Sskrll extern void vax_find_call (Sym *, bfd_vma, bfd_vma);
562a6b7db3Sskrll extern void sparc_find_call (Sym *, bfd_vma, bfd_vma);
572a6b7db3Sskrll extern void mips_find_call (Sym *, bfd_vma, bfd_vma);
585f4eaf39Schristos extern void aarch64_find_call (Sym *, bfd_vma, bfd_vma);
592a6b7db3Sskrll
602a6b7db3Sskrll static void
parse_error(const char * filename)612a6b7db3Sskrll parse_error (const char *filename)
622a6b7db3Sskrll {
632a6b7db3Sskrll fprintf (stderr, _("%s: unable to parse mapping file %s.\n"), whoami, filename);
642a6b7db3Sskrll done (1);
652a6b7db3Sskrll }
662a6b7db3Sskrll
6732998b1cSchristos /* Compare two function_map structs based on function name.
6832998b1cSchristos We want to sort in ascending order. */
6932998b1cSchristos
7032998b1cSchristos static int
cmp_symbol_map(const void * l,const void * r)7132998b1cSchristos cmp_symbol_map (const void * l, const void * r)
7232998b1cSchristos {
7332998b1cSchristos return strcmp (((struct function_map *) l)->function_name,
7432998b1cSchristos ((struct function_map *) r)->function_name);
7532998b1cSchristos }
7632998b1cSchristos
776f226886Schristos #define BUFSIZE (1024)
786f226886Schristos /* This is BUFSIZE - 1 as a string. Suitable for use in fprintf/sscanf format strings. */
796f226886Schristos #define STR_BUFSIZE "1023"
806f226886Schristos
812a6b7db3Sskrll static void
read_function_mappings(const char * filename)822a6b7db3Sskrll read_function_mappings (const char *filename)
832a6b7db3Sskrll {
842a6b7db3Sskrll FILE * file = fopen (filename, "r");
856f226886Schristos char dummy[BUFSIZE];
862a6b7db3Sskrll int count = 0;
8732998b1cSchristos unsigned int i;
882a6b7db3Sskrll
892a6b7db3Sskrll if (!file)
902a6b7db3Sskrll {
912a6b7db3Sskrll fprintf (stderr, _("%s: could not open %s.\n"), whoami, filename);
922a6b7db3Sskrll done (1);
932a6b7db3Sskrll }
942a6b7db3Sskrll
952a6b7db3Sskrll /* First parse the mapping file so we know how big we need to
962a6b7db3Sskrll make our tables. We also do some sanity checks at this
972a6b7db3Sskrll time. */
982a6b7db3Sskrll while (!feof (file))
992a6b7db3Sskrll {
1002a6b7db3Sskrll int matches;
1012a6b7db3Sskrll
1026f226886Schristos matches = fscanf (file, "%" STR_BUFSIZE "[^\n:]", dummy);
1032a6b7db3Sskrll if (!matches)
1042a6b7db3Sskrll parse_error (filename);
1052a6b7db3Sskrll
1062a6b7db3Sskrll /* Just skip messages about files with no symbols. */
1072a6b7db3Sskrll if (!strncmp (dummy, "No symbols in ", 14))
1082a6b7db3Sskrll {
1092a6b7db3Sskrll matches = fscanf (file, "\n");
1102a6b7db3Sskrll if (matches == EOF)
1112a6b7db3Sskrll parse_error (filename);
1122a6b7db3Sskrll continue;
1132a6b7db3Sskrll }
1142a6b7db3Sskrll
1152a6b7db3Sskrll /* Don't care what else is on this line at this point. */
1166f226886Schristos matches = fscanf (file, "%" STR_BUFSIZE "[^\n]\n", dummy);
1172a6b7db3Sskrll if (!matches)
1182a6b7db3Sskrll parse_error (filename);
1192a6b7db3Sskrll count++;
1202a6b7db3Sskrll }
1212a6b7db3Sskrll
1222a6b7db3Sskrll /* Now we know how big we need to make our table. */
1232a6b7db3Sskrll symbol_map = ((struct function_map *)
1242a6b7db3Sskrll xmalloc (count * sizeof (struct function_map)));
1252a6b7db3Sskrll
1262a6b7db3Sskrll /* Rewind the input file so we can read it again. */
1272a6b7db3Sskrll rewind (file);
1282a6b7db3Sskrll
1292a6b7db3Sskrll /* Read each entry and put it into the table. */
1302a6b7db3Sskrll count = 0;
1312a6b7db3Sskrll while (!feof (file))
1322a6b7db3Sskrll {
1332a6b7db3Sskrll int matches;
1342a6b7db3Sskrll char *tmp;
1352a6b7db3Sskrll
1366f226886Schristos matches = fscanf (file, "%" STR_BUFSIZE "[^\n:]", dummy);
1372a6b7db3Sskrll if (!matches)
1382a6b7db3Sskrll parse_error (filename);
1392a6b7db3Sskrll
1402a6b7db3Sskrll /* Just skip messages about files with no symbols. */
1412a6b7db3Sskrll if (!strncmp (dummy, "No symbols in ", 14))
1422a6b7db3Sskrll {
1432a6b7db3Sskrll matches = fscanf (file, "\n");
1442a6b7db3Sskrll if (matches == EOF)
1452a6b7db3Sskrll parse_error (filename);
1462a6b7db3Sskrll continue;
1472a6b7db3Sskrll }
1482a6b7db3Sskrll
1492a6b7db3Sskrll /* dummy has the filename, go ahead and copy it. */
15032998b1cSchristos symbol_map[count].file_name = (char *) xmalloc (strlen (dummy) + 1);
1512a6b7db3Sskrll strcpy (symbol_map[count].file_name, dummy);
1522a6b7db3Sskrll
1532a6b7db3Sskrll /* Now we need the function name. */
1546f226886Schristos matches = fscanf (file, "%" STR_BUFSIZE "[^\n]\n", dummy);
1552a6b7db3Sskrll if (!matches)
1562a6b7db3Sskrll parse_error (filename);
1572a6b7db3Sskrll tmp = strrchr (dummy, ' ') + 1;
15832998b1cSchristos symbol_map[count].function_name = (char *) xmalloc (strlen (tmp) + 1);
1592a6b7db3Sskrll strcpy (symbol_map[count].function_name, tmp);
1602a6b7db3Sskrll count++;
1612a6b7db3Sskrll }
1622a6b7db3Sskrll
1632a6b7db3Sskrll /* Record the size of the map table for future reference. */
1642a6b7db3Sskrll symbol_map_count = count;
1652a6b7db3Sskrll
16632998b1cSchristos for (i = 0; i < symbol_map_count; ++i)
167b410d692Schristos if (i == 0
168b410d692Schristos || filename_cmp (symbol_map[i].file_name, symbol_map[i - 1].file_name))
16932998b1cSchristos symbol_map[i].is_first = 1;
17032998b1cSchristos
17132998b1cSchristos qsort (symbol_map, symbol_map_count, sizeof (struct function_map), cmp_symbol_map);
1725f4eaf39Schristos
1735f4eaf39Schristos fclose (file);
17432998b1cSchristos }
1752a6b7db3Sskrll
1762a6b7db3Sskrll void
core_init(const char * aout_name)1772a6b7db3Sskrll core_init (const char * aout_name)
1782a6b7db3Sskrll {
1792a6b7db3Sskrll int core_sym_bytes;
1802a6b7db3Sskrll asymbol *synthsyms;
1812a6b7db3Sskrll long synth_count;
1822a6b7db3Sskrll
1832a6b7db3Sskrll core_bfd = bfd_openr (aout_name, 0);
1842a6b7db3Sskrll
1852a6b7db3Sskrll if (!core_bfd)
1862a6b7db3Sskrll {
1872a6b7db3Sskrll perror (aout_name);
1882a6b7db3Sskrll done (1);
1892a6b7db3Sskrll }
1902a6b7db3Sskrll
191106c59e5Schristos core_bfd->flags |= BFD_DECOMPRESS;
192106c59e5Schristos
1932a6b7db3Sskrll if (!bfd_check_format (core_bfd, bfd_object))
1942a6b7db3Sskrll {
1952a6b7db3Sskrll fprintf (stderr, _("%s: %s: not in executable format\n"), whoami, aout_name);
1962a6b7db3Sskrll done (1);
1972a6b7db3Sskrll }
1982a6b7db3Sskrll
1992a6b7db3Sskrll /* Get core's text section. */
2002a6b7db3Sskrll core_text_sect = bfd_get_section_by_name (core_bfd, ".text");
2012a6b7db3Sskrll if (!core_text_sect)
2022a6b7db3Sskrll {
2032a6b7db3Sskrll core_text_sect = bfd_get_section_by_name (core_bfd, "$CODE$");
2042a6b7db3Sskrll if (!core_text_sect)
2052a6b7db3Sskrll {
2062a6b7db3Sskrll fprintf (stderr, _("%s: can't find .text section in %s\n"),
2072a6b7db3Sskrll whoami, aout_name);
2082a6b7db3Sskrll done (1);
2092a6b7db3Sskrll }
2102a6b7db3Sskrll }
2112a6b7db3Sskrll
2122a6b7db3Sskrll /* Read core's symbol table. */
2132a6b7db3Sskrll
2142a6b7db3Sskrll /* This will probably give us more than we need, but that's ok. */
2152a6b7db3Sskrll core_sym_bytes = bfd_get_symtab_upper_bound (core_bfd);
2162a6b7db3Sskrll if (core_sym_bytes < 0)
2172a6b7db3Sskrll {
2182a6b7db3Sskrll fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
2192a6b7db3Sskrll bfd_errmsg (bfd_get_error ()));
2202a6b7db3Sskrll done (1);
2212a6b7db3Sskrll }
2222a6b7db3Sskrll
2232a6b7db3Sskrll core_syms = (asymbol **) xmalloc (core_sym_bytes);
2242a6b7db3Sskrll core_num_syms = bfd_canonicalize_symtab (core_bfd, core_syms);
2252a6b7db3Sskrll
2262a6b7db3Sskrll if (core_num_syms < 0)
2272a6b7db3Sskrll {
2282a6b7db3Sskrll fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
2292a6b7db3Sskrll bfd_errmsg (bfd_get_error ()));
2302a6b7db3Sskrll done (1);
2312a6b7db3Sskrll }
2322a6b7db3Sskrll
2332a6b7db3Sskrll synth_count = bfd_get_synthetic_symtab (core_bfd, core_num_syms, core_syms,
2342a6b7db3Sskrll 0, NULL, &synthsyms);
2352a6b7db3Sskrll if (synth_count > 0)
2362a6b7db3Sskrll {
2372a6b7db3Sskrll asymbol **symp;
2382a6b7db3Sskrll long new_size;
2392a6b7db3Sskrll long i;
2402a6b7db3Sskrll
2412a6b7db3Sskrll new_size = (core_num_syms + synth_count + 1) * sizeof (*core_syms);
24232998b1cSchristos core_syms = (asymbol **) xrealloc (core_syms, new_size);
2432a6b7db3Sskrll symp = core_syms + core_num_syms;
2442a6b7db3Sskrll core_num_syms += synth_count;
2452a6b7db3Sskrll for (i = 0; i < synth_count; i++)
2462a6b7db3Sskrll *symp++ = synthsyms + i;
2472a6b7db3Sskrll *symp = 0;
2482a6b7db3Sskrll }
2492a6b7db3Sskrll
2502a6b7db3Sskrll min_insn_size = 1;
2512a6b7db3Sskrll offset_to_code = 0;
2522a6b7db3Sskrll
2532a6b7db3Sskrll switch (bfd_get_arch (core_bfd))
2542a6b7db3Sskrll {
2552a6b7db3Sskrll case bfd_arch_vax:
2562a6b7db3Sskrll offset_to_code = 2;
2572a6b7db3Sskrll break;
2582a6b7db3Sskrll
2592a6b7db3Sskrll case bfd_arch_alpha:
2602a6b7db3Sskrll min_insn_size = 4;
2612a6b7db3Sskrll break;
2622a6b7db3Sskrll
2632a6b7db3Sskrll default:
2642a6b7db3Sskrll break;
2652a6b7db3Sskrll }
2662a6b7db3Sskrll
2672a6b7db3Sskrll if (function_mapping_file)
2682a6b7db3Sskrll read_function_mappings (function_mapping_file);
2692a6b7db3Sskrll }
2702a6b7db3Sskrll
2712a6b7db3Sskrll /* Read in the text space of an a.out file. */
2722a6b7db3Sskrll
2732a6b7db3Sskrll void
core_get_text_space(bfd * cbfd)2742a6b7db3Sskrll core_get_text_space (bfd *cbfd)
2752a6b7db3Sskrll {
276106c59e5Schristos core_text_space = malloc (bfd_section_size (core_text_sect));
2772a6b7db3Sskrll
2782a6b7db3Sskrll if (!core_text_space)
2792a6b7db3Sskrll {
2802a6b7db3Sskrll fprintf (stderr, _("%s: ran out room for %lu bytes of text space\n"),
281106c59e5Schristos whoami, (unsigned long) bfd_section_size (core_text_sect));
2822a6b7db3Sskrll done (1);
2832a6b7db3Sskrll }
2842a6b7db3Sskrll
2852a6b7db3Sskrll if (!bfd_get_section_contents (cbfd, core_text_sect, core_text_space,
286106c59e5Schristos 0, bfd_section_size (core_text_sect)))
2872a6b7db3Sskrll {
2882a6b7db3Sskrll bfd_perror ("bfd_get_section_contents");
2892a6b7db3Sskrll free (core_text_space);
2902a6b7db3Sskrll core_text_space = 0;
2912a6b7db3Sskrll }
2922a6b7db3Sskrll
2932a6b7db3Sskrll if (!core_text_space)
2942a6b7db3Sskrll fprintf (stderr, _("%s: can't do -c\n"), whoami);
2952a6b7db3Sskrll }
2962a6b7db3Sskrll
2972a6b7db3Sskrll
2982a6b7db3Sskrll void
find_call(Sym * parent,bfd_vma p_lowpc,bfd_vma p_highpc)2992a6b7db3Sskrll find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
3002a6b7db3Sskrll {
3012a6b7db3Sskrll if (core_text_space == 0)
3022a6b7db3Sskrll return;
3032a6b7db3Sskrll
3042a6b7db3Sskrll hist_clip_symbol_address (&p_lowpc, &p_highpc);
3052a6b7db3Sskrll
3062a6b7db3Sskrll switch (bfd_get_arch (core_bfd))
3072a6b7db3Sskrll {
3082a6b7db3Sskrll case bfd_arch_i386:
3092a6b7db3Sskrll i386_find_call (parent, p_lowpc, p_highpc);
3102a6b7db3Sskrll break;
3112a6b7db3Sskrll
3122a6b7db3Sskrll case bfd_arch_alpha:
3132a6b7db3Sskrll alpha_find_call (parent, p_lowpc, p_highpc);
3142a6b7db3Sskrll break;
3152a6b7db3Sskrll
3162a6b7db3Sskrll case bfd_arch_vax:
3172a6b7db3Sskrll vax_find_call (parent, p_lowpc, p_highpc);
3182a6b7db3Sskrll break;
3192a6b7db3Sskrll
3202a6b7db3Sskrll case bfd_arch_sparc:
3212a6b7db3Sskrll sparc_find_call (parent, p_lowpc, p_highpc);
3222a6b7db3Sskrll break;
3232a6b7db3Sskrll
3242a6b7db3Sskrll case bfd_arch_mips:
3252a6b7db3Sskrll mips_find_call (parent, p_lowpc, p_highpc);
3262a6b7db3Sskrll break;
3272a6b7db3Sskrll
3285f4eaf39Schristos case bfd_arch_aarch64:
3295f4eaf39Schristos aarch64_find_call (parent, p_lowpc, p_highpc);
3305f4eaf39Schristos break;
3315f4eaf39Schristos
3322a6b7db3Sskrll default:
3332a6b7db3Sskrll fprintf (stderr, _("%s: -c not supported on architecture %s\n"),
3342a6b7db3Sskrll whoami, bfd_printable_name(core_bfd));
3352a6b7db3Sskrll
3362a6b7db3Sskrll /* Don't give the error more than once. */
33703f5171aSchristos ignore_direct_calls = false;
3382a6b7db3Sskrll }
3392a6b7db3Sskrll }
3402a6b7db3Sskrll
3412a6b7db3Sskrll /* Return class of symbol SYM. The returned class can be any of:
3422a6b7db3Sskrll 0 -> symbol is not interesting to us
3432a6b7db3Sskrll 'T' -> symbol is a global name
3442a6b7db3Sskrll 't' -> symbol is a local (static) name. */
3452a6b7db3Sskrll
3462a6b7db3Sskrll static int
core_sym_class(asymbol * sym)3472a6b7db3Sskrll core_sym_class (asymbol *sym)
3482a6b7db3Sskrll {
3492a6b7db3Sskrll symbol_info syminfo;
3502a6b7db3Sskrll const char *name;
3512a6b7db3Sskrll char sym_prefix;
3522a6b7db3Sskrll int i;
3532a6b7db3Sskrll
3542a6b7db3Sskrll if (sym->section == NULL || (sym->flags & BSF_DEBUGGING) != 0)
3552a6b7db3Sskrll return 0;
3562a6b7db3Sskrll
3572a6b7db3Sskrll /* Must be a text symbol, and static text symbols
3582a6b7db3Sskrll don't qualify if ignore_static_funcs set. */
3592a6b7db3Sskrll if (ignore_static_funcs && (sym->flags & BSF_LOCAL))
3602a6b7db3Sskrll {
3612a6b7db3Sskrll DBG (AOUTDEBUG, printf ("[core_sym_class] %s: not a function\n",
3622a6b7db3Sskrll sym->name));
3632a6b7db3Sskrll return 0;
3642a6b7db3Sskrll }
3652a6b7db3Sskrll
3662a6b7db3Sskrll bfd_get_symbol_info (core_bfd, sym, &syminfo);
3672a6b7db3Sskrll i = syminfo.type;
3682a6b7db3Sskrll
3692a6b7db3Sskrll if (i == 'T')
3702a6b7db3Sskrll return i; /* It's a global symbol. */
3712a6b7db3Sskrll
3722a6b7db3Sskrll if (i == 'W')
3732a6b7db3Sskrll /* Treat weak symbols as text symbols. FIXME: a weak symbol may
3742a6b7db3Sskrll also be a data symbol. */
3752a6b7db3Sskrll return 'T';
3762a6b7db3Sskrll
3772a6b7db3Sskrll if (i != 't')
3782a6b7db3Sskrll {
3792a6b7db3Sskrll /* Not a static text symbol. */
3802a6b7db3Sskrll DBG (AOUTDEBUG, printf ("[core_sym_class] %s is of class %c\n",
3812a6b7db3Sskrll sym->name, i));
3822a6b7db3Sskrll return 0;
3832a6b7db3Sskrll }
3842a6b7db3Sskrll
3852a6b7db3Sskrll /* Do some more filtering on static function-names. */
3862a6b7db3Sskrll if (ignore_static_funcs)
3872a6b7db3Sskrll return 0;
3882a6b7db3Sskrll
3892a6b7db3Sskrll /* Can't zero-length name or funny characters in name, where
3902a6b7db3Sskrll `funny' includes: `.' (.o file names) and `$' (Pascal labels). */
3912a6b7db3Sskrll if (!sym->name || sym->name[0] == '\0')
3922a6b7db3Sskrll return 0;
3932a6b7db3Sskrll
3942a6b7db3Sskrll for (name = sym->name; *name; ++name)
3952a6b7db3Sskrll {
3962a6b7db3Sskrll if (*name == '$')
3972a6b7db3Sskrll return 0;
3982a6b7db3Sskrll
399b410d692Schristos while (*name == '.')
40032998b1cSchristos {
401b410d692Schristos /* Allow both nested subprograms (which end with ".NNN", where N is
402b410d692Schristos a digit) and GCC cloned functions (which contain ".clone").
403b410d692Schristos Allow for multiple iterations of both - apparently GCC can clone
404b410d692Schristos clones and subprograms. */
405b410d692Schristos int digit_seen = 0;
406b410d692Schristos #define CLONE_NAME ".clone."
407b410d692Schristos #define CLONE_NAME_LEN strlen (CLONE_NAME)
4085f4eaf39Schristos #define CONSTPROP_NAME ".constprop."
4095f4eaf39Schristos #define CONSTPROP_NAME_LEN strlen (CONSTPROP_NAME)
41032998b1cSchristos
411b410d692Schristos if (strlen (name) > CLONE_NAME_LEN
412b410d692Schristos && strncmp (name, CLONE_NAME, CLONE_NAME_LEN) == 0)
413b410d692Schristos name += CLONE_NAME_LEN - 1;
414b410d692Schristos
4155f4eaf39Schristos else if (strlen (name) > CONSTPROP_NAME_LEN
4165f4eaf39Schristos && strncmp (name, CONSTPROP_NAME, CONSTPROP_NAME_LEN) == 0)
4175f4eaf39Schristos name += CONSTPROP_NAME_LEN - 1;
4185f4eaf39Schristos
4192a6b7db3Sskrll for (name++; *name; name++)
420b410d692Schristos if (digit_seen && *name == '.')
42132998b1cSchristos break;
422b410d692Schristos else if (ISDIGIT (*name))
423b410d692Schristos digit_seen = 1;
424b410d692Schristos else
425b410d692Schristos return 0;
42632998b1cSchristos }
4272a6b7db3Sskrll }
4282a6b7db3Sskrll
4292a6b7db3Sskrll /* On systems where the C compiler adds an underscore to all
4302a6b7db3Sskrll names, static names without underscores seem usually to be
4312a6b7db3Sskrll labels in hand written assembler in the library. We don't want
4322a6b7db3Sskrll these names. This is certainly necessary on a Sparc running
4332a6b7db3Sskrll SunOS 4.1 (try profiling a program that does a lot of
4342a6b7db3Sskrll division). I don't know whether it has harmful side effects on
4352a6b7db3Sskrll other systems. Perhaps it should be made configurable. */
4362a6b7db3Sskrll sym_prefix = bfd_get_symbol_leading_char (core_bfd);
4372a6b7db3Sskrll
4382a6b7db3Sskrll if ((sym_prefix && sym_prefix != sym->name[0])
4392a6b7db3Sskrll /* GCC may add special symbols to help gdb figure out the file
4402a6b7db3Sskrll language. We want to ignore these, since sometimes they mask
4412a6b7db3Sskrll the real function. (dj@ctron) */
4422a6b7db3Sskrll || !strncmp (sym->name, "__gnu_compiled", 14)
4432a6b7db3Sskrll || !strncmp (sym->name, "___gnu_compiled", 15))
4442a6b7db3Sskrll {
4452a6b7db3Sskrll return 0;
4462a6b7db3Sskrll }
4472a6b7db3Sskrll
4482a6b7db3Sskrll /* If the object file supports marking of function symbols, then
4492a6b7db3Sskrll we can zap anything that doesn't have BSF_FUNCTION set. */
4502a6b7db3Sskrll if (ignore_non_functions && (sym->flags & BSF_FUNCTION) == 0)
4512a6b7db3Sskrll return 0;
4522a6b7db3Sskrll
4532a6b7db3Sskrll return 't'; /* It's a static text symbol. */
4542a6b7db3Sskrll }
4552a6b7db3Sskrll
4562a6b7db3Sskrll /* Get whatever source info we can get regarding address ADDR. */
4572a6b7db3Sskrll
45803f5171aSchristos static bool
get_src_info(bfd_vma addr,const char ** filename,const char ** name,int * line_num)45903f5171aSchristos get_src_info (bfd_vma addr, const char **filename, const char **name,
46003f5171aSchristos int *line_num)
4612a6b7db3Sskrll {
4622a6b7db3Sskrll const char *fname = 0, *func_name = 0;
4632a6b7db3Sskrll int l = 0;
4642a6b7db3Sskrll
4652a6b7db3Sskrll if (bfd_find_nearest_line (core_bfd, core_text_sect, core_syms,
4662a6b7db3Sskrll addr - core_text_sect->vma,
4672a6b7db3Sskrll &fname, &func_name, (unsigned int *) &l)
4682a6b7db3Sskrll && fname && func_name && l)
4692a6b7db3Sskrll {
4702a6b7db3Sskrll DBG (AOUTDEBUG, printf ("[get_src_info] 0x%lx -> %s:%d (%s)\n",
4712a6b7db3Sskrll (unsigned long) addr, fname, l, func_name));
4722a6b7db3Sskrll *filename = fname;
4732a6b7db3Sskrll *name = func_name;
4742a6b7db3Sskrll *line_num = l;
47503f5171aSchristos return true;
4762a6b7db3Sskrll }
4772a6b7db3Sskrll else
4782a6b7db3Sskrll {
4792a6b7db3Sskrll DBG (AOUTDEBUG, printf ("[get_src_info] no info for 0x%lx (%s:%d,%s)\n",
4802a6b7db3Sskrll (unsigned long) addr,
4812a6b7db3Sskrll fname ? fname : "<unknown>", l,
4822a6b7db3Sskrll func_name ? func_name : "<unknown>"));
48303f5171aSchristos return false;
4842a6b7db3Sskrll }
4852a6b7db3Sskrll }
4862a6b7db3Sskrll
4876f226886Schristos static char buf[BUFSIZE];
4886f226886Schristos static char address[BUFSIZE];
4896f226886Schristos static char name[BUFSIZE];
4906f226886Schristos
49132998b1cSchristos /* Return number of symbols in a symbol-table file. */
49232998b1cSchristos
4936f226886Schristos static unsigned int
num_of_syms_in(FILE * f)49432998b1cSchristos num_of_syms_in (FILE * f)
49532998b1cSchristos {
49632998b1cSchristos char type;
4976f226886Schristos unsigned int num = 0;
49832998b1cSchristos
49932998b1cSchristos while (!feof (f) && fgets (buf, BUFSIZE - 1, f))
50032998b1cSchristos {
5016f226886Schristos if (sscanf (buf, "%" STR_BUFSIZE "s %c %" STR_BUFSIZE "s", address, &type, name) == 3)
50232998b1cSchristos if (type == 't' || type == 'T')
5036f226886Schristos {
5046f226886Schristos /* PR 20499 - prevent integer overflow computing argument to xmalloc. */
5056f226886Schristos if (++num >= UINT_MAX / sizeof (Sym))
5066f226886Schristos return -1U;
50732998b1cSchristos }
5086f226886Schristos }
50932998b1cSchristos
51032998b1cSchristos return num;
51132998b1cSchristos }
51232998b1cSchristos
51332998b1cSchristos /* Read symbol table from a file. */
51432998b1cSchristos
51532998b1cSchristos void
core_create_syms_from(const char * sym_table_file)51632998b1cSchristos core_create_syms_from (const char * sym_table_file)
51732998b1cSchristos {
51832998b1cSchristos char type;
51932998b1cSchristos bfd_vma min_vma = ~(bfd_vma) 0;
52032998b1cSchristos bfd_vma max_vma = 0;
52132998b1cSchristos FILE * f;
52232998b1cSchristos
52332998b1cSchristos f = fopen (sym_table_file, "r");
52432998b1cSchristos if (!f)
52532998b1cSchristos {
52632998b1cSchristos fprintf (stderr, _("%s: could not open %s.\n"), whoami, sym_table_file);
52732998b1cSchristos done (1);
52832998b1cSchristos }
52932998b1cSchristos
53032998b1cSchristos /* Pass 1 - determine upper bound on number of function names. */
53132998b1cSchristos symtab.len = num_of_syms_in (f);
53232998b1cSchristos
53332998b1cSchristos if (symtab.len == 0)
53432998b1cSchristos {
53532998b1cSchristos fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, sym_table_file);
53632998b1cSchristos done (1);
53732998b1cSchristos }
5386f226886Schristos else if (symtab.len == -1U)
5396f226886Schristos {
5406f226886Schristos fprintf (stderr, _("%s: file `%s' has too many symbols\n"),
5416f226886Schristos whoami, sym_table_file);
5426f226886Schristos done (1);
5436f226886Schristos }
54432998b1cSchristos
54532998b1cSchristos symtab.base = (Sym *) xmalloc (symtab.len * sizeof (Sym));
54632998b1cSchristos
54732998b1cSchristos /* Pass 2 - create symbols. */
54832998b1cSchristos symtab.limit = symtab.base;
54932998b1cSchristos
55032998b1cSchristos if (fseek (f, 0, SEEK_SET) != 0)
55132998b1cSchristos {
55232998b1cSchristos perror (sym_table_file);
55332998b1cSchristos done (1);
55432998b1cSchristos }
55532998b1cSchristos
55632998b1cSchristos while (!feof (f) && fgets (buf, BUFSIZE - 1, f))
55732998b1cSchristos {
5586f226886Schristos if (sscanf (buf, "%" STR_BUFSIZE "s %c %" STR_BUFSIZE "s", address, &type, name) != 3)
5596f226886Schristos continue;
56032998b1cSchristos if (type != 't' && type != 'T')
56132998b1cSchristos continue;
56232998b1cSchristos
56332998b1cSchristos sym_init (symtab.limit);
56432998b1cSchristos
565*dd7241dfSchristos uint64_t addr;
566*dd7241dfSchristos sscanf (address, "%" SCNx64, &addr);
567*dd7241dfSchristos symtab.limit->addr = addr;
56832998b1cSchristos
56932998b1cSchristos symtab.limit->name = (char *) xmalloc (strlen (name) + 1);
57032998b1cSchristos strcpy ((char *) symtab.limit->name, name);
57132998b1cSchristos symtab.limit->mapped = 0;
57203f5171aSchristos symtab.limit->is_func = true;
57303f5171aSchristos symtab.limit->is_bb_head = true;
57432998b1cSchristos symtab.limit->is_static = (type == 't');
57532998b1cSchristos min_vma = MIN (symtab.limit->addr, min_vma);
57632998b1cSchristos max_vma = MAX (symtab.limit->addr, max_vma);
57732998b1cSchristos
57832998b1cSchristos ++symtab.limit;
57932998b1cSchristos }
58032998b1cSchristos fclose (f);
58132998b1cSchristos
58232998b1cSchristos symtab.len = symtab.limit - symtab.base;
58332998b1cSchristos symtab_finalize (&symtab);
58432998b1cSchristos }
58532998b1cSchristos
58632998b1cSchristos static int
search_mapped_symbol(const void * l,const void * r)58732998b1cSchristos search_mapped_symbol (const void * l, const void * r)
58832998b1cSchristos {
58932998b1cSchristos return strcmp ((const char *) l, ((const struct function_map *) r)->function_name);
59032998b1cSchristos }
59132998b1cSchristos
5922a6b7db3Sskrll /* Read in symbol table from core.
5932a6b7db3Sskrll One symbol per function is entered. */
5942a6b7db3Sskrll
5952a6b7db3Sskrll void
core_create_function_syms(void)59632998b1cSchristos core_create_function_syms (void)
5972a6b7db3Sskrll {
5982a6b7db3Sskrll bfd_vma min_vma = ~ (bfd_vma) 0;
5992a6b7db3Sskrll bfd_vma max_vma = 0;
60032998b1cSchristos int cxxclass;
60132998b1cSchristos long i;
602b410d692Schristos struct function_map * found = NULL;
60332998b1cSchristos int core_has_func_syms = 0;
60432998b1cSchristos
60532998b1cSchristos switch (core_bfd->xvec->flavour)
60632998b1cSchristos {
60732998b1cSchristos default:
60832998b1cSchristos break;
60932998b1cSchristos case bfd_target_coff_flavour:
61032998b1cSchristos case bfd_target_ecoff_flavour:
61132998b1cSchristos case bfd_target_xcoff_flavour:
61232998b1cSchristos case bfd_target_elf_flavour:
61332998b1cSchristos case bfd_target_som_flavour:
61432998b1cSchristos core_has_func_syms = 1;
61532998b1cSchristos }
6162a6b7db3Sskrll
6172a6b7db3Sskrll /* Pass 1 - determine upper bound on number of function names. */
6182a6b7db3Sskrll symtab.len = 0;
6192a6b7db3Sskrll
6202a6b7db3Sskrll for (i = 0; i < core_num_syms; ++i)
6212a6b7db3Sskrll {
6222a6b7db3Sskrll if (!core_sym_class (core_syms[i]))
6232a6b7db3Sskrll continue;
6242a6b7db3Sskrll
62532998b1cSchristos /* Don't create a symtab entry for a function that has
6262a6b7db3Sskrll a mapping to a file, unless it's the first function
6272a6b7db3Sskrll in the file. */
628b410d692Schristos if (symbol_map_count != 0)
629b410d692Schristos {
630b410d692Schristos /* Note: some systems (SunOS 5.8) crash if bsearch base argument
631b410d692Schristos is NULL. */
632b410d692Schristos found = (struct function_map *) bsearch
633b410d692Schristos (core_syms[i]->name, symbol_map, symbol_map_count,
634b410d692Schristos sizeof (struct function_map), search_mapped_symbol);
635b410d692Schristos }
63632998b1cSchristos if (found == NULL || found->is_first)
6372a6b7db3Sskrll ++symtab.len;
6382a6b7db3Sskrll }
6392a6b7db3Sskrll
6402a6b7db3Sskrll if (symtab.len == 0)
6412a6b7db3Sskrll {
6422a6b7db3Sskrll fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, a_out_name);
6432a6b7db3Sskrll done (1);
6442a6b7db3Sskrll }
6452a6b7db3Sskrll
64632998b1cSchristos symtab.base = (Sym *) xmalloc (symtab.len * sizeof (Sym));
6472a6b7db3Sskrll
6482a6b7db3Sskrll /* Pass 2 - create symbols. */
6492a6b7db3Sskrll symtab.limit = symtab.base;
6502a6b7db3Sskrll
6512a6b7db3Sskrll for (i = 0; i < core_num_syms; ++i)
6522a6b7db3Sskrll {
6532a6b7db3Sskrll asection *sym_sec;
6542a6b7db3Sskrll
65532998b1cSchristos cxxclass = core_sym_class (core_syms[i]);
6562a6b7db3Sskrll
65732998b1cSchristos if (!cxxclass)
6582a6b7db3Sskrll {
6592a6b7db3Sskrll DBG (AOUTDEBUG,
6602a6b7db3Sskrll printf ("[core_create_function_syms] rejecting: 0x%lx %s\n",
6612a6b7db3Sskrll (unsigned long) core_syms[i]->value,
6622a6b7db3Sskrll core_syms[i]->name));
6632a6b7db3Sskrll continue;
6642a6b7db3Sskrll }
6652a6b7db3Sskrll
666b410d692Schristos if (symbol_map_count != 0)
667b410d692Schristos {
668b410d692Schristos /* Note: some systems (SunOS 5.8) crash if bsearch base argument
669b410d692Schristos is NULL. */
670b410d692Schristos found = (struct function_map *) bsearch
671b410d692Schristos (core_syms[i]->name, symbol_map, symbol_map_count,
67232998b1cSchristos sizeof (struct function_map), search_mapped_symbol);
673b410d692Schristos }
67432998b1cSchristos if (found && ! found->is_first)
6752a6b7db3Sskrll continue;
6762a6b7db3Sskrll
6772a6b7db3Sskrll sym_init (symtab.limit);
6782a6b7db3Sskrll
6792a6b7db3Sskrll /* Symbol offsets are always section-relative. */
6802a6b7db3Sskrll sym_sec = core_syms[i]->section;
6812a6b7db3Sskrll symtab.limit->addr = core_syms[i]->value;
6822a6b7db3Sskrll if (sym_sec)
683106c59e5Schristos symtab.limit->addr += bfd_section_vma (sym_sec);
6842a6b7db3Sskrll
68532998b1cSchristos if (found)
6862a6b7db3Sskrll {
68732998b1cSchristos symtab.limit->name = found->file_name;
6882a6b7db3Sskrll symtab.limit->mapped = 1;
6892a6b7db3Sskrll }
6902a6b7db3Sskrll else
6912a6b7db3Sskrll {
6922a6b7db3Sskrll symtab.limit->name = core_syms[i]->name;
6932a6b7db3Sskrll symtab.limit->mapped = 0;
6942a6b7db3Sskrll }
6952a6b7db3Sskrll
6962a6b7db3Sskrll /* Lookup filename and line number, if we can. */
6972a6b7db3Sskrll {
69832998b1cSchristos const char * filename;
69932998b1cSchristos const char * func_name;
7002a6b7db3Sskrll
7012a6b7db3Sskrll if (get_src_info (symtab.limit->addr, & filename, & func_name,
7022a6b7db3Sskrll & symtab.limit->line_num))
7032a6b7db3Sskrll {
7042a6b7db3Sskrll symtab.limit->file = source_file_lookup_path (filename);
7052a6b7db3Sskrll
7062a6b7db3Sskrll /* FIXME: Checking __osf__ here does not work with a cross
7072a6b7db3Sskrll gprof. */
7082a6b7db3Sskrll #ifdef __osf__
7092a6b7db3Sskrll /* Suppress symbols that are not function names. This is
7102a6b7db3Sskrll useful to suppress code-labels and aliases.
7112a6b7db3Sskrll
7122a6b7db3Sskrll This is known to be useful under DEC's OSF/1. Under SunOS 4.x,
7132a6b7db3Sskrll labels do not appear in the symbol table info, so this isn't
7142a6b7db3Sskrll necessary. */
7152a6b7db3Sskrll
7162a6b7db3Sskrll if (strcmp (symtab.limit->name, func_name) != 0)
7172a6b7db3Sskrll {
7182a6b7db3Sskrll /* The symbol's address maps to a different name, so
7192a6b7db3Sskrll it can't be a function-entry point. This happens
7202a6b7db3Sskrll for labels, for example. */
7212a6b7db3Sskrll DBG (AOUTDEBUG,
7222a6b7db3Sskrll printf ("[core_create_function_syms: rej %s (maps to %s)\n",
7232a6b7db3Sskrll symtab.limit->name, func_name));
7242a6b7db3Sskrll continue;
7252a6b7db3Sskrll }
7262a6b7db3Sskrll #endif
7272a6b7db3Sskrll }
7282a6b7db3Sskrll }
7292a6b7db3Sskrll
73032998b1cSchristos symtab.limit->is_func = (!core_has_func_syms
73132998b1cSchristos || (core_syms[i]->flags & BSF_FUNCTION) != 0);
73203f5171aSchristos symtab.limit->is_bb_head = true;
7332a6b7db3Sskrll
73432998b1cSchristos if (cxxclass == 't')
73503f5171aSchristos symtab.limit->is_static = true;
7362a6b7db3Sskrll
7372a6b7db3Sskrll /* Keep track of the minimum and maximum vma addresses used by all
7382a6b7db3Sskrll symbols. When computing the max_vma, use the ending address of the
7392a6b7db3Sskrll section containing the symbol, if available. */
7402a6b7db3Sskrll min_vma = MIN (symtab.limit->addr, min_vma);
7412a6b7db3Sskrll if (sym_sec)
742106c59e5Schristos max_vma = MAX (bfd_section_vma (sym_sec)
743106c59e5Schristos + bfd_section_size (sym_sec) - 1,
7442a6b7db3Sskrll max_vma);
7452a6b7db3Sskrll else
7462a6b7db3Sskrll max_vma = MAX (symtab.limit->addr, max_vma);
7472a6b7db3Sskrll
7482a6b7db3Sskrll DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n",
7492a6b7db3Sskrll (long) (symtab.limit - symtab.base),
7502a6b7db3Sskrll symtab.limit->name,
7512a6b7db3Sskrll (unsigned long) symtab.limit->addr));
7522a6b7db3Sskrll ++symtab.limit;
7532a6b7db3Sskrll }
7542a6b7db3Sskrll
7552a6b7db3Sskrll symtab.len = symtab.limit - symtab.base;
7562a6b7db3Sskrll symtab_finalize (&symtab);
7572a6b7db3Sskrll }
7582a6b7db3Sskrll
7592a6b7db3Sskrll /* Read in symbol table from core.
7602a6b7db3Sskrll One symbol per line of source code is entered. */
7612a6b7db3Sskrll
7622a6b7db3Sskrll void
core_create_line_syms(void)76332998b1cSchristos core_create_line_syms (void)
7642a6b7db3Sskrll {
7652a6b7db3Sskrll char *prev_name, *prev_filename;
7662a6b7db3Sskrll unsigned int prev_name_len, prev_filename_len;
7672a6b7db3Sskrll bfd_vma vma, min_vma = ~(bfd_vma) 0, max_vma = 0;
76832998b1cSchristos Sym *prev, dummy, *sym;
7692a6b7db3Sskrll const char *filename;
7702a6b7db3Sskrll int prev_line_num;
7712a6b7db3Sskrll Sym_Table ltab;
7722a6b7db3Sskrll bfd_vma vma_high;
7732a6b7db3Sskrll
7742a6b7db3Sskrll /* Create symbols for functions as usual. This is necessary in
7752a6b7db3Sskrll cases where parts of a program were not compiled with -g. For
7762a6b7db3Sskrll those parts we still want to get info at the function level. */
7772a6b7db3Sskrll core_create_function_syms ();
7782a6b7db3Sskrll
7792a6b7db3Sskrll /* Pass 1: count the number of symbols. */
7802a6b7db3Sskrll
7812a6b7db3Sskrll /* To find all line information, walk through all possible
7822a6b7db3Sskrll text-space addresses (one by one!) and get the debugging
7832a6b7db3Sskrll info for each address. When the debugging info changes,
7842a6b7db3Sskrll it is time to create a new symbol.
7852a6b7db3Sskrll
7862a6b7db3Sskrll Of course, this is rather slow and it would be better if
7872a6b7db3Sskrll BFD would provide an iterator for enumerating all line infos. */
78803f5171aSchristos prev_name_len = 1024;
78903f5171aSchristos prev_filename_len = 1024;
79032998b1cSchristos prev_name = (char *) xmalloc (prev_name_len);
79132998b1cSchristos prev_filename = (char *) xmalloc (prev_filename_len);
7922a6b7db3Sskrll ltab.len = 0;
7932a6b7db3Sskrll prev_line_num = 0;
7942a6b7db3Sskrll
795106c59e5Schristos vma_high = core_text_sect->vma + bfd_section_size (core_text_sect);
7962a6b7db3Sskrll for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size)
7972a6b7db3Sskrll {
7982a6b7db3Sskrll unsigned int len;
7992a6b7db3Sskrll
8002a6b7db3Sskrll if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num)
8012a6b7db3Sskrll || (prev_line_num == dummy.line_num
8022a6b7db3Sskrll && prev_name != NULL
8032a6b7db3Sskrll && strcmp (prev_name, dummy.name) == 0
804b410d692Schristos && filename_cmp (prev_filename, filename) == 0))
8052a6b7db3Sskrll continue;
8062a6b7db3Sskrll
8072a6b7db3Sskrll ++ltab.len;
8082a6b7db3Sskrll prev_line_num = dummy.line_num;
8092a6b7db3Sskrll
8102a6b7db3Sskrll len = strlen (dummy.name);
8112a6b7db3Sskrll if (len >= prev_name_len)
8122a6b7db3Sskrll {
8132a6b7db3Sskrll prev_name_len = len + 1024;
8142a6b7db3Sskrll free (prev_name);
81532998b1cSchristos prev_name = (char *) xmalloc (prev_name_len);
8162a6b7db3Sskrll }
8172a6b7db3Sskrll
8182a6b7db3Sskrll strcpy (prev_name, dummy.name);
8192a6b7db3Sskrll len = strlen (filename);
8202a6b7db3Sskrll
8212a6b7db3Sskrll if (len >= prev_filename_len)
8222a6b7db3Sskrll {
8232a6b7db3Sskrll prev_filename_len = len + 1024;
8242a6b7db3Sskrll free (prev_filename);
82532998b1cSchristos prev_filename = (char *) xmalloc (prev_filename_len);
8262a6b7db3Sskrll }
8272a6b7db3Sskrll
8282a6b7db3Sskrll strcpy (prev_filename, filename);
8292a6b7db3Sskrll
8302a6b7db3Sskrll min_vma = MIN (vma, min_vma);
8312a6b7db3Sskrll max_vma = MAX (vma, max_vma);
8322a6b7db3Sskrll }
8332a6b7db3Sskrll
8342a6b7db3Sskrll free (prev_name);
8352a6b7db3Sskrll free (prev_filename);
8362a6b7db3Sskrll
8372a6b7db3Sskrll /* Make room for function symbols, too. */
8382a6b7db3Sskrll ltab.len += symtab.len;
8392a6b7db3Sskrll ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym));
8402a6b7db3Sskrll ltab.limit = ltab.base;
8412a6b7db3Sskrll
8422a6b7db3Sskrll /* Pass 2 - create symbols. */
8432a6b7db3Sskrll
8442a6b7db3Sskrll /* We now set is_static as we go along, rather than by running
8452a6b7db3Sskrll through the symbol table at the end.
8462a6b7db3Sskrll
8472a6b7db3Sskrll The old way called symtab_finalize before the is_static pass,
8482a6b7db3Sskrll causing a problem since symtab_finalize uses is_static as part of
8492a6b7db3Sskrll its address conflict resolution algorithm. Since global symbols
8506f226886Schristos were preferred over static symbols, and all line symbols were
8512a6b7db3Sskrll global at that point, static function names that conflicted with
8522a6b7db3Sskrll their own line numbers (static, but labeled as global) were
8532a6b7db3Sskrll rejected in favor of the line num.
8542a6b7db3Sskrll
8552a6b7db3Sskrll This was not the desired functionality. We always want to keep
8562a6b7db3Sskrll our function symbols and discard any conflicting line symbols.
8572a6b7db3Sskrll Perhaps symtab_finalize should be modified to make this
8582a6b7db3Sskrll distinction as well, but the current fix works and the code is a
8592a6b7db3Sskrll lot cleaner now. */
8602a6b7db3Sskrll prev = 0;
8612a6b7db3Sskrll
8622a6b7db3Sskrll for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size)
8632a6b7db3Sskrll {
8642a6b7db3Sskrll sym_init (ltab.limit);
8652a6b7db3Sskrll
8662a6b7db3Sskrll if (!get_src_info (vma, &filename, <ab.limit->name, <ab.limit->line_num)
8672a6b7db3Sskrll || (prev && prev->line_num == ltab.limit->line_num
8682a6b7db3Sskrll && strcmp (prev->name, ltab.limit->name) == 0
869b410d692Schristos && filename_cmp (prev->file->name, filename) == 0))
8702a6b7db3Sskrll continue;
8712a6b7db3Sskrll
8722a6b7db3Sskrll /* Make name pointer a malloc'ed string. */
8732a6b7db3Sskrll ltab.limit->name = xstrdup (ltab.limit->name);
8742a6b7db3Sskrll ltab.limit->file = source_file_lookup_path (filename);
8752a6b7db3Sskrll
8762a6b7db3Sskrll ltab.limit->addr = vma;
8772a6b7db3Sskrll
8782a6b7db3Sskrll /* Set is_static based on the enclosing function, using either:
8792a6b7db3Sskrll 1) the previous symbol, if it's from the same function, or
8802a6b7db3Sskrll 2) a symtab lookup. */
8812a6b7db3Sskrll if (prev && ltab.limit->file == prev->file &&
8822a6b7db3Sskrll strcmp (ltab.limit->name, prev->name) == 0)
8832a6b7db3Sskrll {
8842a6b7db3Sskrll ltab.limit->is_static = prev->is_static;
8852a6b7db3Sskrll }
8862a6b7db3Sskrll else
8872a6b7db3Sskrll {
8882a6b7db3Sskrll sym = sym_lookup(&symtab, ltab.limit->addr);
88932998b1cSchristos if (sym)
8902a6b7db3Sskrll ltab.limit->is_static = sym->is_static;
8912a6b7db3Sskrll }
8922a6b7db3Sskrll
8932a6b7db3Sskrll prev = ltab.limit;
8942a6b7db3Sskrll
8952a6b7db3Sskrll DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n",
8962a6b7db3Sskrll (unsigned long) (ltab.limit - ltab.base),
8972a6b7db3Sskrll ltab.limit->name,
8982a6b7db3Sskrll (unsigned long) ltab.limit->addr));
8992a6b7db3Sskrll ++ltab.limit;
9002a6b7db3Sskrll }
9012a6b7db3Sskrll
9022a6b7db3Sskrll /* Copy in function symbols. */
9032a6b7db3Sskrll memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym));
9042a6b7db3Sskrll ltab.limit += symtab.len;
9052a6b7db3Sskrll
9062a6b7db3Sskrll if ((unsigned int) (ltab.limit - ltab.base) != ltab.len)
9072a6b7db3Sskrll {
9082a6b7db3Sskrll fprintf (stderr,
9092a6b7db3Sskrll _("%s: somebody miscounted: ltab.len=%d instead of %ld\n"),
9102a6b7db3Sskrll whoami, ltab.len, (long) (ltab.limit - ltab.base));
9112a6b7db3Sskrll done (1);
9122a6b7db3Sskrll }
9132a6b7db3Sskrll
9142a6b7db3Sskrll /* Finalize ltab and make it symbol table. */
9152a6b7db3Sskrll symtab_finalize (<ab);
9162a6b7db3Sskrll free (symtab.base);
9172a6b7db3Sskrll symtab = ltab;
9182a6b7db3Sskrll }
919