OSDN Git Service

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