Hi Dave, There is a bug on get_be_long() that causes high 32 bits truncated. As a result, we get wrong registers values from dump file. Patch 1 fixes this. Once we can get right cpu registers values, it's better to use the sp/ip for backtracing the active task. This can show a more accurate backtrace, not including those invalid frames beyond sp. pathes 2 and 3 do this on kvmdump case(virsh dump). To verify: run that km_probe.c test module on a x86_64 system, then `echo q > /proc/sysrq-trigger' to trigger the kprobe which does looping in post_handler. Then vrish dump then crash. -- Thanks, Hu Tao
diff --git a/qemu-load.c b/qemu-load.c index 998b6d4..95eaf97 100644 --- a/qemu-load.c +++ b/qemu-load.c @@ -408,7 +408,7 @@ cpu_common_init_load (struct qemu_device_list *dl, /* CPU loader. */ -static inline int +static inline uint64_t get_be_long (FILE *fp, int size) { uint32_t a = size == 32 ? 0 : get_be32 (fp);
diff --git a/qemu-load.h b/qemu-load.h index 578fedd..0d8db4e 100644 --- a/qemu-load.h +++ b/qemu-load.h @@ -140,6 +140,18 @@ struct qemu_x86_mce { uint64_t mce_banks[10 * 4]; }; +enum CPU_REG { + R_EAX, + R_ECX, + R_EDX, + R_EBX, + R_ESP, + R_EBP, + R_ESI, + R_EDI, + R_GP_MAX, +}; + struct qemu_device_x86 { struct qemu_device dev_base;
diff --git a/kernel.c b/kernel.c index e399099..2627020 100755 --- a/kernel.c +++ b/kernel.c @@ -16,6 +16,7 @@ */ #include "defs.h" +#include "qemu-load.h" #include "xen_hyper_defs.h" #include <elf.h> diff --git a/kvmdump.c b/kvmdump.c index 1bf0d9e..557d329 100644 --- a/kvmdump.c +++ b/kvmdump.c @@ -17,6 +17,7 @@ #include "defs.h" #include "kvmdump.h" +#include "qemu-load.h" static struct kvmdump_data kvmdump_data = { 0 }; struct kvmdump_data *kvm = &kvmdump_data; @@ -310,7 +311,11 @@ kvmdump_memory_dump(FILE *ofp) void get_kvmdump_regs(struct bt_info *bt, ulong *pc, ulong *sp) { - machdep->get_stack_frame(bt, pc, sp); + if (is_task_active(bt->task)) { + *sp = device_list->dx86->regs[R_ESP]; + *pc = device_list->dx86->eip; + } else + machdep->get_stack_frame(bt, pc, sp); } ulong diff --git a/main.c b/main.c index 925de2f..ecab83c 100755 --- a/main.c +++ b/main.c @@ -16,6 +16,7 @@ */ #include "defs.h" +#include "qemu-load.h" #include "xen_hyper_defs.h" #include <curses.h> #include <getopt.h> @@ -1445,6 +1446,8 @@ clean_exit(int status) if (pc->flags & MEMMOD) cleanup_memory_driver(); + device_list_free (device_list); + exit(status); } diff --git a/qemu-load.c b/qemu-load.c index 95eaf97..c807c49 100644 --- a/qemu-load.c +++ b/qemu-load.c @@ -18,6 +18,7 @@ */ #define _GNU_SOURCE +#include "defs.h" #include "qemu-load.h" #include <stdlib.h> #include <string.h> @@ -881,6 +882,7 @@ qemu_load (const struct qemu_device_loader *devices, uint32_t required_features, dprintf("\n"); result = calloc (1, sizeof (struct qemu_device_list)); + result->dx86 = NULL; for (;;) { struct qemu_device *d; uint32_t features; @@ -904,6 +906,9 @@ qemu_load (const struct qemu_device_loader *devices, uint32_t required_features, if (feof (fp) || ferror (fp)) break; + if (STREQ(d->vtbl->name, "cpu")) + result->dx86 = d; + if (sec == QEMU_VM_SECTION_END || sec == QEMU_VM_SECTION_FULL) result->features |= features; } @@ -924,7 +929,6 @@ fail: * crash utility adaptation. */ -#include "defs.h" int is_qemu_vm_file(char *filename) diff --git a/qemu-load.h b/qemu-load.h index 0d8db4e..3872899 100644 --- a/qemu-load.h +++ b/qemu-load.h @@ -40,6 +40,7 @@ enum qemu_features { struct qemu_device_list { struct qemu_device *head, *tail; + struct qemu_device_x86 *dx86; uint32_t features; }; @@ -232,4 +233,6 @@ extern const struct qemu_device_loader devices_x86_32[]; /* For a 64-bit KVM host. */ extern const struct qemu_device_loader devices_x86_64[]; +extern struct qemu_device_list *device_list; + #endif diff --git a/qemu.c b/qemu.c index 84b6f96..a355c4f 100644 --- a/qemu.c +++ b/qemu.c @@ -280,10 +280,11 @@ int main (int argc, char **argv) #include "defs.h" +struct qemu_device_list *device_list = NULL; + int qemu_init(char *filename) { - struct qemu_device_list *dl; struct qemu_device_ram *dram; uint64_t idt = 0; @@ -298,24 +299,24 @@ qemu_init(char *filename) please_wait("scanning KVM dumpfile"); if (machine_type("X86")) - dl = qemu_load(devices_x86_32, + device_list = qemu_load(devices_x86_32, QEMU_FEATURE_CPU|QEMU_FEATURE_RAM, kvm->vmp); else if (machine_type("X86_64")) - dl = qemu_load(devices_x86_64, + device_list = qemu_load(devices_x86_64, QEMU_FEATURE_CPU|QEMU_FEATURE_RAM, kvm->vmp); else - dl = NULL; + device_list = NULL; please_wait_done(); - if (dl) { + if (device_list) { if (machine_type("X86_64")) { - idt = get_idt_base(dl); - kvm->mapinfo.phys_base = get_kernel_base(dl); + idt = get_idt_base(device_list); + kvm->mapinfo.phys_base = get_kernel_base(device_list); } dram = (struct qemu_device_ram *) - device_find_instance (dl, "ram", 0); + device_find_instance (device_list, "ram", 0); if (CRASHDEBUG(1)) { if (machine_type("X86_64")) { @@ -327,10 +328,8 @@ qemu_init(char *filename) fprintf(kvm->ofp, "last RAM offset: %llx\n", (ulonglong)dram->last_ram_offset); } - - device_list_free (dl); } else fclose(kvm->vmp); - return dl ? TRUE : FALSE; + return device_list ? TRUE : FALSE; }
-- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility