gprof.c revision 1.5
1/* 2 * Copyright (c) 1983, 1998 Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that: (1) source distributions retain this entire copyright 7 * notice and comment, and (2) distributions including binaries display 8 * the following acknowledgement: ``This product includes software 9 * developed by the University of California, Berkeley and its contributors'' 10 * in the documentation or other materials provided with the distribution 11 * and in all advertising materials mentioning features or use of this 12 * software. Neither the name of the University nor the names of its 13 * contributors may be used to endorse or promote products derived 14 * from this software without specific prior written permission. 15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 18 */ 19#include "getopt.h" 20#include "libiberty.h" 21#include "gprof.h" 22#include "basic_blocks.h" 23#include "call_graph.h" 24#include "cg_arcs.h" 25#include "cg_print.h" 26#include "corefile.h" 27#include "gmon_io.h" 28#include "hertz.h" 29#include "hist.h" 30#include "source.h" 31#include "sym_ids.h" 32 33const char *whoami; 34const char *function_mapping_file; 35const char *a_out_name = A_OUTNAME; 36long hz = HZ_WRONG; 37 38/* 39 * Default options values: 40 */ 41int debug_level = 0; 42int output_style = 0; 43int output_width = 80; 44bool bsd_style_output = FALSE; 45bool demangle = TRUE; 46bool discard_underscores = TRUE; 47bool ignore_direct_calls = FALSE; 48bool ignore_static_funcs = FALSE; 49bool ignore_zeros = TRUE; 50bool line_granularity = FALSE; 51bool print_descriptions = TRUE; 52bool print_path = FALSE; 53bool ignore_non_functions = FALSE; 54File_Format file_format = FF_AUTO; 55 56bool first_output = TRUE; 57 58char copyright[] = 59 "@(#) Copyright (c) 1983 Regents of the University of California.\n\ 60 All rights reserved.\n"; 61 62static char *gmon_name = GMONNAME; /* profile filename */ 63 64bfd *abfd; 65 66/* 67 * Functions that get excluded by default: 68 */ 69static char *default_excluded_list[] = 70{ 71 "_gprof_mcount", "mcount", "_mcount", "__mcount", "__mcount_internal", 72 "__mcleanup", 73 "<locore>", "<hicore>", 74 0 75}; 76 77/* Codes used for the long options with no short synonyms. 150 isn't 78 special; it's just an arbitrary non-ASCII char value. */ 79 80#define OPTION_DEMANGLE (150) 81#define OPTION_NO_DEMANGLE (OPTION_DEMANGLE + 1) 82 83static struct option long_options[] = 84{ 85 {"line", no_argument, 0, 'l'}, 86 {"no-static", no_argument, 0, 'a'}, 87 {"ignore-non-functions", no_argument, 0, 'D'}, 88 89 /* output styles: */ 90 91 {"annotated-source", optional_argument, 0, 'A'}, 92 {"no-annotated-source", optional_argument, 0, 'J'}, 93 {"flat-profile", optional_argument, 0, 'p'}, 94 {"no-flat-profile", optional_argument, 0, 'P'}, 95 {"graph", optional_argument, 0, 'q'}, 96 {"no-graph", optional_argument, 0, 'Q'}, 97 {"exec-counts", optional_argument, 0, 'C'}, 98 {"no-exec-counts", optional_argument, 0, 'Z'}, 99 {"function-ordering", no_argument, 0, 'r'}, 100 {"file-ordering", required_argument, 0, 'R'}, 101 {"file-info", no_argument, 0, 'i'}, 102 {"sum", no_argument, 0, 's'}, 103 104 /* various options to affect output: */ 105 106 {"all-lines", no_argument, 0, 'x'}, 107 {"demangle", no_argument, 0, OPTION_DEMANGLE}, 108 {"no-demangle", no_argument, 0, OPTION_NO_DEMANGLE}, 109 {"directory-path", required_argument, 0, 'I'}, 110 {"display-unused-functions", no_argument, 0, 'z'}, 111 {"min-count", required_argument, 0, 'm'}, 112 {"print-path", no_argument, 0, 'L'}, 113 {"separate-files", no_argument, 0, 'y'}, 114 {"static-call-graph", no_argument, 0, 'c'}, 115 {"table-length", required_argument, 0, 't'}, 116 {"time", required_argument, 0, 'n'}, 117 {"no-time", required_argument, 0, 'N'}, 118 {"width", required_argument, 0, 'w'}, 119 /* 120 * These are for backwards-compatibility only. Their functionality 121 * is provided by the output style options already: 122 */ 123 {"", required_argument, 0, 'e'}, 124 {"", required_argument, 0, 'E'}, 125 {"", required_argument, 0, 'f'}, 126 {"", required_argument, 0, 'F'}, 127 {"", required_argument, 0, 'k'}, 128 129 /* miscellaneous: */ 130 131 {"brief", no_argument, 0, 'b'}, 132 {"debug", optional_argument, 0, 'd'}, 133 {"help", no_argument, 0, 'h'}, 134 {"file-format", required_argument, 0, 'O'}, 135 {"traditional", no_argument, 0, 'T'}, 136 {"version", no_argument, 0, 'v'}, 137 {0, no_argument, 0, 0} 138}; 139 140 141static void 142DEFUN (usage, (stream, status), FILE * stream AND int status) 143{ 144 fprintf (stream, _("\ 145Usage: %s [-[abcDhilLsTvwxyz]] [-[ACeEfFJnNOpPqQZ][name]] [-I dirs]\n\ 146 [-d[num]] [-k from/to] [-m min-count] [-t table-length]\n\ 147 [--[no-]annotated-source[=name]] [--[no-]exec-counts[=name]]\n\ 148 [--[no-]flat-profile[=name]] [--[no-]graph[=name]]\n\ 149 [--[no-]time=name] [--all-lines] [--brief] [--debug[=level]]\n\ 150 [--function-ordering] [--file-ordering]\n\ 151 [--directory-path=dirs] [--display-unused-functions]\n\ 152 [--file-format=name] [--file-info] [--help] [--line] [--min-count=n]\n\ 153 [--no-static] [--print-path] [--separate-files]\n\ 154 [--static-call-graph] [--sum] [--table-length=len] [--traditional]\n\ 155 [--version] [--width=n] [--ignore-non-functions]\n\ 156 [--demangle] [--no-demangle]\n\ 157 [image-file] [profile-file...]\n"), 158 whoami); 159 if (status == 0) 160 fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO); 161 done (status); 162} 163 164 165int 166DEFUN (main, (argc, argv), int argc AND char **argv) 167{ 168 char **sp, *str; 169 Sym **cg = 0; 170 int ch, user_specified = 0; 171 172#if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES) 173 setlocale (LC_MESSAGES, ""); 174#endif 175 bindtextdomain (PACKAGE, LOCALEDIR); 176 textdomain (PACKAGE); 177 178 whoami = argv[0]; 179 xmalloc_set_program_name (whoami); 180 181 while ((ch = getopt_long (argc, argv, 182 "aA::bBcCdD::e:E:f:F:hiI:J::k:lLm:n::N::O:p::P::q::Q::st:Tvw:xyzZ::", 183 long_options, 0)) 184 != EOF) 185 { 186 switch (ch) 187 { 188 case 'a': 189 ignore_static_funcs = TRUE; 190 break; 191 case 'A': 192 if (optarg) 193 { 194 sym_id_add (optarg, INCL_ANNO); 195 } 196 output_style |= STYLE_ANNOTATED_SOURCE; 197 user_specified |= STYLE_ANNOTATED_SOURCE; 198 break; 199 case 'b': 200 print_descriptions = FALSE; 201 break; 202 case 'B': 203 output_style |= STYLE_CALL_GRAPH; 204 user_specified |= STYLE_CALL_GRAPH; 205 break; 206 case 'c': 207 ignore_direct_calls = TRUE; 208 break; 209 case 'C': 210 if (optarg) 211 { 212 sym_id_add (optarg, INCL_EXEC); 213 } 214 output_style |= STYLE_EXEC_COUNTS; 215 user_specified |= STYLE_EXEC_COUNTS; 216 break; 217 case 'd': 218 if (optarg) 219 { 220 debug_level |= atoi (optarg); 221 debug_level |= ANYDEBUG; 222 } 223 else 224 { 225 debug_level = ~0; 226 } 227 DBG (ANYDEBUG, printf ("[main] debug-level=0x%x\n", debug_level)); 228#ifndef DEBUG 229 printf (_("%s: debugging not supported; -d ignored\n"), whoami); 230#endif /* DEBUG */ 231 break; 232 case 'D': 233 ignore_non_functions = TRUE; 234 break; 235 case 'E': 236 sym_id_add (optarg, EXCL_TIME); 237 case 'e': 238 sym_id_add (optarg, EXCL_GRAPH); 239 break; 240 case 'F': 241 sym_id_add (optarg, INCL_TIME); 242 case 'f': 243 sym_id_add (optarg, INCL_GRAPH); 244 break; 245 case 'g': 246 sym_id_add (optarg, EXCL_FLAT); 247 break; 248 case 'G': 249 sym_id_add (optarg, INCL_FLAT); 250 break; 251 case 'h': 252 usage (stdout, 0); 253 case 'i': 254 output_style |= STYLE_GMON_INFO; 255 user_specified |= STYLE_GMON_INFO; 256 break; 257 case 'I': 258 search_list_append (&src_search_list, optarg); 259 break; 260 case 'J': 261 if (optarg) 262 { 263 sym_id_add (optarg, EXCL_ANNO); 264 output_style |= STYLE_ANNOTATED_SOURCE; 265 } 266 else 267 { 268 output_style &= ~STYLE_ANNOTATED_SOURCE; 269 } 270 user_specified |= STYLE_ANNOTATED_SOURCE; 271 break; 272 case 'k': 273 sym_id_add (optarg, EXCL_ARCS); 274 break; 275 case 'l': 276 line_granularity = TRUE; 277 break; 278 case 'L': 279 print_path = TRUE; 280 break; 281 case 'm': 282 bb_min_calls = (unsigned long) strtoul (optarg, (char **) NULL, 10); 283 break; 284 case 'n': 285 sym_id_add (optarg, INCL_TIME); 286 break; 287 case 'N': 288 sym_id_add (optarg, EXCL_TIME); 289 break; 290 case 'O': 291 switch (optarg[0]) 292 { 293 case 'a': 294 file_format = FF_AUTO; 295 break; 296 case 'm': 297 file_format = FF_MAGIC; 298 break; 299 case 'b': 300 file_format = FF_BSD; 301 break; 302 case '4': 303 file_format = FF_BSD44; 304 break; 305 case 'p': 306 file_format = FF_PROF; 307 break; 308 default: 309 fprintf (stderr, _("%s: unknown file format %s\n"), 310 optarg, whoami); 311 done (1); 312 } 313 break; 314 case 'p': 315 if (optarg) 316 { 317 sym_id_add (optarg, INCL_FLAT); 318 } 319 output_style |= STYLE_FLAT_PROFILE; 320 user_specified |= STYLE_FLAT_PROFILE; 321 break; 322 case 'P': 323 if (optarg) 324 { 325 sym_id_add (optarg, EXCL_FLAT); 326 output_style |= STYLE_FLAT_PROFILE; 327 } 328 else 329 { 330 output_style &= ~STYLE_FLAT_PROFILE; 331 } 332 user_specified |= STYLE_FLAT_PROFILE; 333 break; 334 case 'q': 335 if (optarg) 336 { 337 if (strchr (optarg, '/')) 338 { 339 sym_id_add (optarg, INCL_ARCS); 340 } 341 else 342 { 343 sym_id_add (optarg, INCL_GRAPH); 344 } 345 } 346 output_style |= STYLE_CALL_GRAPH; 347 user_specified |= STYLE_CALL_GRAPH; 348 break; 349 case 'r': 350 output_style |= STYLE_FUNCTION_ORDER; 351 user_specified |= STYLE_FUNCTION_ORDER; 352 break; 353 case 'R': 354 output_style |= STYLE_FILE_ORDER; 355 user_specified |= STYLE_FILE_ORDER; 356 function_mapping_file = optarg; 357 break; 358 case 'Q': 359 if (optarg) 360 { 361 if (strchr (optarg, '/')) 362 { 363 sym_id_add (optarg, EXCL_ARCS); 364 } 365 else 366 { 367 sym_id_add (optarg, EXCL_GRAPH); 368 } 369 output_style |= STYLE_CALL_GRAPH; 370 } 371 else 372 { 373 output_style &= ~STYLE_CALL_GRAPH; 374 } 375 user_specified |= STYLE_CALL_GRAPH; 376 break; 377 case 's': 378 output_style |= STYLE_SUMMARY_FILE; 379 user_specified |= STYLE_SUMMARY_FILE; 380 break; 381 case 't': 382 bb_table_length = atoi (optarg); 383 if (bb_table_length < 0) 384 { 385 bb_table_length = 0; 386 } 387 break; 388 case 'T': 389 bsd_style_output = TRUE; 390 break; 391 case 'v': 392 /* This output is intended to follow the GNU standards document. */ 393 printf (_("GNU gprof %s\n"), VERSION); 394 printf (_("Based on BSD gprof, copyright 1983 Regents of the University of California.\n")); 395 printf (_("\ 396This program is free software. This program has absolutely no warranty.\n")); 397 done (0); 398 case 'w': 399 output_width = atoi (optarg); 400 if (output_width < 1) 401 { 402 output_width = 1; 403 } 404 break; 405 case 'x': 406 bb_annotate_all_lines = TRUE; 407 break; 408 case 'y': 409 create_annotation_files = TRUE; 410 break; 411 case 'z': 412 ignore_zeros = FALSE; 413 break; 414 case 'Z': 415 if (optarg) 416 { 417 sym_id_add (optarg, EXCL_EXEC); 418 output_style |= STYLE_EXEC_COUNTS; 419 } 420 else 421 { 422 output_style &= ~STYLE_EXEC_COUNTS; 423 } 424 user_specified |= STYLE_ANNOTATED_SOURCE; 425 break; 426 case OPTION_DEMANGLE: 427 demangle = TRUE; 428 break; 429 case OPTION_NO_DEMANGLE: 430 demangle = FALSE; 431 break; 432 default: 433 usage (stderr, 1); 434 } 435 } 436 437 /* Don't allow both ordering options, they modify the arc data in-place. */ 438 if ((user_specified & STYLE_FUNCTION_ORDER) 439 && (user_specified & STYLE_FILE_ORDER)) 440 { 441 fprintf (stderr,_("\ 442%s: Only one of --function-ordering and --file-ordering may be specified.\n"), 443 whoami); 444 done (1); 445 } 446 447 /* --sum implies --line, otherwise we'd lose b-b counts in gmon.sum */ 448 if (output_style & STYLE_SUMMARY_FILE) 449 { 450 line_granularity = 1; 451 } 452 453 /* append value of GPROF_PATH to source search list if set: */ 454 str = (char *) getenv ("GPROF_PATH"); 455 if (str) 456 { 457 search_list_append (&src_search_list, str); 458 } 459 460 if (optind < argc) 461 { 462 a_out_name = argv[optind++]; 463 } 464 if (optind < argc) 465 { 466 gmon_name = argv[optind++]; 467 } 468 469 /* 470 * Turn off default functions: 471 */ 472 for (sp = &default_excluded_list[0]; *sp; sp++) 473 { 474 sym_id_add (*sp, EXCL_TIME); 475 sym_id_add (*sp, EXCL_GRAPH); 476#ifdef __alpha__ 477 sym_id_add (*sp, EXCL_FLAT); 478#endif 479 } 480 481 /* 482 * For line-by-line profiling, also want to keep those 483 * functions off the flat profile: 484 */ 485 if (line_granularity) 486 { 487 for (sp = &default_excluded_list[0]; *sp; sp++) 488 { 489 sym_id_add (*sp, EXCL_FLAT); 490 } 491 } 492 493 /* 494 * Read symbol table from core file: 495 */ 496 core_init (a_out_name); 497 498 /* 499 * If we should ignore direct function calls, we need to load 500 * to core's text-space: 501 */ 502 if (ignore_direct_calls) 503 { 504 core_get_text_space (core_bfd); 505 } 506 507 /* 508 * Create symbols from core image: 509 */ 510 if (line_granularity) 511 { 512 core_create_line_syms (core_bfd); 513 } 514 else 515 { 516 core_create_function_syms (core_bfd); 517 } 518 519 /* 520 * Translate sym specs into syms: 521 */ 522 sym_id_parse (); 523 524 if (file_format == FF_PROF) 525 { 526#ifdef PROF_SUPPORT_IMPLEMENTED 527 /* 528 * Get information about mon.out file(s): 529 */ 530 do 531 { 532 mon_out_read (gmon_name); 533 if (optind < argc) 534 { 535 gmon_name = argv[optind]; 536 } 537 } 538 while (optind++ < argc); 539#else 540 fprintf (stderr, 541 _("%s: sorry, file format `prof' is not yet supported\n"), 542 whoami); 543 done (1); 544#endif 545 } 546 else 547 { 548 /* 549 * Get information about gmon.out file(s): 550 */ 551 do 552 { 553 gmon_out_read (gmon_name); 554 if (optind < argc) 555 { 556 gmon_name = argv[optind]; 557 } 558 } 559 while (optind++ < argc); 560 } 561 562 /* 563 * If user did not specify output style, try to guess something 564 * reasonable: 565 */ 566 if (output_style == 0) 567 { 568 if (gmon_input & (INPUT_HISTOGRAM | INPUT_CALL_GRAPH)) 569 { 570 output_style = STYLE_FLAT_PROFILE | STYLE_CALL_GRAPH; 571 } 572 else 573 { 574 output_style = STYLE_EXEC_COUNTS; 575 } 576 output_style &= ~user_specified; 577 } 578 579 /* 580 * Dump a gmon.sum file if requested (before any other processing!): 581 */ 582 if (output_style & STYLE_SUMMARY_FILE) 583 { 584 gmon_out_write (GMONSUM); 585 } 586 587 if (gmon_input & INPUT_HISTOGRAM) 588 { 589 hist_assign_samples (); 590 } 591 592 if (gmon_input & INPUT_CALL_GRAPH) 593 { 594 cg = cg_assemble (); 595 } 596 597 /* do some simple sanity checks: */ 598 599 if ((output_style & STYLE_FLAT_PROFILE) 600 && !(gmon_input & INPUT_HISTOGRAM)) 601 { 602 fprintf (stderr, _("%s: gmon.out file is missing histogram\n"), whoami); 603 done (1); 604 } 605 606 if ((output_style & STYLE_CALL_GRAPH) && !(gmon_input & INPUT_CALL_GRAPH)) 607 { 608 fprintf (stderr, 609 _("%s: gmon.out file is missing call-graph data\n"), whoami); 610 done (1); 611 } 612 613 /* output whatever user whishes to see: */ 614 615 if (cg && (output_style & STYLE_CALL_GRAPH) && bsd_style_output) 616 { 617 cg_print (cg); /* print the dynamic profile */ 618 } 619 620 if (output_style & STYLE_FLAT_PROFILE) 621 { 622 hist_print (); /* print the flat profile */ 623 } 624 625 if (cg && (output_style & STYLE_CALL_GRAPH)) 626 { 627 if (!bsd_style_output) 628 { 629 cg_print (cg); /* print the dynamic profile */ 630 } 631 cg_print_index (); 632 } 633 634 if (output_style & STYLE_EXEC_COUNTS) 635 { 636 print_exec_counts (); 637 } 638 639 if (output_style & STYLE_ANNOTATED_SOURCE) 640 { 641 print_annotated_source (); 642 } 643 if (output_style & STYLE_FUNCTION_ORDER) 644 { 645 cg_print_function_ordering (); 646 } 647 if (output_style & STYLE_FILE_ORDER) 648 { 649 cg_print_file_ordering (); 650 } 651 return 0; 652} 653 654void 655done (status) 656 int status; 657{ 658 exit (status); 659} 660