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