From nobody Thu Mar 24 18:48:32 2022 X-Original-To: dev-commits-src-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id D3EF11A47DCF; Thu, 24 Mar 2022 18:48:32 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4KPZ4J47PRz3lwV; Thu, 24 Mar 2022 18:48:32 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1648147712; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=qIcFNKrHIgKtyipbEgWGu1yOD/owHERczdA340yRgQY=; b=E4TIZxJjxQPy6MKWlGY8v5RSQ73AVjk3/Cs6lp6hDo+U86RScPtHWPDDbu7UA3Tr60ViUd 5RVJSCRGAm6TkOH/kHgM+eK3LZ8Jzpzl6JOgvHC+0h84DoWE4GvYCaFL7kK4q0DUadbdmA y0bpsOGERLE+NitBkcZWh0VO4jt48AwVxdhiqCLXLgUGmxgdTUXzGRliyFZdQvhR+x8n1d gL/qsz6zFa75mvC/YkCNysD/9FECwLg+ocM2Oo55sei3R4QJwDs1ZOnuFrAcXh+IYd0foN WFg5Olmto2eCQSGSqsaDbIP7TBK59fSspX/Wa4ziW28erhj6hJLDUFoSPjcBqg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 6A7151D147; Thu, 24 Mar 2022 18:48:32 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 22OImWhL080717; Thu, 24 Mar 2022 18:48:32 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 22OImWii080716; Thu, 24 Mar 2022 18:48:32 GMT (envelope-from git) Date: Thu, 24 Mar 2022 18:48:32 GMT Message-Id: <202203241848.22OImWii080716@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: John Baldwin Subject: git: 931983ee0864 - main - x86: Add a NT_X86_SEGBASES register set. List-Id: Commit messages for the main branch of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-main@freebsd.org X-BeenThere: dev-commits-src-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: jhb X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 931983ee0864079c5f1be0a6b3b9ef097d84ffba Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1648147712; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=qIcFNKrHIgKtyipbEgWGu1yOD/owHERczdA340yRgQY=; b=dek/i+xX1t6weUZecRyvyBm3Og0F3u1e/RPrCGpnRpBOJMEGndBaUKDgVCZBBrboHO8jz4 Jc8RF5dxDPfsEu/HlYHWndJC78UxcdXl1nYFjZMN4pzrBGwAMyjkEQfDwNmqR2Hac56nUB RA1l9rGVPyiL1uiqIu6bU0Z6eiIjIJG6p868N7Yaw2NtzvmYRFVRw4WKf3se/yEN0zhtg6 4LK5B15sTKOOLG/WM8uQepzMoS/OuKtSdmgyVdiezPF7fWb2uE9BBQ6khJ17QqwL3CqnNk bgg4igWGRwTvPwPSx9QHhL2eB75NBq3hqqFZFAcL88iBRqCt6NrLTMK2Kkzo1A== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1648147712; a=rsa-sha256; cv=none; b=Do7gZVba3rfkAtZJOv1UEP2CA81528nGgFoavNtEDkcgwOMgiZLL2GIJVTkJcfgFcsTWkj EL/dqDh3dxeWyzh51sk5FmF9o2KoKWww6Rs0WxRX9DO78BQv+g3IkDY56lAS7EslAMCMUA XxE3wPj5xN71vGRO96ANi2Vgjlj5neBlxYuMlK3kTfxCnmAv/7NM9Bjazzuyr+SUfX9CBA b3hNI3hkVkKy23Vg6ZrA2MyRprQ4/cc1i+6CJrBOL/aejvySOp9W3nxh2e2uU8tG6HJui2 2tHTVULcIWMM+M0uAJlUAwHfKUfRlm/JBRyT+0P0McyairN4JOOy3ZRHEkUskw== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by jhb: URL: https://cgit.FreeBSD.org/src/commit/?id=931983ee0864079c5f1be0a6b3b9ef097d84ffba commit 931983ee0864079c5f1be0a6b3b9ef097d84ffba Author: John Baldwin AuthorDate: 2022-03-24 18:36:19 +0000 Commit: John Baldwin CommitDate: 2022-03-24 18:36:19 +0000 x86: Add a NT_X86_SEGBASES register set. This register set contains the values of the fsbase and gsbase registers. Note that these registers can already be controlled individually via ptrace(2) via MD operations, so the main reason for adding this is to include these register values in core dumps. In particular, this will enable looking up the value of TLS variables from core dumps in gdb. The value of NT_X86_SEGBASES was chosen to match the value of NT_386_TLS on Linux. The notes serve similar purposes, but FreeBSD will never dump a note equivalent to NT_386_TLS (which dumps a single segment descriptor rather than a pair of addresses) and picking a currently-unused value in the NT_X86_* range could result in a future conflict. Reviewed by: markj Differential Revision: https://reviews.freebsd.org/D34650 --- contrib/elftoolchain/readelf/readelf.c | 1 + sys/amd64/amd64/ptrace_machdep.c | 102 +++++++++++++++++++++++++++++++++ sys/amd64/ia32/ia32_reg.c | 50 ++++++++++++++++ sys/i386/i386/ptrace_machdep.c | 51 ++++++++++++++++- sys/sys/elf_common.h | 1 + sys/x86/include/reg.h | 18 ++++++ usr.bin/gcore/elfcore.c | 1 + 7 files changed, 223 insertions(+), 1 deletion(-) diff --git a/contrib/elftoolchain/readelf/readelf.c b/contrib/elftoolchain/readelf/readelf.c index fa3cdca3d682..25dda95f2a50 100644 --- a/contrib/elftoolchain/readelf/readelf.c +++ b/contrib/elftoolchain/readelf/readelf.c @@ -1195,6 +1195,7 @@ note_type_freebsd_core(unsigned int nt) case 17: return "NT_PTLWPINFO"; case 0x100: return "NT_PPC_VMX (ppc Altivec registers)"; case 0x102: return "NT_PPC_VSX (ppc VSX registers)"; + case 0x200: return "NT_X86_SEGBASES (x86 segment base registers)"; case 0x202: return "NT_X86_XSTATE (x86 XSAVE extended state)"; case 0x400: return "NT_ARM_VFP (arm VFP registers)"; case 0x401: return "NT_ARM_TLS (arm TLS register)"; diff --git a/sys/amd64/amd64/ptrace_machdep.c b/sys/amd64/amd64/ptrace_machdep.c index 74fd48c68492..069a5b4cdb9d 100644 --- a/sys/amd64/amd64/ptrace_machdep.c +++ b/sys/amd64/amd64/ptrace_machdep.c @@ -32,11 +32,13 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -52,6 +54,106 @@ struct ptrace_xstate_info32 { }; #endif +static bool +get_segbases(struct regset *rs, struct thread *td, void *buf, + size_t *sizep) +{ + struct segbasereg *reg; + struct pcb *pcb; + + if (buf != NULL) { + KASSERT(*sizep == sizeof(*reg), ("%s: invalid size", __func__)); + reg = buf; + + pcb = td->td_pcb; + if (td == curthread) + update_pcb_bases(pcb); + reg->r_fsbase = pcb->pcb_fsbase; + reg->r_gsbase = pcb->pcb_gsbase; + } + *sizep = sizeof(*reg); + return (true); +} + +static bool +set_segbases(struct regset *rs, struct thread *td, void *buf, + size_t size) +{ + struct segbasereg *reg; + struct pcb *pcb; + + KASSERT(size == sizeof(*reg), ("%s: invalid size", __func__)); + reg = buf; + + pcb = td->td_pcb; + set_pcb_flags(pcb, PCB_FULL_IRET); + pcb->pcb_fsbase = reg->r_fsbase; + td->td_frame->tf_fs = _ufssel; + pcb->pcb_gsbase = reg->r_gsbase; + td->td_frame->tf_gs = _ugssel; + + return (true); +} + +static struct regset regset_segbases = { + .note = NT_X86_SEGBASES, + .size = sizeof(struct segbasereg), + .get = get_segbases, + .set = set_segbases, +}; +ELF_REGSET(regset_segbases); + +#ifdef COMPAT_FREEBSD32 +static bool +get_segbases32(struct regset *rs, struct thread *td, void *buf, + size_t *sizep) +{ + struct segbasereg32 *reg; + struct pcb *pcb; + + if (buf != NULL) { + KASSERT(*sizep == sizeof(*reg), ("%s: invalid size", __func__)); + reg = buf; + + pcb = td->td_pcb; + if (td == curthread) + update_pcb_bases(pcb); + reg->r_fsbase = (uint32_t)pcb->pcb_fsbase; + reg->r_gsbase = (uint32_t)pcb->pcb_gsbase; + } + *sizep = sizeof(*reg); + return (true); +} + +static bool +set_segbases32(struct regset *rs, struct thread *td, void *buf, + size_t size) +{ + struct segbasereg32 *reg; + struct pcb *pcb; + + KASSERT(size == sizeof(*reg), ("%s: invalid size", __func__)); + reg = buf; + + pcb = td->td_pcb; + set_pcb_flags(pcb, PCB_FULL_IRET); + pcb->pcb_fsbase = reg->r_fsbase; + td->td_frame->tf_fs = _ufssel; + pcb->pcb_gsbase = reg->r_gsbase; + td->td_frame->tf_gs = _ugssel; + + return (true); +} + +static struct regset regset_segbases32 = { + .note = NT_X86_SEGBASES, + .size = sizeof(struct segbasereg32), + .get = get_segbases32, + .set = set_segbases32, +}; +ELF32_REGSET(regset_segbases32); +#endif + static int cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data) { diff --git a/sys/amd64/ia32/ia32_reg.c b/sys/amd64/ia32/ia32_reg.c index 343d1564e1ff..539a268ef350 100644 --- a/sys/amd64/ia32/ia32_reg.c +++ b/sys/amd64/ia32/ia32_reg.c @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include +#include #include #include #include @@ -266,3 +267,52 @@ set_dbregs32(struct thread *td, struct dbreg32 *regs) dr.dr[i] = 0; return (set_dbregs(td, &dr)); } + +static bool +get_i386_segbases(struct regset *rs, struct thread *td, void *buf, + size_t *sizep) +{ + struct segbasereg32 *reg; + struct pcb *pcb; + + if (buf != NULL) { + KASSERT(*sizep == sizeof(*reg), ("%s: invalid size", __func__)); + reg = buf; + + pcb = td->td_pcb; + if (td == curthread) + update_pcb_bases(pcb); + reg->r_fsbase = pcb->pcb_fsbase; + reg->r_gsbase = pcb->pcb_gsbase; + } + *sizep = sizeof(*reg); + return (true); +} + +static bool +set_i386_segbases(struct regset *rs, struct thread *td, void *buf, + size_t size) +{ + struct segbasereg32 *reg; + struct pcb *pcb; + + KASSERT(size == sizeof(*reg), ("%s: invalid size", __func__)); + reg = buf; + + pcb = td->td_pcb; + set_pcb_flags(pcb, PCB_FULL_IRET); + pcb->pcb_fsbase = reg->r_fsbase; + td->td_frame->tf_fs = _ufssel; + pcb->pcb_gsbase = reg->r_gsbase; + td->td_frame->tf_gs = _ugssel; + + return (true); +} + +static struct regset regset_i386_segbases = { + .note = NT_X86_SEGBASES, + .size = sizeof(struct segbasereg), + .get = get_i386_segbases, + .set = set_i386_segbases, +}; +ELF32_REGSET(regset_i386_segbases); diff --git a/sys/i386/i386/ptrace_machdep.c b/sys/i386/i386/ptrace_machdep.c index 7ddc697502cf..29551336f8a6 100644 --- a/sys/i386/i386/ptrace_machdep.c +++ b/sys/i386/i386/ptrace_machdep.c @@ -34,15 +34,64 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include #include #include +#include #include #include #include +static uint32_t +get_segbase(struct segment_descriptor *sdp) +{ + return (sdp->sd_hibase << 24 | sdp->sd_lobase); +} + +static bool +get_segbases(struct regset *rs, struct thread *td, void *buf, + size_t *sizep) +{ + struct segbasereg *reg; + + if (buf != NULL) { + KASSERT(*sizep == sizeof(*reg), ("%s: invalid size", __func__)); + reg = buf; + reg->r_fsbase = get_segbase(&td->td_pcb->pcb_fsd); + reg->r_gsbase = get_segbase(&td->td_pcb->pcb_gsd); + } + *sizep = sizeof(*reg); + return (true); +} + +static bool +set_segbases(struct regset *rs, struct thread *td, void *buf, + size_t size) +{ + struct segbasereg *reg; + + KASSERT(size == sizeof(*reg), ("%s: invalid size", __func__)); + reg = buf; + + fill_based_sd(&td->td_pcb->pcb_fsd, reg->r_fsbase); + td->td_frame->tf_fs = GSEL(GUFS_SEL, SEL_UPL); + fill_based_sd(&td->td_pcb->pcb_gsd, reg->r_gsbase); + td->td_pcb->pcb_gs = GSEL(GUGS_SEL, SEL_UPL); + + return (true); +} + +static struct regset regset_segbases = { + .note = NT_X86_SEGBASES, + .size = sizeof(struct segbasereg), + .get = get_segbases, + .set = set_segbases, +}; +ELF_REGSET(regset_segbases); + static int cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data) { @@ -173,7 +222,7 @@ cpu_ptrace(struct thread *td, int req, void *addr, int data) case PT_GETGSBASE: sdp = req == PT_GETFSBASE ? &td->td_pcb->pcb_fsd : &td->td_pcb->pcb_gsd; - r = sdp->sd_hibase << 24 | sdp->sd_lobase; + r = get_segbase(sdp); error = copyout(&r, addr, sizeof(r)); break; diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h index 022bbf450e6c..4eae060895ab 100644 --- a/sys/sys/elf_common.h +++ b/sys/sys/elf_common.h @@ -823,6 +823,7 @@ typedef struct { #define NT_PTLWPINFO 17 /* Thread ptrace miscellaneous info. */ #define NT_PPC_VMX 0x100 /* PowerPC Altivec/VMX registers */ #define NT_PPC_VSX 0x102 /* PowerPC VSX registers */ +#define NT_X86_SEGBASES 0x200 /* x86 FS/GS base addresses. */ #define NT_X86_XSTATE 0x202 /* x86 XSAVE extended state. */ #define NT_ARM_VFP 0x400 /* ARM VFP registers */ #define NT_ARM_TLS 0x401 /* ARM TLS register */ diff --git a/sys/x86/include/reg.h b/sys/x86/include/reg.h index 7be3e24850c3..e237b080be1c 100644 --- a/sys/x86/include/reg.h +++ b/sys/x86/include/reg.h @@ -86,6 +86,7 @@ #define __reg32 reg #define __fpreg32 fpreg #define __dbreg32 dbreg +#define __segbasereg32 segbasereg #else #define __reg32 reg32 #define __reg64 reg @@ -93,6 +94,8 @@ #define __fpreg64 fpreg #define __dbreg32 dbreg32 #define __dbreg64 dbreg +#define __segbasereg32 segbasereg32 +#define __segbasereg64 segbasereg #define __HAVE_REG32 #endif @@ -236,12 +239,27 @@ struct __dbreg64 { #define DBREG_DRX(d,x) ((d)->dr[(x)]) /* reference dr0 - dr7 by register number */ +/* + * Register set accessible via NT_X86_SEGBASES. + */ +struct __segbasereg32 { + __uint32_t r_fsbase; + __uint32_t r_gsbase; +}; + +struct __segbasereg64 { + __uint64_t r_fsbase; + __uint64_t r_gsbase; +}; + #undef __reg32 #undef __reg64 #undef __fpreg32 #undef __fpreg64 #undef __dbreg32 #undef __dbreg64 +#undef __segbasereg32 +#undef __segbasereg64 #ifdef _KERNEL /* diff --git a/usr.bin/gcore/elfcore.c b/usr.bin/gcore/elfcore.c index c3ef36938ea9..1fcd14698a9e 100644 --- a/usr.bin/gcore/elfcore.c +++ b/usr.bin/gcore/elfcore.c @@ -379,6 +379,7 @@ elf_putnotes(pid_t pid, struct sbuf *sb, size_t *sizep) elf_putregnote(NT_ARM_VFP, tids[i], sb); #endif #if defined(__i386__) || defined(__amd64__) + elf_putregnote(NT_X86_SEGBASES, tids[i], sb); elf_putnote(NT_X86_XSTATE, elf_note_x86_xstate, tids + i, sb); #endif #if defined(__powerpc__)