summaryrefslogtreecommitdiff
path: root/recipes/gcc/gcc-4.0.2/GCOV_PREFIX_STRIP-cross-profile_4.1.patch
blob: 92ce00a1e3d937e1f72369bfb392dfb3025c0cd1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
2005-05-04  Grigory Zagorodnev  <grigory.zagorodnev@intel.com>
	    H.J. Lu  <hongjiu.lu@intel.com>

	* gcov-io.c (gcov_open): When in libgcov library
	use given data file relocation prefix to build file name.
	* gcov-io.h (gcov_open): Updated proto to accept
	data file relocation prefix.
	* libgcov.c (create_file_directory): New function.
	(gcov_prefix): New static variable to hold data file
	relocation prefix.
	(gcov_version): Use relocation prefix.
	(gcov_exit): Always try to create directory for output
	file. Relocate filename at each use.
	(__gcov_init): Initialize directory relocation prefix
	if required. Strip off leading directories from
	the initial filename.
	* tsystem.h: include filenames.h
	(DIR_SEPARATOR): Macro copied from system.h.
	(DIR_SEPARATOR_2): Likewise.
	* doc/gcov.texi (Cross-profiling): New node documenting
	cross-profiling management.
	* doc/invoke.texi (-fprofile-arcs): xref to cross-profiling.

--- gcc-4/gcc/doc/gcov.texi.prefix	2005-03-28 11:56:34.000000000 -0800
+++ gcc-4/gcc/doc/gcov.texi	2005-05-04 15:07:44.000000000 -0700
@@ -42,6 +42,7 @@ test code coverage in your programs.
 * 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 files relocation.
 @end menu
 
 @node Gcov Intro
@@ -531,3 +532,36 @@ information.
 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 files 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 at the same system as it was build or having same 
+absolute directory structure on the target system (program will try 
+to create needed directory structure).
+
+To support cross-profiling, program compiled with @option{-fprofile-arcs}
+performs data file relocation basing on two environment variables:
+
+@itemize @bullet
+@item
+GCOV_PREFIX contains the prefix to add to the absolute paths 
+in the object file.
+
+@item
+GCOV_PREFIX_STRIP indicates the how many initial directory names to strip off 
+the hardwired absolute paths. Default value is 0.
+@end itemize
+
+For example, if object file @file{/user/build/foo.o} was build with 
+@option{-fprofile-arcs}, the final executable will try to create data file 
+@file{/user/build/foo.gcda} when running at the target system and will 
+fail if corresponding directory does not exists and is not allowed to create. 
+
+In this case, manipulating environment variables you can relocate data file 
+to the suitable local directory. For our example, setting @samp{GCOV_PREFIX=/target/run} 
+and @samp{GCOV_PREFIX_STRIP=1} values will force use of @file{/target/run/build/foo.gcda} 
+file name.
--- gcc-4/gcc/doc/invoke.texi.prefix	2005-05-04 11:21:00.000000000 -0700
+++ gcc-4/gcc/doc/invoke.texi	2005-05-04 15:07:44.000000000 -0700
@@ -3420,6 +3420,7 @@ explicitly specified and it is not the f
 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
--- gcc-4/gcc/gcov-io.c.prefix	2005-04-28 16:11:30.000000000 -0700
+++ gcc-4/gcc/gcov-io.c	2005-05-04 20:02:35.000000000 -0700
@@ -55,13 +55,14 @@ static inline gcov_unsigned_t from_file 
 
 GCOV_LINKAGE int
 #if IN_LIBGCOV
