X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gprof%2Fcorefile.c;h=45f743127de1d04e2d1c317955b4acfa6f2aab26;hb=f9d1eeed58ec0b3063e014273164179586b1f141;hp=0d90b06ff7e1ceb383a62b9cf6f5e032d3d9b90c;hpb=74335607500eaa6894aa7dc8c103d73a85758504;p=deliverable%2Fbinutils-gdb.git diff --git a/gprof/corefile.c b/gprof/corefile.c index 0d90b06ff7..45f743127d 100644 --- a/gprof/corefile.c +++ b/gprof/corefile.c @@ -1,13 +1,12 @@ /* corefile.c - Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005 - Free Software Foundation, Inc. + Copyright (C) 1999-2014 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, @@ -20,24 +19,27 @@ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */ -#include "libiberty.h" #include "gprof.h" +#include "libiberty.h" +#include "filenames.h" #include "search_list.h" #include "source.h" #include "symtab.h" +#include "hist.h" #include "corefile.h" +#include "safe-ctype.h" bfd *core_bfd; static int core_num_syms; static asymbol **core_syms; asection *core_text_sect; -PTR core_text_space; +void * core_text_space; static int min_insn_size; int offset_to_code; /* For mapping symbols to specific .o files during file ordering. */ -struct function_map *symbol_map; +struct function_map * symbol_map; unsigned int symbol_map_count; static void read_function_mappings (const char *); @@ -51,6 +53,7 @@ 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); +extern void aarch64_find_call (Sym *, bfd_vma, bfd_vma); static void parse_error (const char *filename) @@ -59,12 +62,23 @@ parse_error (const char *filename) done (1); } +/* Compare two function_map structs based on function name. + We want to sort in ascending order. */ + +static int +cmp_symbol_map (const void * l, const void * r) +{ + return strcmp (((struct function_map *) l)->function_name, + ((struct function_map *) r)->function_name); +} + static void read_function_mappings (const char *filename) { - FILE *file = fopen (filename, "r"); + FILE * file = fopen (filename, "r"); char dummy[1024]; int count = 0; + unsigned int i; if (!file) { @@ -127,7 +141,7 @@ read_function_mappings (const char *filename) } /* dummy has the filename, go ahead and copy it. */ - symbol_map[count].file_name = xmalloc (strlen (dummy) + 1); + symbol_map[count].file_name = (char *) xmalloc (strlen (dummy) + 1); strcpy (symbol_map[count].file_name, dummy); /* Now we need the function name. */ @@ -135,18 +149,26 @@ read_function_mappings (const char *filename) if (!matches) parse_error (filename); tmp = strrchr (dummy, ' ') + 1; - symbol_map[count].function_name = xmalloc (strlen (tmp) + 1); + symbol_map[count].function_name = (char *) xmalloc (strlen (tmp) + 1); strcpy (symbol_map[count].function_name, tmp); count++; } /* Record the size of the map table for future reference. */ symbol_map_count = count; -} + for (i = 0; i < symbol_map_count; ++i) + if (i == 0 + || filename_cmp (symbol_map[i].file_name, symbol_map[i - 1].file_name)) + symbol_map[i].is_first = 1; + + qsort (symbol_map, symbol_map_count, sizeof (struct function_map), cmp_symbol_map); + + fclose (file); +} void -core_init (const char *aout_name) +core_init (const char * aout_name) { int core_sym_bytes; asymbol *synthsyms; @@ -209,7 +231,7 @@ core_init (const char *aout_name) long i; new_size = (core_num_syms + synth_count + 1) * sizeof (*core_syms); - core_syms = xrealloc (core_syms, new_size); + core_syms = (asymbol **) xrealloc (core_syms, new_size); symp = core_syms + core_num_syms; core_num_syms += synth_count; for (i = 0; i < synth_count; i++) @@ -269,6 +291,11 @@ core_get_text_space (bfd *cbfd) void 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: @@ -295,6 +322,10 @@ find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc) mips_find_call (parent, p_lowpc, p_highpc); break; + case bfd_arch_aarch64: + aarch64_find_call (parent, p_lowpc, p_highpc); + break; + default: fprintf (stderr, _("%s: -c not supported on architecture %s\n"), whoami, bfd_printable_name(core_bfd)); @@ -359,8 +390,37 @@ core_sym_class (asymbol *sym) for (name = sym->name; *name; ++name) { - if (*name == '.' || *name == '$') - return 0; + if (*name == '$') + return 0; + + while (*name == '.') + { + /* Allow both nested subprograms (which end with ".NNN", where N is + a digit) and GCC cloned functions (which contain ".clone"). + Allow for multiple iterations of both - apparently GCC can clone + clones and subprograms. */ + int digit_seen = 0; +#define CLONE_NAME ".clone." +#define CLONE_NAME_LEN strlen (CLONE_NAME) +#define CONSTPROP_NAME ".constprop." +#define CONSTPROP_NAME_LEN strlen (CONSTPROP_NAME) + + if (strlen (name) > CLONE_NAME_LEN + && strncmp (name, CLONE_NAME, CLONE_NAME_LEN) == 0) + name += CLONE_NAME_LEN - 1; + + else if (strlen (name) > CONSTPROP_NAME_LEN + && strncmp (name, CONSTPROP_NAME, CONSTPROP_NAME_LEN) == 0) + name += CONSTPROP_NAME_LEN - 1; + + for (name++; *name; name++) + if (digit_seen && *name == '.') + break; + else if (ISDIGIT (*name)) + digit_seen = 1; + else + return 0; + } } /* On systems where the C compiler adds an underscore to all @@ -413,23 +473,142 @@ get_src_info (bfd_vma addr, const char **filename, const char **name, int *line_ else { DBG (AOUTDEBUG, printf ("[get_src_info] no info for 0x%lx (%s:%d,%s)\n", - (long) addr, fname ? fname : "", l, + (unsigned long) addr, + fname ? fname : "", l, func_name ? func_name : "")); return FALSE; } } +/* Return number of symbols in a symbol-table file. */ + +static int +num_of_syms_in (FILE * f) +{ + const int BUFSIZE = 1024; + char * buf = (char *) xmalloc (BUFSIZE); + char * address = (char *) xmalloc (BUFSIZE); + char type; + char * name = (char *) xmalloc (BUFSIZE); + int num = 0; + + while (!feof (f) && fgets (buf, BUFSIZE - 1, f)) + { + if (sscanf (buf, "%s %c %s", address, &type, name) == 3) + if (type == 't' || type == 'T') + ++num; + } + + free (buf); + free (address); + free (name); + + return num; +} + +/* Read symbol table from a file. */ + +void +core_create_syms_from (const char * sym_table_file) +{ + const int BUFSIZE = 1024; + char * buf = (char *) xmalloc (BUFSIZE); + char * address = (char *) xmalloc (BUFSIZE); + char type; + char * name = (char *) xmalloc (BUFSIZE); + bfd_vma min_vma = ~(bfd_vma) 0; + bfd_vma max_vma = 0; + FILE * f; + + f = fopen (sym_table_file, "r"); + if (!f) + { + fprintf (stderr, _("%s: could not open %s.\n"), whoami, sym_table_file); + done (1); + } + + /* Pass 1 - determine upper bound on number of function names. */ + symtab.len = num_of_syms_in (f); + + if (symtab.len == 0) + { + fprintf (stderr, _("%s: file `%s' has no symbols\n"), whoami, sym_table_file); + done (1); + } + + symtab.base = (Sym *) xmalloc (symtab.len * sizeof (Sym)); + + /* Pass 2 - create symbols. */ + symtab.limit = symtab.base; + + if (fseek (f, 0, SEEK_SET) != 0) + { + perror (sym_table_file); + done (1); + } + + while (!feof (f) && fgets (buf, BUFSIZE - 1, f)) + { + if (sscanf (buf, "%s %c %s", address, &type, name) == 3) + if (type != 't' && type != 'T') + continue; + + sym_init (symtab.limit); + + sscanf (address, "%" BFD_VMA_FMT "x", &(symtab.limit->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; + } + fclose (f); + + symtab.len = symtab.limit - symtab.base; + symtab_finalize (&symtab); + + free (buf); + free (address); + free (name); +} + +static int +search_mapped_symbol (const void * l, const void * r) +{ + return strcmp ((const char *) l, ((const struct function_map *) r)->function_name); +} + /* Read in symbol table from core. One symbol per function is entered. */ void -core_create_function_syms () +core_create_function_syms (void) { - bfd_vma min_vma = ~(bfd_vma) 0; + bfd_vma min_vma = ~ (bfd_vma) 0; bfd_vma max_vma = 0; - int class; - long i, found, skip; - unsigned int j; + int cxxclass; + long i; + struct function_map * found = NULL; + int core_has_func_syms = 0; + + switch (core_bfd->xvec->flavour) + { + default: + break; + case bfd_target_coff_flavour: + case bfd_target_ecoff_flavour: + case bfd_target_xcoff_flavour: + case bfd_target_elf_flavour: + case bfd_target_nlm_flavour: + case bfd_target_som_flavour: + core_has_func_syms = 1; + } /* Pass 1 - determine upper bound on number of function names. */ symtab.len = 0; @@ -439,23 +618,18 @@ core_create_function_syms () if (!core_sym_class (core_syms[i])) continue; - /* This should be replaced with a binary search or hashed - search. Gross. - - Don't create a symtab entry for a function that has + /* Don't create a symtab entry for a function that has a mapping to a file, unless it's the first function 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 (j > 0 && ! strcmp (symbol_map [j].file_name, - symbol_map [j - 1].file_name)) - skip = 1; - break; - } - - if (!skip) + if (symbol_map_count != 0) + { + /* Note: some systems (SunOS 5.8) crash if bsearch base argument + is NULL. */ + found = (struct function_map *) bsearch + (core_syms[i]->name, symbol_map, symbol_map_count, + sizeof (struct function_map), search_mapped_symbol); + } + if (found == NULL || found->is_first) ++symtab.len; } @@ -465,8 +639,7 @@ core_create_function_syms () done (1); } - /* The "+ 2" is for the sentinels. */ - symtab.base = (Sym *) xmalloc ((symtab.len + 2) * sizeof (Sym)); + symtab.base = (Sym *) xmalloc (symtab.len * sizeof (Sym)); /* Pass 2 - create symbols. */ symtab.limit = symtab.base; @@ -475,9 +648,9 @@ core_create_function_syms () { asection *sym_sec; - class = core_sym_class (core_syms[i]); + cxxclass = core_sym_class (core_syms[i]); - if (!class) + if (!cxxclass) { DBG (AOUTDEBUG, printf ("[core_create_function_syms] rejecting: 0x%lx %s\n", @@ -486,23 +659,15 @@ core_create_function_syms () continue; } - /* This should be replaced with a binary search or hashed - search. Gross. */ - skip = 0; - found = 0; - - for (j = 0; j < symbol_map_count; j++) - if (!strcmp (core_syms[i]->name, symbol_map[j].function_name)) - { - if (j > 0 && ! strcmp (symbol_map [j].file_name, - symbol_map [j - 1].file_name)) - skip = 1; - else - found = j; - break; - } - - if (skip) + if (symbol_map_count != 0) + { + /* Note: some systems (SunOS 5.8) crash if bsearch base argument + is NULL. */ + found = (struct function_map *) bsearch + (core_syms[i]->name, symbol_map, symbol_map_count, + sizeof (struct function_map), search_mapped_symbol); + } + if (found && ! found->is_first) continue; sym_init (symtab.limit); @@ -513,10 +678,9 @@ core_create_function_syms () 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)) + if (found) { - symtab.limit->name = symbol_map[found].file_name; + symtab.limit->name = found->file_name; symtab.limit->mapped = 1; } else @@ -527,10 +691,11 @@ core_create_function_syms () /* Lookup filename and line number, if we can. */ { - const char *filename, *func_name; + 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); @@ -558,10 +723,11 @@ core_create_function_syms () } } - symtab.limit->is_func = TRUE; + symtab.limit->is_func = (!core_has_func_syms + || (core_syms[i]->flags & BSF_FUNCTION) != 0); symtab.limit->is_bb_head = TRUE; - if (class == 't') + if (cxxclass == 't') symtab.limit->is_static = TRUE; /* Keep track of the minimum and maximum vma addresses used by all @@ -575,12 +741,6 @@ core_create_function_syms () else 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; - DBG (AOUTDEBUG, printf ("[core_create_function_syms] %ld %s 0x%lx\n", (long) (symtab.limit - symtab.base), symtab.limit->name, @@ -588,19 +748,6 @@ core_create_function_syms () ++symtab.limit; } - /* 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; - symtab.len = symtab.limit - symtab.base; symtab_finalize (&symtab); } @@ -609,12 +756,12 @@ core_create_function_syms () One symbol per line of source code is entered. */ void -core_create_line_syms () +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, *sentinel, *sym; + Sym *prev, dummy, *sym; const char *filename; int prev_line_num; Sym_Table ltab; @@ -636,8 +783,8 @@ core_create_line_syms () 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); - prev_filename = xmalloc (prev_filename_len); + prev_name = (char *) xmalloc (prev_name_len); + prev_filename = (char *) xmalloc (prev_filename_len); ltab.len = 0; prev_line_num = 0; @@ -650,7 +797,7 @@ core_create_line_syms () || (prev_line_num == dummy.line_num && prev_name != NULL && strcmp (prev_name, dummy.name) == 0 - && strcmp (prev_filename, filename) == 0)) + && filename_cmp (prev_filename, filename) == 0)) continue; ++ltab.len; @@ -661,7 +808,7 @@ core_create_line_syms () { prev_name_len = len + 1024; free (prev_name); - prev_name = xmalloc (prev_name_len); + prev_name = (char *) xmalloc (prev_name_len); } strcpy (prev_name, dummy.name); @@ -671,7 +818,7 @@ core_create_line_syms () { prev_filename_len = len + 1024; free (prev_filename); - prev_filename = xmalloc (prev_filename_len); + prev_filename = (char *) xmalloc (prev_filename_len); } strcpy (prev_filename, filename); @@ -715,7 +862,7 @@ core_create_line_syms () 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)) + && filename_cmp (prev->file->name, filename) == 0)) continue; /* Make name pointer a malloc'ed string. */ @@ -735,17 +882,12 @@ core_create_line_syms () else { sym = sym_lookup(&symtab, ltab.limit->addr); - ltab.limit->is_static = sym->is_static; + if (sym) + ltab.limit->is_static = sym->is_static; } 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, @@ -753,21 +895,6 @@ core_create_line_syms () ++ltab.limit; } - /* Update sentinels. */ - sentinel = sym_lookup (&symtab, (bfd_vma) 0); - - if (sentinel - && strcmp (sentinel->name, "") == 0 - && min_vma <= sentinel->end_addr) - sentinel->end_addr = min_vma - 1; - - sentinel = sym_lookup (&symtab, ~(bfd_vma) 0); - - if (sentinel - && strcmp (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;