X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gprof%2Fcorefile.c;h=37942b564addb3bf91829ff81e83a851a9f9992c;hb=8b8c7c9f49992750f66f81b4601d593a3858d98c;hp=b3433c299c6ea5941c01b0ce8ea3b2341df0fa79;hpb=d401d98a57f2e2d30befd5dbe479aaa2d5e83deb;p=deliverable%2Fbinutils-gdb.git diff --git a/gprof/corefile.c b/gprof/corefile.c index b3433c299c..37942b564a 100644 --- a/gprof/corefile.c +++ b/gprof/corefile.c @@ -1,7 +1,6 @@ /* corefile.c - Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008 - Free Software Foundation, Inc. + Copyright (C) 1999-2016 Free Software Foundation, Inc. This file is part of GNU Binutils. @@ -22,6 +21,7 @@ #include "gprof.h" #include "libiberty.h" +#include "filenames.h" #include "search_list.h" #include "source.h" #include "symtab.h" @@ -33,13 +33,13 @@ 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 *); @@ -53,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) @@ -61,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) { @@ -129,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. */ @@ -137,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; @@ -211,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++) @@ -302,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)); @@ -369,12 +393,34 @@ core_sym_class (asymbol *sym) 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; + 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 @@ -434,17 +480,135 @@ get_src_info (bfd_vma addr, const char **filename, const char **name, int *line_ } } +/* 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; @@ -454,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; } @@ -489,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", @@ -500,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); @@ -527,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 @@ -541,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); @@ -572,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 @@ -604,7 +756,7 @@ 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; @@ -631,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; @@ -645,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; @@ -656,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); @@ -666,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); @@ -710,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. */