This is the mail archive of the binutils@sourceware.org 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]

Re: [patch] Add external symbol table file support for gprof


Hi Nick,

I updated the patch, with the following modification:

* The return values of the functions such as sscanf () and fseek () are checked.

* The fixed length buffers on the stack are replaced by buffers dynamically allocated on the heap.

* Make sure that the reading of each line of the external symbol table is successful.

* By fseek (f, 0, 0), the twice fopen/fclose are reduced to one fopen/fclose.

* The description of the new feature is added in gprof/gprof.texi

Besides, I agree to file a binutils copyright assignment with the FSF. :)

Best regards,
  Homer

diff -rup binutils-2.19.51.origin/gprof/corefile.c binutils-2.19.51/gprof/corefile.c
--- binutils-2.19.51.origin/gprof/corefile.c	2009-05-01 13:28:01.000000000 +0800
+++ binutils-2.19.51/gprof/corefile.c	2009-05-05 19:13:47.000000000 +0800
@@ -434,6 +434,104 @@ get_src_info (bfd_vma addr, const char *
     }
 }
 
+/* Return number of symbols in a symbol-table file.  */
+
+static int 
+num_of_syms_in (FILE *f)
+{
+  const int BUFSIZE = 1024;
+  char *buf = (char *) xmalloc (BUFSIZE);
+  char *address = (char *) xmalloc (BUFSIZE);
+  char type;
+  char *name = (char *) xmalloc (BUFSIZE);
+  int num = 0;
+  
+  while (!feof (f) && fgets (buf, BUFSIZE - 1, f))
+    {
+      if(sscanf (buf, "%s %c %s", address, &type, name) == 3)
+        if (type == 't' || type == 'T')
+          ++num;
+    }
+
+  free (buf);
+  free (address);
+  free (name);
+
+  return num;
+}
+
+/* Read symbol table from a file.  */
+
+void
+core_create_syms_from (const char *sym_table_file)
+{
+  const int BUFSIZE = 1024;
+  char *buf = (char *) xmalloc (BUFSIZE);
+  char *address = (char *) xmalloc (BUFSIZE);
+  char type;
+  char *name = (char *) xmalloc (BUFSIZE);
+  bfd_vma min_vma = ~(bfd_vma) 0;
+  bfd_vma max_vma = 0;
+  FILE *f;
+
+  f = fopen (sym_table_file, "r");
+  if (!f)
+    {
+      fprintf (stderr, _("%s: could not open %s.\n"), whoami, sym_table_file);
+      done (1);
+    }
+
+  /* Pass 1 - determine upper bound on number of function names.  */
+  symtab.len = num_of_syms_in (f);
+
+  if (symtab.len == 0)
+    {
+      fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, sym_table_file);
+      done (1);
+    }
+
+  symtab.base = (Sym *) xmalloc (symtab.len * sizeof (Sym));
+
+  /* Pass 2 - create symbols.  */
+  symtab.limit = symtab.base;
+
+  if (fseek (f, 0, SEEK_SET) != 0)
+    {
+      perror (sym_table_file);
+      done (1);
+    }
+
+  while (!feof (f) && fgets (buf, sizeof (buf), f))
+    {
+      if(sscanf (buf, "%s %c %s", address, &type, name) == 3)
+        if (type != 't' && type != 'T')
+          continue;
+
+      sym_init (symtab.limit);
+
+      sscanf (address, "%lx", &(symtab.limit->addr) );
+
+      symtab.limit->name = (char *) xmalloc (strlen (name) + 1);
+      strcpy ((char *)symtab.limit->name, name);
+      symtab.limit->mapped = 0;
+      symtab.limit->is_func = TRUE;
+      symtab.limit->is_bb_head = TRUE;
+      symtab.limit->is_static = (type == 't');
+      min_vma = MIN (symtab.limit->addr, min_vma);
+      max_vma = MAX (symtab.limit->addr, max_vma);
+
+      ++symtab.limit;
+    }
+  fclose (f);
+
+  symtab.len = symtab.limit - symtab.base;
+  symtab_finalize (&symtab);
+
+  free (buf);
+  free (address);
+  free (name);
+}
+
 /* Read in symbol table from core.
    One symbol per function is entered.  */
 
