On Mon, Jan 6, 2025 at 11:38 AM Christophe Leroy <christophe.le...@csgroup.eu> wrote: > > Since commit 659ad3492b91 ("perf maps: Switch from rbtree to lazily > sorted array for addresses"), perf doesn't display anymore kernel > symbols on powerpc, allthough it still detects them as kernel addresses. > > # Overhead Command Shared Object Symbol > # ........ .......... ............. > ...................................... > # > 80.49% Coeur main [unknown] [k] 0xc005f0f8 > 3.91% Coeur main gau [.] > engine_loop.constprop.0.isra.0 > 1.72% Coeur main [unknown] [k] 0xc005f11c > 1.09% Coeur main [unknown] [k] 0xc01f82c8 > 0.44% Coeur main libc.so.6 [.] epoll_wait > 0.38% Coeur main [unknown] [k] 0xc0011718 > 0.36% Coeur main [unknown] [k] 0xc01f45c0 > > This is because function maps__find_next_entry() now returns current > entry instead of next entry, leading to kernel map end address > getting mis-configured with its own start address instead of the > start address of the following map. > > Fix it by really taking the next entry. > > Fixes: 659ad3492b91 ("perf maps: Switch from rbtree to lazily sorted array > for addresses") > Signed-off-by: Christophe Leroy <christophe.le...@csgroup.eu> > Reviewed-by: Arnaldo Carvalho de Melo <a...@redhat.com> > --- > tools/perf/util/maps.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c > index 432399cbe5dd..d39bf27a5fdd 100644 > --- a/tools/perf/util/maps.c > +++ b/tools/perf/util/maps.c > @@ -1137,7 +1137,7 @@ struct map *maps__find_next_entry(struct maps *maps, > struct map *map) > > down_read(maps__lock(maps)); > i = maps__by_address_index(maps, map); > - if (i < maps__nr_maps(maps)) > + if (++i < maps__nr_maps(maps)) > result = map__get(maps__maps_by_address(maps)[i]);
Thanks for diagnosing this and sorry for the bug! Using the next entry in this way won't work if the entries aren't sorted. I think the code needs to be a little more complex, something like: ``` while (1) { down_read(maps__lock(maps)); if (!maps__maps_by_address_sorted(maps)) { up_read(maps__lock(maps)); maps__sort_by_address(maps); continue; } i = maps__by_address_index(maps, map) + 1; if (i < maps__nr_maps(maps)) result = map__get(maps__maps_by_address(maps)[i]); up_read(maps__lock(maps)); break; } ``` We could also implement the code similar to maps__by_address_index but with some kind of best next value in the unsorted case. Given the function has a single caller then this is probably overkill, but we've seen performance issues in this code before. Thanks, Ian