diff options
author | Andrew Turner <andrew@FreeBSD.org> | 2022-01-24 11:24:17 +0000 |
---|---|---|
committer | John Baldwin <jhb@FreeBSD.org> | 2022-05-12 22:12:59 +0000 |
commit | 658631a37d78c9ea5debe4642630c7154b86bcd6 (patch) | |
tree | 4c6c6628a88f0bd5b1323ccc0061659f40673620 /sys/compat/freebsd32 | |
parent | e5e2c7ffa0f7d9ba0874b95924f4d977b116f45b (diff) |
Add PT_GETREGSET
This adds the PT_GETREGSET and PT_SETREGSET ptrace types. These can be
used to access all the registers from a specified core dump note type.
The NT_PRSTATUS and NT_FPREGSET notes are initially supported. Other
machine-dependant types are expected to be added in the future.
The ptrace addr points to a struct iovec pointing at memory to hold the
registers along with its length. On success the length in the iovec is
updated to tell userspace the actual length the kernel wrote or, if the
base address is NULL, the length the kernel would have written.
Because the data field is an int the arguments are backwards when
compared to the Linux PTRACE_GETREGSET call.
Reviewed by: kib
Sponsored by: The FreeBSD Foundation
Differential Revision: https://reviews.freebsd.org/D19831
(cherry picked from commit 548a2ec49bd4ebf9ab00d362257c6bb4d2d7edbc)
Diffstat (limited to 'sys/compat/freebsd32')
-rw-r--r-- | sys/compat/freebsd32/freebsd32_misc.c | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/sys/compat/freebsd32/freebsd32_misc.c b/sys/compat/freebsd32/freebsd32_misc.c index 4ef33774d6bb..7c82aebb55c3 100644 --- a/sys/compat/freebsd32/freebsd32_misc.c +++ b/sys/compat/freebsd32/freebsd32_misc.c @@ -924,6 +924,7 @@ freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap) struct dbreg32 dbreg; struct fpreg32 fpreg; struct reg32 reg; + struct iovec vec; register_t args[nitems(td->td_sa.args)]; struct ptrace_sc_ret psr; int ptevents; @@ -935,6 +936,7 @@ freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap) struct ptrace_coredump32 pc; uint32_t args[nitems(td->td_sa.args)]; struct ptrace_sc_ret32 psr; + struct iovec32 vec; } r32; void *addr; int data, error, i; @@ -984,6 +986,22 @@ freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap) case PT_SETDBREGS: error = copyin(uap->addr, &r.dbreg, sizeof(r.dbreg)); break; + case PT_SETREGSET: + error = copyin(uap->addr, &r32.vec, sizeof(r32.vec)); + if (error != 0) + break; + + r.vec.iov_len = r32.vec.iov_len; + r.vec.iov_base = PTRIN(r32.vec.iov_base); + break; + case PT_GETREGSET: + error = copyin(uap->addr, &r32.vec, sizeof(r32.vec)); + if (error != 0) + break; + + r.vec.iov_len = r32.vec.iov_len; + r.vec.iov_base = PTRIN(r32.vec.iov_base); + break; case PT_SET_EVENT_MASK: if (uap->data != sizeof(r.ptevents)) error = EINVAL; @@ -1062,6 +1080,10 @@ freebsd32_ptrace(struct thread *td, struct freebsd32_ptrace_args *uap) case PT_GETDBREGS: error = copyout(&r.dbreg, uap->addr, sizeof(r.dbreg)); break; + case PT_GETREGSET: + r32.vec.iov_len = r.vec.iov_len; + error = copyout(&r32.vec, uap->addr, sizeof(r32.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); |