diff -u binutils-2.13/gprof/README binutils-2.13-jsgf/gprof/README
--- binutils-2.13/gprof/README	Thu Jul 19 03:43:13 2001
+++ binutils-2.13-jsgf/gprof/README	Thu Oct  3 15:53:26 2002
@@ -440,3 +440,11 @@
 file in a suitable format.  This should be fixed for future releases
 of gcc.  In the meantime, contact davidm@cs.arizona.edu for a version
 of __bb_exit_func() to is appropriate.
+
+*** Shared Object Mapping Records
+
+(version 2) These records explain where shared objects have been
+mapped into the address space, and gives their names.  This allows
+gprof to resolve references into these mappings symbolically.  If
+present, these records must be before any other, so that gprof can
+organize its symbols before needing them.
diff -u binutils-2.13/gprof/alpha.c binutils-2.13-jsgf/gprof/alpha.c
--- binutils-2.13/gprof/alpha.c	Tue Jul 30 11:20:36 2002
+++ binutils-2.13-jsgf/gprof/alpha.c	Mon Oct  7 12:06:48 2002
@@ -96,6 +96,10 @@
   bfd_vma pc, dest_pc;
   unsigned int insn;
   Sym *child;
+  asection *text_sect;
+  PTR text_space;
+
+  text_space = core_get_text_space(p_lowpc, &text_sect);
 
   if (indirect_child.name == NULL)
     {
@@ -105,7 +109,7 @@
       indirect_child.cg.cyc.head = &indirect_child;
     }
 
-  if (!core_text_space)
+  if (!text_space)
     {
       return;
     }
@@ -122,8 +126,8 @@
 			  (unsigned long) p_highpc));
   for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4)
     {
-      insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space
-				    + pc - core_text_sect->vma));
+      insn = bfd_get_32 (core_bfd, ((unsigned char *) text_space
+				    + pc - text_sect->vma));
       switch (insn & (0x3f << 26))
 	{
 	case OP_Jxx << 26:
diff -u binutils-2.13/gprof/cg_print.c binutils-2.13-jsgf/gprof/cg_print.c
--- binutils-2.13/gprof/cg_print.c	Fri Feb  1 00:24:15 2002
+++ binutils-2.13-jsgf/gprof/cg_print.c	Wed Oct  9 18:21:08 2002
@@ -76,7 +76,7 @@
     }
 
   printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
-	  (long) hist_scale * sizeof (UNIT));
+	  (long) hist_scale);
 
   if (print_time > 0.0)
     printf (_(" for %.2f%% of %.2f seconds\n\n"),
diff -u binutils-2.13/gprof/corefile.c binutils-2.13-jsgf/gprof/corefile.c
--- binutils-2.13/gprof/corefile.c	Fri Feb  1 00:24:15 2002
+++ binutils-2.13-jsgf/gprof/corefile.c	Fri Oct 11 11:52:34 2002
@@ -25,15 +25,12 @@
 #include "source.h"
 #include "symtab.h"
 #include "corefile.h"
+#include "gmon_io.h"
 
 bfd *core_bfd;
-int core_num_syms;
-asymbol **core_syms;
-asection *core_text_sect;
-PTR core_text_space;
 
-int min_insn_size;
-int offset_to_code;
+int min_insn_size = 1;
+int offset_to_code = 0;
 
 /* For mapping symbols to specific .o files during file ordering.  */
 struct function_map *symbol_map;
@@ -42,7 +39,10 @@
 static void read_function_mappings PARAMS ((const char *));
 static int core_sym_class PARAMS ((asymbol *));
 static boolean get_src_info
-  PARAMS ((bfd_vma, const char **, const char **, int *));
+  PARAMS ((bfd_vma, const char **, const char **, int *, bfd *, asymbol **, int, asection *));
+static void core_create_function_syms PARAMS ((bfd *, const char *, bfd_vma, asection *, asymbol **, int));
+static void core_create_line_syms PARAMS ((bfd *, const char *, bfd_vma, asection *, asymbol **, int));
+static void core_load_text_space PARAMS ((bfd *, asection *));
 
 extern void i386_find_call  PARAMS ((Sym *, bfd_vma, bfd_vma));
 extern void alpha_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
@@ -51,6 +51,47 @@
 extern void sparc_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
 extern void mips_find_call  PARAMS ((Sym *, bfd_vma, bfd_vma));
 
+Search_List obj_search_list;
+
+static const char *intern PARAMS ((const char *));
+
+/* keep unique copies of all strings */
+static const char *intern(str)
+     const char *str;
+{
+#define STR_HASHSZ	1023u
+  struct str {
+    struct str *next;
+    char str[1];
+  };
+  static struct str *strhash[STR_HASHSZ];
+  struct str *strp;
+  const char *cp;
+  unsigned int hash = 0;
+
+  for(cp = str; *cp; cp++)
+    hash = *cp ^ ((hash << 13) | (hash >> (32-13)));
+  hash %= STR_HASHSZ;
+
+  for(strp = strhash[hash]; strp; strp = strp->next)
+    if (strcmp(strp->str, str) == 0)
+      return strp->str;
+
+  strp = xmalloc(sizeof(*strp) + strlen(str));
+  strcpy(strp->str, str);
+  strp->next = strhash[hash];
+  strhash[hash] = strp;
+
+  return strp->str;
+}
+
+static int streq(const char *a, const char *b)
+{
+  if (a == b)
+    return 0;
+  return strcmp(a, b);
+}
+
 static void
 read_function_mappings (filename)
      const char *filename;
@@ -138,105 +179,72 @@
 }
 
 
+/* load any unloaded files */
 void
-core_init (aout_name)
-     const char *aout_name;
+core_init ()
 {
-  core_bfd = bfd_openr (aout_name, 0);
-
-  if (!core_bfd)
-    {
-      perror (aout_name);
-      done (1);
-    }
-
-  if (!bfd_check_format (core_bfd, bfd_object))
-    {
-      fprintf (stderr, _("%s: %s: not in a.out format\n"), whoami, aout_name);
-      done (1);
-    }
-
-  /* Get core's text section.  */
-  core_text_sect = bfd_get_section_by_name (core_bfd, ".text");
-  if (!core_text_sect)
-    {
-      core_text_sect = bfd_get_section_by_name (core_bfd, "$CODE$");
-      if (!core_text_sect)
-	{
-	  fprintf (stderr, _("%s: can't find .text section in %s\n"),
-		   whoami, aout_name);
-	  done (1);
-	}
-    }
-
-  /* Read core's symbol table.  */
-
-  /* This will probably give us more than we need, but that's ok.  */
-  core_num_syms = bfd_get_symtab_upper_bound (core_bfd);
-  if (core_num_syms < 0)
-    {
-      fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
-	       bfd_errmsg (bfd_get_error ()));
-      done (1);
-    }
-
-  core_syms = (asymbol **) xmalloc (core_num_syms);
-  core_num_syms = bfd_canonicalize_symtab (core_bfd, core_syms);
+}
 
-  if (core_num_syms < 0)
-    {
-      fprintf (stderr, "%s: %s: %s\n", whoami, aout_name,
-	       bfd_errmsg (bfd_get_error ()));
-      done (1);
-    }
+/* Read in the text space of an a.out file.  */
 
-  min_insn_size = 1;
-  offset_to_code = 0;
+struct text_space
+{
+  bfd_vma addr;
+  unsigned int size;
+  PTR text;
+  asection *sect;
+  struct text_space *next;
+};
 
