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 | |
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')
-rw-r--r-- | sys/fs/procfs/procfs_dbregs.c | 49 | ||||
-rw-r--r-- | sys/fs/procfs/procfs_fpregs.c | 49 | ||||
-rw-r--r-- | sys/fs/procfs/procfs_ioctl.c | 35 | ||||
-rw-r--r-- | sys/fs/procfs/procfs_map.c | 27 | ||||
-rw-r--r-- | sys/fs/procfs/procfs_regs.c | 49 |
5 files changed, 199 insertions, 10 deletions
diff --git a/sys/fs/procfs/procfs_dbregs.c b/sys/fs/procfs/procfs_dbregs.c index 0e129bb..c30f231 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 <sys/param.h> #include <sys/systm.h> #include <sys/lock.h> @@ -56,11 +58,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, 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 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); diff --git a/sys/fs/procfs/procfs_ioctl.c b/sys/fs/procfs/procfs_ioctl.c index 6ff00e7..7acf7d2 100644 --- a/sys/fs/procfs/procfs_ioctl.c +++ b/sys/fs/procfs/procfs_ioctl.c @@ -41,6 +41,19 @@ #include <fs/pseudofs/pseudofs.h> #include <fs/procfs/procfs.h> +#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 de0a58c..b98d207 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 <sys/param.h> #include <sys/systm.h> #include <sys/lock.h> @@ -54,6 +56,14 @@ #include <vm/vm_page.h> #include <vm/vm_object.h> +#ifdef COMPAT_IA32 +#include <sys/procfs.h> +#include <machine/fpu.h> +#include <compat/ia32/ia32_reg.h> + +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 7da0f8c..cba2b7b 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 <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, 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); |