From 62919d788b37bba3390d9b9ed29ff5220d09840e Mon Sep 17 00:00:00 2001 From: Peter Wemm Date: Thu, 30 Jun 2005 07:49:22 +0000 Subject: [PATCH] Jumbo-commit to enhance 32 bit application support on 64 bit kernels. This is good enough to be able to run a RELENG_4 gdb binary against a RELENG_4 application, along with various other tools (eg: 4.x gcore). We use this at work. ia32_reg.[ch]: handle the 32 bit register file format, used by ptrace, procfs and core dumps. procfs_*regs.c: vary the format of proc/XXX/*regs depending on the client and target application. procfs_map.c: Don't print a 64 bit value to 32 bit consumers, or their sscanf fails. They expect an unsigned long. imgact_elf.c: produce a valid 32 bit coredump for 32 bit apps. sys_process.c: handle 32 bit consumers debugging 32 bit targets. Note that 64 bit consumers can still debug 32 bit targets. IA64 has got stubs for ia32_reg.c. Known limitations: a 5.x/6.x gdb uses get/setcontext(), which isn't implemented in the 32/64 wrapper yet. We also make a tiny patch to gdb pacify it over conflicting formats of ld-elf.so.1. Approved by: re --- sys/amd64/ia32/ia32_reg.c | 224 ++++++++++++++++++++++++++++++++++ sys/compat/ia32/ia32_reg.h | 141 +++++++++++++++++++++ sys/conf/files.amd64 | 1 + sys/conf/files.ia64 | 1 + sys/fs/procfs/procfs_dbregs.c | 49 +++++++- sys/fs/procfs/procfs_fpregs.c | 49 +++++++- sys/fs/procfs/procfs_ioctl.c | 35 ++++++ sys/fs/procfs/procfs_map.c | 27 +++- sys/fs/procfs/procfs_regs.c | 49 +++++++- sys/ia64/ia32/ia32_reg.c | 82 +++++++++++++ sys/kern/imgact_elf.c | 50 ++++++-- sys/kern/kern_clock.c | 33 ++++- sys/kern/sys_process.c | 200 ++++++++++++++++++++++++++---- sys/sys/ptrace.h | 11 ++ 14 files changed, 908 insertions(+), 44 deletions(-) create mode 100644 sys/amd64/ia32/ia32_reg.c create mode 100644 sys/compat/ia32/ia32_reg.h create mode 100644 sys/ia64/ia32/ia32_reg.c diff --git a/sys/amd64/ia32/ia32_reg.c b/sys/amd64/ia32/ia32_reg.c new file mode 100644 index 000000000000..4f75e4dc51eb --- /dev/null +++ b/sys/amd64/ia32/ia32_reg.c @@ -0,0 +1,224 @@ +/*- + * Copyright (c) 2005 Peter Wemm + * All rights reserved. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL) +#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0) + +int +fill_regs32(struct thread *td, struct reg32 *regs) +{ + struct pcb *pcb; + struct trapframe *tp; + + tp = td->td_frame; + pcb = td->td_pcb; + regs->r_fs = pcb->pcb_fs; + regs->r_es = pcb->pcb_es; + regs->r_ds = pcb->pcb_ds; + regs->r_edi = tp->tf_rdi; + regs->r_esi = tp->tf_rsi; + regs->r_ebp = tp->tf_rbp; + regs->r_ebx = tp->tf_rbx; + regs->r_edx = tp->tf_rdx; + regs->r_ecx = tp->tf_rcx; + regs->r_eax = tp->tf_rax; + regs->r_eip = tp->tf_rip; + regs->r_cs = tp->tf_cs; + regs->r_eflags = tp->tf_rflags; + regs->r_esp = tp->tf_rsp; + regs->r_ss = tp->tf_ss; + regs->r_gs = pcb->pcb_gs; + return (0); +} + +int +set_regs32(struct thread *td, struct reg32 *regs) +{ + struct pcb *pcb; + struct trapframe *tp; + + tp = td->td_frame; + if (!EFL_SECURE(regs->r_eflags, tp->tf_rflags) || !CS_SECURE(regs->r_cs)) + return (EINVAL); + pcb = td->td_pcb; + load_fs(regs->r_fs); + pcb->pcb_fs = regs->r_fs; + load_es(regs->r_es); + pcb->pcb_es = regs->r_es; + load_ds(regs->r_ds); + pcb->pcb_ds = regs->r_ds; + tp->tf_rdi = regs->r_edi; + tp->tf_rsi = regs->r_esi; + tp->tf_rbp = regs->r_ebp; + tp->tf_rbx = regs->r_ebx; + tp->tf_rdx = regs->r_edx; + tp->tf_rcx = regs->r_ecx; + tp->tf_rax = regs->r_eax; + tp->tf_rip = regs->r_eip; + tp->tf_cs = regs->r_cs; + tp->tf_rflags = regs->r_eflags; + tp->tf_rsp = regs->r_esp; + tp->tf_ss = regs->r_ss; + load_gs(regs->r_gs); + pcb->pcb_gs = regs->r_gs; + return (0); +} + +int +fill_fpregs32(struct thread *td, struct fpreg32 *regs) +{ + struct save87 *sv_87 = (struct save87 *)regs; + struct env87 *penv_87 = &sv_87->sv_env; + struct savefpu *sv_fpu = &td->td_pcb->pcb_save; + struct envxmm *penv_xmm = &sv_fpu->sv_env; + int i; + + bzero(regs, sizeof(*regs)); + + /* FPU control/status */ + penv_87->en_cw = penv_xmm->en_cw; + penv_87->en_sw = penv_xmm->en_sw; + penv_87->en_tw = penv_xmm->en_tw; + /* + * XXX for en_fip/fcs/foo/fos, check if the fxsave format + * uses the old-style layout for 32 bit user apps. If so, + * read the ip and operand segment registers from there. + * For now, use the process's %cs/%ds. + */ + penv_87->en_fip = penv_xmm->en_rip; + penv_87->en_fcs = td->td_frame->tf_cs; + penv_87->en_opcode = penv_xmm->en_opcode; + penv_87->en_foo = penv_xmm->en_rdp; + penv_87->en_fos = td->td_pcb->pcb_ds; + + /* FPU registers */ + for (i = 0; i < 8; ++i) + sv_87->sv_ac[i] = sv_fpu->sv_fp[i].fp_acc; + + return (0); +} + +int +set_fpregs32(struct thread *td, struct fpreg32 *regs) +{ + struct save87 *sv_87 = (struct save87 *)regs; + struct env87 *penv_87 = &sv_87->sv_env; + struct savefpu *sv_fpu = &td->td_pcb->pcb_save; + struct envxmm *penv_xmm = &sv_fpu->sv_env; + int i; + + /* FPU control/status */ + penv_xmm->en_cw = penv_87->en_cw; + penv_xmm->en_sw = penv_87->en_sw; + penv_xmm->en_tw = penv_87->en_tw; + penv_xmm->en_rip = penv_87->en_fip; + /* penv_87->en_fcs and en_fos ignored, see above */ + penv_xmm->en_opcode = penv_87->en_opcode; + penv_xmm->en_rdp = penv_87->en_foo; + + /* FPU registers */ + for (i = 0; i < 8; ++i) + sv_fpu->sv_fp[i].fp_acc = sv_87->sv_ac[i]; + for (i = 8; i < 16; ++i) + bzero(&sv_fpu->sv_fp[i].fp_acc, sizeof(sv_fpu->sv_fp[i].fp_acc)); + + return (0); +} + +int +fill_dbregs32(struct thread *td, struct dbreg32 *regs) +{ + struct dbreg dr; + int err, i; + + err = fill_dbregs(td, &dr); + for (i = 0; i < 8; i++) + regs->dr[i] = dr.dr[i]; + for (i = 8; i < 16; i++) + regs->dr[i] = 0; + return (err); +} + +int +set_dbregs32(struct thread *td, struct dbreg32 *regs) +{ + struct dbreg dr; + int i; + + for (i = 0; i < 8; i++) + dr.dr[i] = regs->dr[i]; + for (i = 8; i < 16; i++) + dr.dr[i] = 0; + return (set_dbregs(td, &dr)); +} diff --git a/sys/compat/ia32/ia32_reg.h b/sys/compat/ia32/ia32_reg.h new file mode 100644 index 000000000000..5a9cdf2eebf9 --- /dev/null +++ b/sys/compat/ia32/ia32_reg.h @@ -0,0 +1,141 @@ +/*- + * Copyright (c) 1990 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * 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. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + * + * from: @(#)reg.h 5.5 (Berkeley) 1/18/91 + * $FreeBSD$ + */ + +#ifndef _COMPAT_IA32_IA32_REG_H_ +#define _COMPAT_IA32_IA32_REG_H_ + +/* + * Register set accessible via /proc/$pid/regs and PT_{SET,GET}REGS. + */ +struct reg32 { + unsigned int r_fs; + unsigned int r_es; + unsigned int r_ds; + unsigned int r_edi; + unsigned int r_esi; + unsigned int r_ebp; + unsigned int r_isp; + unsigned int r_ebx; + unsigned int r_edx; + unsigned int r_ecx; + unsigned int r_eax; + unsigned int r_trapno; + unsigned int r_err; + unsigned int r_eip; + unsigned int r_cs; + unsigned int r_eflags; + unsigned int r_esp; + unsigned int r_ss; + unsigned int r_gs; +}; + +/* + * Register set accessible via /proc/$pid/fpregs. + */ +struct fpreg32 { + unsigned int fpr_env[7]; + unsigned char fpr_acc[8][10]; + unsigned int fpr_ex_sw; + unsigned char fpr_pad[64]; +}; + +/* + * Register set accessible via /proc/$pid/dbregs. + */ +struct dbreg32 { + unsigned int dr[8]; /* debug registers */ +}; + +/* Environment information of floating point unit */ +struct env87 { + int en_cw; /* control word (16bits) */ + int en_sw; /* status word (16bits) */ + int en_tw; /* tag word (16bits) */ + int en_fip; /* floating point instruction pointer */ + u_short en_fcs; /* floating code segment selector */ + u_short en_opcode; /* opcode last executed (11 bits ) */ + int en_foo; /* floating operand offset */ + int en_fos; /* floating operand segment selector */ +}; + +#ifdef __ia64__ +/* Layout of an x87 fpu register (amd64 gets this elsewhere) */ +struct fpacc87 { + u_char fp_bytes[10]; +}; +#endif + +/* Floating point context */ +struct save87 { + struct env87 sv_env; /* floating point control/status */ + struct fpacc87 sv_ac[8]; /* accumulator contents, 0-7 */ + u_char sv_pad0[4]; /* padding for (now unused) saved status word */ + u_char sv_pad[64]; /* padding; used by emulators */ +}; + + +/* + * Alternative layouts for + * Used in core dumps, the reason for this file existing. + */ +struct prstatus32 { + int pr_version; + u_int pr_statussz; + u_int pr_gregsetsz; + u_int pr_fpregsetsz; + int pr_osreldate; + int pr_cursig; + pid_t pr_pid; + struct reg32 pr_reg; +}; + +struct prpsinfo32 { + int pr_version; + u_int pr_psinfosz; + char pr_fname[PRFNAMESZ+1]; + char pr_psargs[PRARGSZ+1]; +}; + +/* + * Wrappers and converters. + */ +int fill_regs32(struct thread *, struct reg32 *); +int set_regs32(struct thread *, struct reg32 *); +int fill_fpregs32(struct thread *, struct fpreg32 *); +int set_fpregs32(struct thread *, struct fpreg32 *); +int fill_dbregs32(struct thread *, struct dbreg32 *); +int set_dbregs32(struct thread *, struct dbreg32 *); + +#endif /* !_COMPAT_IA32_IA32_REG_H_ */ diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index a2b594ce25b1..a1b201fa4425 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -188,6 +188,7 @@ pci/agp_intel.c optional agp # IA32 binary support # #amd64/ia32/ia32_exception.S optional compat_ia32 +amd64/ia32/ia32_reg.c optional compat_ia32 amd64/ia32/ia32_signal.c optional compat_ia32 amd64/ia32/ia32_sigtramp.S optional compat_ia32 amd64/ia32/ia32_syscall.c optional compat_ia32 diff --git a/sys/conf/files.ia64 b/sys/conf/files.ia64 index 40be4506bf4e..856e5c5d9106 100644 --- a/sys/conf/files.ia64 +++ b/sys/conf/files.ia64 @@ -89,6 +89,7 @@ ia64/acpica/madt.c optional acpi ia64/disasm/disasm_decode.c standard ia64/disasm/disasm_extract.c standard ia64/disasm/disasm_format.c standard +ia64/ia32/ia32_reg.c optional compat_ia32 ia64/ia32/ia32_signal.c optional compat_ia32 ia64/ia32/ia32_sigtramp.c optional compat_ia32 ia64/ia32/ia32_trap.c optional compat_ia32 diff --git a/sys/fs/procfs/procfs_dbregs.c b/sys/fs/procfs/procfs_dbregs.c index 0e129bbafd39..c30f231c67a9 100644 --- a/sys/fs/procfs/procfs_dbregs.c +++ b/sys/fs/procfs/procfs_dbregs.c @@ -43,6 +43,8 @@ * $FreeBSD$ */ +#include "opt_compat.h" + #include #include #include @@ -56,11 +58,42 @@ #include #include +#ifdef COMPAT_IA32 +#include +#include +#include + +extern struct sysentvec ia32_freebsd_sysvec; +/* + * PROC(write, dbregs, td2, &r) becomes + * proc_write_dbregs(td2, &r) or + * proc_write_dbregs32(td2, &r32) + * + * UIOMOVE_FROMBUF(r, uio) becomes + * uiomove_frombuf(&r, sizeof(r), uio) or + * uiomove_frombuf(&r32, sizeof(r32), uio) + */ +#define PROC(d, w, t, r) wrap32 ? \ + proc_ ## d ## _ ## w ## 32(t, r ## 32) : \ + proc_ ## d ## _ ## w(t, r) +#define UIOMOVE_FROMBUF(k, u) wrap32 ? \ + uiomove_frombuf(& k ## 32, sizeof(k ## 32), u) : \ + uiomove_frombuf(& k, sizeof(k), u) +#else +#define PROC(d, w, t, r) proc_ ## d ## _ ## w(t, r) +#define UIOMOVE_FROMBUF(k, u) uiomove_frombuf(& k, sizeof(k), u) +#endif + int procfs_doprocdbregs(PFS_FILL_ARGS) { int error; struct dbreg r; + struct thread *td2; +#ifdef COMPAT_IA32 + struct dbreg32 r32; + int wrap32 = 0; +#endif PROC_LOCK(p); KASSERT(p->p_lock > 0, ("proc not held")); @@ -70,10 +103,20 @@ procfs_doprocdbregs(PFS_FILL_ARGS) } /* XXXKSE: */ - error = proc_read_dbregs(FIRST_THREAD_IN_PROC(p), &r); + td2 = FIRST_THREAD_IN_PROC(p); +#ifdef COMPAT_IA32 + if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) { + if (td2->td_proc->p_sysent != &ia32_freebsd_sysvec) { + PROC_UNLOCK(p); + return (EINVAL); + } + wrap32 = 1; + } +#endif + error = PROC(read, dbregs, td2, &r); if (error == 0) { PROC_UNLOCK(p); - error = uiomove_frombuf(&r, sizeof(r), uio); + error = UIOMOVE_FROMBUF(r, uio); PROC_LOCK(p); } if (error == 0 && uio->uio_rw == UIO_WRITE) { @@ -81,7 +124,7 @@ procfs_doprocdbregs(PFS_FILL_ARGS) error = EBUSY; else /* XXXKSE: */ - error = proc_write_dbregs(FIRST_THREAD_IN_PROC(p), &r); + error = PROC(write, dbregs, td2, &r); } PROC_UNLOCK(p); diff --git a/sys/fs/procfs/procfs_fpregs.c b/sys/fs/procfs/procfs_fpregs.c index 93356ce6e7b4..cb9797b0081e 100644 --- a/sys/fs/procfs/procfs_fpregs.c +++ b/sys/fs/procfs/procfs_fpregs.c @@ -37,6 +37,8 @@ * $FreeBSD$ */ +#include "opt_compat.h" + #include #include #include @@ -50,11 +52,42 @@ #include #include +#ifdef COMPAT_IA32 +#include +#include +#include + +extern struct sysentvec ia32_freebsd_sysvec; +/* + * PROC(write, fpregs, td2, &r) becomes + * proc_write_fpregs(td2, &r) or + * proc_write_fpregs32(td2, &r32) + * + * UIOMOVE_FROMBUF(r, uio) becomes + * uiomove_frombuf(&r, sizeof(r), uio) or + * uiomove_frombuf(&r32, sizeof(r32), uio) + */ +#define PROC(d, w, t, r) wrap32 ? \ + proc_ ## d ## _ ## w ## 32(t, r ## 32) : \ + proc_ ## d ## _ ## w(t, r) +#define UIOMOVE_FROMBUF(k, u) wrap32 ? \ + uiomove_frombuf(& k ## 32, sizeof(k ## 32), u) : \ + uiomove_frombuf(& k, sizeof(k), u) +#else +#define PROC(d, w, t, r) proc_ ## d ## _ ## w(t, r) +#define UIOMOVE_FROMBUF(k, u) uiomove_frombuf(& k, sizeof(k), u) +#endif + int procfs_doprocfpregs(PFS_FILL_ARGS) { int error; struct fpreg r; + struct thread *td2; +#ifdef COMPAT_IA32 + struct fpreg32 r32; + int wrap32 = 0; +#endif PROC_LOCK(p); KASSERT(p->p_lock > 0, ("proc not held")); @@ -64,10 +97,20 @@ procfs_doprocfpregs(PFS_FILL_ARGS) } /* XXXKSE: */ - error = proc_read_fpregs(FIRST_THREAD_IN_PROC(p), &r); + td2 = FIRST_THREAD_IN_PROC(p); +#ifdef COMPAT_IA32 + if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) { + if (td2->td_proc->p_sysent != &ia32_freebsd_sysvec) { + PROC_UNLOCK(p); + return (EINVAL); + } + wrap32 = 1; + } +#endif + error = PROC(read, fpregs, td2, &r); if (error == 0) { PROC_UNLOCK(p); - error = uiomove_frombuf(&r, sizeof(r), uio); + error = UIOMOVE_FROMBUF(r, uio); PROC_LOCK(p); } if (error == 0 && uio->uio_rw == UIO_WRITE) { @@ -75,7 +118,7 @@ procfs_doprocfpregs(PFS_FILL_ARGS) error = EBUSY; else /* XXXKSE: */ - error = proc_write_fpregs(FIRST_THREAD_IN_PROC(p), &r); + error = PROC(write, fpregs, td2, &r); } PROC_UNLOCK(p); diff --git a/sys/fs/procfs/procfs_ioctl.c b/sys/fs/procfs/procfs_ioctl.c index 6ff00e79e360..7acf7d25333d 100644 --- a/sys/fs/procfs/procfs_ioctl.c +++ b/sys/fs/procfs/procfs_ioctl.c @@ -41,6 +41,19 @@ #include #include +#ifdef COMPAT_IA32 +struct procfs_status32 { + int state; /* Running, stopped, something else? */ + int flags; /* Any flags */ + unsigned int events; /* Events to stop on */ + int why; /* What event, if any, proc stopped on */ + unsigned int val; /* Any extra data */ +}; + +#define PIOCWAIT32 _IOR('p', 4, struct procfs_status32) +#define PIOCSTATUS32 _IOR('p', 6, struct procfs_status32) +#endif + /* * Process ioctls */ @@ -48,6 +61,9 @@ int procfs_ioctl(PFS_IOCTL_ARGS) { struct procfs_status *ps; +#ifdef COMPAT_IA32 + struct procfs_status32 *ps32; +#endif int error, flags, sig; PROC_LOCK(p); @@ -94,6 +110,25 @@ procfs_ioctl(PFS_IOCTL_ARGS) ps->why = p->p_step ? p->p_stype : 0; ps->val = p->p_step ? p->p_xstat : 0; break; +#ifdef COMPAT_IA32 + case PIOCWAIT32: + while (p->p_step == 0) { + /* sleep until p stops */ + error = msleep(&p->p_stype, &p->p_mtx, + PWAIT|PCATCH, "pioctl", 0); + if (error != 0) + break; + } + /* fall through to PIOCSTATUS32 */ + case PIOCSTATUS32: + ps32 = (struct procfs_status32 *)data; + ps32->state = (p->p_step == 0); + ps32->flags = 0; /* nope */ + ps32->events = p->p_stops; + ps32->why = p->p_step ? p->p_stype : 0; + ps32->val = p->p_step ? p->p_xstat : 0; + break; +#endif #if defined(COMPAT_FREEBSD5) || defined(COMPAT_FREEBSD4) || defined(COMPAT_43) case _IOC(IOC_IN, 'p', 5, 0): #endif diff --git a/sys/fs/procfs/procfs_map.c b/sys/fs/procfs/procfs_map.c index de0a58c6188e..b98d207ad386 100644 --- a/sys/fs/procfs/procfs_map.c +++ b/sys/fs/procfs/procfs_map.c @@ -35,6 +35,8 @@ * $FreeBSD$ */ +#include "opt_compat.h" + #include #include #include @@ -54,6 +56,14 @@ #include #include +#ifdef COMPAT_IA32 +#include +#include +#include + +extern struct sysentvec ia32_freebsd_sysvec; +#endif + #define MEBUFFERSIZE 256 @@ -77,6 +87,9 @@ procfs_doprocmap(PFS_FILL_ARGS) vm_map_entry_t entry; char mebuffer[MEBUFFERSIZE]; char *fullpath, *freepath; +#ifdef COMPAT_IA32 + int wrap32 = 0; +#endif GIANT_REQUIRED; @@ -92,6 +105,13 @@ procfs_doprocmap(PFS_FILL_ARGS) if (uio->uio_offset != 0) return (0); +#ifdef COMPAT_IA32 + if (curthread->td_proc->p_sysent == &ia32_freebsd_sysvec) { + if (p->p_sysent != &ia32_freebsd_sysvec) + return (EOPNOTSUPP); + wrap32 = 1; + } +#endif error = 0; if (map != &curthread->td_proc->p_vmspace->vm_map) vm_map_lock_read(map); @@ -164,7 +184,12 @@ procfs_doprocmap(PFS_FILL_ARGS) snprintf(mebuffer, sizeof mebuffer, "0x%lx 0x%lx %d %d %p %s%s%s %d %d 0x%x %s %s %s %s\n", (u_long)entry->start, (u_long)entry->end, - resident, privateresident, obj, + resident, privateresident, +#ifdef COMPAT_IA32 + wrap32 ? NULL : obj, /* Hide 64 bit value */ +#else + obj, +#endif (entry->protection & VM_PROT_READ)?"r":"-", (entry->protection & VM_PROT_WRITE)?"w":"-", (entry->protection & VM_PROT_EXECUTE)?"x":"-", diff --git a/sys/fs/procfs/procfs_regs.c b/sys/fs/procfs/procfs_regs.c index 7da0f8c81590..cba2b7bc14a4 100644 --- a/sys/fs/procfs/procfs_regs.c +++ b/sys/fs/procfs/procfs_regs.c @@ -37,6 +37,8 @@ * $FreeBSD$ */ +#include "opt_compat.h" + #include #include #include @@ -50,11 +52,42 @@ #include #include +#ifdef COMPAT_IA32 +#include +#include +#include + +extern struct sysentvec ia32_freebsd_sysvec; +/* + * PROC(write, regs, td2, &r) becomes + * proc_write_regs(td2, &r) or + * proc_write_regs32(td2, &r32) + * + * UIOMOVE_FROMBUF(r, uio) becomes + * uiomove_frombuf(&r, sizeof(r), uio) or + * uiomove_frombuf(&r32, sizeof(r32), uio) + */ +#define PROC(d, w, t, r) wrap32 ? \ + proc_ ## d ## _ ## w ## 32(t, r ## 32) : \ + proc_ ## d ## _ ## w(t, r) +#define UIOMOVE_FROMBUF(k, u) wrap32 ? \ + uiomove_frombuf(& k ## 32, sizeof(k ## 32), u) : \ + uiomove_frombuf(& k, sizeof(k), u) +#else +#define PROC(d, w, t, r) proc_ ## d ## _ ## w(t, r) +#define UIOMOVE_FROMBUF(k, u) uiomove_frombuf(& k, sizeof(k), u) +#endif + int procfs_doprocregs(PFS_FILL_ARGS) { int error; struct reg r; + struct thread *td2; +#ifdef COMPAT_IA32 + struct reg32 r32; + int wrap32 = 0; +#endif PROC_LOCK(p); KASSERT(p->p_lock > 0, ("proc not held")); @@ -64,10 +97,20 @@ procfs_doprocregs(PFS_FILL_ARGS) } /* XXXKSE: */ - error = proc_read_regs(FIRST_THREAD_IN_PROC(p), &r); + td2 = FIRST_THREAD_IN_PROC(p); +#ifdef COMPAT_IA32 + if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) { + if (td2->td_proc->p_sysent != &ia32_freebsd_sysvec) { + PROC_UNLOCK(p); + return (EINVAL); + } + wrap32 = 1; + } +#endif + error = PROC(read, regs, td2, &r); if (error == 0) { PROC_UNLOCK(p); - error = uiomove_frombuf(&r, sizeof(r), uio); + error = UIOMOVE_FROMBUF(r, uio); PROC_LOCK(p); } if (error == 0 && uio->uio_rw == UIO_WRITE) { @@ -75,7 +118,7 @@ procfs_doprocregs(PFS_FILL_ARGS) error = EBUSY; else /* XXXKSE: */ - error = proc_write_regs(FIRST_THREAD_IN_PROC(p), &r); + error = PROC(write, regs, td2, &r); } PROC_UNLOCK(p); diff --git a/sys/ia64/ia32/ia32_reg.c b/sys/ia64/ia32/ia32_reg.c new file mode 100644 index 000000000000..dde8b89f8c81 --- /dev/null +++ b/sys/ia64/ia32/ia32_reg.c @@ -0,0 +1,82 @@ +/*- + * Copyright (c) 2005 Peter Wemm + * All rights reserved. + * + * 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 AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#include + +int +fill_regs32(struct thread *td, struct reg32 *regs) +{ + + bzero(regs, sizeof(*regs)); + return (EOPNOTSUPP); +} + +int +set_regs32(struct thread *td, struct reg32 *regs) +{ + + return (EOPNOTSUPP); +} + +int +fill_fpregs32(struct thread *td, struct fpreg32 *regs) +{ + + bzero(regs, sizeof(*regs)); + return (EOPNOTSUPP); +} + +int +set_fpregs32(struct thread *td, struct fpreg32 *regs) +{ + + return (EOPNOTSUPP); +} + +int +fill_dbregs32(struct thread *td, struct dbreg32 *regs) +{ + + bzero(regs, sizeof(*regs)); + return (EOPNOTSUPP); +} + +int +set_dbregs32(struct thread *td, struct dbreg32 *regs) +{ + + return (EOPNOTSUPP); +} diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c index 9f46c9791ad4..6a8850063021 100644 --- a/sys/kern/imgact_elf.c +++ b/sys/kern/imgact_elf.c @@ -31,6 +31,8 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_compat.h" + #include #include #include @@ -66,6 +68,11 @@ __FBSDID("$FreeBSD$"); #include #include +#if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32 +#include +#include +#endif + #define OLD_EI_BRAND 8 static int __elfN(check_header)(const Elf_Ehdr *hdr); @@ -1118,17 +1125,31 @@ __elfN(corehdr)(td, vp, cred, numsegs, hdr, hdrsize) td)); /* XXXKSE */ } +#if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32 +typedef struct prstatus32 elf_prstatus_t; +typedef struct prpsinfo32 elf_prpsinfo_t; +typedef struct fpreg32 elf_prfpregset_t; +typedef struct fpreg32 elf_fpregset_t; +typedef struct reg32 elf_gregset_t; +#else +typedef prstatus_t elf_prstatus_t; +typedef prpsinfo_t elf_prpsinfo_t; +typedef prfpregset_t elf_prfpregset_t; +typedef prfpregset_t elf_fpregset_t; +typedef gregset_t elf_gregset_t; +#endif + static void __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs) { struct { - prstatus_t status; - prfpregset_t fpregset; - prpsinfo_t psinfo; + elf_prstatus_t status; + elf_prfpregset_t fpregset; + elf_prpsinfo_t psinfo; } *tempdata; - prstatus_t *status; - prfpregset_t *fpregset; - prpsinfo_t *psinfo; + elf_prstatus_t *status; + elf_prfpregset_t *fpregset; + elf_prpsinfo_t *psinfo; struct proc *p; struct thread *thr; size_t ehoff, noteoff, notesz, phoff; @@ -1160,7 +1181,7 @@ __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs) if (dst != NULL) { psinfo->pr_version = PRPSINFO_VERSION; - psinfo->pr_psinfosz = sizeof(prpsinfo_t); + psinfo->pr_psinfosz = sizeof(elf_prpsinfo_t); strlcpy(psinfo->pr_fname, p->p_comm, sizeof(psinfo->pr_fname)); /* * XXX - We don't fill in the command line arguments properly @@ -1182,14 +1203,19 @@ __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs) while (thr != NULL) { if (dst != NULL) { status->pr_version = PRSTATUS_VERSION; - status->pr_statussz = sizeof(prstatus_t); - status->pr_gregsetsz = sizeof(gregset_t); - status->pr_fpregsetsz = sizeof(fpregset_t); + status->pr_statussz = sizeof(elf_prstatus_t); + status->pr_gregsetsz = sizeof(elf_gregset_t); + status->pr_fpregsetsz = sizeof(elf_fpregset_t); status->pr_osreldate = osreldate; status->pr_cursig = p->p_sig; status->pr_pid = thr->td_tid; +#if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32 + fill_regs32(thr, &status->pr_reg); + fill_fpregs32(thr, fpregset); +#else fill_regs(thr, &status->pr_reg); fill_fpregs(thr, fpregset); +#endif } __elfN(putnote)(dst, off, "FreeBSD", NT_PRSTATUS, status, sizeof *status); @@ -1235,7 +1261,11 @@ __elfN(puthdr)(struct thread *td, void *dst, size_t *off, int numsegs) ehdr->e_ident[EI_ABIVERSION] = 0; ehdr->e_ident[EI_PAD] = 0; ehdr->e_type = ET_CORE; +#if defined(COMPAT_IA32) && __ELF_WORD_SIZE == 32 + ehdr->e_machine = EM_386; +#else ehdr->e_machine = ELF_ARCH; +#endif ehdr->e_version = EV_CURRENT; ehdr->e_entry = 0; ehdr->e_phoff = phoff; diff --git a/sys/kern/kern_clock.c b/sys/kern/kern_clock.c index cfcc5747e583..76e2be6e3d4f 100644 --- a/sys/kern/kern_clock.c +++ b/sys/kern/kern_clock.c @@ -37,6 +37,7 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_compat.h" #include "opt_hwpmc_hooks.h" #include "opt_ntp.h" #include "opt_watchdog.h" @@ -84,8 +85,36 @@ SYSINIT(clocks, SI_SUB_CLOCKS, SI_ORDER_FIRST, initclocks, NULL) /* Some of these don't belong here, but it's easiest to concentrate them. */ long cp_time[CPUSTATES]; -SYSCTL_OPAQUE(_kern, OID_AUTO, cp_time, CTLFLAG_RD, &cp_time, sizeof(cp_time), - "LU", "CPU time statistics"); +#ifdef COMPAT_IA32 +extern struct sysentvec ia32_freebsd_sysvec; +#endif + +static int +sysctl_kern_cp_time(SYSCTL_HANDLER_ARGS) +{ + int error; +#ifdef COMPAT_IA32 + int i; + unsigned int cp_time32[CPUSTATES]; + + if (req->td->td_proc->p_sysent == &ia32_freebsd_sysvec) { + if (!req->oldptr) + return SYSCTL_OUT(req, 0, sizeof(cp_time32)); + for (i = 0; i < CPUSTATES; i++) + cp_time32[i] = (unsigned int)cp_time[i]; + error = SYSCTL_OUT(req, cp_time32, sizeof(cp_time32)); + } else +#endif + { + if (!req->oldptr) + return SYSCTL_OUT(req, 0, sizeof(cp_time)); + error = SYSCTL_OUT(req, cp_time, sizeof(cp_time)); + } + return error; +} + +SYSCTL_PROC(_kern, OID_AUTO, cp_time, CTLTYPE_LONG|CTLFLAG_RD, + 0,0, sysctl_kern_cp_time, "LU", "CPU time statistics"); #ifdef SW_WATCHDOG #include diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c index b9afb6a795e0..11b66da43091 100644 --- a/sys/kern/sys_process.c +++ b/sys/kern/sys_process.c @@ -32,6 +32,8 @@ #include __FBSDID("$FreeBSD$"); +#include "opt_compat.h" + #include #include #include @@ -55,6 +57,21 @@ __FBSDID("$FreeBSD$"); #include #include +#ifdef COMPAT_IA32 +#include +#include +#include + +extern struct sysentvec ia32_freebsd_sysvec; + +struct ptrace_io_desc32 { + int piod_op; + u_int32_t piod_offs; + u_int32_t piod_addr; + u_int32_t piod_len; +}; +#endif + /* * Functions implemented using PROC_ACTION(): * @@ -138,6 +155,51 @@ proc_write_fpregs(struct thread *td, struct fpreg *fpregs) PROC_ACTION(set_fpregs(td, fpregs)); } +#ifdef COMPAT_IA32 +/* For 32 bit binaries, we need to expose the 32 bit regs layouts. */ +int +proc_read_regs32(struct thread *td, struct reg32 *regs32) +{ + + PROC_ACTION(fill_regs32(td, regs32)); +} + +int +proc_write_regs32(struct thread *td, struct reg32 *regs32) +{ + + PROC_ACTION(set_regs32(td, regs32)); +} + +int +proc_read_dbregs32(struct thread *td, struct dbreg32 *dbregs32) +{ + + PROC_ACTION(fill_dbregs32(td, dbregs32)); +} + +int +proc_write_dbregs32(struct thread *td, struct dbreg32 *dbregs32) +{ + + PROC_ACTION(set_dbregs32(td, dbregs32)); +} + +int +proc_read_fpregs32(struct thread *td, struct fpreg32 *fpregs32) +{ + + PROC_ACTION(fill_fpregs32(td, fpregs32)); +} + +int +proc_write_fpregs32(struct thread *td, struct fpreg32 *fpregs32) +{ + + PROC_ACTION(set_fpregs32(td, fpregs32)); +} +#endif + int proc_sstep(struct thread *td) { @@ -290,6 +352,27 @@ struct ptrace_args { }; #endif +#ifdef COMPAT_IA32 +/* + * This CPP subterfuge is to try and reduce the number of ifdefs in + * the body of the code. + * COPYIN(uap->addr, &r.reg, sizeof r.reg); + * becomes either: + * copyin(uap->addr, &r.reg, sizeof r.reg); + * or + * copyin(uap->addr, &r.reg32, sizeof r.reg32); + * .. except this is done at runtime. + */ +#define COPYIN(u, k, s) wrap32 ? \ + copyin(u, k ## 32, s ## 32) : \ + copyin(u, k, s) +#define COPYOUT(k, u, s) wrap32 ? \ + copyout(k ## 32, u, s ## 32) : \ + copyout(k, u, s) +#else +#define COPYIN(u, k, s) copyin(u, k, s) +#define COPYOUT(k, u, s) copyout(k, u, s) +#endif /* * MPSAFE */ @@ -306,10 +389,21 @@ ptrace(struct thread *td, struct ptrace_args *uap) struct dbreg dbreg; struct fpreg fpreg; struct reg reg; +#ifdef COMPAT_IA32 + struct dbreg32 dbreg32; + struct fpreg32 fpreg32; + struct reg32 reg32; + struct ptrace_io_desc32 piod32; +#endif } r; void *addr; int error = 0; +#ifdef COMPAT_IA32 + int wrap32 = 0; + if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) + wrap32 = 1; +#endif addr = &r; switch (uap->req) { case PT_GETREGS: @@ -318,16 +412,16 @@ ptrace(struct thread *td, struct ptrace_args *uap) case PT_LWPINFO: break; case PT_SETREGS: - error = copyin(uap->addr, &r.reg, sizeof r.reg); + error = COPYIN(uap->addr, &r.reg, sizeof r.reg); break; case PT_SETFPREGS: - error = copyin(uap->addr, &r.fpreg, sizeof r.fpreg); + error = COPYIN(uap->addr, &r.fpreg, sizeof r.fpreg); break; case PT_SETDBREGS: - error = copyin(uap->addr, &r.dbreg, sizeof r.dbreg); + error = COPYIN(uap->addr, &r.dbreg, sizeof r.dbreg); break; case PT_IO: - error = copyin(uap->addr, &r.piod, sizeof r.piod); + error = COPYIN(uap->addr, &r.piod, sizeof r.piod); break; default: addr = uap->addr; @@ -342,16 +436,16 @@ ptrace(struct thread *td, struct ptrace_args *uap) switch (uap->req) { case PT_IO: - (void)copyout(&r.piod, uap->addr, sizeof r.piod); + error = COPYOUT(&r.piod, uap->addr, sizeof r.piod); break; case PT_GETREGS: - error = copyout(&r.reg, uap->addr, sizeof r.reg); + error = COPYOUT(&r.reg, uap->addr, sizeof r.reg); break; case PT_GETFPREGS: - error = copyout(&r.fpreg, uap->addr, sizeof r.fpreg); + error = COPYOUT(&r.fpreg, uap->addr, sizeof r.fpreg); break; case PT_GETDBREGS: - error = copyout(&r.dbreg, uap->addr, sizeof r.dbreg); + error = COPYOUT(&r.dbreg, uap->addr, sizeof r.dbreg); break; case PT_LWPINFO: error = copyout(&r.pl, uap->addr, uap->data); @@ -360,6 +454,30 @@ ptrace(struct thread *td, struct ptrace_args *uap) return (error); } +#undef COPYIN +#undef COPYOUT + +#ifdef COMPAT_IA32 +/* + * PROC_READ(regs, td2, addr); + * becomes either: + * proc_read_regs(td2, addr); + * or + * proc_read_regs32(td2, addr); + * .. except this is done at runtime. There is an additional + * complication in that PROC_WRITE disallows 32 bit consumers + * from writing to 64 bit address space targets. + */ +#define PROC_READ(w, t, a) wrap32 ? \ + proc_read_ ## w ## 32(t, a) : \ + proc_read_ ## w (t, a) +#define PROC_WRITE(w, t, a) wrap32 ? \ + (safe ? proc_write_ ## w ## 32(t, a) : EINVAL ) : \ + proc_write_ ## w (t, a) +#else +#define PROC_READ(w, t, a) proc_read_ ## w (t, a) +#define PROC_WRITE(w, t, a) proc_write_ ## w (t, a) +#endif int kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) @@ -368,12 +486,16 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) struct uio uio; struct proc *curp, *p, *pp; struct thread *td2 = NULL; - struct ptrace_io_desc *piod; + struct ptrace_io_desc *piod = NULL; struct ptrace_lwpinfo *pl; int error, write, tmp, num; int proctree_locked = 0; lwpid_t tid = 0, *buf; pid_t saved_pid = pid; +#ifdef COMPAT_IA32 + int wrap32 = 0, safe = 0; + struct ptrace_io_desc32 *piod32 = NULL; +#endif curp = td->td_proc; @@ -449,6 +571,17 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) tid = td2->td_tid; } +#ifdef COMPAT_IA32 + /* + * Test if we're a 32 bit client and what the target is. + * Set the wrap controls accordingly. + */ + if (td->td_proc->p_sysent == &ia32_freebsd_sysvec) { + if (td2->td_proc->p_sysent == &ia32_freebsd_sysvec) + safe = 1; + wrap32 = 1; + } +#endif /* * Permissions check */ @@ -723,16 +856,32 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) case PT_IO: PROC_UNLOCK(p); - piod = addr; - iov.iov_base = piod->piod_addr; - iov.iov_len = piod->piod_len; +#ifdef COMPAT_IA32 + if (wrap32) { + piod32 = addr; + iov.iov_base = (void *)(uintptr_t)piod32->piod_addr; + iov.iov_len = piod32->piod_len; + uio.uio_offset = (off_t)(uintptr_t)piod32->piod_offs; + uio.uio_resid = piod32->piod_len; + } else +#endif + { + piod = addr; + iov.iov_base = piod->piod_addr; + iov.iov_len = piod->piod_len; + uio.uio_offset = (off_t)(uintptr_t)piod->piod_offs; + uio.uio_resid = piod->piod_len; + } uio.uio_iov = &iov; uio.uio_iovcnt = 1; - uio.uio_offset = (off_t)(uintptr_t)piod->piod_offs; - uio.uio_resid = piod->piod_len; uio.uio_segflg = UIO_USERSPACE; uio.uio_td = td; - switch (piod->piod_op) { +#ifdef COMPAT_IA32 + tmp = wrap32 ? piod32->piod_op : piod->piod_op; +#else + tmp = piod->piod_op; +#endif + switch (tmp) { case PIOD_READ_D: case PIOD_READ_I: uio.uio_rw = UIO_READ; @@ -745,7 +894,12 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) return (EINVAL); } error = proc_rwmem(p, &uio); - piod->piod_len -= uio.uio_resid; +#ifdef COMPAT_IA32 + if (wrap32) + piod32->piod_len -= uio.uio_resid; + else +#endif + piod->piod_len -= uio.uio_resid; return (error); case PT_KILL: @@ -754,42 +908,42 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) case PT_SETREGS: _PHOLD(p); - error = proc_write_regs(td2, addr); + error = PROC_WRITE(regs, td2, addr); _PRELE(p); PROC_UNLOCK(p); return (error); case PT_GETREGS: _PHOLD(p); - error = proc_read_regs(td2, addr); + error = PROC_READ(regs, td2, addr); _PRELE(p); PROC_UNLOCK(p); return (error); case PT_SETFPREGS: _PHOLD(p); - error = proc_write_fpregs(td2, addr); + error = PROC_WRITE(fpregs, td2, addr); _PRELE(p); PROC_UNLOCK(p); return (error); case PT_GETFPREGS: _PHOLD(p); - error = proc_read_fpregs(td2, addr); + error = PROC_READ(fpregs, td2, addr); _PRELE(p); PROC_UNLOCK(p); return (error); case PT_SETDBREGS: _PHOLD(p); - error = proc_write_dbregs(td2, addr); + error = PROC_WRITE(dbregs, td2, addr); _PRELE(p); PROC_UNLOCK(p); return (error); case PT_GETDBREGS: _PHOLD(p); - error = proc_read_dbregs(td2, addr); + error = PROC_READ(dbregs, td2, addr); _PRELE(p); PROC_UNLOCK(p); return (error); @@ -872,6 +1026,8 @@ kern_ptrace(struct thread *td, int req, pid_t pid, void *addr, int data) sx_xunlock(&proctree_lock); return (error); } +#undef PROC_READ +#undef PROC_WRITE /* * Stop a process because of a debugging event; diff --git a/sys/sys/ptrace.h b/sys/sys/ptrace.h index 0058683da9b0..93b1a7d6d0fc 100644 --- a/sys/sys/ptrace.h +++ b/sys/sys/ptrace.h @@ -135,6 +135,17 @@ int proc_read_dbregs(struct thread *_td, struct dbreg *_dbreg); int proc_write_dbregs(struct thread *_td, struct dbreg *_dbreg); int proc_sstep(struct thread *_td); int proc_rwmem(struct proc *_p, struct uio *_uio); +#ifdef COMPAT_IA32 +struct reg32; +struct fpreg32; +struct dbreg32; +int proc_read_regs32(struct thread *_td, struct reg32 *_reg32); +int proc_write_regs32(struct thread *_td, struct reg32 *_reg32); +int proc_read_fpregs32(struct thread *_td, struct fpreg32 *_fpreg32); +int proc_write_fpregs32(struct thread *_td, struct fpreg32 *_fpreg32); +int proc_read_dbregs32(struct thread *_td, struct dbreg32 *_dbreg32); +int proc_write_dbregs32(struct thread *_td, struct dbreg32 *_dbreg32); +#endif #else /* !_KERNEL */ #include