-  switch (bfd_get_arch (core_bfd))
-    {
-    case bfd_arch_vax:
-    case bfd_arch_tahoe:
-      offset_to_code = 2;
-      break;
+static struct text_space *text_spaces;
 
-    case bfd_arch_alpha:
-      min_insn_size = 4;
-      break;
+PTR core_get_text_space(addr, text_sectp)
+     bfd_vma addr;
+     asection **text_sectp;
+{
+  struct text_space *ts;
 
-    default:
-      break;
+  for(ts = text_spaces; ts != NULL; ts = ts->next) {
+    if (addr >= ts->addr && addr < (ts->addr + ts->size)) {
+      *text_sectp = ts->sect;
+      return ts->text;
     }
+  }
 
-  if (function_mapping_file)
-    read_function_mappings (function_mapping_file);
+  return 0;
 }
 
-/* Read in the text space of an a.out file.  */
-
 void
-core_get_text_space (cbfd)
+core_load_text_space (cbfd, text_sect)
      bfd *cbfd;
+     asection *text_sect;
 {
-  core_text_space = (PTR) malloc ((unsigned int) core_text_sect->_raw_size);
+  struct text_space *ts = xmalloc(sizeof(*ts));
+
+  ts->addr = text_sect->vma;
+  ts->size = text_sect->_raw_size;
+  ts->sect = text_sect;
+  ts->text = (PTR) malloc ((unsigned int) text_sect->_raw_size);
 
-  if (!core_text_space)
+  if (!ts->text)
     {
       fprintf (stderr, _("%s: ran out room for %lu bytes of text space\n"),
-	       whoami, (unsigned long) core_text_sect->_raw_size);
+	       whoami, (unsigned long) text_sect->_raw_size);
       done (1);
     }
 
-  if (!bfd_get_section_contents (cbfd, core_text_sect, core_text_space,
-				 (bfd_vma) 0, core_text_sect->_raw_size))
+  if (!bfd_get_section_contents (cbfd, text_sect, ts->text,
+				 (bfd_vma) 0, text_sect->_raw_size))
     {
       bfd_perror ("bfd_get_section_contents");
-      free (core_text_space);
-      core_text_space = 0;
+      free (ts->text);
+      free (ts);
+    }
+  else
+    {
+      ts->next = text_spaces;
+      text_spaces = ts;
     }
-
-  if (!core_text_space)
-    fprintf (stderr, _("%s: can't do -c\n"), whoami);
 }
 
 
@@ -371,17 +379,21 @@
 /* Get whatever source info we can get regarding address ADDR.  */
 
 static boolean
-get_src_info (addr, filename, name, line_num)
+get_src_info (addr, filename, name, line_num, cbfd, syms, num_syms, text_sect)
      bfd_vma addr;
      const char **filename;
      const char **name;
      int *line_num;
+     bfd *cbfd;
+     asymbol **syms;
+     int num_syms ATTRIBUTE_UNUSED;
+     asection *text_sect;
 {
   const char *fname = 0, *func_name = 0;
   int l = 0;
 
-  if (bfd_find_nearest_line (core_bfd, core_text_sect, core_syms,
-			     addr - core_text_sect->vma,
+  if (bfd_find_nearest_line (cbfd, text_sect, syms,
+			     addr - text_sect->vma,
 			     &fname, &func_name, (unsigned int *) &l)
       && fname && func_name && l)
     {
@@ -404,22 +416,29 @@
 /* Read in symbol table from core.
    One symbol per function is entered.  */
 
-void
-core_create_function_syms (cbfd)
+static void
+core_create_function_syms (cbfd, obj_filename, obj_offset, text_sect, syms, num_syms)
      bfd *cbfd ATTRIBUTE_UNUSED;
+     const char *obj_filename ATTRIBUTE_UNUSED;
+     bfd_vma obj_offset;
+     asection *text_sect;
+     asymbol **syms;
+     int num_syms;
 {
   bfd_vma min_vma = ~(bfd_vma) 0;
   bfd_vma max_vma = 0;
   int class;
   long i, found, skip;
   unsigned int j;
+  Sym_Table ltab;
+  asymbol filesym, endsym, *filesymp[2] = { &filesym, &endsym };
 
   /* Pass 1 - determine upper bound on number of function names.  */
-  symtab.len = 0;
+  ltab.len = 0;
 
-  for (i = 0; i < core_num_syms; ++i)
+  for (i = 0; i < num_syms; ++i)
     {
-      if (!core_sym_class (core_syms[i]))
+      if (!core_sym_class (syms[i]))
 	continue;
 
       /* This should be replaced with a binary search or hashed
@@ -430,40 +449,70 @@
 	 in the file.  */
       skip = 0;
       for (j = 0; j < symbol_map_count; j++)
-	if (!strcmp (core_syms[i]->name, symbol_map[j].function_name))
+	if (!streq (syms[i]->name, symbol_map[j].function_name))
 	  {
-	    if (j > 0 && ! strcmp (symbol_map [j].file_name,
+	    if (j > 0 && ! streq (symbol_map [j].file_name,
 				   symbol_map [j - 1].file_name))
 	      skip = 1;
 	    break;
 	  }
 
       if (!skip)
-	++symtab.len;
+	++ltab.len;
     }
 
-  if (symtab.len == 0)
+  if (ltab.len == 0)
     {
-      fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, a_out_name);
-      done (1);
+      char *buf = xmalloc(strlen(obj_filename) + 6); /* __end */
+
+      fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, obj_filename);
+      /* make up a function which covers the whole library */
+      syms = filesymp;
+      num_syms = 2;
+
+      memset(&filesym, 0, sizeof(filesym));
+      filesym.flags = BSF_GLOBAL | BSF_FUNCTION;
+      filesym.name = intern(obj_filename);
+      filesym.value = obj_offset;
+      filesym.section = text_sect;
+
+      memset(&endsym, 0, sizeof(endsym));
+      endsym.flags = BSF_GLOBAL | BSF_FUNCTION;
+      sprintf(buf, "%s__end", obj_filename);
+      endsym.name = intern(buf);
+      endsym.value = obj_offset + text_sect->_raw_size;
+      endsym.section = text_sect;
+
+      ltab.len = 2;
+
+      free(buf);
     }
 
-  /* The "+ 2" is for the sentinels.  */
-  symtab.base = (Sym *) xmalloc ((symtab.len + 2) * sizeof (Sym));
+  if (symtab.base == NULL)
+    {
+      /* The "+ 2" is for the sentinels.  */
+      ltab.len += 2;
+    } 
+  else
+    {
+      ltab.len += symtab.len;
+    }
+
+  ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym));
+  ltab.limit = ltab.base;
 
   /* Pass 2 - create symbols.  */
-  symtab.limit = symtab.base;
 
-  for (i = 0; i < core_num_syms; ++i)
+  for (i = 0; i < num_syms; ++i)
     {
-      class = core_sym_class (core_syms[i]);
+      class = core_sym_class (syms[i]);
 
       if (!class)
 	{
 	  DBG (AOUTDEBUG,
 	       printf ("[core_create_function_syms] rejecting: 0x%lx %s\n",
-		       (unsigned long) core_syms[i]->value,
-		       core_syms[i]->name));
+		       (unsigned long) syms[i]->value,
+		       syms[i]->name));
 	  continue;
 	}
 
@@ -473,9 +522,9 @@
       found = 0;
 
       for (j = 0; j < symbol_map_count; j++)
-	if (!strcmp (core_syms[i]->name, symbol_map[j].function_name))
+	if (!streq (syms[i]->name, symbol_map[j].function_name))
 	  {
-	    if (j > 0 && ! strcmp (symbol_map [j].file_name,
+	    if (j > 0 && ! streq (symbol_map [j].file_name,
 				   symbol_map [j - 1].file_name))
 	      skip = 1;
 	    else
@@ -486,31 +535,32 @@
       if (skip)
 	continue;
 
-      sym_init (symtab.limit);
+      sym_init (ltab.limit);
 
       /* Symbol offsets are always section-relative.  */
-      symtab.limit->addr = core_syms[i]->value + core_syms[i]->section->vma;
+      ltab.limit->addr = syms[i]->value + syms[i]->section->vma;
 
       if (symbol_map_count
-	  && !strcmp (core_syms[i]->name, symbol_map[found].function_name))
+	  && !streq (syms[i]->name, symbol_map[found].function_name))
 	{
-	  symtab.limit->name = symbol_map[found].file_name;
-	  symtab.limit->mapped = 1;
+	  ltab.limit->name = intern(symbol_map[found].file_name);
+	  ltab.limit->mapped = 1;
 	}
       else
 	{
-	  symtab.limit->name = core_syms[i]->name;
-	  symtab.limit->mapped = 0;
+	  ltab.limit->name = intern(syms[i]->name);
+	  ltab.limit->mapped = 0;
 	}
 
       /* Lookup filename and line number, if we can.  */
       {
 	const char *filename, *func_name;
 
-	if (get_src_info (symtab.limit->addr, &filename, &func_name,
-			  &symtab.limit->line_num))
+	if (get_src_info (ltab.limit->addr, &filename, &func_name,
+			  &ltab.limit->line_num,
+			  cbfd, syms, num_syms, text_sect))
 	  {
-	    symtab.limit->file = source_file_lookup_path (filename);
+	    ltab.limit->file = source_file_lookup_path (filename);
 
 	    /* FIXME: Checking __osf__ here does not work with a cross
 	       gprof.  */
@@ -522,65 +572,108 @@
 	       labels do not appear in the symbol table info, so this isn't
 	       necessary.  */
 
-	    if (strcmp (symtab.limit->name, func_name) != 0)
+	    if (streq (ltab.limit->name, func_name) != 0)
 	      {
 		/* The symbol's address maps to a different name, so
 		   it can't be a function-entry point.  This happens
 		   for labels, for example.  */
 		DBG (AOUTDEBUG,
 		     printf ("[core_create_function_syms: rej %s (maps to %s)\n",
-			     symtab.limit->name, func_name));
+			     ltab.limit->name, func_name));
 		continue;
 	      }
 #endif
 	  }
       }
 
-      symtab.limit->is_func = true;
-      symtab.limit->is_bb_head = true;
+      ltab.limit->addr += obj_offset;
+      ltab.limit->is_func = true;
+      ltab.limit->is_bb_head = true;
 
       if (class == 't')
-	symtab.limit->is_static = true;
+	ltab.limit->is_static = true;
 
-      min_vma = MIN (symtab.limit->addr, min_vma);
-      max_vma = MAX (symtab.limit->addr, max_vma);
+      min_vma = MIN (ltab.limit->addr, min_vma);
+      max_vma = MAX (ltab.limit->addr, max_vma);
 
       /* If we see "main" without an initial '_', we assume names
 	 are *not* prefixed by '_'.  */
-      if (symtab.limit->name[0] == 'm' && discard_underscores
-	  && strcmp (symtab.limit->name, "main") == 0)
+      if (ltab.limit->name[0] == 'm' && discard_underscores
+	  && streq (ltab.limit->name, "main") == 0)
 	discard_underscores = 0;
 
       DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n",
-			      (long) (symtab.limit - symtab.base),
-			      symtab.limit->name,
-			      (unsigned long) symtab.limit->addr));
+			      (long) (ltab.limit - ltab.base),
+			      ltab.limit->name,
+			      (unsigned long) ltab.limit->addr));
+      ++ltab.limit;
+    }
+
+  /* merge ltab with existing symtab (if any) */
+  if (symtab.base == 0)
+    {
+      /* Create sentinels.  */
+      symtab = ltab;
+
+      sym_init (symtab.limit);
+      symtab.limit->name = "<locore>";
+      symtab.limit->addr = 0;
+      symtab.limit->end_addr = min_vma - 1;
+      ++symtab.limit;
+
+      sym_init (symtab.limit);
+      symtab.limit->name = "<hicore>";
+      symtab.limit->addr = max_vma + 1;
+      symtab.limit->end_addr = ~(bfd_vma) 0;
       ++symtab.limit;
+
+      symtab.len = symtab.limit - symtab.base;
+      symtab_finalize(&symtab, text_sect);
     }
