source: branches/libc-0.6/src/binutils/gprof/gprof.c

Last change on this file was 610, checked in by bird, 22 years ago

This commit was generated by cvs2svn to compensate for changes in r609,
which included commits to RCS files with non-trunk default branches.

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