Page MenuHomeFreeBSD

D19831.id55838.diff
No OneTemporary

D19831.id55838.diff

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

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)

Event Timeline