diff options
Diffstat (limited to 'plugins/plugin_kvm.c')
-rw-r--r-- | plugins/plugin_kvm.c | 74 |
1 files changed, 69 insertions, 5 deletions
diff --git a/plugins/plugin_kvm.c b/plugins/plugin_kvm.c index 51ceeb9..9852c35 100644 --- a/plugins/plugin_kvm.c +++ b/plugins/plugin_kvm.c @@ -10,6 +10,8 @@ #include "event-parse.h" #include "trace-seq.h" +#define __weak __attribute__((weak)) + #ifdef HAVE_UDIS86 #include <udis86.h> @@ -273,15 +275,49 @@ static int print_exit_reason(struct trace_seq *s, struct tep_record *record, return 0; } +__weak const char *tep_plugin_kvm_get_func(struct tep_event *event, + struct tep_record *record, + unsigned long long *val) +{ + return NULL; +} + +__weak void tep_plugin_kvm_put_func(const char *func) +{ +} + + +static void add_rip_function(struct trace_seq *s, struct tep_record *record, + struct tep_event *event, unsigned long long rip) +{ + unsigned long long ip = rip; + const char *func; + + func = tep_plugin_kvm_get_func(event, record, &ip); + if (func) { + trace_seq_printf(s, " %s", func); + /* The application may upate ip to the start of the function */ + if (ip != rip) + trace_seq_printf(s, "+0x%0llx", rip - ip); + tep_plugin_kvm_put_func(func); + } +} + static int kvm_exit_handler(struct trace_seq *s, struct tep_record *record, struct tep_event *event, void *context) { unsigned long long info1 = 0, info2 = 0; + unsigned long long rip; if (print_exit_reason(s, record, event, "exit_reason") < 0) return -1; - tep_print_num_field(s, " rip 0x%lx", event, "guest_rip", record, 1); + if (tep_get_field_val(s, event, "guest_rip", record, &rip, 1) < 0) + return -1; + + trace_seq_printf(s, " rip 0x%llx", rip); + + add_rip_function(s, record, event, rip); if (tep_get_field_val(s, event, "info1", record, &info1, 0) >= 0 && tep_get_field_val(s, event, "info2", record, &info2, 0) >= 0) @@ -290,6 +326,22 @@ static int kvm_exit_handler(struct trace_seq *s, struct tep_record *record, return 0; } +static int kvm_entry_handler(struct trace_seq *s, struct tep_record *record, + struct tep_event *event, void *context) +{ + unsigned long long rip; + + tep_print_num_field(s, " vcpu %u", event, "vcpu_id", record, 1); + + if (tep_get_field_val(s, event, "rip", record, &rip, 1) < 0) + return -1; + + trace_seq_printf(s, " rip 0x%llx", rip); + add_rip_function(s, record, event, rip); + + return 0; +} + #define KVM_EMUL_INSN_F_CR0_PE (1 << 0) #define KVM_EMUL_INSN_F_EFL_VM (1 << 1) #define KVM_EMUL_INSN_F_CS_D (1 << 2) @@ -329,12 +381,12 @@ static int kvm_emulate_insn_handler(struct trace_seq *s, 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" : ""); + trace_seq_printf(s, "%llx:%llx", csbase, rip); + add_rip_function(s, record, event, rip); + trace_seq_printf(s, ": %s%s", disasm, failed ? " FAIL" : ""); return 0; } - static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct tep_record *record, struct tep_event *event, void *context) { @@ -352,7 +404,13 @@ static int kvm_nested_vmexit_inject_handler(struct trace_seq *s, struct tep_reco static int kvm_nested_vmexit_handler(struct trace_seq *s, struct tep_record *record, struct tep_event *event, void *context) { - tep_print_num_field(s, "rip %llx ", event, "rip", record, 1); + unsigned long long rip; + + if (tep_get_field_val(s, event, "rip", record, &rip, 1) < 0) + return -1; + + trace_seq_printf(s, " rip %llx", rip); + add_rip_function(s, record, event, rip); return kvm_nested_vmexit_inject_handler(s, record, event, context); } @@ -456,6 +514,9 @@ int TEP_PLUGIN_LOADER(struct tep_handle *tep) tep_register_event_handler(tep, -1, "kvm", "kvm_exit", kvm_exit_handler, NULL); + tep_register_event_handler(tep, -1, "kvm", "kvm_entry", + kvm_entry_handler, NULL); + tep_register_event_handler(tep, -1, "kvm", "kvm_emulate_insn", kvm_emulate_insn_handler, NULL); @@ -496,6 +557,9 @@ void TEP_PLUGIN_UNLOADER(struct tep_handle *tep) tep_unregister_event_handler(tep, -1, "kvm", "kvm_exit", kvm_exit_handler, NULL); + tep_unregister_event_handler(tep, -1, "kvm", "kvm_entry", + kvm_entry_handler, NULL); + tep_unregister_event_handler(tep, -1, "kvm", "kvm_emulate_insn", kvm_emulate_insn_handler, NULL); |