Re: [PATCH 7/8] Windows gdb: Implement XState (Intel AVX) support

Hannes Domani <[email protected]> Thu, 30 Jul 2026 15:41:18 +0000 (UTC)
Newsgroups gmane.comp.gdb.patches
Message-ID <[email protected]>
 Am Donnerstag, 30. Juli 2026 um 10:20:53 MESZ hat Joos, Christina <christi=
[email protected]> Folgendes geschrieben:

> > -----Original Message-----
> > From: Hannes Domani <[email protected]>
> > Sent: Samstag, 18. Juli 2026 18:07
> > To: [email protected]; Schimpe, Christina
> > <[email protected]>
> > Subject: Re: [PATCH 7/8] Windows gdb: Implement XState (Intel AVX) supp=
ort
> >
> >=C2=A0 Am Freitag, 17. Juli 2026 um 21:06:16 MESZ hat Schimpe, Christina
> > <[email protected]> Folgendes geschrieben:
> >
> > > > -----Original Message-----
> > > > From: Hannes Domani <[email protected]>
> > > > Sent: Freitag, 17. Juli 2026 18:27
> > > > To: [email protected]; Schimpe, Christina
> > > > <[email protected]>
> > > > Subject: Re: [PATCH 7/8] Windows gdb: Implement XState (Intel AVX)
> > > > support
> > > >
> > > >=C2=A0 Am Freitag, 17. Juli 2026 um 17:26:14 MESZ hat Schimpe, Chris=
tina
> > > ><[email protected]> Folgendes geschrieben:
> > > >
> > > > > > -----Original Message-----
> > > > > > From: Hannes Domani <[email protected]>
> > > > > > Sent: Freitag, 17. Juli 2026 16:50
> > > > > > To: [email protected]; Schimpe, Christina
> > > > > > <[email protected]>
> > > > > > Subject: Re: [PATCH 7/8] Windows gdb: Implement XState (Intel
> > > > > > AVX) support
> > > > > >
> > > > > >=C2=A0 Am Freitag, 17. Juli 2026 um 16:16:31 MESZ hat Schimpe,
> > > > > >Christina <[email protected]> Folgendes geschrieben:
> > > > > >
> > > > > > > > -----Original Message-----
> > > > > > > > From: Hannes Domani <[email protected]>
> > > > > > > > Sent: Freitag, 17. Juli 2026 15:47
> > > > > > > > To: [email protected]; Schimpe, Christina
> > > > > > > > <[email protected]>
> > > > > > > > Subject: Re: [PATCH 7/8] Windows gdb: Implement XState
> > > > > > > > (Intel
> > > > > > > > AVX) support
> > > > > > > >
> > > > > > > >=C2=A0 Am Freitag, 17. Juli 2026 um 14:54:59 MESZ hat Schimp=
e,
> > > > > > > >Christina <[email protected]> Folgendes geschriebe=
n:
> > > > > > > >
> > > > > > > > > Hi Hannes,
> > > > > > > > >
> > > > > > > > > Thank you for working on this.
> > > > > > > > > It appears that this patch uses the same commit message
> > > > > > > > > header as patch #8. Is it intentional that these are sepa=
rate
> > commits?
> > > > > > > >
> > > > > > > > This one is the gdb part, and #8 is the gdbserver part, tha=
t
> > > > > > > > is stated in the title.
> > > > > > >
> > > > > > > Oups, I wonder how I came to that conclusion.=C2=A0 Sorry for=
 that.
> > > > > > >
> > > > > > > >
> > > > > > > > > In any case, IMO, commit messages should not have identic=
al
> > headers.
> > > > > > > > > Also, this patch seems big enough for a commit message
> > > > > > > > > which is not header only. :)
> > > > > > >
> > > > > > > This part still stands for the commit message. Since it's not
> > > > > > > only avx registers, I believe it makes sense to share more de=
tails here.
> > > > > >
> > > > > > Yes, I will do that.
> > > > > >
> > > > > >
> > > > > > > > > Do any AVX-* specific tests pass on Windows now? If so, i=
t
> > > > > > > > > would be helpful to mention that in the commit message as=
 well.
