NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: kern/51514: ptrace(2) fails for 32-bit process on 64-bit kernel



The following reply was made to PR kern/51514; it has been noted by GNATS.

From: Nick Hudson <skrll%netbsd.org@localhost>
To: gnats-bugs%NetBSD.org@localhost, gnats-admin%netbsd.org@localhost, netbsd-bugs%netbsd.org@localhost,
 rokuyama%rk.phys.keio.ac.jp@localhost
Cc: 
Subject: Re: kern/51514: ptrace(2) fails for 32-bit process on 64-bit kernel
Date: Sun, 16 Oct 2016 09:09:10 +0100

 This is a multi-part message in MIME format.
 --------------050409000904030005020102
 Content-Type: text/plain; charset=utf-8; format=flowed
 Content-Transfer-Encoding: 7bit
 
 On 09/29/16 14:30, Nick Hudson wrote:
 > The following reply was made to PR kern/51514; it has been noted by GNATS.
 
 >   >   > the problem with your patch is that invades the main kernel with
 >   >   > comaptibility code that currently mostly works as a module.  it
 >   >   > really would be best to do this in compat/netbsd32 sources.
 >   >
 >   >   I agree with you. But it is difficult, at least for me, to separate
 >   >   compatibility code from kern/sys_process.c.
 >   >
 >   >   For sys_ptrace(9), the situation is similar to the case of
 >   >   copy_procargs(9) in kern/kern_proc.c, which has also compatibility
 >   >   code in it:
 >   >
 >   >https://nxr.netbsd.org/source/xref/src/sys/kern/kern_proc.c#2086
 >   >
 >   >   The procedure is almost common for native and 32-bit processes, but
 >   >   just small parts are different. How do we separate compat code from
 >   >   functions like this?
 >   >
 >   >   For process_{,fp}regs(9), the situation is more complicated as they
 >   >   are used not only by ptrace(2), but also by procfs.
 >   >
 >   >   I do not, of course, stick to my patch. My hope is just to implement
 >   >   COMPAT_NETBSD32 support to ptrace(2); without it, we cannot use GDB
 >   >   on mips64 at the moment. I would greatly appreciate it if you kindly
 >   >   give me any suggestions.
 >   
 >   I'm working on this. Hopefully the rabbit hole isn't too deep.
 
 Here's what I've got... Some things to nodes are
 
 - New compat_netbsd32_ptrace modules is created, but a ptrace module isn't
 - Should more be moved into compat32, e.g. PROC_{PTR,REG,FPREG}SZ and
    the netbsd32_process_{read,write}_{,fp}regs?
 -
 
 --------------050409000904030005020102
 Content-Type: text/x-patch;
  name="ptrace32.diff"
 Content-Transfer-Encoding: 7bit
 Content-Disposition: attachment;
  filename="ptrace32.diff"
 
 Index: sys/arch/amd64/amd64/netbsd32_machdep.c
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/amd64/amd64/netbsd32_machdep.c,v
 retrieving revision 1.96
 diff -u -p -r1.96 netbsd32_machdep.c
 --- sys/arch/amd64/amd64/netbsd32_machdep.c	2 Sep 2016 07:51:05 -0000	1.96
 +++ sys/arch/amd64/amd64/netbsd32_machdep.c	15 Oct 2016 12:40:13 -0000
 @@ -487,12 +487,12 @@ netbsd32_process_read_regs(struct lwp *l
  {
  	struct trapframe *tf = l->l_md.md_regs;
  
 -	regs->r_gs = LSEL(LUCODE32_SEL, SEL_UPL);
 -	regs->r_fs = LSEL(LUCODE32_SEL, SEL_UPL);
 -	regs->r_es = LSEL(LUCODE32_SEL, SEL_UPL);
 -	regs->r_ds = LSEL(LUCODE32_SEL, SEL_UPL);
 -	regs->r_eflags = tf->tf_rflags;
  	/* XXX avoid sign extension problems with unknown upper bits? */
 +	regs->r_gs = tf->tf_gs & 0xffff;
 +	regs->r_fs = tf->tf_fs & 0xffff;
 +	regs->r_es = tf->tf_es & 0xffff;
 +	regs->r_ds = tf->tf_ds & 0xffff;
 +	regs->r_eflags = tf->tf_rflags;
  	regs->r_edi = tf->tf_rdi & 0xffffffff;
  	regs->r_esi = tf->tf_rsi & 0xffffffff;
  	regs->r_ebp = tf->tf_rbp & 0xffffffff;
 @@ -501,9 +501,9 @@ netbsd32_process_read_regs(struct lwp *l
  	regs->r_ecx = tf->tf_rcx & 0xffffffff;
  	regs->r_eax = tf->tf_rax & 0xffffffff;
  	regs->r_eip = tf->tf_rip & 0xffffffff;
 -	regs->r_cs = tf->tf_cs;
 +	regs->r_cs = tf->tf_cs & 0xffff;
  	regs->r_esp = tf->tf_rsp & 0xffffffff;
 -	regs->r_ss = tf->tf_ss;
 +	regs->r_ss = tf->tf_ss & 0xffff;
  
  	return (0);
  }
 @@ -511,22 +511,52 @@ netbsd32_process_read_regs(struct lwp *l
  int
  netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *regs, size_t *sz)
  {
 -	struct fpreg regs64;
 -	int error;
 -	size_t fp_size;
 +
 +	__CTASSERT(sizeof *regs == sizeof (struct save87));
 +	process_read_fpregs_s87(l, (struct save87 *)regs);
 +	return 0;
 +}
 +
 +int
 +netbsd32_process_write_regs(struct lwp *l, const struct reg32 *regs)
 +{
 +	struct trapframe *tf = l->l_md.md_regs;
  
  	/*
 -	 * All that stuff makes no sense in i386 code :(
 +	 * Check for security violations. Taken from i386/process_machdep.c.
  	 */
 +	if (((regs->r_eflags ^ tf->tf_rflags) & PSL_USERSTATIC) != 0 ||
 +	    !VALID_USER_CSEL32(regs->r_cs))
 +		return EINVAL;
  
 -	fp_size = sizeof regs64;
 -	error = process_read_fpregs(l, &regs64, &fp_size);
 -	if (error)
 -		return error;
 -	__CTASSERT(sizeof *regs == sizeof (struct save87));
 -	process_xmm_to_s87(&regs64.fxstate, (struct save87 *)regs);
 +	tf->tf_rax = regs->r_eax;
 +	tf->tf_rcx = regs->r_ecx;
 +	tf->tf_rdx = regs->r_edx;
 +	tf->tf_rbx = regs->r_ebx;
 +	tf->tf_rsp = regs->r_esp;
 +	tf->tf_rbp = regs->r_ebp;
 +	tf->tf_rsi = regs->r_esi;
 +	tf->tf_rdi = regs->r_edi;
 +	tf->tf_rip = regs->r_eip;
 +	tf->tf_rflags = regs->r_eflags;
 +	tf->tf_cs = regs->r_cs;
 +	tf->tf_ss = regs->r_ss;
 +	tf->tf_ds = regs->r_ds;
 +	tf->tf_es = regs->r_es;
 +	tf->tf_fs = regs->r_fs;
 +	tf->tf_gs = regs->r_gs;
  
 -	return (0);
 +	return 0;
 +}
 +
 +int
 +netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *regs,
 +    size_t sz)
 +{
 +
 +	__CTASSERT(sizeof *regs == sizeof (struct save87));
 +	process_write_fpregs_s87(l, (const struct save87 *)regs);
 +	return 0;
  }
  
  int
 Index: sys/arch/amd64/include/netbsd32_machdep.h
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/amd64/include/netbsd32_machdep.h,v
 retrieving revision 1.19
 diff -u -p -r1.19 netbsd32_machdep.h
 --- sys/arch/amd64/include/netbsd32_machdep.h	7 Feb 2014 22:40:22 -0000	1.19
 +++ sys/arch/amd64/include/netbsd32_machdep.h	15 Oct 2016 12:40:13 -0000
 @@ -138,4 +138,7 @@ struct x86_64_set_mtrr_args32 {
  int netbsd32_process_read_regs(struct lwp *, struct reg32 *);
  int netbsd32_process_read_fpregs(struct lwp *, struct fpreg32 *, size_t *);
  
 +int netbsd32_process_write_regs(struct lwp *, const struct reg32 *);
 +int netbsd32_process_write_fpregs(struct lwp *, const struct fpreg32 *, size_t);
 +
  #endif /* _MACHINE_NETBSD32_H_ */
 Index: sys/arch/amd64/include/ptrace.h
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/amd64/include/ptrace.h,v
 retrieving revision 1.6
 diff -u -p -r1.6 ptrace.h
 --- sys/arch/amd64/include/ptrace.h	25 Sep 2015 16:05:17 -0000	1.6
 +++ sys/arch/amd64/include/ptrace.h	15 Oct 2016 12:40:13 -0000
 @@ -68,6 +68,9 @@
  #define process_read_regs32	netbsd32_process_read_regs
  #define process_read_fpregs32	netbsd32_process_read_fpregs
  
 +#define process_write_regs32	netbsd32_process_write_regs
 +#define process_write_fpregs32	netbsd32_process_write_fpregs
 +
  #define process_reg32		struct reg32
  #define process_fpreg32		struct fpreg32
  #endif	/* COMPAT_NETBSD32 */
 Index: sys/arch/sparc64/include/netbsd32_machdep.h
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/sparc64/include/netbsd32_machdep.h,v
 retrieving revision 1.28
 diff -u -p -r1.28 netbsd32_machdep.h
 --- sys/arch/sparc64/include/netbsd32_machdep.h	4 Jan 2014 00:10:03 -0000	1.28
 +++ sys/arch/sparc64/include/netbsd32_machdep.h	15 Oct 2016 12:40:13 -0000
 @@ -79,4 +79,7 @@ int netbsd32_md_ioctl(struct file *, net
  int netbsd32_process_read_regs(struct lwp *, struct reg32 *);
  int netbsd32_process_read_fpregs(struct lwp *, struct fpreg32 *, size_t *);
  
 +int netbsd32_process_write_regs(struct lwp *, const struct reg32 *);
 +int netbsd32_process_write_fpregs(struct lwp *, const struct fpreg32 *, size_t);
 +
  #endif /* _MACHINE_NETBSD32_H_ */
 Index: sys/arch/sparc64/include/ptrace.h
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/sparc64/include/ptrace.h,v
 retrieving revision 1.4
 diff -u -p -r1.4 ptrace.h
 --- sys/arch/sparc64/include/ptrace.h	28 Sep 2016 11:44:16 -0000	1.4
 +++ sys/arch/sparc64/include/ptrace.h	15 Oct 2016 12:40:13 -0000
 @@ -11,6 +11,9 @@
  #define process_read_regs32	netbsd32_process_read_regs
  #define process_read_fpregs32	netbsd32_process_read_fpregs
  
 +#define process_write_regs32	netbsd32_process_write_regs
 +#define process_write_fpregs32	netbsd32_process_write_fpregs
 +
  #define process_reg32		struct reg32
  #define process_fpreg32		struct fpreg32
  #endif
 Index: sys/arch/sparc64/sparc64/netbsd32_machdep.c
 ===================================================================
 RCS file: /cvsroot/src/sys/arch/sparc64/sparc64/netbsd32_machdep.c,v
 retrieving revision 1.109
 diff -u -p -r1.109 netbsd32_machdep.c
 --- sys/arch/sparc64/sparc64/netbsd32_machdep.c	26 Nov 2015 13:15:34 -0000	1.109
 +++ sys/arch/sparc64/sparc64/netbsd32_machdep.c	15 Oct 2016 12:40:14 -0000
 @@ -624,16 +624,15 @@ netbsd32_process_read_regs(struct lwp *l
  	return (0);
  }
  
 -#if 0
  int
  netbsd32_process_write_regs(struct lwp *l, const struct reg32 *regs)
  {
 -	struct trapframe64* tf = p->p_md.md_tf;
 +	struct trapframe64* tf = l->l_md.md_tf;
  	int i;
  
  	tf->tf_pc = regs->r_pc;
  	tf->tf_npc = regs->r_npc;
 -	tf->tf_y = regs->r_pc;
 +	tf->tf_y = regs->r_y;
  	for (i = 0; i < 8; i++) {
  		tf->tf_global[i] = regs->r_global[i];
  		tf->tf_out[i] = regs->r_out[i];
 @@ -643,7 +642,6 @@ netbsd32_process_write_regs(struct lwp *
  		PSRCC_TO_TSTATE(regs->r_psr);
  	return (0);
  }
 -#endif
  
  int
  netbsd32_process_read_fpregs(struct lwp *l, struct fpreg32 *regs, size_t *sz)
 @@ -661,9 +659,9 @@ netbsd32_process_read_fpregs(struct lwp 
  	return 0;
  }
  
 -#if 0
  int
 -netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *regs)
 +netbsd32_process_write_fpregs(struct lwp *l, const struct fpreg32 *regs,
 +    size_t sz)
  {
  	struct fpstate64	*statep;
  	int i;
 @@ -678,7 +676,6 @@ netbsd32_process_write_fpregs(struct lwp
  
  	return 0;
  }
 -#endif
  
  /*
   * 32-bit version of cpu_coredump.
 Index: sys/compat/netbsd32/files.netbsd32
 ===================================================================
 RCS file: /cvsroot/src/sys/compat/netbsd32/files.netbsd32,v
 retrieving revision 1.38
 diff -u -p -r1.38 files.netbsd32
 --- sys/compat/netbsd32/files.netbsd32	3 Dec 2015 11:25:45 -0000	1.38
 +++ sys/compat/netbsd32/files.netbsd32	15 Oct 2016 12:40:14 -0000
 @@ -21,6 +21,7 @@ file	compat/netbsd32/netbsd32_module.c	c
  file	compat/netbsd32/netbsd32_mod.c		compat_netbsd32
  file	compat/netbsd32/netbsd32_mqueue.c	compat_netbsd32 & mqueue
  file	compat/netbsd32/netbsd32_nfssvc.c	compat_netbsd32 & nfsserver
 +file	compat/netbsd32/netbsd32_ptrace.c	compat_netbsd32 & ptrace
  file	compat/netbsd32/netbsd32_select.c	compat_netbsd32
  file	compat/netbsd32/netbsd32_sem.c		compat_netbsd32
  file	compat/netbsd32/netbsd32_signal.c	compat_netbsd32
 Index: sys/compat/netbsd32/netbsd32.h
 ===================================================================
 RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32.h,v
 retrieving revision 1.112
 diff -u -p -r1.112 netbsd32.h
 --- sys/compat/netbsd32/netbsd32.h	23 Sep 2016 14:16:32 -0000	1.112
 +++ sys/compat/netbsd32/netbsd32.h	15 Oct 2016 12:40:17 -0000
 @@ -282,6 +282,16 @@ struct netbsd32_export_args30 {
  /* from <sys/poll.h> */
  typedef netbsd32_pointer_t netbsd32_pollfdp_t;
  
 +/* from <sys/ptrace.h> */
 +typedef netbsd32_pointer_t netbsd32_ptrace_io_descp_t;
 +struct netbsd32_ptrace_io_desc {
 +	int	piod_op;		/* I/O operation */
 +	netbsd32_voidp piod_offs;	/* child offset */
 +	netbsd32_voidp piod_addr;	/* parent offset */
 +	netbsd32_size_t piod_len;	/* request length (in) /
 +					   actual count (out) */
 +};
 +
  /* from <sys/quotactl.h> */
  typedef netbsd32_pointer_t netbsd32_quotactlargsp_t;
  struct netbsd32_quotactlargs {
 Index: sys/compat/netbsd32/netbsd32_netbsd.c
 ===================================================================
 RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_netbsd.c,v
 retrieving revision 1.204
 diff -u -p -r1.204 netbsd32_netbsd.c
 --- sys/compat/netbsd32/netbsd32_netbsd.c	17 Sep 2016 02:44:38 -0000	1.204
 +++ sys/compat/netbsd32/netbsd32_netbsd.c	15 Oct 2016 12:40:17 -0000
 @@ -406,25 +406,6 @@ netbsd32_setuid(struct lwp *l, const str
  }
  
  int
 -netbsd32_ptrace(struct lwp *l, const struct netbsd32_ptrace_args *uap, register_t *retval)
 -{
 -	/* {
 -		syscallarg(int) req;
 -		syscallarg(pid_t) pid;
 -		syscallarg(netbsd32_voidp) addr;
 -		syscallarg(int) data;
 -	} */
 -	struct sys_ptrace_args ua;
 -
 -	NETBSD32TO64_UAP(req);
 -	NETBSD32TO64_UAP(pid);
 -	NETBSD32TOP_UAP(addr, void *);
 -	NETBSD32TO64_UAP(data);
 -
 -	return (*sysent[SYS_ptrace].sy_call)(l, &ua, retval);
 -}
 -
 -int
  netbsd32_accept(struct lwp *l, const struct netbsd32_accept_args *uap, register_t *retval)
  {
  	/* {
 Index: sys/compat/netbsd32/netbsd32_ptrace.c
 ===================================================================
 RCS file: sys/compat/netbsd32/netbsd32_ptrace.c
 diff -N sys/compat/netbsd32/netbsd32_ptrace.c
 --- /dev/null	1 Jan 1970 00:00:00 -0000
 +++ sys/compat/netbsd32/netbsd32_ptrace.c	15 Oct 2016 12:40:17 -0000
 @@ -0,0 +1,217 @@
 +/*	$NetBSD$	*/
 +
 +/*
 + * Copyright (c) 2016 The NetBSD Foundation, Inc.
 + * All rights reserved.
 + *
 + * This code is derived from software contributed to The NetBSD Foundation
 + * by Nick Hudson
 + *
 + * Redistribution and use in source and binary forms, with or without
 + * modification, are permitted provided that the following conditions
 + * are met:
 + * 1. Redistributions of source code must retain the above copyright
 + *    notice, this list of conditions and the following disclaimer.
 + * 2. Redistributions in binary form must reproduce the above copyright
 + *    notice, this list of conditions and the following disclaimer in the
 + *    documentation and/or other materials provided with the distribution.
 + *
 + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
 + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
 + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 + * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
 + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 + * POSSIBILITY OF SUCH DAMAGE.
 + */
 +
 +#include <sys/cdefs.h>
 +__KERNEL_RCSID(0, "$NetBSD$");
 +
 +#if defined(_KERNEL_OPT)
 +#include "opt_ptrace.h"
 +#include "opt_compat_netbsd.h"
 +#endif
 +
 +#include <sys/param.h>
 +#include <sys/module.h>
 +#include <sys/ptrace.h>
 +#include <sys/syscallvar.h>
 +
 +#include <compat/netbsd32/netbsd32.h>
 +#include <compat/netbsd32/netbsd32_syscall.h>
 +#include <compat/netbsd32/netbsd32_syscallargs.h>
 +#include <compat/netbsd32/netbsd32_conv.h>
 +
 +extern struct emul emul_netbsd32;
 +
 +
 +/*
 + * PTRACE methods
 + */
 +
 +static int netbsd32_copyinpiod(struct ptrace_io_desc *, const void *);
 +static void netbsd32_copyoutpiod(const struct ptrace_io_desc *, void *);
 +static int netbsd32_doregs(struct lwp *, struct lwp *, struct uio *);
 +static int netbsd32_dofpregs(struct lwp *, struct lwp *, struct uio *);
 +
 +
 +static int
 +netbsd32_copyinpiod(struct ptrace_io_desc *piod, const void *addr)
 +{
 +	struct netbsd32_ptrace_io_desc piod32;
 +
 +	int error = copyin(addr, &piod32, sizeof(piod32));
 +	if (error)
 +		return error;
 +	piod->piod_op = piod32.piod_op;
 +	piod->piod_offs = NETBSD32PTR64(piod32.piod_offs);
 +	piod->piod_addr = NETBSD32PTR64(piod32.piod_addr);
 +	piod->piod_len = (size_t)piod32.piod_len;
 +
 +	return 0;
 +}
 +
 +static void
 +netbsd32_copyoutpiod(const struct ptrace_io_desc *piod, void *addr)
 +{
 +	struct netbsd32_ptrace_io_desc piod32;
 +
 +	piod32.piod_op = piod->piod_op;
 +	NETBSD32PTR32(piod32.piod_offs, piod->piod_offs);
 +	NETBSD32PTR32(piod32.piod_addr, piod->piod_addr);
 +	piod32.piod_len = (netbsd32_size_t)piod->piod_len;
 +	(void) copyout(&piod32, addr, sizeof(piod32));
 +}
 +
 +
 +static int
 +netbsd32_doregs(struct lwp *curl /*tracer*/,
 +    struct lwp *l /*traced*/,
 +    struct uio *uio)
 +{
 +#if defined(PT_GETREGS) || defined(PT_SETREGS)
 +	process_reg32 r32;
 +	int error;
 +	char *kv;
 +	int kl;
 +
 +	if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r32))
 +		return EINVAL;
 +
 +	kl = sizeof(r32);
 +	kv = (char *)&r32;
 +
 +	kv += uio->uio_offset;
 +	kl -= uio->uio_offset;
 +	if ((size_t)kl > uio->uio_resid)
 +		kl = uio->uio_resid;
 +	error = process_read_regs32(l, &r32);
 +	if (error == 0)
 +		error = uiomove(kv, kl, uio);
 +	if (error == 0 && uio->uio_rw == UIO_WRITE) {
 +		if (l->l_stat != LSSTOP)
 +			error = EBUSY;
 +		else
 +			error = process_write_regs32(l, &r32);
 +	}
 +
 +	uio->uio_offset = 0;
 +	return error;
 +#else
 +	return EINVAL;
 +#endif
 +}
 +
 +static int
 +netbsd32_dofpregs(struct lwp *curl /*tracer*/,
 +    struct lwp *l /*traced*/,
 +    struct uio *uio)
 +{
 +#if defined(PT_GETFPREGS) || defined(PT_SETFPREGS)
 +	process_fpreg32 r32;
 +	int error;
 +	char *kv;
 +	size_t kl;
 +
 +	KASSERT(l->l_proc->p_flag & PK_32);
 +	if (uio->uio_offset < 0 || uio->uio_offset > (off_t)sizeof(r32))
 +		return EINVAL;
 +	kl = sizeof(r32);
 +	kv = (char *)&r32;
 +
 +	kv += uio->uio_offset;
 +	kl -= uio->uio_offset;
 +	if (kl > uio->uio_resid)
 +		kl = uio->uio_resid;
 +
 +	error = process_read_fpregs32(l, &r32, &kl);
 +	if (error == 0)
 +		error = uiomove(kv, kl, uio);
 +	if (error == 0 && uio->uio_rw == UIO_WRITE) {
 +		if (l->l_stat != LSSTOP)
 +			error = EBUSY;
 +		else
 +			error = process_write_fpregs32(l, &r32, kl);
 +	}
 +	uio->uio_offset = 0;
 +	return error;
 +#else
 +	return EINVAL;
 +#endif
 +}
 +
 +static struct ptrace_methods netbsd32_ptm = {
 +	.ptm_copyinpiod = netbsd32_copyinpiod,
 +	.ptm_copyoutpiod = netbsd32_copyoutpiod,
 +	.ptm_doregs = netbsd32_doregs,
 +	.ptm_dofpregs = netbsd32_dofpregs
 +};
 +
 +
 +int
 +netbsd32_ptrace(struct lwp *l, const struct netbsd32_ptrace_args *uap,
 +    register_t *retval)
 +{
 +	/* {
 +		syscallarg(int) req;
 +		syscallarg(pid_t) pid;
 +		syscallarg(netbsd32_voidp *) addr;
 +		syscallarg(int) data;
 +	} */
 +
 +	return do_ptrace(&netbsd32_ptm, l, SCARG(uap, req), SCARG(uap, pid),
 +	    SCARG_P32(uap, addr), SCARG(uap, data), retval);
 +}
 +
 +static const struct syscall_package compat_ptrace_syscalls[] = {
 +	{ NETBSD32_SYS_netbsd32_ptrace, 0, (sy_call_t *)netbsd32_ptrace },
 +	{ 0, 0, NULL },
 +};
 +
 +MODULE(MODULE_CLASS_EXEC, compat_netbsd32_ptrace, "compat_netbsd32");
 +
 +static int
 +compat_netbsd32_ptrace_modcmd(modcmd_t cmd, void *arg)
 +{
 +	int error;
 +
 +	switch (cmd) {
 +	case MODULE_CMD_INIT:
 +		error = syscall_establish(&emul_netbsd32,
 +		    compat_ptrace_syscalls);
 +		break;
 +	case MODULE_CMD_FINI:
 +		error = syscall_disestablish(&emul_netbsd32,
 +		    compat_ptrace_syscalls);
 +		break;
 +	default:
 +		error = ENOTTY;
 +		break;
 +	}
 +	return error;
 +}
 Index: sys/compat/netbsd32/netbsd32_syscalls_autoload.c
 ===================================================================
 RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_syscalls_autoload.c,v
 retrieving revision 1.6
 diff -u -p -r1.6 netbsd32_syscalls_autoload.c
 --- sys/compat/netbsd32/netbsd32_syscalls_autoload.c	23 Sep 2016 14:12:25 -0000	1.6
 +++ sys/compat/netbsd32/netbsd32_syscalls_autoload.c	15 Oct 2016 12:40:18 -0000
 @@ -1,4 +1,4 @@
 -/* $NetBSD: netbsd32_syscalls_autoload.c,v 1.6 2016/09/23 14:12:25 skrll Exp $ */
 +/* $NetBSD$ */
  
  /*
   * System call autoload table.
 @@ -8,10 +8,11 @@
   */
  
  #include <sys/cdefs.h>
 -__KERNEL_RCSID(0, "$NetBSD: netbsd32_syscalls_autoload.c,v 1.6 2016/09/23 14:12:25 skrll Exp $");
 +__KERNEL_RCSID(0, "$NetBSD$");
  
  #include <sys/proc.h>
  static struct sc_autoload netbsd32_syscalls_autoload[] = {
 +	    { NETBSD32_SYS_netbsd32_ptrace, "compat_netbsd32_ptrace" },
  	    { NETBSD32_SYS_netbsd32_nfssvc, "compat_netbsd32_nfssrv" },
  	    { NETBSD32_SYS_compat_10_osemsys, "compat_netbsd32_sysvipc" },
  	    { NETBSD32_SYS_compat_10_omsgsys, "compat_netbsd32_sysvipc" },
 Index: sys/compat/netbsd32/netbsd32_sysent.c
 ===================================================================
 RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_sysent.c,v
 retrieving revision 1.123
 diff -u -p -r1.123 netbsd32_sysent.c
 --- sys/compat/netbsd32/netbsd32_sysent.c	23 Sep 2016 14:12:25 -0000	1.123
 +++ sys/compat/netbsd32/netbsd32_sysent.c	15 Oct 2016 12:40:18 -0000
 @@ -1,4 +1,4 @@
 -/* $NetBSD: netbsd32_sysent.c,v 1.123 2016/09/23 14:12:25 skrll Exp $ */
 +/* $NetBSD$ */
  
  /*
   * System call switch table.
 @@ -8,7 +8,7 @@
   */
  
  #include <sys/cdefs.h>
 -__KERNEL_RCSID(0, "$NetBSD: netbsd32_sysent.c,v 1.123 2016/09/23 14:12:25 skrll Exp $");
 +__KERNEL_RCSID(0, "$NetBSD$");
  
  #if defined(_KERNEL_OPT)
  #include "opt_compat_netbsd.h"
 @@ -220,7 +220,7 @@ struct sysent netbsd32_sysent[] = {
  	},		/* 25 = geteuid */
  	{
  		ns(struct netbsd32_ptrace_args),
 -		.sy_call = (sy_call_t *)netbsd32_ptrace
 +		.sy_call = (sy_call_t *)sys_nomodule
  	},		/* 26 = netbsd32_ptrace */
  	{
  		ns(struct netbsd32_recvmsg_args),
 Index: sys/compat/netbsd32/netbsd32_systrace_args.c
 ===================================================================
 RCS file: /cvsroot/src/sys/compat/netbsd32/netbsd32_systrace_args.c,v
 retrieving revision 1.14
 diff -u -p -r1.14 netbsd32_systrace_args.c
 --- sys/compat/netbsd32/netbsd32_systrace_args.c	23 Sep 2016 14:12:25 -0000	1.14
 +++ sys/compat/netbsd32/netbsd32_systrace_args.c	15 Oct 2016 12:40:21 -0000
 @@ -1,4 +1,4 @@
 -/* $NetBSD: netbsd32_systrace_args.c,v 1.14 2016/09/23 14:12:25 skrll Exp $ */
 +/* $NetBSD$ */
  
  /*
   * System call argument to DTrace register array converstion.
 Index: sys/compat/netbsd32/syscalls.master
 ===================================================================
 RCS file: /cvsroot/src/sys/compat/netbsd32/syscalls.master,v
 retrieving revision 1.114
 diff -u -p -r1.114 syscalls.master
 --- sys/compat/netbsd32/syscalls.master	23 Sep 2016 14:10:28 -0000	1.114
 +++ sys/compat/netbsd32/syscalls.master	15 Oct 2016 12:40:21 -0000
 @@ -99,7 +99,8 @@
  23	STD		{ int|netbsd32||setuid(uid_t uid); }
  24	NOARGS 		{ uid_t|sys||getuid(void); }
  25	NOARGS		{ uid_t|sys||geteuid(void); }
 -26	STD		{ int|netbsd32||ptrace(int req, pid_t pid, \
 +26	STD MODULAR compat_netbsd32_ptrace \
 +			{ int|netbsd32||ptrace(int req, pid_t pid, \
  			    netbsd32_voidp addr, int data); }
  27	STD		{ netbsd32_ssize_t|netbsd32||recvmsg(int s, \
  			    netbsd32_msghdrp_t msg, int flags); }
 Index: sys/kern/sys_process.c
 ===================================================================
 RCS file: /cvsroot/src/sys/kern/sys_process.c,v
 retrieving revision 1.173
 diff -u -p -r1.173 sys_process.c
 --- sys/kern/sys_process.c	15 Oct 2016 09:09:55 -0000	1.173
 +++ sys/kern/sys_process.c	15 Oct 2016 12:40:21 -0000
 @@ -120,9 +120,11 @@
  #include <sys/cdefs.h>
  __KERNEL_RCSID(0, "$NetBSD: sys_process.c,v 1.173 2016/10/15 09:09:55 skrll Exp $");
  
 +#ifdef _KERNEL_OPT
  #include "opt_ptrace.h"
  #include "opt_ktrace.h"
  #include "opt_pax.h"
 +#endif
  
  #include <sys/param.h>
  #include <sys/systm.h>
 @@ -231,6 +233,26 @@ ptrace_init(void)
  	    ptrace_listener_cb, NULL);
  }
  
 +static int
 +ptrace_copyinpiod(struct ptrace_io_desc *piod, const void *addr)
 +{
 +	return copyin(addr, piod, sizeof(*piod));
 +}
 +
 +static void
 +ptrace_copyoutpiod(const struct ptrace_io_desc *piod, void *addr)
 +{
 +	(void) copyout(piod, addr, sizeof(*piod));
 +}
 +
 +
 +static struct ptrace_methods native_ptm = {
 +	.ptm_copyinpiod = ptrace_copyinpiod,
 +	.ptm_copyoutpiod = ptrace_copyoutpiod,
 +	.ptm_doregs = process_doregs,
 +	.ptm_dofpregs = process_dofpregs,
 +};
 +
  /*
   * Process debugging system call.
   */
 @@ -243,6 +265,15 @@ sys_ptrace(struct lwp *l, const struct s
  		syscallarg(void *) addr;
  		syscallarg(int) data;
  	} */
 +
 +	return do_ptrace(&native_ptm, l, SCARG(uap, req), SCARG(uap, pid),
 +	    SCARG(uap, addr), SCARG(uap, data), retval);
 +}
 +
 +int
 +do_ptrace(struct ptrace_methods *ptm, struct lwp *l, int req, pid_t pid,
 +    void *addr, int data, register_t *retval)
 +{
  	struct proc *p = l->l_proc;
  	struct lwp *lt;
  #ifdef PT_STEP
 @@ -256,15 +287,13 @@ sys_ptrace(struct lwp *l, const struct s
  	struct ptrace_state ps;
  	struct ptrace_lwpinfo pl;
  	struct vmspace *vm;
 -	int error, write, tmp, req, pheld;
 +	int error, write, tmp, pheld;
  	int signo = 0;
  	int resume_all;
  	ksiginfo_t ksi;
  	char *path;
  	int len = 0;
 -
  	error = 0;
 -	req = SCARG(uap, req);
  
  	/*
  	 * If attaching or detaching, we need to get a write hold on the
 @@ -278,7 +307,7 @@ sys_ptrace(struct lwp *l, const struct s
  		mutex_enter(t->p_lock);
  	} else {
  		/* Find the process we're supposed to be operating on. */
 -		t = proc_find(SCARG(uap, pid));
 +		t = proc_find(pid);
  		if (t == NULL) {
  			mutex_exit(proc_lock);
  			return ESRCH;
 @@ -507,13 +536,13 @@ sys_ptrace(struct lwp *l, const struct s
  		/*
  		 * Can't write to a RAS
  		 */
 -		if (ras_lookup(t, SCARG(uap, addr)) != (void *)-1) {
 +		if (ras_lookup(t, addr) != (void *)-1) {
  			error = EACCES;
  			break;
  		}
  #endif
  		write = 1;
 -		tmp = SCARG(uap, data);
 +		tmp = data;
  		/* FALLTHROUGH */
  
  	case  PT_READ_I:		/* XXX no separate I and D spaces */
 @@ -523,7 +552,7 @@ sys_ptrace(struct lwp *l, const struct s
  		iov.iov_len = sizeof(tmp);
  		uio.uio_iov = &iov;
  		uio.uio_iovcnt = 1;
 -		uio.uio_offset = (off_t)(unsigned long)SCARG(uap, addr);
 +		uio.uio_offset = (off_t)(unsigned long)addr;
  		uio.uio_resid = sizeof(tmp);
  		uio.uio_rw = write ? UIO_WRITE : UIO_READ;
  		UIO_SETUP_SYSSPACE(&uio);
 @@ -534,7 +563,7 @@ sys_ptrace(struct lwp *l, const struct s
  		break;
  
  	case  PT_IO:
 -		error = copyin(SCARG(uap, addr), &piod, sizeof(piod));
 +		error = ptm->ptm_copyinpiod(&piod, addr);
  		if (error)
  			break;
  
 @@ -555,7 +584,7 @@ sys_ptrace(struct lwp *l, const struct s
  			/*
  			 * Can't write to a RAS
  			 */
 -			if (ras_lookup(t, SCARG(uap, addr)) != (void *)-1) {
 +			if (ras_lookup(t, addr) != (void *)-1) {
  				return EACCES;
  			}
  			uio.uio_rw = UIO_WRITE;
 @@ -586,14 +615,15 @@ sys_ptrace(struct lwp *l, const struct s
  
  		error = process_domem(l, lt, &uio);
  		piod.piod_len -= uio.uio_resid;
 -		(void) copyout(&piod, SCARG(uap, addr), sizeof(piod));
 +		(void) ptm->ptm_copyoutpiod(&piod, addr);
 +
  		uvmspace_free(vm);
  		break;
  
  	case  PT_DUMPCORE:
 -		if ((path = SCARG(uap, addr)) != NULL) {
 +		if ((path = addr) != NULL) {
  			char *dst;
 -			len = SCARG(uap, data);
 +			len = data;
  
  			if (len < 0 || len >= MAXPATHLEN) {
  				error = EINVAL;
 @@ -648,7 +678,7 @@ sys_ptrace(struct lwp *l, const struct s
  		 * For operations other than PT_STEP, data > 0 means
  		 * data is the signo to deliver to the process.
  		 */
 -		tmp = SCARG(uap, data);
 +		tmp = data;
  		if (tmp >= 0) {
  #ifdef PT_STEP
  			if (req == PT_STEP)
 @@ -697,8 +727,8 @@ sys_ptrace(struct lwp *l, const struct s
  		}
  
  		/* If the address parameter is not (int *)1, set the pc. */
 -		if ((int *)SCARG(uap, addr) != (int *)1) {
 -			error = process_set_pc(lt, SCARG(uap, addr));
 +		if ((int *)addr != (int *)1) {
 +			error = process_set_pc(lt, addr);
  			if (error != 0)
  				break;
  		}
 @@ -797,26 +827,26 @@ sys_ptrace(struct lwp *l, const struct s
  		goto sendsig;
  
  	case  PT_GET_EVENT_MASK:
 -		if (SCARG(uap, data) != sizeof(pe)) {
 +		if (data != sizeof(pe)) {
  			DPRINTF(("ptrace(%d): %d != %zu\n", req,
 -			    SCARG(uap, data), sizeof(pe)));
 +			    data, sizeof(pe)));
  			error = EINVAL;
  			break;
  		}
  		memset(&pe, 0, sizeof(pe));
  		pe.pe_set_event = ISSET(t->p_slflag, PSL_TRACEFORK) ?
  		    PTRACE_FORK : 0;
 -		error = copyout(&pe, SCARG(uap, addr), sizeof(pe));
 +		error = copyout(&pe, addr, sizeof(pe));
  		break;
  
  	case  PT_SET_EVENT_MASK:
 -		if (SCARG(uap, data) != sizeof(pe)) {
 -			DPRINTF(("ptrace(%d): %d != %zu\n", req,
 -			    SCARG(uap, data), sizeof(pe)));
 +		if (data != sizeof(pe)) {
 +			DPRINTF(("ptrace(%d): %d != %zu\n", req, data,
 +			    sizeof(pe)));
  			error = EINVAL;
  			break;
  		}
 -		if ((error = copyin(SCARG(uap, addr), &pe, sizeof(pe))) != 0)
 +		if ((error = copyin(addr, &pe, sizeof(pe))) != 0)
  			return error;
  		if (pe.pe_set_event & PTRACE_FORK)
  			SET(t->p_slflag, PSL_TRACEFORK);
 @@ -825,9 +855,9 @@ sys_ptrace(struct lwp *l, const struct s
  		break;
  
  	case  PT_GET_PROCESS_STATE:
 -		if (SCARG(uap, data) != sizeof(ps)) {
 -			DPRINTF(("ptrace(%d): %d != %zu\n", req,
 -			    SCARG(uap, data), sizeof(ps)));
 +		if (data != sizeof(ps)) {
 +			DPRINTF(("ptrace(%d): %d != %zu\n", req, data,
 +			    sizeof(ps)));
  			error = EINVAL;
  			break;
  		}
 @@ -836,17 +866,17 @@ sys_ptrace(struct lwp *l, const struct s
  			ps.pe_report_event = PTRACE_FORK;
  			ps.pe_other_pid = t->p_fpid;
  		}
 -		error = copyout(&ps, SCARG(uap, addr), sizeof(ps));
 +		error = copyout(&ps, addr, sizeof(ps));
  		break;
  
  	case PT_LWPINFO:
 -		if (SCARG(uap, data) != sizeof(pl)) {
 -			DPRINTF(("ptrace(%d): %d != %zu\n", req,
 -			    SCARG(uap, data), sizeof(pl)));
 +		if (data != sizeof(pl)) {
 +			DPRINTF(("ptrace(%d): %d != %zu\n", req, data,
 +			    sizeof(pl)));
  			error = EINVAL;
  			break;
  		}
 -		error = copyin(SCARG(uap, addr), &pl, sizeof(pl));
 +		error = copyin(addr, &pl, sizeof(pl));
  		if (error)
  			break;
  		tmp = pl.pl_lwpid;
 @@ -875,7 +905,7 @@ sys_ptrace(struct lwp *l, const struct s
  		}
  		mutex_exit(t->p_lock);
  
 -		error = copyout(&pl, SCARG(uap, addr), sizeof(pl));
 +		error = copyout(&pl, addr, sizeof(pl));
  		break;
  
  #ifdef PT_SETREGS
 @@ -887,7 +917,7 @@ sys_ptrace(struct lwp *l, const struct s
  		/* write = 0 done above. */
  #endif
  #if defined(PT_SETREGS) || defined(PT_GETREGS)
 -		tmp = SCARG(uap, data);
 +		tmp = data;
  		if (tmp != 0 && t->p_nlwps > 1) {
  			lwp_delref(lt);
  			mutex_enter(t->p_lock);
 @@ -903,19 +933,19 @@ sys_ptrace(struct lwp *l, const struct s
  		if (!process_validregs(lt))
  			error = EINVAL;
  		else {
 -			error = proc_vmspace_getref(l->l_proc, &vm);
 +			error = proc_vmspace_getref(p, &vm);
  			if (error)
  				break;
 -			iov.iov_base = SCARG(uap, addr);
 -			iov.iov_len = sizeof(struct reg);
 +			iov.iov_base = addr;
 +			iov.iov_len = PROC_REGSZ(p);
  			uio.uio_iov = &iov;
  			uio.uio_iovcnt = 1;
  			uio.uio_offset = 0;
 -			uio.uio_resid = sizeof(struct reg);
 +			uio.uio_resid = iov.iov_len;
  			uio.uio_rw = write ? UIO_WRITE : UIO_READ;
  			uio.uio_vmspace = vm;
  
 -			error = process_doregs(l, lt, &uio);
 +			error = ptm->ptm_doregs(l, lt, &uio);
  			uvmspace_free(vm);
  		}
  		break;
 @@ -930,7 +960,7 @@ sys_ptrace(struct lwp *l, const struct s
  		/* write = 0 done above. */
  #endif
  #if defined(PT_SETFPREGS) || defined(PT_GETFPREGS)
 -		tmp = SCARG(uap, data);
 +		tmp = data;
  		if (tmp != 0 && t->p_nlwps > 1) {
  			lwp_delref(lt);
  			mutex_enter(t->p_lock);
 @@ -946,19 +976,19 @@ sys_ptrace(struct lwp *l, const struct s
  		if (!process_validfpregs(lt))
  			error = EINVAL;
  		else {
 -			error = proc_vmspace_getref(l->l_proc, &vm);
 +			error = proc_vmspace_getref(p, &vm);
  			if (error)
  				break;
 -			iov.iov_base = SCARG(uap, addr);
 -			iov.iov_len = sizeof(struct fpreg);
 +			iov.iov_base = addr;
 +			iov.iov_len = PROC_FPREGSZ(p);
  			uio.uio_iov = &iov;
  			uio.uio_iovcnt = 1;
  			uio.uio_offset = 0;
 -			uio.uio_resid = sizeof(struct fpreg);
 +			uio.uio_resid = iov.iov_len;
  			uio.uio_rw = write ? UIO_WRITE : UIO_READ;
  			uio.uio_vmspace = vm;
  
 -			error = process_dofpregs(l, lt, &uio);
 +			error = ptm->ptm_dofpregs(l, lt, &uio);
  			uvmspace_free(vm);
  		}
  		break;
 @@ -966,8 +996,7 @@ sys_ptrace(struct lwp *l, const struct s
  
  #ifdef __HAVE_PTRACE_MACHDEP
  	PTRACE_MACHDEP_REQUEST_CASES
 -		error = ptrace_machdep_dorequest(l, lt,
 -		    req, SCARG(uap, addr), SCARG(uap, data));
 +		error = ptrace_machdep_dorequest(l, lt, req, addr, data);
  		break;
  #endif
  	}
 Index: sys/modules/Makefile
 ===================================================================
 RCS file: /cvsroot/src/sys/modules/Makefile,v
 retrieving revision 1.180
 diff -u -p -r1.180 Makefile
 --- sys/modules/Makefile	15 Oct 2016 12:38:03 -0000	1.180
 +++ sys/modules/Makefile	15 Oct 2016 12:40:21 -0000
 @@ -236,6 +236,7 @@ SUBDIR+=	wmimsi
  SUBDIR+=	compat_netbsd32
  SUBDIR+=	compat_netbsd32_mqueue
  SUBDIR+=	compat_netbsd32_nfssrv
 +SUBDIR+=	compat_netbsd32_ptrace
  SUBDIR+=	compat_netbsd32_sysvipc
  .endif
  
 @@ -244,6 +245,7 @@ SUBDIR+=	compat_linux32
  SUBDIR+=	compat_netbsd32
  SUBDIR+=	compat_netbsd32_mqueue
  SUBDIR+=	compat_netbsd32_nfssrv
 +SUBDIR+=	compat_netbsd32_ptrace
  SUBDIR+=	compat_netbsd32_sysvipc
  .endif
  
 Index: sys/sys/proc.h
 ===================================================================
 RCS file: /cvsroot/src/sys/sys/proc.h,v
 retrieving revision 1.334
 diff -u -p -r1.334 proc.h
 --- sys/sys/proc.h	29 Sep 2016 20:40:53 -0000	1.334
 +++ sys/sys/proc.h	15 Oct 2016 12:40:22 -0000
 @@ -557,6 +557,10 @@ _proclist_skipmarker(struct proc *p0)
  }
  
  #define PROC_PTRSZ(p) (((p)->p_flag & PK_32) ? sizeof(int) : sizeof(void *))
 +#define PROC_REGSZ(p) (((p)->p_flag & PK_32) ? \
 +    sizeof(process_reg32) : sizeof(struct reg))
 +#define PROC_FPREGSZ(p) (((p)->p_flag & PK_32) ? \
 +    sizeof(process_fpreg32) : sizeof(struct fpreg))
  
  /*
   * PROCLIST_FOREACH: iterate on the given proclist, skipping PK_MARKER ones.
 Index: sys/sys/ptrace.h
 ===================================================================
 RCS file: /cvsroot/src/sys/sys/ptrace.h,v
 retrieving revision 1.46
 diff -u -p -r1.46 ptrace.h
 --- sys/sys/ptrace.h	2 Jul 2015 03:47:54 -0000	1.46
 +++ sys/sys/ptrace.h	15 Oct 2016 12:40:22 -0000
 @@ -139,6 +139,13 @@ struct fpreg;
  #endif
  #endif
  
 +struct ptrace_methods {
 +	int (*ptm_copyinpiod)(struct ptrace_io_desc *, const void *);
 +	void (*ptm_copyoutpiod)(const struct ptrace_io_desc *, void *);
 +	int (*ptm_doregs)(struct lwp *, struct lwp *, struct uio *);
 +	int (*ptm_dofpregs)(struct lwp *, struct lwp *, struct uio *);
 +};
 +
  void	ptrace_init(void);
  
  int	process_doregs(struct lwp *, struct lwp *, struct uio *);
 @@ -153,6 +160,10 @@ void	process_stoptrace(void);
  
  void	proc_reparent(struct proc *, struct proc *);
  
 +
 +int	do_ptrace(struct ptrace_methods *, struct lwp *, int, pid_t, void *,
 +	    int, register_t *);
 +
  /*
   * 64bit architectures that support 32bit emulation (amd64 and sparc64)
   * will #define process_read_regs32 to netbsd32_process_read_regs (etc).
 @@ -180,9 +191,21 @@ int	process_set_pc(struct lwp *, void *)
  int	process_sstep(struct lwp *, int);
  #ifdef PT_SETFPREGS
  int	process_write_fpregs(struct lwp *, const struct fpreg *, size_t);
 +#ifndef process_write_fpregs32
 +#define process_write_fpregs32	process_write_fpregs
 +#endif
 +#ifndef process_write_fpregs64
 +#define process_write_fpregs64	process_write_fpregs
 +#endif
  #endif
  #ifdef PT_SETREGS
  int	process_write_regs(struct lwp *, const struct reg *);
 +#ifndef process_write_regs32
 +#define process_write_regs32	process_write_regs
 +#endif
 +#ifndef process_write_regs64
 +#define process_write_regs64	process_write_regs
 +#endif
  #endif
  
  #ifdef __HAVE_PROCFS_MACHDEP
 
 
 
 --------------050409000904030005020102
 Content-Type: text/plain; charset=UTF-8;
  name="Makefile"
 Content-Transfer-Encoding: base64
 Content-Disposition: attachment;
  filename="Makefile"
 
 IwkkTmV0QlNEJAoKLmluY2x1ZGUgIi4uL01ha2VmaWxlLmluYyIKLmluY2x1ZGUgIi4uL01h
 a2VmaWxlLmFzc3ltIgoKS01PRD0JY29tcGF0X25ldGJzZDMyX3B0cmFjZQoKQ1BQRkxBR1Mr
 PQktRENPTVBBVF9ORVRCU0QzMgpDUFBGTEFHUys9CS1EUFRSQUNFCkNQUEZMQUdTKz0JLURQ
 VF9TRVRSRUdTIC1EUFRfR0VUUkVHUwoKLlBBVEg6CSR7U30vY29tcGF0L25ldGJzZDMyClNS
 Q1MrPQluZXRic2QzMl9wdHJhY2UuYwoKLmluY2x1ZGUgPGJzZC5rbW9kdWxlLm1rPgoK
 --------------050409000904030005020102--
 


Home | Main Index | Thread Index | Old Index