mirror of
https://github.com/openbsd/src.git
synced 2024-12-22 07:27:59 -08:00
Add ptrace commands used to read/write the XSAVE area of a traced
process. Intended to give debuggers access to xmm/ymm registers. Inspired by FreeBSD which exposes a similar set of ptrace commands. ok kettenis@
This commit is contained in:
parent
484eec8f97
commit
deef986e6c
@ -1,8 +1,8 @@
|
||||
.\" $OpenBSD: ptrace.2,v 1.43 2022/09/11 06:38:11 jmc Exp $
|
||||
.\" $OpenBSD: ptrace.2,v 1.44 2024/11/27 05:25:56 anton Exp $
|
||||
.\" $NetBSD: ptrace.2,v 1.3 1996/02/23 01:39:41 jtc Exp $
|
||||
.\"
|
||||
.\" This file is in the public domain.
|
||||
.Dd $Mdocdate: September 11 2022 $
|
||||
.Dd $Mdocdate: November 27 2024 $
|
||||
.Dt PTRACE 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -500,6 +500,58 @@ pointed to by
|
||||
The window cookie needs to be
|
||||
.Sq XOR'ed
|
||||
to stack-saved program counters.
|
||||
.It Dv PT_GETXSTATE_INFO Pq amd64 only
|
||||
This request can be used to obtain details about the traced process XSAVE area,
|
||||
specified in a
|
||||
.Dq Li "struct ptrace_xstate_info"
|
||||
defined as follows:
|
||||
.Bd -literal -offset indent
|
||||
struct ptrace_xstate_info {
|
||||
uint64_t xsave_mask;
|
||||
uint32_t xsave_len;
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
The
|
||||
.Fa xsave_mask
|
||||
field denotes the enabled XSAVE components.
|
||||
The
|
||||
.Fa xsave_len
|
||||
field denotes the size of XSAVE area intended to be used with the
|
||||
.Dv PT_GETXSTATE
|
||||
and
|
||||
.Dv PT_SETXSTATE
|
||||
requests.
|
||||
.Pp
|
||||
A pointer to
|
||||
.Dq Li "struct ptrace_xstate_info"
|
||||
must be passed in
|
||||
.Fa addr
|
||||
and the
|
||||
.Fa data
|
||||
argument must be set to
|
||||
.Li sizeof(struct ptrace_xstate_info) .
|
||||
.It Dv PT_GETXSTATE Pq amd64 only
|
||||
This request can be used to read the XSAVE area of the traced process.
|
||||
A pointer to a buffer must be passed in
|
||||
.Fa addr
|
||||
with a capacity of the length obtained using the
|
||||
.Dv PT_GETXSTATE_INFO
|
||||
request.
|
||||
The
|
||||
.Fa data
|
||||
argument must reflect the same length.
|
||||
.It Dv PT_SETXSTATE Pq amd64 only
|
||||
This request can be used to write the XSAVE area of the traced process.
|
||||
Only changes to the x87, SSE and AVX state components are honored.
|
||||
A pointer to a buffer must be passed in
|
||||
.Fa addr
|
||||
with a capacity of the length obtained using the
|
||||
.Dv PT_GETXSTATE_INFO
|
||||
request.
|
||||
The
|
||||
.Fa data
|
||||
argument must reflect the same length.
|
||||
.El
|
||||
.Sh ERRORS
|
||||
Some requests can cause
|
||||
@ -579,6 +631,12 @@ An attempt was made to use
|
||||
.Dv PT_ATTACH
|
||||
on a system process.
|
||||
.El
|
||||
.It Bq Er ENOTSUP
|
||||
.Dv PT_GETXSTATE_INFO ,
|
||||
.Dv PT_GETXSTATE ,
|
||||
or
|
||||
.Dv PT_SETXSTATE
|
||||
was attempted on a CPU lacking support for XSAVE.
|
||||
.El
|
||||
.Sh HISTORY
|
||||
The
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: process_machdep.c,v 1.17 2024/05/13 01:15:50 jsg Exp $ */
|
||||
/* $OpenBSD: process_machdep.c,v 1.18 2024/11/27 05:25:56 anton Exp $ */
|
||||
/* $NetBSD: process_machdep.c,v 1.1 2003/04/26 18:39:31 fvdl Exp $ */
|
||||
|
||||
/*-
|
||||
@ -56,6 +56,7 @@
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/user.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
@ -200,4 +201,84 @@ process_set_pc(struct proc *p, caddr_t addr)
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
process_read_xstate_info(struct proc *p, void *addr)
|
||||
{
|
||||
struct ptrace_xstate_info *info = addr;
|
||||
|
||||
if (xsave_mask == 0)
|
||||
return (ENOTSUP);
|
||||
|
||||
info->xsave_mask = xsave_mask;
|
||||
info->xsave_len = fpu_save_len;
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct xsave_area {
|
||||
uint8_t legacy_region[512];
|
||||
|
||||
struct xsave_header {
|
||||
uint64_t xstate_bv;
|
||||
uint64_t xcomp_bv;
|
||||
uint8_t rsvd0[48];
|
||||
} xsave_header;
|
||||
|
||||
uint8_t extended_region[];
|
||||
} __attribute__((packed));
|
||||
|
||||
#define XSTATE_COMPONENT_X87 (1ULL << 0)
|
||||
#define XSTATE_COMPONENT_SSE (1ULL << 1)
|
||||
#define XSTATE_COMPONENT_AVX (1ULL << 2)
|
||||
|
||||
int
|
||||
process_read_xstate(struct proc *p, void *addr)
|
||||
{
|
||||
struct xsave_area *area =
|
||||
(struct xsave_area *)&p->p_addr->u_pcb.pcb_savefpu;
|
||||
|
||||
if (xsave_mask == 0)
|
||||
return (ENOTSUP);
|
||||
|
||||
memcpy(addr, area, fpu_save_len);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
process_write_xstate(struct proc *p, void *addr)
|
||||
{
|
||||
struct xsave_area *area =
|
||||
(struct xsave_area *)&p->p_addr->u_pcb.pcb_savefpu;
|
||||
struct xsave_area *new_area = (struct xsave_area *)addr;
|
||||
uint32_t offset_extended_region = offsetof(struct xsave_area,
|
||||
extended_region);
|
||||
uint32_t a, b, c, d;
|
||||
|
||||
if (xsave_mask == 0)
|
||||
return (ENOTSUP);
|
||||
|
||||
/*
|
||||
* Honor changes to x87, SSE and AVX components and mark them as in use.
|
||||
* Required to ensure any changes are restored once the traced process
|
||||
* continues execution.
|
||||
*/
|
||||
if ((xsave_mask & XSTATE_COMPONENT_X87) ||
|
||||
(xsave_mask & XSTATE_COMPONENT_SSE)) {
|
||||
memcpy(area->legacy_region, new_area->legacy_region,
|
||||
sizeof(area->legacy_region));
|
||||
area->xsave_header.xstate_bv |= xsave_mask &
|
||||
(XSTATE_COMPONENT_X87 | XSTATE_COMPONENT_SSE);
|
||||
}
|
||||
if (xsave_mask & XSTATE_COMPONENT_AVX) {
|
||||
CPUID_LEAF(0xd, 2, a, b, c, d);
|
||||
if (offset_extended_region == b &&
|
||||
offset_extended_region + a <= fpu_save_len) {
|
||||
memcpy(area->extended_region,
|
||||
new_area->extended_region, a);
|
||||
area->xsave_header.xstate_bv |= XSTATE_COMPONENT_AVX;
|
||||
}
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif /* PTRACE */
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: ptrace.h,v 1.1 2004/01/28 01:39:39 mickey Exp $ */
|
||||
/* $OpenBSD: ptrace.h,v 1.2 2024/11/27 05:25:57 anton Exp $ */
|
||||
/* $NetBSD: ptrace.h,v 1.1 2003/04/26 18:39:47 fvdl Exp $ */
|
||||
|
||||
/*
|
||||
@ -39,3 +39,18 @@
|
||||
#define PT_SETREGS (PT_FIRSTMACH + 2)
|
||||
#define PT_GETFPREGS (PT_FIRSTMACH + 3)
|
||||
#define PT_SETFPREGS (PT_FIRSTMACH + 4)
|
||||
|
||||
#define PT_GETXSTATE_INFO (PT_FIRSTMACH + 5)
|
||||
#define PT_GETXSTATE (PT_FIRSTMACH + 6)
|
||||
#define PT_SETXSTATE (PT_FIRSTMACH + 7)
|
||||
|
||||
struct ptrace_xstate_info {
|
||||
uint64_t xsave_mask;
|
||||
uint32_t xsave_len;
|
||||
};
|
||||
|
||||
#ifdef _KERNEL
|
||||
int process_read_xstate_info(struct proc *, void *);
|
||||
int process_read_xstate(struct proc *, void *);
|
||||
int process_write_xstate(struct proc *, void *);
|
||||
#endif
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $OpenBSD: sys_process.c,v 1.102 2024/10/08 12:02:24 claudio Exp $ */
|
||||
/* $OpenBSD: sys_process.c,v 1.103 2024/11/27 05:25:57 anton Exp $ */
|
||||
/* $NetBSD: sys_process.c,v 1.55 1996/05/15 06:17:47 tls Exp $ */
|
||||
|
||||
/*-
|
||||
@ -66,6 +66,7 @@
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
||||
#include <machine/fpu.h>
|
||||
#include <machine/reg.h>
|
||||
|
||||
#ifdef PTRACE
|
||||
@ -206,6 +207,24 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
|
||||
mode = OUT;
|
||||
size = sizeof u.u_pacmask;
|
||||
break;
|
||||
#endif
|
||||
#ifdef PT_GETXSTATE_INFO
|
||||
case PT_GETXSTATE_INFO:
|
||||
mode = OUT_ALLOC;
|
||||
size = sizeof(struct ptrace_xstate_info);
|
||||
break;
|
||||
#endif
|
||||
#ifdef PT_GETXSTATE
|
||||
case PT_GETXSTATE:
|
||||
mode = OUT_ALLOC;
|
||||
size = fpu_save_len;
|
||||
break;
|
||||
#endif
|
||||
#ifdef PT_SETXSTATE
|
||||
case PT_SETXSTATE:
|
||||
mode = IN_ALLOC;
|
||||
size = fpu_save_len;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return EINVAL;
|
||||
@ -759,6 +778,18 @@ ptrace_ustate(struct proc *p, int req, pid_t pid, void *addr, int data,
|
||||
((register_t *)addr)[0] = process_get_pacmask(t);
|
||||
((register_t *)addr)[1] = process_get_pacmask(t);
|
||||
return 0;
|
||||
#endif
|
||||
#ifdef PT_GETXSTATE_INFO
|
||||
case PT_GETXSTATE_INFO:
|
||||
return process_read_xstate_info(t, addr);
|
||||
#endif
|
||||
#ifdef PT_GETXSTATE
|
||||
case PT_GETXSTATE:
|
||||
return process_read_xstate(t, addr);
|
||||
#endif
|
||||
#ifdef PT_SETXSTATE
|
||||
case PT_SETXSTATE:
|
||||
return process_write_xstate(t, addr);
|
||||
#endif
|
||||
default:
|
||||
KASSERTMSG(0, "%s: unhandled request %d", __func__, req);
|
||||
|
Loading…
Reference in New Issue
Block a user