When is_crash_occurred_cpu is set in QEMUCPUState (version > 1), copy that CPU's context into WinDumpHeader64 ContextBuffer so WinDbg opens on the faulting CPU instead of CPU 0.
Also extract KiBugCheckData from the guest kernel to populate BugcheckCode and BugcheckParameters in the dump header. Signed-off-by: Zhengrong Li <[email protected]> --- contrib/elf2dmp/kdbg.h | 9 +++++++++ contrib/elf2dmp/main.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/contrib/elf2dmp/kdbg.h b/contrib/elf2dmp/kdbg.h index 002e3d0cd5..15e4fb1140 100644 --- a/contrib/elf2dmp/kdbg.h +++ b/contrib/elf2dmp/kdbg.h @@ -195,4 +195,13 @@ typedef struct KDDEBUGGER_DATA64 { uint16_t OffsetPrcbContext; } KDDEBUGGER_DATA64; +typedef struct KIBUGCHECK_INFO { + uint32_t BugcheckCode; + uint32_t unused0; + uint64_t BugcheckParameter1; + uint64_t BugcheckParameter2; + uint64_t BugcheckParameter3; + uint64_t BugcheckParameter4; +} KIBUGCHECK_INFO; + #endif /* KDBG_H */ diff --git a/contrib/elf2dmp/main.c b/contrib/elf2dmp/main.c index a62abadcc0..302601065b 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -338,7 +338,7 @@ static bool fill_header(WinDumpHeader64 *hdr, struct pa_space *ps, * A dump may still contain valuable information even if it lacks contexts of * some CPUs due to dump corruption or a failure before starting CPUs. */ -static void fill_context(KDDEBUGGER_DATA64 *kdbg, +static void fill_context(WinDumpHeader64 *hdr, KDDEBUGGER_DATA64 *kdbg, struct va_space *vs, QEMU_Elf *qe) { int i; @@ -373,6 +373,10 @@ static void fill_context(KDDEBUGGER_DATA64 *kdbg, eprintf("Failed to fill CPU #%d context\n", i); continue; } + + if (s->version > 1 && s->is_crash_occurred_cpu) { + memcpy(hdr->ContextBuffer, &ctx, sizeof(ctx)); + } } } @@ -512,6 +516,7 @@ int main(int argc, char *argv[]) uint64_t KdVersionBlock; bool kernel_found = false; OMFSignatureRSDS rsds; + uint64_t KiBugCheckData; if (argc != 3) { eprintf("usage:\n\t%s elf_file dmp_file\n", argv[0]); @@ -611,7 +616,30 @@ int main(int argc, char *argv[]) goto out_kdbg; } - fill_context(kdbg, &vs, &qemu_elf); + if (!SYM_RESOLVE(KernBase, &pdb, KiBugCheckData)) { + eprintf("Failed to get KiBugCheckData.\n"); + } else { + KIBUGCHECK_INFO data = { 0 }; + if (va_space_rw(&vs, KiBugCheckData, &data, sizeof(data), 0)) { + header.BugcheckCode = data.BugcheckCode; + header.BugcheckParameter1 = data.BugcheckParameter1; + header.BugcheckParameter2 = data.BugcheckParameter2; + header.BugcheckParameter3 = data.BugcheckParameter3; + header.BugcheckParameter4 = data.BugcheckParameter4; + + printf("KiBugCheckData: 0x%016" PRIx64 + ", BugcheckCode: 0x%08x, Args:" + " 0x%016" PRIx64 " 0x%016" PRIx64 + " 0x%016" PRIx64 " 0x%016" PRIx64 "\n", + KiBugCheckData, header.BugcheckCode, + data.BugcheckParameter1, data.BugcheckParameter2, + data.BugcheckParameter3, data.BugcheckParameter4); + } else { + eprintf("Failed to va_space_rw KiBugCheckData.\n"); + } + } + + fill_context(&header, kdbg, &vs, &qemu_elf); if (!write_dump(&ps, &header, argv[2])) { eprintf("Failed to save dump\n"); -- 2.43.0
