Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F108330248
D19831.id94898.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
20 KB
Referenced Files
None
Subscribers
None
D19831.id94898.diff
View Options
Index: lib/libc/sys/ptrace.2
===================================================================
--- lib/libc/sys/ptrace.2
+++ lib/libc/sys/ptrace.2
@@ -2,7 +2,7 @@
.\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $
.\"
.\" This file is in the public domain.
-.Dd May 20, 2021
+.Dd Sep ??, 2021
.Dt PTRACE 2
.Os
.Sh NAME
@@ -462,6 +462,24 @@
.In machine/reg.h )
pointed to by
.Fa addr .
+.It Dv PT_GETREGSET
+This request reads the traced process's machine registers.
+The
+.Fa data
+argument specifies the register set to read, with the
+.Fa addr
+argument pointing at a
+.Vt "struct iovec"
+that points to a register set specific structure to hold the registers.
+.It Dv PT_SETREGSET
+This request writes to the traced process's machine registers.
+The
+.Fa data
+argument specifies the register set to write to, with the
+.Fa addr
+argument pointing at a
+.Vt "struct iovec"
+that points to a request specific structure that holds the new registers.
.It Dv PT_LWPINFO
This request can be used to obtain information about the kernel thread,
also known as light-weight process, that caused the traced process to stop.
Index: sys/amd64/amd64/elf_machdep.c
===================================================================
--- sys/amd64/amd64/elf_machdep.c
+++ sys/amd64/amd64/elf_machdep.c
@@ -35,6 +35,7 @@
#include <sys/imgact.h>
#include <sys/linker.h>
#include <sys/proc.h>
+#include <sys/reg.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
#include <sys/syscall.h>
@@ -88,6 +89,8 @@
.sv_onexec_old = exec_onexec_old,
.sv_onexit = exit_onexit,
.sv_set_fork_retval = x86_set_fork_retval,
+ .sv_regset_begin = SET_BEGIN(__elfN(regset)),
+ .sv_regset_end = SET_LIMIT(__elfN(regset)),
};
struct sysentvec elf64_freebsd_sysvec_la57 = {
@@ -129,6 +132,8 @@
.sv_onexec_old = exec_onexec_old,
.sv_onexit = exit_onexit,
.sv_set_fork_retval= x86_set_fork_retval,
+ .sv_regset_begin = SET_BEGIN(__elfN(regset)),
+ .sv_regset_end = SET_LIMIT(__elfN(regset)),
};
static void
Index: sys/arm/arm/elf_machdep.c
===================================================================
--- sys/arm/arm/elf_machdep.c
+++ sys/arm/arm/elf_machdep.c
@@ -34,6 +34,7 @@
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/linker.h>
+#include <sys/reg.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
#include <sys/proc.h>
@@ -102,6 +103,8 @@
.sv_hwcap2 = &elf_hwcap2,
.sv_onexec_old = exec_onexec_old,
.sv_onexit = exit_onexit,
+ .sv_regset_begin = SET_BEGIN(__elfN(regset)),
+ .sv_regset_end = SET_LIMIT(__elfN(regset)),
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
Index: sys/arm64/arm64/elf32_machdep.c
===================================================================
--- sys/arm64/arm64/elf32_machdep.c
+++ sys/arm64/arm64/elf32_machdep.c
@@ -44,6 +44,7 @@
#include <sys/imgact.h>
#include <sys/linker.h>
#include <sys/proc.h>
+#include <sys/reg.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
#include <sys/syscall.h>
@@ -119,6 +120,8 @@
.sv_hwcap2 = &elf32_hwcap2,
.sv_onexec_old = exec_onexec_old,
.sv_onexit = exit_onexit,
+ .sv_regset_begin = SET_BEGIN(__elfN(regset)),
+ .sv_regset_end = SET_LIMIT(__elfN(regset)),
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
Index: sys/arm64/arm64/elf_machdep.c
===================================================================
--- sys/arm64/arm64/elf_machdep.c
+++ sys/arm64/arm64/elf_machdep.c
@@ -41,6 +41,7 @@
#include <sys/imgact.h>
#include <sys/linker.h>
#include <sys/proc.h>
+#include <sys/reg.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
#include <sys/syscall.h>
@@ -97,6 +98,8 @@
.sv_hwcap2 = &elf_hwcap2,
.sv_onexec_old = exec_onexec_old,
.sv_onexit = exit_onexit,
+ .sv_regset_begin = SET_BEGIN(__elfN(regset)),
+ .sv_regset_end = SET_LIMIT(__elfN(regset)),
};
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
Index: sys/compat/freebsd32/freebsd32_misc.c
===================================================================
--- sys/compat/freebsd32/freebsd32_misc.c
+++ sys/compat/freebsd32/freebsd32_misc.c
@@ -935,6 +935,7 @@
struct dbreg32 dbreg;
struct fpreg32 fpreg;
struct reg32 reg;
+ struct iovec32 vec;
register_t args[nitems(td->td_sa.args)];
struct ptrace_sc_ret psr;
int ptevents;
@@ -947,6 +948,7 @@
uint32_t args[nitems(td->td_sa.args)];
struct ptrace_sc_ret32 psr;
} r32;
+ struct iovec kern_vec;
void *addr;
int data, error = 0, i;
@@ -991,6 +993,30 @@
case PT_SETDBREGS:
error = copyin(uap->addr, &r.dbreg, sizeof(r.dbreg));
break;
+ case PT_SETREGSET:
+ error = copyin(uap->addr, &r.vec, sizeof(r.vec));
+ if (error != 0)
+ break;
+ kern_vec.iov_len = r.vec.iov_len;
+ kern_vec.iov_base = malloc(r.vec.iov_len + 1, M_TEMP, M_WAITOK);
+ error = copyin((const void *)(uintptr_t)r.vec.iov_base,
+ kern_vec.iov_base, r.vec.iov_len);
+ if (error == 0)
+ addr = &kern_vec;
+ break;
+ case PT_GETREGSET:
+ error = copyin(uap->addr, &r.vec, sizeof(r.vec));
+ if (error != 0)
+ break;
+
+ if (r.vec.iov_base != 0) {
+ /* TODO: Check this length isn't too long */
+ kern_vec.iov_len = r.vec.iov_len;
+ kern_vec.iov_base = malloc(r.vec.iov_len, M_TEMP,
+ M_WAITOK);
+ addr = &kern_vec;
+ }
+ break;
case PT_SET_EVENT_MASK:
if (uap->data != sizeof(r.ptevents))
error = EINVAL;
@@ -1037,11 +1063,11 @@
break;
}
if (error)
- return (error);
+ goto out;
error = kern_ptrace(td, uap->req, uap->pid, addr, data);
if (error)
- return (error);
+ goto out;
switch (uap->req) {
case PT_VM_ENTRY:
@@ -1069,6 +1095,15 @@
case PT_GETDBREGS:
error = copyout(&r.dbreg, uap->addr, sizeof(r.dbreg));
break;
+ case PT_GETREGSET:
+ if (r.vec.iov_base != 0) {
+ r.vec.iov_len = MIN(r.vec.iov_len, kern_vec.iov_len);
+ error = copyout(kern_vec.iov_base,
+ (void *)(uintptr_t)r.vec.iov_base, r.vec.iov_len);
+ }
+ if (error == 0)
+ error = copyout(&r.vec, uap->addr, sizeof(r.vec));
+ break;
case PT_GET_EVENT_MASK:
/* NB: The size in uap->data is validated in kern_ptrace(). */
error = copyout(&r.ptevents, uap->addr, uap->data);
@@ -1090,6 +1125,8 @@
break;
}
+out:
+ free(kern_vec.iov_base, M_TEMP);
return (error);
}
Index: sys/compat/ia32/ia32_sysvec.c
===================================================================
--- sys/compat/ia32/ia32_sysvec.c
+++ sys/compat/ia32/ia32_sysvec.c
@@ -33,6 +33,7 @@
#define __ELF_WORD_SIZE 32
#include <sys/param.h>
+#include <sys/elf.h>
#include <sys/exec.h>
#include <sys/fcntl.h>
#include <sys/imgact.h>
@@ -44,6 +45,7 @@
#include <sys/namei.h>
#include <sys/proc.h>
#include <sys/procfs.h>
+#include <sys/reg.h>
#include <sys/resourcevar.h>
#include <sys/systm.h>
#include <sys/signalvar.h>
@@ -134,6 +136,8 @@
.sv_onexec_old = exec_onexec_old,
.sv_onexit = exit_onexit,
.sv_set_fork_retval = x86_set_fork_retval,
+ .sv_regset_begin = SET_BEGIN(__elfN(regset)),
+ .sv_regset_end = SET_LIMIT(__elfN(regset)),
};
INIT_SYSENTVEC(elf_ia32_sysvec, &ia32_freebsd_sysvec);
Index: sys/i386/i386/elf_machdep.c
===================================================================
--- sys/i386/i386/elf_machdep.c
+++ sys/i386/i386/elf_machdep.c
@@ -36,6 +36,7 @@
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/linker.h>
+#include <sys/reg.h>
#include <sys/proc.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
@@ -89,6 +90,8 @@
.sv_onexec_old = exec_onexec_old,
.sv_onexit = exit_onexit,
.sv_set_fork_retval = x86_set_fork_retval,
+ .sv_regset_begin = SET_BEGIN(__elfN(regset)),
+ .sv_regset_end = SET_LIMIT(__elfN(regset)),
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
Index: sys/kern/imgact_elf.c
===================================================================
--- sys/kern/imgact_elf.c
+++ sys/kern/imgact_elf.c
@@ -2102,16 +2102,16 @@
*sizep = sizeof(*psinfo);
}
-static void
-__elfN(note_prstatus)(void *arg, struct sbuf *sb, size_t *sizep)
+static bool
+__elfN(get_prstatus)(struct regset *rs, struct thread *td, void *buf,
+ size_t *sizep)
{
- struct thread *td;
elf_prstatus_t *status;
- td = arg;
- if (sb != NULL) {
- KASSERT(*sizep == sizeof(*status), ("invalid size"));
- status = malloc(sizeof(*status), M_TEMP, M_ZERO | M_WAITOK);
+ if (buf != NULL) {
+ KASSERT(*sizep == sizeof(*status), ("%s: invalid size",
+ __func__));
+ status = buf;
status->pr_version = PRSTATUS_VERSION;
status->pr_statussz = sizeof(elf_prstatus_t);
status->pr_gregsetsz = sizeof(elf_gregset_t);
@@ -2124,12 +2124,97 @@
#else
fill_regs(td, &status->pr_reg);
#endif
+ }
+ *sizep = sizeof(*status);
+ return (true);
+}
+
+static bool
+__elfN(set_prstatus)(struct regset *rs, struct thread *td, void *buf,
+ size_t size)
+{
+ elf_prstatus_t *status;
+
+ KASSERT(size == sizeof(*status), ("%s: invalid size", __func__));
+ status = buf;
+#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
+ set_regs32(td, &status->pr_reg);
+#else
+ set_regs(td, &status->pr_reg);
+#endif
+ return (true);
+}
+
+static struct regset __elfN(regset_prstatus) = {
+ .note = NT_PRSTATUS,
+ .size = sizeof(elf_prstatus_t),
+ .get = __elfN(get_prstatus),
+ .set = __elfN(set_prstatus),
+};
+ELF_REGSET(__elfN(regset_prstatus));
+
+static void
+__elfN(note_prstatus)(void *arg, struct sbuf *sb, size_t *sizep)
+{
+ struct thread *td;
+ elf_prstatus_t *status;
+
+ td = arg;
+ if (sb != NULL) {
+ KASSERT(*sizep == sizeof(*status), ("%s: invalid size",
+ __func__));
+ status = malloc(sizeof(*status), M_TEMP, M_ZERO | M_WAITOK);
+ __elfN(get_prstatus)(NULL, td, status, sizep);
sbuf_bcat(sb, status, sizeof(*status));
free(status, M_TEMP);
}
*sizep = sizeof(*status);
}
+static bool
+__elfN(get_fpregset)(struct regset *rs, struct thread *td, void *buf,
+ size_t *sizep)
+{
+ elf_prfpregset_t *fpregset;
+
+ if (buf != NULL) {
+ KASSERT(*sizep == sizeof(*fpregset), ("%s: invalid size",
+ __func__));
+ fpregset = buf;
+#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
+ fill_fpregs32(td, fpregset);
+#else
+ fill_fpregs(td, fpregset);
+#endif
+ }
+ *sizep = sizeof(fpregset);
+ return (true);
+}
+
+static bool
+__elfN(set_fpregset)(struct regset *rs, struct thread *td, void *buf,
+ size_t size)
+{
+ elf_prfpregset_t *fpregset;
+
+ fpregset = buf;
+ KASSERT(size == sizeof(*fpregset), ("%s: invalid size", __func__));
+#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
+ set_fpregs32(td, fpregset);
+#else
+ set_fpregs(td, fpregset);
+#endif
+ return (true);
+}
+
+static struct regset __elfN(regset_fpregset) = {
+ .note = NT_FPREGSET,
+ .size = sizeof(elf_prfpregset_t),
+ .get = __elfN(get_fpregset),
+ .set = __elfN(set_fpregset),
+};
+ELF_REGSET(__elfN(regset_fpregset));
+
static void
__elfN(note_fpregset)(void *arg, struct sbuf *sb, size_t *sizep)
{
@@ -2140,11 +2225,7 @@
if (sb != NULL) {
KASSERT(*sizep == sizeof(*fpregset), ("invalid size"));
fpregset = malloc(sizeof(*fpregset), M_TEMP, M_ZERO | M_WAITOK);
-#if defined(COMPAT_FREEBSD32) && __ELF_WORD_SIZE == 32
- fill_fpregs32(td, fpregset);
-#else
- fill_fpregs(td, fpregset);
-#endif
+ __elfN(get_fpregset)(NULL, td, fpregset, sizep);
sbuf_bcat(sb, fpregset, sizeof(*fpregset));
free(fpregset, M_TEMP);
}
Index: sys/kern/init_main.c
===================================================================
--- sys/kern/init_main.c
+++ sys/kern/init_main.c
@@ -437,6 +437,8 @@
.sv_thread_detach = NULL,
.sv_trap = NULL,
.sv_set_fork_retval = null_set_fork_retval,
+ .sv_regset_begin = NULL,
+ .sv_regset_end = NULL,
};
/*
Index: sys/kern/sys_process.c
===================================================================
--- sys/kern/sys_process.c
+++ sys/kern/sys_process.c
@@ -153,6 +153,94 @@
PROC_ACTION(set_fpregs(td, fpregs));
}
+static struct regset *
+proc_find_regset(struct thread *td, int note)
+{
+ struct regset **regsetp, **regset_end, *regset;
+ struct sysentvec *sv;
+
+ sv = td->td_proc->p_sysent;
+ regsetp = sv->sv_regset_begin;
+ if (regsetp == NULL)
+ return (NULL);
+ regset_end = sv->sv_regset_end;
+ MPASS(regset_end != NULL);
+ for (; regsetp < regset_end; regsetp++) {
+ regset = *regsetp;
+ if (regset->note != note)
+ continue;
+
+ return (regset);
+ }
+
+ return (NULL);
+}
+
+static int
+proc_read_regset(struct thread *td, int note, struct iovec *vec)
+{
+ struct regset *regset;
+ size_t size;
+ int error;
+
+ regset = proc_find_regset(td, note);
+ if (regset == NULL)
+ return (EINVAL);
+
+ if (vec->iov_base == NULL) {
+ vec->iov_len = regset->size;
+ if (vec->iov_len == 0)
+ return (EINVAL);
+
+ return (0);
+ }
+
+ /* The length is wrong, return an error */
+ if (vec->iov_len != regset->size)
+ return (EINVAL);
+
+ if (regset->get == NULL)
+ return (EINVAL);
+
+ error = 0;
+ size = vec->iov_len;
+ if (!regset->get(regset, td, vec->iov_base, &size)) {
+ return (EINVAL);
+ }
+
+ KASSERT(size == vec->iov_len,
+ ("%s: Getter function changed the size", __func__));
+
+ return (error);
+}
+
+static int
+proc_write_regset(struct thread *td, int note, struct iovec *vec)
+{
+ struct regset *regset;
+ size_t size;
+
+ regset = proc_find_regset(td, note);
+ if (regset == NULL)
+ return (EINVAL);
+
+ /* The length is wrong, return an error */
+ if (vec->iov_len != regset->size)
+ return (EINVAL);
+
+ if (regset->set == NULL)
+ return (EINVAL);
+
+ size = vec->iov_len;
+ if (!regset->set(regset, td, vec->iov_base, size))
+ return (EINVAL);
+
+ KASSERT(size == vec->iov_len,
+ ("proc_write_regset: Set function changed the size"));
+
+ return (0);
+}
+
#ifdef COMPAT_FREEBSD32
/* For 32 bit binaries, we need to expose the 32 bit regs layouts. */
int
@@ -474,10 +562,12 @@
struct dbreg dbreg;
struct fpreg fpreg;
struct reg reg;
+ struct iovec vec;
char args[sizeof(td->td_sa.args)];
struct ptrace_sc_ret psr;
int ptevents;
} r;
+ struct iovec kern_vec;
void *addr;
int error = 0;
@@ -485,6 +575,7 @@
AUDIT_ARG_CMD(uap->req);
AUDIT_ARG_VALUE(uap->data);
addr = &r;
+ kern_vec.iov_base = NULL;
switch (uap->req) {
case PT_GET_EVENT_MASK:
case PT_LWPINFO:
@@ -500,6 +591,30 @@
case PT_GETDBREGS:
bzero(&r.dbreg, sizeof(r.dbreg));
break;
+ case PT_SETREGSET:
+ error = copyin(uap->addr, &r.vec, sizeof(r.vec));
+ if (error != 0)
+ break;
+ kern_vec.iov_len = r.vec.iov_len;
+ kern_vec.iov_base = malloc(r.vec.iov_len + 1, M_TEMP, M_WAITOK);
+ error = copyin(r.vec.iov_base, kern_vec.iov_base,
+ r.vec.iov_len);
+ if (error == 0)
+ addr = &kern_vec;
+ break;
+ case PT_GETREGSET:
+ error = copyin(uap->addr, &r.vec, sizeof(r.vec));
+ if (error != 0)
+ break;
+
+ if (r.vec.iov_base != NULL) {
+ /* TODO: Check this length isn't too long */
+ kern_vec.iov_len = r.vec.iov_len;
+ kern_vec.iov_base = malloc(r.vec.iov_len, M_TEMP,
+ M_WAITOK);
+ addr = &kern_vec;
+ }
+ break;
case PT_SETREGS:
error = copyin(uap->addr, &r.reg, sizeof(r.reg));
break;
@@ -532,11 +647,11 @@
break;
}
if (error)
- return (error);
+ goto out;
error = kern_ptrace(td, uap->req, uap->pid, addr, uap->data);
if (error)
- return (error);
+ goto out;
switch (uap->req) {
case PT_VM_ENTRY:
@@ -554,6 +669,15 @@
case PT_GETDBREGS:
error = copyout(&r.dbreg, uap->addr, sizeof(r.dbreg));
break;
+ case PT_GETREGSET:
+ if (r.vec.iov_base != NULL) {
+ r.vec.iov_len = MIN(r.vec.iov_len, kern_vec.iov_len);
+ error = copyout(kern_vec.iov_base, r.vec.iov_base,
+ r.vec.iov_len);
+ }
+ if (error == 0)
+ error = copyout(&r.vec, uap->addr, sizeof(r.vec));
+ break;
case PT_GET_EVENT_MASK:
/* NB: The size in uap->data is validated in kern_ptrace(). */
error = copyout(&r.ptevents, uap->addr, uap->data);
@@ -572,6 +696,8 @@
break;
}
+out:
+ free(kern_vec.iov_base, M_TEMP);
return (error);
}
@@ -1285,6 +1411,18 @@
error = PROC_READ(dbregs, td2, addr);
break;
+ case PT_SETREGSET:
+ CTR2(KTR_PTRACE, "PT_SETREGSET: tid %d (pid %d)", td2->td_tid,
+ p->p_pid);
+ error = proc_write_regset(td2, data, addr);
+ break;
+
+ case PT_GETREGSET:
+ CTR2(KTR_PTRACE, "PT_GETREGSET: tid %d (pid %d)", td2->td_tid,
+ p->p_pid);
+ error = proc_read_regset(td2, data, addr);
+ break;
+
case PT_LWPINFO:
if (data <= 0 || data > sizeof(*pl)) {
error = EINVAL;
Index: sys/mips/mips/elf_machdep.c
===================================================================
--- sys/mips/mips/elf_machdep.c
+++ sys/mips/mips/elf_machdep.c
@@ -39,6 +39,7 @@
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
#include <sys/proc.h>
+#include <sys/reg.h>
#include <sys/syscall.h>
#include <sys/signalvar.h>
#include <sys/vnode.h>
@@ -93,6 +94,8 @@
.sv_trap = NULL,
.sv_onexec_old = exec_onexec_old,
.sv_onexit = exit_onexit,
+ .sv_regset_begin = SET_BEGIN(__elfN(regset)),
+ .sv_regset_end = SET_LIMIT(__elfN(regset)),
};
static __ElfN(Brandinfo) freebsd_brand_info = {
Index: sys/mips/mips/freebsd32_machdep.c
===================================================================
--- sys/mips/mips/freebsd32_machdep.c
+++ sys/mips/mips/freebsd32_machdep.c
@@ -107,6 +107,8 @@
.sv_schedtail = NULL,
.sv_thread_detach = NULL,
.sv_trap = NULL,
+ .sv_regset_begin = SET_BEGIN(__elfN(regset)),
+ .sv_regset_end = SET_LIMIT(__elfN(regset)),
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
Index: sys/powerpc/powerpc/elf32_machdep.c
===================================================================
--- sys/powerpc/powerpc/elf32_machdep.c
+++ sys/powerpc/powerpc/elf32_machdep.c
@@ -136,6 +136,8 @@
.sv_hwcap2 = &cpu_features2,
.sv_onexec_old = exec_onexec_old,
.sv_onexit = exit_onexit,
+ .sv_regset_begin = SET_BEGIN(__elfN(regset)),
+ .sv_regset_end = SET_LIMIT(__elfN(regset)),
};
INIT_SYSENTVEC(elf32_sysvec, &elf32_freebsd_sysvec);
Index: sys/powerpc/powerpc/elf64_machdep.c
===================================================================
--- sys/powerpc/powerpc/elf64_machdep.c
+++ sys/powerpc/powerpc/elf64_machdep.c
@@ -30,12 +30,14 @@
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/systm.h>
+#include <sys/elf.h>
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/malloc.h>
#include <sys/proc.h>
#include <sys/namei.h>
#include <sys/fcntl.h>
+#include <sys/reg.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
#include <sys/jail.h>
@@ -98,6 +100,8 @@
.sv_hwcap2 = &cpu_features2,
.sv_onexec_old = exec_onexec_old,
.sv_onexit = exit_onexit,
+ .sv_regset_begin = SET_BEGIN(__elfN(regset)),
+ .sv_regset_end = SET_LIMIT(__elfN(regset)),
};
struct sysentvec elf64_freebsd_sysvec_v2 = {
@@ -139,6 +143,8 @@
.sv_hwcap2 = &cpu_features2,
.sv_onexec_old = exec_onexec_old,
.sv_onexit = exit_onexit,
+ .sv_regset_begin = SET_BEGIN(__elfN(regset)),
+ .sv_regset_end = SET_LIMIT(__elfN(regset)),
};
static boolean_t ppc64_elfv1_header_match(struct image_params *params,
Index: sys/riscv/riscv/elf_machdep.c
===================================================================
--- sys/riscv/riscv/elf_machdep.c
+++ sys/riscv/riscv/elf_machdep.c
@@ -44,6 +44,7 @@
#include <sys/imgact.h>
#include <sys/linker.h>
#include <sys/proc.h>
+#include <sys/reg.h>
#include <sys/sysctl.h>
#include <sys/sysent.h>
#include <sys/imgact_elf.h>
@@ -101,6 +102,8 @@
.sv_machine_arch = riscv_machine_arch,
.sv_onexec_old = exec_onexec_old,
.sv_onexit = exit_onexit,
+ .sv_regset_begin = SET_BEGIN(__elfN(regset)),
+ .sv_regset_end = SET_LIMIT(__elfN(regset)),
};
INIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec);
Index: sys/sys/ptrace.h
===================================================================
--- sys/sys/ptrace.h
+++ sys/sys/ptrace.h
@@ -85,6 +85,8 @@
#define PT_VM_TIMESTAMP 40 /* Get VM version (timestamp) */
#define PT_VM_ENTRY 41 /* Get VM map (entry) */
+#define PT_GETREGSET 42 /* Get a target register set */
+#define PT_SETREGSET 43 /* Set a target register set */
#define PT_FIRSTMACH 64 /* for machine-specific requests */
#include <machine/ptrace.h> /* machine-specific requests, if any */
Index: sys/sys/reg.h
===================================================================
--- sys/sys/reg.h
+++ sys/sys/reg.h
@@ -41,6 +41,25 @@
#include <machine/reg.h>
#ifdef _KERNEL
+struct sbuf;
+struct regset;
+
+typedef bool (regset_get)(struct regset *, struct thread *, void *,
+ size_t *);
+typedef bool (regset_set)(struct regset *, struct thread *, void *, size_t);
+
+struct regset {
+ int note;
+ size_t size;
+ regset_get *get;
+ regset_set *set;
+};
+
+#if defined(__ELF_WORD_SIZE)
+SET_DECLARE(__elfN(regset), struct regset);
+#define ELF_REGSET(_regset) DATA_SET(__elfN(regset), _regset)
+#endif
+
int fill_regs(struct thread *, struct reg *);
int set_regs(struct thread *, struct reg *);
int fill_fpregs(struct thread *, struct fpreg *);
Index: sys/sys/sysent.h
===================================================================
--- sys/sys/sysent.h
+++ sys/sys/sysent.h
@@ -158,6 +158,8 @@
struct image_params *imgp);
void (*sv_set_fork_retval)(struct thread *);
/* Only used on x86 */
+ struct regset **sv_regset_begin;
+ struct regset **sv_regset_end;
};
#define SV_ILP32 0x000100 /* 32-bit executable. */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Jan 24, 10:20 PM (5 m, 45 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16106904
Default Alt Text
D19831.id94898.diff (20 KB)
Attached To
Mode
D19831: Add PT_GETREGSET
Attached
Detach File
Event Timeline
Log In to Comment