mirror of
https://github.com/openbsd/src.git
synced 2024-12-22 16:42:56 -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 $
|
.\" $NetBSD: ptrace.2,v 1.3 1996/02/23 01:39:41 jtc Exp $
|
||||||
.\"
|
.\"
|
||||||
.\" This file is in the public domain.
|
.\" This file is in the public domain.
|
||||||
.Dd $Mdocdate: September 11 2022 $
|
.Dd $Mdocdate: November 27 2024 $
|
||||||
.Dt PTRACE 2
|
.Dt PTRACE 2
|
||||||
.Os
|
.Os
|
||||||
.Sh NAME
|
.Sh NAME
|
||||||
@ -500,6 +500,58 @@ pointed to by
|
|||||||
The window cookie needs to be
|
The window cookie needs to be
|
||||||
.Sq XOR'ed
|
.Sq XOR'ed
|
||||||
to stack-saved program counters.
|
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
|
.El
|
||||||
.Sh ERRORS
|
.Sh ERRORS
|
||||||
Some requests can cause
|
Some requests can cause
|
||||||
@ -579,6 +631,12 @@ An attempt was made to use
|
|||||||
.Dv PT_ATTACH
|
.Dv PT_ATTACH
|
||||||
on a system process.
|
on a system process.
|
||||||
.El
|
.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
|
.El
|
||||||
.Sh HISTORY
|
.Sh HISTORY
|
||||||
The
|
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 $ */
|
/* $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/param.h>
|
||||||
#include <sys/systm.h>
|
#include <sys/systm.h>
|
||||||
#include <sys/proc.h>
|
#include <sys/proc.h>
|
||||||
|
#include <sys/ptrace.h>
|
||||||
#include <sys/user.h>
|
#include <sys/user.h>
|
||||||
|
|
||||||
#include <uvm/uvm_extern.h>
|
#include <uvm/uvm_extern.h>
|
||||||
@ -200,4 +201,84 @@ process_set_pc(struct proc *p, caddr_t addr)
|
|||||||
return (0);
|
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 */
|
#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 $ */
|
/* $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_SETREGS (PT_FIRSTMACH + 2)
|
||||||
#define PT_GETFPREGS (PT_FIRSTMACH + 3)
|
#define PT_GETFPREGS (PT_FIRSTMACH + 3)
|
||||||
#define PT_SETFPREGS (PT_FIRSTMACH + 4)
|
#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 $ */
|
/* $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 <uvm/uvm_extern.h>
|
||||||
|
|
||||||
|
#include <machine/fpu.h>
|
||||||
#include <machine/reg.h>
|
#include <machine/reg.h>
|
||||||
|
|
||||||
#ifdef PTRACE
|
#ifdef PTRACE
|
||||||
@ -206,6 +207,24 @@ sys_ptrace(struct proc *p, void *v, register_t *retval)
|
|||||||
mode = OUT;
|
mode = OUT;
|
||||||
size = sizeof u.u_pacmask;
|
size = sizeof u.u_pacmask;
|
||||||
break;
|
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
|
#endif
|
||||||
default:
|
default:
|
||||||
return EINVAL;
|
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)[0] = process_get_pacmask(t);
|
||||||
((register_t *)addr)[1] = process_get_pacmask(t);
|
((register_t *)addr)[1] = process_get_pacmask(t);
|
||||||
return 0;
|
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
|
#endif
|
||||||
default:
|
default:
|
||||||
KASSERTMSG(0, "%s: unhandled request %d", __func__, req);
|
KASSERTMSG(0, "%s: unhandled request %d", __func__, req);
|
||||||
|
Loading…
Reference in New Issue
Block a user