Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F111102412
D19831.id55838.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
6 KB
Referenced Files
None
Subscribers
None
D19831.id55838.diff
View Options
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>
@@ -152,6 +153,44 @@
(sysinit_cfunc_t) elf64_insert_brand_entry,
&kfreebsd_brand_info);
+static regset_get x86_xstate_get;
+static struct regset x86_xstate = {
+ .note = NT_X86_XSTATE,
+ .size = 0,
+ .align = _Alignof(uint64_t),
+ .get = &x86_xstate_get,
+};
+ELF_REGSET(x86_xstate);
+
+static void
+x86_xstate_update(void *arg __unused)
+{
+
+ x86_xstate.size = cpu_max_ext_state_size;
+}
+SYSINIT(x86_xstate_update, SI_SUB_DRIVERS, SI_ORDER_ANY, x86_xstate_update,
+ NULL);
+
+static bool
+x86_xstate_get(struct regset *rs, struct thread *td, void *dst, size_t *sizep)
+{
+
+ if (!use_xsave)
+ return (false);
+
+ KASSERT(*sizep >= cpu_max_ext_state_size,
+ ("x86_xstate_get: Size is too small (%zu < %u)", *sizep,
+ cpu_max_ext_state_size));
+ *sizep = cpu_max_ext_state_size;
+ if (dst != NULL) {
+ fpugetregs(td);
+ memcpy(dst, get_pcb_user_save_td(td), cpu_max_ext_state_size);
+ *(uint64_t *)((char *)dst + X86_XSTATE_XCR0_OFFSET) =
+ xsave_mask;
+ }
+ return (true);
+}
+
void
elf64_dump_thread(struct thread *td, void *dst, size_t *off)
{
Index: sys/kern/sys_process.c
===================================================================
--- sys/kern/sys_process.c
+++ sys/kern/sys_process.c
@@ -88,6 +88,11 @@
};
#endif
+struct ptrace_regset {
+ void *prs_addr;
+ size_t prs_size;
+};
+
/*
* Functions implemented using PROC_ACTION():
*
@@ -171,6 +176,47 @@
PROC_ACTION(set_fpregs(td, fpregs));
}
+SET_DECLARE(elf_regset, struct regset);
+static size_t
+proc_regset_maxsize(int note)
+{
+ struct regset **regsetpp, *regsetp;
+
+ SET_FOREACH(regsetpp, elf_regset) {
+ regsetp = *regsetpp;
+ if (regsetp->note != note)
+ continue;
+
+ return (regsetp->size);
+ }
+
+ return (0);
+}
+
+static int
+proc_read_regset(struct thread *td, int note, struct iovec *vec)
+{
+ struct regset **regsetpp, *regsetp;
+ size_t size;
+ int err;
+
+ SET_FOREACH(regsetpp, elf_regset) {
+ regsetp = *regsetpp;
+ if (regsetp->note != note)
+ continue;
+
+ err = 0;
+ size = vec->iov_len;
+ if (!regsetp->get(regsetp, td, vec->iov_base, &size))
+ err = EINVAL;
+ KASSERT(size == vec->iov_len,
+ ("proc_read_regset: Get function changed the size"));
+
+ return (err);
+ }
+ return (EINVAL);
+}
+
#ifdef COMPAT_FREEBSD32
/* For 32 bit binaries, we need to expose the 32 bit regs layouts. */
int
@@ -568,6 +614,7 @@
struct dbreg dbreg;
struct fpreg fpreg;
struct reg reg;
+ struct iovec vec;
#ifdef COMPAT_FREEBSD32
struct dbreg32 dbreg32;
struct fpreg32 fpreg32;
@@ -579,6 +626,7 @@
char args[sizeof(td->td_sa.args)];
int ptevents;
} r;
+ struct iovec kern_vec;
void *addr;
int error = 0;
#ifdef COMPAT_FREEBSD32
@@ -591,6 +639,8 @@
AUDIT_ARG_CMD(uap->req);
AUDIT_ARG_VALUE(uap->data);
addr = &r;
+ kern_vec.iov_base = NULL;
+ kern_vec.iov_len = 0;
switch (uap->req) {
case PT_GET_EVENT_MASK:
case PT_LWPINFO:
@@ -605,6 +655,25 @@
case PT_GETDBREGS:
BZERO(&r.dbreg, sizeof r.dbreg);
break;
+ case PT_GETREGSET:
+ if (wrap32) {
+ /* TODO: compat32 support */
+ error = EINVAL;
+ break;
+ }
+
+ error = copyin(uap->addr, &r.vec, sizeof r.vec);
+ if (error != 0)
+ break;
+ kern_vec.iov_len = proc_regset_maxsize(uap->data);
+ if (kern_vec.iov_len == 0) {
+ error = EINVAL;
+ break;
+ }
+ kern_vec.iov_base = malloc(kern_vec.iov_len, M_TEMP,
+ M_WAITOK | M_ZERO);
+ addr = &kern_vec;
+ break;
case PT_SETREGS:
error = COPYIN(uap->addr, &r.reg, sizeof r.reg);
break;
@@ -634,8 +703,10 @@
return (error);
error = kern_ptrace(td, uap->req, uap->pid, addr, uap->data);
- if (error)
+ if (error) {
+ free(kern_vec.iov_base, M_TEMP);
return (error);
+ }
switch (uap->req) {
case PT_VM_ENTRY:
@@ -653,6 +724,16 @@
case PT_GETDBREGS:
error = COPYOUT(&r.dbreg, uap->addr, sizeof r.dbreg);
break;
+ case PT_GETREGSET:
+ 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) {
+ break;
+ }
+ error = copyout(&r.vec, uap->addr, sizeof r.vec);
+ free(kern_vec.iov_base, M_TEMP);
+ 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);
@@ -1319,6 +1400,12 @@
error = PROC_READ(dbregs, td2, 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 ||
#ifdef COMPAT_FREEBSD32
Index: sys/sys/ptrace.h
===================================================================
--- sys/sys/ptrace.h
+++ sys/sys/ptrace.h
@@ -37,6 +37,7 @@
#include <sys/signal.h>
#include <sys/param.h>
+#include <sys/_iovec.h>
#include <sys/reg.h>
#define PT_TRACE_ME 0 /* child declares it's being traced */
@@ -83,6 +84,9 @@
#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
@@ -5,6 +5,20 @@
#include <machine/reg.h>
#ifdef _KERNEL
+struct regset;
+
+typedef bool (regset_get)(struct regset *, struct thread *, void *,
+ size_t *);
+
+struct regset {
+ int note;
+ size_t size;
+ size_t align;
+ regset_get *get;
+};
+
+#define ELF_REGSET(regset) DATA_SET(elf_regset, regset)
+
int fill_regs(struct thread *, struct reg *);
int set_regs(struct thread *, struct reg *);
int fill_fpregs(struct thread *, struct fpreg *);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Feb 28, 11:10 AM (20 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16884628
Default Alt Text
D19831.id55838.diff (6 KB)
Attached To
Mode
D19831: Add PT_GETREGSET
Attached
Detach File
Event Timeline
Log In to Comment