aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/builtin-annotate.c
diff options
context:
space:
mode:
authorArnaldo Carvalho de Melo <acme@redhat.com>2009-11-27 13:29:23 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-27 14:22:02 -0500
commit1ed091c45ae33b2179d387573c3fe3f3b4adf60a (patch)
treed2b689de158e5a11673b5f0d08b491d243768138 /tools/perf/builtin-annotate.c
parent62daacb51a2bf8480e6f6b3696b03f102fc15eb0 (diff)
perf tools: Consolidate symbol resolving across all tools
Now we have a very high level routine for simple tools to process IP sample events: int event__preprocess_sample(const event_t *self, struct addr_location *al, symbol_filter_t filter) It receives the event itself and will insert new threads in the global threads list and resolve the map and symbol, filling all this info into the new addr_location struct, so that tools like annotate and report can further process the event by creating hist_entries in their specific way (with or without callgraphs, etc). It in turn uses the new next layer function: void thread__find_addr_location(struct thread *self, u8 cpumode, enum map_type type, u64 addr, struct addr_location *al, symbol_filter_t filter) This one will, given a thread (userspace or the kernel kthread one), will find the given type (MAP__FUNCTION now, MAP__VARIABLE too in the near future) at the given cpumode, taking vdsos into account (userspace hit, but kernel symbol) and will fill all these details in the addr_location given. Tools that need a more compact API for plain function resolution, like 'kmem', can use this other one: struct symbol *thread__find_function(struct thread *self, u64 addr, symbol_filter_t filter) So, to resolve a kernel symbol, that is all the 'kmem' tool needs, its just a matter of calling: sym = thread__find_function(kthread, addr, NULL); The 'filter' parameter is needed because we do lazy parsing/loading of ELF symtabs or /proc/kallsyms. With this we remove more code duplication all around, which is always good, huh? :-) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: Frédéric Weisbecker <fweisbec@gmail.com> Cc: John Kacur <jkacur@redhat.com> Cc: Mike Galbraith <efault@gmx.de> Cc: Peter Zijlstra <a.p.zijlstra@chello.nl> Cc: Paul Mackerras <paulus@samba.org> LKML-Reference: <1259346563-12568-12-git-send-email-acme@infradead.org> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/builtin-annotate.c')
-rw-r--r--tools/perf/builtin-annotate.c55
1 files changed, 7 insertions, 48 deletions
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c
index 7d39bd2b19b8..7f85c6e159a4 100644
--- a/tools/perf/builtin-annotate.c
+++ b/tools/perf/builtin-annotate.c
@@ -124,71 +124,30 @@ static void hist_hit(struct hist_entry *he, u64 ip)
124 h->ip[offset]); 124 h->ip[offset]);
125} 125}
126 126
127static int hist_entry__add(struct thread *thread, struct map *map, 127static int hist_entry__add(struct addr_location *al, u64 count)
128 struct symbol *sym, u64 ip, u64 count, char level)
129{ 128{
130 bool hit; 129 bool hit;
131 struct hist_entry *he = __hist_entry__add(thread, map, sym, NULL, ip, 130 struct hist_entry *he = __hist_entry__add(al, NULL, count, &hit);
132 count, level, &hit);
133 if (he == NULL) 131 if (he == NULL)
134 return -ENOMEM; 132 return -ENOMEM;
135 hist_hit(he, ip); 133 hist_hit(he, al->addr);
136 return 0; 134 return 0;
137} 135}
138 136
139static int process_sample_event(event_t *event) 137static int process_sample_event(event_t *event)
140{ 138{
141 char level; 139 struct addr_location al;
142 u64 ip = event->ip.ip;
143 struct map *map = NULL;
144 struct symbol *sym = NULL;
145 struct thread *thread = threads__findnew(event->ip.pid);
146 140
147 dump_printf("(IP, %d): %d: %p\n", event->header.misc, 141 dump_printf("(IP, %d): %d: %p\n", event->header.misc,
148 event->ip.pid, (void *)(long)ip); 142 event->ip.pid, (void *)(long)event->ip.ip);
149 143
150 if (thread == NULL) { 144 if (event__preprocess_sample(event, &al, symbol_filter) < 0) {
151 fprintf(stderr, "problem processing %d event, skipping it.\n", 145 fprintf(stderr, "problem processing %d event, skipping it.\n",
152 event->header.type); 146 event->header.type);
153 return -1; 147 return -1;
154 } 148 }
155 149
156 dump_printf(" ... thread: %s:%d\n", thread->comm, thread->pid); 150 if (hist_entry__add(&al, 1)) {
157
158 if (event->header.misc & PERF_RECORD_MISC_KERNEL) {
159 level = 'k';
160 sym = kernel_maps__find_function(ip, &map, symbol_filter);
161 dump_printf(" ...... dso: %s\n",
162 map ? map->dso->long_name : "<not found>");
163 } else if (event->header.misc & PERF_RECORD_MISC_USER) {
164 level = '.';
165 map = thread__find_map(thread, MAP__FUNCTION, ip);
166 if (map != NULL) {
167 ip = map->map_ip(map, ip);
168 sym = map__find_symbol(map, ip, symbol_filter);
169 } else {
170 /*
171 * If this is outside of all known maps,
172 * and is a negative address, try to look it
173 * up in the kernel dso, as it might be a
174 * vsyscall or vdso (which executes in user-mode).
175 *
176 * XXX This is nasty, we should have a symbol list in
177 * the "[vdso]" dso, but for now lets use the old
178 * trick of looking in the whole kernel symbol list.
179 */
180 if ((long long)ip < 0)
181 sym = kernel_maps__find_function(ip, &map,
182 symbol_filter);
183 }
184 dump_printf(" ...... dso: %s\n",
185 map ? map->dso->long_name : "<not found>");
186 } else {
187 level = 'H';
188 dump_printf(" ...... dso: [hypervisor]\n");
189 }
190
191 if (hist_entry__add(thread, map, sym, ip, 1, level)) {
192 fprintf(stderr, "problem incrementing symbol count, " 151 fprintf(stderr, "problem incrementing symbol count, "
193 "skipping event\n"); 152 "skipping event\n");
194 return -1; 153 return -1;