diff options
-rw-r--r-- | gprof/COPYING | 340 | ||||
-rw-r--r-- | gprof/ChangeLog | 26 | ||||
-rw-r--r-- | gprof/basic_blocks.c | 292 | ||||
-rw-r--r-- | gprof/basic_blocks.h | 41 | ||||
-rw-r--r-- | gprof/call_graph.c | 49 | ||||
-rw-r--r-- | gprof/call_graph.h | 27 | ||||
-rw-r--r-- | gprof/cg_print.c | 411 | ||||
-rw-r--r-- | gprof/cg_print.h | 30 | ||||
-rw-r--r-- | gprof/corefile.c | 305 | ||||
-rw-r--r-- | gprof/corefile.h | 45 | ||||
-rw-r--r-- | gprof/gmon_io.c | 123 | ||||
-rw-r--r-- | gprof/gmon_io.h | 39 | ||||
-rw-r--r-- | gprof/gmon_out.h | 62 | ||||
-rw-r--r-- | gprof/hist.c | 354 | ||||
-rw-r--r-- | gprof/hist.h | 45 | ||||
-rw-r--r-- | gprof/po/gprof.pot | 173 | ||||
-rw-r--r-- | gprof/search_list.c | 43 | ||||
-rw-r--r-- | gprof/search_list.h | 22 | ||||
-rw-r--r-- | gprof/source.c | 153 | ||||
-rw-r--r-- | gprof/source.h | 73 | ||||
-rw-r--r-- | gprof/sym_ids.c | 218 | ||||
-rw-r--r-- | gprof/sym_ids.h | 27 | ||||
-rw-r--r-- | gprof/symtab.c | 164 | ||||
-rw-r--r-- | gprof/symtab.h | 153 |
24 files changed, 1853 insertions, 1362 deletions
diff --git a/gprof/COPYING b/gprof/COPYING new file mode 100644 index 00000000000..60549be514a --- /dev/null +++ b/gprof/COPYING @@ -0,0 +1,340 @@ + 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. + + 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.) + +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. + + 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. + + 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 + + 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. diff --git a/gprof/ChangeLog b/gprof/ChangeLog index 43653e5c874..938fca0e032 100644 --- a/gprof/ChangeLog +++ b/gprof/ChangeLog @@ -1,3 +1,29 @@ +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 diff --git a/gprof/basic_blocks.c b/gprof/basic_blocks.c index 43dd762b01c..926743ff057 100644 --- a/gprof/basic_blocks.c +++ b/gprof/basic_blocks.c @@ -1,8 +1,26 @@ -/* - * 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. */ + #include <stdio.h> #include <unistd.h> #include "basic_blocks.h" @@ -14,26 +32,19 @@ #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) @@ -45,36 +56,25 @@ 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) { @@ -82,13 +82,9 @@ 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; @@ -98,10 +94,7 @@ DEFUN (cmp_ncalls, (lp, rp), const void *lp AND const void *rp) 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) { @@ -110,17 +103,13 @@ 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) { @@ -136,20 +125,18 @@ 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) @@ -170,15 +157,11 @@ DEFUN (bb_read_rec, (ifp, filename), FILE * ifp AND const char *filename) } } - /* - * 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); @@ -212,7 +195,7 @@ DEFUN (bb_read_rec, (ifp, filename), FILE * ifp AND const char *filename) { 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); } } @@ -220,12 +203,9 @@ DEFUN (bb_read_rec, (ifp, filename), FILE * ifp AND const char *filename) 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) { @@ -236,8 +216,7 @@ 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++) @@ -245,7 +224,7 @@ DEFUN (bb_write_blocks, (ofp, filename), FILE * ofp AND const char *filename) 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) @@ -254,7 +233,7 @@ DEFUN (bb_write_blocks, (ofp, filename), FILE * ofp AND const char *filename) done (1); } - /* write counts: */ + /* Write counts: */ for (sym = symtab.base; sym < symtab.limit; ++sym) { for (i = 0; i < NBBS && sym->bb_addr[i]; i++) @@ -272,13 +251,11 @@ DEFUN (bb_write_blocks, (ofp, filename), FILE * ofp AND const char *filename) } } +/* 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) { @@ -286,25 +263,19 @@ 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))) @@ -312,9 +283,10 @@ DEFUN_VOID (print_exec_counts) 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) { @@ -325,6 +297,7 @@ DEFUN_VOID (print_exec_counts) 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) @@ -340,17 +313,15 @@ DEFUN_VOID (print_exec_counts) 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), @@ -363,10 +334,10 @@ 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++) @@ -390,13 +361,11 @@ DEFUN (annotate_with_count, (buf, width, line_num, arg), 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); @@ -417,9 +386,8 @@ DEFUN (annotate_with_count, (buf, width, line_num, arg), } /* 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++) { @@ -432,9 +400,7 @@ DEFUN (annotate_with_count, (buf, width, line_num, arg), ncalls += last_count; if (bb_annotate_all_lines && last_count == last_print) - { - continue; - } + continue; if (p > tmpbuf) *p++ = ','; @@ -445,11 +411,10 @@ DEFUN (annotate_with_count, (buf, width, line_num, arg), } /* 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) { @@ -497,11 +462,10 @@ DEFUN (annotate_with_count, (buf, width, line_num, arg), } } -/* - * 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) { @@ -510,18 +474,14 @@ 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 @@ -531,8 +491,7 @@ DEFUN_VOID (print_annotated_source) } } - /* allocate line descriptors: */ - + /* Allocate line descriptors: */ for (sf = first_src_file; sf; sf = sf->next) { if (sf->num_lines > 0) @@ -542,8 +501,7 @@ DEFUN_VOID (print_annotated_source) } } - /* count executions per line: */ - + /* Count executions per line: */ for (sym = symtab.base; sym < symtab.limit; ++sym) { if (sym->file && sym->file->num_lines @@ -553,19 +511,20 @@ DEFUN_VOID (print_annotated_source) { 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; @@ -575,41 +534,37 @@ DEFUN_VOID (print_annotated_source) } } - /* 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); } } @@ -631,9 +586,8 @@ DEFUN_VOID (print_annotated_source) num_executable_lines ? (double) sf->ncalls / (double) num_executable_lines : 0.0); + if (ofp != stdout) - { - fclose (ofp); - } + fclose (ofp); } } diff --git a/gprof/basic_blocks.h b/gprof/basic_blocks.h index 923eca11f73..b6210aa84f7 100644 --- a/gprof/basic_blocks.h +++ b/gprof/basic_blocks.h @@ -1,3 +1,22 @@ +/* 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. */ + #ifndef basic_blocks_h #define basic_blocks_h @@ -6,18 +25,14 @@ #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 */ diff --git a/gprof/call_graph.c b/gprof/call_graph.c index 6eee251ff08..ac442cbb562 100644 --- a/gprof/call_graph.c +++ b/gprof/call_graph.c @@ -1,3 +1,24 @@ +/* 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. */ + #include "cg_arcs.h" #include "call_graph.h" #include "corefile.h" @@ -28,17 +49,14 @@ DEFUN (cg_tally, (from_pc, self_pc, count), 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))) @@ -51,13 +69,11 @@ DEFUN (cg_tally, (from_pc, self_pc, count), } } +/* 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) { @@ -71,22 +87,21 @@ 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) { diff --git a/gprof/call_graph.h b/gprof/call_graph.h index be5139b758f..af7cc78d210 100644 --- a/gprof/call_graph.h +++ b/gprof/call_graph.h @@ -1,3 +1,23 @@ +/* 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. */ + #ifndef call_graph_h #define call_graph_h @@ -5,9 +25,8 @@ #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 */ diff --git a/gprof/cg_print.c b/gprof/cg_print.c index e645bc7f82f..24613809931 100644 --- a/gprof/cg_print.c +++ b/gprof/cg_print.c @@ -1,12 +1,31 @@ +/* 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. */ + #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 @@ -14,7 +33,7 @@ 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)); @@ -25,39 +44,32 @@ static void 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", @@ -75,10 +87,8 @@ DEFUN_VOID (print_header) } } +/* Print a cycle header. */ -/* - * Print a cycle header. - */ static void DEFUN (print_cycle, (cyc), Sym * cyc) { @@ -90,22 +100,18 @@ 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) { @@ -115,64 +121,56 @@ 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 @@ -180,30 +178,26 @@ DEFUN (print_members, (cyc), Sym * cyc) : "%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) { @@ -228,69 +222,62 @@ 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; } } @@ -302,32 +289,30 @@ DEFUN (sort_parents, (child), Sym * child) { 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; } @@ -340,13 +325,10 @@ DEFUN (print_parents, (child), Sym * child) 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 @@ -355,14 +337,16 @@ DEFUN (print_parents, (child), Sym * child) "", "", "", "", "", ""); 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 ", @@ -373,7 +357,7 @@ DEFUN (print_parents, (child), Sym * child) } 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 ", @@ -391,32 +375,31 @@ static void 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; } @@ -429,13 +412,14 @@ DEFUN (print_children, (parent), Sym * parent) 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 ", @@ -445,7 +429,7 @@ DEFUN (print_children, (parent), Sym * parent) } 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 ", @@ -470,30 +454,28 @@ DEFUN (print_line, (np), Sym * np) : "%-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) { @@ -501,26 +483,24 @@ 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); } @@ -530,17 +510,20 @@ DEFUN (cg_print, (timesortsym), Sym ** timesortsym) 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); } @@ -563,44 +546,44 @@ DEFUN_VOID (cg_print_index) 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) @@ -610,27 +593,27 @@ DEFUN_VOID (cg_print_index) 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; } @@ -655,15 +638,19 @@ DEFUN_VOID (cg_print_index) 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) { @@ -678,8 +665,9 @@ 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) { @@ -873,8 +861,8 @@ DEFUN_VOID (cg_print_function_ordering) 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) @@ -884,6 +872,7 @@ DEFUN_VOID (cg_print_function_ordering) } arc = sym->cg.parents; + while (arc) { if (arc->parent != arc->child) @@ -895,13 +884,13 @@ DEFUN_VOID (cg_print_function_ordering) /* 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]; @@ -920,22 +909,22 @@ DEFUN_VOID (cg_print_function_ordering) } } - /* 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); @@ -1003,6 +992,7 @@ order_and_dump_functions_by_arcs (arcs, numarcs, all, total_arcs = 0; tmp_arcs = 0; + for (index = 0; index < numarcs; index++) { Sym *sym1, *sym2; @@ -1062,7 +1052,7 @@ order_and_dump_functions_by_arcs (arcs, numarcs, all, /* Choose the closest. */ child = next_count < prev_count ? next : prev; - } + } else if (! child->next && !child->prev) { int next_count = 0; @@ -1145,14 +1135,14 @@ order_and_dump_functions_by_arcs (arcs, numarcs, all, 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; @@ -1191,8 +1181,8 @@ order_and_dump_functions_by_arcs (arcs, numarcs, all, } } - /* 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++) { @@ -1212,7 +1202,8 @@ order_and_dump_functions_by_arcs (arcs, numarcs, all, 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; }; @@ -1253,8 +1244,8 @@ DEFUN_VOID (cg_print_file_ordering) { 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; @@ -1267,8 +1258,8 @@ DEFUN_VOID (cg_print_file_ordering) 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; diff --git a/gprof/cg_print.h b/gprof/cg_print.h index 782c4aa04c2..03a4a8482e7 100644 --- a/gprof/cg_print.h +++ b/gprof/cg_print.h @@ -1,14 +1,34 @@ +/* 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. */ + #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 */ diff --git a/gprof/corefile.c b/gprof/corefile.c index 790fc286208..255a0a3933c 100644 --- a/gprof/corefile.c +++ b/gprof/corefile.c @@ -1,3 +1,24 @@ +/* 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. */ + #include "libiberty.h" #include "gprof.h" #include "corefile.h" @@ -13,7 +34,8 @@ int min_insn_size; 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; }; @@ -21,9 +43,9 @@ struct function_map { 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)); @@ -112,6 +134,7 @@ DEFUN (read_function_mappings, (filename), const char *filename) symbol_map_count = count; } + void DEFUN (core_init, (a_out_name), const char *a_out_name) { @@ -129,7 +152,7 @@ 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) { @@ -142,9 +165,9 @@ DEFUN (core_init, (a_out_name), const char *a_out_name) } } - /* 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) { @@ -155,6 +178,7 @@ DEFUN (core_init, (a_out_name), const char *a_out_name) 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, @@ -184,10 +208,8 @@ DEFUN (core_init, (a_out_name), const char *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) { @@ -199,6 +221,7 @@ 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)) { @@ -206,10 +229,9 @@ DEFUN (core_get_text_space, (core_bfd), bfd * core_bfd) 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); } @@ -248,12 +270,11 @@ DEFUN (find_call, (parent, p_lowpc, p_highpc), } } -/* - * 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) { @@ -263,14 +284,10 @@ 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", @@ -282,81 +299,65 @@ DEFUN (core_sym_class, (sym), asymbol * sym) 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 @@ -386,11 +387,9 @@ DEFUN (get_src_info, (addr, filename, name, line_num), } } +/* 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; @@ -400,14 +399,13 @@ core_create_function_syms (core_bfd) 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. @@ -424,6 +422,7 @@ core_create_function_syms (core_bfd) skip = 1; break; } + if (!skip) ++symtab.len; } @@ -434,15 +433,16 @@ core_create_function_syms (core_bfd) 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, @@ -451,11 +451,12 @@ core_create_function_syms (core_bfd) 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)) { @@ -472,9 +473,9 @@ core_create_function_syms (core_bfd) 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)) { @@ -487,8 +488,7 @@ core_create_function_syms (core_bfd) 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; @@ -500,22 +500,18 @@ core_create_function_syms (core_bfd) /* 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)); @@ -527,23 +523,18 @@ core_create_function_syms (core_bfd) 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), @@ -552,8 +543,7 @@ core_create_function_syms (core_bfd) ++symtab.limit; } - /* create sentinels: */ - + /* Create sentinels. */ sym_init (symtab.limit); symtab.limit->name = "<locore>"; symtab.limit->addr = 0; @@ -570,11 +560,9 @@ core_create_function_syms (core_bfd) 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) { @@ -586,43 +574,40 @@ 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; @@ -634,15 +619,17 @@ DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) 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); @@ -652,12 +639,12 @@ DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) 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. @@ -675,31 +662,28 @@ DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) 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) { @@ -713,15 +697,11 @@ DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) 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), @@ -730,22 +710,19 @@ DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) ++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; @@ -757,10 +734,8 @@ DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) done (1); } - /* finalize ltab and make it symbol table: */ - + /* Finalize ltab and make it symbol table. */ symtab_finalize (<ab); free (symtab.base); symtab = ltab; - } diff --git a/gprof/corefile.h b/gprof/corefile.h index b396f8500b2..3259b804975 100644 --- a/gprof/corefile.h +++ b/gprof/corefile.h @@ -1,21 +1,40 @@ +/* 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. */ + #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 */ diff --git a/gprof/gmon_io.c b/gprof/gmon_io.c index f2ac524ac6f..af1d7677451 100644 --- a/gprof/gmon_io.c +++ b/gprof/gmon_io.c @@ -1,6 +1,24 @@ -/* - * 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. */ + #include "cg_arcs.h" #include "basic_blocks.h" #include "bfd.h" @@ -8,18 +26,17 @@ #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) { @@ -37,9 +54,8 @@ 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) { @@ -67,8 +83,7 @@ DEFUN (gmon_out_read, (filename), const char *filename) unsigned char tag; int nhist = 0, narcs = 0, nbbs = 0; - /* open gmon.out file: */ - + /* Open gmon.out file. */ if (strcmp (filename, "-") == 0) { ifp = stdin; @@ -79,12 +94,14 @@ DEFUN (gmon_out_read, (filename), const char *filename) 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"), @@ -102,9 +119,9 @@ DEFUN (gmon_out_read, (filename), const char *filename) 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, @@ -113,7 +130,7 @@ DEFUN (gmon_out_read, (filename), const char *filename) done (1); } - /* read in all the records: */ + /* Read in all the records. */ while (fread (&tag, sizeof (tag), 1, ifp) == 1) { switch (tag) @@ -163,22 +180,19 @@ DEFUN (gmon_out_read, (filename), const char *filename) 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)) { @@ -186,6 +200,7 @@ DEFUN (gmon_out_read, (filename), const char *filename) filename); done (1); } + tmp.low_pc = get_vma (core_bfd, (bfd_byte *) &raw.low_pc[0]); tmp.high_pc = get_vma (core_bfd, (bfd_byte *) &raw.high_pc[0]); tmp.ncnt = bfd_get_32 (core_bfd, (bfd_byte *) &raw.ncnt[0]); @@ -196,8 +211,8 @@ DEFUN (gmon_out_read, (filename), const char *filename) 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) @@ -212,7 +227,7 @@ DEFUN (gmon_out_read, (filename), const char *filename) } else { - /* old style BSD format. */ + /* Old style BSD format. */ if (file_format == FF_BSD44) { fprintf (stderr, _("%s: file `%s' has bad magic cookie\n"), @@ -236,6 +251,7 @@ DEFUN (gmon_out_read, (filename), const char *filename) filename); done (1); } + h = tmp; s_lowpc = (bfd_vma) h.low_pc; s_highpc = (bfd_vma) h.high_pc; @@ -243,6 +259,7 @@ DEFUN (gmon_out_read, (filename), const char *filename) 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, @@ -264,14 +281,13 @@ DEFUN (gmon_out_read, (filename), const char *filename) } 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])); } @@ -284,34 +300,35 @@ DEFUN (gmon_out_read, (filename), const char *filename) 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; @@ -356,33 +373,28 @@ DEFUN (gmon_out_write, (filename), const char *filename) 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) { @@ -423,8 +435,7 @@ DEFUN (gmon_out_write, (filename), const char *filename) } } - /* 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]); @@ -435,8 +446,7 @@ DEFUN (gmon_out_write, (filename), const char *filename) } } - /* 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) @@ -457,6 +467,7 @@ DEFUN (gmon_out_write, (filename), const char *filename) (unsigned long) arc->child->addr, arc->count)); } } + fclose (ofp); } else diff --git a/gprof/gmon_io.h b/gprof/gmon_io.h index 06bca377b48..b081561bcd8 100644 --- a/gprof/gmon_io.h +++ b/gprof/gmon_io.h @@ -1,3 +1,23 @@ +/* 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. */ + #ifndef gmon_io_h #define gmon_io_h @@ -22,17 +42,16 @@ #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 */ diff --git a/gprof/gmon_out.h b/gprof/gmon_out.h index 2144fb5954b..3bec88b10b9 100644 --- a/gprof/gmon_out.h +++ b/gprof/gmon_out.h @@ -1,22 +1,38 @@ -/* - * 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. */ + +/* 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]; @@ -24,7 +40,7 @@ struct gmon_hdr 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 @@ -33,19 +49,19 @@ GMON_Record_Tag; 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 */ diff --git a/gprof/hist.c b/gprof/hist.c index 56ef25a0a3c..a4cb1a40bd9 100644 --- a/gprof/hist.c +++ b/gprof/hist.c @@ -1,6 +1,24 @@ -/* - * 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. */ + #include <stdio.h> #include "libiberty.h" #include "gprof.h" @@ -16,25 +34,24 @@ 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; @@ -88,10 +105,10 @@ SItab[] = , /* 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) { @@ -117,9 +134,7 @@ 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); @@ -165,10 +180,9 @@ DEFUN (hist_read_rec, (ifp, filename), FILE * ifp AND const char *filename) } -/* - * 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) { @@ -177,7 +191,7 @@ 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); @@ -197,6 +211,7 @@ DEFUN (hist_write_hist, (ofp, filename), FILE * ofp AND const char *filename) 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); @@ -206,14 +221,13 @@ DEFUN (hist_write_hist, (ofp, filename), FILE * ofp AND const char *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 () { @@ -239,44 +253,43 @@ 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) { @@ -287,23 +300,22 @@ 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", @@ -312,28 +324,22 @@ DEFUN_VOID (hist_assign_samples) 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) @@ -345,13 +351,13 @@ DEFUN_VOID (hist_assign_samples) (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))) @@ -365,14 +371,14 @@ DEFUN_VOID (hist_assign_samples) } } } + 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) { @@ -398,7 +404,8 @@ 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; } @@ -414,50 +421,39 @@ static void 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) { @@ -466,31 +462,25 @@ 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) { @@ -501,15 +491,12 @@ 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) @@ -522,36 +509,36 @@ DEFUN_VOID (hist_print) { 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; @@ -559,9 +546,11 @@ DEFUN_VOID (hist_print) } } } + 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)) @@ -571,30 +560,25 @@ DEFUN_VOID (hist_print) } } - /* - * 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); } diff --git a/gprof/hist.h b/gprof/hist.h index df62ef770f4..b36528164f3 100644 --- a/gprof/hist.h +++ b/gprof/hist.h @@ -1,23 +1,42 @@ +/* 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. */ + #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 */ diff --git a/gprof/po/gprof.pot b/gprof/po/gprof.pot index 47f6fda1461..6b4482dcee9 100644 --- a/gprof/po/gprof.pot +++ b/gprof/po/gprof.pot @@ -6,7 +6,7 @@ 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" @@ -33,27 +33,27 @@ msgstr "" 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" @@ -64,262 +64,262 @@ msgid "" "\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" @@ -333,117 +333,122 @@ msgid "" "\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" @@ -451,16 +456,16 @@ msgid "" "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 "" diff --git a/gprof/search_list.c b/gprof/search_list.c index ca2928935c0..8a496a66fa0 100644 --- a/gprof/search_list.c +++ b/gprof/search_list.c @@ -1,3 +1,24 @@ +/* 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. */ + #include "libiberty.h" #include "gprof.h" #include "search_list.h" @@ -16,28 +37,24 @@ DEFUN (search_list_append, (list, paths), { 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); diff --git a/gprof/search_list.h b/gprof/search_list.h index 6f5acae934f..a864810d34c 100644 --- a/gprof/search_list.h +++ b/gprof/search_list.h @@ -1,3 +1,23 @@ +/* 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. */ + #ifndef search_list_h #define search_list_h @@ -23,6 +43,6 @@ typedef struct } 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 */ diff --git a/gprof/source.c b/gprof/source.c index dd671d5e159..a083a07b399 100644 --- a/gprof/source.c +++ b/gprof/source.c @@ -1,21 +1,36 @@ -/* - * 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. */ + #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; @@ -27,20 +42,21 @@ DEFUN (source_file_lookup_path, (path), const char *path) 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; } @@ -50,28 +66,24 @@ DEFUN (source_file_lookup_name, (filename), const char *filename) { 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; } @@ -91,25 +103,23 @@ DEFUN (annotate_source, (sf, max_width, annote, arg), 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, '/'); @@ -124,11 +134,12 @@ DEFUN (annotate_source, (sf, max_width, annote, arg), #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); @@ -138,38 +149,34 @@ DEFUN (annotate_source, (sf, max_width, annote, arg), 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 { @@ -181,13 +188,9 @@ DEFUN (annotate_source, (sf, max_width, annote, arg), } #endif if (filename) - { - ++filename; - } + ++filename; else - { - filename = sf->name; - } + filename = sf->name; strcpy (fname, filename); strcat (fname, EXT_ANNO); @@ -210,6 +213,7 @@ DEFUN (annotate_source, (sf, max_width, annote, arg), } #endif ofp = fopen (fname, "w"); + if (!ofp) { perror (fname); @@ -217,34 +221,27 @@ DEFUN (annotate_source, (sf, max_width, annote, arg), } } - /* - * 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) @@ -256,10 +253,12 @@ DEFUN (annotate_source, (sf, max_width, annote, arg), ++line_num; new_line = FALSE; } + new_line = (buf[i] == '\n'); fputc (buf[i], ofp); } } + free (annotation); return ofp; } diff --git a/gprof/source.h b/gprof/source.h index b33bad3e0a6..cc2e9d060c3 100644 --- a/gprof/source.h +++ b/gprof/source.h @@ -1,3 +1,23 @@ +/* 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. */ + #ifndef source_h #define source_h @@ -8,48 +28,37 @@ 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 */ diff --git a/gprof/sym_ids.c b/gprof/sym_ids.c index 1e05914c952..8bde3b9d5d6 100644 --- a/gprof/sym_ids.c +++ b/gprof/sym_ids.c @@ -1,3 +1,24 @@ +/* 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. */ + #include <ctype.h> #include "libiberty.h" @@ -7,14 +28,15 @@ 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; @@ -35,13 +57,11 @@ const char *table_name[] = }; #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 = @@ -69,17 +89,16 @@ DEFUN (sym_id_add, (spec, which_table), } -/* - * 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) { @@ -87,40 +106,38 @@ 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)) { @@ -134,10 +151,9 @@ DEFUN (parse_spec, (spec, sym), char *spec AND Sym * sym) } -/* - * 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) { @@ -158,44 +174,35 @@ 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) { @@ -214,37 +221,36 @@ DEFUN (extend_match, (m, sym, tab, second_pass), { 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) { @@ -252,33 +258,24 @@ 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) @@ -288,6 +285,7 @@ DEFUN_VOID (sym_id_parse) tab->len = 0; } } + if (right_ids.len) { right_ids.base = (Sym *) xmalloc (right_ids.len * sizeof (Sym)); @@ -295,25 +293,20 @@ DEFUN_VOID (sym_id_parse) 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) @@ -334,14 +327,14 @@ DEFUN_VOID (sym_id_parse) (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", @@ -351,14 +344,12 @@ DEFUN_VOID (sym_id_parse) } -/* - * 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) @@ -369,9 +360,8 @@ DEFUN (sym_id_arc_is_present, (symtab, from, to), { if (from->addr >= sym->addr && from->addr <= sym->end_addr && arc_lookup (sym, to)) - { - return TRUE; - } + return TRUE; } + return FALSE; } diff --git a/gprof/sym_ids.h b/gprof/sym_ids.h index 90963381b22..8bb3f907063 100644 --- a/gprof/sym_ids.h +++ b/gprof/sym_ids.h @@ -1,3 +1,23 @@ +/* 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. */ + #ifndef sym_ids_h #define sym_ids_h @@ -17,9 +37,8 @@ Table_Id; 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 */ diff --git a/gprof/symtab.c b/gprof/symtab.c index e4fda46533f..ac9e95f7ab2 100644 --- a/gprof/symtab.c +++ b/gprof/symtab.c @@ -1,3 +1,24 @@ +/* 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. */ + #include "gprof.h" #include "cg_arcs.h" #include "corefile.h" @@ -6,17 +27,15 @@ 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; @@ -25,16 +44,15 @@ DEFUN (sym_init, (sym), Sym * sym) } -/* - * 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) { @@ -42,18 +60,12 @@ 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; } @@ -66,33 +78,26 @@ DEFUN (symtab_finalize, (tab), Sym_Table * tab) 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) @@ -109,6 +114,7 @@ DEFUN (symtab_finalize, (tab), Sym_Table * tab) 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 @@ -125,11 +131,9 @@ DEFUN (symtab_finalize, (tab), Sym_Table * tab) 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; @@ -138,10 +142,9 @@ DEFUN (symtab_finalize, (tab), Sym_Table * tab) } } } + 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", @@ -154,11 +157,11 @@ DEFUN (symtab_finalize, (tab), Sym_Table * tab) 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); + } ); } @@ -178,35 +181,32 @@ DEFUN (dbg_sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address 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) { @@ -218,23 +218,20 @@ 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 @@ -245,20 +242,18 @@ DEFUN (sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address) 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 @@ -268,5 +263,6 @@ DEFUN (sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address) return &sym[mid + 1]; } } + return 0; } diff --git a/gprof/symtab.h b/gprof/symtab.h index a6a450ef1ee..3d127946ba9 100644 --- a/gprof/symtab.h +++ b/gprof/symtab.h @@ -1,111 +1,124 @@ +/* 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. */ + #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 */ |