This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC 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: [4.1 patch] relocate profile data file


Nathan Sidwell wrote:

I'll take care of it. Thanks

I committed a slightly edited patch. I fixed some formatting & typos. Plus comonized a call to alloca and used IS_ABSOLUTE_PATH so we have some chance of working on msdos file systems.

nathan

--
Nathan Sidwell    ::   http://www.codesourcery.com   ::     CodeSourcery LLC
nathan@codesourcery.com    ::     http://www.planetfall.pwp.blueyonder.co.uk

Index: ChangeLog
===================================================================
RCS file: /cvs/gcc/gcc/gcc/ChangeLog,v
retrieving revision 2.8703
diff -c -3 -p -r2.8703 ChangeLog
*** ChangeLog	10 May 2005 10:27:44 -0000	2.8703
--- ChangeLog	10 May 2005 15:16:16 -0000
***************
*** 1,3 ****
--- 1,18 ----
+ 2005-05-11  Grigory Zagorodnev  <grigory.zagorodnev@intel.com>
+             H.J. Lu  <hongjiu.lu@intel.com   
+ 
+ 	* libgcov.c (create_file_directory): New function. Create
+ 	directory for the given file name.
+ 	(gcov_max_filename): New static var. Keeps size of the longest
+ 	file name.
+ 	(gcov_exit): Always try to create directory for output
+ 	file. Relocate each filename basing on environment vars.
+ 	(__gcov_init): Remember the longest file name.
+ 	* tsystem.h: include filenames.h to get IS_DIR_SEPARATOR
+ 	* doc/gcov.texi (Cross-profiling): New node documenting
+ 	cross-profiling management.
+ 	* doc/invoke.texi (-fprofile-arcs): Add xref to cross-profiling.
+ 
  2005-05-10  Nathan Sidwell  <nathan@codesourcery.com>
  
  	* crtstuff.c: Revert part of 2005-05-08 Change.
Index: libgcov.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/libgcov.c,v
retrieving revision 1.30
diff -c -3 -p -r1.30 libgcov.c
*** libgcov.c	8 May 2005 10:13:18 -0000	1.30
--- libgcov.c	10 May 2005 15:16:17 -0000
*************** static struct gcov_info *gcov_list;
*** 88,95 ****
     object file included in multiple programs.  */
  static gcov_unsigned_t gcov_crc32;
  
  static int
! gcov_version (struct gcov_info *ptr, gcov_unsigned_t version)
  {
    if (version != GCOV_VERSION)
      {
--- 88,136 ----
     object file included in multiple programs.  */
  static gcov_unsigned_t gcov_crc32;
  
+ /* Size of the longest file name. */
+ static size_t gcov_max_filename = 0;
+ 
+ /* Make sure path compenent of the given FILENAME exists, create 
+    missing directories. FILENAME must be writable. 
+    Returns zero on success, or -1 if an error occurred.  */
+ 
  static int
! create_file_directory (char *filename)
! {
!   char *s;
! 
!   for (s = filename + 1; *s != '\0'; s++)
!     if (IS_DIR_SEPARATOR(*s))
!       {
!         char sep = *s;
! 	*s  = '\0';
! 
!         /* Try to make directory if it doesn't already exist.  */
!         if (access (filename, F_OK) == -1
!             && mkdir (filename, 0755) == -1
!             /* The directory might have been made by another process.  */
! 	    && errno != EEXIST)
! 	  {
!             fprintf (stderr, "profiling:%s:Cannot create directory\n",
! 		     filename);
!             *s = sep;
! 	    return -1;
! 	  };
!         
! 	*s = sep;
!       };
!   return 0;
! }
! 
! /* Check if VERSION of the info block PTR matches libgcov one.
!    Return 1 on success, or zero in case of versions mismatch.
!    If FILENAME is not NULL, its value used for reporting purposes 
!    instead of value from the info block.  */
!    
! static int
! gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
! 	      const char *filename)
  {
    if (version != GCOV_VERSION)
      {
*************** gcov_version (struct gcov_info *ptr, gco
*** 100,106 ****
        
        fprintf (stderr,
  	       "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
! 	       ptr->filename, e, v);
        return 0;
      }
    return 1;
--- 141,147 ----
        
        fprintf (stderr,
  	       "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
! 	       filename? filename : ptr->filename, e, v);
        return 0;
      }
    return 1;
*************** gcov_exit (void)
*** 123,128 ****
--- 164,173 ----
    const struct gcov_ctr_info *ci_ptr;
    unsigned t_ix;
    gcov_unsigned_t c_num;
+   const char *gcov_prefix;
+   int gcov_prefix_strip = 0;
+   size_t prefix_length;
+   char *gi_filename, *gi_filename_up;
  
    memset (&all, 0, sizeof (all));
    /* Find the totals for this execution.  */
*************** gcov_exit (void)
*** 147,152 ****
--- 192,224 ----
  	}
      }
  
