From 12516a373c27abe4516c2a3c84cfe9d94f02e18f Mon Sep 17 00:00:00 2001 From: Ken Raeburn Date: Wed, 8 Feb 1995 02:35:44 +0000 Subject: ran "indent -gnu"; have not fixed block comment style --- gprof/ChangeLog | 4 + gprof/alpha.c | 203 +++++----- gprof/alpha.h | 2 +- gprof/basic_blocks.c | 730 +++++++++++++++++++----------------- gprof/basic_blocks.h | 14 +- gprof/call_graph.c | 119 +++--- gprof/call_graph.h | 6 +- gprof/cg_arcs.c | 1001 +++++++++++++++++++++++++++----------------------- gprof/cg_arcs.h | 30 +- gprof/cg_dfn.c | 363 ++++++++++-------- gprof/cg_dfn.h | 2 +- gprof/cg_print.c | 982 +++++++++++++++++++++++++++---------------------- gprof/cg_print.h | 6 +- gprof/core.c | 810 +++++++++++++++++++++------------------- gprof/core.h | 18 +- gprof/dummy.c | 12 +- gprof/dummy.h | 5 +- gprof/gmon.h | 39 +- gprof/gmon_io.c | 648 +++++++++++++++++--------------- gprof/gmon_io.h | 12 +- gprof/gmon_out.h | 45 ++- gprof/gprof.c | 798 +++++++++++++++++++++++----------------- gprof/gprof.h | 100 ++--- gprof/hertz.c | 31 +- gprof/hertz.h | 4 +- gprof/hist.c | 829 ++++++++++++++++++++++------------------- gprof/hist.h | 18 +- gprof/i386.c | 113 +++--- gprof/i386.h | 8 +- gprof/ns532.c | 8 +- gprof/ns532.h | 11 +- gprof/search_list.c | 64 ++-- gprof/search_list.h | 18 +- gprof/source.c | 367 +++++++++--------- gprof/source.h | 30 +- gprof/sparc.c | 98 ++--- gprof/sparc.h | 9 +- gprof/sym_ids.c | 509 +++++++++++++------------ gprof/sym_ids.h | 14 +- gprof/symtab.c | 372 ++++++++++--------- gprof/symtab.h | 100 ++--- gprof/tahoe.c | 496 +++++++++++++------------ gprof/tahoe.h | 19 +- gprof/utils.c | 123 ++++--- gprof/utils.h | 4 +- gprof/vax.c | 492 +++++++++++++------------ gprof/vax.h | 29 +- 47 files changed, 5259 insertions(+), 4456 deletions(-) diff --git a/gprof/ChangeLog b/gprof/ChangeLog index 4f7fe33..df21343 100644 --- a/gprof/ChangeLog +++ b/gprof/ChangeLog @@ -1,5 +1,9 @@ Tue Feb 7 17:24:12 1995 Ken Raeburn + * All *.c and *.h files: Ran "indent -gnu". Cleaned up a couple + of constructs GNU indent couldn't handle. Block comments not yet + rewritten in GNU format. + * gprof.c (VERSION): Changed to 2.6, to get in sync for next binutils release. diff --git a/gprof/alpha.c b/gprof/alpha.c index 9051634..e81b372 100644 --- a/gprof/alpha.c +++ b/gprof/alpha.c @@ -33,24 +33,32 @@ #define Jxx_FUNC_RET 2 #define Jxx_FUNC_JSR_COROUTINE 3 -typedef union { - struct { - unsigned other : 26; - unsigned op_code : 6; - } a; /* any format */ - struct { - signed disp : 21; - unsigned ra : 5; - unsigned op_code : 6; - } b; /* branch format */ - struct { - signed hint : 14; - unsigned func : 2; - unsigned rb : 5; - unsigned ra : 5; - unsigned op_code : 6; - } j; /* jump format */ -} Instruction; +typedef union + { + struct + { + unsigned other:26; + unsigned op_code:6; + } + a; /* any format */ + struct + { + signed disp:21; + unsigned ra:5; + unsigned op_code:6; + } + b; /* branch format */ + struct + { + signed hint:14; + unsigned func:2; + unsigned rb:5; + unsigned ra:5; + unsigned op_code:6; + } + j; /* jump format */ + } +Instruction; static Sym indirect_child; @@ -63,92 +71,99 @@ static Sym indirect_child; * potentially call integer division routines, for example.) */ void -find_call(parent, p_lowpc, p_highpc) +find_call (parent, p_lowpc, p_highpc) Sym *parent; bfd_vma p_lowpc; bfd_vma p_highpc; { - static bfd_vma delta = 0; - bfd_vma dest_pc; - Instruction *pc; - Sym *child; - - if (!delta) { - delta = (bfd_vma) core_text_space - core_text_sect->vma; + static bfd_vma delta = 0; + bfd_vma dest_pc; + Instruction *pc; + Sym *child; - sym_init(&indirect_child); - indirect_child.name = ""; - indirect_child.cg.prop.fract = 1.0; - indirect_child.cg.cyc.head = &indirect_child; - } /* if */ - - if (!core_text_space) { - return; - } /* if */ - if (p_lowpc < s_lowpc) { - p_lowpc = s_lowpc; - } /* if */ - if (p_highpc > s_highpc) { - p_highpc = s_highpc; - } /* if */ - DBG(CALLDEBUG, printf("[find_call] %s: 0x%lx to 0x%lx\n", + if (!delta) + { + delta = (bfd_vma) core_text_space - core_text_sect->vma; + + sym_init (&indirect_child); + indirect_child.name = ""; + indirect_child.cg.prop.fract = 1.0; + indirect_child.cg.cyc.head = &indirect_child; + } /* if */ + + if (!core_text_space) + { + return; + } /* if */ + if (p_lowpc < s_lowpc) + { + p_lowpc = s_lowpc; + } /* if */ + if (p_highpc > s_highpc) + { + p_highpc = s_highpc; + } /* if */ + DBG (CALLDEBUG, printf ("[find_call] %s: 0x%lx to 0x%lx\n", parent->name, p_lowpc, p_highpc)); - for (pc = (Instruction*)(p_lowpc + delta); - pc < (Instruction*)(p_highpc + delta); - ++pc) + for (pc = (Instruction *) (p_lowpc + delta); + pc < (Instruction *) (p_highpc + delta); + ++pc) { - switch (pc->a.op_code) { - case OP_Jxx: - /* - * There is no simple and reliable way to determine the - * target of a jsr (the hint bits help, but there aren't - * enough bits to get a satisfactory hit rate). Instead, - * for any indirect jump we simply add an arc from PARENT - * to INDIRECT_CHILD---that way the user it at least able - * to see that there are other calls as well. - */ - if (pc->j.func == Jxx_FUNC_JSR - || pc->j.func == Jxx_FUNC_JSR_COROUTINE) + switch (pc->a.op_code) + { + case OP_Jxx: + /* + * There is no simple and reliable way to determine the + * target of a jsr (the hint bits help, but there aren't + * enough bits to get a satisfactory hit rate). Instead, + * for any indirect jump we simply add an arc from PARENT + * to INDIRECT_CHILD---that way the user it at least able + * to see that there are other calls as well. + */ + if (pc->j.func == Jxx_FUNC_JSR + || pc->j.func == Jxx_FUNC_JSR_COROUTINE) { - DBG(CALLDEBUG, - printf("[find_call] 0x%lx: jsr%s \n", + DBG (CALLDEBUG, + printf ("[find_call] 0x%lx: jsr%s \n", (bfd_vma) pc - delta, pc->j.func == Jxx_FUNC_JSR ? "" : "_coroutine")); - arc_add(parent, &indirect_child, 0); - } /* if */ - break; + arc_add (parent, &indirect_child, 0); + } /* if */ + break; - case OP_BSR: - DBG(CALLDEBUG, - printf("[find_call] 0x%lx: bsr", (bfd_vma) pc - delta)); - /* - * Regular PC relative addressing. Check that this is the - * address of a function. The linker sometimes redirects - * the entry point by 8 bytes to skip loading the global - * pointer, so we all for either address: - */ - dest_pc = ((bfd_vma) (pc + 1 + pc->b.disp)) - delta; - if (dest_pc >= s_lowpc && dest_pc <= s_highpc) { - child = sym_lookup(&symtab, dest_pc); - DBG(CALLDEBUG, - printf(" 0x%lx\t; name=%s, addr=0x%lx", + case OP_BSR: + DBG (CALLDEBUG, + printf ("[find_call] 0x%lx: bsr", (bfd_vma) pc - delta)); + /* + * Regular PC relative addressing. Check that this is the + * address of a function. The linker sometimes redirects + * the entry point by 8 bytes to skip loading the global + * pointer, so we all for either address: + */ + dest_pc = ((bfd_vma) (pc + 1 + pc->b.disp)) - delta; + if (dest_pc >= s_lowpc && dest_pc <= s_highpc) + { + child = sym_lookup (&symtab, dest_pc); + DBG (CALLDEBUG, + printf (" 0x%lx\t; name=%s, addr=0x%lx", dest_pc, child->name, child->addr)); - if (child->addr == dest_pc || child->addr == dest_pc - 8) { - DBG(CALLDEBUG, printf("\n")); - /* a hit: */ - arc_add(parent, child, 0); - continue; - } /* if */ - } /* if */ - /* - * Something funny going on. - */ - DBG(CALLDEBUG, printf("\tbut it's a botch\n")); - break; + if (child->addr == dest_pc || child->addr == dest_pc - 8) + { + DBG (CALLDEBUG, printf ("\n")); + /* a hit: */ + arc_add (parent, child, 0); + continue; + } /* if */ + } /* if */ + /* + * Something funny going on. + */ + DBG (CALLDEBUG, printf ("\tbut it's a botch\n")); + break; - default: - break; - } /* switch */ - } /* for */ -} /* find_call */ - /*** end of alpha.c ***/ + default: + break; + } /* switch */ + } /* for */ +} /* find_call */ +/*** end of alpha.c ***/ diff --git a/gprof/alpha.h b/gprof/alpha.h index d66f359..9eb92bc 100644 --- a/gprof/alpha.h +++ b/gprof/alpha.h @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#)alpha.h 1.4 (Berkeley) 6/1/90 + * @(#)alpha.h 1.4 (Berkeley) 6/1/90 */ #ifndef alpha_h #define alpha_h diff --git a/gprof/basic_blocks.c b/gprof/basic_blocks.c index 7d69db6..3c21083 100644 --- a/gprof/basic_blocks.c +++ b/gprof/basic_blocks.c @@ -35,31 +35,39 @@ static long num_lines_executed; * number, and basic-block address (in that order). */ static int -DEFUN(cmp_bb, (lp, rp), const void *lp AND const void *rp) +DEFUN (cmp_bb, (lp, rp), const void *lp AND const void *rp) { - int r; - const Sym *left = *(const Sym**)lp; - const Sym *right = *(const Sym**)rp; - - if (left->file && right->file) { - r = strcmp(left->file->name, right->file->name); - if (r) { - return r; - } /* if */ - - if (left->line_num != right->line_num) { - return left->line_num - right->line_num; - } /* if */ - } /* if */ - - if (left->addr < right->addr) { - return -1; - } else if (left->addr > right->addr) { - return 1; - } else { - return 0; - } /* if */ -} /* cmp_bb */ + int r; + const Sym *left = *(const Sym **) lp; + const Sym *right = *(const Sym **) rp; + + if (left->file && right->file) + { + r = strcmp (left->file->name, right->file->name); + if (r) + { + return r; + } /* if */ + + if (left->line_num != right->line_num) + { + return left->line_num - right->line_num; + } /* if */ + } /* if */ + + if (left->addr < right->addr) + { + return -1; + } + else if (left->addr > right->addr) + { + return 1; + } + else + { + return 0; + } /* if */ +} /* cmp_bb */ /* @@ -67,39 +75,45 @@ DEFUN(cmp_bb, (lp, rp), const void *lp AND const void *rp) * calls, ties are broken in increasing order of line numbers. */ static int -DEFUN(cmp_ncalls, (lp, rp), const void *lp AND const void *rp) +DEFUN (cmp_ncalls, (lp, rp), const void *lp AND const void *rp) { - const Sym *left = *(const Sym**)lp; - const Sym *right = *(const Sym**)rp; + const Sym *left = *(const Sym **) lp; + const Sym *right = *(const Sym **) rp; - if (!left) { - return 1; - } else if (!right) { - return -1; - } /* if */ + if (!left) + { + return 1; + } + else if (!right) + { + return -1; + } /* if */ - if (right->ncalls != left->ncalls) { - return right->ncalls - left->ncalls; - } /* if */ + if (right->ncalls != left->ncalls) + { + return right->ncalls - left->ncalls; + } /* if */ - return left->line_num - right->line_num; -} /* cmp_ncalls */ + return left->line_num - right->line_num; +} /* cmp_ncalls */ /* * Skip over variable length string. */ static void -DEFUN(fskip_string, (fp), FILE *fp) +DEFUN (fskip_string, (fp), FILE * fp) { - int ch; + int ch; - while ((ch = fgetc(fp)) != EOF) { - if (ch == '\0') { - break; - } /* if */ - } /* if */ -} /* fskip_string */ + while ((ch = fgetc (fp)) != EOF) + { + if (ch == '\0') + { + break; + } /* if */ + } /* if */ +} /* fskip_string */ /* @@ -107,77 +121,87 @@ DEFUN(fskip_string, (fp), FILE *fp) * of file IFP and is provided for formatting error-messages only. */ void -DEFUN(bb_read_rec, (ifp, filename), FILE *ifp AND const char *filename) +DEFUN (bb_read_rec, (ifp, filename), FILE * ifp AND const char *filename) { - int nblocks, b; - bfd_vma addr; - long ncalls; - Sym *sym; - - if (fread(&nblocks, sizeof(nblocks), 1, ifp) != 1) { - fprintf(stderr, "%s: %s: unexpected end of file\n", whoami, filename); - done(1); - } /* if */ - - nblocks = bfd_get_32(core_bfd, (bfd_byte*) &nblocks); - if (gmon_file_version == 0) { - fskip_string(ifp); - } /* if */ - - 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. - */ - if ((fread(&ncalls, sizeof(ncalls), 1, ifp) != 1) - || (fread(&addr, sizeof(addr), 1, ifp) != 1) - || (fskip_string(ifp), FALSE) - || (fskip_string(ifp), FALSE) - || (fread(&line_num, sizeof(line_num), 1, ifp) != 1)) + int nblocks, b; + bfd_vma addr; + long ncalls; + Sym *sym; + + if (fread (&nblocks, sizeof (nblocks), 1, ifp) != 1) + { + fprintf (stderr, "%s: %s: unexpected end of file\n", whoami, filename); + done (1); + } /* if */ + + nblocks = bfd_get_32 (core_bfd, (bfd_byte *) & nblocks); + if (gmon_file_version == 0) + { + fskip_string (ifp); + } /* if */ + + 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. + */ + if ((fread (&ncalls, sizeof (ncalls), 1, ifp) != 1) + || (fread (&addr, sizeof (addr), 1, ifp) != 1) + || (fskip_string (ifp), FALSE) + || (fskip_string (ifp), FALSE) + || (fread (&line_num, sizeof (line_num), 1, ifp) != 1)) { - perror(filename); - done(1); - } /* if */ - } else { - if (fread(&addr, sizeof(addr), 1, ifp) != 1 - || fread(&ncalls, sizeof(ncalls), 1, ifp) != 1) + perror (filename); + done (1); + } /* if */ + } + else + { + if (fread (&addr, sizeof (addr), 1, ifp) != 1 + || fread (&ncalls, sizeof (ncalls), 1, ifp) != 1) { - perror(filename); - done(1); - } /* if */ - } /* if */ - - /* - * Basic-block execution counts are meaningful only if we're - * profiling at the line-by-line level: - */ - if (line_granularity) { + perror (filename); + done (1); + } /* if */ + } /* if */ + + /* + * 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); + addr = get_vma (core_bfd, (bfd_byte *) & addr); - sym = sym_lookup(&symtab, addr); - sym->is_bb_head = TRUE; - sym->ncalls += bfd_get_32(core_bfd, (bfd_byte*)&ncalls); + sym = sym_lookup (&symtab, addr); + sym->is_bb_head = TRUE; + sym->ncalls += bfd_get_32 (core_bfd, (bfd_byte *) & ncalls); - DBG(BBDEBUG, printf("[bb_read_rec] 0x%lx->0x%lx (%s) cnt=%d\n", + DBG (BBDEBUG, printf ("[bb_read_rec] 0x%lx->0x%lx (%s) cnt=%d\n", addr, sym->addr, sym->name, sym->ncalls)); - } else { - static bool user_warned = FALSE; + } + else + { + static bool user_warned = FALSE; - if (!user_warned) { - user_warned = TRUE; - fprintf(stderr, -"%s: warning: ignoring basic-block exec counts (use -l or --line)\n", - whoami); - } /* if */ - } /* if */ - } /* for */ - return; -} /* bb_read_rec */ + if (!user_warned) + { + user_warned = TRUE; + fprintf (stderr, + "%s: warning: ignoring basic-block exec counts (use -l or --line)\n", + whoami); + } /* if */ + } /* if */ + } /* for */ + return; +} /* bb_read_rec */ /* @@ -186,99 +210,108 @@ DEFUN(bb_read_rec, (ifp, filename), FILE *ifp AND const char *filename) * only. */ void -DEFUN(bb_write_blocks, (ofp, filename), FILE *ofp AND const char *filename) +DEFUN (bb_write_blocks, (ofp, filename), FILE * ofp AND const char *filename) { - const unsigned char tag = GMON_TAG_BB_COUNT; - int nblocks = 0; - bfd_vma addr; - long ncalls; - Sym *sym; - - /* count how many non-zero blocks with have: */ - - for (sym = symtab.base; sym < symtab.limit; ++sym) { - if (sym->ncalls > 0) { - ++nblocks; - } /* if */ - } /* for */ - - /* 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) + const unsigned char tag = GMON_TAG_BB_COUNT; + int nblocks = 0; + bfd_vma addr; + long ncalls; + Sym *sym; + + /* count how many non-zero blocks with have: */ + + for (sym = symtab.base; sym < symtab.limit; ++sym) { - perror(filename); - done(1); - } /* if */ + if (sym->ncalls > 0) + { + ++nblocks; + } /* if */ + } /* for */ + + /* 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) + { + perror (filename); + done (1); + } /* if */ - /* write counts: */ - for (sym = symtab.base; sym < symtab.limit; ++sym) { - if (sym->ncalls == 0) { - continue; - } /* if */ + /* write counts: */ + for (sym = symtab.base; sym < symtab.limit; ++sym) + { + if (sym->ncalls == 0) + { + continue; + } /* if */ - put_vma(core_bfd, sym->addr, (bfd_byte*) &addr); - bfd_put_32(core_bfd, sym->ncalls, (bfd_byte*) &ncalls); + put_vma (core_bfd, sym->addr, (bfd_byte *) & addr); + bfd_put_32 (core_bfd, sym->ncalls, (bfd_byte *) & ncalls); - if (fwrite(&addr, sizeof(addr), 1, ofp) != 1 - || fwrite(&ncalls, sizeof(ncalls), 1, ofp) != 1) + if (fwrite (&addr, sizeof (addr), 1, ofp) != 1 + || fwrite (&ncalls, sizeof (ncalls), 1, ofp) != 1) { - perror(filename); - done(1); - } /* if */ - } /* for */ -} /* bb_write_blocks */ + perror (filename); + done (1); + } /* if */ + } /* for */ +} /* bb_write_blocks */ /* * Output basic-block statistics in a format that is easily parseable. * Current the format is: * - * :: (: + * :: (: */ void -DEFUN_VOID(print_exec_counts) +DEFUN_VOID (print_exec_counts) { - Sym **sorted_bbs, *sym; - int i, len; - - if (first_output) { - first_output = FALSE; - } else { - printf("\f\n"); - } /* if */ - - /* 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 the start of a basic-block and it is - * called at least bb_min_calls times and 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->is_bb_head && sym->ncalls >= bb_min_calls - && (sym_lookup(&syms[INCL_EXEC], sym->addr) - || (syms[INCL_EXEC].len == 0 - && !sym_lookup(&syms[EXCL_EXEC], sym->addr)))) + Sym **sorted_bbs, *sym; + int i, len; + + if (first_output) + { + first_output = FALSE; + } + else + { + printf ("\f\n"); + } /* if */ + + /* 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 the start of a basic-block and it is + * called at least bb_min_calls times and 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->is_bb_head && sym->ncalls >= bb_min_calls + && (sym_lookup (&syms[INCL_EXEC], sym->addr) + || (syms[INCL_EXEC].len == 0 + && !sym_lookup (&syms[EXCL_EXEC], sym->addr)))) { - sorted_bbs[len++] = sym; - } /* if */ - } /* for */ - qsort(sorted_bbs, len, sizeof(sorted_bbs[0]), cmp_bb); + sorted_bbs[len++] = sym; + } /* if */ + } /* for */ + qsort (sorted_bbs, len, sizeof (sorted_bbs[0]), cmp_bb); - /* output basic-blocks: */ + /* output basic-blocks: */ - for (i = 0; i < len; ++i) { - sym = sorted_bbs[i]; - printf("%s:%d: (%s:0x%lx) %d executions\n", - sym->file ? sym->file->name : "", sym->line_num, - sym->name, sym->addr, sym->ncalls); - } /* for */ - free(sorted_bbs); -} /* print_exec_counts */ + for (i = 0; i < len; ++i) + { + sym = sorted_bbs[i]; + printf ("%s:%d: (%s:0x%lx) %d executions\n", + sym->file ? sym->file->name : "", sym->line_num, + sym->name, sym->addr, sym->ncalls); + } /* for */ + free (sorted_bbs); +} /* print_exec_counts */ /* @@ -286,44 +319,56 @@ DEFUN_VOID(print_exec_counts) * number of line executions. */ static void -DEFUN(annotate_with_count, (buf, width, line_num, arg), - char *buf AND int width AND int line_num AND void *arg) +DEFUN (annotate_with_count, (buf, width, line_num, arg), + char *buf AND int width AND int line_num AND void *arg) { - Source_File *sf = arg; - Sym *b; - long cnt; - static long last_count; - - if (line_num == 1) { - last_count = -1; - } /* if */ - - b = 0; - if (line_num <= sf->num_lines) { - b = sf->line[line_num - 1]; - } /* if */ - if (!b) { - cnt = -1; - } else { - ++num_executable_lines; - cnt = b->ncalls; - } /* if */ - if (cnt > 0) { - ++num_lines_executed; - } /* if */ - if (cnt < 0 && bb_annotate_all_lines) { - cnt = last_count; - } /* if */ - - if (cnt < 0) { - strcpy(buf, "\t\t"); - } else if (cnt < bb_min_calls) { - strcpy(buf, " ##### -> "); - } else { - sprintf(buf, "%12ld -> ", cnt); - } /* if */ - last_count = cnt; -} /* annotate_with_count */ + Source_File *sf = arg; + Sym *b; + long cnt; + static long last_count; + + if (line_num == 1) + { + last_count = -1; + } /* if */ + + b = 0; + if (line_num <= sf->num_lines) + { + b = sf->line[line_num - 1]; + } /* if */ + if (!b) + { + cnt = -1; + } + else + { + ++num_executable_lines; + cnt = b->ncalls; + } /* if */ + if (cnt > 0) + { + ++num_lines_executed; + } /* if */ + if (cnt < 0 && bb_annotate_all_lines) + { + cnt = last_count; + } /* if */ + + if (cnt < 0) + { + strcpy (buf, "\t\t"); + } + else if (cnt < bb_min_calls) + { + strcpy (buf, " ##### -> "); + } + else + { + sprintf (buf, "%12ld -> ", cnt); + } /* if */ + last_count = cnt; +} /* annotate_with_count */ /* @@ -332,121 +377,138 @@ DEFUN(annotate_with_count, (buf, width, line_num, arg), * regarding that source file are printed. */ void -DEFUN_VOID(print_annotated_source) +DEFUN_VOID (print_annotated_source) { - Sym *sym, *line_stats, *new_line; - Source_File *sf; - int i, table_len; - FILE *ofp; - - /* - * 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. - */ - if (sym->file && sym->line_num > sym->file->num_lines - && (sym_lookup(&syms[INCL_ANNO], sym->addr) - || (syms[INCL_ANNO].len == 0 - && !sym_lookup(&syms[EXCL_ANNO], sym->addr)))) + Sym *sym, *line_stats, *new_line; + Source_File *sf; + int i, table_len; + FILE *ofp; + + /* + * 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. + */ + if (sym->file && sym->line_num > sym->file->num_lines + && (sym_lookup (&syms[INCL_ANNO], sym->addr) + || (syms[INCL_ANNO].len == 0 + && !sym_lookup (&syms[EXCL_ANNO], sym->addr)))) + { + sym->file->num_lines = sym->line_num; + } /* if */ + } /* for */ + + /* allocate line descriptors: */ + + for (sf = first_src_file; sf; sf = sf->next) + { + if (sf->num_lines > 0) + { + sf->line = (void *) xmalloc (sf->num_lines * sizeof (sf->line[0])); + memset (sf->line, 0, sf->num_lines * sizeof (sf->line[0])); + } /* if */ + } /* for */ + + /* count executions per line: */ + + for (sym = symtab.base; sym < symtab.limit; ++sym) + { + if (sym->is_bb_head && sym->file && sym->file->num_lines + && (sym_lookup (&syms[INCL_ANNO], sym->addr) + || (syms[INCL_ANNO].len == 0 + && !sym_lookup (&syms[EXCL_ANNO], sym->addr)))) + { + 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: */ + sym->file->line[sym->line_num - 1] = sym; + } + else if (!line_stats->addr) + { + /* 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 */ + new_line = (Sym *) xmalloc (sizeof (*new_line)); + *new_line = *line_stats; + new_line->addr = 0; + new_line->ncalls += sym->ncalls; + sym->file->line[sym->line_num - 1] = new_line; + } /* if */ + } /* if */ + } /* for */ + + /* plod over source files, annotating them: */ + + for (sf = first_src_file; sf; sf = sf->next) + { + if (!sf->num_lines || (ignore_zeros && sf->ncalls == 0)) { - sym->file->num_lines = sym->line_num; - } /* if */ - } /* for */ - - /* allocate line descriptors: */ - - for (sf = first_src_file; sf; sf = sf->next) { - if (sf->num_lines > 0) { - sf->line = (void*) xmalloc(sf->num_lines * sizeof(sf->line[0])); - memset(sf->line, 0, sf->num_lines * sizeof(sf->line[0])); - } /* if */ - } /* for */ - - /* count executions per line: */ - - for (sym = symtab.base; sym < symtab.limit; ++sym) { - if (sym->is_bb_head && sym->file && sym->file->num_lines - && (sym_lookup(&syms[INCL_ANNO], sym->addr) - || (syms[INCL_ANNO].len == 0 - && !sym_lookup(&syms[EXCL_ANNO], sym->addr)))) + continue; + } /* if */ + + num_executable_lines = num_lines_executed = 0; + ofp = annotate_source (sf, 16, annotate_with_count, sf); + if (!ofp) { - 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: */ - sym->file->line[sym->line_num - 1] = sym; - } else if (!line_stats->addr) { - /* 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 */ - new_line = (Sym*) xmalloc(sizeof(*new_line)); - *new_line = *line_stats; - new_line->addr = 0; - new_line->ncalls += sym->ncalls; - sym->file->line[sym->line_num - 1] = new_line; - } /* if */ - } /* if */ - } /* for */ - - /* 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; - } /* if */ - - num_executable_lines = num_lines_executed = 0; - ofp = annotate_source(sf, 16, annotate_with_count, sf); - if (!ofp) { - continue; - } /* if */ - - 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: */ - 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; - } /* if */ - for (i = 0; i < table_len; ++i) { - sym = sf->line[i]; - if (!sym || sym->ncalls <= 0) { - break; - } /* if */ - fprintf(ofp, "%9d %10d\n", sym->line_num, sym->ncalls); - } /* for */ - } /* if */ - - free(sf->line); - sf->line = 0; - - fprintf(ofp, "\nExecution Summary:\n\n"); - fprintf(ofp, "%9ld Executable lines in this file\n", - num_executable_lines); - fprintf(ofp, "%9ld Lines executed\n", num_lines_executed); - fprintf(ofp, "%9.2f Percent of the file executed\n", - num_executable_lines - ? 100.0 * num_lines_executed / (double) num_executable_lines - : 100.0); - fprintf(ofp, "\n%9d Total number of line executions\n", sf->ncalls); - fprintf(ofp, "%9.2f Average executions per line\n", - num_executable_lines - ? sf->ncalls / (double) num_executable_lines - : 0.0); - if (ofp != stdout) { - fclose(ofp); - } /* if */ - } /* for */ -} /* print_annotated_source */ - - /*** end of basic_block.c ***/ + continue; + } /* if */ + + 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: */ + 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; + } /* if */ + for (i = 0; i < table_len; ++i) + { + sym = sf->line[i]; + if (!sym || sym->ncalls <= 0) + { + break; + } /* if */ + fprintf (ofp, "%9d %10d\n", sym->line_num, sym->ncalls); + } /* for */ + } /* if */ + + free (sf->line); + sf->line = 0; + + fprintf (ofp, "\nExecution Summary:\n\n"); + fprintf (ofp, "%9ld Executable lines in this file\n", + num_executable_lines); + fprintf (ofp, "%9ld Lines executed\n", num_lines_executed); + fprintf (ofp, "%9.2f Percent of the file executed\n", + num_executable_lines + ? 100.0 * num_lines_executed / (double) num_executable_lines + : 100.0); + fprintf (ofp, "\n%9d Total number of line executions\n", sf->ncalls); + fprintf (ofp, "%9.2f Average executions per line\n", + num_executable_lines + ? sf->ncalls / (double) num_executable_lines + : 0.0); + if (ofp != stdout) + { + fclose (ofp); + } /* if */ + } /* for */ +} /* print_annotated_source */ + +/*** end of basic_block.c ***/ diff --git a/gprof/basic_blocks.h b/gprof/basic_blocks.h index 0e7070c..daba408 100644 --- a/gprof/basic_blocks.h +++ b/gprof/basic_blocks.h @@ -10,14 +10,14 @@ * Options: */ extern bool bb_annotate_all_lines; /* force annotation of all lines? */ -extern int bb_table_length; /* length of most-used bb table */ -extern int bb_min_calls; /* minimum execution count */ +extern int bb_table_length; /* length of most-used bb table */ +extern int 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 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)); +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 bba8b8c..bd2a471 100644 --- a/gprof/call_graph.c +++ b/gprof/call_graph.c @@ -7,30 +7,30 @@ #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) +DEFUN (cg_tally, (from_pc, self_pc, count), + bfd_vma from_pc AND bfd_vma self_pc AND int count) { - Sym *parent; - Sym *child; + Sym *parent; + Sym *child; - parent = sym_lookup(&symtab, from_pc); - child = sym_lookup(&symtab, self_pc); + 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))) + /* + * 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", + 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 */ + arc_add (parent, child, count); + } /* if */ +} /* cg_tally */ /* @@ -40,26 +40,27 @@ DEFUN(cg_tally, (from_pc, self_pc, count), * for formatting error-messages only. */ void -DEFUN(cg_read_rec, (ifp, filename), FILE *ifp AND CONST char *filename) +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; + 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", + 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 */ + /* add this arc: */ + cg_tally (from_pc, self_pc, count); +} /* cg_read_rec */ /* @@ -68,29 +69,31 @@ DEFUN(cg_read_rec, (ifp, filename), FILE *ifp AND CONST char *filename) * only. */ void -DEFUN(cg_write_arcs, (ofp, filename), FILE *ofp AND const char *filename) +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; + 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) + 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 */ + 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 ***/ +/*** end of call_graph.c ***/ diff --git a/gprof/call_graph.h b/gprof/call_graph.h index d3d77da..6e9413a 100644 --- a/gprof/call_graph.h +++ b/gprof/call_graph.h @@ -5,8 +5,8 @@ #include "gprof.h" #include "symtab.h" -extern void cg_tally PARAMS((bfd_vma from_pc, bfd_vma self_pc, int 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 from_pc, bfd_vma self_pc, int count)); +extern void cg_read_rec PARAMS ((FILE * ifp, const char *filename)); +extern void cg_write_arcs PARAMS ((FILE * ofp, const char *filename)); #endif /* call_graph_h */ diff --git a/gprof/cg_arcs.c b/gprof/cg_arcs.c index 85ab9a7..5c2c806 100644 --- a/gprof/cg_arcs.c +++ b/gprof/cg_arcs.c @@ -32,143 +32,157 @@ int num_cycles; * Return TRUE iff PARENT has an arc to covers the address * range covered by CHILD. */ -Arc* -DEFUN(arc_lookup, (parent, child), Sym *parent AND Sym *child) +Arc * +DEFUN (arc_lookup, (parent, child), Sym * parent AND Sym * child) { - Arc *arc; - - if (!parent || !child) { - printf("[arc_lookup] parent == 0 || child == 0\n"); - return 0; - } /* if */ - DBG(LOOKUPDEBUG, printf("[arc_lookup] parent %s child %s\n", + Arc *arc; + + if (!parent || !child) + { + printf ("[arc_lookup] parent == 0 || child == 0\n"); + return 0; + } /* if */ + DBG (LOOKUPDEBUG, printf ("[arc_lookup] parent %s child %s\n", parent->name, child->name)); - for (arc = parent->cg.children; arc; arc = arc->next_child) { - DBG(LOOKUPDEBUG, printf("[arc_lookup]\t parent %s child %s\n", + for (arc = parent->cg.children; arc; arc = arc->next_child) + { + DBG (LOOKUPDEBUG, printf ("[arc_lookup]\t parent %s child %s\n", arc->parent->name, arc->child->name)); - if (child->addr >= arc->child->addr - && child->end_addr <= arc->child->end_addr) + if (child->addr >= arc->child->addr + && child->end_addr <= arc->child->end_addr) { - return arc; - } /* if */ - } /* for */ - return 0; -} /* arc_lookup */ + return arc; + } /* if */ + } /* for */ + return 0; +} /* arc_lookup */ /* * Add (or just increment) an arc: */ void -DEFUN(arc_add, (parent, child, count), - Sym *parent AND Sym *child AND int count) +DEFUN (arc_add, (parent, child, count), + Sym * parent AND Sym * child AND int count) { - Arc *arc; + Arc *arc; - DBG(TALLYDEBUG, printf("[arc_add] %d arcs from %s to %s\n", + DBG (TALLYDEBUG, printf ("[arc_add] %d arcs from %s to %s\n", count, parent->name, child->name)); - arc = arc_lookup(parent, child); - if (arc) { - /* - * A hit: just increment the count. - */ - DBG(TALLYDEBUG, printf("[tally] hit %d += %d\n", + arc = arc_lookup (parent, child); + if (arc) + { + /* + * A hit: just increment the count. + */ + DBG (TALLYDEBUG, printf ("[tally] hit %d += %d\n", arc->count, count)); - arc->count += count; - return; - } /* if */ - arc = (Arc*)xmalloc(sizeof(*arc)); - arc->parent = parent; - arc->child = child; - arc->count = count; + arc->count += count; + return; + } /* if */ + arc = (Arc *) xmalloc (sizeof (*arc)); + arc->parent = parent; + arc->child = child; + arc->count = count; - /* prepend this child to the children of this parent: */ - arc->next_child = parent->cg.children; - parent->cg.children = arc; + /* prepend this child to the children of this parent: */ + arc->next_child = parent->cg.children; + parent->cg.children = arc; - /* prepend this parent to the parents of this child: */ - arc->next_parent = child->cg.parents; - child->cg.parents = arc; -} /* arc_add */ + /* prepend this parent to the parents of this child: */ + arc->next_parent = child->cg.parents; + child->cg.parents = arc; +} /* arc_add */ static int -DEFUN(cmp_topo, (lp, rp), const PTR lp AND const PTR rp) +DEFUN (cmp_topo, (lp, rp), const PTR lp AND const PTR rp) { - const Sym *left = *(const Sym **) lp; - const Sym *right = *(const Sym **) rp; + const Sym *left = *(const Sym **) lp; + const Sym *right = *(const Sym **) rp; - return left->cg.top_order - right->cg.top_order; -} /* cmp_topo */ + return left->cg.top_order - right->cg.top_order; +} /* cmp_topo */ static void -DEFUN(propagate_time, (parent), Sym *parent) +DEFUN (propagate_time, (parent), Sym * parent) { - Arc *arc; - Sym *child; - double share, prop_share; - - if (parent->cg.prop.fract == 0.0) { - return; - } /* if */ - - /* gather time from children of this parent: */ - - for (arc = parent->cg.children; arc; arc = arc->next_child) { - child = arc->child; - if (arc->count == 0 || child == parent || child->cg.prop.fract == 0) { - continue; - } /* if */ - if (child->cg.cyc.head != child) { - if (parent->cg.cyc.num == child->cg.cyc.num) { - continue; - } /* if */ - if (parent->cg.top_order <= child->cg.top_order) { - fprintf(stderr, "[propagate] toporder botches\n"); - } /* if */ - child = child->cg.cyc.head; - } else { - if (parent->cg.top_order <= child->cg.top_order) { - fprintf(stderr, "[propagate] toporder botches\n"); - continue; - } /* if */ - } /* if */ - if (child->ncalls == 0) { - continue; - } /* if */ - - /* distribute time for this arc: */ - arc->time = child->hist.time * (((double) arc->count) - / ((double) child->ncalls)); - arc->child_time = child->cg.child_time - * (((double) arc->count) / ((double) child->ncalls)); - share = arc->time + arc->child_time; - parent->cg.child_time += share; - - /* (1 - cg.prop.fract) gets lost along the way: */ - prop_share = parent->cg.prop.fract * share; - - /* fix things for printing: */ - parent->cg.prop.child += prop_share; - arc->time *= parent->cg.prop.fract; - arc->child_time *= parent->cg.prop.fract; - - /* add this share to the parent's cycle header, if any: */ - if (parent->cg.cyc.head != parent) { - parent->cg.cyc.head->cg.child_time += share; - parent->cg.cyc.head->cg.prop.child += prop_share; - } /* if */ - DBG(PROPDEBUG, - printf("[prop_time] child \t"); - print_name(child); - printf(" with %f %f %d/%d\n", child->hist.time, + Arc *arc; + Sym *child; + double share, prop_share; + + if (parent->cg.prop.fract == 0.0) + { + return; + } /* if */ + + /* gather time from children of this parent: */ + + for (arc = parent->cg.children; arc; arc = arc->next_child) + { + child = arc->child; + if (arc->count == 0 || child == parent || child->cg.prop.fract == 0) + { + continue; + } /* if */ + if (child->cg.cyc.head != child) + { + if (parent->cg.cyc.num == child->cg.cyc.num) + { + continue; + } /* if */ + if (parent->cg.top_order <= child->cg.top_order) + { + fprintf (stderr, "[propagate] toporder botches\n"); + } /* if */ + child = child->cg.cyc.head; + } + else + { + if (parent->cg.top_order <= child->cg.top_order) + { + fprintf (stderr, "[propagate] toporder botches\n"); + continue; + } /* if */ + } /* if */ + if (child->ncalls == 0) + { + continue; + } /* if */ + + /* distribute time for this arc: */ + arc->time = child->hist.time * (((double) arc->count) + / ((double) child->ncalls)); + arc->child_time = child->cg.child_time + * (((double) arc->count) / ((double) child->ncalls)); + share = arc->time + arc->child_time; + parent->cg.child_time += share; + + /* (1 - cg.prop.fract) gets lost along the way: */ + prop_share = parent->cg.prop.fract * share; + + /* fix things for printing: */ + parent->cg.prop.child += prop_share; + arc->time *= parent->cg.prop.fract; + arc->child_time *= parent->cg.prop.fract; + + /* add this share to the parent's cycle header, if any: */ + if (parent->cg.cyc.head != parent) + { + parent->cg.cyc.head->cg.child_time += share; + parent->cg.cyc.head->cg.prop.child += prop_share; + } /* if */ + DBG (PROPDEBUG, + printf ("[prop_time] child \t"); + print_name (child); + printf (" with %f %f %d/%d\n", child->hist.time, child->cg.child_time, arc->count, child->ncalls); - printf("[prop_time] parent\t"); - print_name(parent); - printf("\n[prop_time] share %f\n", share)); - } /* for */ -} /* propagate_time */ + printf ("[prop_time] parent\t"); + print_name (parent); + printf ("\n[prop_time] share %f\n", share)); + } /* for */ +} /* propagate_time */ /* @@ -176,92 +190,109 @@ DEFUN(propagate_time, (parent), Sym *parent) * its members. */ static void -DEFUN_VOID(cycle_time) +DEFUN_VOID (cycle_time) { - Sym *member, *cyc; - - for (cyc = &cycle_header[1]; cyc <= &cycle_header[num_cycles]; ++cyc) { - for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next) { - if (member->cg.prop.fract == 0.0) { - /* - * All members have the same propfraction except those - * that were excluded with -E. - */ - continue; - } /* if */ - cyc->hist.time += member->hist.time; - } /* for */ - cyc->cg.prop.self = cyc->cg.prop.fract * cyc->hist.time; - } /* for */ -} /* cycle_time */ + Sym *member, *cyc; + + for (cyc = &cycle_header[1]; cyc <= &cycle_header[num_cycles]; ++cyc) + { + for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next) + { + if (member->cg.prop.fract == 0.0) + { + /* + * All members have the same propfraction except those + * that were excluded with -E. + */ + continue; + } /* if */ + cyc->hist.time += member->hist.time; + } /* for */ + cyc->cg.prop.self = cyc->cg.prop.fract * cyc->hist.time; + } /* for */ +} /* cycle_time */ static void -DEFUN_VOID(cycle_link) +DEFUN_VOID (cycle_link) { - Sym *sym, *cyc, *member; - Arc *arc; - int num; - - /* count the number of cycles, and initialize the cycle lists: */ - - num_cycles = 0; - for (sym = symtab.base; sym < symtab.limit; ++sym) { - /* this is how you find unattached cycles: */ - if (sym->cg.cyc.head == sym && sym->cg.cyc.next) { - ++num_cycles; - } /* if */ - } /* for */ - - /* - * cycle_header is indexed by cycle number: i.e. it is origin 1, - * not origin 0. - */ - cycle_header = (Sym*)xmalloc((num_cycles + 1) * sizeof(Sym)); - - /* - * Now link cycles to true cycle-heads, number them, accumulate - * the data for the cycle. - */ - num = 0; cyc = cycle_header; - for (sym = symtab.base; sym < symtab.limit; ++sym) { - if (!(sym->cg.cyc.head == sym && sym->cg.cyc.next != 0)) { - continue; - } /* if */ - ++num; ++cyc; - sym_init(cyc); - cyc->cg.print_flag = TRUE; /* should this be printed? */ - cyc->cg.top_order = DFN_NAN; /* graph call chain top-sort order */ - cyc->cg.cyc.num = num; /* internal number of cycle on */ - cyc->cg.cyc.head = cyc; /* pointer to head of cycle */ - cyc->cg.cyc.next = sym; /* pointer to next member of cycle */ - DBG(CYCLEDEBUG, printf("[cycle_link] "); print_name(sym); - printf(" is the head of cycle %d\n", num)); - - /* link members to cycle header: */ - for (member = sym; member; member = member->cg.cyc.next) { - member->cg.cyc.num = num; - member->cg.cyc.head = cyc; - } /* for */ - - /* - * Count calls from outside the cycle and those among cycle - * members: - */ - for (member = sym; member; member = member->cg.cyc.next) { - for (arc = member->cg.parents; arc; arc = arc->next_parent) { - if (arc->parent == member) { - continue; - } /* if */ - if (arc->parent->cg.cyc.num == num) { - cyc->cg.self_calls += arc->count; - } else { - cyc->ncalls += arc->count; - } /* if */ - } /* for */ - } /* for */ - } /* for */ -} /* cycle_link */ + Sym *sym, *cyc, *member; + Arc *arc; + int num; + + /* count the number of cycles, and initialize the cycle lists: */ + + num_cycles = 0; + for (sym = symtab.base; sym < symtab.limit; ++sym) + { + /* this is how you find unattached cycles: */ + if (sym->cg.cyc.head == sym && sym->cg.cyc.next) + { + ++num_cycles; + } /* if */ + } /* for */ + + /* + * cycle_header is indexed by cycle number: i.e. it is origin 1, + * not origin 0. + */ + cycle_header = (Sym *) xmalloc ((num_cycles + 1) * sizeof (Sym)); + + /* + * Now link cycles to true cycle-heads, number them, accumulate + * the data for the cycle. + */ + num = 0; + cyc = cycle_header; + for (sym = symtab.base; sym < symtab.limit; ++sym) + { + if (!(sym->cg.cyc.head == sym && sym->cg.cyc.next != 0)) + { + continue; + } /* if */ + ++num; + ++cyc; + sym_init (cyc); + cyc->cg.print_flag = TRUE; /* should this be printed? */ + cyc->cg.top_order = DFN_NAN; /* graph call chain top-sort order */ + cyc->cg.cyc.num = num; /* internal number of cycle on */ + cyc->cg.cyc.head = cyc; /* pointer to head of cycle */ + cyc->cg.cyc.next = sym; /* pointer to next member of cycle */ + DBG (CYCLEDEBUG, printf ("[cycle_link] "); + print_name (sym); + printf (" is the head of cycle %d\n", num)); + + /* link members to cycle header: */ + for (member = sym; member; member = member->cg.cyc.next) + { + member->cg.cyc.num = num; + member->cg.cyc.head = cyc; + } /* for */ + + /* + * Count calls from outside the cycle and those among cycle + * members: + */ + for (member = sym; member; member = member->cg.cyc.next) + { + for (arc = member->cg.parents; arc; arc = arc->next_parent) + { + if (arc->parent == member) + { + continue; + } /* if */ + if (arc->parent->cg.cyc.num == num) + { + cyc->cg.self_calls += arc->count; + } + else + { + cyc->ncalls += arc->count; + } /* if */ + } /* for */ + } /* for */ + } /* for */ +} /* cycle_link */ /* @@ -271,157 +302,175 @@ DEFUN_VOID(cycle_link) * fractions from parents. */ static void -DEFUN(inherit_flags, (child), Sym *child) +DEFUN (inherit_flags, (child), Sym * child) { - Sym *head, *parent, *member; - Arc *arc; - - head = child->cg.cyc.head; - if (child == head) { - /* just a regular child, check its parents: */ - child->cg.print_flag = FALSE; - child->cg.prop.fract = 0.0; - for (arc = child->cg.parents; arc; arc = arc->next_parent) { - parent = arc->parent; - if (child == parent) { - continue; - } /* if */ - child->cg.print_flag |= parent->cg.print_flag; - /* - * If the child was never actually called (e.g., this arc - * is static (and all others are, too)) no time propagates - * along this arc. - */ - if (child->ncalls) { - child->cg.prop.fract += parent->cg.prop.fract - * (((double) arc->count) / ((double) child->ncalls)); - } /* if */ - } /* for */ - } else { - /* - * Its a member of a cycle, look at all parents from outside - * the cycle. - */ - head->cg.print_flag = FALSE; - head->cg.prop.fract = 0.0; - for (member = head->cg.cyc.next; member; member = member->cg.cyc.next) + Sym *head, *parent, *member; + Arc *arc; + + head = child->cg.cyc.head; + if (child == head) + { + /* just a regular child, check its parents: */ + child->cg.print_flag = FALSE; + child->cg.prop.fract = 0.0; + for (arc = child->cg.parents; arc; arc = arc->next_parent) + { + parent = arc->parent; + if (child == parent) + { + continue; + } /* if */ + child->cg.print_flag |= parent->cg.print_flag; + /* + * If the child was never actually called (e.g., this arc + * is static (and all others are, too)) no time propagates + * along this arc. + */ + if (child->ncalls) + { + child->cg.prop.fract += parent->cg.prop.fract + * (((double) arc->count) / ((double) child->ncalls)); + } /* if */ + } /* for */ + } + else + { + /* + * Its a member of a cycle, look at all parents from outside + * the cycle. + */ + head->cg.print_flag = FALSE; + head->cg.prop.fract = 0.0; + for (member = head->cg.cyc.next; member; member = member->cg.cyc.next) + { + for (arc = member->cg.parents; arc; arc = arc->next_parent) + { + if (arc->parent->cg.cyc.head == head) + { + continue; + } /* if */ + parent = arc->parent; + head->cg.print_flag |= parent->cg.print_flag; + /* + * If the cycle was never actually called (e.g. this + * arc is static (and all others are, too)) no time + * propagates along this arc. + */ + if (head->ncalls) + { + head->cg.prop.fract += parent->cg.prop.fract + * (((double) arc->count) / ((double) head->ncalls)); + } /* if */ + } /* for */ + } /* for */ + for (member = head; member; member = member->cg.cyc.next) { - for (arc = member->cg.parents; arc; arc = arc->next_parent) { - if (arc->parent->cg.cyc.head == head) { - continue; - } /* if */ - parent = arc->parent; - head->cg.print_flag |= parent->cg.print_flag; - /* - * If the cycle was never actually called (e.g. this - * arc is static (and all others are, too)) no time - * propagates along this arc. - */ - if (head->ncalls) { - head->cg.prop.fract += parent->cg.prop.fract - * (((double) arc->count) / ((double) head->ncalls)); - } /* if */ - } /* for */ - } /* for */ - for (member = head; member; member = member->cg.cyc.next) { - member->cg.print_flag = head->cg.print_flag; - member->cg.prop.fract = head->cg.prop.fract; - } /* for */ - } /* if */ -} /* inherit_flags */ + member->cg.print_flag = head->cg.print_flag; + member->cg.prop.fract = head->cg.prop.fract; + } /* for */ + } /* if */ +} /* inherit_flags */ /* * In one top-to-bottom pass over the topologically sorted symbols * propagate: - * cg.print_flag as the union of parents' print_flags - * propfraction as the sum of fractional parents' propfractions + * cg.print_flag as the union of parents' print_flags + * propfraction as the sum of fractional parents' propfractions * and while we're here, sum time for functions. */ static void -DEFUN(propagate_flags, (symbols), Sym **symbols) +DEFUN (propagate_flags, (symbols), Sym ** symbols) { - int index; - Sym *old_head, *child; - - old_head = 0; - for (index = symtab.len - 1; index >= 0; --index) { - child = symbols[index]; - /* - * If we haven't done this function or cycle, inherit things - * from parent. This way, we are linear in the number of arcs - * since we do all members of a cycle (and the cycle itself) - * as we hit the first member of the cycle. - */ - if (child->cg.cyc.head != old_head) { - old_head = child->cg.cyc.head; - inherit_flags(child); - } /* if */ - DBG(PROPDEBUG, - printf("[prop_flags] "); - print_name(child); - printf("inherits print-flag %d and prop-fract %f\n", + int index; + Sym *old_head, *child; + + old_head = 0; + for (index = symtab.len - 1; index >= 0; --index) + { + child = symbols[index]; + /* + * If we haven't done this function or cycle, inherit things + * from parent. This way, we are linear in the number of arcs + * since we do all members of a cycle (and the cycle itself) + * as we hit the first member of the cycle. + */ + if (child->cg.cyc.head != old_head) + { + old_head = child->cg.cyc.head; + inherit_flags (child); + } /* if */ + DBG (PROPDEBUG, + printf ("[prop_flags] "); + print_name (child); + printf ("inherits print-flag %d and prop-fract %f\n", child->cg.print_flag, child->cg.prop.fract)); - if (!child->cg.print_flag) { - /* - * Printflag is off. It gets turned on by being in the - * INCL_GRAPH table, or there being an empty INCL_GRAPH - * table and not being in the EXCL_GRAPH table. - */ - if (sym_lookup(&syms[INCL_GRAPH], child->addr) - || (syms[INCL_GRAPH].len == 0 - && !sym_lookup(&syms[EXCL_GRAPH], child->addr))) + if (!child->cg.print_flag) + { + /* + * Printflag is off. It gets turned on by being in the + * INCL_GRAPH table, or there being an empty INCL_GRAPH + * table and not being in the EXCL_GRAPH table. + */ + if (sym_lookup (&syms[INCL_GRAPH], child->addr) + || (syms[INCL_GRAPH].len == 0 + && !sym_lookup (&syms[EXCL_GRAPH], child->addr))) { - child->cg.print_flag = TRUE; - } /* if */ - } else { - /* - * This function has printing parents: maybe someone wants - * to shut it up by putting it in the EXCL_GRAPH table. - * (But favor INCL_GRAPH over EXCL_GRAPH.) - */ - if (!sym_lookup(&syms[INCL_GRAPH], child->addr) - && sym_lookup(&syms[EXCL_GRAPH], child->addr)) + child->cg.print_flag = TRUE; + } /* if */ + } + else + { + /* + * This function has printing parents: maybe someone wants + * to shut it up by putting it in the EXCL_GRAPH table. + * (But favor INCL_GRAPH over EXCL_GRAPH.) + */ + if (!sym_lookup (&syms[INCL_GRAPH], child->addr) + && sym_lookup (&syms[EXCL_GRAPH], child->addr)) { - child->cg.print_flag = FALSE; - } /* if */ - } /* if */ - if (child->cg.prop.fract == 0.0) { - /* - * No parents to pass time to. Collect time from children - * if its in the INCL_TIME table, or there is an empty - * INCL_TIME table and its not in the EXCL_TIME table. - */ - if (sym_lookup(&syms[INCL_TIME], child->addr) - || (syms[INCL_TIME].len == 0 - && !sym_lookup(&syms[EXCL_TIME], child->addr))) + child->cg.print_flag = FALSE; + } /* if */ + } /* if */ + if (child->cg.prop.fract == 0.0) + { + /* + * No parents to pass time to. Collect time from children + * if its in the INCL_TIME table, or there is an empty + * INCL_TIME table and its not in the EXCL_TIME table. + */ + if (sym_lookup (&syms[INCL_TIME], child->addr) + || (syms[INCL_TIME].len == 0 + && !sym_lookup (&syms[EXCL_TIME], child->addr))) { - child->cg.prop.fract = 1.0; - } /* if */ - } else { - /* - * It has parents to pass time to, but maybe someone wants - * to shut it up by puttting it in the EXCL_TIME table. - * (But favor being in INCL_TIME tabe over being in - * EXCL_TIME table.) - */ - if (!sym_lookup(&syms[INCL_TIME], child->addr) - && sym_lookup(&syms[EXCL_TIME], child->addr)) + child->cg.prop.fract = 1.0; + } /* if */ + } + else + { + /* + * It has parents to pass time to, but maybe someone wants + * to shut it up by puttting it in the EXCL_TIME table. + * (But favor being in INCL_TIME tabe over being in + * EXCL_TIME table.) + */ + if (!sym_lookup (&syms[INCL_TIME], child->addr) + && sym_lookup (&syms[EXCL_TIME], child->addr)) { - child->cg.prop.fract = 0.0; - } /* if */ - } /* if */ - child->cg.prop.self = child->hist.time * child->cg.prop.fract; - print_time += child->cg.prop.self; - DBG(PROPDEBUG, - printf("[prop_flags] "); - print_name(child); - printf(" ends up with printflag %d and prop-fract %f\n", + child->cg.prop.fract = 0.0; + } /* if */ + } /* if */ + child->cg.prop.self = child->hist.time * child->cg.prop.fract; + print_time += child->cg.prop.self; + DBG (PROPDEBUG, + printf ("[prop_flags] "); + print_name (child); + printf (" ends up with printflag %d and prop-fract %f\n", child->cg.print_flag, child->cg.prop.fract); - printf("[prop_flags] time %f propself %f print_time %f\n", + printf ("[prop_flags] time %f propself %f print_time %f\n", child->hist.time, child->cg.prop.self, print_time)); - } /* if */ -} /* propagate_flags */ + } /* if */ +} /* propagate_flags */ /* @@ -431,150 +480,174 @@ DEFUN(propagate_flags, (symbols), Sym **symbols) * first. All else being equal, compare by names. */ static int -DEFUN(cmp_total, (lp, rp), const PTR lp AND const PTR rp) +DEFUN (cmp_total, (lp, rp), const PTR lp AND const PTR rp) { - const Sym *left = *(const Sym**)lp; - const Sym *right = *(const Sym**)rp; - double diff; - - diff = (left->cg.prop.self + left->cg.prop.child) - - (right->cg.prop.self + right->cg.prop.child); - if (diff < 0.0) { - return 1; - } /* if */ - if (diff > 0.0) { - return -1; - } /* if */ - if (!left->name && left->cg.cyc.num != 0) { - return -1; - } /* if */ - if (!right->name && right->cg.cyc.num != 0) { - return 1; - } /* if */ - if (!left->name) { - return -1; - } /* if */ - if (!right->name) { - return 1; - } /* if */ - if (left->name[0] != '_' && right->name[0] == '_') { - return -1; - } /* if */ - if (left->name[0] == '_' && right->name[0] != '_') { - return 1; - } /* if */ - if (left->ncalls > right->ncalls) { - return -1; - } /* if */ - if (left->ncalls < right->ncalls) { - return 1; - } /* if */ - return strcmp(left->name, right->name); -} /* cmp_total */ + const Sym *left = *(const Sym **) lp; + const Sym *right = *(const Sym **) rp; + double diff; + + diff = (left->cg.prop.self + left->cg.prop.child) + - (right->cg.prop.self + right->cg.prop.child); + if (diff < 0.0) + { + return 1; + } /* if */ + if (diff > 0.0) + { + return -1; + } /* if */ + if (!left->name && left->cg.cyc.num != 0) + { + return -1; + } /* if */ + if (!right->name && right->cg.cyc.num != 0) + { + return 1; + } /* if */ + if (!left->name) + { + return -1; + } /* if */ + if (!right->name) + { + return 1; + } /* if */ + if (left->name[0] != '_' && right->name[0] == '_') + { + return -1; + } /* if */ + if (left->name[0] == '_' && right->name[0] != '_') + { + return 1; + } /* if */ + if (left->ncalls > right->ncalls) + { + return -1; + } /* if */ + if (left->ncalls < right->ncalls) + { + return 1; + } /* if */ + return strcmp (left->name, right->name); +} /* cmp_total */ /* * Topologically sort the graph (collapsing cycles), and propagates * time bottom up and flags top down. */ -Sym** -DEFUN_VOID(cg_assemble) +Sym ** +DEFUN_VOID (cg_assemble) { - Sym *parent, **time_sorted_syms, **top_sorted_syms; - long index; - Arc *arc; - extern void find_call PARAMS((Sym *parent, - bfd_vma p_lowpc, bfd_vma p_highpc)); - /* - * initialize various things: - * zero out child times. - * count self-recursive calls. - * indicate that nothing is on cycles. - */ - for (parent = symtab.base; parent < symtab.limit; parent++) { - parent->cg.child_time = 0.0; - arc = arc_lookup(parent, parent); - if (arc && parent == arc->child) { - parent->ncalls -= arc->count; - parent->cg.self_calls = arc->count; - } else { - parent->cg.self_calls = 0; - } /* if */ - parent->cg.prop.fract = 0.0; - parent->cg.prop.self = 0.0; - parent->cg.prop.child = 0.0; - parent->cg.print_flag = FALSE; - parent->cg.top_order = DFN_NAN; - parent->cg.cyc.num = 0; - parent->cg.cyc.head = parent; - parent->cg.cyc.next = 0; - if (ignore_direct_calls) { - find_call(parent, parent->addr, (parent+1)->addr); - } /* if */ - } /* for */ - /* - * Topologically order things. If any node is unnumbered, number - * it and any of its descendents. - */ - for (parent = symtab.base; parent < symtab.limit; parent++) { - if (parent->cg.top_order == DFN_NAN) { - cg_dfn(parent); - } /* if */ - } /* for */ - - /* link together nodes on the same cycle: */ - cycle_link(); - - /* sort the symbol table in reverse topological order: */ - top_sorted_syms = (Sym**)xmalloc(symtab.len * sizeof(Sym*)); - for (index = 0; index < symtab.len; ++index) { - top_sorted_syms[index] = &symtab.base[index]; - } /* for */ - qsort(top_sorted_syms, symtab.len, sizeof(Sym *), cmp_topo); - DBG(DFNDEBUG, - printf("[cg_assemble] topological sort listing\n"); - for (index = 0; index < symtab.len; ++index) { - printf("[cg_assemble] "); - printf("%d:", top_sorted_syms[index]->cg.top_order); - print_name(top_sorted_syms[index]); - printf("\n"); - } /* for */); - /* - * Starting from the topological top, propagate print flags to - * children. also, calculate propagation fractions. this happens - * before time propagation since time propagation uses the - * fractions. - */ - propagate_flags(top_sorted_syms); - - /* - * Starting from the topological bottom, propogate children times - * up to parents. - */ - cycle_time(); - for (index = 0; index < symtab.len; ++index) { - propagate_time(top_sorted_syms[index]); - } /* for */ - - free(top_sorted_syms); - - /* - * Now, sort by CG.PROP.SELF + CG.PROP.CHILD. Sorting both the regular - * function names and cycle headers. - */ - time_sorted_syms = (Sym**)xmalloc((symtab.len + num_cycles)*sizeof(Sym*)); - for (index = 0; index < symtab.len; index++) { - time_sorted_syms[index] = &symtab.base[index]; - } /* if */ - for (index = 1; index <= num_cycles; index++) { - time_sorted_syms[symtab.len + index - 1] = &cycle_header[index]; - } /* for */ - qsort(time_sorted_syms, symtab.len + num_cycles, sizeof(Sym*), - cmp_total); - for (index = 0; index < symtab.len + num_cycles; index++) { - time_sorted_syms[index]->cg.index = index + 1; - } /* for */ - return time_sorted_syms; -} /* cg_assemble */ - - /*** end of cg_arcs.c ***/ + Sym *parent, **time_sorted_syms, **top_sorted_syms; + long index; + Arc *arc; + extern void find_call PARAMS ((Sym * parent, + bfd_vma p_lowpc, bfd_vma p_highpc)); + /* + * initialize various things: + * zero out child times. + * count self-recursive calls. + * indicate that nothing is on cycles. + */ + for (parent = symtab.base; parent < symtab.limit; parent++) + { + parent->cg.child_time = 0.0; + arc = arc_lookup (parent, parent); + if (arc && parent == arc->child) + { + parent->ncalls -= arc->count; + parent->cg.self_calls = arc->count; + } + else + { + parent->cg.self_calls = 0; + } /* if */ + parent->cg.prop.fract = 0.0; + parent->cg.prop.self = 0.0; + parent->cg.prop.child = 0.0; + parent->cg.print_flag = FALSE; + parent->cg.top_order = DFN_NAN; + parent->cg.cyc.num = 0; + parent->cg.cyc.head = parent; + parent->cg.cyc.next = 0; + if (ignore_direct_calls) + { + find_call (parent, parent->addr, (parent + 1)->addr); + } /* if */ + } /* for */ + /* + * Topologically order things. If any node is unnumbered, number + * it and any of its descendents. + */ + for (parent = symtab.base; parent < symtab.limit; parent++) + { + if (parent->cg.top_order == DFN_NAN) + { + cg_dfn (parent); + } /* if */ + } /* for */ + + /* link together nodes on the same cycle: */ + cycle_link (); + + /* sort the symbol table in reverse topological order: */ + top_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *)); + for (index = 0; index < symtab.len; ++index) + { + top_sorted_syms[index] = &symtab.base[index]; + } /* for */ + qsort (top_sorted_syms, symtab.len, sizeof (Sym *), cmp_topo); + DBG (DFNDEBUG, + printf ("[cg_assemble] topological sort listing\n"); + for (index = 0; index < symtab.len; ++index) + { + printf ("[cg_assemble] "); + printf ("%d:", top_sorted_syms[index]->cg.top_order); + print_name (top_sorted_syms[index]); + printf ("\n"); + } /* for */ + ); + /* + * Starting from the topological top, propagate print flags to + * children. also, calculate propagation fractions. this happens + * before time propagation since time propagation uses the + * fractions. + */ + propagate_flags (top_sorted_syms); + + /* + * Starting from the topological bottom, propogate children times + * up to parents. + */ + cycle_time (); + for (index = 0; index < symtab.len; ++index) + { + propagate_time (top_sorted_syms[index]); + } /* for */ + + free (top_sorted_syms); + + /* + * Now, sort by CG.PROP.SELF + CG.PROP.CHILD. Sorting both the regular + * function names and cycle headers. + */ + time_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *)); + for (index = 0; index < symtab.len; index++) + { + time_sorted_syms[index] = &symtab.base[index]; + } /* if */ + for (index = 1; index <= num_cycles; index++) + { + time_sorted_syms[symtab.len + index - 1] = &cycle_header[index]; + } /* for */ + qsort (time_sorted_syms, symtab.len + num_cycles, sizeof (Sym *), + cmp_total); + for (index = 0; index < symtab.len + num_cycles; index++) + { + time_sorted_syms[index]->cg.index = index + 1; + } /* for */ + return time_sorted_syms; +} /* cg_assemble */ + +/*** end of cg_arcs.c ***/ diff --git a/gprof/cg_arcs.h b/gprof/cg_arcs.h index 73c2c4b..25d5b61 100644 --- a/gprof/cg_arcs.h +++ b/gprof/cg_arcs.h @@ -11,21 +11,23 @@ * of how many times this arc was traversed, and pointers to the next * parent of this child and the next child of this parent. */ -typedef struct arc { - Sym *parent; /* source vertice of arc */ - Sym *child; /* dest vertice of arc */ - int count; /* # of calls from parent to child */ - double time; /* time inherited along arc */ - double child_time; /* child-time inherited along arc */ - struct arc *next_parent; /* next parent of CHILD */ - struct arc *next_child; /* next child of PARENT */ -} Arc; +typedef struct arc + { + Sym *parent; /* source vertice of arc */ + Sym *child; /* dest vertice of arc */ + int count; /* # of calls from parent to child */ + double time; /* time inherited along arc */ + double child_time; /* child-time inherited along arc */ + struct arc *next_parent; /* next parent of CHILD */ + struct arc *next_child; /* next child of PARENT */ + } +Arc; -extern int num_cycles; /* number of cycles discovered */ -extern Sym *cycle_header; /* cycle headers */ +extern int num_cycles; /* number of cycles discovered */ +extern Sym *cycle_header; /* cycle headers */ -extern void arc_add PARAMS((Sym *parent, Sym *child, int count)); -extern Arc *arc_lookup PARAMS((Sym *parent, Sym *child)); -extern Sym **cg_assemble PARAMS((void)); +extern void arc_add PARAMS ((Sym * parent, Sym * child, int count)); +extern Arc *arc_lookup PARAMS ((Sym * parent, Sym * child)); +extern Sym **cg_assemble PARAMS ((void)); #endif /* cg_arcs_h */ diff --git a/gprof/cg_dfn.c b/gprof/cg_dfn.c index f93a9d8..29eb64c 100644 --- a/gprof/cg_dfn.c +++ b/gprof/cg_dfn.c @@ -25,37 +25,40 @@ #define DFN_DEPTH 100 -typedef struct { +typedef struct + { Sym *sym; int cycle_top; -} DFN_Stack; + } +DFN_Stack; DFN_Stack dfn_stack[DFN_DEPTH]; -int dfn_depth = 0; -int dfn_counter = DFN_NAN; +int dfn_depth = 0; +int dfn_counter = DFN_NAN; /* * Is CHILD already numbered? */ static bool -DEFUN(is_numbered, (child), Sym *child) +DEFUN (is_numbered, (child), Sym * child) { - return child->cg.top_order != DFN_NAN && child->cg.top_order != DFN_BUSY; -} /* is_numbered */ + return child->cg.top_order != DFN_NAN && child->cg.top_order != DFN_BUSY; +} /* is_numbered */ /* * Is CHILD already busy? */ static bool -DEFUN(is_busy, (child), Sym *child) +DEFUN (is_busy, (child), Sym * child) { - if (child->cg.top_order == DFN_NAN) { - return FALSE; - } /* if */ - return TRUE; -} /* is_busy */ + if (child->cg.top_order == DFN_NAN) + { + return FALSE; + } /* if */ + return TRUE; +} /* is_busy */ /* @@ -65,92 +68,122 @@ DEFUN(is_busy, (child), Sym *child) * depth-first number). */ static void -DEFUN(find_cycle, (child), Sym *child) +DEFUN (find_cycle, (child), Sym * child) { - Sym *head = 0; - Sym *tail; - int cycle_top; - int index; - - for (cycle_top = dfn_depth; cycle_top > 0; --cycle_top) { - head = dfn_stack[cycle_top].sym; - if (child == head) { - break; - } /* if */ - if (child->cg.cyc.head != child && child->cg.cyc.head == head) { - break; - } /* if */ - } /* for */ - if (cycle_top <= 0) { - fprintf(stderr, "[find_cycle] couldn't find head of cycle\n"); - done(1); - } /* if */ - DBG(DFNDEBUG, printf("[find_cycle] dfn_depth %d cycle_top %d ", - dfn_depth, cycle_top); - if (head) { - print_name(head); - } else { - printf(""); - } /* if */ - printf("\n")); - if (cycle_top == dfn_depth) { - /* - * This is previous function, e.g. this calls itself. Sort of - * boring. - * - * Since we are taking out self-cycles elsewhere no need for - * the special case, here. - */ - DBG(DFNDEBUG, - printf("[find_cycle] "); print_name(child); printf("\n")); - } else { - /* - * Glom intervening functions that aren't already glommed into - * this cycle. Things have been glommed when their cyclehead - * field points to the head of the cycle they are glommed - * into. - */ - for (tail = head; tail->cg.cyc.next; tail = tail->cg.cyc.next) { - /* void: chase down to tail of things already glommed */ - DBG(DFNDEBUG, - printf("[find_cycle] tail "); print_name(tail); printf("\n")); - } /* for */ - /* - * If what we think is the top of the cycle has a cyclehead - * field, then it's not really the head of the cycle, which is - * really what we want. - */ - if (head->cg.cyc.head != head) { - head = head->cg.cyc.head; - DBG(DFNDEBUG, printf("[find_cycle] new cyclehead "); - print_name(head); printf("\n")); - } /* if */ - for (index = cycle_top + 1; index <= dfn_depth; ++index) { - child = dfn_stack[index].sym; - if (child->cg.cyc.head == child) { - /* - * Not yet glommed anywhere, glom it and fix any - * children it has glommed. - */ - tail->cg.cyc.next = child; - child->cg.cyc.head = head; - DBG(DFNDEBUG, printf("[find_cycle] glomming "); - print_name(child); printf(" onto "); print_name(head); - printf("\n")); - for (tail = child; tail->cg.cyc.next; tail = tail->cg.cyc.next) + Sym *head = 0; + Sym *tail; + int cycle_top; + int index; + + for (cycle_top = dfn_depth; cycle_top > 0; --cycle_top) + { + head = dfn_stack[cycle_top].sym; + if (child == head) + { + break; + } /* if */ + if (child->cg.cyc.head != child && child->cg.cyc.head == head) + { + break; + } /* if */ + } /* for */ + if (cycle_top <= 0) + { + fprintf (stderr, "[find_cycle] couldn't find head of cycle\n"); + done (1); + } /* if */ +#ifdef DEBUG + if (debug_level & DFNDEBUG) + { + printf ("[find_cycle] dfn_depth %d cycle_top %d ", + dfn_depth, cycle_top); + if (head) + { + print_name (head); + } + else + { + printf (""); + } /* if */ + printf ("\n"); + } +#endif + if (cycle_top == dfn_depth) + { + /* + * This is previous function, e.g. this calls itself. Sort of + * boring. + * + * Since we are taking out self-cycles elsewhere no need for + * the special case, here. + */ + DBG (DFNDEBUG, + printf ("[find_cycle] "); + print_name (child); + printf ("\n")); + } + else + { + /* + * Glom intervening functions that aren't already glommed into + * this cycle. Things have been glommed when their cyclehead + * field points to the head of the cycle they are glommed + * into. + */ + for (tail = head; tail->cg.cyc.next; tail = tail->cg.cyc.next) + { + /* void: chase down to tail of things already glommed */ + DBG (DFNDEBUG, + printf ("[find_cycle] tail "); + print_name (tail); + printf ("\n")); + } /* for */ + /* + * If what we think is the top of the cycle has a cyclehead + * field, then it's not really the head of the cycle, which is + * really what we want. + */ + if (head->cg.cyc.head != head) + { + head = head->cg.cyc.head; + DBG (DFNDEBUG, printf ("[find_cycle] new cyclehead "); + print_name (head); + printf ("\n")); + } /* if */ + for (index = cycle_top + 1; index <= dfn_depth; ++index) + { + child = dfn_stack[index].sym; + if (child->cg.cyc.head == child) + { + /* + * Not yet glommed anywhere, glom it and fix any + * children it has glommed. + */ + tail->cg.cyc.next = child; + child->cg.cyc.head = head; + DBG (DFNDEBUG, printf ("[find_cycle] glomming "); + print_name (child); + printf (" onto "); + print_name (head); + printf ("\n")); + for (tail = child; tail->cg.cyc.next; tail = tail->cg.cyc.next) { - tail->cg.cyc.next->cg.cyc.head = head; - DBG(DFNDEBUG, printf("[find_cycle] and its tail "); - print_name(tail->cg.cyc.next); printf(" onto "); - print_name(head); printf("\n")); - } /* for */ - } else if (child->cg.cyc.head != head /* firewall */) { - fprintf(stderr, "[find_cycle] glommed, but not to head\n"); - done(1); - } /* if */ - } /* for */ - } /* if */ -} /* find_cycle */ + tail->cg.cyc.next->cg.cyc.head = head; + DBG (DFNDEBUG, printf ("[find_cycle] and its tail "); + print_name (tail->cg.cyc.next); + printf (" onto "); + print_name (head); + printf ("\n")); + } /* for */ + } + else if (child->cg.cyc.head != head /* firewall */ ) + { + fprintf (stderr, "[find_cycle] glommed, but not to head\n"); + done (1); + } /* if */ + } /* for */ + } /* if */ +} /* find_cycle */ /* @@ -158,19 +191,21 @@ DEFUN(find_cycle, (child), Sym *child) * the stack and mark it busy. */ static void -DEFUN(pre_visit, (parent), Sym *parent) +DEFUN (pre_visit, (parent), Sym * parent) { - ++dfn_depth; - if (dfn_depth >= DFN_DEPTH) { - fprintf(stderr, "[pre_visit] dfn_stack overflow\n"); - done(1); - } /* if */ - dfn_stack[dfn_depth].sym = parent; - dfn_stack[dfn_depth].cycle_top = dfn_depth; - parent->cg.top_order = DFN_BUSY; - DBG(DFNDEBUG, printf("[pre_visit]\t\t%d:", dfn_depth); print_name(parent); - printf("\n")); -} /* pre_visit */ + ++dfn_depth; + if (dfn_depth >= DFN_DEPTH) + { + fprintf (stderr, "[pre_visit] dfn_stack overflow\n"); + done (1); + } /* if */ + dfn_stack[dfn_depth].sym = parent; + dfn_stack[dfn_depth].cycle_top = dfn_depth; + parent->cg.top_order = DFN_BUSY; + DBG (DFNDEBUG, printf ("[pre_visit]\t\t%d:", dfn_depth); + print_name (parent); + printf ("\n")); +} /* pre_visit */ /* @@ -178,61 +213,71 @@ DEFUN(pre_visit, (parent), Sym *parent) * and number functions if PARENT is head of a cycle. */ static void -DEFUN(post_visit, (parent), Sym *parent) +DEFUN (post_visit, (parent), Sym * parent) { - Sym *member; - - DBG(DFNDEBUG, printf("[post_visit]\t%d: ", dfn_depth); - print_name(parent); printf("\n")); - /* - * Number functions and things in their cycles unless the function - * is itself part of a cycle: - */ - if (parent->cg.cyc.head == parent) { - ++dfn_counter; - for (member = parent; member; member = member->cg.cyc.next) { - member->cg.top_order = dfn_counter; - DBG(DFNDEBUG, printf("[post_visit]\t\tmember "); - print_name(member); - printf("-> cg.top_order = %d\n", dfn_counter)); - } /* for */ - } else { - DBG(DFNDEBUG, printf("[post_visit]\t\tis part of a cycle\n")); - } /* if */ - --dfn_depth; -} /* post_visit */ + Sym *member; + + DBG (DFNDEBUG, printf ("[post_visit]\t%d: ", dfn_depth); + print_name (parent); + printf ("\n")); + /* + * Number functions and things in their cycles unless the function + * is itself part of a cycle: + */ + if (parent->cg.cyc.head == parent) + { + ++dfn_counter; + for (member = parent; member; member = member->cg.cyc.next) + { + member->cg.top_order = dfn_counter; + DBG (DFNDEBUG, printf ("[post_visit]\t\tmember "); + print_name (member); + printf ("-> cg.top_order = %d\n", dfn_counter)); + } /* for */ + } + else + { + DBG (DFNDEBUG, printf ("[post_visit]\t\tis part of a cycle\n")); + } /* if */ + --dfn_depth; +} /* post_visit */ /* * Given this PARENT, depth first number its children. */ void -DEFUN(cg_dfn, (parent), Sym *parent) +DEFUN (cg_dfn, (parent), Sym * parent) { - Arc *arc; - - DBG(DFNDEBUG, printf("[dfn] dfn( "); print_name(parent); printf(")\n")); - /* - * If we're already numbered, no need to look any further: - */ - if (is_numbered(parent)) { - return; - } /* if */ - /* - * If we're already busy, must be a cycle: - */ - if (is_busy(parent)) { - find_cycle(parent); - return; - } /* if */ - pre_visit(parent); - /* - * Recursively visit children: - */ - for (arc = parent->cg.children; arc; arc = arc->next_child) { - cg_dfn(arc->child); - } /* for */ - post_visit(parent); -} /* cg_dfn */ - - /*** end of cg_dfn.c ***/ + Arc *arc; + + DBG (DFNDEBUG, printf ("[dfn] dfn( "); + print_name (parent); + printf (")\n")); + /* + * If we're already numbered, no need to look any further: + */ + if (is_numbered (parent)) + { + return; + } /* if */ + /* + * If we're already busy, must be a cycle: + */ + if (is_busy (parent)) + { + find_cycle (parent); + return; + } /* if */ + pre_visit (parent); + /* + * Recursively visit children: + */ + for (arc = parent->cg.children; arc; arc = arc->next_child) + { + cg_dfn (arc->child); + } /* for */ + post_visit (parent); +} /* cg_dfn */ + +/*** end of cg_dfn.c ***/ diff --git a/gprof/cg_dfn.h b/gprof/cg_dfn.h index ac20330..4bd3030 100644 --- a/gprof/cg_dfn.h +++ b/gprof/cg_dfn.h @@ -12,6 +12,6 @@ * Depth-first numbering of a call-graph. */ -extern void cg_dfn PARAMS((Sym *root)); +extern void cg_dfn PARAMS ((Sym * root)); #endif /* cg_dfn_h */ diff --git a/gprof/cg_print.c b/gprof/cg_print.c index d123f3e..cbff366 100644 --- a/gprof/cg_print.c +++ b/gprof/cg_print.c @@ -12,73 +12,89 @@ #define GREATERTHAN 1 /* declarations of automatically generated functions to output blurbs: */ -extern void bsd_callg_blurb PARAMS((FILE *fp)); -extern void fsf_callg_blurb PARAMS((FILE *fp)); +extern void bsd_callg_blurb PARAMS ((FILE * fp)); +extern void fsf_callg_blurb PARAMS ((FILE * fp)); double print_time = 0.0; static void -DEFUN_VOID(print_header) +DEFUN_VOID (print_header) { - if (first_output) { - first_output = FALSE; - } else { - printf("\f\n"); - } /* if */ - if (!bsd_style_output) { - if (print_descriptions) { - printf("\t\t Call graph (explanation follows)\n\n"); - } else { - printf("\t\t\tCall graph\n\n"); - } /* if */ - } /* if */ - 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); - } else { - printf(" no time propagated\n\n"); - /* - * This doesn't hurt, since all the numerators will be 0.0: - */ - print_time = 1.0; - } /* if */ - if (bsd_style_output) { - printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", - "", "", "", "", "called", "total", "parents"); - printf("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n", - "index", "%time", "self", "descendents", - "called", "self", "name", "index"); - printf("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", - "", "", "", "", "called", "total", "children"); - printf("\n"); - } else { - printf("index %% time self children called name\n"); - } /* if */ -} /* print_header */ + if (first_output) + { + first_output = FALSE; + } + else + { + printf ("\f\n"); + } /* if */ + if (!bsd_style_output) + { + if (print_descriptions) + { + printf ("\t\t Call graph (explanation follows)\n\n"); + } + else + { + printf ("\t\t\tCall graph\n\n"); + } /* if */ + } /* if */ + 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); + } + else + { + printf (" no time propagated\n\n"); + /* + * This doesn't hurt, since all the numerators will be 0.0: + */ + print_time = 1.0; + } /* if */ + if (bsd_style_output) + { + printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", + "", "", "", "", "called", "total", "parents"); + printf ("%-6.6s %5.5s %7.7s %11.11s %7.7s+%-7.7s %-8.8s\t%5.5s\n", + "index", "%time", "self", "descendents", + "called", "self", "name", "index"); + printf ("%6.6s %5.5s %7.7s %11.11s %7.7s/%-7.7s %-8.8s\n", + "", "", "", "", "called", "total", "children"); + printf ("\n"); + } + else + { + printf ("index %% time self children called name\n"); + } /* if */ +} /* print_header */ /* * Print a cycle header. */ static void -DEFUN(print_cycle, (cyc), Sym *cyc) +DEFUN (print_cycle, (cyc), Sym * cyc) { - char buf[BUFSIZ]; + char buf[BUFSIZ]; - sprintf(buf, "[%d]", cyc->cg.index); - printf("%-6.6s %5.1f %7.2f %11.2f %7d", 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("+%-7d", cyc->cg.self_calls); - } else { - printf(" %7.7s", ""); - } /* if */ - printf(" \t[%d]\n", cyc->cg.cyc.num, cyc->cg.index); -} /* print_cycle */ + sprintf (buf, "[%d]", cyc->cg.index); + printf ("%-6.6s %5.1f %7.2f %11.2f %7d", 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 ("+%-7d", cyc->cg.self_calls); + } + else + { + printf (" %7.7s", ""); + } /* if */ + printf (" \t[%d]\n", cyc->cg.cyc.num, cyc->cg.index); +} /* print_cycle */ /* @@ -86,468 +102,540 @@ DEFUN(print_cycle, (cyc), Sym *cyc) * 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) +DEFUN (cmp_member, (left, right), Sym * left AND Sym * right) { - double left_time = left->cg.prop.self + left->cg.prop.child; - double right_time = right->cg.prop.self + right->cg.prop.child; - long left_calls = left->ncalls + left->cg.self_calls; - long right_calls = right->ncalls + right->cg.self_calls; - - if (left_time > right_time) { - return GREATERTHAN; - } /* if */ - if (left_time < right_time) { - return LESSTHAN; - } /* if */ - - if (left_calls > right_calls) { - return GREATERTHAN; - } /* if */ - if (left_calls < right_calls) { - return LESSTHAN; - } /* if */ - return EQUALTO; -} /* cmp_member */ + double left_time = left->cg.prop.self + left->cg.prop.child; + double right_time = right->cg.prop.self + right->cg.prop.child; + long left_calls = left->ncalls + left->cg.self_calls; + long right_calls = right->ncalls + right->cg.self_calls; + + if (left_time > right_time) + { + return GREATERTHAN; + } /* if */ + if (left_time < right_time) + { + return LESSTHAN; + } /* if */ + + if (left_calls > right_calls) + { + return GREATERTHAN; + } /* if */ + if (left_calls < right_calls) + { + return LESSTHAN; + } /* if */ + return EQUALTO; +} /* cmp_member */ /* * Sort members of a cycle. */ static void -DEFUN(sort_members, (cyc), Sym *cyc) +DEFUN (sort_members, (cyc), Sym * cyc) { - Sym *todo, *doing, *prev; - /* - * 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; - } /* if */ - } /* for */ - doing->cg.cyc.next = prev->cg.cyc.next; - prev->cg.cyc.next = doing; - } /* for */ -} /* sort_members */ + Sym *todo, *doing, *prev; + /* + * 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; + } /* if */ + } /* for */ + doing->cg.cyc.next = prev->cg.cyc.next; + prev->cg.cyc.next = doing; + } /* for */ +} /* sort_members */ /* * Print the members of a cycle. */ static void -DEFUN(print_members, (cyc), Sym *cyc) +DEFUN (print_members, (cyc), Sym * cyc) { - Sym *member; - - sort_members(cyc); - for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next) { - printf("%6.6s %5.5s %7.2f %11.2f %7d", - "", "", member->cg.prop.self / hz, member->cg.prop.child / hz, - member->ncalls); - if (member->cg.self_calls != 0) { - printf("+%-7d", member->cg.self_calls); - } else { - printf(" %7.7s", ""); - } /* if */ - printf(" "); - print_name(member); - printf("\n"); - } /* for */ -} /* print_members */ + Sym *member; + + sort_members (cyc); + for (member = cyc->cg.cyc.next; member; member = member->cg.cyc.next) + { + printf ("%6.6s %5.5s %7.2f %11.2f %7d", + "", "", member->cg.prop.self / hz, member->cg.prop.child / hz, + member->ncalls); + if (member->cg.self_calls != 0) + { + printf ("+%-7d", member->cg.self_calls); + } + else + { + printf (" %7.7s", ""); + } /* if */ + printf (" "); + print_name (member); + printf ("\n"); + } /* for */ +} /* print_members */ /* * 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 + * - 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) +DEFUN (cmp_arc, (left, right), Arc * left AND Arc * right) { - Sym *left_parent = left->parent; - Sym *left_child = left->child; - Sym *right_parent = right->parent; - Sym *right_child = right->child; - double left_time, right_time; - - DBG(TIMEDEBUG, - printf("[cmp_arc] "); - print_name(left_parent); - printf(" calls "); - print_name(left_child); - printf(" %f + %f %d/%d\n", left->time, left->child_time, + Sym *left_parent = left->parent; + Sym *left_child = left->child; + Sym *right_parent = right->parent; + Sym *right_child = right->child; + double left_time, right_time; + + DBG (TIMEDEBUG, + printf ("[cmp_arc] "); + print_name (left_parent); + printf (" calls "); + print_name (left_child); + printf (" %f + %f %d/%d\n", left->time, left->child_time, left->count, left_child->ncalls); - printf("[cmp_arc] "); - print_name(right_parent); - printf(" calls "); - print_name(right_child); - printf(" %f + %f %d/%d\n", right->time, right->child_time, + printf ("[cmp_arc] "); + print_name (right_parent); + printf (" calls "); + print_name (right_child); + printf (" %f + %f %d/%d\n", right->time, right->child_time, right->count, right_child->ncalls); - printf("\n"); - ); - if (left_parent == left_child) { - return LESSTHAN; /* left is a self call */ - } /* if */ - if (right_parent == right_child) { - return GREATERTHAN; /* right is a self call */ - } /* if */ - - 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 */ - if (right_parent->cg.cyc.num != 0 && right_child->cg.cyc.num != 0 - && right_parent->cg.cyc.num == right_child->cg.cyc.num) + printf ("\n"); + ); + if (left_parent == left_child) + { + return LESSTHAN; /* left is a self call */ + } /* if */ + if (right_parent == right_child) + { + return GREATERTHAN; /* right is a self call */ + } /* if */ + + 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 */ + 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 */ + if (left->count < right->count) + { + return LESSTHAN; + } /* if */ + if (left->count > right->count) + { + return GREATERTHAN; + } /* if */ + return EQUALTO; + } + else { - /* right is a call within the cycle, too */ - if (left->count < right->count) { - return LESSTHAN; - } /* if */ - if (left->count > right->count) { - return GREATERTHAN; - } /* if */ - return EQUALTO; - } else { - /* right isn't a call within the cycle */ - return LESSTHAN; - } /* if */ - } else { - /* 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 isn't a call within the cycle */ + return LESSTHAN; + } /* if */ + } + else + { + /* 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 */ - return GREATERTHAN; - } else { - /* 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; - } /* if */ - if (left_time > right_time) { - return GREATERTHAN; - } /* if */ - if (left->count < right->count) { - return LESSTHAN; - } /* if */ - if (left->count > right->count) { - return GREATERTHAN; - } /* if */ - return EQUALTO; - } /* if */ - } /* if */ -} /* cmp_arc */ + /* right is a call within a cycle */ + return GREATERTHAN; + } + else + { + /* 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; + } /* if */ + if (left_time > right_time) + { + return GREATERTHAN; + } /* if */ + if (left->count < right->count) + { + return LESSTHAN; + } /* if */ + if (left->count > right->count) + { + return GREATERTHAN; + } /* if */ + return EQUALTO; + } /* if */ + } /* if */ +} /* cmp_arc */ static void -DEFUN(sort_parents, (child), Sym *child) +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. - */ - sorted.next_parent = 0; - for (arc = child->cg.parents; arc; arc = detached) { - detached = arc->next_parent; - - /* 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; - } /* if */ - } /* for */ - arc->next_parent = prev->next_parent; - prev->next_parent = arc; - } /* for */ - - /* reattach sorted arcs to child: */ - child->cg.parents = sorted.next_parent; -} /* sort_parents */ + 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. + */ + sorted.next_parent = 0; + for (arc = child->cg.parents; arc; arc = detached) + { + detached = arc->next_parent; + + /* 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; + } /* if */ + } /* for */ + arc->next_parent = prev->next_parent; + prev->next_parent = arc; + } /* for */ + + /* reattach sorted arcs to child: */ + child->cg.parents = sorted.next_parent; +} /* sort_parents */ static void -DEFUN(print_parents, (child), Sym *child) +DEFUN (print_parents, (child), Sym * child) { - Sym *parent; - Arc *arc; - Sym *cycle_head; - - if (child->cg.cyc.head != 0) { - cycle_head = child->cg.cyc.head; - } else { - cycle_head = child; - } /* if */ - if (!child->cg.parents) { - printf(bsd_style_output - ? "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s \n" - : "%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s \n", - "", "", "", "", "", ""); - return; - } /* if */ - 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)) + Sym *parent; + Arc *arc; + Sym *cycle_head; + + if (child->cg.cyc.head != 0) + { + cycle_head = child->cg.cyc.head; + } + else + { + cycle_head = child; + } /* if */ + if (!child->cg.parents) + { + printf (bsd_style_output + ? "%6.6s %5.5s %7.7s %11.11s %7.7s %7.7s \n" + : "%6.6s %5.5s %7.7s %7.7s %7.7s %7.7s \n", + "", "", "", "", "", ""); + return; + } /* if */ + 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: */ - printf(bsd_style_output - ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " - : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s ", - "", "", "", "", - arc->count, ""); - print_name(parent); - printf("\n"); - } else { - /* regular parent of child: */ - printf(bsd_style_output - ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " - : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d ", - "", "", - arc->time / hz, arc->child_time / hz, - arc->count, cycle_head->ncalls); - print_name(parent); - printf("\n"); - } /* if */ - } /* for */ -} /* print_parents */ + /* selfcall or call among siblings: */ + printf (bsd_style_output + ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " + : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s ", + "", "", "", "", + arc->count, ""); + print_name (parent); + printf ("\n"); + } + else + { + /* regular parent of child: */ + printf (bsd_style_output + ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " + : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d ", + "", "", + arc->time / hz, arc->child_time / hz, + arc->count, cycle_head->ncalls); + print_name (parent); + printf ("\n"); + } /* if */ + } /* for */ +} /* print_parents */ static void -DEFUN(sort_children, (parent), Sym *parent) +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. - */ - sorted.next_child = 0; - for (arc = parent->cg.children; arc; arc = detached) { - detached = arc->next_child; - - /* 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; - } /* if */ - } /* for */ - arc->next_child = prev->next_child; - prev->next_child = arc; - } /* for */ - - /* reattach sorted children to parent: */ - parent->cg.children = sorted.next_child; -} /* sort_children */ + 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. + */ + sorted.next_child = 0; + for (arc = parent->cg.children; arc; arc = detached) + { + detached = arc->next_child; + + /* 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; + } /* if */ + } /* for */ + arc->next_child = prev->next_child; + prev->next_child = arc; + } /* for */ + + /* reattach sorted children to parent: */ + parent->cg.children = sorted.next_child; +} /* sort_children */ static void -DEFUN(print_children, (parent), Sym *parent) +DEFUN (print_children, (parent), Sym * parent) { - Sym *child; - Arc *arc; - - 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)) + Sym *child; + Arc *arc; + + 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: */ + printf (bsd_style_output + ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " + : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s ", + "", "", "", "", arc->count, ""); + print_name (child); + printf ("\n"); + } + else { - /* self call or call to sibling: */ - printf(bsd_style_output - ? "%6.6s %5.5s %7.7s %11.11s %7d %7.7s " - : "%6.6s %5.5s %7.7s %7.7s %7d %7.7s ", - "", "", "", "", arc->count, ""); - print_name(child); - printf("\n"); - } else { - /* regular child of parent: */ - printf(bsd_style_output - ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " - : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d ", - "", "", - arc->time / hz, arc->child_time / hz, - arc->count, child->cg.cyc.head->ncalls); - print_name(child); - printf("\n"); - } /* if */ - } /* for */ -} /* print_children */ + /* regular child of parent: */ + printf (bsd_style_output + ? "%6.6s %5.5s %7.2f %11.2f %7d/%-7d " + : "%6.6s %5.5s %7.2f %7.2f %7d/%-7d ", + "", "", + arc->time / hz, arc->child_time / hz, + arc->count, child->cg.cyc.head->ncalls); + print_name (child); + printf ("\n"); + } /* if */ + } /* for */ +} /* print_children */ static void -DEFUN(print_line, (np), Sym *np) +DEFUN (print_line, (np), Sym * np) { - char buf[BUFSIZ]; - - sprintf(buf, "[%d]", np->cg.index); - printf(bsd_style_output - ? "%-6.6s %5.1f %7.2f %11.2f" - : "%-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(" %7d", np->ncalls); - if (np->cg.self_calls != 0) { - printf("+%-7d ", np->cg.self_calls); - } else { - printf(" %7.7s ", ""); - } /* if */ - } else { - printf(" %7.7s %7.7s ", "", ""); - } /* if */ - print_name(np); - printf("\n"); -} /* print_line */ + char buf[BUFSIZ]; + + sprintf (buf, "[%d]", np->cg.index); + printf (bsd_style_output + ? "%-6.6s %5.1f %7.2f %11.2f" + : "%-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 (" %7d", np->ncalls); + if (np->cg.self_calls != 0) + { + printf ("+%-7d ", np->cg.self_calls); + } + else + { + printf (" %7.7s ", ""); + } /* if */ + } + else + { + printf (" %7.7s %7.7s ", "", ""); + } /* if */ + print_name (np); + printf ("\n"); +} /* print_line */ /* * Print dynamic call graph. */ void -DEFUN(cg_print, (timesortsym), Sym **timesortsym) +DEFUN (cg_print, (timesortsym), Sym ** timesortsym) { - int index; - Sym *parent; + int index; + Sym *parent; - if (print_descriptions && bsd_style_output) { - bsd_callg_blurb(stdout); - } /* if */ + if (print_descriptions && bsd_style_output) + { + bsd_callg_blurb (stdout); + } /* if */ - print_header(); + 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) + 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) + { + continue; + } /* if */ + if (!parent->name && parent->cg.cyc.num != 0) { - continue; - } /* if */ - if (!parent->name && parent->cg.cyc.num != 0) { - /* cycle header: */ - print_cycle(parent); - print_members(parent); - } else { - print_parents(parent); - print_line(parent); - print_children(parent); - } /* if */ - if (bsd_style_output) - printf("\n"); - printf("-----------------------------------------------\n"); - if (bsd_style_output) - printf("\n"); + /* cycle header: */ + print_cycle (parent); + print_members (parent); + } + else + { + print_parents (parent); + print_line (parent); + print_children (parent); + } /* if */ + 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); + free (timesortsym); + if (print_descriptions && !bsd_style_output) + { + fsf_callg_blurb (stdout); } -} /* cg_print */ +} /* cg_print */ static int -DEFUN(cmp_name, (left, right), const PTR left AND const PTR right) +DEFUN (cmp_name, (left, right), const PTR left AND const PTR right) { - const Sym **npp1 = (const Sym **)left; - const Sym **npp2 = (const Sym **)right; + const Sym **npp1 = (const Sym **) left; + const Sym **npp2 = (const Sym **) right; - return strcmp((*npp1)->name, (*npp2)->name); -} /* cmp_name */ + return strcmp ((*npp1)->name, (*npp2)->name); +} /* cmp_name */ void -DEFUN_VOID(cg_print_index) +DEFUN_VOID (cg_print_index) { - int index, nnames, todo, i, j, col, starting_col; - 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: - */ - 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) + int index, nnames, todo, i, j, col, starting_col; + 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: + */ + 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; + } /* if */ + name_sorted_syms[nnames++] = &symtab.base[index]; + } /* for */ + 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]; + } /* for */ + printf ("\f\nIndex 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) { - continue; - } /* if */ - name_sorted_syms[nnames++] = &symtab.base[index]; - } /* for */ - 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]; - } /* for */ - printf("\f\nIndex 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); - } else { - sprintf(buf, "(%d)", sym->cg.index); - } /* if */ - if (j < nnames) { - if (bsd_style_output) { - printf("%6.6s %-19.19s", buf, sym->name); - } else { - col += strlen(buf); - for (; col < starting_col + 5; ++col) { - putchar(' '); - } /* for */ - 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; - } else { - filename = sym->file->name; - } /* if */ - } /* if */ - printf(" (%s)", filename); - col += strlen(filename) + 3; - } /* if */ - } /* if */ - } else { - printf("%6.6s ", buf); - sprintf(buf, "", sym->cg.cyc.num); - printf("%-19.19s", buf); - } /* if */ - starting_col += column_width; - } /* for */ - printf("\n"); - } /* for */ - free(name_sorted_syms); -} /* cg_print_index */ - - /*** end of cg_print.c ***/ + sym = name_sorted_syms[j]; + if (sym->cg.print_flag) + { + sprintf (buf, "[%d]", sym->cg.index); + } + else + { + sprintf (buf, "(%d)", sym->cg.index); + } /* if */ + if (j < nnames) + { + if (bsd_style_output) + { + printf ("%6.6s %-19.19s", buf, sym->name); + } + else + { + col += strlen (buf); + for (; col < starting_col + 5; ++col) + { + putchar (' '); + } /* for */ + 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; + } + else + { + filename = sym->file->name; + } /* if */ + } /* if */ + printf (" (%s)", filename); + col += strlen (filename) + 3; + } /* if */ + } /* if */ + } + else + { + printf ("%6.6s ", buf); + sprintf (buf, "", sym->cg.cyc.num); + printf ("%-19.19s", buf); + } /* if */ + starting_col += column_width; + } /* for */ + printf ("\n"); + } /* for */ + free (name_sorted_syms); +} /* cg_print_index */ + +/*** end of cg_print.c ***/ diff --git a/gprof/cg_print.h b/gprof/cg_print.h index 15ed436..13511c7 100644 --- a/gprof/cg_print.h +++ b/gprof/cg_print.h @@ -4,9 +4,9 @@ #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 PARAMS ((Sym ** cg)); +extern void cg_print_index PARAMS ((void)); #endif /* cg_print_h */ diff --git a/gprof/core.c b/gprof/core.c index bf02be2..a525c60 100644 --- a/gprof/core.c +++ b/gprof/core.c @@ -11,191 +11,209 @@ PTR core_text_space; void -DEFUN(core_init, (a_out_name), const char *a_out_name) +DEFUN (core_init, (a_out_name), const char *a_out_name) { - core_bfd = bfd_openr(a_out_name, 0); - - if (!core_bfd) { - perror(a_out_name); - done(1); - } /* if */ - - if (!bfd_check_format(core_bfd, bfd_object)) { - fprintf(stderr, "%s: %s: not in a.out format\n", whoami, a_out_name); - done(1); - } /* if */ - - /* get core's text section: */ - core_text_sect = bfd_get_section_by_name(core_bfd, ".text"); - if (!core_text_sect) { - core_text_sect = bfd_get_section_by_name(core_bfd, "$CODE$"); - if (!core_text_sect) { - fprintf(stderr, "%s: can't find .text section in %s\n", - whoami, a_out_name); - done(1); - } /* if */ - } /* if */ - - /* read core's symbol table: */ - - /* 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) { - fprintf(stderr, "%s: %s: %s\n", whoami, a_out_name, - bfd_errmsg(bfd_get_error())); - done(1); - } /* if */ - - 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, - bfd_errmsg(bfd_get_error())); - done(1); - } /* if */ -} /* core_init */ + core_bfd = bfd_openr (a_out_name, 0); + + if (!core_bfd) + { + perror (a_out_name); + done (1); + } /* if */ + + if (!bfd_check_format (core_bfd, bfd_object)) + { + fprintf (stderr, "%s: %s: not in a.out format\n", whoami, a_out_name); + done (1); + } /* if */ + + /* get core's text section: */ + core_text_sect = bfd_get_section_by_name (core_bfd, ".text"); + if (!core_text_sect) + { + core_text_sect = bfd_get_section_by_name (core_bfd, "$CODE$"); + if (!core_text_sect) + { + fprintf (stderr, "%s: can't find .text section in %s\n", + whoami, a_out_name); + done (1); + } /* if */ + } /* if */ + + /* read core's symbol table: */ + + /* 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) + { + fprintf (stderr, "%s: %s: %s\n", whoami, a_out_name, + bfd_errmsg (bfd_get_error ())); + done (1); + } /* if */ + + 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, + bfd_errmsg (bfd_get_error ())); + done (1); + } /* if */ +} /* core_init */ /* * Read in the text space of an a.out file */ void -DEFUN(core_get_text_space, (core_bfd), bfd *core_bfd) +DEFUN (core_get_text_space, (core_bfd), bfd * core_bfd) { - core_text_space = (PTR) malloc(core_text_sect->_raw_size); - - if (!core_text_space) { - fprintf(stderr, "%s: ran out room for %ld bytes of text space\n", - whoami, core_text_sect->_raw_size); - done(1); - } /* if */ - if (!bfd_get_section_contents(core_bfd, core_text_sect, core_text_space, - 0, core_text_sect->_raw_size)) + core_text_space = (PTR) malloc (core_text_sect->_raw_size); + + if (!core_text_space) { - bfd_perror("bfd_get_section_contents"); - free(core_text_space); - core_text_space = 0; - } /* if */ - if (!core_text_space) { - fprintf(stderr, "%s: can't do -c\n", whoami); - } /* if */ -} /* core_get_text_space */ + fprintf (stderr, "%s: ran out room for %ld bytes of text space\n", + whoami, core_text_sect->_raw_size); + done (1); + } /* if */ + if (!bfd_get_section_contents (core_bfd, core_text_sect, core_text_space, + 0, core_text_sect->_raw_size)) + { + bfd_perror ("bfd_get_section_contents"); + free (core_text_space); + core_text_space = 0; + } /* if */ + if (!core_text_space) + { + fprintf (stderr, "%s: can't do -c\n", whoami); + } /* if */ +} /* core_get_text_space */ /* * 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 + * 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) +DEFUN (core_sym_class, (sym), asymbol * sym) { - symbol_info syminfo; - const char *name; - char sym_prefix; - int i; - - /* - * Must be a text symbol, and static text symbols don't qualify if - * ignore_static_funcs set. - */ - if (!sym->section) { - return 0; - } /* if */ - - if (ignore_static_funcs && (sym->flags & BSF_LOCAL)) { - DBG(AOUTDEBUG, printf("[core_sym_class] %s: not a function\n", + symbol_info syminfo; + const char *name; + char sym_prefix; + int i; + + /* + * Must be a text symbol, and static text symbols don't qualify if + * ignore_static_funcs set. + */ + if (!sym->section) + { + return 0; + } /* if */ + + if (ignore_static_funcs && (sym->flags & BSF_LOCAL)) + { + DBG (AOUTDEBUG, printf ("[core_sym_class] %s: not a function\n", sym->name)); - return 0; - } /* if */ + return 0; + } /* if */ - bfd_get_symbol_info(core_bfd, sym, &syminfo); - i = syminfo.type; + bfd_get_symbol_info (core_bfd, sym, &syminfo); + i = syminfo.type; - if (i == 'T') { - return i; /* it's a global symbol */ - } /* if */ + if (i == 'T') + { + return i; /* it's a global symbol */ + } /* if */ - if (i != 't') { - /* not a static text symbol */ - DBG(AOUTDEBUG, printf("[core_sym_class] %s is of class %c\n", + if (i != 't') + { + /* not a static text symbol */ + DBG (AOUTDEBUG, printf ("[core_sym_class] %s is of class %c\n", sym->name, i)); - return 0; - } /* if */ - - /* do some more filtering on static function-names: */ - - if (ignore_static_funcs) { - return 0; - } /* if */ - /* - * 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; - } /* if */ - - for (name = sym->name; *name; ++name) { - if (*name == '.' || *name == '$') { - return 0; - } /* if */ - } /* if */ - /* - * 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) - */ - || !strncmp (sym->name, "__gnu_compiled", 14) - || !strncmp (sym->name, "___gnu_compiled", 15)) + return 0; + } /* if */ + + /* do some more filtering on static function-names: */ + + if (ignore_static_funcs) + { + return 0; + } /* if */ + /* + * 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; - } /* if */ - return 't'; /* it's a static text symbol */ -} /* core_sym_class */ + return 0; + } /* if */ + + for (name = sym->name; *name; ++name) + { + if (*name == '.' || *name == '$') + { + return 0; + } /* if */ + } /* if */ + /* + * 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) + */ + || !strncmp (sym->name, "__gnu_compiled", 14) + || !strncmp (sym->name, "___gnu_compiled", 15)) + { + return 0; + } /* if */ + return 't'; /* it's a static text symbol */ +} /* core_sym_class */ /* * 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 - AND int *line_num) +DEFUN (get_src_info, (addr, filename, name, line_num), + bfd_vma addr AND const char **filename AND const char **name + AND int *line_num) { - const char *fname = 0, *func_name = 0; - int l = 0; + const char *fname = 0, *func_name = 0; + int l = 0; - if (bfd_find_nearest_line(core_bfd, core_text_sect, core_syms, - addr - core_text_sect->vma, - &fname, &func_name, &l) - && fname && func_name && l) + if (bfd_find_nearest_line (core_bfd, core_text_sect, core_syms, + addr - core_text_sect->vma, + &fname, &func_name, &l) + && fname && func_name && l) { - DBG(AOUTDEBUG, printf("[get_src_info] 0x%lx -> %s:%d (%s)\n", + DBG (AOUTDEBUG, printf ("[get_src_info] 0x%lx -> %s:%d (%s)\n", addr, fname, l, func_name)); - *filename = fname; - *name = func_name; - *line_num = l; - return TRUE; - } else { - DBG(AOUTDEBUG, printf("[get_src_info] no info for 0x%lx (%s:%d,%s)\n", + *filename = fname; + *name = func_name; + *line_num = l; + return TRUE; + } + else + { + DBG (AOUTDEBUG, printf ("[get_src_info] no info for 0x%lx (%s:%d,%s)\n", (long) addr, fname ? fname : "", l, func_name ? func_name : "")); - return FALSE; - } /* if */ -} /* get_src_info */ + return FALSE; + } /* if */ +} /* get_src_info */ /* @@ -203,119 +221,126 @@ DEFUN(get_src_info, (addr, filename, name, line_num), * entered. */ void -DEFUN(core_create_function_syms, (core_bfd), bfd *core_bfd) +DEFUN (core_create_function_syms, (core_bfd), bfd * core_bfd) { - bfd_vma min_vma = ~0, max_vma = 0; - const char *filename, *func_name; - int class; - long i; - - /* 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; - } /* if */ - ++symtab.len; - } /* for */ - - if (symtab.len == 0) { - fprintf(stderr, "%s: file `%s' has no symbols\n", whoami, a_out_name); - done(1); - } /* if */ - - /* the "+ 2" is for the sentinels: */ - symtab.base = (Sym*)xmalloc((symtab.len + 2) * sizeof(Sym)); - - /* 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, - printf("[core_create_function_syms] rejecting: 0x%lx %s\n", + bfd_vma min_vma = ~0, max_vma = 0; + const char *filename, *func_name; + int class; + long i; + + /* 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; + } /* if */ + ++symtab.len; + } /* for */ + + if (symtab.len == 0) + { + fprintf (stderr, "%s: file `%s' has no symbols\n", whoami, a_out_name); + done (1); + } /* if */ + + /* the "+ 2" is for the sentinels: */ + symtab.base = (Sym *) xmalloc ((symtab.len + 2) * sizeof (Sym)); + + /* 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, + printf ("[core_create_function_syms] rejecting: 0x%lx %s\n", core_syms[i]->value, core_syms[i]->name)); - continue; - } /* if */ + continue; + } /* if */ - sym_init(symtab.limit); + 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; - symtab.limit->name = core_syms[i]->name; + symtab.limit->addr = core_syms[i]->value + core_syms[i]->section->vma; + symtab.limit->name = core_syms[i]->name; #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. - */ - if (get_src_info(symtab.limit->addr, &filename, &func_name, - &symtab.limit->line_num)) + /* + * 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 (get_src_info (symtab.limit->addr, &filename, &func_name, + &symtab.limit->line_num)) { - symtab.limit->file = source_file_lookup_path(filename); - - 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. - */ - DBG(AOUTDEBUG, - printf("[core_create_function_syms: rej %s (maps to %s)\n", - symtab.limit->name, func_name)); - continue; - } /* if */ - } /* if */ + symtab.limit->file = source_file_lookup_path (filename); + + 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. + */ + DBG (AOUTDEBUG, + printf ("[core_create_function_syms: rej %s (maps to %s)\n", + symtab.limit->name, func_name)); + continue; + } /* if */ + } /* if */ #endif - symtab.limit->is_func = TRUE; - symtab.limit->is_bb_head = TRUE; - if (class == 't') { - symtab.limit->is_static = TRUE; - } /* if */ - - 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 (symtab.limit->name[0] == 'm' && discard_underscores - && strcmp(symtab.limit->name, "main") == 0) + symtab.limit->is_func = TRUE; + symtab.limit->is_bb_head = TRUE; + if (class == 't') + { + symtab.limit->is_static = TRUE; + } /* if */ + + 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 (symtab.limit->name[0] == 'm' && discard_underscores + && strcmp (symtab.limit->name, "main") == 0) { - discard_underscores = 0; - } /* if */ + discard_underscores = 0; + } /* if */ - DBG(AOUTDEBUG, printf("[core_create_function_syms] %ld %s 0x%lx\n", - (long)(symtab.limit - symtab.base), + DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n", + (long) (symtab.limit - symtab.base), symtab.limit->name, symtab.limit->addr)); - ++symtab.limit; - } /* for */ + ++symtab.limit; + } /* for */ - /* create sentinels: */ + /* create sentinels: */ - sym_init(symtab.limit); - symtab.limit->name = ""; - symtab.limit->addr = 0; - symtab.limit->end_addr = min_vma - 1; - ++symtab.limit; + sym_init (symtab.limit); + symtab.limit->name = ""; + symtab.limit->addr = 0; + symtab.limit->end_addr = min_vma - 1; + ++symtab.limit; - sym_init(symtab.limit); - symtab.limit->name = ""; - symtab.limit->addr = max_vma + 1; - symtab.limit->end_addr = ~0; - ++symtab.limit; + sym_init (symtab.limit); + symtab.limit->name = ""; + symtab.limit->addr = max_vma + 1; + symtab.limit->end_addr = ~0; + ++symtab.limit; - symtab.len = symtab.limit - symtab.base; - symtab_finalize(&symtab); -} /* core_create_function_syms */ + symtab.len = symtab.limit - symtab.base; + symtab_finalize (&symtab); +} /* core_create_function_syms */ /* @@ -323,154 +348,163 @@ DEFUN(core_create_function_syms, (core_bfd), bfd *core_bfd) * is entered. */ void -DEFUN(core_create_line_syms, (core_bfd), bfd *core_bfd) +DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) { - char prev_name[PATH_MAX], prev_filename[PATH_MAX]; - bfd_vma vma, min_vma = ~0, max_vma = 0; - bfd_vma offset, prev_offset, min_dist; - Sym *prev, dummy, *sentinel, *sym; - const char *filename; - int prev_line_num, i; - 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: - */ - 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, but for now, we try to speed up the second pass - * by determining what the minimum code distance between two - * lines is. - */ - prev_name[0] = '\0'; - ltab.len = 0; - min_dist = core_text_sect->_raw_size; - prev_offset = -min_dist; - prev_filename[0] = '\0'; - prev_line_num = 0; - for (offset = 0; offset < core_text_sect->_raw_size; ++offset) { - vma = core_text_sect->vma + offset; - if (!get_src_info(vma, &filename, &dummy.name, &dummy.line_num) - || (prev_line_num == dummy.line_num && - strcmp(prev_name, dummy.name) == 0 - && strcmp(prev_filename, filename) == 0)) + char prev_name[PATH_MAX], prev_filename[PATH_MAX]; + bfd_vma vma, min_vma = ~0, max_vma = 0; + bfd_vma offset, prev_offset, min_dist; + Sym *prev, dummy, *sentinel, *sym; + const char *filename; + int prev_line_num, i; + 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: + */ + 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, but for now, we try to speed up the second pass + * by determining what the minimum code distance between two + * lines is. + */ + prev_name[0] = '\0'; + ltab.len = 0; + min_dist = core_text_sect->_raw_size; + prev_offset = -min_dist; + prev_filename[0] = '\0'; + prev_line_num = 0; + for (offset = 0; offset < core_text_sect->_raw_size; ++offset) + { + vma = core_text_sect->vma + offset; + if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num) + || (prev_line_num == dummy.line_num && + strcmp (prev_name, dummy.name) == 0 + && strcmp (prev_filename, filename) == 0)) { - continue; - } /* if */ - - ++ltab.len; - prev_line_num = dummy.line_num; - strcpy(prev_name, dummy.name); - strcpy(prev_filename, filename); - - if (offset - prev_offset < min_dist) { - min_dist = offset - prev_offset; - } /* if */ - prev_offset = offset; - - min_vma = MIN(vma, min_vma); - max_vma = MAX(vma, max_vma); - } /* for */ - - DBG(AOUTDEBUG, printf("[core_create_line_syms] min_dist=%lx\n", min_dist)); - - /* 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: */ - - prev = 0; - for (offset = 0; offset < core_text_sect->_raw_size; offset += min_dist) { - 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; + } /* if */ + + ++ltab.len; + prev_line_num = dummy.line_num; + strcpy (prev_name, dummy.name); + strcpy (prev_filename, filename); + + if (offset - prev_offset < min_dist) { - continue; - } /* if */ - - /* make name pointer a malloc'ed string: */ - ltab.limit->name = strdup(ltab.limit->name); - ltab.limit->file = source_file_lookup_path(filename); - - ltab.limit->addr = core_text_sect->vma + offset; - prev = ltab.limit; - - /* - * 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) + min_dist = offset - prev_offset; + } /* if */ + prev_offset = offset; + + min_vma = MIN (vma, min_vma); + max_vma = MAX (vma, max_vma); + } /* for */ + + DBG (AOUTDEBUG, printf ("[core_create_line_syms] min_dist=%lx\n", min_dist)); + + /* 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: */ + + prev = 0; + for (offset = 0; offset < core_text_sect->_raw_size; offset += min_dist) + { + 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)) { - discard_underscores = 0; - } /* if */ + continue; + } /* if */ + + /* make name pointer a malloc'ed string: */ + ltab.limit->name = strdup (ltab.limit->name); + ltab.limit->file = source_file_lookup_path (filename); + + ltab.limit->addr = core_text_sect->vma + offset; + prev = ltab.limit; + + /* + * 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; + } /* if */ - DBG(AOUTDEBUG, printf("[core_create_line_syms] %d %s 0x%lx\n", + DBG (AOUTDEBUG, printf ("[core_create_line_syms] %d %s 0x%lx\n", ltab.len, ltab.limit->name, ltab.limit->addr)); - ++ltab.limit; - } /* for */ + ++ltab.limit; + } /* for */ + + /* update sentinels: */ + + sentinel = sym_lookup (&symtab, 0); + if (strcmp (sentinel->name, "") == 0 + && min_vma <= sentinel->end_addr) + { + sentinel->end_addr = min_vma - 1; + } /* if */ + + sentinel = sym_lookup (&symtab, ~0); + if (strcmp (sentinel->name, "") == 0 && max_vma >= sentinel->addr) + { + sentinel->addr = max_vma + 1; + } /* if */ - /* update sentinels: */ + /* copy in function symbols: */ + memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym)); + ltab.limit += symtab.len; - sentinel = sym_lookup(&symtab, 0); - if (strcmp(sentinel->name, "") == 0 - && min_vma <= sentinel->end_addr) + if (ltab.limit - ltab.base != ltab.len) { - sentinel->end_addr = min_vma - 1; - } /* if */ - - sentinel = sym_lookup(&symtab, ~0); - if (strcmp(sentinel->name, "") == 0 && max_vma >= sentinel->addr) { - sentinel->addr = max_vma + 1; - } /* if */ - - /* copy in function symbols: */ - memcpy(ltab.limit, symtab.base, symtab.len * sizeof(Sym)); - ltab.limit += symtab.len; - - if (ltab.limit - ltab.base != ltab.len) { - fprintf(stderr, - "%s: somebody miscounted: ltab.len=%ld instead of %d\n", - whoami, (long) (ltab.limit - ltab.base), ltab.len); - done(1); - } /* if */ - - /* finalize ltab and make it symbol table: */ - - symtab_finalize(<ab); - free(symtab.base); - symtab = ltab; - - /* now go through all core symbols and set is_static accordingly: */ - - for (i = 0; i < core_num_syms; ++i) { - if (core_sym_class(core_syms[i]) == 't') { - sym = sym_lookup(&symtab, core_syms[i]->value - + core_syms[i]->section->vma); - do { - sym++->is_static = TRUE; - } while (sym->file == sym[-1].file && - strcmp(sym->name, sym[-1].name) == 0); - } /* if */ - } /* for */ - -} /* core_create_line_syms */ - - /*** end of core.c ***/ + fprintf (stderr, + "%s: somebody miscounted: ltab.len=%ld instead of %d\n", + whoami, (long) (ltab.limit - ltab.base), ltab.len); + done (1); + } /* if */ + + /* finalize ltab and make it symbol table: */ + + symtab_finalize (<ab); + free (symtab.base); + symtab = ltab; + + /* now go through all core symbols and set is_static accordingly: */ + + for (i = 0; i < core_num_syms; ++i) + { + if (core_sym_class (core_syms[i]) == 't') + { + sym = sym_lookup (&symtab, core_syms[i]->value + + core_syms[i]->section->vma); + do + { + sym++->is_static = TRUE; + } + while (sym->file == sym[-1].file && + strcmp (sym->name, sym[-1].name) == 0); + } /* if */ + } /* for */ + +} /* core_create_line_syms */ + +/*** end of core.c ***/ diff --git a/gprof/core.h b/gprof/core.h index c74268d..81c79ad 100644 --- a/gprof/core.h +++ b/gprof/core.h @@ -3,15 +3,15 @@ #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 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 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 *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)); #endif /* core_h */ diff --git a/gprof/dummy.c b/gprof/dummy.c index a78caec..7fa2fd6 100644 --- a/gprof/dummy.c +++ b/gprof/dummy.c @@ -8,11 +8,11 @@ */ void -DEFUN(find_call, (parent, p_lowpc, p_highpc), - Sym *parent AND bfd_vma p_lowpc AND bfd_vma p_highpc) +DEFUN (find_call, (parent, p_lowpc, p_highpc), + Sym * parent AND bfd_vma p_lowpc AND bfd_vma p_highpc) { - fprintf(stderr, "%s: -c supported on this machine architecture\n", - whoami); -} /* find_call */ + fprintf (stderr, "%s: -c supported on this machine architecture\n", + whoami); +} /* find_call */ - /*** end of dummy.c ***/ +/*** end of dummy.c ***/ diff --git a/gprof/dummy.h b/gprof/dummy.h index f8a6bb6..4c37c15 100644 --- a/gprof/dummy.h +++ b/gprof/dummy.h @@ -46,7 +46,10 @@ #define OFFSET_TO_CODE 0 #define UNITS_TO_CODE (OFFSET_TO_CODE / sizeof(UNIT)) -enum opermodes { dummy }; +enum opermodes + { + dummy + }; typedef enum opermodes operandenum; #endif /* dummy_h */ diff --git a/gprof/gmon.h b/gprof/gmon.h index 0e6c93f..74cd4b8 100644 --- a/gprof/gmon.h +++ b/gprof/gmon.h @@ -35,9 +35,10 @@ #ifndef gmon_h #define gmon_h -struct raw_phdr { - char low_pc[sizeof(bfd_vma)]; /* base pc address of sample buffer */ - char high_pc[sizeof(bfd_vma)]; /* max pc address of sampled buffer */ +struct raw_phdr + { + char low_pc[sizeof (bfd_vma)]; /* base pc address of sample buffer */ + char high_pc[sizeof (bfd_vma)]; /* max pc address of sampled buffer */ char ncnt[4]; /* size of sample buffer (plus this header) */ #ifdef __osf__ /* @@ -46,7 +47,7 @@ struct raw_phdr { */ char pad[4]; #endif -}; + }; /* * Histogram counters are unsigned shorts: @@ -65,17 +66,17 @@ struct raw_phdr { * Given MIN_SUBR_SEPARATION bytes of separation the value of * HASHFRACTION is calculated as: * - * HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1); + * HASHFRACTION = MIN_SUBR_SEPARATION / (2 * sizeof(short) - 1); * * For the VAX, the shortest two call sequence is: * - * calls $0,(r0) - * calls $0,(r0) + * calls $0,(r0) + * calls $0,(r0) * * which is separated by only three bytes, thus HASHFRACTION is * calculated as: * - * HASHFRACTION = 3 / (2 * 2 - 1) = 1 + * HASHFRACTION = 3 / (2 * 2 - 1) = 1 * * Note that the division above rounds down, thus if MIN_SUBR_FRACTION * is less than three, this algorithm will not work! @@ -88,11 +89,12 @@ struct raw_phdr { #define ARCDENSITY 2 #define MINARCS 50 -struct tostruct { - char *selfpc; - int count; - unsigned short link; -}; +struct tostruct + { + char *selfpc; + int count; + unsigned short link; + }; /* * A raw arc, with pointers to the calling site and the called site @@ -100,11 +102,12 @@ struct tostruct { * as to get a packed representation (otherwise, different compilers * might introduce different padding): */ -struct raw_arc { - char from_pc[sizeof(bfd_vma)]; - char self_pc[sizeof(bfd_vma)]; - char count[sizeof(long)]; -}; +struct raw_arc + { + char from_pc[sizeof (bfd_vma)]; + char self_pc[sizeof (bfd_vma)]; + char count[sizeof (long)]; + }; /* * General rounding functions: diff --git a/gprof/gmon_io.c b/gprof/gmon_io.c index 45d1708..cec1973 100644 --- a/gprof/gmon_io.c +++ b/gprof/gmon_io.c @@ -8,7 +8,7 @@ #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" @@ -21,334 +21,378 @@ int gmon_file_version = 0; /* 0 == old (non-versioned) file format */ * This probably ought to be in libbfd. */ bfd_vma -DEFUN(get_vma, (abfd, addr), bfd *abfd AND bfd_byte *addr) +DEFUN (get_vma, (abfd, addr), bfd * abfd AND bfd_byte * addr) { - switch (sizeof(bfd_vma)) { - case 4: return bfd_get_32(abfd, addr); - case 8: return bfd_get_64(abfd, addr); - default: - fprintf(stderr, "%s: bfd_vma has unexpected size of %ld bytes\n", - whoami, (long) sizeof(bfd_vma)); - done(1); - } /* switch */ -} /* get_vma */ + switch (sizeof (bfd_vma)) + { + case 4: + return bfd_get_32 (abfd, addr); + case 8: + return bfd_get_64 (abfd, addr); + default: + fprintf (stderr, "%s: bfd_vma has unexpected size of %ld bytes\n", + whoami, (long) sizeof (bfd_vma)); + done (1); + } /* switch */ +} /* get_vma */ /* * This probably ought to be in libbfd. */ void -DEFUN(put_vma, (abfd, val, addr), bfd *abfd AND bfd_vma val AND bfd_byte *addr) +DEFUN (put_vma, (abfd, val, addr), bfd * abfd AND bfd_vma val AND bfd_byte * addr) { - switch (sizeof(bfd_vma)) { - case 4: bfd_put_32(abfd, val, addr); break; - case 8: bfd_put_64(abfd, val, addr); break; - default: - fprintf(stderr, "%s: bfd_vma has unexpected size of %ld bytes\n", - whoami, (long) sizeof(bfd_vma)); - done(1); - } /* switch */ -} /* put_vma */ + switch (sizeof (bfd_vma)) + { + case 4: + bfd_put_32 (abfd, val, addr); + break; + case 8: + bfd_put_64 (abfd, val, addr); + break; + default: + fprintf (stderr, "%s: bfd_vma has unexpected size of %ld bytes\n", + whoami, (long) sizeof (bfd_vma)); + done (1); + } /* switch */ +} /* put_vma */ void -DEFUN(gmon_out_read, (filename), const char *filename) +DEFUN (gmon_out_read, (filename), const char *filename) { - FILE *ifp; - struct gmon_hdr ghdr; - unsigned char tag; - int nhist = 0, narcs = 0, nbbs = 0; - - /* open gmon.out file: */ - - if (strcmp(filename, "-") == 0) { - ifp = stdin; - } else { - ifp = fopen(filename, FOPEN_RB); - if (!ifp) { - perror(filename); - done(1); - } /* if */ - } /* if */ - if (fread(&ghdr, sizeof(struct gmon_hdr), 1, ifp) != 1) { - fprintf(stderr, "%s: file too short to be a gmon file\n", - filename); - done(1); - } /* if */ - - if ((file_format == FF_MAGIC) || - (file_format == FF_AUTO && !strncmp(&ghdr.cookie[0], GMON_MAGIC, 4))) + FILE *ifp; + struct gmon_hdr ghdr; + unsigned char tag; + int nhist = 0, narcs = 0, nbbs = 0; + + /* open gmon.out file: */ + + if (strcmp (filename, "-") == 0) + { + ifp = stdin; + } + else + { + ifp = fopen (filename, FOPEN_RB); + if (!ifp) + { + perror (filename); + done (1); + } /* if */ + } /* if */ + if (fread (&ghdr, sizeof (struct gmon_hdr), 1, ifp) != 1) + { + fprintf (stderr, "%s: file too short to be a gmon file\n", + filename); + done (1); + } /* if */ + + if ((file_format == FF_MAGIC) || + (file_format == FF_AUTO && !strncmp (&ghdr.cookie[0], GMON_MAGIC, 4))) + { + if (file_format == FF_MAGIC && strncmp (&ghdr.cookie[0], GMON_MAGIC, 4)) + { + fprintf (stderr, "%s: file `%s' has bad magic cookie\n", + whoami, filename); + done (1); + } /* if */ + + /* 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, + "%s: file `%s' has unsupported version %d\n", + whoami, filename, gmon_file_version); + done (1); + } /* if */ + + /* read in all the records: */ + while (fread (&tag, sizeof (tag), 1, ifp) == 1) + { + switch (tag) + { + case GMON_TAG_TIME_HIST: + ++nhist; + gmon_input |= INPUT_HISTOGRAM; + hist_read_rec (ifp, filename); + break; + + case GMON_TAG_CG_ARC: + ++narcs; + gmon_input |= INPUT_CALL_GRAPH; + cg_read_rec (ifp, filename); + break; + + case GMON_TAG_BB_COUNT: + ++nbbs; + gmon_input |= INPUT_BB_COUNTS; + bb_read_rec (ifp, filename); + break; + + default: + fprintf (stderr, + "%s: %s: found bad tag %d (file corrupted?)\n", + whoami, filename, tag); + done (1); + } /* switch */ + } /* while */ + } + else if (file_format == FF_AUTO || file_format == FF_BSD) { - if (file_format == FF_MAGIC && strncmp(&ghdr.cookie[0], GMON_MAGIC, 4)) + struct hdr + { + bfd_vma low_pc; + bfd_vma high_pc; + int ncnt; + }; + int i, samp_bytes, count; + bfd_vma from_pc, self_pc; + struct raw_arc raw_arc; + struct raw_phdr raw; + static struct hdr h; + 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. + */ + 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?). + */ + if (fseek (ifp, 0, SEEK_SET) < 0) { - fprintf(stderr, "%s: file `%s' has bad magic cookie\n", - whoami, filename); - done(1); - } /* if */ - - /* 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, - "%s: file `%s' has unsupported version %d\n", - whoami, filename, gmon_file_version); - done(1); - } /* if */ - - /* read in all the records: */ - while (fread(&tag, sizeof(tag), 1, ifp) == 1) { - switch (tag) { - case GMON_TAG_TIME_HIST: - ++nhist; - gmon_input |= INPUT_HISTOGRAM; - hist_read_rec(ifp, filename); - break; - - case GMON_TAG_CG_ARC: - ++narcs; - gmon_input |= INPUT_CALL_GRAPH; - cg_read_rec(ifp, filename); - break; - - case GMON_TAG_BB_COUNT: - ++nbbs; - gmon_input |= INPUT_BB_COUNTS; - bb_read_rec(ifp, filename); - break; - - default: - fprintf(stderr, - "%s: %s: found bad tag %d (file corrupted?)\n", - whoami, filename, tag); - done(1); - } /* switch */ - } /* while */ - } else if (file_format == FF_AUTO || file_format == FF_BSD) { - struct hdr { - bfd_vma low_pc; - bfd_vma high_pc; - int ncnt; - }; - int i, samp_bytes, count; - bfd_vma from_pc, self_pc; - struct raw_arc raw_arc; - struct raw_phdr raw; - static struct hdr h; - 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. - */ - 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?). - */ - if (fseek(ifp, 0, SEEK_SET) < 0) { - perror(filename); - done(1); - } /* if */ - if (fread(&raw, 1, sizeof(struct raw_phdr), ifp) - != sizeof(struct raw_phdr)) + perror (filename); + done (1); + } /* if */ + if (fread (&raw, 1, sizeof (struct raw_phdr), ifp) + != sizeof (struct raw_phdr)) { - fprintf(stderr, "%s: file too short to be a gmon file\n", - filename); - done(1); - } /* if */ - 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]); - if (s_highpc && (tmp.low_pc != h.low_pc || - tmp.high_pc != h.high_pc || tmp.ncnt != h.ncnt)) + fprintf (stderr, "%s: file too short to be a gmon file\n", + filename); + done (1); + } /* if */ + 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]); + if (s_highpc && (tmp.low_pc != h.low_pc || + tmp.high_pc != h.high_pc || tmp.ncnt != h.ncnt)) { - fprintf(stderr, "%s: incompatible with first gmon file\n", - filename); - done(1); - } /* if */ - h = tmp; - s_lowpc = (bfd_vma) h.low_pc; - s_highpc = (bfd_vma) h.high_pc; - lowpc = (bfd_vma) h.low_pc / sizeof(UNIT); - highpc = (bfd_vma) h.high_pc / sizeof(UNIT); - samp_bytes = h.ncnt - sizeof(struct raw_phdr); - hist_num_bins = samp_bytes / sizeof (UNIT); - DBG(SAMPLEDEBUG, - printf("[gmon_out_read] lowpc 0x%lx highpc 0x%lx ncnt %d\n", + fprintf (stderr, "%s: incompatible with first gmon file\n", + filename); + done (1); + } /* if */ + h = tmp; + s_lowpc = (bfd_vma) h.low_pc; + s_highpc = (bfd_vma) h.high_pc; + lowpc = (bfd_vma) h.low_pc / sizeof (UNIT); + highpc = (bfd_vma) h.high_pc / sizeof (UNIT); + samp_bytes = h.ncnt - sizeof (struct raw_phdr); + hist_num_bins = samp_bytes / sizeof (UNIT); + DBG (SAMPLEDEBUG, + printf ("[gmon_out_read] lowpc 0x%lx highpc 0x%lx ncnt %d\n", h.low_pc, h.high_pc, h.ncnt); - printf("[gmon_out_read] s_lowpc 0x%lx s_highpc 0x%lx\n", + printf ("[gmon_out_read] s_lowpc 0x%lx s_highpc 0x%lx\n", s_lowpc, s_highpc); - printf("[gmon_out_read] lowpc 0x%lx highpc 0x%lx\n", + printf ("[gmon_out_read] lowpc 0x%lx highpc 0x%lx\n", lowpc, highpc); - printf("[gmon_out_read] samp_bytes %d hist_num_bins %d\n", + printf ("[gmon_out_read] samp_bytes %d hist_num_bins %d\n", samp_bytes, hist_num_bins)); - if (hist_num_bins) { - ++nhist; - } /* if */ - - 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])); - } /* if */ - - for (i = 0; i < hist_num_bins; ++i) { - if (fread(raw_bin_count, sizeof(raw_bin_count), 1, ifp) != 1) { - fprintf(stderr, - "%s: unexpected EOF after reading %d/%d bins\n", - whoami, --i, hist_num_bins); - done(1); - } /* if */ - hist_sample[i] += bfd_get_16(core_bfd, (bfd_byte*) raw_bin_count); - } /* for */ - - /* - * The rest of the file consists of a bunch of - * 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 %d\n", - from_pc, self_pc, count)); - /* add this arc: */ - cg_tally(from_pc, self_pc, count); - } /* while */ - fclose(ifp); - - if (hz == HZ_WRONG) { - /* - * How many ticks per second? If we can't tell, report - * time in ticks. - */ - hz = hertz(); - if (hz == HZ_WRONG) { - hz = 1; - fprintf(stderr, "time is in ticks, not seconds\n"); - } /* if */ - } /* if */ - } else { - fprintf(stderr, "%s: don't know how to deal with file format %d\n", - whoami, file_format); - done(1); - } /* if */ - - if (output_style & STYLE_GMON_INFO) { - printf("File `%s' (version %d) contains:\n", - filename, gmon_file_version); - printf("\t%d histogram record%s\n", - nhist, nhist == 1 ? "" : "s"); - printf("\t%d call-graph record%s\n", - narcs, narcs == 1 ? "" : "s"); - printf("\t%d basic-block count record%s\n", - nbbs, nbbs == 1 ? "" : "s"); - first_output = FALSE; - } /* if */ -} /* gmon_out_read */ + if (hist_num_bins) + { + ++nhist; + } /* if */ + + 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])); + } /* if */ + + for (i = 0; i < hist_num_bins; ++i) + { + if (fread (raw_bin_count, sizeof (raw_bin_count), 1, ifp) != 1) + { + fprintf (stderr, + "%s: unexpected EOF after reading %d/%d bins\n", + whoami, --i, hist_num_bins); + done (1); + } /* if */ + hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) raw_bin_count); + } /* for */ + + /* + * The rest of the file consists of a bunch of + * 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 %d\n", + from_pc, self_pc, count)); + /* add this arc: */ + cg_tally (from_pc, self_pc, count); + } /* while */ + fclose (ifp); + + if (hz == HZ_WRONG) + { + /* + * How many ticks per second? If we can't tell, report + * time in ticks. + */ + hz = hertz (); + if (hz == HZ_WRONG) + { + hz = 1; + fprintf (stderr, "time is in ticks, not seconds\n"); + } /* if */ + } /* if */ + } + else + { + fprintf (stderr, "%s: don't know how to deal with file format %d\n", + whoami, file_format); + done (1); + } /* if */ + + if (output_style & STYLE_GMON_INFO) + { + printf ("File `%s' (version %d) contains:\n", + filename, gmon_file_version); + printf ("\t%d histogram record%s\n", + nhist, nhist == 1 ? "" : "s"); + printf ("\t%d call-graph record%s\n", + narcs, narcs == 1 ? "" : "s"); + printf ("\t%d basic-block count record%s\n", + nbbs, nbbs == 1 ? "" : "s"); + first_output = FALSE; + } /* if */ +} /* gmon_out_read */ void -DEFUN(gmon_out_write, (filename), const char *filename) +DEFUN (gmon_out_write, (filename), const char *filename) { - FILE *ofp; - struct gmon_hdr ghdr; - - ofp = fopen(filename, FOPEN_WB); - if (!ofp) { - perror(filename); - done(1); - } /* if */ - - if (file_format == FF_AUTO || file_format == FF_MAGIC) { - /* 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); - } /* if */ - - /* write execution time histogram if we have one: */ - if (gmon_input & INPUT_HISTOGRAM) { - hist_write_hist(ofp, filename); - } /* if */ - - /* write call graph arcs if we have any: */ - if (gmon_input & INPUT_CALL_GRAPH) { - cg_write_arcs(ofp, filename); - } /* if */ - - /* write basic-block info if we have it: */ - if (gmon_input & INPUT_BB_COUNTS) { - bb_write_blocks(ofp, filename); - } /* if */ - } else if (file_format == FF_BSD) { - struct raw_arc raw_arc; - UNIT raw_bin_count; - bfd_vma lpc, hpc; - int i, ncnt; - Arc *arc; - Sym *sym; - - put_vma(core_bfd, s_lowpc, (bfd_byte*) &lpc); - put_vma(core_bfd, s_highpc, (bfd_byte*) &hpc); - bfd_put_32(core_bfd, - hist_num_bins * sizeof(UNIT) + sizeof(struct raw_phdr), - (bfd_byte*) &ncnt); - - /* write header: */ - if (fwrite(&lpc, sizeof(lpc), 1, ofp) != 1 - || fwrite(&hpc, sizeof(hpc), 1, ofp) != 1 - || fwrite(&ncnt, sizeof(ncnt), 1, ofp) != 1) + FILE *ofp; + struct gmon_hdr ghdr; + + ofp = fopen (filename, FOPEN_WB); + if (!ofp) + { + perror (filename); + done (1); + } /* if */ + + if (file_format == FF_AUTO || file_format == FF_MAGIC) + { + /* 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); + } /* if */ + + /* write execution time histogram if we have one: */ + if (gmon_input & INPUT_HISTOGRAM) + { + hist_write_hist (ofp, filename); + } /* if */ + + /* write call graph arcs if we have any: */ + if (gmon_input & INPUT_CALL_GRAPH) + { + cg_write_arcs (ofp, filename); + } /* if */ + + /* write basic-block info if we have it: */ + if (gmon_input & INPUT_BB_COUNTS) + { + bb_write_blocks (ofp, filename); + } /* if */ + } + else if (file_format == FF_BSD) + { + struct raw_arc raw_arc; + UNIT raw_bin_count; + bfd_vma lpc, hpc; + int i, ncnt; + Arc *arc; + Sym *sym; + + put_vma (core_bfd, s_lowpc, (bfd_byte *) & lpc); + put_vma (core_bfd, s_highpc, (bfd_byte *) & hpc); + bfd_put_32 (core_bfd, + hist_num_bins * sizeof (UNIT) + sizeof (struct raw_phdr), + (bfd_byte *) & ncnt); + + /* write header: */ + if (fwrite (&lpc, sizeof (lpc), 1, ofp) != 1 + || fwrite (&hpc, sizeof (hpc), 1, ofp) != 1 + || fwrite (&ncnt, sizeof (ncnt), 1, ofp) != 1) + { + perror (filename); + done (1); + } /* if */ + + /* dump the samples: */ + + for (i = 0; i < hist_num_bins; ++i) { - perror(filename); - done(1); - } /* if */ + bfd_put_16 (core_bfd, hist_sample[i], (bfd_byte *) & raw_bin_count[0]); + if (fwrite (&raw_bin_count[0], sizeof (raw_bin_count), 1, ofp) != 1) + { + perror (filename); + done (1); + } /* if */ + } /* for */ - /* dump the samples: */ + /* dump the normalized raw arc information: */ - for (i = 0; i < hist_num_bins; ++i) { - bfd_put_16(core_bfd, hist_sample[i], (bfd_byte*)&raw_bin_count[0]); - if (fwrite(&raw_bin_count[0], sizeof(raw_bin_count), 1, ofp) != 1) + for (sym = symtab.base; sym < symtab.limit; ++sym) + { + for (arc = sym->cg.children; arc; arc = arc->next_child) { - perror(filename); - done(1); - } /* if */ - } /* for */ - - /* dump the normalized raw arc information: */ - - 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(&raw_arc, sizeof(raw_arc), 1, ofp) != 1) { - perror(filename); - done(1); - } /* if */ - DBG(SAMPLEDEBUG, - printf("[dumpsum] frompc 0x%lx selfpc 0x%lx count %d\n", + 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 (&raw_arc, sizeof (raw_arc), 1, ofp) != 1) + { + perror (filename); + done (1); + } /* if */ + DBG (SAMPLEDEBUG, + printf ("[dumpsum] frompc 0x%lx selfpc 0x%lx count %d\n", arc->parent->addr, arc->child->addr, arc->count)); - } /* for */ - } /* for */ - fclose(ofp); - } else { - fprintf(stderr, "%s: don't know how to deal with file format %d\n", - whoami, file_format); - done(1); - } /* if */ -} /* gmon_out_write */ - - /*** gmon_out.c ***/ + } /* for */ + } /* for */ + fclose (ofp); + } + else + { + fprintf (stderr, "%s: don't know how to deal with file format %d\n", + whoami, file_format); + done (1); + } /* if */ +} /* gmon_out_write */ + +/*** gmon_out.c ***/ diff --git a/gprof/gmon_io.h b/gprof/gmon_io.h index 1709eeb..bf257a4 100644 --- a/gprof/gmon_io.h +++ b/gprof/gmon_io.h @@ -8,13 +8,13 @@ #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 */ +extern int gmon_input; /* what input did we see? */ +extern int gmon_file_version; /* file version are we dealing with */ -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 bfd_vma get_vma PARAMS ((bfd * abfd, bfd_byte * addr)); +extern void put_vma PARAMS ((bfd * abfd, bfd_vma val, bfd_byte * addr)); -extern void gmon_out_read PARAMS((const char *filename)); -extern void gmon_out_write PARAMS((const char *filename)); +extern void gmon_out_read PARAMS ((const char *filename)); +extern void gmon_out_write PARAMS ((const char *filename)); #endif /* gmon_io_h */ diff --git a/gprof/gmon_out.h b/gprof/gmon_out.h index c963869..d0d8ec5 100644 --- a/gprof/gmon_out.h +++ b/gprof/gmon_out.h @@ -17,30 +17,35 @@ /* * Raw header as it appears on file (without padding): */ -struct gmon_hdr { - char cookie[4]; - char version[4]; - char spare[3*4]; -}; +struct gmon_hdr + { + char cookie[4]; + char version[4]; + char spare[3 * 4]; + }; /* types of records in this file: */ -typedef enum { +typedef enum + { GMON_TAG_TIME_HIST, GMON_TAG_CG_ARC, GMON_TAG_BB_COUNT -} GMON_Record_Tag; + } +GMON_Record_Tag; -struct gmon_hist_hdr { - char low_pc[sizeof(bfd_vma)]; /* base pc address of sample buffer */ - char high_pc[sizeof(bfd_vma)]; /* 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_hist_hdr + { + char low_pc[sizeof (bfd_vma)]; /* base pc address of sample buffer */ + char high_pc[sizeof (bfd_vma)]; /* 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(bfd_vma)]; /* address within caller's body */ - char self_pc[sizeof(bfd_vma)]; /* address within callee's body */ - char count[4]; /* number of arc traversals */ -}; +struct gmon_cg_arc_record + { + char from_pc[sizeof (bfd_vma)]; /* address within caller's body */ + char self_pc[sizeof (bfd_vma)]; /* address within callee's body */ + char count[4]; /* number of arc traversals */ + }; #endif /* gmon_out_h */ diff --git a/gprof/gprof.c b/gprof/gprof.c index eb0e1c5..1e3226f 100644 --- a/gprof/gprof.c +++ b/gprof/gprof.c @@ -58,76 +58,77 @@ char copyright[] = "@(#) Copyright (c) 1983 Regents of the University of California.\n\ All rights reserved.\n"; -static char *gmon_name = GMONNAME; /* profile filename */ +static char *gmon_name = GMONNAME; /* profile filename */ -bfd *abfd; +bfd *abfd; /* * Functions that get excluded by default: */ -static char *default_excluded_list[] = { - "_gprof_mcount", "mcount", "_mcount", "__mcleanup", - "", "", - 0 +static char *default_excluded_list[] = +{ + "_gprof_mcount", "mcount", "_mcount", "__mcleanup", + "", "", + 0 }; static struct option long_options[] = { - {"line", no_argument, 0, 'l'}, - {"no-static", no_argument, 0, 'a'}, + {"line", no_argument, 0, 'l'}, + {"no-static", no_argument, 0, 'a'}, /* output styles: */ - {"annotated-source", optional_argument, 0, 'A'}, - {"no-annotated-source", optional_argument, 0, 'J'}, - {"flat-profile", optional_argument, 0, 'p'}, - {"no-flat-profile", optional_argument, 0, 'P'}, - {"graph", optional_argument, 0, 'q'}, - {"no-graph", optional_argument, 0, 'Q'}, - {"exec-counts", optional_argument, 0, 'C'}, - {"no-exec-counts", optional_argument, 0, 'Z'}, - {"file-info", no_argument, 0, 'i'}, - {"sum", no_argument, 0, 's'}, + {"annotated-source", optional_argument, 0, 'A'}, + {"no-annotated-source", optional_argument, 0, 'J'}, + {"flat-profile", optional_argument, 0, 'p'}, + {"no-flat-profile", optional_argument, 0, 'P'}, + {"graph", optional_argument, 0, 'q'}, + {"no-graph", optional_argument, 0, 'Q'}, + {"exec-counts", optional_argument, 0, 'C'}, + {"no-exec-counts", optional_argument, 0, 'Z'}, + {"file-info", no_argument, 0, 'i'}, + {"sum", no_argument, 0, 's'}, /* various options to affect output: */ - {"all-lines", no_argument, 0, 'x'}, - {"directory-path", required_argument, 0, 'I'}, - {"display-unused-functions", no_argument, 0, 'z'}, - {"min-count", required_argument, 0, 'm'}, - {"print-path", no_argument, 0, 'L'}, - {"separate-files", no_argument, 0, 'y'}, - {"static-call-graph", no_argument, 0, 'c'}, - {"table-length", required_argument, 0, 't'}, - {"time", required_argument, 0, 'n'}, - {"no-time", required_argument, 0, 'N'}, - {"width", required_argument, 0, 'w'}, + {"all-lines", no_argument, 0, 'x'}, + {"directory-path", required_argument, 0, 'I'}, + {"display-unused-functions", no_argument, 0, 'z'}, + {"min-count", required_argument, 0, 'm'}, + {"print-path", no_argument, 0, 'L'}, + {"separate-files", no_argument, 0, 'y'}, + {"static-call-graph", no_argument, 0, 'c'}, + {"table-length", required_argument, 0, 't'}, + {"time", required_argument, 0, 'n'}, + {"no-time", required_argument, 0, 'N'}, + {"width", required_argument, 0, 'w'}, /* * These are for backwards-compatibility only. Their functionality * is provided by the output style options already: */ - {"", required_argument, 0, 'e'}, - {"", required_argument, 0, 'E'}, - {"", required_argument, 0, 'f'}, - {"", required_argument, 0, 'F'}, - {"", required_argument, 0, 'k'}, + {"", required_argument, 0, 'e'}, + {"", required_argument, 0, 'E'}, + {"", required_argument, 0, 'f'}, + {"", required_argument, 0, 'F'}, + {"", required_argument, 0, 'k'}, /* miscellaneous: */ - {"brief", no_argument, 0, 'b'}, - {"debug", optional_argument, 0, 'd'}, - {"help", no_argument, 0, 'h'}, - {"file-format", required_argument, 0, 'O'}, - {"traditional", no_argument, 0, 'T'}, - {"version", no_argument, 0, 'v'}, - {0, no_argument, 0, 0} + {"brief", no_argument, 0, 'b'}, + {"debug", optional_argument, 0, 'd'}, + {"help", no_argument, 0, 'h'}, + {"file-format", required_argument, 0, 'O'}, + {"traditional", no_argument, 0, 'T'}, + {"version", no_argument, 0, 'v'}, + {0, no_argument, 0, 0} }; static void -DEFUN(usage, (stream, status), FILE *stream AND int status) +DEFUN (usage, (stream, status), FILE * stream AND int status) { - fprintf(stream, "\ + fprintf (stream, "\ Usage: %s [-[abchilLsTvwxyz]] [-[ACeEfFJnNOpPqQZ][name]] [-I dirs]\n\ [-d[num]] [-k from/to] [-m min-count] [-t table-length]\n\ [--[no-]annotated-source[=name]] [--[no-]exec-counts[=name]]\n\ @@ -139,337 +140,448 @@ Usage: %s [-[abchilLsTvwxyz]] [-[ACeEfFJnNOpPqQZ][name]] [-I dirs]\n\ [--static-call-graph] [--sum] [--table-length=len] [--traditional]\n\ [--version] [--width=n]\n\ [image-file] [profile-file...]\n", - whoami); - done(status); -} /* usage */ + whoami); + done (status); +} /* usage */ int -DEFUN(main, (argc, argv), int argc AND char **argv) +DEFUN (main, (argc, argv), int argc AND char **argv) { - char **sp, *str; - Sym **cg = 0; - int ch, user_specified = 0; + char **sp, *str; + Sym **cg = 0; + int ch, user_specified = 0; - whoami = argv[0]; - xmalloc_set_program_name(whoami); + whoami = argv[0]; + xmalloc_set_program_name (whoami); - while ((ch = getopt_long(argc, argv, - "aA::bBcCd::e:E:f:F:hiI:J::k:lLm:n::N::O:p::P::q::Q::st:Tvw:xyzZ::", - long_options, 0)) - != EOF) + while ((ch = getopt_long (argc, argv, + "aA::bBcCd::e:E:f:F:hiI:J::k:lLm:n::N::O:p::P::q::Q::st:Tvw:xyzZ::", + long_options, 0)) + != EOF) { - switch (ch) { - case 'a': ignore_static_funcs = TRUE; break; - case 'A': - if (optarg) { - sym_id_add(optarg, INCL_ANNO); - } /* if */ - output_style |= STYLE_ANNOTATED_SOURCE; - user_specified |= STYLE_ANNOTATED_SOURCE; - break; - case 'b': print_descriptions = FALSE; break; - case 'B': - output_style |= STYLE_CALL_GRAPH; - user_specified |= STYLE_CALL_GRAPH; - break; - case 'c': ignore_direct_calls = TRUE; break; - case 'C': - if (optarg) { - sym_id_add(optarg, INCL_EXEC); - } /* if */ - output_style |= STYLE_EXEC_COUNTS; - user_specified |= STYLE_EXEC_COUNTS; - break; - case 'd': - if (optarg) { - debug_level |= atoi(optarg); - debug_level |= ANYDEBUG; - } else { - debug_level = ~0; - } /* if */ - DBG(ANYDEBUG, printf("[main] debug-level=0x%x\n", debug_level)); + switch (ch) + { + case 'a': + ignore_static_funcs = TRUE; + break; + case 'A': + if (optarg) + { + sym_id_add (optarg, INCL_ANNO); + } /* if */ + output_style |= STYLE_ANNOTATED_SOURCE; + user_specified |= STYLE_ANNOTATED_SOURCE; + break; + case 'b': + print_descriptions = FALSE; + break; + case 'B': + output_style |= STYLE_CALL_GRAPH; + user_specified |= STYLE_CALL_GRAPH; + break; + case 'c': + ignore_direct_calls = TRUE; + break; + case 'C': + if (optarg) + { + sym_id_add (optarg, INCL_EXEC); + } /* if */ + output_style |= STYLE_EXEC_COUNTS; + user_specified |= STYLE_EXEC_COUNTS; + break; + case 'd': + if (optarg) + { + debug_level |= atoi (optarg); + debug_level |= ANYDEBUG; + } + else + { + debug_level = ~0; + } /* if */ + DBG (ANYDEBUG, printf ("[main] debug-level=0x%x\n", debug_level)); #ifndef DEBUG - printf("%s: debugging not supported; -d ignored\n", whoami); -#endif DEBUG - break; - case 'E': sym_id_add(optarg, EXCL_TIME); - case 'e': sym_id_add(optarg, EXCL_GRAPH); break; - case 'F': sym_id_add(optarg, INCL_TIME); - case 'f': sym_id_add(optarg, INCL_GRAPH); break; - case 'g': sym_id_add(optarg, EXCL_FLAT); break; - case 'G': sym_id_add(optarg, INCL_FLAT); break; - case 'h': usage(stdout, 0); - case 'i': - output_style |= STYLE_GMON_INFO; - user_specified |= STYLE_GMON_INFO; - break; - case 'I': search_list_append(&src_search_list, optarg); break; - case 'J': - if (optarg) { - sym_id_add(optarg, EXCL_ANNO); - output_style |= STYLE_ANNOTATED_SOURCE; - } else { - output_style &= ~STYLE_ANNOTATED_SOURCE; - } /* if */ - user_specified |= STYLE_ANNOTATED_SOURCE; - break; - case 'k': sym_id_add(optarg, EXCL_ARCS); break; - case 'l': line_granularity = TRUE; break; - case 'L': print_path = TRUE; break; - case 'm': bb_min_calls = atoi(optarg); break; - case 'n': sym_id_add(optarg, INCL_TIME); break; - case 'N': sym_id_add(optarg, EXCL_TIME); break; - case 'O': - switch (optarg[0]) { - case 'a': file_format = FF_AUTO; break; - case 'm': file_format = FF_MAGIC; break; - case 'b': file_format = FF_BSD; break; - case 'p': file_format = FF_PROF; break; - default: - fprintf(stderr, "%s: unknown file format %s\n", - optarg, whoami); - done(1); - } /* switch */ - break; - case 'p': - if (optarg) { - sym_id_add(optarg, INCL_FLAT); - } /* if */ - output_style |= STYLE_FLAT_PROFILE; - user_specified |= STYLE_FLAT_PROFILE; - break; - case 'P': - if (optarg) { - sym_id_add(optarg, EXCL_FLAT); - output_style |= STYLE_FLAT_PROFILE; - } else { - output_style &= ~STYLE_FLAT_PROFILE; - } /* if */ - user_specified |= STYLE_FLAT_PROFILE; - break; - case 'q': - if (optarg) { - if (strchr(optarg, '/')) { - sym_id_add(optarg, INCL_ARCS); - } else { - sym_id_add(optarg, INCL_GRAPH); - } /* if */ - } /* if */ - output_style |= STYLE_CALL_GRAPH; - user_specified |= STYLE_CALL_GRAPH; - break; - case 'Q': - if (optarg) { - if (strchr(optarg, '/')) { - sym_id_add(optarg, EXCL_ARCS); - } else { - sym_id_add(optarg, EXCL_GRAPH); - } /* if */ - output_style |= STYLE_CALL_GRAPH; - } else { - output_style &= ~STYLE_CALL_GRAPH; - } /* if */ - user_specified |= STYLE_CALL_GRAPH; - break; - case 's': - output_style |= STYLE_SUMMARY_FILE; - user_specified |= STYLE_SUMMARY_FILE; - break; - case 't': - bb_table_length = atoi(optarg); - if (bb_table_length < 0) { - bb_table_length = 0; - } /* if */ - break; - case 'T': bsd_style_output = TRUE; break; - case 'v': printf ("%s version %s\n", whoami, VERSION); done(0); - case 'w': - output_width = atoi(optarg); - if (output_width < 1) { - output_width = 1; - } /* if */ - break; - case 'x': bb_annotate_all_lines = TRUE; break; - case 'y': create_annotation_files = TRUE; break; - case 'z': ignore_zeros = FALSE; break; - case 'Z': - if (optarg) { - sym_id_add(optarg, EXCL_EXEC); - output_style |= STYLE_EXEC_COUNTS; - } else { - output_style &= ~STYLE_EXEC_COUNTS; - } /* if */ - user_specified |= STYLE_ANNOTATED_SOURCE; - break; - default: usage(stderr, 1); - } /* switch */ - } /* while */ - - /* append value of GPROF_PATH to source search list if set: */ - str = getenv("GPROF_PATH"); - if (str) { - search_list_append(&src_search_list, str); - } /* if */ - - if (optind < argc) { - a_out_name = argv[optind++]; - } /* if */ - if (optind < argc) { - gmon_name = argv[optind++]; - } /* if */ + printf ("%s: debugging not supported; -d ignored\n", whoami); +#endif /* DEBUG */ + break; + case 'E': + sym_id_add (optarg, EXCL_TIME); + case 'e': + sym_id_add (optarg, EXCL_GRAPH); + break; + case 'F': + sym_id_add (optarg, INCL_TIME); + case 'f': + sym_id_add (optarg, INCL_GRAPH); + break; + case 'g': + sym_id_add (optarg, EXCL_FLAT); + break; + case 'G': + sym_id_add (optarg, INCL_FLAT); + break; + case 'h': + usage (stdout, 0); + case 'i': + output_style |= STYLE_GMON_INFO; + user_specified |= STYLE_GMON_INFO; + break; + case 'I': + search_list_append (&src_search_list, optarg); + break; + case 'J': + if (optarg) + { + sym_id_add (optarg, EXCL_ANNO); + output_style |= STYLE_ANNOTATED_SOURCE; + } + else + { + output_style &= ~STYLE_ANNOTATED_SOURCE; + } /* if */ + user_specified |= STYLE_ANNOTATED_SOURCE; + break; + case 'k': + sym_id_add (optarg, EXCL_ARCS); + break; + case 'l': + line_granularity = TRUE; + break; + case 'L': + print_path = TRUE; + break; + case 'm': + bb_min_calls = atoi (optarg); + break; + case 'n': + sym_id_add (optarg, INCL_TIME); + break; + case 'N': + sym_id_add (optarg, EXCL_TIME); + break; + case 'O': + switch (optarg[0]) + { + case 'a': + file_format = FF_AUTO; + break; + case 'm': + file_format = FF_MAGIC; + break; + case 'b': + file_format = FF_BSD; + break; + case 'p': + file_format = FF_PROF; + break; + default: + fprintf (stderr, "%s: unknown file format %s\n", + optarg, whoami); + done (1); + } /* switch */ + break; + case 'p': + if (optarg) + { + sym_id_add (optarg, INCL_FLAT); + } /* if */ + output_style |= STYLE_FLAT_PROFILE; + user_specified |= STYLE_FLAT_PROFILE; + break; + case 'P': + if (optarg) + { + sym_id_add (optarg, EXCL_FLAT); + output_style |= STYLE_FLAT_PROFILE; + } + else + { + output_style &= ~STYLE_FLAT_PROFILE; + } /* if */ + user_specified |= STYLE_FLAT_PROFILE; + break; + case 'q': + if (optarg) + { + if (strchr (optarg, '/')) + { + sym_id_add (optarg, INCL_ARCS); + } + else + { + sym_id_add (optarg, INCL_GRAPH); + } /* if */ + } /* if */ + output_style |= STYLE_CALL_GRAPH; + user_specified |= STYLE_CALL_GRAPH; + break; + case 'Q': + if (optarg) + { + if (strchr (optarg, '/')) + { + sym_id_add (optarg, EXCL_ARCS); + } + else + { + sym_id_add (optarg, EXCL_GRAPH); + } /* if */ + output_style |= STYLE_CALL_GRAPH; + } + else + { + output_style &= ~STYLE_CALL_GRAPH; + } /* if */ + user_specified |= STYLE_CALL_GRAPH; + break; + case 's': + output_style |= STYLE_SUMMARY_FILE; + user_specified |= STYLE_SUMMARY_FILE; + break; + case 't': + bb_table_length = atoi (optarg); + if (bb_table_length < 0) + { + bb_table_length = 0; + } /* if */ + break; + case 'T': + bsd_style_output = TRUE; + break; + case 'v': + printf ("%s version %s\n", whoami, VERSION); + done (0); + case 'w': + output_width = atoi (optarg); + if (output_width < 1) + { + output_width = 1; + } /* if */ + break; + case 'x': + bb_annotate_all_lines = TRUE; + break; + case 'y': + create_annotation_files = TRUE; + break; + case 'z': + ignore_zeros = FALSE; + break; + case 'Z': + if (optarg) + { + sym_id_add (optarg, EXCL_EXEC); + output_style |= STYLE_EXEC_COUNTS; + } + else + { + output_style &= ~STYLE_EXEC_COUNTS; + } /* if */ + user_specified |= STYLE_ANNOTATED_SOURCE; + break; + default: + usage (stderr, 1); + } /* switch */ + } /* while */ + + /* append value of GPROF_PATH to source search list if set: */ + str = getenv ("GPROF_PATH"); + if (str) + { + search_list_append (&src_search_list, str); + } /* if */ - /* - * Turn off default functions: - */ - for (sp = &default_excluded_list[0]; *sp; sp++) { - sym_id_add(*sp, EXCL_TIME); - sym_id_add(*sp, EXCL_GRAPH); + if (optind < argc) + { + a_out_name = argv[optind++]; + } /* if */ + if (optind < argc) + { + gmon_name = argv[optind++]; + } /* if */ + + /* + * Turn off default functions: + */ + for (sp = &default_excluded_list[0]; *sp; sp++) + { + sym_id_add (*sp, EXCL_TIME); + sym_id_add (*sp, EXCL_GRAPH); #ifdef __osf__ - sym_id_add(*sp, EXCL_FLAT); + sym_id_add (*sp, EXCL_FLAT); #endif - } /* for */ - - /* - * For line-by-line profiling, also want to keep those - * functions off the flat profile: - */ - if (line_granularity) { - for (sp = &default_excluded_list[0]; *sp; sp++) { - sym_id_add(*sp, EXCL_FLAT); - } /* for */ - } /* if */ + } /* for */ - /* - * Read symbol table from core file: - */ - core_init(a_out_name); - - /* - * If we should ignore direct function calls, we need to load - * to core's text-space: - */ - if (ignore_direct_calls) { - core_get_text_space(core_bfd); - } /* if */ + /* + * For line-by-line profiling, also want to keep those + * functions off the flat profile: + */ + if (line_granularity) + { + for (sp = &default_excluded_list[0]; *sp; sp++) + { + sym_id_add (*sp, EXCL_FLAT); + } /* for */ + } /* if */ + + /* + * Read symbol table from core file: + */ + core_init (a_out_name); + + /* + * If we should ignore direct function calls, we need to load + * to core's text-space: + */ + if (ignore_direct_calls) + { + core_get_text_space (core_bfd); + } /* if */ - /* - * Create symbols from core image: - */ - if (line_granularity) { - core_create_line_syms(core_bfd); - } else { - core_create_function_syms(core_bfd); - } /* if */ + /* + * Create symbols from core image: + */ + if (line_granularity) + { + core_create_line_syms (core_bfd); + } + else + { + core_create_function_syms (core_bfd); + } /* if */ - /* - * Translate sym specs into syms: - */ - sym_id_parse(); + /* + * Translate sym specs into syms: + */ + sym_id_parse (); - if (file_format == FF_PROF) { + if (file_format == FF_PROF) + { #ifdef PROF_SUPPORT_IMPLEMENTED - /* - * Get information about mon.out file(s): - */ - do { - mon_out_read(gmon_name); - if (optind < argc) { - gmon_name = argv[optind]; - } /* if */ - } while (optind++ < argc); + /* + * Get information about mon.out file(s): + */ + do + { + mon_out_read (gmon_name); + if (optind < argc) + { + gmon_name = argv[optind]; + } /* if */ + } + while (optind++ < argc); #else - fprintf(stderr, - "%s: sorry, file format `prof' is not yet supported\n", - whoami); - done(1); + fprintf (stderr, + "%s: sorry, file format `prof' is not yet supported\n", + whoami); + done (1); #endif - } else { - /* - * Get information about gmon.out file(s): - */ - do { - gmon_out_read(gmon_name); - if (optind < argc) { - gmon_name = argv[optind]; - } /* if */ - } while (optind++ < argc); - } /* if */ + } + else + { + /* + * Get information about gmon.out file(s): + */ + do + { + gmon_out_read (gmon_name); + if (optind < argc) + { + gmon_name = argv[optind]; + } /* if */ + } + while (optind++ < argc); + } /* if */ + + /* + * If user did not specify output style, try to guess something + * reasonable: + */ + if (output_style == 0) + { + if (gmon_input & (INPUT_HISTOGRAM | INPUT_CALL_GRAPH)) + { + output_style = STYLE_FLAT_PROFILE | STYLE_CALL_GRAPH; + } + else + { + output_style = STYLE_EXEC_COUNTS; + } /* if */ + output_style &= ~user_specified; + } /* if */ + + /* + * Dump a gmon.sum file if requested (before any other processing!): + */ + if (output_style & STYLE_SUMMARY_FILE) + { + gmon_out_write (GMONSUM); + } /* if */ - /* - * If user did not specify output style, try to guess something - * reasonable: - */ - if (output_style == 0) { - if (gmon_input & (INPUT_HISTOGRAM | INPUT_CALL_GRAPH)) { - output_style = STYLE_FLAT_PROFILE | STYLE_CALL_GRAPH; - } else { - output_style = STYLE_EXEC_COUNTS; - } /* if */ - output_style &= ~user_specified; - } /* if */ + if (gmon_input & INPUT_HISTOGRAM) + { + hist_assign_samples (); + } /* if */ - /* - * Dump a gmon.sum file if requested (before any other processing!): - */ - if (output_style & STYLE_SUMMARY_FILE) { - gmon_out_write(GMONSUM); - } /* if */ + if (gmon_input & INPUT_CALL_GRAPH) + { + cg = cg_assemble (); + } /* if */ + + /* do some simple sanity checks: */ + + if ((output_style & STYLE_FLAT_PROFILE) + && !(gmon_input & INPUT_HISTOGRAM)) + { + fprintf (stderr, "%s: gmon.out file is missing histogram\n", whoami); + done (1); + } /* if */ - if (gmon_input & INPUT_HISTOGRAM) { - hist_assign_samples(); - } /* if */ + if ((output_style & STYLE_CALL_GRAPH) && !(gmon_input & INPUT_CALL_GRAPH)) + { + fprintf (stderr, + "%s: gmon.out file is missing call-graph data\n", whoami); + done (1); + } /* if */ - if (gmon_input & INPUT_CALL_GRAPH) { - cg = cg_assemble(); - } /* if */ + /* output whatever user whishes to see: */ - /* do some simple sanity checks: */ + if (cg && (output_style & STYLE_CALL_GRAPH) && bsd_style_output) + { + cg_print (cg); /* print the dynamic profile */ + } /* if */ - if ((output_style & STYLE_FLAT_PROFILE) - && !(gmon_input & INPUT_HISTOGRAM)) + if (output_style & STYLE_FLAT_PROFILE) + { + hist_print (); /* print the flat profile */ + } /* if */ + + if (cg && (output_style & STYLE_CALL_GRAPH)) + { + if (!bsd_style_output) + { + cg_print (cg); /* print the dynamic profile */ + } /* if */ + cg_print_index (); + } /* if */ + + if (output_style & STYLE_EXEC_COUNTS) { - fprintf(stderr, "%s: gmon.out file is missing histogram\n", whoami); - done(1); - } /* if */ + print_exec_counts (); + } /* if */ - if ((output_style & STYLE_CALL_GRAPH) && !(gmon_input & INPUT_CALL_GRAPH)) + if (output_style & STYLE_ANNOTATED_SOURCE) { - fprintf(stderr, - "%s: gmon.out file is missing call-graph data\n", whoami); - done(1); - } /* if */ - - /* output whatever user whishes to see: */ - - if (cg && (output_style & STYLE_CALL_GRAPH) && bsd_style_output) { - cg_print(cg); /* print the dynamic profile */ - } /* if */ - - if (output_style & STYLE_FLAT_PROFILE) { - hist_print(); /* print the flat profile */ - } /* if */ - - if (cg && (output_style & STYLE_CALL_GRAPH)) { - if (!bsd_style_output) { - cg_print(cg); /* print the dynamic profile */ - } /* if */ - cg_print_index(); - } /* if */ - - if (output_style & STYLE_EXEC_COUNTS) { - print_exec_counts(); - } /* if */ - - if (output_style & STYLE_ANNOTATED_SOURCE) { - print_annotated_source(); - } /* if */ - return 0; + print_annotated_source (); + } /* if */ + return 0; } void done (status) int status; { - exit(status); + exit (status); } diff --git a/gprof/gprof.h b/gprof/gprof.h index c4d9da1..e4177a9 100644 --- a/gprof/gprof.h +++ b/gprof/gprof.h @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#)gprof.h 5.9 (Berkeley) 6/1/90 + * @(#)gprof.h 5.9 (Berkeley) 6/1/90 */ #ifndef gprof_h #define gprof_h @@ -25,41 +25,41 @@ #include "sysdep.h" #ifndef MIN -# define MIN(a,b) ((a) < (b) ? (a) : (b)) +#define MIN(a,b) ((a) < (b) ? (a) : (b)) #endif #ifndef MAX -# define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) #endif /* AIX defines hz as a macro. */ #undef hz #ifdef MACHINE_H -# include MACHINE_H +#include MACHINE_H #else -# if vax -# include "vax.h" -# endif -# if sun -# include "sun.h" -# endif -# if tahoe -# include "tahoe.h" -# endif +#if vax +#include "vax.h" +#endif +#if sun +#include "sun.h" +#endif +#if tahoe +#include "tahoe.h" +#endif #endif #ifndef FOPEN_RB -# define FOPEN_RB "r" +#define FOPEN_RB "r" #endif #ifndef FOPEN_WB -# define FOPEN_WB "w" +#define FOPEN_WB "w" #endif #ifndef PATH_MAX -# define PATH_MAX 1024 +#define PATH_MAX 1024 #endif -#define A_OUTNAME "a.out" /* default core filename */ +#define A_OUTNAME "a.out" /* default core filename */ #define GMONNAME "gmon.out" /* default profile filename */ #define GMONSUM "gmon.sum" /* profile summary filename */ @@ -80,56 +80,58 @@ #define STYLE_ANNOTATED_SOURCE (1<<4) #define STYLE_GMON_INFO (1<<5) -#define ANYDEBUG (1<<0) /* 1 */ -#define DFNDEBUG (1<<1) /* 2 */ -#define CYCLEDEBUG (1<<2) /* 4 */ -#define ARCDEBUG (1<<3) /* 8 */ -#define TALLYDEBUG (1<<4) /* 16 */ -#define TIMEDEBUG (1<<5) /* 32 */ -#define SAMPLEDEBUG (1<<6) /* 64 */ -#define AOUTDEBUG (1<<7) /* 128 */ -#define CALLDEBUG (1<<8) /* 256 */ -#define LOOKUPDEBUG (1<<9) /* 512 */ -#define PROPDEBUG (1<<10) /* 1024 */ -#define BBDEBUG (1<<11) /* 2048 */ -#define IDDEBUG (1<<12) /* 4096 */ -#define SRCDEBUG (1<<13) /* 8192 */ +#define ANYDEBUG (1<<0) /* 1 */ +#define DFNDEBUG (1<<1) /* 2 */ +#define CYCLEDEBUG (1<<2) /* 4 */ +#define ARCDEBUG (1<<3) /* 8 */ +#define TALLYDEBUG (1<<4) /* 16 */ +#define TIMEDEBUG (1<<5) /* 32 */ +#define SAMPLEDEBUG (1<<6) /* 64 */ +#define AOUTDEBUG (1<<7) /* 128 */ +#define CALLDEBUG (1<<8) /* 256 */ +#define LOOKUPDEBUG (1<<9) /* 512 */ +#define PROPDEBUG (1<<10) /* 1024 */ +#define BBDEBUG (1<<11) /* 2048 */ +#define IDDEBUG (1<<12) /* 4096 */ +#define SRCDEBUG (1<<13) /* 8192 */ #ifdef DEBUG -# define DBG(l,s) if (debug_level & (l)) {s;} +#define DBG(l,s) if (debug_level & (l)) {s;} #else -# define DBG(l,s) +#define DBG(l,s) #endif -typedef enum { +typedef enum + { FF_AUTO = 0, FF_MAGIC, FF_BSD, FF_PROF -} File_Format; + } +File_Format; typedef int bool; -typedef unsigned char UNIT[2]; /* unit of profiling */ +typedef unsigned char UNIT[2]; /* unit of profiling */ -extern const char *whoami; /* command-name, for error messages */ -extern const char *a_out_name; /* core filename */ -extern long hz; /* ticks per second */ +extern const char *whoami; /* command-name, for error messages */ +extern const char *a_out_name; /* core filename */ +extern long hz; /* ticks per second */ /* * Command-line options: */ -extern int debug_level; /* debug level */ +extern int debug_level; /* debug level */ extern int output_style; -extern int output_width; /* controls column width in index */ -extern bool bsd_style_output; /* as opposed to FSF style output */ +extern int output_width; /* controls column width in index */ +extern bool bsd_style_output; /* as opposed to FSF style output */ extern bool discard_underscores; /* discard leading underscores? */ extern bool ignore_direct_calls; /* don't count direct calls */ extern bool ignore_static_funcs; /* suppress static functions */ -extern bool ignore_zeros; /* ignore unused symbols/files */ -extern bool line_granularity; /* function or line granularity? */ -extern bool print_descriptions; /* output profile description */ -extern bool print_path; /* print path or just filename? */ -extern File_Format file_format; /* requested file format */ +extern bool ignore_zeros; /* ignore unused symbols/files */ +extern bool line_granularity; /* function or line granularity? */ +extern bool print_descriptions; /* output profile description */ +extern bool print_path; /* print path or just filename? */ +extern File_Format file_format; /* requested file format */ -extern bool first_output; /* no output so far? */ +extern bool first_output; /* no output so far? */ -extern void done PARAMS((int status)); +extern void done PARAMS ((int status)); #endif /* gprof_h */ diff --git a/gprof/hertz.c b/gprof/hertz.c index 979ad37..5391041 100644 --- a/gprof/hertz.c +++ b/gprof/hertz.c @@ -21,26 +21,27 @@ #ifdef __MSDOS__ -# define HERTZ 18 +#define HERTZ 18 #endif int -hertz() +hertz () { #ifdef HERTZ - return HERTZ; + return HERTZ; #else - struct itimerval tim; + struct itimerval tim; - tim.it_interval.tv_sec = 0; - tim.it_interval.tv_usec = 1; - tim.it_value.tv_sec = 0; - tim.it_value.tv_usec = 0; - setitimer(ITIMER_REAL, &tim, 0); - setitimer(ITIMER_REAL, 0, &tim); - if (tim.it_interval.tv_usec < 2) { - return HZ_WRONG; - } /* if */ - return 1000000 / tim.it_interval.tv_usec; + tim.it_interval.tv_sec = 0; + tim.it_interval.tv_usec = 1; + tim.it_value.tv_sec = 0; + tim.it_value.tv_usec = 0; + setitimer (ITIMER_REAL, &tim, 0); + setitimer (ITIMER_REAL, 0, &tim); + if (tim.it_interval.tv_usec < 2) + { + return HZ_WRONG; + } /* if */ + return 1000000 / tim.it_interval.tv_usec; #endif -} /* hertz */ +} /* hertz */ diff --git a/gprof/hertz.h b/gprof/hertz.h index 6708be1..d5a23d3 100644 --- a/gprof/hertz.h +++ b/gprof/hertz.h @@ -3,12 +3,12 @@ #include "gprof.h" -#define HZ_WRONG 0 /* impossible clock frequency */ +#define HZ_WRONG 0 /* impossible clock frequency */ /* * Discover the tick frequency of the machine if something goes wrong, * we return HZ_WRONG, an impossible sampling frequency. */ -extern int hertz PARAMS((void)); +extern int hertz PARAMS ((void)); #endif /* hertz_h */ diff --git a/gprof/hist.c b/gprof/hist.c index 0b2719b..2b015a4 100644 --- a/gprof/hist.c +++ b/gprof/hist.c @@ -13,7 +13,7 @@ #include "utils.h" /* declarations of automatically generated functions to output blurbs: */ -extern void flat_blurb PARAMS((FILE *fp)); +extern void flat_blurb PARAMS ((FILE * fp)); bfd_vma s_lowpc; /* lowest address in .text */ bfd_vma s_highpc = 0; /* highest address in .text */ @@ -21,8 +21,8 @@ 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[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() */ @@ -31,21 +31,57 @@ 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 { +const struct + { char prefix; double scale; -} SItab[] = { - {'T', 1e-12}, /* tera */ - {'G', 1e-09}, /* giga */ - {'M', 1e-06}, /* mega */ - {'K', 1e-03}, /* kilo */ - {' ', 1e-00}, - {'m', 1e+03}, /* milli */ - {'u', 1e+06}, /* micro */ - {'n', 1e+09}, /* nano */ - {'p', 1e+12}, /* pico */ - {'f', 1e+15}, /* femto */ - {'a', 1e+18}, /* ato */ + } +SItab[] = +{ + { + 'T', 1e-12 + } + , /* tera */ + { + 'G', 1e-09 + } + , /* giga */ + { + 'M', 1e-06 + } + , /* mega */ + { + 'K', 1e-03 + } + , /* kilo */ + { + ' ', 1e-00 + } + , + { + 'm', 1e+03 + } + , /* milli */ + { + 'u', 1e+06 + } + , /* micro */ + { + 'n', 1e+09 + } + , /* nano */ + { + 'p', 1e+12 + } + , /* pico */ + { + 'f', 1e+15 + } + , /* femto */ + { + 'a', 1e+18 + } + , /* ato */ }; /* @@ -53,70 +89,75 @@ const struct { * is provided for formatting error messages only. */ void -DEFUN(hist_read_rec, (ifp, filename), FILE *ifp AND const char *filename) +DEFUN (hist_read_rec, (ifp, filename), FILE * ifp AND const char *filename) { - struct gmon_hist_hdr hdr; - bfd_vma n_lowpc, n_highpc; - int i, ncnt, profrate; - UNIT count; - - if (fread(&hdr, sizeof(hdr), 1, ifp) != 1) { - fprintf(stderr, "%s: %s: unexpected end of file\n", - whoami, filename); - done(1); - } /* if */ - - n_lowpc = (bfd_vma) get_vma(core_bfd, (bfd_byte *) hdr.low_pc); - n_highpc = (bfd_vma) get_vma(core_bfd, (bfd_byte *) hdr.high_pc); - ncnt = bfd_get_32(core_bfd, (bfd_byte *) hdr.hist_size); - profrate = bfd_get_32(core_bfd, (bfd_byte *) hdr.prof_rate); - strncpy(hist_dimension, hdr.dimen, sizeof(hdr.dimen)); - hist_dimension[sizeof(hdr.dimen)] = '\0'; - hist_dimension_abbrev = hdr.dimen_abbrev; - - if (!s_highpc) { - - /* this is the first histogram record: */ - - s_lowpc = n_lowpc; - s_highpc = n_highpc; - lowpc = (bfd_vma) n_lowpc / sizeof(UNIT); - highpc = (bfd_vma) n_highpc / sizeof(UNIT); - hist_num_bins = ncnt; - hz = profrate; - } /* if */ - - DBG(SAMPLEDEBUG, - printf("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %d\n", + struct gmon_hist_hdr hdr; + bfd_vma n_lowpc, n_highpc; + int i, ncnt, profrate; + UNIT count; + + if (fread (&hdr, sizeof (hdr), 1, ifp) != 1) + { + fprintf (stderr, "%s: %s: unexpected end of file\n", + whoami, filename); + done (1); + } /* if */ + + n_lowpc = (bfd_vma) get_vma (core_bfd, (bfd_byte *) hdr.low_pc); + n_highpc = (bfd_vma) get_vma (core_bfd, (bfd_byte *) hdr.high_pc); + ncnt = bfd_get_32 (core_bfd, (bfd_byte *) hdr.hist_size); + profrate = bfd_get_32 (core_bfd, (bfd_byte *) hdr.prof_rate); + strncpy (hist_dimension, hdr.dimen, sizeof (hdr.dimen)); + hist_dimension[sizeof (hdr.dimen)] = '\0'; + hist_dimension_abbrev = hdr.dimen_abbrev; + + if (!s_highpc) + { + + /* this is the first histogram record: */ + + s_lowpc = n_lowpc; + s_highpc = n_highpc; + lowpc = (bfd_vma) n_lowpc / sizeof (UNIT); + highpc = (bfd_vma) n_highpc / sizeof (UNIT); + hist_num_bins = ncnt; + hz = profrate; + } /* if */ + + DBG (SAMPLEDEBUG, + printf ("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %d\n", n_lowpc, n_highpc, ncnt); - printf("[hist_read_rec] s_lowpc 0x%lx s_highpc 0x%lx nsamples %d\n", + printf ("[hist_read_rec] s_lowpc 0x%lx s_highpc 0x%lx nsamples %d\n", s_lowpc, s_highpc, hist_num_bins); - printf("[hist_read_rec] lowpc 0x%lx highpc 0x%lx\n", + printf ("[hist_read_rec] lowpc 0x%lx highpc 0x%lx\n", lowpc, highpc)); - if (n_lowpc != s_lowpc || n_highpc != s_highpc - || ncnt != hist_num_bins || hz != profrate) + if (n_lowpc != s_lowpc || n_highpc != s_highpc + || ncnt != hist_num_bins || hz != profrate) { - fprintf(stderr, "%s: `%s' is incompatible with first gmon file\n", - whoami, filename); - done(1); - } /* if */ + fprintf (stderr, "%s: `%s' is incompatible with first gmon file\n", + whoami, filename); + done (1); + } /* if */ - 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])); - } /* if */ + 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])); + } /* if */ - for (i = 0; i < hist_num_bins; ++i) { - if (fread(&count[0], sizeof(count), 1, ifp) != 1) { - fprintf(stderr, - "%s: %s: unexpected EOF after reading %d of %d samples\n", - whoami, filename, i, hist_num_bins); - done(1); - } /* if */ - hist_sample[i] += bfd_get_16(core_bfd, (bfd_byte*) &count[0]); - } /* for */ -} /* hist_read_rec */ + for (i = 0; i < hist_num_bins; ++i) + { + if (fread (&count[0], sizeof (count), 1, ifp) != 1) + { + fprintf (stderr, + "%s: %s: unexpected EOF after reading %d of %d samples\n", + whoami, filename, i, hist_num_bins); + done (1); + } /* if */ + hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]); + } /* for */ +} /* hist_read_rec */ /* @@ -124,38 +165,40 @@ DEFUN(hist_read_rec, (ifp, filename), FILE *ifp AND const char *filename) * of OFP and is provided for formatting error-messages only. */ void -DEFUN(hist_write_hist, (ofp, filename), FILE *ofp AND const char *filename) +DEFUN (hist_write_hist, (ofp, filename), FILE * ofp AND const char *filename) { - struct gmon_hist_hdr hdr; - unsigned char tag; - UNIT count; - int i; - - /* write header: */ - - tag = GMON_TAG_TIME_HIST; - put_vma(core_bfd, s_lowpc, (bfd_byte*) hdr.low_pc); - put_vma(core_bfd, s_highpc, (bfd_byte*) hdr.high_pc); - bfd_put_32(core_bfd, hist_num_bins, (bfd_byte*) hdr.hist_size); - bfd_put_32(core_bfd, hz, (bfd_byte*) hdr.prof_rate); - strncpy(hdr.dimen, hist_dimension, sizeof(hdr.dimen)); - hdr.dimen_abbrev = hist_dimension_abbrev; - - if (fwrite(&tag, sizeof(tag), 1, ofp) != 1 - || fwrite(&hdr, sizeof(hdr), 1, ofp) != 1) - { - perror(filename); - done(1); - } /* if */ - - 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); - done(1); - } /* if */ - } /* for */ -} /* hist_write_hist */ + struct gmon_hist_hdr hdr; + unsigned char tag; + UNIT count; + int i; + + /* write header: */ + + tag = GMON_TAG_TIME_HIST; + put_vma (core_bfd, s_lowpc, (bfd_byte *) hdr.low_pc); + put_vma (core_bfd, s_highpc, (bfd_byte *) hdr.high_pc); + bfd_put_32 (core_bfd, hist_num_bins, (bfd_byte *) hdr.hist_size); + bfd_put_32 (core_bfd, hz, (bfd_byte *) hdr.prof_rate); + strncpy (hdr.dimen, hist_dimension, sizeof (hdr.dimen)); + hdr.dimen_abbrev = hist_dimension_abbrev; + + if (fwrite (&tag, sizeof (tag), 1, ofp) != 1 + || fwrite (&hdr, sizeof (hdr), 1, ofp) != 1) + { + perror (filename); + done (1); + } /* if */ + + 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); + done (1); + } /* if */ + } /* for */ +} /* hist_write_hist */ /* @@ -167,28 +210,30 @@ DEFUN(hist_write_hist, (ofp, filename), FILE *ofp AND const char *filename) * next bin. */ static void -DEFUN_VOID(scale_and_align_entries) +DEFUN_VOID (scale_and_align_entries) { - Sym *sym; + Sym *sym; #if OFFSET_TO_CODE > 0 - bfd_vma bin_of_entry; - bfd_vma bin_of_code; + bfd_vma bin_of_entry; + bfd_vma bin_of_code; #endif - for (sym = symtab.base; sym < symtab.limit; sym++) { - sym->hist.scaled_addr = sym->addr / sizeof(UNIT); + for (sym = symtab.base; sym < symtab.limit; sym++) + { + sym->hist.scaled_addr = sym->addr / sizeof (UNIT); #if OFFSET_TO_CODE > 0 - bin_of_entry = (sym->hist.scaled_addr - lowpc) / hist_scale; - bin_of_code = (sym->hist.scaled_addr + UNITS_TO_CODE - lowpc) / hist_scale; - if (bin_of_entry < bin_of_code) { - DBG(SAMPLEDEBUG, - printf("[scale_and_align_entries] pushing 0x%lx to 0x%lx\n", - sym->hist.scaled_addr, sym->aligned_addr + UNITS_TO_CODE)); - sym->aligned_addr += UNITS_TO_CODE; - } /* if */ + bin_of_entry = (sym->hist.scaled_addr - lowpc) / hist_scale; + bin_of_code = (sym->hist.scaled_addr + UNITS_TO_CODE - lowpc) / hist_scale; + if (bin_of_entry < bin_of_code) + { + DBG (SAMPLEDEBUG, + printf ("[scale_and_align_entries] pushing 0x%lx to 0x%lx\n", + sym->hist.scaled_addr, sym->aligned_addr + UNITS_TO_CODE)); + sym->aligned_addr += UNITS_TO_CODE; + } /* if */ #endif /* OFFSET_TO_CODE > 0 */ - } /* for */ -} /* scale_and_align_entries */ + } /* for */ +} /* scale_and_align_entries */ /* @@ -206,18 +251,18 @@ DEFUN_VOID(scale_and_align_entries) * sample that is to be credited to the symbol which starts at * SYM_LOW_PC. * - * sym_low_pc sym_high_pc - * | | - * v v + * 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 @@ -230,153 +275,176 @@ DEFUN_VOID(scale_and_align_entries) * cases, above). */ void -DEFUN_VOID(hist_assign_samples) +DEFUN_VOID (hist_assign_samples) { - bfd_vma bin_low_pc, bin_high_pc; - bfd_vma sym_low_pc, sym_high_pc; - bfd_vma overlap, addr; - int bin_count, i, j; - double time, credit; - - /* read samples and assign to symbols: */ - hist_scale = highpc - lowpc; - hist_scale /= hist_num_bins; - scale_and_align_entries(); - - /* 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_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", - sizeof(UNIT) * bin_low_pc, sizeof(UNIT) * bin_high_pc, - bin_count)); - total_time += time; - - /* 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 (bin_high_pc < sym_low_pc) { - break; - } /* if */ - /* - * If low end of bin is above high end of symbol, go for - * next symbol. - */ - if (bin_low_pc >= sym_high_pc) { - continue; - } /* if */ - overlap = - MIN(bin_high_pc, sym_high_pc) - MAX(bin_low_pc, sym_low_pc); - if (overlap > 0) { - DBG(SAMPLEDEBUG, - printf( -"[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n", - symtab.base[j].addr, sizeof(UNIT) * sym_high_pc, - symtab.base[j].name, overlap * time / hist_scale, - 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. - */ - if (sym_lookup(&syms[INCL_FLAT], addr) - || (syms[INCL_FLAT].len == 0 - && !sym_lookup(&syms[EXCL_FLAT], addr))) + bfd_vma bin_low_pc, bin_high_pc; + bfd_vma sym_low_pc, sym_high_pc; + bfd_vma overlap, addr; + int bin_count, i, j; + double time, credit; + + /* read samples and assign to symbols: */ + hist_scale = highpc - lowpc; + hist_scale /= hist_num_bins; + scale_and_align_entries (); + + /* 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_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", + sizeof (UNIT) * bin_low_pc, sizeof (UNIT) * bin_high_pc, + bin_count)); + total_time += time; + + /* 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 (bin_high_pc < sym_low_pc) + { + break; + } /* if */ + /* + * If low end of bin is above high end of symbol, go for + * next symbol. + */ + if (bin_low_pc >= sym_high_pc) + { + continue; + } /* if */ + overlap = + MIN (bin_high_pc, sym_high_pc) - MAX (bin_low_pc, sym_low_pc); + if (overlap > 0) + { + DBG (SAMPLEDEBUG, + printf ( + "[assign_samples] [0x%lx,0x%lx) %s gets %f ticks %ld overlap\n", + symtab.base[j].addr, sizeof (UNIT) * sym_high_pc, + symtab.base[j].name, overlap * time / hist_scale, + 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. + */ + if (sym_lookup (&syms[INCL_FLAT], addr) + || (syms[INCL_FLAT].len == 0 + && !sym_lookup (&syms[EXCL_FLAT], addr))) { - symtab.base[j].hist.time += credit; - } else { - total_time -= credit; - } /* if */ - } /* if */ - } /* if */ - } /* for */ - DBG(SAMPLEDEBUG, printf("[assign_samples] total_time %f\n", + symtab.base[j].hist.time += credit; + } + else + { + total_time -= credit; + } /* if */ + } /* if */ + } /* if */ + } /* for */ + DBG (SAMPLEDEBUG, printf ("[assign_samples] total_time %f\n", total_time)); -} /* hist_assign_samples */ +} /* hist_assign_samples */ /* * Print header for flag histogram profile: */ static void -DEFUN(print_header, (prefix), const char prefix) +DEFUN (print_header, (prefix), const char prefix) { - char unit[64]; - - sprintf(unit, "%c%c/call", prefix, hist_dimension_abbrev); - - if (bsd_style_output) { - printf("\ngranularity: each sample hit covers %ld byte(s)", - (long) hist_scale * sizeof(UNIT)); - if (total_time > 0.0) { - printf(" for %.2f%% of %.2f %s\n\n", - 100.0/total_time, total_time/hz, hist_dimension); - } /* if */ - } else { - printf("\nEach sample counts as %g %s.\n", 1.0 / hz, hist_dimension); - } /* if */ - - if (total_time <= 0.0) { - printf(" no time accumulated\n\n"); - /* this doesn't hurt since all the numerators will be zero: */ - total_time = 1.0; - } /* if */ - - printf("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", - "% ", "cumulative", "self ", "", "self ", "total ", ""); - printf("%5.5s %9.9s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", - "time", hist_dimension, hist_dimension, "calls", unit, unit, - "name"); -} /* print_header */ + char unit[64]; + + sprintf (unit, "%c%c/call", prefix, hist_dimension_abbrev); + + if (bsd_style_output) + { + printf ("\ngranularity: each sample hit covers %ld byte(s)", + (long) hist_scale * sizeof (UNIT)); + if (total_time > 0.0) + { + printf (" for %.2f%% of %.2f %s\n\n", + 100.0 / total_time, total_time / hz, hist_dimension); + } /* if */ + } + else + { + printf ("\nEach sample counts as %g %s.\n", 1.0 / hz, hist_dimension); + } /* if */ + + if (total_time <= 0.0) + { + printf (" no time accumulated\n\n"); + /* this doesn't hurt since all the numerators will be zero: */ + total_time = 1.0; + } /* if */ + + printf ("%5.5s %10.10s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", + "% ", "cumulative", "self ", "", "self ", "total ", ""); + printf ("%5.5s %9.9s %8.8s %8.8s %8.8s %8.8s %-8.8s\n", + "time", hist_dimension, hist_dimension, "calls", unit, unit, + "name"); +} /* print_header */ static void -DEFUN(print_line, (sym, scale), Sym *sym AND double scale) +DEFUN (print_line, (sym, scale), Sym * sym AND double scale) { - if (ignore_zeros && sym->ncalls == 0 && sym->hist.time == 0) { - return; - } /* if */ - - 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); - } 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); - } /* if */ - if (sym->ncalls) { - printf(" %8d %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 ", "", "", ""); - } /* if */ - if (bsd_style_output) { - print_name(sym); - } else { - print_name_only(sym); - } /* if */ - printf("\n"); -} /* print_line */ + if (ignore_zeros && sym->ncalls == 0 && sym->hist.time == 0) + { + return; + } /* if */ + + 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); + } + 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); + } /* if */ + if (sym->ncalls) + { + printf (" %8d %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 ", "", "", ""); + } /* if */ + if (bsd_style_output) + { + print_name (sym); + } + else + { + print_name_only (sym); + } /* if */ + printf ("\n"); +} /* print_line */ /* @@ -385,123 +453,144 @@ DEFUN(print_line, (sym, scale), Sym *sym AND double scale) * lexicographic order of the function names. */ static int -DEFUN(cmp_time, (lp, rp), const PTR lp AND const PTR rp) +DEFUN (cmp_time, (lp, rp), const PTR lp AND const PTR rp) { - const Sym *left = *(const Sym **)lp; - const Sym *right = *(const Sym **)rp; - double time_diff; - long call_diff; - - time_diff = right->hist.time - left->hist.time; - if (time_diff > 0.0) { - return 1; - } /* if */ - if (time_diff < 0.0) { - return -1; - } /* if */ - - call_diff = right->ncalls - left->ncalls; - if (call_diff > 0) { - return 1; - } /* if */ - if (call_diff < 0) { - return -1; - } /* if */ - - return strcmp(left->name, right->name); -} /* cmp_time */ + const Sym *left = *(const Sym **) lp; + const Sym *right = *(const Sym **) rp; + double time_diff; + long call_diff; + + time_diff = right->hist.time - left->hist.time; + if (time_diff > 0.0) + { + return 1; + } /* if */ + if (time_diff < 0.0) + { + return -1; + } /* if */ + + call_diff = right->ncalls - left->ncalls; + if (call_diff > 0) + { + return 1; + } /* if */ + if (call_diff < 0) + { + return -1; + } /* if */ + + return strcmp (left->name, right->name); +} /* cmp_time */ /* * Print the flat histogram profile. */ void -DEFUN_VOID(hist_print) +DEFUN_VOID (hist_print) { - Sym **time_sorted_syms, *top_dog, *sym; - int index, log_scale; - double top_time, time; - bfd_vma addr; - - if (first_output) { - first_output = FALSE; - } else { - printf("\f\n"); - } /* if */ - - accum_time = 0.0; - if (bsd_style_output) { - if (print_descriptions) { - printf("\n\n\nflat profile:\n"); - flat_blurb(stdout); - } /* if */ - } else { - printf ("Flat profile:\n"); - } /* if */ - /* - * 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]; - } /* for */ - qsort(time_sorted_syms, symtab.len, sizeof(Sym *), cmp_time); - - if (bsd_style_output) { - log_scale = 5; /* milli-seconds is BSD-default */ - } else { - /* - * 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) { - time = (sym->hist.time + sym->cg.child_time) / sym->ncalls; - if (time > top_time) { - top_dog = sym; - top_time = time; - } /* if */ - } /* if */ - } /* for */ - if (top_dog && top_dog->ncalls && top_time > 0.0) { - top_time /= hz; - while (SItab[log_scale].scale * top_time < 1000.0 - && log_scale < sizeof(SItab)/sizeof(SItab[0]) - 1) + Sym **time_sorted_syms, *top_dog, *sym; + int index, log_scale; + double top_time, time; + bfd_vma addr; + + if (first_output) + { + first_output = FALSE; + } + else + { + printf ("\f\n"); + } /* if */ + + accum_time = 0.0; + if (bsd_style_output) + { + if (print_descriptions) + { + printf ("\n\n\nflat profile:\n"); + flat_blurb (stdout); + } /* if */ + } + else + { + printf ("Flat profile:\n"); + } /* if */ + /* + * 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]; + } /* for */ + qsort (time_sorted_syms, symtab.len, sizeof (Sym *), cmp_time); + + if (bsd_style_output) + { + log_scale = 5; /* milli-seconds is BSD-default */ + } + else + { + /* + * 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) + { + time = (sym->hist.time + sym->cg.child_time) / sym->ncalls; + if (time > top_time) + { + top_dog = sym; + top_time = time; + } /* if */ + } /* if */ + } /* for */ + if (top_dog && top_dog->ncalls && top_time > 0.0) + { + top_time /= hz; + while (SItab[log_scale].scale * top_time < 1000.0 + && log_scale < sizeof (SItab) / sizeof (SItab[0]) - 1) { - ++log_scale; - } /* while */ - } /* if */ - } /* if */ - - /* - * 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. - */ - if (sym_lookup(&syms[INCL_FLAT], addr) - || (syms[INCL_FLAT].len == 0 - && !sym_lookup(&syms[EXCL_FLAT], addr))) + ++log_scale; + } /* while */ + } /* if */ + } /* if */ + + /* + * 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. + */ + 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); - } /* if */ - } /* for */ - free(time_sorted_syms); + print_line (time_sorted_syms[index], SItab[log_scale].scale); + } /* if */ + } /* for */ + free (time_sorted_syms); - if (print_descriptions && !bsd_style_output) { - flat_blurb(stdout); - } /* if */ -} /* hist_print */ + if (print_descriptions && !bsd_style_output) + { + flat_blurb (stdout); + } /* if */ +} /* hist_print */ - /*** end of hist.c ***/ +/*** end of hist.c ***/ diff --git a/gprof/hist.h b/gprof/hist.h index 1335b83..df62ef7 100644 --- a/gprof/hist.h +++ b/gprof/hist.h @@ -3,11 +3,11 @@ #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 */ +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: @@ -15,9 +15,9 @@ extern int *hist_sample; /* code histogram */ 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 * 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)); #endif /* hist_h */ diff --git a/gprof/i386.c b/gprof/i386.c index 219be72..01202a7 100644 --- a/gprof/i386.c +++ b/gprof/i386.c @@ -24,80 +24,87 @@ int -DEFUN(iscall, (ip), unsigned char *ip) +DEFUN (iscall, (ip), unsigned char *ip) { - if (*ip == 0xeb || *ip == 0x9a) + if (*ip == 0xeb || *ip == 0x9a) return 1; return 0; } void -find_call(parent, p_lowpc, p_highpc) - Sym *parent; - bfd_vma p_lowpc; - bfd_vma p_highpc; +find_call (parent, p_lowpc, p_highpc) + Sym *parent; + bfd_vma p_lowpc; + bfd_vma p_highpc; { - unsigned char *instructp; - long length; - Sym *child; - bfd_vma destpc; + unsigned char *instructp; + long length; + Sym *child; + bfd_vma destpc; - if (core_text_space == 0) { - return; + if (core_text_space == 0) + { + return; } - if (p_lowpc < s_lowpc) { - p_lowpc = s_lowpc; + if (p_lowpc < s_lowpc) + { + p_lowpc = s_lowpc; } - if (p_highpc > s_highpc) { - p_highpc = s_highpc; + if (p_highpc > s_highpc) + { + p_highpc = s_highpc; } - DBG(CALLDEBUG, printf("[findcall] %s: 0x%lx to 0x%lx\n", + DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n", parent->name, p_lowpc, p_highpc)); - for ( instructp = (unsigned char*) core_text_space + p_lowpc ; - instructp < (unsigned char*) core_text_space + p_highpc ; - instructp += length) { - length = 1; - if (iscall (instructp)) { - DBG(CALLDEBUG, - printf("[findcall]\t0x%x:callf", - instructp - (unsigned char*) core_text_space)); + for (instructp = (unsigned char *) core_text_space + p_lowpc; + instructp < (unsigned char *) core_text_space + p_highpc; + instructp += length) + { + length = 1; + if (iscall (instructp)) + { + DBG (CALLDEBUG, + printf ("[findcall]\t0x%x:callf", + instructp - (unsigned char *) core_text_space)); length = 4; /* - * regular pc relative addressing - * check that this is the address of - * a function. + * regular pc relative addressing + * check that this is the address of + * a function. */ - destpc = ((bfd_vma)instructp + 5 - (bfd_vma) core_text_space); - if (destpc >= s_lowpc && destpc <= s_highpc) { - child = sym_lookup(&symtab, destpc); - DBG(CALLDEBUG, - printf("[findcall]\tdestpc 0x%lx", destpc); - printf(" child->name %s", child->name); - printf(" child->addr 0x%lx\n", child->addr); + destpc = ((bfd_vma) instructp + 5 - (bfd_vma) core_text_space); + if (destpc >= s_lowpc && destpc <= s_highpc) + { + child = sym_lookup (&symtab, destpc); + DBG (CALLDEBUG, + printf ("[findcall]\tdestpc 0x%lx", destpc); + printf (" child->name %s", child->name); + printf (" child->addr 0x%lx\n", child->addr); ); - if (child->addr == destpc) { - /* - * a hit - */ - arc_add(parent, child, (long) 0); - length += 4; /* constant lengths */ - continue; + if (child->addr == destpc) + { + /* + * a hit + */ + arc_add (parent, child, (long) 0); + length += 4; /* constant lengths */ + continue; + } + goto botched; } - goto botched; - } /* - * else: - * it looked like a callf, - * but it wasn't to anywhere. + * else: + * it looked like a callf, + * but it wasn't to anywhere. */ botched: /* - * something funny going on. + * something funny going on. */ - DBG(CALLDEBUG, printf("[findcall]\tbut it's a botch\n")); - length = 1; - continue; + DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n")); + length = 1; + continue; } - } - } + } +} diff --git a/gprof/i386.h b/gprof/i386.h index baf856a..f85f55c 100644 --- a/gprof/i386.h +++ b/gprof/i386.h @@ -16,7 +16,7 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#)tahoe.h 1.4 (Berkeley) 6/1/90 + * @(#)tahoe.h 1.4 (Berkeley) 6/1/90 */ /* @@ -24,11 +24,11 @@ */ /* - * opcode of the `callf' instruction + * opcode of the `callf' instruction */ /* - * offset (in bytes) of the code from the entry address of a routine. - * (see asgnsamples for use and explanation.) + * offset (in bytes) of the code from the entry address of a routine. + * (see asgnsamples for use and explanation.) */ #define OFFSET_TO_CODE 0 #define UNITS_TO_CODE (OFFSET_TO_CODE / sizeof(UNIT)) diff --git a/gprof/ns532.c b/gprof/ns532.c index 21a6db3..ae3f801 100644 --- a/gprof/ns532.c +++ b/gprof/ns532.c @@ -5,9 +5,9 @@ * It does nothing, but prevents findcall() from being unresolved. */ -findcall( parentp , p_lowpc , p_highpc ) - nltype *parentp; - unsigned long p_lowpc; - unsigned long p_highpc; +findcall (parentp, p_lowpc, p_highpc) + nltype *parentp; + unsigned long p_lowpc; + unsigned long p_highpc; { } diff --git a/gprof/ns532.h b/gprof/ns532.h index 6e6d349..9eb92a5 100644 --- a/gprof/ns532.h +++ b/gprof/ns532.h @@ -38,8 +38,8 @@ */ /* - * offset (in bytes) of the code from the entry address of a routine. - * (see asgnsamples for use and explanation.) + * offset (in bytes) of the code from the entry address of a routine. + * (see asgnsamples for use and explanation.) */ #ifdef MACH #include @@ -48,5 +48,8 @@ #define OFFSET_OF_CODE 0 #define UNITS_TO_CODE (OFFSET_OF_CODE / sizeof(UNIT)) -enum opermodes { dummy }; -typedef enum opermodes operandenum; +enum opermodes + { + dummy + }; +typedef enum opermodes operandenum; diff --git a/gprof/search_list.c b/gprof/search_list.c index 565b83b..e49cc8a 100644 --- a/gprof/search_list.c +++ b/gprof/search_list.c @@ -4,35 +4,43 @@ void -DEFUN(search_list_append, (list, paths), - Search_List *list AND const char *paths) +DEFUN (search_list_append, (list, paths), + Search_List * list AND const char *paths) { - Search_List_Elem *new_el; - const char *beg, *colon; - int len; + Search_List_Elem *new_el; + const char *beg, *colon; + int len; - colon = paths - 1; - do { - beg = colon + 1; - colon = strchr(beg, ':'); - if (colon) { - len = colon - beg; - } else { - len = strlen(beg); - } /* if */ - new_el = (Search_List_Elem*) xmalloc(sizeof(*new_el) + len); - memcpy(new_el->path, beg, len); - new_el->path[len] = '\0'; + colon = paths - 1; + do + { + beg = colon + 1; + colon = strchr (beg, ':'); + if (colon) + { + len = colon - beg; + } + else + { + len = strlen (beg); + } /* if */ + 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: */ - new_el->next = 0; - if (list->tail) { - list->tail->next = new_el; - } else { - list->head = new_el; - } /* if */ - list->tail = new_el; - } while (colon); -} /* search_list_append */ + /* append new path at end of list: */ + new_el->next = 0; + if (list->tail) + { + list->tail->next = new_el; + } + else + { + list->head = new_el; + } /* if */ + list->tail = new_el; + } + while (colon); +} /* search_list_append */ - /*** end of search_list.c ***/ +/*** end of search_list.c ***/ diff --git a/gprof/search_list.h b/gprof/search_list.h index 092d956..54dfe35 100644 --- a/gprof/search_list.h +++ b/gprof/search_list.h @@ -1,16 +1,20 @@ #ifndef search_list_h #define search_list_h -typedef struct search_list_elem { - struct search_list_elem *next; - char path[1]; -} Search_List_Elem; +typedef struct search_list_elem + { + struct search_list_elem *next; + char path[1]; + } +Search_List_Elem; -typedef struct { +typedef struct + { struct search_list_elem *head; struct search_list_elem *tail; -} Search_List; + } +Search_List; -extern void search_list_append PARAMS((Search_List *list, const char *paths)); +extern void search_list_append PARAMS ((Search_List * list, const char *paths)); #endif /* search_list_h */ diff --git a/gprof/source.c b/gprof/source.c index 7917bba..1fb0e53 100644 --- a/gprof/source.c +++ b/gprof/source.c @@ -13,174 +13,213 @@ */ 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; -Source_File* -DEFUN(source_file_lookup_path, (path), const char *path) +Source_File * +DEFUN (source_file_lookup_path, (path), const char *path) { - Source_File *sf; - - for (sf = first_src_file; sf; sf = sf->next) { - if (strcmp(path, sf->name) == 0) { - break; - } /* if */ - } /* for */ - if (!sf) { - /* create a new source file descriptor: */ - - sf = (Source_File*) xmalloc(sizeof(*sf)); - memset(sf, 0, sizeof(*sf)); - sf->name = strdup(path); - sf->next = first_src_file; - first_src_file = sf; - } /* if */ - return sf; -} /* source_file_lookup_path */ - - -Source_File* -DEFUN(source_file_lookup_name, (filename), const char *filename) + Source_File *sf; + + for (sf = first_src_file; sf; sf = sf->next) + { + if (strcmp (path, sf->name) == 0) + { + break; + } /* if */ + } /* for */ + if (!sf) + { + /* create a new source file descriptor: */ + + sf = (Source_File *) xmalloc (sizeof (*sf)); + memset (sf, 0, sizeof (*sf)); + sf->name = strdup (path); + sf->next = first_src_file; + first_src_file = sf; + } /* if */ + return sf; +} /* source_file_lookup_path */ + + +Source_File * +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: - */ - for (sf = first_src_file; sf; sf = sf->next) { - fname = strrchr(sf->name, '/'); - if (fname) { - ++fname; - } else { - fname = sf->name; - } /* if */ - if (strcmp(filename, fname) == 0) { - break; - } /* if */ - } /* for */ - return sf; -} /* source_file_lookup_name */ - - -FILE* -DEFUN(annotate_source, (sf, max_width, annote, arg), - Source_File *sf AND int max_width - AND void (*annote) PARAMS((char *buf, int w, int l, void *arg)) - AND void *arg) + 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: + */ + for (sf = first_src_file; sf; sf = sf->next) + { + fname = strrchr (sf->name, '/'); + if (fname) + { + ++fname; + } + else + { + fname = sf->name; + } /* if */ + if (strcmp (filename, fname) == 0) + { + break; + } /* if */ + } /* for */ + return sf; +} /* source_file_lookup_name */ + + +FILE * +DEFUN (annotate_source, (sf, max_width, annote, arg), + Source_File * sf AND int max_width + AND void (*annote) PARAMS ((char *buf, int w, int l, void *arg)) + AND void *arg) { - static bool first_file = TRUE; - int i, line_num, nread; - bool new_line; - char buf[8192]; - char fname[PATH_MAX]; - char *annotation, *name_only; - 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: - */ - strcpy(fname, sf->name); - if (sf->name[0] == '/') { - sle = 0; /* don't use search list for absolute paths */ - } /* if */ - name_only = 0; - while (TRUE) { - DBG(SRCDEBUG, printf("[annotate_source]: looking for %s, trying %s\n", + static bool first_file = TRUE; + int i, line_num, nread; + bool new_line; + char buf[8192]; + char fname[PATH_MAX]; + char *annotation, *name_only; + 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: + */ + strcpy (fname, sf->name); + if (sf->name[0] == '/') + { + sle = 0; /* don't use search list for absolute paths */ + } /* if */ + 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; - } /* if */ - if (!sle && !name_only) { - name_only = strrchr(sf->name, '/'); - if (name_only) { - /* try search-list again, but this time with name only: */ - ++name_only; - sle = src_search_list.head; - } /* if */ - } /* if */ - if (sle) { - strcpy(fname, sle->path); - strcat(fname, "/"); - if (name_only) { - strcat(fname, name_only); - } else { - strcat(fname, sf->name); - } /* if */ - sle = sle->next; - } else { - if (errno == ENOENT) { - fprintf(stderr, "%s: could not locate `%s'\n", - whoami, sf->name); - } else { - perror(sf->name); - } /* if */ - return 0; - } /* if */ - } /* while */ - - ofp = stdout; - if (create_annotation_files) { - /* try to create annotated source file: */ - const char *filename; - - /* create annotation files in the current working directory: */ - filename = strrchr(sf->name, '/'); - if (filename) { - ++filename; - } else { - filename = sf->name; - } /* if */ - - strcpy(fname, filename); - strcat(fname, EXT_ANNO); - ofp = fopen(fname, "w"); - if (!ofp) { - perror(fname); - return 0; - } /* if */ - } /* if */ - - /* - * 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; - } else { - fputc('\n', ofp); - } /* if */ - if (first_output) { - first_output = FALSE; - } else { - fprintf(ofp, "\f\n"); - } /* if */ - fprintf(ofp, "*** File %s:\n", sf->name); - } /* if */ - - 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) { - if (new_line) { - (*annote)(annotation, max_width, line_num, arg); - fputs(annotation, ofp); - ++line_num; new_line = FALSE; - } /* if */ - new_line = (buf[i] == '\n'); - fputc(buf[i], ofp); - } /* for */ - } /* while */ - free(annotation); - return ofp; -} /* annotate_source */ - - /*** end of source.c ***/ + ifp = fopen (fname, FOPEN_RB); + if (ifp) + { + break; + } /* if */ + if (!sle && !name_only) + { + name_only = strrchr (sf->name, '/'); + if (name_only) + { + /* try search-list again, but this time with name only: */ + ++name_only; + sle = src_search_list.head; + } /* if */ + } /* if */ + if (sle) + { + strcpy (fname, sle->path); + strcat (fname, "/"); + if (name_only) + { + strcat (fname, name_only); + } + else + { + strcat (fname, sf->name); + } /* if */ + sle = sle->next; + } + else + { + if (errno == ENOENT) + { + fprintf (stderr, "%s: could not locate `%s'\n", + whoami, sf->name); + } + else + { + perror (sf->name); + } /* if */ + return 0; + } /* if */ + } /* while */ + + ofp = stdout; + if (create_annotation_files) + { + /* try to create annotated source file: */ + const char *filename; + + /* create annotation files in the current working directory: */ + filename = strrchr (sf->name, '/'); + if (filename) + { + ++filename; + } + else + { + filename = sf->name; + } /* if */ + + strcpy (fname, filename); + strcat (fname, EXT_ANNO); + ofp = fopen (fname, "w"); + if (!ofp) + { + perror (fname); + return 0; + } /* if */ + } /* if */ + + /* + * 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; + } + else + { + fputc ('\n', ofp); + } /* if */ + if (first_output) + { + first_output = FALSE; + } + else + { + fprintf (ofp, "\f\n"); + } /* if */ + fprintf (ofp, "*** File %s:\n", sf->name); + } /* if */ + + 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) + { + if (new_line) + { + (*annote) (annotation, max_width, line_num, arg); + fputs (annotation, ofp); + ++line_num; + new_line = FALSE; + } /* if */ + new_line = (buf[i] == '\n'); + fputc (buf[i], ofp); + } /* for */ + } /* while */ + free (annotation); + return ofp; +} /* annotate_source */ + +/*** end of source.c ***/ diff --git a/gprof/source.h b/gprof/source.h index a542446..ebdbb3b 100644 --- a/gprof/source.h +++ b/gprof/source.h @@ -5,14 +5,16 @@ #include "gprof.h" #include "search_list.h" -typedef struct source_file { - struct source_file *next; - const char *name; /* name of source file */ - int 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; +typedef struct source_file + { + struct source_file *next; + const char *name; /* name of source file */ + int 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: @@ -32,8 +34,8 @@ 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)); +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 @@ -45,9 +47,9 @@ extern Source_File *source_file_lookup_name PARAMS((const char *filename)); * 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)); +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/sparc.c b/gprof/sparc.c index 98e29ce..b78ef43 100644 --- a/gprof/sparc.c +++ b/gprof/sparc.c @@ -24,56 +24,62 @@ void -find_call(parent, p_lowpc, p_highpc) +find_call (parent, p_lowpc, p_highpc) Sym *parent; bfd_vma p_lowpc; bfd_vma p_highpc; { - bfd_vma dest_pc, delta; - unsigned int *instr; - Sym *child; - - delta = (bfd_vma) core_text_space - core_text_sect->vma; - - if (core_text_space == 0) { - return; - } /* if */ - if (p_lowpc < s_lowpc) { - p_lowpc = s_lowpc; - } /* if */ - if (p_highpc > s_highpc) { - p_highpc = s_highpc; - } /* if */ - DBG(CALLDEBUG, printf("[find_call] %s: 0x%lx to 0x%lx\n", + bfd_vma dest_pc, delta; + unsigned int *instr; + Sym *child; + + delta = (bfd_vma) core_text_space - core_text_sect->vma; + + if (core_text_space == 0) + { + return; + } /* if */ + if (p_lowpc < s_lowpc) + { + p_lowpc = s_lowpc; + } /* if */ + if (p_highpc > s_highpc) + { + p_highpc = s_highpc; + } /* if */ + DBG (CALLDEBUG, printf ("[find_call] %s: 0x%lx to 0x%lx\n", parent->name, p_lowpc, p_highpc)); - for (instr = (unsigned int*)(p_lowpc + delta); - instr < (unsigned int*)(p_highpc + delta); - ++instr) + for (instr = (unsigned int *) (p_lowpc + delta); + instr < (unsigned int *) (p_highpc + delta); + ++instr) { - if ((*instr & CALL)) { - DBG(CALLDEBUG, - printf("[find_call] 0x%lx: callf", (bfd_vma) instr - delta)); - /* - * Regular pc relative addressing check that this is the - * address of a function. - */ - dest_pc = ((bfd_vma) (instr + (*instr & ~CALL))) - delta; - if (dest_pc >= s_lowpc && dest_pc <= s_highpc) { - child = sym_lookup(&symtab, dest_pc); - DBG(CALLDEBUG, - printf("\tdest_pc=0x%lx, (name=%s, addr=0x%lx)\n", + if ((*instr & CALL)) + { + DBG (CALLDEBUG, + printf ("[find_call] 0x%lx: callf", (bfd_vma) instr - delta)); + /* + * Regular pc relative addressing check that this is the + * address of a function. + */ + dest_pc = ((bfd_vma) (instr + (*instr & ~CALL))) - delta; + if (dest_pc >= s_lowpc && dest_pc <= s_highpc) + { + child = sym_lookup (&symtab, dest_pc); + DBG (CALLDEBUG, + printf ("\tdest_pc=0x%lx, (name=%s, addr=0x%lx)\n", dest_pc, child->name, child->addr)); - if (child->addr == dest_pc) { - /* a hit: */ - arc_add(parent, child, 0); - continue; - } /* if */ - } /* if */ - /* - * Something funny going on. - */ - DBG(CALLDEBUG, printf("\tbut it's a botch\n")); - } /* if */ - } /* for */ -} /* find_call */ - /*** end of sparc.c ***/ + if (child->addr == dest_pc) + { + /* a hit: */ + arc_add (parent, child, 0); + continue; + } /* if */ + } /* if */ + /* + * Something funny going on. + */ + DBG (CALLDEBUG, printf ("\tbut it's a botch\n")); + } /* if */ + } /* for */ +} /* find_call */ +/*** end of sparc.c ***/ diff --git a/gprof/sparc.h b/gprof/sparc.h index a5b46ad..48e5d23 100644 --- a/gprof/sparc.h +++ b/gprof/sparc.h @@ -16,17 +16,16 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#)tahoe.h 1.4 (Berkeley) 6/1/90 + * @(#)tahoe.h 1.4 (Berkeley) 6/1/90 */ /* - * opcode of the `callf' instruction + * opcode of the `callf' instruction */ #define CALL (0xc0000000) /* - * offset (in bytes) of the code from the entry address of a routine. - * (see asgnsamples for use and explanation.) + * offset (in bytes) of the code from the entry address of a routine. + * (see asgnsamples for use and explanation.) */ #define OFFSET_TO_CODE 0 #define UNITS_TO_CODE (OFFSET_TO_CODE / sizeof(UNIT)) - diff --git a/gprof/sym_ids.c b/gprof/sym_ids.c index 5bd94f1..fdc958b 100644 --- a/gprof/sym_ids.c +++ b/gprof/sym_ids.c @@ -2,29 +2,34 @@ #include "cg_arcs.h" #include "sym_ids.h" -struct sym_id { - struct sym_id *next; - 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 */ - Sym sym; - } left, right; -} *id_list; +struct sym_id + { + struct sym_id *next; + 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 */ + Sym sym; + } + left, right; + } + *id_list; Sym_Table syms[NUM_TABLES]; #ifdef DEBUG -const char *table_name[] = { - "INCL_GRAPH", "EXCL_GRAPH", - "INCL_ARCS", "EXCL_ARCS", - "INCL_FLAT", "EXCL_FLAT", - "INCL_TIME", "EXCL_TIME", - "INCL_ANNO", "EXCL_ANNO", - "INCL_EXEC", "EXCL_EXEC" +const char *table_name[] = +{ + "INCL_GRAPH", "EXCL_GRAPH", + "INCL_ARCS", "EXCL_ARCS", + "INCL_FLAT", "EXCL_FLAT", + "INCL_TIME", "EXCL_TIME", + "INCL_ANNO", "EXCL_ANNO", + "INCL_EXEC", "EXCL_EXEC" }; #endif /* DEBUG */ @@ -37,78 +42,94 @@ const char *table_name[] = { */ static Sym_Table right_ids; -static Source_File non_existent_file = { - 0, "" +static Source_File non_existent_file = +{ + 0, "" }; void -DEFUN(sym_id_add, (spec, which_table), - const char *spec AND Table_Id which_table) +DEFUN (sym_id_add, (spec, which_table), + const char *spec AND Table_Id which_table) { - struct sym_id *id; - int len = strlen(spec); + struct sym_id *id; + int len = strlen (spec); - id = (struct sym_id*) xmalloc(sizeof(*id) + len + 1); - memset(id, 0, sizeof(*id)); + id = (struct sym_id *) xmalloc (sizeof (*id) + len + 1); + memset (id, 0, sizeof (*id)); - id->spec = (char*)id + sizeof(*id); - strcpy(id->spec, spec); - id->which_table = which_table; + id->spec = (char *) id + sizeof (*id); + strcpy (id->spec, spec); + id->which_table = which_table; - id->next = id_list; - id_list = id; -} /* sym_id_add */ + id->next = id_list; + id_list = id; +} /* sym_id_add */ /* * 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 + * (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) +DEFUN (parse_spec, (spec, sym), char *spec AND Sym * sym) { - char *colon; - - 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; - } /* if */ - } /* if */ - spec = colon + 1; - if (strlen(spec)) { - if (isdigit(spec[0])) { - sym->line_num = atoi(spec); - } else { - sym->name = spec; - } /* if */ - } /* if */ - } else if (strlen(spec)) { - /* 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; - } /* if */ - } else if (isdigit(*spec)) { - sym->line_num = atoi(spec); - } else if (strlen(spec)) { - sym->name = spec; - } /* if */ - } /* if */ -} /* parse_spec */ + char *colon; + + 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; + } /* if */ + } /* if */ + spec = colon + 1; + if (strlen (spec)) + { + if (isdigit (spec[0])) + { + sym->line_num = atoi (spec); + } + else + { + sym->name = spec; + } /* if */ + } /* if */ + } + else if (strlen (spec)) + { + /* 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; + } /* if */ + } + else if (isdigit (*spec)) + { + sym->line_num = atoi (spec); + } + else if (strlen (spec)) + { + sym->name = spec; + } /* if */ + } /* if */ +} /* parse_spec */ /* @@ -116,79 +137,98 @@ DEFUN(parse_spec, (spec, sym), char *spec AND Sym *sym) * by parse_spec(). */ static void -DEFUN(parse_id, (id), struct sym_id *id) +DEFUN (parse_id, (id), struct sym_id *id) { - char *slash; - - DBG(IDDEBUG, printf("[parse_id] %s -> ", id->spec)); - - slash = strchr(id->spec, '/'); - if (slash) { - parse_spec(slash + 1, &id->right.sym); - *slash = '\0'; - id->has_right = TRUE; - } /* if */ - parse_spec(id->spec, &id->left.sym); - - DBG(IDDEBUG, - printf("%s:", id->left.sym.file ? id->left.sym.file->name : "*"); - if (id->left.sym.name) { - printf("%s", id->left.sym.name); - } else if (id->left.sym.line_num) { - printf("%d", id->left.sym.line_num); - } else { - printf("*"); - } /* if */ - 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); - } else if (id->right.sym.line_num) { - printf("%d", id->right.sym.line_num); - } else { - printf("*"); - } /* if */ - } /* if */ - printf("\n")); -} /* parse_id */ + char *slash; + + DBG (IDDEBUG, printf ("[parse_id] %s -> ", id->spec)); + + slash = strchr (id->spec, '/'); + if (slash) + { + parse_spec (slash + 1, &id->right.sym); + *slash = '\0'; + id->has_right = TRUE; + } /* if */ + parse_spec (id->spec, &id->left.sym); + +#ifdef DEBUG + 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); + } + else if (id->left.sym.line_num) + { + printf ("%d", id->left.sym.line_num); + } + else + { + printf ("*"); + } /* if */ + 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); + } + else if (id->right.sym.line_num) + { + printf ("%d", id->right.sym.line_num); + } + else + { + printf ("*"); + } /* if */ + } /* if */ + printf ("\n"); + } +#endif +} /* parse_id */ /* * Return TRUE iff PATTERN matches SYM. */ static bool -DEFUN(match, (pattern, sym), Sym *pattern AND Sym *sym) +DEFUN (match, (pattern, sym), Sym * pattern AND Sym * sym) { - return (pattern->file ? pattern->file == sym->file : TRUE) - && (pattern->line_num ? pattern->line_num == sym->line_num : TRUE) - && (pattern->name ? strcmp(pattern->name, sym->name) == 0 : TRUE); -} /* match */ + return (pattern->file ? pattern->file == sym->file : TRUE) + && (pattern->line_num ? pattern->line_num == sym->line_num : TRUE) + && (pattern->name ? strcmp (pattern->name, sym->name) == 0 : TRUE); +} /* match */ static void -DEFUN(extend_match, (m, sym, tab, second_pass), - struct match *m AND Sym *sym AND Sym_Table *tab AND bool second_pass) +DEFUN (extend_match, (m, sym, tab, second_pass), + struct match *m AND Sym * sym AND Sym_Table * tab AND bool second_pass) { - if (m->prev_match != sym - 1) { - /* 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: */ - tab->base[tab->len].next = m->first_match; - m->first_match = &tab->base[tab->len]; - } /* if */ - ++tab->len; - } /* if */ - - /* extend match to include this symbol: */ - if (second_pass) { - tab->base[m->prev_index].end_addr = sym->end_addr; - } /* if */ - m->prev_match = sym; -} /* extend_match */ + if (m->prev_match != sym - 1) + { + /* 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: */ + tab->base[tab->len].next = m->first_match; + m->first_match = &tab->base[tab->len]; + } /* if */ + ++tab->len; + } /* if */ + + /* extend match to include this symbol: */ + if (second_pass) + { + tab->base[m->prev_index].end_addr = sym->end_addr; + } /* if */ + m->prev_match = sym; +} /* extend_match */ /* @@ -201,91 +241,107 @@ DEFUN(extend_match, (m, sym, tab, second_pass), * requests---you get what you ask for! */ void -DEFUN_VOID(sym_id_parse) +DEFUN_VOID (sym_id_parse) { - Sym *sym, *left, *right; - struct sym_id *id; - Sym_Table *tab; - - /* - * Convert symbol ids into Syms, so we can deal with them more easily: - */ - for (id = id_list; id; id = id->next) { - parse_id(id); - } /* for */ - - /* 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); - } /* if */ - if (id->has_right && match(&id->right.sym, sym)) { - extend_match(&id->right, sym, &right_ids, FALSE); - } /* if */ - } /* for */ - } /* for */ - - /* create tables of appropriate size and reset lengths: */ - - for (tab = syms; tab < &syms[NUM_TABLES]; ++tab) { - if (tab->len) { - tab->base = (Sym*) xmalloc(tab->len * sizeof(Sym)); - tab->limit = tab->base + tab->len; - tab->len = 0; - } /* if */ - } /* for */ - if (right_ids.len) { - right_ids.base = (Sym*) xmalloc(right_ids.len * sizeof(Sym)); - right_ids.limit = right_ids.base + right_ids.len; - right_ids.len = 0; - } /* if */ - - /* 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); - } /* if */ - if (id->has_right && match(&id->right.sym, sym)) { - extend_match(&id->right, sym, &right_ids, TRUE); - } /* if */ - } /* for */ - } /* for */ - - /* go through ids creating arcs as needed: */ - - for (id = id_list; id; id = id->next) { - if (id->has_right) { - for (left = id->left.first_match; left; left = left->next) { - for (right = id->right.first_match; right; right = right->next) + Sym *sym, *left, *right; + struct sym_id *id; + Sym_Table *tab; + + /* + * Convert symbol ids into Syms, so we can deal with them more easily: + */ + for (id = id_list; id; id = id->next) + { + parse_id (id); + } /* for */ + + /* 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); + } /* if */ + if (id->has_right && match (&id->right.sym, sym)) + { + extend_match (&id->right, sym, &right_ids, FALSE); + } /* if */ + } /* for */ + } /* for */ + + /* create tables of appropriate size and reset lengths: */ + + for (tab = syms; tab < &syms[NUM_TABLES]; ++tab) + { + if (tab->len) + { + tab->base = (Sym *) xmalloc (tab->len * sizeof (Sym)); + tab->limit = tab->base + tab->len; + tab->len = 0; + } /* if */ + } /* for */ + if (right_ids.len) + { + right_ids.base = (Sym *) xmalloc (right_ids.len * sizeof (Sym)); + right_ids.limit = right_ids.base + right_ids.len; + right_ids.len = 0; + } /* if */ + + /* 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); + } /* if */ + if (id->has_right && match (&id->right.sym, sym)) + { + extend_match (&id->right, sym, &right_ids, TRUE); + } /* if */ + } /* for */ + } /* for */ + + /* go through ids creating arcs as needed: */ + + for (id = id_list; id; id = id->next) + { + if (id->has_right) + { + for (left = id->left.first_match; left; left = left->next) + { + for (right = id->right.first_match; right; right = right->next) { - DBG(IDDEBUG, - printf( -"[sym_id_parse]: arc %s:%s(%lx-%lx) -> %s:%s(%lx-%lx) to %s\n", - left->file ? left->file->name : "*", - left->name ? left->name : "*", left->addr, - left->end_addr, - right->file ? right->file->name : "*", - right->name ? right->name : "*", right->addr, - right->end_addr, - table_name[id->which_table])); - arc_add(left, right, 0); - } /* for */ - } /* for */ - } /* if */ - } /* for */ - - /* 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", + DBG (IDDEBUG, + printf ( + "[sym_id_parse]: arc %s:%s(%lx-%lx) -> %s:%s(%lx-%lx) to %s\n", + left->file ? left->file->name : "*", + left->name ? left->name : "*", left->addr, + left->end_addr, + right->file ? right->file->name : "*", + right->name ? right->name : "*", right->addr, + right->end_addr, + table_name[id->which_table])); + arc_add (left, right, 0); + } /* for */ + } /* for */ + } /* if */ + } /* for */ + + /* 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", table_name[tab - &syms[0]])); - symtab_finalize(tab); - } /* for */ -} /* sym_id_parse */ + symtab_finalize (tab); + } /* for */ +} /* sym_id_parse */ /* @@ -297,19 +353,20 @@ DEFUN_VOID(sym_id_parse) * tolerable. */ bool -DEFUN(sym_id_arc_is_present, (symtab, from, to), - Sym_Table *symtab AND Sym *from AND Sym *to) +DEFUN (sym_id_arc_is_present, (symtab, from, to), + Sym_Table * symtab AND Sym * from AND Sym * to) { - Sym *sym; + Sym *sym; - for (sym = symtab->base; sym < symtab->limit; ++sym) { - if (from->addr >= sym->addr && from->addr <= sym->end_addr - && arc_lookup(sym, to)) + for (sym = symtab->base; sym < symtab->limit; ++sym) + { + if (from->addr >= sym->addr && from->addr <= sym->end_addr + && arc_lookup (sym, to)) { - return TRUE; - } /* if */ - } /* for */ - return FALSE; -} /* sym_id_arc_is_present */ + return TRUE; + } /* if */ + } /* for */ + return FALSE; +} /* sym_id_arc_is_present */ - /*** end of sym_ids.h ***/ +/*** end of sym_ids.h ***/ diff --git a/gprof/sym_ids.h b/gprof/sym_ids.h index 68604de..9096338 100644 --- a/gprof/sym_ids.h +++ b/gprof/sym_ids.h @@ -3,7 +3,8 @@ #include "symtab.h" -typedef enum { +typedef enum + { INCL_GRAPH = 0, EXCL_GRAPH, INCL_ARCS, EXCL_ARCS, INCL_FLAT, EXCL_FLAT, @@ -11,13 +12,14 @@ typedef enum { INCL_ANNO, EXCL_ANNO, INCL_EXEC, EXCL_EXEC, NUM_TABLES -} Table_Id; + } +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 *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)); #endif /* sym_ids_h */ diff --git a/gprof/symtab.c b/gprof/symtab.c index 6591844..aab4ca2 100644 --- a/gprof/symtab.c +++ b/gprof/symtab.c @@ -10,19 +10,19 @@ Sym_Table symtab; * Initialize a symbol (so it's empty). */ void -DEFUN(sym_init, (sym), Sym *sym) +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: - */ - sym->hist.time = 0.0; - sym->cg.child_time = 0.0; - sym->cg.prop.fract = 0.0; - sym->cg.prop.self = 0.0; - sym->cg.prop.child = 0.0; -} /* sym_init */ + 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: + */ + sym->hist.time = 0.0; + sym->cg.child_time = 0.0; + sym->cg.prop.fract = 0.0; + sym->cg.prop.self = 0.0; + sym->cg.prop.child = 0.0; +} /* sym_init */ /* @@ -36,198 +36,232 @@ DEFUN(sym_init, (sym), Sym *sym) * the global symbol survives. */ static int -DEFUN(cmp_addr, (lp, rp), const PTR lp AND const PTR rp) +DEFUN (cmp_addr, (lp, rp), const PTR lp AND const PTR rp) { - Sym *left = (Sym*) lp; - Sym *right = (Sym*) rp; + Sym *left = (Sym *) lp; + Sym *right = (Sym *) rp; - if (left->addr > right->addr) { - return 1; - } else if (left->addr < right->addr) { - return -1; - } /* if */ + if (left->addr > right->addr) + { + return 1; + } + else if (left->addr < right->addr) + { + return -1; + } /* if */ - if (left->is_func != right->is_func) { - return right->is_func - left->is_func; - } /* if */ + if (left->is_func != right->is_func) + { + return right->is_func - left->is_func; + } /* if */ - return left->is_static - right->is_static; -} /* cmp_addr */ + return left->is_static - right->is_static; +} /* cmp_addr */ void -DEFUN(symtab_finalize, (tab), Sym_Table *tab) +DEFUN (symtab_finalize, (tab), Sym_Table * tab) { - Sym *src, *dst; - bfd_vma prev_addr; - - if (!tab->len) { - return; - } /* if */ - - /* - * 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: - */ - 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. - * If both symbols are either static or global, 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->name[0] != '_' && dst[-1].name[0] == '_') - || (src->name[0] - && src->name[1] != '_' && dst[-1].name[1] == '_'))) + Sym *src, *dst; + bfd_vma prev_addr; + + if (!tab->len) + { + return; + } /* if */ + + /* + * 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: + */ + 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. + * If both symbols are either static or global, 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->name[0] != '_' && dst[-1].name[0] == '_') + || (src->name[0] + && src->name[1] != '_' && dst[-1].name[1] == '_'))) { - DBG(AOUTDEBUG|IDDEBUG, - printf("[symtab_finalize] favor %s@%c%c over %s@%c%c", + DBG (AOUTDEBUG | IDDEBUG, + printf ("[symtab_finalize] favor %s@%c%c over %s@%c%c", src->name, src->is_static ? 't' : 'T', src->is_func ? 'F' : 'f', dst[-1].name, dst[-1].is_static ? 't' : 'T', dst[-1].is_func ? 'F' : 'f'); - printf(" (addr=%lx)\n", src->addr)); - dst[-1] = *src; - } else { - DBG(AOUTDEBUG|IDDEBUG, - printf("[symtab_finalize] favor %s@%c%c over %s@%c%c", + printf (" (addr=%lx)\n", src->addr)); + dst[-1] = *src; + } + else + { + DBG (AOUTDEBUG | IDDEBUG, + printf ("[symtab_finalize] favor %s@%c%c over %s@%c%c", dst[-1].name, dst[-1].is_static ? 't' : 'T', dst[-1].is_func ? 'F' : 'f', src->name, src->is_static ? 't' : 'T', src->is_func ? 'F' : 'f'); - printf(" (addr=%lx)\n", src->addr)); - } /* if */ - } else { - if (dst > tab->base && dst[-1].end_addr == 0) { - dst[-1].end_addr = src->addr - 1; - } /* if */ - - /* retain sym only if it has a non-empty address range: */ - if (!src->end_addr || src->addr <= src->end_addr) { - *dst++ = *src; - prev_addr = src->addr; - } /* if */ - } /* if */ - } /* if */ - if (tab->len > 0 && dst[-1].end_addr == 0) { - dst[-1].end_addr = core_text_sect->vma + core_text_sect->_raw_size - 1; - } /* if */ - - DBG(AOUTDEBUG|IDDEBUG, - printf("[symtab_finalize]: removed %d duplicate entries\n", + printf (" (addr=%lx)\n", src->addr)); + } /* if */ + } + else + { + if (dst > tab->base && dst[-1].end_addr == 0) + { + dst[-1].end_addr = src->addr - 1; + } /* if */ + + /* retain sym only if it has a non-empty address range: */ + if (!src->end_addr || src->addr <= src->end_addr) + { + *dst++ = *src; + prev_addr = src->addr; + } /* if */ + } /* if */ + } /* if */ + if (tab->len > 0 && dst[-1].end_addr == 0) + { + dst[-1].end_addr = core_text_sect->vma + core_text_sect->_raw_size - 1; + } /* if */ + + DBG (AOUTDEBUG | IDDEBUG, + printf ("[symtab_finalize]: removed %d duplicate entries\n", tab->len - (int) (dst - tab->base))); - tab->limit = dst; - tab->len = tab->limit - tab->base; + tab->limit = dst; + tab->len = tab->limit - tab->base; - DBG(AOUTDEBUG|IDDEBUG, - int j; + DBG (AOUTDEBUG | IDDEBUG, + 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); - } /* for */); -} /* symtab_finalize */ + 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); + } /* for */ + ); +} /* symtab_finalize */ #ifdef DEBUG -Sym* -DEFUN(dbg_sym_lookup, (symtab, address), Sym_Table *symtab AND bfd_vma address) +Sym * +DEFUN (dbg_sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address) { - long low, mid, high; - Sym *sym; - - fprintf(stderr,"[sym_lookup] address 0x%lx\n", address); - - sym = symtab->base; - 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", - sym[mid].addr, sym[mid + 1].addr); - if (sym[mid].addr <= address && sym[mid + 1].addr > address) { - return &sym[mid]; - } /* if */ - if (sym[mid].addr > address) { - high = mid; - } else { - low = mid + 1; - } /* if */ - } /* for */ - fprintf(stderr, "[sym_lookup] binary search fails???\n"); - return 0; -} /* dbg_sym_lookup */ - -#endif DEBUG + long low, mid, high; + Sym *sym; + + fprintf (stderr, "[sym_lookup] address 0x%lx\n", address); + + sym = symtab->base; + 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", + sym[mid].addr, sym[mid + 1].addr); + if (sym[mid].addr <= address && sym[mid + 1].addr > address) + { + return &sym[mid]; + } /* if */ + if (sym[mid].addr > address) + { + high = mid; + } + else + { + low = mid + 1; + } /* if */ + } /* for */ + fprintf (stderr, "[sym_lookup] binary search fails???\n"); + return 0; +} /* dbg_sym_lookup */ + +#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. */ -Sym* -DEFUN(sym_lookup, (symtab, address), Sym_Table *symtab AND bfd_vma address) +Sym * +DEFUN (sym_lookup, (symtab, address), Sym_Table * symtab AND bfd_vma address) { - long low, high; - long mid = -1; - Sym *sym; -#ifdef DEBUG - int probes = 0; + long low, high; + long mid = -1; + Sym *sym; +#ifdef DEBUG + int probes = 0; #endif /* DEBUG */ - if (!symtab->len) { - return 0; - } /* if */ - - 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]: - */ - return 0; - } else { - DBG(LOOKUPDEBUG, - printf("[sym_lookup] %d probes (symtab->len=%d)\n", + if (!symtab->len) + { + return 0; + } /* if */ + + 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]: + */ + return 0; + } + else + { + DBG (LOOKUPDEBUG, + printf ("[sym_lookup] %d probes (symtab->len=%d)\n", probes, symtab->len - 1)); - return &sym[mid]; - } /* if */ - } /* if */ - if (sym[mid].addr > address) { - high = mid; - } else { - low = mid + 1; - } /* if */ - } /* for */ - if (sym[mid + 1].addr <= address) { - if (address > sym[mid + 1].end_addr) { - /* address is beyond end of sym[mid + 1]: */ - return 0; - } else { - DBG(LOOKUPDEBUG, printf("[sym_lookup] %d (%d) probes, fall off\n", + return &sym[mid]; + } /* if */ + } /* if */ + if (sym[mid].addr > address) + { + high = mid; + } + else + { + low = mid + 1; + } /* if */ + } /* for */ + if (sym[mid + 1].addr <= address) + { + if (address > sym[mid + 1].end_addr) + { + /* address is beyond end of sym[mid + 1]: */ + return 0; + } + else + { + DBG (LOOKUPDEBUG, printf ("[sym_lookup] %d (%d) probes, fall off\n", probes, symtab->len - 1)); - return &sym[mid + 1]; - } /* if */ - } /* if */ - return 0; -} /* sym_lookup */ + return &sym[mid + 1]; + } /* if */ + } /* if */ + return 0; +} /* sym_lookup */ - /*** end of symtab.c ***/ +/*** end of symtab.c ***/ diff --git a/gprof/symtab.h b/gprof/symtab.h index 1702a9c..07c7751 100644 --- a/gprof/symtab.h +++ b/gprof/symtab.h @@ -20,7 +20,8 @@ * 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 { +typedef struct sym + { /* * Common information: * @@ -28,61 +29,72 @@ typedef struct sym { * 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? */ - int ncalls; /* how many times executed */ - struct sym *next; /* for building chains of syms */ + 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? */ + int ncalls; /* how many times executed */ + struct sym *next; /* for building chains of syms */ /* profile-specific information: */ /* histogram specific info: */ - struct { - double time; /* (weighted) ticks in this routine */ - bfd_vma scaled_addr; /* scaled entry point */ - } hist; + struct + { + double time; /* (weighted) ticks in this routine */ + bfd_vma scaled_addr; /* scaled entry point */ + } + hist; /* call-graph specific info: */ - struct { - int 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 */ - } prop; - struct { - 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 */ - } cg; -} Sym; + struct + { + int 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 */ + } + prop; + struct + { + 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 */ + } + cg; + } +Sym; /* * Symbol-tables are always assumed to be sorted in increasing order * of addresses: */ -typedef struct { - int len; /* # of symbols in this table */ - Sym *base; /* first element in symbol table */ - Sym *limit; /* limit = base + len */ -} Sym_Table; +typedef struct + { + 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 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 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)); #endif /* symtab_h */ diff --git a/gprof/tahoe.c b/gprof/tahoe.c index 5e3d7d9..e02bbb0 100644 --- a/gprof/tahoe.c +++ b/gprof/tahoe.c @@ -26,279 +26,293 @@ Sym indirectchild; operandenum -operandmode(modep) - unsigned char *modep; +operandmode (modep) + unsigned char *modep; { - long usesreg = ((long)*modep) & 0xf; - - switch (((long)*modep) >> 4) { - case 0: - case 1: - case 2: - case 3: - return literal; - case 4: - return indexed; - case 5: - return reg; - case 6: - return regdef; - case 7: - return autodec; - case 8: - return usesreg != 0xe ? autoinc : immediate; - case 9: - return usesreg != PC ? autoincdef : absolute; - case 10: - return usesreg != PC ? bytedisp : byterel; - case 11: - return usesreg != PC ? bytedispdef : bytereldef; - case 12: - return usesreg != PC ? worddisp : wordrel; - case 13: - return usesreg != PC ? worddispdef : wordreldef; - case 14: - return usesreg != PC ? longdisp : longrel; - case 15: - return usesreg != PC ? longdispdef : longreldef; + long usesreg = ((long) *modep) & 0xf; + + switch (((long) *modep) >> 4) + { + case 0: + case 1: + case 2: + case 3: + return literal; + case 4: + return indexed; + case 5: + return reg; + case 6: + return regdef; + case 7: + return autodec; + case 8: + return usesreg != 0xe ? autoinc : immediate; + case 9: + return usesreg != PC ? autoincdef : absolute; + case 10: + return usesreg != PC ? bytedisp : byterel; + case 11: + return usesreg != PC ? bytedispdef : bytereldef; + case 12: + return usesreg != PC ? worddisp : wordrel; + case 13: + return usesreg != PC ? worddispdef : wordreldef; + case 14: + return usesreg != PC ? longdisp : longrel; + case 15: + return usesreg != PC ? longdispdef : longreldef; } - /* NOTREACHED */ + /* NOTREACHED */ } char * -operandname(mode) - operandenum mode; +operandname (mode) + operandenum mode; { - - switch (mode) { - case literal: - return "literal"; - case indexed: - return "indexed"; - case reg: - return "register"; - case regdef: - return "register deferred"; - case autodec: - return "autodecrement"; - case autoinc: - return "autoincrement"; - case autoincdef: - return "autoincrement deferred"; - case bytedisp: - return "byte displacement"; - case bytedispdef: - return "byte displacement deferred"; - case byterel: - return "byte relative"; - case bytereldef: - return "byte relative deferred"; - case worddisp: - return "word displacement"; - case worddispdef: - return "word displacement deferred"; - case wordrel: - return "word relative"; - case wordreldef: - return "word relative deferred"; - case immediate: - return "immediate"; - case absolute: - return "absolute"; - case longdisp: - return "long displacement"; - case longdispdef: - return "long displacement deferred"; - case longrel: - return "long relative"; - case longreldef: - return "long relative deferred"; + + switch (mode) + { + case literal: + return "literal"; + case indexed: + return "indexed"; + case reg: + return "register"; + case regdef: + return "register deferred"; + case autodec: + return "autodecrement"; + case autoinc: + return "autoincrement"; + case autoincdef: + return "autoincrement deferred"; + case bytedisp: + return "byte displacement"; + case bytedispdef: + return "byte displacement deferred"; + case byterel: + return "byte relative"; + case bytereldef: + return "byte relative deferred"; + case worddisp: + return "word displacement"; + case worddispdef: + return "word displacement deferred"; + case wordrel: + return "word relative"; + case wordreldef: + return "word relative deferred"; + case immediate: + return "immediate"; + case absolute: + return "absolute"; + case longdisp: + return "long displacement"; + case longdispdef: + return "long displacement deferred"; + case longrel: + return "long relative"; + case longreldef: + return "long relative deferred"; } - /* NOTREACHED */ + /* NOTREACHED */ } long -operandlength(modep) - unsigned char *modep; +operandlength (modep) + unsigned char *modep; { - - switch (operandmode(modep)) { - case literal: - case reg: - case regdef: - case autodec: - case autoinc: - case autoincdef: - return 1; - case bytedisp: - case bytedispdef: - case byterel: - case bytereldef: - return 2; - case worddisp: - case worddispdef: - case wordrel: - case wordreldef: - return 3; - case immediate: - case absolute: - case longdisp: - case longdispdef: - case longrel: - case longreldef: - return 5; - case indexed: - return 1+operandlength(modep + 1); + + switch (operandmode (modep)) + { + case literal: + case reg: + case regdef: + case autodec: + case autoinc: + case autoincdef: + return 1; + case bytedisp: + case bytedispdef: + case byterel: + case bytereldef: + return 2; + case worddisp: + case worddispdef: + case wordrel: + case wordreldef: + return 3; + case immediate: + case absolute: + case longdisp: + case longdispdef: + case longrel: + case longreldef: + return 5; + case indexed: + return 1 + operandlength (modep + 1); } - /* NOTREACHED */ + /* NOTREACHED */ } bfd_vma -reladdr(modep) - char *modep; +reladdr (modep) + char *modep; { - operandenum mode = operandmode(modep); - char *cp; - short *sp; - long *lp; - int i; - long value = 0; + operandenum mode = operandmode (modep); + char *cp; + short *sp; + long *lp; + int i; + long value = 0; - cp = modep; - ++cp; /* skip over the mode */ - switch (mode) { - default: - fprintf(stderr, "[reladdr] not relative address\n"); - return (bfd_vma) modep; - case byterel: - return (bfd_vma) (cp + sizeof *cp + *cp); - case wordrel: - for (i = 0; i < sizeof *sp; i++) - value = (value << 8) + (cp[i] & 0xff); - return (bfd_vma) (cp + sizeof *sp + value); - case longrel: - for (i = 0; i < sizeof *lp; i++) - value = (value << 8) + (cp[i] & 0xff); - return (bfd_vma) (cp + sizeof *lp + value); + cp = modep; + ++cp; /* skip over the mode */ + switch (mode) + { + default: + fprintf (stderr, "[reladdr] not relative address\n"); + return (bfd_vma) modep; + case byterel: + return (bfd_vma) (cp + sizeof *cp + *cp); + case wordrel: + for (i = 0; i < sizeof *sp; i++) + value = (value << 8) + (cp[i] & 0xff); + return (bfd_vma) (cp + sizeof *sp + value); + case longrel: + for (i = 0; i < sizeof *lp; i++) + value = (value << 8) + (cp[i] & 0xff); + return (bfd_vma) (cp + sizeof *lp + value); } } -find_call(parent, p_lowpc, p_highpc) +find_call (parent, p_lowpc, p_highpc) Sym *parent; bfd_vma p_lowpc; bfd_vma p_highpc; { - unsigned char *instructp; - long length; - Sym *child; - operandenum mode; - operandenum firstmode; - bfd_vma destpc; - static bool inited = FALSE; + unsigned char *instructp; + long length; + Sym *child; + operandenum mode; + operandenum firstmode; + bfd_vma destpc; + static bool inited = FALSE; - if (!inited) { - inited = TRUE; - sym_init(&indirectchild); - indirectchild.cg.prop.fract = 1.0; - indirectchild.cg.cyc.head = &indirectchild; - } /* if */ + if (!inited) + { + inited = TRUE; + sym_init (&indirectchild); + indirectchild.cg.prop.fract = 1.0; + indirectchild.cg.cyc.head = &indirectchild; + } /* if */ - if (textspace == 0) { - return; + if (textspace == 0) + { + return; } - if (p_lowpc < s_lowpc) { - p_lowpc = s_lowpc; + if (p_lowpc < s_lowpc) + { + p_lowpc = s_lowpc; } - if (p_highpc > s_highpc) { - p_highpc = s_highpc; + if (p_highpc > s_highpc) + { + p_highpc = s_highpc; } - DBG(CALLDEBUG, printf("[findcall] %s: 0x%x to 0x%x\n", - parent -> name, p_lowpc, p_highpc)); - for ( instructp = textspace + p_lowpc ; - instructp < textspace + p_highpc ; - instructp += length) { - length = 1; - if (*instructp == CALLF) { - /* - * maybe a callf, better check it out. - * skip the count of the number of arguments. - */ - DBG(CALLDEBUG, printf("[findcall]\t0x%x:callf", + DBG (CALLDEBUG, printf ("[findcall] %s: 0x%x to 0x%x\n", + parent->name, p_lowpc, p_highpc)); + for (instructp = textspace + p_lowpc; + instructp < textspace + p_highpc; + instructp += length) + { + length = 1; + if (*instructp == CALLF) + { + /* + * maybe a callf, better check it out. + * skip the count of the number of arguments. + */ + DBG (CALLDEBUG, printf ("[findcall]\t0x%x:callf", instructp - textspace)); - firstmode = operandmode(instructp+length); - switch (firstmode) { - case literal: - case immediate: - break; - default: - goto botched; + firstmode = operandmode (instructp + length); + switch (firstmode) + { + case literal: + case immediate: + break; + default: + goto botched; } - length += operandlength(instructp+length); - mode = operandmode(instructp + length); - DBG(CALLDEBUG, - printf("\tfirst operand is %s", operandname(firstmode)); - printf("\tsecond operand is %s\n", operandname(mode)); - ); - switch (mode) { - case regdef: - case bytedispdef: - case worddispdef: - case longdispdef: - case bytereldef: - case wordreldef: - case longreldef: - /* - * indirect call: call through pointer - * either *d(r) as a parameter or local - * (r) as a return value - * *f as a global pointer - * [are there others that we miss?, - * e.g. arrays of pointers to functions???] - */ - arc_add(parent, &indirectchild, (long) 0); - length += operandlength(instructp + length); - continue; - case byterel: - case wordrel: - case longrel: - /* - * regular pc relative addressing - * check that this is the address of - * a function. - */ - destpc = reladdr(instructp+length) - - (bfd_vma) textspace; - if (destpc >= s_lowpc && destpc <= s_highpc) { - child = sym_lookup(destpc); - DBG(CALLDEBUG, - printf("[findcall]\tdestpc 0x%x", destpc); - printf(" child->name %s", child -> name); - printf(" child->addr 0x%x\n", child -> addr); - ); - if (child -> addr == destpc) { - /* - * a hit - */ - arc_add(parent, child, (long) 0); - length += operandlength(instructp + length); - continue; - } - goto botched; + length += operandlength (instructp + length); + mode = operandmode (instructp + length); + DBG (CALLDEBUG, + printf ("\tfirst operand is %s", operandname (firstmode)); + printf ("\tsecond operand is %s\n", operandname (mode)); + ); + switch (mode) + { + case regdef: + case bytedispdef: + case worddispdef: + case longdispdef: + case bytereldef: + case wordreldef: + case longreldef: + /* + * indirect call: call through pointer + * either *d(r) as a parameter or local + * (r) as a return value + * *f as a global pointer + * [are there others that we miss?, + * e.g. arrays of pointers to functions???] + */ + arc_add (parent, &indirectchild, (long) 0); + length += operandlength (instructp + length); + continue; + case byterel: + case wordrel: + case longrel: + /* + * regular pc relative addressing + * check that this is the address of + * a function. + */ + destpc = reladdr (instructp + length) + - (bfd_vma) textspace; + if (destpc >= s_lowpc && destpc <= s_highpc) + { + child = sym_lookup (destpc); + DBG (CALLDEBUG, + printf ("[findcall]\tdestpc 0x%x", destpc); + printf (" child->name %s", child->name); + printf (" child->addr 0x%x\n", child->addr); + ); + if (child->addr == destpc) + { + /* + * a hit + */ + arc_add (parent, child, (long) 0); + length += operandlength (instructp + length); + continue; } - /* - * else: - * it looked like a callf, - * but it wasn't to anywhere. - */ - goto botched; - default: - botched: - /* - * something funny going on. - */ - DBG(CALLDEBUG, printf("[findcall]\tbut it's a botch\n")); - length = 1; - continue; + goto botched; + } + /* + * else: + * it looked like a callf, + * but it wasn't to anywhere. + */ + goto botched; + default: + botched: + /* + * something funny going on. + */ + DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n")); + length = 1; + continue; } } } diff --git a/gprof/tahoe.h b/gprof/tahoe.h index 1e311b8..4d153a4 100644 --- a/gprof/tahoe.h +++ b/gprof/tahoe.h @@ -16,30 +16,31 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#)tahoe.h 1.4 (Berkeley) 6/1/90 + * @(#)tahoe.h 1.4 (Berkeley) 6/1/90 */ /* - * opcode of the `callf' instruction + * opcode of the `callf' instruction */ #define CALLF 0xfe /* - * offset (in bytes) of the code from the entry address of a routine. - * (see asgnsamples for use and explanation.) + * offset (in bytes) of the code from the entry address of a routine. + * (see asgnsamples for use and explanation.) */ #define OFFSET_TO_CODE 2 #define UNITS_TO_CODE (OFFSET_TO_CODE / sizeof(UNIT)) /* - * register for pc relative addressing + * register for pc relative addressing */ #define PC 0xf -enum opermodes { - literal, indexed, reg, regdef, autodec, autoinc, autoincdef, +enum opermodes + { + literal, indexed, reg, regdef, autodec, autoinc, autoincdef, bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef, immediate, absolute, byterel, bytereldef, wordrel, wordreldef, longrel, longreldef -}; -typedef enum opermodes operandenum; + }; +typedef enum opermodes operandenum; diff --git a/gprof/utils.c b/gprof/utils.c index 9549a8d..19ea34b 100644 --- a/gprof/utils.c +++ b/gprof/utils.c @@ -26,65 +26,80 @@ * Print name of symbol. Return number of characters printed. */ int -DEFUN(print_name_only, (self), Sym *self) +DEFUN (print_name_only, (self), Sym * self) { - const char *name = self->name; - const char *filename; - char *demangled = 0; - char buf[PATH_MAX]; - int size = 0; + const char *name = self->name; + const char *filename; + char *demangled = 0; + char buf[PATH_MAX]; + int size = 0; - if (name) { - if (!bsd_style_output) { - if (name[0] == '_' && name[1] && discard_underscores) { - name++; - } /* if */ - demangled = cplus_demangle(name, DMGL_ANSI|DMGL_PARAMS); - if (demangled) { - name = demangled; - } /* if */ - } /* if */ - printf("%s", name); - size = strlen(name); - if (line_granularity && self->file) { - filename = self->file->name; - if (!print_path) { - filename = strrchr(filename, '/'); - if (filename) { - ++filename; - } else { - filename = self->file->name; - } /* if */ - } /* if */ - sprintf(buf, " (%s:%d)", filename, self->line_num); - printf(buf); - size += strlen(buf); - } /* if */ - if (demangled) { - free(demangled); - } /* if */ - DBG(DFNDEBUG, printf("{%d} ", self->cg.top_order)); - DBG(PROPDEBUG, printf("%4.0f%% ", 100.0 * self->cg.prop.fract)); - } /* if */ - return size; -} /* print_name_only */ + if (name) + { + if (!bsd_style_output) + { + if (name[0] == '_' && name[1] && discard_underscores) + { + name++; + } /* if */ + demangled = cplus_demangle (name, DMGL_ANSI | DMGL_PARAMS); + if (demangled) + { + name = demangled; + } /* if */ + } /* if */ + printf ("%s", name); + size = strlen (name); + if (line_granularity && self->file) + { + filename = self->file->name; + if (!print_path) + { + filename = strrchr (filename, '/'); + if (filename) + { + ++filename; + } + else + { + filename = self->file->name; + } /* if */ + } /* if */ + sprintf (buf, " (%s:%d)", filename, self->line_num); + printf (buf); + size += strlen (buf); + } /* if */ + if (demangled) + { + free (demangled); + } /* if */ + DBG (DFNDEBUG, printf ("{%d} ", self->cg.top_order)); + DBG (PROPDEBUG, printf ("%4.0f%% ", 100.0 * self->cg.prop.fract)); + } /* if */ + return size; +} /* print_name_only */ void -DEFUN(print_name, (self), Sym *self) +DEFUN (print_name, (self), Sym * self) { - print_name_only(self); + print_name_only (self); - if (self->cg.cyc.num != 0) { - printf(" ", self->cg.cyc.num); - } /* if */ - if (self->cg.index != 0) { - if (self->cg.print_flag) { - printf(" [%d]", self->cg.index); - } else { - printf(" (%d)", self->cg.index); - } /* if */ - } /* if */ -} /* print_name */ + if (self->cg.cyc.num != 0) + { + printf (" ", self->cg.cyc.num); + } /* if */ + if (self->cg.index != 0) + { + if (self->cg.print_flag) + { + printf (" [%d]", self->cg.index); + } + else + { + printf (" (%d)", self->cg.index); + } /* if */ + } /* if */ +} /* print_name */ - /*** end of utils.c ***/ +/*** end of utils.c ***/ diff --git a/gprof/utils.h b/gprof/utils.h index 7f5d342..27fb9c6 100644 --- a/gprof/utils.h +++ b/gprof/utils.h @@ -1,7 +1,7 @@ #ifndef utils_h #define utils_h -extern int print_name_only PARAMS((Sym *self)); -extern void print_name PARAMS((Sym *self)); +extern int print_name_only PARAMS ((Sym * self)); +extern void print_name PARAMS ((Sym * self)); #endif /* utils_h */ diff --git a/gprof/vax.c b/gprof/vax.c index 7bde442..8b70699 100644 --- a/gprof/vax.c +++ b/gprof/vax.c @@ -30,279 +30,293 @@ Sym indirectchild; static operandenum -operandmode(modep) - struct modebyte *modep; +operandmode (modep) + struct modebyte *modep; { - long usesreg = modep->regfield; - - switch (modep->modefield) { - case 0: - case 1: - case 2: - case 3: - return literal; - case 4: - return indexed; - case 5: - return reg; - case 6: - return regdef; - case 7: - return autodec; - case 8: - return usesreg != PC ? autoinc : immediate; - case 9: - return usesreg != PC ? autoincdef : absolute; - case 10: - return usesreg != PC ? bytedisp : byterel; - case 11: - return usesreg != PC ? bytedispdef : bytereldef; - case 12: - return usesreg != PC ? worddisp : wordrel; - case 13: - return usesreg != PC ? worddispdef : wordreldef; - case 14: - return usesreg != PC ? longdisp : longrel; - case 15: - return usesreg != PC ? longdispdef : longreldef; + long usesreg = modep->regfield; + + switch (modep->modefield) + { + case 0: + case 1: + case 2: + case 3: + return literal; + case 4: + return indexed; + case 5: + return reg; + case 6: + return regdef; + case 7: + return autodec; + case 8: + return usesreg != PC ? autoinc : immediate; + case 9: + return usesreg != PC ? autoincdef : absolute; + case 10: + return usesreg != PC ? bytedisp : byterel; + case 11: + return usesreg != PC ? bytedispdef : bytereldef; + case 12: + return usesreg != PC ? worddisp : wordrel; + case 13: + return usesreg != PC ? worddispdef : wordreldef; + case 14: + return usesreg != PC ? longdisp : longrel; + case 15: + return usesreg != PC ? longdispdef : longreldef; } - /* NOTREACHED */ + /* NOTREACHED */ } static char * -operandname(mode) - operandenum mode; +operandname (mode) + operandenum mode; { - - switch (mode) { - case literal: - return "literal"; - case indexed: - return "indexed"; - case reg: - return "register"; - case regdef: - return "register deferred"; - case autodec: - return "autodecrement"; - case autoinc: - return "autoincrement"; - case autoincdef: - return "autoincrement deferred"; - case bytedisp: - return "byte displacement"; - case bytedispdef: - return "byte displacement deferred"; - case byterel: - return "byte relative"; - case bytereldef: - return "byte relative deferred"; - case worddisp: - return "word displacement"; - case worddispdef: - return "word displacement deferred"; - case wordrel: - return "word relative"; - case wordreldef: - return "word relative deferred"; - case immediate: - return "immediate"; - case absolute: - return "absolute"; - case longdisp: - return "long displacement"; - case longdispdef: - return "long displacement deferred"; - case longrel: - return "long relative"; - case longreldef: - return "long relative deferred"; + + switch (mode) + { + case literal: + return "literal"; + case indexed: + return "indexed"; + case reg: + return "register"; + case regdef: + return "register deferred"; + case autodec: + return "autodecrement"; + case autoinc: + return "autoincrement"; + case autoincdef: + return "autoincrement deferred"; + case bytedisp: + return "byte displacement"; + case bytedispdef: + return "byte displacement deferred"; + case byterel: + return "byte relative"; + case bytereldef: + return "byte relative deferred"; + case worddisp: + return "word displacement"; + case worddispdef: + return "word displacement deferred"; + case wordrel: + return "word relative"; + case wordreldef: + return "word relative deferred"; + case immediate: + return "immediate"; + case absolute: + return "absolute"; + case longdisp: + return "long displacement"; + case longdispdef: + return "long displacement deferred"; + case longrel: + return "long relative"; + case longreldef: + return "long relative deferred"; } - /* NOTREACHED */ + /* NOTREACHED */ } static long -operandlength(modep) - struct modebyte *modep; +operandlength (modep) + struct modebyte *modep; { - - switch (operandmode(modep)) { - case literal: - case reg: - case regdef: - case autodec: - case autoinc: - case autoincdef: - return 1; - case bytedisp: - case bytedispdef: - case byterel: - case bytereldef: - return 2; - case worddisp: - case worddispdef: - case wordrel: - case wordreldef: - return 3; - case immediate: - case absolute: - case longdisp: - case longdispdef: - case longrel: - case longreldef: - return 5; - case indexed: - return 1+operandlength((struct modebyte *) ((char *) modep) + 1); + + switch (operandmode (modep)) + { + case literal: + case reg: + case regdef: + case autodec: + case autoinc: + case autoincdef: + return 1; + case bytedisp: + case bytedispdef: + case byterel: + case bytereldef: + return 2; + case worddisp: + case worddispdef: + case wordrel: + case wordreldef: + return 3; + case immediate: + case absolute: + case longdisp: + case longdispdef: + case longrel: + case longreldef: + return 5; + case indexed: + return 1 + operandlength ((struct modebyte *) ((char *) modep) + 1); } - /* NOTREACHED */ + /* NOTREACHED */ } static bfd_vma -reladdr(modep) - struct modebyte *modep; +reladdr (modep) + struct modebyte *modep; { - operandenum mode = operandmode(modep); - char *cp; - short *sp; - long *lp; + operandenum mode = operandmode (modep); + char *cp; + short *sp; + long *lp; - cp = (char *) modep; - ++cp; /* skip over the mode */ - switch (mode) { - default: - fprintf(stderr, "[reladdr] not relative address\n"); - return (bfd_vma) modep; - case byterel: - return (bfd_vma) (cp + sizeof *cp + *cp); - case wordrel: - sp = (short *) cp; - return (bfd_vma) (cp + sizeof *sp + *sp); - case longrel: - lp = (long *) cp; - return (bfd_vma) (cp + sizeof *lp + *lp); + cp = (char *) modep; + ++cp; /* skip over the mode */ + switch (mode) + { + default: + fprintf (stderr, "[reladdr] not relative address\n"); + return (bfd_vma) modep; + case byterel: + return (bfd_vma) (cp + sizeof *cp + *cp); + case wordrel: + sp = (short *) cp; + return (bfd_vma) (cp + sizeof *sp + *sp); + case longrel: + lp = (long *) cp; + return (bfd_vma) (cp + sizeof *lp + *lp); } } void -find_call(parent, p_lowpc, p_highpc) +find_call (parent, p_lowpc, p_highpc) Sym *parent; bfd_vma p_lowpc; bfd_vma p_highpc; { - unsigned char *instructp; - long length; - Sym *child; - operandenum mode; - operandenum firstmode; - bfd_vma destpc; - static bool inited = FALSE; + unsigned char *instructp; + long length; + Sym *child; + operandenum mode; + operandenum firstmode; + bfd_vma destpc; + static bool inited = FALSE; - if (!inited) { - inited = TRUE; - sym_init(&indirectchild); - indirectchild.cg.prop.fract = 1.0; - indirectchild.cg.cyc.head = &indirectchild; - } /* if */ + if (!inited) + { + inited = TRUE; + sym_init (&indirectchild); + indirectchild.cg.prop.fract = 1.0; + indirectchild.cg.cyc.head = &indirectchild; + } /* if */ - if (core_text_space == 0) { - return; + if (core_text_space == 0) + { + return; } - if (p_lowpc < s_lowpc) { - p_lowpc = s_lowpc; + if (p_lowpc < s_lowpc) + { + p_lowpc = s_lowpc; } - if (p_highpc > s_highpc) { - p_highpc = s_highpc; + if (p_highpc > s_highpc) + { + p_highpc = s_highpc; } - DBG(CALLDEBUG, printf("[findcall] %s: 0x%lx to 0x%lx\n", + DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n", parent->name, p_lowpc, p_highpc)); - for ( instructp = (unsigned char*) core_text_space + p_lowpc ; - instructp < (unsigned char*) core_text_space + p_highpc ; - instructp += length) { - length = 1; - if (*instructp == CALLS) { - /* - * maybe a calls, better check it out. - * skip the count of the number of arguments. - */ - DBG(CALLDEBUG, - printf("[findcall]\t0x%x:calls", - instructp - (unsigned char*) core_text_space)); - firstmode = operandmode((struct modebyte *) (instructp+length)); - switch (firstmode) { - case literal: - case immediate: - break; - default: - goto botched; + for (instructp = (unsigned char *) core_text_space + p_lowpc; + instructp < (unsigned char *) core_text_space + p_highpc; + instructp += length) + { + length = 1; + if (*instructp == CALLS) + { + /* + * maybe a calls, better check it out. + * skip the count of the number of arguments. + */ + DBG (CALLDEBUG, + printf ("[findcall]\t0x%x:calls", + instructp - (unsigned char *) core_text_space)); + firstmode = operandmode ((struct modebyte *) (instructp + length)); + switch (firstmode) + { + case literal: + case immediate: + break; + default: + goto botched; } - length += operandlength((struct modebyte *) (instructp+length)); - mode = operandmode((struct modebyte *) (instructp + length)); - DBG(CALLDEBUG, - printf("\tfirst operand is %s", operandname(firstmode)); - printf("\tsecond operand is %s\n", operandname(mode))); - switch (mode) { - case regdef: - case bytedispdef: - case worddispdef: - case longdispdef: - case bytereldef: - case wordreldef: - case longreldef: - /* - * indirect call: call through pointer - * either *d(r) as a parameter or local - * (r) as a return value - * *f as a global pointer - * [are there others that we miss?, - * e.g. arrays of pointers to functions???] - */ - arc_add(parent, &indirectchild, (long) 0); - length += operandlength( - (struct modebyte *) (instructp + length)); - continue; - case byterel: - case wordrel: - case longrel: - /* - * regular pc relative addressing - * check that this is the address of - * a function. - */ - destpc = reladdr((struct modebyte *) (instructp+length)) - - (bfd_vma) core_text_space; - if (destpc >= s_lowpc && destpc <= s_highpc) { - child = sym_lookup(&symtab, destpc); - DBG(CALLDEBUG, - printf("[findcall]\tdestpc 0x%lx", destpc); - printf(" child->name %s", child->name); - printf(" child->addr 0x%lx\n", child->addr); - ); - if (child->addr == destpc) { - /* - * a hit - */ - arc_add(parent, child, (long) 0); - length += operandlength((struct modebyte *) - (instructp + length)); - continue; - } - goto botched; + length += operandlength ((struct modebyte *) (instructp + length)); + mode = operandmode ((struct modebyte *) (instructp + length)); + DBG (CALLDEBUG, + printf ("\tfirst operand is %s", operandname (firstmode)); + printf ("\tsecond operand is %s\n", operandname (mode))); + switch (mode) + { + case regdef: + case bytedispdef: + case worddispdef: + case longdispdef: + case bytereldef: + case wordreldef: + case longreldef: + /* + * indirect call: call through pointer + * either *d(r) as a parameter or local + * (r) as a return value + * *f as a global pointer + * [are there others that we miss?, + * e.g. arrays of pointers to functions???] + */ + arc_add (parent, &indirectchild, (long) 0); + length += operandlength ( + (struct modebyte *) (instructp + length)); + continue; + case byterel: + case wordrel: + case longrel: + /* + * regular pc relative addressing + * check that this is the address of + * a function. + */ + destpc = reladdr ((struct modebyte *) (instructp + length)) + - (bfd_vma) core_text_space; + if (destpc >= s_lowpc && destpc <= s_highpc) + { + child = sym_lookup (&symtab, destpc); + DBG (CALLDEBUG, + printf ("[findcall]\tdestpc 0x%lx", destpc); + printf (" child->name %s", child->name); + printf (" child->addr 0x%lx\n", child->addr); + ); + if (child->addr == destpc) + { + /* + * a hit + */ + arc_add (parent, child, (long) 0); + length += operandlength ((struct modebyte *) + (instructp + length)); + continue; } - /* - * else: - * it looked like a calls, - * but it wasn't to anywhere. - */ - goto botched; - default: - botched: - /* - * something funny going on. - */ - DBG(CALLDEBUG, printf("[findcall]\tbut it's a botch\n")); - length = 1; - continue; + goto botched; + } + /* + * else: + * it looked like a calls, + * but it wasn't to anywhere. + */ + goto botched; + default: + botched: + /* + * something funny going on. + */ + DBG (CALLDEBUG, printf ("[findcall]\tbut it's a botch\n")); + length = 1; + continue; } } } diff --git a/gprof/vax.h b/gprof/vax.h index a8edc54..69ec9c2 100644 --- a/gprof/vax.h +++ b/gprof/vax.h @@ -16,36 +16,37 @@ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * - * @(#)vax.h 5.4 (Berkeley) 6/1/90 + * @(#)vax.h 5.4 (Berkeley) 6/1/90 */ /* - * opcode of the `calls' instruction + * opcode of the `calls' instruction */ #define CALLS 0xfb /* - * offset (in bytes) of the code from the entry address of a routine. - * (see asgnsamples for use and explanation.) + * offset (in bytes) of the code from the entry address of a routine. + * (see asgnsamples for use and explanation.) */ #define OFFSET_TO_CODE 2 #define UNITS_TO_CODE (OFFSET_TO_CODE / sizeof(UNIT)) /* - * register for pc relative addressing + * register for pc relative addressing */ #define PC 0xf -enum opermodes { - literal, indexed, reg, regdef, autodec, autoinc, autoincdef, +enum opermodes + { + literal, indexed, reg, regdef, autodec, autoinc, autoincdef, bytedisp, bytedispdef, worddisp, worddispdef, longdisp, longdispdef, immediate, absolute, byterel, bytereldef, wordrel, wordreldef, longrel, longreldef -}; -typedef enum opermodes operandenum; - -struct modebyte { - unsigned int regfield:4; - unsigned int modefield:4; -}; + }; +typedef enum opermodes operandenum; +struct modebyte + { + unsigned int regfield:4; + unsigned int modefield:4; + }; -- cgit v1.1