Re: [PATCH v2 7/8] Windows gdb: Implement XState (Intel AVX) support
Hannes Domani <[email protected]>
| Newsgroups | gmane.comp.gdb.patches |
|---|---|
| Message-ID | <[email protected]> |
Ping for this series. Am Montag, 27. Juli 2026 um 19:47:52 MESZ hat Hannes Domani <[email protected]> Folgendes geschrieben: > This adds support for the Intel AVX and AVX-512 registers on Windows. > It enables accessing registers $ymm0 - $ymm31, $zmm0 - $zmm31, and > $k0 - $k7 where they are available. > > It also enables reading the shadow stack pointer register $pl3_ssp (for > executables marked compatible with CET shadow stack [1]), but modifying > it seems to be restricted restricted by windows. > > After this patch the tests gdb.arch/i386-avx.exp and gdb.arch/i386-avx512.exp > pass on windows. > > [1] https://learn.microsoft.com/en-us/cpp/build/reference/cetcompat > --- > v2: > - Extended commit message and NEWS entry > - Remove PKRU support > - Fixed context offset of $pl3_ssp > --- > gdb/NEWS | 6 +++ > gdb/x86-windows-nat.c | 108 ++++++++++++++++++++++++++++++++++++++++-- > 2 files changed, 111 insertions(+), 3 deletions(-) > > diff --git a/gdb/NEWS b/gdb/NEWS > index 8f40ca5cb11..71ff5508d6d 100644 > --- a/gdb/NEWS > +++ b/gdb/NEWS > @@ -116,6 +116,12 @@ > intent to remove it in a future release. > The s390 64-bit target (s390x-*) remains supported. > > +* Support for Intel AVX registers on Windows. > + Support displaying and modifying Intel AVX registers $ymm0 - $ymm31. > + Support displaying and modifying Intel AVX-512 registers $zmm0 - $zmm31 > + and $k0 - $k7. > + Support displaying the shadow stack pointer register $pl3_ssp. > + > * Configure changes > > ** --with-babeltrace has been removed. The babeltrace library was > diff --git a/gdb/x86-windows-nat.c b/gdb/x86-windows-nat.c > index 3af5ef4dae0..270f9eae8e7 100644 > --- a/gdb/x86-windows-nat.c > +++ b/gdb/x86-windows-nat.c > @@ -27,6 +27,9 @@ > > #include "i386-tdep.h" > #include "i387-tdep.h" > +#ifdef __x86_64__ > +#include "amd64-tdep.h" > +#endif > > using namespace windows_nat; > > @@ -70,6 +73,8 @@ struct x86_windows_nat_target final : public x86_nat_target<windows_nat_target> > windows_thread_info *th, int r) override; > > bool is_sw_breakpoint (const EXCEPTION_RECORD *er) const override; > + > + const struct target_desc *read_description () override; > }; > > /* The current process. */ > @@ -109,7 +114,31 @@ x86_windows_per_inferior::fill_thread_context (windows_thread_info *th) > if (context->ContextFlags == 0) > { > context->ContextFlags = WindowsContext<decltype(context)>::all; > + if (xstate_features != 0) > + { > + context->ContextFlags |= CONTEXT_XSTATE_FLAG; > + set_xstate_features_mask (context, xstate_features); > + } > CHECK (get_thread_context (th->h, context)); > + > + if (xstate_features != 0) > + { > + DWORD64 features = 0; > + CHECK (get_xstate_features_mask (context, &features)); > + DWORD64 zeroed_features = xstate_features & ~features; > + > + for (int f = X86_XSTATE_AVX_ID; f <= X86_XSTATE_CET_U_ID; f++) > + { > + DWORD64 flag = 1ULL << f; > + if ((zeroed_features & flag) != 0) > + { > + DWORD size = 0; > + void *loc = locate_xstate_feature (context, f, &size); > + if (loc != nullptr && size > 0) > + memset (loc, 0, size); > + } > + } > + } > } > }); > } > @@ -198,6 +227,14 @@ x86_windows_nat_target::thread_context_continue (windows_thread_info *th, > if (GetExitCodeThread (th->h, &ec) > && ec == STILL_ACTIVE) > { > + DWORD debug_registers = WindowsContext<decltype(context)>::debug; > + if (xstate_features != 0 > + && (context->ContextFlags & ~debug_registers) != 0) > + { > + context->ContextFlags |= CONTEXT_XSTATE_FLAG; > + set_xstate_features_mask (context, xstate_features); > + } > + > BOOL status = set_thread_context (th->h, context); > > if (!killed) > @@ -227,7 +264,7 @@ x86_windows_nat_target::thread_context_step (windows_thread_info *th, > > template<typename Context> > static char * > -get_context_reg_ptr (Context *context, int r) > +get_context_reg_ptr (Context *context, int r, i386_gdbarch_tdep *tdep) > { > const int *mappings; > int mappings_count; > @@ -247,6 +284,54 @@ get_context_reg_ptr (Context *context, int r) > char *context_offset; > if (r < mappings_count) > context_offset = (char *) context + mappings[r]; > + else if (I387_ZMM0H_REGNUM (tdep) > 0 && r >= I387_ZMM0H_REGNUM (tdep) > + && r < I387_ZMM16H_REGNUM (tdep) && r < I387_ZMMENDH_REGNUM (tdep)) > + { > + context_offset = (char *) locate_xstate_feature > + (context, X86_XSTATE_ZMM_H_ID, NULL); > + context_offset += 32 * (r - I387_ZMM0H_REGNUM (tdep)); > + } > + else if (I387_ZMM0H_REGNUM (tdep) > 0 && r >= I387_ZMM16H_REGNUM (tdep) > + && r < I387_ZMMENDH_REGNUM (tdep)) > + { > + context_offset = (char *) locate_xstate_feature > + (context, X86_XSTATE_ZMM_ID, NULL); > + context_offset += 32 + 64 * (r - I387_ZMM16H_REGNUM (tdep)); > + } > + else if (I387_K0_REGNUM (tdep) > 0 && r >= I387_K0_REGNUM (tdep) > + && r < I387_KEND_REGNUM (tdep)) > + { > + context_offset = (char *) locate_xstate_feature > + (context, X86_XSTATE_K_ID, NULL); > + context_offset += 8 * (r - I387_K0_REGNUM (tdep)); > + } > + else if (I387_YMM16H_REGNUM (tdep) > 0 && r >= I387_YMM16H_REGNUM (tdep) > + && r < I387_YMMH_AVX512_END_REGNUM (tdep)) > + { > + context_offset = (char *) locate_xstate_feature > + (context, X86_XSTATE_ZMM_ID, NULL); > + context_offset += 16 + 64 * (r - I387_YMM16H_REGNUM (tdep)); > + } > + else if (I387_XMM16_REGNUM (tdep) > 0 && r >= I387_XMM16_REGNUM (tdep) > + && r < I387_XMM_AVX512_END_REGNUM (tdep)) > + { > + context_offset = (char *) locate_xstate_feature > + (context, X86_XSTATE_ZMM_ID, NULL); > + context_offset += 64 * (r - I387_XMM16_REGNUM (tdep)); > + } > + else if (I387_YMM0H_REGNUM (tdep) > 0 && r >= I387_YMM0H_REGNUM (tdep) > + && r < I387_YMMENDH_REGNUM (tdep)) > + { > + context_offset = (char *) locate_xstate_feature > + (context, X86_XSTATE_AVX_ID, NULL); > + context_offset += 16 * (r - I387_YMM0H_REGNUM (tdep)); > + } > + else if (tdep->ssp_regnum > 0 && r == tdep->ssp_regnum) > + { > + context_offset = (char *) locate_xstate_feature > + (context, X86_XSTATE_CET_U_ID, NULL); > + context_offset += 8; > + } > else > gdb_assert_not_reached ("invalid register number %d", r); > > @@ -267,7 +352,7 @@ x86_windows_nat_target::fetch_one_register (struct regcache *regcache, > char *context_offset > = x86_windows_process.with_context (th, [&] (auto *context) > { > - return get_context_reg_ptr (context, r); > + return get_context_reg_ptr (context, r, tdep); > }); > > gdb_assert (!gdbarch_read_pc_p (gdbarch)); > @@ -333,7 +418,7 @@ x86_windows_nat_target::store_one_register (const struct regcache *regcache, > = x86_windows_process.with_context (th, [&] (auto *context) > { > gdb_assert (context->ContextFlags != 0); > - return get_context_reg_ptr (context, r); > + return get_context_reg_ptr (context, r, tdep); > }); > > /* GDB treats some registers as 32-bit, where they are in fact only > @@ -368,6 +453,23 @@ x86_windows_nat_target::is_sw_breakpoint (const EXCEPTION_RECORD *er) const > || er->ExceptionCode == STATUS_WX86_BREAKPOINT); > } > > +const struct target_desc * > +x86_windows_nat_target::read_description () > +{ > + if (inferior_ptid == null_ptid) > + return this->beneath ()->read_description (); > + > + if (xstate_features == 0) > + return nullptr; > + > +#ifdef __x86_64__ > + if (!x86_windows_process.wow64_process) > + return amd64_target_description (xstate_features, false); > + else > +#endif > + return i386_target_description (xstate_features, false); > +} > + > /* Hardware watchpoint support, adapted from go32-nat.c code. */ > > /* Pass the address ADDR to the inferior in the I'th debug register. > -- > 2.54.0