[Ada] No Default_Initial_Condition check when declaring an imported object
[gcc.git] / gcc / gcov-dump.c
1 /* Dump a gcov file, for debugging use.
2 Copyright (C) 2002-2020 Free Software Foundation, Inc.
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"
24 #include "intl.h"
25 #include "diagnostic.h"
26 #include <getopt.h>
27 #define IN_GCOV (-1)
28 #include "gcov-io.h"
29 #include "gcov-io.c"
30
31 static void dump_gcov_file (const char *);
32 static void print_prefix (const char *, unsigned, gcov_position_t);
33 static void print_usage (void);
34 static void print_version (void);
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 extern int main (int, char **);
42
43 typedef struct tag_format
44 {
45 unsigned tag;
46 char const *name;
47 void (*proc) (const char *, unsigned, unsigned, unsigned);
48 } tag_format_t;
49
50 static int flag_dump_contents = 0;
51 static int flag_dump_positions = 0;
52 static int flag_dump_raw = 0;
53
54 static const struct option options[] =
55 {
56 { "help", no_argument, NULL, 'h' },
57 { "version", no_argument, NULL, 'v' },
58 { "long", no_argument, NULL, 'l' },
59 { "positions", no_argument, NULL, 'o' },
60 { 0, 0, 0, 0 }
61 };
62
63 #define VALUE_PADDING_PREFIX " "
64 #define VALUE_PREFIX "%2d: "
65
66 static const tag_format_t tag_table[] =
67 {
68 {0, "NOP", NULL},
69 {0, "UNKNOWN", NULL},
70 {0, "COUNTERS", tag_counters},
71 {GCOV_TAG_FUNCTION, "FUNCTION", tag_function},
72 {GCOV_TAG_BLOCKS, "BLOCKS", tag_blocks},
73 {GCOV_TAG_ARCS, "ARCS", tag_arcs},
74 {GCOV_TAG_LINES, "LINES", tag_lines},
75 {GCOV_TAG_OBJECT_SUMMARY, "OBJECT_SUMMARY", tag_summary},
76 {0, NULL, NULL}
77 };
78
79 int
80 main (int argc ATTRIBUTE_UNUSED, char **argv)
81 {
82 int opt;
83 const char *p;
84
85 p = argv[0] + strlen (argv[0]);
86 while (p != argv[0] && !IS_DIR_SEPARATOR (p[-1]))
87 --p;
88 progname = p;
89
90 xmalloc_set_program_name (progname);
91
92 /* Unlock the stdio streams. */
93 unlock_std_streams ();
94
95 gcc_init_libintl ();
96
97 diagnostic_initialize (global_dc, 0);
98
99 while ((opt = getopt_long (argc, argv, "hlprvw", options, NULL)) != -1)
100 {
101 switch (opt)
102 {
103 case 'h':
104 print_usage ();
105 break;
106 case 'v':
107 print_version ();
108 break;
109 case 'l':
110 flag_dump_contents = 1;
111 break;
112 case 'p':
113 flag_dump_positions = 1;
114 break;
115 case 'r':
116 flag_dump_raw = 1;
117 break;
118 default:
119 fprintf (stderr, "unknown flag `%c'\n", opt);
120 }
121 }
122
123 while (argv[optind])
124 dump_gcov_file (argv[optind++]);
125 return 0;
126 }
127
128 static void
129 print_usage (void)
130 {
131 printf ("Usage: gcov-dump [OPTION] ... gcovfiles\n");
132 printf ("Print coverage file contents\n");
133 printf (" -h, --help Print this help\n");
134 printf (" -l, --long Dump record contents too\n");
135 printf (" -p, --positions Dump record positions\n");
136 printf (" -r, --raw Print content records in raw format\n");
137 printf (" -v, --version Print version number\n");
138 printf ("\nFor bug reporting instructions, please see:\n%s.\n",
139 bug_report_url);
140 }
141
142 static void
143 print_version (void)
144 {
145 printf ("gcov-dump %s%s\n", pkgversion_string, version_string);
146 printf ("Copyright (C) 2020 Free Software Foundation, Inc.\n");
147 printf ("This is free software; see the source for copying conditions. There is NO\n\
148 warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\n");
149 }
150
151 static void
152 print_prefix (const char *filename, unsigned depth, gcov_position_t position)
153 {
154 static const char prefix[] = " ";
155
156 printf ("%s:", filename);
157 if (flag_dump_positions)
158 printf ("%5lu:", (unsigned long) position);
159 printf ("%.*s", (int) 2 * depth, prefix);
160 }
161
162 static void
163 dump_gcov_file (const char *filename)
164 {
165 unsigned tags[4];
166 unsigned depth = 0;
167 bool is_data_type;
168
169 if (!gcov_open (filename, 1))
170 {
171 fprintf (stderr, "%s:cannot open\n", filename);
172 return;
173 }
174
175 /* magic */
176 {
177 unsigned magic = gcov_read_unsigned ();
178 unsigned version;
179 int endianness = 0;
180 char m[4], v[4];
181
182 if ((endianness = gcov_magic (magic, GCOV_DATA_MAGIC)))
183 is_data_type = true;
184 else if ((endianness = gcov_magic (magic, GCOV_NOTE_MAGIC)))
185 is_data_type = false;
186 else
187 {
188 printf ("%s:not a gcov file\n", filename);
189 gcov_close ();
190 return;
191 }
192 version = gcov_read_unsigned ();
193 GCOV_UNSIGNED2STRING (v, version);
194 GCOV_UNSIGNED2STRING (m, magic);
195
196 printf ("%s:%s:magic `%.4s':version `%.4s'%s\n", filename,
197 is_data_type ? "data" : "note",
198 m, v, endianness < 0 ? " (swapped endianness)" : "");
199 if (version != GCOV_VERSION)
200 {
201 char e[4];
202
203 GCOV_UNSIGNED2STRING (e, GCOV_VERSION);
204 printf ("%s:warning:current version is `%.4s'\n", filename, e);
205 }
206 }
207
208 /* stamp */
209 {
210 unsigned stamp = gcov_read_unsigned ();
211
212 printf ("%s:stamp %lu\n", filename, (unsigned long)stamp);
213 }
214
215 if (!is_data_type)
216 {
217 printf ("%s:cwd: %s\n", filename, gcov_read_string ());
218
219 /* Support for unexecuted basic blocks. */
220 unsigned support_unexecuted_blocks = gcov_read_unsigned ();
221 if (!support_unexecuted_blocks)
222 printf ("%s: has_unexecuted_block is not supported\n", filename);
223 }
224
225 while (1)
226 {
227 gcov_position_t base, position = gcov_position ();
228 unsigned tag, length;
229 tag_format_t const *format;
230 unsigned tag_depth;
231 int error;
232 unsigned mask;
233
234 tag = gcov_read_unsigned ();
235 if (!tag)
236 break;
237 length = gcov_read_unsigned ();
238 base = gcov_position ();
239 mask = GCOV_TAG_MASK (tag) >> 1;
240 for (tag_depth = 4; mask; mask >>= 8)
241 {
242 if ((mask & 0xff) != 0xff)
243 {
244 printf ("%s:tag `%08x' is invalid\n", filename, tag);
245 break;
246 }
247 tag_depth--;
248 }
249 for (format = tag_table; format->name; format++)
250 if (format->tag == tag)
251 goto found;
252 format = &tag_table[GCOV_TAG_IS_COUNTER (tag) ? 2 : 1];
253 found:;
254 if (tag)
255 {
256 if (depth && depth < tag_depth)
257 {
258 if (!GCOV_TAG_IS_SUBTAG (tags[depth - 1], tag))
259 printf ("%s:tag `%08x' is incorrectly nested\n",
260 filename, tag);
261 }
262 depth = tag_depth;
263 tags[depth - 1] = tag;
264 }
265
266 print_prefix (filename, tag_depth, position);
267 printf ("%08x:%4u:%s", tag, length, format->name);
268 if (format->proc)
269 (*format->proc) (filename, tag, length, depth);
270
271 printf ("\n");
272 if (flag_dump_contents && format->proc)
273 {
274 unsigned long actual_length = gcov_position () - base;
275
276 if (actual_length > length)
277 printf ("%s:record size mismatch %lu bytes overread\n",
278 filename, actual_length - length);
279 else if (length > actual_length)
280 printf ("%s:record size mismatch %lu bytes unread\n",
281 filename, length - actual_length);
282 }
283 gcov_sync (base, length);
284 if ((error = gcov_is_error ()))
285 {
286 printf (error < 0 ? "%s:counter overflow at %lu\n" :
287 "%s:read error at %lu\n", filename,
288 (long unsigned) gcov_position ());
289 break;
290 }
291 }
292 gcov_close ();
293 }
294
295 static void
296 tag_function (const char *filename ATTRIBUTE_UNUSED,
297 unsigned tag ATTRIBUTE_UNUSED, unsigned length,
298 unsigned depth ATTRIBUTE_UNUSED)
299 {
300 unsigned long pos = gcov_position ();
301
302 if (!length)
303 printf (" placeholder");
304 else
305 {
306 printf (" ident=%u", gcov_read_unsigned ());
307 printf (", lineno_checksum=0x%08x", gcov_read_unsigned ());
308 printf (", cfg_checksum=0x%08x", gcov_read_unsigned ());
309
310 if (gcov_position () - pos < length)
311 {
312 const char *name;
313
314 name = gcov_read_string ();
315 printf (", `%s'", name ? name : "NULL");
316 unsigned artificial = gcov_read_unsigned ();
317 name = gcov_read_string ();
318 printf (" %s", name ? name : "NULL");
319 unsigned line_start = gcov_read_unsigned ();
320 unsigned column_start = gcov_read_unsigned ();
321 unsigned line_end = gcov_read_unsigned ();
322 unsigned column_end = gcov_read_unsigned ();
323 printf (":%u:%u-%u:%u", line_start, column_start,
324 line_end, column_end);
325 if (artificial)
326 printf (", artificial");
327 }
328 }
329 }
330
331 static void
332 tag_blocks (const char *filename ATTRIBUTE_UNUSED,
333 unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED,
334 unsigned depth ATTRIBUTE_UNUSED)
335 {
336 printf (" %u blocks", gcov_read_unsigned ());
337 }
338
339 static void
340 tag_arcs (const char *filename ATTRIBUTE_UNUSED,
341 unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED,
342 unsigned depth)
343 {
344 unsigned n_arcs = GCOV_TAG_ARCS_NUM (length);
345
346 printf (" %u arcs", n_arcs);
347 if (flag_dump_contents)
348 {
349 unsigned ix;
350 unsigned blockno = gcov_read_unsigned ();
351
352 for (ix = 0; ix != n_arcs; ix++)
353 {
354 unsigned dst, flags;
355
356 if (!(ix & 3))
357 {
358 printf ("\n");
359 print_prefix (filename, depth, gcov_position ());
360 printf (VALUE_PADDING_PREFIX "block %u:", blockno);
361 }
362 dst = gcov_read_unsigned ();
363 flags = gcov_read_unsigned ();
364 printf (" %u:%04x", dst, flags);
365 if (flags)
366 {
367 char c = '(';
368
369 if (flags & GCOV_ARC_ON_TREE)
370 printf ("%ctree", c), c = ',';
371 if (flags & GCOV_ARC_FAKE)
372 printf ("%cfake", c), c = ',';
373 if (flags & GCOV_ARC_FALLTHROUGH)
374 printf ("%cfall", c), c = ',';
375 printf (")");
376 }
377 }
378 }
379 }
380
381 static void
382 tag_lines (const char *filename ATTRIBUTE_UNUSED,
383 unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED,
384 unsigned depth)
385 {
386 if (flag_dump_contents)
387 {
388 unsigned blockno = gcov_read_unsigned ();
389 char const *sep = NULL;
390
391 while (1)
392 {
393 gcov_position_t position = gcov_position ();
394 const char *source = NULL;
395 unsigned lineno = gcov_read_unsigned ();
396
397 if (!lineno)
398 {
399 source = gcov_read_string ();
400 if (!source)
401 break;
402 sep = NULL;
403 }
404
405 if (!sep)
406 {
407 printf ("\n");
408 print_prefix (filename, depth, position);
409 printf (VALUE_PADDING_PREFIX "block %u:", blockno);
410 sep = "";
411 }
412 if (lineno)
413 {
414 printf ("%s%u", sep, lineno);
415 sep = ", ";
416 }
417 else
418 {
419 printf ("%s`%s'", sep, source);
420 sep = ":";
421 }
422 }
423 }
424 }
425
426 static void
427 tag_counters (const char *filename ATTRIBUTE_UNUSED,
428 unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED,
429 unsigned depth)
430 {
431 #define DEF_GCOV_COUNTER(COUNTER, NAME, MERGE_FN) NAME,
432 static const char *const counter_names[] = {
433 #include "gcov-counter.def"
434 };
435 #undef DEF_GCOV_COUNTER
436 unsigned n_counts = GCOV_TAG_COUNTER_NUM (length);
437
438 printf (" %s %u counts",
439 counter_names[GCOV_COUNTER_FOR_TAG (tag)], n_counts);
440 if (flag_dump_contents)
441 {
442 unsigned ix;
443
444 for (ix = 0; ix != n_counts; ix++)
445 {
446 gcov_type count;
447
448 if (flag_dump_raw)
449 {
450 if (ix == 0)
451 printf (": ");
452 }
453 else if (!(ix & 7))
454 {
455 printf ("\n");
456 print_prefix (filename, depth, gcov_position ());
457 printf (VALUE_PADDING_PREFIX VALUE_PREFIX, ix);
458 }
459
460 count = gcov_read_counter ();
461 printf ("%" PRId64 " ", count);
462 }
463 }
464 }
465
466 static void
467 tag_summary (const char *filename ATTRIBUTE_UNUSED,
468 unsigned tag ATTRIBUTE_UNUSED, unsigned length ATTRIBUTE_UNUSED,
469 unsigned depth ATTRIBUTE_UNUSED)
470 {
471 gcov_summary summary;
472 gcov_read_summary (&summary);
473 printf (" runs=%d, sum_max=%" PRId64,
474 summary.runs, summary.sum_max);
475 }