diff -u binutils-2.13/gprof/README binutils-2.13-jsgf/gprof/README --- binutils-2.13/gprof/README Thu Jul 19 03:43:13 2001 +++ binutils-2.13-jsgf/gprof/README Thu Oct 3 15:53:26 2002 @@ -440,3 +440,11 @@ file in a suitable format. This should be fixed for future releases of gcc. In the meantime, contact davidm@cs.arizona.edu for a version of __bb_exit_func() to is appropriate. + +*** Shared Object Mapping Records + +(version 2) These records explain where shared objects have been +mapped into the address space, and gives their names. This allows +gprof to resolve references into these mappings symbolically. If +present, these records must be before any other, so that gprof can +organize its symbols before needing them. diff -u binutils-2.13/gprof/alpha.c binutils-2.13-jsgf/gprof/alpha.c --- binutils-2.13/gprof/alpha.c Tue Jul 30 11:20:36 2002 +++ binutils-2.13-jsgf/gprof/alpha.c Mon Oct 7 12:06:48 2002 @@ -96,6 +96,10 @@ bfd_vma pc, dest_pc; unsigned int insn; Sym *child; + asection *text_sect; + PTR text_space; + + text_space = core_get_text_space(p_lowpc, &text_sect); if (indirect_child.name == NULL) { @@ -105,7 +109,7 @@ indirect_child.cg.cyc.head = &indirect_child; } - if (!core_text_space) + if (!text_space) { return; } @@ -122,8 +126,8 @@ (unsigned long) p_highpc)); for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4) { - insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space - + pc - core_text_sect->vma)); + insn = bfd_get_32 (core_bfd, ((unsigned char *) text_space + + pc - text_sect->vma)); switch (insn & (0x3f << 26)) { case OP_Jxx << 26: diff -u binutils-2.13/gprof/cg_print.c binutils-2.13-jsgf/gprof/cg_print.c --- binutils-2.13/gprof/cg_print.c Fri Feb 1 00:24:15 2002 +++ binutils-2.13-jsgf/gprof/cg_print.c Wed Oct 9 18:21:08 2002 @@ -76,7 +76,7 @@ } printf (_("\ngranularity: each sample hit covers %ld byte(s)"), - (long) hist_scale * sizeof (UNIT)); + (long) hist_scale); if (print_time > 0.0) printf (_(" for %.2f%% of %.2f seconds\n\n"), diff -u binutils-2.13/gprof/corefile.c binutils-2.13-jsgf/gprof/corefile.c --- binutils-2.13/gprof/corefile.c Fri Feb 1 00:24:15 2002 +++ binutils-2.13-jsgf/gprof/corefile.c Fri Oct 11 11:52:34 2002 @@ -25,15 +25,12 @@ #include "source.h" #include "symtab.h" #include "corefile.h" +#include "gmon_io.h" bfd *core_bfd; -int core_num_syms; -asymbol **core_syms; -asection *core_text_sect; -PTR core_text_space; -int min_insn_size; -int offset_to_code; +int min_insn_size = 1; +int offset_to_code = 0; /* For mapping symbols to specific .o files during file ordering. */ struct function_map *symbol_map; @@ -42,7 +39,10 @@ static void read_function_mappings PARAMS ((const char *)); static int core_sym_class PARAMS ((asymbol *)); static boolean get_src_info - PARAMS ((bfd_vma, const char **, const char **, int *)); + PARAMS ((bfd_vma, const char **, const char **, int *, bfd *, asymbol **, int, asection *)); +static void core_create_function_syms PARAMS ((bfd *, const char *, bfd_vma, asection *, asymbol **, int)); +static void core_create_line_syms PARAMS ((bfd *, const char *, bfd_vma, asection *, asymbol **, int)); +static void core_load_text_space PARAMS ((bfd *, asection *)); extern void i386_find_call PARAMS ((Sym *, bfd_vma, bfd_vma)); extern void alpha_find_call PARAMS ((Sym *, bfd_vma, bfd_vma)); @@ -51,6 +51,47 @@ extern void sparc_find_call PARAMS ((Sym *, bfd_vma, bfd_vma)); extern void mips_find_call PARAMS ((Sym *, bfd_vma, bfd_vma)); +Search_List obj_search_list; + +static const char *intern PARAMS ((const char *)); + +/* keep unique copies of all strings */ +static const char *intern(str) + const char *str; +{ +#define STR_HASHSZ 1023u + struct str { + struct str *next; + char str[1]; + }; + static struct str *strhash[STR_HASHSZ]; + struct str *strp; + const char *cp; + unsigned int hash = 0; + + for(cp = str; *cp; cp++) + hash = *cp ^ ((hash << 13) | (hash >> (32-13))); + hash %= STR_HASHSZ; + + for(strp = strhash[hash]; strp; strp = strp->next) + if (strcmp(strp->str, str) == 0) + return strp->str; + + strp = xmalloc(sizeof(*strp) + strlen(str)); + strcpy(strp->str, str); + strp->next = strhash[hash]; + strhash[hash] = strp; + + return strp->str; +} + +static int streq(const char *a, const char *b) +{ + if (a == b) + return 0; + return strcmp(a, b); +} + static void read_function_mappings (filename) const char *filename; @@ -138,105 +179,72 @@ } +/* load any unloaded files */ void -core_init (aout_name) - const char *aout_name; +core_init () { - core_bfd = bfd_openr (aout_name, 0); - - if (!core_bfd) - { - perror (aout_name); - done (1); - } - - if (!bfd_check_format (core_bfd, bfd_object)) - { - fprintf (stderr, _("%s: %s: not in a.out format\n"), whoami, aout_name); - done (1); - } - - /* 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, aout_name); - done (1); - } - } - - /* 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, aout_name, - bfd_errmsg (bfd_get_error ())); - done (1); - } - - 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, aout_name, - bfd_errmsg (bfd_get_error ())); - done (1); - } +/* Read in the text space of an a.out file. */ - min_insn_size = 1; - offset_to_code = 0; +struct text_space +{ + bfd_vma addr; + unsigned int size; + PTR text; + asection *sect; + struct text_space *next; +}; - switch (bfd_get_arch (core_bfd)) - { - case bfd_arch_vax: - case bfd_arch_tahoe: - offset_to_code = 2; - break; +static struct text_space *text_spaces; - case bfd_arch_alpha: - min_insn_size = 4; - break; +PTR core_get_text_space(addr, text_sectp) + bfd_vma addr; + asection **text_sectp; +{ + struct text_space *ts; - default: - break; + for(ts = text_spaces; ts != NULL; ts = ts->next) { + if (addr >= ts->addr && addr < (ts->addr + ts->size)) { + *text_sectp = ts->sect; + return ts->text; } + } - if (function_mapping_file) - read_function_mappings (function_mapping_file); + return 0; } -/* Read in the text space of an a.out file. */ - void -core_get_text_space (cbfd) +core_load_text_space (cbfd, text_sect) bfd *cbfd; + asection *text_sect; { - core_text_space = (PTR) malloc ((unsigned int) core_text_sect->_raw_size); + struct text_space *ts = xmalloc(sizeof(*ts)); + + ts->addr = text_sect->vma; + ts->size = text_sect->_raw_size; + ts->sect = text_sect; + ts->text = (PTR) malloc ((unsigned int) text_sect->_raw_size); - if (!core_text_space) + if (!ts->text) { fprintf (stderr, _("%s: ran out room for %lu bytes of text space\n"), - whoami, (unsigned long) core_text_sect->_raw_size); + whoami, (unsigned long) text_sect->_raw_size); done (1); } - if (!bfd_get_section_contents (cbfd, core_text_sect, core_text_space, - (bfd_vma) 0, core_text_sect->_raw_size)) + if (!bfd_get_section_contents (cbfd, text_sect, ts->text, + (bfd_vma) 0, text_sect->_raw_size)) { bfd_perror ("bfd_get_section_contents"); - free (core_text_space); - core_text_space = 0; + free (ts->text); + free (ts); + } + else + { + ts->next = text_spaces; + text_spaces = ts; } - - if (!core_text_space) - fprintf (stderr, _("%s: can't do -c\n"), whoami); } @@ -371,17 +379,21 @@ /* Get whatever source info we can get regarding address ADDR. */ static boolean -get_src_info (addr, filename, name, line_num) +get_src_info (addr, filename, name, line_num, cbfd, syms, num_syms, text_sect) bfd_vma addr; const char **filename; const char **name; int *line_num; + bfd *cbfd; + asymbol **syms; + int num_syms ATTRIBUTE_UNUSED; + asection *text_sect; { 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, + if (bfd_find_nearest_line (cbfd, text_sect, syms, + addr - text_sect->vma, &fname, &func_name, (unsigned int *) &l) && fname && func_name && l) { @@ -404,22 +416,29 @@ /* Read in symbol table from core. One symbol per function is entered. */ -void -core_create_function_syms (cbfd) +static void +core_create_function_syms (cbfd, obj_filename, obj_offset, text_sect, syms, num_syms) bfd *cbfd ATTRIBUTE_UNUSED; + const char *obj_filename ATTRIBUTE_UNUSED; + bfd_vma obj_offset; + asection *text_sect; + asymbol **syms; + int num_syms; { bfd_vma min_vma = ~(bfd_vma) 0; bfd_vma max_vma = 0; int class; long i, found, skip; unsigned int j; + Sym_Table ltab; + asymbol filesym, endsym, *filesymp[2] = { &filesym, &endsym }; /* Pass 1 - determine upper bound on number of function names. */ - symtab.len = 0; + ltab.len = 0; - for (i = 0; i < core_num_syms; ++i) + for (i = 0; i < num_syms; ++i) { - if (!core_sym_class (core_syms[i])) + if (!core_sym_class (syms[i])) continue; /* This should be replaced with a binary search or hashed @@ -430,40 +449,70 @@ in the file. */ skip = 0; for (j = 0; j < symbol_map_count; j++) - if (!strcmp (core_syms[i]->name, symbol_map[j].function_name)) + if (!streq (syms[i]->name, symbol_map[j].function_name)) { - if (j > 0 && ! strcmp (symbol_map [j].file_name, + if (j > 0 && ! streq (symbol_map [j].file_name, symbol_map [j - 1].file_name)) skip = 1; break; } if (!skip) - ++symtab.len; + ++ltab.len; } - if (symtab.len == 0) + if (ltab.len == 0) { - fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, a_out_name); - done (1); + char *buf = xmalloc(strlen(obj_filename) + 6); /* __end */ + + fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, obj_filename); + /* make up a function which covers the whole library */ + syms = filesymp; + num_syms = 2; + + memset(&filesym, 0, sizeof(filesym)); + filesym.flags = BSF_GLOBAL | BSF_FUNCTION; + filesym.name = intern(obj_filename); + filesym.value = obj_offset; + filesym.section = text_sect; + + memset(&endsym, 0, sizeof(endsym)); + endsym.flags = BSF_GLOBAL | BSF_FUNCTION; + sprintf(buf, "%s__end", obj_filename); + endsym.name = intern(buf); + endsym.value = obj_offset + text_sect->_raw_size; + endsym.section = text_sect; + + ltab.len = 2; + + free(buf); } - /* The "+ 2" is for the sentinels. */ - symtab.base = (Sym *) xmalloc ((symtab.len + 2) * sizeof (Sym)); + if (symtab.base == NULL) + { + /* The "+ 2" is for the sentinels. */ + ltab.len += 2; + } + else + { + ltab.len += symtab.len; + } + + ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym)); + ltab.limit = ltab.base; /* Pass 2 - create symbols. */ - symtab.limit = symtab.base; - for (i = 0; i < core_num_syms; ++i) + for (i = 0; i < num_syms; ++i) { - class = core_sym_class (core_syms[i]); + class = core_sym_class (syms[i]); if (!class) { DBG (AOUTDEBUG, printf ("[core_create_function_syms] rejecting: 0x%lx %s\n", - (unsigned long) core_syms[i]->value, - core_syms[i]->name)); + (unsigned long) syms[i]->value, + syms[i]->name)); continue; } @@ -473,9 +522,9 @@ found = 0; for (j = 0; j < symbol_map_count; j++) - if (!strcmp (core_syms[i]->name, symbol_map[j].function_name)) + if (!streq (syms[i]->name, symbol_map[j].function_name)) { - if (j > 0 && ! strcmp (symbol_map [j].file_name, + if (j > 0 && ! streq (symbol_map [j].file_name, symbol_map [j - 1].file_name)) skip = 1; else @@ -486,31 +535,32 @@ if (skip) continue; - sym_init (symtab.limit); + sym_init (ltab.limit); /* Symbol offsets are always section-relative. */ - symtab.limit->addr = core_syms[i]->value + core_syms[i]->section->vma; + ltab.limit->addr = syms[i]->value + syms[i]->section->vma; if (symbol_map_count - && !strcmp (core_syms[i]->name, symbol_map[found].function_name)) + && !streq (syms[i]->name, symbol_map[found].function_name)) { - symtab.limit->name = symbol_map[found].file_name; - symtab.limit->mapped = 1; + ltab.limit->name = intern(symbol_map[found].file_name); + ltab.limit->mapped = 1; } else { - symtab.limit->name = core_syms[i]->name; - symtab.limit->mapped = 0; + ltab.limit->name = intern(syms[i]->name); + ltab.limit->mapped = 0; } /* Lookup filename and line number, if we can. */ { const char *filename, *func_name; - if (get_src_info (symtab.limit->addr, &filename, &func_name, - &symtab.limit->line_num)) + if (get_src_info (ltab.limit->addr, &filename, &func_name, + <ab.limit->line_num, + cbfd, syms, num_syms, text_sect)) { - symtab.limit->file = source_file_lookup_path (filename); + ltab.limit->file = source_file_lookup_path (filename); /* FIXME: Checking __osf__ here does not work with a cross gprof. */ @@ -522,65 +572,108 @@ labels do not appear in the symbol table info, so this isn't necessary. */ - if (strcmp (symtab.limit->name, func_name) != 0) + if (streq (ltab.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)); + ltab.limit->name, func_name)); continue; } #endif } } - symtab.limit->is_func = true; - symtab.limit->is_bb_head = true; + ltab.limit->addr += obj_offset; + ltab.limit->is_func = true; + ltab.limit->is_bb_head = true; if (class == 't') - symtab.limit->is_static = true; + ltab.limit->is_static = true; - min_vma = MIN (symtab.limit->addr, min_vma); - max_vma = MAX (symtab.limit->addr, max_vma); + min_vma = MIN (ltab.limit->addr, min_vma); + max_vma = MAX (ltab.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) + if (ltab.limit->name[0] == 'm' && discard_underscores + && streq (ltab.limit->name, "main") == 0) discard_underscores = 0; DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n", - (long) (symtab.limit - symtab.base), - symtab.limit->name, - (unsigned long) symtab.limit->addr)); + (long) (ltab.limit - ltab.base), + ltab.limit->name, + (unsigned long) ltab.limit->addr)); + ++ltab.limit; + } + + /* merge ltab with existing symtab (if any) */ + if (symtab.base == 0) + { + /* Create sentinels. */ + symtab = ltab; + + 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 = ~(bfd_vma) 0; ++symtab.limit; + + symtab.len = symtab.limit - symtab.base; + symtab_finalize(&symtab, text_sect); } + else + { + /* Update sentinels. */ + Sym *sentinel = sym_lookup (&symtab, (bfd_vma) 0); + + if (streq (sentinel->name, "") == 0 + && min_vma <= sentinel->end_addr) + sentinel->end_addr = min_vma - 1; + + sentinel = sym_lookup (&symtab, ~(bfd_vma) 0); + + if (streq (sentinel->name, "") == 0 && max_vma >= sentinel->addr) + sentinel->addr = max_vma + 1; + + /* Copy in function symbols. */ + memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym)); + ltab.limit += symtab.len; + if ((unsigned int) (ltab.limit - ltab.base) != ltab.len) + { + fprintf (stderr, + _("%s: somebody miscounted: ltab.len=%d instead of %ld\n"), + whoami, ltab.len, (long) (ltab.limit - ltab.base)); + done (1); + } - /* 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 = max_vma + 1; - symtab.limit->end_addr = ~(bfd_vma) 0; - ++symtab.limit; + /* Finalize ltab and make it symbol table. */ + symtab_finalize(<ab, text_sect); + free (symtab.base); - symtab.len = symtab.limit - symtab.base; - symtab_finalize (&symtab); + symtab = ltab; + } } /* Read in symbol table from core. One symbol per line of source code is entered. */ void -core_create_line_syms (cbfd) +core_create_line_syms (cbfd, obj_filename, obj_offset, text_sect, syms, num_syms) bfd *cbfd; + const char *obj_filename; + bfd_vma obj_offset; + asection *text_sect; + asymbol **syms; + int num_syms; { char *prev_name, *prev_filename; unsigned int prev_name_len, prev_filename_len; @@ -594,7 +687,7 @@ /* 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 (cbfd); + core_create_function_syms (cbfd, obj_filename, obj_offset, text_sect, syms, num_syms); /* Pass 1 - counter number of symbols. */ @@ -612,17 +705,18 @@ ltab.len = 0; prev_line_num = 0; - for (offset = 0; offset < core_text_sect->_raw_size; offset += min_insn_size) + for (offset = 0; offset < text_sect->_raw_size; offset += min_insn_size) { unsigned int len; - vma = core_text_sect->vma + offset; + vma = text_sect->vma + offset; - if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num) + if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num, + cbfd, syms, num_syms, text_sect) || (prev_line_num == dummy.line_num && prev_name != NULL - && strcmp (prev_name, dummy.name) == 0 - && strcmp (prev_filename, filename) == 0)) + && streq (prev_name, dummy.name) == 0 + && streq (prev_filename, filename) == 0)) continue; ++ltab.len; @@ -680,28 +774,29 @@ lot cleaner now. */ prev = 0; - for (offset = 0; offset < core_text_sect->_raw_size; offset += min_insn_size) + for (offset = 0; offset < text_sect->_raw_size; offset += min_insn_size) { sym_init (ltab.limit); - if (!get_src_info (core_text_sect->vma + offset, &filename, - <ab.limit->name, <ab.limit->line_num) + if (!get_src_info (text_sect->vma + offset, &filename, + <ab.limit->name, <ab.limit->line_num, + cbfd, syms, num_syms, text_sect) || (prev && prev->line_num == ltab.limit->line_num - && strcmp (prev->name, ltab.limit->name) == 0 - && strcmp (prev->file->name, filename) == 0)) + && streq (prev->name, ltab.limit->name) == 0 + && streq (prev->file->name, filename) == 0)) continue; /* Make name pointer a malloc'ed string. */ - ltab.limit->name = xstrdup (ltab.limit->name); + ltab.limit->name = intern (ltab.limit->name); ltab.limit->file = source_file_lookup_path (filename); - ltab.limit->addr = core_text_sect->vma + offset; + ltab.limit->addr = text_sect->vma + offset + obj_offset; /* Set is_static based on the enclosing function, using either: 1) the previous symbol, if it's from the same function, or 2) a symtab lookup. */ if (prev && ltab.limit->file == prev->file && - strcmp (ltab.limit->name, prev->name) == 0) + streq (ltab.limit->name, prev->name) == 0) { ltab.limit->is_static = prev->is_static; } @@ -716,7 +811,7 @@ /* 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) + && streq (ltab.limit->name, "main") == 0) discard_underscores = 0; DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n", @@ -729,13 +824,13 @@ /* Update sentinels. */ sentinel = sym_lookup (&symtab, (bfd_vma) 0); - if (strcmp (sentinel->name, "") == 0 + if (streq (sentinel->name, "") == 0 && min_vma <= sentinel->end_addr) sentinel->end_addr = min_vma - 1; sentinel = sym_lookup (&symtab, ~(bfd_vma) 0); - if (strcmp (sentinel->name, "") == 0 && max_vma >= sentinel->addr) + if (streq (sentinel->name, "") == 0 && max_vma >= sentinel->addr) sentinel->addr = max_vma + 1; /* Copy in function symbols. */ @@ -751,7 +846,195 @@ } /* Finalize ltab and make it symbol table. */ - symtab_finalize (<ab); + symtab_finalize(<ab, text_sect); free (symtab.base); symtab = ltab; } + +struct file +{ + const char *filename; + struct file *next; +}; + +static struct file *files; + +void core_add_file(_filename, offset) + const char *_filename; + bfd_vma offset; +{ + bfd *bfd; + asymbol **syms; + int num_syms; + asection *text_sect; + struct file *f; + char *filepath = NULL; + + if (obj_search_list.head != NULL) + { + Search_List_Elem *e; + + for(e = obj_search_list.head; e != NULL; e = e->next) + { + filepath = xmalloc(strlen(e->path) + 1 + strlen(_filename) + 1); + sprintf(filepath, "%s/%s", e->path, _filename); + if (access(filepath, R_OK) == 0) + break; + free(filepath); + filepath = NULL; + } + } + else + filepath = xstrdup(_filename); + + if (filepath == NULL) + { + fprintf(stderr, _("%s: can't find file %s\n"), whoami, _filename); + return; + } + + /* Suppress duplicate files */ + for(f = files; f != NULL; f = f->next) + if (strcmp(filepath, f->filename) == 0) + { + DBG( AOUTDEBUG, printf ("[core_add_file] skipping already-seen file %s\n", + filepath) ); + free(filepath); + return; + } + f = xmalloc(sizeof(*f)); + f->filename = filepath; + f->next = files; + files = f; + + DBG( AOUTDEBUG, printf ("[core_add_file] name=%s offset=%x\n", + filepath, (unsigned int)offset) ); + + bfd = bfd_openr (filepath, 0); + + if (!bfd) + { + perror(filepath); + done(1); + } + + if (core_bfd == NULL) + core_bfd = bfd; + + if (offset == 0) + { + switch (bfd_get_arch (bfd)) + { + case bfd_arch_vax: + case bfd_arch_tahoe: + offset_to_code = 2; + break; + + case bfd_arch_alpha: + min_insn_size = 4; + break; + + default: + break; + } + } + + if (!bfd_check_format (bfd, bfd_object)) + { + fprintf (stderr, _("%s: %s: not in a.out format\n"), whoami, filepath); + done (1); + } + + /* Get core's text section. */ + text_sect = bfd_get_section_by_name (bfd, ".text"); + if (!text_sect) + { + text_sect = bfd_get_section_by_name (bfd, "$CODE$"); + if (!text_sect) + { + fprintf (stderr, _("%s: can't find .text section in %s\n"), + whoami, filepath); + done (1); + } + } + + /* Read core's symbol table. */ + + /* This will probably give us more than we need, but that's ok. */ + num_syms = bfd_get_symtab_upper_bound (bfd); + if (num_syms < 0) + { + fprintf (stderr, "%s: %s: %s\n", whoami, filepath, + bfd_errmsg (bfd_get_error ())); + done (1); + } + + syms = (asymbol **) xmalloc (num_syms); + num_syms = bfd_canonicalize_symtab (bfd, syms); + + if (num_syms < 0) + { + fprintf (stderr, "%s: %s: %s\n", whoami, filepath, + bfd_errmsg (bfd_get_error ())); + done (1); + } + + if (line_granularity) + { + core_create_line_syms(bfd, filepath, offset, text_sect, syms, num_syms); + } + else + { + core_create_function_syms(bfd, filepath, offset, text_sect, syms, num_syms); + } + + /* + * If we should ignore direct function calls, we need to load + * to core's text-space: + */ + if (ignore_direct_calls) + { + core_load_text_space(bfd, text_sect); + } + + if (bfd != core_bfd) + bfd_close(bfd); + free(syms); +} + +void somap_read_rec (ifp, filename) + FILE *ifp; + const char *filename; +{ + bfd_vma start; + unsigned int size; + bfd_vma offset; + unsigned char namelen; + char *name; + + if (gmon_file_version < 2) { + fprintf (stderr, _("%s: %s: not expecting somap in version %d file\n"), + whoami, filename, gmon_file_version); + done (1); + } + + if (gmon_io_read_vma (ifp, &start) || + gmon_io_read_32 (ifp, &size) || + gmon_io_read_vma (ifp, &offset) || + gmon_io_read (ifp, &namelen, 1)) { + fprintf (stderr, _("%s: %s: unexpected end of file\n"), + whoami, filename); + done (1); + } + + name = xmalloc(namelen+1); + if (gmon_io_read(ifp, name, namelen)) { + fprintf (stderr, _("%s: %s: unexpected end of file\n"), + whoami, filename); + done (1); + } + name[namelen] = 0; + + core_add_file(name, offset); + free(name); +} diff -u binutils-2.13/gprof/corefile.h binutils-2.13-jsgf/gprof/corefile.h --- binutils-2.13/gprof/corefile.h Fri Feb 1 00:24:16 2002 +++ binutils-2.13-jsgf/gprof/corefile.h Fri Oct 11 11:38:02 2002 @@ -21,6 +21,8 @@ #ifndef corefile_h #define corefile_h +#include "search_list.h" + struct function_map { char *function_name; @@ -30,18 +32,16 @@ extern struct function_map *symbol_map; extern unsigned int symbol_map_count; +extern Search_List obj_search_list; + 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 int min_insn_size; /* Size of smallest instruction, in bytes. */ extern int offset_to_code; /* Offset (in bytes) of code from entry address of routine. */ -extern void core_init PARAMS ((const char *)); -extern void core_get_text_space PARAMS ((bfd *)); -extern void core_create_function_syms PARAMS ((bfd *)); -extern void core_create_line_syms PARAMS ((bfd *)); +extern void core_init PARAMS ((void)); +extern PTR core_get_text_space PARAMS ((bfd_vma, asection **)); +extern void somap_read_rec PARAMS ((FILE *, const char *)); +extern void core_add_file PARAMS ((const char *, bfd_vma)); #endif /* corefile_h */ diff -u binutils-2.13/gprof/gmon_io.c binutils-2.13-jsgf/gprof/gmon_io.c --- binutils-2.13/gprof/gmon_io.c Fri Feb 1 00:24:16 2002 +++ binutils-2.13-jsgf/gprof/gmon_io.c Tue Oct 8 13:15:40 2002 @@ -303,7 +303,7 @@ /* 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) + if (gmon_file_version > GMON_VERSION) { fprintf (stderr, _("%s: file `%s' has unsupported version %d\n"), @@ -334,6 +334,10 @@ bb_read_rec (ifp, filename); break; + case GMON_TAG_SOMAP: + somap_read_rec (ifp, filename); + break; + default: fprintf (stderr, _("%s: %s: found bad tag %d (file corrupted?)\n"), @@ -426,6 +430,7 @@ } else { +#if 0 /* Old style BSD format. */ if (file_format == FF_BSD44) { @@ -498,14 +503,6 @@ if (hist_num_bins) ++nhist; - 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])); - } - for (i = 0; i < hist_num_bins; ++i) { if (fread (raw_bin_count, sizeof (raw_bin_count), 1, ifp) != 1) @@ -546,6 +543,7 @@ hz = 1; fprintf (stderr, _("time is in ticks, not seconds\n")); } +#endif } } else @@ -577,6 +575,7 @@ gmon_out_write (filename) const char *filename; { +#if 0 FILE *ofp; struct gmon_hdr ghdr; @@ -743,4 +742,5 @@ whoami, file_format); done (1); } +#endif } diff -u binutils-2.13/gprof/gmon_out.h binutils-2.13-jsgf/gprof/gmon_out.h --- binutils-2.13/gprof/gmon_out.h Thu Jan 31 04:56:07 2002 +++ binutils-2.13-jsgf/gprof/gmon_out.h Thu Oct 3 14:29:04 2002 @@ -25,7 +25,7 @@ #define gmon_out_h #define GMON_MAGIC "gmon" /* magic cookie */ -#define GMON_VERSION 1 /* version number */ +#define GMON_VERSION 2 /* version number */ /* Raw header as it appears on file (without padding). */ struct gmon_hdr @@ -38,7 +38,8 @@ /* Types of records in this file. */ typedef enum { - GMON_TAG_TIME_HIST = 0, GMON_TAG_CG_ARC = 1, GMON_TAG_BB_COUNT = 2 + GMON_TAG_TIME_HIST = 0, GMON_TAG_CG_ARC = 1, GMON_TAG_BB_COUNT = 2, + GMON_TAG_SOMAP = 3 } GMON_Record_Tag; diff -u binutils-2.13/gprof/gprof.c binutils-2.13-jsgf/gprof/gprof.c --- binutils-2.13/gprof/gprof.c Tue Jul 30 11:20:36 2002 +++ binutils-2.13-jsgf/gprof/gprof.c Fri Oct 11 11:45:45 2002 @@ -102,6 +102,7 @@ {"line", no_argument, 0, 'l'}, {"no-static", no_argument, 0, 'a'}, {"ignore-non-functions", no_argument, 0, 'D'}, + {"object-path", required_argument, 0, 'o' }, /* output styles: */ @@ -161,13 +162,14 @@ int status; { fprintf (stream, _("\ -Usage: %s [-[abcDhilLsTvwxyz]] [-[ACeEfFJnNOpPqQZ][name]] [-I dirs]\n\ +Usage: %s [-[abcDhilLsTvwxyz]] [-[ACeEfFJnNOopPqQZ][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\ [--[no-]flat-profile[=name]] [--[no-]graph[=name]]\n\ [--[no-]time=name] [--all-lines] [--brief] [--debug[=level]]\n\ [--function-ordering] [--file-ordering]\n\ [--directory-path=dirs] [--display-unused-functions]\n\ + [--object-path=dirs]\n\ [--file-format=name] [--file-info] [--help] [--line] [--min-count=n]\n\ [--no-static] [--print-path] [--separate-files]\n\ [--static-call-graph] [--sum] [--table-length=len] [--traditional]\n\ @@ -203,7 +205,7 @@ xmalloc_set_program_name (whoami); while ((ch = getopt_long (argc, argv, - "aA::bBcCd::De:E:f:F:hiI:J::k:lLm:n::N::O:p::P::q::Q::st:Tvw:xyzZ::", + "aA::bBcCd::De:E:f:F:hiI:J::k:lLm:n::N::O:o:p::P::q::Q::st:Tvw:xyzZ::", long_options, 0)) != EOF) { @@ -335,6 +337,9 @@ done (1); } break; + case 'o': + search_list_append(&obj_search_list, optarg); + break; case 'p': if (optarg) { @@ -532,33 +537,14 @@ /* * 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); - } - - /* - * Create symbols from core image: - */ - if (line_granularity) - { - core_create_line_syms (core_bfd); - } - else + core_add_file(a_out_name, 0); + + if (core_bfd == NULL) { - core_create_function_syms (core_bfd); + done(1); /* couldn't even find a.out */ } - /* - * Translate sym specs into syms: - */ - sym_id_parse (); + core_init(); if (file_format == FF_PROF) { @@ -599,6 +585,11 @@ } /* + * Translate sym specs into syms: + */ + sym_id_parse (); + + /* * If user did not specify output style, try to guess something * reasonable: */ diff -u binutils-2.13/gprof/hist.c binutils-2.13-jsgf/gprof/hist.c --- binutils-2.13/gprof/hist.c Tue Feb 19 10:29:08 2002 +++ binutils-2.13-jsgf/gprof/hist.c Thu Oct 10 11:11:06 2002 @@ -31,7 +31,7 @@ #include "sym_ids.h" #include "utils.h" -#define UNITS_TO_CODE (offset_to_code / sizeof(UNIT)) +#define UNITS_TO_CODE (offset_to_code) static void scale_and_align_entries PARAMS ((void)); static void print_header PARAMS ((int)); @@ -43,16 +43,137 @@ bfd_vma s_lowpc; /* Lowest address in .text. */ bfd_vma s_highpc = 0; /* Highest address in .text. */ -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[16] = "seconds"; -char hist_dimension_abbrev = 's'; +static unsigned int hist_scale_int; +static char hist_dimension[16] = "seconds"; +static char hist_dimension_abbrev = 's'; static double accum_time; /* Accumulated time so far for print_line(). */ static double total_time; /* Total time for all routines. */ +/* Two level table to deal with sparse array of histogram + information. + XXX what about 64 bit address spaces? +*/ +/* one-level page table which has HPG_SIZE entries pointing to pages + of HPG_IDX_SIZE histo buckets */ +#define HPG_BITS 20 +#define HPG_SIZE (1 << HPG_BITS) +#define HPG_MASK (HPG_SIZE - 1) + +#define HPG_IDX (32 - HPG_BITS) +#define HPG_IDX_SIZE (1 << HPG_IDX) +#define HPG_IDX_MASK (HPG_IDX_SIZE - 1) + +static int **hist_table = 0; + +static int hist_page (bfd_vma addr) +{ + addr /= hist_scale_int; + addr >>= HPG_IDX; + return addr & HPG_MASK; +} + +static int hist_pg_idx(bfd_vma addr) +{ + addr /= hist_scale_int; + return addr & HPG_IDX_MASK; +} + +static int hist_addr_idx(bfd_vma addr) +{ + return (addr - s_lowpc) / hist_scale_int; +} + +bfd_vma hist_idx_addr(int idx) +{ + if (idx == -1) + return 0; + + return s_lowpc + idx * hist_scale_int; +} + +int *hist_sample_ptr(bfd_vma addr) +{ + unsigned int page = hist_page(addr); + unsigned int idx = hist_pg_idx(addr); + + if (hist_table == NULL) + { + hist_table = (int **)xmalloc(HPG_SIZE * sizeof(*hist_table) / hist_scale_int); + memset(hist_table, 0, HPG_SIZE * sizeof(*hist_table) / hist_scale_int); + } + + if (hist_table[page] == NULL) + { + //printf("allocating page %d for addr 0x%lx (idx=%d)\n", page, addr, hist_addr_idx(addr)); + hist_table[page] = (int *)xmalloc(HPG_IDX_SIZE * sizeof(**hist_table)); + memset(hist_table[page], 0, HPG_IDX_SIZE * sizeof(**hist_table)); + } + + return &hist_table[page][idx]; +} + +int hist_sample(bfd_vma addr) +{ + unsigned int page = hist_page(addr); + unsigned int idx = hist_pg_idx(addr); + + if (0) + printf("hist_sample(%lx [%d/%d]) -> %d\n", addr, page, idx, + hist_table && hist_table[page] ? hist_table[page][idx] : 0); + if (hist_table == NULL || hist_table[page] == NULL) + return 0; + return hist_table[page][idx]; +} + +bfd_vma hist_next_sample(bfd_vma addr) +{ + bfd_vma orig_addr = addr; + unsigned int page; + unsigned int idx; + + addr += hist_scale_int; + + page = hist_page(addr); + idx = hist_pg_idx(addr); + + if (hist_table == NULL) + addr = 0; + else if (hist_table[page] == NULL) { + addr -= addr % (HPG_IDX_SIZE * hist_scale_int); + do { + addr += HPG_IDX_SIZE * hist_scale_int; + page = hist_page(addr); + } while(addr != 0 && hist_table[page] == NULL); + } + + //printf("hist_next_sample(%lx) -> %lx\n", orig_addr, addr); + return addr; +} + +int hist_idx(bfd_vma addr) +{ + unsigned int idx; + + if (addr < s_lowpc) + return -1; + + idx = addr - s_lowpc; + idx /= hist_scale_int; + return idx; +} + +int hist_next_idx(unsigned idx) +{ + bfd_vma addr = hist_next_sample(s_lowpc + idx * hist_scale_int); + + if (addr == 0) + return -1; + + return hist_idx(addr); +} + /* Table of SI prefixes for powers of 10 (used to automatically scale some of the values in the flat profile). */ const struct @@ -84,7 +205,7 @@ FILE * ifp; const char *filename; { - bfd_vma n_lowpc, n_highpc; + bfd_vma n_lowpc, n_highpc, addr; int i, ncnt, profrate; UNIT count; @@ -104,52 +225,53 @@ 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; + hist_scale = n_highpc - n_lowpc; + hist_scale /= ncnt; + hist_scale_int = (n_highpc - n_lowpc) / ncnt; + s_highpc = s_highpc; } + if (!s_highpc || n_lowpc < s_lowpc) + s_lowpc = n_lowpc; + if (n_highpc > s_highpc) + s_highpc = n_highpc; + DBG (SAMPLEDEBUG, printf ("[hist_read_rec] n_lowpc 0x%lx n_highpc 0x%lx ncnt %d\n", (unsigned long) n_lowpc, (unsigned long) n_highpc, ncnt); printf ("[hist_read_rec] s_lowpc 0x%lx s_highpc 0x%lx nsamples %d\n", (unsigned long) s_lowpc, (unsigned long) s_highpc, - hist_num_bins); - printf ("[hist_read_rec] lowpc 0x%lx highpc 0x%lx\n", - (unsigned long) lowpc, (unsigned long) highpc)); + ncnt); + printf ("[hist_read_rec] hist_scale=%g hist_scale_int=%d\n", + hist_scale, hist_scale_int); + ); - if (n_lowpc != s_lowpc || n_highpc != s_highpc - || ncnt != hist_num_bins || hz != profrate) + if (hz != profrate || (n_highpc - n_lowpc) / ncnt != hist_scale_int) { - fprintf (stderr, _("%s: `%s' is incompatible with first gmon file\n"), - whoami, filename); + fprintf (stderr, _("%s: `%s' is incompatible with first gmon file (hz=%ld profrate=%d)\n"), + whoami, filename, hz, profrate); done (1); } - 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])); - } - - for (i = 0; i < hist_num_bins; ++i) + for (addr = n_lowpc, i = 0; i < ncnt; ++i, addr += hist_scale_int) { 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); + whoami, filename, i, ncnt); done (1); } - hist_sample[i] += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]); - DBG (SAMPLEDEBUG, - printf ("[hist_read_rec] 0x%lx: %u\n", - (unsigned long) (n_lowpc + i * (n_highpc - n_lowpc) / ncnt), - hist_sample[i])); + *hist_sample_ptr(addr) += bfd_get_16 (core_bfd, (bfd_byte *) & count[0]); + + if (0) + DBG (SAMPLEDEBUG, + printf ("[hist_read_rec] 0x%lx: %u\n", + (unsigned long) hist_idx_addr(i), + hist_sample(hist_idx_addr(i)))); } + } @@ -161,6 +283,7 @@ FILE * ofp; const char *filename; { +#if 0 UNIT count; int i; @@ -178,9 +301,9 @@ done (1); } - for (i = 0; i < hist_num_bins; ++i) + for (i = 0; i > 0; i = hist_next_idx(i)) { - bfd_put_16 (core_bfd, (bfd_vma) hist_sample[i], (bfd_byte *) &count[0]); + bfd_put_16 (core_bfd, (bfd_vma) hist_sample(hist_idx_addr(i)), (bfd_byte *) &count[0]); if (fwrite (&count[0], sizeof (count), 1, ofp) != 1) { @@ -188,6 +311,7 @@ done (1); } } +#endif } @@ -207,9 +331,9 @@ for (sym = symtab.base; sym < symtab.limit; sym++) { - sym->hist.scaled_addr = sym->addr / sizeof (UNIT); - bin_of_entry = (sym->hist.scaled_addr - lowpc) / hist_scale; - bin_of_code = ((sym->hist.scaled_addr + UNITS_TO_CODE - lowpc) + sym->hist.scaled_addr = sym->addr; + bin_of_entry = (sym->hist.scaled_addr - (s_lowpc)) / hist_scale; + bin_of_code = ((sym->hist.scaled_addr + UNITS_TO_CODE - (s_lowpc)) / hist_scale); if (bin_of_entry < bin_of_code) { @@ -267,31 +391,40 @@ bfd_vma bin_low_pc, bin_high_pc; bfd_vma sym_low_pc, sym_high_pc; bfd_vma overlap, addr; - int bin_count, i; unsigned int j; double time, credit; + int idx; /* 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) + + for (idx = 0, j = 1; + idx != -1; + idx = hist_next_idx(idx)) { - bin_count = hist_sample[i]; - if (! bin_count) + bfd_vma bin_addr; + int bin_count; + + bin_addr = hist_idx_addr(idx); + bin_count = hist_sample(bin_addr); + + if (!bin_count) continue; + + //printf("idx=%d -> addr=0x%lx\n", idx, bin_addr - bin_low_pc = lowpc + (bfd_vma) (hist_scale * i); - bin_high_pc = lowpc + (bfd_vma) (hist_scale * (i + 1)); + bin_low_pc = bin_addr; + bin_high_pc = bin_addr + hist_scale_int; time = bin_count; - + DBG (SAMPLEDEBUG, printf ( - "[assign_samples] bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%d\n", - (unsigned long) (sizeof (UNIT) * bin_low_pc), - (unsigned long) (sizeof (UNIT) * bin_high_pc), + "[assign_samples] idx=%d bin_low_pc=0x%lx, bin_high_pc=0x%lx, bin_count=%d\n", + idx, + (unsigned long) (bin_low_pc), + (unsigned long) (bin_high_pc), bin_count)); total_time += time; @@ -313,14 +446,16 @@ 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", + "[assign_samples] [0x%lx,0x%lx) %s-%s gets %f ticks %ld overlap\n", (unsigned long) symtab.base[j].addr, - (unsigned long) (sizeof (UNIT) * sym_high_pc), - symtab.base[j].name, overlap * time / hist_scale, + (unsigned long) (sym_high_pc), + symtab.base[j].name, symtab.base[j+1].name, + overlap * time / hist_scale, (long) overlap)); addr = symtab.base[j].addr; @@ -361,7 +496,7 @@ if (bsd_style_output) { printf (_("\ngranularity: each sample hit covers %ld byte(s)"), - (long) hist_scale * sizeof (UNIT)); + (long) hist_scale); if (total_time > 0.0) { printf (_(" for %.2f%% of %.2f %s\n\n"), diff -u binutils-2.13/gprof/hist.h binutils-2.13-jsgf/gprof/hist.h --- binutils-2.13/gprof/hist.h Thu Jan 31 04:56:07 2002 +++ binutils-2.13-jsgf/gprof/hist.h Tue Oct 1 23:59:00 2002 @@ -23,9 +23,16 @@ 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 int hist_num_bins; /* Number of histogram bins. */ +//extern int *hist_sample; /* Code histogram. */ + +extern int hist_sample PARAMS ((bfd_vma addr)); +extern int *hist_sample_ptr PARAMS ((bfd_vma addr)); +extern bfd_vma hist_next_sample PARAMS ((bfd_vma addr)); + +extern int hist_idx PARAMS ((bfd_vma addr)); +extern int hist_next_idx PARAMS ((unsigned int idx)); +extern bfd_vma hist_idx_addr PARAMS ((int idx)); /* Scale factor converting samples to pc values: each sample covers HIST_SCALE bytes. */ diff -u binutils-2.13/gprof/i386.c binutils-2.13-jsgf/gprof/i386.c --- binutils-2.13/gprof/i386.c Tue Jul 30 11:20:36 2002 +++ binutils-2.13-jsgf/gprof/i386.c Mon Oct 7 12:06:48 2002 @@ -56,8 +56,11 @@ unsigned char *instructp; Sym *child; bfd_vma pc, destpc; + asection *text_sect; + PTR text_space; - if (core_text_space == 0) + text_space = core_get_text_space(p_lowpc, &text_sect); + if (text_space == 0) { return; } @@ -75,7 +78,7 @@ for (pc = p_lowpc; pc < p_highpc; ++pc) { - instructp = (unsigned char *) core_text_space + pc - core_text_sect->vma; + instructp = (unsigned char *) text_space + pc - text_sect->vma; if (i386_iscall (instructp)) { DBG (CALLDEBUG, diff -u binutils-2.13/gprof/mips.c binutils-2.13-jsgf/gprof/mips.c --- binutils-2.13/gprof/mips.c Tue Jul 30 11:20:36 2002 +++ binutils-2.13-jsgf/gprof/mips.c Mon Oct 7 12:10:11 2002 @@ -49,6 +49,10 @@ int offset; Sym *child; static boolean inited = false; + asection *text_sect; + PTR text_space; + + text_space = core_get_text_space(p_lowpc, &text_sect); if (!inited) { @@ -59,7 +63,7 @@ indirect_child.cg.cyc.head = &indirect_child; } - if (!core_text_space) + if (!text_space) { return; } @@ -76,7 +80,7 @@ (unsigned long) p_highpc)); for (pc = p_lowpc; pc < p_highpc; pc += 4) { - op = bfd_get_32 (core_bfd, &((char *)core_text_space)[pc - s_lowpc]); + op = bfd_get_32 (core_bfd, &((char *)text_space)[pc - s_lowpc]); if ((op & 0xfc000000) == 0x0c000000) { /* This is a "jal" instruction. Check that the destination Common subdirectories: binutils-2.13/gprof/po and binutils-2.13-jsgf/gprof/po diff -u binutils-2.13/gprof/source.c binutils-2.13-jsgf/gprof/source.c --- binutils-2.13/gprof/source.c Fri Feb 1 00:24:16 2002 +++ binutils-2.13-jsgf/gprof/source.c Mon Oct 7 15:20:18 2002 @@ -27,20 +27,47 @@ #define EXT_ANNO "-ann" /* Postfix of annotated files. */ +static unsigned int hash_path PARAMS ((const char *)); + /* Default option values. */ boolean create_annotation_files = false; Search_List src_search_list = {0, 0}; -Source_File *first_src_file = 0; +Source_File *first_src_file = NULL; + +#define SRC_HASHSZ 1023 +static Source_File *srcfile_hash[SRC_HASHSZ]; + +static unsigned int hash_path(path) + const char *path; +{ + unsigned char *cp; + unsigned hash = 0; + + cp = strrchr(path, '/'); + if (cp == NULL) + cp = path; + for(; *cp; cp++) { + hash ^= *cp; + hash = (hash << 17) | (hash >> (32-17)); + } + + hash %= SRC_HASHSZ; + + return hash; +} Source_File * source_file_lookup_path (path) const char *path; { + unsigned int hash = 0; Source_File *sf; - for (sf = first_src_file; sf; sf = sf->next) + hash = hash_path(path); + + for (sf = srcfile_hash[hash]; sf; sf = sf->hash_next) { if (FILENAME_CMP (path, sf->name) == 0) break; @@ -54,6 +81,9 @@ memset (sf, 0, sizeof (*sf)); sf->name = xstrdup (path); + sf->hash_next = srcfile_hash[hash]; + srcfile_hash[hash] = sf; + sf->next = first_src_file; first_src_file = sf; } @@ -68,12 +98,13 @@ { const char *fname; Source_File *sf; + unsigned int hash = hash_path(filename); /* 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) + for (sf = srcfile_hash[hash]; sf; sf = sf->hash_next) { fname = strrchr (sf->name, '/'); diff -u binutils-2.13/gprof/source.h binutils-2.13-jsgf/gprof/source.h --- binutils-2.13/gprof/source.h Fri Feb 1 00:24:16 2002 +++ binutils-2.13-jsgf/gprof/source.h Thu Oct 10 11:07:57 2002 @@ -29,6 +29,7 @@ int num_lines; /* # of lines in file. */ int nalloced; /* Number of lines allocated. */ void **line; /* Usage-dependent per-line data. */ + struct source_file *hash_next; } Source_File; diff -u binutils-2.13/gprof/sparc.c binutils-2.13-jsgf/gprof/sparc.c --- binutils-2.13/gprof/sparc.c Tue Jul 30 11:20:36 2002 +++ binutils-2.13-jsgf/gprof/sparc.c Mon Oct 7 12:08:50 2002 @@ -50,8 +50,12 @@ bfd_vma pc, dest_pc; unsigned int insn; Sym *child; + asection *text_sect; + PTR text_space; - if (core_text_space == 0) + text_space = core_get_text_space(p_lowpc, &text_sect); + + if (text_space == 0) { return; } @@ -68,8 +72,8 @@ (unsigned long) p_highpc)); for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4) { - insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space - + pc - core_text_sect->vma)); + insn = bfd_get_32 (core_bfd, ((unsigned char *) text_space + + pc - text_sect->vma)); if (insn & CALL) { DBG (CALLDEBUG, diff -u binutils-2.13/gprof/sym_ids.c binutils-2.13-jsgf/gprof/sym_ids.c --- binutils-2.13/gprof/sym_ids.c Fri Feb 1 00:24:16 2002 +++ binutils-2.13-jsgf/gprof/sym_ids.c Thu Oct 10 11:11:05 2002 @@ -75,7 +75,7 @@ static Source_File non_existent_file = { - 0, "", 0, 0, 0, NULL + NULL, "", 0, 0, 0, NULL, NULL }; @@ -357,7 +357,7 @@ { DBG (IDDEBUG, printf ("[sym_id_parse] syms[%s]:\n", table_name[tab - &syms[0]])); - symtab_finalize (tab); + symtab_finalize (tab, 0); } } diff -u binutils-2.13/gprof/symtab.c binutils-2.13-jsgf/gprof/symtab.c --- binutils-2.13/gprof/symtab.c Fri Feb 1 00:24:16 2002 +++ binutils-2.13-jsgf/gprof/symtab.c Thu Oct 10 11:10:06 2002 @@ -29,7 +29,7 @@ static int cmp_addr PARAMS ((const PTR, const PTR)); Sym_Table symtab; - +int symtab_needs_finalize = 1; /* Initialize a symbol (so it's empty). */ @@ -79,8 +79,9 @@ void -symtab_finalize (tab) +symtab_finalize (tab, text_sect) Sym_Table *tab; + asection *text_sect; { Sym *src, *dst; bfd_vma prev_addr; @@ -151,8 +152,8 @@ } } - if (tab->len > 0 && dst[-1].end_addr == 0) - dst[-1].end_addr = core_text_sect->vma + core_text_sect->_raw_size - 1; + if (text_sect && tab->len > 0 && dst[-1].end_addr == 0) + dst[-1].end_addr = text_sect->vma + text_sect->_raw_size - 1; DBG (AOUTDEBUG | IDDEBUG, printf ("[symtab_finalize]: removed %d duplicate entries\n", diff -u binutils-2.13/gprof/symtab.h binutils-2.13-jsgf/gprof/symtab.h --- binutils-2.13/gprof/symtab.h Fri Feb 1 00:24:16 2002 +++ binutils-2.13-jsgf/gprof/symtab.h Thu Oct 10 11:10:05 2002 @@ -112,7 +112,7 @@ extern Sym_Table symtab; /* The symbol table. */ extern void sym_init PARAMS ((Sym *)); -extern void symtab_finalize PARAMS ((Sym_Table *)); +extern void symtab_finalize PARAMS ((Sym_Table *, asection *)); #ifdef DEBUG extern Sym *dbg_sym_lookup PARAMS ((Sym_Table *, bfd_vma)); #endif diff -u binutils-2.13/gprof/tahoe.c binutils-2.13-jsgf/gprof/tahoe.c --- binutils-2.13/gprof/tahoe.c Tue Jul 30 11:20:36 2002 +++ binutils-2.13-jsgf/gprof/tahoe.c Mon Oct 7 12:10:15 2002 @@ -232,7 +232,10 @@ tahoe_operandenum firstmode; bfd_vma pc, destpc; static boolean inited = false; + asection *text_sect; + PTR text_space; + text_space = core_get_text_space(p_lowpc, &text_sect); if (!inited) { inited = true; @@ -241,7 +244,7 @@ indirectchild.cg.cyc.head = &indirectchild; } - if (core_text_space == 0) + if (text_space == 0) { return; } @@ -259,8 +262,8 @@ for (pc = p_lowpc; pc < p_highpc; pc += length) { length = 1; - instructp = ((unsigned char *) core_text_space - + pc - core_text_sect->vma); + instructp = ((unsigned char *) text_space + + pc - text_sect->vma); if ((*instructp & 0xff) == CALLF) { /* diff -u binutils-2.13/gprof/vax.c binutils-2.13-jsgf/gprof/vax.c --- binutils-2.13/gprof/vax.c Tue Jul 30 11:20:36 2002 +++ binutils-2.13-jsgf/gprof/vax.c Mon Oct 7 12:10:16 2002 @@ -243,6 +243,10 @@ operandenum firstmode; bfd_vma pc, destpc; static boolean inited = false; + asection *text_sect; + PTR text_space; + + text_space = core_get_text_space(p_lowpc, &text_sect); if (!inited) { @@ -252,7 +256,7 @@ indirectchild.cg.cyc.head = &indirectchild; } - if (core_text_space == 0) + if (text_space == 0) { return; } @@ -270,8 +274,8 @@ for (pc = p_lowpc; pc < p_highpc; pc += length) { length = 1; - instructp = ((unsigned char *) core_text_space - + pc - core_text_sect->vma); + instructp = ((unsigned char *) text_space + + pc - text_sect->vma); if ((*instructp & 0xff) == CALLS) { /*