diff options
author | peter <peter@FreeBSD.org> | 2005-06-30 07:49:22 +0000 |
---|---|---|
committer | peter <peter@FreeBSD.org> | 2005-06-30 07:49:22 +0000 |
commit | 921b3c5ee4556d6428b9c88c71d3b69e0da1345b (patch) | |
tree | dad118ce52d6d607680db2768f086c4ee826fd22 /sys/fs/procfs/procfs_fpregs.c | |
parent | 14ff9254d85bc5b36288a2b4ba9db5bcb52f7587 (diff) | |
download | FreeBSD-src-921b3c5ee4556d6428b9c88c71d3b69e0da1345b.zip FreeBSD-src-921b3c5ee4556d6428b9c88c71d3b69e0da1345b.tar.gz |
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
Diffstat (limited to 'sys/fs/procfs/procfs_fpregs.c')
-rw-r--r-- | sys/fs/procfs/procfs_fpregs.c | 49 |
1 files changed, 46 insertions, 3 deletions
diff --git a/sys/fs/procfs/procfs_fpregs.c b/sys/fs/procfs/procfs_fpregs.c index 93356ce..cb9797b 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 <sys/param.h> #include <sys/systm.h> #include <sys/lock.h> @@ -50,11 +52,42 @@ #include <fs/pseudofs/pseudofs.h> #include <fs/procfs/procfs.h> +#ifdef COMPAT_IA32 +#include <sys/procfs.h> +#include <machine/fpu.h> +#include <compat/ia32/ia32_reg.h> + +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); |