#include "core.h"
#include "symtab.h"
+#ifndef MIN_INSN_SIZE
+/* If not defined in MACHINE_H, assume smallest instruction is 1 byte
+ long. THis is safe but may be needlessly slow on machines where
+ all instructions are longer. */
+#define MIN_INSN_SIZE 1
+#endif
+
bfd *core_bfd;
int core_num_syms;
asymbol **core_syms;
asection *core_text_sect;
PTR core_text_space;
+/* For mapping symbols to specific .o files during file ordering. */
+struct function_map {
+ char *function_name;
+ char *file_name;
+};
+
+struct function_map *symbol_map;
+int symbol_map_count;
+
+static void
+DEFUN (read_function_mappings, (filename), const char *filename)
+{
+ FILE *file = fopen (filename, "r");
+ char dummy[1024];
+ int count = 0;
+
+ if (!file)
+ {
+ fprintf (stderr, "%s: could not open %s.\n", whoami, filename);
+ done (1);
+ }
+
+ /* First parse the mapping file so we know how big we need to
+ make our tables. We also do some sanity checks at this
+ time. */
+ while (!feof (file))
+ {
+ int matches;
+
+ matches = fscanf (file, "%[^\n:]", dummy);
+ if (!matches)
+ {
+ fprintf (stderr, "%s: unable to parse mapping file %s.\n",
+ whoami, filename);
+ done (1);
+ }
+
+ /* Just skip messages about files with no symbols. */
+ if (!strncmp (dummy, "No symbols in ", 14))
+ {
+ fscanf (file, "\n");
+ continue;
+ }
+
+ /* Don't care what else is on this line at this point. */
+ fscanf (file, "%[^\n]\n", dummy);
+ count++;
+ }
+
+ /* Now we know how big we need to make our table. */
+ symbol_map = ((struct function_map *)
+ xmalloc (count * sizeof (struct function_map)));
+
+ /* Rewind the input file so we can read it again. */
+ rewind (file);
+
+ /* Read each entry and put it into the table. */
+ count = 0;
+ while (!feof (file))
+ {
+ int matches;
+ char *tmp;
+
+ matches = fscanf (file, "%[^\n:]", dummy);
+ if (!matches)
+ {
+ fprintf (stderr, "%s: unable to parse mapping file %s.\n",
+ whoami, filename);
+ done (1);
+ }
+
+ /* Just skip messages about files with no symbols. */
+ if (!strncmp (dummy, "No symbols in ", 14))
+ {
+ fscanf (file, "\n");
+ continue;
+ }
+
+ /* dummy has the filename, go ahead and copy it. */
+ symbol_map[count].file_name = xmalloc (strlen (dummy) + 1);
+ strcpy (symbol_map[count].file_name, dummy);
+
+ /* Now we need the function name. */
+ fscanf (file, "%[^\n]\n", dummy);
+ tmp = strrchr (dummy, ' ') + 1;
+ symbol_map[count].function_name = xmalloc (strlen (tmp) + 1);
+ strcpy (symbol_map[count].function_name, tmp);
+ count++;
+ }
+
+ /* Record the size of the map table for future reference. */
+ symbol_map_count = count;
+}
void
DEFUN (core_init, (a_out_name), const char *a_out_name)
{
perror (a_out_name);
done (1);
- } /* if */
+ }
if (!bfd_check_format (core_bfd, bfd_object))
{
fprintf (stderr, "%s: %s: not in a.out format\n", whoami, a_out_name);
done (1);
- } /* if */
+ }
/* get core's text section: */
core_text_sect = bfd_get_section_by_name (core_bfd, ".text");
fprintf (stderr, "%s: can't find .text section in %s\n",
whoami, a_out_name);
done (1);
- } /* if */
- } /* if */
+ }
+ }
/* read core's symbol table: */
fprintf (stderr, "%s: %s: %s\n", whoami, a_out_name,
bfd_errmsg (bfd_get_error ()));
done (1);
- } /* if */
+ }
core_syms = (asymbol **) xmalloc (core_num_syms);
core_num_syms = bfd_canonicalize_symtab (core_bfd, core_syms);
fprintf (stderr, "%s: %s: %s\n", whoami, a_out_name,
bfd_errmsg (bfd_get_error ()));
done (1);
- } /* if */
-} /* core_init */
+ }
+
+ if (function_mapping_file)
+ read_function_mappings (function_mapping_file);
+}
/*
fprintf (stderr, "%s: ran out room for %ld bytes of text space\n",
whoami, core_text_sect->_raw_size);
done (1);
- } /* if */
+ }
if (!bfd_get_section_contents (core_bfd, core_text_sect, core_text_space,
0, core_text_sect->_raw_size))
{
bfd_perror ("bfd_get_section_contents");
free (core_text_space);
core_text_space = 0;
- } /* if */
+ }
if (!core_text_space)
{
fprintf (stderr, "%s: can't do -c\n", whoami);
- } /* if */
-} /* core_get_text_space */
+ }
+}
/*
char sym_prefix;
int i;
+ if (sym->section == NULL || (sym->flags & BSF_DEBUGGING) != 0)
+ {
+ return 0;
+ }
+
/*
* Must be a text symbol, and static text symbols don't qualify if
* ignore_static_funcs set.
*/
- if (!sym->section)
- {
- return 0;
- } /* if */
-
if (ignore_static_funcs && (sym->flags & BSF_LOCAL))
{
DBG (AOUTDEBUG, printf ("[core_sym_class] %s: not a function\n",
sym->name));
return 0;
- } /* if */
+ }
bfd_get_symbol_info (core_bfd, sym, &syminfo);
i = syminfo.type;
if (i == 'T')
{
return i; /* it's a global symbol */
- } /* if */
+ }
if (i != 't')
{
DBG (AOUTDEBUG, printf ("[core_sym_class] %s is of class %c\n",
sym->name, i));
return 0;
- } /* if */
+ }
/* do some more filtering on static function-names: */
if (ignore_static_funcs)
{
return 0;
- } /* if */
+ }
/*
* Can't zero-length name or funny characters in name, where
* `funny' includes: `.' (.o file names) and `$' (Pascal labels).
if (!sym->name || sym->name[0] == '\0')
{
return 0;
- } /* if */
+ }
for (name = sym->name; *name; ++name)
{
if (*name == '.' || *name == '$')
{
return 0;
- } /* if */
- } /* if */
+ }
+ }
/*
* On systems where the C compiler adds an underscore to all
* names, static names without underscores seem usually to be
* other systems. Perhaps it should be made configurable.
*/
sym_prefix = bfd_get_symbol_leading_char (core_bfd);
- if (sym_prefix && sym_prefix != sym->name[0]
+ if ((sym_prefix && sym_prefix != sym->name[0])
/*
* GCC may add special symbols to help gdb figure out the file
* language. We want to ignore these, since sometimes they mask
|| !strncmp (sym->name, "___gnu_compiled", 15))
{
return 0;
- } /* if */
+ }
+
+ /* If the object file supports marking of function symbols, then we can
+ zap anything that doesn't have BSF_FUNCTION set. */
+ if (ignore_non_functions && (sym->flags & BSF_FUNCTION) == 0)
+ return 0;
+
return 't'; /* it's a static text symbol */
-} /* core_sym_class */
+}
/*
if (bfd_find_nearest_line (core_bfd, core_text_sect, core_syms,
addr - core_text_sect->vma,
- &fname, &func_name, &l)
+ &fname, &func_name, (unsigned int *) &l)
&& fname && func_name && l)
{
DBG (AOUTDEBUG, printf ("[get_src_info] 0x%lx -> %s:%d (%s)\n",
(long) addr, fname ? fname : "<unknown>", l,
func_name ? func_name : "<unknown>"));
return FALSE;
- } /* if */
-} /* get_src_info */
+ }
+}
/*
DEFUN (core_create_function_syms, (core_bfd), bfd * core_bfd)
{
bfd_vma min_vma = ~0, max_vma = 0;
- const char *filename, *func_name;
int class;
- long i;
+ long i, j, found, skip;
/* pass 1 - determine upper bound on number of function names: */
symtab.len = 0;
if (!core_sym_class (core_syms[i]))
{
continue;
- } /* if */
- ++symtab.len;
- } /* for */
+ }
+
+ /* This should be replaced with a binary search or hashed
+ search. Gross.
+
+ Don't create a symtab entry for a function that has
+ a mapping to a file, unless it's the first function
+ in the file. */
+ skip = 0;
+ for (j = 0; j < symbol_map_count; j++)
+ if (!strcmp (core_syms[i]->name, symbol_map[j].function_name))
+ {
+ if (j > 0 && ! strcmp (symbol_map [j].file_name,
+ symbol_map [j - 1].file_name))
+ skip = 1;
+ break;
+ }
+ if (!skip)
+ ++symtab.len;
+ }
if (symtab.len == 0)
{
fprintf (stderr, "%s: file `%s' has no symbols\n", whoami, a_out_name);
done (1);
- } /* if */
+ }
/* the "+ 2" is for the sentinels: */
symtab.base = (Sym *) xmalloc ((symtab.len + 2) * sizeof (Sym));
printf ("[core_create_function_syms] rejecting: 0x%lx %s\n",
core_syms[i]->value, core_syms[i]->name));
continue;
- } /* if */
+ }
+ /* This should be replaced with a binary search or hashed
+ search. Gross. */
+
+ skip = 0;
+ found = 0;
+ for (j = 0; j < symbol_map_count; j++)
+ if (!strcmp (core_syms[i]->name, symbol_map[j].function_name))
+ {
+ if (j > 0 && ! strcmp (symbol_map [j].file_name,
+ symbol_map [j - 1].file_name))
+ skip = 1;
+ else
+ found = j;
+ break;
+ }
+
+ if (skip)
+ continue;
sym_init (symtab.limit);
/* symbol offsets are always section-relative: */
symtab.limit->addr = core_syms[i]->value + core_syms[i]->section->vma;
- symtab.limit->name = core_syms[i]->name;
+ if (symbol_map_count
+ && !strcmp (core_syms[i]->name, symbol_map[found].function_name))
+ {
+ symtab.limit->name = symbol_map[found].file_name;
+ symtab.limit->mapped = 1;
+ }
+ else
+ {
+ symtab.limit->name = core_syms[i]->name;
+ symtab.limit->mapped = 0;
+ }
#ifdef __osf__
/*
* labels do not appear in the symbol table info, so this isn't
* necessary.
*/
- if (get_src_info (symtab.limit->addr, &filename, &func_name,
- &symtab.limit->line_num))
- {
- symtab.limit->file = source_file_lookup_path (filename);
-
- if (strcmp (symtab.limit->name, func_name) != 0)
- {
- /*
- * The symbol's address maps to a different name, so
- * it can't be a function-entry point. This happens
- * for labels, for example.
- */
- DBG (AOUTDEBUG,
- printf ("[core_create_function_syms: rej %s (maps to %s)\n",
- symtab.limit->name, func_name));
- continue;
- } /* if */
- } /* if */
+ {
+ const char *filename, *func_name;
+
+ if (get_src_info (symtab.limit->addr, &filename, &func_name,
+ &symtab.limit->line_num))
+ {
+ symtab.limit->file = source_file_lookup_path (filename);
+
+ if (strcmp (symtab.limit->name, func_name) != 0)
+ {
+ /*
+ * The symbol's address maps to a different name, so
+ * it can't be a function-entry point. This happens
+ * for labels, for example.
+ */
+ DBG (AOUTDEBUG,
+ printf ("[core_create_function_syms: rej %s (maps to %s)\n",
+ symtab.limit->name, func_name));
+ continue;
+ }
+ }
+ }
#endif
symtab.limit->is_func = TRUE;
if (class == 't')
{
symtab.limit->is_static = TRUE;
- } /* if */
+ }
min_vma = MIN (symtab.limit->addr, min_vma);
max_vma = MAX (symtab.limit->addr, max_vma);
&& strcmp (symtab.limit->name, "main") == 0)
{
discard_underscores = 0;
- } /* if */
+ }
DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n",
(long) (symtab.limit - symtab.base),
symtab.limit->name, symtab.limit->addr));
++symtab.limit;
- } /* for */
+ }
/* create sentinels: */
symtab.len = symtab.limit - symtab.base;
symtab_finalize (&symtab);
-} /* core_create_function_syms */
+}
/*
prev_offset = -min_dist;
prev_filename[0] = '\0';
prev_line_num = 0;
- for (offset = 0; offset < core_text_sect->_raw_size; ++offset)
+ for (offset = 0; offset < core_text_sect->_raw_size; offset += MIN_INSN_SIZE)
{
vma = core_text_sect->vma + offset;
if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num)
&& strcmp (prev_filename, filename) == 0))
{
continue;
- } /* if */
+ }
++ltab.len;
prev_line_num = dummy.line_num;
if (offset - prev_offset < min_dist)
{
min_dist = offset - prev_offset;
- } /* if */
+ }
prev_offset = offset;
min_vma = MIN (vma, min_vma);
max_vma = MAX (vma, max_vma);
- } /* for */
+ }
DBG (AOUTDEBUG, printf ("[core_create_line_syms] min_dist=%lx\n", min_dist));
&& strcmp (prev->file->name, filename) == 0))
{
continue;
- } /* if */
+ }
/* make name pointer a malloc'ed string: */
- ltab.limit->name = strdup (ltab.limit->name);
+ ltab.limit->name = xstrdup (ltab.limit->name);
ltab.limit->file = source_file_lookup_path (filename);
ltab.limit->addr = core_text_sect->vma + offset;
&& strcmp (ltab.limit->name, "main") == 0)
{
discard_underscores = 0;
- } /* if */
+ }
DBG (AOUTDEBUG, printf ("[core_create_line_syms] %d %s 0x%lx\n",
ltab.len, ltab.limit->name,
ltab.limit->addr));
++ltab.limit;
- } /* for */
+ }
/* update sentinels: */
&& min_vma <= sentinel->end_addr)
{
sentinel->end_addr = min_vma - 1;
- } /* if */
+ }
sentinel = sym_lookup (&symtab, ~0);
if (strcmp (sentinel->name, "<hicore>") == 0 && max_vma >= sentinel->addr)
{
sentinel->addr = max_vma + 1;
- } /* if */
+ }
/* copy in function symbols: */
memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym));
"%s: somebody miscounted: ltab.len=%ld instead of %d\n",
whoami, (long) (ltab.limit - ltab.base), ltab.len);
done (1);
- } /* if */
+ }
/* finalize ltab and make it symbol table: */
}
while (sym->file == sym[-1].file &&
strcmp (sym->name, sym[-1].name) == 0);
- } /* if */
- } /* for */
-
-} /* core_create_line_syms */
+ }
+ }
-/*** end of core.c ***/
+}