Lots of changes from David Mosberger-Tang; see ChangeLog and NOTES for details:
[external/binutils.git] / gprof / call_graph.c
1 #include "cg_arcs.h"
2 #include "call_graph.h"
3 #include "core.h"
4 #include "gmon_io.h"
5 #include "gmon_out.h"
6 #include "symtab.h"
7 #include "sym_ids.h"
8
9 extern void
10 DEFUN(cg_tally, (from_pc, self_pc, count),
11       bfd_vma from_pc AND bfd_vma self_pc AND int count)
12 {
13     Sym *parent;
14     Sym *child;
15
16     parent = sym_lookup(&symtab, from_pc);
17     child = sym_lookup(&symtab, self_pc);
18
19     /*
20      * Keep arc if it is on INCL_ARCS table or if the INCL_ARCS table
21      * is empty and it is not in the EXCL_ARCS table.
22      */
23     if (sym_id_arc_is_present(&syms[INCL_ARCS], parent, child)
24         || (syms[INCL_ARCS].len == 0
25             && !sym_id_arc_is_present(&syms[EXCL_ARCS], parent, child)))
26     {
27         child->ncalls += count;
28         DBG(TALLYDEBUG,
29             printf("[cg_tally] arc from %s to %s traversed %d times\n",
30                    parent->name, child->name, count));
31         arc_add(parent, child, count);
32     } /* if */
33 } /* cg_tally */
34
35
36 /*
37  * Read a record from file IFP describing an arc in the function
38  * call-graph and the count of how many times the arc has been
39  * traversed.  FILENAME is the name of file IFP and is provided
40  * for formatting error-messages only.
41  */
42 void
43 DEFUN(cg_read_rec, (ifp, filename), FILE *ifp AND CONST char *filename)
44 {
45     bfd_vma from_pc, self_pc;
46     struct gmon_cg_arc_record arc;
47     int count;
48
49     if (fread(&arc, sizeof(arc), 1, ifp) != 1) {
50         fprintf(stderr, "%s: %s: unexpected end of file\n",
51                 whoami, filename);
52         done(1);
53     } /* if */
54     from_pc = get_vma(core_bfd, (bfd_byte *)arc.from_pc);
55     self_pc = get_vma(core_bfd, (bfd_byte *)arc.self_pc);
56     count = bfd_get_32(core_bfd, (bfd_byte *)arc.count);
57     DBG(SAMPLEDEBUG,
58         printf("[cg_read_rec] frompc 0x%lx selfpc 0x%lx count %d\n",
59                from_pc, self_pc, count));
60     /* add this arc: */
61     cg_tally(from_pc, self_pc, count);
62 } /* cg_read_rec */
63
64
65 /*
66  * Write all the arcs in the call-graph to file OFP.  FILENAME is
67  * the name of OFP and is provided for formatting error-messages
68  * only.
69  */
70 void
71 DEFUN(cg_write_arcs, (ofp, filename), FILE *ofp AND const char *filename)
72 {
73     const unsigned char tag = GMON_TAG_CG_ARC;
74     struct gmon_cg_arc_record raw_arc;
75     Arc *arc;
76     Sym *sym;
77
78     for (sym = symtab.base; sym < symtab.limit; sym++) {
79         for (arc = sym->cg.children; arc; arc = arc->next_child) {
80             put_vma(core_bfd, arc->parent->addr, (bfd_byte*) raw_arc.from_pc);
81             put_vma(core_bfd, arc->child->addr, (bfd_byte*) raw_arc.self_pc);
82             bfd_put_32(core_bfd, arc->count, (bfd_byte*) raw_arc.count);
83             if (fwrite(&tag, sizeof(tag), 1, ofp) != 1
84                 || fwrite(&raw_arc, sizeof(raw_arc), 1, ofp) != 1)
85             {
86                 perror(filename);
87                 done(1);
88             } /* if */
89             DBG(SAMPLEDEBUG,
90                 printf("[cg_write_arcs] frompc 0x%lx selfpc 0x%lx count %d\n",
91                        arc->parent->addr, arc->child->addr, arc->count));
92         } /* for */
93     } /* for */
94 } /* cg_write_arcs */
95
96                         /*** end of call_graph.c ***/