Mercurial > hg > CbC > CbC_gcc
annotate 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 |
rev | line source |
---|---|
0 | 1 /* Routines required for instrumenting a program. */ |
2 /* Compile this one with gcc. */ | |
3 /* Copyright (C) 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
4 2000, 2001, 2002, 2003, 2004, 2005, 2008, 2009, 2010 |
0 | 5 Free Software Foundation, Inc. |
6 | |
7 This file is part of GCC. | |
8 | |
9 GCC is free software; you can redistribute it and/or modify it under | |
10 the terms of the GNU General Public License as published by the Free | |
11 Software Foundation; either version 3, or (at your option) any later | |
12 version. | |
13 | |
14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 Under Section 7 of GPL version 3, you are granted additional | |
20 permissions described in the GCC Runtime Library Exception, version | |
21 3.1, as published by the Free Software Foundation. | |
22 | |
23 You should have received a copy of the GNU General Public License and | |
24 a copy of the GCC Runtime Library Exception along with this program; | |
25 see the files COPYING3 and COPYING.RUNTIME respectively. If not, see | |
26 <http://www.gnu.org/licenses/>. */ | |
27 | |
28 #include "tconfig.h" | |
29 #include "tsystem.h" | |
30 #include "coretypes.h" | |
31 #include "tm.h" | |
32 | |
33 #if defined(inhibit_libc) | |
34 #define IN_LIBGCOV (-1) | |
35 #else | |
36 #undef NULL /* Avoid errors if stdio.h and our stddef.h mismatch. */ | |
37 #include <stdio.h> | |
38 #define IN_LIBGCOV 1 | |
39 #if defined(L_gcov) | |
40 #define GCOV_LINKAGE /* nothing */ | |
41 #endif | |
42 #endif | |
43 #include "gcov-io.h" | |
44 | |
45 #if defined(inhibit_libc) | |
46 /* If libc and its header files are not available, provide dummy functions. */ | |
47 | |
48 #ifdef L_gcov | |
49 void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {} | |
50 void __gcov_flush (void) {} | |
51 #endif | |
52 | |
53 #ifdef L_gcov_merge_add | |
54 void __gcov_merge_add (gcov_type *counters __attribute__ ((unused)), | |
55 unsigned n_counters __attribute__ ((unused))) {} | |
56 #endif | |
57 | |
58 #ifdef L_gcov_merge_single | |
59 void __gcov_merge_single (gcov_type *counters __attribute__ ((unused)), | |
60 unsigned n_counters __attribute__ ((unused))) {} | |
61 #endif | |
62 | |
63 #ifdef L_gcov_merge_delta | |
64 void __gcov_merge_delta (gcov_type *counters __attribute__ ((unused)), | |
65 unsigned n_counters __attribute__ ((unused))) {} | |
66 #endif | |
67 | |
68 #else | |
69 | |
70 #include <string.h> | |
71 #if GCOV_LOCKED | |
72 #include <fcntl.h> | |
73 #include <errno.h> | |
74 #include <sys/stat.h> | |
75 #endif | |
76 | |
77 #ifdef L_gcov | |
78 #include "gcov-io.c" | |
79 | |
80 /* Chain of per-object gcov structures. */ | |
81 static struct gcov_info *gcov_list; | |
82 | |
83 /* A program checksum allows us to distinguish program data for an | |
84 object file included in multiple programs. */ | |
85 static gcov_unsigned_t gcov_crc32; | |
86 | |
87 /* Size of the longest file name. */ | |
88 static size_t gcov_max_filename = 0; | |
89 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
90 /* Make sure path component of the given FILENAME exists, create |
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
91 missing directories. FILENAME must be writable. |
0 | 92 Returns zero on success, or -1 if an error occurred. */ |
93 | |
94 static int | |
95 create_file_directory (char *filename) | |
96 { | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
97 #if !defined(TARGET_POSIX_IO) && !defined(_WIN32) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
98 (void) filename; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
99 return -1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
100 #else |
0 | 101 char *s; |
102 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
103 s = filename; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
104 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
105 if (HAS_DRIVE_SPEC(s)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
106 s += 2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
107 if (IS_DIR_SEPARATOR(*s)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
108 ++s; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
109 for (; *s != '\0'; s++) |
0 | 110 if (IS_DIR_SEPARATOR(*s)) |
111 { | |
112 char sep = *s; | |
113 *s = '\0'; | |
114 | |
115 /* Try to make directory if it doesn't already exist. */ | |
116 if (access (filename, F_OK) == -1 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
117 #ifdef TARGET_POSIX_IO |
0 | 118 && mkdir (filename, 0755) == -1 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
119 #else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
120 && mkdir (filename) == -1 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
121 #endif |
0 | 122 /* The directory might have been made by another process. */ |
123 && errno != EEXIST) | |
124 { | |
125 fprintf (stderr, "profiling:%s:Cannot create directory\n", | |
126 filename); | |
127 *s = sep; | |
128 return -1; | |
129 }; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
130 |
0 | 131 *s = sep; |
132 }; | |
133 return 0; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
134 #endif |
0 | 135 } |
136 | |
137 /* Check if VERSION of the info block PTR matches libgcov one. | |
138 Return 1 on success, or zero in case of versions mismatch. | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
139 If FILENAME is not NULL, its value used for reporting purposes |
0 | 140 instead of value from the info block. */ |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
141 |
0 | 142 static int |
143 gcov_version (struct gcov_info *ptr, gcov_unsigned_t version, | |
144 const char *filename) | |
145 { | |
146 if (version != GCOV_VERSION) | |
147 { | |
148 char v[4], e[4]; | |
149 | |
150 GCOV_UNSIGNED2STRING (v, version); | |
151 GCOV_UNSIGNED2STRING (e, GCOV_VERSION); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
152 |
0 | 153 fprintf (stderr, |
154 "profiling:%s:Version mismatch - expected %.4s got %.4s\n", | |
155 filename? filename : ptr->filename, e, v); | |
156 return 0; | |
157 } | |
158 return 1; | |
159 } | |
160 | |
161 /* Dump the coverage counts. We merge with existing counts when | |
162 possible, to avoid growing the .da files ad infinitum. We use this | |
163 program's checksum to make sure we only accumulate whole program | |
164 statistics to the correct summary. An object file might be embedded | |
165 in two separate programs, and we must keep the two program | |
166 summaries separate. */ | |
167 | |
168 static void | |
169 gcov_exit (void) | |
170 { | |
171 struct gcov_info *gi_ptr; | |
172 struct gcov_summary this_program; | |
173 struct gcov_summary all; | |
174 struct gcov_ctr_summary *cs_ptr; | |
175 const struct gcov_ctr_info *ci_ptr; | |
176 unsigned t_ix; | |
177 gcov_unsigned_t c_num; | |
178 const char *gcov_prefix; | |
179 int gcov_prefix_strip = 0; | |
180 size_t prefix_length; | |
181 char *gi_filename, *gi_filename_up; | |
182 | |
183 memset (&all, 0, sizeof (all)); | |
184 /* Find the totals for this execution. */ | |
185 memset (&this_program, 0, sizeof (this_program)); | |
186 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) | |
187 { | |
188 ci_ptr = gi_ptr->counts; | |
189 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) | |
190 { | |
191 if (!((1 << t_ix) & gi_ptr->ctr_mask)) | |
192 continue; | |
193 | |
194 cs_ptr = &this_program.ctrs[t_ix]; | |
195 cs_ptr->num += ci_ptr->num; | |
196 for (c_num = 0; c_num < ci_ptr->num; c_num++) | |
197 { | |
198 cs_ptr->sum_all += ci_ptr->values[c_num]; | |
199 if (cs_ptr->run_max < ci_ptr->values[c_num]) | |
200 cs_ptr->run_max = ci_ptr->values[c_num]; | |
201 } | |
202 ci_ptr++; | |
203 } | |
204 } | |
205 | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
206 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
207 /* Check if the level of dirs to strip off specified. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
208 char *tmp = getenv("GCOV_PREFIX_STRIP"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
209 if (tmp) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
210 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
211 gcov_prefix_strip = atoi (tmp); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
212 /* Do not consider negative values. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
213 if (gcov_prefix_strip < 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
214 gcov_prefix_strip = 0; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
215 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
216 } |
0 | 217 /* Get file name relocation prefix. Non-absolute values are ignored. */ |
218 gcov_prefix = getenv("GCOV_PREFIX"); | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
219 if (gcov_prefix) |
0 | 220 { |
221 prefix_length = strlen(gcov_prefix); | |
222 | |
223 /* Remove an unnecessary trailing '/' */ | |
224 if (IS_DIR_SEPARATOR (gcov_prefix[prefix_length - 1])) | |
225 prefix_length--; | |
226 } | |
227 else | |
228 prefix_length = 0; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
229 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
230 /* If no prefix was specified and a prefix stip, then we assume |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
231 relative. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
232 if (gcov_prefix_strip != 0 && prefix_length == 0) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
233 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
234 gcov_prefix = "."; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
235 prefix_length = 1; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
236 } |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
237 /* Allocate and initialize the filename scratch space plus one. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
238 gi_filename = (char *) alloca (prefix_length + gcov_max_filename + 2); |
0 | 239 if (prefix_length) |
240 memcpy (gi_filename, gcov_prefix, prefix_length); | |
241 gi_filename_up = gi_filename + prefix_length; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
242 |
0 | 243 /* Now merge each file. */ |
244 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) | |
245 { | |
246 struct gcov_summary this_object; | |
247 struct gcov_summary object, program; | |
248 gcov_type *values[GCOV_COUNTERS]; | |
249 const struct gcov_fn_info *fi_ptr; | |
250 unsigned fi_stride; | |
251 unsigned c_ix, f_ix, n_counts; | |
252 struct gcov_ctr_summary *cs_obj, *cs_tobj, *cs_prg, *cs_tprg, *cs_all; | |
253 int error = 0; | |
254 gcov_unsigned_t tag, length; | |
255 gcov_position_t summary_pos = 0; | |
256 gcov_position_t eof_pos = 0; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
257 const char *fname, *s; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
258 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
259 fname = gi_ptr->filename; |
0 | 260 |
261 memset (&this_object, 0, sizeof (this_object)); | |
262 memset (&object, 0, sizeof (object)); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
263 |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
264 /* Avoid to add multiple drive letters into combined path. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
265 if (prefix_length != 0 && HAS_DRIVE_SPEC(fname)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
266 fname += 2; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
267 |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
268 /* Build relocated filename, stripping off leading |
0 | 269 directories from the initial filename if requested. */ |
270 if (gcov_prefix_strip > 0) | |
271 { | |
272 int level = 0; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
273 s = fname; |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
274 if (IS_DIR_SEPARATOR(*s)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
275 ++s; |
0 | 276 |
277 /* Skip selected directory levels. */ | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
278 for (; (*s != '\0') && (level < gcov_prefix_strip); s++) |
0 | 279 if (IS_DIR_SEPARATOR(*s)) |
280 { | |
281 fname = s; | |
282 level++; | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
283 } |
0 | 284 } |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
285 /* Update complete filename with stripped original. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
286 if (!IS_DIR_SEPARATOR (*fname) && !HAS_DRIVE_SPEC(fname)) |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
287 { |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
288 strcpy (gi_filename_up, "/"); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
289 strcpy (gi_filename_up + 1, fname); |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
290 } |
0 | 291 else |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
292 strcpy (gi_filename_up, fname); |
0 | 293 |
294 /* Totals for this object file. */ | |
295 ci_ptr = gi_ptr->counts; | |
296 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) | |
297 { | |
298 if (!((1 << t_ix) & gi_ptr->ctr_mask)) | |
299 continue; | |
300 | |
301 cs_ptr = &this_object.ctrs[t_ix]; | |
302 cs_ptr->num += ci_ptr->num; | |
303 for (c_num = 0; c_num < ci_ptr->num; c_num++) | |
304 { | |
305 cs_ptr->sum_all += ci_ptr->values[c_num]; | |
306 if (cs_ptr->run_max < ci_ptr->values[c_num]) | |
307 cs_ptr->run_max = ci_ptr->values[c_num]; | |
308 } | |
309 | |
310 ci_ptr++; | |
311 } | |
312 | |
313 c_ix = 0; | |
314 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) | |
315 if ((1 << t_ix) & gi_ptr->ctr_mask) | |
316 { | |
317 values[c_ix] = gi_ptr->counts[c_ix].values; | |
318 c_ix++; | |
319 } | |
320 | |
321 /* Calculate the function_info stride. This depends on the | |
322 number of counter types being measured. */ | |
323 fi_stride = sizeof (struct gcov_fn_info) + c_ix * sizeof (unsigned); | |
324 if (__alignof__ (struct gcov_fn_info) > sizeof (unsigned)) | |
325 { | |
326 fi_stride += __alignof__ (struct gcov_fn_info) - 1; | |
327 fi_stride &= ~(__alignof__ (struct gcov_fn_info) - 1); | |
328 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
329 |
0 | 330 if (!gcov_open (gi_filename)) |
331 { | |
332 /* Open failed likely due to missed directory. | |
333 Create directory and retry to open file. */ | |
334 if (create_file_directory (gi_filename)) | |
335 { | |
336 fprintf (stderr, "profiling:%s:Skip\n", gi_filename); | |
337 continue; | |
338 } | |
339 if (!gcov_open (gi_filename)) | |
340 { | |
341 fprintf (stderr, "profiling:%s:Cannot open\n", gi_filename); | |
342 continue; | |
343 } | |
344 } | |
345 | |
346 tag = gcov_read_unsigned (); | |
347 if (tag) | |
348 { | |
349 /* Merge data from file. */ | |
350 if (tag != GCOV_DATA_MAGIC) | |
351 { | |
352 fprintf (stderr, "profiling:%s:Not a gcov data file\n", | |
353 gi_filename); | |
354 goto read_fatal; | |
355 } | |
356 length = gcov_read_unsigned (); | |
357 if (!gcov_version (gi_ptr, length, gi_filename)) | |
358 goto read_fatal; | |
359 | |
360 length = gcov_read_unsigned (); | |
361 if (length != gi_ptr->stamp) | |
362 /* Read from a different compilation. Overwrite the file. */ | |
363 goto rewrite; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
364 |
0 | 365 /* Merge execution counts for each function. */ |
366 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) | |
367 { | |
368 fi_ptr = (const struct gcov_fn_info *) | |
369 ((const char *) gi_ptr->functions + f_ix * fi_stride); | |
370 tag = gcov_read_unsigned (); | |
371 length = gcov_read_unsigned (); | |
372 | |
373 /* Check function. */ | |
374 if (tag != GCOV_TAG_FUNCTION | |
375 || length != GCOV_TAG_FUNCTION_LENGTH | |
376 || gcov_read_unsigned () != fi_ptr->ident | |
377 || gcov_read_unsigned () != fi_ptr->checksum) | |
378 { | |
379 read_mismatch:; | |
380 fprintf (stderr, "profiling:%s:Merge mismatch for %s\n", | |
381 gi_filename, | |
382 f_ix + 1 ? "function" : "summaries"); | |
383 goto read_fatal; | |
384 } | |
385 | |
386 c_ix = 0; | |
387 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) | |
388 { | |
389 gcov_merge_fn merge; | |
390 | |
391 if (!((1 << t_ix) & gi_ptr->ctr_mask)) | |
392 continue; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
393 |
0 | 394 n_counts = fi_ptr->n_ctrs[c_ix]; |
395 merge = gi_ptr->counts[c_ix].merge; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
396 |
0 | 397 tag = gcov_read_unsigned (); |
398 length = gcov_read_unsigned (); | |
399 if (tag != GCOV_TAG_FOR_COUNTER (t_ix) | |
400 || length != GCOV_TAG_COUNTER_LENGTH (n_counts)) | |
401 goto read_mismatch; | |
402 (*merge) (values[c_ix], n_counts); | |
403 values[c_ix] += n_counts; | |
404 c_ix++; | |
405 } | |
406 if ((error = gcov_is_error ())) | |
407 goto read_error; | |
408 } | |
409 | |
410 f_ix = ~0u; | |
411 /* Check program & object summary */ | |
412 while (1) | |
413 { | |
414 int is_program; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
415 |
0 | 416 eof_pos = gcov_position (); |
417 tag = gcov_read_unsigned (); | |
418 if (!tag) | |
419 break; | |
420 | |
421 length = gcov_read_unsigned (); | |
422 is_program = tag == GCOV_TAG_PROGRAM_SUMMARY; | |
423 if (length != GCOV_TAG_SUMMARY_LENGTH | |
424 || (!is_program && tag != GCOV_TAG_OBJECT_SUMMARY)) | |
425 goto read_mismatch; | |
426 gcov_read_summary (is_program ? &program : &object); | |
427 if ((error = gcov_is_error ())) | |
428 goto read_error; | |
429 if (is_program && program.checksum == gcov_crc32) | |
430 { | |
431 summary_pos = eof_pos; | |
432 goto rewrite; | |
433 } | |
434 } | |
435 } | |
436 goto rewrite; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
437 |
0 | 438 read_error:; |
439 fprintf (stderr, error < 0 ? "profiling:%s:Overflow merging\n" | |
440 : "profiling:%s:Error merging\n", gi_filename); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
441 |
0 | 442 read_fatal:; |
443 gcov_close (); | |
444 continue; | |
445 | |
446 rewrite:; | |
447 gcov_rewrite (); | |
448 if (!summary_pos) | |
449 memset (&program, 0, sizeof (program)); | |
450 | |
451 /* Merge the summaries. */ | |
452 f_ix = ~0u; | |
453 for (t_ix = 0; t_ix < GCOV_COUNTERS_SUMMABLE; t_ix++) | |
454 { | |
455 cs_obj = &object.ctrs[t_ix]; | |
456 cs_tobj = &this_object.ctrs[t_ix]; | |
457 cs_prg = &program.ctrs[t_ix]; | |
458 cs_tprg = &this_program.ctrs[t_ix]; | |
459 cs_all = &all.ctrs[t_ix]; | |
460 | |
461 if ((1 << t_ix) & gi_ptr->ctr_mask) | |
462 { | |
463 if (!cs_obj->runs++) | |
464 cs_obj->num = cs_tobj->num; | |
465 else if (cs_obj->num != cs_tobj->num) | |
466 goto read_mismatch; | |
467 cs_obj->sum_all += cs_tobj->sum_all; | |
468 if (cs_obj->run_max < cs_tobj->run_max) | |
469 cs_obj->run_max = cs_tobj->run_max; | |
470 cs_obj->sum_max += cs_tobj->run_max; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
471 |
0 | 472 if (!cs_prg->runs++) |
473 cs_prg->num = cs_tprg->num; | |
474 else if (cs_prg->num != cs_tprg->num) | |
475 goto read_mismatch; | |
476 cs_prg->sum_all += cs_tprg->sum_all; | |
477 if (cs_prg->run_max < cs_tprg->run_max) | |
478 cs_prg->run_max = cs_tprg->run_max; | |
479 cs_prg->sum_max += cs_tprg->run_max; | |
480 } | |
481 else if (cs_obj->num || cs_prg->num) | |
482 goto read_mismatch; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
483 |
0 | 484 if (!cs_all->runs && cs_prg->runs) |
485 memcpy (cs_all, cs_prg, sizeof (*cs_all)); | |
486 else if (!all.checksum | |
487 && (!GCOV_LOCKED || cs_all->runs == cs_prg->runs) | |
488 && memcmp (cs_all, cs_prg, sizeof (*cs_all))) | |
489 { | |
490 fprintf (stderr, "profiling:%s:Invocation mismatch - some data files may have been removed%s", | |
491 gi_filename, GCOV_LOCKED | |
492 ? "" : " or concurrent update without locking support"); | |
493 all.checksum = ~0u; | |
494 } | |
495 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
496 |
0 | 497 c_ix = 0; |
498 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) | |
499 if ((1 << t_ix) & gi_ptr->ctr_mask) | |
500 { | |
501 values[c_ix] = gi_ptr->counts[c_ix].values; | |
502 c_ix++; | |
503 } | |
504 | |
505 program.checksum = gcov_crc32; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
506 |
0 | 507 /* Write out the data. */ |
508 gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION); | |
509 gcov_write_unsigned (gi_ptr->stamp); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
510 |
0 | 511 /* Write execution counts for each function. */ |
512 for (f_ix = 0; f_ix < gi_ptr->n_functions; f_ix++) | |
513 { | |
514 fi_ptr = (const struct gcov_fn_info *) | |
515 ((const char *) gi_ptr->functions + f_ix * fi_stride); | |
516 | |
517 /* Announce function. */ | |
518 gcov_write_tag_length (GCOV_TAG_FUNCTION, GCOV_TAG_FUNCTION_LENGTH); | |
519 gcov_write_unsigned (fi_ptr->ident); | |
520 gcov_write_unsigned (fi_ptr->checksum); | |
521 | |
522 c_ix = 0; | |
523 for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++) | |
524 { | |
525 gcov_type *c_ptr; | |
526 | |
527 if (!((1 << t_ix) & gi_ptr->ctr_mask)) | |
528 continue; | |
529 | |
530 n_counts = fi_ptr->n_ctrs[c_ix]; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
531 |
0 | 532 gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix), |
533 GCOV_TAG_COUNTER_LENGTH (n_counts)); | |
534 c_ptr = values[c_ix]; | |
535 while (n_counts--) | |
536 gcov_write_counter (*c_ptr++); | |
537 | |
538 values[c_ix] = c_ptr; | |
539 c_ix++; | |
540 } | |
541 } | |
542 | |
543 /* Object file summary. */ | |
544 gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, &object); | |
545 | |
546 /* Generate whole program statistics. */ | |
547 if (eof_pos) | |
548 gcov_seek (eof_pos); | |
549 gcov_write_summary (GCOV_TAG_PROGRAM_SUMMARY, &program); | |
550 if (!summary_pos) | |
551 gcov_write_unsigned (0); | |
552 if ((error = gcov_close ())) | |
553 fprintf (stderr, error < 0 ? | |
554 "profiling:%s:Overflow writing\n" : | |
555 "profiling:%s:Error writing\n", | |
556 gi_filename); | |
557 } | |
558 } | |
559 | |
560 /* Add a new object file onto the bb chain. Invoked automatically | |
561 when running an object file's global ctors. */ | |
562 | |
563 void | |
564 __gcov_init (struct gcov_info *info) | |
565 { | |
566 if (!info->version) | |
567 return; | |
568 if (gcov_version (info, info->version, 0)) | |
569 { | |
570 const char *ptr = info->filename; | |
571 gcov_unsigned_t crc32 = gcov_crc32; | |
572 size_t filename_length = strlen(info->filename); | |
573 | |
574 /* Refresh the longest file name information */ | |
575 if (filename_length > gcov_max_filename) | |
576 gcov_max_filename = filename_length; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
577 |
0 | 578 do |
579 { | |
580 unsigned ix; | |
581 gcov_unsigned_t value = *ptr << 24; | |
582 | |
583 for (ix = 8; ix--; value <<= 1) | |
584 { | |
585 gcov_unsigned_t feedback; | |
586 | |
587 feedback = (value ^ crc32) & 0x80000000 ? 0x04c11db7 : 0; | |
588 crc32 <<= 1; | |
589 crc32 ^= feedback; | |
590 } | |
591 } | |
592 while (*ptr++); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
593 |
0 | 594 gcov_crc32 = crc32; |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
595 |
0 | 596 if (!gcov_list) |
597 atexit (gcov_exit); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
598 |
0 | 599 info->next = gcov_list; |
600 gcov_list = info; | |
601 } | |
602 info->version = 0; | |
603 } | |
604 | |
605 /* Called before fork or exec - write out profile information gathered so | |
606 far and reset it to zero. This avoids duplication or loss of the | |
607 profile information gathered so far. */ | |
608 | |
609 void | |
610 __gcov_flush (void) | |
611 { | |
612 const struct gcov_info *gi_ptr; | |
613 | |
614 gcov_exit (); | |
615 for (gi_ptr = gcov_list; gi_ptr; gi_ptr = gi_ptr->next) | |
616 { | |
617 unsigned t_ix; | |
618 const struct gcov_ctr_info *ci_ptr; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
619 |
0 | 620 for (t_ix = 0, ci_ptr = gi_ptr->counts; t_ix != GCOV_COUNTERS; t_ix++) |
621 if ((1 << t_ix) & gi_ptr->ctr_mask) | |
622 { | |
623 memset (ci_ptr->values, 0, sizeof (gcov_type) * ci_ptr->num); | |
624 ci_ptr++; | |
625 } | |
626 } | |
627 } | |
628 | |
629 #endif /* L_gcov */ | |
630 | |
631 #ifdef L_gcov_merge_add | |
632 /* The profile merging function that just adds the counters. It is given | |
633 an array COUNTERS of N_COUNTERS old counters and it reads the same number | |
634 of counters from the gcov file. */ | |
635 void | |
636 __gcov_merge_add (gcov_type *counters, unsigned n_counters) | |
637 { | |
638 for (; n_counters; counters++, n_counters--) | |
639 *counters += gcov_read_counter (); | |
640 } | |
641 #endif /* L_gcov_merge_add */ | |
642 | |
643 #ifdef L_gcov_merge_ior | |
644 /* The profile merging function that just adds the counters. It is given | |
645 an array COUNTERS of N_COUNTERS old counters and it reads the same number | |
646 of counters from the gcov file. */ | |
647 void | |
648 __gcov_merge_ior (gcov_type *counters, unsigned n_counters) | |
649 { | |
650 for (; n_counters; counters++, n_counters--) | |
651 *counters |= gcov_read_counter (); | |
652 } | |
653 #endif | |
654 | |
655 #ifdef L_gcov_merge_single | |
656 /* The profile merging function for choosing the most common value. | |
657 It is given an array COUNTERS of N_COUNTERS old counters and it | |
658 reads the same number of counters from the gcov file. The counters | |
659 are split into 3-tuples where the members of the tuple have | |
660 meanings: | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
661 |
0 | 662 -- the stored candidate on the most common value of the measured entity |
663 -- counter | |
664 -- total number of evaluations of the value */ | |
665 void | |
666 __gcov_merge_single (gcov_type *counters, unsigned n_counters) | |
667 { | |
668 unsigned i, n_measures; | |
669 gcov_type value, counter, all; | |
670 | |
671 gcc_assert (!(n_counters % 3)); | |
672 n_measures = n_counters / 3; | |
673 for (i = 0; i < n_measures; i++, counters += 3) | |
674 { | |
675 value = gcov_read_counter (); | |
676 counter = gcov_read_counter (); | |
677 all = gcov_read_counter (); | |
678 | |
679 if (counters[0] == value) | |
680 counters[1] += counter; | |
681 else if (counter > counters[1]) | |
682 { | |
683 counters[0] = value; | |
684 counters[1] = counter - counters[1]; | |
685 } | |
686 else | |
687 counters[1] -= counter; | |
688 counters[2] += all; | |
689 } | |
690 } | |
691 #endif /* L_gcov_merge_single */ | |
692 | |
693 #ifdef L_gcov_merge_delta | |
694 /* The profile merging function for choosing the most common | |
695 difference between two consecutive evaluations of the value. It is | |
696 given an array COUNTERS of N_COUNTERS old counters and it reads the | |
697 same number of counters from the gcov file. The counters are split | |
698 into 4-tuples where the members of the tuple have meanings: | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
699 |
0 | 700 -- the last value of the measured entity |
701 -- the stored candidate on the most common difference | |
702 -- counter | |
703 -- total number of evaluations of the value */ | |
704 void | |
705 __gcov_merge_delta (gcov_type *counters, unsigned n_counters) | |
706 { | |
707 unsigned i, n_measures; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
708 gcov_type value, counter, all; |
0 | 709 |
710 gcc_assert (!(n_counters % 4)); | |
711 n_measures = n_counters / 4; | |
712 for (i = 0; i < n_measures; i++, counters += 4) | |
713 { | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
714 /* last = */ gcov_read_counter (); |
0 | 715 value = gcov_read_counter (); |
716 counter = gcov_read_counter (); | |
717 all = gcov_read_counter (); | |
718 | |
719 if (counters[1] == value) | |
720 counters[2] += counter; | |
721 else if (counter > counters[2]) | |
722 { | |
723 counters[1] = value; | |
724 counters[2] = counter - counters[2]; | |
725 } | |
726 else | |
727 counters[2] -= counter; | |
728 counters[3] += all; | |
729 } | |
730 } | |
731 #endif /* L_gcov_merge_delta */ | |
732 | |
733 #ifdef L_gcov_interval_profiler | |
734 /* If VALUE is in interval <START, START + STEPS - 1>, then increases the | |
735 corresponding counter in COUNTERS. If the VALUE is above or below | |
736 the interval, COUNTERS[STEPS] or COUNTERS[STEPS + 1] is increased | |
737 instead. */ | |
738 | |
739 void | |
740 __gcov_interval_profiler (gcov_type *counters, gcov_type value, | |
741 int start, unsigned steps) | |
742 { | |
743 gcov_type delta = value - start; | |
744 if (delta < 0) | |
745 counters[steps + 1]++; | |
746 else if (delta >= steps) | |
747 counters[steps]++; | |
748 else | |
749 counters[delta]++; | |
750 } | |
751 #endif | |
752 | |
753 #ifdef L_gcov_pow2_profiler | |
754 /* If VALUE is a power of two, COUNTERS[1] is incremented. Otherwise | |
755 COUNTERS[0] is incremented. */ | |
756 | |
757 void | |
758 __gcov_pow2_profiler (gcov_type *counters, gcov_type value) | |
759 { | |
760 if (value & (value - 1)) | |
761 counters[0]++; | |
762 else | |
763 counters[1]++; | |
764 } | |
765 #endif | |
766 | |
767 /* Tries to determine the most common value among its inputs. Checks if the | |
768 value stored in COUNTERS[0] matches VALUE. If this is the case, COUNTERS[1] | |
769 is incremented. If this is not the case and COUNTERS[1] is not zero, | |
770 COUNTERS[1] is decremented. Otherwise COUNTERS[1] is set to one and | |
771 VALUE is stored to COUNTERS[0]. This algorithm guarantees that if this | |
772 function is called more than 50% of the time with one value, this value | |
773 will be in COUNTERS[0] in the end. | |
774 | |
775 In any case, COUNTERS[2] is incremented. */ | |
776 | |
777 static inline void | |
778 __gcov_one_value_profiler_body (gcov_type *counters, gcov_type value) | |
779 { | |
780 if (value == counters[0]) | |
781 counters[1]++; | |
782 else if (counters[1] == 0) | |
783 { | |
784 counters[1] = 1; | |
785 counters[0] = value; | |
786 } | |
787 else | |
788 counters[1]--; | |
789 counters[2]++; | |
790 } | |
791 | |
792 #ifdef L_gcov_one_value_profiler | |
793 void | |
794 __gcov_one_value_profiler (gcov_type *counters, gcov_type value) | |
795 { | |
796 __gcov_one_value_profiler_body (counters, value); | |
797 } | |
798 #endif | |
799 | |
800 #ifdef L_gcov_indirect_call_profiler | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
801 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
802 /* By default, the C++ compiler will use function addresses in the |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
803 vtable entries. Setting TARGET_VTABLE_USES_DESCRIPTORS to nonzero |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
804 tells the compiler to use function descriptors instead. The value |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
805 of this macro says how many words wide the descriptor is (normally 2), |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
806 but it may be dependent on target flags. Since we do not have access |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
807 to the target flags here we just check to see if it is set and use |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
808 that to set VTABLE_USES_DESCRIPTORS to 0 or 1. |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
809 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
810 It is assumed that the address of a function descriptor may be treated |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
811 as a pointer to a function. */ |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
812 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
813 #ifdef TARGET_VTABLE_USES_DESCRIPTORS |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
814 #define VTABLE_USES_DESCRIPTORS 1 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
815 #else |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
816 #define VTABLE_USES_DESCRIPTORS 0 |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
817 #endif |
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
818 |
0 | 819 /* Tries to determine the most common value among its inputs. */ |
820 void | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
0
diff
changeset
|
821 __gcov_indirect_call_profiler (gcov_type* counter, gcov_type value, |
0 | 822 void* cur_func, void* callee_func) |
823 { | |
824 /* If the C++ virtual tables contain function descriptors then one | |
825 function may have multiple descriptors and we need to dereference | |
826 the descriptors to see if they point to the same function. */ | |
827 if (cur_func == callee_func | |
67
f6334be47118
update gcc from gcc-4.6-20100522 to gcc-4.6-20110318
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
55
diff
changeset
|
828 || (VTABLE_USES_DESCRIPTORS && callee_func |
0 | 829 && *(void **) cur_func == *(void **) callee_func)) |
830 __gcov_one_value_profiler_body (counter, value); | |
831 } | |
832 #endif | |
833 | |
834 | |
835 #ifdef L_gcov_average_profiler | |
836 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want | |
837 to saturate up. */ | |
838 | |
839 void | |
840 __gcov_average_profiler (gcov_type *counters, gcov_type value) | |
841 { | |
842 counters[0] += value; | |
843 counters[1] ++; | |
844 } | |
845 #endif | |
846 | |
847 #ifdef L_gcov_ior_profiler | |
848 /* Increase corresponding COUNTER by VALUE. FIXME: Perhaps we want | |
849 to saturate up. */ | |
850 | |
851 void | |
852 __gcov_ior_profiler (gcov_type *counters, gcov_type value) | |
853 { | |
854 *counters |= value; | |
855 } | |
856 #endif | |
857 | |
858 #ifdef L_gcov_fork | |
859 /* A wrapper for the fork function. Flushes the accumulated profiling data, so | |
860 that they are not counted twice. */ | |
861 | |
862 pid_t | |
863 __gcov_fork (void) | |
864 { | |
865 __gcov_flush (); | |
866 return fork (); | |
867 } | |
868 #endif | |
869 | |
870 #ifdef L_gcov_execl | |
871 /* A wrapper for the execl function. Flushes the accumulated profiling data, so | |
872 that they are not lost. */ | |
873 | |
874 int | |
875 __gcov_execl (const char *path, char *arg, ...) | |
876 { | |
877 va_list ap, aq; | |
878 unsigned i, length; | |
879 char **args; | |
880 | |
881 __gcov_flush (); | |
882 | |
883 va_start (ap, arg); | |
884 va_copy (aq, ap); | |
885 | |
886 length = 2; | |
887 while (va_arg (ap, char *)) | |
888 length++; | |
889 va_end (ap); | |
890 | |
891 args = (char **) alloca (length * sizeof (void *)); | |
892 args[0] = arg; | |
893 for (i = 1; i < length; i++) | |
894 args[i] = va_arg (aq, char *); | |
895 va_end (aq); | |
896 | |
897 return execv (path, args); | |
898 } | |
899 #endif | |
900 | |
901 #ifdef L_gcov_execlp | |
902 /* A wrapper for the execlp function. Flushes the accumulated profiling data, so | |
903 that they are not lost. */ | |
904 | |
905 int | |
906 __gcov_execlp (const char *path, char *arg, ...) | |
907 { | |
908 va_list ap, aq; | |
909 unsigned i, length; | |
910 char **args; | |
911 | |
912 __gcov_flush (); | |
913 | |
914 va_start (ap, arg); | |
915 va_copy (aq, ap); | |
916 | |
917 length = 2; | |
918 while (va_arg (ap, char *)) | |
919 length++; | |
920 va_end (ap); | |
921 | |
922 args = (char **) alloca (length * sizeof (void *)); | |
923 args[0] = arg; | |
924 for (i = 1; i < length; i++) | |
925 args[i] = va_arg (aq, char *); | |
926 va_end (aq); | |
927 | |
928 return execvp (path, args); | |
929 } | |
930 #endif | |
931 | |
932 #ifdef L_gcov_execle | |
933 /* A wrapper for the execle function. Flushes the accumulated profiling data, so | |
934 that they are not lost. */ | |
935 | |
936 int | |
937 __gcov_execle (const char *path, char *arg, ...) | |
938 { | |
939 va_list ap, aq; | |
940 unsigned i, length; | |
941 char **args; | |
942 char **envp; | |
943 | |
944 __gcov_flush (); | |
945 | |
946 va_start (ap, arg); | |
947 va_copy (aq, ap); | |
948 | |
949 length = 2; | |
950 while (va_arg (ap, char *)) | |
951 length++; | |
952 va_end (ap); | |
953 | |
954 args = (char **) alloca (length * sizeof (void *)); | |
955 args[0] = arg; | |
956 for (i = 1; i < length; i++) | |
957 args[i] = va_arg (aq, char *); | |
958 envp = va_arg (aq, char **); | |
959 va_end (aq); | |
960 | |
961 return execve (path, args, envp); | |
962 } | |
963 #endif | |
964 | |
965 #ifdef L_gcov_execv | |
966 /* A wrapper for the execv function. Flushes the accumulated profiling data, so | |
967 that they are not lost. */ | |
968 | |
969 int | |
970 __gcov_execv (const char *path, char *const argv[]) | |
971 { | |
972 __gcov_flush (); | |
973 return execv (path, argv); | |
974 } | |
975 #endif | |
976 | |
977 #ifdef L_gcov_execvp | |
978 /* A wrapper for the execvp function. Flushes the accumulated profiling data, so | |
979 that they are not lost. */ | |
980 | |
981 int | |
982 __gcov_execvp (const char *path, char *const argv[]) | |
983 { | |
984 __gcov_flush (); | |
985 return execvp (path, argv); | |
986 } | |
987 #endif | |
988 | |
989 #ifdef L_gcov_execve | |
990 /* A wrapper for the execve function. Flushes the accumulated profiling data, so | |
991 that they are not lost. */ | |
992 | |
993 int | |
994 __gcov_execve (const char *path, char *const argv[], char *const envp[]) | |
995 { | |
996 __gcov_flush (); | |
997 return execve (path, argv, envp); | |
998 } | |
999 #endif | |
1000 #endif /* inhibit_libc */ |