Blame gprof/corefile.c

Packit bbfece
/* corefile.c
Packit bbfece
Packit bbfece
   Copyright (C) 1999-2018 Free Software Foundation, Inc.
Packit bbfece
Packit bbfece
   This file is part of GNU Binutils.
Packit bbfece
Packit bbfece
   This program is free software; you can redistribute it and/or modify
Packit bbfece
   it under the terms of the GNU General Public License as published by
Packit bbfece
   the Free Software Foundation; either version 3 of the License, or
Packit bbfece
   (at your option) any later version.
Packit bbfece
Packit bbfece
   This program is distributed in the hope that it will be useful,
Packit bbfece
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit bbfece
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit bbfece
   GNU General Public License for more details.
Packit bbfece
Packit bbfece
   You should have received a copy of the GNU General Public License
Packit bbfece
   along with this program; if not, write to the Free Software
Packit bbfece
   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
Packit bbfece
   02110-1301, USA.  */
Packit bbfece

Packit bbfece
#include "gprof.h"
Packit bbfece
#include "libiberty.h"
Packit bbfece
#include "filenames.h"
Packit bbfece
#include "search_list.h"
Packit bbfece
#include "source.h"
Packit bbfece
#include "symtab.h"
Packit bbfece
#include "hist.h"
Packit bbfece
#include "corefile.h"
Packit bbfece
#include "safe-ctype.h"
Packit bbfece
#include <limits.h>    /* For UINT_MAX.  */
Packit bbfece
Packit bbfece
bfd *core_bfd;
Packit bbfece
static int core_num_syms;
Packit bbfece
static asymbol **core_syms;
Packit bbfece
asection *core_text_sect;
Packit bbfece
void * core_text_space;
Packit bbfece
Packit bbfece
static int min_insn_size;
Packit bbfece
int offset_to_code;
Packit bbfece
Packit bbfece
/* For mapping symbols to specific .o files during file ordering.  */
Packit bbfece
struct function_map * symbol_map;
Packit bbfece
unsigned int symbol_map_count;
Packit bbfece
Packit bbfece
static void read_function_mappings (const char *);
Packit bbfece
static int core_sym_class (asymbol *);
Packit bbfece
static bfd_boolean get_src_info
Packit bbfece
  (bfd_vma, const char **, const char **, int *);
Packit bbfece
Packit bbfece
extern void i386_find_call  (Sym *, bfd_vma, bfd_vma);
Packit bbfece
extern void alpha_find_call (Sym *, bfd_vma, bfd_vma);
Packit bbfece
extern void vax_find_call   (Sym *, bfd_vma, bfd_vma);
Packit bbfece
extern void tahoe_find_call (Sym *, bfd_vma, bfd_vma);
Packit bbfece
extern void sparc_find_call (Sym *, bfd_vma, bfd_vma);
Packit bbfece
extern void mips_find_call  (Sym *, bfd_vma, bfd_vma);
Packit bbfece
extern void aarch64_find_call (Sym *, bfd_vma, bfd_vma);
Packit bbfece
Packit bbfece
static void
Packit bbfece
parse_error (const char *filename)
Packit bbfece
{
Packit bbfece
  fprintf (stderr, _("%s: unable to parse mapping file %s.\n"), whoami, filename);
Packit bbfece
  done (1);
Packit bbfece
}
Packit bbfece
Packit bbfece
/* Compare two function_map structs based on function name.
Packit bbfece
   We want to sort in ascending order.  */
