diff options
Diffstat (limited to 'tools/perf/util/symbol.c')
| -rw-r--r-- | tools/perf/util/symbol.c | 37 | 
1 files changed, 27 insertions, 10 deletions
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index dea0fc495185..f72baf636724 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -101,11 +101,6 @@ static int prefix_underscores_count(const char *str)  	return tail - str;  } -void __weak arch__symbols__fixup_end(struct symbol *p, struct symbol *c) -{ -	p->end = c->start; -} -  const char * __weak arch__normalize_symbol_name(const char *name)  {  	return name; @@ -217,7 +212,8 @@ again:  	}  } -void symbols__fixup_end(struct rb_root_cached *symbols) +/* Update zero-sized symbols using the address of the next symbol */ +void symbols__fixup_end(struct rb_root_cached *symbols, bool is_kallsyms)  {  	struct rb_node *nd, *prevnd = rb_first_cached(symbols);  	struct symbol *curr, *prev; @@ -231,8 +227,29 @@ void symbols__fixup_end(struct rb_root_cached *symbols)  		prev = curr;  		curr = rb_entry(nd, struct symbol, rb_node); -		if (prev->end == prev->start || prev->end != curr->start) -			arch__symbols__fixup_end(prev, curr); +		/* +		 * On some architecture kernel text segment start is located at +		 * some low memory address, while modules are located at high +		 * memory addresses (or vice versa).  The gap between end of +		 * kernel text segment and beginning of first module's text +		 * segment is very big.  Therefore do not fill this gap and do +		 * not assign it to the kernel dso map (kallsyms). +		 * +		 * In kallsyms, it determines module symbols using '[' character +		 * like in: +		 *   ffffffffc1937000 T hdmi_driver_init  [snd_hda_codec_hdmi] +		 */ +		if (prev->end == prev->start) { +			/* Last kernel/module symbol mapped to end of page */ +			if (is_kallsyms && (!strchr(prev->name, '[') != +					    !strchr(curr->name, '['))) +				prev->end = roundup(prev->end + 4096, 4096); +			else +				prev->end = curr->start; + +			pr_debug4("%s sym:%s end:%#" PRIx64 "\n", +				  __func__, prev->name, prev->end); +		}  	}  	/* Last entry */ @@ -1467,7 +1484,7 @@ int __dso__load_kallsyms(struct dso *dso, const char *filename,  	if (kallsyms__delta(kmap, filename, &delta))  		return -1; -	symbols__fixup_end(&dso->symbols); +	symbols__fixup_end(&dso->symbols, true);  	symbols__fixup_duplicate(&dso->symbols);  	if (dso->kernel == DSO_SPACE__KERNEL_GUEST) @@ -1659,7 +1676,7 @@ int dso__load_bfd_symbols(struct dso *dso, const char *debugfile)  #undef bfd_asymbol_section  #endif -	symbols__fixup_end(&dso->symbols); +	symbols__fixup_end(&dso->symbols, false);  	symbols__fixup_duplicate(&dso->symbols);  	dso->adjust_symbols = 1;  | 
