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