home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / binutils-2.7-src.tgz / tar.out / fsf / binutils / gprof / gprof.c < prev    next >
C/C++ Source or Header  |  1996-09-28  |  14KB  |  624 lines

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