-gcov_open (const char *name)
+gcov_open (const char *prefix, const char *name)
 #else
 gcov_open (const char *name, int mode)
 #endif
 {
 #if IN_LIBGCOV
   const int mode = 0;
+  char *tmp;
 #endif
 #if GCOV_LOCKED
   struct flock s_flock;
@@ -82,6 +83,13 @@ gcov_open (const char *name, int mode)
 #if !IN_LIBGCOV
   gcov_var.endian = 0;
 #endif
+
+#if IN_LIBGCOV
+  /* Build complete filename with prefix */
+  tmp = alloca (strlen (prefix) + strlen (name) + 1);
+  name = strcat (strcpy (tmp, prefix), name);
+#endif
+
 #if GCOV_LOCKED
   if (mode > 0)
     fd = open (name, O_RDWR);
--- gcc-4/gcc/gcov-io.h.prefix	2005-05-02 17:43:08.000000000 -0700
+++ gcc-4/gcc/gcov-io.h	2005-05-04 15:07:44.000000000 -0700
@@ -515,7 +515,7 @@ GCOV_LINKAGE struct gcov_var
    functions for writing.  Your file may become corrupted if you break
    these invariants.  */
 #if IN_LIBGCOV
-GCOV_LINKAGE int gcov_open (const char */*name*/) ATTRIBUTE_HIDDEN;
+GCOV_LINKAGE int gcov_open (const char */*prefix*/, const char */*name*/) ATTRIBUTE_HIDDEN;
 #else
 GCOV_LINKAGE int gcov_open (const char */*name*/, int /*direction*/);
 GCOV_LINKAGE int gcov_magic (gcov_unsigned_t, gcov_unsigned_t);
--- gcc-4/gcc/libgcov.c.prefix	2005-04-28 16:11:30.000000000 -0700
+++ gcc-4/gcc/libgcov.c	2005-05-04 15:07:44.000000000 -0700
@@ -92,6 +92,70 @@ static struct gcov_info *gcov_list;
    object file included in multiple programs.  */
 static gcov_unsigned_t gcov_crc32;
 
+/* Directory prefix to relocate coverage data file names */
+static char *gcov_prefix = 0;
+
+/* Level of dirs to strip off the initial filename to relocate */
+static int gcov_prefix_strip = 0;
+
+static int
+create_file_directory (const char *prefix, const char *filename)
+{
+  char *dname;
+  char sep, *r, *s;
+  size_t plen, flen;
+  
+  /* Detect directory separator */
+  s = strrchr (prefix, DIR_SEPARATOR);
+#ifdef DIR_SEPARATOR_2
+  if (! s)
+    s = strrchr (prefix, DIR_SEPARATOR_2);
+#endif
+  if (s)
+    sep = *s;
+  else
+    sep = DIR_SEPARATOR;
+
+  /* join prefix and filename, split path */
+  plen  = strlen(prefix);
+  flen  = strlen(filename);
+  r     = alloca(plen + flen + 1);
+  strncpy(r, prefix, plen);
+  strncpy(r + plen, filename, flen);
+  r[plen + flen] = '\0';
+  s = strrchr(r, sep);
+  if (s)
+    *(s + 1) = '\0';
+
+  if (access (r, F_OK) == 0)
+    return 0;
+
+  /* Skip consecutive separators.  */
+  for (dname = r; *dname && *dname == sep; ++dname);
+  while (1)
+    {
+      char *s = strchr (dname, sep);
+      if (s == 0)
+        break;
+      *s = '\0';
+      /* Try to make directory if it doesn't already exist.  */
+      if (access (r, F_OK) == -1
+          && mkdir (r, 0755) == -1
+          /* The directory might have been made by another process.  */
+	  && errno != EEXIST)
+	{
+          *s = sep;
+          fprintf (stderr, "profiling:%s:Cannot create directory\n", r);
+	  return -1;
+	};
+      *s = sep;
+      /* Skip consecutive separators.  */
+      for (dname = s + 1; *dname && *dname == sep; ++dname)
+        ;
+    }
+  return 0;
+}
+
 static int
 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version)
 {
@@ -103,8 +167,8 @@ gcov_version (struct gcov_info *ptr, gco
       GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
       
       fprintf (stderr,
-	       "profiling:%s:Version mismatch - expected %.4s got %.4s\n",
-	       ptr->filename, e, v);
+	       "profiling:%s%s:Version mismatch - expected %.4s got %.4s\n",
+	       gcov_prefix, ptr->filename, e, v);
       return 0;
     }
   return 1;
@@ -205,9 +269,16 @@ gcov_exit (void)
 	  fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1);
 	}
       
-      if (!gcov_open (gi_ptr->filename))
+      if (create_file_directory (gcov_prefix, gi_ptr->filename))
+	{
+	  fprintf (stderr, "profiling:%s%s:Skip\n", gcov_prefix,
+		   gi_ptr->filename);
+	  continue;
+	}
+      else if (!gcov_open (gcov_prefix, gi_ptr->filename))
 	{
-	  fprintf (stderr, "profiling:%s:Cannot open\n", gi_ptr->filename);
+	  fprintf (stderr, "profiling:%s%s:Cannot open\n", gcov_prefix,
+		   gi_ptr->filename);
 	  continue;
 	}
 
@@ -217,8 +288,8 @@ gcov_exit (void)
 	  /* Merge data from file.  */
 	  if (tag != GCOV_DATA_MAGIC)
 	    {
-	      fprintf (stderr, "profiling:%s:Not a gcov data file\n",
-		       gi_ptr->filename);
+	      fprintf (stderr, "profiling:%s%s:Not a gcov data file\n",
+		       gcov_prefix, gi_ptr->filename);
 	      goto read_fatal;
 	    }
 	  length = gcov_read_unsigned ();
