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