Merge branch 'perf/core' of ssh://k/pub/scm/linux/kernel/git/acme/linux into perf/core

This commit is contained in:
Ingo Molnar 2011-06-03 10:43:03 +02:00
commit aef29bf20b
13 changed files with 244 additions and 109 deletions

View File

@ -115,10 +115,10 @@ OPTIONS
-f::
--fields::
Comma separated list of fields to print. Options are:
comm, tid, pid, time, cpu, event, trace, sym. Field
list can be prepended with the type, trace, sw or hw,
comm, tid, pid, time, cpu, event, trace, ip, sym, dso, addr.
Field list can be prepended with the type, trace, sw or hw,
to indicate to which event type the field list applies.
e.g., -f sw:comm,tid,time,sym and -f trace:time,cpu,trace
e.g., -f sw:comm,tid,time,ip,sym and -f trace:time,cpu,trace
perf script -f <fields>
@ -132,17 +132,17 @@ OPTIONS
The arguments are processed in the order received. A later usage can
reset a prior request. e.g.:
-f trace: -f comm,tid,time,sym
-f trace: -f comm,tid,time,ip,sym
The first -f suppresses trace events (field list is ""), but then the
second invocation sets the fields to comm,tid,time,sym. In this case a
second invocation sets the fields to comm,tid,time,ip,sym. In this case a
warning is given to the user:
"Overriding previous field request for all events."
Alternativey, consider the order:
-f comm,tid,time,sym -f trace:
-f comm,tid,time,ip,sym -f trace:
The first -f sets the fields for all events and the second -f
suppresses trace events. The user is given a warning message about

View File

