From: Richard Allen Date: Sun, 16 Feb 2025 22:50:05 +0000 (-0600) Subject: gprof: only process line numbers for intersection of vmas and histograms X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b8189cf9e40bd90502c9a2ce0df39dd54419bea4;p=thirdparty%2Fbinutils-gdb.git gprof: only process line numbers for intersection of vmas and histograms Some programs like RTOS firmware may have a large number of symbols. By loading the histograms before loading symbols, we can look up only the line numbers that were captured in the histogram file, which reduces processing time for such a firmware from ~2 minutes to ~2 seconds. Signed-off-by: Richard Allen --- diff --git a/gprof/corefile.c b/gprof/corefile.c index bc26bd7883e..a8970b3200d 100644 --- a/gprof/corefile.c +++ b/gprof/corefile.c @@ -755,8 +755,9 @@ core_create_line_syms (void) Sym prev, *sym; const char *filename; Sym_Table ltab; - bfd_vma vma_high; size_t ltab_reserved; + 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 @@ -786,53 +787,58 @@ core_create_line_syms (void) lot cleaner now. */ memset (&prev, 0, sizeof (prev)); - vma_high = core_text_sect->vma + bfd_section_size (core_text_sect); - for (vma = core_text_sect->vma; vma < vma_high; vma += insn_boundary) + for (size_t i = 0; i < num_histograms; ++i) { - if (ltab.len >= ltab_reserved) + 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) { - /* 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; + 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; + } + + 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; + ++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 (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; - - 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; } /* Reserve space for function symbols and/or trim excess space. */ diff --git a/gprof/gprof.c b/gprof/gprof.c index 9392575f747..d1cbf25fa28 100644 --- a/gprof/gprof.c +++ b/gprof/gprof.c @@ -527,17 +527,6 @@ This program is free software. This program has absolutely no warranty.\n")); if (ignore_direct_calls) core_get_text_space (core_bfd); - /* Create symbols from core image. */ - if (external_symbol_table) - core_create_syms_from (external_symbol_table); - else if (line_granularity) - core_create_line_syms (); - else - core_create_function_syms (); - - /* Translate sym specs into syms. */ - sym_id_parse (); - if (file_format == FF_PROF) { fprintf (stderr, @@ -557,6 +546,18 @@ This program is free software. This program has absolutely no warranty.\n")); while (optind++ < argc); } + /* Create symbols from core image. */ + if (external_symbol_table) + core_create_syms_from (external_symbol_table); + else if (line_granularity) + core_create_line_syms (); + else + core_create_function_syms (); + + /* Translate sym specs into syms. */ + sym_id_parse (); + + /* If user did not specify output style, try to guess something reasonable. */ if (output_style == 0)