mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 13:55:32 +00:00
![John Keeping](/assets/img/avatar_default.png)
Commite5adfc3e7e
("perf map: Synthesize maps only for thread group leader") changed the recording side so that we no longer get mmap events for threads other than the thread group leader (when synthesising these events for threads which exist before perf is started). When a file recorded after this change is loaded, the lack of mmap records mean that unwinding is not set up for any other threads. This can be seen in a simple record/report scenario: perf record --call-graph=dwarf -t $TID perf report If $TID is a process ID then the report will show call graphs, but if $TID is a secondary thread the output is as if --call-graph=none was specified. Following the rationale in that commit, move the libunwind fields into struct map_groups and update the libunwind functions to take this instead of the struct thread. This is only required for unwind__finish_access which must now be called from map_groups__delete and the others are changed for symmetry. Note that unwind__get_entries keeps the thread argument since it is required for symbol lookup and the libdw unwind provider uses the thread ID. Signed-off-by: John Keeping <john@metanate.com> Reviewed-by: Jiri Olsa <jolsa@kernel.org> Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com> Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru> Cc: Namhyung Kim <namhyung@kernel.org> Cc: Peter Zijlstra <peterz@infradead.org> Fixes:e5adfc3e7e
("perf map: Synthesize maps only for thread group leader") Link: http://lkml.kernel.org/r/20190815100146.28842-2-john@metanate.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
97 lines
2.6 KiB
C
97 lines
2.6 KiB
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef __PERF_MAP_GROUPS_H
|
|
#define __PERF_MAP_GROUPS_H
|
|
|
|
#include <linux/refcount.h>
|
|
#include <linux/rbtree.h>
|
|
#include <stdio.h>
|
|
#include <stdbool.h>
|
|
#include <linux/types.h>
|
|
#include "rwsem.h"
|
|
|
|
struct ref_reloc_sym;
|
|
struct machine;
|
|
struct map;
|
|
struct thread;
|
|
|
|
struct maps {
|
|
struct rb_root entries;
|
|
struct rb_root names;
|
|
struct rw_semaphore lock;
|
|
};
|
|
|
|
void 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 map *maps__first(struct maps *maps);
|
|
struct map *map__next(struct map *map);
|
|
struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *name, struct map **mapp);
|
|
|
|
struct map_groups {
|
|
struct maps maps;
|
|
struct machine *machine;
|
|
refcount_t refcnt;
|
|
#ifdef HAVE_LIBUNWIND_SUPPORT
|
|
void *addr_space;
|
|
struct unwind_libunwind_ops *unwind_libunwind_ops;
|
|
#endif
|
|
};
|
|
|
|
#define KMAP_NAME_LEN 256
|
|
|
|
struct kmap {
|
|
struct ref_reloc_sym *ref_reloc_sym;
|
|
struct map_groups *kmaps;
|
|
char name[KMAP_NAME_LEN];
|
|
};
|
|
|
|
struct map_groups *map_groups__new(struct machine *machine);
|
|
void map_groups__delete(struct map_groups *mg);
|
|
bool map_groups__empty(struct map_groups *mg);
|
|
|
|
static inline struct map_groups *map_groups__get(struct map_groups *mg)
|
|
{
|
|
if (mg)
|
|
refcount_inc(&mg->refcnt);
|
|
return mg;
|
|
}
|
|
|
|
void map_groups__put(struct map_groups *mg);
|
|
void map_groups__init(struct map_groups *mg, struct machine *machine);
|
|
void map_groups__exit(struct map_groups *mg);
|
|
int map_groups__clone(struct thread *thread, struct map_groups *parent);
|
|
size_t map_groups__fprintf(struct map_groups *mg, FILE *fp);
|
|
|
|
void map_groups__insert(struct map_groups *mg, struct map *map);
|
|
|
|
static inline void map_groups__remove(struct map_groups *mg, struct map *map)
|
|
{
|
|
maps__remove(&mg->maps, map);
|
|
}
|
|
|
|
static inline struct map *map_groups__find(struct map_groups *mg, u64 addr)
|
|
{
|
|
return maps__find(&mg->maps, addr);
|
|
}
|
|
|
|
struct map *map_groups__first(struct map_groups *mg);
|
|
|
|
static inline struct map *map_groups__next(struct map *map)
|
|
{
|
|
return map__next(map);
|
|
}
|
|
|
|
struct symbol *map_groups__find_symbol(struct map_groups *mg, u64 addr, struct map **mapp);
|
|
struct symbol *map_groups__find_symbol_by_name(struct map_groups *mg, const char *name, struct map **mapp);
|
|
|
|
struct addr_map_symbol;
|
|
|
|
int map_groups__find_ams(struct addr_map_symbol *ams);
|
|
|
|
int map_groups__fixup_overlappings(struct map_groups *mg, struct map *map, FILE *fp);
|
|
|
|
struct map *map_groups__find_by_name(struct map_groups *mg, const char *name);
|
|
|
|
int map_groups__merge_in(struct map_groups *kmaps, struct map *new_map);
|
|
|
|
#endif // __PERF_MAP_GROUPS_H
|