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");