diff options
author | Ian Lance Taylor <ian@airs.com> | 1998-02-04 00:30:48 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 1998-02-04 00:30:48 +0000 |
commit | 7862d7d065c91e32b2d1d12590b0b6219034c7cf (patch) | |
tree | 7bfb85a6bfb8c0c2cfe349a141e1696916a442f7 /gprof/basic_blocks.c | |
parent | 70b3329c0cdaac62bf1ea1b8bc8b133439420234 (diff) | |
download | gdb-7862d7d065c91e32b2d1d12590b0b6219034c7cf.zip gdb-7862d7d065c91e32b2d1d12590b0b6219034c7cf.tar.gz gdb-7862d7d065c91e32b2d1d12590b0b6219034c7cf.tar.bz2 |
Tue Feb 3 14:25:25 1998 Brent Baccala <baccala@freesoft.org>
* symtab.c (symtab_finalize): Prefer function symbols over line
symbols.
(dbg_sym_lookup): Correct debugging messages.
* gprof.c (main): --sum implies --line.
* cg_print.c (cg_print): When doing line by line profiling, don't
use a non-function as a main listing item.
* call_graph.c (cg_tally): When using line by line profiling, use
the function symbol as the child.
* symtab.h (NBBS): Define.
(Sym): Add bb_addr and bb_calls fields.
* basic_blocks.c (bb_read_rec): Save multiple basic blocks per
symbol.
(bb_write_blocks): Adjust for multiple basic blocks per symbol.
(print_exec_counts): Don't check whether a symbol is the start of
a basic block. Print all basic blocks for a symbol.
(annotate_with_count): Rewrite to print all basic block counts and
to pay attention to width argument.
(print_annotated_source): Don't check whether symbol is the start
of a basic block.
Diffstat (limited to 'gprof/basic_blocks.c')
-rw-r--r-- | gprof/basic_blocks.c | 250 |
1 files changed, 182 insertions, 68 deletions
diff --git a/gprof/basic_blocks.c b/gprof/basic_blocks.c index 2502803..7420174 100644 --- a/gprof/basic_blocks.c +++ b/gprof/basic_blocks.c @@ -30,10 +30,11 @@ static long num_lines_executed; /* - * Helper for sorting. Compares two basic-blocks and returns result + * Helper for sorting. Compares two symbols and returns result * such that sorting will be increasing according to filename, line - * number, and basic-block address (in that order). + * number, and address (in that order). */ + static int DEFUN (cmp_bb, (lp, rp), const void *lp AND const void *rp) { @@ -179,13 +180,28 @@ DEFUN (bb_read_rec, (ifp, filename), FILE * ifp AND const char *filename) /* convert from target to host endianness: */ addr = get_vma (core_bfd, (bfd_byte *) & addr); + 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", - addr, sym->addr, sym->name, sym->ncalls)); + if (sym) + { + int i; + + DBG (BBDEBUG, + printf ("[bb_read_rec] 0x%lx->0x%lx (%s:%d) cnt=%ld\n", + addr, sym->addr, sym->name, sym->line_num, ncalls)); + + for (i = 0; i < NBBS; i++) + { + if (! sym->bb_addr[i] || sym->bb_addr[i] == addr) + { + sym->bb_addr[i] = addr; + sym->bb_calls[i] += ncalls; + break; + } + } + } } else { @@ -217,15 +233,15 @@ DEFUN (bb_write_blocks, (ofp, filename), FILE * ofp AND const char *filename) bfd_vma addr; long ncalls; Sym *sym; + int i; /* count how many non-zero blocks with have: */ for (sym = symtab.base; sym < symtab.limit; ++sym) { - if (sym->ncalls > 0) - { - ++nblocks; - } + for (i = 0; i < NBBS && sym->bb_addr[i]; i++) + ; + nblocks += i; } /* write header: */ @@ -240,19 +256,17 @@ DEFUN (bb_write_blocks, (ofp, filename), FILE * ofp AND const char *filename) /* write counts: */ for (sym = symtab.base; sym < symtab.limit; ++sym) { - if (sym->ncalls == 0) + for (i = 0; i < NBBS && sym->bb_addr[i]; i++) { - continue; - } + put_vma (core_bfd, sym->bb_addr[i], (bfd_byte *) & addr); + bfd_put_32 (core_bfd, sym->bb_calls[i], (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) - { - perror (filename); - done (1); + if (fwrite (&addr, sizeof (addr), 1, ofp) != 1 + || fwrite (&ncalls, sizeof (ncalls), 1, ofp) != 1) + { + perror (filename); + done (1); + } } } } @@ -268,7 +282,7 @@ void DEFUN_VOID (print_exec_counts) { Sym **sorted_bbs, *sym; - int i, len; + int i, j, len; if (first_output) { @@ -286,15 +300,13 @@ DEFUN_VOID (print_exec_counts) 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. + * Accept symbol if it's in the INCL_EXEC table + * or there is no INCL_EXEC table + * and it does not appear in the EXCL_EXEC table. */ - if (sym->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)))) + if (sym_lookup (&syms[INCL_EXEC], sym->addr) + || (syms[INCL_EXEC].len == 0 + && !sym_lookup (&syms[EXCL_EXEC], sym->addr))) { sorted_bbs[len++] = sym; } @@ -305,72 +317,174 @@ DEFUN_VOID (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 : "<unknown>", sym->line_num, - sym->name, sym->addr, sym->ncalls); + if (sym->ncalls > 0 || ! ignore_zeros) + { + printf ("%s:%d: (%s:0x%lx) %d executions\n", + sym->file ? sym->file->name : "<unknown>", sym->line_num, + sym->name, sym->addr, sym->ncalls); + } + for (j = 0; j < NBBS && sym->bb_addr[j]; j ++) + { + if (sym->bb_calls[j] > 0 || ! ignore_zeros) + { + printf ("%s:%d: (%s:0x%lx) %d executions\n", + sym->file ? sym->file->name : "<unknown>", sym->line_num, + sym->name, sym->bb_addr[j], sym->bb_calls[j]); + } + } } free (sorted_bbs); } - /* * Helper for bb_annotated_source: format annotation containing - * number of line executions. + * number of line executions. Depends on being called on each + * line of a file in sequential order. + * + * Global variable bb_annotate_all_lines enables execution count + * compression (counts are supressed if identical to the last one) + * and prints counts on all executed lines. Otherwise, print + * all basic-block execution counts exactly once on the line + * that starts the basic-block. */ + static void DEFUN (annotate_with_count, (buf, width, line_num, arg), char *buf AND int width AND int line_num AND void *arg) { Source_File *sf = arg; Sym *b; - long cnt; - static long last_count; + int i; + static int last_count; + int last_print=-1; - if (line_num == 1) - { - last_count = -1; - } - - b = 0; + b = NULL; if (line_num <= sf->num_lines) { b = sf->line[line_num - 1]; } if (!b) { - cnt = -1; + for (i = 0; i < width; i++) + buf[i] = ' '; + buf[width] = '\0'; } else { + char tmpbuf[NBBS * 30]; + char *p; + int ncalls; + int len; + ++num_executable_lines; - cnt = b->ncalls; - } - if (cnt > 0) - { + + p = tmpbuf; + *p = '\0'; + + ncalls = -1; + + /* If this is a function entry point, label the line no matter what. + * Otherwise, we're in the middle of a function, so check to see + * if the first basic-block address is larger than the starting + * address of the line. If so, then this line begins with a + * a portion of the previous basic-block, so print that prior + * execution count (if bb_annotate_all_lines is set). + */ + + if (b->is_func) + { + sprintf (p, "%d", b->ncalls); + p += strlen (p); + last_count = b->ncalls; + last_print = last_count; + ncalls = b->ncalls; + } + else if (bb_annotate_all_lines + && b->bb_addr[0] && b->bb_addr[0] > b->addr) + { + sprintf (p, "%d", last_count); + p += strlen (p); + last_print = last_count; + ncalls = last_count; + } + + /* Loop through all of this line's basic-blocks. For each one, + * update last_count, then compress sequential identical counts + * (if bb_annotate_all_lines) and print the execution count. + */ + + for (i = 0; i < NBBS && b->bb_addr[i]; i++) + { + last_count = b->bb_calls[i]; + if (ncalls < 0) + ncalls = 0; + ncalls += last_count; + + if (bb_annotate_all_lines && last_count == last_print) + { + continue; + } + + if (p > tmpbuf) + *p++ = ','; + sprintf (p, "%d", last_count); + p += strlen (p); + + last_print = last_count; + } + + /* We're done. If nothing has been printed on this line, + * print the last execution count (bb_annotate_all_lines), + * which could be from either a previous line (if there were + * no BBs on this line), or from this line (if all our BB + * counts were compressed out because they were identical). + */ + + if (bb_annotate_all_lines && p == tmpbuf) + { + sprintf (p, "%d", last_count); + p += strlen (p); + ncalls = last_count; + } + + if (ncalls < 0) + { + int c; + + for (c = 0; c < width; c++) + buf[c] = ' '; + buf[width] = '\0'; + return; + } + ++num_lines_executed; - } - if (cnt < 0 && bb_annotate_all_lines) - { - cnt = last_count; - } - if (cnt < 0) - { - strcpy (buf, "\t\t"); - } - else if (cnt < bb_min_calls) - { - strcpy (buf, " ##### -> "); - } - else - { - sprintf (buf, "%12ld -> ", cnt); + if (ncalls < bb_min_calls) + { + strcpy (tmpbuf, "#####"); + p = tmpbuf + 5; + } + + strcpy (p, " -> "); + p += 4; + + len = p - tmpbuf; + if (len >= width) + { + strncpy (buf, tmpbuf, width); + buf[width] = '\0'; + } + else + { + int c; + + strcpy (buf + width - len, tmpbuf); + for (c = 0; c < width - len; ++c) + buf[c] = ' '; + } } - last_count = cnt; } - /* * Annotate the files named in SOURCE_FILES with basic-block statistics * (execution counts). After each source files, a few statistics @@ -420,7 +534,7 @@ DEFUN_VOID (print_annotated_source) for (sym = symtab.base; sym < symtab.limit; ++sym) { - if (sym->is_bb_head && sym->file && sym->file->num_lines + if (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)))) |