mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
synced 2026-10-31 22:34:33 +01:00
The unwind-libdw dwfl has ELF binaries associated with mmap addresses. Experimenting with using the per dso dwfl it is required to alter the address to be 0 based variant. Unfortunately libdwfl doesn't allow a single unwind and then an update to the return address to be 0 based as there are assertions that registers aren't updated once an unwind has started, etc. As removing the dwfl didn't prove possible, an alternative is to just not discard the dwfl when the unwind ends. The dwfl is valid for a process unless a dso is loaded at the same address as a previous one. So keep the dwfl with the maps, invalidate it if a map is removed (in case a new map replaces it) and recycle the dwfl in the unwinding code. A wrinkly in the implementation of this is that the attached thread argument is remembered by the dwfl and so it needs to be a pointer to memory that also persists with the dwfl (struct dwfl_ui_thread_info in the code). Recording 10 seconds of system wide data with --call-graph=dwarf and then processing with perf report shows a total runtime improvement from 41.583s to 2.279s (an 18x speedup). Signed-off-by: Ian Rogers <[email protected]> Cc: Aditya Bodkhe <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Albert Ou <[email protected]> Cc: Alexandre Ghiti <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Athira Rajeev <[email protected]> Cc: Chun-Tse Shao <[email protected]> Cc: Dmitriy Vyukov <[email protected]> Cc: Dr. David Alan Gilbert <[email protected]> Cc: Guo Ren <[email protected]> Cc: Haibo Xu <[email protected]> Cc: Howard Chu <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: James Clark <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: John Garry <[email protected]> Cc: Krzysztof Łopatowski <[email protected]> Cc: Leo Yan <[email protected]> Cc: Mark Wielaard <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Palmer Dabbelt <[email protected]> Cc: Paul Walmsley <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Sergei Trofimovich <[email protected]> Cc: Shimin Guo <[email protected]> Cc: Stephen Brennan <[email protected]> Cc: Thomas Falcon <[email protected]> Cc: Will Deacon <[email protected]> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
86 lines
2.6 KiB
C
86 lines
2.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __PERF_MAPS_H
|
|
#define __PERF_MAPS_H
|
|
|
|
#include <linux/refcount.h>
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <linux/types.h>
|
|
|
|
struct ref_reloc_sym;
|
|
struct machine;
|
|
struct map;
|
|
struct maps;
|
|
|
|
#define KMAP_NAME_LEN 256
|
|
|
|
struct kmap {
|
|
struct ref_reloc_sym *ref_reloc_sym;
|
|
struct maps *kmaps;
|
|
char name[KMAP_NAME_LEN];
|
|
};
|
|
|
|
struct maps *maps__new(struct machine *machine);
|
|
bool maps__empty(struct maps *maps);
|
|
int maps__copy_from(struct maps *maps, struct maps *parent);
|
|
|
|
struct maps *maps__get(struct maps *maps);
|
|
void maps__put(struct maps *maps);
|
|
|
|
static inline void __maps__zput(struct maps **map)
|
|
{
|
|
maps__put(*map);
|
|
*map = NULL;
|
|
}
|
|
|
|
#define maps__zput(map) __maps__zput(&map)
|
|
|
|
bool maps__equal(struct maps *a, struct maps *b);
|
|
|
|
/* Iterate over map calling cb for each entry. */
|
|
int maps__for_each_map(struct maps *maps, int (*cb)(struct map *map, void *data), void *data);
|
|
/* Iterate over map removing an entry if cb returns true. */
|
|
void maps__remove_maps(struct maps *maps, bool (*cb)(struct map *map, void *data), void *data);
|
|
|
|
struct machine *maps__machine(const struct maps *maps);
|
|
unsigned int maps__nr_maps(const struct maps *maps); /* Test only. */
|
|
refcount_t *maps__refcnt(struct maps *maps); /* Test only. */
|
|
|
|
#ifdef HAVE_LIBUNWIND_SUPPORT
|
|
void *maps__addr_space(const struct maps *maps);
|
|
void maps__set_addr_space(struct maps *maps, void *addr_space);
|
|
const struct unwind_libunwind_ops *maps__unwind_libunwind_ops(const struct maps *maps);
|
|
void maps__set_unwind_libunwind_ops(struct maps *maps, const struct unwind_libunwind_ops *ops);
|
|
#endif
|
|
#ifdef HAVE_LIBDW_SUPPORT
|
|
void *maps__libdw_addr_space_dwfl(const struct maps *maps);
|
|
void maps__set_libdw_addr_space_dwfl(struct maps *maps, void *dwfl);
|
|
#endif
|
|
|
|
size_t maps__fprintf(struct maps *maps, FILE *fp);
|
|
|
|
int maps__insert(struct maps *maps, struct map *map);
|
|
void maps__remove(struct maps *maps, struct map *map);
|
|
|
|
struct map *maps__find(struct maps *maps, u64 addr);
|
|
struct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map **mapp);
|
|
struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp);
|
|
|
|
struct addr_map_symbol;
|
|
|
|
int maps__find_ams(struct maps *maps, struct addr_map_symbol *ams);
|
|
|
|
int maps__fixup_overlap_and_insert(struct maps *maps, struct map *new);
|
|
|
|
struct map *maps__find_by_name(struct maps *maps, const char *name);
|
|
|
|
struct map *maps__find_next_entry(struct maps *maps, struct map *map);
|
|
|
|
int maps__merge_in(struct maps *kmaps, struct map *new_map);
|
|
|
|
void maps__fixup_end(struct maps *maps);
|
|
|
|
void maps__load_first(struct maps *maps);
|
|
|
|
#endif // __PERF_MAPS_H
|