Commit 9de89fe7 authored by Arnaldo Carvalho de Melo's avatar Arnaldo Carvalho de Melo Committed by Ingo Molnar

perf symbols: Remove perf_session usage in symbols layer

I noticed while writing the first test in 'perf regtest' that to
just test the symbol handling routines one needs to create a
perf session, that is a layer centered on a perf.data file,
events, etc, so I untied these layers.

This reduces the complexity for the users as the number of
parameters to most of the symbols and session APIs now was
reduced while not adding more state to all the map instances by
only having data that is needed to split the kernel (kallsyms
and ELF symtab sections) maps and do vmlinux relocation on the
main kernel map.
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: Frédéric Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
LKML-Reference: <1265223128-11786-1-git-send-email-acme@infradead.org>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent b8f46c5a
...@@ -369,7 +369,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session, ...@@ -369,7 +369,7 @@ static void __print_result(struct rb_root *root, struct perf_session *session,
if (is_caller) { if (is_caller) {
addr = data->call_site; addr = data->call_site;
if (!raw_ip) if (!raw_ip)
sym = map_groups__find_function(&session->kmaps, session, addr, NULL); sym = map_groups__find_function(&session->kmaps, addr, NULL);
} else } else
addr = data->ptr; addr = data->ptr;
......
...@@ -122,8 +122,7 @@ static int opt_del_probe_event(const struct option *opt __used, ...@@ -122,8 +122,7 @@ static int opt_del_probe_event(const struct option *opt __used,
static void evaluate_probe_point(struct probe_point *pp) static void evaluate_probe_point(struct probe_point *pp)
{ {
struct symbol *sym; struct symbol *sym;
sym = map__find_symbol_by_name(session.kmap, pp->function, sym = map__find_symbol_by_name(session.kmap, pp->function, NULL);
session.psession, NULL);
if (!sym) if (!sym)
die("Kernel symbol \'%s\' not found - probe not added.", die("Kernel symbol \'%s\' not found - probe not added.",
pp->function); pp->function);
...@@ -132,7 +131,7 @@ static void evaluate_probe_point(struct probe_point *pp) ...@@ -132,7 +131,7 @@ static void evaluate_probe_point(struct probe_point *pp)
#ifndef NO_LIBDWARF #ifndef NO_LIBDWARF
static int open_vmlinux(void) static int open_vmlinux(void)
{ {
if (map__load(session.kmap, session.psession, NULL) < 0) { if (map__load(session.kmap, NULL) < 0) {
pr_debug("Failed to load kernel map.\n"); pr_debug("Failed to load kernel map.\n");
return -EINVAL; return -EINVAL;
} }
......
...@@ -374,9 +374,7 @@ int event__process_mmap(event_t *self, struct perf_session *session) ...@@ -374,9 +374,7 @@ int event__process_mmap(event_t *self, struct perf_session *session)
goto out_problem; goto out_problem;
kernel->kernel = 1; kernel->kernel = 1;
if (__map_groups__create_kernel_maps(&session->kmaps, if (__perf_session__create_kernel_maps(session, kernel) < 0)
session->vmlinux_maps,
kernel) < 0)
goto out_problem; goto out_problem;
session->vmlinux_maps[MAP__FUNCTION]->start = self->mmap.start; session->vmlinux_maps[MAP__FUNCTION]->start = self->mmap.start;
...@@ -476,7 +474,7 @@ void thread__find_addr_location(struct thread *self, ...@@ -476,7 +474,7 @@ void thread__find_addr_location(struct thread *self,
{ {
thread__find_addr_map(self, session, cpumode, type, addr, al); thread__find_addr_map(self, session, cpumode, type, addr, al);
if (al->map != NULL) if (al->map != NULL)
al->sym = map__find_symbol(al->map, session, al->addr, filter); al->sym = map__find_symbol(al->map, al->addr, filter);
else else
al->sym = NULL; al->sym = NULL;
} }
......
...@@ -104,8 +104,7 @@ void map__fixup_end(struct map *self) ...@@ -104,8 +104,7 @@ void map__fixup_end(struct map *self)
#define DSO__DELETED "(deleted)" #define DSO__DELETED "(deleted)"
int map__load(struct map *self, struct perf_session *session, int map__load(struct map *self, symbol_filter_t filter)
symbol_filter_t filter)
{ {
const char *name = self->dso->long_name; const char *name = self->dso->long_name;
int nr; int nr;
...@@ -113,7 +112,7 @@ int map__load(struct map *self, struct perf_session *session, ...@@ -113,7 +112,7 @@ int map__load(struct map *self, struct perf_session *session,
if (dso__loaded(self->dso, self->type)) if (dso__loaded(self->dso, self->type))
return 0; return 0;
nr = dso__load(self->dso, self, session, filter); nr = dso__load(self->dso, self, filter);
if (nr < 0) { if (nr < 0) {
if (self->dso->has_build_id) { if (self->dso->has_build_id) {
char sbuild_id[BUILD_ID_SIZE * 2 + 1]; char sbuild_id[BUILD_ID_SIZE * 2 + 1];
...@@ -144,24 +143,29 @@ int map__load(struct map *self, struct perf_session *session, ...@@ -144,24 +143,29 @@ int map__load(struct map *self, struct perf_session *session,
return -1; return -1;
} }
/*
* Only applies to the kernel, as its symtabs aren't relative like the
* module ones.
*/
if (self->dso->kernel)
map__reloc_vmlinux(self);
return 0; return 0;
} }
struct symbol *map__find_symbol(struct map *self, struct perf_session *session, struct symbol *map__find_symbol(struct map *self, u64 addr,
u64 addr, symbol_filter_t filter) symbol_filter_t filter)
{ {
if (map__load(self, session, filter) < 0) if (map__load(self, filter) < 0)
return NULL; return NULL;
return dso__find_symbol(self->dso, self->type, addr); return dso__find_symbol(self->dso, self->type, addr);
} }
struct symbol *map__find_symbol_by_name(struct map *self, const char *name, struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
struct perf_session *session,
symbol_filter_t filter) symbol_filter_t filter)
{ {
if (map__load(self, session, filter) < 0) if (map__load(self, filter) < 0)
return NULL; return NULL;
if (!dso__sorted_by_name(self->dso, self->type)) if (!dso__sorted_by_name(self->dso, self->type))
......
...@@ -14,6 +14,8 @@ enum map_type { ...@@ -14,6 +14,8 @@ enum map_type {
#define MAP__NR_TYPES (MAP__VARIABLE + 1) #define MAP__NR_TYPES (MAP__VARIABLE + 1)
struct dso; struct dso;
struct ref_reloc_sym;
struct map_groups;
struct map { struct map {
union { union {
...@@ -29,6 +31,16 @@ struct map { ...@@ -29,6 +31,16 @@ struct map {
struct dso *dso; struct dso *dso;
}; };
struct kmap {
struct ref_reloc_sym *ref_reloc_sym;
struct map_groups *kmaps;
};
static inline struct kmap *map__kmap(struct map *self)
{
return (struct kmap *)(self + 1);
}
static inline u64 map__map_ip(struct map *map, u64 ip) static inline u64 map__map_ip(struct map *map, u64 ip)
{ {
return ip - map->start + map->pgoff; return ip - map->start + map->pgoff;
...@@ -58,16 +70,14 @@ struct map *map__clone(struct map *self); ...@@ -58,16 +70,14 @@ struct map *map__clone(struct map *self);
int map__overlap(struct map *l, struct map *r); int map__overlap(struct map *l, struct map *r);
size_t map__fprintf(struct map *self, FILE *fp); size_t map__fprintf(struct map *self, FILE *fp);
struct perf_session; int map__load(struct map *self, symbol_filter_t filter);
struct symbol *map__find_symbol(struct map *self,
int map__load(struct map *self, struct perf_session *session,
symbol_filter_t filter);
struct symbol *map__find_symbol(struct map *self, struct perf_session *session,
u64 addr, symbol_filter_t filter); u64 addr, symbol_filter_t filter);
struct symbol *map__find_symbol_by_name(struct map *self, const char *name, struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
struct perf_session *session,
symbol_filter_t filter); symbol_filter_t filter);
void map__fixup_start(struct map *self); void map__fixup_start(struct map *self);
void map__fixup_end(struct map *self); void map__fixup_end(struct map *self);
void map__reloc_vmlinux(struct map *self);
#endif /* __PERF_MAP_H */ #endif /* __PERF_MAP_H */
...@@ -53,6 +53,11 @@ static int perf_session__open(struct perf_session *self, bool force) ...@@ -53,6 +53,11 @@ static int perf_session__open(struct perf_session *self, bool force)
return -1; return -1;
} }
static inline int perf_session__create_kernel_maps(struct perf_session *self)
{
return map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps);
}
struct perf_session *perf_session__new(const char *filename, int mode, bool force) struct perf_session *perf_session__new(const char *filename, int mode, bool force)
{ {
size_t len = filename ? strlen(filename) + 1 : 0; size_t len = filename ? strlen(filename) + 1 : 0;
...@@ -507,6 +512,7 @@ int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self, ...@@ -507,6 +512,7 @@ int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self,
u64 addr) u64 addr)
{ {
char *bracket; char *bracket;
enum map_type i;
self->ref_reloc_sym.name = strdup(symbol_name); self->ref_reloc_sym.name = strdup(symbol_name);
if (self->ref_reloc_sym.name == NULL) if (self->ref_reloc_sym.name == NULL)
...@@ -517,6 +523,12 @@ int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self, ...@@ -517,6 +523,12 @@ int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self,
*bracket = '\0'; *bracket = '\0';
self->ref_reloc_sym.addr = addr; self->ref_reloc_sym.addr = addr;
for (i = 0; i < MAP__NR_TYPES; ++i) {
struct kmap *kmap = map__kmap(self->vmlinux_maps[i]);
kmap->ref_reloc_sym = &self->ref_reloc_sym;
}
return 0; return 0;
} }
...@@ -530,20 +542,21 @@ static u64 map__reloc_unmap_ip(struct map *map, u64 ip) ...@@ -530,20 +542,21 @@ static u64 map__reloc_unmap_ip(struct map *map, u64 ip)
return ip - (s64)map->pgoff; return ip - (s64)map->pgoff;
} }
void perf_session__reloc_vmlinux_maps(struct perf_session *self, void map__reloc_vmlinux(struct map *self)
u64 unrelocated_addr)
{ {
enum map_type type; struct kmap *kmap = map__kmap(self);
s64 reloc = unrelocated_addr - self->ref_reloc_sym.addr; s64 reloc;
if (!reloc) if (!kmap->ref_reloc_sym || !kmap->ref_reloc_sym->unrelocated_addr)
return; return;
for (type = 0; type < MAP__NR_TYPES; ++type) { reloc = (kmap->ref_reloc_sym->unrelocated_addr -
struct map *map = self->vmlinux_maps[type]; kmap->ref_reloc_sym->addr);
map->map_ip = map__reloc_map_ip; if (!reloc)
map->unmap_ip = map__reloc_unmap_ip; return;
map->pgoff = reloc;
} self->map_ip = map__reloc_map_ip;
self->unmap_ip = map__reloc_unmap_ip;
self->pgoff = reloc;
} }
...@@ -3,13 +3,13 @@ ...@@ -3,13 +3,13 @@
#include "event.h" #include "event.h"
#include "header.h" #include "header.h"
#include "symbol.h"
#include "thread.h" #include "thread.h"
#include <linux/rbtree.h> #include <linux/rbtree.h>
#include "../../../include/linux/perf_event.h" #include "../../../include/linux/perf_event.h"
struct ip_callchain; struct ip_callchain;
struct thread; struct thread;
struct symbol;
struct perf_session { struct perf_session {
struct perf_header header; struct perf_header header;
...@@ -24,10 +24,7 @@ struct perf_session { ...@@ -24,10 +24,7 @@ struct perf_session {
unsigned long unknown_events; unsigned long unknown_events;
struct rb_root hists; struct rb_root hists;
u64 sample_type; u64 sample_type;
struct { struct ref_reloc_sym ref_reloc_sym;
const char *name;
u64 addr;
} ref_reloc_sym;
int fd; int fd;
int cwdlen; int cwdlen;
char *cwd; char *cwd;
...@@ -69,9 +66,20 @@ int perf_header__read_build_ids(struct perf_header *self, int input, ...@@ -69,9 +66,20 @@ int perf_header__read_build_ids(struct perf_header *self, int input,
int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self, int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self,
const char *symbol_name, const char *symbol_name,
u64 addr); u64 addr);
void perf_session__reloc_vmlinux_maps(struct perf_session *self,
u64 unrelocated_addr);
void mem_bswap_64(void *src, int byte_size); void mem_bswap_64(void *src, int byte_size);
static inline int __perf_session__create_kernel_maps(struct perf_session *self,
struct dso *kernel)
{
return __map_groups__create_kernel_maps(&self->kmaps,
self->vmlinux_maps, kernel);
}
static inline struct map *
perf_session__new_module_map(struct perf_session *self,
u64 start, const char *filename)
{
return map_groups__new_module(&self->kmaps, start, filename);
}
#endif /* __PERF_SESSION_H */ #endif /* __PERF_SESSION_H */
This diff is collapsed.
...@@ -80,6 +80,12 @@ static inline void *symbol__priv(struct symbol *self) ...@@ -80,6 +80,12 @@ static inline void *symbol__priv(struct symbol *self)
return ((void *)self) - symbol_conf.priv_size; return ((void *)self) - symbol_conf.priv_size;
} }
struct ref_reloc_sym {
const char *name;
u64 addr;
u64 unrelocated_addr;
};
struct addr_location { struct addr_location {
struct thread *thread; struct thread *thread;
struct map *map; struct map *map;
...@@ -126,12 +132,11 @@ static inline struct dso *dsos__findnew(const char *name) ...@@ -126,12 +132,11 @@ static inline struct dso *dsos__findnew(const char *name)
return __dsos__findnew(&dsos__user, name); return __dsos__findnew(&dsos__user, name);
} }
struct perf_session; int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
int dso__load(struct dso *self, struct map *map, struct perf_session *session,
symbol_filter_t filter);
int dso__load_vmlinux_path(struct dso *self, struct map *map, int dso__load_vmlinux_path(struct dso *self, struct map *map,
struct perf_session *session, symbol_filter_t filter); symbol_filter_t filter);
int dso__load_kallsyms(struct dso *self, const char *filename, struct map *map,
symbol_filter_t filter);
void dsos__fprintf(FILE *fp); void dsos__fprintf(FILE *fp);
size_t dsos__fprintf_buildid(FILE *fp, bool with_hits); size_t dsos__fprintf_buildid(FILE *fp, bool with_hits);
...@@ -156,9 +161,5 @@ int kallsyms__parse(const char *filename, void *arg, ...@@ -156,9 +161,5 @@ int kallsyms__parse(const char *filename, void *arg,
int symbol__init(void); int symbol__init(void);
bool symbol_type__is_a(char symbol_type, enum map_type map_type); bool symbol_type__is_a(char symbol_type, enum map_type map_type);
int perf_session__create_kernel_maps(struct perf_session *self);
struct map *perf_session__new_module_map(struct perf_session *self, u64 start,
const char *filename);
extern struct dso *vdso; extern struct dso *vdso;
#endif /* __PERF_SYMBOL */ #endif /* __PERF_SYMBOL */
...@@ -282,14 +282,13 @@ size_t perf_session__fprintf(struct perf_session *self, FILE *fp) ...@@ -282,14 +282,13 @@ size_t perf_session__fprintf(struct perf_session *self, FILE *fp)
} }
struct symbol *map_groups__find_symbol(struct map_groups *self, struct symbol *map_groups__find_symbol(struct map_groups *self,
struct perf_session *session,
enum map_type type, u64 addr, enum map_type type, u64 addr,
symbol_filter_t filter) symbol_filter_t filter)
{ {
struct map *map = map_groups__find(self, type, addr); struct map *map = map_groups__find(self, type, addr);
if (map != NULL) if (map != NULL)
return map__find_symbol(map, session, map->map_ip(map, addr), filter); return map__find_symbol(map, map->map_ip(map, addr), filter);
return NULL; return NULL;
} }
...@@ -59,15 +59,14 @@ void thread__find_addr_location(struct thread *self, ...@@ -59,15 +59,14 @@ void thread__find_addr_location(struct thread *self,
struct addr_location *al, struct addr_location *al,
symbol_filter_t filter); symbol_filter_t filter);
struct symbol *map_groups__find_symbol(struct map_groups *self, struct symbol *map_groups__find_symbol(struct map_groups *self,
struct perf_session *session,
enum map_type type, u64 addr, enum map_type type, u64 addr,
symbol_filter_t filter); symbol_filter_t filter);
static inline struct symbol * static inline struct symbol *map_groups__find_function(struct map_groups *self,
map_groups__find_function(struct map_groups *self, struct perf_session *session, u64 addr,
u64 addr, symbol_filter_t filter) symbol_filter_t filter)
{ {
return map_groups__find_symbol(self, session, MAP__FUNCTION, addr, filter); return map_groups__find_symbol(self, MAP__FUNCTION, addr, filter);
} }
struct map *map_groups__find_by_name(struct map_groups *self, struct map *map_groups__find_by_name(struct map_groups *self,
...@@ -76,4 +75,9 @@ struct map *map_groups__find_by_name(struct map_groups *self, ...@@ -76,4 +75,9 @@ struct map *map_groups__find_by_name(struct map_groups *self,
int __map_groups__create_kernel_maps(struct map_groups *self, int __map_groups__create_kernel_maps(struct map_groups *self,
struct map *vmlinux_maps[MAP__NR_TYPES], struct map *vmlinux_maps[MAP__NR_TYPES],
struct dso *kernel); struct dso *kernel);
int map_groups__create_kernel_maps(struct map_groups *self,
struct map *vmlinux_maps[MAP__NR_TYPES]);
struct map *map_groups__new_module(struct map_groups *self, u64 start,
const char *filename);
#endif /* __PERF_THREAD_H */ #endif /* __PERF_THREAD_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment