aboutsummaryrefslogtreecommitdiff
path: root/gprof/call_graph.c
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@cygnus>1995-02-07 22:34:18 +0000
committerKen Raeburn <raeburn@cygnus>1995-02-07 22:34:18 +0000
commit5489fcc3d9dbb1f529dddb19b615e23d8ed59dc7 (patch)
tree1a79cfffd92f2afb67780dd7372c1759c49791aa /gprof/call_graph.c
parent2559e01429d193b7957c106a6a8b0598476f9845 (diff)
downloadgdb-5489fcc3d9dbb1f529dddb19b615e23d8ed59dc7.zip
gdb-5489fcc3d9dbb1f529dddb19b615e23d8ed59dc7.tar.gz
gdb-5489fcc3d9dbb1f529dddb19b615e23d8ed59dc7.tar.bz2
Lots of changes from David Mosberger-Tang; see ChangeLog and NOTES for details:
Alpha support. Long options. New file format to support more information; backwards compatibility. Line-level profiling, on systems where bfd_find_nearest_line works. Selective display of data.
Diffstat (limited to 'gprof/call_graph.c')
-rw-r--r--gprof/call_graph.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/gprof/call_graph.c b/gprof/call_graph.c
new file mode 100644
index 0000000..bba8b8c
--- /dev/null
+++ b/gprof/call_graph.c
@@ -0,0 +1,96 @@
+#include "cg_arcs.h"
+#include "call_graph.h"
+#include "core.h"
+#include "gmon_io.h"
+#include "gmon_out.h"
+#include "symtab.h"
+#include "sym_ids.h"
+
+extern void
+DEFUN(cg_tally, (from_pc, self_pc, count),
+ bfd_vma from_pc AND bfd_vma self_pc AND int count)
+{
+ Sym *parent;
+ Sym *child;
+
+ parent = sym_lookup(&symtab, from_pc);
+ child = sym_lookup(&symtab, self_pc);
+
+ /*
+ * 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)))
+ {
+ child->ncalls += count;
+ DBG(TALLYDEBUG,
+ printf("[cg_tally] arc from %s to %s traversed %d times\n",
+ parent->name, child->name, count));
+ arc_add(parent, child, count);
+ } /* if */
+} /* cg_tally */
+
+
+/*
+ * 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)
+{
+ bfd_vma from_pc, self_pc;
+ struct gmon_cg_arc_record arc;
+ int count;
+
+ if (fread(&arc, sizeof(arc), 1, ifp) != 1) {
+ fprintf(stderr, "%s: %s: unexpected end of file\n",
+ whoami, filename);
+ done(1);
+ } /* if */
+ 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 %d\n",
+ from_pc, self_pc, count));
+ /* add this arc: */
+ cg_tally(from_pc, self_pc, count);
+} /* cg_read_rec */
+
+
+/*
+ * 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)
+{
+ const unsigned char tag = GMON_TAG_CG_ARC;
+ struct gmon_cg_arc_record raw_arc;
+ Arc *arc;
+ Sym *sym;
+
+ for (sym = symtab.base; sym < symtab.limit; sym++) {
+ for (arc = sym->cg.children; arc; arc = arc->next_child) {
+ put_vma(core_bfd, arc->parent->addr, (bfd_byte*) raw_arc.from_pc);
+ put_vma(core_bfd, arc->child->addr, (bfd_byte*) raw_arc.self_pc);
+ bfd_put_32(core_bfd, arc->count, (bfd_byte*) raw_arc.count);
+ if (fwrite(&tag, sizeof(tag), 1, ofp) != 1
+ || fwrite(&raw_arc, sizeof(raw_arc), 1, ofp) != 1)
+ {
+ perror(filename);
+ done(1);
+ } /* if */
+ DBG(SAMPLEDEBUG,
+ printf("[cg_write_arcs] frompc 0x%lx selfpc 0x%lx count %d\n",
+ arc->parent->addr, arc->child->addr, arc->count));
+ } /* for */
+ } /* for */
+} /* cg_write_arcs */
+
+ /*** end of call_graph.c ***/