X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gprof%2Fcorefile.c;h=fa0db2c4535fe49d39d6e634227bcf5533da4963;hb=8d4e307105edd5f21154824fd5839896ae6e6d84;hp=9f3ca03cd2d6d1fc3dbdc60a94bc51bb778fde2d;hpb=bde52789b2840efede7cba2971d8b174586018fc;p=deliverable%2Fbinutils-gdb.git diff --git a/gprof/corefile.c b/gprof/corefile.c index 9f3ca03cd2..fa0db2c453 100644 --- a/gprof/corefile.c +++ b/gprof/corefile.c @@ -1,12 +1,13 @@ /* corefile.c - Copyright 2000, 2001, 2002 Free Software Foundation, Inc. + Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007 + Free Software Foundation, Inc. This file is part of GNU Binutils. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -16,44 +17,52 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA + 02110-1301, USA. */ #include "libiberty.h" #include "gprof.h" #include "search_list.h" #include "source.h" #include "symtab.h" +#include "hist.h" #include "corefile.h" +#include "safe-ctype.h" bfd *core_bfd; -int core_num_syms; -asymbol **core_syms; +static int core_num_syms; +static asymbol **core_syms; asection *core_text_sect; PTR core_text_space; -int min_insn_size; +static int min_insn_size; int offset_to_code; /* For mapping symbols to specific .o files during file ordering. */ -struct function_map -{ - char *function_name; - char *file_name; -}; - struct function_map *symbol_map; unsigned int symbol_map_count; -extern void i386_find_call PARAMS ((Sym *, bfd_vma, bfd_vma)); -extern void alpha_find_call PARAMS ((Sym *, bfd_vma, bfd_vma)); -extern void vax_find_call PARAMS ((Sym *, bfd_vma, bfd_vma)); -extern void tahoe_find_call PARAMS ((Sym *, bfd_vma, bfd_vma)); -extern void sparc_find_call PARAMS ((Sym *, bfd_vma, bfd_vma)); -extern void mips_find_call PARAMS ((Sym *, bfd_vma, bfd_vma)); +static void read_function_mappings (const char *); +static int core_sym_class (asymbol *); +static bfd_boolean get_src_info + (bfd_vma, const char **, const char **, int *); + +extern void i386_find_call (Sym *, bfd_vma, bfd_vma); +extern void alpha_find_call (Sym *, bfd_vma, bfd_vma); +extern void vax_find_call (Sym *, bfd_vma, bfd_vma); +extern void tahoe_find_call (Sym *, bfd_vma, bfd_vma); +extern void sparc_find_call (Sym *, bfd_vma, bfd_vma); +extern void mips_find_call (Sym *, bfd_vma, bfd_vma); + +static void +parse_error (const char *filename) +{ + fprintf (stderr, _("%s: unable to parse mapping file %s.\n"), whoami, filename); + done (1); +} static void -DEFUN (read_function_mappings, (filename), const char *filename) +read_function_mappings (const char *filename) { FILE *file = fopen (filename, "r"); char dummy[1024]; @@ -74,21 +83,21 @@ DEFUN (read_function_mappings, (filename), const char *filename) matches = fscanf (file, "%[^\n:]", dummy); if (!matches) - { - fprintf (stderr, _("%s: unable to parse mapping file %s.\n"), - whoami, filename); - done (1); - } + parse_error (filename); /* Just skip messages about files with no symbols. */ if (!strncmp (dummy, "No symbols in ", 14)) { - fscanf (file, "\n"); + matches = fscanf (file, "\n"); + if (matches == EOF) + parse_error (filename); continue; } /* Don't care what else is on this line at this point. */ - fscanf (file, "%[^\n]\n", dummy); + matches = fscanf (file, "%[^\n]\n", dummy); + if (!matches) + parse_error (filename); count++; } @@ -108,16 +117,14 @@ DEFUN (read_function_mappings, (filename), const char *filename) matches = fscanf (file, "%[^\n:]", dummy); if (!matches) - { - fprintf (stderr, _("%s: unable to parse mapping file %s.\n"), - whoami, filename); - done (1); - } + parse_error (filename); /* Just skip messages about files with no symbols. */ if (!strncmp (dummy, "No symbols in ", 14)) { - fscanf (file, "\n"); + matches = fscanf (file, "\n"); + if (matches == EOF) + parse_error (filename); continue; } @@ -126,7 +133,9 @@ DEFUN (read_function_mappings, (filename), const char *filename) strcpy (symbol_map[count].file_name, dummy); /* Now we need the function name. */ - fscanf (file, "%[^\n]\n", dummy); + matches = fscanf (file, "%[^\n]\n", dummy); + if (!matches) + parse_error (filename); tmp = strrchr (dummy, ' ') + 1; symbol_map[count].function_name = xmalloc (strlen (tmp) + 1); strcpy (symbol_map[count].function_name, tmp); @@ -139,19 +148,23 @@ DEFUN (read_function_mappings, (filename), const char *filename) void -DEFUN (core_init, (a_out_name), const char *a_out_name) +core_init (const char *aout_name) { - core_bfd = bfd_openr (a_out_name, 0); + int core_sym_bytes; + asymbol *synthsyms; + long synth_count; + + core_bfd = bfd_openr (aout_name, 0); if (!core_bfd) { - perror (a_out_name); + perror (aout_name); done (1); } if (!bfd_check_format (core_bfd, bfd_object)) { - fprintf (stderr, _("%s: %s: not in a.out format\n"), whoami, a_out_name); + fprintf (stderr, _("%s: %s: not in executable format\n"), whoami, aout_name); done (1); } @@ -163,7 +176,7 @@ DEFUN (core_init, (a_out_name), const char *a_out_name) if (!core_text_sect) { fprintf (stderr, _("%s: can't find .text section in %s\n"), - whoami, a_out_name); + whoami, aout_name); done (1); } } @@ -171,24 +184,41 @@ DEFUN (core_init, (a_out_name), const char *a_out_name) /* 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) + core_sym_bytes = bfd_get_symtab_upper_bound (core_bfd); + if (core_sym_bytes < 0) { - fprintf (stderr, "%s: %s: %s\n", whoami, a_out_name, + fprintf (stderr, "%s: %s: %s\n", whoami, aout_name, bfd_errmsg (bfd_get_error ())); done (1); } - core_syms = (asymbol **) xmalloc (core_num_syms); + core_syms = (asymbol **) xmalloc (core_sym_bytes); 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, + fprintf (stderr, "%s: %s: %s\n", whoami, aout_name, bfd_errmsg (bfd_get_error ())); done (1); } + synth_count = bfd_get_synthetic_symtab (core_bfd, core_num_syms, core_syms, + 0, NULL, &synthsyms); + if (synth_count > 0) + { + asymbol **symp; + long new_size; + long i; + + new_size = (core_num_syms + synth_count + 1) * sizeof (*core_syms); + core_syms = xrealloc (core_syms, new_size); + symp = core_syms + core_num_syms; + core_num_syms += synth_count; + for (i = 0; i < synth_count; i++) + *symp++ = synthsyms + i; + *symp = 0; + } + min_insn_size = 1; offset_to_code = 0; @@ -214,19 +244,19 @@ DEFUN (core_init, (a_out_name), const char *a_out_name) /* Read in the text space of an a.out file. */ void -DEFUN (core_get_text_space, (core_bfd), bfd * core_bfd) +core_get_text_space (bfd *cbfd) { - core_text_space = (PTR) malloc (core_text_sect->_raw_size); + core_text_space = malloc (bfd_get_section_size (core_text_sect)); if (!core_text_space) { fprintf (stderr, _("%s: ran out room for %lu bytes of text space\n"), - whoami, (unsigned long) core_text_sect->_raw_size); + whoami, (unsigned long) bfd_get_section_size (core_text_sect)); done (1); } - if (!bfd_get_section_contents (core_bfd, core_text_sect, core_text_space, - 0, core_text_sect->_raw_size)) + if (!bfd_get_section_contents (cbfd, core_text_sect, core_text_space, + 0, bfd_get_section_size (core_text_sect))) { bfd_perror ("bfd_get_section_contents"); free (core_text_space); @@ -239,9 +269,13 @@ DEFUN (core_get_text_space, (core_bfd), bfd * core_bfd) void -DEFUN (find_call, (parent, p_lowpc, p_highpc), - Sym * parent AND bfd_vma p_lowpc AND bfd_vma p_highpc) +find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc) { + if (core_text_space == 0) + return; + + hist_clip_symbol_address (&p_lowpc, &p_highpc); + switch (bfd_get_arch (core_bfd)) { case bfd_arch_i386: @@ -273,7 +307,7 @@ DEFUN (find_call, (parent, p_lowpc, p_highpc), whoami, bfd_printable_name(core_bfd)); /* Don't give the error more than once. */ - ignore_direct_calls = false; + ignore_direct_calls = FALSE; } } @@ -283,7 +317,7 @@ DEFUN (find_call, (parent, p_lowpc, p_highpc), 't' -> symbol is a local (static) name. */ static int -DEFUN (core_sym_class, (sym), asymbol * sym) +core_sym_class (asymbol *sym) { symbol_info syminfo; const char *name; @@ -332,8 +366,15 @@ DEFUN (core_sym_class, (sym), asymbol * sym) for (name = sym->name; *name; ++name) { - if (*name == '.' || *name == '$') - return 0; + if (*name == '$') + return 0; + + /* Do not discard nested subprograms (those + which end with .NNN, where N are digits). */ + if (*name == '.') + for (name++; *name; name++) + if (! ISDIGIT (*name)) + return 0; } /* On systems where the C compiler adds an underscore to all @@ -365,10 +406,8 @@ DEFUN (core_sym_class, (sym), asymbol * sym) /* Get whatever source info we can get regarding address ADDR. */ -static boolean -DEFUN (get_src_info, (addr, filename, name, line_num), - bfd_vma addr AND const char **filename AND const char **name - AND int *line_num) +static bfd_boolean +get_src_info (bfd_vma addr, const char **filename, const char **name, int *line_num) { const char *fname = 0, *func_name = 0; int l = 0; @@ -383,14 +422,14 @@ DEFUN (get_src_info, (addr, filename, name, line_num), *filename = fname; *name = func_name; *line_num = l; - return true; + 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; + return FALSE; } } @@ -398,10 +437,10 @@ DEFUN (get_src_info, (addr, filename, name, line_num), One symbol per function is entered. */ void -core_create_function_syms (core_bfd) - bfd *core_bfd ATTRIBUTE_UNUSED; +core_create_function_syms () { - bfd_vma min_vma = ~0, max_vma = 0; + bfd_vma min_vma = ~(bfd_vma) 0; + bfd_vma max_vma = 0; int class; long i, found, skip; unsigned int j; @@ -448,6 +487,8 @@ core_create_function_syms (core_bfd) for (i = 0; i < core_num_syms; ++i) { + asection *sym_sec; + class = core_sym_class (core_syms[i]); if (!class) @@ -481,7 +522,10 @@ core_create_function_syms (core_bfd) sym_init (symtab.limit); /* Symbol offsets are always section-relative. */ - symtab.limit->addr = core_syms[i]->value + core_syms[i]->section->vma; + sym_sec = core_syms[i]->section; + symtab.limit->addr = core_syms[i]->value; + if (sym_sec) + symtab.limit->addr += bfd_get_section_vma (sym_sec->owner, sym_sec); if (symbol_map_count && !strcmp (core_syms[i]->name, symbol_map[found].function_name)) @@ -528,20 +572,22 @@ core_create_function_syms (core_bfd) } } - symtab.limit->is_func = true; - symtab.limit->is_bb_head = true; + symtab.limit->is_func = TRUE; + symtab.limit->is_bb_head = TRUE; if (class == 't') - symtab.limit->is_static = true; + 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); - 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 (sym_sec) + max_vma = MAX (bfd_get_section_vma (sym_sec->owner, sym_sec) + + bfd_section_size (sym_sec->owner, sym_sec) - 1, + max_vma); + else + max_vma = MAX (symtab.limit->addr, max_vma); DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n", (long) (symtab.limit - symtab.base), @@ -560,7 +606,7 @@ core_create_function_syms (core_bfd) sym_init (symtab.limit); symtab.limit->name = ""; symtab.limit->addr = max_vma + 1; - symtab.limit->end_addr = ~0; + symtab.limit->end_addr = ~(bfd_vma) 0; ++symtab.limit; symtab.len = symtab.limit - symtab.base; @@ -571,23 +617,23 @@ core_create_function_syms (core_bfd) One symbol per line of source code is entered. */ void -DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) +core_create_line_syms () { char *prev_name, *prev_filename; - int prev_name_len, prev_filename_len; - bfd_vma vma, min_vma = ~0, max_vma = 0; - bfd_vma offset; + unsigned int prev_name_len, prev_filename_len; + bfd_vma vma, min_vma = ~(bfd_vma) 0, max_vma = 0; Sym *prev, dummy, *sentinel, *sym; const char *filename; int prev_line_num; Sym_Table ltab; + bfd_vma vma_high; /* 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); + core_create_function_syms (); - /* Pass 1 - counter number of symbols. */ + /* 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 @@ -595,7 +641,7 @@ DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) 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. */ + BFD would provide an iterator for enumerating all line infos. */ prev_name_len = PATH_MAX; prev_filename_len = PATH_MAX; prev_name = xmalloc (prev_name_len); @@ -603,11 +649,10 @@ DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) ltab.len = 0; prev_line_num = 0; - for (offset = 0; offset < core_text_sect->_raw_size; offset += min_insn_size) + vma_high = core_text_sect->vma + bfd_get_section_size (core_text_sect); + for (vma = core_text_sect->vma; vma < vma_high; vma += min_insn_size) { - int len; - - vma = core_text_sect->vma + offset; + unsigned int len; if (!get_src_info (vma, &filename, &dummy.name, &dummy.line_num) || (prev_line_num == dummy.line_num @@ -671,12 +716,11 @@ DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) lot cleaner now. */ prev = 0; - for (offset = 0; offset < core_text_sect->_raw_size; offset += min_insn_size) + for (vma = core_text_sect->vma; vma < vma_high; vma += 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 (vma, &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)) @@ -686,7 +730,7 @@ DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) ltab.limit->name = xstrdup (ltab.limit->name); ltab.limit->file = source_file_lookup_path (filename); - ltab.limit->addr = core_text_sect->vma + offset; + 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 @@ -704,12 +748,6 @@ DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) 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; - DBG (AOUTDEBUG, printf ("[core_create_line_syms] %lu %s 0x%lx\n", (unsigned long) (ltab.limit - ltab.base), ltab.limit->name, @@ -718,15 +756,18 @@ DEFUN (core_create_line_syms, (core_bfd), bfd * core_bfd) } /* Update sentinels. */ - sentinel = sym_lookup (&symtab, 0); + sentinel = sym_lookup (&symtab, (bfd_vma) 0); - if (strcmp (sentinel->name, "") == 0 + if (sentinel + && strcmp (sentinel->name, "") == 0 && min_vma <= sentinel->end_addr) sentinel->end_addr = min_vma - 1; - sentinel = sym_lookup (&symtab, ~0); + sentinel = sym_lookup (&symtab, ~(bfd_vma) 0); - if (strcmp (sentinel->name, "") == 0 && max_vma >= sentinel->addr) + if (sentinel + && strcmp (sentinel->name, "") == 0 + && max_vma >= sentinel->addr) sentinel->addr = max_vma + 1; /* Copy in function symbols. */