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