aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/event.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/event.c')
-rw-r--r--tools/perf/util/event.c64
1 files changed, 61 insertions, 3 deletions
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index bb0fd6da2d56..1a31feb9999f 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -189,6 +189,50 @@ void event__synthesize_threads(int (*process)(event_t *event,
189 closedir(proc); 189 closedir(proc);
190} 190}
191 191
192struct process_symbol_args {
193 const char *name;
194 u64 start;
195};
196
197static int find_symbol_cb(void *arg, const char *name, char type, u64 start)
198{
199 struct process_symbol_args *args = arg;
200
201 if (!symbol_type__is_a(type, MAP__FUNCTION) || strcmp(name, args->name))
202 return 0;
203
204 args->start = start;
205 return 1;
206}
207
208int event__synthesize_kernel_mmap(int (*process)(event_t *event,
209 struct perf_session *session),
210 struct perf_session *session,
211 const char *symbol_name)
212{
213 size_t size;
214 event_t ev = {
215 .header = { .type = PERF_RECORD_MMAP },
216 };
217 /*
218 * We should get this from /sys/kernel/sections/.text, but till that is
219 * available use this, and after it is use this as a fallback for older
220 * kernels.
221 */
222 struct process_symbol_args args = { .name = symbol_name, };
223
224 if (kallsyms__parse(&args, find_symbol_cb) <= 0)
225 return -ENOENT;
226
227 size = snprintf(ev.mmap.filename, sizeof(ev.mmap.filename),
228 "[kernel.kallsyms.%s]", symbol_name) + 1;
229 size = ALIGN(size, sizeof(u64));
230 ev.mmap.header.size = (sizeof(ev.mmap) - (sizeof(ev.mmap.filename) - size));
231 ev.mmap.start = args.start;
232
233 return process(&ev, session);
234}
235
192static void thread__comm_adjust(struct thread *self) 236static void thread__comm_adjust(struct thread *self)
193{ 237{
194 char *comm = self->comm; 238 char *comm = self->comm;
@@ -240,9 +284,9 @@ int event__process_lost(event_t *self, struct perf_session *session)
240 284
241int event__process_mmap(event_t *self, struct perf_session *session) 285int event__process_mmap(event_t *self, struct perf_session *session)
242{ 286{
243 struct thread *thread = perf_session__findnew(session, self->mmap.pid); 287 struct thread *thread;
244 struct map *map = map__new(&self->mmap, MAP__FUNCTION, 288 struct map *map;
245 session->cwd, session->cwdlen); 289 static const char kmmap_prefix[] = "[kernel.kallsyms.";
246 290
247 dump_printf(" %d/%d: [%p(%p) @ %p]: %s\n", 291 dump_printf(" %d/%d: [%p(%p) @ %p]: %s\n",
248 self->mmap.pid, self->mmap.tid, 292 self->mmap.pid, self->mmap.tid,
@@ -251,6 +295,20 @@ int event__process_mmap(event_t *self, struct perf_session *session)
251 (void *)(long)self->mmap.pgoff, 295 (void *)(long)self->mmap.pgoff,
252 self->mmap.filename); 296 self->mmap.filename);
253 297
298 if (self->mmap.pid == 0 &&
299 memcmp(self->mmap.filename, kmmap_prefix,
300 sizeof(kmmap_prefix) - 1) == 0) {
301 const char *symbol_name = (self->mmap.filename +
302 sizeof(kmmap_prefix) - 1);
303 perf_session__set_kallsyms_ref_reloc_sym(session, symbol_name,
304 self->mmap.start);
305 return 0;
306 }
307
308 thread = perf_session__findnew(session, self->mmap.pid);
309 map = map__new(&self->mmap, MAP__FUNCTION,
310 session->cwd, session->cwdlen);
311
254 if (thread == NULL || map == NULL) 312 if (thread == NULL || map == NULL)
255 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n"); 313 dump_printf("problem processing PERF_RECORD_MMAP, skipping event.\n");
256 else 314 else