Add copy of GPL.
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
+2000-07-24 Nick Clifton <nickc@cygnus.com>
+
+ * COPYING: New file: Describes GPL.
+
+ * basic_blocks.c: Add copyright notice.
+ * basic_blocks.h: Add copyright notice.
+ * call_graph.c: Add copyright notice.
+ * call_graph.h: Add copyright notice.
+ * cg_print.c: Add copyright notice.
+ * cg_print.h: Add copyright notice.
+ * corefile.c: Add copyright notice.
+ * corefile.h: Add copyright notice.
+ * gmon_io.c: Add copyright notice.
+ * gmon_io.h: Add copyright notice.
+ * gmon_out.h: Add copyright notice.
+ * hist.c: Add copyright notice.
+ * hist.h: Add copyright notice.
+ * search_list.c: Add copyright notice.
+ * search_list.h: Add copyright notice.
+ * source.c: Add copyright notice.
+ * source.h: Add copyright notice.
+ * sym_ids.c: Add copyright notice.
+ * sym_ids.h: Add copyright notice.
+ * symtab.c: Add copyright notice.
+ * symtab.h: Add copyright notice.
+
2000-07-05 Kenneth Block <krblock@computer.org>
* gprof/gprof.c: Add optional style to demangle switch
-/*
- * Basic-block level related code: reading/writing of basic-block info
- * to/from gmon.out; computing and formatting of basic-block related
- * statistics.
- */
+/* basic_blocks.c - Basic-block level related code: reading/writing
+ of basic-block info to/from gmon.out; computing and formatting of
+ basic-block related statistics.
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+\f
#include <stdio.h>
#include <unistd.h>
#include "basic_blocks.h"
#include "source.h"
#include "sym_ids.h"
-
-/*
- * Default option values:
- */
+/* Default option values: */
bool bb_annotate_all_lines = FALSE;
unsigned long bb_min_calls = 1;
int bb_table_length = 10;
-/*
- * Variables used to compute annotated source listing stats:
- */
+/* Variables used to compute annotated source listing stats: */
static long num_executable_lines;
static long num_lines_executed;
-/*
- * Helper for sorting. Compares two symbols and returns result
- * such that sorting will be increasing according to filename, line
- * number, and address (in that order).
- */
+/* Helper for sorting. Compares two symbols and returns result
+ such that sorting will be increasing according to filename, line
+ number, and address (in that order). */
static int
DEFUN (cmp_bb, (lp, rp), const void *lp AND const void *rp)
if (left->file && right->file)
{
r = strcmp (left->file->name, right->file->name);
+
if (r)
- {
- return r;
- }
+ return r;
if (left->line_num != right->line_num)
- {
- return left->line_num - right->line_num;
- }
+ return left->line_num - right->line_num;
}
if (left->addr < right->addr)
- {
- return -1;
- }
+ return -1;
else if (left->addr > right->addr)
- {
- return 1;
- }
+ return 1;
else
- {
- return 0;
- }
+ return 0;
}
-/*
- * Helper for sorting. Order basic blocks in decreasing number of
- * calls, ties are broken in increasing order of line numbers.
- */
+/* Helper for sorting. Order basic blocks in decreasing number of
+ calls, ties are broken in increasing order of line numbers. */
static int
DEFUN (cmp_ncalls, (lp, rp), const void *lp AND const void *rp)
{
const Sym *right = *(const Sym **) rp;
if (!left)
- {
- return 1;
- }
+ return 1;
else if (!right)
- {
- return -1;
- }
+ return -1;
if (left->ncalls < right->ncalls)
return 1;
return left->line_num - right->line_num;
}
-
-/*
- * Skip over variable length string.
- */
+/* Skip over variable length string. */
static void
DEFUN (fskip_string, (fp), FILE * fp)
{
while ((ch = fgetc (fp)) != EOF)
{
if (ch == '\0')
- {
- break;
- }
+ break;
}
}
+/* Read a basic-block record from file IFP. FILENAME is the name
+ of file IFP and is provided for formatting error-messages only. */
-/*
- * Read a basic-block record from file IFP. FILENAME is the name
- * of file IFP and is provided for formatting error-messages only.
- */
void
DEFUN (bb_read_rec, (ifp, filename), FILE * ifp AND const char *filename)
{
}
nblocks = bfd_get_32 (core_bfd, (bfd_byte *) & nblocks);
+
if (gmon_file_version == 0)
- {
- fskip_string (ifp);
- }
+ fskip_string (ifp);
for (b = 0; b < nblocks; ++b)
{
if (gmon_file_version == 0)
{
int line_num;
- /*
- * Version 0 had lots of extra stuff that we don't
- * care about anymore.
- */
+
+ /* Version 0 had lots of extra stuff that we don't
+ care about anymore. */
if ((fread (&ncalls, sizeof (ncalls), 1, ifp) != 1)
|| (fread (&addr, sizeof (addr), 1, ifp) != 1)
|| (fskip_string (ifp), FALSE)
}
}
- /*
- * Basic-block execution counts are meaningful only if we're
- * profiling at the line-by-line level:
- */
+ /* Basic-block execution counts are meaningful only if we're
+ profiling at the line-by-line level: */
if (line_granularity)
{
-
- /* convert from target to host endianness: */
-
+ /* Convert from target to host endianness: */
addr = get_vma (core_bfd, (bfd_byte *) & addr);
ncalls = bfd_get_32 (core_bfd, (bfd_byte *) &ncalls);
{
user_warned = TRUE;
fprintf (stderr,
- _("%s: warning: ignoring basic-block exec counts (use -l or --line)\n"),
+ _("%s: warning: ignoring basic-block exec counts (use -l or --line)\n"),
whoami);
}
}
return;
}
-
-/*
- * Write all basic-blocks with non-zero counts to file OFP. FILENAME
- * is the name of OFP and is provided for producing error-messages
- * only.
- */
+/* Write all basic-blocks with non-zero counts to file OFP. FILENAME
+ is the name of OFP and is provided for producing error-messages
+ only. */
void
DEFUN (bb_write_blocks, (ofp, filename), FILE * ofp AND const char *filename)
{
Sym *sym;
int i;
- /* count how many non-zero blocks with have: */
-
+ /* Count how many non-zero blocks with have: */
for (sym = symtab.base; sym < symtab.limit; ++sym)
{
for (i = 0; i < NBBS && sym->bb_addr[i]; i++)
nblocks += i;
}
- /* write header: */
+ /* Write header: */
bfd_put_32 (core_bfd, nblocks, (bfd_byte *) & nblocks);
if (fwrite (&tag, sizeof (tag), 1, ofp) != 1
|| fwrite (&nblocks, sizeof (nblocks), 1, ofp) != 1)
done (1);
}
- /* write counts: */
+ /* Write counts: */
for (sym = symtab.base; sym < symtab.limit; ++sym)
{
for (i = 0; i < NBBS && sym->bb_addr[i]; i++)
}
}
+/* Output basic-block statistics in a format that is easily parseable.
+ Current the format is:
+
+ <filename>:<line-number>: (<function-name>:<bb-addr): <ncalls> */
-/*
- * Output basic-block statistics in a format that is easily parseable.
- * Current the format is:
- *
- * <filename>:<line-number>: (<function-name>:<bb-addr): <ncalls>
- */
void
DEFUN_VOID (print_exec_counts)
{
int i, j, len;
if (first_output)
- {
- first_output = FALSE;
- }
+ first_output = FALSE;
else
- {
- printf ("\f\n");
- }
-
- /* sort basic-blocks according to function name and line number: */
+ printf ("\f\n");
+ /* Sort basic-blocks according to function name and line number: */
sorted_bbs = (Sym **) xmalloc (symtab.len * sizeof (sorted_bbs[0]));
len = 0;
+
for (sym = symtab.base; sym < symtab.limit; ++sym)
{
- /*
- * Accept symbol if it's in the INCL_EXEC table
- * or there is no INCL_EXEC table
- * and it does not appear in the EXCL_EXEC table.
- */
+ /* Accept symbol if it's in the INCL_EXEC table
+ or there is no INCL_EXEC table
+ and it does not appear in the EXCL_EXEC table. */
if (sym_lookup (&syms[INCL_EXEC], sym->addr)
|| (syms[INCL_EXEC].len == 0
&& !sym_lookup (&syms[EXCL_EXEC], sym->addr)))
sorted_bbs[len++] = sym;
}
}
+
qsort (sorted_bbs, len, sizeof (sorted_bbs[0]), cmp_bb);
- /* output basic-blocks: */
+ /* Output basic-blocks: */
for (i = 0; i < len; ++i)
{
sym->file ? sym->file->name : _("<unknown>"), sym->line_num,
sym->name, (unsigned long) sym->addr, sym->ncalls);
}
+
for (j = 0; j < NBBS && sym->bb_addr[j]; j ++)
{
if (sym->bb_calls[j] > 0 || ! ignore_zeros)
free (sorted_bbs);
}
-/*
- * Helper for bb_annotated_source: format annotation containing
- * number of line executions. Depends on being called on each
- * line of a file in sequential order.
- *
- * Global variable bb_annotate_all_lines enables execution count
- * compression (counts are supressed if identical to the last one)
- * and prints counts on all executed lines. Otherwise, print
- * all basic-block execution counts exactly once on the line
- * that starts the basic-block.
- */
+/* Helper for bb_annotated_source: format annotation containing
+ number of line executions. Depends on being called on each
+ line of a file in sequential order.
+
+ Global variable bb_annotate_all_lines enables execution count
+ compression (counts are supressed if identical to the last one)
+ and prints counts on all executed lines. Otherwise, print
+ all basic-block execution counts exactly once on the line
+ that starts the basic-block. */
static void
DEFUN (annotate_with_count, (buf, width, line_num, arg),
unsigned long last_print = (unsigned long) -1;
b = NULL;
+
if (line_num <= sf->num_lines)
- {
- b = sf->line[line_num - 1];
- }
+ b = sf->line[line_num - 1];
+
if (!b)
{
for (i = 0; i < width; i++)
ncalls_set = 0;
/* If this is a function entry point, label the line no matter what.
- * Otherwise, we're in the middle of a function, so check to see
- * if the first basic-block address is larger than the starting
- * address of the line. If so, then this line begins with a
- * a portion of the previous basic-block, so print that prior
- * execution count (if bb_annotate_all_lines is set).
- */
-
+ Otherwise, we're in the middle of a function, so check to see
+ if the first basic-block address is larger than the starting
+ address of the line. If so, then this line begins with a
+ a portion of the previous basic-block, so print that prior
+ execution count (if bb_annotate_all_lines is set). */
if (b->is_func)
{
sprintf (p, "%lu", b->ncalls);
}
/* Loop through all of this line's basic-blocks. For each one,
- * update last_count, then compress sequential identical counts
- * (if bb_annotate_all_lines) and print the execution count.
- */
+ update last_count, then compress sequential identical counts
+ (if bb_annotate_all_lines) and print the execution count. */
for (i = 0; i < NBBS && b->bb_addr[i]; i++)
{
ncalls += last_count;
if (bb_annotate_all_lines && last_count == last_print)
- {
- continue;
- }
+ continue;
if (p > tmpbuf)
*p++ = ',';
}
/* We're done. If nothing has been printed on this line,
- * print the last execution count (bb_annotate_all_lines),
- * which could be from either a previous line (if there were
- * no BBs on this line), or from this line (if all our BB
- * counts were compressed out because they were identical).
- */
+ print the last execution count (bb_annotate_all_lines),
+ which could be from either a previous line (if there were
+ no BBs on this line), or from this line (if all our BB
+ counts were compressed out because they were identical). */
if (bb_annotate_all_lines && p == tmpbuf)
{
}
}
-/*
- * Annotate the files named in SOURCE_FILES with basic-block statistics
- * (execution counts). After each source files, a few statistics
- * regarding that source file are printed.
- */
+/* Annotate the files named in SOURCE_FILES with basic-block statistics
+ (execution counts). After each source files, a few statistics
+ regarding that source file are printed. */
+
void
DEFUN_VOID (print_annotated_source)
{
int i, table_len;
FILE *ofp;
- /*
- * Find maximum line number for each source file that user is
- * interested in:
- */
+ /* Find maximum line number for each source file that user is
+ interested in: */
for (sym = symtab.base; sym < symtab.limit; ++sym)
{
- /*
- * Accept symbol if it's file is known, its line number is
- * bigger than anything we have seen for that file so far and
- * if it's in the INCL_ANNO table or there is no INCL_ANNO
- * table and it does not appear in the EXCL_ANNO table.
- */
+ /* Accept symbol if it's file is known, its line number is
+ bigger than anything we have seen for that file so far and
+ if it's in the INCL_ANNO table or there is no INCL_ANNO
+ table and it does not appear in the EXCL_ANNO table. */
if (sym->file && sym->line_num > sym->file->num_lines
&& (sym_lookup (&syms[INCL_ANNO], sym->addr)
|| (syms[INCL_ANNO].len == 0
}
}
- /* allocate line descriptors: */
-
+ /* Allocate line descriptors: */
for (sf = first_src_file; sf; sf = sf->next)
{
if (sf->num_lines > 0)
}
}
- /* count executions per line: */
-
+ /* Count executions per line: */
for (sym = symtab.base; sym < symtab.limit; ++sym)
{
if (sym->file && sym->file->num_lines
{
sym->file->ncalls += sym->ncalls;
line_stats = sym->file->line[sym->line_num - 1];
+
if (!line_stats)
{
- /* common case has at most one basic-block per source line: */
+ /* Common case has at most one basic-block per source line: */
sym->file->line[sym->line_num - 1] = sym;
}
else if (!line_stats->addr)
{
- /* sym is the 3rd .. nth basic block for this line: */
+ /* sym is the 3rd .. nth basic block for this line: */
line_stats->ncalls += sym->ncalls;
}
else
{
- /* sym is the second basic block for this line */
+ /* sym is the second basic block for this line. */
new_line = (Sym *) xmalloc (sizeof (*new_line));
*new_line = *line_stats;
new_line->addr = 0;
}
}
- /* plod over source files, annotating them: */
-
+ /* Plod over source files, annotating them: */
for (sf = first_src_file; sf; sf = sf->next)
{
if (!sf->num_lines || (ignore_zeros && sf->ncalls == 0))
- {
- continue;
- }
+ continue;
num_executable_lines = num_lines_executed = 0;
+
ofp = annotate_source (sf, 16, annotate_with_count, sf);
if (!ofp)
- {
- continue;
- }
+ continue;
if (bb_table_length > 0)
{
fprintf (ofp, _("\n\nTop %d Lines:\n\n Line Count\n\n"),
bb_table_length);
- /* abuse line arrays---it's not needed anymore: */
+ /* Abuse line arrays---it's not needed anymore: */
qsort (sf->line, sf->num_lines, sizeof (sf->line[0]), cmp_ncalls);
table_len = bb_table_length;
+
if (table_len > sf->num_lines)
- {
- table_len = sf->num_lines;
- }
+ table_len = sf->num_lines;
+
for (i = 0; i < table_len; ++i)
{
sym = sf->line[i];
+
if (!sym || sym->ncalls == 0)
- {
break;
- }
+
fprintf (ofp, "%9d %10lu\n", sym->line_num, sym->ncalls);
}
}
num_executable_lines
? (double) sf->ncalls / (double) num_executable_lines
: 0.0);
+
if (ofp != stdout)
- {
- fclose (ofp);
- }
+ fclose (ofp);
}
}
+/* basic_blocks.h
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+\f
#ifndef basic_blocks_h
#define basic_blocks_h
#include "source.h"
#include "symtab.h"
-/*
- * Options:
- */
-extern bool bb_annotate_all_lines; /* force annotation of all lines? */
-extern int bb_table_length; /* length of most-used bb table */
-extern unsigned long bb_min_calls; /* minimum execution count */
-
-extern void bb_read_rec PARAMS ((FILE * ifp, const char *filename));
-extern void bb_write_blocks PARAMS ((FILE * ofp, const char *filename));
-extern void bb_create_syms PARAMS ((void));
-
-extern void print_annotated_source PARAMS ((void));
-extern void print_exec_counts PARAMS ((void));
+/* Options: */
+extern bool bb_annotate_all_lines; /* Force annotation of all lines? */
+extern int bb_table_length; /* Length of most-used bb table. */
+extern unsigned long bb_min_calls; /* Minimum execution count. */
+extern void bb_read_rec PARAMS ((FILE *, const char *));
+extern void bb_write_blocks PARAMS ((FILE *, const char *));
+extern void bb_create_syms PARAMS ((void));
+extern void print_annotated_source PARAMS ((void));
+extern void print_exec_counts PARAMS ((void));
#endif /* basic_blocks_h */
+/* call_graph.c - Create call graphs.
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+\f
#include "cg_arcs.h"
#include "call_graph.h"
#include "corefile.h"
For normal profiling, is_func will be set on all symbols, so this
code will do nothing. */
-
while (child >= symtab.base && ! child->is_func)
--child;
if (child < symtab.base)
return;
- /*
- * Keep arc if it is on INCL_ARCS table or if the INCL_ARCS table
- * is empty and it is not in the EXCL_ARCS table.
- */
+ /* Keep arc if it is on INCL_ARCS table or if the INCL_ARCS table
+ is empty and it is not in the EXCL_ARCS table. */
if (sym_id_arc_is_present (&syms[INCL_ARCS], parent, child)
|| (syms[INCL_ARCS].len == 0
&& !sym_id_arc_is_present (&syms[EXCL_ARCS], parent, child)))
}
}
+/* Read a record from file IFP describing an arc in the function
+ call-graph and the count of how many times the arc has been
+ traversed. FILENAME is the name of file IFP and is provided
+ for formatting error-messages only. */
-/*
- * Read a record from file IFP describing an arc in the function
- * call-graph and the count of how many times the arc has been
- * traversed. FILENAME is the name of file IFP and is provided
- * for formatting error-messages only.
- */
void
DEFUN (cg_read_rec, (ifp, filename), FILE * ifp AND CONST char *filename)
{
whoami, filename);
done (1);
}
+
from_pc = get_vma (core_bfd, (bfd_byte *) arc.from_pc);
self_pc = get_vma (core_bfd, (bfd_byte *) arc.self_pc);
count = bfd_get_32 (core_bfd, (bfd_byte *) arc.count);
DBG (SAMPLEDEBUG,
printf ("[cg_read_rec] frompc 0x%lx selfpc 0x%lx count %lu\n",
(unsigned long) from_pc, (unsigned long) self_pc, count));
- /* add this arc: */
+ /* Add this arc: */
cg_tally (from_pc, self_pc, count);
}
+/* Write all the arcs in the call-graph to file OFP. FILENAME is
+ the name of OFP and is provided for formatting error-messages
+ only. */
-/*
- * Write all the arcs in the call-graph to file OFP. FILENAME is
- * the name of OFP and is provided for formatting error-messages
- * only.
- */
void
DEFUN (cg_write_arcs, (ofp, filename), FILE * ofp AND const char *filename)
{
+/* call_graph.h
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+\f
#ifndef call_graph_h
#define call_graph_h
#include "gprof.h"
#include "symtab.h"
-extern void cg_tally PARAMS ((bfd_vma from_pc, bfd_vma self_pc,
- unsigned long count));
-extern void cg_read_rec PARAMS ((FILE * ifp, const char *filename));
-extern void cg_write_arcs PARAMS ((FILE * ofp, const char *filename));
+extern void cg_tally PARAMS ((bfd_vma, bfd_vma, unsigned long));
+extern void cg_read_rec PARAMS ((FILE *, const char *));
+extern void cg_write_arcs PARAMS ((FILE *, const char *));
#endif /* call_graph_h */
+/* cg_print.c - Print routines for displaying call graphs.
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+\f
#include "libiberty.h"
#include "cg_arcs.h"
#include "cg_print.h"
#include "hist.h"
#include "utils.h"
-/*
- * Return value of comparison functions used to sort tables:
- */
+/* Return value of comparison functions used to sort tables. */
#define LESSTHAN -1
#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: */
+/* Declarations of automatically generated functions to output blurbs. */
extern void bsd_callg_blurb PARAMS ((FILE * fp));
extern void fsf_callg_blurb PARAMS ((FILE * fp));
DEFUN_VOID (print_header)
{
if (first_output)
- {
- first_output = FALSE;
- }
+ first_output = FALSE;
else
- {
- printf ("\f\n");
- }
+ printf ("\f\n");
+
if (!bsd_style_output)
{
if (print_descriptions)
- {
- printf (_("\t\t Call graph (explanation follows)\n\n"));
- }
+ printf (_("\t\t Call graph (explanation follows)\n\n"));
else
- {
- printf (_("\t\t\tCall graph\n\n"));
- }
+ printf (_("\t\t\tCall graph\n\n"));
}
+
printf (_("\ngranularity: each sample hit covers %ld byte(s)"),
(long) hist_scale * sizeof (UNIT));
+
if (print_time > 0.0)
- {
- printf (_(" for %.2f%% of %.2f seconds\n\n"),
- 100.0 / print_time, print_time / hz);
- }
+ printf (_(" for %.2f%% of %.2f seconds\n\n"),
+ 100.0 / print_time, print_time / hz);
else
{
printf (_(" no time propagated\n\n"));
- /*
- * This doesn't hurt, since all the numerators will be 0.0:
- */
+
+ /* This doesn't hurt, since all the numerators will be 0.0. */
print_time = 1.0;
}
+
if (bsd_style_output)
{
printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n",
}
}
+/* Print a cycle header. */
-/*
- * Print a cycle header.
- */
static void
DEFUN (print_cycle, (cyc), Sym * cyc)
{
: "%-6.6s %5.1f %7.2f %7.2f %7lu", buf,
100 * (cyc->cg.prop.self + cyc->cg.prop.child) / print_time,
cyc->cg.prop.self / hz, cyc->cg.prop.child / hz, cyc->ncalls);
+
if (cyc->cg.self_calls != 0)
- {
- printf ("+%-7lu", cyc->cg.self_calls);
- }
+ printf ("+%-7lu", cyc->cg.self_calls);
else
- {
- printf (" %7.7s", "");
- }
+ printf (" %7.7s", "");
+
printf (_(" <cycle %d as a whole> [%d]\n"), cyc->cg.cyc.num, cyc->cg.index);
}
+/* Compare LEFT and RIGHT membmer. Major comparison key is
+ CG.PROP.SELF+CG.PROP.CHILD, secondary key is NCALLS+CG.SELF_CALLS. */
-/*
- * Compare LEFT and RIGHT membmer. Major comparison key is
- * CG.PROP.SELF+CG.PROP.CHILD, secondary key is NCALLS+CG.SELF_CALLS.
- */
static int
DEFUN (cmp_member, (left, right), Sym * left AND Sym * right)
{
unsigned long right_calls = right->ncalls + right->cg.self_calls;
if (left_time > right_time)
- {
- return GREATERTHAN;
- }
+ return GREATERTHAN;
+
if (left_time < right_time)
- {
- return LESSTHAN;
- }
+ return LESSTHAN;
if (left_calls > right_calls)
- {
- return GREATERTHAN;
- }
+ return GREATERTHAN;
+
if (left_calls < right_calls)
- {
- return LESSTHAN;
- }
+ return LESSTHAN;
+
return EQUALTO;
}
+/* Sort members of a cycle. */
-/*
- * Sort members of a cycle.
- */
static void
DEFUN (sort_members, (cyc), Sym * cyc)
{
Sym *todo, *doing, *prev;
- /*
- * Detach cycle members from cyclehead, and insertion sort them
- * back on.
- */
+
+ /* Detach cycle members from cyclehead,
+ and insertion sort them back on. */
todo = cyc->cg.cyc.next;
cyc->cg.cyc.next = 0;
+
for (doing = todo; doing && doing->cg.cyc.next; doing = todo)
{
todo = doing->cg.cyc.next;
+
for (prev = cyc; prev->cg.cyc.next; prev = prev->cg.cyc.next)
{
if (cmp_member (doing, prev->cg.cyc.next) == GREATERTHAN)
- {
- break;
- }
+ break;
}
+
doing->cg.cyc.next = prev->cg.cyc.next;
prev->cg.cyc.next = doing;
}
}
+/* Print the members of a cycle. */
-/*
- * Print the members of a cycle.
- */
static void
DEFUN (print_members, (cyc), Sym * cyc)
{
Sym *member;
sort_members (cyc);
+
for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next)
{
printf (bsd_style_output
: "%6.6s %5.5s %7.2f %7.2f %7lu",
"", "", member->cg.prop.self / hz, member->cg.prop.child / hz,
member->ncalls);
+
if (member->cg.self_calls != 0)
- {
- printf ("+%-7lu", member->cg.self_calls);
- }
+ printf ("+%-7lu", member->cg.self_calls);
else
- {
- printf (" %7.7s", "");
- }
+ printf (" %7.7s", "");
+
printf (" ");
print_name (member);
printf ("\n");
}
}
+/* Compare two arcs to/from the same child/parent.
+ - if one arc is a self arc, it's least.
+ - if one arc is within a cycle, it's less than.
+ - if both arcs are within a cycle, compare arc counts.
+ - if neither arc is within a cycle, compare with
+ time + child_time as major key
+ arc count as minor key. */
-/*
- * Compare two arcs to/from the same child/parent.
- * - if one arc is a self arc, it's least.
- * - if one arc is within a cycle, it's less than.
- * - if both arcs are within a cycle, compare arc counts.
- * - if neither arc is within a cycle, compare with
- * time + child_time as major key
- * arc count as minor key
- */
static int
DEFUN (cmp_arc, (left, right), Arc * left AND Arc * right)
{
right->count, right_child->ncalls);
printf ("\n");
);
+
if (left_parent == left_child)
- {
- return LESSTHAN; /* left is a self call */
- }
+ return LESSTHAN; /* Left is a self call. */
+
if (right_parent == right_child)
- {
- return GREATERTHAN; /* right is a self call */
- }
+ return GREATERTHAN; /* Right is a self call. */
if (left_parent->cg.cyc.num != 0 && left_child->cg.cyc.num != 0
&& left_parent->cg.cyc.num == left_child->cg.cyc.num)
{
- /* left is a call within a cycle */
+ /* Left is a call within a cycle. */
if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0
&& right_parent->cg.cyc.num == right_child->cg.cyc.num)
{
- /* right is a call within the cycle, too */
+ /* Right is a call within the cycle, too. */
if (left->count < right->count)
- {
- return LESSTHAN;
- }
+ return LESSTHAN;
+
if (left->count > right->count)
- {
- return GREATERTHAN;
- }
+ return GREATERTHAN;
+
return EQUALTO;
}
else
{
- /* right isn't a call within the cycle */
+ /* Right isn't a call within the cycle. */
return LESSTHAN;
}
}
else
{
- /* left isn't a call within a cycle */
+ /* Left isn't a call within a cycle. */
if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0
&& right_parent->cg.cyc.num == right_child->cg.cyc.num)
{
- /* right is a call within a cycle */
+ /* Right is a call within a cycle. */
return GREATERTHAN;
}
else
{
- /* neither is a call within a cycle */
+ /* Neither is a call within a cycle. */
left_time = left->time + left->child_time;
right_time = right->time + right->child_time;
+
if (left_time < right_time)
- {
- return LESSTHAN;
- }
+ return LESSTHAN;
+
if (left_time > right_time)
- {
- return GREATERTHAN;
- }
+ return GREATERTHAN;
+
if (left->count < right->count)
- {
- return LESSTHAN;
- }
+ return LESSTHAN;
+
if (left->count > right->count)
- {
- return GREATERTHAN;
- }
+ return GREATERTHAN;
+
return EQUALTO;
}
}
{
Arc *arc, *detached, sorted, *prev;
- /*
- * Unlink parents from child, then insertion sort back on to
- * sorted's parents.
- * *arc the arc you have detached and are inserting.
- * *detached the rest of the arcs to be sorted.
- * sorted arc list onto which you insertion sort.
- * *prev arc before the arc you are comparing.
- */
+ /* Unlink parents from child, then insertion sort back on to
+ sorted's parents.
+ *arc the arc you have detached and are inserting.
+ *detached the rest of the arcs to be sorted.
+ sorted arc list onto which you insertion sort.
+ *prev arc before the arc you are comparing. */
sorted.next_parent = 0;
+
for (arc = child->cg.parents; arc; arc = detached)
{
detached = arc->next_parent;
- /* consider *arc as disconnected; insert it into sorted: */
+ /* Consider *arc as disconnected; insert it into sorted. */
for (prev = &sorted; prev->next_parent; prev = prev->next_parent)
{
if (cmp_arc (arc, prev->next_parent) != GREATERTHAN)
- {
- break;
- }
+ break;
}
+
arc->next_parent = prev->next_parent;
prev->next_parent = arc;
}
- /* reattach sorted arcs to child: */
+ /* Reattach sorted arcs to child. */
child->cg.parents = sorted.next_parent;
}
Sym *cycle_head;
if (child->cg.cyc.head != 0)
- {
- cycle_head = child->cg.cyc.head;
- }
+ cycle_head = child->cg.cyc.head;
else
- {
- cycle_head = child;
- }
+ cycle_head = child;
+
if (!child->cg.parents)
{
printf (bsd_style_output
"", "", "", "", "", "");
return;
}
+
sort_parents (child);
+
for (arc = child->cg.parents; arc; arc = arc->next_parent)
{
parent = arc->parent;
if (child == parent || (child->cg.cyc.num != 0
&& parent->cg.cyc.num == child->cg.cyc.num))
{
- /* selfcall or call among siblings: */
+ /* Selfcall or call among siblings. */
printf (bsd_style_output
? "%6.6s %5.5s %7.7s %11.11s %7lu %7.7s "
: "%6.6s %5.5s %7.7s %7.7s %7lu %7.7s ",
}
else
{
- /* regular parent of child: */
+ /* Regular parent of child. */
printf (bsd_style_output
? "%6.6s %5.5s %7.2f %11.2f %7lu/%-7lu "
: "%6.6s %5.5s %7.2f %7.2f %7lu/%-7lu ",
DEFUN (sort_children, (parent), Sym * parent)
{
Arc *arc, *detached, sorted, *prev;
- /*
- * Unlink children from parent, then insertion sort back on to
- * sorted's children.
- * *arc the arc you have detached and are inserting.
- * *detached the rest of the arcs to be sorted.
- * sorted arc list onto which you insertion sort.
- * *prev arc before the arc you are comparing.
- */
+
+ /* Unlink children from parent, then insertion sort back on to
+ sorted's children.
+ *arc the arc you have detached and are inserting.
+ *detached the rest of the arcs to be sorted.
+ sorted arc list onto which you insertion sort.
+ *prev arc before the arc you are comparing. */
sorted.next_child = 0;
+
for (arc = parent->cg.children; arc; arc = detached)
{
detached = arc->next_child;
- /* consider *arc as disconnected; insert it into sorted: */
+ /* Consider *arc as disconnected; insert it into sorted. */
for (prev = &sorted; prev->next_child; prev = prev->next_child)
{
if (cmp_arc (arc, prev->next_child) != LESSTHAN)
- {
- break;
- }
+ break;
}
+
arc->next_child = prev->next_child;
prev->next_child = arc;
}
- /* reattach sorted children to parent: */
+ /* Reattach sorted children to parent. */
parent->cg.children = sorted.next_child;
}
sort_children (parent);
arc = parent->cg.children;
+
for (arc = parent->cg.children; arc; arc = arc->next_child)
{
child = arc->child;
if (child == parent || (child->cg.cyc.num != 0
&& child->cg.cyc.num == parent->cg.cyc.num))
{
- /* self call or call to sibling: */
+ /* Self call or call to sibling. */
printf (bsd_style_output
? "%6.6s %5.5s %7.7s %11.11s %7lu %7.7s "
: "%6.6s %5.5s %7.7s %7.7s %7lu %7.7s ",
}
else
{
- /* regular child of parent: */
+ /* Regular child of parent. */
printf (bsd_style_output
? "%6.6s %5.5s %7.2f %11.2f %7lu/%-7lu "
: "%6.6s %5.5s %7.2f %7.2f %7lu/%-7lu ",
: "%-6.6s %5.1f %7.2f %7.2f", buf,
100 * (np->cg.prop.self + np->cg.prop.child) / print_time,
np->cg.prop.self / hz, np->cg.prop.child / hz);
+
if ((np->ncalls + np->cg.self_calls) != 0)
{
printf (" %7lu", np->ncalls);
+
if (np->cg.self_calls != 0)
- {
printf ("+%-7lu ", np->cg.self_calls);
- }
else
- {
printf (" %7.7s ", "");
- }
}
else
{
printf (" %7.7s %7.7s ", "", "");
}
+
print_name (np);
printf ("\n");
}
-/*
- * Print dynamic call graph.
- */
+/* Print dynamic call graph. */
+
void
DEFUN (cg_print, (timesortsym), Sym ** timesortsym)
{
Sym *parent;
if (print_descriptions && bsd_style_output)
- {
- bsd_callg_blurb (stdout);
- }
+ bsd_callg_blurb (stdout);
print_header ();
for (index = 0; index < symtab.len + num_cycles; ++index)
{
parent = timesortsym[index];
+
if ((ignore_zeros && parent->ncalls == 0
&& parent->cg.self_calls == 0 && parent->cg.prop.self == 0
&& parent->cg.prop.child == 0)
|| !parent->cg.print_flag
|| (line_granularity && ! parent->is_func))
- {
- continue;
- }
+ continue;
+
if (!parent->name && parent->cg.cyc.num != 0)
{
- /* cycle header: */
+ /* Cycle header. */
print_cycle (parent);
print_members (parent);
}
print_line (parent);
print_children (parent);
}
+
if (bsd_style_output)
printf ("\n");
+
printf ("-----------------------------------------------\n");
+
if (bsd_style_output)
printf ("\n");
}
+
free (timesortsym);
+
if (print_descriptions && !bsd_style_output)
- {
- fsf_callg_blurb (stdout);
- }
+ fsf_callg_blurb (stdout);
}
Sym **name_sorted_syms, *sym;
const char *filename;
char buf[20];
- int column_width = (output_width - 1) / 3; /* don't write in last col! */
- /*
- * Now, sort regular function name alphabetically to create an
- * index:
- */
+ int column_width = (output_width - 1) / 3; /* Don't write in last col! */
+
+ /* Now, sort regular function name
+ alphabetically to create an index. */
name_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *));
+
for (index = 0, nnames = 0; index < symtab.len; index++)
{
if (ignore_zeros && symtab.base[index].ncalls == 0
&& symtab.base[index].hist.time == 0)
- {
- continue;
- }
+ continue;
+
name_sorted_syms[nnames++] = &symtab.base[index];
}
+
qsort (name_sorted_syms, nnames, sizeof (Sym *), cmp_name);
+
for (index = 1, todo = nnames; index <= num_cycles; index++)
- {
- name_sorted_syms[todo++] = &cycle_header[index];
- }
+ name_sorted_syms[todo++] = &cycle_header[index];
+
printf ("\f\n");
printf (_("Index by function name\n\n"));
index = (todo + 2) / 3;
+
for (i = 0; i < index; i++)
{
col = 0;
starting_col = 0;
+
for (j = i; j < todo; j += index)
{
sym = name_sorted_syms[j];
+
if (sym->cg.print_flag)
- {
- sprintf (buf, "[%d]", sym->cg.index);
- }
+ sprintf (buf, "[%d]", sym->cg.index);
else
- {
- sprintf (buf, "(%d)", sym->cg.index);
- }
+ sprintf (buf, "(%d)", sym->cg.index);
+
if (j < nnames)
{
if (bsd_style_output)
else
{
col += strlen (buf);
+
for (; col < starting_col + 5; ++col)
- {
- putchar (' ');
- }
+ putchar (' ');
+
printf (" %s ", buf);
col += print_name_only (sym);
+
if (!line_granularity && sym->is_static && sym->file)
{
filename = sym->file->name;
+
if (!print_path)
{
filename = strrchr (filename, '/');
+
if (filename)
- {
- ++filename;
- }
+ ++filename;
else
- {
- filename = sym->file->name;
- }
+ filename = sym->file->name;
}
+
printf (" (%s)", filename);
col += strlen (filename) + 3;
}
col += strlen (buf);
}
}
+
starting_col += column_width;
}
+
printf ("\n");
}
+
free (name_sorted_syms);
}
-/* Compare two arcs based on their usage counts. We want to sort
- in descending order. */
+/* 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)
{
return 0;
}
-/* Compare two funtions based on their usage counts. We want to sort
- in descending order. */
+/* 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)
{
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)
}
arc = sym->cg.parents;
+
while (arc)
{
if (arc->parent != arc->child)
/* Keep track of how many symbols we're going to place. */
scratch_index = index;
- /* A lie, but it makes identifying these functions easier
- later. */
+ /* 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. */
+ /* 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];
}
}
- /* Dump the multi-site high usage functions which are not going
- to be ordered by the main ordering algorithm. */
+ /* 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. */
+ /* 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 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);
total_arcs = 0;
tmp_arcs = 0;
+
for (index = 0; index < numarcs; index++)
{
Sym *sym1, *sym2;
/* Choose the closest. */
child = next_count < prev_count ? next : prev;
- }
+ }
else if (! child->next && !child->prev)
{
int next_count = 0;
on where we've got space in the child. */
if (child->prev)
{
- /* parent-prev and child-next */
+ /* 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 and child-prev. */
parent->next = child;
child->prev = parent;
arcs[index]->has_been_placed = 1;
}
}
- /* If we want to place all the arcs, then output those which weren't
- placed by the main algorithm. */
+ /* 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++)
{
on profiling information. This uses the function placement
code for the bulk of its work. */
-struct function_map {
+struct function_map
+{
char *function_name;
char *file_name;
};
{
unsigned int index2;
- /* Don't bother searching if this symbol is the
- same as the previous one. */
+ /* Don't bother searching if this symbol
+ is the same as the previous one. */
if (last && !strcmp (last, symbol_map[index].file_name))
continue;
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 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;
+/* cg_print.h
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+\f
#ifndef cg_print_h
#define cg_print_h
#include "gprof.h"
#include "symtab.h"
-extern double print_time; /* total of time being printed */
+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));
+extern void cg_print PARAMS ((Sym **));
+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 */
+/* corefile.c
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+\f
#include "libiberty.h"
#include "gprof.h"
#include "corefile.h"
int offset_to_code;
/* For mapping symbols to specific .o files during file ordering. */
-struct function_map {
+struct function_map
+{
char *function_name;
char *file_name;
};
struct function_map *symbol_map;
unsigned int symbol_map_count;
-extern void i386_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
+extern void i386_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
extern void alpha_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
-extern void vax_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
+extern void vax_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
extern void tahoe_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
extern void sparc_find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
symbol_map_count = count;
}
+
void
DEFUN (core_init, (a_out_name), const char *a_out_name)
{
done (1);
}
- /* get core's text section: */
+ /* Get core's text section. */
core_text_sect = bfd_get_section_by_name (core_bfd, ".text");
if (!core_text_sect)
{
}
}
- /* read core's symbol table: */
+ /* Read core's symbol table. */
- /* this will probably give us more than we need, but that's ok: */
+ /* This will probably give us more than we need, but that's ok. */
core_num_syms = bfd_get_symtab_upper_bound (core_bfd);
if (core_num_syms < 0)
{
core_syms = (asymbol **) xmalloc (core_num_syms);
core_num_syms = bfd_canonicalize_symtab (core_bfd, core_syms);
+
if (core_num_syms < 0)
{
fprintf (stderr, "%s: %s: %s\n", whoami, a_out_name,
read_function_mappings (function_mapping_file);
}
+/* Read in the text space of an a.out file. */
-/*
- * Read in the text space of an a.out file
- */
void
DEFUN (core_get_text_space, (core_bfd), bfd * core_bfd)
{
whoami, (unsigned long) core_text_sect->_raw_size);
done (1);
}
+
if (!bfd_get_section_contents (core_bfd, core_text_sect, core_text_space,
0, core_text_sect->_raw_size))
{
free (core_text_space);
core_text_space = 0;
}
+
if (!core_text_space)
- {
- fprintf (stderr, _("%s: can't do -c\n"), whoami);
- }
+ fprintf (stderr, _("%s: can't do -c\n"), whoami);
}
}
}
-/*
- * Return class of symbol SYM. The returned class can be any of:
- * 0 -> symbol is not interesting to us
- * 'T' -> symbol is a global name
- * 't' -> symbol is a local (static) name
- */
+/* Return class of symbol SYM. The returned class can be any of:
+ 0 -> symbol is not interesting to us
+ 'T' -> symbol is a global name
+ 't' -> symbol is a local (static) name. */
+
static int
DEFUN (core_sym_class, (sym), asymbol * sym)
{
int i;
if (sym->section == NULL || (sym->flags & BSF_DEBUGGING) != 0)
- {
- return 0;
- }
+ return 0;
- /*
- * Must be a text symbol, and static text symbols don't qualify if
- * ignore_static_funcs set.
- */
+ /* 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",
i = syminfo.type;
if (i == 'T')
- {
- return i; /* it's a global symbol */
- }
+ return i; /* It's a global symbol. */
if (i == 'W')
- {
- /* Treat weak symbols as text symbols. FIXME: a weak symbol may
- also be a data symbol. */
- return 'T';
- }
+ /* Treat weak symbols as text symbols. FIXME: a weak symbol may
+ also be a data symbol. */
+ return 'T';
if (i != 't')
{
- /* not a static text symbol */
+ /* Not a static text symbol. */
DBG (AOUTDEBUG, printf ("[core_sym_class] %s is of class %c\n",
sym->name, i));
return 0;
}
- /* do some more filtering on static function-names: */
-
+ /* Do some more filtering on static function-names. */
if (ignore_static_funcs)
- {
- return 0;
- }
- /*
- * Can't zero-length name or funny characters in name, where
- * `funny' includes: `.' (.o file names) and `$' (Pascal labels).
- */
+ return 0;
+
+ /* Can't zero-length name or funny characters in name, where
+ `funny' includes: `.' (.o file names) and `$' (Pascal labels). */
if (!sym->name || sym->name[0] == '\0')
- {
- return 0;
- }
+ return 0;
for (name = sym->name; *name; ++name)
{
if (*name == '.' || *name == '$')
- {
- return 0;
- }
- }
- /*
- * On systems where the C compiler adds an underscore to all
- * names, static names without underscores seem usually to be
- * labels in hand written assembler in the library. We don't want
- * these names. This is certainly necessary on a Sparc running
- * SunOS 4.1 (try profiling a program that does a lot of
- * division). I don't know whether it has harmful side effects on
- * other systems. Perhaps it should be made configurable.
- */
+ return 0;
+ }
+
+ /* On systems where the C compiler adds an underscore to all
+ names, static names without underscores seem usually to be
+ labels in hand written assembler in the library. We don't want
+ these names. This is certainly necessary on a Sparc running
+ SunOS 4.1 (try profiling a program that does a lot of
+ division). I don't know whether it has harmful side effects on
+ 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])
- /*
- * GCC may add special symbols to help gdb figure out the file
- * language. We want to ignore these, since sometimes they mask
- * the real function. (dj@ctron)
- */
+ /* GCC may add special symbols to help gdb figure out the file
+ language. We want to ignore these, since sometimes they mask
+ the real function. (dj@ctron) */
|| !strncmp (sym->name, "__gnu_compiled", 14)
|| !strncmp (sym->name, "___gnu_compiled", 15))
{
return 0;
}
- /* If the object file supports marking of function symbols, then we can
- zap anything that doesn't have BSF_FUNCTION set. */
+ /* 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 */
+ return 't'; /* It's a static text symbol. */
}
+/* Get whatever source info we can get regarding address ADDR. */
-/*
- * Get whatever source info we can get regarding address ADDR:
- */
static bool
DEFUN (get_src_info, (addr, filename, name, line_num),
bfd_vma addr AND const char **filename AND const char **name
}
}
+/* Read in symbol table from core.
+ One symbol per function is entered. */
-/*
- * Read in symbol table from core. One symbol per function is
- * entered.
- */
void
core_create_function_syms (core_bfd)
bfd *core_bfd ATTRIBUTE_UNUSED;
long i, found, skip;
unsigned int j;
- /* pass 1 - determine upper bound on number of function names: */
+ /* Pass 1 - determine upper bound on number of function names. */
symtab.len = 0;
+
for (i = 0; i < core_num_syms; ++i)
{
if (!core_sym_class (core_syms[i]))
- {
- continue;
- }
+ continue;
/* This should be replaced with a binary search or hashed
search. Gross.
skip = 1;
break;
}
+
if (!skip)
++symtab.len;
}
done (1);
}
- /* the "+ 2" is for the sentinels: */
+ /* The "+ 2" is for the sentinels. */
symtab.base = (Sym *) xmalloc ((symtab.len + 2) * sizeof (Sym));
- /* pass 2 - create symbols: */
-
+ /* Pass 2 - create symbols. */
symtab.limit = symtab.base;
+
for (i = 0; i < core_num_syms; ++i)
{
class = core_sym_class (core_syms[i]);
+
if (!class)
{
DBG (AOUTDEBUG,
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))
{
sym_init (symtab.limit);
- /* symbol offsets are always section-relative: */
-
+ /* Symbol offsets are always section-relative. */
symtab.limit->addr = core_syms[i]->value + core_syms[i]->section->vma;
+
if (symbol_map_count
&& !strcmp (core_syms[i]->name, symbol_map[found].function_name))
{
symtab.limit->mapped = 0;
}
- /* Lookup filename and line number, if we can */
-
+ /* Lookup filename and line number, if we can. */
{
const char *filename, *func_name;
/* FIXME: Checking __osf__ here does not work with a cross
gprof. */
#ifdef __osf__
- /*
- * Suppress symbols that are not function names. This is
- * useful to suppress code-labels and aliases.
- *
- * This is known to be useful under DEC's OSF/1. Under SunOS 4.x,
- * labels do not appear in the symbol table info, so this isn't
- * necessary.
- */
+ /* Suppress symbols that are not function names. This is
+ useful to suppress code-labels and aliases.
+
+ This is known to be useful under DEC's OSF/1. Under SunOS 4.x,
+ labels do not appear in the symbol table info, so this isn't
+ necessary. */
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.
- */
+ /* 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));
symtab.limit->is_func = TRUE;
symtab.limit->is_bb_head = TRUE;
+
if (class == 't')
- {
- symtab.limit->is_static = TRUE;
- }
+ symtab.limit->is_static = TRUE;
min_vma = MIN (symtab.limit->addr, min_vma);
max_vma = MAX (symtab.limit->addr, max_vma);
- /*
- * If we see "main" without an initial '_', we assume names
- * are *not* prefixed by '_'.
- */
+ /* If we see "main" without an initial '_', we assume names
+ are *not* prefixed by '_'. */
if (symtab.limit->name[0] == 'm' && discard_underscores
&& strcmp (symtab.limit->name, "main") == 0)
- {
- discard_underscores = 0;
- }
+ discard_underscores = 0;
DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n",
(long) (symtab.limit - symtab.base),
++symtab.limit;
}
- /* create sentinels: */
-
+ /* Create sentinels. */
sym_init (symtab.limit);
symtab.limit->name = "<locore>";
symtab.limit->addr = 0;
symtab_finalize (&symtab);
}
+/* Read in symbol table from core.
+ One symbol per line of source code is entered. */
-/*
- * Read in symbol table from core. One symbol per line of source code
- * is entered.
- */
void
DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd)
{
const char *filename;
int prev_line_num;
Sym_Table ltab;
- /*
- * Create symbols for functions as usual. This is necessary in
- * cases where parts of a program were not compiled with -g. For
- * those parts we still want to get info at the function level:
- */
+
+ /* Create symbols for functions as usual. This is necessary in
+ cases where parts of a program were not compiled with -g. For
+ those parts we still want to get info at the function level. */
core_create_function_syms (core_bfd);
- /* pass 1 - counter number of symbols: */
-
- /*
- * To find all line information, walk through all possible
- * text-space addresses (one by one!) and get the debugging
- * info for each address. When the debugging info changes,
- * it is time to create a new symbol.
- *
- * Of course, this is rather slow and it would be better if
- * bfd would provide an iterator for enumerating all line infos
- */
+ /* Pass 1 - counter number of symbols. */
+
+ /* To find all line information, walk through all possible
+ text-space addresses (one by one!) and get the debugging
+ info for each address. When the debugging info changes,
+ it is time to create a new symbol.
+
+ Of course, this is rather slow and it would be better if
+ bfd would provide an iterator for enumerating all line infos. */
prev_name_len = PATH_MAX;
prev_filename_len = PATH_MAX;
prev_name = xmalloc (prev_name_len);
prev_filename = xmalloc (prev_filename_len);
ltab.len = 0;
prev_line_num = 0;
+
for (offset = 0; offset < core_text_sect->_raw_size; offset += min_insn_size)
{
int len;
vma = core_text_sect->vma + offset;
+
if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num)
|| (prev_line_num == dummy.line_num
&& prev_name != NULL
&& strcmp (prev_name, dummy.name) == 0
&& strcmp (prev_filename, filename) == 0))
- {
- continue;
- }
+ continue;
++ltab.len;
prev_line_num = dummy.line_num;
free (prev_name);
prev_name = xmalloc (prev_name_len);
}
+
strcpy (prev_name, dummy.name);
-
len = strlen (filename);
+
if (len >= prev_filename_len)
{
prev_filename_len = len + 1024;
free (prev_filename);
prev_filename = xmalloc (prev_filename_len);
}
+
strcpy (prev_filename, filename);
min_vma = MIN (vma, min_vma);
free (prev_name);
free (prev_filename);
- /* make room for function symbols, too: */
+ /* Make room for function symbols, too. */
ltab.len += symtab.len;
ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym));
ltab.limit = ltab.base;
- /* pass 2 - create symbols: */
+ /* Pass 2 - create symbols. */
/* We now set is_static as we go along, rather than by running
through the symbol table at the end.
Perhaps symtab_finalize should be modified to make this
distinction as well, but the current fix works and the code is a
lot cleaner now. */
-
prev = 0;
+
for (offset = 0; offset < core_text_sect->_raw_size; offset += min_insn_size)
{
sym_init (ltab.limit);
+
if (!get_src_info (core_text_sect->vma + offset, &filename,
<ab.limit->name, <ab.limit->line_num)
|| (prev && prev->line_num == ltab.limit->line_num
&& strcmp (prev->name, ltab.limit->name) == 0
&& strcmp (prev->file->name, filename) == 0))
- {
- continue;
- }
+ continue;
- /* make name pointer a malloc'ed string: */
+ /* Make name pointer a malloc'ed string. */
ltab.limit->name = xstrdup (ltab.limit->name);
ltab.limit->file = source_file_lookup_path (filename);
ltab.limit->addr = core_text_sect->vma + offset;
/* Set is_static based on the enclosing function, using either:
- * 1) the previous symbol, if it's from the same function, or
- * 2) a symtab lookup
- */
-
+ 1) the previous symbol, if it's from the same function, or
+ 2) a symtab lookup. */
if (prev && ltab.limit->file == prev->file &&
strcmp (ltab.limit->name, prev->name) == 0)
{
prev = ltab.limit;
- /*
- * If we see "main" without an initial '_', we assume names
- * are *not* prefixed by '_'.
- */
+ /* If we see "main" without an initial '_', we assume names
+ are *not* prefixed by '_'. */
if (ltab.limit->name[0] == 'm' && discard_underscores
&& strcmp (ltab.limit->name, "main") == 0)
- {
- discard_underscores = 0;
- }
+ discard_underscores = 0;
DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n",
(unsigned long) (ltab.limit - ltab.base),
++ltab.limit;
}
- /* update sentinels: */
-
+ /* Update sentinels. */
sentinel = sym_lookup (&symtab, 0);
+
if (strcmp (sentinel->name, "<locore>") == 0
&& min_vma <= sentinel->end_addr)
- {
- sentinel->end_addr = min_vma - 1;
- }
+ sentinel->end_addr = min_vma - 1;
sentinel = sym_lookup (&symtab, ~0);
+
if (strcmp (sentinel->name, "<hicore>") == 0 && max_vma >= sentinel->addr)
- {
- sentinel->addr = max_vma + 1;
- }
+ sentinel->addr = max_vma + 1;
- /* copy in function symbols: */
+ /* Copy in function symbols. */
memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym));
ltab.limit += symtab.len;
done (1);
}
- /* finalize ltab and make it symbol table: */
-
+ /* Finalize ltab and make it symbol table. */
symtab_finalize (<ab);
free (symtab.base);
symtab = ltab;
-
}
+/* corefile.h
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+\f
#ifndef corefile_h
#define corefile_h
#include "bfd.h"
-extern bfd *core_bfd; /* bfd for core-file */
-extern int core_num_syms; /* # of entries in symbol-table */
-extern asymbol **core_syms; /* symbol table in a.out */
-extern asection *core_text_sect; /* core text section */
-extern PTR core_text_space; /* text space of a.out in core */
-
-extern int min_insn_size; /* size of smallest instruction, in bytes */
-extern int offset_to_code; /* offset (in bytes) of code from entry
- address of routine */
+extern bfd *core_bfd; /* BFD for core-file. */
+extern int core_num_syms; /* # of entries in symbol-table. */
+extern asymbol **core_syms; /* Symbol table in a.out. */
+extern asection *core_text_sect;/* Core text section. */
+extern PTR core_text_space; /* Text space of a.out in core. */
+extern int min_insn_size; /* Size of smallest instruction, in bytes. */
+extern int offset_to_code; /* Offset (in bytes) of code from entry
+ address of routine. */
-extern void core_init PARAMS ((const char *a_out_name));
-extern void core_get_text_space PARAMS ((bfd * core_bfd));
-extern void core_create_function_syms PARAMS ((bfd * core_bfd));
-extern void core_create_line_syms PARAMS ((bfd * core_bfd));
+extern void core_init PARAMS ((const char *));
+extern void core_get_text_space PARAMS ((bfd *));
+extern void core_create_function_syms PARAMS ((bfd *));
+extern void core_create_line_syms PARAMS ((bfd *));
#endif /* corefile_h */
-/*
- * Input and output from/to gmon.out files.
- */
+/* gmon_io.c - Input and output from/to gmon.out files.
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+\f
#include "cg_arcs.h"
#include "basic_blocks.h"
#include "bfd.h"
#include "call_graph.h"
#include "gmon_io.h"
#include "gmon_out.h"
-#include "gmon.h" /* fetch header for old format */
+#include "gmon.h" /* Fetch header for old format. */
#include "gprof.h"
#include "hertz.h"
#include "hist.h"
#include "libiberty.h"
int gmon_input = 0;
-int gmon_file_version = 0; /* 0 == old (non-versioned) file format */
+int gmon_file_version = 0; /* 0 == old (non-versioned) file format. */
+
+/* This probably ought to be in libbfd. */
-/*
- * This probably ought to be in libbfd.
- */
bfd_vma
DEFUN (get_vma, (abfd, addr), bfd * abfd AND bfd_byte * addr)
{
}
-/*
- * This probably ought to be in libbfd.
- */
+/* This probably ought to be in libbfd. */
+
void
DEFUN (put_vma, (abfd, val, addr), bfd * abfd AND bfd_vma val AND bfd_byte * addr)
{
unsigned char tag;
int nhist = 0, narcs = 0, nbbs = 0;
- /* open gmon.out file: */
-
+ /* Open gmon.out file. */
if (strcmp (filename, "-") == 0)
{
ifp = stdin;
else
{
ifp = fopen (filename, FOPEN_RB);
+
if (!ifp)
{
perror (filename);
done (1);
}
}
+
if (fread (&ghdr, sizeof (struct gmon_hdr), 1, ifp) != 1)
{
fprintf (stderr, _("%s: file too short to be a gmon file\n"),
done (1);
}
- /* right magic, so it's probably really a new gmon.out file */
-
+ /* Right magic, so it's probably really a new gmon.out file. */
gmon_file_version = bfd_get_32 (core_bfd, (bfd_byte *) ghdr.version);
+
if (gmon_file_version != GMON_VERSION && gmon_file_version != 0)
{
fprintf (stderr,
done (1);
}
- /* read in all the records: */
+ /* Read in all the records. */
while (fread (&tag, sizeof (tag), 1, ifp) == 1)
{
switch (tag)
UNIT raw_bin_count;
struct hdr tmp;
- /*
- * Information from a gmon.out file is in two parts: an array of
- * sampling hits within pc ranges, and the arcs.
- */
+ /* Information from a gmon.out file is in two parts: an array of
+ sampling hits within pc ranges, and the arcs. */
gmon_input = INPUT_HISTOGRAM | INPUT_CALL_GRAPH;
- /*
- * This fseek() ought to work even on stdin as long as it's
- * not an interactive device (heck, is there anybody who would
- * want to type in a gmon.out at the terminal?).
- */
+ /* This fseek() ought to work even on stdin as long as it's
+ not an interactive device (heck, is there anybody who would
+ want to type in a gmon.out at the terminal?). */
if (fseek (ifp, 0, SEEK_SET) < 0)
{
perror (filename);
done (1);
}
+
if (fread (&raw, 1, sizeof (struct raw_phdr), ifp)
!= sizeof (struct raw_phdr))
{
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]);
int profrate;
/* 4.4BSD format header. */
-
profrate = bfd_get_32 (core_bfd, (bfd_byte *) &raw.profrate[0]);
+
if (!s_highpc)
hz = profrate;
else if (hz != profrate)
}
else
{
- /* old style BSD format. */
+ /* Old style BSD format. */
if (file_format == FF_BSD44)
{
fprintf (stderr, _("%s: file `%s' has bad magic cookie\n"),
filename);
done (1);
}
+
h = tmp;
s_lowpc = (bfd_vma) h.low_pc;
s_highpc = (bfd_vma) h.high_pc;
highpc = (bfd_vma) h.high_pc / sizeof (UNIT);
samp_bytes = h.ncnt - header_size;
hist_num_bins = samp_bytes / sizeof (UNIT);
+
DBG (SAMPLEDEBUG,
printf ("[gmon_out_read] lowpc 0x%lx highpc 0x%lx ncnt %d\n",
(unsigned long) h.low_pc, (unsigned long) h.high_pc,
}
if (hist_num_bins)
- {
- ++nhist;
- }
+ ++nhist;
if (!hist_sample)
{
hist_sample =
(int *) xmalloc (hist_num_bins * sizeof (hist_sample[0]));
+
memset (hist_sample, 0, hist_num_bins * sizeof (hist_sample[0]));
}
whoami, --i, hist_num_bins);
done (1);
}
+
hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) raw_bin_count);
}
- /*
- * The rest of the file consists of a bunch of <from,self,count>
- * tuples:
- */
+ /* The rest of the file consists of a bunch of
+ <from,self,count> tuples. */
while (fread (&raw_arc, sizeof (raw_arc), 1, ifp) == 1)
{
++narcs;
from_pc = get_vma (core_bfd, (bfd_byte *) raw_arc.from_pc);
self_pc = get_vma (core_bfd, (bfd_byte *) raw_arc.self_pc);
count = bfd_get_32 (core_bfd, (bfd_byte *) raw_arc.count);
+
DBG (SAMPLEDEBUG,
printf ("[gmon_out_read] frompc 0x%lx selfpc 0x%lx count %lu\n",
(unsigned long) from_pc, (unsigned long) self_pc, count));
- /* add this arc: */
+
+ /* Add this arc. */
cg_tally (from_pc, self_pc, count);
}
+
fclose (ifp);
if (hz == HZ_WRONG)
{
- /*
- * How many ticks per second? If we can't tell, report
- * time in ticks.
- */
+ /* How many ticks per second? If we can't tell, report
+ time in ticks. */
hz = hertz ();
+
if (hz == HZ_WRONG)
{
hz = 1;
if (file_format == FF_AUTO || file_format == FF_MAGIC)
{
- /* write gmon header: */
+ /* Write gmon header. */
memcpy (&ghdr.cookie[0], GMON_MAGIC, 4);
bfd_put_32 (core_bfd, GMON_VERSION, (bfd_byte *) ghdr.version);
+
if (fwrite (&ghdr, sizeof (ghdr), 1, ofp) != 1)
{
perror (filename);
done (1);
}
- /* write execution time histogram if we have one: */
+ /* Write execution time histogram if we have one. */
if (gmon_input & INPUT_HISTOGRAM)
- {
- hist_write_hist (ofp, filename);
- }
+ hist_write_hist (ofp, filename);
- /* write call graph arcs if we have any: */
+ /* Write call graph arcs if we have any. */
if (gmon_input & INPUT_CALL_GRAPH)
- {
- cg_write_arcs (ofp, filename);
- }
+ cg_write_arcs (ofp, filename);
- /* write basic-block info if we have it: */
+ /* Write basic-block info if we have it. */
if (gmon_input & INPUT_BB_COUNTS)
- {
- bb_write_blocks (ofp, filename);
- }
+ bb_write_blocks (ofp, filename);
}
else if (file_format == FF_BSD || file_format == FF_BSD44)
{
}
}
- /* dump the samples: */
-
+ /* Dump the samples. */
for (i = 0; i < hist_num_bins; ++i)
{
bfd_put_16 (core_bfd, hist_sample[i], (bfd_byte *) & raw_bin_count[0]);
}
}
- /* dump the normalized raw arc information: */
-
+ /* Dump the normalized raw arc information. */
for (sym = symtab.base; sym < symtab.limit; ++sym)
{
for (arc = sym->cg.children; arc; arc = arc->next_child)
(unsigned long) arc->child->addr, arc->count));
}
}
+
fclose (ofp);
}
else
+/* gmon_io.h
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+\f
#ifndef gmon_io_h
#define gmon_io_h
#endif
#endif
-#define INPUT_HISTOGRAM (1<<0)
-#define INPUT_CALL_GRAPH (1<<1)
-#define INPUT_BB_COUNTS (1<<2)
-
-extern int gmon_input; /* what input did we see? */
-extern int gmon_file_version; /* file version are we dealing with */
+#define INPUT_HISTOGRAM (1 << 0)
+#define INPUT_CALL_GRAPH (1 << 1)
+#define INPUT_BB_COUNTS (1 << 2)
-extern bfd_vma get_vma PARAMS ((bfd * abfd, bfd_byte * addr));
-extern void put_vma PARAMS ((bfd * abfd, bfd_vma val, bfd_byte * addr));
+extern int gmon_input; /* What input did we see? */
+extern int gmon_file_version; /* File version are we dealing with. */
-extern void gmon_out_read PARAMS ((const char *filename));
-extern void gmon_out_write PARAMS ((const char *filename));
+extern bfd_vma get_vma PARAMS ((bfd *, bfd_byte *));
+extern void put_vma PARAMS ((bfd *, bfd_vma, bfd_byte *));
+extern void gmon_out_read PARAMS ((const char *));
+extern void gmon_out_write PARAMS ((const char *));
#endif /* gmon_io_h */
-/*
- * This file specifies the format of gmon.out files. It should have
- * as few external dependencies as possible as it is going to be
- * included in many different programs. That is, minimize the
- * number of #include's.
- *
- * A gmon.out file consists of a header (defined by gmon_hdr) followed
- * by a sequence of records. Each record starts with a one-byte tag
- * identifying the type of records, followed by records specific data.
- */
+/* gmon_out.h
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+\f
+/* This file specifies the format of gmon.out files. It should have
+ as few external dependencies as possible as it is going to be
+ included in many different programs. That is, minimize the
+ number of #include's.
+
+ A gmon.out file consists of a header (defined by gmon_hdr) followed
+ by a sequence of records. Each record starts with a one-byte tag
+ identifying the type of records, followed by records specific data. */
#ifndef gmon_out_h
#define gmon_out_h
#define GMON_MAGIC "gmon" /* magic cookie */
#define GMON_VERSION 1 /* version number */
-/*
- * Raw header as it appears on file (without padding):
- */
+/* Raw header as it appears on file (without padding). */
struct gmon_hdr
{
char cookie[4];
char spare[3 * 4];
};
-/* types of records in this file: */
+/* Types of records in this file. */
typedef enum
{
GMON_TAG_TIME_HIST = 0, GMON_TAG_CG_ARC = 1, GMON_TAG_BB_COUNT = 2
struct gmon_hist_hdr
{
- char low_pc[sizeof (char*)]; /* base pc address of sample buffer */
- char high_pc[sizeof (char*)]; /* max pc address of sampled buffer */
- char hist_size[4]; /* size of sample buffer */
- char prof_rate[4]; /* profiling clock rate */
- char dimen[15]; /* phys. dim., usually "seconds" */
- char dimen_abbrev; /* usually 's' for "seconds" */
+ char low_pc[sizeof (char*)]; /* Base pc address of sample buffer. */
+ char high_pc[sizeof (char*)]; /* Max pc address of sampled buffer. */
+ char hist_size[4]; /* Size of sample buffer. */
+ char prof_rate[4]; /* Profiling clock rate. */
+ char dimen[15]; /* Phys. dim., usually "seconds". */
+ char dimen_abbrev; /* Usually 's' for "seconds". */
};
struct gmon_cg_arc_record
{
- char from_pc[sizeof (char*)]; /* address within caller's body */
- char self_pc[sizeof (char*)]; /* address within callee's body */
- char count[4]; /* number of arc traversals */
+ char from_pc[sizeof (char*)]; /* Address within caller's body. */
+ char self_pc[sizeof (char*)]; /* Address within callee's body. */
+ char count[4]; /* Number of arc traversals. */
};
#endif /* gmon_out_h */
-/*
- * Histogram related operations.
- */
+/* hist.c - Histogram related operations.
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+\f
#include <stdio.h>
#include "libiberty.h"
#include "gprof.h"
static void scale_and_align_entries PARAMS ((void));
-/* declarations of automatically generated functions to output blurbs: */
+/* Declarations of automatically generated functions to output blurbs. */
extern void flat_blurb PARAMS ((FILE * fp));
-bfd_vma s_lowpc; /* lowest address in .text */
-bfd_vma s_highpc = 0; /* highest address in .text */
-bfd_vma lowpc, highpc; /* same, but expressed in UNITs */
-int hist_num_bins = 0; /* number of histogram samples */
-int *hist_sample = 0; /* histogram samples (shorts in the file!) */
+bfd_vma s_lowpc; /* Lowest address in .text. */
+bfd_vma s_highpc = 0; /* Highest address in .text. */
+bfd_vma lowpc, highpc; /* Same, but expressed in UNITs. */
+int hist_num_bins = 0; /* Number of histogram samples. */
+int *hist_sample = 0; /* Histogram samples (shorts in the file!). */
double hist_scale;
char hist_dimension[sizeof (((struct gmon_hist_hdr *) 0)->dimen) + 1] =
"seconds";
char hist_dimension_abbrev = 's';
-static double accum_time; /* accumulated time so far for print_line() */
-static double total_time; /* total time for all routines */
-/*
- * Table of SI prefixes for powers of 10 (used to automatically
- * scale some of the values in the flat profile).
- */
+static double accum_time; /* Accumulated time so far for print_line(). */
+static double total_time; /* Total time for all routines. */
+
+/* Table of SI prefixes for powers of 10 (used to automatically
+ scale some of the values in the flat profile). */
const struct
{
char prefix;
, /* ato */
};
-/*
- * Read the histogram from file IFP. FILENAME is the name of IFP and
- * is provided for formatting error messages only.
- */
+
+/* Read the histogram from file IFP. FILENAME is the name of IFP and
+ is provided for formatting error messages only. */
+
void
DEFUN (hist_read_rec, (ifp, filename), FILE * ifp AND const char *filename)
{
if (!s_highpc)
{
-
- /* this is the first histogram record: */
-
+ /* This is the first histogram record. */
s_lowpc = n_lowpc;
s_highpc = n_highpc;
lowpc = (bfd_vma) n_lowpc / sizeof (UNIT);
}
-/*
- * Write execution histogram to file OFP. FILENAME is the name
- * of OFP and is provided for formatting error-messages only.
- */
+/* Write execution histogram to file OFP. FILENAME is the name
+ of OFP and is provided for formatting error-messages only. */
+
void
DEFUN (hist_write_hist, (ofp, filename), FILE * ofp AND const char *filename)
{
UNIT count;
int i;
- /* write header: */
+ /* Write header. */
tag = GMON_TAG_TIME_HIST;
put_vma (core_bfd, s_lowpc, (bfd_byte *) hdr.low_pc);
for (i = 0; i < hist_num_bins; ++i)
{
bfd_put_16 (core_bfd, hist_sample[i], (bfd_byte *) & count[0]);
+
if (fwrite (&count[0], sizeof (count), 1, ofp) != 1)
{
perror (filename);
}
-/*
- * Calculate scaled entry point addresses (to save time in
- * hist_assign_samples), and, on architectures that have procedure
- * entry masks at the start of a function, possibly push the scaled
- * entry points over the procedure entry mask, if it turns out that
- * the entry point is in one bin and the code for a routine is in the
- * next bin.
- */
+/* Calculate scaled entry point addresses (to save time in
+ hist_assign_samples), and, on architectures that have procedure
+ entry masks at the start of a function, possibly push the scaled
+ entry points over the procedure entry mask, if it turns out that
+ the entry point is in one bin and the code for a routine is in the
+ next bin. */
+
static void
scale_and_align_entries ()
{
}
-/*
- * Assign samples to the symbol to which they belong.
- *
- * Histogram bin I covers some address range [BIN_LOWPC,BIN_HIGH_PC)
- * which may overlap one more symbol address ranges. If a symbol
- * overlaps with the bin's address range by O percent, then O percent
- * of the bin's count is credited to that symbol.
- *
- * There are three cases as to where BIN_LOW_PC and BIN_HIGH_PC can be
- * with respect to the symbol's address range [SYM_LOW_PC,
- * SYM_HIGH_PC) as shown in the following diagram. OVERLAP computes
- * the distance (in UNITs) between the arrows, the fraction of the
- * sample that is to be credited to the symbol which starts at
- * SYM_LOW_PC.
- *
- * sym_low_pc sym_high_pc
- * | |
- * v v
- *
- * +-----------------------------------------------+
- * | |
- * | ->| |<- ->| |<- ->| |<- |
- * | | | | | |
- * +---------+ +---------+ +---------+
- *
- * ^ ^ ^ ^ ^ ^
- * | | | | | |
- * bin_low_pc bin_high_pc bin_low_pc bin_high_pc bin_low_pc bin_high_pc
- *
- * For the VAX we assert that samples will never fall in the first two
- * bytes of any routine, since that is the entry mask, thus we call
- * scale_and_align_entries() to adjust the entry points if the entry
- * mask falls in one bin but the code for the routine doesn't start
- * until the next bin. In conjunction with the alignment of routine
- * addresses, this should allow us to have only one sample for every
- * four bytes of text space and never have any overlap (the two end
- * cases, above).
- */
+/* Assign samples to the symbol to which they belong.
+
+ Histogram bin I covers some address range [BIN_LOWPC,BIN_HIGH_PC)
+ which may overlap one more symbol address ranges. If a symbol
+ overlaps with the bin's address range by O percent, then O percent
+ of the bin's count is credited to that symbol.
+
+ There are three cases as to where BIN_LOW_PC and BIN_HIGH_PC can be
+ with respect to the symbol's address range [SYM_LOW_PC,
+ SYM_HIGH_PC) as shown in the following diagram. OVERLAP computes
+ the distance (in UNITs) between the arrows, the fraction of the
+ sample that is to be credited to the symbol which starts at
+ SYM_LOW_PC.
+
+ sym_low_pc sym_high_pc
+ | |
+ v v
+
+ +-----------------------------------------------+
+ | |
+ | ->| |<- ->| |<- ->| |<- |
+ | | | | | |
+ +---------+ +---------+ +---------+
+
+ ^ ^ ^ ^ ^ ^
+ | | | | | |
+ bin_low_pc bin_high_pc bin_low_pc bin_high_pc bin_low_pc bin_high_pc
+
+ For the VAX we assert that samples will never fall in the first two
+ bytes of any routine, since that is the entry mask, thus we call
+ scale_and_align_entries() to adjust the entry points if the entry
+ mask falls in one bin but the code for the routine doesn't start
+ until the next bin. In conjunction with the alignment of routine
+ addresses, this should allow us to have only one sample for every
+ four bytes of text space and never have any overlap (the two end
+ cases, above). */
+
void
DEFUN_VOID (hist_assign_samples)
{
unsigned int j;
double time, credit;
- /* read samples and assign to symbols: */
+ /* Read samples and assign to symbols. */
hist_scale = highpc - lowpc;
hist_scale /= hist_num_bins;
scale_and_align_entries ();
- /* iterate over all sample bins: */
-
+ /* Iterate over all sample bins. */
for (i = 0, j = 1; i < hist_num_bins; ++i)
{
bin_count = hist_sample[i];
- if (!bin_count)
- {
- continue;
- }
+ if (! bin_count)
+ continue;
+
bin_low_pc = lowpc + (bfd_vma) (hist_scale * i);
bin_high_pc = lowpc + (bfd_vma) (hist_scale * (i + 1));
time = bin_count;
+
DBG (SAMPLEDEBUG,
printf (
"[assign_samples] bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%d\n",
bin_count));
total_time += time;
- /* credit all symbols that are covered by bin I: */
-
+ /* Credit all symbols that are covered by bin I. */
for (j = j - 1; j < symtab.len; ++j)
{
sym_low_pc = symtab.base[j].hist.scaled_addr;
sym_high_pc = symtab.base[j + 1].hist.scaled_addr;
- /*
- * If high end of bin is below entry address, go for next
- * bin:
- */
+
+ /* If high end of bin is below entry address,
+ go for next bin. */
if (bin_high_pc < sym_low_pc)
- {
- break;
- }
- /*
- * If low end of bin is above high end of symbol, go for
- * next symbol.
- */
+ break;
+
+ /* If low end of bin is above high end of symbol,
+ go for next symbol. */
if (bin_low_pc >= sym_high_pc)
- {
- continue;
- }
+ continue;
+
overlap =
MIN (bin_high_pc, sym_high_pc) - MAX (bin_low_pc, sym_low_pc);
if (overlap > 0)
(unsigned long) (sizeof (UNIT) * sym_high_pc),
symtab.base[j].name, overlap * time / hist_scale,
(long) overlap));
+
addr = symtab.base[j].addr;
credit = overlap * time / hist_scale;
- /*
- * Credit symbol if it appears in INCL_FLAT or that
- * table is empty and it does not appear it in
- * EXCL_FLAT.
- */
+
+ /* Credit symbol if it appears in INCL_FLAT or that
+ table is empty and it does not appear it in
+ EXCL_FLAT. */
if (sym_lookup (&syms[INCL_FLAT], addr)
|| (syms[INCL_FLAT].len == 0
&& !sym_lookup (&syms[EXCL_FLAT], addr)))
}
}
}
+
DBG (SAMPLEDEBUG, printf ("[assign_samples] total_time %f\n",
total_time));
}
-/*
- * Print header for flag histogram profile:
- */
+/* Print header for flag histogram profile. */
+
static void
DEFUN (print_header, (prefix), const char prefix)
{
if (total_time <= 0.0)
{
printf (_(" no time accumulated\n\n"));
- /* this doesn't hurt since all the numerators will be zero: */
+
+ /* This doesn't hurt since all the numerators will be zero. */
total_time = 1.0;
}
DEFUN (print_line, (sym, scale), Sym * sym AND double scale)
{
if (ignore_zeros && sym->ncalls == 0 && sym->hist.time == 0)
- {
- return;
- }
+ return;
accum_time += sym->hist.time;
+
if (bsd_style_output)
- {
- printf ("%5.1f %10.2f %8.2f",
- total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
- accum_time / hz, sym->hist.time / hz);
- }
+ printf ("%5.1f %10.2f %8.2f",
+ total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
+ accum_time / hz, sym->hist.time / hz);
else
- {
- printf ("%6.2f %9.2f %8.2f",
- total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
- accum_time / hz, sym->hist.time / hz);
- }
+ printf ("%6.2f %9.2f %8.2f",
+ total_time > 0.0 ? 100 * sym->hist.time / total_time : 0.0,
+ accum_time / hz, sym->hist.time / hz);
+
if (sym->ncalls != 0)
- {
- printf (" %8lu %8.2f %8.2f ",
- sym->ncalls, scale * sym->hist.time / hz / sym->ncalls,
- scale * (sym->hist.time + sym->cg.child_time) / hz / sym->ncalls);
- }
+ printf (" %8lu %8.2f %8.2f ",
+ sym->ncalls, scale * sym->hist.time / hz / sym->ncalls,
+ scale * (sym->hist.time + sym->cg.child_time) / hz / sym->ncalls);
else
- {
- printf (" %8.8s %8.8s %8.8s ", "", "", "");
- }
+ printf (" %8.8s %8.8s %8.8s ", "", "", "");
+
if (bsd_style_output)
- {
- print_name (sym);
- }
+ print_name (sym);
else
- {
- print_name_only (sym);
- }
+ print_name_only (sym);
+
printf ("\n");
}
-/*
- * Compare LP and RP. The primary comparison key is execution time,
- * the secondary is number of invocation, and the tertiary is the
- * lexicographic order of the function names.
- */
+/* Compare LP and RP. The primary comparison key is execution time,
+ the secondary is number of invocation, and the tertiary is the
+ lexicographic order of the function names. */
+
static int
DEFUN (cmp_time, (lp, rp), const PTR lp AND const PTR rp)
{
double time_diff;
time_diff = right->hist.time - left->hist.time;
+
if (time_diff > 0.0)
- {
- return 1;
- }
+ return 1;
+
if (time_diff < 0.0)
- {
- return -1;
- }
+ return -1;
if (right->ncalls > left->ncalls)
- {
- return 1;
- }
+ return 1;
+
if (right->ncalls < left->ncalls)
- {
- return -1;
- }
+ return -1;
return strcmp (left->name, right->name);
}
-/*
- * Print the flat histogram profile.
- */
+/* Print the flat histogram profile. */
+
void
DEFUN_VOID (hist_print)
{
bfd_vma addr;
if (first_output)
- {
- first_output = FALSE;
- }
+ first_output = FALSE;
else
- {
- printf ("\f\n");
- }
+ printf ("\f\n");
accum_time = 0.0;
+
if (bsd_style_output)
{
if (print_descriptions)
{
printf (_("Flat profile:\n"));
}
- /*
- * Sort the symbol table by time (call-count and name as secondary
- * and tertiary keys):
- */
+
+ /* Sort the symbol table by time (call-count and name as secondary
+ and tertiary keys). */
time_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
+
for (index = 0; index < symtab.len; ++index)
- {
- time_sorted_syms[index] = &symtab.base[index];
- }
+ time_sorted_syms[index] = &symtab.base[index];
+
qsort (time_sorted_syms, symtab.len, sizeof (Sym *), cmp_time);
if (bsd_style_output)
{
- log_scale = 5; /* milli-seconds is BSD-default */
+ log_scale = 5; /* Milli-seconds is BSD-default. */
}
else
{
- /*
- * Search for symbol with highest per-call execution time and
- * scale accordingly:
- */
+ /* Search for symbol with highest per-call
+ execution time and scale accordingly. */
log_scale = 0;
top_dog = 0;
top_time = 0.0;
+
for (index = 0; index < symtab.len; ++index)
{
sym = time_sorted_syms[index];
+
if (sym->ncalls != 0)
{
time = (sym->hist.time + sym->cg.child_time) / sym->ncalls;
+
if (time > top_time)
{
top_dog = sym;
}
}
}
+
if (top_dog && top_dog->ncalls != 0 && top_time > 0.0)
{
top_time /= hz;
+
while (SItab[log_scale].scale * top_time < 1000.0
&& ((size_t) log_scale
< sizeof (SItab) / sizeof (SItab[0]) - 1))
}
}
- /*
- * For now, the dimension is always seconds. In the future, we
- * may also want to support other (pseudo-)dimensions (such as
- * I-cache misses etc.).
- */
+ /* For now, the dimension is always seconds. In the future, we
+ may also want to support other (pseudo-)dimensions (such as
+ I-cache misses etc.). */
print_header (SItab[log_scale].prefix);
+
for (index = 0; index < symtab.len; ++index)
{
addr = time_sorted_syms[index]->addr;
- /*
- * Print symbol if its in INCL_FLAT table or that table
- * is empty and the symbol is not in EXCL_FLAT.
- */
+
+ /* Print symbol if its in INCL_FLAT table or that table
+ is empty and the symbol is not in EXCL_FLAT. */
if (sym_lookup (&syms[INCL_FLAT], addr)
|| (syms[INCL_FLAT].len == 0
&& !sym_lookup (&syms[EXCL_FLAT], addr)))
- {
- print_line (time_sorted_syms[index], SItab[log_scale].scale);
- }
+ print_line (time_sorted_syms[index], SItab[log_scale].scale);
}
+
free (time_sorted_syms);
if (print_descriptions && !bsd_style_output)
- {
- flat_blurb (stdout);
- }
+ flat_blurb (stdout);
}
+/* hist.h
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+\f
#ifndef hist_h
#define hist_h
#include "bfd.h"
-extern bfd_vma s_lowpc; /* lowpc from the profile file */
-extern bfd_vma s_highpc; /* highpc from the profile file */
-extern bfd_vma lowpc, highpc; /* range profiled, in UNIT's */
-extern int hist_num_bins; /* number of histogram bins */
-extern int *hist_sample; /* code histogram */
-/*
- * Scale factor converting samples to pc values: each sample covers
- * HIST_SCALE bytes:
- */
+extern bfd_vma s_lowpc; /* Lowpc from the profile file. */
+extern bfd_vma s_highpc; /* Highpc from the profile file. */
+extern bfd_vma lowpc, highpc; /* Range profiled, in UNIT's. */
+extern int hist_num_bins; /* Number of histogram bins. */
+extern int *hist_sample; /* Code histogram. */
+
+/* Scale factor converting samples to pc values:
+ each sample covers HIST_SCALE bytes. */
extern double hist_scale;
-extern void hist_read_rec PARAMS ((FILE * ifp, const char *filename));
-extern void hist_write_hist PARAMS ((FILE * ofp, const char *filename));
-extern void hist_assign_samples PARAMS ((void));
-extern void hist_print PARAMS ((void));
+extern void hist_read_rec PARAMS ((FILE *, const char *));
+extern void hist_write_hist PARAMS ((FILE *, const char *));
+extern void hist_assign_samples PARAMS ((void));
+extern void hist_print PARAMS ((void));
#endif /* hist_h */
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
-"POT-Creation-Date: 2000-06-18 16:58-0700\n"
+"POT-Creation-Date: 2000-07-24 13:55-0700\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
msgid "[find_call] 0x%lx: bsr"
msgstr ""
-#: basic_blocks.c:134 call_graph.c:70 hist.c:105
+#: basic_blocks.c:123 call_graph.c:86 hist.c:122
#, c-format
msgid "%s: %s: unexpected end of file\n"
msgstr ""
-#: basic_blocks.c:215
+#: basic_blocks.c:198
#, c-format
msgid "%s: warning: ignoring basic-block exec counts (use -l or --line)\n"
msgstr ""
#. FIXME: This only works if bfd_vma is unsigned long.
-#: basic_blocks.c:324 basic_blocks.c:333
+#: basic_blocks.c:296 basic_blocks.c:306
#, c-format
msgid "%s:%d: (%s:0x%lx) %lu executions\n"
msgstr ""
-#: basic_blocks.c:325 basic_blocks.c:334
+#: basic_blocks.c:297 basic_blocks.c:307
msgid "<unknown>"
msgstr ""
-#: basic_blocks.c:596
+#: basic_blocks.c:551
#, c-format
msgid ""
"\n"
"\n"
msgstr ""
-#: basic_blocks.c:620
+#: basic_blocks.c:575
msgid ""
"\n"
"Execution Summary:\n"
"\n"
msgstr ""
-#: basic_blocks.c:621
+#: basic_blocks.c:576
#, c-format
msgid "%9ld Executable lines in this file\n"
msgstr ""
-#: basic_blocks.c:623
+#: basic_blocks.c:578
#, c-format
msgid "%9ld Lines executed\n"
msgstr ""
-#: basic_blocks.c:624
+#: basic_blocks.c:579
#, c-format
msgid "%9.2f Percent of the file executed\n"
msgstr ""
-#: basic_blocks.c:628
+#: basic_blocks.c:583
#, c-format
msgid ""
"\n"
"%9lu Total number of line executions\n"
msgstr ""
-#: basic_blocks.c:630
+#: basic_blocks.c:585
#, c-format
msgid "%9.2f Average executions per line\n"
msgstr ""
-#: call_graph.c:48
+#: call_graph.c:66
#, c-format
msgid "[cg_tally] arc from %s to %s traversed %lu times\n"
msgstr ""
-#: cg_print.c:39
+#: cg_print.c:54
msgid ""
"\t\t Call graph (explanation follows)\n"
"\n"
msgstr ""
-#: cg_print.c:43
+#: cg_print.c:56
msgid ""
"\t\t\tCall graph\n"
"\n"
msgstr ""
-#: cg_print.c:46 hist.c:385
+#: cg_print.c:59 hist.c:391
#, c-format
msgid ""
"\n"
"granularity: each sample hit covers %ld byte(s)"
msgstr ""
-#: cg_print.c:50
+#: cg_print.c:63
msgid ""
" for %.2f%% of %.2f seconds\n"
"\n"
msgstr ""
-#: cg_print.c:55
+#: cg_print.c:67
msgid ""
" no time propagated\n"
"\n"
msgstr ""
-#: cg_print.c:64 cg_print.c:67 cg_print.c:69
+#: cg_print.c:76 cg_print.c:79 cg_print.c:81
msgid "called"
msgstr ""
-#: cg_print.c:64 cg_print.c:69
+#: cg_print.c:76 cg_print.c:81
msgid "total"
msgstr ""
-#: cg_print.c:64
+#: cg_print.c:76
msgid "parents"
msgstr ""
-#: cg_print.c:66 cg_print.c:67
+#: cg_print.c:78 cg_print.c:79
msgid "index"
msgstr ""
-#: cg_print.c:66
+#: cg_print.c:78
msgid "%time"
msgstr ""
-#: cg_print.c:66 cg_print.c:67
+#: cg_print.c:78 cg_print.c:79
msgid "self"
msgstr ""
-#: cg_print.c:66
+#: cg_print.c:78
msgid "descendents"
msgstr ""
-#: cg_print.c:67 hist.c:409
+#: cg_print.c:79 hist.c:416
msgid "name"
msgstr ""
-#: cg_print.c:69
+#: cg_print.c:81
msgid "children"
msgstr ""
-#: cg_print.c:74
+#: cg_print.c:86
msgid "index %% time self children called name\n"
msgstr ""
-#: cg_print.c:101
+#: cg_print.c:109
#, c-format
msgid " <cycle %d as a whole> [%d]\n"
msgstr ""
-#: cg_print.c:353
+#: cg_print.c:335
#, c-format
msgid "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s <spontaneous>\n"
msgstr ""
-#: cg_print.c:354
+#: cg_print.c:336
#, c-format
msgid "%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s <spontaneous>\n"
msgstr ""
-#: cg_print.c:587
+#: cg_print.c:570
msgid ""
"Index by function name\n"
"\n"
msgstr ""
-#: cg_print.c:644 cg_print.c:653
+#: cg_print.c:627 cg_print.c:636
#, c-format
msgid "<cycle %d>"
msgstr ""
-#: corefile.c:39
+#: corefile.c:61
#, c-format
msgid "%s: could not open %s.\n"
msgstr ""
-#: corefile.c:53 corefile.c:87
+#: corefile.c:75 corefile.c:109
#, c-format
msgid "%s: unable to parse mapping file %s.\n"
msgstr ""
-#: corefile.c:128
+#: corefile.c:151
#, c-format
msgid "%s: %s: not in a.out format\n"
msgstr ""
-#: corefile.c:139
+#: corefile.c:162
#, c-format
msgid "%s: can't find .text section in %s\n"
msgstr ""
-#: corefile.c:198
+#: corefile.c:220
#, c-format
msgid "%s: ran out room for %lu bytes of text space\n"
msgstr ""
-#: corefile.c:211
+#: corefile.c:234
#, c-format
msgid "%s: can't do -c\n"
msgstr ""
-#: corefile.c:243
+#: corefile.c:265
#, c-format
msgid "%s: -c not supported on architecture %s\n"
msgstr ""
-#: corefile.c:433
+#: corefile.c:432
#, c-format
msgid "%s: file `%s' has no symbols\n"
msgstr ""
-#: corefile.c:755
+#: corefile.c:732
#, c-format
msgid "%s: somebody miscounted: ltab.len=%d instead of %ld\n"
msgstr ""
-#: gmon_io.c:33 gmon_io.c:55
+#: gmon_io.c:50 gmon_io.c:71
#, c-format
msgid "%s: bfd_vma has unexpected size of %ld bytes\n"
msgstr ""
-#: gmon_io.c:90 gmon_io.c:185
+#: gmon_io.c:107 gmon_io.c:199
#, c-format
msgid "%s: file too short to be a gmon file\n"
msgstr ""
-#: gmon_io.c:100 gmon_io.c:218
+#: gmon_io.c:117 gmon_io.c:233
#, c-format
msgid "%s: file `%s' has bad magic cookie\n"
msgstr ""
-#: gmon_io.c:111
+#: gmon_io.c:128
#, c-format
msgid "%s: file `%s' has unsupported version %d\n"
msgstr ""
-#: gmon_io.c:141
+#: gmon_io.c:158
#, c-format
msgid "%s: %s: found bad tag %d (file corrupted?)\n"
msgstr ""
-#: gmon_io.c:206
+#: gmon_io.c:221
#, c-format
msgid "%s: profiling rate incompatible with first gmon file\n"
msgstr ""
-#: gmon_io.c:235
+#: gmon_io.c:250
#, c-format
msgid "%s: incompatible with first gmon file\n"
msgstr ""
-#: gmon_io.c:261
+#: gmon_io.c:278
#, c-format
msgid "%s: file '%s' does not appear to be in gmon.out format\n"
msgstr ""
-#: gmon_io.c:283
+#: gmon_io.c:299
#, c-format
msgid "%s: unexpected EOF after reading %d/%d bins\n"
msgstr ""
-#: gmon_io.c:318
+#: gmon_io.c:335
msgid "time is in ticks, not seconds\n"
msgstr ""
-#: gmon_io.c:324 gmon_io.c:464
+#: gmon_io.c:341 gmon_io.c:475
#, c-format
msgid "%s: don't know how to deal with file format %d\n"
msgstr ""
-#: gmon_io.c:331
+#: gmon_io.c:348
#, c-format
msgid "File `%s' (version %d) contains:\n"
msgstr ""
-#: gmon_io.c:333
+#: gmon_io.c:350
#, c-format
msgid "\t%d histogram record%s\n"
msgstr ""
-#: gmon_io.c:335
+#: gmon_io.c:352
#, c-format
msgid "\t%d call-graph record%s\n"
msgstr ""
-#: gmon_io.c:337
+#: gmon_io.c:354
#, c-format
msgid "\t%d basic-block count record%s\n"
msgstr ""
-#: gprof.c:144
+#: gprof.c:145
#, c-format
msgid ""
"Usage: %s [-[abcDhilLsTvwxyz]] [-[ACeEfFJnNOpPqQZ][name]] [-I dirs]\n"
"\t[--no-static] [--print-path] [--separate-files]\n"
"\t[--static-call-graph] [--sum] [--table-length=len] [--traditional]\n"
"\t[--version] [--width=n] [--ignore-non-functions]\n"
-"\t[--demangle] [--no-demangle]\n"
+"\t[--demangle[=STYLE]] [--no-demangle]\n"
"\t[image-file] [profile-file...]\n"
msgstr ""
-#: gprof.c:160
+#: gprof.c:161
#, c-format
msgid "Report bugs to %s\n"
msgstr ""
-#: gprof.c:229
+#: gprof.c:230
#, c-format
msgid "%s: debugging not supported; -d ignored\n"
msgstr ""
-#: gprof.c:309
+#: gprof.c:310
#, c-format
msgid "%s: unknown file format %s\n"
msgstr ""
#. This output is intended to follow the GNU standards document.
-#: gprof.c:393
+#: gprof.c:394
#, c-format
msgid "GNU gprof %s\n"
msgstr ""
-#: gprof.c:394
+#: gprof.c:395
msgid ""
"Based on BSD gprof, copyright 1983 Regents of the University of California.\n"
msgstr ""
-#: gprof.c:395
+#: gprof.c:396
msgid ""
"This program is free software. This program has absolutely no warranty.\n"
msgstr ""
-#: gprof.c:441
+#: gprof.c:437
+#, c-format
+msgid "%s: unknown demangling style `%s'\n"
+msgstr ""
+
+#: gprof.c:457
#, c-format
msgid ""
"%s: Only one of --function-ordering and --file-ordering may be specified.\n"
msgstr ""
-#: gprof.c:541
+#: gprof.c:557
#, c-format
msgid "%s: sorry, file format `prof' is not yet supported\n"
msgstr ""
-#: gprof.c:602
+#: gprof.c:618
#, c-format
msgid "%s: gmon.out file is missing histogram\n"
msgstr ""
-#: gprof.c:609
+#: gprof.c:625
#, c-format
msgid "%s: gmon.out file is missing call-graph data\n"
msgstr ""
-#: hist.c:143
+#: hist.c:158
#, c-format
msgid "%s: `%s' is incompatible with first gmon file\n"
msgstr ""
-#: hist.c:159
+#: hist.c:174
#, c-format
msgid "%s: %s: unexpected EOF after reading %d of %d samples\n"
msgstr ""
-#: hist.c:381
+#: hist.c:387
#, c-format
msgid "%c%c/call"
msgstr ""
-#: hist.c:389
+#: hist.c:395
msgid ""
" for %.2f%% of %.2f %s\n"
"\n"
msgstr ""
-#: hist.c:395
+#: hist.c:401
#, c-format
msgid ""
"\n"
"Each sample counts as %g %s.\n"
msgstr ""
-#: hist.c:400
+#: hist.c:406
msgid ""
" no time accumulated\n"
"\n"
msgstr ""
-#: hist.c:406
+#: hist.c:413
msgid "cumulative"
msgstr ""
-#: hist.c:406
+#: hist.c:413
msgid "self "
msgstr ""
-#: hist.c:406
+#: hist.c:413
msgid "total "
msgstr ""
-#: hist.c:408
+#: hist.c:415
msgid "time"
msgstr ""
-#: hist.c:408
+#: hist.c:415
msgid "calls"
msgstr ""
-#: hist.c:517
+#: hist.c:504
msgid ""
"\n"
"\n"
"flat profile:\n"
msgstr ""
-#: hist.c:523
+#: hist.c:510
msgid "Flat profile:\n"
msgstr ""
-#: source.c:155
+#: source.c:163
#, c-format
msgid "%s: could not locate `%s'\n"
msgstr ""
-#: source.c:242
+#: source.c:238
#, c-format
msgid "*** File %s:\n"
msgstr ""
+/* search-list.c
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+\f
#include "libiberty.h"
#include "gprof.h"
#include "search_list.h"
{
beg = colon + 1;
colon = strchr (beg, PATH_SEP_CHAR);
+
if (colon)
- {
- len = colon - beg;
- }
+ len = colon - beg;
else
- {
- len = strlen (beg);
- }
+ len = strlen (beg);
+
new_el = (Search_List_Elem *) xmalloc (sizeof (*new_el) + len);
memcpy (new_el->path, beg, len);
new_el->path[len] = '\0';
- /* append new path at end of list: */
+ /* Append new path at end of list. */
new_el->next = 0;
+
if (list->tail)
- {
- list->tail->next = new_el;
- }
+ list->tail->next = new_el;
else
- {
- list->head = new_el;
- }
+ list->head = new_el;
+
list->tail = new_el;
}
while (colon);
+/* search-list.h
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+\f
#ifndef search_list_h
#define search_list_h
}
Search_List;
-extern void search_list_append PARAMS ((Search_List * list, const char *paths));
+extern void search_list_append PARAMS ((Search_List *, const char *));
#endif /* search_list_h */
-/*
- * Keeps track of source files.
- */
+/* source.c - Keep track of source files.
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+\f
#include "gprof.h"
#include "libiberty.h"
#include "filenames.h"
#include "search_list.h"
#include "source.h"
-#define EXT_ANNO "-ann" /* postfix of annotated files */
+#define EXT_ANNO "-ann" /* Postfix of annotated files. */
-/*
- * Default option values:
- */
+/* Default option values. */
bool create_annotation_files = FALSE;
-Search_List src_search_list =
-{0, 0};
+Search_List src_search_list = {0, 0};
Source_File *first_src_file = 0;
for (sf = first_src_file; sf; sf = sf->next)
{
if (FILENAME_CMP (path, sf->name) == 0)
- {
- break;
- }
+ break;
}
+
if (!sf)
{
- /* create a new source file descriptor: */
-
+ /* Create a new source file descriptor. */
sf = (Source_File *) xmalloc (sizeof (*sf));
+
memset (sf, 0, sizeof (*sf));
+
sf->name = xstrdup (path);
sf->next = first_src_file;
first_src_file = sf;
}
+
return sf;
}
{
const char *fname;
Source_File *sf;
- /*
- * The user cannot know exactly how a filename will be stored in
- * the debugging info (e.g., ../include/foo.h
- * vs. /usr/include/foo.h). So we simply compare the filename
- * component of a path only:
- */
+
+ /* The user cannot know exactly how a filename will be stored in
+ the debugging info (e.g., ../include/foo.h
+ vs. /usr/include/foo.h). So we simply compare the filename
+ component of a path only. */
for (sf = first_src_file; sf; sf = sf->next)
{
fname = strrchr (sf->name, '/');
+
if (fname)
- {
- ++fname;
- }
+ ++fname;
else
- {
- fname = sf->name;
- }
+ fname = sf->name;
+
if (FILENAME_CMP (filename, fname) == 0)
- {
- break;
- }
+ break;
}
+
return sf;
}
FILE *ifp, *ofp;
Search_List_Elem *sle = src_search_list.head;
- /*
- * Open input file. If open fails, walk along search-list until
- * open succeeds or reaching end of list:
- */
+ /* Open input file. If open fails, walk along search-list until
+ open succeeds or reaching end of list. */
strcpy (fname, sf->name);
+
if (IS_ABSOLUTE_PATH (sf->name))
- {
- sle = 0; /* don't use search list for absolute paths */
- }
+ sle = 0; /* Don't use search list for absolute paths. */
+
name_only = 0;
while (TRUE)
{
DBG (SRCDEBUG, printf ("[annotate_source]: looking for %s, trying %s\n",
sf->name, fname));
+
ifp = fopen (fname, FOPEN_RB);
if (ifp)
- {
- break;
- }
+ break;
+
if (!sle && !name_only)
{
name_only = strrchr (sf->name, '/');
#endif
if (name_only)
{
- /* try search-list again, but this time with name only: */
+ /* Try search-list again, but this time with name only. */
++name_only;
sle = src_search_list.head;
}
}
+
if (sle)
{
strcpy (fname, sle->path);
strcat (fname, ".");
#endif
strcat (fname, "/");
+
if (name_only)
- {
- strcat (fname, name_only);
- }
+ strcat (fname, name_only);
else
- {
- strcat (fname, sf->name);
- }
+ strcat (fname, sf->name);
+
sle = sle->next;
}
else
{
if (errno == ENOENT)
- {
- fprintf (stderr, _("%s: could not locate `%s'\n"),
- whoami, sf->name);
- }
+ fprintf (stderr, _("%s: could not locate `%s'\n"),
+ whoami, sf->name);
else
- {
- perror (sf->name);
- }
+ perror (sf->name);
+
return 0;
}
}
ofp = stdout;
+
if (create_annotation_files)
{
- /* try to create annotated source file: */
+ /* Try to create annotated source file. */
const char *filename;
- /* create annotation files in the current working directory: */
+ /* Create annotation files in the current working directory. */
filename = strrchr (sf->name, '/');
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
{
}
#endif
if (filename)
- {
- ++filename;
- }
+ ++filename;
else
- {
- filename = sf->name;
- }
+ filename = sf->name;
strcpy (fname, filename);
strcat (fname, EXT_ANNO);
}
#endif
ofp = fopen (fname, "w");
+
if (!ofp)
{
perror (fname);
}
}
- /*
- * Print file names if output goes to stdout and there are
- * more than one source file:
- */
+ /* Print file names if output goes to stdout
+ and there are more than one source file. */
if (ofp == stdout)
{
if (first_file)
- {
- first_file = FALSE;
- }
+ first_file = FALSE;
else
- {
- fputc ('\n', ofp);
- }
+ fputc ('\n', ofp);
+
if (first_output)
- {
- first_output = FALSE;
- }
+ first_output = FALSE;
else
- {
- fprintf (ofp, "\f\n");
- }
+ fprintf (ofp, "\f\n");
+
fprintf (ofp, _("*** File %s:\n"), sf->name);
}
annotation = xmalloc (max_width + 1);
line_num = 1;
new_line = TRUE;
+
while ((nread = fread (buf, 1, sizeof (buf), ifp)) > 0)
{
for (i = 0; i < nread; ++i)
++line_num;
new_line = FALSE;
}
+
new_line = (buf[i] == '\n');
fputc (buf[i], ofp);
}
}
+
free (annotation);
return ofp;
}
+/* source.h
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+\f
#ifndef source_h
#define source_h
typedef struct source_file
{
struct source_file *next;
- const char *name; /* name of source file */
- unsigned long ncalls; /* # of "calls" to this file */
- int num_lines; /* # of lines in file */
- int nalloced; /* number of lines allocated */
- void **line; /* usage-dependent per-line data */
+ const char *name; /* Name of source file. */
+ unsigned long ncalls; /* # of "calls" to this file. */
+ int num_lines; /* # of lines in file. */
+ int nalloced; /* Number of lines allocated. */
+ void **line; /* Usage-dependent per-line data. */
}
Source_File;
-/*
- * Options:
- */
-extern bool create_annotation_files; /* create annotated output files? */
+/* Options. */
+extern bool create_annotation_files; /* Create annotated output files? */
-/*
- * List of directories to search for source files:
- */
+/* List of directories to search for source files. */
extern Search_List src_search_list;
-/*
- * Chain of source-file descriptors:
- */
+/* Chain of source-file descriptors. */
extern Source_File *first_src_file;
-/*
- * Returns pointer to source file descriptor for PATH/FILENAME.
- */
-extern Source_File *source_file_lookup_path PARAMS ((const char *path));
-extern Source_File *source_file_lookup_name PARAMS ((const char *filename));
-
-/*
- * Read source file SF output annotated source. The annotation is at
- * MAX_WIDTH characters wide and for each source-line an annotation is
- * obtained by invoking function ANNOTE. ARG is an argument passed to
- * ANNOTE that is left uninterpreted by annotate_source().
- *
- * Returns a pointer to the output file (which maybe stdout) such
- * that summary statistics can be printed. If the returned file
- * is not stdout, it should be closed when done with it.
- */
+/* Returns pointer to source file descriptor for PATH/FILENAME. */
+extern Source_File *source_file_lookup_path PARAMS ((const char *));
+extern Source_File *source_file_lookup_name PARAMS ((const char *));
+
+/* Read source file SF output annotated source. The annotation is at
+ MAX_WIDTH characters wide and for each source-line an annotation is
+ obtained by invoking function ANNOTE. ARG is an argument passed to
+ ANNOTE that is left uninterpreted by annotate_source().
+
+ Returns a pointer to the output file (which maybe stdout) such
+ that summary statistics can be printed. If the returned file
+ is not stdout, it should be closed when done with it. */
extern FILE *annotate_source PARAMS ((Source_File * sf, int max_width,
void (*annote) (char *b, int w, int l,
void *arg),
void *arg));
-
#endif /* source_h */
+/* sym_ids.c
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+\f
#include <ctype.h>
#include "libiberty.h"
struct sym_id
{
struct sym_id *next;
- char *spec; /* parsing modifies this */
+ char *spec; /* Parsing modifies this. */
Table_Id which_table;
bool has_right;
+
struct match
{
- int prev_index; /* index of prev match */
- Sym *prev_match; /* previous match */
- Sym *first_match; /* chain of all matches */
+ int prev_index; /* Index of prev match. */
+ Sym *prev_match; /* Previous match. */
+ Sym *first_match; /* Chain of all matches. */
Sym sym;
}
left, right;
};
#endif /* DEBUG */
-/*
- * This is the table in which we keep all the syms that match
- * the right half of an arc id. It is NOT sorted according
- * to the addresses, because it is accessed only through
- * the left half's CHILDREN pointers (so it's crucial not
- * to reorder this table once pointers into it exist).
- */
+/* This is the table in which we keep all the syms that match
+ the right half of an arc id. It is NOT sorted according
+ to the addresses, because it is accessed only through
+ the left half's CHILDREN pointers (so it's crucial not
+ to reorder this table once pointers into it exist). */
static Sym_Table right_ids;
static Source_File non_existent_file =
}
-/*
- * A spec has the syntax FILENAME:(FUNCNAME|LINENUM). As a convenience
- * to the user, a spec without a colon is interpreted as:
- *
- * (i) a FILENAME if it contains a dot
- * (ii) a FUNCNAME if it starts with a non-digit character
- * (iii) a LINENUM if it starts with a digit
- *
- * A FUNCNAME containing a dot can be specified by :FUNCNAME, a
- * FILENAME not containing a dot can be specified by FILENAME:.
- */
+/* A spec has the syntax FILENAME:(FUNCNAME|LINENUM). As a convenience
+ to the user, a spec without a colon is interpreted as:
+
+ (i) a FILENAME if it contains a dot
+ (ii) a FUNCNAME if it starts with a non-digit character
+ (iii) a LINENUM if it starts with a digit
+
+ A FUNCNAME containing a dot can be specified by :FUNCNAME, a
+ FILENAME not containing a dot can be specified by FILENAME. */
+
static void
DEFUN (parse_spec, (spec, sym), char *spec AND Sym * sym)
{
sym_init (sym);
colon = strrchr (spec, ':');
+
if (colon)
{
*colon = '\0';
+
if (colon > spec)
{
sym->file = source_file_lookup_name (spec);
+
if (!sym->file)
- {
- sym->file = &non_existent_file;
- }
+ sym->file = &non_existent_file;
}
+
spec = colon + 1;
+
if (strlen (spec))
{
if (isdigit ((unsigned char) spec[0]))
- {
- sym->line_num = atoi (spec);
- }
+ sym->line_num = atoi (spec);
else
- {
- sym->name = spec;
- }
+ sym->name = spec;
}
}
else if (strlen (spec))
{
- /* no colon: spec is a filename if it contains a dot: */
+ /* No colon: spec is a filename if it contains a dot. */
if (strchr (spec, '.'))
{
sym->file = source_file_lookup_name (spec);
+
if (!sym->file)
- {
- sym->file = &non_existent_file;
- }
+ sym->file = &non_existent_file;
}
else if (isdigit ((unsigned char) *spec))
{
}
-/*
- * A symbol id has the syntax SPEC[/SPEC], where SPEC is is defined
- * by parse_spec().
- */
+/* A symbol id has the syntax SPEC[/SPEC], where SPEC is is defined
+ by parse_spec(). */
+
static void
DEFUN (parse_id, (id), struct sym_id *id)
{
if (debug_level & IDDEBUG)
{
printf ("%s:", id->left.sym.file ? id->left.sym.file->name : "*");
+
if (id->left.sym.name)
- {
- printf ("%s", id->left.sym.name);
- }
+ printf ("%s", id->left.sym.name);
else if (id->left.sym.line_num)
- {
- printf ("%d", id->left.sym.line_num);
- }
+ printf ("%d", id->left.sym.line_num);
else
- {
- printf ("*");
- }
+ printf ("*");
+
if (id->has_right)
{
printf ("/%s:",
id->right.sym.file ? id->right.sym.file->name : "*");
+
if (id->right.sym.name)
- {
- printf ("%s", id->right.sym.name);
- }
+ printf ("%s", id->right.sym.name);
else if (id->right.sym.line_num)
- {
- printf ("%d", id->right.sym.line_num);
- }
+ printf ("%d", id->right.sym.line_num);
else
- {
- printf ("*");
- }
+ printf ("*");
}
+
printf ("\n");
}
#endif
}
-/*
- * Return TRUE iff PATTERN matches SYM.
- */
+/* Return TRUE iff PATTERN matches SYM. */
+
static bool
DEFUN (match, (pattern, sym), Sym * pattern AND Sym * sym)
{
{
if (m->prev_match != sym - 1)
{
- /* discontinuity: add new match to table: */
+ /* Discontinuity: add new match to table. */
if (second_pass)
{
tab->base[tab->len] = *sym;
m->prev_index = tab->len;
- /* link match into match's chain: */
+ /* Link match into match's chain. */
tab->base[tab->len].next = m->first_match;
m->first_match = &tab->base[tab->len];
}
+
++tab->len;
}
- /* extend match to include this symbol: */
+ /* Extend match to include this symbol. */
if (second_pass)
- {
- tab->base[m->prev_index].end_addr = sym->end_addr;
- }
+ tab->base[m->prev_index].end_addr = sym->end_addr;
+
m->prev_match = sym;
}
-/*
- * Go through sym_id list produced by option processing and fill
- * in the various symbol tables indicating what symbols should
- * be displayed or suppressed for the various kinds of outputs.
- *
- * This can potentially produce huge tables and in particulars
- * tons of arcs, but this happens only if the user makes silly
- * requests---you get what you ask for!
- */
+/* Go through sym_id list produced by option processing and fill
+ in the various symbol tables indicating what symbols should
+ be displayed or suppressed for the various kinds of outputs.
+
+ This can potentially produce huge tables and in particulars
+ tons of arcs, but this happens only if the user makes silly
+ requests---you get what you ask for! */
+
void
DEFUN_VOID (sym_id_parse)
{
struct sym_id *id;
Sym_Table *tab;
- /*
- * Convert symbol ids into Syms, so we can deal with them more easily:
- */
+ /* Convert symbol ids into Syms, so we can deal with them more easily. */
for (id = id_list; id; id = id->next)
- {
- parse_id (id);
- }
-
- /* first determine size of each table: */
+ parse_id (id);
+ /* First determine size of each table. */
for (sym = symtab.base; sym < symtab.limit; ++sym)
{
for (id = id_list; id; id = id->next)
{
if (match (&id->left.sym, sym))
- {
- extend_match (&id->left, sym, &syms[id->which_table], FALSE);
- }
+ extend_match (&id->left, sym, &syms[id->which_table], FALSE);
+
if (id->has_right && match (&id->right.sym, sym))
- {
- extend_match (&id->right, sym, &right_ids, FALSE);
- }
+ extend_match (&id->right, sym, &right_ids, FALSE);
}
}
- /* create tables of appropriate size and reset lengths: */
-
+ /* Create tables of appropriate size and reset lengths. */
for (tab = syms; tab < &syms[NUM_TABLES]; ++tab)
{
if (tab->len)
tab->len = 0;
}
}
+
if (right_ids.len)
{
right_ids.base = (Sym *) xmalloc (right_ids.len * sizeof (Sym));
right_ids.len = 0;
}
- /* make a second pass through symtab, creating syms as necessary: */
-
+ /* Make a second pass through symtab, creating syms as necessary. */
for (sym = symtab.base; sym < symtab.limit; ++sym)
{
for (id = id_list; id; id = id->next)
{
if (match (&id->left.sym, sym))
- {
- extend_match (&id->left, sym, &syms[id->which_table], TRUE);
- }
+ extend_match (&id->left, sym, &syms[id->which_table], TRUE);
+
if (id->has_right && match (&id->right.sym, sym))
- {
- extend_match (&id->right, sym, &right_ids, TRUE);
- }
+ extend_match (&id->right, sym, &right_ids, TRUE);
}
}
- /* go through ids creating arcs as needed: */
-
+ /* Go through ids creating arcs as needed. */
for (id = id_list; id; id = id->next)
{
if (id->has_right)
(unsigned long) right->addr,
(unsigned long) right->end_addr,
table_name[id->which_table]));
+
arc_add (left, right, (unsigned long) 0);
}
}
}
}
- /* finally, we can sort the tables and we're done: */
-
+ /* Finally, we can sort the tables and we're done. */
for (tab = &syms[0]; tab < &syms[NUM_TABLES]; ++tab)
{
DBG (IDDEBUG, printf ("[sym_id_parse] syms[%s]:\n",
}
-/*
- * Symbol tables storing the FROM symbols of arcs do not necessarily
- * have distinct address ranges. For example, somebody might request
- * -k /_mcount to suppress any arcs into _mcount, while at the same
- * time requesting -k a/b. Fortunately, those symbol tables don't get
- * very big (the user has to type them!), so a linear search is probably
- * tolerable.
- */
+/* Symbol tables storing the FROM symbols of arcs do not necessarily
+ have distinct address ranges. For example, somebody might request
+ -k /_mcount to suppress any arcs into _mcount, while at the same
+ time requesting -k a/b. Fortunately, those symbol tables don't get
+ very big (the user has to type them!), so a linear search is probably
+ tolerable. */
bool
DEFUN (sym_id_arc_is_present, (symtab, from, to),
Sym_Table * symtab AND Sym * from AND Sym * to)
{
if (from->addr >= sym->addr && from->addr <= sym->end_addr
&& arc_lookup (sym, to))
- {
- return TRUE;
- }
+ return TRUE;
}
+
return FALSE;
}
+/* sym_ids.h
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+\f
#ifndef sym_ids_h
#define sym_ids_h
extern Sym_Table syms[NUM_TABLES];
-extern void sym_id_add PARAMS ((const char *spec, Table_Id which_table));
-extern void sym_id_parse PARAMS ((void));
-extern bool sym_id_arc_is_present PARAMS ((Sym_Table * symtab,
- Sym * from, Sym * to));
+extern void sym_id_add PARAMS ((const char *, Table_Id));
+extern void sym_id_parse PARAMS ((void));
+extern bool sym_id_arc_is_present PARAMS ((Sym_Table *, Sym *, Sym *));
#endif /* sym_ids_h */
+/* symtab.c
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+ This file is part of GNU Binutils.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
+\f
#include "gprof.h"
#include "cg_arcs.h"
#include "corefile.h"
Sym_Table symtab;
-/*
- * Initialize a symbol (so it's empty).
- */
+/* Initialize a symbol (so it's empty). */
+
void
DEFUN (sym_init, (sym), Sym * sym)
{
memset (sym, 0, sizeof (*sym));
- /*
- * It is not safe to assume that a binary zero corresponds to
- * a floating-point 0.0, so initialize floats explicitly:
- */
+
+ /* It is not safe to assume that a binary zero corresponds
+ to a floating-point 0.0, so initialize floats explicitly. */
sym->hist.time = 0.0;
sym->cg.child_time = 0.0;
sym->cg.prop.fract = 0.0;
}
-/*
- * Compare the function entry-point of two symbols and return <0, =0,
- * or >0 depending on whether the left value is smaller than, equal
- * to, or greater than the right value. If two symbols are equal
- * but one has is_func set and the other doesn't, we make the
- * non-function symbol one "bigger" so that the function symbol will
- * survive duplicate removal. Finally, if both symbols have the
- * same is_func value, we discriminate against is_static such that
- * the global symbol survives.
- */
+/* Compare the function entry-point of two symbols and return <0, =0,
+ or >0 depending on whether the left value is smaller than, equal
+ to, or greater than the right value. If two symbols are equal
+ but one has is_func set and the other doesn't, we make the
+ non-function symbol one "bigger" so that the function symbol will
+ survive duplicate removal. Finally, if both symbols have the
+ same is_func value, we discriminate against is_static such that
+ the global symbol survives. */
+
static int
DEFUN (cmp_addr, (lp, rp), const PTR lp AND const PTR rp)
{
Sym *right = (Sym *) rp;
if (left->addr > right->addr)
- {
- return 1;
- }
+ return 1;
else if (left->addr < right->addr)
- {
- return -1;
- }
+ return -1;
if (left->is_func != right->is_func)
- {
- return right->is_func - left->is_func;
- }
+ return right->is_func - left->is_func;
return left->is_static - right->is_static;
}
bfd_vma prev_addr;
if (!tab->len)
- {
- return;
- }
+ return;
- /*
- * Sort symbol table in order of increasing function addresses:
- */
+ /* Sort symbol table in order of increasing function addresses. */
qsort (tab->base, tab->len, sizeof (Sym), cmp_addr);
- /*
- * Remove duplicate entries to speed-up later processing and
- * set end_addr if its not set yet:
- */
+ /* Remove duplicate entries to speed-up later processing and
+ set end_addr if its not set yet. */
prev_addr = tab->base[0].addr + 1;
+
for (src = dst = tab->base; src < tab->limit; ++src)
{
if (src->addr == prev_addr)
{
- /*
- * If same address, favor global symbol over static one,
- * then function over line number. If both symbols are
- * either static or global and either function or line, check
- * whether one has name beginning with underscore while
- * the other doesn't. In such cases, keep sym without
- * underscore. This takes cares of compiler generated
- * symbols (such as __gnu_compiled, __c89_used, etc.).
- */
+ /* If same address, favor global symbol over static one,
+ then function over line number. If both symbols are
+ either static or global and either function or line, check
+ whether one has name beginning with underscore while
+ the other doesn't. In such cases, keep sym without
+ underscore. This takes cares of compiler generated
+ symbols (such as __gnu_compiled, __c89_used, etc.). */
if ((!src->is_static && dst[-1].is_static)
|| ((src->is_static == dst[-1].is_static)
&& ((src->is_func && !dst[-1].is_func)
dst[-1].name, dst[-1].is_static ? 't' : 'T',
dst[-1].is_func ? 'F' : 'f');
printf (" (addr=%lx)\n", (unsigned long) src->addr));
+
dst[-1] = *src;
}
else
else
{
if (dst > tab->base && dst[-1].end_addr == 0)
- {
- dst[-1].end_addr = src->addr - 1;
- }
+ dst[-1].end_addr = src->addr - 1;
- /* retain sym only if it has a non-empty address range: */
+ /* Retain sym only if it has a non-empty address range. */
if (!src->end_addr || src->addr <= src->end_addr)
{
*dst = *src;
}
}
}
+
if (tab->len > 0 && dst[-1].end_addr == 0)
- {
- dst[-1].end_addr = core_text_sect->vma + core_text_sect->_raw_size - 1;
- }
+ dst[-1].end_addr = core_text_sect->vma + core_text_sect->_raw_size - 1;
DBG (AOUTDEBUG | IDDEBUG,
printf ("[symtab_finalize]: removed %d duplicate entries\n",
unsigned int j;
for (j = 0; j < tab->len; ++j)
- {
- printf ("[symtab_finalize] 0x%lx-0x%lx\t%s\n",
- (long) tab->base[j].addr, (long) tab->base[j].end_addr,
- tab->base[j].name);
- }
+ {
+ printf ("[symtab_finalize] 0x%lx-0x%lx\t%s\n",
+ (long) tab->base[j].addr, (long) tab->base[j].end_addr,
+ tab->base[j].name);
+ }
);
}
for (low = 0, high = symtab->len - 1; low != high;)
{
mid = (high + low) >> 1;
+
fprintf (stderr, "[dbg_sym_lookup] low=0x%lx, mid=0x%lx, high=0x%lx\n",
low, mid, high);
fprintf (stderr, "[dbg_sym_lookup] sym[m]=0x%lx sym[m + 1]=0x%lx\n",
(unsigned long) sym[mid].addr,
(unsigned long) sym[mid + 1].addr);
+
if (sym[mid].addr <= address && sym[mid + 1].addr > address)
- {
- return &sym[mid];
- }
+ return &sym[mid];
+
if (sym[mid].addr > address)
- {
- high = mid;
- }
+ high = mid;
else
- {
- low = mid + 1;
- }
+ low = mid + 1;
}
+
fprintf (stderr, "[dbg_sym_lookup] binary search fails???\n");
+
return 0;
}
#endif /* DEBUG */
-/*
- * Look up an address in the symbol-table that is sorted by address.
- * If address does not hit any symbol, 0 is returned.
- */
+/* Look up an address in the symbol-table that is sorted by address.
+ If address does not hit any symbol, 0 is returned. */
Sym *
DEFUN (sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address)
{
#endif /* DEBUG */
if (!symtab->len)
- {
- return 0;
- }
+ return 0;
sym = symtab->base;
for (low = 0, high = symtab->len - 1; low != high;)
{
DBG (LOOKUPDEBUG, ++probes);
mid = (high + low) / 2;
+
if (sym[mid].addr <= address && sym[mid + 1].addr > address)
{
if (address > sym[mid].end_addr)
{
- /*
- * Address falls into gap between sym[mid] and
- * sym[mid + 1]:
- */
+ /* Address falls into gap between
+ sym[mid] and sym[mid + 1]. */
return 0;
}
else
return &sym[mid];
}
}
+
if (sym[mid].addr > address)
- {
- high = mid;
- }
+ high = mid;
else
- {
- low = mid + 1;
- }
+ low = mid + 1;
}
+
if (sym[mid + 1].addr <= address)
{
if (address > sym[mid + 1].end_addr)
{
- /* address is beyond end of sym[mid + 1]: */
+ /* Address is beyond end of sym[mid + 1]. */
return 0;
}
else
return &sym[mid + 1];
}
}
+
return 0;
}
+/* symtab.h
+
+ Copyright (C) 2000 Free Software Foundation, Inc.
+
+This file is part of GNU Binutils.
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+\f
#ifndef symtab_h
#define symtab_h
#include "bfd.h"
#include "gprof.h"
-/*
- * For a profile to be intelligible to a human user, it is necessary
- * to map code-addresses into source-code information. Source-code
- * information can be any combination of: (i) function-name, (ii)
- * source file-name, and (iii) source line number.
- *
- * The symbol table is used to map addresses into source-code
- * information.
- */
+/* For a profile to be intelligible to a human user, it is necessary
+ to map code-addresses into source-code information. Source-code
+ information can be any combination of: (i) function-name, (ii)
+ source file-name, and (iii) source line number.
+
+ The symbol table is used to map addresses into source-code
+ information. */
#include "source.h"
#define NBBS 10
-/*
- * Symbol-entry. For each external in the specified file we gather
- * its address, the number of calls and compute its share of cpu time.
- */
+/* Symbol-entry. For each external in the specified file we gather
+ its address, the number of calls and compute its share of cpu time. */
typedef struct sym
{
- /*
- * Common information:
- *
- * In the symbol-table, fields ADDR and FUNC_NAME are guaranteed
- * to contain valid information. FILE may be 0, if unknown and
- * LINE_NUM maybe 0 if unknown.
- */
- bfd_vma addr; /* address of entry point */
- bfd_vma end_addr; /* end-address */
- const char *name; /* name of function this sym is from */
- Source_File *file; /* source file symbol comes from */
- 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? */
- mapped:1, /* this symbol was mapped to another name */
- has_been_placed:1; /* have we placed this symbol? */
- unsigned long ncalls; /* how many times executed */
- int nuses; /* how many times this symbol appears in
- a particular context */
- bfd_vma bb_addr[NBBS]; /* address of basic-block start */
- unsigned long bb_calls[NBBS]; /* how many times basic-block was called */
- struct sym *next; /* for building chains of syms */
- struct sym *prev; /* for building chains of syms */
-
- /* profile-specific information: */
-
- /* histogram specific info: */
+ /* Common information:
+
+ In the symbol-table, fields ADDR and FUNC_NAME are guaranteed
+ to contain valid information. FILE may be 0, if unknown and
+ LINE_NUM maybe 0 if unknown. */
+
+ bfd_vma addr; /* Address of entry point. */
+ bfd_vma end_addr; /* End-address. */
+ const char *name; /* Name of function this sym is from. */
+ Source_File *file; /* Source file symbol comes from. */
+ int line_num; /* Source line number. */
+ unsigned int /* Boolean fields: */
+ 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? */
+ mapped:1, /* This symbol was mapped to another name. */
+ has_been_placed:1; /* Have we placed this symbol? */
+ unsigned long ncalls; /* How many times executed */
+ int nuses; /* How many times this symbol appears in
+ a particular context. */
+ bfd_vma bb_addr[NBBS]; /* Address of basic-block start. */
+ unsigned long bb_calls[NBBS];/* How many times basic-block was called. */
+ struct sym *next; /* For building chains of syms. */
+ struct sym *prev; /* For building chains of syms. */
+
+ /* Profile specific information: */
+
+ /* Histogram specific information: */
struct
{
- double time; /* (weighted) ticks in this routine */
- bfd_vma scaled_addr; /* scaled entry point */
+ double time; /* (Weighted) ticks in this routine. */
+ bfd_vma scaled_addr; /* Scaled entry point. */
}
hist;
- /* call-graph specific info: */
+ /* Call-graph specific information: */
struct
{
- unsigned long self_calls; /* how many calls to self */
- double child_time; /* cumulative ticks in children */
- int index; /* index in the graph list */
- int top_order; /* graph call chain top-sort order */
- bool print_flag; /* should this be printed? */
+ unsigned long self_calls; /* How many calls to self. */
+ double child_time; /* Cumulative ticks in children. */
+ int index; /* Index in the graph list. */
+ int top_order; /* Graph call chain top-sort order. */
+ bool print_flag; /* Should this be printed? */
struct
{
- double fract; /* what % of time propagates */
- double self; /* how much self time propagates */
- double child; /* how much child time propagates */
+ double fract; /* What % of time propagates. */
+ double self; /* How much self time propagates. */
+ double child; /* How much child time propagates. */
}
prop;
struct
{
- int num; /* internal number of cycle on */
- struct sym *head; /* head of cycle */
- struct sym *next; /* next member of cycle */
+ int num; /* Internal number of cycle on. */
+ struct sym *head; /* Head of cycle. */
+ struct sym *next; /* Next member of cycle. */
}
cyc;
- struct arc *parents; /* list of caller arcs */
- struct arc *children; /* list of callee arcs */
+ struct arc *parents; /* List of caller arcs. */
+ struct arc *children; /* List of callee arcs. */
}
cg;
}
Sym;
-/*
- * Symbol-tables are always assumed to be sorted in increasing order
- * of addresses:
- */
+/* Symbol-tables are always assumed to be sorted
+ in increasing order of addresses. */
typedef struct
{
- unsigned int len; /* # of symbols in this table */
- Sym *base; /* first element in symbol table */
- Sym *limit; /* limit = base + len */
+ unsigned int len; /* # of symbols in this table. */
+ Sym *base; /* First element in symbol table. */
+ Sym *limit; /* Limit = base + len. */
}
Sym_Table;
-extern Sym_Table symtab; /* the symbol table */
-
-extern void sym_init PARAMS ((Sym * sym));
-extern void symtab_finalize PARAMS ((Sym_Table * symtab));
-extern Sym *sym_lookup PARAMS ((Sym_Table * symtab, bfd_vma address));
+extern Sym_Table symtab; /* The symbol table. */
-extern void find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
+extern void sym_init PARAMS ((Sym *));
+extern void symtab_finalize PARAMS ((Sym_Table *));
+extern Sym *sym_lookup PARAMS ((Sym_Table *, bfd_vma));
+extern void find_call PARAMS ((Sym *, bfd_vma, bfd_vma));
#endif /* symtab_h */