|
|
|
@ -39,7 +39,8 @@
|
|
|
|
|
|
|
|
|
|
#ifdef HAVE_ZSTD_SUPPORT
|
|
|
|
|
static int perf_session__process_compressed_event(struct perf_session *session,
|
|
|
|
|
union perf_event *event, u64 file_offset)
|
|
|
|
|
union perf_event *event, u64 file_offset,
|
|
|
|
|
const char *file_path)
|
|
|
|
|
{
|
|
|
|
|
void *src;
|
|
|
|
|
size_t decomp_size, src_size;
|
|
|
|
@ -61,6 +62,7 @@ static int perf_session__process_compressed_event(struct perf_session *session,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
decomp->file_pos = file_offset;
|
|
|
|
|
decomp->file_path = file_path;
|
|
|
|
|
decomp->mmap_len = mmap_len;
|
|
|
|
|
decomp->head = 0;
|
|
|
|
|
|
|
|
|
@ -100,7 +102,8 @@ static int perf_session__process_compressed_event(struct perf_session *session,
|
|
|
|
|
static int perf_session__deliver_event(struct perf_session *session,
|
|
|
|
|
union perf_event *event,
|
|
|
|
|
struct perf_tool *tool,
|
|
|
|
|
u64 file_offset);
|
|
|
|
|
u64 file_offset,
|
|
|
|
|
const char *file_path);
|
|
|
|
|
|
|
|
|
|
static int perf_session__open(struct perf_session *session, int repipe_fd)
|
|
|
|
|
{
|
|
|
|
@ -182,7 +185,8 @@ static int ordered_events__deliver_event(struct ordered_events *oe,
|
|
|
|
|
ordered_events);
|
|
|
|
|
|
|
|
|
|
return perf_session__deliver_event(session, event->event,
|
|
|
|
|
session->tool, event->file_offset);
|
|
|
|
|
session->tool, event->file_offset,
|
|
|
|
|
event->file_path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct perf_session *__perf_session__new(struct perf_data *data,
|
|
|
|
@ -471,7 +475,8 @@ static int process_event_time_conv_stub(struct perf_session *perf_session __mayb
|
|
|
|
|
|
|
|
|
|
static int perf_session__process_compressed_event_stub(struct perf_session *session __maybe_unused,
|
|
|
|
|
union perf_event *event __maybe_unused,
|
|
|
|
|
u64 file_offset __maybe_unused)
|
|
|
|
|
u64 file_offset __maybe_unused,
|
|
|
|
|
const char *file_path __maybe_unused)
|
|
|
|
|
{
|
|
|
|
|
dump_printf(": unhandled!\n");
|
|
|
|
|
return 0;
|
|
|
|
@ -1072,9 +1077,9 @@ static int process_finished_round(struct perf_tool *tool __maybe_unused,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int perf_session__queue_event(struct perf_session *s, union perf_event *event,
|
|
|
|
|
u64 timestamp, u64 file_offset)
|
|
|
|
|
u64 timestamp, u64 file_offset, const char *file_path)
|
|
|
|
|
{
|
|
|
|
|
return ordered_events__queue(&s->ordered_events, event, timestamp, file_offset);
|
|
|
|
|
return ordered_events__queue(&s->ordered_events, event, timestamp, file_offset, file_path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void callchain__lbr_callstack_printf(struct perf_sample *sample)
|
|
|
|
@ -1277,13 +1282,14 @@ static void sample_read__printf(struct perf_sample *sample, u64 read_format)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void dump_event(struct evlist *evlist, union perf_event *event,
|
|
|
|
|
u64 file_offset, struct perf_sample *sample)
|
|
|
|
|
u64 file_offset, struct perf_sample *sample,
|
|
|
|
|
const char *file_path)
|
|
|
|
|
{
|
|
|
|
|
if (!dump_trace)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
printf("\n%#" PRIx64 " [%#x]: event: %d\n",
|
|
|
|
|
file_offset, event->header.size, event->header.type);
|
|
|
|
|
printf("\n%#" PRIx64 "@%s [%#x]: event: %d\n",
|
|
|
|
|
file_offset, file_path, event->header.size, event->header.type);
|
|
|
|
|
|
|
|
|
|
trace_event(event);
|
|
|
|
|
if (event->header.type == PERF_RECORD_SAMPLE && evlist->trace_event_sample_raw)
|
|
|
|
@ -1486,12 +1492,13 @@ static int machines__deliver_event(struct machines *machines,
|
|
|
|
|
struct evlist *evlist,
|
|
|
|
|
union perf_event *event,
|
|
|
|
|
struct perf_sample *sample,
|
|
|
|
|
struct perf_tool *tool, u64 file_offset)
|
|
|
|
|
struct perf_tool *tool, u64 file_offset,
|
|
|
|
|
const char *file_path)
|
|
|
|
|
{
|
|
|
|
|
struct evsel *evsel;
|
|
|
|
|
struct machine *machine;
|
|
|
|
|
|
|
|
|
|
dump_event(evlist, event, file_offset, sample);
|
|
|
|
|
dump_event(evlist, event, file_offset, sample, file_path);
|
|
|
|
|
|
|
|
|
|
evsel = evlist__id2evsel(evlist, sample->id);
|
|
|
|
|
|
|
|
|
@ -1573,7 +1580,8 @@ static int machines__deliver_event(struct machines *machines,
|
|
|
|
|
static int perf_session__deliver_event(struct perf_session *session,
|
|
|
|
|
union perf_event *event,
|
|
|
|
|
struct perf_tool *tool,
|
|
|
|
|
u64 file_offset)
|
|
|
|
|
u64 file_offset,
|
|
|
|
|
const char *file_path)
|
|
|
|
|
{
|
|
|
|
|
struct perf_sample sample;
|
|
|
|
|
int ret = evlist__parse_sample(session->evlist, event, &sample);
|
|
|
|
@ -1590,7 +1598,7 @@ static int perf_session__deliver_event(struct perf_session *session,
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
ret = machines__deliver_event(&session->machines, session->evlist,
|
|
|
|
|
event, &sample, tool, file_offset);
|
|
|
|
|
event, &sample, tool, file_offset, file_path);
|
|
|
|
|
|
|
|
|
|
if (dump_trace && sample.aux_sample.size)
|
|
|
|
|
auxtrace__dump_auxtrace_sample(session, &sample);
|
|
|
|
@ -1600,7 +1608,8 @@ static int perf_session__deliver_event(struct perf_session *session,
|
|
|
|
|
|
|
|
|
|
static s64 perf_session__process_user_event(struct perf_session *session,
|
|
|
|
|
union perf_event *event,
|
|
|
|
|
u64 file_offset)
|
|
|
|
|
u64 file_offset,
|
|
|
|
|
const char *file_path)
|
|
|
|
|
{
|
|
|
|
|
struct ordered_events *oe = &session->ordered_events;
|
|
|
|
|
struct perf_tool *tool = session->tool;
|
|
|
|
@ -1610,7 +1619,7 @@ static s64 perf_session__process_user_event(struct perf_session *session,
|
|
|
|
|
|
|
|
|
|
if (event->header.type != PERF_RECORD_COMPRESSED ||
|
|
|
|
|
tool->compressed == perf_session__process_compressed_event_stub)
|
|
|
|
|
dump_event(session->evlist, event, file_offset, &sample);
|
|
|
|
|
dump_event(session->evlist, event, file_offset, &sample, file_path);
|
|
|
|
|
|
|
|
|
|
/* These events are processed right away */
|
|
|
|
|
switch (event->header.type) {
|
|
|
|
@ -1669,9 +1678,9 @@ static s64 perf_session__process_user_event(struct perf_session *session,
|
|
|
|
|
case PERF_RECORD_HEADER_FEATURE:
|
|
|
|
|
return tool->feature(session, event);
|
|
|
|
|
case PERF_RECORD_COMPRESSED:
|
|
|
|
|
err = tool->compressed(session, event, file_offset);
|
|
|
|
|
err = tool->compressed(session, event, file_offset, file_path);
|
|
|
|
|
if (err)
|
|
|
|
|
dump_event(session->evlist, event, file_offset, &sample);
|
|
|
|
|
dump_event(session->evlist, event, file_offset, &sample, file_path);
|
|
|
|
|
return err;
|
|
|
|
|
default:
|
|
|
|
|
return -EINVAL;
|
|
|
|
@ -1688,9 +1697,9 @@ int perf_session__deliver_synth_event(struct perf_session *session,
|
|
|
|
|
events_stats__inc(&evlist->stats, event->header.type);
|
|
|
|
|
|
|
|
|
|
if (event->header.type >= PERF_RECORD_USER_TYPE_START)
|
|
|
|
|
return perf_session__process_user_event(session, event, 0);
|
|
|
|
|
return perf_session__process_user_event(session, event, 0, NULL);
|
|
|
|
|
|
|
|
|
|
return machines__deliver_event(&session->machines, evlist, event, sample, tool, 0);
|
|
|
|
|
return machines__deliver_event(&session->machines, evlist, event, sample, tool, 0, NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void event_swap(union perf_event *event, bool sample_id_all)
|
|
|
|
@ -1787,7 +1796,8 @@ int perf_session__peek_events(struct perf_session *session, u64 offset,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static s64 perf_session__process_event(struct perf_session *session,
|
|
|
|
|
union perf_event *event, u64 file_offset)
|
|
|
|
|
union perf_event *event, u64 file_offset,
|
|
|
|
|
const char *file_path)
|
|
|
|
|
{
|
|
|
|
|
struct evlist *evlist = session->evlist;
|
|
|
|
|
struct perf_tool *tool = session->tool;
|
|
|
|
@ -1802,7 +1812,7 @@ static s64 perf_session__process_event(struct perf_session *session,
|
|
|
|
|
events_stats__inc(&evlist->stats, event->header.type);
|
|
|
|
|
|
|
|
|
|
if (event->header.type >= PERF_RECORD_USER_TYPE_START)
|
|
|
|
|
return perf_session__process_user_event(session, event, file_offset);
|
|
|
|
|
return perf_session__process_user_event(session, event, file_offset, file_path);
|
|
|
|
|
|
|
|
|
|
if (tool->ordered_events) {
|
|
|
|
|
u64 timestamp = -1ULL;
|
|
|
|
@ -1811,12 +1821,12 @@ static s64 perf_session__process_event(struct perf_session *session,
|
|
|
|
|
if (ret && ret != -1)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
ret = perf_session__queue_event(session, event, timestamp, file_offset);
|
|
|
|
|
ret = perf_session__queue_event(session, event, timestamp, file_offset, file_path);
|
|
|
|
|
if (ret != -ETIME)
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return perf_session__deliver_event(session, event, tool, file_offset);
|
|
|
|
|
return perf_session__deliver_event(session, event, tool, file_offset, file_path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void perf_event_header__bswap(struct perf_event_header *hdr)
|
|
|
|
@ -2043,7 +2053,7 @@ more:
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((skip = perf_session__process_event(session, event, head)) < 0) {
|
|
|
|
|
if ((skip = perf_session__process_event(session, event, head, "pipe")) < 0) {
|
|
|
|
|
pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
|
|
|
|
|
head, event->header.size, event->header.type);
|
|
|
|
|
err = -EINVAL;
|
|
|
|
@ -2140,7 +2150,8 @@ static int __perf_session__process_decomp_events(struct perf_session *session)
|
|
|
|
|
size = event->header.size;
|
|
|
|
|
|
|
|
|
|
if (size < sizeof(struct perf_event_header) ||
|
|
|
|
|
(skip = perf_session__process_event(session, event, decomp->file_pos)) < 0) {
|
|
|
|
|
(skip = perf_session__process_event(session, event, decomp->file_pos,
|
|
|
|
|
decomp->file_path)) < 0) {
|
|
|
|
|
pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
|
|
|
|
|
decomp->file_pos + decomp->head, event->header.size, event->header.type);
|
|
|
|
|
return -EINVAL;
|
|
|
|
@ -2171,10 +2182,12 @@ struct reader;
|
|
|
|
|
|
|
|
|
|
typedef s64 (*reader_cb_t)(struct perf_session *session,
|
|
|
|
|
union perf_event *event,
|
|
|
|
|
u64 file_offset);
|
|
|
|
|
u64 file_offset,
|
|
|
|
|
const char *file_path);
|
|
|
|
|
|
|
|
|
|
struct reader {
|
|
|
|
|
int fd;
|
|
|
|
|
const char *path;
|
|
|
|
|
u64 data_size;
|
|
|
|
|
u64 data_offset;
|
|
|
|
|
reader_cb_t process;
|
|
|
|
@ -2294,7 +2307,7 @@ reader__read_event(struct reader *rd, struct perf_session *session,
|
|
|
|
|
skip = -EINVAL;
|
|
|
|
|
|
|
|
|
|
if (size < sizeof(struct perf_event_header) ||
|
|
|
|
|
(skip = rd->process(session, event, rd->file_pos)) < 0) {
|
|
|
|
|
(skip = rd->process(session, event, rd->file_pos, rd->path)) < 0) {
|
|
|
|
|
pr_err("%#" PRIx64 " [%#x]: failed to process type: %d [%s]\n",
|
|
|
|
|
rd->file_offset + rd->head, event->header.size,
|
|
|
|
|
event->header.type, strerror(-skip));
|
|
|
|
@ -2362,15 +2375,17 @@ out:
|
|
|
|
|
|
|
|
|
|
static s64 process_simple(struct perf_session *session,
|
|
|
|
|
union perf_event *event,
|
|
|
|
|
u64 file_offset)
|
|
|
|
|
u64 file_offset,
|
|
|
|
|
const char *file_path)
|
|
|
|
|
{
|
|
|
|
|
return perf_session__process_event(session, event, file_offset);
|
|
|
|
|
return perf_session__process_event(session, event, file_offset, file_path);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int __perf_session__process_events(struct perf_session *session)
|
|
|
|
|
{
|
|
|
|
|
struct reader rd = {
|
|
|
|
|
.fd = perf_data__fd(session->data),
|
|
|
|
|
.path = session->data->file.path,
|
|
|
|
|
.data_size = session->header.data_size,
|
|
|
|
|
.data_offset = session->header.data_offset,
|
|
|
|
|
.process = process_simple,
|
|
|
|
@ -2451,6 +2466,7 @@ static int __perf_session__process_dir_events(struct perf_session *session)
|
|
|
|
|
|
|
|
|
|
rd[0] = (struct reader) {
|
|
|
|
|
.fd = perf_data__fd(session->data),
|
|
|
|
|
.path = session->data->file.path,
|
|
|
|
|
.data_size = session->header.data_size,
|
|
|
|
|
.data_offset = session->header.data_offset,
|
|
|
|
|
.process = process_simple,
|
|
|
|
@ -2469,6 +2485,7 @@ static int __perf_session__process_dir_events(struct perf_session *session)
|
|
|
|
|
continue;
|
|
|
|
|
rd[readers] = (struct reader) {
|
|
|
|
|
.fd = data->dir.files[i].fd,
|
|
|
|
|
.path = data->dir.files[i].path,
|
|
|
|
|
.data_size = data->dir.files[i].size,
|
|
|
|
|
.data_offset = 0,
|
|
|
|
|
.process = process_simple,
|
|
|
|
|