Mercurial > hg > CbC > CbC_gcc
annotate gcc/gcov-dump.c @ 116:367f9f4f266e
fix gimple.h
author | mir3636 |
---|---|
date | Tue, 28 Nov 2017 20:22:01 +0900 |
parents | 04ced10e8804 |
children | 84e7813d76e9 |
rev | line source |
---|---|
0 | 1 /* Dump a gcov file, for debugging use. |
111 | 2 Copyright (C) 2002-2017 Free Software Foundation, Inc. |
0 | 3 Contributed by Nathan Sidwell <nathan@codesourcery.com> |
4 | |
5 Gcov is free software; you can redistribute it and/or modify | |
6 it under the terms of the GNU General Public License as published by | |
7 the Free Software Foundation; either version 3, or (at your option) | |
8 any later version. | |
9 | |
10 Gcov is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 GNU General Public License for more details. | |
14 | |
15 You should have received a copy of the GNU General Public License | |
16 along with Gcov; see the file COPYING3. If not see | |
17 <http://www.gnu.org/licenses/>. */ | |
18 | |
19 #include "config.h" | |
20 #include "system.h" | |
21 #include "coretypes.h" | |
22 #include "tm.h" | |
23 #include "version.h" | |
111 | 24 #include "intl.h" |
25 #include "diagnostic.h" | |
0 | 26 #include <getopt.h> |
27 #define IN_GCOV (-1) | |
28 #include "gcov-io.h" | |
29 #include "gcov-io.c" | |
30 | |
111 | 31 static void dump_gcov_file (const char *); |
0 | 32 static void print_prefix (const char *, unsigned, gcov_position_t); |
33 static void print_usage (void); | |
34 static void print_version (void); | |
111 | 35 static void tag_function (const char *, unsigned, unsigned, unsigned); |
36 static void tag_blocks (const char *, unsigned, unsigned, unsigned); | |
37 static void tag_arcs (const char *, unsigned, unsigned, unsigned); | |
38 static void tag_lines (const char *, unsigned, unsigned, unsigned); | |
39 static void tag_counters (const char *, unsigned, unsigned, unsigned); | |
40 static void tag_summary (const char *, unsigned, unsigned, unsigned); | |
41 static void dump_working_sets (const char *filename ATTRIBUTE_UNUSED, | |
42 const struct gcov_ctr_summary *summary, | |
43 unsigned depth); | |
0 | 44 extern int main (int, char **); |
45 | |
46 typedef struct tag_format | |
47 { | |
48 unsigned tag; | |
49 char const *name; | |
111 | 50 void (*proc) (const char *, unsigned, unsigned, unsigned); |
0 | 51 } tag_format_t; |
52 | |
53 static int flag_dump_contents = 0; | |
54 static int flag_dump_positions = 0; | |
111 | 55 static int flag_dump_working_sets = 0; |
0 | 56 |
57 static const struct option options[] = | |
58 { | |
59 { "help", no_argument, NULL, 'h' }, | |
60 { "version", no_argument, NULL, 'v' }, | |
61 { "long", no_argument, NULL, 'l' }, | |
62 { "positions", no_argument, NULL, 'o' }, | |
111 | 63 { "working-sets", no_argument, NULL, 'w' }, |
0 | 64 { 0, 0, 0, 0 } |
65 }; | |
66 | |
111 | 67 #define VALUE_PADDING_PREFIX " " |
68 #define VALUE_PREFIX "%2d: " | |
69 | |
0 | 70 static const tag_format_t tag_table[] = |
71 { | |
72 {0, "NOP", NULL}, | |
73 {0, "UNKNOWN", NULL}, | |
74 {0, "COUNTERS", tag_counters}, | |
75 {GCOV_TAG_FUNCTION, "FUNCTION", tag_function}, | |
76 {GCOV_TAG_BLOCKS, "BLOCKS", tag_blocks}, | |
77 {GCOV_TAG_ARCS, "ARCS", tag_arcs}, | |
78 {GCOV_TAG_LINES, "LINES", tag_lines}, | |
79 {GCOV_TAG_OBJECT_SUMMARY, "OBJECT_SUMMARY", tag_summary}, | |
80 {GCOV_TAG_PROGRAM_SUMMARY, "PROGRAM_SUMMARY", tag_summary}, | |
81 {0, NULL, NULL} | |
82 }; | |
83 | |
84 int | |
85 main (int argc ATTRIBUTE_UNUSED, char **argv) | |
86 { | |
87 int opt; | |
111 | 88 const char *p; |
89 | |
90 p = argv[0] + strlen (argv[0]); | |
91 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1])) | |
92 --p; | |
93 progname = p; | |
94 | |
95 xmalloc_set_program_name (progname); | |
0 | 96 |
97 /* Unlock the stdio streams. */ | |
98 unlock_std_streams (); | |
99 | |
111 | 100 gcc_init_libintl (); |
101 | |
102 diagnostic_initialize (global_dc, 0); | |
103 | |
104 while ((opt = getopt_long (argc, argv, "hlpvw", options, NULL)) != -1) | |
0 | 105 { |
106 switch (opt) | |
107 { | |
108 case 'h': | |
109 print_usage (); | |
110 break; | |
111 case 'v': | |
112 print_version (); | |
113 break; | |
114 case 'l': | |
115 flag_dump_contents = 1; | |
116 break; | |
117 case 'p': | |
118 flag_dump_positions = 1; | |
119 break; | |
111 | 120 case 'w': |
121 flag_dump_working_sets = 1; | |
122 break; | |
0 | 123 default: |
124 fprintf (stderr, "unknown flag `%c'\n", opt); | |
125 } | |
126 } | |
127 | |
128 while (argv[optind]) | |
111 | 129 dump_gcov_file (argv[optind++]); |
0 | 130 return 0; |
131 } | |
132 | |
133 static void | |
134 print_usage (void) | |
135 { | |
136 printf ("Usage: gcov-dump [OPTION] ... gcovfiles\n"); | |
137 printf ("Print coverage file contents\n"); | |
138 printf (" -h, --help Print this help\n"); | |
139 printf (" -l, --long Dump record contents too\n"); | |
140 printf (" -p, --positions Dump record positions\n"); | |
111 | 141 printf (" -v, --version Print version number\n"); |
142 printf (" -w, --working-sets Dump working set computed from summary\n"); | |
143 printf ("\nFor bug reporting instructions, please see:\n%s.\n", | |
144 bug_report_url); | |
0 | 145 } |
146 | |
147 static void | |
148 print_version (void) | |
149 { | |
150 printf ("gcov-dump %s%s\n", pkgversion_string, version_string); | |
111 | 151 printf ("Copyright (C) 2017 Free Software Foundation, Inc.\n"); |
0 | 152 printf ("This is free software; see the source for copying conditions.\n" |
153 "There is NO warranty; not even for MERCHANTABILITY or \n" | |
154 "FITNESS FOR A PARTICULAR PURPOSE.\n\n"); | |
155 } | |
156 | |
157 static void | |
158 print_prefix (const char *filename, unsigned depth, gcov_position_t position) | |
159 { | |
160 static const char prefix[] = " "; | |
161 | |
162 printf ("%s:", filename); | |
163 if (flag_dump_positions) | |
111 | 164 printf ("%5lu:", (unsigned long) position); |
165 printf ("%.*s", (int) 2 * depth, prefix); | |
0 | 166 } |
167 | |
168 static void | |
111 | 169 dump_gcov_file (const char *filename) |
0 | 170 { |
171 unsigned tags[4]; | |
172 unsigned depth = 0; | |
173 | |
174 if (!gcov_open (filename, 1)) | |
175 { | |
176 fprintf (stderr, "%s:cannot open\n", filename); | |
177 return; | |
178 } | |
179 | |
180 /* magic */ | |
181 { | |
182 unsigned magic = gcov_read_unsigned (); | |
183 unsigned version; | |
184 const char *type = NULL; | |
185 int endianness = 0; | |
186 char m[4], v[4]; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
47
diff
changeset
|
187 |
0 | 188 if ((endianness = gcov_magic (magic, GCOV_DATA_MAGIC))) |
189 type = "data"; | |
190 else if ((endianness = gcov_magic (magic, GCOV_NOTE_MAGIC))) | |
191 type = "note"; | |
192 else | |
193 { | |
194 printf ("%s:not a gcov file\n", filename); | |
195 gcov_close (); | |
196 return; | |
197 } | |
198 version = gcov_read_unsigned (); | |
199 GCOV_UNSIGNED2STRING (v, version); | |
200 GCOV_UNSIGNED2STRING (m, magic); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
47
diff
changeset
|
201 |
0 | 202 printf ("%s:%s:magic `%.4s':version `%.4s'%s\n", filename, type, |
203 m, v, endianness < 0 ? " (swapped endianness)" : ""); | |
204 if (version != GCOV_VERSION) | |
205 { | |
206 char e[4]; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
47
diff
changeset
|
207 |
0 | 208 GCOV_UNSIGNED2STRING (e, GCOV_VERSION); |
209 printf ("%s:warning:current version is `%.4s'\n", filename, e); | |
210 } | |
211 } | |
212 | |
213 /* stamp */ | |
214 { | |
215 unsigned stamp = gcov_read_unsigned (); | |
216 | |
217 printf ("%s:stamp %lu\n", filename, (unsigned long)stamp); | |
218 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
47
diff
changeset
|
219 |
0 | 220 while (1) |
221 { | |
222 gcov_position_t base, position = gcov_position (); | |
223 unsigned tag, length; | |
224 tag_format_t const *format; | |
225 unsigned tag_depth; | |
226 int error; | |
227 unsigned mask; | |
228 | |
229 tag = gcov_read_unsigned (); | |
230 if (!tag) | |
231 break; | |
232 length = gcov_read_unsigned (); | |
233 base = gcov_position (); | |
234 mask = GCOV_TAG_MASK (tag) >> 1; | |
235 for (tag_depth = 4; mask; mask >>= 8) | |
236 { | |
237 if ((mask & 0xff) != 0xff) | |
238 { | |
239 printf ("%s:tag `%08x' is invalid\n", filename, tag); | |
240 break; | |
241 } | |
242 tag_depth--; | |
243 } | |
244 for (format = tag_table; format->name; format++) | |
245 if (format->tag == tag) | |
246 goto found; | |
247 format = &tag_table[GCOV_TAG_IS_COUNTER (tag) ? 2 : 1]; | |
248 found:; | |
249 if (tag) | |
250 { | |
251 if (depth && depth < tag_depth) | |
252 { | |
253 if (!GCOV_TAG_IS_SUBTAG (tags[depth - 1], tag)) | |
254 printf ("%s:tag `%08x' is incorrectly nested\n", | |
255 filename, tag); | |
256 } | |
257 depth = tag_depth; | |
258 tags[depth - 1] = tag; | |
259 } | |
260 | |
261 print_prefix (filename, tag_depth, position); | |
262 printf ("%08x:%4u:%s", tag, length, format->name); | |
263 if (format->proc) | |
111 | 264 (*format->proc) (filename, tag, length, depth); |
0 | 265 |
266 printf ("\n"); | |
267 if (flag_dump_contents && format->proc) | |
268 { | |
269 unsigned long actual_length = gcov_position () - base; | |
270 | |
271 if (actual_length > length) | |
272 printf ("%s:record size mismatch %lu bytes overread\n", | |
273 filename, actual_length - length); | |
274 else if (length > actual_length) | |
275 printf ("%s:record size mismatch %lu bytes unread\n", | |
276 filename, length - actual_length); | |
277 } | |
278 gcov_sync (base, length); | |
279 if ((error = gcov_is_error ())) | |
280 { | |
281 printf (error < 0 ? "%s:counter overflow at %lu\n" : | |
282 "%s:read error at %lu\n", filename, | |
283 (long unsigned) gcov_position ()); | |
284 break; | |
285 } | |
286 } | |
287 gcov_close (); | |
288 } | |
289 | |
290 static void | |
291 tag_function (const char *filename ATTRIBUTE_UNUSED, | |
111 | 292 unsigned tag ATTRIBUTE_UNUSED, unsigned length, |
293 unsigned depth ATTRIBUTE_UNUSED) | |
0 | 294 { |
295 unsigned long pos = gcov_position (); | |
296 | |
111 | 297 if (!length) |
298 printf (" placeholder"); | |
299 else | |
0 | 300 { |
111 | 301 printf (" ident=%u", gcov_read_unsigned ()); |
302 printf (", lineno_checksum=0x%08x", gcov_read_unsigned ()); | |
303 printf (", cfg_checksum=0x%08x", gcov_read_unsigned ()); | |
0 | 304 |
111 | 305 if (gcov_position () - pos < length) |
306 { | |
307 const char *name; | |
308 | |
309 name = gcov_read_string (); | |
310 printf (", `%s'", name ? name : "NULL"); | |
311 name = gcov_read_string (); | |
312 printf (" %s", name ? name : "NULL"); | |
313 printf (":%u", gcov_read_unsigned ()); | |
314 } | |
0 | 315 } |
316 } | |
317 | |
318 static void | |
319 tag_blocks (const char *filename ATTRIBUTE_UNUSED, | |
111 | 320 unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED, |
321 unsigned depth ATTRIBUTE_UNUSED) | |
0 | 322 { |
111 | 323 printf (" %u blocks", gcov_read_unsigned ()); |
0 | 324 } |
325 | |
326 static void | |
327 tag_arcs (const char *filename ATTRIBUTE_UNUSED, | |
111 | 328 unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED, |
329 unsigned depth) | |
0 | 330 { |
331 unsigned n_arcs = GCOV_TAG_ARCS_NUM (length); | |
332 | |
333 printf (" %u arcs", n_arcs); | |
334 if (flag_dump_contents) | |
335 { | |
336 unsigned ix; | |
337 unsigned blockno = gcov_read_unsigned (); | |
338 | |
339 for (ix = 0; ix != n_arcs; ix++) | |
340 { | |
341 unsigned dst, flags; | |
342 | |
343 if (!(ix & 3)) | |
344 { | |
345 printf ("\n"); | |
111 | 346 print_prefix (filename, depth, gcov_position ()); |
347 printf (VALUE_PADDING_PREFIX "block %u:", blockno); | |
0 | 348 } |
349 dst = gcov_read_unsigned (); | |
350 flags = gcov_read_unsigned (); | |
351 printf (" %u:%04x", dst, flags); | |
111 | 352 if (flags) |
353 { | |
354 char c = '('; | |
355 | |
356 if (flags & GCOV_ARC_ON_TREE) | |
357 printf ("%ctree", c), c = ','; | |
358 if (flags & GCOV_ARC_FAKE) | |
359 printf ("%cfake", c), c = ','; | |
360 if (flags & GCOV_ARC_FALLTHROUGH) | |
361 printf ("%cfall", c), c = ','; | |
362 printf (")"); | |
363 } | |
0 | 364 } |
365 } | |
366 } | |
367 | |
368 static void | |
369 tag_lines (const char *filename ATTRIBUTE_UNUSED, | |
111 | 370 unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED, |
371 unsigned depth) | |
0 | 372 { |
373 if (flag_dump_contents) | |
374 { | |
375 unsigned blockno = gcov_read_unsigned (); | |
376 char const *sep = NULL; | |
377 | |
378 while (1) | |
379 { | |
380 gcov_position_t position = gcov_position (); | |
381 const char *source = NULL; | |
382 unsigned lineno = gcov_read_unsigned (); | |
383 | |
384 if (!lineno) | |
385 { | |
386 source = gcov_read_string (); | |
387 if (!source) | |
388 break; | |
389 sep = NULL; | |
390 } | |
391 | |
392 if (!sep) | |
393 { | |
394 printf ("\n"); | |
111 | 395 print_prefix (filename, depth, position); |
396 printf (VALUE_PADDING_PREFIX "block %u:", blockno); | |
0 | 397 sep = ""; |
398 } | |
399 if (lineno) | |
400 { | |
401 printf ("%s%u", sep, lineno); | |
402 sep = ", "; | |
403 } | |
404 else | |
405 { | |
406 printf ("%s`%s'", sep, source); | |
407 sep = ":"; | |
408 } | |
409 } | |
410 } | |
411 } | |
412 | |
413 static void | |
414 tag_counters (const char *filename ATTRIBUTE_UNUSED, | |
111 | 415 unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED, |
416 unsigned depth) | |
0 | 417 { |
111 | 418 #define DEF_GCOV_COUNTER(COUNTER, NAME, MERGE_FN) NAME, |
419 static const char *const counter_names[] = { | |
420 #include "gcov-counter.def" | |
421 }; | |
422 #undef DEF_GCOV_COUNTER | |
0 | 423 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length); |
424 | |
425 printf (" %s %u counts", | |
426 counter_names[GCOV_COUNTER_FOR_TAG (tag)], n_counts); | |
427 if (flag_dump_contents) | |
428 { | |
429 unsigned ix; | |
430 | |
431 for (ix = 0; ix != n_counts; ix++) | |
432 { | |
433 gcov_type count; | |
434 | |
435 if (!(ix & 7)) | |
436 { | |
437 printf ("\n"); | |
111 | 438 print_prefix (filename, depth, gcov_position ()); |
439 printf (VALUE_PADDING_PREFIX VALUE_PREFIX, ix); | |
0 | 440 } |
441 | |
442 count = gcov_read_counter (); | |
111 | 443 printf ("%" PRId64 " ", count); |
0 | 444 } |
445 } | |
446 } | |
447 | |
448 static void | |
449 tag_summary (const char *filename ATTRIBUTE_UNUSED, | |
111 | 450 unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED, |
451 unsigned depth) | |
0 | 452 { |
453 struct gcov_summary summary; | |
111 | 454 unsigned ix, h_ix; |
455 gcov_bucket_type *histo_bucket; | |
0 | 456 |
457 gcov_read_summary (&summary); | |
458 printf (" checksum=0x%08x", summary.checksum); | |
459 | |
460 for (ix = 0; ix != GCOV_COUNTERS_SUMMABLE; ix++) | |
461 { | |
462 printf ("\n"); | |
111 | 463 print_prefix (filename, depth, 0); |
464 printf (VALUE_PADDING_PREFIX "counts=%u, runs=%u", | |
0 | 465 summary.ctrs[ix].num, summary.ctrs[ix].runs); |
466 | |
111 | 467 printf (", sum_all=%" PRId64, |
468 (int64_t)summary.ctrs[ix].sum_all); | |
469 printf (", run_max=%" PRId64, | |
470 (int64_t)summary.ctrs[ix].run_max); | |
471 printf (", sum_max=%" PRId64, | |
472 (int64_t)summary.ctrs[ix].sum_max); | |
473 if (ix != GCOV_COUNTER_ARCS) | |
474 continue; | |
475 printf ("\n"); | |
476 print_prefix (filename, depth, 0); | |
477 printf (VALUE_PADDING_PREFIX "counter histogram:"); | |
478 for (h_ix = 0; h_ix < GCOV_HISTOGRAM_SIZE; h_ix++) | |
479 { | |
480 histo_bucket = &summary.ctrs[ix].histogram[h_ix]; | |
481 if (!histo_bucket->num_counters) | |
482 continue; | |
483 printf ("\n"); | |
484 print_prefix (filename, depth, 0); | |
485 printf (VALUE_PADDING_PREFIX VALUE_PREFIX "num counts=%u, " | |
486 "min counter=%" PRId64 ", cum_counter=%" PRId64, | |
487 h_ix, histo_bucket->num_counters, | |
488 (int64_t)histo_bucket->min_value, | |
489 (int64_t)histo_bucket->cum_value); | |
490 } | |
491 if (flag_dump_working_sets) | |
492 dump_working_sets (filename, &summary.ctrs[ix], depth); | |
0 | 493 } |
494 } | |
111 | 495 |
496 static void | |
497 dump_working_sets (const char *filename ATTRIBUTE_UNUSED, | |
498 const struct gcov_ctr_summary *summary, | |
499 unsigned depth) | |
500 { | |
501 gcov_working_set_t gcov_working_sets[NUM_GCOV_WORKING_SETS]; | |
502 unsigned ws_ix, pctinc, pct; | |
503 gcov_working_set_t *ws_info; | |
504 | |
505 compute_working_sets (summary, gcov_working_sets); | |
506 | |
507 printf ("\n"); | |
508 print_prefix (filename, depth, 0); | |
509 printf (VALUE_PADDING_PREFIX "counter working sets:"); | |
510 /* Multiply the percentage by 100 to avoid float. */ | |
511 pctinc = 100 * 100 / NUM_GCOV_WORKING_SETS; | |
512 for (ws_ix = 0, pct = pctinc; ws_ix < NUM_GCOV_WORKING_SETS; | |
513 ws_ix++, pct += pctinc) | |
514 { | |
515 if (ws_ix == NUM_GCOV_WORKING_SETS - 1) | |
516 pct = 9990; | |
517 ws_info = &gcov_working_sets[ws_ix]; | |
518 /* Print out the percentage using int arithmatic to avoid float. */ | |
519 printf ("\n"); | |
520 print_prefix (filename, depth + 1, 0); | |
521 printf (VALUE_PADDING_PREFIX "%u.%02u%%: num counts=%u, min counter=" | |
522 "%" PRId64, | |
523 pct / 100, pct - (pct / 100 * 100), | |
524 ws_info->num_counters, | |
525 (int64_t)ws_info->min_counter); | |
526 } | |
527 } |