libgcov-driver.c revision 1.6 1 1.1 mrg /* Routines required for instrumenting a program. */
2 1.1 mrg /* Compile this one with gcc. */
3 1.6 mrg /* Copyright (C) 1989-2020 Free Software Foundation, Inc.
4 1.1 mrg
5 1.1 mrg This file is part of GCC.
6 1.1 mrg
7 1.1 mrg GCC is free software; you can redistribute it and/or modify it under
8 1.1 mrg the terms of the GNU General Public License as published by the Free
9 1.1 mrg Software Foundation; either version 3, or (at your option) any later
10 1.1 mrg version.
11 1.1 mrg
12 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 1.1 mrg for more details.
16 1.1 mrg
17 1.1 mrg Under Section 7 of GPL version 3, you are granted additional
18 1.1 mrg permissions described in the GCC Runtime Library Exception, version
19 1.1 mrg 3.1, as published by the Free Software Foundation.
20 1.1 mrg
21 1.1 mrg You should have received a copy of the GNU General Public License and
22 1.1 mrg a copy of the GCC Runtime Library Exception along with this program;
23 1.1 mrg see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
24 1.1 mrg <http://www.gnu.org/licenses/>. */
25 1.1 mrg
26 1.1 mrg #include "libgcov.h"
27 1.5 mrg #include "gcov-io.h"
28 1.1 mrg
29 1.1 mrg #if defined(inhibit_libc)
30 1.1 mrg /* If libc and its header files are not available, provide dummy functions. */
31 1.1 mrg
32 1.1 mrg #if defined(L_gcov)
33 1.1 mrg void __gcov_init (struct gcov_info *p __attribute__ ((unused))) {}
34 1.1 mrg #endif
35 1.1 mrg
36 1.1 mrg #else /* inhibit_libc */
37 1.1 mrg
38 1.1 mrg #include <string.h>
39 1.1 mrg #if GCOV_LOCKED
40 1.1 mrg #include <fcntl.h>
41 1.1 mrg #include <errno.h>
42 1.1 mrg #include <sys/stat.h>
43 1.1 mrg #endif
44 1.1 mrg
45 1.1 mrg #ifdef L_gcov
46 1.1 mrg
47 1.3 mrg /* A utility function for outputting errors. */
48 1.1 mrg static int gcov_error (const char *, ...);
49 1.1 mrg
50 1.3 mrg #if !IN_GCOV_TOOL
51 1.3 mrg static void gcov_error_exit (void);
52 1.3 mrg #endif
53 1.3 mrg
54 1.1 mrg #include "gcov-io.c"
55 1.1 mrg
56 1.5 mrg #define GCOV_PROF_PREFIX "libgcov profiling error:%s:"
57 1.5 mrg
58 1.1 mrg struct gcov_fn_buffer
59 1.1 mrg {
60 1.1 mrg struct gcov_fn_buffer *next;
61 1.1 mrg unsigned fn_ix;
62 1.1 mrg struct gcov_fn_info info;
63 1.1 mrg /* note gcov_fn_info ends in a trailing array. */
64 1.1 mrg };
65 1.1 mrg
66 1.1 mrg struct gcov_summary_buffer
67 1.1 mrg {
68 1.1 mrg struct gcov_summary_buffer *next;
69 1.1 mrg struct gcov_summary summary;
70 1.1 mrg };
71 1.1 mrg
72 1.1 mrg /* A struct that bundles all the related information about the
73 1.1 mrg gcda filename. */
74 1.1 mrg
75 1.1 mrg struct gcov_filename
76 1.1 mrg {
77 1.1 mrg char *filename; /* filename buffer */
78 1.1 mrg int strip; /* leading chars to strip from filename */
79 1.5 mrg char *prefix; /* prefix string */
80 1.1 mrg };
81 1.1 mrg
82 1.1 mrg static struct gcov_fn_buffer *
83 1.1 mrg free_fn_data (const struct gcov_info *gi_ptr, struct gcov_fn_buffer *buffer,
84 1.1 mrg unsigned limit)
85 1.1 mrg {
86 1.1 mrg struct gcov_fn_buffer *next;
87 1.1 mrg unsigned ix, n_ctr = 0;
88 1.1 mrg
89 1.1 mrg if (!buffer)
90 1.1 mrg return 0;
91 1.1 mrg next = buffer->next;
92 1.1 mrg
93 1.1 mrg for (ix = 0; ix != limit; ix++)
94 1.1 mrg if (gi_ptr->merge[ix])
95 1.1 mrg free (buffer->info.ctrs[n_ctr++].values);
96 1.1 mrg free (buffer);
97 1.1 mrg return next;
98 1.1 mrg }
99 1.1 mrg
100 1.1 mrg static struct gcov_fn_buffer **
101 1.1 mrg buffer_fn_data (const char *filename, const struct gcov_info *gi_ptr,
102 1.1 mrg struct gcov_fn_buffer **end_ptr, unsigned fn_ix)
103 1.1 mrg {
104 1.1 mrg unsigned n_ctrs = 0, ix = 0;
105 1.1 mrg struct gcov_fn_buffer *fn_buffer;
106 1.1 mrg unsigned len;
107 1.1 mrg
108 1.1 mrg for (ix = GCOV_COUNTERS; ix--;)
109 1.1 mrg if (gi_ptr->merge[ix])
110 1.1 mrg n_ctrs++;
111 1.1 mrg
112 1.1 mrg len = sizeof (*fn_buffer) + sizeof (fn_buffer->info.ctrs[0]) * n_ctrs;
113 1.1 mrg fn_buffer = (struct gcov_fn_buffer *) xmalloc (len);
114 1.1 mrg
115 1.1 mrg if (!fn_buffer)
116 1.1 mrg goto fail;
117 1.1 mrg
118 1.1 mrg fn_buffer->next = 0;
119 1.1 mrg fn_buffer->fn_ix = fn_ix;
120 1.1 mrg fn_buffer->info.ident = gcov_read_unsigned ();
121 1.1 mrg fn_buffer->info.lineno_checksum = gcov_read_unsigned ();
122 1.1 mrg fn_buffer->info.cfg_checksum = gcov_read_unsigned ();
123 1.1 mrg
124 1.1 mrg for (n_ctrs = ix = 0; ix != GCOV_COUNTERS; ix++)
125 1.1 mrg {
126 1.1 mrg gcov_unsigned_t length;
127 1.1 mrg gcov_type *values;
128 1.1 mrg
129 1.1 mrg if (!gi_ptr->merge[ix])
130 1.1 mrg continue;
131 1.1 mrg
132 1.1 mrg if (gcov_read_unsigned () != GCOV_TAG_FOR_COUNTER (ix))
133 1.1 mrg {
134 1.1 mrg len = 0;
135 1.1 mrg goto fail;
136 1.1 mrg }
137 1.1 mrg
138 1.1 mrg length = GCOV_TAG_COUNTER_NUM (gcov_read_unsigned ());
139 1.1 mrg len = length * sizeof (gcov_type);
140 1.1 mrg values = (gcov_type *) xmalloc (len);
141 1.1 mrg if (!values)
142 1.1 mrg goto fail;
143 1.1 mrg
144 1.1 mrg fn_buffer->info.ctrs[n_ctrs].num = length;
145 1.1 mrg fn_buffer->info.ctrs[n_ctrs].values = values;
146 1.1 mrg
147 1.1 mrg while (length--)
148 1.1 mrg *values++ = gcov_read_counter ();
149 1.1 mrg n_ctrs++;
150 1.1 mrg }
151 1.1 mrg
152 1.1 mrg *end_ptr = fn_buffer;
153 1.1 mrg return &fn_buffer->next;
154 1.1 mrg
155 1.1 mrg fail:
156 1.5 mrg gcov_error (GCOV_PROF_PREFIX "Function %u %s %u \n", filename, fn_ix,
157 1.1 mrg len ? "cannot allocate" : "counter mismatch", len ? len : ix);
158 1.1 mrg
159 1.1 mrg return (struct gcov_fn_buffer **)free_fn_data (gi_ptr, fn_buffer, ix);
160 1.1 mrg }
161 1.1 mrg
162 1.5 mrg /* Convert VERSION into a string description and return the it.
163 1.5 mrg BUFFER is used for storage of the string. The code should be
164 1.5 mrg aligned wit gcov-iov.c. */
165 1.5 mrg
166 1.5 mrg static char *
167 1.5 mrg gcov_version_string (char *buffer, char version[4])
168 1.5 mrg {
169 1.5 mrg if (version[0] < 'A' || version[0] > 'Z'
170 1.5 mrg || version[1] < '0' || version[1] > '9'
171 1.5 mrg || version[2] < '0' || version[2] > '9')
172 1.5 mrg sprintf (buffer, "(unknown)");
173 1.5 mrg else
174 1.1 mrg {
175 1.5 mrg unsigned major = 10 * (version[0] - 'A') + (version[1] - '0');
176 1.5 mrg unsigned minor = version[2] - '0';
177 1.5 mrg sprintf (buffer, "%u.%u (%s)", major, minor,
178 1.5 mrg version[3] == '*' ? "release" : "experimental");
179 1.1 mrg }
180 1.5 mrg return buffer;
181 1.1 mrg }
182 1.1 mrg
183 1.1 mrg /* Check if VERSION of the info block PTR matches libgcov one.
184 1.1 mrg Return 1 on success, or zero in case of versions mismatch.
185 1.1 mrg If FILENAME is not NULL, its value used for reporting purposes
186 1.1 mrg instead of value from the info block. */
187 1.1 mrg
188 1.1 mrg static int
189 1.1 mrg gcov_version (struct gcov_info *ptr, gcov_unsigned_t version,
190 1.1 mrg const char *filename)
191 1.1 mrg {
192 1.1 mrg if (version != GCOV_VERSION)
193 1.1 mrg {
194 1.1 mrg char v[4], e[4];
195 1.5 mrg char version_string[128], expected_string[128];
196 1.1 mrg
197 1.1 mrg GCOV_UNSIGNED2STRING (v, version);
198 1.1 mrg GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
199 1.1 mrg
200 1.5 mrg gcov_error (GCOV_PROF_PREFIX "Version mismatch - expected %s (%.4s) "
201 1.5 mrg "got %s (%.4s)\n",
202 1.5 mrg filename? filename : ptr->filename,
203 1.5 mrg gcov_version_string (expected_string, e), e,
204 1.5 mrg gcov_version_string (version_string, v), v);
205 1.1 mrg return 0;
206 1.1 mrg }
207 1.1 mrg return 1;
208 1.1 mrg }
209 1.1 mrg
210 1.1 mrg /* buffer for the fn_data from another program. */
211 1.1 mrg static struct gcov_fn_buffer *fn_buffer;
212 1.1 mrg
213 1.1 mrg /* Including system dependent components. */
214 1.1 mrg #include "libgcov-driver-system.c"
215 1.1 mrg
216 1.6 mrg /* Prune TOP N value COUNTERS. It's needed in order to preserve
217 1.6 mrg reproducibility of builds. */
218 1.6 mrg
219 1.6 mrg static void
220 1.6 mrg prune_topn_counter (gcov_type *counters, gcov_type all)
221 1.6 mrg {
222 1.6 mrg for (unsigned i = 0; i < GCOV_TOPN_VALUES; i++)
223 1.6 mrg if (counters[2 * i + 1] < all)
224 1.6 mrg {
225 1.6 mrg counters[2 * i] = 0;
226 1.6 mrg counters[2 * i + 1] = 0;
227 1.6 mrg }
228 1.6 mrg }
229 1.6 mrg
230 1.6 mrg /* Prune counters so that they are ready to store or merge. */
231 1.6 mrg
232 1.6 mrg static void
233 1.6 mrg prune_counters (struct gcov_info *gi)
234 1.6 mrg {
235 1.6 mrg for (unsigned i = 0; i < gi->n_functions; i++)
236 1.6 mrg {
237 1.6 mrg const struct gcov_fn_info *gfi = gi->functions[i];
238 1.6 mrg const struct gcov_ctr_info *ci = gfi->ctrs;
239 1.6 mrg
240 1.6 mrg for (unsigned j = 0; j < GCOV_COUNTERS; j++)
241 1.6 mrg {
242 1.6 mrg if (gi->merge[j] == NULL)
243 1.6 mrg continue;
244 1.6 mrg
245 1.6 mrg if (j == GCOV_COUNTER_V_TOPN || j == GCOV_COUNTER_V_INDIR)
246 1.6 mrg {
247 1.6 mrg gcc_assert (!(ci->num % GCOV_TOPN_VALUES_COUNTERS));
248 1.6 mrg for (unsigned k = 0; k < (ci->num / GCOV_TOPN_VALUES_COUNTERS);
249 1.6 mrg k++)
250 1.6 mrg {
251 1.6 mrg gcov_type *counters
252 1.6 mrg = ci->values + (k * GCOV_TOPN_VALUES_COUNTERS);
253 1.6 mrg prune_topn_counter (counters + 1, *counters);
254 1.6 mrg }
255 1.6 mrg }
256 1.6 mrg ci++;
257 1.6 mrg }
258 1.6 mrg }
259 1.6 mrg }
260 1.6 mrg
261 1.1 mrg /* This function merges counters in GI_PTR to an existing gcda file.
262 1.1 mrg Return 0 on success.
263 1.1 mrg Return -1 on error. In this case, caller will goto read_fatal. */
264 1.1 mrg
265 1.1 mrg static int
266 1.1 mrg merge_one_data (const char *filename,
267 1.1 mrg struct gcov_info *gi_ptr,
268 1.5 mrg struct gcov_summary *summary)
269 1.1 mrg {
270 1.1 mrg gcov_unsigned_t tag, length;
271 1.1 mrg unsigned t_ix;
272 1.5 mrg int f_ix = -1;
273 1.1 mrg int error = 0;
274 1.1 mrg struct gcov_fn_buffer **fn_tail = &fn_buffer;
275 1.1 mrg
276 1.1 mrg length = gcov_read_unsigned ();
277 1.1 mrg if (!gcov_version (gi_ptr, length, filename))
278 1.1 mrg return -1;
279 1.1 mrg
280 1.1 mrg length = gcov_read_unsigned ();
281 1.1 mrg if (length != gi_ptr->stamp)
282 1.1 mrg {
283 1.5 mrg /* Read from a different compilation. Overwrite the file. */
284 1.5 mrg gcov_error (GCOV_PROF_PREFIX "overwriting an existing profile data "
285 1.5 mrg "with a different timestamp\n", filename);
286 1.5 mrg return 0;
287 1.5 mrg }
288 1.1 mrg
289 1.5 mrg tag = gcov_read_unsigned ();
290 1.5 mrg if (tag != GCOV_TAG_OBJECT_SUMMARY)
291 1.5 mrg goto read_mismatch;
292 1.5 mrg length = gcov_read_unsigned ();
293 1.5 mrg gcc_assert (length > 0);
294 1.5 mrg gcov_read_summary (summary);
295 1.1 mrg
296 1.5 mrg tag = gcov_read_unsigned ();
297 1.1 mrg /* Merge execution counts for each function. */
298 1.1 mrg for (f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions;
299 1.1 mrg f_ix++, tag = gcov_read_unsigned ())
300 1.1 mrg {
301 1.1 mrg const struct gcov_ctr_info *ci_ptr;
302 1.1 mrg const struct gcov_fn_info *gfi_ptr = gi_ptr->functions[f_ix];
303 1.1 mrg
304 1.1 mrg if (tag != GCOV_TAG_FUNCTION)
305 1.1 mrg goto read_mismatch;
306 1.1 mrg
307 1.1 mrg length = gcov_read_unsigned ();
308 1.1 mrg if (!length)
309 1.1 mrg /* This function did not appear in the other program.
310 1.1 mrg We have nothing to merge. */
311 1.1 mrg continue;
312 1.1 mrg
313 1.1 mrg if (length != GCOV_TAG_FUNCTION_LENGTH)
314 1.1 mrg goto read_mismatch;
315 1.1 mrg
316 1.1 mrg if (!gfi_ptr || gfi_ptr->key != gi_ptr)
317 1.1 mrg {
318 1.1 mrg /* This function appears in the other program. We
319 1.1 mrg need to buffer the information in order to write
320 1.1 mrg it back out -- we'll be inserting data before
321 1.1 mrg this point, so cannot simply keep the data in the
322 1.1 mrg file. */
323 1.1 mrg fn_tail = buffer_fn_data (filename, gi_ptr, fn_tail, f_ix);
324 1.1 mrg if (!fn_tail)
325 1.1 mrg goto read_mismatch;
326 1.1 mrg continue;
327 1.1 mrg }
328 1.1 mrg
329 1.1 mrg length = gcov_read_unsigned ();
330 1.1 mrg if (length != gfi_ptr->ident)
331 1.1 mrg goto read_mismatch;
332 1.1 mrg
333 1.1 mrg length = gcov_read_unsigned ();
334 1.1 mrg if (length != gfi_ptr->lineno_checksum)
335 1.1 mrg goto read_mismatch;
336 1.1 mrg
337 1.1 mrg length = gcov_read_unsigned ();
338 1.1 mrg if (length != gfi_ptr->cfg_checksum)
339 1.1 mrg goto read_mismatch;
340 1.1 mrg
341 1.1 mrg ci_ptr = gfi_ptr->ctrs;
342 1.1 mrg for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
343 1.1 mrg {
344 1.1 mrg gcov_merge_fn merge = gi_ptr->merge[t_ix];
345 1.1 mrg
346 1.1 mrg if (!merge)
347 1.1 mrg continue;
348 1.1 mrg
349 1.1 mrg tag = gcov_read_unsigned ();
350 1.1 mrg length = gcov_read_unsigned ();
351 1.1 mrg if (tag != GCOV_TAG_FOR_COUNTER (t_ix)
352 1.1 mrg || length != GCOV_TAG_COUNTER_LENGTH (ci_ptr->num))
353 1.1 mrg goto read_mismatch;
354 1.1 mrg (*merge) (ci_ptr->values, ci_ptr->num);
355 1.1 mrg ci_ptr++;
356 1.1 mrg }
357 1.1 mrg if ((error = gcov_is_error ()))
358 1.1 mrg goto read_error;
359 1.1 mrg }
360 1.1 mrg
361 1.1 mrg if (tag)
362 1.1 mrg {
363 1.1 mrg read_mismatch:;
364 1.5 mrg gcov_error (GCOV_PROF_PREFIX "Merge mismatch for %s %u\n",
365 1.1 mrg filename, f_ix >= 0 ? "function" : "summary",
366 1.1 mrg f_ix < 0 ? -1 - f_ix : f_ix);
367 1.1 mrg return -1;
368 1.1 mrg }
369 1.1 mrg return 0;
370 1.1 mrg
371 1.1 mrg read_error:
372 1.5 mrg gcov_error (GCOV_PROF_PREFIX "%s merging\n", filename,
373 1.1 mrg error < 0 ? "Overflow": "Error");
374 1.1 mrg return -1;
375 1.1 mrg }
376 1.1 mrg
377 1.1 mrg /* Write counters in GI_PTR and the summary in PRG to a gcda file. In
378 1.1 mrg the case of appending to an existing file, SUMMARY_POS will be non-zero.
379 1.1 mrg We will write the file starting from SUMMAY_POS. */
380 1.1 mrg
381 1.1 mrg static void
382 1.1 mrg write_one_data (const struct gcov_info *gi_ptr,
383 1.5 mrg const struct gcov_summary *prg_p)
384 1.1 mrg {
385 1.1 mrg unsigned f_ix;
386 1.1 mrg
387 1.5 mrg gcov_write_tag_length (GCOV_DATA_MAGIC, GCOV_VERSION);
388 1.5 mrg gcov_write_unsigned (gi_ptr->stamp);
389 1.1 mrg
390 1.1 mrg /* Generate whole program statistics. */
391 1.5 mrg gcov_write_summary (GCOV_TAG_OBJECT_SUMMARY, prg_p);
392 1.1 mrg
393 1.1 mrg /* Write execution counts for each function. */
394 1.1 mrg for (f_ix = 0; f_ix != gi_ptr->n_functions; f_ix++)
395 1.1 mrg {
396 1.1 mrg unsigned buffered = 0;
397 1.1 mrg const struct gcov_fn_info *gfi_ptr;
398 1.1 mrg const struct gcov_ctr_info *ci_ptr;
399 1.1 mrg gcov_unsigned_t length;
400 1.1 mrg unsigned t_ix;
401 1.1 mrg
402 1.1 mrg if (fn_buffer && fn_buffer->fn_ix == f_ix)
403 1.1 mrg {
404 1.1 mrg /* Buffered data from another program. */
405 1.1 mrg buffered = 1;
406 1.1 mrg gfi_ptr = &fn_buffer->info;
407 1.1 mrg length = GCOV_TAG_FUNCTION_LENGTH;
408 1.1 mrg }
409 1.1 mrg else
410 1.1 mrg {
411 1.1 mrg gfi_ptr = gi_ptr->functions[f_ix];
412 1.1 mrg if (gfi_ptr && gfi_ptr->key == gi_ptr)
413 1.1 mrg length = GCOV_TAG_FUNCTION_LENGTH;
414 1.1 mrg else
415 1.1 mrg length = 0;
416 1.1 mrg }
417 1.1 mrg
418 1.1 mrg gcov_write_tag_length (GCOV_TAG_FUNCTION, length);
419 1.1 mrg if (!length)
420 1.1 mrg continue;
421 1.1 mrg
422 1.1 mrg gcov_write_unsigned (gfi_ptr->ident);
423 1.1 mrg gcov_write_unsigned (gfi_ptr->lineno_checksum);
424 1.1 mrg gcov_write_unsigned (gfi_ptr->cfg_checksum);
425 1.1 mrg
426 1.1 mrg ci_ptr = gfi_ptr->ctrs;
427 1.1 mrg for (t_ix = 0; t_ix < GCOV_COUNTERS; t_ix++)
428 1.1 mrg {
429 1.1 mrg gcov_unsigned_t n_counts;
430 1.1 mrg gcov_type *c_ptr;
431 1.1 mrg
432 1.1 mrg if (!gi_ptr->merge[t_ix])
433 1.1 mrg continue;
434 1.1 mrg
435 1.1 mrg n_counts = ci_ptr->num;
436 1.1 mrg gcov_write_tag_length (GCOV_TAG_FOR_COUNTER (t_ix),
437 1.1 mrg GCOV_TAG_COUNTER_LENGTH (n_counts));
438 1.1 mrg c_ptr = ci_ptr->values;
439 1.1 mrg while (n_counts--)
440 1.1 mrg gcov_write_counter (*c_ptr++);
441 1.1 mrg ci_ptr++;
442 1.1 mrg }
443 1.1 mrg if (buffered)
444 1.1 mrg fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
445 1.1 mrg }
446 1.1 mrg
447 1.1 mrg gcov_write_unsigned (0);
448 1.1 mrg }
449 1.1 mrg
450 1.5 mrg /* Helper function for merging summary. */
451 1.1 mrg
452 1.5 mrg static void
453 1.5 mrg merge_summary (int run_counted, struct gcov_summary *summary,
454 1.5 mrg gcov_type run_max)
455 1.1 mrg {
456 1.5 mrg if (!run_counted)
457 1.1 mrg {
458 1.5 mrg summary->runs++;
459 1.5 mrg summary->sum_max += run_max;
460 1.1 mrg }
461 1.1 mrg }
462 1.1 mrg
463 1.1 mrg /* Dump the coverage counts for one gcov_info object. We merge with existing
464 1.1 mrg counts when possible, to avoid growing the .da files ad infinitum. We use
465 1.1 mrg this program's checksum to make sure we only accumulate whole program
466 1.1 mrg statistics to the correct summary. An object file might be embedded
467 1.1 mrg in two separate programs, and we must keep the two program
468 1.1 mrg summaries separate. */
469 1.1 mrg
470 1.1 mrg static void
471 1.1 mrg dump_one_gcov (struct gcov_info *gi_ptr, struct gcov_filename *gf,
472 1.5 mrg unsigned run_counted, gcov_type run_max)
473 1.1 mrg {
474 1.5 mrg struct gcov_summary summary = {};
475 1.1 mrg int error;
476 1.1 mrg gcov_unsigned_t tag;
477 1.1 mrg fn_buffer = 0;
478 1.1 mrg
479 1.6 mrg /* Prune current counters before we merge them. */
480 1.6 mrg prune_counters (gi_ptr);
481 1.1 mrg
482 1.1 mrg error = gcov_exit_open_gcda_file (gi_ptr, gf);
483 1.1 mrg if (error == -1)
484 1.1 mrg return;
485 1.1 mrg
486 1.1 mrg tag = gcov_read_unsigned ();
487 1.1 mrg if (tag)
488 1.1 mrg {
489 1.1 mrg /* Merge data from file. */
490 1.1 mrg if (tag != GCOV_DATA_MAGIC)
491 1.1 mrg {
492 1.5 mrg gcov_error (GCOV_PROF_PREFIX "Not a gcov data file\n",
493 1.5 mrg gf->filename);
494 1.1 mrg goto read_fatal;
495 1.1 mrg }
496 1.5 mrg error = merge_one_data (gf->filename, gi_ptr, &summary);
497 1.1 mrg if (error == -1)
498 1.1 mrg goto read_fatal;
499 1.1 mrg }
500 1.1 mrg
501 1.1 mrg gcov_rewrite ();
502 1.1 mrg
503 1.5 mrg merge_summary (run_counted, &summary, run_max);
504 1.1 mrg
505 1.5 mrg write_one_data (gi_ptr, &summary);
506 1.1 mrg /* fall through */
507 1.1 mrg
508 1.1 mrg read_fatal:;
509 1.1 mrg while (fn_buffer)
510 1.1 mrg fn_buffer = free_fn_data (gi_ptr, fn_buffer, GCOV_COUNTERS);
511 1.1 mrg
512 1.1 mrg if ((error = gcov_close ()))
513 1.1 mrg gcov_error (error < 0 ?
514 1.5 mrg GCOV_PROF_PREFIX "Overflow writing\n" :
515 1.5 mrg GCOV_PROF_PREFIX "Error writing\n",
516 1.1 mrg gf->filename);
517 1.1 mrg }
518 1.1 mrg
519 1.1 mrg
520 1.1 mrg /* Dump all the coverage counts for the program. It first computes program
521 1.1 mrg summary and then traverses gcov_list list and dumps the gcov_info
522 1.1 mrg objects one by one. */
523 1.1 mrg
524 1.1 mrg #if !IN_GCOV_TOOL
525 1.1 mrg static
526 1.1 mrg #endif
527 1.1 mrg void
528 1.1 mrg gcov_do_dump (struct gcov_info *list, int run_counted)
529 1.1 mrg {
530 1.1 mrg struct gcov_info *gi_ptr;
531 1.1 mrg struct gcov_filename gf;
532 1.1 mrg
533 1.5 mrg /* Compute run_max of this program run. */
534 1.5 mrg gcov_type run_max = 0;
535 1.5 mrg for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
536 1.5 mrg for (unsigned f_ix = 0; (unsigned)f_ix != gi_ptr->n_functions; f_ix++)
537 1.5 mrg {
538 1.5 mrg const struct gcov_ctr_info *cinfo
539 1.5 mrg = &gi_ptr->functions[f_ix]->ctrs[GCOV_COUNTER_ARCS];
540 1.5 mrg
541 1.5 mrg for (unsigned i = 0; i < cinfo->num; i++)
542 1.5 mrg if (run_max < cinfo->values[i])
543 1.5 mrg run_max = cinfo->values[i];
544 1.5 mrg }
545 1.1 mrg
546 1.1 mrg allocate_filename_struct (&gf);
547 1.1 mrg
548 1.1 mrg /* Now merge each file. */
549 1.1 mrg for (gi_ptr = list; gi_ptr; gi_ptr = gi_ptr->next)
550 1.5 mrg {
551 1.5 mrg dump_one_gcov (gi_ptr, &gf, run_counted, run_max);
552 1.5 mrg free (gf.filename);
553 1.5 mrg }
554 1.1 mrg
555 1.5 mrg free (gf.prefix);
556 1.1 mrg }
557 1.1 mrg
558 1.3 mrg #if IN_GCOV_TOOL
559 1.3 mrg const char *
560 1.3 mrg __attribute__ ((unused))
561 1.3 mrg gcov_get_filename (struct gcov_info *list)
562 1.3 mrg {
563 1.3 mrg return list->filename;
564 1.3 mrg }
565 1.3 mrg #endif
566 1.3 mrg
567 1.1 mrg #if !IN_GCOV_TOOL
568 1.1 mrg void
569 1.1 mrg __gcov_dump_one (struct gcov_root *root)
570 1.1 mrg {
571 1.1 mrg if (root->dumped)
572 1.1 mrg return;
573 1.1 mrg
574 1.1 mrg gcov_do_dump (root->list, root->run_counted);
575 1.1 mrg
576 1.1 mrg root->dumped = 1;
577 1.1 mrg root->run_counted = 1;
578 1.1 mrg }
579 1.1 mrg
580 1.1 mrg /* Per-dynamic-object gcov state. */
581 1.1 mrg struct gcov_root __gcov_root;
582 1.1 mrg
583 1.1 mrg /* Exactly one of these will be live in the process image. */
584 1.1 mrg struct gcov_master __gcov_master =
585 1.1 mrg {GCOV_VERSION, 0};
586 1.1 mrg
587 1.3 mrg void
588 1.3 mrg __gcov_exit (void)
589 1.1 mrg {
590 1.1 mrg __gcov_dump_one (&__gcov_root);
591 1.1 mrg if (__gcov_root.next)
592 1.1 mrg __gcov_root.next->prev = __gcov_root.prev;
593 1.1 mrg if (__gcov_root.prev)
594 1.1 mrg __gcov_root.prev->next = __gcov_root.next;
595 1.1 mrg else
596 1.1 mrg __gcov_master.root = __gcov_root.next;
597 1.3 mrg
598 1.3 mrg gcov_error_exit ();
599 1.1 mrg }
600 1.1 mrg
601 1.1 mrg /* Add a new object file onto the bb chain. Invoked automatically
602 1.1 mrg when running an object file's global ctors. */
603 1.1 mrg
604 1.1 mrg void
605 1.1 mrg __gcov_init (struct gcov_info *info)
606 1.1 mrg {
607 1.1 mrg if (!info->version || !info->n_functions)
608 1.1 mrg return;
609 1.1 mrg if (gcov_version (info, info->version, 0))
610 1.1 mrg {
611 1.1 mrg if (!__gcov_root.list)
612 1.1 mrg {
613 1.1 mrg /* Add to master list and at exit function. */
614 1.1 mrg if (gcov_version (NULL, __gcov_master.version, "<master>"))
615 1.1 mrg {
616 1.1 mrg __gcov_root.next = __gcov_master.root;
617 1.1 mrg if (__gcov_master.root)
618 1.1 mrg __gcov_master.root->prev = &__gcov_root;
619 1.1 mrg __gcov_master.root = &__gcov_root;
620 1.1 mrg }
621 1.1 mrg }
622 1.1 mrg
623 1.1 mrg info->next = __gcov_root.list;
624 1.1 mrg __gcov_root.list = info;
625 1.1 mrg }
626 1.1 mrg }
627 1.1 mrg #endif /* !IN_GCOV_TOOL */
628 1.1 mrg #endif /* L_gcov */
629 1.1 mrg #endif /* inhibit_libc */
630