@ -30,7 +30,10 @@ enum perf_output_field {
PERF_OUTPUT_CPU = 1U << 4,
PERF_OUTPUT_EVNAME = 1U << 5,
PERF_OUTPUT_TRACE = 1U << 6,
PERF_OUTPUT_SYM = 1U << 7,
PERF_OUTPUT_IP = 1U << 7,
PERF_OUTPUT_SYM = 1U << 8,
PERF_OUTPUT_DSO = 1U << 9,
PERF_OUTPUT_ADDR = 1U << 10,
};
struct output_option {
@ -44,7 +47,10 @@ struct output_option {
{.str = "cpu", .field = PERF_OUTPUT_CPU},
{.str = "event", .field = PERF_OUTPUT_EVNAME},
{.str = "trace", .field = PERF_OUTPUT_TRACE},
{.str = "ip", .field = PERF_OUTPUT_IP},
{.str = "sym", .field = PERF_OUTPUT_SYM},
{.str = "dso", .field = PERF_OUTPUT_DSO},
{.str = "addr", .field = PERF_OUTPUT_ADDR},
};
/* default set to maintain compatibility with current format */
@ -60,7 +66,8 @@ static struct {
.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
.invalid_fields = PERF_OUTPUT_TRACE,
},
@ -70,7 +77,8 @@ static struct {
.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
.invalid_fields = PERF_OUTPUT_TRACE,
},
@ -88,7 +96,8 @@ static struct {
.fields = PERF_OUTPUT_COMM | PERF_OUTPUT_TID |
PERF_OUTPUT_CPU | PERF_OUTPUT_TIME |
PERF_OUTPUT_EVNAME | PERF_OUTPUT_SYM,
PERF_OUTPUT_EVNAME | PERF_OUTPUT_IP |
PERF_OUTPUT_SYM | PERF_OUTPUT_DSO,
.invalid_fields = PERF_OUTPUT_TRACE,
},
@ -157,9 +166,9 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
!perf_session__has_traces(session, "record -R"))
return -EINVAL;
if (PRINT_FIELD(SYM)) {
if (PRINT_FIELD(IP)) {
if (perf_event_attr__check_stype(attr, PERF_SAMPLE_IP, "IP",
PERF_OUTPUT_SYM))
PERF_OUTPUT_IP))
return -EINVAL;
if (!no_callchain &&
@ -167,6 +176,24 @@ static int perf_evsel__check_attr(struct perf_evsel *evsel,
symbol_conf.use_callchain = false;
}
if (PRINT_FIELD(ADDR) &&
perf_event_attr__check_stype(attr, PERF_SAMPLE_ADDR, "ADDR",
PERF_OUTPUT_ADDR))
return -EINVAL;
if (PRINT_FIELD(SYM) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
pr_err("Display of symbols requested but neither sample IP nor "
"sample address\nis selected. Hence, no addresses to convert "
"to symbols.\n");
return -EINVAL;
}
if (PRINT_FIELD(DSO) && !PRINT_FIELD(IP) && !PRINT_FIELD(ADDR)) {
pr_err("Display of DSO requested but neither sample IP nor "
"sample address\nis selected. Hence, no addresses to convert "
"to DSO.\n");
return -EINVAL;
}
if ((PRINT_FIELD(PID) || PRINT_FIELD(TID)) &&
perf_event_attr__check_stype(attr, PERF_SAMPLE_TID, "TID",
PERF_OUTPUT_TID|PERF_OUTPUT_PID))
@ -230,7 +257,7 @@ static void print_sample_start(struct perf_sample *sample,
if (PRINT_FIELD(COMM)) {
if (latency_format)
printf("%8.8s ", thread->comm);
else if (PRINT_FIELD(SYM) && symbol_conf.use_callchain)
else if (PRINT_FIELD(IP) && symbol_conf.use_callchain)
printf("%s ", thread->comm);
else
printf("%16s ", thread->comm);
@ -271,6 +298,63 @@ static void print_sample_start(struct perf_sample *sample,
}
}
static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
{
if ((attr->type == PERF_TYPE_SOFTWARE) &&
((attr->config == PERF_COUNT_SW_PAGE_FAULTS) ||
(attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN) ||
(attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)))
return true;
return false;
}
static void print_sample_addr(union perf_event *event,
struct perf_sample *sample,
struct perf_session *session,
struct thread *thread,
struct perf_event_attr *attr)
{
struct addr_location al;
u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
const char *symname, *dsoname;
printf("%16" PRIx64, sample->addr);
if (!sample_addr_correlates_sym(attr))
return;
thread__find_addr_map(thread, session, cpumode, MAP__FUNCTION,
event->ip.pid, sample->addr, &al);
if (!al.map)
thread__find_addr_map(thread, session, cpumode, MAP__VARIABLE,
event->ip.pid, sample->addr, &al);
al.cpu = sample->cpu;
al.sym = NULL;
if (al.map)
al.sym = map__find_symbol(al.map, al.addr, NULL);
if (PRINT_FIELD(SYM)) {
if (al.sym && al.sym->name)
symname = al.sym->name;
else
symname = "";
printf(" %16s", symname);
}
if (PRINT_FIELD(DSO)) {
if (al.map && al.map->dso && al.map->dso->name)
dsoname = al.map->dso->name;
else
dsoname = "";
printf(" (%s)", dsoname);
}
}
static void process_event(union perf_event *event __unused,
struct perf_sample *sample,
struct perf_evsel *evsel,
@ -288,12 +372,16 @@ static void process_event(union perf_event *event __unused,
print_trace_event(sample->cpu, sample->raw_data,
sample->raw_size);
if (PRINT_FIELD(SYM)) {
if (PRINT_FIELD(ADDR))
print_sample_addr(event, sample, session, thread, attr);
if (PRINT_FIELD(IP)) {
if (!symbol_conf.use_callchain)
printf(" ");
else
printf("\n");
perf_session__print_symbols(event, sample, session);
perf_session__print_ip(event, sample, session,
PRINT_FIELD(SYM), PRINT_FIELD(DSO));
}
printf("\n");
@ -985,7 +1073,7 @@ static const struct option options[] = {
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
"Look for files with symbols relative to this directory"),
OPT_CALLBACK('f', "fields", NULL, "str",
"comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,sym",
"comma separated output fields prepend with 'type:'. Valid types: hw,sw,trace,raw. Fields: comm,tid,pid,time,cpu,event,trace,ip,sym,dso,addr",
parse_output_fields),
OPT_END()

View File

@ -61,6 +61,8 @@
#include <locale.h>
#define DEFAULT_SEPARATOR " "
#define CNTR_NOT_SUPPORTED "<not supported>"
#define CNTR_NOT_COUNTED "<not counted>"
static struct perf_event_attr default_attrs[] = {
@ -448,6 +450,7 @@ static int run_perf_stat(int argc __used, const char **argv)
if (verbose)
ui__warning("%s event is not supported by the kernel.\n",
event_name(counter));
counter->supported = false;
continue;
}
@ -466,6 +469,7 @@ static int run_perf_stat(int argc __used, const char **argv)
die("Not all events could be opened.\n");
return -1;
}
counter->supported = true;
}
if (perf_evlist__set_filters(evsel_list)) {
@ -861,7 +865,7 @@ static void print_counter_aggr(struct perf_evsel *counter)
if (scaled == -1) {
fprintf(stderr, "%*s%s%*s",
csv_output ? 0 : 18,
"<not counted>",
counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
csv_sep,
csv_output ? 0 : -24,
event_name(counter));
@ -914,7 +918,8 @@ static void print_counter(struct perf_evsel *counter)
csv_output ? 0 : -4,
evsel_list->cpus->map[cpu], csv_sep,
csv_output ? 0 : 18,
"<not counted>", csv_sep,
counter->supported ? CNTR_NOT_COUNTED : CNTR_NOT_SUPPORTED,
csv_sep,
csv_output ? 0 : -24,
event_name(counter));

View File

@ -474,7 +474,7 @@ static int test__basic_mmap(void)
unsigned int nr_events[nsyscalls],
expected_nr_events[nsyscalls], i, j;
struct perf_evsel *evsels[nsyscalls], *evsel;
int sample_size = perf_sample_size(attr.sample_type);
int sample_size = __perf_evsel__sample_size(attr.sample_type);
for (i = 0; i < nsyscalls; ++i) {
char name[64];

View File

@ -35,22 +35,6 @@ const char *perf_event__name(unsigned int id)
return perf_event__names[id];
}
int perf_sample_size(u64 sample_type)
{
u64 mask = sample_type & PERF_SAMPLE_MASK;
int size = 0;
int i;
for (i = 0; i < 64; i++) {
if (mask & (1ULL << i))
size++;
}
size *= sizeof(u64);
return size;
}
static struct perf_sample synth_sample = {
.pid = -1,
.tid = -1,

View File

@ -82,8 +82,6 @@ struct perf_sample {
struct ip_callchain *callchain;
};
int perf_sample_size(u64 sample_type);
#define BUILD_ID_SIZE 20
struct build_id_event {

View File

@ -12,7 +12,6 @@
#include "evlist.h"
#include "evsel.h"
#include "util.h"
#include "debug.h"
#include <sys/mman.h>
@ -257,19 +256,15 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
return evlist->mmap != NULL ? 0 : -ENOMEM;
}
static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel,
static int __perf_evlist__mmap(struct perf_evlist *evlist,
int idx, int prot, int mask, int fd)
{
evlist->mmap[idx].prev = 0;
evlist->mmap[idx].mask = mask;
evlist->mmap[idx].base = mmap(NULL, evlist->mmap_len, prot,
MAP_SHARED, fd, 0);
if (evlist->mmap[idx].base == MAP_FAILED) {
if (evlist->cpus->map[idx] == -1 && evsel->attr.inherit)
ui__warning("Inherit is not allowed on per-task "
"events using mmap.\n");
if (evlist->mmap[idx].base == MAP_FAILED)
return -1;
}
perf_evlist__add_pollfd(evlist, fd);
return 0;
@ -289,7 +284,7 @@ static int perf_evlist__mmap_per_cpu(struct perf_evlist *evlist, int prot, int m
if (output == -1) {
output = fd;
if (__perf_evlist__mmap(evlist, evsel, cpu,
if (__perf_evlist__mmap(evlist, cpu,
prot, mask, output) < 0)
goto out_unmap;
} else {
@ -329,7 +324,7 @@ static int perf_evlist__mmap_per_thread(struct perf_evlist *evlist, int prot, in
if (output == -1) {
output = fd;
if (__perf_evlist__mmap(evlist, evsel, thread,
if (__perf_evlist__mmap(evlist, thread,
prot, mask, output) < 0)
goto out_unmap;
} else {
@ -460,33 +455,46 @@ int perf_evlist__set_filters(struct perf_evlist *evlist)
return 0;
}
u64 perf_evlist__sample_type(struct perf_evlist *evlist)
bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist)
{
struct perf_evsel *pos;
u64 type = 0;
struct perf_evsel *pos, *first;
list_for_each_entry(pos, &evlist->entries, node) {
if (!type)
type = pos->attr.sample_type;
else if (type != pos->attr.sample_type)
die("non matching sample_type");
pos = first = list_entry(evlist->entries.next, struct perf_evsel, node);
list_for_each_entry_continue(pos, &evlist->entries, node) {
if (first->attr.sample_type != pos->attr.sample_type)
return false;
}
return type;
return true;
}
u64 perf_evlist__sample_type(const struct perf_evlist *evlist)
{
struct perf_evsel *first;
first = list_entry(evlist->entries.next, struct perf_evsel, node);
return first->attr.sample_type;
}
bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist)
{
struct perf_evsel *pos, *first;
pos = first = list_entry(evlist->entries.next, struct perf_evsel, node);
list_for_each_entry_continue(pos, &evlist->entries, node) {
if (first->attr.sample_id_all != pos->attr.sample_id_all)
return false;
}
return true;
}
bool perf_evlist__sample_id_all(const struct perf_evlist *evlist)
{
bool value = false, first = true;
struct perf_evsel *pos;
struct perf_evsel *first;
list_for_each_entry(pos, &evlist->entries, node) {
if (first) {
value = pos->attr.sample_id_all;
first = false;
} else if (value != pos->attr.sample_id_all)
die("non matching sample_id_all");
}
return value;
first = list_entry(evlist->entries.next, struct perf_evsel, node);
return first->attr.sample_id_all;
}

View File

@ -66,7 +66,9 @@ int perf_evlist__create_maps(struct perf_evlist *evlist, pid_t target_pid,
void perf_evlist__delete_maps(struct perf_evlist *evlist);
int perf_evlist__set_filters(struct perf_evlist *evlist);
u64 perf_evlist__sample_type(struct perf_evlist *evlist);
bool perf_evlist__sample_id_all(const struct perf_evlist *evlist);
u64 perf_evlist__sample_type(const struct perf_evlist *evlist);
bool perf_evlist__sample_id_all(const const struct perf_evlist *evlist);
bool perf_evlist__valid_sample_type(const struct perf_evlist *evlist);
bool perf_evlist__valid_sample_id_all(const struct perf_evlist *evlist);
#endif /* __PERF_EVLIST_H */

View File

@ -15,6 +15,22 @@
#define FD(e, x, y) (*(int *)xyarray__entry(e->fd, x, y))
int __perf_evsel__sample_size(u64 sample_type)
{
u64 mask = sample_type & PERF_SAMPLE_MASK;
int size = 0;
int i;
for (i = 0; i < 64; i++) {
if (mask & (1ULL << i))
size++;
}
size *= sizeof(u64);
return size;
}
void perf_evsel__init(struct perf_evsel *evsel,
struct perf_event_attr *attr, int idx)
{
@ -361,6 +377,7 @@ int perf_event__parse_sample(const union perf_event *event, u64 type,
array++;
}
data->addr = 0;
if (type & PERF_SAMPLE_ADDR) {
data->addr = *array;
array++;

View File

@ -61,6 +61,7 @@ struct perf_evsel {
off_t id_offset;
};
struct cgroup_sel *cgrp;
bool supported;
};
struct cpu_map;
@ -149,4 +150,11 @@ static inline int perf_evsel__read_scaled(struct perf_evsel *evsel,
return __perf_evsel__read(evsel, ncpus, nthreads, true);
}
int __perf_evsel__sample_size(u64 sample_type);
static inline int perf_evsel__sample_size(struct perf_evsel *evsel)
{
return __perf_evsel__sample_size(evsel->attr.sample_type);
}
#endif /* __PERF_EVSEL_H */

View File

@ -247,7 +247,7 @@ struct pyrf_cpu_map {
static int pyrf_cpu_map__init(struct pyrf_cpu_map *pcpus,
PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = { "cpustr", NULL, NULL, };
static char *kwlist[] = { "cpustr", NULL };
char *cpustr = NULL;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|s",
@ -316,7 +316,7 @@ struct pyrf_thread_map {
static int pyrf_thread_map__init(struct pyrf_thread_map *pthreads,
PyObject *args, PyObject *kwargs)
{
static char *kwlist[] = { "pid", "tid", NULL, NULL, };
static char *kwlist[] = { "pid", "tid", NULL };
int pid = -1, tid = -1;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii",
@ -418,7 +418,9 @@ static int pyrf_evsel__init(struct pyrf_evsel *pevsel,
"wakeup_events",
"bp_type",
"bp_addr",
"bp_len", NULL, NULL, };
"bp_len",
NULL
};
u64 sample_period = 0;
u32 disabled = 0,
inherit = 0,
@ -499,7 +501,7 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
struct thread_map *threads = NULL;
PyObject *pcpus = NULL, *pthreads = NULL;
int group = 0, inherit = 0;
static char *kwlist[] = {"cpus", "threads", "group", "inherit", NULL, NULL};
static char *kwlist[] = { "cpus", "threads", "group", "inherit", NULL };
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
&pcpus, &pthreads, &group, &inherit))
@ -582,8 +584,7 @@ static PyObject *pyrf_evlist__mmap(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs)
{
struct perf_evlist *evlist = &pevlist->evlist;
static char *kwlist[] = {"pages", "overwrite",
NULL, NULL};
static char *kwlist[] = { "pages", "overwrite", NULL };
int pages = 128, overwrite = false;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ii", kwlist,
@ -603,7 +604,7 @@ static PyObject *pyrf_evlist__poll(struct pyrf_evlist *pevlist,
PyObject *args, PyObject *kwargs)
{
struct perf_evlist *evlist = &pevlist->evlist;
static char *kwlist[] = {"timeout", NULL, NULL};
static char *kwlist[] = { "timeout", NULL };
int timeout = -1, n;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", kwlist, &timeout))
@ -674,7 +675,7 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
struct perf_evlist *evlist = &pevlist->evlist;
union perf_event *event;
int sample_id_all = 1, cpu;
static char *kwlist[] = {"sample_id_all", NULL, NULL};
static char *kwlist[] = { "cpu", "sample_id_all", NULL };
int err;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "i|i", kwlist,
@ -692,16 +693,14 @@ static PyObject *pyrf_evlist__read_on_cpu(struct pyrf_evlist *pevlist,
first = list_entry(evlist->entries.next, struct perf_evsel, node);
err = perf_event__parse_sample(event, first->attr.sample_type,
perf_sample_size(first->attr.sample_type),
perf_evsel__sample_size(first),
sample_id_all, &pevent->sample);
if (err) {
pr_err("Can't parse sample, err = %d\n", err);
goto end;
}
if (err)
return PyErr_Format(PyExc_OSError,
"perf: can't parse sample, err=%d", err);
return pyevent;
}
end:
Py_INCREF(Py_None);
return Py_None;
}

View File

@ -58,6 +58,16 @@ static int perf_session__open(struct perf_session *self, bool force)
goto out_close;
}
if (!perf_evlist__valid_sample_type(self->evlist)) {
pr_err("non matching sample_type");
goto out_close;
}
if (!perf_evlist__valid_sample_id_all(self->evlist)) {
pr_err("non matching sample_id_all");
goto out_close;
}
self->size = input_stat.st_size;
return 0;
@ -97,7 +107,7 @@ out:
void perf_session__update_sample_type(struct perf_session *self)
{
self->sample_type = perf_evlist__sample_type(self->evlist);
self->sample_size = perf_sample_size(self->sample_type);
self->sample_size = __perf_evsel__sample_size(self->sample_type);
self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
perf_session__id_header_size(self);
}
@ -698,9 +708,9 @@ static void dump_sample(struct perf_session *session, union perf_event *event,
if (!dump_trace)
return;
printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 "\n",
printf("(IP, %d): %d/%d: %#" PRIx64 " period: %" PRIu64 " addr: %#" PRIx64 "\n",
event->header.misc, sample->pid, sample->tid, sample->ip,
sample->period);
sample->period, sample->addr);
if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
callchain__printf(sample);
@ -1192,9 +1202,10 @@ struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
return NULL;
}
void perf_session__print_symbols(union perf_event *event,
struct perf_sample *sample,
struct perf_session *session)
void perf_session__print_ip(union perf_event *event,
struct perf_sample *sample,
struct perf_session *session,
int print_sym, int print_dso)
{
struct addr_location al;
const char *symname, *dsoname;
@ -1223,32 +1234,46 @@ void perf_session__print_symbols(union perf_event *event,
if (!node)
break;
if (node->sym && node->sym->name)
symname = node->sym->name;
else
symname = "";
printf("\t%16" PRIx64, node->ip);
if (print_sym) {
if (node->sym && node->sym->name)
symname = node->sym->name;
else
symname = "";
if (node->map && node->map->dso && node->map->dso->name)
dsoname = node->map->dso->name;
else
dsoname = "";
printf(" %s", symname);
}
if (print_dso) {
if (node->map && node->map->dso && node->map->dso->name)
dsoname = node->map->dso->name;
else
dsoname = "";
printf("\t%16" PRIx64 " %s (%s)\n", node->ip, symname, dsoname);
printf(" (%s)", dsoname);
}
printf("\n");
callchain_cursor_advance(cursor);
}
} else {
if (al.sym && al.sym->name)
symname = al.sym->name;
else
symname = "";
printf("%16" PRIx64, al.addr);
if (print_sym) {
if (al.sym && al.sym->name)
symname = al.sym->name;
else
symname = "";
if (al.map && al.map->dso && al.map->dso->name)
dsoname = al.map->dso->name;
else
dsoname = "";
printf(" %s", symname);
}
printf("%16" PRIx64 " %s (%s)", al.addr, symname, dsoname);
if (print_dso) {
if (al.map && al.map->dso && al.map->dso->name)
dsoname = al.map->dso->name;
else
dsoname = "";
printf(" (%s)", dsoname);
}
}
}

View File

@ -167,8 +167,9 @@ static inline int perf_session__parse_sample(struct perf_session *session,
struct perf_evsel *perf_session__find_first_evtype(struct perf_session *session,
unsigned int type);
void perf_session__print_symbols(union perf_event *event,
void perf_session__print_ip(union perf_event *event,
struct perf_sample *sample,
struct perf_session *session);
struct perf_session *session,
int print_sym, int print_dso);
#endif /* __PERF_SESSION_H */