diff -rup binutils-2.19.51.origin/gprof/corefile.h binutils-2.19.51/gprof/corefile.h
--- binutils-2.19.51.origin/gprof/corefile.h	2009-05-01 13:28:01.000000000 +0800
+++ binutils-2.19.51/gprof/corefile.h	2009-05-01 14:17:05.000000000 +0800
@@ -41,5 +41,6 @@ extern void core_init                  (
 extern void core_get_text_space        (bfd *);
 extern void core_create_function_syms  (void);
 extern void core_create_line_syms      (void);
+extern void core_create_syms_from      (const char *);
 
 #endif /* corefile_h */
diff -rup binutils-2.19.51.origin/gprof/gprof.c binutils-2.19.51/gprof/gprof.c
--- binutils-2.19.51.origin/gprof/gprof.c	2009-05-01 13:28:01.000000000 +0800
+++ binutils-2.19.51/gprof/gprof.c	2009-05-05 19:42:49.000000000 +0800
@@ -49,6 +49,7 @@ static void usage (FILE *, int) ATTRIBUT
 
 const char *whoami;
 const char *function_mapping_file;
+const char *external_symbol_table;
 const char *a_out_name = A_OUTNAME;
 long hz = HZ_WRONG;
 
@@ -98,6 +99,7 @@ static struct option long_options[] =
   {"line", no_argument, 0, 'l'},
   {"no-static", no_argument, 0, 'a'},
   {"ignore-non-functions", no_argument, 0, 'D'},
+  {"external-symbol-table", required_argument, 0, 'S'},
 
     /* output styles: */
 
@@ -155,7 +157,7 @@ static void
 usage (FILE *stream, int status)
 {
   fprintf (stream, _("\
-Usage: %s [-[abcDhilLsTvwxyz]] [-[ACeEfFJnNOpPqQZ][name]] [-I dirs]\n\
+Usage: %s [-[abcDhilLsTvwxyz]] [-[ACeEfFJnNOpPqSQZ][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\
@@ -166,7 +168,7 @@ Usage: %s [-[abcDhilLsTvwxyz]] [-[ACeEfF
 	[--no-static] [--print-path] [--separate-files]\n\
 	[--static-call-graph] [--sum] [--table-length=len] [--traditional]\n\
 	[--version] [--width=n] [--ignore-non-functions]\n\
-	[--demangle[=STYLE]] [--no-demangle] [@FILE]\n\
+	[--demangle[=STYLE]] [--no-demangle] [--external-symbol-table=name] [@FILE]\n\
 	[image-file] [profile-file...]\n"),
 	   whoami);
   if (REPORT_BUGS_TO[0] && status == 0)
@@ -199,7 +201,7 @@ main (int argc, char **argv)
   expandargv (&argc, &argv);
 
   while ((ch = getopt_long (argc, argv,
-	"aA::bBcC::d::De:E:f:F:hiI:J::k:lLm:n:N:O:p::P::q::Q::rR:st:Tvw:xyzZ::",
+	"aA::bBcC::d::De:E:f:F:hiI:J::k:lLm:n:N:O:p::P::q::Q::rR:sS:t:Tvw:xyzZ::",
 			    long_options, 0))
 	 != EOF)
     {
@@ -398,6 +400,10 @@ main (int argc, char **argv)
 	  output_style |= STYLE_SUMMARY_FILE;
 	  user_specified |= STYLE_SUMMARY_FILE;
 	  break;
+	case 'S':
+	  external_symbol_table = optarg;
+	  DBG (AOUTDEBUG, printf ("external-symbol-table: %s\n", optarg));
+	  break;
 	case 't':
 	  bb_table_length = atoi (optarg);
 	  if (bb_table_length < 0)
@@ -512,10 +518,16 @@ This program is free software.  This pro
     core_get_text_space (core_bfd);
 
   /* Create symbols from core image.  */
-  if (line_granularity)
-    core_create_line_syms ();
+  if (external_symbol_table)
+    core_create_syms_from (external_symbol_table);
   else
-    core_create_function_syms ();
+    {
+      /* Create symbols from core image.  */
+      if (line_granularity)
+        core_create_line_syms ();
+      else
+        core_create_function_syms ();
+    }
 
   /* Translate sym specs into syms.  */
   sym_id_parse ();
diff -rup binutils-2.19.51.origin/gprof/gprof.texi binutils-2.19.51/gprof/gprof.texi
--- binutils-2.19.51.origin/gprof/gprof.texi	2009-05-01 13:28:01.000000000 +0800
+++ binutils-2.19.51/gprof/gprof.texi	2009-05-05 19:33:35.000000000 +0800
@@ -128,7 +128,8 @@ gprof [ -[abcDhilLrsTvwxyz] ] [ -[ACeEfF
  [ --static-call-graph ] [ --sum ] [ --table-length=@var{len} ]
  [ --traditional ] [ --version ] [ --width=@var{n} ]
  [ --ignore-non-functions ] [ --demangle[=@var{STYLE}] ]
- [ --no-demangle ] [ @var{image-file} ] [ @var{profile-file} @dots{} ]
+ [ --no-demangle ] [--external-symbol-table=name] 
+ [ @var{image-file} ] [ @var{profile-file} @dots{} ]
 @c man end
 @end smallexample
 
@@ -720,6 +721,13 @@ Symbols that are executed less than @var
 The @samp{-n} option causes @code{gprof}, in its call graph analysis,
 to only propagate times for symbols matching @var{symspec}.
 
+@item -S@var{filename}
+@itemx --external-symbol-table=@var{filename}
+The @samp{-S} option causes @code{gprof} to read an external symbol table
+file, such as @file{/proc/kallsyms}, rather than read the symbol table 
+from the given object file (the default is @code{a.out}). This is useful 
+for profiling kernel modules.
+
 @item -N@var{symspec}
 @itemx --no-time=@var{symspec}
 The @samp{-n} option causes @code{gprof}, in its call graph analysis,


      


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