gprof: only process line numbers for intersection of vmas and histograms

Some programs like RTOS firmware may have a large number of symbols.
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, which reduces processing
time for such a firmware from ~2 minutes to ~2 seconds.

Add symbol table access function, get_symtab, get_symtab_direct and
set_symtab to delay loading the symbol table until its first use.

	* aarch64.c (aarch64_find_call): Call get_symtab to get the
	symbol table pointer
	* alpha.c (alpha_find_call): Likewise.
	* basic_blocks.c (bb_read_rec): Likewise.
	(bb_write_blocks): Likewise.
	(print_exec_counts): Likewise.
	(print_annotated_source): Likewise.
	* call_graph.c (cg_tally): Likewise.
	(cg_write_arcs): Likewise.
	* cg_arcs.c (cycle_link): Likewise.
	(propagate_flags): Likewise.
	(cg_assemble): Likewise.
	* cg_print.c (cg_print): Likewise.
	(cg_print_index): Likewise.
	(cg_print_function_ordering): Likewise.
	* corefile.c: Include "gmon_io.h".
	(core_create_syms_from): Call get_symtab_direct to get the
	symbol table pointer.
	(core_create_function_syms): Likewise.
	(core_create_line_syms): Likewise.  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.
	* gmon_io.c (gmon_histograms_first): New.
	(gmon_out_read): Set gmon_histograms_first to true if all
	histogram records come first.
	(gmon_out_write): Call get_symtab to get the symbol table
	pointer.
	* hist.c (scale_and_align_entries): Likewise.
	(hist_assign_samples_1): Likewise.
	(hist_print): Likewise.
	* i386.c (i386_find_call): Likewise.
	* mips.c (mips_find_call): Likewise.
	* sparc.c (sparc_find_call): Likewise.
	* sym_ids.c (sym_id_parse): Likewise.
	* vax.c (vax_find_call): Likewise.
	* gmon_io.h (gmon_histograms_first): New.
	* gprof.c (man): Don't create profile info.
	(symtab_init): New.
	* gprof.h (symtab_init): New.
	* symtab.c (symtab): Changed to static.
	(get_symtab_direct): New.
	(get_symtab): Likewise.
	(set_symtab): Likewise.
	* symtab.h (symtab): Removed.
	(get_symtab_direct): New.
	(get_symtab): Likewise.
	(set_symtab): Likewise.

Signed-off-by: Richard Allen <rsaxvc@gmail.com>
Co-Authored-By: H.J. Lu <hjl.tools@gmail.com>
This commit is contained in:
Richard Allen
2025-03-08 16:44:18 +08:00
committed by H.J. Lu
parent ebe00173e3
commit c912005af7
19 changed files with 335 additions and 186 deletions

View File

