Page MenuHomeFreeBSD

D19831.id94898.diff
No OneTemporary

D19831.id94898.diff

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

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)

Event Timeline