diff options
author | peter <peter@FreeBSD.org> | 2002-10-25 19:10:58 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2002-10-25 19:10:58 +0000 |
commit | f7fa86b743f4851065b80a704e7ee6c9922b5bda (patch) | |
tree | 96a1089f558875f808b1fd36f885179cd78f55de /sys/amd64 | |
parent | c689b5c88a817d10910bb530d1a68187b58db634 (diff) | |
download | FreeBSD-src-f7fa86b743f4851065b80a704e7ee6c9922b5bda.zip FreeBSD-src-f7fa86b743f4851065b80a704e7ee6c9922b5bda.tar.gz |
Split 4.x and 5.x signal handling so that we can keep 4.x signal
handling clean and functional as 5.x evolves. This allows some of the
nasty bandaids in the 5.x codepaths to be unwound.
Encapsulate 4.x signal handling under COMPAT_FREEBSD4 (there is an
anti-foot-shooting measure in place, 5.x folks need this for a while) and
finish encapsulating the older stuff under COMPAT_43. Since the ancient
stuff is required on alpha (longjmp(3) passes a 'struct osigcontext *'
to the current sigreturn(2), instead of the 'ucontext_t *' that sigreturn
is supposed to take), add a compile time check to prevent foot shooting
there too. Add uniform COMPAT_43 stubs for ia64/sparc64/powerpc.
Tested on: i386, alpha, ia64. Compiled on sparc64 (a few days ago).
Approved by: re
Diffstat (limited to 'sys/amd64')
-rw-r--r-- | sys/amd64/amd64/genassym.c | 9 | ||||
-rw-r--r-- | sys/amd64/amd64/locore.S | 26 | ||||
-rw-r--r-- | sys/amd64/amd64/locore.s | 26 | ||||
-rw-r--r-- | sys/amd64/amd64/machdep.c | 276 | ||||
-rw-r--r-- | sys/amd64/include/md_var.h | 8 | ||||
-rw-r--r-- | sys/amd64/include/sigframe.h | 18 | ||||
-rw-r--r-- | sys/amd64/include/signal.h | 4 | ||||
-rw-r--r-- | sys/amd64/include/ucontext.h | 28 |
8 files changed, 363 insertions, 32 deletions
diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c index d4aa9e3..5a8cf70 100644 --- a/sys/amd64/amd64/genassym.c +++ b/sys/amd64/amd64/genassym.c @@ -37,6 +37,7 @@ * $FreeBSD$ */ +#include "opt_compat.h" #include "opt_kstack_pages.h" #include <sys/param.h> @@ -151,12 +152,20 @@ ASSYM(TF_ERR, offsetof(struct trapframe, tf_err)); ASSYM(TF_CS, offsetof(struct trapframe, tf_cs)); ASSYM(TF_EFLAGS, offsetof(struct trapframe, tf_eflags)); ASSYM(SIGF_HANDLER, offsetof(struct sigframe, sf_ahu.sf_handler)); +#ifdef COMPAT_43 ASSYM(SIGF_SC, offsetof(struct osigframe, sf_siginfo.si_sc)); +#endif ASSYM(SIGF_UC, offsetof(struct sigframe, sf_uc)); +#ifdef COMPAT_43 ASSYM(SC_PS, offsetof(struct osigcontext, sc_ps)); ASSYM(SC_FS, offsetof(struct osigcontext, sc_fs)); ASSYM(SC_GS, offsetof(struct osigcontext, sc_gs)); ASSYM(SC_TRAPNO, offsetof(struct osigcontext, sc_trapno)); +#endif +#ifdef COMPAT_FREEBSD4 +ASSYM(UC4_EFLAGS, offsetof(struct ucontext4, uc_mcontext.mc_eflags)); +ASSYM(UC4_GS, offsetof(struct ucontext4, uc_mcontext.mc_gs)); +#endif ASSYM(UC_EFLAGS, offsetof(ucontext_t, uc_mcontext.mc_eflags)); ASSYM(UC_GS, offsetof(ucontext_t, uc_mcontext.mc_gs)); ASSYM(ENOENT, ENOENT); diff --git a/sys/amd64/amd64/locore.S b/sys/amd64/amd64/locore.S index 5d5b39e..8f1d801 100644 --- a/sys/amd64/amd64/locore.S +++ b/sys/amd64/amd64/locore.S @@ -406,6 +406,22 @@ NON_GPROF_ENTRY(sigcode) int $0x80 /* enter kernel with args */ 0: jmp 0b +#ifdef COMPAT_FREEBSD4 + ALIGN_TEXT +freebsd4_sigcode: + call *SIGF_HANDLER(%esp) /* call signal handler */ + lea SIGF_UC(%esp),%eax /* get ucontext_t */ + pushl %eax + testl $PSL_VM,UC4_EFLAGS(%eax) + jne 9f + movl UC4_GS(%eax),%gs /* restore %gs */ +9: + movl $344,%eax /* 4.x SYS_sigreturn */ + pushl %eax /* junk to fake return addr. */ + int $0x80 /* enter kernel with args */ +0: jmp 0b +#endif + #ifdef COMPAT_43 ALIGN_TEXT osigcode: @@ -416,7 +432,7 @@ osigcode: jne 9f movl SC_GS(%eax),%gs /* restore %gs */ 9: - movl $SYS_osigreturn,%eax + movl $103,%eax /* 3.x SYS_sigreturn */ pushl %eax /* junk to fake return addr. */ int $0x80 /* enter kernel with args */ 0: jmp 0b @@ -426,10 +442,16 @@ osigcode: esigcode: .data - .globl szsigcode, szosigcode + .globl szsigcode szsigcode: .long esigcode-sigcode +#ifdef COMPAT_FREEBSD4 + .globl szfreebsd4_sigcode +szfreebsd4_sigcode: + .long esigcode-freebsd4_sigcode +#endif #ifdef COMPAT_43 + .globl szosigcode szosigcode: .long esigcode-osigcode #endif diff --git a/sys/amd64/amd64/locore.s b/sys/amd64/amd64/locore.s index 5d5b39e..8f1d801 100644 --- a/sys/amd64/amd64/locore.s +++ b/sys/amd64/amd64/locore.s @@ -406,6 +406,22 @@ NON_GPROF_ENTRY(sigcode) int $0x80 /* enter kernel with args */ 0: jmp 0b +#ifdef COMPAT_FREEBSD4 + ALIGN_TEXT +freebsd4_sigcode: + call *SIGF_HANDLER(%esp) /* call signal handler */ + lea SIGF_UC(%esp),%eax /* get ucontext_t */ + pushl %eax + testl $PSL_VM,UC4_EFLAGS(%eax) + jne 9f + movl UC4_GS(%eax),%gs /* restore %gs */ +9: + movl $344,%eax /* 4.x SYS_sigreturn */ + pushl %eax /* junk to fake return addr. */ + int $0x80 /* enter kernel with args */ +0: jmp 0b +#endif + #ifdef COMPAT_43 ALIGN_TEXT osigcode: @@ -416,7 +432,7 @@ osigcode: jne 9f movl SC_GS(%eax),%gs /* restore %gs */ 9: - movl $SYS_osigreturn,%eax + movl $103,%eax /* 3.x SYS_sigreturn */ pushl %eax /* junk to fake return addr. */ int $0x80 /* enter kernel with args */ 0: jmp 0b @@ -426,10 +442,16 @@ osigcode: esigcode: .data - .globl szsigcode, szosigcode + .globl szsigcode szsigcode: .long esigcode-sigcode +#ifdef COMPAT_FREEBSD4 + .globl szfreebsd4_sigcode +szfreebsd4_sigcode: + .long esigcode-freebsd4_sigcode +#endif #ifdef COMPAT_43 + .globl szosigcode szosigcode: .long esigcode-osigcode #endif diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 80805a2..ff69b56 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -165,6 +165,10 @@ int cold = 1; #ifdef COMPAT_43 static void osendsig(sig_t catcher, int sig, sigset_t *mask, u_long code); #endif +#ifdef COMPAT_FREEBSD4 +static void freebsd4_sendsig(sig_t catcher, int sig, sigset_t *mask, + u_long code); +#endif static int sysctl_hw_physmem(SYSCTL_HANDLER_ARGS) @@ -286,8 +290,7 @@ osendsig(catcher, sig, mask, code) sigset_t *mask; u_long code; { - struct osigframe sf; - struct osigframe *fp; + struct osigframe sf, *fp; struct proc *p; struct thread *td; struct sigacts *psp; @@ -408,6 +411,129 @@ osendsig(catcher, sig, mask, code) } #endif /* COMPAT_43 */ +#ifdef COMPAT_FREEBSD4 +static void +freebsd4_sendsig(catcher, sig, mask, code) + sig_t catcher; + int sig; + sigset_t *mask; + u_long code; +{ + struct sigframe4 sf, *sfp; + struct proc *p; + struct thread *td; + struct sigacts *psp; + struct trapframe *regs; + int oonstack; + + td = curthread; + p = td->td_proc; + PROC_LOCK_ASSERT(p, MA_OWNED); + psp = p->p_sigacts; + regs = td->td_frame; + oonstack = sigonstack(regs->tf_esp); + + /* Save user context. */ + bzero(&sf, sizeof(sf)); + sf.sf_uc.uc_sigmask = *mask; + sf.sf_uc.uc_stack = p->p_sigstk; + sf.sf_uc.uc_stack.ss_flags = (p->p_flag & P_ALTSTACK) + ? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE; + sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0; + sf.sf_uc.uc_mcontext.mc_gs = rgs(); + bcopy(regs, &sf.sf_uc.uc_mcontext.mc_fs, sizeof(*regs)); + + /* Allocate space for the signal handler context. */ + if ((p->p_flag & P_ALTSTACK) != 0 && !oonstack && + SIGISMEMBER(psp->ps_sigonstack, sig)) { + sfp = (struct sigframe4 *)(p->p_sigstk.ss_sp + + p->p_sigstk.ss_size - sizeof(struct sigframe4)); +#if defined(COMPAT_43) || defined(COMPAT_SUNOS) + p->p_sigstk.ss_flags |= SS_ONSTACK; +#endif + } else + sfp = (struct sigframe4 *)regs->tf_esp - 1; + PROC_UNLOCK(p); + + /* Translate the signal if appropriate. */ + if (p->p_sysent->sv_sigtbl && sig <= p->p_sysent->sv_sigsize) + sig = p->p_sysent->sv_sigtbl[_SIG_IDX(sig)]; + + /* Build the argument list for the signal handler. */ + sf.sf_signum = sig; + sf.sf_ucontext = (register_t)&sfp->sf_uc; + PROC_LOCK(p); + if (SIGISMEMBER(p->p_sigacts->ps_siginfo, sig)) { + /* Signal handler installed with SA_SIGINFO. */ + sf.sf_siginfo = (register_t)&sfp->sf_si; + sf.sf_ahu.sf_action = (__siginfohandler_t *)catcher; + + /* Fill in POSIX parts */ + sf.sf_si.si_signo = sig; + sf.sf_si.si_code = code; + sf.sf_si.si_addr = (void *)regs->tf_err; + sf.sf_si.si_pid = p->p_pid; + sf.sf_si.si_uid = p->p_ucred->cr_uid; + } else { + /* Old FreeBSD-style arguments. */ + sf.sf_siginfo = code; + sf.sf_addr = regs->tf_err; + sf.sf_ahu.sf_handler = catcher; + } + PROC_UNLOCK(p); + + /* + * If we're a vm86 process, we want to save the segment registers. + * We also change eflags to be our emulated eflags, not the actual + * eflags. + */ + if (regs->tf_eflags & PSL_VM) { + struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; + struct vm86_kernel *vm86 = &td->td_pcb->pcb_ext->ext_vm86; + + sf.sf_uc.uc_mcontext.mc_gs = tf->tf_vm86_gs; + sf.sf_uc.uc_mcontext.mc_fs = tf->tf_vm86_fs; + sf.sf_uc.uc_mcontext.mc_es = tf->tf_vm86_es; + sf.sf_uc.uc_mcontext.mc_ds = tf->tf_vm86_ds; + + if (vm86->vm86_has_vme == 0) + sf.sf_uc.uc_mcontext.mc_eflags = + (tf->tf_eflags & ~(PSL_VIF | PSL_VIP)) | + (vm86->vm86_eflags & (PSL_VIF | PSL_VIP)); + + /* + * Clear PSL_NT to inhibit T_TSSFLT faults on return from + * syscalls made by the signal handler. This just avoids + * wasting time for our lazy fixup of such faults. PSL_NT + * does nothing in vm86 mode, but vm86 programs can set it + * almost legitimately in probes for old cpu types. + */ + tf->tf_eflags &= ~(PSL_VM | PSL_NT | PSL_VIF | PSL_VIP); + } + + /* + * Copy the sigframe out to the user's stack. + */ + if (copyout(&sf, sfp, sizeof(*sfp)) != 0) { +#ifdef DEBUG + printf("process %ld has trashed its stack\n", (long)p->p_pid); +#endif + PROC_LOCK(p); + sigexit(td, SIGILL); + } + + regs->tf_esp = (int)sfp; + regs->tf_eip = PS_STRINGS - szfreebsd4_sigcode; + regs->tf_eflags &= ~PSL_T; + regs->tf_cs = _ucodesel; + regs->tf_ds = _udatasel; + regs->tf_es = _udatasel; + regs->tf_fs = _udatasel; + regs->tf_ss = _udatasel; + PROC_LOCK(p); +} +#endif /* COMPAT_FREEBSD4 */ + void sendsig(catcher, sig, mask, code) sig_t catcher; @@ -415,18 +541,23 @@ sendsig(catcher, sig, mask, code) sigset_t *mask; u_long code; { - struct sigframe sf; + struct sigframe sf, *sfp; struct proc *p; struct thread *td; struct sigacts *psp; struct trapframe *regs; - struct sigframe *sfp; int oonstack; td = curthread; p = td->td_proc; PROC_LOCK_ASSERT(p, MA_OWNED); psp = p->p_sigacts; +#ifdef COMPAT_FREEBSD4 + if (SIGISMEMBER(psp->ps_freebsd4, sig)) { + freebsd4_sendsig(catcher, sig, mask, code); + return; + } +#endif #ifdef COMPAT_43 if (SIGISMEMBER(psp->ps_osigset, sig)) { osendsig(catcher, sig, mask, code); @@ -550,6 +681,7 @@ sendsig(catcher, sig, mask, code) * * MPSAFE */ +#ifdef COMPAT_43 int osigreturn(td, uap) struct thread *td; @@ -557,7 +689,6 @@ osigreturn(td, uap) struct osigcontext *sigcntxp; } */ *uap; { -#ifdef COMPAT_43 struct osigcontext sc; struct trapframe *regs; struct osigcontext *scp; @@ -662,10 +793,116 @@ osigreturn(td, uap) signotify(p); PROC_UNLOCK(p); return (EJUSTRETURN); -#else /* !COMPAT_43 */ - return (ENOSYS); +} #endif /* COMPAT_43 */ + +#ifdef COMPAT_FREEBSD4 +/* + * MPSAFE + */ +int +freebsd4_sigreturn(td, uap) + struct thread *td; + struct freebsd4_sigreturn_args /* { + const ucontext4 *sigcntxp; + } */ *uap; +{ + struct ucontext4 uc; + struct proc *p = td->td_proc; + struct trapframe *regs; + const struct ucontext4 *ucp; + int cs, eflags, error; + + error = copyin(uap->sigcntxp, &uc, sizeof(uc)); + if (error != 0) + return (error); + ucp = &uc; + regs = td->td_frame; + eflags = ucp->uc_mcontext.mc_eflags; + if (eflags & PSL_VM) { + struct trapframe_vm86 *tf = (struct trapframe_vm86 *)regs; + struct vm86_kernel *vm86; + + /* + * if pcb_ext == 0 or vm86_inited == 0, the user hasn't + * set up the vm86 area, and we can't enter vm86 mode. + */ + if (td->td_pcb->pcb_ext == 0) + return (EINVAL); + vm86 = &td->td_pcb->pcb_ext->ext_vm86; + if (vm86->vm86_inited == 0) + return (EINVAL); + + /* Go back to user mode if both flags are set. */ + if ((eflags & PSL_VIP) && (eflags & PSL_VIF)) + trapsignal(p, SIGBUS, 0); + + if (vm86->vm86_has_vme) { + eflags = (tf->tf_eflags & ~VME_USERCHANGE) | + (eflags & VME_USERCHANGE) | PSL_VM; + } else { + vm86->vm86_eflags = eflags; /* save VIF, VIP */ + eflags = (tf->tf_eflags & ~VM_USERCHANGE) | + (eflags & VM_USERCHANGE) | PSL_VM; + } + bcopy(&ucp->uc_mcontext.mc_fs, tf, sizeof(struct trapframe)); + tf->tf_eflags = eflags; + tf->tf_vm86_ds = tf->tf_ds; + tf->tf_vm86_es = tf->tf_es; + tf->tf_vm86_fs = tf->tf_fs; + tf->tf_vm86_gs = ucp->uc_mcontext.mc_gs; + tf->tf_ds = _udatasel; + tf->tf_es = _udatasel; + tf->tf_fs = _udatasel; + } else { + /* + * Don't allow users to change privileged or reserved flags. + */ + /* + * XXX do allow users to change the privileged flag PSL_RF. + * The cpu sets PSL_RF in tf_eflags for faults. Debuggers + * should sometimes set it there too. tf_eflags is kept in + * the signal context during signal handling and there is no + * other place to remember it, so the PSL_RF bit may be + * corrupted by the signal handler without us knowing. + * Corruption of the PSL_RF bit at worst causes one more or + * one less debugger trap, so allowing it is fairly harmless. + */ + if (!EFL_SECURE(eflags & ~PSL_RF, regs->tf_eflags & ~PSL_RF)) { + printf("freebsd4_sigreturn: eflags = 0x%x\n", eflags); + return (EINVAL); + } + + /* + * Don't allow users to load a valid privileged %cs. Let the + * hardware check for invalid selectors, excess privilege in + * other selectors, invalid %eip's and invalid %esp's. + */ + cs = ucp->uc_mcontext.mc_cs; + if (!CS_SECURE(cs)) { + printf("freebsd4_sigreturn: cs = 0x%x\n", cs); + trapsignal(p, SIGBUS, T_PROTFLT); + return (EINVAL); + } + + bcopy(&ucp->uc_mcontext.mc_fs, regs, sizeof(*regs)); + } + + PROC_LOCK(p); +#if defined(COMPAT_43) || defined(COMPAT_SUNOS) + if (ucp->uc_mcontext.mc_onstack & 1) + p->p_sigstk.ss_flags |= SS_ONSTACK; + else + p->p_sigstk.ss_flags &= ~SS_ONSTACK; +#endif + + p->p_sigmask = ucp->uc_sigmask; + SIG_CANTMASK(p->p_sigmask); + signotify(p); + PROC_UNLOCK(p); + return (EJUSTRETURN); } +#endif /* COMPAT_FREEBSD4 */ /* * MPSAFE @@ -2162,7 +2399,7 @@ get_fpcontext(struct thread *td, mcontext_t *mcp) #ifndef DEV_NPX mcp->mc_fpformat = _MC_FPFMT_NODEV; mcp->mc_ownedfp = _MC_FPOWNED_NONE; -#else /* DEV_NPX */ +#else union savefpu *addr; /* @@ -2192,9 +2429,8 @@ get_fpcontext(struct thread *td, mcontext_t *mcp) bcopy(addr, &mcp->mc_fpstate, sizeof(mcp->mc_fpstate)); bzero(&mcp->mc_spare2, sizeof(mcp->mc_spare2)); } - bcopy(&mcp->mc_fpstate, &td->td_pcb->pcb_save, sizeof(mcp->mc_fpstate)); mcp->mc_fpformat = npxformat(); -#endif /* !DEV_NPX */ +#endif } static int @@ -2204,7 +2440,10 @@ set_fpcontext(struct thread *td, const mcontext_t *mcp) if (mcp->mc_fpformat == _MC_FPFMT_NODEV) return (0); - if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) + else if (mcp->mc_fpformat != _MC_FPFMT_387 && + mcp->mc_fpformat != _MC_FPFMT_XMM) + return (EINVAL); + else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) /* We don't care what state is left in the FPU or PCB. */ fpstate_drop(td); else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU || @@ -2227,25 +2466,14 @@ set_fpcontext(struct thread *td, const mcontext_t *mcp) * be called with interrupts disabled. */ npxsetregs(td, addr); +#endif /* * Don't bother putting things back where they were in the * misaligned case, since we know that the caller won't use * them again. */ - } else { - /* - * There is no valid FPU state in *mcp, so use the saved - * state in the PCB if there is one. XXX the test for - * whether there is one seems to be quite broken. We - * forcibly drop the state in sendsig(). - */ - if ((td->td_pcb->pcb_flags & PCB_NPXINITDONE) != 0) - npxsetregs(td, &td->td_pcb->pcb_save); -#endif -#if !defined(COMPAT_FREEBSD4) && !defined(COMPAT_43) + } else return (EINVAL); -#endif - } return (0); } diff --git a/sys/amd64/include/md_var.h b/sys/amd64/include/md_var.h index f449c04..9fa3968 100644 --- a/sys/amd64/include/md_var.h +++ b/sys/amd64/include/md_var.h @@ -56,7 +56,13 @@ extern int need_post_dma_flush; #endif extern void (*ovbcopy_vector)(const void *from, void *to, size_t len); extern char sigcode[]; -extern int szsigcode, szosigcode; +extern int szsigcode; +#ifdef COMPAT_FREEBSD4 +extern int szfreebsd4_sigcode; +#endif +#ifdef COMPAT_43 +extern int szosigcode; +#endif typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss); struct thread; diff --git a/sys/amd64/include/sigframe.h b/sys/amd64/include/sigframe.h index 947743d..98be731 100644 --- a/sys/amd64/include/sigframe.h +++ b/sys/amd64/include/sigframe.h @@ -35,6 +35,7 @@ * Signal frames, arguments passed to application signal handlers. */ #ifdef _KERNEL +#ifdef COMPAT_43 struct osigframe { /* * The first four members may be used by applications. @@ -70,6 +71,23 @@ struct osigframe { osiginfo_t sf_siginfo; }; #endif +#ifdef COMPAT_FREEBSD4 +/* FreeBSD 4.x */ +struct sigframe4 { + register_t sf_signum; + register_t sf_siginfo; /* code or pointer to sf_si */ + register_t sf_ucontext; /* points to sf_uc */ + register_t sf_addr; /* undocumented 4th arg */ + + union { + __siginfohandler_t *sf_action; + __sighandler_t *sf_handler; + } sf_ahu; + struct ucontext4 sf_uc; /* = *sf_ucontext */ + siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case) */ +}; +#endif +#endif struct sigframe { /* diff --git a/sys/amd64/include/signal.h b/sys/amd64/include/signal.h index 9fcca63..29a9776 100644 --- a/sys/amd64/include/signal.h +++ b/sys/amd64/include/signal.h @@ -60,7 +60,7 @@ typedef int sig_atomic_t; /* * Only the kernel should need these old type definitions. */ -#ifdef _KERNEL +#if defined(_KERNEL) && defined(COMPAT_43) /* * Information pushed on stack when a signal is delivered. * This is used by the kernel to restore state following @@ -68,8 +68,6 @@ typedef int sig_atomic_t; * to the handler to allow it to restore state properly if * a non-standard exit is performed. */ -typedef unsigned int osigset_t; - struct osigcontext { int sc_onstack; /* sigstack state to restore */ osigset_t sc_mask; /* signal mask to restore */ diff --git a/sys/amd64/include/ucontext.h b/sys/amd64/include/ucontext.h index d02959c..af9b4fd 100644 --- a/sys/amd64/include/ucontext.h +++ b/sys/amd64/include/ucontext.h @@ -73,6 +73,34 @@ typedef struct __mcontext { } mcontext_t; #ifdef _KERNEL +#ifdef COMPAT_FREEBSD4 +/* For 4.x binaries */ +struct mcontext4 { + int mc_onstack; /* XXX - sigcontext compat. */ + int mc_gs; + int mc_fs; + int mc_es; + int mc_ds; + int mc_edi; + int mc_esi; + int mc_ebp; + int mc_isp; + int mc_ebx; + int mc_edx; + int mc_ecx; + int mc_eax; + int mc_trapno; + int mc_err; + int mc_eip; + int mc_cs; + int mc_eflags; + int mc_esp; /* machine state */ + int mc_ss; + int mc_fpregs[28]; /* env87 + fpacc87 + u_long */ + int __spare__[17]; +}; +#endif + struct thread; void get_mcontext(struct thread *td, mcontext_t *mcp); |