Back to index

cell-binutils  2.17cvs20070401
call_graph.c
Go to the documentation of this file.
00001 /* call_graph.c  -  Create call graphs.
00002 
00003    Copyright 1999, 2000, 2001, 2002, 2004 Free Software Foundation, Inc.
00004 
00005    This file is part of GNU Binutils.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 2 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program; if not, write to the Free Software
00019    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
00020    02110-1301, USA.  */
00021 
00022 #include "gprof.h"
00023 #include "search_list.h"
00024 #include "source.h"
00025 #include "symtab.h"
00026 #include "cg_arcs.h"
00027 #include "call_graph.h"
00028 #include "corefile.h"
00029 #include "gmon_io.h"
00030 #include "gmon_out.h"
00031 #include "sym_ids.h"
00032 
00033 void
00034 cg_tally (bfd_vma from_pc, bfd_vma self_pc, unsigned long count)
00035 {
00036   Sym *parent;
00037   Sym *child;
00038 
00039   parent = sym_lookup (&symtab, from_pc);
00040   child = sym_lookup (&symtab, self_pc);
00041 
00042   if (child == NULL || parent == NULL)
00043     return;
00044 
00045   /* If we're doing line-by-line profiling, both the parent and the
00046      child will probably point to line symbols instead of function
00047      symbols.  For the parent this is fine, since this identifies the
00048      line number in the calling routing, but the child should always
00049      point to a function entry point, so we back up in the symbol
00050      table until we find it.
00051 
00052      For normal profiling, is_func will be set on all symbols, so this
00053      code will do nothing.  */
00054   while (child >= symtab.base && ! child->is_func)
00055     --child;
00056 
00057   if (child < symtab.base)
00058     return;
00059 
00060   /* Keep arc if it is on INCL_ARCS table or if the INCL_ARCS table
00061      is empty and it is not in the EXCL_ARCS table.  */
00062   if (sym_id_arc_is_present (&syms[INCL_ARCS], parent, child)
00063       || (syms[INCL_ARCS].len == 0
00064          && !sym_id_arc_is_present (&syms[EXCL_ARCS], parent, child)))
00065     {
00066       child->ncalls += count;
00067       DBG (TALLYDEBUG,
00068           printf (_("[cg_tally] arc from %s to %s traversed %lu times\n"),
00069                  parent->name, child->name, count));
00070       arc_add (parent, child, count);
00071     }
00072 }
00073 
00074 /* Read a record from file IFP describing an arc in the function
00075    call-graph and the count of how many times the arc has been
00076    traversed.  FILENAME is the name of file IFP and is provided
00077    for formatting error-messages only.  */
00078 
00079 void
00080 cg_read_rec (FILE *ifp, const char *filename)
00081 {
00082   bfd_vma from_pc, self_pc;
00083   unsigned int count;
00084 
00085   if (gmon_io_read_vma (ifp, &from_pc)
00086       || gmon_io_read_vma (ifp, &self_pc)
00087       || gmon_io_read_32 (ifp, &count))
00088     {
00089       fprintf (stderr, _("%s: %s: unexpected end of file\n"),
00090               whoami, filename);
00091       done (1);
00092     }
00093 
00094   DBG (SAMPLEDEBUG,
00095        printf ("[cg_read_rec] frompc 0x%lx selfpc 0x%lx count %lu\n",
00096               (unsigned long) from_pc, (unsigned long) self_pc,
00097               (unsigned long) count));
00098   /* Add this arc:  */
00099   cg_tally (from_pc, self_pc, count);
00100 }
00101 
00102 /* Write all the arcs in the call-graph to file OFP.  FILENAME is
00103    the name of OFP and is provided for formatting error-messages
00104    only.  */
00105 
00106 void
00107 cg_write_arcs (FILE *ofp, const char *filename)
00108 {
00109   Arc *arc;
00110   Sym *sym;
00111 
00112   for (sym = symtab.base; sym < symtab.limit; sym++)
00113     {
00114       for (arc = sym->cg.children; arc; arc = arc->next_child)
00115        {
00116          if (gmon_io_write_8 (ofp, GMON_TAG_CG_ARC)
00117              || gmon_io_write_vma (ofp, arc->parent->addr)
00118              || gmon_io_write_vma (ofp, arc->child->addr)
00119              || gmon_io_write_32 (ofp, arc->count))
00120            {
00121              perror (filename);
00122              done (1);
00123            }
00124          DBG (SAMPLEDEBUG,
00125             printf ("[cg_write_arcs] frompc 0x%lx selfpc 0x%lx count %lu\n",
00126                    (unsigned long) arc->parent->addr,
00127                    (unsigned long) arc->child->addr, arc->count));
00128        }
00129     }
00130 }