> > > > > > > >
> > > > > > > > I actually planned to add that info, but forgot.
> > > > > > > >
> > > > > > > > These tests then pass on Windows:
> > > > > > > > gdb.arch/i386-avx.exp
> > > > > > > > gdb.arch/i386-avx512.exp
> > > > > > >
> > > > > > > What's the state for SSE=C2=A0 (gdb.arch/i386-sse.exp) ?
> > > > > >
> > > > > > i386-sse.exp works since patch #1, it was only a compile issue
> > > > > > of the test itself.
> > > > > > I will mention this in the patch as well.
> > > > >
> > > > > Thanks.
> > > > >
> > > > > >
> > > > > > > I also saw you introduced some code for PKRU and the shadow
> > > > > > > stack
> > > > > > pointer.
> > > > > > > We have GDB tests for those registers, too:
> > > > > > > - gdb.arch/i386-pkru.exp
> > > > > > > - gdb.arch/amd64-shadow-stack*.exp
> > > > > >
> > > > > > For these I just added the equivalent code as is done on Linux,
> > > > > > without really knowing what they are for.
> > > > > >
> > > > > > i386-pkru.exp tells me:
> > > > > >
> > > > > > (gdb) print have_pkru()
> > > > > > $1 =3D 0
> > > > > > (gdb) PASS: gdb.arch/i386-pkru.exp: probe PKRU support
> > > > > > UNSUPPORTED: gdb.arch/i386-pkru.exp: processor does not support
> > > > > > protection key feature.
> > > > > >
> > > > > > Do only certain CPU's have this register?
> > > > >
> > > > > Most recent CPUs should have it. To be sure you can check if the
> > > > > corresponding bit is configured in xcr0.
> > > >
> > > > I thought that's what have_pkru() does, but I might be wrong about =
that.
> > >
> > > Yes, this should work for windows, too.
> > >
> > > > > I believe for windows this should be the mask returned by
> > > > get_xstate_features_mask.
> > > >
> > > > You probably mean GetEnabledXStateFeatures, but yes, it also tells
> > > > me my CPU doesn't support this.
> > > >
> > > >
> > > > > If your cpu does have it, I think you must look at the test in
> > > > > more detail to find out why it's unsupported. It might need some
> > > > > adaptions for
> > > > windows.
> > > > Google tells me only not all recent CPUs have this, is mine one of =
them?:
> > > > 11th Gen Intel(R) Core(TM) i7-11850H
> > >
> > > I would have expected this but cannot say for sure.=C2=A0 And I don't=
 know