+  else
+    {
+      /* Update sentinels.  */
+      Sym *sentinel = sym_lookup (&symtab, (bfd_vma) 0);
+
+      if (streq (sentinel->name, "<locore>") == 0
+	  && min_vma <= sentinel->end_addr)
+	sentinel->end_addr = min_vma - 1;
+
+      sentinel = sym_lookup (&symtab, ~(bfd_vma) 0);
+
+      if (streq (sentinel->name, "<hicore>") == 0 && max_vma >= sentinel->addr)
+	sentinel->addr = max_vma + 1;
+
+      /* Copy in function symbols.  */
+      memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym));
+      ltab.limit += symtab.len;
+      if ((unsigned int) (ltab.limit - ltab.base) != ltab.len)
+	{
+	  fprintf (stderr,
+		   _("%s: somebody miscounted: ltab.len=%d instead of %ld\n"),
+		   whoami, ltab.len, (long) (ltab.limit - ltab.base));
+	  done (1);
+	}
 
-  /* Create sentinels.  */
-  sym_init (symtab.limit);
-  symtab.limit->name = "<locore>";
-  symtab.limit->addr = 0;
-  symtab.limit->end_addr = min_vma - 1;
-  ++symtab.limit;
-
-  sym_init (symtab.limit);
-  symtab.limit->name = "<hicore>";
-  symtab.limit->addr = max_vma + 1;
-  symtab.limit->end_addr = ~(bfd_vma) 0;
-  ++symtab.limit;
+      /* Finalize ltab and make it symbol table.  */
+      symtab_finalize(&ltab, text_sect);
+      free (symtab.base);
 
-  symtab.len = symtab.limit - symtab.base;
-  symtab_finalize (&symtab);
+      symtab = ltab;
+    }
 }
 
 /* Read in symbol table from core.
    One symbol per line of source code is entered.  */
 
 void
-core_create_line_syms (cbfd)
+core_create_line_syms (cbfd, obj_filename, obj_offset, text_sect, syms, num_syms)
      bfd *cbfd;
+     const char *obj_filename;
+     bfd_vma obj_offset;
+     asection *text_sect;
+     asymbol **syms;
+     int num_syms;
 {
   char *prev_name, *prev_filename;
   unsigned int prev_name_len, prev_filename_len;
@@ -594,7 +687,7 @@
   /* Create symbols for functions as usual.  This is necessary in
      cases where parts of a program were not compiled with -g.  For
      those parts we still want to get info at the function level.  */
-  core_create_function_syms (cbfd);
+  core_create_function_syms (cbfd, obj_filename, obj_offset, text_sect, syms, num_syms);
 
   /* Pass 1 - counter number of symbols.  */
 
@@ -612,17 +705,18 @@
   ltab.len = 0;
   prev_line_num = 0;
 
-  for (offset = 0; offset < core_text_sect->_raw_size; offset += min_insn_size)
+  for (offset = 0; offset < text_sect->_raw_size; offset += min_insn_size)
     {
       unsigned int len;
 
-      vma = core_text_sect->vma + offset;
+      vma = text_sect->vma + offset;
 
-      if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num)
+      if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num, 
+			 cbfd, syms, num_syms, text_sect)
 	  || (prev_line_num == dummy.line_num
 	      && prev_name != NULL
-	      && strcmp (prev_name, dummy.name) == 0
-	      && strcmp (prev_filename, filename) == 0))
+	      && streq (prev_name, dummy.name) == 0
+	      && streq (prev_filename, filename) == 0))
 	continue;
 
       ++ltab.len;
@@ -680,28 +774,29 @@
      lot cleaner now.  */
   prev = 0;
 
-  for (offset = 0; offset < core_text_sect->_raw_size; offset += min_insn_size)
+  for (offset = 0; offset < text_sect->_raw_size; offset += min_insn_size)
     {
       sym_init (ltab.limit);
 
-      if (!get_src_info (core_text_sect->vma + offset, &filename,
-			 &ltab.limit->name, &ltab.limit->line_num)
+      if (!get_src_info (text_sect->vma + offset, &filename,
+			 &ltab.limit->name, &ltab.limit->line_num,
+			 cbfd, syms, num_syms, text_sect)
 	  || (prev && prev->line_num == ltab.limit->line_num
-	      && strcmp (prev->name, ltab.limit->name) == 0
-	      && strcmp (prev->file->name, filename) == 0))
+	      && streq (prev->name, ltab.limit->name) == 0
+	      && streq (prev->file->name, filename) == 0))
 	continue;
 
       /* Make name pointer a malloc'ed string.  */
-      ltab.limit->name = xstrdup (ltab.limit->name);
+      ltab.limit->name = intern (ltab.limit->name);
       ltab.limit->file = source_file_lookup_path (filename);
 
-      ltab.limit->addr = core_text_sect->vma + offset;
+      ltab.limit->addr = text_sect->vma + offset + obj_offset;
 
       /* Set is_static based on the enclosing function, using either:
 	 1) the previous symbol, if it's from the same function, or
 	 2) a symtab lookup.  */
       if (prev && ltab.limit->file == prev->file &&
-	  strcmp (ltab.limit->name, prev->name) == 0)
+	  streq (ltab.limit->name, prev->name) == 0)
 	{
 	  ltab.limit->is_static = prev->is_static;
 	}
@@ -716,7 +811,7 @@
       /* If we see "main" without an initial '_', we assume names
 	 are *not* prefixed by '_'.  */
       if (ltab.limit->name[0] == 'm' && discard_underscores
-	  && strcmp (ltab.limit->name, "main") == 0)
+	  && streq (ltab.limit->name, "main") == 0)
 	discard_underscores = 0;
 
       DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n",