@@ -275,11 +275,12 @@ cycle_link (void)
Sym *sym, *cyc, *member;
Arc *arc;
int num;
Sym_Table *symtab = get_symtab ();
/* count the number of cycles, and initialize the cycle lists: */
num_cycles = 0;
for (sym = symtab.base; sym < symtab.limit; ++sym)
for (sym = symtab->base; sym < symtab->limit; ++sym)
{
/* this is how you find unattached cycles: */
if (sym->cg.cyc.head == sym && sym->cg.cyc.next)
@@ -300,7 +301,7 @@ cycle_link (void)
*/
num = 0;
cyc = cycle_header;
for (sym = symtab.base; sym < symtab.limit; ++sym)
for (sym = symtab->base; sym < symtab->limit; ++sym)
{
if (!(sym->cg.cyc.head == sym && sym->cg.cyc.next != 0))
{
@@ -440,9 +441,10 @@ propagate_flags (Sym **symbols)
{
int sym_index;
Sym *old_head, *child;
Sym_Table *symtab = get_symtab ();
old_head = 0;
for (sym_index = symtab.len - 1; sym_index >= 0; --sym_index)
for (sym_index = symtab->len - 1; sym_index >= 0; --sym_index)
{
child = symbols[sym_index];
/*
@@ -597,12 +599,13 @@ cg_assemble (void)
Sym *parent, **time_sorted_syms, **top_sorted_syms;
unsigned int sym_index;
Arc *arc;
Sym_Table *symtab = get_symtab ();
/* Initialize various things:
Zero out child times.
Count self-recursive calls.
Indicate that nothing is on cycles. */
for (parent = symtab.base; parent < symtab.limit; parent++)
for (parent = symtab->base; parent < symtab->limit; parent++)
{
parent->cg.child_time = 0.0;
arc = arc_lookup (parent, parent);
@@ -633,7 +636,7 @@ cg_assemble (void)
/* Topologically order things. If any node is unnumbered, number
it and any of its descendents. */
for (parent = symtab.base; parent < symtab.limit; parent++)
for (parent = symtab->base; parent < symtab->limit; parent++)
{
if (parent->cg.top_order == DFN_NAN)
cg_dfn (parent);
@@ -643,14 +646,14 @@ cg_assemble (void)
cycle_link ();
/* Sort the symbol table in reverse topological order. */
top_sorted_syms = (Sym **) xmalloc (symtab.len * sizeof (Sym *));
for (sym_index = 0; sym_index < symtab.len; ++sym_index)
top_sorted_syms[sym_index] = &symtab.base[sym_index];
top_sorted_syms = (Sym **) xmalloc (symtab->len * sizeof (Sym *));
for (sym_index = 0; sym_index < symtab->len; ++sym_index)
top_sorted_syms[sym_index] = &symtab->base[sym_index];
qsort (top_sorted_syms, symtab.len, sizeof (Sym *), cmp_topo);
qsort (top_sorted_syms, symtab->len, sizeof (Sym *), cmp_topo);
DBG (DFNDEBUG,
printf ("[cg_assemble] topological sort listing\n");
for (sym_index = 0; sym_index < symtab.len; ++sym_index)
for (sym_index = 0; sym_index < symtab->len; ++sym_index)
{
printf ("[cg_assemble] ");
printf ("%d:", top_sorted_syms[sym_index]->cg.top_order);
@@ -668,24 +671,24 @@ cg_assemble (void)
/* Starting from the topological bottom, propagate children times
up to parents. */
cycle_time ();
for (sym_index = 0; sym_index < symtab.len; ++sym_index)
for (sym_index = 0; sym_index < symtab->len; ++sym_index)
propagate_time (top_sorted_syms[sym_index]);
free (top_sorted_syms);
/* Now, sort by CG.PROP.SELF + CG.PROP.CHILD. Sorting both the regular
function names and cycle headers. */
time_sorted_syms = (Sym **) xmalloc ((symtab.len + num_cycles) * sizeof (Sym *));
for (sym_index = 0; sym_index < symtab.len; sym_index++)
time_sorted_syms[sym_index] = &symtab.base[sym_index];
time_sorted_syms = (Sym **) xmalloc ((symtab->len + num_cycles) * sizeof (Sym *));
for (sym_index = 0; sym_index < symtab->len; sym_index++)
time_sorted_syms[sym_index] = &symtab->base[sym_index];
for (sym_index = 1; sym_index <= num_cycles; sym_index++)
time_sorted_syms[symtab.len + sym_index - 1] = &cycle_header[sym_index];
time_sorted_syms[symtab->len + sym_index - 1] = &cycle_header[sym_index];
qsort (time_sorted_syms, symtab.len + num_cycles, sizeof (Sym *),
qsort (time_sorted_syms, symtab->len + num_cycles, sizeof (Sym *),
cmp_total);
for (sym_index = 0; sym_index < symtab.len + num_cycles; sym_index++)
for (sym_index = 0; sym_index < symtab->len + num_cycles; sym_index++)
time_sorted_syms[sym_index]->cg.index = sym_index + 1;
return time_sorted_syms;