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