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