Newer
Older
fprintf(fp, "\n");
fprintf(fp, "# ........");
list_for_each_entry(se, &hist_entry__sort_list, list) {
int i;
fprintf(fp, " ");
for (i = 0; i < strlen(se->header); i++)
fprintf(fp, ".");
fprintf(fp, "\n");
fprintf(fp, "#\n");
for (nd = rb_first(&output_hists); nd; nd = rb_next(nd)) {
pos = rb_entry(nd, struct hist_entry, rb_node);
ret += hist_entry__fprintf(fp, pos, total_samples);
}
return ret;
}

Arnaldo Carvalho de Melo
committed
{
unsigned long offset = 0;
unsigned long head = 0;
struct stat stat;
char *buf;
event_t *event;
int ret, rc = EXIT_FAILURE;
unsigned long total = 0, total_mmap = 0, total_comm = 0, total_unknown = 0;

Arnaldo Carvalho de Melo
committed
input = open(input_name, O_RDONLY);
if (input < 0) {
perror("failed to open file");
exit(-1);
}
ret = fstat(input, &stat);
if (ret < 0) {
perror("failed to stat file");
exit(-1);
}
if (!stat.st_size) {
fprintf(stderr, "zero-sized file, nothing to do!\n");
exit(0);
}
if (load_kernel() < 0) {

Arnaldo Carvalho de Melo
committed
perror("failed to open kallsyms");
return EXIT_FAILURE;
}
remap:
buf = (char *)mmap(NULL, page_size * mmap_window, PROT_READ,
MAP_SHARED, input, offset);
if (buf == MAP_FAILED) {
perror("failed to mmap file");
exit(-1);
}
more:
event = (event_t *)(buf + head);
size = event->header.size;
if (!size)
size = 8;

Arnaldo Carvalho de Melo
committed
if (head + event->header.size >= page_size * mmap_window) {
unsigned long shift = page_size * (head / page_size);
int ret;
ret = munmap(buf, page_size * mmap_window);
assert(ret == 0);
offset += shift;
head -= shift;
goto remap;
}
size = event->header.size;
if (!size)
goto broken_event;

Arnaldo Carvalho de Melo
committed
if (event->header.misc & PERF_EVENT_MISC_OVERFLOW) {
char level;
int show = 0;
struct dso *dso = NULL;
struct thread *thread = threads__findnew(event->ip.pid);
struct map *map = NULL;

Arnaldo Carvalho de Melo
committed
fprintf(stderr, "%p [%p]: PERF_EVENT (IP, %d): %d: %p\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->header.misc,
event->ip.pid,
(void *)(long)ip);
if (thread == NULL) {
fprintf(stderr, "problem processing %d event, skipping it.\n",
event->header.type);
goto broken_event;
}

Arnaldo Carvalho de Melo
committed
if (event->header.misc & PERF_EVENT_MISC_KERNEL) {
show = SHOW_KERNEL;
level = 'k';

Arnaldo Carvalho de Melo
committed
dso = kernel_dso;

Arnaldo Carvalho de Melo
committed
} else if (event->header.misc & PERF_EVENT_MISC_USER) {

Arnaldo Carvalho de Melo
committed
show = SHOW_USER;
level = '.';
map = thread__find_map(thread, ip);

Arnaldo Carvalho de Melo
committed
dso = map->dso;
ip -= map->start + map->pgoff;
}

Arnaldo Carvalho de Melo
committed
} else {
show = SHOW_HV;
level = 'H';
}
if (show & show_mask) {
struct symbol *sym = dso__find_symbol(dso, ip);

Arnaldo Carvalho de Melo
committed
if (hist_entry__add(thread, map, dso, sym, ip, level)) {
fprintf(stderr,
"problem incrementing symbol count, skipping event\n");
goto broken_event;
}

Arnaldo Carvalho de Melo
committed
}
total++;
} else switch (event->header.type) {
case PERF_EVENT_MMAP: {
struct thread *thread = threads__findnew(event->mmap.pid);
struct map *map = map__new(&event->mmap);
fprintf(stderr, "%p [%p]: PERF_EVENT_MMAP: [%p(%p) @ %p]: %s\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
(void *)(long)event->mmap.start,
(void *)(long)event->mmap.len,
(void *)(long)event->mmap.pgoff,
if (thread == NULL || map == NULL) {
fprintf(stderr, "problem processing PERF_EVENT_MMAP, skipping event.\n");
goto broken_event;
}

Arnaldo Carvalho de Melo
committed
thread__insert_map(thread, map);

Arnaldo Carvalho de Melo
committed
break;
}
case PERF_EVENT_COMM: {
struct thread *thread = threads__findnew(event->comm.pid);
fprintf(stderr, "%p [%p]: PERF_EVENT_COMM: %s:%d\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->comm.comm, event->comm.pid);
}

Arnaldo Carvalho de Melo
committed
if (thread == NULL ||
thread__set_comm(thread, event->comm.comm)) {
fprintf(stderr, "problem processing PERF_EVENT_COMM, skipping event.\n");
goto broken_event;
}

Arnaldo Carvalho de Melo
committed
break;
}
if (dump_trace)
fprintf(stderr, "%p [%p]: skipping unknown header type: %d\n",
(void *)(offset + head),
(void *)(long)(event->header.size),
event->header.type);
/*
* assume we lost track of the stream, check alignment, and
* increment a single u64 in the hope to catch on again 'soon'.
*/
if (unlikely(head & 7))
head &= ~7ULL;
size = 8;

Arnaldo Carvalho de Melo
committed
}

Arnaldo Carvalho de Melo
committed
if (offset + head < stat.st_size)
goto more;
rc = EXIT_SUCCESS;
close(input);
fprintf(stderr, " IP events: %10ld\n", total);
fprintf(stderr, " mmap events: %10ld\n", total_mmap);
fprintf(stderr, " comm events: %10ld\n", total_comm);
fprintf(stderr, " unknown events: %10ld\n", total_unknown);
dsos__fprintf(stdout);
output__resort();
output__fprintf(stdout, total);

Arnaldo Carvalho de Melo
committed
return rc;
}
static const char * const report_usage[] = {
"perf report [<options>] <command>",
NULL
};
static const struct option options[] = {
OPT_STRING('i', "input", &input_name, "file",
"input file name"),
OPT_BOOLEAN('v', "verbose", &verbose,
"be more verbose (show symbol address, etc)"),
OPT_BOOLEAN('D', "dump-raw-trace", &dump_trace,
"dump raw trace in ASCII"),
OPT_STRING('k', "vmlinux", &vmlinux, "file", "vmlinux pathname"),
OPT_STRING('s', "sort", &sort_order, "foo", "bar"),
OPT_END()
};
int cmd_report(int argc, const char **argv, const char *prefix)
{
elf_version(EV_CURRENT);
page_size = getpagesize();
parse_options(argc, argv, options, report_usage, 0);
setup_sorting();