提交 67b96c18 编写于 作者: I Ingo Molnar

Merge branch 'perf/core' of...

Merge branch 'perf/core' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux-2.6 into perf/core
上级 efc70d24 ddbc24b7
master alk-4.19.24 alk-4.19.30 alk-4.19.34 alk-4.19.36 alk-4.19.43 alk-4.19.48 alk-4.19.57 ck-4.19.67 ck-4.19.81 ck-4.19.91 github/fork/deepanshu1422/fix-typo-in-comment github/fork/haosdent/fix-typo linux-next v4.19.91 v4.19.90 v4.19.89 v4.19.88 v4.19.87 v4.19.86 v4.19.85 v4.19.84 v4.19.83 v4.19.82 v4.19.81 v4.19.80 v4.19.79 v4.19.78 v4.19.77 v4.19.76 v4.19.75 v4.19.74 v4.19.73 v4.19.72 v4.19.71 v4.19.70 v4.19.69 v4.19.68 v4.19.67 v4.19.66 v4.19.65 v4.19.64 v4.19.63 v4.19.62 v4.19.61 v4.19.60 v4.19.59 v4.19.58 v4.19.57 v4.19.56 v4.19.55 v4.19.54 v4.19.53 v4.19.52 v4.19.51 v4.19.50 v4.19.49 v4.19.48 v4.19.47 v4.19.46 v4.19.45 v4.19.44 v4.19.43 v4.19.42 v4.19.41 v4.19.40 v4.19.39 v4.19.38 v4.19.37 v4.19.36 v4.19.35 v4.19.34 v4.19.33 v4.19.32 v4.19.31 v4.19.30 v4.19.29 v4.19.28 v4.19.27 v4.19.26 v4.19.25 v4.19.24 v4.19.23 v4.19.22 v4.19.21 v4.19.20 v4.19.19 v4.19.18 v4.19.17 v4.19.16 v4.19.15 v4.19.14 v4.19.13 v4.19.12 v4.19.11 v4.19.10 v4.19.9 v4.19.8 v4.19.7 v4.19.6 v4.19.5 v4.19.4 v4.19.3 v4.19.2 v4.19.1 v4.19 v4.19-rc8 v4.19-rc7 v4.19-rc6 v4.19-rc5 v4.19-rc4 v4.19-rc3 v4.19-rc2 v4.19-rc1 ck-release-21 ck-release-20 ck-release-19.2 ck-release-19.1 ck-release-19 ck-release-18 ck-release-17.2 ck-release-17.1 ck-release-17 ck-release-16 ck-release-15.1 ck-release-15 ck-release-14 ck-release-13.2 ck-release-13 ck-release-12 ck-release-11 ck-release-10 ck-release-9 ck-release-7 alk-release-15 alk-release-14 alk-release-13.2 alk-release-13 alk-release-12 alk-release-11 alk-release-10 alk-release-9 alk-release-7
无相关合并请求
......@@ -104,6 +104,9 @@ OPTIONS
--vmlinux=<file>::
vmlinux pathname
--kallsyms=<file>::
kallsyms pathname
-m::
--modules::
Load module symbols. WARNING: This should only be used with -k and
......
......@@ -443,6 +443,8 @@ static const struct option options[] = {
"dump raw trace in ASCII"),
OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
"file", "vmlinux pathname"),
OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name,
"file", "kallsyms pathname"),
OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
OPT_BOOLEAN('m', "modules", &symbol_conf.use_modules,
"load module symbols - WARNING: use only with -k and LIVE kernel"),
......
......@@ -7,7 +7,7 @@
#include "strlist.h"
#include "thread.h"
const char *event__name[] = {
static const char *event__name[] = {
[0] = "TOTAL",
[PERF_RECORD_MMAP] = "MMAP",
[PERF_RECORD_LOST] = "LOST",
......@@ -22,8 +22,18 @@ const char *event__name[] = {
[PERF_RECORD_HEADER_EVENT_TYPE] = "EVENT_TYPE",
[PERF_RECORD_HEADER_TRACING_DATA] = "TRACING_DATA",
[PERF_RECORD_HEADER_BUILD_ID] = "BUILD_ID",
[PERF_RECORD_FINISHED_ROUND] = "FINISHED_ROUND",
};
const char *event__get_event_name(unsigned int id)
{
if (id >= ARRAY_SIZE(event__name))
return "INVALID";
if (!event__name[id])
return "UNKNOWN";
return event__name[id];
}
static struct sample_data synth_sample = {
.pid = -1,
.tid = -1,
......
......@@ -85,6 +85,7 @@ struct build_id_event {
};
enum perf_user_event_type { /* above any possible kernel type */
PERF_RECORD_USER_TYPE_START = 64,
PERF_RECORD_HEADER_ATTR = 64,
PERF_RECORD_HEADER_EVENT_TYPE = 65,
PERF_RECORD_HEADER_TRACING_DATA = 66,
......@@ -171,6 +172,6 @@ int event__preprocess_sample(const event_t *self, struct perf_session *session,
int event__parse_sample(const event_t *event, struct perf_session *session,
struct sample_data *sample);
extern const char *event__name[];
const char *event__get_event_name(unsigned int id);
#endif /* __PERF_RECORD_H */
......@@ -1168,10 +1168,13 @@ size_t hists__fprintf_nr_events(struct hists *self, FILE *fp)
size_t ret = 0;
for (i = 0; i < PERF_RECORD_HEADER_MAX; ++i) {
if (!event__name[i])
const char *name = event__get_event_name(i);
if (!strcmp(name, "UNKNOWN"))
continue;
ret += fprintf(fp, "%10s events: %10d\n",
event__name[i], self->stats.nr_events[i]);
ret += fprintf(fp, "%16s events: %10d\n", name,
self->stats.nr_events[i]);
}
return ret;
......
......@@ -444,6 +444,7 @@ static event__swap_op event__swap_ops[] = {
struct sample_queue {
u64 timestamp;
u64 file_offset;
event_t *event;
struct list_head list;
};
......@@ -464,7 +465,8 @@ static void perf_session_free_sample_buffers(struct perf_session *session)
static int perf_session_deliver_event(struct perf_session *session,
event_t *event,
struct sample_data *sample,
struct perf_event_ops *ops);
struct perf_event_ops *ops,
u64 file_offset);
static void flush_sample_queue(struct perf_session *s,
struct perf_event_ops *ops)
......@@ -484,7 +486,8 @@ static void flush_sample_queue(struct perf_session *s,
break;
event__parse_sample(iter->event, s, &sample);
perf_session_deliver_event(s, iter->event, &sample, ops);
perf_session_deliver_event(s, iter->event, &sample, ops,
iter->file_offset);
os->last_flush = iter->timestamp;
list_del(&iter->list);
......@@ -596,14 +599,14 @@ static void __queue_event(struct sample_queue *new, struct perf_session *s)
#define MAX_SAMPLE_BUFFER (64 * 1024 / sizeof(struct sample_queue))
static int perf_session_queue_event(struct perf_session *s, event_t *event,
struct sample_data *data)
struct sample_data *data, u64 file_offset)
{
struct ordered_samples *os = &s->ordered_samples;
struct list_head *sc = &os->sample_cache;
u64 timestamp = data->time;
struct sample_queue *new;
if (!timestamp)
if (!timestamp || timestamp == ~0ULL)
return -ETIME;
if (timestamp < s->ordered_samples.last_flush) {
......@@ -628,6 +631,7 @@ static int perf_session_queue_event(struct perf_session *s, event_t *event,
}
new->timestamp = timestamp;
new->file_offset = file_offset;
new->event = event;
__queue_event(new, s);
......@@ -635,13 +639,10 @@ static int perf_session_queue_event(struct perf_session *s, event_t *event,
return 0;
}
static void callchain__dump(struct sample_data *sample)
static void callchain__printf(struct sample_data *sample)
{
unsigned int i;
if (!dump_trace)
return;
printf("... chain: nr:%Lu\n", sample->callchain->nr);
for (i = 0; i < sample->callchain->nr; i++)
......@@ -665,13 +666,48 @@ static void perf_session__print_tstamp(struct perf_session *session,
printf("%Lu ", sample->time);
}
static void dump_event(struct perf_session *session, event_t *event,
u64 file_offset, struct sample_data *sample)
{
if (!dump_trace)
return;
printf("\n%#Lx [%#x]: event: %d\n", file_offset, event->header.size,
event->header.type);
trace_event(event);
if (sample)
perf_session__print_tstamp(session, event, sample);
printf("%#Lx [%#x]: PERF_RECORD_%s", file_offset, event->header.size,
event__get_event_name(event->header.type));
}
static void dump_sample(struct perf_session *session, event_t *event,
struct sample_data *sample)
{
if (!dump_trace)
return;
printf("(IP, %d): %d/%d: %#Lx period: %Ld\n", event->header.misc,
sample->pid, sample->tid, sample->ip, sample->period);
if (session->sample_type & PERF_SAMPLE_CALLCHAIN)
callchain__printf(sample);
}
static int perf_session_deliver_event(struct perf_session *session,
event_t *event,
struct sample_data *sample,
struct perf_event_ops *ops)
struct perf_event_ops *ops,
u64 file_offset)
{
dump_event(session, event, file_offset, sample);
switch (event->header.type) {
case PERF_RECORD_SAMPLE:
dump_sample(session, event, sample);
return ops->sample(event, sample, session);
case PERF_RECORD_MMAP:
return ops->mmap(event, sample, session);
......@@ -695,54 +731,29 @@ static int perf_session_deliver_event(struct perf_session *session,
}
}
static int perf_session__process_event(struct perf_session *session,
event_t *event,
struct perf_event_ops *ops,
u64 file_offset)
static int perf_session__preprocess_sample(struct perf_session *session,
event_t *event, struct sample_data *sample)
{
struct sample_data sample;
int ret;
trace_event(event);
if (session->header.needs_swap && event__swap_ops[event->header.type])
event__swap_ops[event->header.type](event);
if (event->header.type != PERF_RECORD_SAMPLE ||
!(session->sample_type & PERF_SAMPLE_CALLCHAIN))
return 0;
if (event->header.type >= PERF_RECORD_MMAP &&
event->header.type <= PERF_RECORD_SAMPLE) {
event__parse_sample(event, session, &sample);
if (dump_trace)
perf_session__print_tstamp(session, event, &sample);
if (!ip_callchain__valid(sample->callchain, event)) {
pr_debug("call-chain problem with event, skipping it.\n");
++session->hists.stats.nr_invalid_chains;
session->hists.stats.total_invalid_chains += sample->period;
return -EINVAL;
}
return 0;
}
if (event->header.type < PERF_RECORD_HEADER_MAX) {
dump_printf("%#Lx [%#x]: PERF_RECORD_%s",
file_offset, event->header.size,
event__name[event->header.type]);
hists__inc_nr_events(&session->hists, event->header.type);
}
static int perf_session__process_user_event(struct perf_session *session, event_t *event,
struct perf_event_ops *ops, u64 file_offset)
{
dump_event(session, event, file_offset, NULL);
/* These events are processed right away */
switch (event->header.type) {
case PERF_RECORD_SAMPLE:
dump_printf("(IP, %d): %d/%d: %#Lx period: %Ld\n",
event->header.misc,
sample.pid, sample.tid, sample.ip, sample.period);
if (session->sample_type & PERF_SAMPLE_CALLCHAIN) {
if (!ip_callchain__valid(sample.callchain, event)) {
pr_debug("call-chain problem with event, "
"skipping it.\n");
++session->hists.stats.nr_invalid_chains;
session->hists.stats.total_invalid_chains +=
sample.period;
return 0;
}
callchain__dump(&sample);
}
break;
case PERF_RECORD_HEADER_ATTR:
return ops->attr(event, session);
case PERF_RECORD_HEADER_EVENT_TYPE:
......@@ -756,16 +767,47 @@ static int perf_session__process_event(struct perf_session *session,
case PERF_RECORD_FINISHED_ROUND:
return ops->finished_round(event, session, ops);
default:
break;
return -EINVAL;
}
}
static int perf_session__process_event(struct perf_session *session,
event_t *event,
struct perf_event_ops *ops,
u64 file_offset)
{
struct sample_data sample;
int ret;
if (session->header.needs_swap && event__swap_ops[event->header.type])
event__swap_ops[event->header.type](event);
if (event->header.type >= PERF_RECORD_HEADER_MAX)
return -EINVAL;
hists__inc_nr_events(&session->hists, event->header.type);
if (event->header.type >= PERF_RECORD_USER_TYPE_START)
return perf_session__process_user_event(session, event, ops, file_offset);
/*
* For all kernel events we get the sample data
*/
event__parse_sample(event, session, &sample);
/* Preprocess sample records - precheck callchains */
if (perf_session__preprocess_sample(session, event, &sample))
return 0;
if (ops->ordered_samples) {
ret = perf_session_queue_event(session, event, &sample);
ret = perf_session_queue_event(session, event, &sample,
file_offset);
if (ret != -ETIME)
return ret;
}
return perf_session_deliver_event(session, event, &sample, ops);
return perf_session_deliver_event(session, event, &sample, ops,
file_offset);
}
void perf_event_header__bswap(struct perf_event_header *self)
......@@ -870,9 +912,6 @@ static int __perf_session__process_pipe_events(struct perf_session *self,
head += size;
dump_printf("\n%#Lx [%#x]: event: %d\n",
head, event.header.size, event.header.type);
if (skip > 0)
head += skip;
......@@ -961,9 +1000,6 @@ int __perf_session__process_events(struct perf_session *session,
size = event->header.size;
dump_printf("\n%#Lx [%#x]: event: %d\n",
file_pos, event->header.size, event->header.type);
if (size == 0 ||
perf_session__process_event(session, event, ops, file_pos) < 0) {
dump_printf("%#Lx [%#x]: skipping unknown header type: %d\n",
......
......@@ -1830,8 +1830,8 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
const char *kallsyms_filename = NULL;
char *kallsyms_allocated_filename = NULL;
/*
* Step 1: if the user specified a vmlinux filename, use it and only
* it, reporting errors to the user if it cannot be used.
* Step 1: if the user specified a kallsyms or vmlinux filename, use
* it and only it, reporting errors to the user if it cannot be used.
*
* For instance, try to analyse an ARM perf.data file _without_ a
* build-id, or if the user specifies the wrong path to the right
......@@ -1844,6 +1844,11 @@ static int dso__load_kernel_sym(struct dso *self, struct map *map,
* validation in dso__load_vmlinux and will bail out if they don't
* match.
*/
if (symbol_conf.kallsyms_name != NULL) {
kallsyms_filename = symbol_conf.kallsyms_name;
goto do_kallsyms;
}
if (symbol_conf.vmlinux_name != NULL) {
err = dso__load_vmlinux(self, map,
symbol_conf.vmlinux_name, filter);
......
......@@ -72,6 +72,7 @@ struct symbol_conf {
show_cpu_utilization,
initialized;
const char *vmlinux_name,
*kallsyms_name,
*source_prefix,
*field_sep;
const char *default_guest_vmlinux_name,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册
反馈
建议
客服 返回
顶部