+   /* Get file name relocation prefix.  Non-absolute values are ignored. */
+   gcov_prefix = getenv("GCOV_PREFIX");
+   if (gcov_prefix && IS_ABSOLUTE_PATH (gcov_prefix))
+     {
+       /* Check if the level of dirs to strip off specified. */
+       char *tmp = getenv("GCOV_PREFIX_STRIP");
+       if (tmp)
+         {
+           gcov_prefix_strip = atoi (tmp);
+           /* Do not consider negative values. */
+           if (gcov_prefix_strip < 0)
+             gcov_prefix_strip = 0;
+         }
+       
+       prefix_length = strlen(gcov_prefix);
+ 
+       /* Remove an unneccesary trailing '/' */
+       if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1]))
+ 	prefix_length--;
+     }
+   
+   /* Allocate and initialize the filename scratch space.  */
+   gi_filename = alloca (prefix_length + gcov_max_filename + 1);
+   if (prefix_length)
+     memcpy (gi_filename, gcov_prefix, prefix_length);
+   gi_filename_up = gi_filename + prefix_length;
+   
    /* Now merge each file.  */
    for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next)
      {
*************** gcov_exit (void)
*** 165,170 ****
--- 237,264 ----
        memset (&this_object, 0, sizeof (this_object));
        memset (&object, 0, sizeof (object));
        
+       /* Build relocated filename, stripping off leading 
+          directories from the initial filename if requested. */
+       if (gcov_prefix_strip > 0)
+         {
+           int level = 0;
+           const char *fname = gi_ptr->filename;
+           const char *s;
+ 
+           /* Skip selected directory levels. */
+ 	  for (s = fname + 1; (*s != '\0') && (level < gcov_prefix_strip); s++)
+ 	    if (IS_DIR_SEPARATOR(*s))
+ 	      {
+ 		fname = s;
+ 		level++;
+ 	      };
+ 
+           /* Update complete filename with stripped original. */
+           strcpy (gi_filename_up, fname);
+         }
+       else
+         strcpy (gi_filename_up, gi_ptr->filename);
+ 
        /* Totals for this object file.  */
        ci_ptr = gi_ptr->counts;
        for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++)
*************** gcov_exit (void)
*** 201,210 ****
  	  fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
  	}
        
!       if (!gcov_open (gi_ptr->filename))
  	{
! 	  fprintf (stderr, "profiling:%s:Cannot open\n", gi_ptr->filename);
! 	  continue;
  	}
  
        tag = gcov_read_unsigned ();
--- 295,314 ----
  	  fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
  	}
        
!       if (!gcov_open (gi_filename))
  	{
! 	  /* Open failed likely due to missed directory.
! 	     Create directory and retry to open file. */
!           if (create_file_directory (gi_filename))
! 	    {
! 	      fprintf (stderr, "profiling:%s:Skip\n", gi_filename);
! 	      continue;
! 	    }
! 	  if (!gcov_open (gi_filename))
! 	    {
!               fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename);
! 	      continue;
! 	    }
  	}
  
        tag = gcov_read_unsigned ();
