[PATCH v3 3/3] elf2dmp: fill ContextBuffer with faulting CPU context
Zhengrong Li <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
When is_crash_occurred_cpu is set in QEMUCPUState, copy that CPU's context into WinDumpHeader64 ContextBuffer so WinDbg opens on the faulting CPU instead of CPU 0. A per-CPU size check ensures the field is present before reading, supporting heterogeneous dumps. 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 | 50 ++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 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..e25709b45d 100644 --- a/contrib/elf2dmp/main.c +++ b/contrib/elf2dmp/main.c @@ -338,11 +338,26 @@ 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; + /* First pass: identify faulting CPU and set header context early */ + for (i = 0; i < qe->state_nr; i++) { + QEMUCPUState *s = qe->state[i]; + if (s->size >= offsetof(QEMUCPUState, is_crash_occurred_cpu) + + sizeof(s->is_crash_occurred_cpu) && + s->is_crash_occurred_cpu) { + WinContext64 ctx; + win_context_init_from_qemu_cpu_state(&ctx, s); + memcpy(hdr->ContextBuffer, &ctx, sizeof(ctx)); + printf("Faulting CPU identified: #%d\n", i); + break; + } + } + + /* Second pass: fill context for all CPUs (best-effort) */ for (i = 0; i < qe->state_nr; i++) { uint64_t Prcb; uint64_t Context; @@ -512,6 +527,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 +627,37 @@ 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; + + /* + * If BugcheckCode wasn't saved, we consider guest OS as alive. + */ + if (!header.BugcheckCode) { + header.BugcheckCode = LIVE_SYSTEM_DUMP; + } + + printf("KiBugCheckData: 0x%016" PRIx64 + ", BugcheckCode: 0x%08" PRIx32 ", 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