@@ -245,8 +316,8 @@ gcov_exit (void)
 		  || gcov_read_unsigned () != fi_ptr->checksum)
 		{
 		read_mismatch:;
-		  fprintf (stderr, "profiling:%s:Merge mismatch for %s\n",
-			   gi_ptr->filename,
+		  fprintf (stderr, "profiling:%s%s:Merge mismatch for %s\n",
+			   gcov_prefix, gi_ptr->filename,
 			   f_ix + 1 ? "function" : "summaries");
 		  goto read_fatal;
 		}
@@ -305,7 +376,8 @@ gcov_exit (void)
       
     read_error:;
       fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n"
-	       : "profiling:%s:Error merging\n", gi_ptr->filename);
+	       : "profiling:%s%s:Error merging\n", gcov_prefix,
+	       gi_ptr->filename);
 	      
     read_fatal:;
       gcov_close ();
@@ -355,8 +427,8 @@ gcov_exit (void)
 		   && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs)
 		   && 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
+	      fprintf (stderr, "profiling:%s%s:Invocation mismatch - some data files may have been removed%s",
+		       gcov_prefix, gi_ptr->filename, GCOV_LOCKED
 		       ? "" : " or concurrent update without locking support");
 	      all.checksum = ~0u;
 	    }
@@ -419,9 +491,9 @@ gcov_exit (void)
 	gcov_write_unsigned (0);
       if ((error = gcov_close ()))
 	  fprintf (stderr, error  < 0 ?
-		   "profiling:%s:Overflow writing\n" :
-		   "profiling:%s:Error writing\n",
-		   gi_ptr->filename);
+		   "profiling:%s%s:Overflow writing\n" :
+		   "profiling:%s%s:Error writing\n",
+		   gcov_prefix, gi_ptr->filename);
     }
 }
 
@@ -431,11 +503,69 @@ gcov_exit (void)
 void
 __gcov_init (struct gcov_info *info)
 {
+  /* Save initial filename pointer to calculate CRC. */
+  const char *ptr = info->filename;
+  
   if (!info->version)
     return;
+
+  /* Initialize directory prefix if requred */
+  if (gcov_prefix == 0)
+    {
+      if ((gcov_prefix = getenv("GCOV_PREFIX")))
+        {
+          char *tmp;
+	
+          /* Normalize prefix: take off trailing separator. */
+	  tmp = gcov_prefix + strlen(gcov_prefix) - 1;
+          if (IS_DIR_SEPARATOR(*tmp))
+            *tmp = '\0';
+
+          /* Check if the level of dirs to strip off specified */
+          if ((tmp = getenv("GCOV_PREFIX_STRIP")))
+            {
+	      gcov_prefix_strip = atoi (tmp);
+	      /* Do not consider negative values. */
+	      if (gcov_prefix_strip < 0)
+	        gcov_prefix_strip = 0;
+	    };
+        }
+      else 
+          gcov_prefix = (char *) "";
+    };
+    
+  /* Strip off leading directories from the initial filename */
+  if (gcov_prefix_strip > 0)
+    {
+      char sep, *s;
+      int level;
+      const char *fname = info->filename;
+      
+      /* Detect directory separator */
+      s = strrchr (fname, DIR_SEPARATOR);
+#ifdef DIR_SEPARATOR_2
+      if (! s)
+        s = strrchr (fname, DIR_SEPARATOR_2);
+#endif
+      if (s)
+        sep = *s;
+      else
+        sep = DIR_SEPARATOR;
+
+      /* Skip selected directory levels */
+      for ( level = gcov_prefix_strip; level > 0; level--)
+        if ((s = strchr(fname + 1, sep)))
+	  fname = s;
+	else
+	  break;
+	  
+      /* From this point info block refers stripped file name and 
+         further operations must add prefix to get complete name.*/
+      info->filename = fname;
+    };
+
   if (gcov_version (info, info->version))
     {
-      const char *ptr = info->filename;
       gcov_unsigned_t crc32 = gcov_crc32;
   
       do
--- gcc-4/gcc/tsystem.h.prefix	2005-03-29 16:06:26.000000000 -0800
+++ gcc-4/gcc/tsystem.h	2005-05-04 15:07:44.000000000 -0700
@@ -131,4 +131,15 @@ extern int errno;
    unreachable default case of a switch.  Do not use gcc_assert(0).  */
 #define gcc_unreachable() (abort ())
 
+/* Filename handling macros.  */
+#include "filenames.h"
+
+/* These should be phased out in favor of IS_DIR_SEPARATOR, where possible.  */
+#ifndef DIR_SEPARATOR
+# define DIR_SEPARATOR '/'
+# ifdef HAVE_DOS_BASED_FILE_SYSTEM
+#  define DIR_SEPARATOR_2 '\\'
+# endif
+#endif
+
 #endif /* ! GCC_TSYSTEM_H */