> > > the state for Memory Protection Keys windows support.
> >
> > I have tested this now on another PC, one where have_pkru() returns 1, =
so this
> > CPU really should have PKRU.
> >
> > But GetEnabledXStateFeatures still does not return the PKRU bit, and I =
can find
> > no equivalent XSTATE_PKRU define in winnt.h, this makes me believe that
> > windows just doesn't support this feature.
> >
> > So I'm fine with removing that part.
> >
> >
> > > > > > And amd64-shadow-stack.exp:
> > > > > >
> > > > > > (gdb) print $pl3_ssp
> > > > > > $1 =3D (void *) 0x0
> > > > > > (gdb) FAIL: gdb.arch/amd64-shadow-stack.exp: test shadow stack
> > > > > > support
> > > > > >
> > > > > > No idea if that should work, since Windows is supplying data fo=
r
> > > > > > the $pl3_ssp register.
> > > > > >
> > > > > >
> > > > > > Hannes
> > > > >
> > > > > Without knowing any of the details in windows I believe adding
> > > > > full support for CET shadow stack might need some more changes. A=
t
> > > > > least for
> > > > linux, this was the case:
> > > > > https://inbox.sourceware.org/gdb-patches/20250821171029.1555603-1=
-
> > > > > chri
> > > > > [email protected]/
> > > > >
> > > > > I believe it would be better to handle this in a separate patch-(=
series).
> > > > > This also applies for any other register that you add and whose
> > > > > dedicated
> > > > test does not pass.
> > > > >
> > > > > Does that make sense to you?
> > > >
> > > > I was wondering if it isn't the compiler or linker on windows (or
> > > > maybe windows itself?) that doesn't support this -fcf-protection=3D=
return stuff.
> > >
> > > I don't know the state for windows but would be curious about it. :-)
> > > At least for Kernel Mode, I could find some documentation for it.
> >
> > I did some more tests here as well.
> >
> > It turns out binutils/gcc really don't support this on windows yet.
> > To enable this in the executable, at least a special marker bit has to =
be set in the
> > Extended DLL Characteristics [1].
> > With msvc you can do that with the /CETCOMPAT linker argument [2].
> > So I compiled amd64-shadow-stack.c with msvc and /CETCOMPAT, and tried =
it
> > out with my gdb build.
> > Before I always got $pl3_ssp=3D0, and with this new exe I always get $p=
l3_ssp=3D1.
> >
> > So I had this wrong, because LocateXStateFeature returns for XSTATE_CET=
_U this
> > struct:
> >=C2=A0 =C2=A0 =C2=A0typedef struct _XSAVE_CET_U_FORMAT {
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0DWORD64 Ia32CetUMsr;
> >=C2=A0 =C2=A0 =C2=A0 =C2=A0DWORD64 Ia32Pl3SspMsr;
> >=C2=A0 =C2=A0 =C2=A0} XSAVE_CET_U_FORMAT, *PXSAVE_CET_U_FORMAT;
> >
> > So $pl3_ssp showed Ia32CetUMsr, when it should have shown Ia32Pl3SspMsr
> > instead.
> >
> > With that fixed, I tried again debugging the /CETCOMPAT executable:
>=C2=A0
> Ah ok, good to know.
>=C2=A0
> > (gdb) r
> > Starting program: C:\qiewer\git\amd64-shadow-stack.exe
> >
> > Breakpoint 1, 0x00007ff725812e41 in ?? ()
> > 1: $pl3_ssp =3D (void *) 0x4feff0
> > (gdb) x/1i $pc
> > =3D> 0x7ff725812e41:=C2=A0 =C2=A0 =C2=A0 jmp=C2=A0 =C2=A0 0x7ff72581768=
0
> > (gdb) x/4a $pl3_ssp
> > 0x4feff0:=C2=A0 =C2=A0 =C2=A0 =C2=A00x7ffd62fee957
> > <KERNEL32!BaseThreadInitThunk+23>=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x7ffd6364=
7c1c
> > <ntdll!RtlUserThreadStart+44>
> > 0x4ff000:=C2=A0 =C2=A0 =C2=A0 =C2=A0Cannot access memory at address 0x4=
ff000
> > (gdb) si
> > ...
> > (gdb) si
> > 0x00007ff725817684 in ?? ()
> > 1: $pl3_ssp =3D (void *) 0x4feff0
> > (gdb) x/1i $pc
> > =3D> 0x7ff725817684:=C2=A0 =C2=A0 =C2=A0 call=C2=A0 =C2=A00x7ff725812f1=
d
> > (gdb) si
> > 0x00007ff725812f1d in ?? ()
> > 1: $pl3_ssp =3D (void *) 0x4fefe8
> > (gdb) x/4a $pl3_ssp
> > 0x4fefe8:=C2=A0 =C2=A0 =C2=A0 =C2=A00x7ff725817689=C2=A0 0x7ffd62fee957
> > <KERNEL32!BaseThreadInitThunk+23>
> > 0x4feff8:=C2=A0 =C2=A0 =C2=A0 =C2=A00x7ffd63647c1c <ntdll!RtlUserThread=
Start+44>=C2=A0 =C2=A0 Cannot access
> > memory at address 0x4ff000
> > (gdb) x/1i $pc
> > =3D> 0x7ff725812f1d:=C2=A0 =C2=A0 =C2=A0 jmp=C2=A0 =C2=A0 0x7ff725817c3=
0
> > (gdb) si
> > ...
> > (gdb) si
> > 0x00007ff725817cde in ?? ()
> > 1: $pl3_ssp =3D (void *) 0x4fefe8
> > (gdb) x/1i $pc
> > =3D> 0x7ff725817cde:=C2=A0 =C2=A0 =C2=A0 ret
> > (gdb) si
> > 0x00007ff725817689 in ?? ()
> > 1: $pl3_ssp =3D (void *) 0x4feff0
> > (gdb) x/1i $pc
> > =3D> 0x7ff725817689:=C2=A0 =C2=A0 =C2=A0 add=C2=A0 =C2=A0 $0x28,%rsp
> > (gdb) x/4a $pl3_ssp
> > 0x4feff0:=C2=A0 =C2=A0 =C2=A0 =C2=A00x7ffd62fee957
> > <KERNEL32!BaseThreadInitThunk+23>=C2=A0 =C2=A0 =C2=A0 =C2=A0 0x7ffd6364=
7c1c
> > <ntdll!RtlUserThreadStart+44>
> > 0x4ff000:=C2=A0 =C2=A0 =C2=A0 =C2=A0Cannot access memory at address 0x4=
ff000
> > (gdb)
> >
> > call and ret modify the shadow stack which is pointed to by $pl3_ssp, i=
s that how
> > it's supposed to work?
>=C2=A0
> Yeah kind of, you can read it up here:
> https://inbox.sourceware.org/gdb-patches/20250821171029.1555603-9-christi=
[email protected]/
> https://inbox.sourceware.org/gdb-patches/20250821171029.1555603-10-christ=
[email protected]/
>=C2=A0
> > I'm unsure, because amd64-shadow-stack-cmds.exp makes it look like $pl3=
_ssp
> > should change when moving up or down the frames.
>=C2=A0
> This is also described in the commit message/gdb.texinfo docs.
> The corresponding test is amd64-shadow-stack-cmds.exp.

