Re: [PATCH v3 3/3] elf2dmp: fill ContextBuffer with faulting CPU context
Akihiko Odaki <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
On 2026/08/06 15:20, Zhengrong Li wrote: > 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) { This trusts embedded s->size, while the validated MIN(s->size, n_descsz) at init_states() in contrib/elf2dmp/qemu_elf.c is discarded. A note claiming 448 bytes with a 440-byte descriptor reads the marker beyond that descriptor. Please preserve each note’s validated size. Regards, Akihiko Odaki > + 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");