Back to index

cell-binutils  2.17cvs20070401
gprof.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 1983, 1993, 1998, 2001, 2002
00003  *      The Regents of the University of California.  All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the University nor the names of its contributors
00014  *    may be used to endorse or promote products derived from this software
00015  *    without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
00018  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
00021  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00022  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00023  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00024  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00025  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
00026  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00027  * SUCH DAMAGE.
00028  */
00029 
00030 #include "libiberty.h"
00031 #include "gprof.h"
00032 #include "bfdver.h"
00033 #include "search_list.h"
00034 #include "source.h"
00035 #include "symtab.h"
00036 #include "basic_blocks.h"
00037 #include "call_graph.h"
00038 #include "cg_arcs.h"
00039 #include "cg_print.h"
00040 #include "corefile.h"
00041 #include "gmon_io.h"
00042 #include "hertz.h"
00043 #include "hist.h"
00044 #include "sym_ids.h"
00045 #include "demangle.h"
00046 #include "getopt.h"
00047 
00048 static void usage (FILE *, int) ATTRIBUTE_NORETURN;
00049 
00050 const char *whoami;
00051 const char *function_mapping_file;
00052 const char *a_out_name = A_OUTNAME;
00053 long hz = HZ_WRONG;
00054 
00055 /*
00056  * Default options values:
00057  */
00058 int debug_level = 0;
00059 int output_style = 0;
00060 int output_width = 80;
00061 bfd_boolean bsd_style_output = FALSE;
00062 bfd_boolean demangle = TRUE;
00063 bfd_boolean discard_underscores = TRUE;
00064 bfd_boolean ignore_direct_calls = FALSE;
00065 bfd_boolean ignore_static_funcs = FALSE;
00066 bfd_boolean ignore_zeros = TRUE;
00067 bfd_boolean line_granularity = FALSE;
00068 bfd_boolean print_descriptions = TRUE;
00069 bfd_boolean print_path = FALSE;
00070 bfd_boolean ignore_non_functions = FALSE;
00071 File_Format file_format = FF_AUTO;
00072 
00073 bfd_boolean first_output = TRUE;
00074 
00075 char copyright[] =
00076  "@(#) Copyright (c) 1983 Regents of the University of California.\n\
00077  All rights reserved.\n";
00078 
00079 static char *gmon_name = GMONNAME; /* profile filename */
00080 
00081 /*
00082  * Functions that get excluded by default:
00083  */
00084 static char *default_excluded_list[] =
00085 {
00086   "_gprof_mcount", "mcount", "_mcount", "__mcount", "__mcount_internal",
00087   "__mcleanup",
00088   "<locore>", "<hicore>",
00089   0
00090 };
00091 
00092 /* Codes used for the long options with no short synonyms.  150 isn't
00093    special; it's just an arbitrary non-ASCII char value.  */
00094 
00095 #define OPTION_DEMANGLE            (150)
00096 #define OPTION_NO_DEMANGLE  (OPTION_DEMANGLE + 1)
00097 
00098 static struct option long_options[] =
00099 {
00100   {"line", no_argument, 0, 'l'},
00101   {"no-static", no_argument, 0, 'a'},
00102   {"ignore-non-functions", no_argument, 0, 'D'},
00103 
00104     /* output styles: */
00105 
00106   {"annotated-source", optional_argument, 0, 'A'},
00107   {"no-annotated-source", optional_argument, 0, 'J'},
00108   {"flat-profile", optional_argument, 0, 'p'},
00109   {"no-flat-profile", optional_argument, 0, 'P'},
00110   {"graph", optional_argument, 0, 'q'},
00111   {"no-graph", optional_argument, 0, 'Q'},
00112   {"exec-counts", optional_argument, 0, 'C'},
00113   {"no-exec-counts", optional_argument, 0, 'Z'},
00114   {"function-ordering", no_argument, 0, 'r'},
00115   {"file-ordering", required_argument, 0, 'R'},
00116   {"file-info", no_argument, 0, 'i'},
00117   {"sum", no_argument, 0, 's'},
00118 
00119     /* various options to affect output: */
00120 
00121   {"all-lines", no_argument, 0, 'x'},
00122   {"demangle", optional_argument, 0, OPTION_DEMANGLE},
00123   {"no-demangle", no_argument, 0, OPTION_NO_DEMANGLE},
00124   {"directory-path", required_argument, 0, 'I'},
00125   {"display-unused-functions", no_argument, 0, 'z'},
00126   {"min-count", required_argument, 0, 'm'},
00127   {"print-path", no_argument, 0, 'L'},
00128   {"separate-files", no_argument, 0, 'y'},
00129   {"static-call-graph", no_argument, 0, 'c'},
00130   {"table-length", required_argument, 0, 't'},
00131   {"time", required_argument, 0, 'n'},
00132   {"no-time", required_argument, 0, 'N'},
00133   {"width", required_argument, 0, 'w'},
00134     /*
00135      * These are for backwards-compatibility only.  Their functionality
00136      * is provided by the output style options already:
00137      */
00138   {"", required_argument, 0, 'e'},
00139   {"", required_argument, 0, 'E'},
00140   {"", required_argument, 0, 'f'},
00141   {"", required_argument, 0, 'F'},
00142   {"", required_argument, 0, 'k'},
00143 
00144     /* miscellaneous: */
00145 
00146   {"brief", no_argument, 0, 'b'},
00147   {"debug", optional_argument, 0, 'd'},
00148   {"help", no_argument, 0, 'h'},
00149   {"file-format", required_argument, 0, 'O'},
00150   {"traditional", no_argument, 0, 'T'},
00151   {"version", no_argument, 0, 'v'},
00152   {0, no_argument, 0, 0}
00153 };
00154 
00155 
00156 static void
00157 usage (FILE *stream, int status)
00158 {
00159   fprintf (stream, _("\
00160 Usage: %s [-[abcDhilLsTvwxyz]] [-[ACeEfFJnNOpPqQZ][name]] [-I dirs]\n\
00161        [-d[num]] [-k from/to] [-m min-count] [-t table-length]\n\
00162        [--[no-]annotated-source[=name]] [--[no-]exec-counts[=name]]\n\
00163        [--[no-]flat-profile[=name]] [--[no-]graph[=name]]\n\
00164        [--[no-]time=name] [--all-lines] [--brief] [--debug[=level]]\n\
00165        [--function-ordering] [--file-ordering]\n\
00166        [--directory-path=dirs] [--display-unused-functions]\n\
00167        [--file-format=name] [--file-info] [--help] [--line] [--min-count=n]\n\
00168        [--no-static] [--print-path] [--separate-files]\n\
00169        [--static-call-graph] [--sum] [--table-length=len] [--traditional]\n\
00170        [--version] [--width=n] [--ignore-non-functions]\n\
00171        [--demangle[=STYLE]] [--no-demangle] [@FILE]\n\
00172        [image-file] [profile-file...]\n"),
00173           whoami);
00174   if (REPORT_BUGS_TO[0] && status == 0)
00175     fprintf (stream, _("Report bugs to %s\n"), REPORT_BUGS_TO);
00176   done (status);
00177 }
00178 
00179 
00180 int
00181 main (int argc, char **argv)
00182 {
00183   char **sp, *str;
00184   Sym **cg = 0;
00185   int ch, user_specified = 0;
00186 
00187 #if defined (HAVE_SETLOCALE) && defined (HAVE_LC_MESSAGES)
00188   setlocale (LC_MESSAGES, "");
00189 #endif
00190 #if defined (HAVE_SETLOCALE)
00191   setlocale (LC_CTYPE, "");
00192 #endif
00193 #ifdef ENABLE_NLS
00194   bindtextdomain (PACKAGE, LOCALEDIR);
00195   textdomain (PACKAGE);
00196 #endif
00197 
00198   whoami = argv[0];
00199   xmalloc_set_program_name (whoami);
00200 
00201   expandargv (&argc, &argv);
00202 
00203   while ((ch = getopt_long (argc, argv,
00204        "aA::bBcC::d::De:E:f:F:hiI:J::k:lLm:n:N:O:p::P::q::Q::rR:st:Tvw:xyzZ::",
00205                          long_options, 0))
00206         != EOF)
00207     {
00208       switch (ch)
00209        {
00210        case 'a':
00211          ignore_static_funcs = TRUE;
00212          break;
00213        case 'A':
00214          if (optarg)
00215            {
00216              sym_id_add (optarg, INCL_ANNO);
00217            }
00218          output_style |= STYLE_ANNOTATED_SOURCE;
00219          user_specified |= STYLE_ANNOTATED_SOURCE;
00220          break;
00221        case 'b':
00222          print_descriptions = FALSE;
00223          break;
00224        case 'B':
00225          output_style |= STYLE_CALL_GRAPH;
00226          user_specified |= STYLE_CALL_GRAPH;
00227          break;
00228        case 'c':
00229          ignore_direct_calls = TRUE;
00230          break;
00231        case 'C':
00232          if (optarg)
00233            {
00234              sym_id_add (optarg, INCL_EXEC);
00235            }
00236          output_style |= STYLE_EXEC_COUNTS;
00237          user_specified |= STYLE_EXEC_COUNTS;
00238          break;
00239        case 'd':
00240          if (optarg)
00241            {
00242              debug_level |= atoi (optarg);
00243              debug_level |= ANYDEBUG;
00244            }
00245          else
00246            {
00247              debug_level = ~0;
00248            }
00249          DBG (ANYDEBUG, printf ("[main] debug-level=0x%x\n", debug_level));
00250 #ifndef DEBUG
00251          printf (_("%s: debugging not supported; -d ignored\n"), whoami);
00252 #endif /* DEBUG */
00253          break;
00254        case 'D':
00255          ignore_non_functions = TRUE;
00256          break;
00257        case 'E':
00258          sym_id_add (optarg, EXCL_TIME);
00259        case 'e':
00260          sym_id_add (optarg, EXCL_GRAPH);
00261          break;
00262        case 'F':
00263          sym_id_add (optarg, INCL_TIME);
00264        case 'f':
00265          sym_id_add (optarg, INCL_GRAPH);
00266          break;
00267        case 'g':
00268          sym_id_add (optarg, EXCL_FLAT);
00269          break;
00270        case 'G':
00271          sym_id_add (optarg, INCL_FLAT);
00272          break;
00273        case 'h':
00274          usage (stdout, 0);
00275        case 'i':
00276          output_style |= STYLE_GMON_INFO;
00277          user_specified |= STYLE_GMON_INFO;
00278          break;
00279        case 'I':
00280          search_list_append (&src_search_list, optarg);
00281          break;
00282        case 'J':
00283          if (optarg)
00284            {
00285              sym_id_add (optarg, EXCL_ANNO);
00286              output_style |= STYLE_ANNOTATED_SOURCE;
00287            }
00288          else
00289            {
00290              output_style &= ~STYLE_ANNOTATED_SOURCE;
00291            }
00292          user_specified |= STYLE_ANNOTATED_SOURCE;
00293          break;
00294        case 'k':
00295          sym_id_add (optarg, EXCL_ARCS);
00296          break;
00297        case 'l':
00298          line_granularity = TRUE;
00299          break;
00300        case 'L':
00301          print_path = TRUE;
00302          break;
00303        case 'm':
00304          bb_min_calls = (unsigned long) strtoul (optarg, (char **) NULL, 10);
00305          break;
00306        case 'n':
00307          sym_id_add (optarg, INCL_TIME);
00308          break;
00309        case 'N':
00310          sym_id_add (optarg, EXCL_TIME);
00311          break;
00312        case 'O':
00313          switch (optarg[0])
00314            {
00315            case 'a':
00316              file_format = FF_AUTO;
00317              break;
00318            case 'm':
00319              file_format = FF_MAGIC;
00320              break;
00321            case 'b':
00322              file_format = FF_BSD;
00323              break;
00324            case '4':
00325              file_format = FF_BSD44;
00326              break;
00327            case 'p':
00328              file_format = FF_PROF;
00329              break;
00330            default:
00331              fprintf (stderr, _("%s: unknown file format %s\n"),
00332                      optarg, whoami);
00333              done (1);
00334            }
00335          break;
00336        case 'p':
00337          if (optarg)
00338            {
00339              sym_id_add (optarg, INCL_FLAT);
00340            }
00341          output_style |= STYLE_FLAT_PROFILE;
00342          user_specified |= STYLE_FLAT_PROFILE;
00343          break;
00344        case 'P':
00345          if (optarg)
00346            {
00347              sym_id_add (optarg, EXCL_FLAT);
00348              output_style |= STYLE_FLAT_PROFILE;
00349            }
00350          else
00351            {
00352              output_style &= ~STYLE_FLAT_PROFILE;
00353            }
00354          user_specified |= STYLE_FLAT_PROFILE;
00355          break;
00356        case 'q':
00357          if (optarg)
00358            {
00359              if (strchr (optarg, '/'))
00360               {
00361                 sym_id_add (optarg, INCL_ARCS);
00362               }
00363              else
00364               {
00365                 sym_id_add (optarg, INCL_GRAPH);
00366               }
00367            }
00368          output_style |= STYLE_CALL_GRAPH;
00369          user_specified |= STYLE_CALL_GRAPH;
00370          break;
00371        case 'r':
00372          output_style |= STYLE_FUNCTION_ORDER;
00373          user_specified |= STYLE_FUNCTION_ORDER;
00374          break;
00375        case 'R':
00376          output_style |= STYLE_FILE_ORDER;
00377          user_specified |= STYLE_FILE_ORDER;
00378          function_mapping_file = optarg;
00379          break;
00380        case 'Q':
00381          if (optarg)
00382            {
00383              if (strchr (optarg, '/'))
00384               {
00385                 sym_id_add (optarg, EXCL_ARCS);
00386               }
00387              else
00388               {
00389                 sym_id_add (optarg, EXCL_GRAPH);
00390               }
00391              output_style |= STYLE_CALL_GRAPH;
00392            }
00393          else
00394            {
00395              output_style &= ~STYLE_CALL_GRAPH;
00396            }
00397          user_specified |= STYLE_CALL_GRAPH;
00398          break;
00399        case 's':
00400          output_style |= STYLE_SUMMARY_FILE;
00401          user_specified |= STYLE_SUMMARY_FILE;
00402          break;
00403        case 't':
00404          bb_table_length = atoi (optarg);
00405          if (bb_table_length < 0)
00406            {
00407              bb_table_length = 0;
00408            }
00409          break;
00410        case 'T':
00411          bsd_style_output = TRUE;
00412          break;
00413        case 'v':
00414          /* This output is intended to follow the GNU standards document.  */
00415          printf (_("GNU gprof %s\n"), BFD_VERSION_STRING);
00416          printf (_("Based on BSD gprof, copyright 1983 Regents of the University of California.\n"));
00417          printf (_("\
00418 This program is free software.  This program has absolutely no warranty.\n"));
00419          done (0);
00420        case 'w':
00421          output_width = atoi (optarg);
00422          if (output_width < 1)
00423            {
00424              output_width = 1;
00425            }
00426          break;
00427        case 'x':
00428          bb_annotate_all_lines = TRUE;
00429          break;
00430        case 'y':
00431          create_annotation_files = TRUE;
00432          break;
00433        case 'z':
00434          ignore_zeros = FALSE;
00435          break;
00436        case 'Z':
00437          if (optarg)
00438            {
00439              sym_id_add (optarg, EXCL_EXEC);
00440              output_style |= STYLE_EXEC_COUNTS;
00441            }
00442          else
00443            {
00444              output_style &= ~STYLE_EXEC_COUNTS;
00445            }
00446          user_specified |= STYLE_ANNOTATED_SOURCE;
00447          break;
00448        case OPTION_DEMANGLE:
00449          demangle = TRUE;
00450          if (optarg != NULL)
00451            {
00452              enum demangling_styles style;
00453 
00454              style = cplus_demangle_name_to_style (optarg);
00455              if (style == unknown_demangling)
00456               {
00457                 fprintf (stderr,
00458                         _("%s: unknown demangling style `%s'\n"),
00459                         whoami, optarg);
00460                 xexit (1);
00461               }
00462 
00463              cplus_demangle_set_style (style);
00464           }
00465          break;
00466        case OPTION_NO_DEMANGLE:
00467          demangle = FALSE;
00468          break;
00469        default:
00470          usage (stderr, 1);
00471        }
00472     }
00473 
00474   /* Don't allow both ordering options, they modify the arc data in-place.  */
00475   if ((user_specified & STYLE_FUNCTION_ORDER)
00476       && (user_specified & STYLE_FILE_ORDER))
00477     {
00478       fprintf (stderr,_("\
00479 %s: Only one of --function-ordering and --file-ordering may be specified.\n"),
00480               whoami);
00481       done (1);
00482     }
00483 
00484   /* --sum implies --line, otherwise we'd lose basic block counts in
00485        gmon.sum */
00486   if (output_style & STYLE_SUMMARY_FILE)
00487     line_granularity = 1;
00488 
00489   /* append value of GPROF_PATH to source search list if set: */
00490   str = (char *) getenv ("GPROF_PATH");
00491   if (str)
00492     search_list_append (&src_search_list, str);
00493 
00494   if (optind < argc)
00495     a_out_name = argv[optind++];
00496 
00497   if (optind < argc)
00498     gmon_name = argv[optind++];
00499 
00500   /* Turn off default functions.  */
00501   for (sp = &default_excluded_list[0]; *sp; sp++)
00502     {
00503       sym_id_add (*sp, EXCL_TIME);
00504       sym_id_add (*sp, EXCL_GRAPH);
00505       sym_id_add (*sp, EXCL_FLAT);
00506     }
00507 
00508   /* Read symbol table from core file.  */
00509   core_init (a_out_name);
00510 
00511   /* If we should ignore direct function calls, we need to load to
00512      core's text-space.  */
00513   if (ignore_direct_calls)
00514     core_get_text_space (core_bfd);
00515 
00516   /* Create symbols from core image.  */
00517   if (line_granularity)
00518     core_create_line_syms ();
00519   else
00520     core_create_function_syms ();
00521 
00522   /* Translate sym specs into syms.  */
00523   sym_id_parse ();
00524 
00525   if (file_format == FF_PROF)
00526     {
00527       fprintf (stderr,
00528               _("%s: sorry, file format `prof' is not yet supported\n"),
00529               whoami);
00530       done (1);
00531     }
00532   else
00533     {
00534       /* Get information about gmon.out file(s).  */
00535       do
00536        {
00537          gmon_out_read (gmon_name);
00538          if (optind < argc)
00539            gmon_name = argv[optind];
00540        }
00541       while (optind++ < argc);
00542     }
00543 
00544   /* If user did not specify output style, try to guess something
00545      reasonable.  */
00546   if (output_style == 0)
00547     {
00548       if (gmon_input & (INPUT_HISTOGRAM | INPUT_CALL_GRAPH))
00549        {
00550          if (gmon_input & INPUT_HISTOGRAM)
00551            output_style |= STYLE_FLAT_PROFILE;
00552          if (gmon_input & INPUT_CALL_GRAPH)
00553            output_style |= STYLE_CALL_GRAPH;
00554        }
00555       else
00556        output_style = STYLE_EXEC_COUNTS;
00557 
00558       output_style &= ~user_specified;
00559     }
00560 
00561   /* Dump a gmon.sum file if requested (before any other
00562      processing!)  */
00563   if (output_style & STYLE_SUMMARY_FILE)
00564     {
00565       gmon_out_write (GMONSUM);
00566     }
00567 
00568   if (gmon_input & INPUT_HISTOGRAM)
00569     {
00570       hist_assign_samples ();
00571     }
00572 
00573   if (gmon_input & INPUT_CALL_GRAPH)
00574     {
00575       cg = cg_assemble ();
00576     }
00577 
00578   /* Do some simple sanity checks.  */
00579   if ((output_style & STYLE_FLAT_PROFILE)
00580       && !(gmon_input & INPUT_HISTOGRAM))
00581     {
00582       fprintf (stderr, _("%s: gmon.out file is missing histogram\n"), whoami);
00583       done (1);
00584     }
00585 
00586   if ((output_style & STYLE_CALL_GRAPH) && !(gmon_input & INPUT_CALL_GRAPH))
00587     {
00588       fprintf (stderr,
00589               _("%s: gmon.out file is missing call-graph data\n"), whoami);
00590       done (1);
00591     }
00592 
00593   /* Output whatever user whishes to see.  */
00594   if (cg && (output_style & STYLE_CALL_GRAPH) && bsd_style_output)
00595     {
00596       /* Print the dynamic profile.  */
00597       cg_print (cg);
00598     }
00599 
00600   if (output_style & STYLE_FLAT_PROFILE)
00601     {
00602       /* Print the flat profile.  */
00603       hist_print ();        
00604     }
00605 
00606   if (cg && (output_style & STYLE_CALL_GRAPH))
00607     {
00608       if (!bsd_style_output)
00609        {
00610          /* Print the dynamic profile.  */
00611          cg_print (cg);     
00612        }
00613       cg_print_index ();
00614     }
00615 
00616   if (output_style & STYLE_EXEC_COUNTS)
00617     print_exec_counts ();
00618   
00619   if (output_style & STYLE_ANNOTATED_SOURCE)
00620     print_annotated_source ();
00621   
00622   if (output_style & STYLE_FUNCTION_ORDER)
00623     cg_print_function_ordering ();
00624   
00625   if (output_style & STYLE_FILE_ORDER)
00626     cg_print_file_ordering ();
00627 
00628   return 0;
00629 }
00630 
00631 void
00632 done (int status)
00633 {
00634   exit (status);
00635 }