*************** gcov_exit (void)
*** 214,224 ****
  	  if (tag != GCOV_DATA_MAGIC)
  	    {
  	      fprintf (stderr, "profiling:%s:Not a gcov data file\n",
! 		       gi_ptr->filename);
  	      goto read_fatal;
  	    }
  	  length = gcov_read_unsigned ();
! 	  if (!gcov_version (gi_ptr, length))
  	    goto read_fatal;
  
  	  length = gcov_read_unsigned ();
--- 318,328 ----
  	  if (tag != GCOV_DATA_MAGIC)
  	    {
  	      fprintf (stderr, "profiling:%s:Not a gcov data file\n",
! 		       gi_filename);
  	      goto read_fatal;
  	    }
  	  length = gcov_read_unsigned ();
! 	  if (!gcov_version (gi_ptr, length, gi_filename))
  	    goto read_fatal;
  
  	  length = gcov_read_unsigned ();
*************** gcov_exit (void)
*** 242,248 ****
  		{
  		read_mismatch:;
  		  fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
! 			   gi_ptr->filename,
  			   f_ix + 1 ? "function" : "summaries");
  		  goto read_fatal;
  		}
--- 346,352 ----
  		{
  		read_mismatch:;
  		  fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
! 			   gi_filename,
  			   f_ix + 1 ? "function" : "summaries");
  		  goto read_fatal;
  		}
*************** gcov_exit (void)
*** 301,307 ****
        
      read_error:;
        fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
! 	       : "profiling:%s:Error merging\n", gi_ptr->filename);
  	      
      read_fatal:;
        gcov_close ();
--- 405,411 ----
        
      read_error:;
        fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
! 	       : "profiling:%s:Error merging\n", gi_filename);
  	      
      read_fatal:;
        gcov_close ();
*************** gcov_exit (void)
*** 352,358 ****
  		   && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
  	    {
  	      fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
! 		       gi_ptr->filename, GCOV_LOCKED
  		       ? "" : " or concurrent update without locking support");
  	      all.checksum = ~0u;
  	    }
--- 456,462 ----
  		   && memcmp (cs_all, cs_prg, sizeof (*cs_all)))
  	    {
  	      fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s",
! 		       gi_filename, GCOV_LOCKED
  		       ? "" : " or concurrent update without locking support");
  	      all.checksum = ~0u;
  	    }
*************** gcov_exit (void)
*** 417,423 ****
  	  fprintf (stderr, error  < 0 ?
  		   "profiling:%s:Overflow writing\n" :
  		   "profiling:%s:Error writing\n",
! 		   gi_ptr->filename);
      }
  }
  
--- 521,527 ----
  	  fprintf (stderr, error  < 0 ?
  		   "profiling:%s:Overflow writing\n" :
  		   "profiling:%s:Error writing\n",
! 		   gi_filename);
      }
  }
  