Packit bbfece
Packit bbfece
static int
Packit bbfece
cmp_symbol_map (const void * l, const void * r)
Packit bbfece
{
Packit bbfece
  return strcmp (((struct function_map *) l)->function_name,
Packit bbfece
		 ((struct function_map *) r)->function_name);
Packit bbfece
}
Packit bbfece
Packit bbfece
#define BUFSIZE      (1024)
Packit bbfece
/* This is BUFSIZE - 1 as a string.  Suitable for use in fprintf/sscanf format strings.  */
Packit bbfece
#define STR_BUFSIZE  "1023"
Packit bbfece
Packit bbfece
static void
Packit bbfece
read_function_mappings (const char *filename)
Packit bbfece
{
Packit bbfece
  FILE * file = fopen (filename, "r");
Packit bbfece
  char dummy[BUFSIZE];
Packit bbfece
  int count = 0;
Packit bbfece
  unsigned int i;
Packit bbfece
Packit bbfece
  if (!file)
Packit bbfece
    {
Packit bbfece
      fprintf (stderr, _("%s: could not open %s.\n"), whoami, filename);
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* First parse the mapping file so we know how big we need to
Packit bbfece
     make our tables.  We also do some sanity checks at this
Packit bbfece
     time.  */
Packit bbfece
  while (!feof (file))
Packit bbfece
    {
Packit bbfece
      int matches;
Packit bbfece
Packit bbfece
      matches = fscanf (file, "%" STR_BUFSIZE "[^\n:]", dummy);
Packit bbfece
      if (!matches)
Packit bbfece
	parse_error (filename);
Packit bbfece
Packit bbfece
      /* Just skip messages about files with no symbols.  */
Packit bbfece
      if (!strncmp (dummy, "No symbols in ", 14))
Packit bbfece
	{
Packit bbfece
	  matches = fscanf (file, "\n");
Packit bbfece
	  if (matches == EOF)
Packit bbfece
	    parse_error (filename);
Packit bbfece
	  continue;
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Don't care what else is on this line at this point.  */
Packit bbfece
      matches = fscanf (file, "%" STR_BUFSIZE "[^\n]\n", dummy);
Packit bbfece
      if (!matches)
Packit bbfece
	parse_error (filename);
Packit bbfece
      count++;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* Now we know how big we need to make our table.  */
Packit bbfece
  symbol_map = ((struct function_map *)
Packit bbfece
		xmalloc (count * sizeof (struct function_map)));
Packit bbfece
Packit bbfece
  /* Rewind the input file so we can read it again.  */
Packit bbfece
  rewind (file);
Packit bbfece
Packit bbfece
  /* Read each entry and put it into the table.  */
Packit bbfece
  count = 0;
Packit bbfece
  while (!feof (file))
Packit bbfece
    {
Packit bbfece
      int matches;
Packit bbfece
      char *tmp;
Packit bbfece
Packit bbfece
      matches = fscanf (file, "%" STR_BUFSIZE "[^\n:]", dummy);
Packit bbfece
      if (!matches)
Packit bbfece
	parse_error (filename);
Packit bbfece
Packit bbfece
      /* Just skip messages about files with no symbols.  */
Packit bbfece
      if (!strncmp (dummy, "No symbols in ", 14))
Packit bbfece
	{
Packit bbfece
	  matches = fscanf (file, "\n");
Packit bbfece
	  if (matches == EOF)
Packit bbfece
	    parse_error (filename);
Packit bbfece
	  continue;
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* dummy has the filename, go ahead and copy it.  */
Packit bbfece
      symbol_map[count].file_name = (char *) xmalloc (strlen (dummy) + 1);
Packit bbfece
      strcpy (symbol_map[count].file_name, dummy);
Packit bbfece
Packit bbfece
      /* Now we need the function name.  */
Packit bbfece
      matches = fscanf (file, "%" STR_BUFSIZE "[^\n]\n", dummy);
Packit bbfece
      if (!matches)
Packit bbfece
	parse_error (filename);
Packit bbfece
      tmp = strrchr (dummy, ' ') + 1;
Packit bbfece
      symbol_map[count].function_name = (char *) xmalloc (strlen (tmp) + 1);
Packit bbfece
      strcpy (symbol_map[count].function_name, tmp);
Packit bbfece
      count++;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* Record the size of the map table for future reference.  */
Packit bbfece
  symbol_map_count = count;
Packit bbfece
Packit bbfece
  for (i = 0; i < symbol_map_count; ++i)
Packit bbfece
    if (i == 0
Packit bbfece
        || filename_cmp (symbol_map[i].file_name, symbol_map[i - 1].file_name))
Packit bbfece
      symbol_map[i].is_first = 1;
Packit bbfece
Packit bbfece
  qsort (symbol_map, symbol_map_count, sizeof (struct function_map), cmp_symbol_map);
Packit bbfece
Packit bbfece
  fclose (file);
Packit bbfece
}
Packit bbfece
Packit bbfece
void
Packit bbfece
core_init (const char * aout_name)
Packit bbfece
{
Packit bbfece
  int core_sym_bytes;
Packit bbfece
  asymbol *synthsyms;
Packit bbfece
  long synth_count;
Packit bbfece
Packit bbfece
  core_bfd = bfd_openr (aout_name, 0);
Packit bbfece
Packit bbfece
  if (!core_bfd)
Packit bbfece
    {
Packit bbfece
      perror (aout_name);
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  if (!bfd_check_format (core_bfd, bfd_object))
Packit bbfece
    {
Packit bbfece
      fprintf (stderr, _("%s: %s: not in executable format\n"), whoami, aout_name);
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* Get core's text section.  */
Packit bbfece
  core_text_sect = bfd_get_section_by_name (core_bfd, ".text");
Packit bbfece
  if (!core_text_sect)
Packit bbfece
    {
Packit bbfece
      core_text_sect = bfd_get_section_by_name (core_bfd, "$CODE$");
Packit bbfece
      if (!core_text_sect)
Packit bbfece
	{
Packit bbfece
	  fprintf (stderr, _("%s: can't find .text section in %s\n"),
Packit bbfece
		   whoami, aout_name);
Packit bbfece
	  done (1);
Packit bbfece
	}
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* Read core's symbol table.  */
Packit bbfece
Packit bbfece
  /* This will probably give us more than we need, but that's ok.  */
Packit bbfece
  core_sym_bytes = bfd_get_symtab_upper_bound (core_bfd);
Packit bbfece
  if (core_sym_bytes < 0)
Packit bbfece
    {
Packit bbfece
      fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
Packit bbfece
	       bfd_errmsg (bfd_get_error ()));
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  core_syms = (asymbol **) xmalloc (core_sym_bytes);
Packit bbfece
  core_num_syms = bfd_canonicalize_symtab (core_bfd, core_syms);
Packit bbfece
Packit bbfece
  if (core_num_syms < 0)
Packit bbfece
    {
Packit bbfece
      fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
Packit bbfece
	       bfd_errmsg (bfd_get_error ()));
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  synth_count = bfd_get_synthetic_symtab (core_bfd, core_num_syms, core_syms,
Packit bbfece
					  0, NULL, &synthsyms);
Packit bbfece
  if (synth_count > 0)
Packit bbfece
    {
Packit bbfece
      asymbol **symp;
Packit bbfece
      long new_size;
Packit bbfece
      long i;
Packit bbfece
Packit bbfece
      new_size = (core_num_syms + synth_count + 1) * sizeof (*core_syms);
Packit bbfece
      core_syms = (asymbol **) xrealloc (core_syms, new_size);
Packit bbfece
      symp = core_syms + core_num_syms;
Packit bbfece
      core_num_syms += synth_count;
Packit bbfece
      for (i = 0; i < synth_count; i++)
Packit bbfece
	*symp++ = synthsyms + i;
Packit bbfece
      *symp = 0;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  min_insn_size = 1;
Packit bbfece
  offset_to_code = 0;
Packit bbfece
Packit bbfece
  switch (bfd_get_arch (core_bfd))
Packit bbfece
    {
Packit bbfece
    case bfd_arch_vax:
Packit bbfece
    case bfd_arch_tahoe:
Packit bbfece
      offset_to_code = 2;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case bfd_arch_alpha:
Packit bbfece
      min_insn_size = 4;
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    default:
Packit bbfece
      break;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  if (function_mapping_file)
Packit bbfece
    read_function_mappings (function_mapping_file);
Packit bbfece
}
Packit bbfece
Packit bbfece
/* Read in the text space of an a.out file.  */
Packit bbfece
Packit bbfece
void
Packit bbfece
core_get_text_space (bfd *cbfd)
Packit bbfece
{
Packit bbfece
  core_text_space = malloc (bfd_get_section_size (core_text_sect));
Packit bbfece
Packit bbfece
  if (!core_text_space)
Packit bbfece
    {
Packit bbfece
      fprintf (stderr, _("%s: ran out room for %lu bytes of text space\n"),
Packit bbfece
	       whoami, (unsigned long) bfd_get_section_size (core_text_sect));
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  if (!bfd_get_section_contents (cbfd, core_text_sect, core_text_space,
Packit bbfece
				 0, bfd_get_section_size (core_text_sect)))
Packit bbfece
    {
Packit bbfece
      bfd_perror ("bfd_get_section_contents");
Packit bbfece
      free (core_text_space);
Packit bbfece
      core_text_space = 0;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  if (!core_text_space)
Packit bbfece
    fprintf (stderr, _("%s: can't do -c\n"), whoami);
Packit bbfece
}
Packit bbfece
Packit bbfece
Packit bbfece
void
Packit bbfece
find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
Packit bbfece
{
Packit bbfece
  if (core_text_space == 0)
Packit bbfece
    return;
Packit bbfece
Packit bbfece
  hist_clip_symbol_address (&p_lowpc, &p_highpc);
Packit bbfece
Packit bbfece
  switch (bfd_get_arch (core_bfd))
Packit bbfece
    {
Packit bbfece
    case bfd_arch_i386:
Packit bbfece
      i386_find_call (parent, p_lowpc, p_highpc);
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case bfd_arch_alpha:
Packit bbfece
      alpha_find_call (parent, p_lowpc, p_highpc);
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case bfd_arch_vax:
Packit bbfece
      vax_find_call (parent, p_lowpc, p_highpc);
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case bfd_arch_sparc:
Packit bbfece
      sparc_find_call (parent, p_lowpc, p_highpc);
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case bfd_arch_tahoe:
Packit bbfece
      tahoe_find_call (parent, p_lowpc, p_highpc);
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case bfd_arch_mips:
Packit bbfece
      mips_find_call (parent, p_lowpc, p_highpc);
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    case bfd_arch_aarch64:
Packit bbfece
      aarch64_find_call (parent, p_lowpc, p_highpc);
Packit bbfece
      break;
Packit bbfece
Packit bbfece
    default:
Packit bbfece
      fprintf (stderr, _("%s: -c not supported on architecture %s\n"),
Packit bbfece
	       whoami, bfd_printable_name(core_bfd));
Packit bbfece
Packit bbfece
      /* Don't give the error more than once.  */
Packit bbfece
      ignore_direct_calls = FALSE;
Packit bbfece
    }
Packit bbfece
}
Packit bbfece
Packit bbfece
/* Return class of symbol SYM.  The returned class can be any of:
Packit bbfece
	0   -> symbol is not interesting to us
Packit bbfece
	'T' -> symbol is a global name
Packit bbfece
	't' -> symbol is a local (static) name.  */
Packit bbfece
Packit bbfece
static int
Packit bbfece
core_sym_class (asymbol *sym)
Packit bbfece
{
Packit bbfece
  symbol_info syminfo;
Packit bbfece
  const char *name;
Packit bbfece
  char sym_prefix;
Packit bbfece
  int i;
Packit bbfece
Packit bbfece
  if (sym->section == NULL || (sym->flags & BSF_DEBUGGING) != 0)
Packit bbfece
    return 0;
Packit bbfece
Packit bbfece
  /* Must be a text symbol, and static text symbols
Packit bbfece
     don't qualify if ignore_static_funcs set.   */
Packit bbfece
  if (ignore_static_funcs && (sym->flags & BSF_LOCAL))
Packit bbfece
    {
Packit bbfece
      DBG (AOUTDEBUG, printf ("[core_sym_class] %s: not a function\n",
Packit bbfece
			      sym->name));
Packit bbfece
      return 0;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  bfd_get_symbol_info (core_bfd, sym, &syminfo);
Packit bbfece
  i = syminfo.type;
Packit bbfece
Packit bbfece
  if (i == 'T')
Packit bbfece
    return i;			/* It's a global symbol.  */
Packit bbfece
Packit bbfece
  if (i == 'W')
Packit bbfece
    /* Treat weak symbols as text symbols.  FIXME: a weak symbol may
Packit bbfece
       also be a data symbol.  */
Packit bbfece
    return 'T';
Packit bbfece
Packit bbfece
  if (i != 't')
Packit bbfece
    {
Packit bbfece
      /* Not a static text symbol.  */
Packit bbfece
      DBG (AOUTDEBUG, printf ("[core_sym_class] %s is of class %c\n",
Packit bbfece
			      sym->name, i));
Packit bbfece
      return 0;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* Do some more filtering on static function-names.  */
Packit bbfece
  if (ignore_static_funcs)
Packit bbfece
    return 0;
Packit bbfece
Packit bbfece
  /* Can't zero-length name or funny characters in name, where
Packit bbfece
     `funny' includes: `.' (.o file names) and `$' (Pascal labels).  */
Packit bbfece
  if (!sym->name || sym->name[0] == '\0')
Packit bbfece
    return 0;
Packit bbfece
Packit bbfece
  for (name = sym->name; *name; ++name)
Packit bbfece
    {
Packit bbfece
      if (*name == '$')
Packit bbfece
        return 0;
Packit bbfece
Packit bbfece
      while (*name == '.')
Packit bbfece
	{
Packit bbfece
	  /* Allow both nested subprograms (which end with ".NNN", where N is
Packit bbfece
	     a digit) and GCC cloned functions (which contain ".clone").
Packit bbfece
	     Allow for multiple iterations of both - apparently GCC can clone
Packit bbfece
	     clones and subprograms.  */
Packit bbfece
	  int digit_seen = 0;
Packit bbfece
#define CLONE_NAME	    ".clone."
Packit bbfece
#define CLONE_NAME_LEN	    strlen (CLONE_NAME)
Packit bbfece
#define CONSTPROP_NAME	    ".constprop."
Packit bbfece
#define CONSTPROP_NAME_LEN  strlen (CONSTPROP_NAME)
Packit bbfece
Packit bbfece
	  if (strlen (name) > CLONE_NAME_LEN
Packit bbfece
	      && strncmp (name, CLONE_NAME, CLONE_NAME_LEN) == 0)
Packit bbfece
	    name += CLONE_NAME_LEN - 1;
Packit bbfece
Packit bbfece
	  else if (strlen (name) > CONSTPROP_NAME_LEN
Packit bbfece
	      && strncmp (name, CONSTPROP_NAME, CONSTPROP_NAME_LEN) == 0)
Packit bbfece
	    name += CONSTPROP_NAME_LEN - 1;
Packit bbfece
Packit bbfece
	  for (name++; *name; name++)
Packit bbfece
	    if (digit_seen && *name == '.')
Packit bbfece
	      break;
Packit bbfece
	    else if (ISDIGIT (*name))
Packit bbfece
	      digit_seen = 1;
Packit bbfece
	    else
Packit bbfece
	      return 0;
Packit bbfece
	}
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* On systems where the C compiler adds an underscore to all
Packit bbfece
     names, static names without underscores seem usually to be
Packit bbfece
     labels in hand written assembler in the library.  We don't want
Packit bbfece
     these names.  This is certainly necessary on a Sparc running
Packit bbfece
     SunOS 4.1 (try profiling a program that does a lot of
Packit bbfece
     division). I don't know whether it has harmful side effects on
Packit bbfece
     other systems.  Perhaps it should be made configurable.  */
Packit bbfece
  sym_prefix = bfd_get_symbol_leading_char (core_bfd);
Packit bbfece
Packit bbfece
  if ((sym_prefix && sym_prefix != sym->name[0])
Packit bbfece
      /* GCC may add special symbols to help gdb figure out the file
Packit bbfece
	language.  We want to ignore these, since sometimes they mask
Packit bbfece
	the real function.  (dj@ctron)  */
Packit bbfece
      || !strncmp (sym->name, "__gnu_compiled", 14)
Packit bbfece
      || !strncmp (sym->name, "___gnu_compiled", 15))
Packit bbfece
    {
Packit bbfece
      return 0;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* If the object file supports marking of function symbols, then
Packit bbfece
     we can zap anything that doesn't have BSF_FUNCTION set.  */
Packit bbfece
  if (ignore_non_functions && (sym->flags & BSF_FUNCTION) == 0)
Packit bbfece
    return 0;
Packit bbfece
Packit bbfece
  return 't';			/* It's a static text symbol.  */
Packit bbfece
}
Packit bbfece
Packit bbfece
/* Get whatever source info we can get regarding address ADDR.  */
Packit bbfece
Packit bbfece
static bfd_boolean
Packit bbfece
get_src_info (bfd_vma addr, const char **filename, const char **name, int *line_num)
Packit bbfece
{
Packit bbfece
  const char *fname = 0, *func_name = 0;
Packit bbfece
  int l = 0;
Packit bbfece
Packit bbfece
  if (bfd_find_nearest_line (core_bfd, core_text_sect, core_syms,
Packit bbfece
			     addr - core_text_sect->vma,
Packit bbfece
			     &fname, &func_name, (unsigned int *) &l)
Packit bbfece
      && fname && func_name && l)
Packit bbfece
    {
Packit bbfece
      DBG (AOUTDEBUG, printf ("[get_src_info] 0x%lx -> %s:%d (%s)\n",
Packit bbfece
			      (unsigned long) addr, fname, l, func_name));
Packit bbfece
      *filename = fname;
Packit bbfece
      *name = func_name;
Packit bbfece
      *line_num = l;
Packit bbfece
      return TRUE;
Packit bbfece
    }
Packit bbfece
  else
Packit bbfece
    {
Packit bbfece
      DBG (AOUTDEBUG, printf ("[get_src_info] no info for 0x%lx (%s:%d,%s)\n",
Packit bbfece
			      (unsigned long) addr,
Packit bbfece
			      fname ? fname : "<unknown>", l,
Packit bbfece
			      func_name ? func_name : "<unknown>"));
Packit bbfece
      return FALSE;
Packit bbfece
    }
Packit bbfece
}
Packit bbfece
Packit bbfece
static char buf[BUFSIZE];
Packit bbfece
static char address[BUFSIZE];
Packit bbfece
static char name[BUFSIZE];
Packit bbfece
Packit bbfece
/* Return number of symbols in a symbol-table file.  */
Packit bbfece
Packit bbfece
static unsigned int
Packit bbfece
num_of_syms_in (FILE * f)
Packit bbfece
{
Packit bbfece
  char   type;
Packit bbfece
  unsigned int num = 0;
Packit bbfece
Packit bbfece
  while (!feof (f) && fgets (buf, BUFSIZE - 1, f))
Packit bbfece
    {
Packit bbfece
      if (sscanf (buf, "%" STR_BUFSIZE "s %c %" STR_BUFSIZE "s", address, &type, name) == 3)
Packit bbfece
        if (type == 't' || type == 'T')
Packit bbfece
	  {
Packit bbfece
	    /* PR 20499 - prevent integer overflow computing argument to xmalloc.  */	  
Packit bbfece
	    if (++num >= UINT_MAX / sizeof (Sym))
Packit bbfece
	      return -1U;
Packit bbfece
	  }
Packit bbfece
    }
Packit bbfece
Packit bbfece
  return num;
Packit bbfece
}
Packit bbfece
Packit bbfece
/* Read symbol table from a file.  */
Packit bbfece
Packit bbfece
void
Packit bbfece
core_create_syms_from (const char * sym_table_file)
Packit bbfece
{
Packit bbfece
  char type;
Packit bbfece
  bfd_vma min_vma = ~(bfd_vma) 0;
Packit bbfece
  bfd_vma max_vma = 0;
Packit bbfece
  FILE * f;
Packit bbfece
Packit bbfece
  f = fopen (sym_table_file, "r");
Packit bbfece
  if (!f)
Packit bbfece
    {
Packit bbfece
      fprintf (stderr, _("%s: could not open %s.\n"), whoami, sym_table_file);
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* Pass 1 - determine upper bound on number of function names.  */
Packit bbfece
  symtab.len = num_of_syms_in (f);
Packit bbfece
Packit bbfece
  if (symtab.len == 0)
Packit bbfece
    {
Packit bbfece
      fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, sym_table_file);
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
  else if (symtab.len == -1U)
Packit bbfece
    {
Packit bbfece
      fprintf (stderr, _("%s: file `%s' has too many symbols\n"),
Packit bbfece
	       whoami, sym_table_file);
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  symtab.base = (Sym *) xmalloc (symtab.len * sizeof (Sym));
Packit bbfece
Packit bbfece
  /* Pass 2 - create symbols.  */
Packit bbfece
  symtab.limit = symtab.base;
Packit bbfece
Packit bbfece
  if (fseek (f, 0, SEEK_SET) != 0)
Packit bbfece
    {
Packit bbfece
      perror (sym_table_file);
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  while (!feof (f) && fgets (buf, BUFSIZE - 1, f))
Packit bbfece
    {
Packit bbfece
      if (sscanf (buf, "%" STR_BUFSIZE "s %c %" STR_BUFSIZE "s", address, &type, name) != 3)
Packit bbfece
	continue;
Packit bbfece
      if (type != 't' && type != 'T')
Packit bbfece
	continue;
Packit bbfece
Packit bbfece
      sym_init (symtab.limit);
Packit bbfece
Packit bbfece
      sscanf (address, "%" BFD_VMA_FMT "x", &(symtab.limit->addr) );
Packit bbfece
Packit bbfece
      symtab.limit->name = (char *) xmalloc (strlen (name) + 1);
Packit bbfece
      strcpy ((char *) symtab.limit->name, name);
Packit bbfece
      symtab.limit->mapped = 0;
Packit bbfece
      symtab.limit->is_func = TRUE;
Packit bbfece
      symtab.limit->is_bb_head = TRUE;
Packit bbfece
      symtab.limit->is_static = (type == 't');
Packit bbfece
      min_vma = MIN (symtab.limit->addr, min_vma);
Packit bbfece
      max_vma = MAX (symtab.limit->addr, max_vma);
Packit bbfece
Packit bbfece
      ++symtab.limit;
Packit bbfece
    }
Packit bbfece
  fclose (f);
Packit bbfece
Packit bbfece
  symtab.len = symtab.limit - symtab.base;
Packit bbfece
  symtab_finalize (&symtab);
Packit bbfece
}
Packit bbfece
Packit bbfece
static int
Packit bbfece
search_mapped_symbol (const void * l, const void * r)
Packit bbfece
{
Packit bbfece
    return strcmp ((const char *) l, ((const struct function_map *) r)->function_name);
Packit bbfece
}
Packit bbfece
Packit bbfece
/* Read in symbol table from core.
Packit bbfece
   One symbol per function is entered.  */
Packit bbfece
Packit bbfece
void
Packit bbfece
core_create_function_syms (void)
Packit bbfece
{
Packit bbfece
  bfd_vma min_vma = ~ (bfd_vma) 0;
Packit bbfece
  bfd_vma max_vma = 0;
Packit bbfece
  int cxxclass;
Packit bbfece
  long i;
Packit bbfece
  struct function_map * found = NULL;
Packit bbfece
  int core_has_func_syms = 0;
Packit bbfece
Packit bbfece
  switch (core_bfd->xvec->flavour)
Packit bbfece
    {
Packit bbfece
    default:
Packit bbfece
      break;
Packit bbfece
    case bfd_target_coff_flavour:
Packit bbfece
    case bfd_target_ecoff_flavour:
Packit bbfece
    case bfd_target_xcoff_flavour:
Packit bbfece
    case bfd_target_elf_flavour:
Packit bbfece
    case bfd_target_nlm_flavour:
Packit bbfece
    case bfd_target_som_flavour:
Packit bbfece
      core_has_func_syms = 1;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* Pass 1 - determine upper bound on number of function names.  */
Packit bbfece
  symtab.len = 0;
Packit bbfece
Packit bbfece
  for (i = 0; i < core_num_syms; ++i)
Packit bbfece
    {
Packit bbfece
      if (!core_sym_class (core_syms[i]))
Packit bbfece
	continue;
Packit bbfece
Packit bbfece
      /* Don't create a symtab entry for a function that has
Packit bbfece
	 a mapping to a file, unless it's the first function
Packit bbfece
	 in the file.  */
Packit bbfece
      if (symbol_map_count != 0)
Packit bbfece
	{
Packit bbfece
	  /* Note: some systems (SunOS 5.8) crash if bsearch base argument
Packit bbfece
	     is NULL.  */
Packit bbfece
	  found = (struct function_map *) bsearch
Packit bbfece
	    (core_syms[i]->name, symbol_map, symbol_map_count,
Packit bbfece
	     sizeof (struct function_map), search_mapped_symbol);
Packit bbfece
	}
Packit bbfece
      if (found == NULL || found->is_first)
Packit bbfece
	++symtab.len;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  if (symtab.len == 0)
Packit bbfece
    {
Packit bbfece
      fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, a_out_name);
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  symtab.base = (Sym *) xmalloc (symtab.len * sizeof (Sym));
Packit bbfece
Packit bbfece
  /* Pass 2 - create symbols.  */
Packit bbfece
  symtab.limit = symtab.base;
Packit bbfece
Packit bbfece
  for (i = 0; i < core_num_syms; ++i)
Packit bbfece
    {
Packit bbfece
      asection *sym_sec;
Packit bbfece
Packit bbfece
      cxxclass = core_sym_class (core_syms[i]);
Packit bbfece
Packit bbfece
      if (!cxxclass)
Packit bbfece
	{
Packit bbfece
	  DBG (AOUTDEBUG,
Packit bbfece
	       printf ("[core_create_function_syms] rejecting: 0x%lx %s\n",
Packit bbfece
		       (unsigned long) core_syms[i]->value,
Packit bbfece
		       core_syms[i]->name));
Packit bbfece
	  continue;
Packit bbfece
	}
Packit bbfece
Packit bbfece
      if (symbol_map_count != 0)
Packit bbfece
	{
Packit bbfece
	  /* Note: some systems (SunOS 5.8) crash if bsearch base argument
Packit bbfece
	     is NULL.  */
Packit bbfece
	  found = (struct function_map *) bsearch
Packit bbfece
	    (core_syms[i]->name, symbol_map, symbol_map_count,
Packit bbfece
	     sizeof (struct function_map), search_mapped_symbol);
Packit bbfece
	}
Packit bbfece
      if (found && ! found->is_first)
Packit bbfece
	continue;
Packit bbfece
Packit bbfece
      sym_init (symtab.limit);
Packit bbfece
Packit bbfece
      /* Symbol offsets are always section-relative.  */
Packit bbfece
      sym_sec = core_syms[i]->section;
Packit bbfece
      symtab.limit->addr = core_syms[i]->value;
Packit bbfece
      if (sym_sec)
Packit bbfece
	symtab.limit->addr += bfd_get_section_vma (sym_sec->owner, sym_sec);
Packit bbfece
Packit bbfece
      if (found)
Packit bbfece
	{
Packit bbfece
	  symtab.limit->name = found->file_name;
Packit bbfece
	  symtab.limit->mapped = 1;
Packit bbfece
	}
Packit bbfece
      else
Packit bbfece
	{
Packit bbfece
	  symtab.limit->name = core_syms[i]->name;
Packit bbfece
	  symtab.limit->mapped = 0;
Packit bbfece
	}
Packit bbfece
Packit bbfece
      /* Lookup filename and line number, if we can.  */
Packit bbfece
      {
Packit bbfece
	const char * filename;
Packit bbfece
	const char * func_name;
Packit bbfece
Packit bbfece
	if (get_src_info (symtab.limit->addr, & filename, & func_name,
Packit bbfece
			  & symtab.limit->line_num))
Packit bbfece
	  {
Packit bbfece
	    symtab.limit->file = source_file_lookup_path (filename);
Packit bbfece
Packit bbfece
	    /* FIXME: Checking __osf__ here does not work with a cross
Packit bbfece
	       gprof.  */
Packit bbfece
#ifdef __osf__
Packit bbfece
	    /* Suppress symbols that are not function names.  This is
Packit bbfece
	       useful to suppress code-labels and aliases.
Packit bbfece
Packit bbfece
	       This is known to be useful under DEC's OSF/1.  Under SunOS 4.x,
Packit bbfece
	       labels do not appear in the symbol table info, so this isn't
Packit bbfece
	       necessary.  */
Packit bbfece
Packit bbfece
	    if (strcmp (symtab.limit->name, func_name) != 0)
Packit bbfece
	      {
Packit bbfece
		/* The symbol's address maps to a different name, so
Packit bbfece
		   it can't be a function-entry point.  This happens
Packit bbfece
		   for labels, for example.  */
Packit bbfece
		DBG (AOUTDEBUG,
Packit bbfece
		     printf ("[core_create_function_syms: rej %s (maps to %s)\n",
Packit bbfece
			     symtab.limit->name, func_name));
Packit bbfece
		continue;
Packit bbfece
	      }
Packit bbfece
#endif
Packit bbfece
	  }
Packit bbfece
      }
Packit bbfece
Packit bbfece
      symtab.limit->is_func = (!core_has_func_syms
Packit bbfece
			       || (core_syms[i]->flags & BSF_FUNCTION) != 0);
Packit bbfece
      symtab.limit->is_bb_head = TRUE;
Packit bbfece
Packit bbfece
      if (cxxclass == 't')
Packit bbfece
	symtab.limit->is_static = TRUE;
Packit bbfece
Packit bbfece
      /* Keep track of the minimum and maximum vma addresses used by all
Packit bbfece
	 symbols.  When computing the max_vma, use the ending address of the
Packit bbfece
	 section containing the symbol, if available.  */
Packit bbfece
      min_vma = MIN (symtab.limit->addr, min_vma);
Packit bbfece
      if (sym_sec)
Packit bbfece
	max_vma = MAX (bfd_get_section_vma (sym_sec->owner, sym_sec)
Packit bbfece
		       + bfd_section_size (sym_sec->owner, sym_sec) - 1,
Packit bbfece
		       max_vma);
Packit bbfece
      else
Packit bbfece
	max_vma = MAX (symtab.limit->addr, max_vma);
Packit bbfece
Packit bbfece
      DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n",
Packit bbfece
			      (long) (symtab.limit - symtab.base),
Packit bbfece
			      symtab.limit->name,
Packit bbfece
			      (unsigned long) symtab.limit->addr));
Packit bbfece
      ++symtab.limit;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  symtab.len = symtab.limit - symtab.base;
Packit bbfece
  symtab_finalize (&symtab);
Packit bbfece
}
Packit bbfece
Packit bbfece
/* Read in symbol table from core.
Packit bbfece
   One symbol per line of source code is entered.  */
Packit bbfece
Packit bbfece
void
Packit bbfece
core_create_line_syms (void)
Packit bbfece
{
Packit bbfece
  char *prev_name, *prev_filename;
Packit bbfece
  unsigned int prev_name_len, prev_filename_len;
Packit bbfece
  bfd_vma vma, min_vma = ~(bfd_vma) 0, max_vma = 0;
Packit bbfece
  Sym *prev, dummy, *sym;
Packit bbfece
  const char *filename;
Packit bbfece
  int prev_line_num;
Packit bbfece
  Sym_Table ltab;
Packit bbfece
  bfd_vma vma_high;
Packit bbfece
Packit bbfece
  /* Create symbols for functions as usual.  This is necessary in
Packit bbfece
     cases where parts of a program were not compiled with -g.  For
Packit bbfece
     those parts we still want to get info at the function level.  */
Packit bbfece
  core_create_function_syms ();
Packit bbfece
Packit bbfece
  /* Pass 1: count the number of symbols.  */
Packit bbfece
Packit bbfece
  /* To find all line information, walk through all possible
Packit bbfece
     text-space addresses (one by one!) and get the debugging
Packit bbfece
     info for each address.  When the debugging info changes,
Packit bbfece
     it is time to create a new symbol.
Packit bbfece
Packit bbfece
     Of course, this is rather slow and it would be better if
Packit bbfece
     BFD would provide an iterator for enumerating all line infos.  */
Packit bbfece
  prev_name_len = PATH_MAX;
Packit bbfece
  prev_filename_len = PATH_MAX;
Packit bbfece
  prev_name = (char *) xmalloc (prev_name_len);
Packit bbfece
  prev_filename = (char *) xmalloc (prev_filename_len);
Packit bbfece
  ltab.len = 0;
Packit bbfece
  prev_line_num = 0;
Packit bbfece
Packit bbfece
  vma_high = core_text_sect->vma + bfd_get_section_size (core_text_sect);
Packit bbfece
  for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size)
Packit bbfece
    {
Packit bbfece
      unsigned int len;
Packit bbfece
Packit bbfece
      if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num)
Packit bbfece
	  || (prev_line_num == dummy.line_num
Packit bbfece
	      && prev_name != NULL
Packit bbfece
	      && strcmp (prev_name, dummy.name) == 0
Packit bbfece
	      && filename_cmp (prev_filename, filename) == 0))
Packit bbfece
	continue;
Packit bbfece
Packit bbfece
      ++ltab.len;
Packit bbfece
      prev_line_num = dummy.line_num;
Packit bbfece
Packit bbfece
      len = strlen (dummy.name);
Packit bbfece
      if (len >= prev_name_len)
Packit bbfece
	{
Packit bbfece
	  prev_name_len = len + 1024;
Packit bbfece
	  free (prev_name);
Packit bbfece
	  prev_name = (char *) xmalloc (prev_name_len);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      strcpy (prev_name, dummy.name);
Packit bbfece
      len = strlen (filename);
Packit bbfece
Packit bbfece
      if (len >= prev_filename_len)
Packit bbfece
	{
Packit bbfece
	  prev_filename_len = len + 1024;
Packit bbfece
	  free (prev_filename);
Packit bbfece
	  prev_filename = (char *) xmalloc (prev_filename_len);
Packit bbfece
	}
Packit bbfece
Packit bbfece
      strcpy (prev_filename, filename);
Packit bbfece
Packit bbfece
      min_vma = MIN (vma, min_vma);
Packit bbfece
      max_vma = MAX (vma, max_vma);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  free (prev_name);
Packit bbfece
  free (prev_filename);
Packit bbfece
Packit bbfece
  /* Make room for function symbols, too.  */
Packit bbfece
  ltab.len += symtab.len;
Packit bbfece
  ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym));
Packit bbfece
  ltab.limit = ltab.base;
Packit bbfece
Packit bbfece
  /* Pass 2 - create symbols.  */
Packit bbfece
Packit bbfece
  /* We now set is_static as we go along, rather than by running
Packit bbfece
     through the symbol table at the end.
Packit bbfece
Packit bbfece
     The old way called symtab_finalize before the is_static pass,
Packit bbfece
     causing a problem since symtab_finalize uses is_static as part of
Packit bbfece
     its address conflict resolution algorithm.  Since global symbols
Packit bbfece
     were preferred over static symbols, and all line symbols were
Packit bbfece
     global at that point, static function names that conflicted with
Packit bbfece
     their own line numbers (static, but labeled as global) were
Packit bbfece
     rejected in favor of the line num.
Packit bbfece
Packit bbfece
     This was not the desired functionality.  We always want to keep
Packit bbfece
     our function symbols and discard any conflicting line symbols.
Packit bbfece
     Perhaps symtab_finalize should be modified to make this
Packit bbfece
     distinction as well, but the current fix works and the code is a
Packit bbfece
     lot cleaner now.  */
Packit bbfece
  prev = 0;
Packit bbfece
Packit bbfece
  for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size)
Packit bbfece
    {
Packit bbfece
      sym_init (ltab.limit);
Packit bbfece
Packit bbfece
      if (!get_src_info (vma, &filename, &ltab.limit->name, &ltab.limit->line_num)
Packit bbfece
	  || (prev && prev->line_num == ltab.limit->line_num
Packit bbfece
	      && strcmp (prev->name, ltab.limit->name) == 0
Packit bbfece
	      && filename_cmp (prev->file->name, filename) == 0))
Packit bbfece
	continue;
Packit bbfece
Packit bbfece
      /* Make name pointer a malloc'ed string.  */
Packit bbfece
      ltab.limit->name = xstrdup (ltab.limit->name);
Packit bbfece
      ltab.limit->file = source_file_lookup_path (filename);
Packit bbfece
Packit bbfece
      ltab.limit->addr = vma;
Packit bbfece
Packit bbfece
      /* Set is_static based on the enclosing function, using either:
Packit bbfece
	 1) the previous symbol, if it's from the same function, or
Packit bbfece
	 2) a symtab lookup.  */
Packit bbfece
      if (prev && ltab.limit->file == prev->file &&
Packit bbfece
	  strcmp (ltab.limit->name, prev->name) == 0)
Packit bbfece
	{
Packit bbfece
	  ltab.limit->is_static = prev->is_static;
Packit bbfece
	}
Packit bbfece
      else
Packit bbfece
	{
Packit bbfece
	  sym = sym_lookup(&symtab, ltab.limit->addr);
Packit bbfece
          if (sym)
Packit bbfece
	    ltab.limit->is_static = sym->is_static;
Packit bbfece
	}
Packit bbfece
Packit bbfece
      prev = ltab.limit;
Packit bbfece
Packit bbfece
      DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n",
Packit bbfece
			      (unsigned long) (ltab.limit - ltab.base),
Packit bbfece
			      ltab.limit->name,
Packit bbfece
			      (unsigned long) ltab.limit->addr));
Packit bbfece
      ++ltab.limit;
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* Copy in function symbols.  */
Packit bbfece
  memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym));
Packit bbfece
  ltab.limit += symtab.len;
Packit bbfece
Packit bbfece
  if ((unsigned int) (ltab.limit - ltab.base) != ltab.len)
Packit bbfece
    {
Packit bbfece
      fprintf (stderr,
Packit bbfece
	       _("%s: somebody miscounted: ltab.len=%d instead of %ld\n"),
Packit bbfece
	       whoami, ltab.len, (long) (ltab.limit - ltab.base));
Packit bbfece
      done (1);
Packit bbfece
    }
Packit bbfece
Packit bbfece
  /* Finalize ltab and make it symbol table.  */
Packit bbfece
  symtab_finalize (&ltab);
Packit bbfece
  free (symtab.base);
Packit bbfece
  symtab = ltab;
Packit bbfece
}