blob: 32765cdca058a6b7bdb541b7ec475a2bcea7ebbf [file] [log] [blame]
Xiao Guangrongb8f46c52010-02-03 11:53:14 +08001#define _FILE_OFFSET_BITS 64
2
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -02003#include <linux/kernel.h>
4
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -02005#include <byteswap.h>
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -02006#include <unistd.h>
7#include <sys/types.h>
8
9#include "session.h"
Arnaldo Carvalho de Meloa3286262009-12-14 14:22:59 -020010#include "sort.h"
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -020011#include "util.h"
12
13static int perf_session__open(struct perf_session *self, bool force)
14{
15 struct stat input_stat;
16
Xiao Guangrongf887f302010-02-04 16:46:42 +080017 self->fd = open(self->filename, O_RDONLY);
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -020018 if (self->fd < 0) {
19 pr_err("failed to open file: %s", self->filename);
20 if (!strcmp(self->filename, "perf.data"))
21 pr_err(" (try 'perf record' first)");
22 pr_err("\n");
23 return -errno;
24 }
25
26 if (fstat(self->fd, &input_stat) < 0)
27 goto out_close;
28
29 if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
30 pr_err("file %s not owned by current user or root\n",
31 self->filename);
32 goto out_close;
33 }
34
35 if (!input_stat.st_size) {
36 pr_info("zero-sized file (%s), nothing to do!\n",
37 self->filename);
38 goto out_close;
39 }
40
41 if (perf_header__read(&self->header, self->fd) < 0) {
42 pr_err("incompatible file format");
43 goto out_close;
44 }
45
46 self->size = input_stat.st_size;
47 return 0;
48
49out_close:
50 close(self->fd);
51 self->fd = -1;
52 return -1;
53}
54
Arnaldo Carvalho de Melo9de89fe2010-02-03 16:52:00 -020055static inline int perf_session__create_kernel_maps(struct perf_session *self)
56{
57 return map_groups__create_kernel_maps(&self->kmaps, self->vmlinux_maps);
58}
59
Arnaldo Carvalho de Melo75be6cf2009-12-15 20:04:39 -020060struct perf_session *perf_session__new(const char *filename, int mode, bool force)
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -020061{
Arnaldo Carvalho de Melob3165f42009-12-13 19:50:28 -020062 size_t len = filename ? strlen(filename) + 1 : 0;
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -020063 struct perf_session *self = zalloc(sizeof(*self) + len);
64
65 if (self == NULL)
66 goto out;
67
68 if (perf_header__init(&self->header) < 0)
Arnaldo Carvalho de Melo4aa65632009-12-13 19:50:29 -020069 goto out_free;
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -020070
71 memcpy(self->filename, filename, len);
Arnaldo Carvalho de Melob3165f42009-12-13 19:50:28 -020072 self->threads = RB_ROOT;
Eric B Munsoncb8f0932010-03-05 12:51:07 -030073 self->stats_by_id = RB_ROOT;
Arnaldo Carvalho de Melob3165f42009-12-13 19:50:28 -020074 self->last_match = NULL;
Arnaldo Carvalho de Meloec913362009-12-13 19:50:27 -020075 self->mmap_window = 32;
76 self->cwd = NULL;
77 self->cwdlen = 0;
Arnaldo Carvalho de Melo31d337c2009-12-27 21:37:03 -020078 self->unknown_events = 0;
Arnaldo Carvalho de Melo4aa65632009-12-13 19:50:29 -020079 map_groups__init(&self->kmaps);
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -020080
Arnaldo Carvalho de Melo64abebf72010-01-27 21:05:52 -020081 if (mode == O_RDONLY) {
82 if (perf_session__open(self, force) < 0)
83 goto out_delete;
84 } else if (mode == O_WRONLY) {
85 /*
86 * In O_RDONLY mode this will be performed when reading the
87 * kernel MMAP event, in event__process_mmap().
88 */
89 if (perf_session__create_kernel_maps(self) < 0)
90 goto out_delete;
91 }
Arnaldo Carvalho de Melod549c7692009-12-27 21:37:02 -020092
93 self->sample_type = perf_header__sample_type(&self->header);
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -020094out:
95 return self;
Arnaldo Carvalho de Melo4aa65632009-12-13 19:50:29 -020096out_free:
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -020097 free(self);
98 return NULL;
Arnaldo Carvalho de Melo4aa65632009-12-13 19:50:29 -020099out_delete:
100 perf_session__delete(self);
101 return NULL;
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -0200102}
103
104void perf_session__delete(struct perf_session *self)
105{
106 perf_header__exit(&self->header);
107 close(self->fd);
Arnaldo Carvalho de Meloec913362009-12-13 19:50:27 -0200108 free(self->cwd);
Arnaldo Carvalho de Melo94c744b2009-12-11 21:24:02 -0200109 free(self);
110}
Arnaldo Carvalho de Meloa3286262009-12-14 14:22:59 -0200111
112static bool symbol__match_parent_regex(struct symbol *sym)
113{
114 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
115 return 1;
116
117 return 0;
118}
119
Arnaldo Carvalho de Melob3c9ac02010-03-24 16:40:18 -0300120struct map_symbol *perf_session__resolve_callchain(struct perf_session *self,
121 struct thread *thread,
122 struct ip_callchain *chain,
123 struct symbol **parent)
Arnaldo Carvalho de Meloa3286262009-12-14 14:22:59 -0200124{
125 u8 cpumode = PERF_RECORD_MISC_USER;
Arnaldo Carvalho de Melob3c9ac02010-03-24 16:40:18 -0300126 struct map_symbol *syms = NULL;
Arnaldo Carvalho de Meloa3286262009-12-14 14:22:59 -0200127 unsigned int i;
128
Arnaldo Carvalho de Melod599db32009-12-15 20:04:42 -0200129 if (symbol_conf.use_callchain) {
Arnaldo Carvalho de Meloa3286262009-12-14 14:22:59 -0200130 syms = calloc(chain->nr, sizeof(*syms));
131 if (!syms) {
132 fprintf(stderr, "Can't allocate memory for symbols\n");
133 exit(-1);
134 }
135 }
136
137 for (i = 0; i < chain->nr; i++) {
138 u64 ip = chain->ips[i];
139 struct addr_location al;
140
141 if (ip >= PERF_CONTEXT_MAX) {
142 switch (ip) {
143 case PERF_CONTEXT_HV:
144 cpumode = PERF_RECORD_MISC_HYPERVISOR; break;
145 case PERF_CONTEXT_KERNEL:
146 cpumode = PERF_RECORD_MISC_KERNEL; break;
147 case PERF_CONTEXT_USER:
148 cpumode = PERF_RECORD_MISC_USER; break;
149 default:
150 break;
151 }
152 continue;
153 }
154
155 thread__find_addr_location(thread, self, cpumode,
156 MAP__FUNCTION, ip, &al, NULL);
157 if (al.sym != NULL) {
158 if (sort__has_parent && !*parent &&
159 symbol__match_parent_regex(al.sym))
160 *parent = al.sym;
Arnaldo Carvalho de Melod599db32009-12-15 20:04:42 -0200161 if (!symbol_conf.use_callchain)
Arnaldo Carvalho de Meloa3286262009-12-14 14:22:59 -0200162 break;
Arnaldo Carvalho de Melob3c9ac02010-03-24 16:40:18 -0300163 syms[i].map = al.map;
164 syms[i].sym = al.sym;
Arnaldo Carvalho de Meloa3286262009-12-14 14:22:59 -0200165 }
166 }
167
168 return syms;
169}
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200170
171static int process_event_stub(event_t *event __used,
172 struct perf_session *session __used)
173{
174 dump_printf(": unhandled!\n");
175 return 0;
176}
177
178static void perf_event_ops__fill_defaults(struct perf_event_ops *handler)
179{
Arnaldo Carvalho de Melo55aa640f2009-12-27 21:37:05 -0200180 if (handler->sample == NULL)
181 handler->sample = process_event_stub;
182 if (handler->mmap == NULL)
183 handler->mmap = process_event_stub;
184 if (handler->comm == NULL)
185 handler->comm = process_event_stub;
186 if (handler->fork == NULL)
187 handler->fork = process_event_stub;
188 if (handler->exit == NULL)
189 handler->exit = process_event_stub;
190 if (handler->lost == NULL)
191 handler->lost = process_event_stub;
192 if (handler->read == NULL)
193 handler->read = process_event_stub;
194 if (handler->throttle == NULL)
195 handler->throttle = process_event_stub;
196 if (handler->unthrottle == NULL)
197 handler->unthrottle = process_event_stub;
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200198}
199
200static const char *event__name[] = {
201 [0] = "TOTAL",
202 [PERF_RECORD_MMAP] = "MMAP",
203 [PERF_RECORD_LOST] = "LOST",
204 [PERF_RECORD_COMM] = "COMM",
205 [PERF_RECORD_EXIT] = "EXIT",
206 [PERF_RECORD_THROTTLE] = "THROTTLE",
207 [PERF_RECORD_UNTHROTTLE] = "UNTHROTTLE",
208 [PERF_RECORD_FORK] = "FORK",
209 [PERF_RECORD_READ] = "READ",
210 [PERF_RECORD_SAMPLE] = "SAMPLE",
211};
212
213unsigned long event__total[PERF_RECORD_MAX];
214
215void event__print_totals(void)
216{
217 int i;
218 for (i = 0; i < PERF_RECORD_MAX; ++i)
219 pr_info("%10s events: %10ld\n",
220 event__name[i], event__total[i]);
221}
222
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -0200223void mem_bswap_64(void *src, int byte_size)
224{
225 u64 *m = src;
226
227 while (byte_size > 0) {
228 *m = bswap_64(*m);
229 byte_size -= sizeof(u64);
230 ++m;
231 }
232}
233
234static void event__all64_swap(event_t *self)
235{
236 struct perf_event_header *hdr = &self->header;
237 mem_bswap_64(hdr + 1, self->header.size - sizeof(*hdr));
238}
239
240static void event__comm_swap(event_t *self)
241{
242 self->comm.pid = bswap_32(self->comm.pid);
243 self->comm.tid = bswap_32(self->comm.tid);
244}
245
246static void event__mmap_swap(event_t *self)
247{
248 self->mmap.pid = bswap_32(self->mmap.pid);
249 self->mmap.tid = bswap_32(self->mmap.tid);
250 self->mmap.start = bswap_64(self->mmap.start);
251 self->mmap.len = bswap_64(self->mmap.len);
252 self->mmap.pgoff = bswap_64(self->mmap.pgoff);
253}
254
255static void event__task_swap(event_t *self)
256{
257 self->fork.pid = bswap_32(self->fork.pid);
258 self->fork.tid = bswap_32(self->fork.tid);
259 self->fork.ppid = bswap_32(self->fork.ppid);
260 self->fork.ptid = bswap_32(self->fork.ptid);
261 self->fork.time = bswap_64(self->fork.time);
262}
263
264static void event__read_swap(event_t *self)
265{
266 self->read.pid = bswap_32(self->read.pid);
267 self->read.tid = bswap_32(self->read.tid);
268 self->read.value = bswap_64(self->read.value);
269 self->read.time_enabled = bswap_64(self->read.time_enabled);
270 self->read.time_running = bswap_64(self->read.time_running);
271 self->read.id = bswap_64(self->read.id);
272}
273
274typedef void (*event__swap_op)(event_t *self);
275
276static event__swap_op event__swap_ops[] = {
277 [PERF_RECORD_MMAP] = event__mmap_swap,
278 [PERF_RECORD_COMM] = event__comm_swap,
279 [PERF_RECORD_FORK] = event__task_swap,
280 [PERF_RECORD_EXIT] = event__task_swap,
281 [PERF_RECORD_LOST] = event__all64_swap,
282 [PERF_RECORD_READ] = event__read_swap,
283 [PERF_RECORD_SAMPLE] = event__all64_swap,
284 [PERF_RECORD_MAX] = NULL,
285};
286
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200287static int perf_session__process_event(struct perf_session *self,
288 event_t *event,
289 struct perf_event_ops *ops,
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -0200290 u64 offset, u64 head)
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200291{
292 trace_event(event);
293
294 if (event->header.type < PERF_RECORD_MAX) {
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -0200295 dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
Arnaldo Carvalho de Melo0d755032010-01-14 12:23:09 -0200296 offset + head, event->header.size,
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200297 event__name[event->header.type]);
298 ++event__total[0];
299 ++event__total[event->header.type];
300 }
301
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -0200302 if (self->header.needs_swap && event__swap_ops[event->header.type])
303 event__swap_ops[event->header.type](event);
304
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200305 switch (event->header.type) {
306 case PERF_RECORD_SAMPLE:
Arnaldo Carvalho de Melo55aa640f2009-12-27 21:37:05 -0200307 return ops->sample(event, self);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200308 case PERF_RECORD_MMAP:
Arnaldo Carvalho de Melo55aa640f2009-12-27 21:37:05 -0200309 return ops->mmap(event, self);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200310 case PERF_RECORD_COMM:
Arnaldo Carvalho de Melo55aa640f2009-12-27 21:37:05 -0200311 return ops->comm(event, self);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200312 case PERF_RECORD_FORK:
Arnaldo Carvalho de Melo55aa640f2009-12-27 21:37:05 -0200313 return ops->fork(event, self);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200314 case PERF_RECORD_EXIT:
Arnaldo Carvalho de Melo55aa640f2009-12-27 21:37:05 -0200315 return ops->exit(event, self);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200316 case PERF_RECORD_LOST:
Arnaldo Carvalho de Melo55aa640f2009-12-27 21:37:05 -0200317 return ops->lost(event, self);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200318 case PERF_RECORD_READ:
Arnaldo Carvalho de Melo55aa640f2009-12-27 21:37:05 -0200319 return ops->read(event, self);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200320 case PERF_RECORD_THROTTLE:
Arnaldo Carvalho de Melo55aa640f2009-12-27 21:37:05 -0200321 return ops->throttle(event, self);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200322 case PERF_RECORD_UNTHROTTLE:
Arnaldo Carvalho de Melo55aa640f2009-12-27 21:37:05 -0200323 return ops->unthrottle(event, self);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200324 default:
Arnaldo Carvalho de Melo31d337c2009-12-27 21:37:03 -0200325 self->unknown_events++;
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200326 return -1;
327 }
328}
329
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -0200330void perf_event_header__bswap(struct perf_event_header *self)
331{
332 self->type = bswap_32(self->type);
333 self->misc = bswap_16(self->misc);
334 self->size = bswap_16(self->size);
335}
336
337int perf_header__read_build_ids(struct perf_header *self,
338 int input, u64 offset, u64 size)
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200339{
340 struct build_id_event bev;
341 char filename[PATH_MAX];
342 u64 limit = offset + size;
343 int err = -1;
344
345 while (offset < limit) {
346 struct dso *dso;
347 ssize_t len;
Arnaldo Carvalho de Meloa89e5abe2010-01-07 19:59:39 -0200348 struct list_head *head = &dsos__user;
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200349
350 if (read(input, &bev, sizeof(bev)) != sizeof(bev))
351 goto out;
352
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -0200353 if (self->needs_swap)
354 perf_event_header__bswap(&bev.header);
355
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200356 len = bev.header.size - sizeof(bev);
357 if (read(input, filename, len) != len)
358 goto out;
359
Arnaldo Carvalho de Meloa89e5abe2010-01-07 19:59:39 -0200360 if (bev.header.misc & PERF_RECORD_MISC_KERNEL)
361 head = &dsos__kernel;
362
363 dso = __dsos__findnew(head, filename);
Arnaldo Carvalho de Melob7cece762010-01-13 13:22:17 -0200364 if (dso != NULL) {
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200365 dso__set_build_id(dso, &bev.build_id);
Arnaldo Carvalho de Melob7cece762010-01-13 13:22:17 -0200366 if (head == &dsos__kernel && filename[0] == '[')
367 dso->kernel = 1;
368 }
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200369
370 offset += bev.header.size;
371 }
372 err = 0;
373out:
374 return err;
375}
376
377static struct thread *perf_session__register_idle_thread(struct perf_session *self)
378{
379 struct thread *thread = perf_session__findnew(self, 0);
380
381 if (thread == NULL || thread__set_comm(thread, "swapper")) {
382 pr_err("problem inserting idle task.\n");
383 thread = NULL;
384 }
385
386 return thread;
387}
388
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200389int __perf_session__process_events(struct perf_session *self,
390 u64 data_offset, u64 data_size,
391 u64 file_size, struct perf_event_ops *ops)
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200392{
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -0200393 int err, mmap_prot, mmap_flags;
394 u64 head, shift;
395 u64 offset = 0;
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200396 size_t page_size;
397 event_t *event;
398 uint32_t size;
399 char *buf;
Arnaldo Carvalho de Melo5f4d3f82010-03-26 21:16:22 -0300400 struct ui_progress *progress = ui_progress__new("Processing events...",
401 self->size);
402 if (progress == NULL)
403 return -1;
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200404
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200405 perf_event_ops__fill_defaults(ops);
406
Arnaldo Carvalho de Melo1b759622010-01-14 18:30:04 -0200407 page_size = sysconf(_SC_PAGESIZE);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200408
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200409 head = data_offset;
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200410 shift = page_size * (head / page_size);
411 offset += shift;
412 head -= shift;
413
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -0200414 mmap_prot = PROT_READ;
415 mmap_flags = MAP_SHARED;
416
417 if (self->header.needs_swap) {
418 mmap_prot |= PROT_WRITE;
419 mmap_flags = MAP_PRIVATE;
420 }
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200421remap:
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -0200422 buf = mmap(NULL, page_size * self->mmap_window, mmap_prot,
423 mmap_flags, self->fd, offset);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200424 if (buf == MAP_FAILED) {
425 pr_err("failed to mmap file\n");
426 err = -errno;
427 goto out_err;
428 }
429
430more:
431 event = (event_t *)(buf + head);
Arnaldo Carvalho de Melo5f4d3f82010-03-26 21:16:22 -0300432 ui_progress__update(progress, offset);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200433
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -0200434 if (self->header.needs_swap)
435 perf_event_header__bswap(&event->header);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200436 size = event->header.size;
437 if (size == 0)
438 size = 8;
439
440 if (head + event->header.size >= page_size * self->mmap_window) {
441 int munmap_ret;
442
443 shift = page_size * (head / page_size);
444
445 munmap_ret = munmap(buf, page_size * self->mmap_window);
446 assert(munmap_ret == 0);
447
448 offset += shift;
449 head -= shift;
450 goto remap;
451 }
452
453 size = event->header.size;
454
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -0200455 dump_printf("\n%#Lx [%#x]: event: %d\n",
Arnaldo Carvalho de Melo0d755032010-01-14 12:23:09 -0200456 offset + head, event->header.size, event->header.type);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200457
458 if (size == 0 ||
459 perf_session__process_event(self, event, ops, offset, head) < 0) {
Arnaldo Carvalho de Meloba215942010-01-14 12:23:10 -0200460 dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n",
Arnaldo Carvalho de Melo0d755032010-01-14 12:23:09 -0200461 offset + head, event->header.size,
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200462 event->header.type);
463 /*
464 * assume we lost track of the stream, check alignment, and
465 * increment a single u64 in the hope to catch on again 'soon'.
466 */
467 if (unlikely(head & 7))
468 head &= ~7ULL;
469
470 size = 8;
471 }
472
473 head += size;
474
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200475 if (offset + head >= data_offset + data_size)
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200476 goto done;
477
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200478 if (offset + head < file_size)
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200479 goto more;
480done:
481 err = 0;
482out_err:
Arnaldo Carvalho de Melo5f4d3f82010-03-26 21:16:22 -0300483 ui_progress__delete(progress);
Arnaldo Carvalho de Melo06aae5902009-12-27 21:36:59 -0200484 return err;
485}
Arnaldo Carvalho de Melo27295592009-12-27 21:37:01 -0200486
Arnaldo Carvalho de Melo6122e4e2010-02-03 16:52:05 -0200487int perf_session__process_events(struct perf_session *self,
488 struct perf_event_ops *ops)
489{
490 int err;
491
492 if (perf_session__register_idle_thread(self) == NULL)
493 return -ENOMEM;
494
495 if (!symbol_conf.full_paths) {
496 char bf[PATH_MAX];
497
498 if (getcwd(bf, sizeof(bf)) == NULL) {
499 err = -errno;
500out_getcwd_err:
501 pr_err("failed to get the current directory\n");
502 goto out_err;
503 }
504 self->cwd = strdup(bf);
505 if (self->cwd == NULL) {
506 err = -ENOMEM;
507 goto out_getcwd_err;
508 }
509 self->cwdlen = strlen(self->cwd);
510 }
511
512 err = __perf_session__process_events(self, self->header.data_offset,
513 self->header.data_size,
514 self->size, ops);
515out_err:
516 return err;
517}
518
Arnaldo Carvalho de Melod549c7692009-12-27 21:37:02 -0200519bool perf_session__has_traces(struct perf_session *self, const char *msg)
Arnaldo Carvalho de Melo27295592009-12-27 21:37:01 -0200520{
521 if (!(self->sample_type & PERF_SAMPLE_RAW)) {
Arnaldo Carvalho de Melod549c7692009-12-27 21:37:02 -0200522 pr_err("No trace sample to read. Did you call 'perf %s'?\n", msg);
523 return false;
Arnaldo Carvalho de Melo27295592009-12-27 21:37:01 -0200524 }
525
Arnaldo Carvalho de Melod549c7692009-12-27 21:37:02 -0200526 return true;
Arnaldo Carvalho de Melo27295592009-12-27 21:37:01 -0200527}
Arnaldo Carvalho de Melo56b03f32010-01-05 16:50:31 -0200528
529int perf_session__set_kallsyms_ref_reloc_sym(struct perf_session *self,
530 const char *symbol_name,
531 u64 addr)
532{
533 char *bracket;
Arnaldo Carvalho de Melo9de89fe2010-02-03 16:52:00 -0200534 enum map_type i;
Arnaldo Carvalho de Melo56b03f32010-01-05 16:50:31 -0200535
536 self->ref_reloc_sym.name = strdup(symbol_name);
537 if (self->ref_reloc_sym.name == NULL)
538 return -ENOMEM;
539
540 bracket = strchr(self->ref_reloc_sym.name, ']');
541 if (bracket)
542 *bracket = '\0';
543
544 self->ref_reloc_sym.addr = addr;
Arnaldo Carvalho de Melo9de89fe2010-02-03 16:52:00 -0200545
546 for (i = 0; i < MAP__NR_TYPES; ++i) {
547 struct kmap *kmap = map__kmap(self->vmlinux_maps[i]);
548 kmap->ref_reloc_sym = &self->ref_reloc_sym;
549 }
550
Arnaldo Carvalho de Melo56b03f32010-01-05 16:50:31 -0200551 return 0;
552}