2002-11-30 Nathanael Nerode <neroden@gcc.gnu.org>
[deliverable/binutils-gdb.git] / gprof / basic_blocks.c
CommitLineData
ef368dac
NC
1/* basic_blocks.c - Basic-block level related code: reading/writing
2 of basic-block info to/from gmon.out; computing and formatting of
3 basic-block related statistics.
4
1355568a 5 Copyright 2000, 2001, 2002 Free Software Foundation, Inc.
ef368dac
NC
6
7 This file is part of GNU Binutils.
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
22 02111-1307, USA. */
23\f
6d9c411a
AM
24#include "libiberty.h"
25#include "gprof.h"
252b5132
RH
26#include "basic_blocks.h"
27#include "corefile.h"
28#include "gmon_io.h"
29#include "gmon_out.h"
6d9c411a 30#include "search_list.h"
252b5132 31#include "source.h"
6d9c411a 32#include "symtab.h"
252b5132
RH
33#include "sym_ids.h"
34
1355568a
AM
35static int cmp_bb PARAMS ((const PTR, const PTR));
36static int cmp_ncalls PARAMS ((const PTR, const PTR));
37static void fskip_string PARAMS ((FILE *));
38static void annotate_with_count PARAMS ((char *, unsigned int, int, PTR));
39
ef368dac 40/* Default option values: */
bde52789 41boolean bb_annotate_all_lines = false;
252b5132
RH
42unsigned long bb_min_calls = 1;
43int bb_table_length = 10;
44
ef368dac 45/* Variables used to compute annotated source listing stats: */
252b5132
RH
46static long num_executable_lines;
47static long num_lines_executed;
48
49
ef368dac
NC
50/* Helper for sorting. Compares two symbols and returns result
51 such that sorting will be increasing according to filename, line
52 number, and address (in that order). */
252b5132
RH
53
54static int
1355568a
AM
55cmp_bb (lp, rp)
56 const PTR lp;
57 const PTR rp;
252b5132
RH
58{
59 int r;
60 const Sym *left = *(const Sym **) lp;
61 const Sym *right = *(const Sym **) rp;
62
63 if (left->file && right->file)
64 {
65 r = strcmp (left->file->name, right->file->name);
0eee5820 66
252b5132 67 if (r)
ef368dac 68 return r;
252b5132
RH
69
70 if (left->line_num != right->line_num)
ef368dac 71 return left->line_num - right->line_num;
252b5132
RH
72 }
73
74 if (left->addr < right->addr)
ef368dac 75 return -1;
252b5132 76 else if (left->addr > right->addr)
ef368dac 77 return 1;
252b5132 78 else
ef368dac 79 return 0;
252b5132
RH
80}
81
82
ef368dac
NC
83/* Helper for sorting. Order basic blocks in decreasing number of
84 calls, ties are broken in increasing order of line numbers. */
252b5132 85static int
1355568a
AM
86cmp_ncalls (lp, rp)
87 const PTR lp;
88 const PTR rp;
252b5132
RH
89{
90 const Sym *left = *(const Sym **) lp;
91 const Sym *right = *(const Sym **) rp;
92
93 if (!left)
ef368dac 94 return 1;
252b5132 95 else if (!right)
ef368dac 96 return -1;
252b5132
RH
97
98 if (left->ncalls < right->ncalls)
99 return 1;
100 else if (left->ncalls > right->ncalls)
101 return -1;
102
103 return left->line_num - right->line_num;
104}
105
ef368dac 106/* Skip over variable length string. */
252b5132 107static void
1355568a
AM
108fskip_string (fp)
109 FILE *fp;
252b5132
RH
110{
111 int ch;
112
113 while ((ch = fgetc (fp)) != EOF)
114 {
115 if (ch == '\0')
ef368dac 116 break;
252b5132
RH
117 }
118}
119
ef368dac
NC
120/* Read a basic-block record from file IFP. FILENAME is the name
121 of file IFP and is provided for formatting error-messages only. */
252b5132 122
252b5132 123void
1355568a
AM
124bb_read_rec (ifp, filename)
125 FILE *ifp;
126 const char *filename;
252b5132
RH
127{
128 int nblocks, b;
0eee5820 129 bfd_vma addr, ncalls;
252b5132
RH
130 Sym *sym;
131
0eee5820 132 if (gmon_io_read_32 (ifp, &nblocks))
252b5132 133 {
0eee5820
AM
134 fprintf (stderr, _("%s: %s: unexpected end of file\n"),
135 whoami, filename);
252b5132
RH
136 done (1);
137 }
138
139 nblocks = bfd_get_32 (core_bfd, (bfd_byte *) & nblocks);
140 if (gmon_file_version == 0)
ef368dac 141 fskip_string (ifp);
252b5132
RH
142
143 for (b = 0; b < nblocks; ++b)
144 {
145 if (gmon_file_version == 0)
146 {
147 int line_num;
0eee5820 148
ef368dac
NC
149 /* Version 0 had lots of extra stuff that we don't
150 care about anymore. */
252b5132
RH
151 if ((fread (&ncalls, sizeof (ncalls), 1, ifp) != 1)
152 || (fread (&addr, sizeof (addr), 1, ifp) != 1)
bde52789
AM
153 || (fskip_string (ifp), false)
154 || (fskip_string (ifp), false)
252b5132
RH
155 || (fread (&line_num, sizeof (line_num), 1, ifp) != 1))
156 {
157 perror (filename);
158 done (1);
159 }
160 }
0eee5820
AM
161 else if (gmon_io_read_vma (ifp, &addr)
162 || gmon_io_read_vma (ifp, &ncalls))
252b5132 163 {
0eee5820
AM
164 perror (filename);
165 done (1);
252b5132
RH
166 }
167
ef368dac 168 /* Basic-block execution counts are meaningful only if we're
0eee5820 169 profiling at the line-by-line level: */
252b5132
RH
170 if (line_granularity)
171 {
252b5132
RH
172 sym = sym_lookup (&symtab, addr);
173
174 if (sym)
175 {
176 int i;
177
178 DBG (BBDEBUG,
179 printf ("[bb_read_rec] 0x%lx->0x%lx (%s:%d) cnt=%lu\n",
fdcf7d43 180 (unsigned long) addr, (unsigned long) sym->addr,
0eee5820 181 sym->name, sym->line_num, (unsigned long) ncalls));
252b5132
RH
182
183 for (i = 0; i < NBBS; i++)
184 {
185 if (! sym->bb_addr[i] || sym->bb_addr[i] == addr)
186 {
187 sym->bb_addr[i] = addr;
188 sym->bb_calls[i] += ncalls;
189 break;
190 }
191 }
192 }
193 }
194 else
195 {
bde52789 196 static boolean user_warned = false;
252b5132
RH
197
198 if (!user_warned)
199 {
bde52789 200 user_warned = true;
252b5132 201 fprintf (stderr,
ef368dac 202 _("%s: warning: ignoring basic-block exec counts (use -l or --line)\n"),
252b5132
RH
203 whoami);
204 }
205 }
206 }
207 return;
208}
209
ef368dac
NC
210/* Write all basic-blocks with non-zero counts to file OFP. FILENAME
211 is the name of OFP and is provided for producing error-messages
212 only. */
252b5132 213void
1355568a
AM
214bb_write_blocks (ofp, filename)
215 FILE *ofp;
216 const char *filename;
252b5132 217{
1355568a 218 unsigned int nblocks = 0;
252b5132
RH
219 Sym *sym;
220 int i;
221
ef368dac 222 /* Count how many non-zero blocks with have: */
252b5132
RH
223 for (sym = symtab.base; sym < symtab.limit; ++sym)
224 {
225 for (i = 0; i < NBBS && sym->bb_addr[i]; i++)
226 ;
227 nblocks += i;
228 }
229
ef368dac 230 /* Write header: */
0eee5820
AM
231 if (gmon_io_write_8 (ofp, GMON_TAG_BB_COUNT)
232 || gmon_io_write_32 (ofp, nblocks))
252b5132
RH
233 {
234 perror (filename);
235 done (1);
236 }
237
ef368dac 238 /* Write counts: */
252b5132
RH
239 for (sym = symtab.base; sym < symtab.limit; ++sym)
240 {
241 for (i = 0; i < NBBS && sym->bb_addr[i]; i++)
242 {
0eee5820 243 if (gmon_io_write_vma (ofp, sym->bb_addr[i])
1355568a 244 || gmon_io_write_vma (ofp, (bfd_vma) sym->bb_calls[i]))
252b5132
RH
245 {
246 perror (filename);
247 done (1);
248 }
249 }
250 }
251}
252
ef368dac
NC
253/* Output basic-block statistics in a format that is easily parseable.
254 Current the format is:
0eee5820
AM
255
256 <filename>:<line-number>: (<function-name>:<bb-addr): <ncalls> */
252b5132 257
252b5132 258void
1355568a 259print_exec_counts ()
252b5132
RH
260{
261 Sym **sorted_bbs, *sym;
1355568a 262 unsigned int i, j, len;
252b5132
RH
263
264 if (first_output)
bde52789 265 first_output = false;
252b5132 266 else
ef368dac 267 printf ("\f\n");
252b5132 268
ef368dac 269 /* Sort basic-blocks according to function name and line number: */
252b5132
RH
270 sorted_bbs = (Sym **) xmalloc (symtab.len * sizeof (sorted_bbs[0]));
271 len = 0;
0eee5820 272
252b5132
RH
273 for (sym = symtab.base; sym < symtab.limit; ++sym)
274 {
ef368dac 275 /* Accept symbol if it's in the INCL_EXEC table
0eee5820
AM
276 or there is no INCL_EXEC table
277 and it does not appear in the EXCL_EXEC table. */
252b5132
RH
278 if (sym_lookup (&syms[INCL_EXEC], sym->addr)
279 || (syms[INCL_EXEC].len == 0
280 && !sym_lookup (&syms[EXCL_EXEC], sym->addr)))
281 {
282 sorted_bbs[len++] = sym;
283 }
284 }
0eee5820 285
252b5132
RH
286 qsort (sorted_bbs, len, sizeof (sorted_bbs[0]), cmp_bb);
287
ef368dac 288 /* Output basic-blocks: */
252b5132
RH
289
290 for (i = 0; i < len; ++i)
291 {
292 if (sym->ncalls > 0 || ! ignore_zeros)
293 {
fdcf7d43 294 /* FIXME: This only works if bfd_vma is unsigned long. */
252b5132
RH
295 printf (_("%s:%d: (%s:0x%lx) %lu executions\n"),
296 sym->file ? sym->file->name : _("<unknown>"), sym->line_num,
fdcf7d43 297 sym->name, (unsigned long) sym->addr, sym->ncalls);
252b5132 298 }
0eee5820 299
252b5132
RH
300 for (j = 0; j < NBBS && sym->bb_addr[j]; j ++)
301 {
302 if (sym->bb_calls[j] > 0 || ! ignore_zeros)
303 {
fdcf7d43 304 /* FIXME: This only works if bfd_vma is unsigned long. */
252b5132
RH
305 printf (_("%s:%d: (%s:0x%lx) %lu executions\n"),
306 sym->file ? sym->file->name : _("<unknown>"), sym->line_num,
fdcf7d43
ILT
307 sym->name, (unsigned long) sym->bb_addr[j],
308 sym->bb_calls[j]);
252b5132
RH
309 }
310 }
311 }
312 free (sorted_bbs);
313}
314
ef368dac
NC
315/* Helper for bb_annotated_source: format annotation containing
316 number of line executions. Depends on being called on each
317 line of a file in sequential order.
0eee5820 318
ef368dac
NC
319 Global variable bb_annotate_all_lines enables execution count
320 compression (counts are supressed if identical to the last one)
321 and prints counts on all executed lines. Otherwise, print
322 all basic-block execution counts exactly once on the line
323 that starts the basic-block. */
252b5132
RH
324
325static void
1355568a
AM
326annotate_with_count (buf, width, line_num, arg)
327 char *buf;
328 unsigned int width;
329 int line_num;
330 PTR arg;
252b5132
RH
331{
332 Source_File *sf = arg;
333 Sym *b;
1355568a 334 unsigned int i;
252b5132
RH
335 static unsigned long last_count;
336 unsigned long last_print = (unsigned long) -1;
337
338 b = NULL;
0eee5820 339
252b5132 340 if (line_num <= sf->num_lines)
ef368dac
NC
341 b = sf->line[line_num - 1];
342
252b5132
RH
343 if (!b)
344 {
345 for (i = 0; i < width; i++)
346 buf[i] = ' ';
347 buf[width] = '\0';
348 }
349 else
350 {
351 char tmpbuf[NBBS * 30];
352 char *p;
353 unsigned long ncalls;
354 int ncalls_set;
1355568a 355 unsigned int len;
252b5132
RH
356
357 ++num_executable_lines;
358
359 p = tmpbuf;
360 *p = '\0';
361
362 ncalls = 0;
363 ncalls_set = 0;
364
365 /* If this is a function entry point, label the line no matter what.
0eee5820
AM
366 Otherwise, we're in the middle of a function, so check to see
367 if the first basic-block address is larger than the starting
368 address of the line. If so, then this line begins with a
369 a portion of the previous basic-block, so print that prior
370 execution count (if bb_annotate_all_lines is set). */
252b5132
RH
371 if (b->is_func)
372 {
373 sprintf (p, "%lu", b->ncalls);
374 p += strlen (p);
375 last_count = b->ncalls;
376 last_print = last_count;
377 ncalls = b->ncalls;
378 ncalls_set = 1;
379 }
380 else if (bb_annotate_all_lines
381 && b->bb_addr[0] && b->bb_addr[0] > b->addr)
382 {
383 sprintf (p, "%lu", last_count);
384 p += strlen (p);
385 last_print = last_count;
386 ncalls = last_count;
387 ncalls_set = 1;
388 }
389
390 /* Loop through all of this line's basic-blocks. For each one,
0eee5820
AM
391 update last_count, then compress sequential identical counts
392 (if bb_annotate_all_lines) and print the execution count. */
252b5132
RH
393
394 for (i = 0; i < NBBS && b->bb_addr[i]; i++)
395 {
396 last_count = b->bb_calls[i];
397 if (! ncalls_set)
398 {
399 ncalls = 0;
400 ncalls_set = 1;
401 }
402 ncalls += last_count;
403
404 if (bb_annotate_all_lines && last_count == last_print)
ef368dac 405 continue;
252b5132
RH
406
407 if (p > tmpbuf)
408 *p++ = ',';
409 sprintf (p, "%lu", last_count);
410 p += strlen (p);
411
412 last_print = last_count;
413 }
414
415 /* We're done. If nothing has been printed on this line,
0eee5820
AM
416 print the last execution count (bb_annotate_all_lines),
417 which could be from either a previous line (if there were
418 no BBs on this line), or from this line (if all our BB
419 counts were compressed out because they were identical). */
252b5132
RH
420
421 if (bb_annotate_all_lines && p == tmpbuf)
422 {
423 sprintf (p, "%lu", last_count);
424 p += strlen (p);
425 ncalls = last_count;
426 ncalls_set = 1;
427 }
428
429 if (! ncalls_set)
430 {
1355568a 431 unsigned int c;
252b5132
RH
432
433 for (c = 0; c < width; c++)
434 buf[c] = ' ';
435 buf[width] = '\0';
436 return;
437 }
438
439 ++num_lines_executed;
440
441 if (ncalls < bb_min_calls)
442 {
443 strcpy (tmpbuf, "#####");
444 p = tmpbuf + 5;
445 }
446
447 strcpy (p, " -> ");
448 p += 4;
449
450 len = p - tmpbuf;
451 if (len >= width)
452 {
453 strncpy (buf, tmpbuf, width);
454 buf[width] = '\0';
455 }
456 else
457 {
1355568a 458 unsigned int c;
252b5132
RH
459
460 strcpy (buf + width - len, tmpbuf);
461 for (c = 0; c < width - len; ++c)
462 buf[c] = ' ';
463 }
464 }
465}
466
ef368dac
NC
467/* Annotate the files named in SOURCE_FILES with basic-block statistics
468 (execution counts). After each source files, a few statistics
469 regarding that source file are printed. */
470
252b5132 471void
1355568a 472print_annotated_source ()
252b5132
RH
473{
474 Sym *sym, *line_stats, *new_line;
475 Source_File *sf;
476 int i, table_len;
477 FILE *ofp;
478
ef368dac
NC
479 /* Find maximum line number for each source file that user is
480 interested in: */
252b5132
RH
481 for (sym = symtab.base; sym < symtab.limit; ++sym)
482 {
ef368dac 483 /* Accept symbol if it's file is known, its line number is
0eee5820
AM
484 bigger than anything we have seen for that file so far and
485 if it's in the INCL_ANNO table or there is no INCL_ANNO
486 table and it does not appear in the EXCL_ANNO table. */
252b5132
RH
487 if (sym->file && sym->line_num > sym->file->num_lines
488 && (sym_lookup (&syms[INCL_ANNO], sym->addr)
489 || (syms[INCL_ANNO].len == 0
490 && !sym_lookup (&syms[EXCL_ANNO], sym->addr))))
491 {
492 sym->file->num_lines = sym->line_num;
493 }
494 }
495
ef368dac 496 /* Allocate line descriptors: */
252b5132
RH
497 for (sf = first_src_file; sf; sf = sf->next)
498 {
499 if (sf->num_lines > 0)
500 {
501 sf->line = (void *) xmalloc (sf->num_lines * sizeof (sf->line[0]));
502 memset (sf->line, 0, sf->num_lines * sizeof (sf->line[0]));
503 }
504 }
505
ef368dac 506 /* Count executions per line: */
252b5132
RH
507 for (sym = symtab.base; sym < symtab.limit; ++sym)
508 {
509 if (sym->file && sym->file->num_lines
510 && (sym_lookup (&syms[INCL_ANNO], sym->addr)
511 || (syms[INCL_ANNO].len == 0
512 && !sym_lookup (&syms[EXCL_ANNO], sym->addr))))
513 {
514 sym->file->ncalls += sym->ncalls;
515 line_stats = sym->file->line[sym->line_num - 1];
0eee5820 516
252b5132
RH
517 if (!line_stats)
518 {
ef368dac 519 /* Common case has at most one basic-block per source line: */
252b5132
RH
520 sym->file->line[sym->line_num - 1] = sym;
521 }
522 else if (!line_stats->addr)
523 {
ef368dac 524 /* sym is the 3rd .. nth basic block for this line: */
252b5132
RH
525 line_stats->ncalls += sym->ncalls;
526 }
527 else
528 {
ef368dac 529 /* sym is the second basic block for this line. */
252b5132
RH
530 new_line = (Sym *) xmalloc (sizeof (*new_line));
531 *new_line = *line_stats;
532 new_line->addr = 0;
533 new_line->ncalls += sym->ncalls;
534 sym->file->line[sym->line_num - 1] = new_line;
535 }
536 }
537 }
538
ef368dac 539 /* Plod over source files, annotating them: */
252b5132
RH
540 for (sf = first_src_file; sf; sf = sf->next)
541 {
542 if (!sf->num_lines || (ignore_zeros && sf->ncalls == 0))
ef368dac 543 continue;
252b5132
RH
544
545 num_executable_lines = num_lines_executed = 0;
0eee5820 546
252b5132
RH
547 ofp = annotate_source (sf, 16, annotate_with_count, sf);
548 if (!ofp)
ef368dac 549 continue;
252b5132
RH
550
551 if (bb_table_length > 0)
552 {
553 fprintf (ofp, _("\n\nTop %d Lines:\n\n Line Count\n\n"),
554 bb_table_length);
555
ef368dac 556 /* Abuse line arrays---it's not needed anymore: */
252b5132
RH
557 qsort (sf->line, sf->num_lines, sizeof (sf->line[0]), cmp_ncalls);
558 table_len = bb_table_length;
0eee5820 559
252b5132 560 if (table_len > sf->num_lines)
ef368dac 561 table_len = sf->num_lines;
0eee5820 562
252b5132
RH
563 for (i = 0; i < table_len; ++i)
564 {
565 sym = sf->line[i];
0eee5820 566
252b5132 567 if (!sym || sym->ncalls == 0)
252b5132 568 break;
ef368dac 569
252b5132
RH
570 fprintf (ofp, "%9d %10lu\n", sym->line_num, sym->ncalls);
571 }
572 }
573
574 free (sf->line);
575 sf->line = 0;
576
577 fprintf (ofp, _("\nExecution Summary:\n\n"));
578 fprintf (ofp, _("%9ld Executable lines in this file\n"),
579 num_executable_lines);
580 fprintf (ofp, _("%9ld Lines executed\n"), num_lines_executed);
581 fprintf (ofp, _("%9.2f Percent of the file executed\n"),
582 num_executable_lines
583 ? 100.0 * num_lines_executed / (double) num_executable_lines
584 : 100.0);
585 fprintf (ofp, _("\n%9lu Total number of line executions\n"),
586 sf->ncalls);
587 fprintf (ofp, _("%9.2f Average executions per line\n"),
588 num_executable_lines
589 ? (double) sf->ncalls / (double) num_executable_lines
590 : 0.0);
0eee5820 591
252b5132 592 if (ofp != stdout)
ef368dac 593 fclose (ofp);
252b5132
RH
594 }
595}
This page took 0.224448 seconds and 4 git commands to generate.