[RFC,16/34] hurd: Add sys/ucontext.h and sigcontext.h for x86_64
Checks
Commit Message
This is based on the Linux port's version, but laid out to match Mach's
struct i386_thread_state, much like the i386 version does.
Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
---
I'm not very sure about the FP stuff, nor about any of this, really. Please
do review.
sysdeps/mach/hurd/x86_64/bits/sigcontext.h | 131 +++++++++++++++++
sysdeps/mach/hurd/x86_64/sys/ucontext.h | 157 +++++++++++++++++++++
sysdeps/mach/hurd/x86_64/ucontext_i.sym | 38 +++++
3 files changed, 326 insertions(+)
create mode 100644 sysdeps/mach/hurd/x86_64/bits/sigcontext.h
create mode 100644 sysdeps/mach/hurd/x86_64/sys/ucontext.h
create mode 100644 sysdeps/mach/hurd/x86_64/ucontext_i.sym
Comments
Hello,
Applied, thanks!
Note that I have pushed sysdeps/mach/hurd/x86_64/sys/ucontext.h to
sysdeps/x86_64/sys/ucontext.h since it's not mach-specific, and Linux
has its own for x86.
Samuel
Sergey Bugaev, le dim. 19 mars 2023 18:09:59 +0300, a ecrit:
> This is based on the Linux port's version, but laid out to match Mach's
> struct i386_thread_state, much like the i386 version does.
>
> Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
> ---
>
> I'm not very sure about the FP stuff, nor about any of this, really. Please
> do review.
>
> sysdeps/mach/hurd/x86_64/bits/sigcontext.h | 131 +++++++++++++++++
> sysdeps/mach/hurd/x86_64/sys/ucontext.h | 157 +++++++++++++++++++++
> sysdeps/mach/hurd/x86_64/ucontext_i.sym | 38 +++++
> 3 files changed, 326 insertions(+)
> create mode 100644 sysdeps/mach/hurd/x86_64/bits/sigcontext.h
> create mode 100644 sysdeps/mach/hurd/x86_64/sys/ucontext.h
> create mode 100644 sysdeps/mach/hurd/x86_64/ucontext_i.sym
>
> diff --git a/sysdeps/mach/hurd/x86_64/bits/sigcontext.h b/sysdeps/mach/hurd/x86_64/bits/sigcontext.h
> new file mode 100644
> index 00000000..3a3b34bc
> --- /dev/null
> +++ b/sysdeps/mach/hurd/x86_64/bits/sigcontext.h
> @@ -0,0 +1,131 @@
> +/* Machine-dependent signal context structure for GNU Hurd. x86_64 version.
> + Copyright (C) 1991-2023 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _BITS_SIGCONTEXT_H
> +#define _BITS_SIGCONTEXT_H 1
> +
> +#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H
> +# error "Never use <bits/sigcontext.h> directly; include <signal.h> instead."
> +#endif
> +
> +/* Signal handlers are actually called:
> + void handler (int sig, int code, struct sigcontext *scp); */
> +
> +#include <bits/types/__sigset_t.h>
> +#include <mach/machine/fp_reg.h>
> +
> +/* State of this thread when the signal was taken. */
> +struct sigcontext
> + {
> + /* These first members are machine-independent. */
> +
> + int sc_onstack; /* Nonzero if running on sigstack. */
> + __sigset_t sc_mask; /* Blocked signals to restore. */
> +
> + /* MiG reply port this thread is using. */
> + unsigned int sc_reply_port;
> +
> + /* Port this thread is doing an interruptible RPC on. */
> + unsigned int sc_intr_port;
> +
> + /* Error code associated with this signal (interpreted as `error_t'). */
> + int sc_error;
> +
> + /* All following members are machine-dependent. The rest of this
> + structure is written to be laid out identically to:
> + {
> + struct i386_thread_state basic;
> + struct i386_float_state fpu;
> + }
> + trampoline.c knows this, so it must be changed if this changes. */
> +
> +#define sc_i386_thread_state sc_gs /* Beginning of correspondence. */
> + /* Segment registers. */
> + int sc_gs;
> + int sc_fs;
> + int sc_es;
> + int sc_ds;
> +
> + long sc_r8;
> + long sc_r9;
> + long sc_r10;
> + long sc_r11;
> + long sc_r12;
> + long sc_r13;
> + long sc_r14;
> + long sc_r15;
> + long sc_rdi;
> + long sc_rsi;
> + long sc_rbp;
> + long sc_rsp; /* Not used; sc_ursp is used instead. */
> + long sc_rbx;
> + long sc_rdx;
> + long sc_rcx;
> + long sc_rax;
> + long sc_rip; /* Instruction pointer. */
> +
> + int sc_cs; /* Code segment register. */
> +
> + long sc_rfl; /* Processor flags. */
> +
> + long sc_ursp; /* This stack pointer is used. */
> + int sc_ss; /* Stack segment register. */
> +
> + /* Following mimics struct i386_float_state. Structures and symbolic
> + values can be found in <mach/i386/fp_reg.h>. */
> +#define sc_i386_float_state sc_fpkind
> + int sc_fpkind; /* FP_NO, FP_387, etc. */
> + int sc_fpused; /* If zero, ignore rest of float state. */
> + struct i386_fp_save sc_fpsave;
> + struct i386_fp_regs sc_fpregs;
> + int sc_fpexcsr; /* FPSR including exception bits. */
> + };
> +
> +/* Traditional BSD names for some members. */
> +#define sc_sp sc_ursp /* Stack pointer. */
> +#define sc_fp sc_rbp /* Frame pointer. */
> +#define sc_pc sc_rip /* Process counter. */
> +#define sc_ps sc_rfl
> +
> +
> +/* The deprecated sigcode values below are passed as an extra, non-portable
> + argument to regular signal handlers. You should use SA_SIGINFO handlers
> + instead, which use the standard POSIX signal codes. */
> +
> +/* Codes for SIGFPE. */
> +#define FPE_INTOVF_TRAP 0x1 /* integer overflow */
> +#define FPE_INTDIV_FAULT 0x2 /* integer divide by zero */
> +#define FPE_FLTOVF_FAULT 0x3 /* floating overflow */
> +#define FPE_FLTDIV_FAULT 0x4 /* floating divide by zero */
> +#define FPE_FLTUND_FAULT 0x5 /* floating underflow */
> +#define FPE_SUBRNG_FAULT 0x7 /* BOUNDS instruction failed */
> +#define FPE_FLTDNR_FAULT 0x8 /* denormalized operand */
> +#define FPE_FLTINX_FAULT 0x9 /* floating loss of precision */
> +#define FPE_EMERR_FAULT 0xa /* mysterious emulation error 33 */
> +#define FPE_EMBND_FAULT 0xb /* emulation BOUNDS instruction failed */
> +
> +/* Codes for SIGILL. */
> +#define ILL_INVOPR_FAULT 0x1 /* invalid operation */
> +#define ILL_STACK_FAULT 0x2 /* fault on microkernel stack access */
> +#define ILL_FPEOPR_FAULT 0x3 /* invalid floating operation */
> +
> +/* Codes for SIGTRAP. */
> +#define DBG_SINGLE_TRAP 0x1 /* single step */
> +#define DBG_BRKPNT_FAULT 0x2 /* breakpoint instruction */
> +
> +#endif /* bits/sigcontext.h */
> diff --git a/sysdeps/mach/hurd/x86_64/sys/ucontext.h b/sysdeps/mach/hurd/x86_64/sys/ucontext.h
> new file mode 100644
> index 00000000..d73a8937
> --- /dev/null
> +++ b/sysdeps/mach/hurd/x86_64/sys/ucontext.h
> @@ -0,0 +1,157 @@
> +/* Copyright (C) 2001-2023 Free Software Foundation, Inc.
> + This file is part of the GNU C Library.
> +
> + The GNU C Library is free software; you can redistribute it and/or
> + modify it under the terms of the GNU Lesser General Public
> + License as published by the Free Software Foundation; either
> + version 2.1 of the License, or (at your option) any later version.
> +
> + The GNU C Library is distributed in the hope that it will be useful,
> + but WITHOUT ANY WARRANTY; without even the implied warranty of
> + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
> + Lesser General Public License for more details.
> +
> + You should have received a copy of the GNU Lesser General Public
> + License along with the GNU C Library; if not, see
> + <https://www.gnu.org/licenses/>. */
> +
> +#ifndef _SYS_UCONTEXT_H
> +#define _SYS_UCONTEXT_H 1
> +
> +#include <features.h>
> +
> +#include <bits/types.h>
> +#include <bits/types/sigset_t.h>
> +#include <bits/types/stack_t.h>
> +
> +
> +#ifdef __USE_MISC
> +# define __ctx(fld) fld
> +#else
> +# define __ctx(fld) __ ## fld
> +#endif
> +
> +/* Type for general register. */
> +__extension__ typedef long long int greg_t;
> +
> +/* Number of general registers. */
> +#define __NGREG 23
> +#ifdef __USE_MISC
> +# define NGREG __NGREG
> +#endif
> +
> +/* Container for all general registers. */
> +typedef greg_t gregset_t[__NGREG];
> +
> +#ifdef __USE_GNU
> +/* Number of each register in the `gregset_t' array. */
> +enum
> +{
> + REG_GSFS = 0, /* Actually int gs, fs. */
> +# define REG_GSFS REG_GSFS
> + REG_ESDS, /* Actually int es, ds. */
> +# define REG_ESDS REG_ESDS
> + REG_R8,
> +# define REG_R8 REG_R8
> + REG_R9,
> +# define REG_R9 REG_R9
> + REG_R10,
> +# define REG_R10 REG_R10
> + REG_R11,
> +# define REG_R11 REG_R11
> + REG_R12,
> +# define REG_R12 REG_R12
> + REG_R13,
> +# define REG_R13 REG_R13
> + REG_R14,
> +# define REG_R14 REG_R14
> + REG_R15,
> +# define REG_R15 REG_R15
> + REG_RDI,
> +# define REG_RDI REG_RDI
> + REG_RSI,
> +# define REG_RSI REG_RSI
> + REG_RBP,
> +# define REG_RBP REG_RBP
> + REG_RSP,
> +# define REG_RSP REG_RSP
> + REG_RBX,
> +# define REG_RBX REG_RBX
> + REG_RDX,
> +# define REG_RDX REG_RDX
> + REG_RCX,
> +# define REG_RCX REG_RCX
> + REG_RAX,
> +# define REG_RAX REG_RAX
> + REG_RIP,
> +# define REG_RIP REG_RIP
> + REG_CS, /* Actually int cs, pad. */
> +# define REG_CS REG_CS
> + REG_RFL,
> +# define REG_RFL REG_RFL
> + REG_ERR,
> +# define REG_ERR REG_ERR
> + REG_TRAPNO,
> +# define REG_TRAPNO REG_TRAPNO
> + REG_OLDMASK,
> +# define REG_OLDMASK REG_OLDMASK
> + REG_CR2
> +# define REG_CR2 REG_CR2
> +};
> +#endif
> +
> +struct _libc_fpxreg
> +{
> + unsigned short int __ctx(significand)[4];
> + unsigned short int __ctx(exponent);
> + unsigned short int __glibc_reserved1[3];
> +};
> +
> +struct _libc_xmmreg
> +{
> + __uint32_t __ctx(element)[4];
> +};
> +
> +struct _libc_fpstate
> +{
> + /* 64-bit FXSAVE format. */
> + __uint16_t __ctx(cwd);
> + __uint16_t __ctx(swd);
> + __uint16_t __ctx(ftw);
> + __uint16_t __ctx(fop);
> + __uint64_t __ctx(rip);
> + __uint64_t __ctx(rdp);
> + __uint32_t __ctx(mxcsr);
> + __uint32_t __ctx(mxcr_mask);
> + struct _libc_fpxreg _st[8];
> + struct _libc_xmmreg _xmm[16];
> + __uint32_t __glibc_reserved1[24];
> +};
> +
> +/* Structure to describe FPU registers. */
> +typedef struct _libc_fpstate *fpregset_t;
> +
> +/* Context to describe whole processor state. */
> +typedef struct
> + {
> + gregset_t __ctx(gregs);
> + /* Note that fpregs is a pointer. */
> + fpregset_t __ctx(fpregs);
> + __extension__ unsigned long long __reserved1 [8];
> +} mcontext_t;
> +
> +/* Userlevel context. */
> +typedef struct ucontext_t
> + {
> + unsigned long int __ctx(uc_flags);
> + struct ucontext_t *uc_link;
> + stack_t uc_stack;
> + mcontext_t uc_mcontext;
> + sigset_t uc_sigmask;
> + struct _libc_fpstate __fpregs_mem;
> + __extension__ unsigned long long int __ssp[4];
> + } ucontext_t;
> +
> +#undef __ctx
> +
> +#endif /* sys/ucontext.h */
> diff --git a/sysdeps/mach/hurd/x86_64/ucontext_i.sym b/sysdeps/mach/hurd/x86_64/ucontext_i.sym
> new file mode 100644
> index 00000000..7e536956
> --- /dev/null
> +++ b/sysdeps/mach/hurd/x86_64/ucontext_i.sym
> @@ -0,0 +1,38 @@
> +#include <stddef.h>
> +#include <signal.h>
> +#include <sys/ucontext.h>
> +
> +--
> +
> +SIG_BLOCK
> +SIG_SETMASK
> +
> +_NSIG8 (_NSIG / 8)
> +
> +#define ucontext(member) offsetof (ucontext_t, member)
> +#define mcontext(member) ucontext (uc_mcontext.member)
> +#define mreg(reg) mcontext (gregs[REG_##reg])
> +
> +oRBP mreg (RBP)
> +oRSP mreg (RSP)
> +oRBX mreg (RBX)
> +oR8 mreg (R8)
> +oR9 mreg (R9)
> +oR10 mreg (R10)
> +oR11 mreg (R11)
> +oR12 mreg (R12)
> +oR13 mreg (R13)
> +oR14 mreg (R14)
> +oR15 mreg (R15)
> +oRDI mreg (RDI)
> +oRSI mreg (RSI)
> +oRDX mreg (RDX)
> +oRAX mreg (RAX)
> +oRCX mreg (RCX)
> +oRIP mreg (RIP)
> +oRFL mreg (RFL)
> +oFPREGS mcontext (fpregs)
> +oSIGMASK ucontext (uc_sigmask)
> +oFPREGSMEM ucontext (__fpregs_mem)
> +oMXCSR ucontext (__fpregs_mem.mxcsr)
> +oSSP ucontext (__ssp)
> --
> 2.39.2
>
Sergey Bugaev, le dim. 19 mars 2023 18:09:59 +0300, a ecrit:
> +#ifdef __USE_GNU
> +/* Number of each register in the `gregset_t' array. */
> +enum
> +{
> + REG_GSFS = 0, /* Actually int gs, fs. */
> +# define REG_GSFS REG_GSFS
> + REG_ESDS, /* Actually int es, ds. */
> +# define REG_ESDS REG_ESDS
On second thought, why REG_ESDS? They are basically useless on amd64
Linux packs all segment registers in REG_CSGSFS, probably better to
stuff them the same way? (all three really are 16bit only, even if the
thread_state is padding them to 32bits).
Samuel
On Mon, Apr 10, 2023, 21:39 Samuel Thibault <samuel.thibault@gnu.org> wrote:
>
> Hello,
>
> Applied, thanks!
Yay! Thank you for finding the time to review some more patches!
Here's to hoping that the rest will follow.
> Note that I have pushed sysdeps/mach/hurd/x86_64/sys/ucontext.h to
> sysdeps/x86_64/sys/ucontext.h since it's not mach-specific, and Linux
> has its own for x86.
It's not technically Mach specific, but it's arranged the same way as
Mach's struct i386_thread_state, and code in hurdsig.c relies on this.
If, say, Flavio would have arranged registers differently in gnumach
commit feba9b7b1d88e505feb6579e41dc45e48c264e6f — say, put rdi & rsi
before the r{8..15} gang, like it's done in the 32-bit version — then
ucontext definitions would also have to be different. So while it
could work for any port (provided it doesn't care about the ordering),
putting it into the generic tree underemphasizes why it has to be
arranged this specifically.
But it's up to you, of course.
Sergey
On Mon, Apr 10, 2023 at 9:58 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
>
> Sergey Bugaev, le dim. 19 mars 2023 18:09:59 +0300, a ecrit:
> > +#ifdef __USE_GNU
> > +/* Number of each register in the `gregset_t' array. */
> > +enum
> > +{
> > + REG_GSFS = 0, /* Actually int gs, fs. */
> > +# define REG_GSFS REG_GSFS
> > + REG_ESDS, /* Actually int es, ds. */
> > +# define REG_ESDS REG_ESDS
>
> On second thought, why REG_ESDS? They are basically useless on amd64
>
> Linux packs all segment registers in REG_CSGSFS, probably better to
> stuff them the same way? (all three really are 16bit only, even if the
> thread_state is padding them to 32bits).
Exactly because that's how they are laid out in struct
i386_thread_state, if you count in 8-byte chunks.
Look at how these REG_* definitions are used in fill_ucontext () in
trampoline.c (that's the one, not hursig.c like my previous message
said).
Sergey
Sergey Bugaev, le lun. 10 avril 2023 22:07:33 +0300, a ecrit:
> On Mon, Apr 10, 2023, 21:39 Samuel Thibault <samuel.thibault@gnu.org> wrote:
> > Note that I have pushed sysdeps/mach/hurd/x86_64/sys/ucontext.h to
> > sysdeps/x86_64/sys/ucontext.h since it's not mach-specific, and Linux
> > has its own for x86.
>
> It's not technically Mach specific, but it's arranged the same way as
> Mach's struct i386_thread_state,
It doesn't need to be.
> and code in hurdsig.c relies on this.
Yes, but that can surely be changed to fix the mapping?
Samuel
Sergey Bugaev, le lun. 10 avril 2023 22:13:06 +0300, a ecrit:
> On Mon, Apr 10, 2023 at 9:58 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> >
> > Sergey Bugaev, le dim. 19 mars 2023 18:09:59 +0300, a ecrit:
> > > +#ifdef __USE_GNU
> > > +/* Number of each register in the `gregset_t' array. */
> > > +enum
> > > +{
> > > + REG_GSFS = 0, /* Actually int gs, fs. */
> > > +# define REG_GSFS REG_GSFS
> > > + REG_ESDS, /* Actually int es, ds. */
> > > +# define REG_ESDS REG_ESDS
> >
> > On second thought, why REG_ESDS? They are basically useless on amd64
> >
> > Linux packs all segment registers in REG_CSGSFS, probably better to
> > stuff them the same way? (all three really are 16bit only, even if the
> > thread_state is padding them to 32bits).
>
> Exactly because that's how they are laid out in struct
> i386_thread_state, if you count in 8-byte chunks.
But we don't have to map to that.
Samuel
On Mon, Apr 10, 2023 at 10:22 PM Samuel Thibault
<samuel.thibault@gnu.org> wrote:
>
> Sergey Bugaev, le lun. 10 avril 2023 22:13:06 +0300, a ecrit:
> > On Mon, Apr 10, 2023 at 9:58 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> > >
> > > Sergey Bugaev, le dim. 19 mars 2023 18:09:59 +0300, a ecrit:
> > > > +#ifdef __USE_GNU
> > > > +/* Number of each register in the `gregset_t' array. */
> > > > +enum
> > > > +{
> > > > + REG_GSFS = 0, /* Actually int gs, fs. */
> > > > +# define REG_GSFS REG_GSFS
> > > > + REG_ESDS, /* Actually int es, ds. */
> > > > +# define REG_ESDS REG_ESDS
> > >
> > > On second thought, why REG_ESDS? They are basically useless on amd64
> > >
> > > Linux packs all segment registers in REG_CSGSFS, probably better to
> > > stuff them the same way? (all three really are 16bit only, even if the
> > > thread_state is padding them to 32bits).
> >
> > Exactly because that's how they are laid out in struct
> > i386_thread_state, if you count in 8-byte chunks.
>
> But we don't have to map to that.
Well yes, I was trying to make the x86_64 version do the same thing as
i386 does, hence arranging registers in sigcontext, ucontext, and
thread state in the same way, so they can be memcpied, like on i386.
But we could also lay this out differently and just write some more
code to fill the ucontext.
Sergey
Sergey Bugaev, le mar. 11 avril 2023 00:50:25 +0300, a ecrit:
> On Mon, Apr 10, 2023 at 10:22 PM Samuel Thibault
> <samuel.thibault@gnu.org> wrote:
> >
> > Sergey Bugaev, le lun. 10 avril 2023 22:13:06 +0300, a ecrit:
> > > On Mon, Apr 10, 2023 at 9:58 PM Samuel Thibault <samuel.thibault@gnu.org> wrote:
> > > >
> > > > Sergey Bugaev, le dim. 19 mars 2023 18:09:59 +0300, a ecrit:
> > > > > +#ifdef __USE_GNU
> > > > > +/* Number of each register in the `gregset_t' array. */
> > > > > +enum
> > > > > +{
> > > > > + REG_GSFS = 0, /* Actually int gs, fs. */
> > > > > +# define REG_GSFS REG_GSFS
> > > > > + REG_ESDS, /* Actually int es, ds. */
> > > > > +# define REG_ESDS REG_ESDS
> > > >
> > > > On second thought, why REG_ESDS? They are basically useless on amd64
> > > >
> > > > Linux packs all segment registers in REG_CSGSFS, probably better to
> > > > stuff them the same way? (all three really are 16bit only, even if the
> > > > thread_state is padding them to 32bits).
> > >
> > > Exactly because that's how they are laid out in struct
> > > i386_thread_state, if you count in 8-byte chunks.
> >
> > But we don't have to map to that.
>
> Well yes, I was trying to make the x86_64 version do the same thing as
> i386 does, hence arranging registers in sigcontext, ucontext, and
> thread state in the same way, so they can be memcpied, like on i386.
Ah, but on i386 it's only coincidence that it's the same layout, just
because that's the pusha layourt :)
> But we could also lay this out differently and just write some more
> code to fill the ucontext.
I'd say better stick to some sane layout that makes it simpler for most
uses. We don't have to stick to the Linux layout either.
Samuel
new file mode 100644
@@ -0,0 +1,131 @@
+/* Machine-dependent signal context structure for GNU Hurd. x86_64 version.
+ Copyright (C) 1991-2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _BITS_SIGCONTEXT_H
+#define _BITS_SIGCONTEXT_H 1
+
+#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H
+# error "Never use <bits/sigcontext.h> directly; include <signal.h> instead."
+#endif
+
+/* Signal handlers are actually called:
+ void handler (int sig, int code, struct sigcontext *scp); */
+
+#include <bits/types/__sigset_t.h>
+#include <mach/machine/fp_reg.h>
+
+/* State of this thread when the signal was taken. */
+struct sigcontext
+ {
+ /* These first members are machine-independent. */
+
+ int sc_onstack; /* Nonzero if running on sigstack. */
+ __sigset_t sc_mask; /* Blocked signals to restore. */
+
+ /* MiG reply port this thread is using. */
+ unsigned int sc_reply_port;
+
+ /* Port this thread is doing an interruptible RPC on. */
+ unsigned int sc_intr_port;
+
+ /* Error code associated with this signal (interpreted as `error_t'). */
+ int sc_error;
+
+ /* All following members are machine-dependent. The rest of this
+ structure is written to be laid out identically to:
+ {
+ struct i386_thread_state basic;
+ struct i386_float_state fpu;
+ }
+ trampoline.c knows this, so it must be changed if this changes. */
+
+#define sc_i386_thread_state sc_gs /* Beginning of correspondence. */
+ /* Segment registers. */
+ int sc_gs;
+ int sc_fs;
+ int sc_es;
+ int sc_ds;
+
+ long sc_r8;
+ long sc_r9;
+ long sc_r10;
+ long sc_r11;
+ long sc_r12;
+ long sc_r13;
+ long sc_r14;
+ long sc_r15;
+ long sc_rdi;
+ long sc_rsi;
+ long sc_rbp;
+ long sc_rsp; /* Not used; sc_ursp is used instead. */
+ long sc_rbx;
+ long sc_rdx;
+ long sc_rcx;
+ long sc_rax;
+ long sc_rip; /* Instruction pointer. */
+
+ int sc_cs; /* Code segment register. */
+
+ long sc_rfl; /* Processor flags. */
+
+ long sc_ursp; /* This stack pointer is used. */
+ int sc_ss; /* Stack segment register. */
+
+ /* Following mimics struct i386_float_state. Structures and symbolic
+ values can be found in <mach/i386/fp_reg.h>. */
+#define sc_i386_float_state sc_fpkind
+ int sc_fpkind; /* FP_NO, FP_387, etc. */
+ int sc_fpused; /* If zero, ignore rest of float state. */
+ struct i386_fp_save sc_fpsave;
+ struct i386_fp_regs sc_fpregs;
+ int sc_fpexcsr; /* FPSR including exception bits. */
+ };
+
+/* Traditional BSD names for some members. */
+#define sc_sp sc_ursp /* Stack pointer. */
+#define sc_fp sc_rbp /* Frame pointer. */
+#define sc_pc sc_rip /* Process counter. */
+#define sc_ps sc_rfl
+
+
+/* The deprecated sigcode values below are passed as an extra, non-portable
+ argument to regular signal handlers. You should use SA_SIGINFO handlers
+ instead, which use the standard POSIX signal codes. */
+
+/* Codes for SIGFPE. */
+#define FPE_INTOVF_TRAP 0x1 /* integer overflow */
+#define FPE_INTDIV_FAULT 0x2 /* integer divide by zero */
+#define FPE_FLTOVF_FAULT 0x3 /* floating overflow */
+#define FPE_FLTDIV_FAULT 0x4 /* floating divide by zero */
+#define FPE_FLTUND_FAULT 0x5 /* floating underflow */
+#define FPE_SUBRNG_FAULT 0x7 /* BOUNDS instruction failed */
+#define FPE_FLTDNR_FAULT 0x8 /* denormalized operand */
+#define FPE_FLTINX_FAULT 0x9 /* floating loss of precision */
+#define FPE_EMERR_FAULT 0xa /* mysterious emulation error 33 */
+#define FPE_EMBND_FAULT 0xb /* emulation BOUNDS instruction failed */
+
+/* Codes for SIGILL. */
+#define ILL_INVOPR_FAULT 0x1 /* invalid operation */
+#define ILL_STACK_FAULT 0x2 /* fault on microkernel stack access */
+#define ILL_FPEOPR_FAULT 0x3 /* invalid floating operation */
+
+/* Codes for SIGTRAP. */
+#define DBG_SINGLE_TRAP 0x1 /* single step */
+#define DBG_BRKPNT_FAULT 0x2 /* breakpoint instruction */
+
+#endif /* bits/sigcontext.h */
new file mode 100644
@@ -0,0 +1,157 @@
+/* Copyright (C) 2001-2023 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _SYS_UCONTEXT_H
+#define _SYS_UCONTEXT_H 1
+
+#include <features.h>
+
+#include <bits/types.h>
+#include <bits/types/sigset_t.h>
+#include <bits/types/stack_t.h>
+
+
+#ifdef __USE_MISC
+# define __ctx(fld) fld
+#else
+# define __ctx(fld) __ ## fld
+#endif
+
+/* Type for general register. */
+__extension__ typedef long long int greg_t;
+
+/* Number of general registers. */
+#define __NGREG 23
+#ifdef __USE_MISC
+# define NGREG __NGREG
+#endif
+
+/* Container for all general registers. */
+typedef greg_t gregset_t[__NGREG];
+
+#ifdef __USE_GNU
+/* Number of each register in the `gregset_t' array. */
+enum
+{
+ REG_GSFS = 0, /* Actually int gs, fs. */
+# define REG_GSFS REG_GSFS
+ REG_ESDS, /* Actually int es, ds. */
+# define REG_ESDS REG_ESDS
+ REG_R8,
+# define REG_R8 REG_R8
+ REG_R9,
+# define REG_R9 REG_R9
+ REG_R10,
+# define REG_R10 REG_R10
+ REG_R11,
+# define REG_R11 REG_R11
+ REG_R12,
+# define REG_R12 REG_R12
+ REG_R13,
+# define REG_R13 REG_R13
+ REG_R14,
+# define REG_R14 REG_R14
+ REG_R15,
+# define REG_R15 REG_R15
+ REG_RDI,
+# define REG_RDI REG_RDI
+ REG_RSI,
+# define REG_RSI REG_RSI
+ REG_RBP,
+# define REG_RBP REG_RBP
+ REG_RSP,
+# define REG_RSP REG_RSP
+ REG_RBX,
+# define REG_RBX REG_RBX
+ REG_RDX,
+# define REG_RDX REG_RDX
+ REG_RCX,
+# define REG_RCX REG_RCX
+ REG_RAX,
+# define REG_RAX REG_RAX
+ REG_RIP,
+# define REG_RIP REG_RIP
+ REG_CS, /* Actually int cs, pad. */
+# define REG_CS REG_CS
+ REG_RFL,
+# define REG_RFL REG_RFL
+ REG_ERR,
+# define REG_ERR REG_ERR
+ REG_TRAPNO,
+# define REG_TRAPNO REG_TRAPNO
+ REG_OLDMASK,
+# define REG_OLDMASK REG_OLDMASK
+ REG_CR2
+# define REG_CR2 REG_CR2
+};
+#endif
+
+struct _libc_fpxreg
+{
+ unsigned short int __ctx(significand)[4];
+ unsigned short int __ctx(exponent);
+ unsigned short int __glibc_reserved1[3];
+};
+
+struct _libc_xmmreg
+{
+ __uint32_t __ctx(element)[4];
+};
+
+struct _libc_fpstate
+{
+ /* 64-bit FXSAVE format. */
+ __uint16_t __ctx(cwd);
+ __uint16_t __ctx(swd);
+ __uint16_t __ctx(ftw);
+ __uint16_t __ctx(fop);
+ __uint64_t __ctx(rip);
+ __uint64_t __ctx(rdp);
+ __uint32_t __ctx(mxcsr);
+ __uint32_t __ctx(mxcr_mask);
+ struct _libc_fpxreg _st[8];
+ struct _libc_xmmreg _xmm[16];
+ __uint32_t __glibc_reserved1[24];
+};
+
+/* Structure to describe FPU registers. */
+typedef struct _libc_fpstate *fpregset_t;
+
+/* Context to describe whole processor state. */
+typedef struct
+ {
+ gregset_t __ctx(gregs);
+ /* Note that fpregs is a pointer. */
+ fpregset_t __ctx(fpregs);
+ __extension__ unsigned long long __reserved1 [8];
+} mcontext_t;
+
+/* Userlevel context. */
+typedef struct ucontext_t
+ {
+ unsigned long int __ctx(uc_flags);
+ struct ucontext_t *uc_link;
+ stack_t uc_stack;
+ mcontext_t uc_mcontext;
+ sigset_t uc_sigmask;
+ struct _libc_fpstate __fpregs_mem;
+ __extension__ unsigned long long int __ssp[4];
+ } ucontext_t;
+
+#undef __ctx
+
+#endif /* sys/ucontext.h */
new file mode 100644
@@ -0,0 +1,38 @@
+#include <stddef.h>
+#include <signal.h>
+#include <sys/ucontext.h>
+
+--
+
+SIG_BLOCK
+SIG_SETMASK
+
+_NSIG8 (_NSIG / 8)
+
+#define ucontext(member) offsetof (ucontext_t, member)
+#define mcontext(member) ucontext (uc_mcontext.member)
+#define mreg(reg) mcontext (gregs[REG_##reg])
+
+oRBP mreg (RBP)
+oRSP mreg (RSP)
+oRBX mreg (RBX)
+oR8 mreg (R8)
+oR9 mreg (R9)
+oR10 mreg (R10)
+oR11 mreg (R11)
+oR12 mreg (R12)
+oR13 mreg (R13)
+oR14 mreg (R14)
+oR15 mreg (R15)
+oRDI mreg (RDI)
+oRSI mreg (RSI)
+oRDX mreg (RDX)
+oRAX mreg (RAX)
+oRCX mreg (RCX)
+oRIP mreg (RIP)
+oRFL mreg (RFL)
+oFPREGS mcontext (fpregs)
+oSIGMASK ucontext (uc_sigmask)
+oFPREGSMEM ucontext (__fpregs_mem)
+oMXCSR ucontext (__fpregs_mem.mxcsr)
+oSSP ucontext (__ssp)