@@ -729,13 +824,13 @@
   /* Update sentinels.  */
   sentinel = sym_lookup (&symtab, (bfd_vma) 0);
 
-  if (strcmp (sentinel->name, "<locore>") == 0
+  if (streq (sentinel->name, "<locore>") == 0
       && min_vma <= sentinel->end_addr)
     sentinel->end_addr = min_vma - 1;
 
   sentinel = sym_lookup (&symtab, ~(bfd_vma) 0);
 
-  if (strcmp (sentinel->name, "<hicore>") == 0 && max_vma >= sentinel->addr)
+  if (streq (sentinel->name, "<hicore>") == 0 && max_vma >= sentinel->addr)
     sentinel->addr = max_vma + 1;
 
   /* Copy in function symbols.  */
@@ -751,7 +846,195 @@
     }
 
   /* Finalize ltab and make it symbol table.  */
-  symtab_finalize (&ltab);
+  symtab_finalize(&ltab, text_sect);
   free (symtab.base);
   symtab = ltab;
 }
+
+struct file
+{
+  const char *filename;
+  struct file *next;
+};
+
+static struct file *files;
+
+void core_add_file(_filename, offset)
+     const char *_filename;
+     bfd_vma offset;
+{
+  bfd *bfd;
+  asymbol **syms;
+  int num_syms;
+  asection *text_sect;
+  struct file *f;
+  char *filepath = NULL;
+
+  if (obj_search_list.head != NULL)
+    {
+      Search_List_Elem *e;
+
+      for(e = obj_search_list.head; e != NULL; e = e->next)
+	{
+	  filepath = xmalloc(strlen(e->path) + 1 + strlen(_filename) + 1);
+	  sprintf(filepath, "%s/%s", e->path, _filename);
+	  if (access(filepath, R_OK) == 0)
+	    break;
+	  free(filepath);
+	  filepath = NULL;
+	}
+    }
+  else
+    filepath = xstrdup(_filename);
+
+  if (filepath == NULL)
+    {
+      fprintf(stderr, _("%s: can't find file %s\n"), whoami, _filename);
+      return;
+    }
+
+  /* Suppress duplicate files */
+  for(f = files; f != NULL; f = f->next)
+    if (strcmp(filepath, f->filename) == 0)
+      {
+	DBG( AOUTDEBUG, printf ("[core_add_file] skipping already-seen file %s\n",
+				filepath) );
+	free(filepath);
+	return;
+      }
+  f = xmalloc(sizeof(*f));
+  f->filename = filepath;
+  f->next = files;
+  files = f;
+
+  DBG( AOUTDEBUG, printf ("[core_add_file] name=%s offset=%x\n",
+			  filepath, (unsigned int)offset) );
+
+  bfd = bfd_openr (filepath, 0);
+
+  if (!bfd)
+    {
+      perror(filepath);
+      done(1);
+    }
+
+  if (core_bfd == NULL)
+    core_bfd = bfd;
+
+  if (offset == 0)
+    {
+      switch (bfd_get_arch (bfd))
+	{
+	case bfd_arch_vax:
+	case bfd_arch_tahoe:
+	  offset_to_code = 2;
+	  break;
+	
+	case bfd_arch_alpha:
+	  min_insn_size = 4;
+	  break;
+	
+	default:
+	  break;
+	}
+    }
+
+  if (!bfd_check_format (bfd, bfd_object))
+    {
+      fprintf (stderr, _("%s: %s: not in a.out format\n"), whoami, filepath);
+      done (1);
+    }
+
+  /* Get core's text section.  */
+  text_sect = bfd_get_section_by_name (bfd, ".text");
+  if (!text_sect)
+    {
+      text_sect = bfd_get_section_by_name (bfd, "$CODE$");
+      if (!text_sect)
+	{
+	  fprintf (stderr, _("%s: can't find .text section in %s\n"),
+		   whoami, filepath);
+	  done (1);
+	}
+    }
+
+  /* Read core's symbol table.  */
+
+  /* This will probably give us more than we need, but that's ok.  */
+  num_syms = bfd_get_symtab_upper_bound (bfd);
+  if (num_syms < 0)
+    {
+      fprintf (stderr, "%s: %s: %s\n", whoami, filepath,
+	       bfd_errmsg (bfd_get_error ()));
+      done (1);
+    }
+
+  syms = (asymbol **) xmalloc (num_syms);
+  num_syms = bfd_canonicalize_symtab (bfd, syms);
+
+  if (num_syms < 0)
+    {
+      fprintf (stderr, "%s: %s: %s\n", whoami, filepath,
+	       bfd_errmsg (bfd_get_error ()));
+      done (1);
+    }
+
+  if (line_granularity)
+    {
+      core_create_line_syms(bfd, filepath, offset, text_sect, syms, num_syms);
+    }
+  else
+    {
+      core_create_function_syms(bfd, filepath, offset, text_sect, syms, num_syms);
+    }
+  
+  /*
+   * If we should ignore direct function calls, we need to load
+   * to core's text-space:
+   */
+  if (ignore_direct_calls)
+    {
+      core_load_text_space(bfd, text_sect);
+    }
+
+  if (bfd != core_bfd)
+    bfd_close(bfd);
+  free(syms);
+}
+
+void somap_read_rec (ifp, filename)
+     FILE *ifp;
+     const char *filename;
+{
+  bfd_vma start;
+  unsigned int size;
+  bfd_vma offset;
+  unsigned char namelen;
+  char *name;
+
+  if (gmon_file_version < 2) {
+    fprintf (stderr, _("%s: %s: not expecting somap in version %d file\n"),
+		       whoami, filename, gmon_file_version);
+    done (1);
+  }
+
+  if (gmon_io_read_vma (ifp, &start) ||
+      gmon_io_read_32  (ifp, &size) ||
+      gmon_io_read_vma (ifp, &offset) ||
+      gmon_io_read     (ifp, &namelen, 1)) {
+      fprintf (stderr, _("%s: %s: unexpected end of file\n"),
+	       whoami, filename);
+      done (1);
+  }
+
+  name = xmalloc(namelen+1);
+  if (gmon_io_read(ifp, name, namelen)) {
+    fprintf (stderr, _("%s: %s: unexpected end of file\n"),
+	     whoami, filename);
+    done (1);
+  }
+  name[namelen] = 0;
+
+  core_add_file(name, offset);
+  free(name);
+}
diff -u binutils-2.13/gprof/corefile.h binutils-2.13-jsgf/gprof/corefile.h
--- binutils-2.13/gprof/corefile.h	Fri Feb  1 00:24:16 2002
+++ binutils-2.13-jsgf/gprof/corefile.h	Fri Oct 11 11:38:02 2002
@@ -21,6 +21,8 @@
 #ifndef corefile_h
 #define corefile_h
 
