libtraceevent/perf: Add support for trace-cmd plugins
cover libtraceevent/perf: Add support for trace-cmd plugins
Now that perf is using libtraceevent and libtraceevent is based on trace-cmd both can be extended to leverage the plugins written for trace-cmd to improve pretty printing of the events.
Given that it is based on code from trace-cmd I am not sure what the right approach is, so wanted to throw this out for comments/suggestions.
David Ahern (2):
libtraceevent: Add support for tracecmd plugins
perf: add support for trace-cmd plugins
tools/lib/traceevent/Makefile | 2 +- tools/lib/traceevent/tracecmd-plugins.c | 280 +++++++++++++++++++++++++++++++ tools/lib/traceevent/tracecmd-plugins.h | 34 ++++ tools/perf/util/trace-event-parse.c | 4 + 4 files changed, 319 insertions(+), 1 deletion(-) create mode 100644 tools/lib/traceevent/tracecmd-plugins.c create mode 100644 tools/lib/traceevent/tracecmd-plugins.h
Signature · 1 line
1.7.10.1
RFC PATCH 1/2 libtraceevent: Add support for tracecmd plugins
Plugin code pulled from trace-cmd repository as of 9a5cd1c1, cherry-picked the plugin loading functions from trace-util.c and declarations in trace-cmd.h
--- tools/lib/traceevent/Makefile | 2 +- tools/lib/traceevent/tracecmd-plugins.c | 280 +++++++++++++++++++++++++++++++ tools/lib/traceevent/tracecmd-plugins.h | 34 ++++ 3 files changed, 315 insertions(+), 1 deletion(-) create mode 100644 tools/lib/traceevent/tracecmd-plugins.c create mode 100644 tools/lib/traceevent/tracecmd-plugins.h
tools/lib/traceevent/Makefile +1 -1
@@ -188,7 +188,7 @@ $(obj)/%.o: $(src)/%.c %.o: $(src)/%.c $(Q)$(call do_compile) -PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o +PEVENT_LIB_OBJS = event-parse.o trace-seq.o parse-filter.o parse-utils.o tracecmd-plugins.o ALL_OBJS = $(PEVENT_LIB_OBJS)
tools/lib/traceevent/tracecmd-plugins.c new file +280 -0
280 lines not on this page · raw message
tools/lib/traceevent/tracecmd-plugins.h new file +34 -0
@@ -0,0 +1,34 @@ +/* +* Copyright (C) 2008, 2009, 2010 Red Hat Inc, Steven Rostedt <[email protected]> +* +* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +* This program is free software; you can redistribute it and/or +* modify it under the terms of the GNU Lesser General Public +* License as published by the Free Software Foundation; +* version 2.1 of the License (not later!) +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU Lesser General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public +* License along with this program; if not, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +* +* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ +#ifndef _TRACECMD__PLUGINS_H +#define _TRACECMD__PLUGINS_H + +#include <stdlib.h> +#include "event-parse.h" + +extern int tracecmd_disable_sys_plugins; +extern int tracecmd_disable_plugins; + +struct plugin_list ; +struct plugin_list *tracecmd_load_plugins (struct pevent *pevent); +void tracecmd_unload_plugins (struct plugin_list *list); + +#endif /* _TRACECMD__PLUGINS_H */
Signature · 1 line
1.7.10.1
RFC PATCH 2/2 perf: add support for trace-cmd plugins
In reply to David AhernImproves pretty printing of events when using perf-script. e.g., perf record -p 8731 -e kvm:* -fo /tmp/perf.data -- sleep 1
Currently when dumping kvm events you ugliness like this:
$ perf script -i /tmp/perf.data
Warning: bad op token {
Warning: failed to read event print fmt for kvm_emulate_insn
...
qemu-kvm 8734 [006] 826443.468554: kvm_emulate_insn:
<...>-8734 [006] 0.000000000: kvm_emulate_insn:
[FAILED TO PARSE] rip=18446744071579001937 csbase=0 len=6
insn=<89><B7> flags=9 failed=0Ignoring the duplication of data the event is not readable. With this patch and using the kvm plugin for trace-cmd you get:
qemu-kvm 8734 [006] 826443.468554: kvm_emulate_insn:
0:ffffffff81026451: mov %esi, 0xff5fb000(%rdi)
which is a bit more readable.
--- tools/perf/util/trace-event-parse.c | 4 ++++ 1 file changed, 4 insertions(+)
tools/perf/util/trace-event-parse.c +4 -0
@@ -27,6 +27,7 @@#include "../perf.h" #include "util.h" #include "trace-event.h" +#include "tracecmd-plugins.h" int header_page_size_size;int header_page_ts_size;
@@ -36,6 +37,7 @@ struct pevent *perf_pevent;static struct pevent *pevent;bool latency_format; +struct plugin_list *list;int read_trace_init (int file_bigendian,int host_bigendian) {
@@ -45,6 +47,8 @@ int read_trace_init(int file_bigendian, int host_bigendian) perf_pevent =pevent_alloc (); pevent = perf_pevent; + list =tracecmd_load_plugins (pevent); +pevent_set_flag (pevent,PEVENT_NSEC_OUTPUT );pevent_set_file_bigendian (pevent, file_bigendian);pevent_set_host_bigendian (pevent, host_bigendian);
Signature · 1 line
1.7.10.1
Namhyung Kim
maintainerHi, David
Quoted 7 lines · David Ahern
Now that perf is using libtraceevent and libtraceevent is based on trace-cmd both can be extended to leverage the plugins written for trace-cmd to improve pretty printing of the events.
Given that it is based on code from trace-cmd I am not sure what the right approach is, so wanted to throw this out for comments/suggestions.
Yeah, it can be useful to reuse existing code for extending the functionality. But I'm not so sure including the plugin APIs into libtraceevent is the right thing (at least in its current form).
And for this particular case in patch 2/2, it seems that format of the kvm_emulate_insn event is broken already and should be fixed anyway. Further improvement in this area can be addressed in perf kvm or other users if needed.
So I'd like to hear from others.
Arnaldo and Steven, what do you think?
Thanks,
Namhyung
Quoted 15 lines · Namhyung Kim
Hi, David
Quoted 7 lines · David Ahern
Now that perf is using libtraceevent and libtraceevent is based on trace-cmd both can be extended to leverage the plugins written for trace-cmd to improve pretty printing of the events.
Given that it is based on code from trace-cmd I am not sure what the right approach is, so wanted to throw this out for comments/suggestions.
Yeah, it can be useful to reuse existing code for extending the functionality. But I'm not so sure including the plugin APIs into libtraceevent is the right thing (at least in its current form).
Quoted 7 lines
And for this particular case in patch 2/2, it seems that format of the
kvm_emulate_insnevent is broken already and should be fixed anyway. Further improvement in this area can be addressed in perf kvm or other users if needed.So I'd like to hear from others.
Arnaldo and Steven, what do you think?
It's been crazy lately, so sorry for the late reply David.
Anyway, I think it is important to get this into either libtraceevent or another library, but I agree with Namhyung that it should not go in, in its current form.
Either we add the 'pevent_' names to it, and we need to change things a bit.
I want to redesign the plugin interface. Well, I do not need to be the one to redesign it, but it needs to be updated by someone.
Plugins need an interface that they can take parameters, or be modified at run time. An option passed to perf or trace-cmd could modify how the plugin works. Or during viewing of the output, parameters can be passed to tell plugins to do things differently.
Basically, we need to discuss the interface between plugins and the libtraceevent library. Once we get a good idea of what is needed, then we can start reusing the code from trace-cmd to make a much better interface for users.
Thanks!
-- Steve
Quoted 4 lines · Steven Rostedt
Anyway, I think it is important to get this into either libtraceevent or another library, but I agree with Namhyung that it should not go in, in its current form.
Great. No resistance to bringing this in.
Quoted 2 lines
Either we add the '
pevent_' names to it, and we need to change things a bit.
Sure, namespace cleanup is trivial.
Quoted 8 lines
I want to redesign the plugin interface. Well, I do not need to be the one to redesign it, but it needs to be updated by someone.
Plugins need an interface that they can take parameters, or be modified at run time. An option passed to perf or trace-cmd could modify how the plugin works. Or during viewing of the output, parameters can be passed to tell plugins to do things differently.
Quoted 4 lines
Basically, we need to discuss the interface between plugins and the libtraceevent library. Once we get a good idea of what is needed, then we can start reusing the code from trace-cmd to make a much better interface for users.
Ok. I'll poke around with this over the summer as I get spare time.
David
Hi Namhyung:
Quoted 4 lines · Namhyung Kim
And for this particular case in patch 2/2, it seems that format of the
kvm_emulate_insnevent is broken already and should be fixed anyway. Further improvement in this area can be addressed in perf kvm or other users if needed.
kvm tracepoints are fine; perf just doesn't handle their (advanced) formatting.
Note that I am referring to kvm:* tracepoints, not perf-kvm which has its own issues that need to be fixed.
David
Namhyung Kim
maintainerQuoted 2 lines · David Ahern
Hi Namhyung:
Hi David,
Quoted 9 lines · Namhyung Kim
Quoted 4 lines
And for this particular case in patch 2/2, it seems that format of the
kvm_emulate_insnevent is broken already and should be fixed anyway. Further improvement in this area can be addressed in perf kvm or other users if needed.kvm tracepoints are fine; perf just doesn't handle their (advanced) formatting.
Yeah, I think it's a libtraceevent's issue, not perf's. Please see below:
TRACE_EVENT(kvm_emulate_insn,
...
TP_printk("%x:%llx:%s (%s)%s",
__entry->csbase, __entry->rip,
__print_insn(__entry->insn, __entry->len),
__print_symbolic(__entry->flags,
kvm_trace_symbol_emul_flags),
__entry->failed ? " failed" : ""
)
);And __print_insn is defined as:
#define __print_insn(insn, ilen) ({ \
int i; \
const char *ret = p->buffer + p->len; \
\
for (i = 0; i < ilen; ++i) \
trace_seq_printf(p, " %02x", insn[i]); \
trace_seq_printf(p, "%c", 0); \
ret; \
})The parse error is occurred at the beginning of the compound statment:
Warning: bad op token {
Warning: failed to read event print fmt for kvm_emulate_insn
I don't think we can handle this kind of compound statments easily. So I just said it *seems* broken. :) Btw, calling trace_seq_printf() here also looks like a problem and I have no idea where the 'p' came from.
Thanks,
Namhyung
Quoted 4 lines
Note that I am referring to kvm:* tracepoints, not perf-kvm which has its own issues that need to be fixed.
David
Quoted 23 lines · Namhyung Kim
TRACE_EVENT(kvm_emulate_insn,
... TP_printk("%x:%llx:%s (%s)%s", __entry->csbase, __entry->rip, __print_insn(__entry->insn, __entry->len), __print_symbolic(__entry->flags, kvm_trace_symbol_emul_flags), __entry->failed ? " failed" : "" ) );And
__print_insnis defined as:#define __print_insn(insn, ilen) ({ \ int i; \ const char *ret = p->buffer + p->len; \ \ for (i = 0; i < ilen; ++i) \ trace_seq_printf(p, " %02x", insn[i]); \ trace_seq_printf(p, "%c", 0); \ ret; \ })
Quoted 8 lines
The parse error is occurred at the beginning of the compound statment:
Warning: bad op token {
Warning: failed to read event print fmt forkvm_emulate_insnI don't think we can handle this kind of compound statments easily. So I just said it *seems* broken. :) Btw, calling
trace_seq_printf()here also looks like a problem and I have no idea where the 'p' came from.
This is why we want the plugin. What the plugins do is registers how to parse the data of the event. The event format file is still parsed to find where the data is located, but the printf fmt: field (TP_printk) is ignored. The plugin provides the format to print the data with.
Lets look at the kvm plugin for kvm_emulate_insn:
static int kvm_emulate_insn_handler(struct trace_seq *s, struct record *record,
struct event_format *event, void *context)
{
unsigned long long rip, csbase, len, flags, failed;
int llen;
uint8_t *insn;
const char *disasm;
if (pevent_get_field_val(s, event, "rip", record, &rip, 1) < 0)
return -1;
if (pevent_get_field_val(s, event, "csbase", record, &csbase, 1) < 0)
return -1;
if (pevent_get_field_val(s, event, "len", record, &len, 1) < 0)
return -1;
if (pevent_get_field_val(s, event, "flags", record, &flags, 1) < 0)
return -1;
if (pevent_get_field_val(s, event, "failed", record, &failed, 1) < 0)
return -1;
insn = pevent_get_field_raw(s, event, "insn", record, &llen, 1);
if (!insn)
return -1;
disasm = disassemble(insn, len, rip,
flags & KVM_EMUL_INSN_F_CR0_PE,
flags & KVM_EMUL_INSN_F_EFL_VM,
flags & KVM_EMUL_INSN_F_CS_D,
flags & KVM_EMUL_INSN_F_CS_L);
trace_seq_printf(s, "%llx:%llx: %s%s", csbase, rip, disasm,
failed ? " FAIL" : "");
return 0;
}You see, this uses the information from libtraceevent to get the required fields. Then it prints it out nicely for users. Here's the output of trace-cmd report after a trace-cmd record -e kvm and starting a guest:
kvm-6172 [000] 14669573.114126: kvm_entry: vcpu 0
kvm-6172 [000] 14669573.114127: kvm_exit: reason IO_INSTRUCTION rip 0xffff357a info cfc0008 0
kvm-6172 [000] 14669573.114130: kvm_emulate_insn: 0:ffff357a: ec
kvm-6172 [000] 14669573.114130: kvm_pio: pio_read at 0xcfc size 1 count 1
kvm-6172 [000] 14669573.114131: kvm_userspace_exit: reason KVM_EXIT_IO (2)
kvm-6172 [000] 14669573.114134: kvm_entry: vcpu 0
kvm-6172 [000] 14669573.114135: kvm_exit: reason IO_INSTRUCTION rip 0xffff34f9 info cf80003 0
kvm-6172 [000] 14669573.114136: kvm_pio: pio_write at 0xcf8 size 4 count 1
kvm-6172 [000] 14669573.114136: kvm_userspace_exit: reason KVM_EXIT_IO (2)I can disable plugins to show you the result of what happens without them:
trace-cmd report -N
[...]
kvm-6172 [000] 14669573.114126: kvm_entry: vcpu 0
kvm-6172 [000] 14669573.114127: kvm_exit: [FAILED TO PARSE] exit_reason=30 guest_rip=0xffff357a isa=1 info1=217841672 info2=0
kvm-6172 [000] 14669573.114130: kvm_emulate_insn: [FAILED TO PARSE] rip=4294915450 csbase=0 len=1 insn=ì[ÃWVS<89>Ã<89>Öš^Gu^Q^O^E flags=5 failed=0
kvm-6172 [000] 14669573.114130: kvm_pio: pio_read at 0xcfc size 1 count 1
kvm-6172 [000] 14669573.114131: kvm_userspace_exit: reason KVM_EXIT_IO (2)
kvm-6172 [000] 14669573.114134: kvm_entry: vcpu 0This is the power of plugins. I would expect to add something like:
tools/events/plugins/
where these can be added for everyone.
-- Steve
Namhyung Kim
maintainerQuoted 30 lines · Steven Rostedt
Quoted 28 lines · Namhyung Kim
TRACE_EVENT(kvm_emulate_insn,
... TP_printk("%x:%llx:%s (%s)%s", __entry->csbase, __entry->rip, __print_insn(__entry->insn, __entry->len), __print_symbolic(__entry->flags, kvm_trace_symbol_emul_flags), __entry->failed ? " failed" : "" ) );And
__print_insnis defined as:#define __print_insn(insn, ilen) ({ \ int i; \ const char *ret = p->buffer + p->len; \ \ for (i = 0; i < ilen; ++i) \ trace_seq_printf(p, " %02x", insn[i]); \ trace_seq_printf(p, "%c", 0); \ ret; \ })The parse error is occurred at the beginning of the compound statment:
Warning: bad op token {
Warning: failed to read event print fmt forkvm_emulate_insn
Quoted 9 lines
Quoted 3 lines
I don't think we can handle this kind of compound statments easily. So I just said it *seems* broken. :) Btw, calling
trace_seq_printf()here also looks like a problem and I have no idea where the 'p' came from.This is why we want the plugin. What the plugins do is registers how to parse the data of the event. The event format file is still parsed to find where the data is located, but the printf fmt: field (
TP_printk) is ignored. The plugin provides the format to print the data with.
Yeah, I know. It's great. :)
Quoted 60 lines
Lets look at the kvm plugin for
kvm_emulate_insn:static int kvm_emulate_insn_handler(struct
trace_seq*s, struct record *record,
structevent_format*event, void *context){ unsigned long long rip, csbase, len, flags, failed; int llen; uint8_t *insn; const char *disasm; if (pevent_get_field_val(s, event, "rip", record, &rip, 1) < 0) return -1; if (pevent_get_field_val(s, event, "csbase", record, &csbase, 1) < 0) return -1; if (pevent_get_field_val(s, event, "len", record, &len, 1) < 0) return -1; if (pevent_get_field_val(s, event, "flags", record, &flags, 1) < 0) return -1; if (pevent_get_field_val(s, event, "failed", record, &failed, 1) < 0) return -1; insn = pevent_get_field_raw(s, event, "insn", record, &llen, 1); if (!insn) return -1; disasm = disassemble(insn, len, rip, flags & KVM_EMUL_INSN_F_CR0_PE, flags & KVM_EMUL_INSN_F_EFL_VM, flags & KVM_EMUL_INSN_F_CS_D, flags & KVM_EMUL_INSN_F_CS_L); trace_seq_printf(s, "%llx:%llx: %s%s", csbase, rip, disasm, failed ? " FAIL" : ""); return 0; }You see, this uses the information from libtraceevent to get the required fields. Then it prints it out nicely for users. Here's the output of trace-cmd report after a trace-cmd record -e kvm and starting a guest:
kvm-6172 [000] 14669573.114126: kvm_entry: vcpu 0 kvm-6172 [000] 14669573.114127: kvm_exit: reason IO_INSTRUCTION rip 0xffff357a info cfc0008 0 kvm-6172 [000] 14669573.114130: kvm_emulate_insn: 0:ffff357a: ec kvm-6172 [000] 14669573.114130: kvm_pio: pio_read at 0xcfc size 1 count 1 kvm-6172 [000] 14669573.114131: kvm_userspace_exit: reason KVM_EXIT_IO (2) kvm-6172 [000] 14669573.114134: kvm_entry: vcpu 0 kvm-6172 [000] 14669573.114135: kvm_exit: reason IO_INSTRUCTION rip 0xffff34f9 info cf80003 0 kvm-6172 [000] 14669573.114136: kvm_pio: pio_write at 0xcf8 size 4 count 1 kvm-6172 [000] 14669573.114136: kvm_userspace_exit: reason KVM_EXIT_IO (2)I can disable plugins to show you the result of what happens without them:
Quoted 9 lines
trace-cmd report -N
[...]kvm-6172 [000] 14669573.114126: kvm_entry: vcpu 0 kvm-6172 [000] 14669573.114127: kvm_exit: [FAILED TO PARSE] exit_reason=30 guest_rip=0xffff357a isa=1 info1=217841672 info2=0 kvm-6172 [000] 14669573.114130: kvm_emulate_insn: [FAILED TO PARSE] rip=4294915450 csbase=0 len=1 insn=ì[ÃWVS<89>Ã<89>Öš^Gu^Q^O^E flags=5 failed=0 kvm-6172 [000] 14669573.114130: kvm_pio: pio_read at 0xcfc size 1 count 1 kvm-6172 [000] 14669573.114131: kvm_userspace_exit: reason KVM_EXIT_IO (2) kvm-6172 [000] 14669573.114134: kvm_entry: vcpu 0
What I want to do is make it not to fail with default print_fmt (ie. w/o plugin support). IOW using a plugin to improve things like above is good, but not using it shouldn't break/fail anything. So I think fixing the TP_printk is needed.
Thanks,
Namhyung
Quoted 7 lines
This is the power of plugins. I would expect to add something like:
tools/events/plugins/where these can be added for everyone.
-- Steve
Quoted 10 lines · Namhyung Kim
Quoted 9 lines
trace-cmd report -N
[...]kvm-6172 [000] 14669573.114126: kvm_entry: vcpu 0 kvm-6172 [000] 14669573.114127: kvm_exit: [FAILED TO PARSE] exit_reason=30 guest_rip=0xffff357a isa=1 info1=217841672 info2=0 kvm-6172 [000] 14669573.114130: kvm_emulate_insn: [FAILED TO PARSE] rip=4294915450 csbase=0 len=1 insn=ì[ÃWVS<89>Ã<89>Öš^Gu^Q^O^E flags=5 failed=0 kvm-6172 [000] 14669573.114130: kvm_pio: pio_read at 0xcfc size 1 count 1 kvm-6172 [000] 14669573.114131: kvm_userspace_exit: reason KVM_EXIT_IO (2) kvm-6172 [000] 14669573.114134: kvm_entry: vcpu 0
Quoted 4 lines
What I want to do is make it not to fail with default
print_fmt(ie. w/o plugin support). IOW using a plugin to improve things like above is good, but not using it shouldn't break/fail anything. So I think fixing theTP_printkis needed.
I'm not sure its broken anymore per-say. As I just ran this without plugins (with the -N switch) and it doesn't break. It sends out some nasty warnings, but continues on its happy way with a warning that it '[FAILED TO PARSE]'. And some warnings in the beginning.
But it doesn't totally fail. We could probably clean it up a bit too. What it does above is simply print out the raw data and lists the fields.
The problem with modifying the TP_printk() is that this is also used by raw tracing (the /debug/tracing/trace file). Without using tools. The TP_printk() is really for that. The plugins is the way for tools to handle it.
-- Steve
Namhyung Kim
maintainerQuoted 22 lines · Steven Rostedt
Quoted 10 lines · Namhyung Kim
Quoted 9 lines
trace-cmd report -N
[...]kvm-6172 [000] 14669573.114126: kvm_entry: vcpu 0 kvm-6172 [000] 14669573.114127: kvm_exit: [FAILED TO PARSE] exit_reason=30 guest_rip=0xffff357a isa=1 info1=217841672 info2=0 kvm-6172 [000] 14669573.114130: kvm_emulate_insn: [FAILED TO PARSE] rip=4294915450 csbase=0 len=1 insn=ì[ÃWVS<89>Ã<89>Öš^Gu^Q^O^E flags=5 failed=0 kvm-6172 [000] 14669573.114130: kvm_pio: pio_read at 0xcfc size 1 count 1 kvm-6172 [000] 14669573.114131: kvm_userspace_exit: reason KVM_EXIT_IO (2) kvm-6172 [000] 14669573.114134: kvm_entry: vcpu 0Quoted 4 lines
What I want to do is make it not to fail with default
print_fmt(ie. w/o plugin support). IOW using a plugin to improve things like above is good, but not using it shouldn't break/fail anything. So I think fixing theTP_printkis needed.I'm not sure its broken anymore per-say. As I just ran this without plugins (with the -N switch) and it doesn't break. It sends out some nasty warnings, but continues on its happy way with a warning that it '[FAILED TO PARSE]'. And some warnings in the beginning.
Quoted 9 lines
But it doesn't totally fail. We could probably clean it up a bit too. What it does above is simply print out the raw data and lists the fields.
The problem with modifying the
TP_printk()is that this is also used by raw tracing (the /debug/tracing/trace file). Without using tools. TheTP_printk()is really for that. The plugins is the way for tools to handle it.
Ok. Then how about using __print_hex() for __print_insn? AFAICS ftrace_print_hex_seq() looks almost same as __print_insn() and as it's a generic function we can add its handler in libtraceevnt.
Thanks,
Namhyung
[ I'm tired of getting error messages from sending to some stranger at [email protected], I might as well send it to someone I know. Someone with an 'f' ]
Quoted 14 lines · Namhyung Kim
Quoted 12 lines · Steven Rostedt
Quoted 10 lines · Namhyung Kim
Quoted 9 lines
trace-cmd report -N
[...]kvm-6172 [000] 14669573.114126: kvm_entry: vcpu 0 kvm-6172 [000] 14669573.114127: kvm_exit: [FAILED TO PARSE] exit_reason=30 guest_rip=0xffff357a isa=1 info1=217841672 info2=0 kvm-6172 [000] 14669573.114130: kvm_emulate_insn: [FAILED TO PARSE] rip=4294915450 csbase=0 len=1 insn=ì[ÃWVS<89>Ã<89>Öš^Gu^Q^O^E flags=5 failed=0 kvm-6172 [000] 14669573.114130: kvm_pio: pio_read at 0xcfc size 1 count 1 kvm-6172 [000] 14669573.114131: kvm_userspace_exit: reason KVM_EXIT_IO (2) kvm-6172 [000] 14669573.114134: kvm_entry: vcpu 0
Quoted 3 lines
Ok. Then how about using
__print_hex()for__print_insn? AFAICSftrace_print_hex_seq()looks almost same as__print_insn()and as it's a generic function we can add its handler in libtraceevnt.
We can be a bit better at the raw print, sure. Here's the format that's there:
field:__u64 rip; offset:16; size:8; signed:0; field:__u32 csbase; offset:24; size:4; signed:0; field:__u8 len; offset:28; size:1; signed:0; field:__u8 insn[15]; offset:29; size:15; signed:0; field:__u8 flags; offset:44; size:1; signed:0; field:__u8 failed; offset:45; size:1; signed:0;
It treated __u* as decimal numbers, but it also saw that insn[15] was an array, and with single bytes at that. So it thought it was a string, and tried to print it out as such.
We can change the heuristics of this to make it more readable.
-- Steve
Namhyung Kim
maintainerQuoted 10 lines · Steven Rostedt
We can be a bit better at the raw print, sure. Here's the format that's there:
field:__u64 rip; offset:16; size:8; signed:0; field:__u32 csbase; offset:24; size:4; signed:0; field:__u8 len; offset:28; size:1; signed:0; field:__u8 insn[15]; offset:29; size:15; signed:0; field:__u8 flags; offset:44; size:1; signed:0; field:__u8 failed; offset:45; size:1; signed:0;
Quoted 6 lines
It treated __u* as decimal numbers, but it also saw that insn[15] was an array, and with single bytes at that. So it thought it was a string, and tried to print it out as such.
We can change the heuristics of this to make it more readable.
Right. The current heuristic treats an u8 array as a string:
static int field_is_string(struct format_field *field)
{
if ((field->flags & FIELD_IS_ARRAY) &&
(strstr(field->type, "char") || strstr(field->type, "u8") ||
strstr(field->type, "s8")))
return 1;
return 0;
}Do you want to get rid of u8 from the function? Or is there a better way?
Thanks,
Namhyung
Quoted 30 lines · Namhyung Kim
Quoted 10 lines · Steven Rostedt
We can be a bit better at the raw print, sure. Here's the format that's there:
field:__u64 rip; offset:16; size:8; signed:0; field:__u32 csbase; offset:24; size:4; signed:0; field:__u8 len; offset:28; size:1; signed:0; field:__u8 insn[15]; offset:29; size:15; signed:0; field:__u8 flags; offset:44; size:1; signed:0; field:__u8 failed; offset:45; size:1; signed:0;Quoted 6 lines
It treated __u* as decimal numbers, but it also saw that insn[15] was an array, and with single bytes at that. So it thought it was a string, and tried to print it out as such.
We can change the heuristics of this to make it more readable.
Right. The current heuristic treats an u8 array as a string:
static int
field_is_string(struct format_field *field){ if ((field->flags & FIELD_IS_ARRAY) && (strstr(field->type, "char") || strstr(field->type, "u8") || strstr(field->type, "s8"))) return 1; return 0; }
Quoted 3 lines
Do you want to get rid of u8 from the function? Or is there a better way?
We could simply check if all the characters in the array passes 'isprint()' and if it does then print the string, otherwise print the hex. Do this for all events, and if it one fails, then mark it always to print hex.
-- Steve
Namhyung Kim
maintainerQuoted 5 lines · Steven Rostedt
We could simply check if all the characters in the array passes '
isprint()' and if it does then print the string, otherwise print the hex. Do this for all events, and if it one fails, then mark it always to print hex.
Ok, checking it at parse time is not possible because we cannot access to its data. You meant something like this?
tools/lib/traceevent/event-parse.c +13 -1
@@ -3655,6 +3655,16 @@ static void print_mac_arg(struct trace_seq *s, int mac, void *data, int size,trace_seq_printf (s, fmt, buf[0 ], buf[1 ], buf[2 ], buf[3 ], buf[4 ], buf[5 ]); } +static int is_printable_array (char *p,unsigned int len) +{ +unsigned int i; + +for (i =0 ; i < len && p[i]; i++) +if (!isprint (p[i])) +return 0 ; +return 1 ; +} +static void print_event_fields (struct trace_seq *s,void *data,int size,struct event_format *event) {
@@ -3674,7 +3684,8 @@ static void print_event_fields(struct trace_seq *s, void *data, int size, len = offset >>16 ; offset &=0xffff ; } -if (field->flags &FIELD_IS_STRING ) { +if ((field->flags &FIELD_IS_STRING ) && +is_printable_array (data + offset, len)) {trace_seq_printf (s,"%s" , (char *)data + offset); }else {trace_seq_puts (s,"ARRAY[" );
@@ -3685,6 +3696,7 @@ static void print_event_fields(struct trace_seq *s, void *data, int size, *((unsigned char *)data + offset + i)); }trace_seq_putc (s,']' ); + field->flags &= ~FIELD_IS_STRING ; } }else { val = pevent_read_number(event->pevent, data + field->offset,
Quoted 10 lines · Namhyung Kim
Quoted 5 lines · Steven Rostedt
We could simply check if all the characters in the array passes '
isprint()' and if it does then print the string, otherwise print the hex. Do this for all events, and if it one fails, then mark it always to print hex.Ok, checking it at parse time is not possible because we cannot access to its data. You meant something like this?
Exactly!
-- Steve
Quoted 6 lines · Namhyung Kim
Quoted 3 lines
kvm tracepoints are fine; perf just doesn't handle their (advanced) formatting.
Yeah, I think it's a libtraceevent's issue, not perf's. Please see below:
Well documented problem (search perf kvm bad op token.
In April 2011 (pre first libparseevent patch) I mentioned a desire/wish/dream for perf to be able to use trace-cmd's plugins to fix this:
http://lkml.indiana.edu/hypermail/linux/kernel/1104.1/00411.html
Maybe this dream can come true... ;-)
David