*************** __gcov_init (struct gcov_info *info)
*** 429,439 ****
  {
    if (!info->version)
      return;
!   if (gcov_version (info, info->version))
      {
        const char *ptr = info->filename;
        gcov_unsigned_t crc32 = gcov_crc32;
!   
        do
  	{
  	  unsigned ix;
--- 533,548 ----
  {
    if (!info->version)
      return;
!   if (gcov_version (info, info->version, 0))
      {
        const char *ptr = info->filename;
        gcov_unsigned_t crc32 = gcov_crc32;
!       size_t filename_length =  strlen(info->filename);
! 
!       /* Refresh the longest file name information */
!       if (filename_length > gcov_max_filename)
!         gcov_max_filename = filename_length;
!       
        do
  	{
  	  unsigned ix;
Index: tsystem.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/tsystem.h,v
retrieving revision 1.17
diff -c -3 -p -r1.17 tsystem.h
*** tsystem.h	29 Mar 2005 22:15:53 -0000	1.17
--- tsystem.h	10 May 2005 15:16:17 -0000
*************** extern int errno;
*** 131,134 ****
--- 131,137 ----
     unreachable default case of a switch.  Do not use gcc_assert(0).  */
  #define gcc_unreachable() (abort ())
  
+ /* Filename handling macros.  */
+ #include "filenames.h"
+ 
  #endif /* ! GCC_TSYSTEM_H */
Index: doc/gcov.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/gcov.texi,v
retrieving revision 1.26
diff -c -3 -p -r1.26 gcov.texi
*** doc/gcov.texi	21 Mar 2005 12:31:10 -0000	1.26
--- doc/gcov.texi	10 May 2005 15:16:19 -0000
*************** test code coverage in your programs.
*** 42,47 ****
--- 42,48 ----
  * Invoking Gcov::       	How to use gcov.
  * Gcov and Optimization::       Using gcov with GCC optimization.
  * Gcov Data Files::             The files used by gcov.
+ * Cross-profiling::             Data file relocation.
  @end menu
  
  @node Gcov Intro
*************** information.
*** 531,533 ****
--- 532,573 ----
  The full details of the file format is specified in @file{gcov-io.h},
  and functions provided in that header file should be used to access the
  coverage files.
+ 
+ @node Cross-profiling
+ @section Data file relocation to support cross-profiling
+ 
+ Running the program will cause profile output to be generated.  For each 
+ source file compiled with @option{-fprofile-arcs}, an accompanying @file{.gcda} 
+ file will be placed in the object file directory. That implicitly requires 
+ running the program on the same system as it was built or having the same 
+ absolute directory structure on the target system. The program will try
+ to create the needed directory structure, if it is not already present.
+ 
+ To support cross-profiling, a program compiled with @option{-fprofile-arcs}
+ can relocate the data files based on two environment variables: 
+ 
+ @itemize @bullet
+ @item
+ GCOV_PREFIX contains the prefix to add to the absolute paths 
+ in the object file. Prefix must be absolute as well, otherwise its 
+ value is ignored. The default is no prefix.
+ 
+ @item
+ GCOV_PREFIX_STRIP indicates the how many initial directory names to strip off
+ the hardwired absolute paths. Default value is 0.
+ 
+ @emph{Note:} GCOV_PREFIX_STRIP has no effect if GCOV_PREFIX is undefined, empty
+ or non-absolute.
+ @end itemize
+ 
+ For example, if the object file @file{/user/build/foo.o} was built with
+ @option{-fprofile-arcs}, the final executable will try to create the data file
+ @file{/user/build/foo.gcda} when running on the target system.  This will
+ fail if the corresponding directory does not exist and it is unable to create
+ it.  This can be overcome by, for example, setting the environment as
+ @samp{GCOV_PREFIX=/target/run} and @samp{GCOV_PREFIX_STRIP=1}.  Such a
+ setting will name the data file @file{/target/run/build/foo.gcda}.
+ 
+ You must move the data files to the expected directory tree in order to
+ use them for profile directed optimizations (@option{--use-profile}), or to
+ use the the @command{gcov} tool.
Index: doc/invoke.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/invoke.texi,v
retrieving revision 1.615
diff -c -3 -p -r1.615 invoke.texi
*** doc/invoke.texi	7 May 2005 09:48:22 -0000	1.615
--- doc/invoke.texi	10 May 2005 15:16:52 -0000
*************** explicitly specified and it is not the f
*** 3422,3427 ****
--- 3422,3428 ----
  the basename of the source file.  In both cases any suffix is removed
  (e.g.@: @file{foo.gcda} for input file @file{dir/foo.c}, or
  @file{dir/foo.gcda} for output file specified as @option{-o dir/foo.o}).
+ @xref{Cross-profiling}.
  
  @cindex @command{gcov}
  @item --coverage

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