diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1996-06-10 10:55:58 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 1996-06-10 10:55:58 +0000 |
commit | a7e831079363e3bb45f3172f6e59ba48e335682b (patch) | |
tree | ee4324eac9a9d66f189fab60498ec42b8226b7fc /gnu/usr.bin/binutils/gprof | |
parent | 467cb0a471d13c5186a6ee166e60b47c30da64e9 (diff) |
Bring Cygnus versions into the trunk, keeping our local patches
Diffstat (limited to 'gnu/usr.bin/binutils/gprof')
24 files changed, 1461 insertions, 1282 deletions
diff --git a/gnu/usr.bin/binutils/gprof/ChangeLog b/gnu/usr.bin/binutils/gprof/ChangeLog index c5089b5e098..8551292f67c 100644 --- a/gnu/usr.bin/binutils/gprof/ChangeLog +++ b/gnu/usr.bin/binutils/gprof/ChangeLog @@ -1,4 +1,133 @@ -Thu Nov 16 17:34:01 1995 Ken Raeburn <raeburn@cygnus.com> +Mon Apr 8 14:44:33 1996 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Permit --enable-shared to specify a list of + directories. + * configure: Rebuild. + +Thu Mar 21 17:18:25 1996 Ian Lance Taylor <ian@cygnus.com> + + * core.c (core_create_function_syms): Move filename and func_name + inside ifdef where they are used. + + * core.c (core_sym_class): Parenthesize && within ||. + * symtab.c (symtab_finalize): Correct parenthesization. + + * cg_print.h (cg_print_file_ordering): Declare. + (cg_print_function_ordering): Declare. + + * __bb_exit_func.c (__bb_exit_func): Replace bcopy with memcpy. + * cg_arcs.c (arc_add): Likewise. + * cg_print.c (cg_print_function_ordering): Likewise. + +Thu Mar 21 17:02:02 1996 David Mosberger-Tang <davidm@azstarnet.com> + + * gprof.c (default_excluded_list): Add "__mcount". + + * gprof.c (main): Change ifdef __osf__ to __alpha__. + + * gmon_io.c (gmon_out_read): If BSD44_FORMAT is defined, get the + profiling rate from the header. + + * gmon.h (struct raw_phdr): Only include pad if both __alpha__ and + __osf__ are defined. Add new fields if BSD44_FORMAT is defined. + + * alpha.h (MIN_INSN_SIZE): Define. + * core.c (MIN_INSN_SIZE): If not defined, define as 1. + (core_sym_class): Ignore debugging symbols. + (core_create_line_syms): Use MIN_INSN_SIZE when gathering line + information. + +Wed Mar 20 18:15:47 1996 Andreas Schwab <schwab@issan.informatik.uni-dortmund.de> + + * cg_print.c (cg_print_function_ordering): Fix __GNUC__ misspelled + as __GNU_C__. + (order_and_dump_functions_by_arcs): Likewise. + +Tue Mar 12 12:19:50 1996 Ian Lance Taylor <ian@cygnus.com> + + * configure: Rebuild with autoconf 2.8. + +Sun Feb 18 15:06:18 1996 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Check for 'do not mix' from native linker before + trying to use -rpath. + * configure: Rebuild. + +Tue Feb 13 15:32:53 1996 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Set HDLFLAGS for *-*-hpux with --enable-shared. + * configure: Rebuild. + +Wed Feb 7 14:03:17 1996 Ian Lance Taylor <ian@cygnus.com> + + * configure.in: Don't set CC. Look for --enable-shared. Set + BFDLIB and HLDFLAGS and substitute them. + * configure: Rebuild. + * Makefile.in (LIBS): Use @BFDLIB@. + (HLDFLAGS): New variable. + (gprof): Use $(HLDFLAGS). + +Mon Feb 5 16:34:44 1996 Ian Lance Taylor <ian@cygnus.com> + + Support for building bfd and opcodes as shared libraries, based on + patches from Alan Modra <alan@spri.levels.unisa.edu.au>: + * Makefile.in (LIBDEPS): New variable. + (LIBS): Use -L../bfd -lbfd. + (gprof): Depend upon $(LIBDEPS) rather than $(LIBS). + +Sat Dec 30 10:11:03 1995 Jeffrey A Law (law@cygnus.com) + + * gprof.c (long_options): Add "--function-ordering" and + "--file-ordering" options. + (usage): Add new options to usage message. + (main): Handle new options. + * gprof.h (STYLE_FUNCTION_ORDER): Define. + (STYLE_FILE_ORDER): Define. + (function_mapping_file): Declare. + * cg_arcs.c (arcs, numarcs): New globals. + (arc_add): Put new arcs into the arc array so the function/file + ordering code can examine them. + * cg_arcs.h (struct arc): New field "has_been_placed". + (arcs, numarcs): Declare new globals. + * core.c (symbol_map, symbol_map_count): New globals. + (read_function_mappings): New function to read in a function + to object map file. + (core_init): Call read_function_mappings if a function mapping + file exists. + (core_create_function_syms): Handle function to object file + mappings. + * symtab.h (struct sym): New fields "mapped", "has_been_placed", + "nuses", "prev". + * cg_print.c (cmp_arc_count): New function for sorting arcs. + (cmp_fun_nuses): Likewise for functions. + (cg_print_function_ordering): New function to print a suggested + function ordering. + (cg_print_file_ordering): Likewise for ordering .o files. + (order_and_dump_functions_by_arcs): Helper function for function + and object file ordering code. + +Sun Dec 24 21:32:27 1995 Jeffrey A Law (law@cygnus.com) + + * core.c (core_sym_class): Ignore symbols without BSF_FUNCTION + set if ignore_non_function is set. + * gprof.h (ignore_non_functions): Declare. + * gprof.c (ignore_non_functions): Define. + (long_options): Add "ignore-non-functions". + (usage): Add new options. + (main): Recognize "-D" and "--ignore-non-functions" option. + +Tue Nov 21 13:24:39 1995 Ken Raeburn <raeburn@cygnus.com> + + * Makefile.in (.m.c): Strip out directory name from function + name. + + * hist.c (scale_and_align_entries): Don't use DEFUN_VOID. Do + UNITS_TO_CODE adjustment unconditionally; compiler can optimize + away zero-offset case. Refer to scaled_addr, not aligned_addr. + + * vax.c: Don't include vax.h here. + +Thu Nov 16 03:41:37 1995 Ken Raeburn <raeburn@cygnus.com> Version 2.6 released. diff --git a/gnu/usr.bin/binutils/gprof/Makefile.in b/gnu/usr.bin/binutils/gprof/Makefile.in index d9a6f24fe77..1f5e0f02a57 100644 --- a/gnu/usr.bin/binutils/gprof/Makefile.in +++ b/gnu/usr.bin/binutils/gprof/Makefile.in @@ -40,7 +40,8 @@ SRCS= $(MY_TARGET).c basic_blocks.c call_graph.c \ gmon_io.c gprof.c hertz.c hist.c source.c search_list.c symtab.c \ sym_ids.c utils.c -LIBS = ../bfd/libbfd.a ../libiberty/libiberty.a +LIBDEPS = ../bfd/libbfd.a ../libiberty/libiberty.a +LIBS = @BFDLIB@ ../libiberty/libiberty.a OBJS= $(MY_TARGET).o basic_blocks.o bsd_callg_bl.o call_graph.o \ cg_arcs.o cg_dfn.o cg_print.o core.o flat_bl.o fsf_callg_bl.o \ @@ -52,6 +53,7 @@ GEN_FILES = flat_bl.c bsd_callg_bl.c fsf_callg_bl.c CFLAGS=-g -DDEBUG LDFLAGS= +HLDFLAGS = @HLDFLAGS@ .c.o: $(CC) -c $(CFLAGS) -I. -I$(srcdir) -I../bfd -I$(srcdir)/../include -I$(srcdir)/../bfd -DMACHINE_H=\"$(MY_TARGET).h\" $(TCFLAGS) $(HCFLAGS) $< @@ -62,7 +64,7 @@ all: $(GEN_FILES) $(PROG) .m.c: awk -f $(srcdir)/gen-c-prog.awk > ./$*.c \ - FUNCTION=`(echo $*|sed -e 's/_bl//')`_blurb \ + FUNCTION=`(echo $*|sed -e 's,.*/,,g' -e 's/_bl//')`_blurb \ FILE=$*.m $(srcdir)/$*.m diststuff: $(GEN_FILES) info @@ -100,8 +102,8 @@ install: all $(INSTALL_XFORM) gprof $(bindir)/gprof $(INSTALL_XFORM1) $(srcdir)/gprof.1 $(man1dir)/gprof.1 -gprof: $(OBJS) $(LIBS) - $(CC) -o $(PROG) $(LDFLAGS) $(OBJS) $(LIBS) +gprof: $(OBJS) $(LIBDEPS) + $(CC) -o $(PROG) $(HLDFLAGS) $(LDFLAGS) $(OBJS) $(LIBS) mostlyclean: -rm -f *.o core gprof nohup.out \ diff --git a/gnu/usr.bin/binutils/gprof/__bb_exit_func.c b/gnu/usr.bin/binutils/gprof/__bb_exit_func.c index 512056ed4af..813321566c7 100644 --- a/gnu/usr.bin/binutils/gprof/__bb_exit_func.c +++ b/gnu/usr.bin/binutils/gprof/__bb_exit_func.c @@ -54,8 +54,8 @@ __bb_exit_func (void) perror(OUT_NAME); return; } /* if */ - bcopy(GMON_MAGIC, &ghdr.cookie[0], 4); - bcopy(&version, &ghdr.version, sizeof(version)); + memcpy(&ghdr.cookie[0], GMON_MAGIC, 4); + memcpy(&ghdr.version, &version, sizeof(version)); fwrite(&ghdr, sizeof(ghdr), 1, fp); for (ptr = __bb_head; ptr != 0; ptr = ptr->next) { diff --git a/gnu/usr.bin/binutils/gprof/alpha.h b/gnu/usr.bin/binutils/gprof/alpha.h index 9eb92bc2620..b91324ed8db 100644 --- a/gnu/usr.bin/binutils/gprof/alpha.h +++ b/gnu/usr.bin/binutils/gprof/alpha.h @@ -28,4 +28,9 @@ #define OFFSET_TO_CODE 0 #define UNITS_TO_CODE (OFFSET_TO_CODE / sizeof(UNIT)) +/* + * Minimum size of an instruction (in bytes): + */ +#define MIN_INSN_SIZE 4 + #endif /* alpha_h */ diff --git a/gnu/usr.bin/binutils/gprof/bsd_callg_bl.c b/gnu/usr.bin/binutils/gprof/bsd_callg_bl.c deleted file mode 100644 index 5be63b9a24c..00000000000 --- a/gnu/usr.bin/binutils/gprof/bsd_callg_bl.c +++ /dev/null @@ -1,118 +0,0 @@ -/* ==> Do not modify this file!! It is created automatically - from bsd_callg_bl.m using the gen-c-prog.awk script. <== */ - -#include <stdio.h> - -void -bsd_callg_blurb (file) - FILE *file; -{ - fputs ("\n", file); - fputs ("\n", file); - fputs ("\n", file); - fputs ("call graph profile:\n", file); - fputs (" The sum of self and descendents is the major sort\n", file); - fputs (" for this listing.\n", file); - fputs ("\n", file); - fputs (" function entries:\n", file); - fputs ("\n", file); - fputs ("index the index of the function in the call graph\n", file); - fputs (" listing, as an aid to locating it (see below).\n", file); - fputs ("\n", file); - fputs ("%time the percentage of the total time of the program\n", file); - fputs (" accounted for by this function and its\n", file); - fputs (" descendents.\n", file); - fputs ("\n", file); - fputs ("self the number of seconds spent in this function\n", file); - fputs (" itself.\n", file); - fputs ("\n", file); - fputs ("descendents\n", file); - fputs (" the number of seconds spent in the descendents of\n", file); - fputs (" this function on behalf of this function.\n", file); - fputs ("\n", file); - fputs ("called the number of times this function is called (other\n", file); - fputs (" than recursive calls).\n", file); - fputs ("\n", file); - fputs ("self the number of times this function calls itself\n", file); - fputs (" recursively.\n", file); - fputs ("\n", file); - fputs ("name the name of the function, with an indication of\n", file); - fputs (" its membership in a cycle, if any.\n", file); - fputs ("\n", file); - fputs ("index the index of the function in the call graph\n", file); - fputs (" listing, as an aid to locating it.\n", file); - fputs ("\n", file); - fputs ("\n", file); - fputs ("\n", file); - fputs (" parent listings:\n", file); - fputs ("\n", file); - fputs ("self* the number of seconds of this function's self time\n", file); - fputs (" which is due to calls from this parent.\n", file); - fputs ("\n", file); - fputs ("descendents*\n", file); - fputs (" the number of seconds of this function's\n", file); - fputs (" descendent time which is due to calls from this\n", file); - fputs (" parent.\n", file); - fputs ("\n", file); - fputs ("called** the number of times this function is called by\n", file); - fputs (" this parent. This is the numerator of the\n", file); - fputs (" fraction which divides up the function's time to\n", file); - fputs (" its parents.\n", file); - fputs ("\n", file); - fputs ("total* the number of times this function was called by\n", file); - fputs (" all of its parents. This is the denominator of\n", file); - fputs (" the propagation fraction.\n", file); - fputs ("\n", file); - fputs ("parents the name of this parent, with an indication of the\n", file); - fputs (" parent's membership in a cycle, if any.\n", file); - fputs ("\n", file); - fputs ("index the index of this parent in the call graph\n", file); - fputs (" listing, as an aid in locating it.\n", file); - fputs ("\n", file); - fputs ("\n", file); - fputs ("\n", file); - fputs (" children listings:\n", file); - fputs ("\n", file); - fputs ("self* the number of seconds of this child's self time\n", file); - fputs (" which is due to being called by this function.\n", file); - fputs ("\n", file); - fputs ("descendent*\n", file); - fputs (" the number of seconds of this child's descendent's\n", file); - fputs (" time which is due to being called by this\n", file); - fputs (" function.\n", file); - fputs ("\n", file); - fputs ("called** the number of times this child is called by this\n", file); - fputs (" function. This is the numerator of the\n", file); - fputs (" propagation fraction for this child.\n", file); - fputs ("\n", file); - fputs ("total* the number of times this child is called by all\n", file); - fputs (" functions. This is the denominator of the\n", file); - fputs (" propagation fraction.\n", file); - fputs ("\n", file); - fputs ("children the name of this child, and an indication of its\n", file); - fputs (" membership in a cycle, if any.\n", file); - fputs ("\n", file); - fputs ("index the index of this child in the call graph listing,\n", file); - fputs (" as an aid to locating it.\n", file); - fputs ("\n", file); - fputs ("\n", file); - fputs ("\n", file); - fputs (" * these fields are omitted for parents (or\n", file); - fputs (" children) in the same cycle as the function. If\n", file); - fputs (" the function (or child) is a member of a cycle,\n", file); - fputs (" the propagated times and propagation denominator\n", file); - fputs (" represent the self time and descendent time of the\n", file); - fputs (" cycle as a whole.\n", file); - fputs ("\n", file); - fputs (" ** static-only parents and children are indicated\n", file); - fputs (" by a call count of 0.\n", file); - fputs ("\n", file); - fputs ("\n", file); - fputs ("\n", file); - fputs (" cycle listings:\n", file); - fputs (" the cycle as a whole is listed with the same\n", file); - fputs (" fields as a function entry. Below it are listed\n", file); - fputs (" the members of the cycle, and their contributions\n", file); - fputs (" to the time and call counts of the cycle.\n", file); - fputs ("\n", file); -} diff --git a/gnu/usr.bin/binutils/gprof/cg_arcs.c b/gnu/usr.bin/binutils/gprof/cg_arcs.c index 8b6184b6bcc..b63102948b0 100644 --- a/gnu/usr.bin/binutils/gprof/cg_arcs.c +++ b/gnu/usr.bin/binutils/gprof/cg_arcs.c @@ -27,6 +27,8 @@ Sym *cycle_header; int num_cycles; +Arc **arcs; +int numarcs; /* * Return TRUE iff PARENT has an arc to covers the address @@ -65,7 +67,8 @@ void DEFUN (arc_add, (parent, child, count), Sym * parent AND Sym * child AND int count) { - Arc *arc; + static int maxarcs = 0; + Arc *arc, **newarcs; DBG (TALLYDEBUG, printf ("[arc_add] %d arcs from %s to %s\n", count, parent->name, child->name)); @@ -85,6 +88,37 @@ DEFUN (arc_add, (parent, child, count), arc->child = child; arc->count = count; + /* If this isn't an arc for a recursive call to parent, then add it + to the array of arcs. */ + if (parent != child) + { + /* If we've exhausted space in our current array, get a new one + and copy the contents. We might want to throttle the doubling + factor one day. */ + if (numarcs == maxarcs) + { + /* Determine how much space we want to allocate. */ + if (maxarcs == 0) + maxarcs = 1; + maxarcs *= 2; + + /* Allocate the new array. */ + newarcs = (Arc **)xmalloc(sizeof (Arc *) * maxarcs); + + /* Copy the old array's contents into the new array. */ + memcpy (newarcs, arcs, numarcs * sizeof (Arc *)); + + /* Free up the old array. */ + free (arcs); + + /* And make the new array be the current array. */ + arcs = newarcs; + } + + /* Place this arc in the arc array. */ + arcs[numarcs++] = arc; + } + /* prepend this child to the children of this parent: */ arc->next_child = parent->cg.children; parent->cg.children = arc; diff --git a/gnu/usr.bin/binutils/gprof/cg_arcs.h b/gnu/usr.bin/binutils/gprof/cg_arcs.h index 25d5b616737..132ee73667a 100644 --- a/gnu/usr.bin/binutils/gprof/cg_arcs.h +++ b/gnu/usr.bin/binutils/gprof/cg_arcs.h @@ -20,6 +20,7 @@ typedef struct arc double child_time; /* child-time inherited along arc */ struct arc *next_parent; /* next parent of CHILD */ struct arc *next_child; /* next child of PARENT */ + int has_been_placed; /* have this arc's functions been placed? */ } Arc; @@ -29,5 +30,7 @@ extern Sym *cycle_header; /* cycle headers */ extern void arc_add PARAMS ((Sym * parent, Sym * child, int count)); extern Arc *arc_lookup PARAMS ((Sym * parent, Sym * child)); extern Sym **cg_assemble PARAMS ((void)); +extern Arc **arcs; +extern int numarcs; #endif /* cg_arcs_h */ diff --git a/gnu/usr.bin/binutils/gprof/cg_print.c b/gnu/usr.bin/binutils/gprof/cg_print.c index 460bc045c47..015f710ce32 100644 --- a/gnu/usr.bin/binutils/gprof/cg_print.c +++ b/gnu/usr.bin/binutils/gprof/cg_print.c @@ -11,6 +11,9 @@ #define EQUALTO 0 #define GREATERTHAN 1 +static void order_and_dump_functions_by_arcs PARAMS ((Arc **, unsigned long, + int, Arc **, + unsigned long *)); /* declarations of automatically generated functions to output blurbs: */ extern void bsd_callg_blurb PARAMS ((FILE * fp)); extern void fsf_callg_blurb PARAMS ((FILE * fp)); @@ -654,3 +657,616 @@ DEFUN_VOID (cg_print_index) } free (name_sorted_syms); } + +/* Compare two arcs based on their usage counts. We want to sort + in descending order. */ +static int +DEFUN (cmp_arc_count, (left, right), const PTR left AND const PTR right) +{ + const Arc **npp1 = (const Arc **) left; + const Arc **npp2 = (const Arc **) right; + + if ((*npp1)->count > (*npp2)->count) + return -1; + else if ((*npp1)->count < (*npp2)->count) + return 1; + else + return 0; +} + +/* Compare two funtions based on their usage counts. We want to sort + in descending order. */ +static int +DEFUN (cmp_fun_nuses, (left, right), const PTR left AND const PTR right) +{ + const Sym **npp1 = (const Sym **) left; + const Sym **npp2 = (const Sym **) right; + + if ((*npp1)->nuses > (*npp2)->nuses) + return -1; + else if ((*npp1)->nuses < (*npp2)->nuses) + return 1; + else + return 0; +} + +/* Print a suggested function ordering based on the profiling data. + + We perform 4 major steps when ordering functions: + + * Group unused functions together and place them at the + end of the function order. + + * Search the highest use arcs (those which account for 90% of + the total arc count) for functions which have several parents. + + Group those with the most call sites together (currently the + top 1.25% which have at least five different call sites). + + These are emitted at the start of the function order. + + * Use a greedy placement algorithm to place functions which + occur in the top 99% of the arcs in the profile. Some provisions + are made to handle high usage arcs where the parent and/or + child has already been placed. + + * Run the same greedy placement algorithm on the remaining + arcs to place the leftover functions. + + + The various "magic numbers" should (one day) be tuneable by command + line options. They were arrived at by benchmarking a few applications + with various values to see which values produced better overall function + orderings. + + Of course, profiling errors, machine limitations (PA long calls), and + poor cutoff values for the placement algorithm may limit the usefullness + of the resulting function order. Improvements would be greatly appreciated. + + Suggestions: + + * Place the functions with many callers near the middle of the + list to reduce long calls. + + * Propagate arc usage changes as functions are placed. Ie if + func1 and func2 are placed together, arcs to/from those arcs + to the same parent/child should be combined, then resort the + arcs to choose the next one. + + * Implement some global positioning algorithm to place the + chains made by the greedy local positioning algorithm. Probably + by examining arcs which haven't been placed yet to tie two + chains together. + + * Take a function's size and time into account in the algorithm; + size in particular is important on the PA (long calls). Placing + many small functions onto their own page may be wise. + + * Use better profiling information; many published algorithms + are based on call sequences through time, rather than just + arc counts. + + * Prodecure cloning could improve performance when a small number + of arcs account for most of the calls to a particular function. + + * Use relocation information to avoid moving unused functions + completely out of the code stream; this would avoid severe lossage + when the profile data bears little resemblance to actual runs. + + * Propagation of arc usages should also improve .o link line + ordering which shares the same arc placement algorithm with + the function ordering code (in fact it is a degenerate case + of function ordering). */ + +void +DEFUN_VOID (cg_print_function_ordering) +{ + unsigned long index, used, unused, scratch_index; + unsigned long unplaced_arc_count, high_arc_count, scratch_arc_count; +#ifdef __GNUC__ + unsigned long long total_arcs, tmp_arcs_count; +#else + unsigned long total_arcs, tmp_arcs_count; +#endif + Sym **unused_syms, **used_syms, **scratch_syms; + Arc **unplaced_arcs, **high_arcs, **scratch_arcs; + + index = 0; + used = 0; + unused = 0; + scratch_index = 0; + unplaced_arc_count = 0; + high_arc_count = 0; + scratch_arc_count = 0; + + /* First group all the unused functions together. */ + unused_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *)); + used_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *)); + scratch_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *)); + high_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *)); + scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *)); + unplaced_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *)); + + /* Walk through all the functions; mark those which are never + called as placed (we'll emit them as a group later). */ + for (index = 0, used = 0, unused = 0; index < symtab.len; index++) + { + if (symtab.base[index].ncalls == 0) + { + /* Filter out gprof generated names. */ + if (strcmp (symtab.base[index].name, "<locore>") + && strcmp (symtab.base[index].name, "<hicore>")) + { + unused_syms[unused++] = &symtab.base[index]; + symtab.base[index].has_been_placed = 1; + } + } + else + { + used_syms[used++] = &symtab.base[index]; + symtab.base[index].has_been_placed = 0; + symtab.base[index].next = 0; + symtab.base[index].prev = 0; + symtab.base[index].nuses = 0; + } + } + + /* Sort the arcs from most used to least used. */ + qsort (arcs, numarcs, sizeof (Arc *), cmp_arc_count); + + /* Compute the total arc count. Also mark arcs as unplaced. + + Note we don't compensate for overflow if that happens! + Overflow is much less likely when this file is compiled + with GCC as it can double-wide integers via long long. */ + total_arcs = 0; + for (index = 0; index < numarcs; index++) + { + total_arcs += arcs[index]->count; + arcs[index]->has_been_placed = 0; + } + + /* We want to pull out those functions which are referenced + by many highly used arcs and emit them as a group. This + could probably use some tuning. */ + tmp_arcs_count = 0; + for (index = 0; index < numarcs; index++) + { + tmp_arcs_count += arcs[index]->count; + + /* Count how many times each parent and child are used up + to our threshhold of arcs (90%). */ + if ((double)tmp_arcs_count / (double)total_arcs > 0.90) + break; + + arcs[index]->child->nuses++; + } + + /* Now sort a temporary symbol table based on the number of + times each function was used in the highest used arcs. */ + memcpy (scratch_syms, used_syms, used * sizeof (Sym *)); + qsort (scratch_syms, used, sizeof (Sym *), cmp_fun_nuses); + + /* Now pick out those symbols we're going to emit as + a group. We take up to 1.25% of the used symbols. */ + for (index = 0; index < used / 80; index++) + { + Sym *sym = scratch_syms[index]; + Arc *arc; + + /* If we hit symbols that aren't used from many call sites, + then we can quit. We choose five as the low limit for + no particular reason. */ + if (sym->nuses == 5) + break; + + /* We're going to need the arcs between these functions. + Unfortunately, we don't know all these functions + until we're done. So we keep track of all the arcs + to the functions we care about, then prune out those + which are uninteresting. + + An interesting variation would be to quit when we found + multi-call site functions which account for some percentage + of the arcs. */ + + arc = sym->cg.children; + while (arc) + { + if (arc->parent != arc->child) + scratch_arcs[scratch_arc_count++] = arc; + arc->has_been_placed = 1; + arc = arc->next_child; + } + + arc = sym->cg.parents; + while (arc) + { + if (arc->parent != arc->child) + scratch_arcs[scratch_arc_count++] = arc; + arc->has_been_placed = 1; + arc = arc->next_parent; + } + + /* Keep track of how many symbols we're going to place. */ + scratch_index = index; + + /* A lie, but it makes identifying these functions easier + later. */ + sym->has_been_placed = 1; + } + + /* Now walk through the temporary arcs and copy those we care about + into the high arcs array. */ + for (index = 0; index < scratch_arc_count; index++) + { + Arc *arc = scratch_arcs[index]; + + /* If this arc refers to highly used functions, then + then we want to keep it. */ + if (arc->child->has_been_placed + && arc->parent->has_been_placed) + { + high_arcs[high_arc_count++] = scratch_arcs[index]; + + /* We need to turn of has_been_placed since we're going to + use the main arc placement algorithm on these arcs. */ + arc->child->has_been_placed = 0; + arc->parent->has_been_placed = 0; + } + } + + /* Dump the multi-site high usage functions which are not going + to be ordered by the main ordering algorithm. */ + for (index = 0; index < scratch_index; index++) + { + if (scratch_syms[index]->has_been_placed) + printf ("%s\n", scratch_syms[index]->name); + } + + /* Now we can order the multi-site high use functions based on the + arcs between them. */ + qsort (high_arcs, high_arc_count, sizeof (Arc *), cmp_arc_count); + order_and_dump_functions_by_arcs (high_arcs, high_arc_count, 1, + unplaced_arcs, &unplaced_arc_count); + + /* Order and dump the high use functions left, these typically + have only a few call sites. */ + order_and_dump_functions_by_arcs (arcs, numarcs, 0, + unplaced_arcs, &unplaced_arc_count); + + /* Now place the rarely used functions. */ + order_and_dump_functions_by_arcs (unplaced_arcs, unplaced_arc_count, 1, + scratch_arcs, &scratch_arc_count); + + /* Output any functions not emitted by the order_and_dump calls. */ + for (index = 0; index < used; index++) + if (used_syms[index]->has_been_placed == 0) + printf("%s\n", used_syms[index]->name); + + /* Output the unused functions. */ + for (index = 0; index < unused; index++) + printf("%s\n", unused_syms[index]->name); + + unused_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *)); + used_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *)); + scratch_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *)); + high_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *)); + scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *)); + unplaced_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *)); + + free (unused_syms); + free (used_syms); + free (scratch_syms); + free (high_arcs); + free (scratch_arcs); + free (unplaced_arcs); +} + +/* Place functions based on the arcs in ARCS with NUMARCS entries; + place unused arcs into UNPLACED_ARCS/UNPLACED_ARC_COUNT. + + If ALL is nonzero, then place all functions referenced by ARCS, + else only place those referenced in the top 99% of the arcs in ARCS. */ + +#define MOST 0.99 +static void +order_and_dump_functions_by_arcs (arcs, numarcs, all, + unplaced_arcs, unplaced_arc_count) + Arc **arcs; + unsigned long numarcs; + int all; + Arc **unplaced_arcs; + unsigned long *unplaced_arc_count; +{ +#ifdef __GNUC__ + unsigned long long tmp_arcs, total_arcs; +#else + unsigned long tmp_arcs, total_arcs; +#endif + unsigned int index; + + /* If needed, compute the total arc count. + + Note we don't compensate for overflow if that happens! */ + if (! all) + { + total_arcs = 0; + for (index = 0; index < numarcs; index++) + total_arcs += arcs[index]->count; + } + else + total_arcs = 0; + + tmp_arcs = 0; + for (index = 0; index < numarcs; index++) + { + Sym *sym1, *sym2; + Sym *child, *parent; + + tmp_arcs += arcs[index]->count; + + /* Ignore this arc if it's already been placed. */ + if (arcs[index]->has_been_placed) + continue; + + child = arcs[index]->child; + parent = arcs[index]->parent; + + /* If we're not using all arcs, and this is a rarely used + arc, then put it on the unplaced_arc list. Similarly + if both the parent and child of this arc have been placed. */ + if ((! all && (double)tmp_arcs / (double)total_arcs > MOST) + || child->has_been_placed || parent->has_been_placed) + { + unplaced_arcs[(*unplaced_arc_count)++] = arcs[index]; + continue; + } + + /* If all slots in the parent and child are full, then there isn't + anything we can do right now. We'll place this arc on the + unplaced arc list in the hope that a global positioning + algorithm can use it to place function chains. */ + if (parent->next && parent->prev && child->next && child->prev) + { + unplaced_arcs[(*unplaced_arc_count)++] = arcs[index]; + continue; + } + + /* If the parent is unattached, then find the closest + place to attach it onto child's chain. Similarly + for the opposite case. */ + if (!parent->next && !parent->prev) + { + int next_count = 0; + int prev_count = 0; + Sym *prev = child; + Sym *next = child; + + /* Walk to the beginning and end of the child's chain. */ + while (next->next) + { + next = next->next; + next_count++; + } + + while (prev->prev) + { + prev = prev->prev; + prev_count++; + } + + /* Choose the closest. */ + child = next_count < prev_count ? next : prev; + } + else if (! child->next && !child->prev) + { + int next_count = 0; + int prev_count = 0; + Sym *prev = parent; + Sym *next = parent; + + while (next->next) + { + next = next->next; + next_count++; + } + + while (prev->prev) + { + prev = prev->prev; + prev_count++; + } + + parent = prev_count < next_count ? prev : next; + } + else + { + /* Couldn't find anywhere to attach the functions, + put the arc on the unplaced arc list. */ + unplaced_arcs[(*unplaced_arc_count)++] = arcs[index]; + continue; + } + + /* Make sure we don't tie two ends together. */ + sym1 = parent; + if (sym1->next) + while (sym1->next) + sym1 = sym1->next; + else + while (sym1->prev) + sym1 = sym1->prev; + + sym2 = child; + if (sym2->next) + while (sym2->next) + sym2 = sym2->next; + else + while (sym2->prev) + sym2 = sym2->prev; + + if (sym1 == child + && sym2 == parent) + { + /* This would tie two ends together. */ + unplaced_arcs[(*unplaced_arc_count)++] = arcs[index]; + continue; + } + + if (parent->next) + { + /* Must attach to the parent's prev field. */ + if (! child->next) + { + /* parent-prev and child-next */ + parent->prev = child; + child->next = parent; + arcs[index]->has_been_placed = 1; + } + } + else if (parent->prev) + { + /* Must attach to the parent's next field. */ + if (! child->prev) + { + /* parent-next and child-prev */ + parent->next = child; + child->prev = parent; + arcs[index]->has_been_placed = 1; + } + } + else + { + /* Can attach to either field in the parent, depends + on where we've got space in the child. */ + if (child->prev) + { + /* parent-prev and child-next */ + parent->prev = child; + child->next = parent; + arcs[index]->has_been_placed = 1; + } + else + { + /* parent-next and child-prev */ + parent->next = child; + child->prev = parent; + arcs[index]->has_been_placed = 1; + } + } + } + + /* Dump the chains of functions we've made. */ + for (index = 0; index < numarcs; index++) + { + Sym *sym; + if (arcs[index]->parent->has_been_placed + || arcs[index]->child->has_been_placed) + continue; + + sym = arcs[index]->parent; + + /* If this symbol isn't attached to any other + symbols, then we've got a rarely used arc. + + Skip it for now, we'll deal with them later. */ + if (sym->next == NULL + && sym->prev == NULL) + continue; + + /* Get to the start of this chain. */ + while (sym->prev) + sym = sym->prev; + + while (sym) + { + /* Mark it as placed. */ + sym->has_been_placed = 1; + printf ("%s\n", sym->name); + sym = sym->next; + } + } + + /* If we want to place all the arcs, then output those which weren't + placed by the main algorithm. */ + if (all) + for (index = 0; index < numarcs; index++) + { + Sym *sym; + if (arcs[index]->parent->has_been_placed + || arcs[index]->child->has_been_placed) + continue; + + sym = arcs[index]->parent; + + sym->has_been_placed = 1; + printf ("%s\n", sym->name); + } +} + +/* Print a suggested .o ordering for files on a link line based + on profiling information. This uses the function placement + code for the bulk of its work. */ + +struct function_map { + char *function_name; + char *file_name; +}; + +void +DEFUN_VOID (cg_print_file_ordering) +{ + unsigned long scratch_arc_count, index; + Arc **scratch_arcs; + extern struct function_map *symbol_map; + extern int symbol_map_count; + char *last; + + scratch_arc_count = 0; + + scratch_arcs = (Arc **) xmalloc (numarcs * sizeof (Arc *)); + for (index = 0; index < numarcs; index++) + { + if (! arcs[index]->parent->mapped + || ! arcs[index]->child->mapped) + arcs[index]->has_been_placed = 1; + } + + order_and_dump_functions_by_arcs (arcs, numarcs, 0, + scratch_arcs, &scratch_arc_count); + + /* Output .o's not handled by the main placement algorithm. */ + for (index = 0; index < symtab.len; index++) + { + if (symtab.base[index].mapped + && ! symtab.base[index].has_been_placed) + printf ("%s\n", symtab.base[index].name); + } + + /* Now output any .o's that didn't have any text symbols. */ + last = NULL; + for (index = 0; index < symbol_map_count; index++) + { + int index2; + + /* Don't bother searching if this symbol is the + same as the previous one. */ + if (last && !strcmp (last, symbol_map[index].file_name)) + continue; + + for (index2 = 0; index2 < symtab.len; index2++) + { + if (! symtab.base[index2].mapped) + continue; + + if (!strcmp (symtab.base[index2].name, symbol_map[index].file_name)) + break; + } + + /* If we didn't find it in the symbol table, then it must be a .o + with no text symbols. Output it last. */ + if (index2 == symtab.len) + printf ("%s\n", symbol_map[index].file_name); + last = symbol_map[index].file_name; + } +} diff --git a/gnu/usr.bin/binutils/gprof/cg_print.h b/gnu/usr.bin/binutils/gprof/cg_print.h index 13511c728a0..782c4aa04c2 100644 --- a/gnu/usr.bin/binutils/gprof/cg_print.h +++ b/gnu/usr.bin/binutils/gprof/cg_print.h @@ -8,5 +8,7 @@ extern double print_time; /* total of time being printed */ extern void cg_print PARAMS ((Sym ** cg)); extern void cg_print_index PARAMS ((void)); +extern void cg_print_file_ordering PARAMS ((void)); +extern void cg_print_function_ordering PARAMS ((void)); #endif /* cg_print_h */ diff --git a/gnu/usr.bin/binutils/gprof/configure b/gnu/usr.bin/binutils/gprof/configure index 2408cbd8f26..282bbe2ebbd 100644 --- a/gnu/usr.bin/binutils/gprof/configure +++ b/gnu/usr.bin/binutils/gprof/configure @@ -1,7 +1,7 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated automatically using autoconf version 2.4 +# Generated automatically using autoconf version 2.8 # Copyright (C) 1992, 1993, 1994 Free Software Foundation, Inc. # # This configure script is free software; the Free Software Foundation @@ -11,6 +11,8 @@ ac_help= ac_default_prefix=/usr/local # Any additions from configure.in: +ac_help="$ac_help + --enable-shared build shared BFD library" # Initialize some variables set by options. # The variables have the same names as the options, with @@ -33,9 +35,22 @@ target=NONE verbose= x_includes=NONE x_libraries=NONE +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' # Initialize some other variables. subdirs= +MFLAGS= MAKEFLAGS= ac_prev= for ac_option @@ -57,9 +72,14 @@ do case "$ac_option" in - -build | --build | --buil | --bui | --bu | --b) + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir="$ac_optarg" ;; + + -build | --build | --buil | --bui | --bu) ac_prev=build ;; - -build=* | --build=* | --buil=* | --bui=* | --bu=* | --b=*) + -build=* | --build=* | --buil=* | --bui=* | --bu=*) build="$ac_optarg" ;; -cache-file | --cache-file | --cache-fil | --cache-fi \ @@ -69,6 +89,12 @@ do | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) cache_file="$ac_optarg" ;; + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir="$ac_optarg" ;; + -disable-* | --disable-*) ac_feature=`echo $ac_option|sed -e 's/-*disable-//'` # Reject names that are not valid shell variable names. @@ -119,12 +145,29 @@ Configuration: Directory and file names: --prefix=PREFIX install architecture-independent files in PREFIX [$ac_default_prefix] - --exec-prefix=PREFIX install architecture-dependent files in PREFIX + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX [same as prefix] + --bindir=DIR user executables in DIR [EPREFIX/bin] + --sbindir=DIR system admin executables in DIR [EPREFIX/sbin] + --libexecdir=DIR program executables in DIR [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data in DIR + [PREFIX/share] + --sysconfdir=DIR read-only single-machine data in DIR [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data in DIR + [PREFIX/com] + --localstatedir=DIR modifiable single-machine data in DIR [PREFIX/var] + --libdir=DIR object code libraries in DIR [EPREFIX/lib] + --includedir=DIR C header files in DIR [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc in DIR [/usr/include] + --infodir=DIR info documentation in DIR [PREFIX/info] + --mandir=DIR man documentation in DIR [PREFIX/man] --srcdir=DIR find the sources in DIR [configure dir or ..] --program-prefix=PREFIX prepend PREFIX to installed program names --program-suffix=SUFFIX append SUFFIX to installed program names - --program-transform-name=PROGRAM run sed PROGRAM on installed program names + --program-transform-name=PROGRAM + run sed PROGRAM on installed program names +EOF + cat << EOF Host type: --build=BUILD configure for building on BUILD [BUILD=HOST] --host=HOST configure for HOST [guessed] @@ -136,8 +179,10 @@ Features and packages: --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) --x-includes=DIR X include files are in DIR --x-libraries=DIR X library files are in DIR ---enable and --with options recognized:$ac_help EOF + if test -n "$ac_help"; then + echo "--enable and --with options recognized:$ac_help" + fi exit 0 ;; -host | --host | --hos | --ho) @@ -145,6 +190,44 @@ EOF -host=* | --host=* | --hos=* | --ho=*) host="$ac_optarg" ;; + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir="$ac_optarg" ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir="$ac_optarg" ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir="$ac_optarg" ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir="$ac_optarg" ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir="$ac_optarg" ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir="$ac_optarg" ;; + -nfp | --nfp | --nf) # Obsolete; use --without-fp. with_fp=no ;; @@ -157,6 +240,15 @@ EOF | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) no_recursion=yes ;; + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir="$ac_optarg" ;; + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) ac_prev=prefix ;; -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) @@ -197,6 +289,23 @@ EOF | -silent | --silent | --silen | --sile | --sil) silent=yes ;; + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir="$ac_optarg" ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir="$ac_optarg" ;; + -site | --site | --sit) ac_prev=site ;; -site=* | --site=* | --sit=*) @@ -207,6 +316,13 @@ EOF -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) srcdir="$ac_optarg" ;; + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir="$ac_optarg" ;; + -target | --target | --targe | --targ | --tar | --ta | --t) ac_prev=target ;; -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) @@ -216,7 +332,7 @@ EOF verbose=yes ;; -version | --version | --versio | --versi | --vers) - echo "configure generated by autoconf version 2.4" + echo "configure generated by autoconf version 2.8" exit 0 ;; -with-* | --with-*) @@ -262,7 +378,7 @@ EOF -*) { echo "configure: error: $ac_option: invalid option; use --help to show usage" 1>&2; exit 1; } ;; - *) + *) if test -n "`echo $ac_option| sed 's/[-a-z0-9.]//g'`"; then echo "configure: warning: $ac_option: invalid host type" 1>&2 fi @@ -382,8 +498,8 @@ fi ac_ext=c # CFLAGS is not in ac_cpp because -g, -O, etc. are not valid cpp options. ac_cpp='$CPP $CPPFLAGS' -ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5 2>&5' -ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5 2>&5' +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. @@ -399,7 +515,17 @@ fi -CC=${CC-cc} +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + case "${enableval}" in + yes) shared=true ;; + no) shared=false ;; + *bfd*) shared=true ;; + *) shared=false ;; +esac +fi + # Extract the first word of "gcc", so it can be a program name with args. set dummy gcc; ac_word=$2 echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 @@ -418,7 +544,6 @@ else fi done IFS="$ac_save_ifs" - test -z "$ac_cv_prog_CC" && ac_cv_prog_CC="cc" fi fi CC="$ac_cv_prog_CC" @@ -428,6 +553,55 @@ else echo "$ac_t""no" 1>&6 fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo $ac_n "checking for $ac_word""... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_prog_CC'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}:" + ac_prog_rejected=no + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$ac_word; then + if test "$ac_dir/$ac_word" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + break + fi + done + IFS="$ac_save_ifs" +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + set dummy "$ac_dir/$ac_word" "$@" + shift + ac_cv_prog_CC="$@" + fi +fi +fi +fi +CC="$ac_cv_prog_CC" +if test -n "$CC"; then + echo "$ac_t""$CC" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi + + test -z "$CC" && { echo "configure: error: no acceptable cc found in \$PATH" 1>&2; exit 1; } +fi echo $ac_n "checking whether we are using GNU C""... $ac_c" 1>&6 if eval "test \"`echo '$''{'ac_cv_prog_gcc'+set}'`\" = set"; then @@ -438,12 +612,13 @@ else yes; #endif EOF -if ${CC-cc} -E conftest.c 2>&5 | egrep yes >/dev/null 2>&1; then +if { ac_try='${CC-cc} -E conftest.c'; { (eval echo configure:616: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then ac_cv_prog_gcc=yes else ac_cv_prog_gcc=no fi fi + echo "$ac_t""$ac_cv_prog_gcc" 1>&6 if test $ac_cv_prog_gcc = yes; then GCC=yes @@ -461,7 +636,8 @@ fi rm -f conftest* fi - echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6 + +echo "$ac_t""$ac_cv_prog_gcc_g" 1>&6 if test $ac_cv_prog_gcc_g = yes; then CFLAGS="-g -O" else @@ -500,7 +676,7 @@ ac_configure=$ac_aux_dir/configure # This should be Cygnus configure. # # The rules are: # 1. You are not allowed to specify --host, --target, and nonopt at the -# same time. +# same time. # 2. Host defaults to nonopt. # 3. If nonopt is not specified, then host defaults to the current host, # as determined by config.guess. @@ -582,8 +758,10 @@ test "$host_alias" != "$target_alias" && if test "$program_transform_name" = s,x,x,; then program_transform_name= else - # Double any \ or $. - echo 's,\\,\\\\,g; s,\$,$$,g' > conftestsed + # Double any \ or $. echo might interpret backslashes. + cat <<\EOF_SED > conftestsed +s,\\,\\\\,g; s,\$,$$,g +EOF_SED program_transform_name="`echo $program_transform_name|sed -f conftestsed`" rm -f conftestsed fi @@ -603,11 +781,70 @@ i[345]86-*-*) MY_TARGET=i386 ;; sparc-*-*) MY_TARGET=sparc ;; tahoe-*-*) MY_TARGET=tahoe ;; vax-*-*) MY_TARGET=vax ;; -ns32k-*-*|*-pc532-*) MY_TARGET=ns532;; +ns32k-*-*) MY_TARGET=ns532;; *-*-*) MY_TARGET=dummy ;; esac + +BFDLIB='-L../bfd -lbfd' + +# We need to handle some special cases if BFD was built shared. +if test "${shared}" = "true"; then + case "${host}" in + *-*-sunos*) + # On SunOS, we must link against the name we are going to install, + # not -lbfd, since SunOS does not support SONAME. + BFDLIB='-L../bfd -l`echo bfd | sed '"'"'$(program_transform_name)'"'"'`' + ;; + esac +fi + + +HLDFLAGS= +# If we have shared libraries, try to set rpath reasonably. +if test "${shared}" = "true"; then + case "${host}" in + *-*-hpux*) + HLDFLAGS='-Wl,+s,+b,$(libdir)' + ;; + *-*-irix5*) + HLDFLAGS='-Wl,-rpath,$(libdir)' + ;; + *-*-linux*aout*) + ;; + *-*-linux*) + HLDFLAGS='-Wl,-rpath,$(libdir)' + ;; + *-*-sysv4* | *-*-solaris*) + HLDFLAGS='-R $(libdir)' + ;; + esac +fi + +# On SunOS, if the linker supports the -rpath option, use it to +# prevent ../bfd and ../opcodes from being included in the run time +# search path. +case "${host}" in + *-*-sunos*) + echo 'main () { }' > conftest.c + ${CC} -o conftest -Wl,-rpath= conftest.c >/dev/null 2>conftest.t + if grep 'unrecognized' conftest.t >/dev/null 2>&1; then + : + elif grep 'No such file' conftest.t >/dev/null 2>&1; then + : + elif grep 'do not mix' conftest.t >/dev/null 2>&1; then + : + elif test "${shared}" = "true"; then + HLDFLAGS='-Wl,-rpath=$(libdir)' + else + HLDFLAGS='-Wl,-rpath=' + fi + rm -f conftest.t conftest.c conftest + ;; +esac + + trap '' 1 2 15 cat > confcache <<\EOF # This file is a shell script that caches the results of configure @@ -661,7 +898,7 @@ trap 'rm -f $CONFIG_STATUS conftest*; exit 1' 1 2 15 # Protect against shell expansion while executing Makefile rules. # Protect against Makefile macro expansion. cat > conftest.defs <<\EOF -s%#define \([A-Za-z_][A-Za-z0-9_]*\) \(.*\)%-D\1=\2%g +s%#define \([A-Za-z_][A-Za-z0-9_]*\) *\(.*\)%-D\1=\2%g s%[ `~#$^&*(){}\\|;'"<>?]%\\&%g s%\[%\\&%g s%\]%\\&%g @@ -696,7 +933,7 @@ do echo "running \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion" exec \${CONFIG_SHELL-/bin/sh} $0 $ac_configure_args --no-create --no-recursion ;; -version | --version | --versio | --versi | --vers | --ver | --ve | --v) - echo "$CONFIG_STATUS generated by autoconf version 2.4" + echo "$CONFIG_STATUS generated by autoconf version 2.8" exit 0 ;; -help | --help | --hel | --he | --h) echo "\$ac_cs_usage"; exit 0 ;; @@ -707,10 +944,12 @@ done ac_given_srcdir=$srcdir trap 'rm -fr `echo "Makefile" | sed "s/:[^ ]*//g"` conftest*; exit 1' 1 2 15 +EOF +cat >> $CONFIG_STATUS <<EOF -# Protect against being on the right side of a sed subst in config.status. -sed 's/%@/@@/; s/@%/@@/; s/%g$/@g/; /@g$/s/[\\\\&%]/\\\\&/g; - s/@@/%@/; s/@@/@%/; s/@g$/%g/' > conftest.subs <<\CEOF +# Protect against being on the right side of a sed subst in config.status. +sed 's/%@/@@/; s/@%/@@/; s/%g\$/@g/; /@g\$/s/[\\\\&%]/\\\\&/g; + s/@@/%@/; s/@@/@%/; s/@g\$/%g/' > conftest.subs <<\\CEOF $ac_vpsub $extrasub s%@CFLAGS@%$CFLAGS%g @@ -722,6 +961,18 @@ s%@LIBS@%$LIBS%g s%@exec_prefix@%$exec_prefix%g s%@prefix@%$prefix%g s%@program_transform_name@%$program_transform_name%g +s%@bindir@%$bindir%g +s%@sbindir@%$sbindir%g +s%@libexecdir@%$libexecdir%g +s%@datadir@%$datadir%g +s%@sysconfdir@%$sysconfdir%g +s%@sharedstatedir@%$sharedstatedir%g +s%@localstatedir@%$localstatedir%g +s%@libdir@%$libdir%g +s%@includedir@%$includedir%g +s%@oldincludedir@%$oldincludedir%g +s%@infodir@%$infodir%g +s%@mandir@%$mandir%g s%@CC@%$CC%g s%@host@%$host%g s%@host_alias@%$host_alias%g @@ -739,6 +990,8 @@ s%@build_cpu@%$build_cpu%g s%@build_vendor@%$build_vendor%g s%@build_os@%$build_os%g s%@MY_TARGET@%$MY_TARGET%g +s%@BFDLIB@%$BFDLIB%g +s%@HLDFLAGS@%$HLDFLAGS%g CEOF EOF diff --git a/gnu/usr.bin/binutils/gprof/configure.in b/gnu/usr.bin/binutils/gprof/configure.in index 7849a858962..4b0a616b59a 100644 --- a/gnu/usr.bin/binutils/gprof/configure.in +++ b/gnu/usr.bin/binutils/gprof/configure.in @@ -2,7 +2,15 @@ dnl Process this file with autoconf to produce a configure script. AC_PREREQ(2.3)dnl AC_INIT(gprof.c) -CC=${CC-cc} +AC_ARG_ENABLE(shared, +[ --enable-shared build shared BFD library], +[case "${enableval}" in + yes) shared=true ;; + no) shared=false ;; + *bfd*) shared=true ;; + *) shared=false ;; +esac])dnl + AC_PROG_CC AC_CANONICAL_SYSTEM @@ -21,4 +29,63 @@ ns32k-*-*) MY_TARGET=ns532;; esac AC_SUBST(MY_TARGET) + +BFDLIB='-L../bfd -lbfd' + +# We need to handle some special cases if BFD was built shared. +if test "${shared}" = "true"; then + case "${host}" in + *-*-sunos*) + # On SunOS, we must link against the name we are going to install, + # not -lbfd, since SunOS does not support SONAME. + BFDLIB='-L../bfd -l`echo bfd | sed '"'"'$(program_transform_name)'"'"'`' + ;; + esac +fi +AC_SUBST(BFDLIB) + +HLDFLAGS= +# If we have shared libraries, try to set rpath reasonably. +if test "${shared}" = "true"; then + case "${host}" in + *-*-hpux*) + HLDFLAGS='-Wl,+s,+b,$(libdir)' + ;; + *-*-irix5*) + HLDFLAGS='-Wl,-rpath,$(libdir)' + ;; + *-*-linux*aout*) + ;; + *-*-linux*) + HLDFLAGS='-Wl,-rpath,$(libdir)' + ;; + *-*-sysv4* | *-*-solaris*) + HLDFLAGS='-R $(libdir)' + ;; + esac +fi + +# On SunOS, if the linker supports the -rpath option, use it to +# prevent ../bfd and ../opcodes from being included in the run time +# search path. +case "${host}" in + *-*-sunos*) + echo 'main () { }' > conftest.c + ${CC} -o conftest -Wl,-rpath= conftest.c >/dev/null 2>conftest.t + if grep 'unrecognized' conftest.t >/dev/null 2>&1; then + : + elif grep 'No such file' conftest.t >/dev/null 2>&1; then + : + elif grep 'do not mix' conftest.t >/dev/null 2>&1; then + : + elif test "${shared}" = "true"; then + HLDFLAGS='-Wl,-rpath=$(libdir)' + else + HLDFLAGS='-Wl,-rpath=' + fi + rm -f conftest.t conftest.c conftest + ;; +esac +AC_SUBST(HLDFLAGS) + AC_OUTPUT(Makefile) diff --git a/gnu/usr.bin/binutils/gprof/core.c b/gnu/usr.bin/binutils/gprof/core.c index 19c6e590f99..3117599eba0 100644 --- a/gnu/usr.bin/binutils/gprof/core.c +++ b/gnu/usr.bin/binutils/gprof/core.c @@ -3,12 +3,111 @@ #include "core.h" #include "symtab.h" +#ifndef MIN_INSN_SIZE +/* If not defined in MACHINE_H, assume smallest instruction is 1 byte + long. THis is safe but may be needlessly slow on machines where + all instructions are longer. */ +#define MIN_INSN_SIZE 1 +#endif + bfd *core_bfd; int core_num_syms; asymbol **core_syms; asection *core_text_sect; PTR core_text_space; +/* For mapping symbols to specific .o files during file ordering. */ +struct function_map { + char *function_name; + char *file_name; +}; + +struct function_map *symbol_map; +int symbol_map_count; + +static void +DEFUN (read_function_mappings, (filename), const char *filename) +{ + FILE *file = fopen (filename, "r"); + char dummy[1024]; + int count = 0; + + if (!file) + { + fprintf (stderr, "%s: could not open %s.\n", whoami, filename); + done (1); + } + + /* First parse the mapping file so we know how big we need to + make our tables. We also do some sanity checks at this + time. */ + while (!feof (file)) + { + int matches; + + matches = fscanf (file, "%[^\n:]", dummy); + if (!matches) + { + fprintf (stderr, "%s: unable to parse mapping file %s.\n", + whoami, filename); + done (1); + } + + /* Just skip messages about files with no symbols. */ + if (!strncmp (dummy, "No symbols in ", 14)) + { + fscanf (file, "\n"); + continue; + } + + /* Don't care what else is on this line at this point. */ + fscanf (file, "%[^\n]\n", dummy); + count++; + } + + /* Now we know how big we need to make our table. */ + symbol_map = xmalloc (count * sizeof (struct function_map)); + + /* Rewind the input file so we can read it again. */ + rewind (file); + + /* Read each entry and put it into the table. */ + count = 0; + while (!feof (file)) + { + int matches; + char *tmp; + + matches = fscanf (file, "%[^\n:]", dummy); + if (!matches) + { + fprintf (stderr, "%s: unable to parse mapping file %s.\n", + whoami, filename); + done (1); + } + + /* Just skip messages about files with no symbols. */ + if (!strncmp (dummy, "No symbols in ", 14)) + { + fscanf (file, "\n"); + continue; + } + + /* dummy has the filename, go ahead and copy it. */ + symbol_map[count].file_name = xmalloc (strlen (dummy) + 1); + strcpy (symbol_map[count].file_name, dummy); + + /* Now we need the function name. */ + fscanf (file, "%[^\n]\n", dummy); + tmp = strrchr (dummy, ' ') + 1; + symbol_map[count].function_name = xmalloc (strlen (tmp) + 1); + strcpy (symbol_map[count].function_name, tmp); + count++; + } + + /* Record the size of the map table for future reference. */ + symbol_map_count = count; +} void DEFUN (core_init, (a_out_name), const char *a_out_name) @@ -59,6 +158,9 @@ DEFUN (core_init, (a_out_name), const char *a_out_name) bfd_errmsg (bfd_get_error ())); done (1); } + + if (function_mapping_file) + read_function_mappings (function_mapping_file); } @@ -104,15 +206,15 @@ DEFUN (core_sym_class, (sym), asymbol * sym) char sym_prefix; int i; - /* - * Must be a text symbol, and static text symbols don't qualify if - * ignore_static_funcs set. - */ - if (!sym->section) + if (sym->section == NULL || (sym->flags & BSF_DEBUGGING) != 0) { return 0; } + /* + * Must be a text symbol, and static text symbols don't qualify if + * ignore_static_funcs set. + */ if (ignore_static_funcs && (sym->flags & BSF_LOCAL)) { DBG (AOUTDEBUG, printf ("[core_sym_class] %s: not a function\n", @@ -168,7 +270,7 @@ DEFUN (core_sym_class, (sym), asymbol * sym) * other systems. Perhaps it should be made configurable. */ sym_prefix = bfd_get_symbol_leading_char (core_bfd); - if (sym_prefix && sym_prefix != sym->name[0] + if ((sym_prefix && sym_prefix != sym->name[0]) /* * GCC may add special symbols to help gdb figure out the file * language. We want to ignore these, since sometimes they mask @@ -179,6 +281,12 @@ DEFUN (core_sym_class, (sym), asymbol * sym) { return 0; } + + /* If the object file supports marking of function symbols, then we can + zap anything that doesn't have BSF_FUNCTION set. */ + if (ignore_non_functions && (sym->flags & BSF_FUNCTION) == 0) + return 0; + return 't'; /* it's a static text symbol */ } @@ -224,9 +332,8 @@ void DEFUN (core_create_function_syms, (core_bfd), bfd * core_bfd) { bfd_vma min_vma = ~0, max_vma = 0; - const char *filename, *func_name; int class; - long i; + long i, j, found, skip; /* pass 1 - determine upper bound on number of function names: */ symtab.len = 0; @@ -236,7 +343,24 @@ DEFUN (core_create_function_syms, (core_bfd), bfd * core_bfd) { continue; } - ++symtab.len; + + /* This should be replaced with a binary search or hashed + search. Gross. + + Don't create a symtab entry for a function that has + a mapping to a file, unless it's the first function + in the file. */ + skip = 0; + for (j = 0; j < symbol_map_count; j++) + if (!strcmp (core_syms[i]->name, symbol_map[j].function_name)) + { + if (j > 0 && ! strcmp (symbol_map [j].file_name, + symbol_map [j - 1].file_name)) + skip = 1; + break; + } + if (!skip) + ++symtab.len; } if (symtab.len == 0) @@ -261,13 +385,41 @@ DEFUN (core_create_function_syms, (core_bfd), bfd * core_bfd) core_syms[i]->value, core_syms[i]->name)); continue; } + /* This should be replaced with a binary search or hashed + search. Gross. */ + + skip = 0; + found = 0; + for (j = 0; j < symbol_map_count; j++) + if (!strcmp (core_syms[i]->name, symbol_map[j].function_name)) + { + if (j > 0 && ! strcmp (symbol_map [j].file_name, + symbol_map [j - 1].file_name)) + skip = 1; + else + found = j; + break; + } + + if (skip) + continue; sym_init (symtab.limit); /* symbol offsets are always section-relative: */ symtab.limit->addr = core_syms[i]->value + core_syms[i]->section->vma; - symtab.limit->name = core_syms[i]->name; + if (symbol_map_count + && !strcmp (core_syms[i]->name, symbol_map[found].function_name)) + { + symtab.limit->name = symbol_map[found].file_name; + symtab.limit->mapped = 1; + } + else + { + symtab.limit->name = core_syms[i]->name; + symtab.limit->mapped = 0; + } #ifdef __osf__ /* @@ -278,24 +430,28 @@ DEFUN (core_create_function_syms, (core_bfd), bfd * core_bfd) * labels do not appear in the symbol table info, so this isn't * necessary. */ - if (get_src_info (symtab.limit->addr, &filename, &func_name, - &symtab.limit->line_num)) - { - symtab.limit->file = source_file_lookup_path (filename); - - if (strcmp (symtab.limit->name, func_name) != 0) - { - /* - * The symbol's address maps to a different name, so - * it can't be a function-entry point. This happens - * for labels, for example. - */ - DBG (AOUTDEBUG, - printf ("[core_create_function_syms: rej %s (maps to %s)\n", - symtab.limit->name, func_name)); - continue; - } - } + { + const char *filename, *func_name; + + if (get_src_info (symtab.limit->addr, &filename, &func_name, + &symtab.limit->line_num)) + { + symtab.limit->file = source_file_lookup_path (filename); + + if (strcmp (symtab.limit->name, func_name) != 0) + { + /* + * The symbol's address maps to a different name, so + * it can't be a function-entry point. This happens + * for labels, for example. + */ + DBG (AOUTDEBUG, + printf ("[core_create_function_syms: rej %s (maps to %s)\n", + symtab.limit->name, func_name)); + continue; + } + } + } #endif symtab.limit->is_func = TRUE; @@ -384,7 +540,7 @@ DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) prev_offset = -min_dist; prev_filename[0] = '\0'; prev_line_num = 0; - for (offset = 0; offset < core_text_sect->_raw_size; ++offset) + for (offset = 0; offset < core_text_sect->_raw_size; offset += MIN_INSN_SIZE) { vma = core_text_sect->vma + offset; if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num) diff --git a/gnu/usr.bin/binutils/gprof/flat_bl.c b/gnu/usr.bin/binutils/gprof/flat_bl.c deleted file mode 100644 index e02c209798c..00000000000 --- a/gnu/usr.bin/binutils/gprof/flat_bl.c +++ /dev/null @@ -1,37 +0,0 @@ -/* ==> Do not modify this file!! It is created automatically - from flat_bl.m using the gen-c-prog.awk script. <== */ - -#include <stdio.h> - -void -flat_blurb (file) - FILE *file; -{ - fputs ("\n", file); - fputs (" % the percentage of the total running time of the\n", file); - fputs ("time program used by this function.\n", file); - fputs ("\n", file); - fputs ("cumulative a running sum of the number of seconds accounted\n", file); - fputs (" seconds for by this function and those listed above it.\n", file); - fputs ("\n", file); - fputs (" self the number of seconds accounted for by this\n", file); - fputs ("seconds function alone. This is the major sort for this\n", file); - fputs (" listing.\n", file); - fputs ("\n", file); - fputs ("calls the number of times this function was invoked, if\n", file); - fputs (" this function is profiled, else blank.\n", file); - fputs (" \n", file); - fputs (" self the average number of milliseconds spent in this\n", file); - fputs ("ms/call function per call, if this function is profiled,\n", file); - fputs (" else blank.\n", file); - fputs ("\n", file); - fputs (" total the average number of milliseconds spent in this\n", file); - fputs ("ms/call function and its descendents per call, if this \n", file); - fputs (" function is profiled, else blank.\n", file); - fputs ("\n", file); - fputs ("name the name of the function. This is the minor sort\n", file); - fputs (" for this listing. The index shows the location of\n", file); - fputs (" the function in the gprof listing. If the index is\n", file); - fputs (" in parenthesis it shows where it would appear in\n", file); - fputs (" the gprof listing if it were to be printed.\n", file); -} diff --git a/gnu/usr.bin/binutils/gprof/fsf_callg_bl.c b/gnu/usr.bin/binutils/gprof/fsf_callg_bl.c deleted file mode 100644 index d8182b551b0..00000000000 --- a/gnu/usr.bin/binutils/gprof/fsf_callg_bl.c +++ /dev/null @@ -1,93 +0,0 @@ -/* ==> Do not modify this file!! It is created automatically - from fsf_callg_bl.m using the gen-c-prog.awk script. <== */ - -#include <stdio.h> - -void -fsf_callg_blurb (file) - FILE *file; -{ - fputs ("\n", file); - fputs (" This table describes the call tree of the program, and was sorted by\n", file); - fputs (" the total amount of time spent in each function and its children.\n", file); - fputs ("\n", file); - fputs (" Each entry in this table consists of several lines. The line with the\n", file); - fputs (" index number at the left hand margin lists the current function.\n", file); - fputs (" The lines above it list the functions that called this function,\n", file); - fputs (" and the lines below it list the functions this one called.\n", file); - fputs (" This line lists:\n", file); - fputs (" index A unique number given to each element of the table.\n", file); - fputs (" Index numbers are sorted numerically.\n", file); - fputs (" The index number is printed next to every function name so\n", file); - fputs (" it is easier to look up where the function in the table.\n", file); - fputs ("\n", file); - fputs (" % time This is the percentage of the `total' time that was spent\n", file); - fputs (" in this function and its children. Note that due to\n", file); - fputs (" different viewpoints, functions excluded by options, etc,\n", file); - fputs (" these numbers will NOT add up to 100%.\n", file); - fputs ("\n", file); - fputs (" self This is the total amount of time spent in this function.\n", file); - fputs ("\n", file); - fputs (" children This is the total amount of time propagated into this\n", file); - fputs (" function by its children.\n", file); - fputs ("\n", file); - fputs (" called This is the number of times the function was called.\n", file); - fputs (" If the function called itself recursively, the number\n", file); - fputs (" only includes non-recursive calls, and is followed by\n", file); - fputs (" a `+' and the number of recursive calls.\n", file); - fputs ("\n", file); - fputs (" name The name of the current function. The index number is\n", file); - fputs (" printed after it. If the function is a member of a\n", file); - fputs (" cycle, the cycle number is printed between the\n", file); - fputs (" function's name and the index number.\n", file); - fputs ("\n", file); - fputs ("\n", file); - fputs (" For the function's parents, the fields have the following meanings:\n", file); - fputs ("\n", file); - fputs (" self This is the amount of time that was propagated directly\n", file); - fputs (" from the function into this parent.\n", file); - fputs ("\n", file); - fputs (" children This is the amount of time that was propagated from\n", file); - fputs (" the function's children into this parent.\n", file); - fputs ("\n", file); - fputs (" called This is the number of times this parent called the\n", file); - fputs (" function `/' the total number of times the function\n", file); - fputs (" was called. Recursive calls to the function are not\n", file); - fputs (" included in the number after the `/'.\n", file); - fputs ("\n", file); - fputs (" name This is the name of the parent. The parent's index\n", file); - fputs (" number is printed after it. If the parent is a\n", file); - fputs (" member of a cycle, the cycle number is printed between\n", file); - fputs (" the name and the index number.\n", file); - fputs ("\n", file); - fputs (" If the parents of the function cannot be determined, the word\n", file); - fputs (" `<spontaneous>' is printed in the `name' field, and all the other\n", file); - fputs (" fields are blank.\n", file); - fputs ("\n", file); - fputs (" For the function's children, the fields have the following meanings:\n", file); - fputs ("\n", file); - fputs (" self This is the amount of time that was propagated directly\n", file); - fputs (" from the child into the function.\n", file); - fputs ("\n", file); - fputs (" children This is the amount of time that was propagated from the\n", file); - fputs (" child's children to the function.\n", file); - fputs ("\n", file); - fputs (" called This is the number of times the function called\n", file); - fputs (" this child `/' the total number of times the child\n", file); - fputs (" was called. Recursive calls by the child are not\n", file); - fputs (" listed in the number after the `/'.\n", file); - fputs ("\n", file); - fputs (" name This is the name of the child. The child's index\n", file); - fputs (" number is printed after it. If the child is a\n", file); - fputs (" member of a cycle, the cycle number is printed\n", file); - fputs (" between the name and the index number.\n", file); - fputs ("\n", file); - fputs (" If there are any cycles (circles) in the call graph, there is an\n", file); - fputs (" entry for the cycle-as-a-whole. This entry shows who called the\n", file); - fputs (" cycle (as parents) and the members of the cycle (as children.)\n", file); - fputs (" The `+' recursive calls entry shows the number of function calls that\n", file); - fputs (" were internal to the cycle, and the calls entry for each member shows,\n", file); - fputs (" for that member, how many times it was called from other members of\n", file); - fputs (" the cycle.\n", file); - fputs ("\n", file); -} diff --git a/gnu/usr.bin/binutils/gprof/gmon.h b/gnu/usr.bin/binutils/gprof/gmon.h index 74cd4b8c552..488f11ef8af 100644 --- a/gnu/usr.bin/binutils/gprof/gmon.h +++ b/gnu/usr.bin/binutils/gprof/gmon.h @@ -40,12 +40,17 @@ struct raw_phdr char low_pc[sizeof (bfd_vma)]; /* base pc address of sample buffer */ char high_pc[sizeof (bfd_vma)]; /* max pc address of sampled buffer */ char ncnt[4]; /* size of sample buffer (plus this header) */ -#ifdef __osf__ + +#if defined (__alpha__) && defined (__osf__) /* * DEC's OSF v3.0 uses 4 bytes of padding to bring the header to * a size that is a multiple of 8. */ char pad[4]; +#elif defined (BSD44_FORMAT) + char version[4]; /* version number */ + char profrate[4]; /* profiling clock rate */ + char spare[3*4]; /* reserved */ #endif }; diff --git a/gnu/usr.bin/binutils/gprof/gmon_io.c b/gnu/usr.bin/binutils/gprof/gmon_io.c index 82c3caa37ae..1f0e1acbf24 100644 --- a/gnu/usr.bin/binutils/gprof/gmon_io.c +++ b/gnu/usr.bin/binutils/gprof/gmon_io.c @@ -180,9 +180,27 @@ DEFUN (gmon_out_read, (filename), const char *filename) filename); done (1); } - tmp.low_pc = get_vma (core_bfd, (bfd_byte *) & raw.low_pc[0]); - tmp.high_pc = get_vma (core_bfd, (bfd_byte *) & raw.high_pc[0]); - tmp.ncnt = bfd_get_32 (core_bfd, (bfd_byte *) & raw.ncnt[0]); + tmp.low_pc = get_vma (core_bfd, (bfd_byte *) &raw.low_pc[0]); + tmp.high_pc = get_vma (core_bfd, (bfd_byte *) &raw.high_pc[0]); + tmp.ncnt = bfd_get_32 (core_bfd, (bfd_byte *) &raw.ncnt[0]); + +#ifdef BSD44_FORMAT + { + int profrate; + + profrate = bfd_get_32 (core_bfd, (bfd_byte *) &raw.version[0]); + if (!s_highpc) + hz = profrate; + else if (hz != profrate) + { + fprintf (stderr, + "%s: profiling rate incompatible with first gmon file\n", + filename); + done (1); + } + } +#endif + if (s_highpc && (tmp.low_pc != h.low_pc || tmp.high_pc != h.high_pc || tmp.ncnt != h.ncnt)) { diff --git a/gnu/usr.bin/binutils/gprof/gprof.c b/gnu/usr.bin/binutils/gprof/gprof.c index 5da3180a93e..e99f2d25caf 100644 --- a/gnu/usr.bin/binutils/gprof/gprof.c +++ b/gnu/usr.bin/binutils/gprof/gprof.c @@ -33,6 +33,7 @@ #define VERSION "2.6" const char *whoami; +const char *function_mapping_file; const char *a_out_name = A_OUTNAME; long hz = HZ_WRONG; @@ -50,6 +51,7 @@ bool ignore_zeros = TRUE; bool line_granularity = FALSE; bool print_descriptions = TRUE; bool print_path = FALSE; +bool ignore_non_functions = FALSE; File_Format file_format = FF_AUTO; bool first_output = TRUE; @@ -67,7 +69,7 @@ bfd *abfd; */ static char *default_excluded_list[] = { - "_gprof_mcount", "mcount", "_mcount", "__mcleanup", + "_gprof_mcount", "mcount", "_mcount", "__mcount", "__mcleanup", "<locore>", "<hicore>", 0 }; @@ -76,6 +78,7 @@ static struct option long_options[] = { {"line", no_argument, 0, 'l'}, {"no-static", no_argument, 0, 'a'}, + {"ignore-non-functions", no_argument, 0, 'D'}, /* output styles: */ @@ -87,6 +90,8 @@ static struct option long_options[] = {"no-graph", optional_argument, 0, 'Q'}, {"exec-counts", optional_argument, 0, 'C'}, {"no-exec-counts", optional_argument, 0, 'Z'}, + {"function-ordering", no_argument, 0, 'r'}, + {"file-ordering", required_argument, 0, 'R'}, {"file-info", no_argument, 0, 'i'}, {"sum", no_argument, 0, 's'}, @@ -129,16 +134,17 @@ static void DEFUN (usage, (stream, status), FILE * stream AND int status) { fprintf (stream, "\ -Usage: %s [-[abchilLsTvwxyz]] [-[ACeEfFJnNOpPqQZ][name]] [-I dirs]\n\ +Usage: %s [-[abcDhilLsTvwxyz]] [-[ACeEfFJnNOpPqQZ][name]] [-I dirs]\n\ [-d[num]] [-k from/to] [-m min-count] [-t table-length]\n\ [--[no-]annotated-source[=name]] [--[no-]exec-counts[=name]]\n\ [--[no-]flat-profile[=name]] [--[no-]graph[=name]]\n\ [--[no-]time=name] [--all-lines] [--brief] [--debug[=level]]\n\ + [--function-ordering] [--file-ordering]\n\ [--directory-path=dirs] [--display-unused-functions]\n\ [--file-format=name] [--file-info] [--help] [--line] [--min-count=n]\n\ [--no-static] [--print-path] [--separate-files]\n\ [--static-call-graph] [--sum] [--table-length=len] [--traditional]\n\ - [--version] [--width=n]\n\ + [--version] [--width=n] [--ignore-non-functions]\n\ [image-file] [profile-file...]\n", whoami); done (status); @@ -156,7 +162,7 @@ DEFUN (main, (argc, argv), int argc AND char **argv) xmalloc_set_program_name (whoami); while ((ch = getopt_long (argc, argv, - "aA::bBcCd::e:E:f:F:hiI:J::k:lLm:n::N::O:p::P::q::Q::st:Tvw:xyzZ::", + "aA::bBcCdD::e:E:f:F:hiI:J::k:lLm:n::N::O:p::P::q::Q::st:Tvw:xyzZ::", long_options, 0)) != EOF) { @@ -206,6 +212,9 @@ DEFUN (main, (argc, argv), int argc AND char **argv) printf ("%s: debugging not supported; -d ignored\n", whoami); #endif /* DEBUG */ break; + case 'D': + ignore_non_functions = TRUE; + break; case 'E': sym_id_add (optarg, EXCL_TIME); case 'e': @@ -317,6 +326,15 @@ DEFUN (main, (argc, argv), int argc AND char **argv) output_style |= STYLE_CALL_GRAPH; user_specified |= STYLE_CALL_GRAPH; break; + case 'r': + output_style |= STYLE_FUNCTION_ORDER; + user_specified |= STYLE_FUNCTION_ORDER; + break; + case 'R': + output_style |= STYLE_FILE_ORDER; + user_specified |= STYLE_FILE_ORDER; + function_mapping_file = optarg; + break; case 'Q': if (optarg) { @@ -386,6 +404,16 @@ DEFUN (main, (argc, argv), int argc AND char **argv) } } + /* Don't allow both ordering options, they modify the arc data in-place. */ + if ((user_specified & STYLE_FUNCTION_ORDER) + && (user_specified & STYLE_FILE_ORDER)) + { + fprintf (stderr,"\ +%s: Only one of --function-ordering and --file-ordering may be specified.\n", + whoami); + done (1); + } + /* append value of GPROF_PATH to source search list if set: */ str = (char *) getenv ("GPROF_PATH"); if (str) @@ -409,7 +437,7 @@ DEFUN (main, (argc, argv), int argc AND char **argv) { sym_id_add (*sp, EXCL_TIME); sym_id_add (*sp, EXCL_GRAPH); -#ifdef __osf__ +#ifdef __alpha__ sym_id_add (*sp, EXCL_FLAT); #endif } @@ -576,6 +604,14 @@ DEFUN (main, (argc, argv), int argc AND char **argv) { print_annotated_source (); } + if (output_style & STYLE_FUNCTION_ORDER) + { + cg_print_function_ordering (); + } + if (output_style & STYLE_FILE_ORDER) + { + cg_print_file_ordering (); + } return 0; } diff --git a/gnu/usr.bin/binutils/gprof/gprof.h b/gnu/usr.bin/binutils/gprof/gprof.h index e4177a9a0bb..c61886a4803 100644 --- a/gnu/usr.bin/binutils/gprof/gprof.h +++ b/gnu/usr.bin/binutils/gprof/gprof.h @@ -79,6 +79,8 @@ #define STYLE_EXEC_COUNTS (1<<3) #define STYLE_ANNOTATED_SOURCE (1<<4) #define STYLE_GMON_INFO (1<<5) +#define STYLE_FUNCTION_ORDER (1<<6) +#define STYLE_FILE_ORDER (1<<7) #define ANYDEBUG (1<<0) /* 1 */ #define DFNDEBUG (1<<1) /* 2 */ @@ -111,6 +113,7 @@ typedef int bool; typedef unsigned char UNIT[2]; /* unit of profiling */ extern const char *whoami; /* command-name, for error messages */ +extern const char *function_mapping_file; /* file mapping functions to files */ extern const char *a_out_name; /* core filename */ extern long hz; /* ticks per second */ @@ -128,6 +131,8 @@ extern bool ignore_zeros; /* ignore unused symbols/files */ extern bool line_granularity; /* function or line granularity? */ extern bool print_descriptions; /* output profile description */ extern bool print_path; /* print path or just filename? */ +extern bool ignore_non_functions;/* Ignore non-function symbols. */ + extern File_Format file_format; /* requested file format */ extern bool first_output; /* no output so far? */ diff --git a/gnu/usr.bin/binutils/gprof/gprof.info b/gnu/usr.bin/binutils/gprof/gprof.info deleted file mode 100644 index 60a2d9a9f43..00000000000 --- a/gnu/usr.bin/binutils/gprof/gprof.info +++ /dev/null @@ -1,951 +0,0 @@ -This is Info file gprof.info, produced by Makeinfo-1.55 from the input -file ./gprof.texi. - -START-INFO-DIR-ENTRY -* gprof: (gprof). Profiling your program's execution -END-INFO-DIR-ENTRY - - This file documents the gprof profiler of the GNU system. - - Copyright (C) 1988, 1992 Free Software Foundation, Inc. - - Permission is granted to make and distribute verbatim copies of this -manual provided the copyright notice and this permission notice are -preserved on all copies. - - Permission is granted to copy and distribute modified versions of -this manual under the conditions for verbatim copying, provided that -the entire resulting derived work is distributed under the terms of a -permission notice identical to this one. - - Permission is granted to copy and distribute translations of this -manual into another language, under the above conditions for modified -versions. - - -File: gprof.info, Node: Top, Next: Why, Prev: (DIR), Up: (DIR) - -Profiling a Program: Where Does It Spend Its Time? -************************************************** - - This manual describes the GNU profiler, `gprof', and how you can use -it to determine which parts of a program are taking most of the -execution time. We assume that you know how to write, compile, and -execute programs. GNU `gprof' was written by Jay Fenlason. - - This manual was updated January 1993. - -* Menu: - -* Why:: What profiling means, and why it is useful. -* Compiling:: How to compile your program for profiling. -* Executing:: How to execute your program to generate the - profile data file `gmon.out'. -* Invoking:: How to run `gprof', and how to specify - options for it. - -* Flat Profile:: The flat profile shows how much time was spent - executing directly in each function. -* Call Graph:: The call graph shows which functions called which - others, and how much time each function used - when its subroutine calls are included. - -* Implementation:: How the profile data is recorded and written. -* Sampling Error:: Statistical margins of error. - How to accumulate data from several runs - to make it more accurate. - -* Assumptions:: Some of `gprof''s measurements are based - on assumptions about your program - that could be very wrong. - -* Incompatibilities:: (between GNU `gprof' and Unix `gprof'.) - - -File: gprof.info, Node: Why, Next: Compiling, Prev: Top, Up: Top - -Why Profile -*********** - - Profiling allows you to learn where your program spent its time and -which functions called which other functions while it was executing. -This information can show you which pieces of your program are slower -than you expected, and might be candidates for rewriting to make your -program execute faster. It can also tell you which functions are being -called more or less often than you expected. This may help you spot -bugs that had otherwise been unnoticed. - - Since the profiler uses information collected during the actual -execution of your program, it can be used on programs that are too -large or too complex to analyze by reading the source. However, how -your program is run will affect the information that shows up in the -profile data. If you don't use some feature of your program while it -is being profiled, no profile information will be generated for that -feature. - - Profiling has several steps: - - * You must compile and link your program with profiling enabled. - *Note Compiling::. - - * You must execute your program to generate a profile data file. - *Note Executing::. - - * You must run `gprof' to analyze the profile data. *Note - Invoking::. - - The next three chapters explain these steps in greater detail. - - The result of the analysis is a file containing two tables, the -"flat profile" and the "call graph" (plus blurbs which briefly explain -the contents of these tables). - - The flat profile shows how much time your program spent in each -function, and how many times that function was called. If you simply -want to know which functions burn most of the cycles, it is stated -concisely here. *Note Flat Profile::. - - The call graph shows, for each function, which functions called it, -which other functions it called, and how many times. There is also an -estimate of how much time was spent in the subroutines of each -function. This can suggest places where you might try to eliminate -function calls that use a lot of time. *Note Call Graph::. - - -File: gprof.info, Node: Compiling, Next: Executing, Prev: Why, Up: Top - -Compiling a Program for Profiling -********************************* - - The first step in generating profile information for your program is -to compile and link it with profiling enabled. - - To compile a source file for profiling, specify the `-pg' option when -you run the compiler. (This is in addition to the options you normally -use.) - - To link the program for profiling, if you use a compiler such as `cc' -to do the linking, simply specify `-pg' in addition to your usual -options. The same option, `-pg', alters either compilation or linking -to do what is necessary for profiling. Here are examples: - - cc -g -c myprog.c utils.c -pg - cc -o myprog myprog.o utils.o -pg - - The `-pg' option also works with a command that both compiles and -links: - - cc -o myprog myprog.c utils.c -g -pg - - If you run the linker `ld' directly instead of through a compiler -such as `cc', you must specify the profiling startup file -`/lib/gcrt0.o' as the first input file instead of the usual startup -file `/lib/crt0.o'. In addition, you would probably want to specify -the profiling C library, `/usr/lib/libc_p.a', by writing `-lc_p' -instead of the usual `-lc'. This is not absolutely necessary, but -doing this gives you number-of-calls information for standard library -functions such as `read' and `open'. For example: - - ld -o myprog /lib/gcrt0.o myprog.o utils.o -lc_p - - If you compile only some of the modules of the program with `-pg', -you can still profile the program, but you won't get complete -information about the modules that were compiled without `-pg'. The -only information you get for the functions in those modules is the -total time spent in them; there is no record of how many times they -were called, or from where. This will not affect the flat profile -(except that the `calls' field for the functions will be blank), but -will greatly reduce the usefulness of the call graph. - - -File: gprof.info, Node: Executing, Next: Invoking, Prev: Compiling, Up: Top - -Executing the Program to Generate Profile Data -********************************************** - - Once the program is compiled for profiling, you must run it in order -to generate the information that `gprof' needs. Simply run the program -as usual, using the normal arguments, file names, etc. The program -should run normally, producing the same output as usual. It will, -however, run somewhat slower than normal because of the time spent -collecting and the writing the profile data. - - The way you run the program--the arguments and input that you give -it--may have a dramatic effect on what the profile information shows. -The profile data will describe the parts of the program that were -activated for the particular input you use. For example, if the first -command you give to your program is to quit, the profile data will show -the time used in initialization and in cleanup, but not much else. - - You program will write the profile data into a file called `gmon.out' -just before exiting. If there is already a file called `gmon.out', its -contents are overwritten. There is currently no way to tell the -program to write the profile data under a different name, but you can -rename the file afterward if you are concerned that it may be -overwritten. - - In order to write the `gmon.out' file properly, your program must -exit normally: by returning from `main' or by calling `exit'. Calling -the low-level function `_exit' does not write the profile data, and -neither does abnormal termination due to an unhandled signal. - - The `gmon.out' file is written in the program's *current working -directory* at the time it exits. This means that if your program calls -`chdir', the `gmon.out' file will be left in the last directory your -program `chdir''d to. If you don't have permission to write in this -directory, the file is not written. You may get a confusing error -message if this happens. (We have not yet replaced the part of Unix -responsible for this; when we do, we will make the error message -comprehensible.) - - -File: gprof.info, Node: Invoking, Next: Flat Profile, Prev: Executing, Up: Top - -`gprof' Command Summary -*********************** - - After you have a profile data file `gmon.out', you can run `gprof' -to interpret the information in it. The `gprof' program prints a flat -profile and a call graph on standard output. Typically you would -redirect the output of `gprof' into a file with `>'. - - You run `gprof' like this: - - gprof OPTIONS [EXECUTABLE-FILE [PROFILE-DATA-FILES...]] [> OUTFILE] - -Here square-brackets indicate optional arguments. - - If you omit the executable file name, the file `a.out' is used. If -you give no profile data file name, the file `gmon.out' is used. If -any file is not in the proper format, or if the profile data file does -not appear to belong to the executable file, an error message is -printed. - - You can give more than one profile data file by entering all their -names after the executable file name; then the statistics in all the -data files are summed together. - - The following options may be used to selectively include or exclude -functions in the output: - -`-a' - The `-a' option causes `gprof' to suppress the printing of - statically declared (private) functions. (These are functions - whose names are not listed as global, and which are not visible - outside the file/function/block where they were defined.) Time - spent in these functions, calls to/from them, etc, will all be - attributed to the function that was loaded directly before it in - the executable file. This option affects both the flat profile - and the call graph. - -`-e FUNCTION_NAME' - The `-e FUNCTION' option tells `gprof' to not print information - about the function FUNCTION_NAME (and its children...) in the call - graph. The function will still be listed as a child of any - functions that call it, but its index number will be shown as - `[not printed]'. More than one `-e' option may be given; only one - FUNCTION_NAME may be indicated with each `-e' option. - -`-E FUNCTION_NAME' - The `-E FUNCTION' option works like the `-e' option, but time - spent in the function (and children who were not called from - anywhere else), will not be used to compute the - percentages-of-time for the call graph. More than one `-E' option - may be given; only one FUNCTION_NAME may be indicated with each - `-E' option. - -`-f FUNCTION_NAME' - The `-f FUNCTION' option causes `gprof' to limit the call graph to - the function FUNCTION_NAME and its children (and their - children...). More than one `-f' option may be given; only one - FUNCTION_NAME may be indicated with each `-f' option. - -`-F FUNCTION_NAME' - The `-F FUNCTION' option works like the `-f' option, but only time - spent in the function and its children (and their children...) - will be used to determine total-time and percentages-of-time for - the call graph. More than one `-F' option may be given; only one - FUNCTION_NAME may be indicated with each `-F' option. The `-F' - option overrides the `-E' option. - -`-k FROM... TO...' - The `-k' option allows you to delete from the profile any arcs from - routine FROM to routine TO. - -`-v' - The `-v' flag causes `gprof' to print the current version number, - and then exit. - -`-z' - If you give the `-z' option, `gprof' will mention all functions in - the flat profile, even those that were never called, and that had - no time spent in them. This is useful in conjunction with the - `-c' option for discovering which routines were never called. - - The order of these options does not matter. - - Note that only one function can be specified with each `-e', `-E', -`-f' or `-F' option. To specify more than one function, use multiple -options. For example, this command: - - gprof -e boring -f foo -f bar myprogram > gprof.output - -lists in the call graph all functions that were reached from either -`foo' or `bar' and were not reachable from `boring'. - - There are a few other useful `gprof' options: - -`-b' - If the `-b' option is given, `gprof' doesn't print the verbose - blurbs that try to explain the meaning of all of the fields in the - tables. This is useful if you intend to print out the output, or - are tired of seeing the blurbs. - -`-c' - The `-c' option causes the static call-graph of the program to be - discovered by a heuristic which examines the text space of the - object file. Static-only parents or children are indicated with - call counts of `0'. - -`-d NUM' - The `-d NUM' option specifies debugging options. - -`-s' - The `-s' option causes `gprof' to summarize the information in the - profile data files it read in, and write out a profile data file - called `gmon.sum', which contains all the information from the - profile data files that `gprof' read in. The file `gmon.sum' may - be one of the specified input files; the effect of this is to - merge the data in the other input files into `gmon.sum'. *Note - Sampling Error::. - - Eventually you can run `gprof' again without `-s' to analyze the - cumulative data in the file `gmon.sum'. - -`-T' - The `-T' option causes `gprof' to print its output in - "traditional" BSD style. - - -File: gprof.info, Node: Flat Profile, Next: Call Graph, Prev: Invoking, Up: Top - -How to Understand the Flat Profile -********************************** - - The "flat profile" shows the total amount of time your program spent -executing each function. Unless the `-z' option is given, functions -with no apparent time spent in them, and no apparent calls to them, are -not mentioned. Note that if a function was not compiled for profiling, -and didn't run long enough to show up on the program counter histogram, -it will be indistinguishable from a function that was never called. - - This is part of a flat profile for a small program: - - Flat profile: - - Each sample counts as 0.01 seconds. - % cumulative self self total - time seconds seconds calls ms/call ms/call name - 33.34 0.02 0.02 7208 0.00 0.00 open - 16.67 0.03 0.01 244 0.04 0.12 offtime - 16.67 0.04 0.01 8 1.25 1.25 memccpy - 16.67 0.05 0.01 7 1.43 1.43 write - 16.67 0.06 0.01 mcount - 0.00 0.06 0.00 236 0.00 0.00 tzset - 0.00 0.06 0.00 192 0.00 0.00 tolower - 0.00 0.06 0.00 47 0.00 0.00 strlen - 0.00 0.06 0.00 45 0.00 0.00 strchr - 0.00 0.06 0.00 1 0.00 50.00 main - 0.00 0.06 0.00 1 0.00 0.00 memcpy - 0.00 0.06 0.00 1 0.00 10.11 print - 0.00 0.06 0.00 1 0.00 0.00 profil - 0.00 0.06 0.00 1 0.00 50.00 report - ... - -The functions are sorted by decreasing run-time spent in them. The -functions `mcount' and `profil' are part of the profiling aparatus and -appear in every flat profile; their time gives a measure of the amount -of overhead due to profiling. - - The sampling period estimates the margin of error in each of the time -figures. A time figure that is not much larger than this is not -reliable. In this example, the `self seconds' field for `mcount' might -well be `0' or `0.04' in another run. *Note Sampling Error::, for a -complete discussion. - - Here is what the fields in each line mean: - -`% time' - This is the percentage of the total execution time your program - spent in this function. These should all add up to 100%. - -`cumulative seconds' - This is the cumulative total number of seconds the computer spent - executing this functions, plus the time spent in all the functions - above this one in this table. - -`self seconds' - This is the number of seconds accounted for by this function alone. - The flat profile listing is sorted first by this number. - -`calls' - This is the total number of times the function was called. If the - function was never called, or the number of times it was called - cannot be determined (probably because the function was not - compiled with profiling enabled), the "calls" field is blank. - -`self ms/call' - This represents the average number of milliseconds spent in this - function per call, if this function is profiled. Otherwise, this - field is blank for this function. - -`total ms/call' - This represents the average number of milliseconds spent in this - function and its descendants per call, if this function is - profiled. Otherwise, this field is blank for this function. - -`name' - This is the name of the function. The flat profile is sorted by - this field alphabetically after the "self seconds" field is sorted. - - -File: gprof.info, Node: Call Graph, Next: Implementation, Prev: Flat Profile, Up: Top - -How to Read the Call Graph -************************** - - The "call graph" shows how much time was spent in each function and -its children. From this information, you can find functions that, -while they themselves may not have used much time, called other -functions that did use unusual amounts of time. - - Here is a sample call from a small program. This call came from the -same `gprof' run as the flat profile example in the previous chapter. - - granularity: each sample hit covers 2 byte(s) for 20.00% of 0.05 seconds - - index % time self children called name - <spontaneous> - [1] 100.0 0.00 0.05 start [1] - 0.00 0.05 1/1 main [2] - 0.00 0.00 1/2 on_exit [28] - 0.00 0.00 1/1 exit [59] - ----------------------------------------------- - 0.00 0.05 1/1 start [1] - [2] 100.0 0.00 0.05 1 main [2] - 0.00 0.05 1/1 report [3] - ----------------------------------------------- - 0.00 0.05 1/1 main [2] - [3] 100.0 0.00 0.05 1 report [3] - 0.00 0.03 8/8 timelocal [6] - 0.00 0.01 1/1 print [9] - 0.00 0.01 9/9 fgets [12] - 0.00 0.00 12/34 strncmp <cycle 1> [40] - 0.00 0.00 8/8 lookup [20] - 0.00 0.00 1/1 fopen [21] - 0.00 0.00 8/8 chewtime [24] - 0.00 0.00 8/16 skipspace [44] - ----------------------------------------------- - [4] 59.8 0.01 0.02 8+472 <cycle 2 as a whole> [4] - 0.01 0.02 244+260 offtime <cycle 2> [7] - 0.00 0.00 236+1 tzset <cycle 2> [26] - ----------------------------------------------- - - The lines full of dashes divide this table into "entries", one for -each function. Each entry has one or more lines. - - In each entry, the primary line is the one that starts with an index -number in square brackets. The end of this line says which function -the entry is for. The preceding lines in the entry describe the -callers of this function and the following lines describe its -subroutines (also called "children" when we speak of the call graph). - - The entries are sorted by time spent in the function and its -subroutines. - - The internal profiling function `mcount' (*note Flat Profile::.) is -never mentioned in the call graph. - -* Menu: - -* Primary:: Details of the primary line's contents. -* Callers:: Details of caller-lines' contents. -* Subroutines:: Details of subroutine-lines' contents. -* Cycles:: When there are cycles of recursion, - such as `a' calls `b' calls `a'... - - -File: gprof.info, Node: Primary, Next: Callers, Up: Call Graph - -The Primary Line -================ - - The "primary line" in a call graph entry is the line that describes -the function which the entry is about and gives the overall statistics -for this function. - - For reference, we repeat the primary line from the entry for function -`report' in our main example, together with the heading line that shows -the names of the fields: - - index % time self children called name - ... - [3] 100.0 0.00 0.05 1 report [3] - - Here is what the fields in the primary line mean: - -`index' - Entries are numbered with consecutive integers. Each function - therefore has an index number, which appears at the beginning of - its primary line. - - Each cross-reference to a function, as a caller or subroutine of - another, gives its index number as well as its name. The index - number guides you if you wish to look for the entry for that - function. - -`% time' - This is the percentage of the total time that was spent in this - function, including time spent in subroutines called from this - function. - - The time spent in this function is counted again for the callers of - this function. Therefore, adding up these percentages is - meaningless. - -`self' - This is the total amount of time spent in this function. This - should be identical to the number printed in the `seconds' field - for this function in the flat profile. - -`children' - This is the total amount of time spent in the subroutine calls - made by this function. This should be equal to the sum of all the - `self' and `children' entries of the children listed directly - below this function. - -`called' - This is the number of times the function was called. - - If the function called itself recursively, there are two numbers, - separated by a `+'. The first number counts non-recursive calls, - and the second counts recursive calls. - - In the example above, the function `report' was called once from - `main'. - -`name' - This is the name of the current function. The index number is - repeated after it. - - If the function is part of a cycle of recursion, the cycle number - is printed between the function's name and the index number (*note - Cycles::.). For example, if function `gnurr' is part of cycle - number one, and has index number twelve, its primary line would be - end like this: - - gnurr <cycle 1> [12] - - -File: gprof.info, Node: Callers, Next: Subroutines, Prev: Primary, Up: Call Graph - -Lines for a Function's Callers -============================== - - A function's entry has a line for each function it was called by. -These lines' fields correspond to the fields of the primary line, but -their meanings are different because of the difference in context. - - For reference, we repeat two lines from the entry for the function -`report', the primary line and one caller-line preceding it, together -with the heading line that shows the names of the fields: - - index % time self children called name - ... - 0.00 0.05 1/1 main [2] - [3] 100.0 0.00 0.05 1 report [3] - - Here are the meanings of the fields in the caller-line for `report' -called from `main': - -`self' - An estimate of the amount of time spent in `report' itself when it - was called from `main'. - -`children' - An estimate of the amount of time spent in subroutines of `report' - when `report' was called from `main'. - - The sum of the `self' and `children' fields is an estimate of the - amount of time spent within calls to `report' from `main'. - -`called' - Two numbers: the number of times `report' was called from `main', - followed by the total number of nonrecursive calls to `report' from - all its callers. - -`name and index number' - The name of the caller of `report' to which this line applies, - followed by the caller's index number. - - Not all functions have entries in the call graph; some options to - `gprof' request the omission of certain functions. When a caller - has no entry of its own, it still has caller-lines in the entries - of the functions it calls. - - If the caller is part of a recursion cycle, the cycle number is - printed between the name and the index number. - - If the identity of the callers of a function cannot be determined, a -dummy caller-line is printed which has `<spontaneous>' as the "caller's -name" and all other fields blank. This can happen for signal handlers. - - -File: gprof.info, Node: Subroutines, Next: Cycles, Prev: Callers, Up: Call Graph - -Lines for a Function's Subroutines -================================== - - A function's entry has a line for each of its subroutines--in other -words, a line for each other function that it called. These lines' -fields correspond to the fields of the primary line, but their meanings -are different because of the difference in context. - - For reference, we repeat two lines from the entry for the function -`main', the primary line and a line for a subroutine, together with the -heading line that shows the names of the fields: - - index % time self children called name - ... - [2] 100.0 0.00 0.05 1 main [2] - 0.00 0.05 1/1 report [3] - - Here are the meanings of the fields in the subroutine-line for `main' -calling `report': - -`self' - An estimate of the amount of time spent directly within `report' - when `report' was called from `main'. - -`children' - An estimate of the amount of time spent in subroutines of `report' - when `report' was called from `main'. - - The sum of the `self' and `children' fields is an estimate of the - total time spent in calls to `report' from `main'. - -`called' - Two numbers, the number of calls to `report' from `main' followed - by the total number of nonrecursive calls to `report'. - -`name' - The name of the subroutine of `main' to which this line applies, - followed by the subroutine's index number. - - If the caller is part of a recursion cycle, the cycle number is - printed between the name and the index number. - - -File: gprof.info, Node: Cycles, Prev: Subroutines, Up: Call Graph - -How Mutually Recursive Functions Are Described -============================================== - - The graph may be complicated by the presence of "cycles of -recursion" in the call graph. A cycle exists if a function calls -another function that (directly or indirectly) calls (or appears to -call) the original function. For example: if `a' calls `b', and `b' -calls `a', then `a' and `b' form a cycle. - - Whenever there are call-paths both ways between a pair of functions, -they belong to the same cycle. If `a' and `b' call each other and `b' -and `c' call each other, all three make one cycle. Note that even if -`b' only calls `a' if it was not called from `a', `gprof' cannot -determine this, so `a' and `b' are still considered a cycle. - - The cycles are numbered with consecutive integers. When a function -belongs to a cycle, each time the function name appears in the call -graph it is followed by `<cycle NUMBER>'. - - The reason cycles matter is that they make the time values in the -call graph paradoxical. The "time spent in children" of `a' should -include the time spent in its subroutine `b' and in `b''s -subroutines--but one of `b''s subroutines is `a'! How much of `a''s -time should be included in the children of `a', when `a' is indirectly -recursive? - - The way `gprof' resolves this paradox is by creating a single entry -for the cycle as a whole. The primary line of this entry describes the -total time spent directly in the functions of the cycle. The -"subroutines" of the cycle are the individual functions of the cycle, -and all other functions that were called directly by them. The -"callers" of the cycle are the functions, outside the cycle, that -called functions in the cycle. - - Here is an example portion of a call graph which shows a cycle -containing functions `a' and `b'. The cycle was entered by a call to -`a' from `main'; both `a' and `b' called `c'. - - index % time self children called name - ---------------------------------------- - 1.77 0 1/1 main [2] - [3] 91.71 1.77 0 1+5 <cycle 1 as a whole> [3] - 1.02 0 3 b <cycle 1> [4] - 0.75 0 2 a <cycle 1> [5] - ---------------------------------------- - 3 a <cycle 1> [5] - [4] 52.85 1.02 0 0 b <cycle 1> [4] - 2 a <cycle 1> [5] - 0 0 3/6 c [6] - ---------------------------------------- - 1.77 0 1/1 main [2] - 2 b <cycle 1> [4] - [5] 38.86 0.75 0 1 a <cycle 1> [5] - 3 b <cycle 1> [4] - 0 0 3/6 c [6] - ---------------------------------------- - -(The entire call graph for this program contains in addition an entry -for `main', which calls `a', and an entry for `c', with callers `a' and -`b'.) - - index % time self children called name - <spontaneous> - [1] 100.00 0 1.93 0 start [1] - 0.16 1.77 1/1 main [2] - ---------------------------------------- - 0.16 1.77 1/1 start [1] - [2] 100.00 0.16 1.77 1 main [2] - 1.77 0 1/1 a <cycle 1> [5] - ---------------------------------------- - 1.77 0 1/1 main [2] - [3] 91.71 1.77 0 1+5 <cycle 1 as a whole> [3] - 1.02 0 3 b <cycle 1> [4] - 0.75 0 2 a <cycle 1> [5] - 0 0 6/6 c [6] - ---------------------------------------- - 3 a <cycle 1> [5] - [4] 52.85 1.02 0 0 b <cycle 1> [4] - 2 a <cycle 1> [5] - 0 0 3/6 c [6] - ---------------------------------------- - 1.77 0 1/1 main [2] - 2 b <cycle 1> [4] - [5] 38.86 0.75 0 1 a <cycle 1> [5] - 3 b <cycle 1> [4] - 0 0 3/6 c [6] - ---------------------------------------- - 0 0 3/6 b <cycle 1> [4] - 0 0 3/6 a <cycle 1> [5] - [6] 0.00 0 0 6 c [6] - ---------------------------------------- - - The `self' field of the cycle's primary line is the total time spent -in all the functions of the cycle. It equals the sum of the `self' -fields for the individual functions in the cycle, found in the entry in -the subroutine lines for these functions. - - The `children' fields of the cycle's primary line and subroutine -lines count only subroutines outside the cycle. Even though `a' calls -`b', the time spent in those calls to `b' is not counted in `a''s -`children' time. Thus, we do not encounter the problem of what to do -when the time in those calls to `b' includes indirect recursive calls -back to `a'. - - The `children' field of a caller-line in the cycle's entry estimates -the amount of time spent *in the whole cycle*, and its other -subroutines, on the times when that caller called a function in the -cycle. - - The `calls' field in the primary line for the cycle has two numbers: -first, the number of times functions in the cycle were called by -functions outside the cycle; second, the number of times they were -called by functions in the cycle (including times when a function in -the cycle calls itself). This is a generalization of the usual split -into nonrecursive and recursive calls. - - The `calls' field of a subroutine-line for a cycle member in the -cycle's entry says how many time that function was called from -functions in the cycle. The total of all these is the second number in -the primary line's `calls' field. - - In the individual entry for a function in a cycle, the other -functions in the same cycle can appear as subroutines and as callers. -These lines show how many times each function in the cycle called or -was called from each other function in the cycle. The `self' and -`children' fields in these lines are blank because of the difficulty of -defining meanings for them when recursion is going on. - - -File: gprof.info, Node: Implementation, Next: Sampling Error, Prev: Call Graph, Up: Top - -Implementation of Profiling -*************************** - - Profiling works by changing how every function in your program is -compiled so that when it is called, it will stash away some information -about where it was called from. From this, the profiler can figure out -what function called it, and can count how many times it was called. -This change is made by the compiler when your program is compiled with -the `-pg' option. - - Profiling also involves watching your program as it runs, and -keeping a histogram of where the program counter happens to be every -now and then. Typically the program counter is looked at around 100 -times per second of run time, but the exact frequency may vary from -system to system. - - A special startup routine allocates memory for the histogram and -sets up a clock signal handler to make entries in it. Use of this -special startup routine is one of the effects of using `gcc ... -pg' to -link. The startup file also includes an `exit' function which is -responsible for writing the file `gmon.out'. - - Number-of-calls information for library routines is collected by -using a special version of the C library. The programs in it are the -same as in the usual C library, but they were compiled with `-pg'. If -you link your program with `gcc ... -pg', it automatically uses the -profiling version of the library. - - The output from `gprof' gives no indication of parts of your program -that are limited by I/O or swapping bandwidth. This is because samples -of the program counter are taken at fixed intervals of run time. -Therefore, the time measurements in `gprof' output say nothing about -time that your program was not running. For example, a part of the -program that creates so much data that it cannot all fit in physical -memory at once may run very slowly due to thrashing, but `gprof' will -say it uses little time. On the other hand, sampling by run time has -the advantage that the amount of load due to other users won't directly -affect the output you get. - - -File: gprof.info, Node: Sampling Error, Next: Assumptions, Prev: Implementation, Up: Top - -Statistical Inaccuracy of `gprof' Output -**************************************** - - The run-time figures that `gprof' gives you are based on a sampling -process, so they are subject to statistical inaccuracy. If a function -runs only a small amount of time, so that on the average the sampling -process ought to catch that function in the act only once, there is a -pretty good chance it will actually find that function zero times, or -twice. - - By contrast, the number-of-calls figures are derived by counting, not -sampling. They are completely accurate and will not vary from run to -run if your program is deterministic. - - The "sampling period" that is printed at the beginning of the flat -profile says how often samples are taken. The rule of thumb is that a -run-time figure is accurate if it is considerably bigger than the -sampling period. - - The actual amount of error is usually more than one sampling period. -In fact, if a value is N times the sampling period, the *expected* -error in it is the square-root of N sampling periods. If the sampling -period is 0.01 seconds and `foo''s run-time is 1 second, the expected -error in `foo''s run-time is 0.1 seconds. It is likely to vary this -much *on the average* from one profiling run to the next. (*Sometimes* -it will vary more.) - - This does not mean that a small run-time figure is devoid of -information. If the program's *total* run-time is large, a small -run-time for one function does tell you that that function used an -insignificant fraction of the whole program's time. Usually this means -it is not worth optimizing. - - One way to get more accuracy is to give your program more (but -similar) input data so it will take longer. Another way is to combine -the data from several runs, using the `-s' option of `gprof'. Here is -how: - - 1. Run your program once. - - 2. Issue the command `mv gmon.out gmon.sum'. - - 3. Run your program again, the same as before. - - 4. Merge the new data in `gmon.out' into `gmon.sum' with this command: - - gprof -s EXECUTABLE-FILE gmon.out gmon.sum - - 5. Repeat the last two steps as often as you wish. - - 6. Analyze the cumulative data using this command: - - gprof EXECUTABLE-FILE gmon.sum > OUTPUT-FILE - - -File: gprof.info, Node: Assumptions, Next: Incompatibilities, Prev: Sampling Error, Up: Top - -Estimating `children' Times Uses an Assumption -********************************************** - - Some of the figures in the call graph are estimates--for example, the -`children' time values and all the the time figures in caller and -subroutine lines. - - There is no direct information about these measurements in the -profile data itself. Instead, `gprof' estimates them by making an -assumption about your program that might or might not be true. - - The assumption made is that the average time spent in each call to -any function `foo' is not correlated with who called `foo'. If `foo' -used 5 seconds in all, and 2/5 of the calls to `foo' came from `a', -then `foo' contributes 2 seconds to `a''s `children' time, by -assumption. - - This assumption is usually true enough, but for some programs it is -far from true. Suppose that `foo' returns very quickly when its -argument is zero; suppose that `a' always passes zero as an argument, -while other callers of `foo' pass other arguments. In this program, -all the time spent in `foo' is in the calls from callers other than `a'. -But `gprof' has no way of knowing this; it will blindly and incorrectly -charge 2 seconds of time in `foo' to the children of `a'. - - We hope some day to put more complete data into `gmon.out', so that -this assumption is no longer needed, if we can figure out how. For the -nonce, the estimated figures are usually more useful than misleading. - - -File: gprof.info, Node: Incompatibilities, Prev: Assumptions, Up: Top - -Incompatibilities with Unix `gprof' -*********************************** - - GNU `gprof' and Berkeley Unix `gprof' use the same data file -`gmon.out', and provide essentially the same information. But there -are a few differences. - - * For a recursive function, Unix `gprof' lists the function as a - parent and as a child, with a `calls' field that lists the number - of recursive calls. GNU `gprof' omits these lines and puts the - number of recursive calls in the primary line. - - * When a function is suppressed from the call graph with `-e', GNU - `gprof' still lists it as a subroutine of functions that call it. - - * The blurbs, field widths, and output formats are different. GNU - `gprof' prints blurbs after the tables, so that you can see the - tables without skipping the blurbs. - - - -Tag Table: -Node: Top888 -Node: Why2593 -Node: Compiling4687 -Node: Executing6671 -Node: Invoking8782 -Node: Flat Profile14056 -Node: Call Graph17742 -Node: Primary20981 -Node: Callers23514 -Node: Subroutines25621 -Node: Cycles27280 -Node: Implementation34044 -Node: Sampling Error36144 -Node: Assumptions38463 -Node: Incompatibilities39988 - -End Tag Table diff --git a/gnu/usr.bin/binutils/gprof/gprof.texi b/gnu/usr.bin/binutils/gprof/gprof.texi index ba05b594d65..bb1490de7e5 100644 --- a/gnu/usr.bin/binutils/gprof/gprof.texi +++ b/gnu/usr.bin/binutils/gprof/gprof.texi @@ -294,6 +294,12 @@ function that was loaded directly before it in the executable file. @c This is compatible with Unix @code{gprof}, but a bad idea. This option affects both the flat profile and the call graph. +@item -D +The @samp{-D} option causes @code{gprof} to ignore symbols which +are not known to be functions. This option will give more accurate +profile data on systems where it is supported (Solaris and HPUX for +example). + @item -e @var{function_name} The @samp{-e @var{function}} option tells @code{gprof} to not print information about the function @var{function_name} (and its @@ -388,6 +394,46 @@ cumulative data in the file @file{gmon.sum}. @item -T The @samp{-T} option causes @code{gprof} to print its output in ``traditional'' BSD style. + +@item --function-ordering +The @samp{--function-ordering} option causes @code{gprof} to print a +suggested function ordering for the program based on profiling data. +This option suggests an ordering which may improve paging, tlb and +cache behavior for the program on systems which support arbitrary +ordering of functions in an executable. + +The exact details of how to force the linker to place functions +in a particular order is system dependent and out of the scope of this +manual. + +@item --file-ordering @var{map_file} +The @samp{--file-ordering} option causes @code{gprof} to print a +suggested .o link line ordering for the program based on profiling data. +This option suggests an ordering which may improve paging, tlb and +cache behavior for the program on systems which do not support arbitrary +ordering of functions in an executable. + +Use of the @samp{-a} argument is highly recommended with this option. + +The @var{map_file} argument is a pathname to a file which provides +function name to object file mappings. The format of the file is similar to +the output of the program @code{nm}. + +@smallexample +@group +c-parse.o:00000000 T yyparse +c-parse.o:00000004 C yyerrflag +c-lang.o:00000000 T maybe_objc_method_name +c-lang.o:00000000 T print_lang_statistics +c-lang.o:00000000 T recognize_objc_keyword +c-decl.o:00000000 T print_lang_identifier +c-decl.o:00000000 T print_lang_type +@dots{} + +@end group +@end smallexample + +GNU @code{nm} @samp{--extern-only} @samp{--defined-only} @samp{-v} @samp{--print-file-name} can be used to create @var{map_file}. @end table @node Flat Profile diff --git a/gnu/usr.bin/binutils/gprof/hist.c b/gnu/usr.bin/binutils/gprof/hist.c index 69cc3ea004a..717424d5791 100644 --- a/gnu/usr.bin/binutils/gprof/hist.c +++ b/gnu/usr.bin/binutils/gprof/hist.c @@ -210,28 +210,25 @@ DEFUN (hist_write_hist, (ofp, filename), FILE * ofp AND const char *filename) * next bin. */ static void -DEFUN_VOID (scale_and_align_entries) +scale_and_align_entries () { Sym *sym; -#if OFFSET_TO_CODE > 0 bfd_vma bin_of_entry; bfd_vma bin_of_code; -#endif for (sym = symtab.base; sym < symtab.limit; sym++) { sym->hist.scaled_addr = sym->addr / sizeof (UNIT); -#if OFFSET_TO_CODE > 0 bin_of_entry = (sym->hist.scaled_addr - lowpc) / hist_scale; bin_of_code = (sym->hist.scaled_addr + UNITS_TO_CODE - lowpc) / hist_scale; if (bin_of_entry < bin_of_code) { DBG (SAMPLEDEBUG, printf ("[scale_and_align_entries] pushing 0x%lx to 0x%lx\n", - sym->hist.scaled_addr, sym->aligned_addr + UNITS_TO_CODE)); - sym->aligned_addr += UNITS_TO_CODE; + sym->hist.scaled_addr, + sym->hist.scaled_addr + UNITS_TO_CODE)); + sym->hist.scaled_addr += UNITS_TO_CODE; } -#endif /* OFFSET_TO_CODE > 0 */ } } diff --git a/gnu/usr.bin/binutils/gprof/symtab.c b/gnu/usr.bin/binutils/gprof/symtab.c index 6fd48c3c8f5..b38ae6a62de 100644 --- a/gnu/usr.bin/binutils/gprof/symtab.c +++ b/gnu/usr.bin/binutils/gprof/symtab.c @@ -93,10 +93,10 @@ DEFUN (symtab_finalize, (tab), Sym_Table * tab) * symbols (such as __gnu_compiled, __c89_used, etc.). */ if ((!src->is_static && dst[-1].is_static) - || ((src->is_static == dst[-1].is_static) && - (src->name[0] != '_' && dst[-1].name[0] == '_') - || (src->name[0] - && src->name[1] != '_' && dst[-1].name[1] == '_'))) + || ((src->is_static == dst[-1].is_static) + && ((src->name[0] != '_' && dst[-1].name[0] == '_') + || (src->name[0] + && src->name[1] != '_' && dst[-1].name[1] == '_')))) { DBG (AOUTDEBUG | IDDEBUG, printf ("[symtab_finalize] favor %s@%c%c over %s@%c%c", diff --git a/gnu/usr.bin/binutils/gprof/symtab.h b/gnu/usr.bin/binutils/gprof/symtab.h index 07c7751ed6d..304e6b5c020 100644 --- a/gnu/usr.bin/binutils/gprof/symtab.h +++ b/gnu/usr.bin/binutils/gprof/symtab.h @@ -36,9 +36,14 @@ typedef struct sym int line_num; /* source line number */ unsigned int is_func:1, /* is this a function entry point? */ is_static:1, /* is this a local (static) symbol? */ - is_bb_head:1; /* is this the head of a basic-blk? */ + is_bb_head:1, /* is this the head of a basic-blk? */ + mapped:1, /* this symbol was mapped to another name */ + has_been_placed:1; /* have we placed this symbol? */ int ncalls; /* how many times executed */ + int nuses; /* how many times this symbol appears in + a particular context */ struct sym *next; /* for building chains of syms */ + struct sym *prev; /* for building chains of syms */ /* profile-specific information: */ diff --git a/gnu/usr.bin/binutils/gprof/vax.c b/gnu/usr.bin/binutils/gprof/vax.c index 9d7fa835d00..6a1034c82d3 100644 --- a/gnu/usr.bin/binutils/gprof/vax.c +++ b/gnu/usr.bin/binutils/gprof/vax.c @@ -21,7 +21,6 @@ #include "core.h" #include "hist.h" #include "symtab.h" -#include "vax.h" /* * A symbol to be the child of indirect calls: |