Blame elf/sprof.c

Packit Service 82fcde
/* Read and display shared object profiling data.
Packit Service 82fcde
   Copyright (C) 1997-2018 Free Software Foundation, Inc.
Packit Service 82fcde
   This file is part of the GNU C Library.
Packit Service 82fcde
   Contributed by Ulrich Drepper <drepper@cygnus.com>, 1997.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is free software; you can redistribute it and/or
Packit Service 82fcde
   modify it under the terms of the GNU Lesser General Public
Packit Service 82fcde
   License as published by the Free Software Foundation; either
Packit Service 82fcde
   version 2.1 of the License, or (at your option) any later version.
Packit Service 82fcde
Packit Service 82fcde
   The GNU C Library is distributed in the hope that it will be useful,
Packit Service 82fcde
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 82fcde
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 82fcde
   Lesser General Public License for more details.
Packit Service 82fcde
Packit Service 82fcde
   You should have received a copy of the GNU Lesser General Public
Packit Service 82fcde
   License along with the GNU C Library; if not, see
Packit Service 82fcde
   <http://www.gnu.org/licenses/>.  */
Packit Service 82fcde
Packit Service 82fcde
#include <argp.h>
Packit Service 82fcde
#include <dlfcn.h>
Packit Service 82fcde
#include <elf.h>
Packit Service 82fcde
#include <error.h>
Packit Service 82fcde
#include <fcntl.h>
Packit Service 82fcde
#include <inttypes.h>
Packit Service 82fcde
#include <libintl.h>
Packit Service 82fcde
#include <locale.h>
Packit Service 82fcde
#include <obstack.h>
Packit Service 82fcde
#include <search.h>
Packit Service 82fcde
#include <stdbool.h>
Packit Service 82fcde
#include <stdio.h>
Packit Service 82fcde
#include <stdlib.h>
Packit Service 82fcde
#include <string.h>
Packit Service 82fcde
#include <unistd.h>
Packit Service 82fcde
#include <stdint.h>
Packit Service 82fcde
#include <ldsodefs.h>
Packit Service 82fcde
#include <sys/gmon.h>
Packit Service 82fcde
#include <sys/gmon_out.h>
Packit Service 82fcde
#include <sys/mman.h>
Packit Service 82fcde
#include <sys/param.h>
Packit Service 82fcde
#include <sys/stat.h>
Packit Service 82fcde
Packit Service 82fcde
/* Get libc version number.  */
Packit Service 82fcde
#include "../version.h"
Packit Service 82fcde
Packit Service 82fcde
#define PACKAGE _libc_intl_domainname
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
#include <endian.h>
Packit Service 82fcde
#if BYTE_ORDER == BIG_ENDIAN
Packit Service 82fcde
# define byteorder ELFDATA2MSB
Packit Service 82fcde
# define byteorder_name "big-endian"
Packit Service 82fcde
#elif BYTE_ORDER == LITTLE_ENDIAN
Packit Service 82fcde
# define byteorder ELFDATA2LSB
Packit Service 82fcde
# define byteorder_name "little-endian"
Packit Service 82fcde
#else
Packit Service 82fcde
# error "Unknown BYTE_ORDER " BYTE_ORDER
Packit Service 82fcde
# define byteorder ELFDATANONE
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
#ifndef PATH_MAX
Packit Service 82fcde
# define PATH_MAX 1024
Packit Service 82fcde
#endif
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
extern int __profile_frequency (void);
Packit Service 82fcde
Packit Service 82fcde
/* Name and version of program.  */
Packit Service 82fcde
static void print_version (FILE *stream, struct argp_state *state);
Packit Service 82fcde
void (*argp_program_version_hook) (FILE *, struct argp_state *) = print_version;
Packit Service 82fcde
Packit Service 82fcde
#define OPT_TEST	1
Packit Service 82fcde
Packit Service 82fcde
/* Definitions of arguments for argp functions.  */
Packit Service 82fcde
static const struct argp_option options[] =
Packit Service 82fcde
{
Packit Service 82fcde
  { NULL, 0, NULL, 0, N_("Output selection:") },
Packit Service 82fcde
  { "call-pairs", 'c', NULL, 0,
Packit Service 82fcde
    N_("print list of count paths and their number of use") },
Packit Service 82fcde
  { "flat-profile", 'p', NULL, 0,
Packit Service 82fcde
    N_("generate flat profile with counts and ticks") },
Packit Service 82fcde
  { "graph", 'q', NULL, 0, N_("generate call graph") },
Packit Service 82fcde
Packit Service 82fcde
  { "test", OPT_TEST, NULL, OPTION_HIDDEN, NULL },
Packit Service 82fcde
  { NULL, 0, NULL, 0, NULL }
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/* Short description of program.  */
Packit Service 82fcde
static const char doc[] = N_("Read and display shared object profiling data.");
Packit Service 82fcde
//For bug reporting instructions, please see:\n
Packit Service 82fcde
//<http://www.gnu.org/software/libc/bugs.html>.\n");
Packit Service 82fcde
Packit Service 82fcde
/* Strings for arguments in help texts.  */
Packit Service 82fcde
static const char args_doc[] = N_("SHOBJ [PROFDATA]");
Packit Service 82fcde
Packit Service 82fcde
/* Prototype for option handler.  */
Packit Service 82fcde
static error_t parse_opt (int key, char *arg, struct argp_state *state);
Packit Service 82fcde
Packit Service 82fcde
/* Function to print some extra text in the help message.  */
Packit Service 82fcde
static char *more_help (int key, const char *text, void *input);
Packit Service 82fcde
Packit Service 82fcde
/* Data structure to communicate with argp functions.  */
Packit Service 82fcde
static struct argp argp =
Packit Service 82fcde
{
Packit Service 82fcde
  options, parse_opt, args_doc, doc, NULL, more_help
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Operation modes.  */
Packit Service 82fcde
static enum
Packit Service 82fcde
{
Packit Service 82fcde
  NONE = 0,
Packit Service 82fcde
  FLAT_MODE = 1 << 0,
Packit Service 82fcde
  CALL_GRAPH_MODE = 1 << 1,
Packit Service 82fcde
  CALL_PAIRS = 1 << 2,
Packit Service 82fcde
Packit Service 82fcde
  DEFAULT_MODE = FLAT_MODE | CALL_GRAPH_MODE
Packit Service 82fcde
} mode;
Packit Service 82fcde
Packit Service 82fcde
/* Nozero for testing.  */
Packit Service 82fcde
static int do_test;
Packit Service 82fcde
Packit Service 82fcde
/* Strcuture describing calls.  */
Packit Service 82fcde
struct here_fromstruct
Packit Service 82fcde
{
Packit Service 82fcde
  struct here_cg_arc_record volatile *here;
Packit Service 82fcde
  uint16_t link;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/* We define a special type to address the elements of the arc table.
Packit Service 82fcde
   This is basically the `gmon_cg_arc_record' format but it includes
Packit Service 82fcde
   the room for the tag and it uses real types.  */
Packit Service 82fcde
struct here_cg_arc_record
Packit Service 82fcde
{
Packit Service 82fcde
  uintptr_t from_pc;
Packit Service 82fcde
  uintptr_t self_pc;
Packit Service 82fcde
  uint32_t count;
Packit Service 82fcde
} __attribute__ ((packed));
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
struct known_symbol;
Packit Service 82fcde
struct arc_list
Packit Service 82fcde
{
Packit Service 82fcde
  size_t idx;
Packit Service 82fcde
  uintmax_t count;
Packit Service 82fcde
Packit Service 82fcde
  struct arc_list *next;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
static struct obstack ob_list;
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
struct known_symbol
Packit Service 82fcde
{
Packit Service 82fcde
  const char *name;
Packit Service 82fcde
  uintptr_t addr;
Packit Service 82fcde
  size_t size;
Packit Service 82fcde
  bool weak;
Packit Service 82fcde
  bool hidden;
Packit Service 82fcde
Packit Service 82fcde
  uintmax_t ticks;
Packit Service 82fcde
  uintmax_t calls;
Packit Service 82fcde
Packit Service 82fcde
  struct arc_list *froms;
Packit Service 82fcde
  struct arc_list *tos;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
struct shobj
Packit Service 82fcde
{
Packit Service 82fcde
  const char *name;		/* User-provided name.  */
Packit Service 82fcde
Packit Service 82fcde
  struct link_map *map;
Packit Service 82fcde
  const char *dynstrtab;	/* Dynamic string table of shared object.  */
Packit Service 82fcde
  const char *soname;		/* Soname of shared object.  */
Packit Service 82fcde
Packit Service 82fcde
  uintptr_t lowpc;
Packit Service 82fcde
  uintptr_t highpc;
Packit Service 82fcde
  unsigned long int kcountsize;
Packit Service 82fcde
  size_t expected_size;		/* Expected size of profiling file.  */
Packit Service 82fcde
  size_t tossize;
Packit Service 82fcde
  size_t fromssize;
Packit Service 82fcde
  size_t fromlimit;
Packit Service 82fcde
  unsigned int hashfraction;
Packit Service 82fcde
  int s_scale;
Packit Service 82fcde
Packit Service 82fcde
  void *symbol_map;
Packit Service 82fcde
  size_t symbol_mapsize;
Packit Service 82fcde
  const ElfW(Sym) *symtab;
Packit Service 82fcde
  size_t symtab_size;
Packit Service 82fcde
  const char *strtab;
Packit Service 82fcde
Packit Service 82fcde
  struct obstack ob_str;
Packit Service 82fcde
  struct obstack ob_sym;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
struct real_gmon_hist_hdr
Packit Service 82fcde
{
Packit Service 82fcde
  char *low_pc;
Packit Service 82fcde
  char *high_pc;
Packit Service 82fcde
  int32_t hist_size;
Packit Service 82fcde
  int32_t prof_rate;
Packit Service 82fcde
  char dimen[15];
Packit Service 82fcde
  char dimen_abbrev;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
struct profdata
Packit Service 82fcde
{
Packit Service 82fcde
  void *addr;
Packit Service 82fcde
  off_t size;
Packit Service 82fcde
Packit Service 82fcde
  char *hist;
Packit Service 82fcde
  struct real_gmon_hist_hdr *hist_hdr;
Packit Service 82fcde
  uint16_t *kcount;
Packit Service 82fcde
  uint32_t narcs;		/* Number of arcs in toset.  */
Packit Service 82fcde
  struct here_cg_arc_record *data;
Packit Service 82fcde
  uint16_t *tos;
Packit Service 82fcde
  struct here_fromstruct *froms;
Packit Service 82fcde
};
Packit Service 82fcde
Packit Service 82fcde
/* Search tree for symbols.  */
Packit Service 82fcde
static void *symroot;
Packit Service 82fcde
static struct known_symbol **sortsym;
Packit Service 82fcde
static size_t symidx;
Packit Service 82fcde
static uintmax_t total_ticks;
Packit Service 82fcde
Packit Service 82fcde
/* Prototypes for local functions.  */
Packit Service 82fcde
static struct shobj *load_shobj (const char *name);
Packit Service 82fcde
static void unload_shobj (struct shobj *shobj);
Packit Service 82fcde
static struct profdata *load_profdata (const char *name, struct shobj *shobj);
Packit Service 82fcde
static void unload_profdata (struct profdata *profdata);
Packit Service 82fcde
static void count_total_ticks (struct shobj *shobj, struct profdata *profdata);
Packit Service 82fcde
static void count_calls (struct shobj *shobj, struct profdata *profdata);
Packit Service 82fcde
static void read_symbols (struct shobj *shobj);
Packit Service 82fcde
static void add_arcs (struct profdata *profdata);
Packit Service 82fcde
static void generate_flat_profile (struct profdata *profdata);
Packit Service 82fcde
static void generate_call_graph (struct profdata *profdata);
Packit Service 82fcde
static void generate_call_pair_list (struct profdata *profdata);
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
int
Packit Service 82fcde
main (int argc, char *argv[])
Packit Service 82fcde
{
Packit Service 82fcde
  const char *shobj;
Packit Service 82fcde
  const char *profdata;
Packit Service 82fcde
  struct shobj *shobj_handle;
Packit Service 82fcde
  struct profdata *profdata_handle;
Packit Service 82fcde
  int remaining;
Packit Service 82fcde
Packit Service 82fcde
  setlocale (LC_ALL, "");
Packit Service 82fcde
Packit Service 82fcde
  /* Initialize the message catalog.  */
Packit Service 82fcde
  textdomain (_libc_intl_domainname);
Packit Service 82fcde
Packit Service 82fcde
  /* Parse and process arguments.  */
Packit Service 82fcde
  argp_parse (&argp, argc, argv, 0, &remaining, NULL);
Packit Service 82fcde
Packit Service 82fcde
  if (argc - remaining == 0 || argc - remaining > 2)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* We need exactly two non-option parameter.  */
Packit Service 82fcde
      argp_help (&argp, stdout, ARGP_HELP_SEE | ARGP_HELP_EXIT_ERR,
Packit Service 82fcde
		 program_invocation_short_name);
Packit Service 82fcde
      exit (1);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Get parameters.  */
Packit Service 82fcde
  shobj = argv[remaining];
Packit Service 82fcde
  if (argc - remaining == 2)
Packit Service 82fcde
    profdata = argv[remaining + 1];
Packit Service 82fcde
  else
Packit Service 82fcde
    /* No filename for the profiling data given.  We will determine it
Packit Service 82fcde
       from the soname of the shobj, later.  */
Packit Service 82fcde
    profdata = NULL;
Packit Service 82fcde
Packit Service 82fcde
  /* First see whether we can load the shared object.  */
Packit Service 82fcde
  shobj_handle = load_shobj (shobj);
Packit Service 82fcde
  if (shobj_handle == NULL)
Packit Service 82fcde
    exit (1);
Packit Service 82fcde
Packit Service 82fcde
  /* We can now determine the filename for the profiling data, if
Packit Service 82fcde
     nececessary.  */
Packit Service 82fcde
  if (profdata == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      char *newp;
Packit Service 82fcde
      const char *soname;
Packit Service 82fcde
      size_t soname_len;
Packit Service 82fcde
Packit Service 82fcde
      soname = shobj_handle->soname ?: basename (shobj);
Packit Service 82fcde
      soname_len = strlen (soname);
Packit Service 82fcde
      newp = (char *) alloca (soname_len + sizeof ".profile");
Packit Service 82fcde
      stpcpy (mempcpy (newp, soname, soname_len), ".profile");
Packit Service 82fcde
      profdata = newp;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Now see whether the profiling data file matches the given object.   */
Packit Service 82fcde
  profdata_handle = load_profdata (profdata, shobj_handle);
Packit Service 82fcde
  if (profdata_handle == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      unload_shobj (shobj_handle);
Packit Service 82fcde
Packit Service 82fcde
      exit (1);
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  read_symbols (shobj_handle);
Packit Service 82fcde
Packit Service 82fcde
  /* Count the ticks.  */
Packit Service 82fcde
  count_total_ticks (shobj_handle, profdata_handle);
Packit Service 82fcde
Packit Service 82fcde
  /* Count the calls.  */
Packit Service 82fcde
  count_calls (shobj_handle, profdata_handle);
Packit Service 82fcde
Packit Service 82fcde
  /* Add the arc information.  */
Packit Service 82fcde
  add_arcs (profdata_handle);
Packit Service 82fcde
Packit Service 82fcde
  /* If no mode is specified fall back to the default mode.  */
Packit Service 82fcde
  if (mode == NONE)
Packit Service 82fcde
    mode = DEFAULT_MODE;
Packit Service 82fcde
Packit Service 82fcde
  /* Do some work.  */
Packit Service 82fcde
  if (mode & FLAT_MODE)
Packit Service 82fcde
    generate_flat_profile (profdata_handle);
Packit Service 82fcde
Packit Service 82fcde
  if (mode & CALL_GRAPH_MODE)
Packit Service 82fcde
    generate_call_graph (profdata_handle);
Packit Service 82fcde
Packit Service 82fcde
  if (mode & CALL_PAIRS)
Packit Service 82fcde
    generate_call_pair_list (profdata_handle);
Packit Service 82fcde
Packit Service 82fcde
  /* Free the resources.  */
Packit Service 82fcde
  unload_shobj (shobj_handle);
Packit Service 82fcde
  unload_profdata (profdata_handle);
Packit Service 82fcde
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Handle program arguments.  */
Packit Service 82fcde
static error_t
Packit Service 82fcde
parse_opt (int key, char *arg, struct argp_state *state)
Packit Service 82fcde
{
Packit Service 82fcde
  switch (key)
Packit Service 82fcde
    {
Packit Service 82fcde
    case 'c':
Packit Service 82fcde
      mode |= CALL_PAIRS;
Packit Service 82fcde
      break;
Packit Service 82fcde
    case 'p':
Packit Service 82fcde
      mode |= FLAT_MODE;
Packit Service 82fcde
      break;
Packit Service 82fcde
    case 'q':
Packit Service 82fcde
      mode |= CALL_GRAPH_MODE;
Packit Service 82fcde
      break;
Packit Service 82fcde
    case OPT_TEST:
Packit Service 82fcde
      do_test = 1;
Packit Service 82fcde
      break;
Packit Service 82fcde
    default:
Packit Service 82fcde
      return ARGP_ERR_UNKNOWN;
Packit Service 82fcde
    }
Packit Service 82fcde
  return 0;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static char *
Packit Service 82fcde
more_help (int key, const char *text, void *input)
Packit Service 82fcde
{
Packit Service 82fcde
  char *tp = NULL;
Packit Service 82fcde
  switch (key)
Packit Service 82fcde
    {
Packit Service 82fcde
    case ARGP_KEY_HELP_EXTRA:
Packit Service 82fcde
      /* We print some extra information.  */
Packit Service 82fcde
      if (asprintf (&tp, gettext ("\
Packit Service 82fcde
For bug reporting instructions, please see:\n\
Packit Service 82fcde
%s.\n"), REPORT_BUGS_TO) < 0)
Packit Service 82fcde
	return NULL;
Packit Service 82fcde
      return tp;
Packit Service 82fcde
    default:
Packit Service 82fcde
      break;
Packit Service 82fcde
    }
Packit Service 82fcde
  return (char *) text;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Print the version information.  */
Packit Service 82fcde
static void
Packit Service 82fcde
print_version (FILE *stream, struct argp_state *state)
Packit Service 82fcde
{
Packit Service 82fcde
  fprintf (stream, "sprof %s%s\n", PKGVERSION, VERSION);
Packit Service 82fcde
  fprintf (stream, gettext ("\
Packit Service 82fcde
Copyright (C) %s Free Software Foundation, Inc.\n\
Packit Service 82fcde
This is free software; see the source for copying conditions.  There is NO\n\
Packit Service 82fcde
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\
Packit Service 82fcde
"),
Packit Service 82fcde
	   "2018");
Packit Service 82fcde
  fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper");
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* Note that we must not use `dlopen' etc.  The shobj object must not
Packit Service 82fcde
   be loaded for use.  */
Packit Service 82fcde
static struct shobj *
Packit Service 82fcde
load_shobj (const char *name)
Packit Service 82fcde
{
Packit Service 82fcde
  struct link_map *map = NULL;
Packit Service 82fcde
  struct shobj *result;
Packit Service 82fcde
  ElfW(Addr) mapstart = ~((ElfW(Addr)) 0);
Packit Service 82fcde
  ElfW(Addr) mapend = 0;
Packit Service 82fcde
  const ElfW(Phdr) *ph;
Packit Service 82fcde
  size_t textsize;
Packit Service 82fcde
  ElfW(Ehdr) *ehdr;
Packit Service 82fcde
  int fd;
Packit Service 82fcde
  ElfW(Shdr) *shdr;
Packit Service 82fcde
  size_t pagesize = getpagesize ();
Packit Service 82fcde
Packit Service 82fcde
  /* Since we use dlopen() we must be prepared to work around the sometimes
Packit Service 82fcde
     strange lookup rules for the shared objects.  If we have a file foo.so
Packit Service 82fcde
     in the current directory and the user specfies foo.so on the command
Packit Service 82fcde
     line (without specifying a directory) we should load the file in the
Packit Service 82fcde
     current directory even if a normal dlopen() call would read the other
Packit Service 82fcde
     file.  We do this by adding a directory portion to the name.  */
Packit Service 82fcde
  if (strchr (name, '/') == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      char *load_name = (char *) alloca (strlen (name) + 3);
Packit Service 82fcde
      stpcpy (stpcpy (load_name, "./"), name);
Packit Service 82fcde
Packit Service 82fcde
      map = (struct link_map *) dlopen (load_name, RTLD_LAZY | __RTLD_SPROF);
Packit Service 82fcde
    }
Packit Service 82fcde
  if (map == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      map = (struct link_map *) dlopen (name, RTLD_LAZY | __RTLD_SPROF);
Packit Service 82fcde
      if (map == NULL)
Packit Service 82fcde
	{
Packit Service 82fcde
	  error (0, errno, _("failed to load shared object `%s'"), name);
Packit Service 82fcde
	  return NULL;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Prepare the result.  */
Packit Service 82fcde
  result = (struct shobj *) calloc (1, sizeof (struct shobj));
Packit Service 82fcde
  if (result == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      error (0, errno, _("cannot create internal descriptor"));
Packit Service 82fcde
      dlclose (map);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
  result->name = name;
Packit Service 82fcde
  result->map = map;
Packit Service 82fcde
Packit Service 82fcde
  /* Compute the size of the sections which contain program code.
Packit Service 82fcde
     This must match the code in dl-profile.c (_dl_start_profile).  */
Packit Service 82fcde
  for (ph = map->l_phdr; ph < &map->l_phdr[map->l_phnum]; ++ph)
Packit Service 82fcde
    if (ph->p_type == PT_LOAD && (ph->p_flags & PF_X))
Packit Service 82fcde
      {
Packit Service 82fcde
	ElfW(Addr) start = (ph->p_vaddr & ~(pagesize - 1));
Packit Service 82fcde
	ElfW(Addr) end = ((ph->p_vaddr + ph->p_memsz + pagesize - 1)
Packit Service 82fcde
			  & ~(pagesize - 1));
Packit Service 82fcde
Packit Service 82fcde
	if (start < mapstart)
Packit Service 82fcde
	  mapstart = start;
Packit Service 82fcde
	if (end > mapend)
Packit Service 82fcde
	  mapend = end;
Packit Service 82fcde
      }
Packit Service 82fcde
Packit Service 82fcde
  result->lowpc = ROUNDDOWN ((uintptr_t) (mapstart + map->l_addr),
Packit Service 82fcde
			     HISTFRACTION * sizeof (HISTCOUNTER));
Packit Service 82fcde
  result->highpc = ROUNDUP ((uintptr_t) (mapend + map->l_addr),
Packit Service 82fcde
			    HISTFRACTION * sizeof (HISTCOUNTER));
Packit Service 82fcde
  if (do_test)
Packit Service 82fcde
    printf ("load addr: %0#*" PRIxPTR "\n"
Packit Service 82fcde
	    "lower bound PC: %0#*" PRIxPTR "\n"
Packit Service 82fcde
	    "upper bound PC: %0#*" PRIxPTR "\n",
Packit Service 82fcde
	    __ELF_NATIVE_CLASS == 32 ? 10 : 18, map->l_addr,
Packit Service 82fcde
	    __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->lowpc,
Packit Service 82fcde
	    __ELF_NATIVE_CLASS == 32 ? 10 : 18, result->highpc);
Packit Service 82fcde
Packit Service 82fcde
  textsize = result->highpc - result->lowpc;
Packit Service 82fcde
  result->kcountsize = textsize / HISTFRACTION;
Packit Service 82fcde
  result->hashfraction = HASHFRACTION;
Packit Service 82fcde
  if (do_test)
Packit Service 82fcde
    printf ("hashfraction = %d\ndivider = %Zu\n",
Packit Service 82fcde
	    result->hashfraction,
Packit Service 82fcde
	    result->hashfraction * sizeof (struct here_fromstruct));
Packit Service 82fcde
  result->tossize = textsize / HASHFRACTION;
Packit Service 82fcde
  result->fromlimit = textsize * ARCDENSITY / 100;
Packit Service 82fcde
  if (result->fromlimit < MINARCS)
Packit Service 82fcde
    result->fromlimit = MINARCS;
Packit Service 82fcde
  if (result->fromlimit > MAXARCS)
Packit Service 82fcde
    result->fromlimit = MAXARCS;
Packit Service 82fcde
  result->fromssize = result->fromlimit * sizeof (struct here_fromstruct);
Packit Service 82fcde
Packit Service 82fcde
  result->expected_size = (sizeof (struct gmon_hdr)
Packit Service 82fcde
			   + 4 + sizeof (struct gmon_hist_hdr)
Packit Service 82fcde
			   + result->kcountsize
Packit Service 82fcde
			   + 4 + 4
Packit Service 82fcde
			   + (result->fromssize
Packit Service 82fcde
			      * sizeof (struct here_cg_arc_record)));
Packit Service 82fcde
Packit Service 82fcde
  if (do_test)
Packit Service 82fcde
    printf ("expected size: %Zd\n", result->expected_size);
Packit Service 82fcde
Packit Service 82fcde
#define SCALE_1_TO_1	0x10000L
Packit Service 82fcde
Packit Service 82fcde
  if (result->kcountsize < result->highpc - result->lowpc)
Packit Service 82fcde
    {
Packit Service 82fcde
      size_t range = result->highpc - result->lowpc;
Packit Service 82fcde
      size_t quot = range / result->kcountsize;
Packit Service 82fcde
Packit Service 82fcde
      if (quot >= SCALE_1_TO_1)
Packit Service 82fcde
	result->s_scale = 1;
Packit Service 82fcde
      else if (quot >= SCALE_1_TO_1 / 256)
Packit Service 82fcde
	result->s_scale = SCALE_1_TO_1 / quot;
Packit Service 82fcde
      else if (range > ULONG_MAX / 256)
Packit Service 82fcde
	result->s_scale = ((SCALE_1_TO_1 * 256)
Packit Service 82fcde
			   / (range / (result->kcountsize / 256)));
Packit Service 82fcde
      else
Packit Service 82fcde
	result->s_scale = ((SCALE_1_TO_1 * 256)
Packit Service 82fcde
			   / ((range * 256) / result->kcountsize));
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    result->s_scale = SCALE_1_TO_1;
Packit Service 82fcde
Packit Service 82fcde
  if (do_test)
Packit Service 82fcde
    printf ("s_scale: %d\n", result->s_scale);
Packit Service 82fcde
Packit Service 82fcde
  /* Determine the dynamic string table.  */
Packit Service 82fcde
  if (map->l_info[DT_STRTAB] == NULL)
Packit Service 82fcde
    result->dynstrtab = NULL;
Packit Service 82fcde
  else
Packit Service 82fcde
    result->dynstrtab = (const char *) D_PTR (map, l_info[DT_STRTAB]);
Packit Service 82fcde
  if (do_test)
Packit Service 82fcde
    printf ("string table: %p\n", result->dynstrtab);
Packit Service 82fcde
Packit Service 82fcde
  /* Determine the soname.  */
Packit Service 82fcde
  if (map->l_info[DT_SONAME] == NULL)
Packit Service 82fcde
    result->soname = NULL;
Packit Service 82fcde
  else
Packit Service 82fcde
    result->soname = result->dynstrtab + map->l_info[DT_SONAME]->d_un.d_val;
Packit Service 82fcde
  if (do_test && result->soname != NULL)
Packit Service 82fcde
    printf ("soname: %s\n", result->soname);
Packit Service 82fcde
Packit Service 82fcde
  /* Now we have to load the symbol table.
Packit Service 82fcde
Packit Service 82fcde
     First load the section header table.  */
Packit Service 82fcde
  ehdr = (ElfW(Ehdr) *) map->l_map_start;
Packit Service 82fcde
Packit Service 82fcde
  /* Make sure we are on the right party.  */
Packit Service 82fcde
  if (ehdr->e_shentsize != sizeof (ElfW(Shdr)))
Packit Service 82fcde
    abort ();
Packit Service 82fcde
Packit Service 82fcde
  /* And we need the shared object file descriptor again.  */
Packit Service 82fcde
  fd = open (map->l_name, O_RDONLY);
Packit Service 82fcde
  if (fd == -1)
Packit Service 82fcde
    /* Dooh, this really shouldn't happen.  We know the file is available.  */
Packit Service 82fcde
    error (EXIT_FAILURE, errno, _("Reopening shared object `%s' failed"),
Packit Service 82fcde
	   map->l_name);
Packit Service 82fcde
Packit Service 82fcde
  /* Map the section header.  */
Packit Service 82fcde
  size_t size = ehdr->e_shnum * sizeof (ElfW(Shdr));
Packit Service 82fcde
  shdr = (ElfW(Shdr) *) alloca (size);
Packit Service 82fcde
  if (pread (fd, shdr, size, ehdr->e_shoff) != size)
Packit Service 82fcde
    error (EXIT_FAILURE, errno, _("reading of section headers failed"));
Packit Service 82fcde
Packit Service 82fcde
  /* Get the section header string table.  */
Packit Service 82fcde
  char *shstrtab = (char *) alloca (shdr[ehdr->e_shstrndx].sh_size);
Packit Service 82fcde
  if (pread (fd, shstrtab, shdr[ehdr->e_shstrndx].sh_size,
Packit Service 82fcde
	     shdr[ehdr->e_shstrndx].sh_offset)
Packit Service 82fcde
      != shdr[ehdr->e_shstrndx].sh_size)
Packit Service 82fcde
    error (EXIT_FAILURE, errno,
Packit Service 82fcde
	   _("reading of section header string table failed"));
Packit Service 82fcde
Packit Service 82fcde
  /* Search for the ".symtab" section.  */
Packit Service 82fcde
  ElfW(Shdr) *symtab_entry = NULL;
Packit Service 82fcde
  ElfW(Shdr) *debuglink_entry = NULL;
Packit Service 82fcde
  for (int idx = 0; idx < ehdr->e_shnum; ++idx)
Packit Service 82fcde
    if (shdr[idx].sh_type == SHT_SYMTAB
Packit Service 82fcde
	&& strcmp (shstrtab + shdr[idx].sh_name, ".symtab") == 0)
Packit Service 82fcde
      {
Packit Service 82fcde
	symtab_entry = &shdr[idx];
Packit Service 82fcde
	break;
Packit Service 82fcde
      }
Packit Service 82fcde
    else if (shdr[idx].sh_type == SHT_PROGBITS
Packit Service 82fcde
	     && strcmp (shstrtab + shdr[idx].sh_name, ".gnu_debuglink") == 0)
Packit Service 82fcde
      debuglink_entry = &shdr[idx];
Packit Service 82fcde
Packit Service 82fcde
  /* Get the file name of the debuginfo file if necessary.  */
Packit Service 82fcde
  int symfd = fd;
Packit Service 82fcde
  if (symtab_entry == NULL && debuglink_entry != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      size_t size = debuglink_entry->sh_size;
Packit Service 82fcde
      char *debuginfo_fname = (char *) alloca (size + 1);
Packit Service 82fcde
      debuginfo_fname[size] = '\0';
Packit Service 82fcde
      if (pread (fd, debuginfo_fname, size, debuglink_entry->sh_offset)
Packit Service 82fcde
	  != size)
Packit Service 82fcde
	{
Packit Service 82fcde
	  fprintf (stderr, _("*** Cannot read debuginfo file name: %m\n"));
Packit Service 82fcde
	  goto no_debuginfo;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      static const char procpath[] = "/proc/self/fd/%d";
Packit Service 82fcde
      char origprocname[sizeof (procpath) + sizeof (int) * 3];
Packit Service 82fcde
      snprintf (origprocname, sizeof (origprocname), procpath, fd);
Packit Service 82fcde
      char *origlink = (char *) alloca (PATH_MAX);
Packit Service 82fcde
      ssize_t n = readlink (origprocname, origlink, PATH_MAX - 1);
Packit Service 82fcde
      if (n == -1)
Packit Service 82fcde
	goto no_debuginfo;
Packit Service 82fcde
      origlink[n] = '\0';
Packit Service 82fcde
Packit Service 82fcde
      /* Try to find the actual file.  There are three places:
Packit Service 82fcde
	 1. the same directory the DSO is in
Packit Service 82fcde
	 2. in a subdir named .debug of the directory the DSO is in
Packit Service 82fcde
	 3. in /usr/lib/debug/PATH-OF-DSO
Packit Service 82fcde
      */
Packit Service 82fcde
      char *realname = canonicalize_file_name (origlink);
Packit Service 82fcde
      char *cp = NULL;
Packit Service 82fcde
      if (realname == NULL || (cp = strrchr (realname, '/')) == NULL)
Packit Service 82fcde
	error (EXIT_FAILURE, errno, _("cannot determine file name"));
Packit Service 82fcde
Packit Service 82fcde
      /* Leave the last slash in place.  */
Packit Service 82fcde
      *++cp = '\0';
Packit Service 82fcde
Packit Service 82fcde
      /* First add the debuginfo file name only.  */
Packit Service 82fcde
      static const char usrlibdebug[]= "/usr/lib/debug/";
Packit Service 82fcde
      char *workbuf = (char *) alloca (sizeof (usrlibdebug)
Packit Service 82fcde
				       + (cp - realname)
Packit Service 82fcde
				       + strlen (debuginfo_fname));
Packit Service 82fcde
      strcpy (stpcpy (workbuf, realname), debuginfo_fname);
Packit Service 82fcde
Packit Service 82fcde
      int fd2 = open (workbuf, O_RDONLY);
Packit Service 82fcde
      if (fd2 == -1)
Packit Service 82fcde
	{
Packit Service 82fcde
	  strcpy (stpcpy (stpcpy (workbuf, realname), ".debug/"),
Packit Service 82fcde
		  debuginfo_fname);
Packit Service 82fcde
	  fd2 = open (workbuf, O_RDONLY);
Packit Service 82fcde
	  if (fd2 == -1)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      strcpy (stpcpy (stpcpy (workbuf, usrlibdebug), realname),
Packit Service 82fcde
		      debuginfo_fname);
Packit Service 82fcde
	      fd2 = open (workbuf, O_RDONLY);
Packit Service 82fcde
	    }
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      if (fd2 != -1)
Packit Service 82fcde
	{
Packit Service 82fcde
	  ElfW(Ehdr) ehdr2;
Packit Service 82fcde
Packit Service 82fcde
	  /* Read the ELF header.  */
Packit Service 82fcde
	  if (pread (fd2, &ehdr2, sizeof (ehdr2), 0) != sizeof (ehdr2))
Packit Service 82fcde
	    error (EXIT_FAILURE, errno,
Packit Service 82fcde
		   _("reading of ELF header failed"));
Packit Service 82fcde
Packit Service 82fcde
	  /* Map the section header.  */
Packit Service 82fcde
	  size_t size = ehdr2.e_shnum * sizeof (ElfW(Shdr));
Packit Service 82fcde
	  ElfW(Shdr) *shdr2 = (ElfW(Shdr) *) alloca (size);
Packit Service 82fcde
	  if (pread (fd2, shdr2, size, ehdr2.e_shoff) != size)
Packit Service 82fcde
	    error (EXIT_FAILURE, errno,
Packit Service 82fcde
		   _("reading of section headers failed"));
Packit Service 82fcde
Packit Service 82fcde
	  /* Get the section header string table.  */
Packit Service 82fcde
	  shstrtab = (char *) alloca (shdr2[ehdr2.e_shstrndx].sh_size);
Packit Service 82fcde
	  if (pread (fd2, shstrtab, shdr2[ehdr2.e_shstrndx].sh_size,
Packit Service 82fcde
		     shdr2[ehdr2.e_shstrndx].sh_offset)
Packit Service 82fcde
	      != shdr2[ehdr2.e_shstrndx].sh_size)
Packit Service 82fcde
	    error (EXIT_FAILURE, errno,
Packit Service 82fcde
		   _("reading of section header string table failed"));
Packit Service 82fcde
Packit Service 82fcde
	  /* Search for the ".symtab" section.  */
Packit Service 82fcde
	  for (int idx = 0; idx < ehdr2.e_shnum; ++idx)
Packit Service 82fcde
	    if (shdr2[idx].sh_type == SHT_SYMTAB
Packit Service 82fcde
		&& strcmp (shstrtab + shdr2[idx].sh_name, ".symtab") == 0)
Packit Service 82fcde
	      {
Packit Service 82fcde
		symtab_entry = &shdr2[idx];
Packit Service 82fcde
		shdr = shdr2;
Packit Service 82fcde
		symfd = fd2;
Packit Service 82fcde
		break;
Packit Service 82fcde
	      }
Packit Service 82fcde
Packit Service 82fcde
	  if  (fd2 != symfd)
Packit Service 82fcde
	    close (fd2);
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
 no_debuginfo:
Packit Service 82fcde
  if (symtab_entry == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      fprintf (stderr, _("\
Packit Service 82fcde
*** The file `%s' is stripped: no detailed analysis possible\n"),
Packit Service 82fcde
	      name);
Packit Service 82fcde
      result->symtab = NULL;
Packit Service 82fcde
      result->strtab = NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      ElfW(Off) min_offset, max_offset;
Packit Service 82fcde
      ElfW(Shdr) *strtab_entry;
Packit Service 82fcde
Packit Service 82fcde
      strtab_entry = &shdr[symtab_entry->sh_link];
Packit Service 82fcde
Packit Service 82fcde
      /* Find the minimum and maximum offsets that include both the symbol
Packit Service 82fcde
	 table and the string table.  */
Packit Service 82fcde
      if (symtab_entry->sh_offset < strtab_entry->sh_offset)
Packit Service 82fcde
	{
Packit Service 82fcde
	  min_offset = symtab_entry->sh_offset & ~(pagesize - 1);
Packit Service 82fcde
	  max_offset = strtab_entry->sh_offset + strtab_entry->sh_size;
Packit Service 82fcde
	}
Packit Service 82fcde
      else
Packit Service 82fcde
	{
Packit Service 82fcde
	  min_offset = strtab_entry->sh_offset & ~(pagesize - 1);
Packit Service 82fcde
	  max_offset = symtab_entry->sh_offset + symtab_entry->sh_size;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      result->symbol_map = mmap (NULL, max_offset - min_offset,
Packit Service 82fcde
				 PROT_READ, MAP_SHARED|MAP_FILE, symfd,
Packit Service 82fcde
				 min_offset);
Packit Service 82fcde
      if (result->symbol_map == MAP_FAILED)
Packit Service 82fcde
	error (EXIT_FAILURE, errno, _("failed to load symbol data"));
Packit Service 82fcde
Packit Service 82fcde
      result->symtab
Packit Service 82fcde
	= (const ElfW(Sym) *) ((const char *) result->symbol_map
Packit Service 82fcde
			       + (symtab_entry->sh_offset - min_offset));
Packit Service 82fcde
      result->symtab_size = symtab_entry->sh_size;
Packit Service 82fcde
      result->strtab = ((const char *) result->symbol_map
Packit Service 82fcde
			+ (strtab_entry->sh_offset - min_offset));
Packit Service 82fcde
      result->symbol_mapsize = max_offset - min_offset;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Free the descriptor for the shared object.  */
Packit Service 82fcde
  close (fd);
Packit Service 82fcde
  if (symfd != fd)
Packit Service 82fcde
    close (symfd);
Packit Service 82fcde
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
unload_shobj (struct shobj *shobj)
Packit Service 82fcde
{
Packit Service 82fcde
  munmap (shobj->symbol_map, shobj->symbol_mapsize);
Packit Service 82fcde
  dlclose (shobj->map);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static struct profdata *
Packit Service 82fcde
load_profdata (const char *name, struct shobj *shobj)
Packit Service 82fcde
{
Packit Service 82fcde
  struct profdata *result;
Packit Service 82fcde
  int fd;
Packit Service 82fcde
  struct stat64 st;
Packit Service 82fcde
  void *addr;
Packit Service 82fcde
  uint32_t *narcsp;
Packit Service 82fcde
  size_t fromlimit;
Packit Service 82fcde
  struct here_cg_arc_record *data;
Packit Service 82fcde
  struct here_fromstruct *froms;
Packit Service 82fcde
  uint16_t *tos;
Packit Service 82fcde
  size_t fromidx;
Packit Service 82fcde
  size_t idx;
Packit Service 82fcde
Packit Service 82fcde
  fd = open (name, O_RDONLY);
Packit Service 82fcde
  if (fd == -1)
Packit Service 82fcde
    {
Packit Service 82fcde
      char *ext_name;
Packit Service 82fcde
Packit Service 82fcde
      if (errno != ENOENT || strchr (name, '/') != NULL)
Packit Service 82fcde
	/* The file exists but we are not allowed to read it or the
Packit Service 82fcde
	   file does not exist and the name includes a path
Packit Service 82fcde
	   specification..  */
Packit Service 82fcde
	return NULL;
Packit Service 82fcde
Packit Service 82fcde
      /* A file with the given name does not exist in the current
Packit Service 82fcde
	 directory, try it in the default location where the profiling
Packit Service 82fcde
	 files are created.  */
Packit Service 82fcde
      ext_name = (char *) alloca (strlen (name) + sizeof "/var/tmp/");
Packit Service 82fcde
      stpcpy (stpcpy (ext_name, "/var/tmp/"), name);
Packit Service 82fcde
      name = ext_name;
Packit Service 82fcde
Packit Service 82fcde
      fd = open (ext_name, O_RDONLY);
Packit Service 82fcde
      if (fd == -1)
Packit Service 82fcde
	{
Packit Service 82fcde
	  /* Even this file does not exist.  */
Packit Service 82fcde
	  error (0, errno, _("cannot load profiling data"));
Packit Service 82fcde
	  return NULL;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* We have found the file, now make sure it is the right one for the
Packit Service 82fcde
     data file.  */
Packit Service 82fcde
  if (fstat64 (fd, &st) < 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      error (0, errno, _("while stat'ing profiling data file"));
Packit Service 82fcde
      close (fd);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  if ((size_t) st.st_size != shobj->expected_size)
Packit Service 82fcde
    {
Packit Service 82fcde
      error (0, 0,
Packit Service 82fcde
	     _("profiling data file `%s' does not match shared object `%s'"),
Packit Service 82fcde
	     name, shobj->name);
Packit Service 82fcde
      close (fd);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* The data file is most probably the right one for our shared
Packit Service 82fcde
     object.  Map it now.  */
Packit Service 82fcde
  addr = mmap (NULL, st.st_size, PROT_READ, MAP_SHARED|MAP_FILE, fd, 0);
Packit Service 82fcde
  if (addr == MAP_FAILED)
Packit Service 82fcde
    {
Packit Service 82fcde
      error (0, errno, _("failed to mmap the profiling data file"));
Packit Service 82fcde
      close (fd);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* We don't need the file desriptor anymore.  */
Packit Service 82fcde
  if (close (fd) < 0)
Packit Service 82fcde
    {
Packit Service 82fcde
      error (0, errno, _("error while closing the profiling data file"));
Packit Service 82fcde
      munmap (addr, st.st_size);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Prepare the result.  */
Packit Service 82fcde
  result = (struct profdata *) calloc (1, sizeof (struct profdata));
Packit Service 82fcde
  if (result == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      error (0, errno, _("cannot create internal descriptor"));
Packit Service 82fcde
      munmap (addr, st.st_size);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* Store the address and size so that we can later free the resources.  */
Packit Service 82fcde
  result->addr = addr;
Packit Service 82fcde
  result->size = st.st_size;
Packit Service 82fcde
Packit Service 82fcde
  /* Pointer to data after the header.  */
Packit Service 82fcde
  result->hist = (char *) ((struct gmon_hdr *) addr + 1);
Packit Service 82fcde
  result->hist_hdr = (struct real_gmon_hist_hdr *) ((char *) result->hist
Packit Service 82fcde
						    + sizeof (uint32_t));
Packit Service 82fcde
  result->kcount = (uint16_t *) ((char *) result->hist + sizeof (uint32_t)
Packit Service 82fcde
				 + sizeof (struct real_gmon_hist_hdr));
Packit Service 82fcde
Packit Service 82fcde
  /* Compute pointer to array of the arc information.  */
Packit Service 82fcde
  narcsp = (uint32_t *) ((char *) result->kcount + shobj->kcountsize
Packit Service 82fcde
			 + sizeof (uint32_t));
Packit Service 82fcde
  result->narcs = *narcsp;
Packit Service 82fcde
  result->data = (struct here_cg_arc_record *) ((char *) narcsp
Packit Service 82fcde
						+ sizeof (uint32_t));
Packit Service 82fcde
Packit Service 82fcde
  /* Create the gmon_hdr we expect or write.  */
Packit Service 82fcde
  struct real_gmon_hdr
Packit Service 82fcde
  {
Packit Service 82fcde
    char cookie[4];
Packit Service 82fcde
    int32_t version;
Packit Service 82fcde
    char spare[3 * 4];
Packit Service 82fcde
  } gmon_hdr;
Packit Service 82fcde
  if (sizeof (gmon_hdr) != sizeof (struct gmon_hdr)
Packit Service 82fcde
      || (offsetof (struct real_gmon_hdr, cookie)
Packit Service 82fcde
	  != offsetof (struct gmon_hdr, cookie))
Packit Service 82fcde
      || (offsetof (struct real_gmon_hdr, version)
Packit Service 82fcde
	  != offsetof (struct gmon_hdr, version)))
Packit Service 82fcde
    abort ();
Packit Service 82fcde
Packit Service 82fcde
  memcpy (&gmon_hdr.cookie[0], GMON_MAGIC, sizeof (gmon_hdr.cookie));
Packit Service 82fcde
  gmon_hdr.version = GMON_SHOBJ_VERSION;
Packit Service 82fcde
  memset (gmon_hdr.spare, '\0', sizeof (gmon_hdr.spare));
Packit Service 82fcde
Packit Service 82fcde
  /* Create the hist_hdr we expect or write.  */
Packit Service 82fcde
  struct real_gmon_hist_hdr hist_hdr;
Packit Service 82fcde
  if (sizeof (hist_hdr) != sizeof (struct gmon_hist_hdr)
Packit Service 82fcde
      || (offsetof (struct real_gmon_hist_hdr, low_pc)
Packit Service 82fcde
	  != offsetof (struct gmon_hist_hdr, low_pc))
Packit Service 82fcde
      || (offsetof (struct real_gmon_hist_hdr, high_pc)
Packit Service 82fcde
	  != offsetof (struct gmon_hist_hdr, high_pc))
Packit Service 82fcde
      || (offsetof (struct real_gmon_hist_hdr, hist_size)
Packit Service 82fcde
	  != offsetof (struct gmon_hist_hdr, hist_size))
Packit Service 82fcde
      || (offsetof (struct real_gmon_hist_hdr, prof_rate)
Packit Service 82fcde
	  != offsetof (struct gmon_hist_hdr, prof_rate))
Packit Service 82fcde
      || (offsetof (struct real_gmon_hist_hdr, dimen)
Packit Service 82fcde
	  != offsetof (struct gmon_hist_hdr, dimen))
Packit Service 82fcde
      || (offsetof (struct real_gmon_hist_hdr, dimen_abbrev)
Packit Service 82fcde
	  != offsetof (struct gmon_hist_hdr, dimen_abbrev)))
Packit Service 82fcde
    abort ();
Packit Service 82fcde
Packit Service 82fcde
  hist_hdr.low_pc = (char *) shobj->lowpc - shobj->map->l_addr;
Packit Service 82fcde
  hist_hdr.high_pc = (char *) shobj->highpc - shobj->map->l_addr;
Packit Service 82fcde
  if (do_test)
Packit Service 82fcde
    printf ("low_pc = %p\nhigh_pc = %p\n", hist_hdr.low_pc, hist_hdr.high_pc);
Packit Service 82fcde
  hist_hdr.hist_size = shobj->kcountsize / sizeof (HISTCOUNTER);
Packit Service 82fcde
  hist_hdr.prof_rate = __profile_frequency ();
Packit Service 82fcde
  strncpy (hist_hdr.dimen, "seconds", sizeof (hist_hdr.dimen));
Packit Service 82fcde
  hist_hdr.dimen_abbrev = 's';
Packit Service 82fcde
Packit Service 82fcde
  /* Test whether the header of the profiling data is ok.  */
Packit Service 82fcde
  if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0
Packit Service 82fcde
      || *(uint32_t *) result->hist != GMON_TAG_TIME_HIST
Packit Service 82fcde
      || memcmp (result->hist_hdr, &hist_hdr,
Packit Service 82fcde
		 sizeof (struct gmon_hist_hdr)) != 0
Packit Service 82fcde
      || narcsp[-1] != GMON_TAG_CG_ARC)
Packit Service 82fcde
    {
Packit Service 82fcde
      error (0, 0, _("`%s' is no correct profile data file for `%s'"),
Packit Service 82fcde
	     name, shobj->name);
Packit Service 82fcde
      if (do_test)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if (memcmp (addr, &gmon_hdr, sizeof (struct gmon_hdr)) != 0)
Packit Service 82fcde
	    puts ("gmon_hdr differs");
Packit Service 82fcde
	  if (*(uint32_t *) result->hist != GMON_TAG_TIME_HIST)
Packit Service 82fcde
	    puts ("result->hist differs");
Packit Service 82fcde
	  if (memcmp (result->hist_hdr, &hist_hdr,
Packit Service 82fcde
		      sizeof (struct gmon_hist_hdr)) != 0)
Packit Service 82fcde
	    puts ("hist_hdr differs");
Packit Service 82fcde
	  if (narcsp[-1] != GMON_TAG_CG_ARC)
Packit Service 82fcde
	    puts ("narcsp[-1] differs");
Packit Service 82fcde
	}
Packit Service 82fcde
      free (result);
Packit Service 82fcde
      munmap (addr, st.st_size);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  /* We are pretty sure now that this is a correct input file.  Set up
Packit Service 82fcde
     the remaining information in the result structure and return.  */
Packit Service 82fcde
  result->tos = (uint16_t *) calloc (shobj->tossize + shobj->fromssize, 1);
Packit Service 82fcde
  if (result->tos == NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      error (0, errno, _("cannot create internal descriptor"));
Packit Service 82fcde
      munmap (addr, st.st_size);
Packit Service 82fcde
      free (result);
Packit Service 82fcde
      return NULL;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  result->froms = (struct here_fromstruct *) ((char *) result->tos
Packit Service 82fcde
					      + shobj->tossize);
Packit Service 82fcde
  fromidx = 0;
Packit Service 82fcde
Packit Service 82fcde
  /* Now we have to process all the arc count entries.  */
Packit Service 82fcde
  fromlimit = shobj->fromlimit;
Packit Service 82fcde
  data = result->data;
Packit Service 82fcde
  froms = result->froms;
Packit Service 82fcde
  tos = result->tos;
Packit Service 82fcde
  for (idx = 0; idx < MIN (*narcsp, fromlimit); ++idx)
Packit Service 82fcde
    {
Packit Service 82fcde
      size_t to_index;
Packit Service 82fcde
      size_t newfromidx;
Packit Service 82fcde
      to_index = (data[idx].self_pc / (shobj->hashfraction * sizeof (*tos)));
Packit Service 82fcde
      newfromidx = fromidx++;
Packit Service 82fcde
      froms[newfromidx].here = &data[idx];
Packit Service 82fcde
      froms[newfromidx].link = tos[to_index];
Packit Service 82fcde
      tos[to_index] = newfromidx;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return result;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
unload_profdata (struct profdata *profdata)
Packit Service 82fcde
{
Packit Service 82fcde
  free (profdata->tos);
Packit Service 82fcde
  munmap (profdata->addr, profdata->size);
Packit Service 82fcde
  free (profdata);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
count_total_ticks (struct shobj *shobj, struct profdata *profdata)
Packit Service 82fcde
{
Packit Service 82fcde
  volatile uint16_t *kcount = profdata->kcount;
Packit Service 82fcde
  size_t maxkidx = shobj->kcountsize;
Packit Service 82fcde
  size_t factor = 2 * (65536 / shobj->s_scale);
Packit Service 82fcde
  size_t kidx = 0;
Packit Service 82fcde
  size_t sidx = 0;
Packit Service 82fcde
Packit Service 82fcde
  while (sidx < symidx)
Packit Service 82fcde
    {
Packit Service 82fcde
      uintptr_t start = sortsym[sidx]->addr;
Packit Service 82fcde
      uintptr_t end = start + sortsym[sidx]->size;
Packit Service 82fcde
Packit Service 82fcde
      while (kidx < maxkidx && factor * kidx < start)
Packit Service 82fcde
	++kidx;
Packit Service 82fcde
      if (kidx == maxkidx)
Packit Service 82fcde
	break;
Packit Service 82fcde
Packit Service 82fcde
      while (kidx < maxkidx && factor * kidx < end)
Packit Service 82fcde
	sortsym[sidx]->ticks += kcount[kidx++];
Packit Service 82fcde
      if (kidx == maxkidx)
Packit Service 82fcde
	break;
Packit Service 82fcde
Packit Service 82fcde
      total_ticks += sortsym[sidx++]->ticks;
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static size_t
Packit Service 82fcde
find_symbol (uintptr_t addr)
Packit Service 82fcde
{
Packit Service 82fcde
  size_t sidx = 0;
Packit Service 82fcde
Packit Service 82fcde
  while (sidx < symidx)
Packit Service 82fcde
    {
Packit Service 82fcde
      uintptr_t start = sortsym[sidx]->addr;
Packit Service 82fcde
      uintptr_t end = start + sortsym[sidx]->size;
Packit Service 82fcde
Packit Service 82fcde
      if (addr >= start && addr < end)
Packit Service 82fcde
	return sidx;
Packit Service 82fcde
Packit Service 82fcde
      if (addr < start)
Packit Service 82fcde
	break;
Packit Service 82fcde
Packit Service 82fcde
      ++sidx;
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  return (size_t) -1l;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
count_calls (struct shobj *shobj, struct profdata *profdata)
Packit Service 82fcde
{
Packit Service 82fcde
  struct here_cg_arc_record *data = profdata->data;
Packit Service 82fcde
  uint32_t narcs = profdata->narcs;
Packit Service 82fcde
  uint32_t cnt;
Packit Service 82fcde
Packit Service 82fcde
  for (cnt = 0; cnt < narcs; ++cnt)
Packit Service 82fcde
    {
Packit Service 82fcde
      uintptr_t here = data[cnt].self_pc;
Packit Service 82fcde
      size_t symbol_idx;
Packit Service 82fcde
Packit Service 82fcde
      /* Find the symbol for this address.  */
Packit Service 82fcde
      symbol_idx = find_symbol (here);
Packit Service 82fcde
      if (symbol_idx != (size_t) -1l)
Packit Service 82fcde
	sortsym[symbol_idx]->calls += data[cnt].count;
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
symorder (const void *o1, const void *o2)
Packit Service 82fcde
{
Packit Service 82fcde
  const struct known_symbol *p1 = (const struct known_symbol *) o1;
Packit Service 82fcde
  const struct known_symbol *p2 = (const struct known_symbol *) o2;
Packit Service 82fcde
Packit Service 82fcde
  return p1->addr - p2->addr;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
printsym (const void *node, VISIT value, int level)
Packit Service 82fcde
{
Packit Service 82fcde
  if (value == leaf || value == postorder)
Packit Service 82fcde
    sortsym[symidx++] = *(struct known_symbol **) node;
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
read_symbols (struct shobj *shobj)
Packit Service 82fcde
{
Packit Service 82fcde
  int n = 0;
Packit Service 82fcde
Packit Service 82fcde
  /* Initialize the obstacks.  */
Packit Service 82fcde
#define obstack_chunk_alloc malloc
Packit Service 82fcde
#define obstack_chunk_free free
Packit Service 82fcde
  obstack_init (&shobj->ob_str);
Packit Service 82fcde
  obstack_init (&shobj->ob_sym);
Packit Service 82fcde
  obstack_init (&ob_list);
Packit Service 82fcde
Packit Service 82fcde
  /* Process the symbols.  */
Packit Service 82fcde
  if (shobj->symtab != NULL)
Packit Service 82fcde
    {
Packit Service 82fcde
      const ElfW(Sym) *sym = shobj->symtab;
Packit Service 82fcde
      const ElfW(Sym) *sym_end
Packit Service 82fcde
	= (const ElfW(Sym) *) ((const char *) sym + shobj->symtab_size);
Packit Service 82fcde
      for (; sym < sym_end; sym++)
Packit Service 82fcde
	if ((ELFW(ST_TYPE) (sym->st_info) == STT_FUNC
Packit Service 82fcde
	     || ELFW(ST_TYPE) (sym->st_info) == STT_NOTYPE)
Packit Service 82fcde
	    && sym->st_size != 0)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    struct known_symbol **existp;
Packit Service 82fcde
	    struct known_symbol *newsym
Packit Service 82fcde
	      = (struct known_symbol *) obstack_alloc (&shobj->ob_sym,
Packit Service 82fcde
						       sizeof (*newsym));
Packit Service 82fcde
	    if (newsym == NULL)
Packit Service 82fcde
	      error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
Packit Service 82fcde
Packit Service 82fcde
	    newsym->name = &shobj->strtab[sym->st_name];
Packit Service 82fcde
	    newsym->addr = sym->st_value;
Packit Service 82fcde
	    newsym->size = sym->st_size;
Packit Service 82fcde
	    newsym->weak = ELFW(ST_BIND) (sym->st_info) == STB_WEAK;
Packit Service 82fcde
	    newsym->hidden = (ELFW(ST_VISIBILITY) (sym->st_other)
Packit Service 82fcde
			      != STV_DEFAULT);
Packit Service 82fcde
	    newsym->ticks = 0;
Packit Service 82fcde
	    newsym->calls = 0;
Packit Service 82fcde
Packit Service 82fcde
	    existp = tfind (newsym, &symroot, symorder);
Packit Service 82fcde
	    if (existp == NULL)
Packit Service 82fcde
	      {
Packit Service 82fcde
		/* New function.  */
Packit Service 82fcde
		tsearch (newsym, &symroot, symorder);
Packit Service 82fcde
		++n;
Packit Service 82fcde
	      }
Packit Service 82fcde
	    else
Packit Service 82fcde
	      {
Packit Service 82fcde
		/* The function is already defined.  See whether we have
Packit Service 82fcde
		   a better name here.  */
Packit Service 82fcde
		if (((*existp)->hidden && !newsym->hidden)
Packit Service 82fcde
		    || ((*existp)->name[0] == '_' && newsym->name[0] != '_')
Packit Service 82fcde
		    || ((*existp)->name[0] != '_' && newsym->name[0] != '_'
Packit Service 82fcde
			&& ((*existp)->weak && !newsym->weak)))
Packit Service 82fcde
		  *existp = newsym;
Packit Service 82fcde
		else
Packit Service 82fcde
		  /* We don't need the allocated memory.  */
Packit Service 82fcde
		  obstack_free (&shobj->ob_sym, newsym);
Packit Service 82fcde
	      }
Packit Service 82fcde
	  }
Packit Service 82fcde
    }
Packit Service 82fcde
  else
Packit Service 82fcde
    {
Packit Service 82fcde
      /* Blarg, the binary is stripped.  We have to rely on the
Packit Service 82fcde
	 information contained in the dynamic section of the object.  */
Packit Service 82fcde
      const ElfW(Sym) *symtab = (ElfW(Sym) *) D_PTR (shobj->map,
Packit Service 82fcde
						     l_info[DT_SYMTAB]);
Packit Service 82fcde
      const char *strtab = (const char *) D_PTR (shobj->map,
Packit Service 82fcde
						 l_info[DT_STRTAB]);
Packit Service 82fcde
Packit Service 82fcde
      /* We assume that the string table follows the symbol table,
Packit Service 82fcde
	 because there is no way in ELF to know the size of the
Packit Service 82fcde
	 dynamic symbol table without looking at the section headers.  */
Packit Service 82fcde
      while ((void *) symtab < (void *) strtab)
Packit Service 82fcde
	{
Packit Service 82fcde
	  if ((ELFW(ST_TYPE)(symtab->st_info) == STT_FUNC
Packit Service 82fcde
	       || ELFW(ST_TYPE)(symtab->st_info) == STT_NOTYPE)
Packit Service 82fcde
	      && symtab->st_size != 0)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      struct known_symbol *newsym;
Packit Service 82fcde
	      struct known_symbol **existp;
Packit Service 82fcde
Packit Service 82fcde
	      newsym =
Packit Service 82fcde
		(struct known_symbol *) obstack_alloc (&shobj->ob_sym,
Packit Service 82fcde
						       sizeof (*newsym));
Packit Service 82fcde
	      if (newsym == NULL)
Packit Service 82fcde
		error (EXIT_FAILURE, errno, _("cannot allocate symbol data"));
Packit Service 82fcde
Packit Service 82fcde
	      newsym->name = &strtab[symtab->st_name];
Packit Service 82fcde
	      newsym->addr = symtab->st_value;
Packit Service 82fcde
	      newsym->size = symtab->st_size;
Packit Service 82fcde
	      newsym->weak = ELFW(ST_BIND) (symtab->st_info) == STB_WEAK;
Packit Service 82fcde
	      newsym->hidden = (ELFW(ST_VISIBILITY) (symtab->st_other)
Packit Service 82fcde
				!= STV_DEFAULT);
Packit Service 82fcde
	      newsym->ticks = 0;
Packit Service 82fcde
	      newsym->froms = NULL;
Packit Service 82fcde
	      newsym->tos = NULL;
Packit Service 82fcde
Packit Service 82fcde
	      existp = tfind (newsym, &symroot, symorder);
Packit Service 82fcde
	      if (existp == NULL)
Packit Service 82fcde
		{
Packit Service 82fcde
		  /* New function.  */
Packit Service 82fcde
		  tsearch (newsym, &symroot, symorder);
Packit Service 82fcde
		  ++n;
Packit Service 82fcde
		}
Packit Service 82fcde
	      else
Packit Service 82fcde
		{
Packit Service 82fcde
		  /* The function is already defined.  See whether we have
Packit Service 82fcde
		     a better name here.  */
Packit Service 82fcde
		  if (((*existp)->hidden && !newsym->hidden)
Packit Service 82fcde
		      || ((*existp)->name[0] == '_' && newsym->name[0] != '_')
Packit Service 82fcde
		      || ((*existp)->name[0] != '_' && newsym->name[0] != '_'
Packit Service 82fcde
			  && ((*existp)->weak && !newsym->weak)))
Packit Service 82fcde
		    *existp = newsym;
Packit Service 82fcde
		  else
Packit Service 82fcde
		    /* We don't need the allocated memory.  */
Packit Service 82fcde
		    obstack_free (&shobj->ob_sym, newsym);
Packit Service 82fcde
		}
Packit Service 82fcde
	    }
Packit Service 82fcde
Packit Service 82fcde
	  ++symtab;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
Packit Service 82fcde
  sortsym = malloc (n * sizeof (struct known_symbol *));
Packit Service 82fcde
  if (sortsym == NULL)
Packit Service 82fcde
    abort ();
Packit Service 82fcde
Packit Service 82fcde
  twalk (symroot, printsym);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
add_arcs (struct profdata *profdata)
Packit Service 82fcde
{
Packit Service 82fcde
  uint32_t narcs = profdata->narcs;
Packit Service 82fcde
  struct here_cg_arc_record *data = profdata->data;
Packit Service 82fcde
  uint32_t cnt;
Packit Service 82fcde
Packit Service 82fcde
  for (cnt = 0; cnt < narcs; ++cnt)
Packit Service 82fcde
    {
Packit Service 82fcde
      /* First add the incoming arc.  */
Packit Service 82fcde
      size_t sym_idx = find_symbol (data[cnt].self_pc);
Packit Service 82fcde
Packit Service 82fcde
      if (sym_idx != (size_t) -1l)
Packit Service 82fcde
	{
Packit Service 82fcde
	  struct known_symbol *sym = sortsym[sym_idx];
Packit Service 82fcde
	  struct arc_list *runp = sym->froms;
Packit Service 82fcde
Packit Service 82fcde
	  while (runp != NULL
Packit Service 82fcde
		 && ((data[cnt].from_pc == 0 && runp->idx != (size_t) -1l)
Packit Service 82fcde
		     || (data[cnt].from_pc != 0
Packit Service 82fcde
			 && (runp->idx == (size_t) -1l
Packit Service 82fcde
			     || data[cnt].from_pc < sortsym[runp->idx]->addr
Packit Service 82fcde
			     || (data[cnt].from_pc
Packit Service 82fcde
				 >= (sortsym[runp->idx]->addr
Packit Service 82fcde
				     + sortsym[runp->idx]->size))))))
Packit Service 82fcde
	    runp = runp->next;
Packit Service 82fcde
Packit Service 82fcde
	  if (runp == NULL)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      /* We need a new entry.  */
Packit Service 82fcde
	      struct arc_list *newp = (struct arc_list *)
Packit Service 82fcde
		obstack_alloc (&ob_list, sizeof (struct arc_list));
Packit Service 82fcde
Packit Service 82fcde
	      if (data[cnt].from_pc == 0)
Packit Service 82fcde
		newp->idx = (size_t) -1l;
Packit Service 82fcde
	      else
Packit Service 82fcde
		newp->idx = find_symbol (data[cnt].from_pc);
Packit Service 82fcde
	      newp->count = data[cnt].count;
Packit Service 82fcde
	      newp->next = sym->froms;
Packit Service 82fcde
	      sym->froms = newp;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else
Packit Service 82fcde
	    /* Increment the counter for the found entry.  */
Packit Service 82fcde
	    runp->count += data[cnt].count;
Packit Service 82fcde
	}
Packit Service 82fcde
Packit Service 82fcde
      /* Now add it to the appropriate outgoing list.  */
Packit Service 82fcde
      sym_idx = find_symbol (data[cnt].from_pc);
Packit Service 82fcde
      if (sym_idx != (size_t) -1l)
Packit Service 82fcde
	{
Packit Service 82fcde
	  struct known_symbol *sym = sortsym[sym_idx];
Packit Service 82fcde
	  struct arc_list *runp = sym->tos;
Packit Service 82fcde
Packit Service 82fcde
	  while (runp != NULL
Packit Service 82fcde
		 && (runp->idx == (size_t) -1l
Packit Service 82fcde
		     || data[cnt].self_pc < sortsym[runp->idx]->addr
Packit Service 82fcde
		     || data[cnt].self_pc >= (sortsym[runp->idx]->addr
Packit Service 82fcde
					      + sortsym[runp->idx]->size)))
Packit Service 82fcde
	    runp = runp->next;
Packit Service 82fcde
Packit Service 82fcde
	  if (runp == NULL)
Packit Service 82fcde
	    {
Packit Service 82fcde
	      /* We need a new entry.  */
Packit Service 82fcde
	      struct arc_list *newp = (struct arc_list *)
Packit Service 82fcde
		obstack_alloc (&ob_list, sizeof (struct arc_list));
Packit Service 82fcde
Packit Service 82fcde
	      newp->idx = find_symbol (data[cnt].self_pc);
Packit Service 82fcde
	      newp->count = data[cnt].count;
Packit Service 82fcde
	      newp->next = sym->tos;
Packit Service 82fcde
	      sym->tos = newp;
Packit Service 82fcde
	    }
Packit Service 82fcde
	  else
Packit Service 82fcde
	    /* Increment the counter for the found entry.  */
Packit Service 82fcde
	    runp->count += data[cnt].count;
Packit Service 82fcde
	}
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static int
Packit Service 82fcde
countorder (const void *p1, const void *p2)
Packit Service 82fcde
{
Packit Service 82fcde
  struct known_symbol *s1 = (struct known_symbol *) p1;
Packit Service 82fcde
  struct known_symbol *s2 = (struct known_symbol *) p2;
Packit Service 82fcde
Packit Service 82fcde
  if (s1->ticks != s2->ticks)
Packit Service 82fcde
    return (int) (s2->ticks - s1->ticks);
Packit Service 82fcde
Packit Service 82fcde
  if (s1->calls != s2->calls)
Packit Service 82fcde
    return (int) (s2->calls - s1->calls);
Packit Service 82fcde
Packit Service 82fcde
  return strcmp (s1->name, s2->name);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static double tick_unit;
Packit Service 82fcde
static uintmax_t cumu_ticks;
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
printflat (const void *node, VISIT value, int level)
Packit Service 82fcde
{
Packit Service 82fcde
  if (value == leaf || value == postorder)
Packit Service 82fcde
    {
Packit Service 82fcde
      struct known_symbol *s = *(struct known_symbol **) node;
Packit Service 82fcde
Packit Service 82fcde
      cumu_ticks += s->ticks;
Packit Service 82fcde
Packit Service 82fcde
      printf ("%6.2f%10.2f%9.2f%9" PRIdMAX "%9.2f           %s\n",
Packit Service 82fcde
	      total_ticks ? (100.0 * s->ticks) / total_ticks : 0.0,
Packit Service 82fcde
	      tick_unit * cumu_ticks,
Packit Service 82fcde
	      tick_unit * s->ticks,
Packit Service 82fcde
	      s->calls,
Packit Service 82fcde
	      s->calls ? (s->ticks * 1000000) * tick_unit / s->calls : 0,
Packit Service 82fcde
	      /* FIXME: don't know about called functions.  */
Packit Service 82fcde
	      s->name);
Packit Service 82fcde
    }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
/* ARGUSED */
Packit Service 82fcde
static void
Packit Service 82fcde
freenoop (void *p)
Packit Service 82fcde
{
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
generate_flat_profile (struct profdata *profdata)
Packit Service 82fcde
{
Packit Service 82fcde
  size_t n;
Packit Service 82fcde
  void *data = NULL;
Packit Service 82fcde
Packit Service 82fcde
  tick_unit = 1.0 / profdata->hist_hdr->prof_rate;
Packit Service 82fcde
Packit Service 82fcde
  printf ("Flat profile:\n\n"
Packit Service 82fcde
	  "Each sample counts as %g %s.\n",
Packit Service 82fcde
	  tick_unit, profdata->hist_hdr->dimen);
Packit Service 82fcde
  fputs ("  %   cumulative   self              self     total\n"
Packit Service 82fcde
	 " time   seconds   seconds    calls  us/call  us/call  name\n",
Packit Service 82fcde
	 stdout);
Packit Service 82fcde
Packit Service 82fcde
  for (n = 0; n < symidx; ++n)
Packit Service 82fcde
    if (sortsym[n]->calls != 0 || sortsym[n]->ticks != 0)
Packit Service 82fcde
      tsearch (sortsym[n], &data, countorder);
Packit Service 82fcde
Packit Service 82fcde
  twalk (data, printflat);
Packit Service 82fcde
Packit Service 82fcde
  tdestroy (data, freenoop);
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
generate_call_graph (struct profdata *profdata)
Packit Service 82fcde
{
Packit Service 82fcde
  size_t cnt;
Packit Service 82fcde
Packit Service 82fcde
  puts ("\nindex % time    self  children    called     name\n");
Packit Service 82fcde
Packit Service 82fcde
  for (cnt = 0; cnt < symidx; ++cnt)
Packit Service 82fcde
    if (sortsym[cnt]->froms != NULL || sortsym[cnt]->tos != NULL)
Packit Service 82fcde
      {
Packit Service 82fcde
	struct arc_list *runp;
Packit Service 82fcde
	size_t n;
Packit Service 82fcde
Packit Service 82fcde
	/* First print the from-information.  */
Packit Service 82fcde
	runp = sortsym[cnt]->froms;
Packit Service 82fcde
	while (runp != NULL)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    printf ("            %8.2f%8.2f%9" PRIdMAX "/%-9" PRIdMAX "   %s",
Packit Service 82fcde
		    (runp->idx != (size_t) -1l
Packit Service 82fcde
		     ? sortsym[runp->idx]->ticks * tick_unit : 0.0),
Packit Service 82fcde
		    0.0, /* FIXME: what's time for the children, recursive */
Packit Service 82fcde
		    runp->count, sortsym[cnt]->calls,
Packit Service 82fcde
		    (runp->idx != (size_t) -1l ?
Packit Service 82fcde
		     sortsym[runp->idx]->name : "<UNKNOWN>"));
Packit Service 82fcde
Packit Service 82fcde
	    if (runp->idx != (size_t) -1l)
Packit Service 82fcde
	      printf (" [%Zd]", runp->idx);
Packit Service 82fcde
	    putchar_unlocked ('\n');
Packit Service 82fcde
Packit Service 82fcde
	    runp = runp->next;
Packit Service 82fcde
	  }
Packit Service 82fcde
Packit Service 82fcde
	/* Info about the function itself.  */
Packit Service 82fcde
	n = printf ("[%Zu]", cnt);
Packit Service 82fcde
	printf ("%*s%5.1f%8.2f%8.2f%9" PRIdMAX "         %s [%Zd]\n",
Packit Service 82fcde
		(int) (7 - n), " ",
Packit Service 82fcde
		total_ticks ? (100.0 * sortsym[cnt]->ticks) / total_ticks : 0,
Packit Service 82fcde
		sortsym[cnt]->ticks * tick_unit,
Packit Service 82fcde
		0.0, /* FIXME: what's time for the children, recursive */
Packit Service 82fcde
		sortsym[cnt]->calls,
Packit Service 82fcde
		sortsym[cnt]->name, cnt);
Packit Service 82fcde
Packit Service 82fcde
	/* Info about the functions this function calls.  */
Packit Service 82fcde
	runp = sortsym[cnt]->tos;
Packit Service 82fcde
	while (runp != NULL)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    printf ("            %8.2f%8.2f%9" PRIdMAX "/",
Packit Service 82fcde
		    (runp->idx != (size_t) -1l
Packit Service 82fcde
		     ? sortsym[runp->idx]->ticks * tick_unit : 0.0),
Packit Service 82fcde
		    0.0, /* FIXME: what's time for the children, recursive */
Packit Service 82fcde
		    runp->count);
Packit Service 82fcde
Packit Service 82fcde
	    if (runp->idx != (size_t) -1l)
Packit Service 82fcde
	      printf ("%-9" PRIdMAX "   %s [%Zd]\n",
Packit Service 82fcde
		      sortsym[runp->idx]->calls,
Packit Service 82fcde
		      sortsym[runp->idx]->name,
Packit Service 82fcde
		      runp->idx);
Packit Service 82fcde
	    else
Packit Service 82fcde
	      fputs ("???         <UNKNOWN>\n\n", stdout);
Packit Service 82fcde
Packit Service 82fcde
	    runp = runp->next;
Packit Service 82fcde
	  }
Packit Service 82fcde
Packit Service 82fcde
	fputs ("-----------------------------------------------\n", stdout);
Packit Service 82fcde
      }
Packit Service 82fcde
}
Packit Service 82fcde
Packit Service 82fcde
Packit Service 82fcde
static void
Packit Service 82fcde
generate_call_pair_list (struct profdata *profdata)
Packit Service 82fcde
{
Packit Service 82fcde
  size_t cnt;
Packit Service 82fcde
Packit Service 82fcde
  for (cnt = 0; cnt < symidx; ++cnt)
Packit Service 82fcde
    if (sortsym[cnt]->froms != NULL || sortsym[cnt]->tos != NULL)
Packit Service 82fcde
      {
Packit Service 82fcde
	struct arc_list *runp;
Packit Service 82fcde
Packit Service 82fcde
	/* First print the incoming arcs.  */
Packit Service 82fcde
	runp = sortsym[cnt]->froms;
Packit Service 82fcde
	while (runp != NULL)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    if (runp->idx == (size_t) -1l)
Packit Service 82fcde
	      printf ("\
Packit Service 82fcde
<UNKNOWN>                          %-34s %9" PRIdMAX "\n",
Packit Service 82fcde
		      sortsym[cnt]->name, runp->count);
Packit Service 82fcde
	    runp = runp->next;
Packit Service 82fcde
	  }
Packit Service 82fcde
Packit Service 82fcde
	/* Next the outgoing arcs.  */
Packit Service 82fcde
	runp = sortsym[cnt]->tos;
Packit Service 82fcde
	while (runp != NULL)
Packit Service 82fcde
	  {
Packit Service 82fcde
	    printf ("%-34s %-34s %9" PRIdMAX "\n",
Packit Service 82fcde
		    sortsym[cnt]->name,
Packit Service 82fcde
		    (runp->idx != (size_t) -1l
Packit Service 82fcde
		     ? sortsym[runp->idx]->name : "<UNKNOWN>"),
Packit Service 82fcde
		    runp->count);
Packit Service 82fcde
	    runp = runp->next;
Packit Service 82fcde
	  }
Packit Service 82fcde
      }
Packit Service 82fcde
}