Mercurial > hg > CbC > CbC_gcc
comparison gcc/libgcov.c @ 67:f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
author | nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Tue, 22 Mar 2011 17:18:12 +0900 |
parents | 77e2b8dfacca |
children |
comparison
equal
deleted
inserted
replaced
65:65488c3d617d | 67:f6334be47118 |
---|---|
1 /* Routines required for instrumenting a program. */ | 1 /* Routines required for instrumenting a program. */ |
2 /* Compile this one with gcc. */ | 2 /* Compile this one with gcc. */ |
3 /* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, | 3 /* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, |
4 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009 | 4 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010 |
5 Free Software Foundation, Inc. | 5 Free Software Foundation, Inc. |
6 | 6 |
7 This file is part of GCC. | 7 This file is part of GCC. |
8 | 8 |
9 GCC is free software; you can redistribute it and/or modify it under | 9 GCC is free software; you can redistribute it and/or modify it under |
85 static gcov_unsigned_t gcov_crc32; | 85 static gcov_unsigned_t gcov_crc32; |
86 | 86 |
87 /* Size of the longest file name. */ | 87 /* Size of the longest file name. */ |
88 static size_t gcov_max_filename = 0; | 88 static size_t gcov_max_filename = 0; |
89 | 89 |
90 #ifdef TARGET_POSIX_IO | |
91 /* Make sure path component of the given FILENAME exists, create | 90 /* Make sure path component of the given FILENAME exists, create |
92 missing directories. FILENAME must be writable. | 91 missing directories. FILENAME must be writable. |
93 Returns zero on success, or -1 if an error occurred. */ | 92 Returns zero on success, or -1 if an error occurred. */ |
94 | 93 |
95 static int | 94 static int |
96 create_file_directory (char *filename) | 95 create_file_directory (char *filename) |
97 { | 96 { |
97 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32) | |
98 (void) filename; | |
99 return -1; | |
100 #else | |
98 char *s; | 101 char *s; |
99 | 102 |
100 for (s = filename + 1; *s != '\0'; s++) | 103 s = filename; |
104 | |
105 if (HAS_DRIVE_SPEC(s)) | |
106 s += 2; | |
107 if (IS_DIR_SEPARATOR(*s)) | |
108 ++s; | |
109 for (; *s != '\0'; s++) | |
101 if (IS_DIR_SEPARATOR(*s)) | 110 if (IS_DIR_SEPARATOR(*s)) |
102 { | 111 { |
103 char sep = *s; | 112 char sep = *s; |
104 *s = '\0'; | 113 *s = '\0'; |
105 | 114 |
106 /* Try to make directory if it doesn't already exist. */ | 115 /* Try to make directory if it doesn't already exist. */ |
107 if (access (filename, F_OK) == -1 | 116 if (access (filename, F_OK) == -1 |
117 #ifdef TARGET_POSIX_IO | |
108 && mkdir (filename, 0755) == -1 | 118 && mkdir (filename, 0755) == -1 |
119 #else | |
120 && mkdir (filename) == -1 | |
121 #endif | |
109 /* The directory might have been made by another process. */ | 122 /* The directory might have been made by another process. */ |
110 && errno != EEXIST) | 123 && errno != EEXIST) |
111 { | 124 { |
112 fprintf (stderr, "profiling:%s:Cannot create directory\n", | 125 fprintf (stderr, "profiling:%s:Cannot create directory\n", |
113 filename); | 126 filename); |
116 }; | 129 }; |
117 | 130 |
118 *s = sep; | 131 *s = sep; |
119 }; | 132 }; |
120 return 0; | 133 return 0; |
121 } | 134 #endif |
122 #endif | 135 } |
123 | 136 |
124 /* Check if VERSION of the info block PTR matches libgcov one. | 137 /* Check if VERSION of the info block PTR matches libgcov one. |
125 Return 1 on success, or zero in case of versions mismatch. | 138 Return 1 on success, or zero in case of versions mismatch. |
126 If FILENAME is not NULL, its value used for reporting purposes | 139 If FILENAME is not NULL, its value used for reporting purposes |
127 instead of value from the info block. */ | 140 instead of value from the info block. */ |
188 } | 201 } |
189 ci_ptr++; | 202 ci_ptr++; |
190 } | 203 } |
191 } | 204 } |
192 | 205 |
206 { | |
207 /* Check if the level of dirs to strip off specified. */ | |
208 char *tmp = getenv("GCOV_PREFIX_STRIP"); | |
209 if (tmp) | |
210 { | |
211 gcov_prefix_strip = atoi (tmp); | |
212 /* Do not consider negative values. */ | |
213 if (gcov_prefix_strip < 0) | |
214 gcov_prefix_strip = 0; | |
215 } | |
216 } | |
193 /* Get file name relocation prefix. Non-absolute values are ignored. */ | 217 /* Get file name relocation prefix. Non-absolute values are ignored. */ |
194 gcov_prefix = getenv("GCOV_PREFIX"); | 218 gcov_prefix = getenv("GCOV_PREFIX"); |
195 if (gcov_prefix && IS_ABSOLUTE_PATH (gcov_prefix)) | 219 if (gcov_prefix) |
196 { | 220 { |
197 /* Check if the level of dirs to strip off specified. */ | |
198 char *tmp = getenv("GCOV_PREFIX_STRIP"); | |
199 if (tmp) | |
200 { | |
201 gcov_prefix_strip = atoi (tmp); | |
202 /* Do not consider negative values. */ | |
203 if (gcov_prefix_strip < 0) | |
204 gcov_prefix_strip = 0; | |
205 } | |
206 | |
207 prefix_length = strlen(gcov_prefix); | 221 prefix_length = strlen(gcov_prefix); |
208 | 222 |
209 /* Remove an unnecessary trailing '/' */ | 223 /* Remove an unnecessary trailing '/' */ |
210 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1])) | 224 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1])) |
211 prefix_length--; | 225 prefix_length--; |
212 } | 226 } |
213 else | 227 else |
214 prefix_length = 0; | 228 prefix_length = 0; |
215 | 229 |
216 /* Allocate and initialize the filename scratch space. */ | 230 /* If no prefix was specified and a prefix stip, then we assume |
217 gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 1); | 231 relative. */ |
232 if (gcov_prefix_strip != 0 && prefix_length == 0) | |
233 { | |
234 gcov_prefix = "."; | |
235 prefix_length = 1; | |
236 } | |
237 /* Allocate and initialize the filename scratch space plus one. */ | |
238 gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2); | |
218 if (prefix_length) | 239 if (prefix_length) |
219 memcpy (gi_filename, gcov_prefix, prefix_length); | 240 memcpy (gi_filename, gcov_prefix, prefix_length); |
220 gi_filename_up = gi_filename + prefix_length; | 241 gi_filename_up = gi_filename + prefix_length; |
221 | 242 |
222 /* Now merge each file. */ | 243 /* Now merge each file. */ |
231 struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all; | 252 struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all; |
232 int error = 0; | 253 int error = 0; |
233 gcov_unsigned_t tag, length; | 254 gcov_unsigned_t tag, length; |
234 gcov_position_t summary_pos = 0; | 255 gcov_position_t summary_pos = 0; |
235 gcov_position_t eof_pos = 0; | 256 gcov_position_t eof_pos = 0; |
257 const char *fname, *s; | |
258 | |
259 fname = gi_ptr->filename; | |
236 | 260 |
237 memset (&this_object, 0, sizeof (this_object)); | 261 memset (&this_object, 0, sizeof (this_object)); |
238 memset (&object, 0, sizeof (object)); | 262 memset (&object, 0, sizeof (object)); |
263 | |
264 /* Avoid to add multiple drive letters into combined path. */ | |
265 if (prefix_length != 0 && HAS_DRIVE_SPEC(fname)) | |
266 fname += 2; | |
239 | 267 |
240 /* Build relocated filename, stripping off leading | 268 /* Build relocated filename, stripping off leading |
241 directories from the initial filename if requested. */ | 269 directories from the initial filename if requested. */ |
242 if (gcov_prefix_strip > 0) | 270 if (gcov_prefix_strip > 0) |
243 { | 271 { |
244 int level = 0; | 272 int level = 0; |
245 const char *fname = gi_ptr->filename; | 273 s = fname; |
246 const char *s; | 274 if (IS_DIR_SEPARATOR(*s)) |
275 ++s; | |
247 | 276 |
248 /* Skip selected directory levels. */ | 277 /* Skip selected directory levels. */ |
249 for (s = fname + 1; (*s != '\0') && (level < gcov_prefix_strip); s++) | 278 for (; (*s != '\0') && (level < gcov_prefix_strip); s++) |
250 if (IS_DIR_SEPARATOR(*s)) | 279 if (IS_DIR_SEPARATOR(*s)) |
251 { | 280 { |
252 fname = s; | 281 fname = s; |
253 level++; | 282 level++; |
254 }; | 283 } |
255 | |
256 /* Update complete filename with stripped original. */ | |
257 strcpy (gi_filename_up, fname); | |
258 } | 284 } |
285 /* Update complete filename with stripped original. */ | |
286 if (!IS_DIR_SEPARATOR (*fname) && !HAS_DRIVE_SPEC(fname)) | |
287 { | |
288 strcpy (gi_filename_up, "/"); | |
289 strcpy (gi_filename_up + 1, fname); | |
290 } | |
259 else | 291 else |
260 strcpy (gi_filename_up, gi_ptr->filename); | 292 strcpy (gi_filename_up, fname); |
261 | 293 |
262 /* Totals for this object file. */ | 294 /* Totals for this object file. */ |
263 ci_ptr = gi_ptr->counts; | 295 ci_ptr = gi_ptr->counts; |
264 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) | 296 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) |
265 { | 297 { |
295 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1); | 327 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1); |
296 } | 328 } |
297 | 329 |
298 if (!gcov_open (gi_filename)) | 330 if (!gcov_open (gi_filename)) |
299 { | 331 { |
300 #ifdef TARGET_POSIX_IO | |
301 /* Open failed likely due to missed directory. | 332 /* Open failed likely due to missed directory. |
302 Create directory and retry to open file. */ | 333 Create directory and retry to open file. */ |
303 if (create_file_directory (gi_filename)) | 334 if (create_file_directory (gi_filename)) |
304 { | 335 { |
305 fprintf (stderr, "profiling:%s:Skip\n", gi_filename); | 336 fprintf (stderr, "profiling:%s:Skip\n", gi_filename); |
306 continue; | 337 continue; |
307 } | 338 } |
308 #endif | |
309 if (!gcov_open (gi_filename)) | 339 if (!gcov_open (gi_filename)) |
310 { | 340 { |
311 fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename); | 341 fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename); |
312 continue; | 342 continue; |
313 } | 343 } |
766 __gcov_one_value_profiler_body (counters, value); | 796 __gcov_one_value_profiler_body (counters, value); |
767 } | 797 } |
768 #endif | 798 #endif |
769 | 799 |
770 #ifdef L_gcov_indirect_call_profiler | 800 #ifdef L_gcov_indirect_call_profiler |
801 | |
802 /* By default, the C++ compiler will use function addresses in the | |
803 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero | |
804 tells the compiler to use function descriptors instead. The value | |
805 of this macro says how many words wide the descriptor is (normally 2), | |
806 but it may be dependent on target flags. Since we do not have access | |
807 to the target flags here we just check to see if it is set and use | |
808 that to set VTABLE_USES_DESCRIPTORS to 0 or 1. | |
809 | |
810 It is assumed that the address of a function descriptor may be treated | |
811 as a pointer to a function. */ | |
812 | |
813 #ifdef TARGET_VTABLE_USES_DESCRIPTORS | |
814 #define VTABLE_USES_DESCRIPTORS 1 | |
815 #else | |
816 #define VTABLE_USES_DESCRIPTORS 0 | |
817 #endif | |
818 | |
771 /* Tries to determine the most common value among its inputs. */ | 819 /* Tries to determine the most common value among its inputs. */ |
772 void | 820 void |
773 __gcov_indirect_call_profiler (gcov_type* counter, gcov_type value, | 821 __gcov_indirect_call_profiler (gcov_type* counter, gcov_type value, |
774 void* cur_func, void* callee_func) | 822 void* cur_func, void* callee_func) |
775 { | 823 { |
776 /* If the C++ virtual tables contain function descriptors then one | 824 /* If the C++ virtual tables contain function descriptors then one |
777 function may have multiple descriptors and we need to dereference | 825 function may have multiple descriptors and we need to dereference |
778 the descriptors to see if they point to the same function. */ | 826 the descriptors to see if they point to the same function. */ |
779 if (cur_func == callee_func | 827 if (cur_func == callee_func |
780 || (TARGET_VTABLE_USES_DESCRIPTORS && callee_func | 828 || (VTABLE_USES_DESCRIPTORS && callee_func |
781 && *(void **) cur_func == *(void **) callee_func)) | 829 && *(void **) cur_func == *(void **) callee_func)) |
782 __gcov_one_value_profiler_body (counter, value); | 830 __gcov_one_value_profiler_body (counter, value); |
783 } | 831 } |
784 #endif | 832 #endif |
785 | 833 |