summaryrefslogtreecommitdiffstats
path: root/sys/fs
diff options
context:
space:
mode:
authorpeter <peter@FreeBSD.org>2005-06-30 07:49:22 +0000
committerpeter <peter@FreeBSD.org>2005-06-30 07:49:22 +0000
commit921b3c5ee4556d6428b9c88c71d3b69e0da1345b (patch)
treedad118ce52d6d607680db2768f086c4ee826fd22 /sys/fs
parent14ff9254d85bc5b36288a2b4ba9db5bcb52f7587 (diff)
downloadFreeBSD-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.c49
-rw-r--r--sys/fs/procfs/procfs_fpregs.c49
-rw-r--r--sys/fs/procfs/procfs_ioctl.c35
-rw-r--r--sys/fs/procfs/procfs_map.c27
-rw-r--r--sys/fs/procfs/procfs_regs.c49
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);
OpenPOWER on IntegriCloud