+#include "search_list.h"
+
 struct function_map
 {
   char *function_name;
@@ -30,18 +32,16 @@
 extern struct function_map *symbol_map;
 extern unsigned int symbol_map_count;
 
+extern Search_List obj_search_list;
+
 extern bfd *core_bfd;		/* BFD for core-file.  */
-extern int core_num_syms;	/* # of entries in symbol-table.  */
-extern asymbol **core_syms;	/* Symbol table in a.out.  */
-extern asection *core_text_sect;/* Core text section.  */
 extern PTR core_text_space;	/* Text space of a.out in core.  */
-extern int min_insn_size;	/* Size of smallest instruction, in bytes.  */
 extern int offset_to_code;	/* Offset (in bytes) of code from entry
 				   address of routine.  */
 
-extern void core_init                  PARAMS ((const char *));
-extern void core_get_text_space        PARAMS ((bfd *));
-extern void core_create_function_syms  PARAMS ((bfd *));
-extern void core_create_line_syms      PARAMS ((bfd *));
+extern void core_init                  PARAMS ((void));
+extern PTR core_get_text_space	       PARAMS ((bfd_vma, asection **));
+extern void somap_read_rec	       PARAMS ((FILE *, const char *));
+extern void core_add_file	       PARAMS ((const char *, bfd_vma));
 
 #endif /* corefile_h */
diff -u binutils-2.13/gprof/gmon_io.c binutils-2.13-jsgf/gprof/gmon_io.c
--- binutils-2.13/gprof/gmon_io.c	Fri Feb  1 00:24:16 2002
+++ binutils-2.13-jsgf/gprof/gmon_io.c	Tue Oct  8 13:15:40 2002
@@ -303,7 +303,7 @@
       /* Right magic, so it's probably really a new gmon.out file.  */
       gmon_file_version = bfd_get_32 (core_bfd, (bfd_byte *) ghdr.version);
 
-      if (gmon_file_version != GMON_VERSION && gmon_file_version != 0)
+      if (gmon_file_version > GMON_VERSION)
 	{
 	  fprintf (stderr,
 		   _("%s: file `%s' has unsupported version %d\n"),
@@ -334,6 +334,10 @@
 	      bb_read_rec (ifp, filename);
 	      break;
 
+	    case GMON_TAG_SOMAP:
+	      somap_read_rec (ifp, filename);
+	      break;
+
 	    default:
 	      fprintf (stderr,
 		       _("%s: %s: found bad tag %d (file corrupted?)\n"),
@@ -426,6 +430,7 @@
 	}
       else
 	{
+#if 0
 	  /* Old style BSD format.  */
 	  if (file_format == FF_BSD44)
 	    {
@@ -498,14 +503,6 @@
       if (hist_num_bins)
 	++nhist;
 
-      if (!hist_sample)
-	{
-	  hist_sample =
-	    (int *) xmalloc (hist_num_bins * sizeof (hist_sample[0]));
-
-	  memset (hist_sample, 0, hist_num_bins * sizeof (hist_sample[0]));
-	}
-
       for (i = 0; i < hist_num_bins; ++i)
 	{
 	  if (fread (raw_bin_count, sizeof (raw_bin_count), 1, ifp) != 1)
@@ -546,6 +543,7 @@
 	      hz = 1;
 	      fprintf (stderr, _("time is in ticks, not seconds\n"));
 	    }
+#endif
 	}
     }
   else
@@ -577,6 +575,7 @@
 gmon_out_write (filename)
      const char *filename;
 {
+#if 0
   FILE *ofp;
   struct gmon_hdr ghdr;
 
@@ -743,4 +742,5 @@
 	       whoami, file_format);
       done (1);
     }
+#endif
 }
diff -u binutils-2.13/gprof/gmon_out.h binutils-2.13-jsgf/gprof/gmon_out.h
--- binutils-2.13/gprof/gmon_out.h	Thu Jan 31 04:56:07 2002
+++ binutils-2.13-jsgf/gprof/gmon_out.h	Thu Oct  3 14:29:04 2002
@@ -25,7 +25,7 @@
 #define gmon_out_h
 
 #define	GMON_MAGIC	"gmon"	/* magic cookie */
-#define GMON_VERSION	1	/* version number */
+#define GMON_VERSION	2	/* version number */
 
 /* Raw header as it appears on file (without padding).  */
 struct gmon_hdr
@@ -38,7 +38,8 @@
 /* Types of records in this file.  */
 typedef enum
   {
-    GMON_TAG_TIME_HIST = 0, GMON_TAG_CG_ARC = 1, GMON_TAG_BB_COUNT = 2
+    GMON_TAG_TIME_HIST = 0, GMON_TAG_CG_ARC = 1, GMON_TAG_BB_COUNT = 2, 
+    GMON_TAG_SOMAP = 3
   }
 GMON_Record_Tag;
 
diff -u binutils-2.13/gprof/gprof.c binutils-2.13-jsgf/gprof/gprof.c
--- binutils-2.13/gprof/gprof.c	Tue Jul 30 11:20:36 2002
+++ binutils-2.13-jsgf/gprof/gprof.c	Fri Oct 11 11:45:45 2002
@@ -102,6 +102,7 @@
   {"line", no_argument, 0, 'l'},
   {"no-static", no_argument, 0, 'a'},
   {"ignore-non-functions", no_argument, 0, 'D'},
+  {"object-path", required_argument, 0, 'o' },
 
     /* output styles: */
 
@@ -161,13 +162,14 @@
      int status;
 {
   fprintf (stream, _("\
-Usage: %s [-[abcDhilLsTvwxyz]] [-[ACeEfFJnNOpPqQZ][name]] [-I dirs]\n\
+Usage: %s [-[abcDhilLsTvwxyz]] [-[ACeEfFJnNOopPqQZ][name]] [-I dirs]\n\
 	[-d[num]] [-k from/to] [-m min-count] [-t table-length]\n\
 	[--[no-]annotated-source[=name]] [--[no-]exec-counts[=name]]\n\
 	[--[no-]flat-profile[=name]] [--[no-]graph[=name]]\n\
 	[--[no-]time=name] [--all-lines] [--brief] [--debug[=level]]\n\
 	[--function-ordering] [--file-ordering]\n\
 	[--directory-path=dirs] [--display-unused-functions]\n\
+	[--object-path=dirs]\n\
 	[--file-format=name] [--file-info] [--help] [--line] [--min-count=n]\n\
 	[--no-static] [--print-path] [--separate-files]\n\
 	[--static-call-graph] [--sum] [--table-length=len] [--traditional]\n\
@@ -203,7 +205,7 @@
   xmalloc_set_program_name (whoami);
 
   while ((ch = getopt_long (argc, argv,
-	"aA::bBcCd::De:E:f:F:hiI:J::k:lLm:n::N::O:p::P::q::Q::st:Tvw:xyzZ::",
+	"aA::bBcCd::De:E:f:F:hiI:J::k:lLm:n::N::O:o:p::P::q::Q::st:Tvw:xyzZ::",
 			    long_options, 0))
 	 != EOF)
     {
@@ -335,6 +337,9 @@
 	      done (1);
 	    }
 	  break;
+	case 'o':
+	  search_list_append(&obj_search_list, optarg);
+	  break;
 	case 'p':
 	  if (optarg)
 	    {
@@ -532,33 +537,14 @@
   /*
    * Read symbol table from core file:
    */
-  core_init (a_out_name);
-
-  /*
-   * If we should ignore direct function calls, we need to load
-   * to core's text-space:
-   */
-  if (ignore_direct_calls)
-    {
-      core_get_text_space (core_bfd);
-    }
-
-  /*
-   * Create symbols from core image:
-   */
-  if (line_granularity)
-    {
-      core_create_line_syms (core_bfd);
-    }
-  else
+  core_add_file(a_out_name, 0);
+  
+  if (core_bfd == NULL)
     {
-      core_create_function_syms (core_bfd);
+      done(1);			/* couldn't even find a.out */
     }
 
-  /*
-   * Translate sym specs into syms:
-   */
-  sym_id_parse ();
+  core_init();
 
   if (file_format == FF_PROF)
     {
@@ -599,6 +585,11 @@
     }
 
   /*
+   * Translate sym specs into syms:
+   */
+  sym_id_parse ();
+
+  /*
    * If user did not specify output style, try to guess something
    * reasonable:
    */
diff -u binutils-2.13/gprof/hist.c binutils-2.13-jsgf/gprof/hist.c
--- binutils-2.13/gprof/hist.c	Tue Feb 19 10:29:08 2002
+++ binutils-2.13-jsgf/gprof/hist.c	Thu Oct 10 11:11:06 2002
@@ -31,7 +31,7 @@
 #include "sym_ids.h"
 #include "utils.h"
 
-#define UNITS_TO_CODE (offset_to_code / sizeof(UNIT))
+#define UNITS_TO_CODE (offset_to_code)
 
 static void scale_and_align_entries PARAMS ((void));
 static void print_header PARAMS ((int));
@@ -43,16 +43,137 @@
 
 bfd_vma s_lowpc;		/* Lowest address in .text.  */
 bfd_vma s_highpc = 0;		/* Highest address in .text.  */
-bfd_vma lowpc, highpc;		/* Same, but expressed in UNITs.  */
-int hist_num_bins = 0;		/* Number of histogram samples.  */
-int *hist_sample = 0;		/* Histogram samples (shorts in the file!).  */
 double hist_scale;
-char hist_dimension[16] = "seconds";
-char hist_dimension_abbrev = 's';
+static unsigned int hist_scale_int;
+static char hist_dimension[16] = "seconds";
+static char hist_dimension_abbrev = 's';
 
 static double accum_time;	/* Accumulated time so far for print_line(). */
 static double total_time;	/* Total time for all routines.  */
 
+/* Two level table to deal with sparse array of histogram
+   information.
+   XXX what about 64 bit address spaces?
+*/
+/* one-level page table which has HPG_SIZE entries pointing to pages
+   of HPG_IDX_SIZE histo buckets */
+#define HPG_BITS	20
+#define HPG_SIZE	(1 << HPG_BITS)
+#define HPG_MASK	(HPG_SIZE - 1)
+
+#define HPG_IDX		(32 - HPG_BITS)
+#define HPG_IDX_SIZE	(1 << HPG_IDX)
+#define HPG_IDX_MASK	(HPG_IDX_SIZE - 1)
+
+static int **hist_table = 0;
+
+static int hist_page (bfd_vma addr)
+{
+  addr /= hist_scale_int;
+  addr >>= HPG_IDX;
+  return addr & HPG_MASK;
+}
+
+static int hist_pg_idx(bfd_vma addr)
+{
+  addr /= hist_scale_int;
+  return addr & HPG_IDX_MASK;
+}
+
+static int hist_addr_idx(bfd_vma addr)
+{
+  return (addr - s_lowpc) / hist_scale_int;
+}
+
+bfd_vma hist_idx_addr(int idx)
+{
+  if (idx == -1)
+    return 0;
+
+  return s_lowpc + idx * hist_scale_int;
+}
+
+int *hist_sample_ptr(bfd_vma addr)
+{
+  unsigned int page = hist_page(addr);
+  unsigned int idx = hist_pg_idx(addr);
+
+  if (hist_table == NULL) 
+    {
+      hist_table = (int **)xmalloc(HPG_SIZE * sizeof(*hist_table) / hist_scale_int);
+      memset(hist_table, 0, HPG_SIZE * sizeof(*hist_table) / hist_scale_int);
+    }
+
+  if (hist_table[page] == NULL)
+    {
+      //printf("allocating page %d for addr 0x%lx (idx=%d)\n", page, addr, hist_addr_idx(addr));
+      hist_table[page] = (int *)xmalloc(HPG_IDX_SIZE * sizeof(**hist_table));
+      memset(hist_table[page], 0, HPG_IDX_SIZE * sizeof(**hist_table));
+    }
+
+  return &hist_table[page][idx];
+}
+
+int hist_sample(bfd_vma addr)
+{
+  unsigned int page = hist_page(addr);
+  unsigned int idx = hist_pg_idx(addr);
+
+  if (0)
+    printf("hist_sample(%lx [%d/%d]) -> %d\n", addr, page, idx,
+	   hist_table && hist_table[page] ? hist_table[page][idx] : 0);
+  if (hist_table == NULL || hist_table[page] == NULL)
+    return 0;
+  return hist_table[page][idx];
+}
+
+bfd_vma hist_next_sample(bfd_vma addr)
+{
+  bfd_vma orig_addr = addr;
+  unsigned int page;
+  unsigned int idx;
+
+  addr += hist_scale_int;
+
+  page = hist_page(addr);
+  idx = hist_pg_idx(addr);
+
+  if (hist_table == NULL)
+    addr = 0;
+  else if (hist_table[page] == NULL) {
+    addr -= addr % (HPG_IDX_SIZE * hist_scale_int);
+    do {
+      addr += HPG_IDX_SIZE * hist_scale_int;
+      page = hist_page(addr);
+    } while(addr != 0 && hist_table[page] == NULL);
+  }
+
+  //printf("hist_next_sample(%lx) -> %lx\n", orig_addr, addr);
+  return addr;
+}
+
+int hist_idx(bfd_vma addr)
+{
+  unsigned int idx;
+  
+  if (addr < s_lowpc)
+    return -1;
+
+  idx = addr - s_lowpc;
+  idx /= hist_scale_int;
+  return idx;
+}
+
+int hist_next_idx(unsigned idx)
+{
+  bfd_vma addr = hist_next_sample(s_lowpc + idx * hist_scale_int);
+
+  if (addr == 0)
+    return -1;
+
+  return hist_idx(addr);
+}
+
 /* Table of SI prefixes for powers of 10 (used to automatically
    scale some of the values in the flat profile).  */
 const struct
@@ -84,7 +205,7 @@
      FILE * ifp;
      const char *filename;
 {
-  bfd_vma n_lowpc, n_highpc;
+  bfd_vma n_lowpc, n_highpc, addr;
   int i, ncnt, profrate;
   UNIT count;
 
@@ -104,52 +225,53 @@
   if (!s_highpc)
     {
       /* This is the first histogram record.  */
-      s_lowpc = n_lowpc;
-      s_highpc = n_highpc;
-      lowpc = (bfd_vma) n_lowpc / sizeof (UNIT);
-      highpc = (bfd_vma) n_highpc / sizeof (UNIT);
-      hist_num_bins = ncnt;
       hz = profrate;
+      hist_scale = n_highpc - n_lowpc;
+      hist_scale /= ncnt;
+      hist_scale_int = (n_highpc - n_lowpc) / ncnt;
+      s_highpc = s_highpc;
     }
 
+  if (!s_highpc || n_lowpc < s_lowpc)
+    s_lowpc = n_lowpc;
+  if (n_highpc > s_highpc)
+    s_highpc = n_highpc;
+
   DBG (SAMPLEDEBUG,
        printf ("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %d\n",
 	       (unsigned long) n_lowpc, (unsigned long) n_highpc, ncnt);
        printf ("[hist_read_rec] s_lowpc 0x%lx s_highpc 0x%lx nsamples %d\n",
 	       (unsigned long) s_lowpc, (unsigned long) s_highpc,
-	       hist_num_bins);
-       printf ("[hist_read_rec]   lowpc 0x%lx   highpc 0x%lx\n",
-	       (unsigned long) lowpc, (unsigned long) highpc));
+	       ncnt);
+       printf ("[hist_read_rec]   hist_scale=%g hist_scale_int=%d\n",
+	       hist_scale, hist_scale_int);
+       );
 
-  if (n_lowpc != s_lowpc || n_highpc != s_highpc
-      || ncnt != hist_num_bins || hz != profrate)
+  if (hz != profrate  || (n_highpc - n_lowpc) / ncnt != hist_scale_int)
     {
-      fprintf (stderr, _("%s: `%s' is incompatible with first gmon file\n"),
-	       whoami, filename);
+      fprintf (stderr, _("%s: `%s' is incompatible with first gmon file (hz=%ld profrate=%d)\n"),
+	       whoami, filename, hz, profrate);
       done (1);
     }
 
-  if (!hist_sample)
-    {
-      hist_sample = (int *) xmalloc (hist_num_bins * sizeof (hist_sample[0]));
-      memset (hist_sample, 0, hist_num_bins * sizeof (hist_sample[0]));
-    }
-
-  for (i = 0; i < hist_num_bins; ++i)
+  for (addr = n_lowpc, i = 0; i < ncnt; ++i, addr += hist_scale_int)
     {
       if (fread (&count[0], sizeof (count), 1, ifp) != 1)
 	{
 	  fprintf (stderr,
 		  _("%s: %s: unexpected EOF after reading %d of %d samples\n"),
-		   whoami, filename, i, hist_num_bins);
+		   whoami, filename, i, ncnt);
 	  done (1);
 	}
-      hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]);
-      DBG (SAMPLEDEBUG,
-	   printf ("[hist_read_rec] 0x%lx: %u\n",
-		   (unsigned long) (n_lowpc + i * (n_highpc - n_lowpc) / ncnt),
-		   hist_sample[i]));
+      *hist_sample_ptr(addr) += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]);
+
+      if (0)
+	DBG (SAMPLEDEBUG,
+	     printf ("[hist_read_rec] 0x%lx: %u\n",
+		     (unsigned long) hist_idx_addr(i),
+		     hist_sample(hist_idx_addr(i))));
     }
+
 }
 
 
@@ -161,6 +283,7 @@
      FILE * ofp;
      const char *filename;
 {
+#if 0
   UNIT count;
   int i;
 
@@ -178,9 +301,9 @@
       done (1);
     }
 
-  for (i = 0; i < hist_num_bins; ++i)
+  for (i = 0; i > 0; i = hist_next_idx(i))
     {
-      bfd_put_16 (core_bfd, (bfd_vma) hist_sample[i], (bfd_byte *) &count[0]);
+      bfd_put_16 (core_bfd, (bfd_vma) hist_sample(hist_idx_addr(i)), (bfd_byte *) &count[0]);
 
       if (fwrite (&count[0], sizeof (count), 1, ofp) != 1)
 	{
@@ -188,6 +311,7 @@
 	  done (1);
 	}
     }
+#endif
 }
 
 
@@ -207,9 +331,9 @@
 
   for (sym = symtab.base; sym < symtab.limit; sym++)
     {
-      sym->hist.scaled_addr = sym->addr / sizeof (UNIT);
-      bin_of_entry = (sym->hist.scaled_addr - lowpc) / hist_scale;
-      bin_of_code = ((sym->hist.scaled_addr + UNITS_TO_CODE - lowpc)
+      sym->hist.scaled_addr = sym->addr;
+      bin_of_entry = (sym->hist.scaled_addr - (s_lowpc)) / hist_scale;
+      bin_of_code = ((sym->hist.scaled_addr + UNITS_TO_CODE - (s_lowpc))
 		     / hist_scale);
       if (bin_of_entry < bin_of_code)
 	{
@@ -267,31 +391,40 @@
   bfd_vma bin_low_pc, bin_high_pc;
   bfd_vma sym_low_pc, sym_high_pc;
   bfd_vma overlap, addr;
-  int bin_count, i;
   unsigned int j;
   double time, credit;
+  int idx;
 
   /* Read samples and assign to symbols.  */
-  hist_scale = highpc - lowpc;
-  hist_scale /= hist_num_bins;
   scale_and_align_entries ();
 
   /* Iterate over all sample bins.  */
-  for (i = 0, j = 1; i < hist_num_bins; ++i)
+  
+  for (idx = 0, j = 1;
+       idx != -1;
+       idx = hist_next_idx(idx))
     {
-      bin_count = hist_sample[i];
-      if (! bin_count)
+      bfd_vma bin_addr;
+      int bin_count;
+      
+      bin_addr = hist_idx_addr(idx);
+      bin_count = hist_sample(bin_addr);
+
+      if (!bin_count)
 	continue;
+    
+      //printf("idx=%d -> addr=0x%lx\n", idx, bin_addr
 
-      bin_low_pc = lowpc + (bfd_vma) (hist_scale * i);
-      bin_high_pc = lowpc + (bfd_vma) (hist_scale * (i + 1));
+      bin_low_pc = bin_addr;
+      bin_high_pc = bin_addr + hist_scale_int;
       time = bin_count;
-
+      
       DBG (SAMPLEDEBUG,
 	   printf (
-      "[assign_samples] bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%d\n",
-		    (unsigned long) (sizeof (UNIT) * bin_low_pc),
-		    (unsigned long) (sizeof (UNIT) * bin_high_pc),
+      "[assign_samples] idx=%d bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%d\n",
+		    idx,
+		    (unsigned long) (bin_low_pc),
+		    (unsigned long) (bin_high_pc),
 		    bin_count));
       total_time += time;
 
@@ -313,14 +446,16 @@
 
 	  overlap =
 	    MIN (bin_high_pc, sym_high_pc) - MAX (bin_low_pc, sym_low_pc);
+
 	  if (overlap > 0)
 	    {
 	      DBG (SAMPLEDEBUG,
 		   printf (
-	       "[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n",
+	       "[assign_samples] [0x%lx,0x%lx) %s-%s gets %f ticks %ld overlap\n",
 			   (unsigned long) symtab.base[j].addr,
-			   (unsigned long) (sizeof (UNIT) * sym_high_pc),
-			   symtab.base[j].name, overlap * time / hist_scale,
+			   (unsigned long) (sym_high_pc),
+			   symtab.base[j].name, symtab.base[j+1].name,
+			   overlap * time / hist_scale,
 			   (long) overlap));
 
 	      addr = symtab.base[j].addr;
@@ -361,7 +496,7 @@
   if (bsd_style_output)
     {
       printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
-	      (long) hist_scale * sizeof (UNIT));
+	      (long) hist_scale);
       if (total_time > 0.0)
 	{
 	  printf (_(" for %.2f%% of %.2f %s\n\n"),
diff -u binutils-2.13/gprof/hist.h binutils-2.13-jsgf/gprof/hist.h
--- binutils-2.13/gprof/hist.h	Thu Jan 31 04:56:07 2002
+++ binutils-2.13-jsgf/gprof/hist.h	Tue Oct  1 23:59:00 2002
@@ -23,9 +23,16 @@
 
 extern bfd_vma s_lowpc;		/* Lowpc from the profile file.  */
 extern bfd_vma s_highpc;	/* Highpc from the profile file.  */
-extern bfd_vma lowpc, highpc;	/* Range profiled, in UNIT's.  */
-extern int hist_num_bins;	/* Number of histogram bins.  */
-extern int *hist_sample;	/* Code histogram.  */
+//extern int hist_num_bins;	/* Number of histogram bins.  */
+//extern int *hist_sample;	/* Code histogram.  */
+
+extern int	hist_sample	 PARAMS ((bfd_vma addr));
+extern int     *hist_sample_ptr	 PARAMS ((bfd_vma addr));
+extern bfd_vma	hist_next_sample PARAMS ((bfd_vma addr));
+
+extern int hist_idx		 PARAMS ((bfd_vma addr));
+extern int hist_next_idx	 PARAMS ((unsigned int idx));
+extern bfd_vma hist_idx_addr	 PARAMS ((int idx));
 
 /* Scale factor converting samples to pc values:
    each sample covers HIST_SCALE bytes.  */
diff -u binutils-2.13/gprof/i386.c binutils-2.13-jsgf/gprof/i386.c
--- binutils-2.13/gprof/i386.c	Tue Jul 30 11:20:36 2002
+++ binutils-2.13-jsgf/gprof/i386.c	Mon Oct  7 12:06:48 2002
@@ -56,8 +56,11 @@
   unsigned char *instructp;
   Sym *child;
   bfd_vma pc, destpc;
+  asection *text_sect;
+  PTR text_space;
 
-  if (core_text_space == 0)
+  text_space = core_get_text_space(p_lowpc, &text_sect);
+  if (text_space == 0)
     {
       return;
     }
@@ -75,7 +78,7 @@
 
   for (pc = p_lowpc; pc < p_highpc; ++pc)
     {
-      instructp = (unsigned char *) core_text_space + pc - core_text_sect->vma;
+      instructp = (unsigned char *) text_space + pc - text_sect->vma;
       if (i386_iscall (instructp))
 	{
 	  DBG (CALLDEBUG,
diff -u binutils-2.13/gprof/mips.c binutils-2.13-jsgf/gprof/mips.c
--- binutils-2.13/gprof/mips.c	Tue Jul 30 11:20:36 2002
+++ binutils-2.13-jsgf/gprof/mips.c	Mon Oct  7 12:10:11 2002
@@ -49,6 +49,10 @@
   int offset;
   Sym *child;
   static boolean inited = false;
+  asection *text_sect;
+  PTR text_space;
+
+  text_space = core_get_text_space(p_lowpc, &text_sect);
 
   if (!inited)
     {
@@ -59,7 +63,7 @@
       indirect_child.cg.cyc.head = &indirect_child;
     }
 
-  if (!core_text_space)
+  if (!text_space)
     {
       return;
     }
@@ -76,7 +80,7 @@
 			  (unsigned long) p_highpc));
   for (pc = p_lowpc; pc < p_highpc; pc += 4)
     {
-      op = bfd_get_32 (core_bfd, &((char *)core_text_space)[pc - s_lowpc]);
+      op = bfd_get_32 (core_bfd, &((char *)text_space)[pc - s_lowpc]);
       if ((op & 0xfc000000) == 0x0c000000)
 	{
 	  /* This is a "jal" instruction.  Check that the destination
Common subdirectories: binutils-2.13/gprof/po and binutils-2.13-jsgf/gprof/po
diff -u binutils-2.13/gprof/source.c binutils-2.13-jsgf/gprof/source.c
--- binutils-2.13/gprof/source.c	Fri Feb  1 00:24:16 2002
+++ binutils-2.13-jsgf/gprof/source.c	Mon Oct  7 15:20:18 2002
@@ -27,20 +27,47 @@
 
 #define EXT_ANNO "-ann"		/* Postfix of annotated files.  */
 
+static unsigned int hash_path PARAMS ((const char *));
+
 /* Default option values.  */
 boolean create_annotation_files = false;
 
 Search_List src_search_list = {0, 0};
-Source_File *first_src_file = 0;
+Source_File *first_src_file = NULL;
+
+#define SRC_HASHSZ	1023
+static Source_File *srcfile_hash[SRC_HASHSZ];
+
+static unsigned int hash_path(path)
+     const char *path;
+{
+  unsigned char *cp;
+  unsigned hash = 0;
+
+  cp = strrchr(path, '/');
+  if (cp == NULL)
+    cp = path;
 
+  for(; *cp; cp++) {
+    hash ^= *cp;
+    hash = (hash << 17) | (hash >> (32-17));
+  }
+
+  hash %= SRC_HASHSZ;
+
+  return hash;
+}
 
 Source_File *
 source_file_lookup_path (path)
      const char *path;
 {
+  unsigned int hash = 0;
   Source_File *sf;
 
-  for (sf = first_src_file; sf; sf = sf->next)
+  hash = hash_path(path);
+
+  for (sf = srcfile_hash[hash]; sf; sf = sf->hash_next)
     {
       if (FILENAME_CMP (path, sf->name) == 0)
 	break;
@@ -54,6 +81,9 @@
       memset (sf, 0, sizeof (*sf));
 
       sf->name = xstrdup (path);
+      sf->hash_next = srcfile_hash[hash];
+      srcfile_hash[hash] = sf;
+
       sf->next = first_src_file;
       first_src_file = sf;
     }
@@ -68,12 +98,13 @@
 {
   const char *fname;
   Source_File *sf;
+  unsigned int hash = hash_path(filename);
 
   /* The user cannot know exactly how a filename will be stored in
      the debugging info (e.g., ../include/foo.h
      vs. /usr/include/foo.h).  So we simply compare the filename
      component of a path only.  */
-  for (sf = first_src_file; sf; sf = sf->next)
+  for (sf = srcfile_hash[hash]; sf; sf = sf->hash_next)
     {
       fname = strrchr (sf->name, '/');
 
diff -u binutils-2.13/gprof/source.h binutils-2.13-jsgf/gprof/source.h
--- binutils-2.13/gprof/source.h	Fri Feb  1 00:24:16 2002
+++ binutils-2.13-jsgf/gprof/source.h	Thu Oct 10 11:07:57 2002
@@ -29,6 +29,7 @@
     int num_lines;		/* # of lines in file.  */
     int nalloced;		/* Number of lines allocated.  */
     void **line;		/* Usage-dependent per-line data.  */
+    struct source_file *hash_next;
   }
 Source_File;
 
diff -u binutils-2.13/gprof/sparc.c binutils-2.13-jsgf/gprof/sparc.c
--- binutils-2.13/gprof/sparc.c	Tue Jul 30 11:20:36 2002
+++ binutils-2.13-jsgf/gprof/sparc.c	Mon Oct  7 12:08:50 2002
@@ -50,8 +50,12 @@
   bfd_vma pc, dest_pc;
   unsigned int insn;
   Sym *child;
+  asection *text_sect;
+  PTR text_space;
 
-  if (core_text_space == 0)
+  text_space = core_get_text_space(p_lowpc, &text_sect);
+
+  if (text_space == 0)
     {
       return;
     }
@@ -68,8 +72,8 @@
 			  (unsigned long) p_highpc));
   for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4)
     {
-      insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space
-				    + pc - core_text_sect->vma));
+      insn = bfd_get_32 (core_bfd, ((unsigned char *) text_space
+				    + pc - text_sect->vma));
       if (insn & CALL)
 	{
 	  DBG (CALLDEBUG,
diff -u binutils-2.13/gprof/sym_ids.c binutils-2.13-jsgf/gprof/sym_ids.c
--- binutils-2.13/gprof/sym_ids.c	Fri Feb  1 00:24:16 2002
+++ binutils-2.13-jsgf/gprof/sym_ids.c	Thu Oct 10 11:11:05 2002
@@ -75,7 +75,7 @@
 
 static Source_File non_existent_file =
 {
-  0, "<non-existent-file>", 0, 0, 0, NULL
+  NULL, "<non-existent-file>", 0, 0, 0, NULL, NULL
 };
 
 
@@ -357,7 +357,7 @@
     {
       DBG (IDDEBUG, printf ("[sym_id_parse] syms[%s]:\n",
 			    table_name[tab - &syms[0]]));
-      symtab_finalize (tab);
+      symtab_finalize (tab, 0);
     }
 }
 
diff -u binutils-2.13/gprof/symtab.c binutils-2.13-jsgf/gprof/symtab.c
--- binutils-2.13/gprof/symtab.c	Fri Feb  1 00:24:16 2002
+++ binutils-2.13-jsgf/gprof/symtab.c	Thu Oct 10 11:10:06 2002
@@ -29,7 +29,7 @@
 static int cmp_addr PARAMS ((const PTR, const PTR));
 
 Sym_Table symtab;
-
+int symtab_needs_finalize = 1;
 
 /* Initialize a symbol (so it's empty).  */
 
@@ -79,8 +79,9 @@
 
 
 void
-symtab_finalize (tab)
+symtab_finalize (tab, text_sect)
      Sym_Table *tab;
+     asection *text_sect;
 {
   Sym *src, *dst;
   bfd_vma prev_addr;
@@ -151,8 +152,8 @@
 	}
     }
 
-  if (tab->len > 0 && dst[-1].end_addr == 0)
-    dst[-1].end_addr = core_text_sect->vma + core_text_sect->_raw_size - 1;
+  if (text_sect && tab->len > 0 && dst[-1].end_addr == 0)
+    dst[-1].end_addr = text_sect->vma + text_sect->_raw_size - 1;
 
   DBG (AOUTDEBUG | IDDEBUG,
        printf ("[symtab_finalize]: removed %d duplicate entries\n",
diff -u binutils-2.13/gprof/symtab.h binutils-2.13-jsgf/gprof/symtab.h
--- binutils-2.13/gprof/symtab.h	Fri Feb  1 00:24:16 2002
+++ binutils-2.13-jsgf/gprof/symtab.h	Thu Oct 10 11:10:05 2002
@@ -112,7 +112,7 @@
 extern Sym_Table symtab;	/* The symbol table.  */
 
 extern void sym_init        PARAMS ((Sym *));
-extern void symtab_finalize PARAMS ((Sym_Table *));
+extern void symtab_finalize PARAMS ((Sym_Table *, asection *));
 #ifdef DEBUG
 extern Sym *dbg_sym_lookup  PARAMS ((Sym_Table *, bfd_vma));
 #endif
diff -u binutils-2.13/gprof/tahoe.c binutils-2.13-jsgf/gprof/tahoe.c
--- binutils-2.13/gprof/tahoe.c	Tue Jul 30 11:20:36 2002
+++ binutils-2.13-jsgf/gprof/tahoe.c	Mon Oct  7 12:10:15 2002
@@ -232,7 +232,10 @@
   tahoe_operandenum firstmode;
   bfd_vma pc, destpc;
   static boolean inited = false;
+  asection *text_sect;
+  PTR text_space;
 
+  text_space = core_get_text_space(p_lowpc, &text_sect);
   if (!inited)
     {
       inited = true;
@@ -241,7 +244,7 @@
       indirectchild.cg.cyc.head = &indirectchild;
     }
 
-  if (core_text_space == 0)
+  if (text_space == 0)
     {
       return;
     }
@@ -259,8 +262,8 @@
   for (pc = p_lowpc; pc < p_highpc; pc += length)
     {
       length = 1;
-      instructp = ((unsigned char *) core_text_space
-		   + pc - core_text_sect->vma);
+      instructp = ((unsigned char *) text_space
+		   + pc - text_sect->vma);
       if ((*instructp & 0xff) == CALLF)
 	{
 	  /*
diff -u binutils-2.13/gprof/vax.c binutils-2.13-jsgf/gprof/vax.c
--- binutils-2.13/gprof/vax.c	Tue Jul 30 11:20:36 2002
+++ binutils-2.13-jsgf/gprof/vax.c	Mon Oct  7 12:10:16 2002
@@ -243,6 +243,10 @@
   operandenum firstmode;
   bfd_vma pc, destpc;
   static boolean inited = false;
+  asection *text_sect;
+  PTR text_space;
+
+  text_space = core_get_text_space(p_lowpc, &text_sect);
 
   if (!inited)
     {
@@ -252,7 +256,7 @@
       indirectchild.cg.cyc.head = &indirectchild;
     }
 
-  if (core_text_space == 0)
+  if (text_space == 0)
     {
       return;
     }
@@ -270,8 +274,8 @@
   for (pc = p_lowpc; pc < p_highpc; pc += length)
     {
       length = 1;
-      instructp = ((unsigned char *) core_text_space
-		   + pc - core_text_sect->vma);
+      instructp = ((unsigned char *) text_space
+		   + pc - text_sect->vma);
       if ((*instructp & 0xff) == CALLS)
 	{
 	  /*
