Lots of changes from David Mosberger-Tang; see ChangeLog and NOTES for details:
[external/binutils.git] / gprof / basic_blocks.c
1 /*
2  * Basic-block level related code: reading/writing of basic-block info
3  * to/from gmon.out; computing and formatting of basic-block related
4  * statistics.
5  */
6 #include <stdio.h>
7 #include <unistd.h>
8 #include "basic_blocks.h"
9 #include "core.h"
10 #include "gmon_io.h"
11 #include "gmon_out.h"
12 #include "gprof.h"
13 #include "libiberty.h"
14 #include "source.h"
15 #include "sym_ids.h"
16
17
18 /*
19  * Default option values:
20  */
21 bool bb_annotate_all_lines = FALSE;
22 int bb_min_calls = 1;
23 int bb_table_length = 10;
24
25 /*
26  * Variables used to compute annotated source listing stats:
27  */
28 static long num_executable_lines;
29 static long num_lines_executed;
30
31
32 /*
33  * Helper for sorting.  Compares two basic-blocks and returns result
34  * such that sorting will be increasing according to filename, line
35  * number, and basic-block address (in that order).
36  */
37 static int
38 DEFUN(cmp_bb, (lp, rp), const void *lp AND const void *rp)
39 {
40     int r;
41     const Sym *left = *(const Sym**)lp;
42     const Sym *right = *(const Sym**)rp;
43
44     if (left->file && right->file) {
45         r = strcmp(left->file->name, right->file->name);
46         if (r) {
47             return r;
48         } /* if */
49
50         if (left->line_num != right->line_num) {
51             return left->line_num - right->line_num;
52         } /* if */
53     } /* if */
54
55     if (left->addr < right->addr) {
56         return -1;
57     } else if (left->addr > right->addr) {
58         return  1;
59     } else {
60         return  0;
61     } /* if */
62 } /* cmp_bb */
63
64
65 /*
66  * Helper for sorting.  Order basic blocks in decreasing number of
67  * calls, ties are broken in increasing order of line numbers.
68  */
69 static int
70 DEFUN(cmp_ncalls, (lp, rp), const void *lp AND const void *rp)
71 {
72     const Sym *left = *(const Sym**)lp;
73     const Sym *right = *(const Sym**)rp;
74
75     if (!left) {
76         return 1;
77     } else if (!right) {
78         return -1;
79     } /* if */
80
81     if (right->ncalls != left->ncalls) {
82         return right->ncalls - left->ncalls;
83     } /* if */
84
85     return left->line_num - right->line_num;
86 } /* cmp_ncalls */
87
88
89 /*
90  * Skip over variable length string.
91  */
92 static void
93 DEFUN(fskip_string, (fp), FILE *fp)
94 {
95     int ch;
96
97     while ((ch = fgetc(fp)) != EOF) {
98         if (ch == '\0') {
99             break;
100         } /* if */
101     } /* if */
102 } /* fskip_string */
103
104
105 /*
106  * Read a basic-block record from file IFP.  FILENAME is the name
107  * of file IFP and is provided for formatting error-messages only.
108  */
109 void
110 DEFUN(bb_read_rec, (ifp, filename), FILE *ifp AND const char *filename)
111 {
112     int nblocks, b;
113     bfd_vma addr;
114     long ncalls;
115     Sym *sym;
116
117     if (fread(&nblocks, sizeof(nblocks), 1, ifp) != 1) {
118         fprintf(stderr, "%s: %s: unexpected end of file\n", whoami, filename);
119         done(1);
120     } /* if */
121
122     nblocks = bfd_get_32(core_bfd, (bfd_byte*) &nblocks);
123     if (gmon_file_version == 0) {
124         fskip_string(ifp);
125     } /* if */
126
127     for (b = 0; b < nblocks; ++b) {
128         if (gmon_file_version == 0) {
129             int line_num;
130             /*
131              * Version 0 had lots of extra stuff that we don't
132              * care about anymore.
133              */
134             if ((fread(&ncalls, sizeof(ncalls), 1, ifp) != 1)
135                 || (fread(&addr, sizeof(addr), 1, ifp) != 1)
136                 || (fskip_string(ifp), FALSE)
137                 || (fskip_string(ifp), FALSE)
138                 || (fread(&line_num, sizeof(line_num), 1, ifp) != 1))
139             {
140                 perror(filename);
141                 done(1);
142             } /* if */
143         } else {
144             if (fread(&addr, sizeof(addr), 1, ifp) != 1
145                 || fread(&ncalls, sizeof(ncalls), 1, ifp) != 1)
146             {
147                 perror(filename);
148                 done(1);
149             } /* if */
150         } /* if */
151
152         /*
153          * Basic-block execution counts are meaningful only if we're
154          * profiling at the line-by-line level:
155          */
156         if (line_granularity) {
157
158             /* convert from target to host endianness: */
159
160             addr = get_vma(core_bfd, (bfd_byte*) &addr);
161
162             sym = sym_lookup(&symtab, addr);
163             sym->is_bb_head = TRUE;
164             sym->ncalls += bfd_get_32(core_bfd, (bfd_byte*)&ncalls);
165
166             DBG(BBDEBUG, printf("[bb_read_rec] 0x%lx->0x%lx (%s) cnt=%d\n",
167                                 addr, sym->addr, sym->name, sym->ncalls));
168         } else {
169             static bool user_warned = FALSE;
170
171             if (!user_warned) {
172                 user_warned = TRUE;
173                 fprintf(stderr,
174 "%s: warning: ignoring basic-block exec counts (use -l or --line)\n",
175                         whoami);
176             } /* if */
177         } /* if */
178     } /* for */
179     return;
180 } /* bb_read_rec */
181
182
183 /*
184  * Write all basic-blocks with non-zero counts to file OFP.  FILENAME
185  * is the name of OFP and is provided for producing error-messages
186  * only.
187  */
188 void
189 DEFUN(bb_write_blocks, (ofp, filename), FILE *ofp AND const char *filename)
190 {
191     const unsigned char tag = GMON_TAG_BB_COUNT;
192     int nblocks = 0;
193     bfd_vma addr;
194     long ncalls;
195     Sym *sym;
196
197     /* count how many non-zero blocks with have: */
198
199     for (sym = symtab.base; sym < symtab.limit; ++sym) {
200         if (sym->ncalls > 0) {
201             ++nblocks;
202         } /* if */
203     } /* for */
204
205     /* write header: */
206     bfd_put_32(core_bfd, nblocks, (bfd_byte*) &nblocks);
207     if (fwrite(&tag, sizeof(tag), 1, ofp) != 1
208         || fwrite(&nblocks, sizeof(nblocks), 1, ofp) != 1)
209     {
210         perror(filename);
211         done(1);
212     } /* if */
213
214     /* write counts: */
215     for (sym = symtab.base; sym < symtab.limit; ++sym) {
216         if (sym->ncalls == 0) {
217             continue;
218         } /* if */
219
220         put_vma(core_bfd, sym->addr, (bfd_byte*) &addr);
221         bfd_put_32(core_bfd, sym->ncalls, (bfd_byte*) &ncalls);
222
223         if (fwrite(&addr, sizeof(addr), 1, ofp) != 1
224             || fwrite(&ncalls, sizeof(ncalls), 1, ofp) != 1)
225         {
226             perror(filename);
227             done(1);
228         } /* if */
229     } /* for */
230 } /* bb_write_blocks */
231
232
233 /*
234  * Output basic-block statistics in a format that is easily parseable.
235  * Current the format is:
236  *
237  *      <filename>:<line-number>: (<function-name>:<bb-addr): <ncalls>
238  */
239 void
240 DEFUN_VOID(print_exec_counts)
241 {
242     Sym **sorted_bbs, *sym;
243     int i, len;
244
245     if (first_output) {
246         first_output = FALSE;
247     } else {
248         printf("\f\n");
249     } /* if */
250
251     /* sort basic-blocks according to function name and line number: */
252
253     sorted_bbs = (Sym**)xmalloc(symtab.len * sizeof(sorted_bbs[0]));
254     len = 0;
255     for (sym = symtab.base; sym < symtab.limit; ++sym) {
256         /*
257          * Accept symbol if it's the start of a basic-block and it is
258          * called at least bb_min_calls times and if it's in the
259          * INCL_EXEC table or there is no INCL_EXEC table and it does
260          * not appear in the EXCL_EXEC table.
261          */
262         if (sym->is_bb_head && sym->ncalls >= bb_min_calls
263             && (sym_lookup(&syms[INCL_EXEC], sym->addr)
264                 || (syms[INCL_EXEC].len == 0
265                     && !sym_lookup(&syms[EXCL_EXEC], sym->addr))))
266         {
267             sorted_bbs[len++] = sym;
268         } /* if */
269     } /* for */
270     qsort(sorted_bbs, len, sizeof(sorted_bbs[0]), cmp_bb);
271
272     /* output basic-blocks: */
273
274     for (i = 0; i < len; ++i) {
275         sym = sorted_bbs[i];
276         printf("%s:%d: (%s:0x%lx) %d executions\n",
277                sym->file ? sym->file->name : "<unknown>", sym->line_num,
278                sym->name, sym->addr, sym->ncalls);
279     } /* for */
280     free(sorted_bbs);
281 } /* print_exec_counts */
282
283
284 /*
285  * Helper for bb_annotated_source: format annotation containing
286  * number of line executions.
287  */
288 static void
289 DEFUN(annotate_with_count, (buf, width, line_num, arg),
290       char *buf AND int width AND int line_num AND void *arg)
291 {
292     Source_File *sf = arg;
293     Sym *b;
294     long cnt;
295     static long last_count;
296
297     if (line_num == 1) {
298         last_count = -1;
299     } /* if */
300
301     b = 0;
302     if (line_num <= sf->num_lines)  {
303         b = sf->line[line_num - 1];
304     } /* if */
305     if (!b) {
306         cnt = -1;
307     } else {
308         ++num_executable_lines;
309         cnt = b->ncalls;
310     } /* if */
311     if (cnt > 0) {
312         ++num_lines_executed;
313     } /* if */
314     if (cnt < 0 && bb_annotate_all_lines) {
315         cnt = last_count;
316     } /* if */
317
318     if (cnt < 0) {
319         strcpy(buf, "\t\t");
320     } else if (cnt < bb_min_calls) {
321         strcpy(buf, "       ##### -> ");
322     } else {
323         sprintf(buf, "%12ld -> ", cnt);
324     } /* if */
325     last_count = cnt;
326 } /* annotate_with_count */
327
328
329 /*
330  * Annotate the files named in SOURCE_FILES with basic-block statistics
331  * (execution counts).  After each source files, a few statistics
332  * regarding that source file are printed.
333  */
334 void
335 DEFUN_VOID(print_annotated_source)
336 {
337     Sym *sym, *line_stats, *new_line;
338     Source_File *sf;
339     int i, table_len;
340     FILE *ofp;
341
342     /*
343      * Find maximum line number for each source file that user is
344      * interested in:
345      */
346     for (sym = symtab.base; sym < symtab.limit; ++sym) {
347         /*
348          * Accept symbol if it's file is known, its line number is
349          * bigger than anything we have seen for that file so far and
350          * if it's in the INCL_ANNO table or there is no INCL_ANNO
351          * table and it does not appear in the EXCL_ANNO table.
352          */
353         if (sym->file && sym->line_num > sym->file->num_lines
354             && (sym_lookup(&syms[INCL_ANNO], sym->addr)
355                 || (syms[INCL_ANNO].len == 0
356                     && !sym_lookup(&syms[EXCL_ANNO], sym->addr))))
357         {
358             sym->file->num_lines = sym->line_num;
359         } /* if */
360     } /* for */
361
362     /* allocate line descriptors: */
363
364     for (sf = first_src_file; sf; sf = sf->next) {
365         if (sf->num_lines > 0) {
366             sf->line = (void*) xmalloc(sf->num_lines * sizeof(sf->line[0]));
367             memset(sf->line, 0, sf->num_lines * sizeof(sf->line[0]));
368         } /* if */
369     } /* for */
370
371     /* count executions per line: */
372
373     for (sym = symtab.base; sym < symtab.limit; ++sym) {
374         if (sym->is_bb_head && sym->file && sym->file->num_lines
375             && (sym_lookup(&syms[INCL_ANNO], sym->addr)
376                 || (syms[INCL_ANNO].len == 0
377                     && !sym_lookup(&syms[EXCL_ANNO], sym->addr))))
378         {
379             sym->file->ncalls += sym->ncalls;
380             line_stats = sym->file->line[sym->line_num - 1];
381             if (!line_stats) {
382                 /* common case has at most one basic-block per source line: */
383                 sym->file->line[sym->line_num - 1] = sym;
384             } else if (!line_stats->addr) {
385                 /* sym is the 3rd .. nth basic block for this line: */
386                 line_stats->ncalls += sym->ncalls;
387             } else {
388                 /* sym is the second basic block for this line */
389                 new_line = (Sym*) xmalloc(sizeof(*new_line));
390                 *new_line = *line_stats;
391                 new_line->addr = 0;
392                 new_line->ncalls += sym->ncalls;
393                 sym->file->line[sym->line_num - 1] = new_line;
394             } /* if */
395         } /* if */
396     } /* for */
397
398     /* plod over source files, annotating them: */
399
400     for (sf = first_src_file; sf; sf = sf->next) {
401         if (!sf->num_lines || (ignore_zeros && sf->ncalls == 0)) {
402             continue;
403         } /* if */
404
405         num_executable_lines = num_lines_executed = 0;
406         ofp = annotate_source(sf, 16, annotate_with_count, sf);
407         if (!ofp) {
408             continue;
409         } /* if */
410
411         if (bb_table_length > 0) {
412             fprintf(ofp, "\n\nTop %d Lines:\n\n     Line      Count\n\n",
413                     bb_table_length);
414
415             /* abuse line arrays---it's not needed anymore: */
416             qsort(sf->line, sf->num_lines, sizeof(sf->line[0]), cmp_ncalls);
417             table_len = bb_table_length;
418             if (table_len > sf->num_lines) {
419                 table_len = sf->num_lines;
420             } /* if */
421             for (i = 0; i < table_len; ++i) {
422                 sym = sf->line[i];
423                 if (!sym || sym->ncalls <= 0) {
424                     break;
425                 } /* if */
426                 fprintf(ofp, "%9d %10d\n", sym->line_num, sym->ncalls);
427             } /* for */
428         } /* if */
429
430         free(sf->line);
431         sf->line = 0;
432
433         fprintf(ofp, "\nExecution Summary:\n\n");
434         fprintf(ofp, "%9ld   Executable lines in this file\n",
435                 num_executable_lines);
436         fprintf(ofp, "%9ld   Lines executed\n", num_lines_executed);
437         fprintf(ofp, "%9.2f   Percent of the file executed\n",
438                 num_executable_lines
439                 ? 100.0 * num_lines_executed / (double) num_executable_lines
440                 : 100.0);
441         fprintf(ofp, "\n%9d   Total number of line executions\n", sf->ncalls);
442         fprintf(ofp, "%9.2f   Average executions per line\n",
443                 num_executable_lines
444                 ? sf->ncalls / (double) num_executable_lines
445                 : 0.0);
446         if (ofp != stdout) {
447             fclose(ofp);
448         } /* if */
449     } /* for */
450 } /* print_annotated_source */
451
452                         /*** end of basic_block.c ***/