[Crash-utility] [PATCH] bug on get_be_long() and improvement of bt
Hu Tao
hutao at cn.fujitsu.com
Mon Oct 18 07:22:57 UTC 2010
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
-------------- next part --------------
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);
-------------- next part --------------
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;
-------------- next part --------------
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;
}
More information about the Crash-utility
mailing list