This is the mail archive of the binutils@sources.redhat.com mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

proposed fix for PR 114


PR 114 relates to gprof --line taking a long time.  The problem is
that gprof is stupid about generating the "line table" -- the list of
source lines in the program and their address.  It does it by calling
bfd_find_nearest_line(), over the full range of valid text addresses,
asking "Are you my daddy?"  :-)

I've prototyped a fix which slightly alters BFD's interface, adding a
bfd_vma* parameter to bfd_find_nearest_line that returns the address
of the next source line (where possible; otherwise it returns the
requested address).  This allows us to skip through a large percentage
of the program text and reducing the call overhead.  My experiments
show a ~40x speedup on the "blastall" program submitted by the PR
originator.

This seems to have one flaw, however.  Sometimes, due to instruction
reordering at higher optimisation levels, a source line B can begin at
an address that lies between the start and end of source line A.  With
my patch, that source line will not appear in the profile output.  I'm
not quite sure how to handle this, nor am I sure if this would be
considered catastrophic.

Comments?

Ben

(BFD changes omitted for now)

Index: corefile.c
===================================================================
RCS file: /cvs/src/src/gprof/corefile.c,v
retrieving revision 1.17
diff -u -r1.17 corefile.c
--- corefile.c	26 May 2004 04:55:55 -0000	1.17
+++ corefile.c	26 May 2004 06:03:47 -0000
@@ -41,8 +41,7 @@
 
 static void read_function_mappings (const char *);
 static int core_sym_class (asymbol *);
-static bfd_boolean get_src_info
-  (bfd_vma, const char **, const char **, int *);
+static bfd_boolean get_src_info (bfd_vma, const char **, const char **, int *, bfd_vma *);
 
 extern void i386_find_call  (Sym *, bfd_vma, bfd_vma);
 extern void alpha_find_call (Sym *, bfd_vma, bfd_vma);
@@ -365,14 +364,16 @@
 /* Get whatever source info we can get regarding address ADDR.  */
 
 static bfd_boolean
-get_src_info (bfd_vma addr, const char **filename, const char **name, int *line_num)
+get_src_info (bfd_vma addr, const char **filename, const char **name, int *line_num,
+	      bfd_vma *addr_next)
 {
   const char *fname = 0, *func_name = 0;
   int l = 0;
+  bfd_vma next;
 
   if (bfd_find_nearest_line (core_bfd, core_text_sect, core_syms,
 			     addr - core_text_sect->vma,
-			     &fname, &func_name, (unsigned int *) &l)
+			     &fname, &func_name, (unsigned int *) &l, &next)
       && fname && func_name && l)
     {
       DBG (AOUTDEBUG, printf ("[get_src_info] 0x%lx -> %s:%d (%s)\n",
@@ -380,6 +381,7 @@
       *filename = fname;
       *name = func_name;
       *line_num = l;
+      *addr_next = next;
       return TRUE;
     }
   else
@@ -500,9 +502,10 @@
       /* Lookup filename and line number, if we can.  */
       {
 	const char *filename, *func_name;
+	bfd_vma unused;
 
 	if (get_src_info (symtab.limit->addr, &filename, &func_name,
-			  &symtab.limit->line_num))
+			  &symtab.limit->line_num, &unused))
 	  {
 	    symtab.limit->file = source_file_lookup_path (filename);
 
@@ -590,6 +593,8 @@
   const char *filename;
   int prev_line_num;
   Sym_Table ltab;
+  bfd_vma vma_high;
+  bfd_vma addr_next_line;
 
   /* Create symbols for functions as usual.  This is necessary in
      cases where parts of a program were not compiled with -g.  For
@@ -612,12 +617,12 @@
   ltab.len = 0;
   prev_line_num = 0;
 
-  bfd_vma vma_high = core_text_sect->vma + core_text_sect->_raw_size;
+  vma_high = core_text_sect->vma + core_text_sect->_raw_size;
   for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size)
     {
       unsigned int len;
 
-      if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num)
+      if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num, &addr_next_line)
 	  || (prev_line_num == dummy.line_num
 	      && prev_name != NULL
 	      && strcmp (prev_name, dummy.name) == 0
@@ -626,6 +631,8 @@
 
       ++ltab.len;
       prev_line_num = dummy.line_num;
+      if (addr_next_line > vma)
+	vma = addr_next_line - min_insn_size;
 
       len = strlen (dummy.name);
       if (len >= prev_name_len)
@@ -683,7 +690,8 @@
     {
       sym_init (ltab.limit);
 
-      if (!get_src_info (vma, &filename, &ltab.limit->name, &ltab.limit->line_num)
+      if (!get_src_info (vma, &filename, &ltab.limit->name, &ltab.limit->line_num,
+			 &addr_next_line)
 	  || (prev && prev->line_num == ltab.limit->line_num
 	      && strcmp (prev->name, ltab.limit->name) == 0
 	      && strcmp (prev->file->name, filename) == 0))
@@ -722,6 +730,9 @@
 			      ltab.limit->name,
 			      (unsigned long) ltab.limit->addr));
       ++ltab.limit;
+
+      if (addr_next_line > vma)
+	vma = addr_next_line - min_insn_size;
     }
 
   /* Update sentinels.  */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]