aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util')
-rw-r--r--tools/perf/util/event.c62
-rw-r--r--tools/perf/util/event.h4
-rw-r--r--tools/perf/util/hist.c15
-rw-r--r--tools/perf/util/hist.h6
-rw-r--r--tools/perf/util/symbol.c26
-rw-r--r--tools/perf/util/symbol.h10
-rw-r--r--tools/perf/util/thread.c12
-rw-r--r--tools/perf/util/thread.h23
8 files changed, 117 insertions, 41 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 70b4aa03b472..233d7ad9bd7f 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -249,3 +249,65 @@ int event__process_task(event_t *self)
249 249
250 return 0; 250 return 0;
251} 251}
252
253void thread__find_addr_location(struct thread *self, u8 cpumode,
254 enum map_type type, u64 addr,
255 struct addr_location *al,
256 symbol_filter_t filter)
257{
258 struct thread *thread = al->thread = self;
259
260 al->addr = addr;
261
262 if (cpumode & PERF_RECORD_MISC_KERNEL) {
263 al->level = 'k';
264 thread = kthread;
265 } else if (cpumode & PERF_RECORD_MISC_USER)
266 al->level = '.';
267 else {
268 al->level = 'H';
269 al->map = NULL;
270 al->sym = NULL;
271 return;
272 }
273try_again:
274 al->map = thread__find_map(thread, type, al->addr);
275 if (al->map == NULL) {
276 /*
277 * If this is outside of all known maps, and is a negative
278 * address, try to look it up in the kernel dso, as it might be
279 * a vsyscall or vdso (which executes in user-mode).
280 *
281 * XXX This is nasty, we should have a symbol list in the
282 * "[vdso]" dso, but for now lets use the old trick of looking
283 * in the whole kernel symbol list.
284 */
285 if ((long long)al->addr < 0 && thread != kthread) {
286 thread = kthread;
287 goto try_again;
288 }
289 al->sym = NULL;
290 } else {
291 al->addr = al->map->map_ip(al->map, al->addr);
292 al->sym = map__find_symbol(al->map, al->addr, filter);
293 }
294}
295
296int event__preprocess_sample(const event_t *self, struct addr_location *al,
297 symbol_filter_t filter)
298{
299 u8 cpumode = self->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
300 struct thread *thread = threads__findnew(self->ip.pid);
301
302 if (thread == NULL)
303 return -1;
304
305 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid);
306
307 thread__find_addr_location(thread, cpumode, MAP__FUNCTION,
308 self->ip.ip, al, filter);
309 dump_printf(" ...... dso: %s\n",
310 al->map ? al->map->dso->long_name :
311 al->level == 'H' ? "[hypervisor]" : "<not found>");
312 return 0;
313}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 13c12c75f970..a4cc8105cf67 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -152,4 +152,8 @@ int event__process_lost(event_t *self);
152int event__process_mmap(event_t *self); 152int event__process_mmap(event_t *self);
153int event__process_task(event_t *self); 153int event__process_task(event_t *self);
154 154
155struct addr_location;
156int event__preprocess_sample(const event_t *self, struct addr_location *al,
157 symbol_filter_t filter);
158
155#endif /* __PERF_RECORD_H */ 159#endif /* __PERF_RECORD_H */
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index f26cd9ba00fd..0ebf6ee16caa 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -14,20 +14,19 @@ struct callchain_param callchain_param = {
14 * histogram, sorted on item, collects counts 14 * histogram, sorted on item, collects counts
15 */ 15 */
16 16
17struct hist_entry *__hist_entry__add(struct thread *thread, struct map *map, 17struct hist_entry *__hist_entry__add(struct addr_location *al,
18 struct symbol *sym,
19 struct symbol *sym_parent, 18 struct symbol *sym_parent,
20 u64 ip, u64 count, char level, bool *hit) 19 u64 count, bool *hit)
21{ 20{
22 struct rb_node **p = &hist.rb_node; 21 struct rb_node **p = &hist.rb_node;
23 struct rb_node *parent = NULL; 22 struct rb_node *parent = NULL;
24 struct hist_entry *he; 23 struct hist_entry *he;
25 struct hist_entry entry = { 24 struct hist_entry entry = {
26 .thread = thread, 25 .thread = al->thread,
27 .map = map, 26 .map = al->map,
28 .sym = sym, 27 .sym = al->sym,
29 .ip = ip, 28 .ip = al->addr,
30 .level = level, 29 .level = al->level,
31 .count = count, 30 .count = count,
32 .parent = sym_parent, 31 .parent = sym_parent,
33 }; 32 };
diff --git a/tools/perf/util/hist.h b/tools/perf/util/hist.h
index ac2149c559b0..3020db0c9292 100644
--- a/tools/perf/util/hist.h
+++ b/tools/perf/util/hist.h
@@ -36,9 +36,9 @@ extern unsigned long total_fork;
36extern unsigned long total_unknown; 36extern unsigned long total_unknown;
37extern unsigned long total_lost; 37extern unsigned long total_lost;
38 38
39struct hist_entry *__hist_entry__add(struct thread *thread, struct map *map, 39struct hist_entry *__hist_entry__add(struct addr_location *al,
40 struct symbol *sym, struct symbol *parent, 40 struct symbol *parent,
41 u64 ip, u64 count, char level, bool *hit); 41 u64 count, bool *hit);
42extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *); 42extern int64_t hist_entry__cmp(struct hist_entry *, struct hist_entry *);
43extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *); 43extern int64_t hist_entry__collapse(struct hist_entry *, struct hist_entry *);
44extern void hist_entry__free(struct hist_entry *); 44extern void hist_entry__free(struct hist_entry *);
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index b788c2f5d672..fffcb937cdcb 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -43,7 +43,8 @@ static struct symbol_conf symbol_conf__defaults = {
43 .try_vmlinux_path = true, 43 .try_vmlinux_path = true,
44}; 44};
45 45
46static struct thread kthread_mem, *kthread = &kthread_mem; 46static struct thread kthread_mem;
47struct thread *kthread = &kthread_mem;
47 48
48bool dso__loaded(const struct dso *self, enum map_type type) 49bool dso__loaded(const struct dso *self, enum map_type type)
49{ 50{
@@ -1178,29 +1179,6 @@ out:
1178 return ret; 1179 return ret;
1179} 1180}
1180 1181
1181static struct symbol *thread__find_symbol(struct thread *self, u64 ip,
1182 enum map_type type, struct map **mapp,
1183 symbol_filter_t filter)
1184{
1185 struct map *map = thread__find_map(self, type, ip);
1186
1187 if (mapp)
1188 *mapp = map;
1189
1190 if (map) {
1191 ip = map->map_ip(map, ip);
1192 return map__find_symbol(map, ip, filter);
1193 }
1194
1195 return NULL;
1196}
1197
1198struct symbol *kernel_maps__find_function(u64 ip, struct map **mapp,
1199 symbol_filter_t filter)
1200{
1201 return thread__find_symbol(kthread, ip, MAP__FUNCTION, mapp, filter);
1202}
1203
1204static struct map *thread__find_map_by_name(struct thread *self, char *name) 1182static struct map *thread__find_map_by_name(struct thread *self, char *name)
1205{ 1183{
1206 struct rb_node *nd; 1184 struct rb_node *nd;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 3f9e4a4d83dd..17003efa0b39 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -63,6 +63,14 @@ static inline void *symbol__priv(struct symbol *self)
63 return ((void *)self) - symbol__priv_size; 63 return ((void *)self) - symbol__priv_size;
64} 64}
65 65
66struct addr_location {
67 struct thread *thread;
68 struct map *map;
69 struct symbol *sym;
70 u64 addr;
71 char level;
72};
73
66struct dso { 74struct dso {
67 struct list_head node; 75 struct list_head node;
68 struct rb_root symbols[MAP__NR_TYPES]; 76 struct rb_root symbols[MAP__NR_TYPES];
@@ -105,6 +113,8 @@ size_t kernel_maps__fprintf(FILE *fp);
105 113
106int symbol__init(struct symbol_conf *conf); 114int symbol__init(struct symbol_conf *conf);
107 115
116struct thread;
117struct thread *kthread;
108extern struct list_head dsos__user, dsos__kernel; 118extern struct list_head dsos__user, dsos__kernel;
109extern struct dso *vdso; 119extern struct dso *vdso;
110#endif /* __PERF_SYMBOL */ 120#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 2229f82cd630..603f5610861b 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -285,3 +285,15 @@ size_t threads__fprintf(FILE *fp)
285 285
286 return ret; 286 return ret;
287} 287}
288
289struct symbol *thread__find_symbol(struct thread *self,
290 enum map_type type, u64 addr,
291 symbol_filter_t filter)
292{
293 struct map *map = thread__find_map(self, type, addr);
294
295 if (map != NULL)
296 return map__find_symbol(map, map->map_ip(map, addr), filter);
297
298 return NULL;
299}
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 59b0d9b577d6..686d6e914d9e 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -27,19 +27,30 @@ size_t thread__fprintf_maps(struct thread *self, FILE *fp);
27size_t threads__fprintf(FILE *fp); 27size_t threads__fprintf(FILE *fp);
28 28
29void maps__insert(struct rb_root *maps, struct map *map); 29void maps__insert(struct rb_root *maps, struct map *map);
30struct map *maps__find(struct rb_root *maps, u64 ip); 30struct map *maps__find(struct rb_root *maps, u64 addr);
31
32struct symbol *kernel_maps__find_function(const u64 ip, struct map **mapp,
33 symbol_filter_t filter);
34 31
35static inline struct map *thread__find_map(struct thread *self, 32static inline struct map *thread__find_map(struct thread *self,
36 enum map_type type, u64 ip) 33 enum map_type type, u64 addr)
37{ 34{
38 return self ? maps__find(&self->maps[type], ip) : NULL; 35 return self ? maps__find(&self->maps[type], addr) : NULL;
39} 36}
40 37
41static inline void __thread__insert_map(struct thread *self, struct map *map) 38static inline void __thread__insert_map(struct thread *self, struct map *map)
42{ 39{
43 maps__insert(&self->maps[map->type], map); 40 maps__insert(&self->maps[map->type], map);
44} 41}
42
43void thread__find_addr_location(struct thread *self, u8 cpumode,
44 enum map_type type, u64 addr,
45 struct addr_location *al,
46 symbol_filter_t filter);
47struct symbol *thread__find_symbol(struct thread *self,
48 enum map_type type, u64 addr,
49 symbol_filter_t filter);
50
51static inline struct symbol *
52thread__find_function(struct thread *self, u64 addr, symbol_filter_t filter)
53{
54 return thread__find_symbol(self, MAP__FUNCTION, addr, filter);
55}
45#endif /* __PERF_THREAD_H */ 56#endif /* __PERF_THREAD_H */