On Tue, Oct 24, 2017 at 07:50:06PM +0530, Ravi Bangoria wrote: > Perf top is often crashing at very random locations on powerpc. > After investigating, I found the crash only happens when sample > is of zero length symbol. Powerpc kernel has many such symbols > which does not contain length details in vmlinux binary and thus > start and end addresses of such symbols are same. > > Structure > > struct sym_hist { > u64 nr_samples; > u64 period; > struct sym_hist_entry addr[0]; > }; > > has last member 'addr[]' of size zero. 'addr[]' is an array of > addresses that belongs to one symbol (function). If function > consist of 100 instructions, 'addr' points to an array of 100 > 'struct sym_hist_entry' elements. For zero length symbol, it > points to the *empty* array, i.e. no members in the array and > thus offset 0 is also invalid for such array. > > static int __symbol__inc_addr_samples(...) > { > ... > offset = addr - sym->start; > h = annotation__histogram(notes, evidx); > h->nr_samples++; > h->addr[offset].nr_samples++; > h->period += sample->period; > h->addr[offset].period += sample->period; > ... > } > > Here, when 'addr' is same as 'sym->start', 'offset' becomes 0, > which is valid for normal symbols but *invalid* for zero length > symbols and thus updating h->addr[offset] causes memory corruption. > > Fix this by adding one dummy element for zero length symbols. > > Fixes: edee44be5919 ("perf annotate: Don't throw error for zero length > symbols") > Signed-off-by: Ravi Bangoria <ravi.bango...@linux.vnet.ibm.com>
Acked-by: Namhyung Kim <namhy...@kernel.org> Thanks, Namhyung > --- > tools/perf/util/annotate.c | 12 +++++++++++- > 1 file changed, 11 insertions(+), 1 deletion(-) > > diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c > index 4397a8b..15db525 100644 > --- a/tools/perf/util/annotate.c > +++ b/tools/perf/util/annotate.c > @@ -606,9 +606,19 @@ static struct arch *arch__find(const char *name) > int symbol__alloc_hist(struct symbol *sym) > { > struct annotation *notes = symbol__annotation(sym); > - const size_t size = symbol__size(sym); > + size_t size = symbol__size(sym); > size_t sizeof_sym_hist; > > + /* > + * Add buffer of one element for zero length symbol. > + * When sample is taken from first instruction of > + * zero length symbol, perf still resolves it and > + * shows symbol name in perf report and allows to > + * annotate it. > + */ > + if (size == 0) > + size = 1; > + > /* Check for overflow when calculating sizeof_sym_hist */ > if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(struct > sym_hist_entry)) > return -1; > -- > 1.8.3.1 >