diff options
Diffstat (limited to 'gprof/corefile.c')
-rw-r--r-- | gprof/corefile.c | 364 |
1 files changed, 185 insertions, 179 deletions
diff --git a/gprof/corefile.c b/gprof/corefile.c index 5f749b4..74dbfb5 100644 --- a/gprof/corefile.c +++ b/gprof/corefile.c @@ -18,7 +18,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ - + #include "gprof.h" #include "libiberty.h" #include "filenames.h" @@ -27,6 +27,7 @@ #include "symtab.h" #include "hist.h" #include "corefile.h" +#include "gmon_io.h" #include "safe-ctype.h" #include <limits.h> /* For UINT_MAX. */ @@ -36,7 +37,8 @@ static asymbol **core_syms; asection *core_text_sect; void * core_text_space; -static int min_insn_size; +/* Greatest common divisor of instruction sizes and alignments. */ +static int insn_boundary; int offset_to_code; /* For mapping symbols to specific .o files during file ordering. */ @@ -245,7 +247,7 @@ core_init (const char * aout_name) *symp = 0; } - min_insn_size = 1; + insn_boundary = 1; offset_to_code = 0; switch (bfd_get_arch (core_bfd)) @@ -254,8 +256,15 @@ core_init (const char * aout_name) offset_to_code = 2; break; + case bfd_arch_mips:/* and microMIPS */ + case bfd_arch_powerpc:/* and VLE */ + case bfd_arch_riscv:/* and RVC */ + case bfd_arch_sh: + insn_boundary = 2; + break; + case bfd_arch_alpha: - min_insn_size = 4; + insn_boundary = 4; break; default: @@ -514,9 +523,8 @@ void core_create_syms_from (const char * sym_table_file) { char type; - bfd_vma min_vma = ~(bfd_vma) 0; - bfd_vma max_vma = 0; FILE * f; + Sym_Table *symtab; f = fopen (sym_table_file, "r"); if (!f) @@ -525,25 +533,27 @@ core_create_syms_from (const char * sym_table_file) done (1); } + symtab = get_symtab_direct (); + /* Pass 1 - determine upper bound on number of function names. */ - symtab.len = num_of_syms_in (f); + symtab->len = num_of_syms_in (f); - if (symtab.len == 0) + if (symtab->len == 0) { fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, sym_table_file); done (1); } - else if (symtab.len == -1U) + else if (symtab->len == -1U) { fprintf (stderr, _("%s: file `%s' has too many symbols\n"), whoami, sym_table_file); done (1); } - symtab.base = (Sym *) xmalloc (symtab.len * sizeof (Sym)); + symtab->base = (Sym *) xmalloc (symtab->len * sizeof (Sym)); /* Pass 2 - create symbols. */ - symtab.limit = symtab.base; + symtab->limit = symtab->base; if (fseek (f, 0, SEEK_SET) != 0) { @@ -558,27 +568,25 @@ core_create_syms_from (const char * sym_table_file) if (type != 't' && type != 'T') continue; - sym_init (symtab.limit); + sym_init (symtab->limit); uint64_t addr; sscanf (address, "%" SCNx64, &addr); - symtab.limit->addr = addr; - - symtab.limit->name = (char *) xmalloc (strlen (name) + 1); - strcpy ((char *) symtab.limit->name, name); - symtab.limit->mapped = 0; - symtab.limit->is_func = true; - symtab.limit->is_bb_head = true; - symtab.limit->is_static = (type == 't'); - min_vma = MIN (symtab.limit->addr, min_vma); - max_vma = MAX (symtab.limit->addr, max_vma); - - ++symtab.limit; + symtab->limit->addr = addr; + + symtab->limit->name = (char *) xmalloc (strlen (name) + 1); + strcpy ((char *) symtab->limit->name, name); + symtab->limit->mapped = 0; + symtab->limit->is_func = true; + symtab->limit->is_bb_head = true; + symtab->limit->is_static = (type == 't'); + + ++symtab->limit; } fclose (f); - symtab.len = symtab.limit - symtab.base; - symtab_finalize (&symtab); + symtab->len = symtab->limit - symtab->base; + symtab_finalize (symtab); } static int @@ -593,12 +601,11 @@ search_mapped_symbol (const void * l, const void * r) void core_create_function_syms (void) { - bfd_vma min_vma = ~ (bfd_vma) 0; - bfd_vma max_vma = 0; int cxxclass; long i; struct function_map * found = NULL; int core_has_func_syms = 0; + Sym_Table *symtab = get_symtab_direct (); switch (core_bfd->xvec->flavour) { @@ -613,7 +620,7 @@ core_create_function_syms (void) } /* Pass 1 - determine upper bound on number of function names. */ - symtab.len = 0; + symtab->len = 0; for (i = 0; i < core_num_syms; ++i) { @@ -632,19 +639,19 @@ core_create_function_syms (void) sizeof (struct function_map), search_mapped_symbol); } if (found == NULL || found->is_first) - ++symtab.len; + ++symtab->len; } - if (symtab.len == 0) + if (symtab->len == 0) { fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, a_out_name); done (1); } - symtab.base = (Sym *) xmalloc (symtab.len * sizeof (Sym)); + symtab->base = (Sym *) xmalloc (symtab->len * sizeof (Sym)); /* Pass 2 - create symbols. */ - symtab.limit = symtab.base; + symtab->limit = symtab->base; for (i = 0; i < core_num_syms; ++i) { @@ -672,23 +679,23 @@ core_create_function_syms (void) if (found && ! found->is_first) continue; - sym_init (symtab.limit); + sym_init (symtab->limit); /* Symbol offsets are always section-relative. */ sym_sec = core_syms[i]->section; - symtab.limit->addr = core_syms[i]->value; + symtab->limit->addr = core_syms[i]->value; if (sym_sec) - symtab.limit->addr += bfd_section_vma (sym_sec); + symtab->limit->addr += bfd_section_vma (sym_sec); if (found) { - symtab.limit->name = found->file_name; - symtab.limit->mapped = 1; + symtab->limit->name = found->file_name; + symtab->limit->mapped = 1; } else { - symtab.limit->name = core_syms[i]->name; - symtab.limit->mapped = 0; + symtab->limit->name = core_syms[i]->name; + symtab->limit->mapped = 0; } /* Lookup filename and line number, if we can. */ @@ -696,10 +703,10 @@ core_create_function_syms (void) const char * filename; const char * func_name; - if (get_src_info (symtab.limit->addr, & filename, & func_name, - & symtab.limit->line_num)) + if (get_src_info (symtab->limit->addr, & filename, & func_name, + & symtab->limit->line_num)) { - symtab.limit->file = source_file_lookup_path (filename); + symtab->limit->file = source_file_lookup_path (filename); /* FIXME: Checking __osf__ here does not work with a cross gprof. */ @@ -711,47 +718,36 @@ core_create_function_syms (void) labels do not appear in the symbol table info, so this isn't necessary. */ - if (strcmp (symtab.limit->name, func_name) != 0) + 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)); + symtab->limit->name, func_name)); continue; } #endif } } - symtab.limit->is_func = (!core_has_func_syms + symtab->limit->is_func = (!core_has_func_syms || (core_syms[i]->flags & BSF_FUNCTION) != 0); - symtab.limit->is_bb_head = true; + symtab->limit->is_bb_head = true; if (cxxclass == 't') - symtab.limit->is_static = true; - - /* Keep track of the minimum and maximum vma addresses used by all - symbols. When computing the max_vma, use the ending address of the - section containing the symbol, if available. */ - min_vma = MIN (symtab.limit->addr, min_vma); - if (sym_sec) - max_vma = MAX (bfd_section_vma (sym_sec) - + bfd_section_size (sym_sec) - 1, - max_vma); - else - max_vma = MAX (symtab.limit->addr, max_vma); + symtab->limit->is_static = true; 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)); - ++symtab.limit; + (long) (symtab->limit - symtab->base), + symtab->limit->name, + (unsigned long) symtab->limit->addr)); + ++symtab->limit; } - symtab.len = symtab.limit - symtab.base; - symtab_finalize (&symtab); + symtab->len = symtab->limit - symtab->base; + symtab_finalize (symtab); } /* Read in symbol table from core. @@ -760,85 +756,25 @@ core_create_function_syms (void) void core_create_line_syms (void) { - char *prev_name, *prev_filename; - unsigned int prev_name_len, prev_filename_len; - bfd_vma vma, min_vma = ~(bfd_vma) 0, max_vma = 0; - Sym *prev, dummy, *sym; + bfd_vma vma; + Sym prev, *sym; const char *filename; - int prev_line_num; Sym_Table ltab; - bfd_vma vma_high; + size_t ltab_reserved; + Sym_Table *symtab = get_symtab_direct (); + bfd_vma bfd_vma_low = core_text_sect->vma; + bfd_vma bfd_vma_high = bfd_vma_low + bfd_section_size (core_text_sect); /* 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 (); - /* Pass 1: count the 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. */ - prev_name_len = 1024; - prev_filename_len = 1024; - prev_name = (char *) xmalloc (prev_name_len); - prev_filename = (char *) xmalloc (prev_filename_len); + ltab_reserved = 1024; ltab.len = 0; - prev_line_num = 0; - - vma_high = core_text_sect->vma + bfd_section_size (core_text_sect); - for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size) - { - unsigned int len; - - if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num) - || (prev_line_num == dummy.line_num - && prev_name != NULL - && strcmp (prev_name, dummy.name) == 0 - && filename_cmp (prev_filename, filename) == 0)) - continue; - - ++ltab.len; - prev_line_num = dummy.line_num; - - len = strlen (dummy.name); - if (len >= prev_name_len) - { - prev_name_len = len + 1024; - free (prev_name); - prev_name = (char *) xmalloc (prev_name_len); - } - - strcpy (prev_name, dummy.name); - len = strlen (filename); - - if (len >= prev_filename_len) - { - prev_filename_len = len + 1024; - free (prev_filename); - prev_filename = (char *) xmalloc (prev_filename_len); - } - - strcpy (prev_filename, filename); - - min_vma = MIN (vma, min_vma); - max_vma = MAX (vma, max_vma); - } - - free (prev_name); - free (prev_filename); - - /* Make room for function symbols, too. */ - ltab.len += symtab.len; - ltab.base = (Sym *) xmalloc (ltab.len * sizeof (Sym)); + ltab.base = xmalloc (ltab_reserved * sizeof (Sym)); ltab.limit = ltab.base; - /* Pass 2 - create symbols. */ - /* We now set is_static as we go along, rather than by running through the symbol table at the end. @@ -855,62 +791,132 @@ core_create_line_syms (void) Perhaps symtab_finalize should be modified to make this distinction as well, but the current fix works and the code is a lot cleaner now. */ - prev = 0; + memset (&prev, 0, sizeof (prev)); + + /* The profile information in the profile data file includes histogram + records, which capture low PC and high PC of program execution. If + all histogram records come in the profile data file before any + call-graph records and basic-block records, we can look up only the + line numbers within low PC and high PC in histogram records. */ + if (gmon_histograms_first) + for (size_t i = 0; i < num_histograms; ++i) + { + bfd_vma hist_vma_high = histograms[i].highpc; + bfd_vma vma_low = MAX (histograms[i].lowpc, bfd_vma_low); + bfd_vma vma_high = MIN (bfd_vma_high, hist_vma_high); + for (vma = vma_low; vma < vma_high; vma += insn_boundary) + { + if (ltab.len >= ltab_reserved) + { + /* Reserve more space for line symbols. */ + ltab_reserved *= 2; + ltab.base = xrealloc (ltab.base, + ltab_reserved * sizeof (Sym)); + ltab.limit = ltab.base + ltab.len; + } + sym_init (ltab.limit); + + if (!get_src_info (vma, &filename, <ab.limit->name, + <ab.limit->line_num) + || (prev.name && prev.line_num == ltab.limit->line_num + && strcmp (prev.name, ltab.limit->name) == 0 + && filename_cmp (prev.file->name, filename) == 0)) + continue; + + /* Make name pointer a malloc'ed string. */ + ltab.limit->name = xstrdup (ltab.limit->name); + ltab.limit->file = source_file_lookup_path (filename); + + ltab.limit->addr = vma; + + /* 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.name && ltab.limit->file == prev.file + && strcmp (ltab.limit->name, prev.name) == 0) + { + ltab.limit->is_static = prev.is_static; + } + else + { + sym = sym_lookup (symtab, ltab.limit->addr); + if (sym) + ltab.limit->is_static = sym->is_static; + } - for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size) - { - sym_init (ltab.limit); + prev = *ltab.limit; - if (!get_src_info (vma, &filename, <ab.limit->name, <ab.limit->line_num) - || (prev && prev->line_num == ltab.limit->line_num - && strcmp (prev->name, ltab.limit->name) == 0 - && filename_cmp (prev->file->name, filename) == 0)) - continue; + DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n", + (unsigned long) (ltab.limit - ltab.base), + ltab.limit->name, + (unsigned long) ltab.limit->addr)); + ++ltab.limit; + ++ltab.len; + } + } + else + for (vma = bfd_vma_low; vma < bfd_vma_high; vma += insn_boundary) + { + if (ltab.len >= ltab_reserved) + { + /* Reserve more space for line symbols. */ + ltab_reserved *= 2; + ltab.base = (Sym *) xrealloc (ltab.base, + ltab_reserved * sizeof (Sym)); + ltab.limit = ltab.base + ltab.len; + } + sym_init (ltab.limit); - /* Make name pointer a malloc'ed string. */ - ltab.limit->name = xstrdup (ltab.limit->name); - ltab.limit->file = source_file_lookup_path (filename); + if (!get_src_info (vma, &filename, <ab.limit->name, + <ab.limit->line_num) + || (prev.name && prev.line_num == ltab.limit->line_num + && strcmp (prev.name, ltab.limit->name) == 0 + && filename_cmp (prev.file->name, filename) == 0)) + continue; - ltab.limit->addr = vma; + /* Make name pointer a malloc'ed string. */ + ltab.limit->name = xstrdup (ltab.limit->name); + ltab.limit->file = source_file_lookup_path (filename); - /* 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) - { - ltab.limit->is_static = prev->is_static; - } - else - { - sym = sym_lookup(&symtab, ltab.limit->addr); - if (sym) - ltab.limit->is_static = sym->is_static; - } + ltab.limit->addr = vma; + + /* 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 (ltab.limit->file == prev.file + && strcmp (ltab.limit->name, prev.name) == 0) + { + ltab.limit->is_static = prev.is_static; + } + else + { + sym = sym_lookup (symtab, ltab.limit->addr); + if (sym) + ltab.limit->is_static = sym->is_static; + } - prev = ltab.limit; + prev = *ltab.limit; - DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n", - (unsigned long) (ltab.limit - ltab.base), - ltab.limit->name, - (unsigned long) ltab.limit->addr)); - ++ltab.limit; - } + DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n", + (unsigned long) (ltab.limit - ltab.base), + ltab.limit->name, + (unsigned long) ltab.limit->addr)); + ++ltab.limit; + ++ltab.len; + } - /* Copy in function symbols. */ - memcpy (ltab.limit, symtab.base, symtab.len * sizeof (Sym)); - ltab.limit += symtab.len; + /* Reserve space for function symbols and/or trim excess space. */ + ltab_reserved = ltab.len + symtab->len; + ltab.base = xrealloc (ltab.base, ltab_reserved * sizeof (Sym)); + ltab.limit = ltab.base + ltab.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); - } + /* Copy in function symbols. */ + memcpy (ltab.limit, symtab->base, symtab->len * sizeof (Sym)); + ltab.limit += symtab->len; + ltab.len += symtab->len; /* Finalize ltab and make it symbol table. */ symtab_finalize (<ab); - free (symtab.base); - symtab = ltab; + free (symtab->base); + set_symtab (<ab); } |