Re: [PATCH 3/3] elf2dmp: fill ContextBuffer with faulting CPU context
Akihiko Odaki <[email protected]> Wed, 5 Aug 2026 15:31:19 +0900
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
On 2026/07/22 10:48, 李峥嵘(村叔) wrote: > 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) { version > 1 does not prove byte 440 exists. init_states() in contrib/elf2dmp/qemu_elf.c accepts shorter descriptors and then discards their validated size, so a truncated version-2 note can read beyond its descriptor. Please check what's done for kernel_gs_base. > + memcpy(hdr->ContextBuffer, &ctx, sizeof(ctx)); > + } ContextBuffer is populated only after PRCB lookup, ContextFrame lookup, and guest-memory patching all succeed. Partial dumps therefore lose the header context even though the QEMU note already contains the faulting CPU registers. Please select the header context before those best-effort operations. > } > } > > @@ -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; patch_bugcheck_data() in dump/win_dump-x86.c fills BugcheckCode with LIVE_SYSTEM_DUMP when BugcheckCode is zero. Perhaps we may do the same here too. > + 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:" Let's use PRIx32. Regards, Akihiko Odaki > + " 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");