That's more or less working like I thought.
But why do we unwind $pl3_ssp when moving up the frames, couldn't it just
stay the same in all frames?


> > Is $pl3_ssp maybe supposed to provide Ia32Pl3SspMsr[$frame] instead?
> > How does that work on linux?
> >
> > In any case, I tried modifying $pl3_ssp like it is done in amd64-shadow=
-
> > stack.exp.
> >
> > (gdb) p $pl3_ssp
> > $10 =3D (void *) 0x4fefe8
> > (gdb) p $pl3_ssp=3D0x12345678
> > $11 =3D (void *) 0x12345678
> > (gdb) ni
> > error return C:/gdb/src/gdb.git/gdb/x86-windows-nat.c:242 was 1660: The=
 thread
> > context could not be updated because this has been restricted for the p=
rocess.
> > 0x00007ffd63720574 in ntdll!ZwMapViewOfSection () from
> > C:\WINDOWS\SYSTEM32\ntdll.dll
> >
> > So windows doesn't allow modifying the shadow stack pointer.
> > (gdb) p $pl3_ssp
> > $14 =3D (void *) 0x4fefe8
> > (gdb) p ((void**)$pl3_ssp)[0]
> > $15 =3D (void *) 0x7ff725817689
> > (gdb) p ((void**)$pl3_ssp)[0]=3D0x12345678 Cannot access memory at addr=
ess
> > 0x4fefe8
> >
> > And looks like modifying the shadow stack entries is also prohibited.
>=C2=A0
> If writing to shadow stack memory and pushing entries on the shadow stack
> does not work in windows,=C2=A0 displaced stepping, the return command, i=
nferior
> function calls and frame updates cannot be enabled for shadow stack enabl=
ed
> programs.
>=C2=A0
> In linux we have a ptrace call to read and write the shadow stack pointer=
:
> https://github.com/torvalds/linux/blob/11028ab62899e4191e074ee364c712b778=
23a9c4/tools/testing/selftests/x86/test_shadow_stack.c#L994

Yeah, it really looks like modifying the shadow stack isn't possible on win=
dows.
I just tried doing a function call in windbg:

0:000> .call call1()
Thread is set up for call, 'g' will execute.
WARNING: This can have serious side-effects,
including deadlocks and corruption of the debuggee.
0:000> g
(6854.108c): Security check failure or stack buffer overrun - code c0000409=
 (!!! second chance !!!)
Subcode: 0x39 FAST_FAIL_CONTROL_INVALID_RETURN_ADDRESS Shadow stack violati=
on
amd64_shadow_stack_cet!call1+0xd:

And only reading the ssp register is possible there:

0:000> r ssp
ssp=3D000000b5470fefe0
0:000> r ssp=3D000000b5470fefe1
Amd64MachineInfo::SetVal: unknown register 9c requested
=C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=
=A0 =C2=A0 =C2=A0 =C2=A0 ^ Bad register error in 'r ssp=3D000000b5470fefe1'


Hannes