From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail.baldwin.cx (bigwig.baldwin.cx [IPv6:2607:f138:0:13::2]) by sourceware.org (Postfix) with ESMTPS id 7F9CB385DC02 for ; Thu, 17 Mar 2022 18:37:33 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7F9CB385DC02 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=FreeBSD.org Authentication-Results: sourceware.org; spf=fail smtp.mailfrom=FreeBSD.org Received: from ralph.com (ralph.baldwin.cx [66.234.199.215]) by mail.baldwin.cx (Postfix) with ESMTPSA id 9FF021A84C82; Thu, 17 Mar 2022 14:37:32 -0400 (EDT) From: John Baldwin To: gdb-patches@sourceware.org Cc: Willgerodt, Felix Subject: [RFC PATCH v2 2/5] core: Support fetching TARGET_OBJECT_X86_XSAVE_LAYOUT from architectures. Date: Thu, 17 Mar 2022 11:36:00 -0700 Message-Id: <20220317183603.34789-3-jhb@FreeBSD.org> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20220317183603.34789-1-jhb@FreeBSD.org> References: <20220317183603.34789-1-jhb@FreeBSD.org> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.6.4 (mail.baldwin.cx [0.0.0.0]); Thu, 17 Mar 2022 14:37:33 -0400 (EDT) X-Virus-Scanned: clamav-milter 0.103.1 at mail.baldwin.cx X-Virus-Status: Clean X-Spam-Status: No, score=-12.3 required=5.0 tests=BAYES_00, FORGED_SPF_HELO, GIT_PATCH_0, KAM_DMARC_STATUS, KHOP_HELO_FCRDNS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 17 Mar 2022 18:37:35 -0000 Add gdbarch_core_xfer_x86_xsave_layout to fetch the x86 XSAVE layout structure from a core file. Current OS's do not export the offsets of XSAVE state components in core dumps, so provide an i387_set_xsave_layout helper function to set offsets based on known combinations of XCR0 masks and total state sizes. Eventually when core dumps do contain this information this function should only be used as a fall back for older core dumps. --- gdb/corelow.c | 22 +++++++++++++++++ gdb/gdbarch-components.py | 13 ++++++++++ gdb/gdbarch-gen.h | 10 ++++++++ gdb/gdbarch.c | 32 ++++++++++++++++++++++++ gdb/i387-tdep.c | 51 +++++++++++++++++++++++++++++++++++++++ gdb/i387-tdep.h | 7 ++++++ 6 files changed, 135 insertions(+) diff --git a/gdb/corelow.c b/gdb/corelow.c index 001c4f147fc..71bfdcff9dd 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -987,6 +987,28 @@ core_target::xfer_partial (enum target_object object, const char *annex, } return TARGET_XFER_E_IO; + case TARGET_OBJECT_X86_XSAVE_LAYOUT: + if (readbuf) + { + if (m_core_gdbarch != nullptr + && gdbarch_core_xfer_x86_xsave_layout_p (m_core_gdbarch)) + { + LONGEST l = gdbarch_core_xfer_x86_xsave_layout (m_core_gdbarch, + readbuf, offset, + len); + + if (l >= 0) + { + *xfered_len = l; + if (l == 0) + return TARGET_XFER_EOF; + else + return TARGET_XFER_OK; + } + } + } + return TARGET_XFER_E_IO; + default: return this->beneath ()->xfer_partial (object, annex, readbuf, writebuf, offset, len, diff --git a/gdb/gdbarch-components.py b/gdb/gdbarch-components.py index c820ddae764..99eaca7f7e2 100644 --- a/gdb/gdbarch-components.py +++ b/gdb/gdbarch-components.py @@ -1584,6 +1584,19 @@ of bytes read (zero indicates EOF, a negative value indicates failure). invalid=True, ) +Method( + comment=""" +Read offset OFFSET of TARGET_OBJECT_X86_XSAVE_LAYOUT from core file +into buffer READBUF with length LEN. Return the number of bytes read +(zero indicates EOF, a negative value indicates failure). +""", + type="LONGEST", + name="core_xfer_x86_xsave_layout", + params=[("gdb_byte *", "readbuf"), ("ULONGEST", "offset"), ("ULONGEST", "len")], + predicate=True, + invalid=True, +) + Value( comment=""" BFD target to use when generating a core file. diff --git a/gdb/gdbarch-gen.h b/gdb/gdbarch-gen.h index 7a8721328ab..82292f9c954 100644 --- a/gdb/gdbarch-gen.h +++ b/gdb/gdbarch-gen.h @@ -921,6 +921,16 @@ typedef LONGEST (gdbarch_core_xfer_siginfo_ftype) (struct gdbarch *gdbarch, gdb_ extern LONGEST gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len); extern void set_gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch, gdbarch_core_xfer_siginfo_ftype *core_xfer_siginfo); +/* Read offset OFFSET of TARGET_OBJECT_X86_XSAVE_LAYOUT from core file + into buffer READBUF with length LEN. Return the number of bytes read + (zero indicates EOF, a negative value indicates failure). */ + +extern bool gdbarch_core_xfer_x86_xsave_layout_p (struct gdbarch *gdbarch); + +typedef LONGEST (gdbarch_core_xfer_x86_xsave_layout_ftype) (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len); +extern LONGEST gdbarch_core_xfer_x86_xsave_layout (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len); +extern void set_gdbarch_core_xfer_x86_xsave_layout (struct gdbarch *gdbarch, gdbarch_core_xfer_x86_xsave_layout_ftype *core_xfer_x86_xsave_layout); + /* BFD target to use when generating a core file. */ extern bool gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch); diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 9fdcf1505fe..e8681d8930b 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -176,6 +176,7 @@ struct gdbarch gdbarch_core_pid_to_str_ftype *core_pid_to_str; gdbarch_core_thread_name_ftype *core_thread_name; gdbarch_core_xfer_siginfo_ftype *core_xfer_siginfo; + gdbarch_core_xfer_x86_xsave_layout_ftype *core_xfer_x86_xsave_layout; const char * gcore_bfd_target; int vtable_function_descriptors; int vbit_in_delta; @@ -532,6 +533,7 @@ verify_gdbarch (struct gdbarch *gdbarch) /* Skip verify of core_pid_to_str, has predicate. */ /* Skip verify of core_thread_name, has predicate. */ /* Skip verify of core_xfer_siginfo, has predicate. */ + /* Skip verify of core_xfer_x86_xsave_layout, has predicate. */ /* Skip verify of gcore_bfd_target, has predicate. */ /* Skip verify of vtable_function_descriptors, invalid_p == 0 */ /* Skip verify of vbit_in_delta, invalid_p == 0 */ @@ -1126,6 +1128,12 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file) fprintf_filtered (file, "gdbarch_dump: core_xfer_siginfo = <%s>\n", host_address_to_string (gdbarch->core_xfer_siginfo)); + fprintf_filtered (file, + "gdbarch_dump: gdbarch_core_xfer_x86_xsave_layout_p() = %d\n", + gdbarch_core_xfer_x86_xsave_layout_p (gdbarch)); + fprintf_filtered (file, + "gdbarch_dump: core_xfer_x86_xsave_layout = <%s>\n", + host_address_to_string (gdbarch->core_xfer_x86_xsave_layout)); fprintf_filtered (file, "gdbarch_dump: gdbarch_gcore_bfd_target_p() = %d\n", gdbarch_gcore_bfd_target_p (gdbarch)); @@ -3864,6 +3872,30 @@ set_gdbarch_core_xfer_siginfo (struct gdbarch *gdbarch, gdbarch->core_xfer_siginfo = core_xfer_siginfo; } +bool +gdbarch_core_xfer_x86_xsave_layout_p (struct gdbarch *gdbarch) +{ + gdb_assert (gdbarch != NULL); + return gdbarch->core_xfer_x86_xsave_layout != NULL; +} + +LONGEST +gdbarch_core_xfer_x86_xsave_layout (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, ULONGEST len) +{ + gdb_assert (gdbarch != NULL); + gdb_assert (gdbarch->core_xfer_x86_xsave_layout != NULL); + if (gdbarch_debug >= 2) + fprintf_unfiltered (gdb_stdlog, "gdbarch_core_xfer_x86_xsave_layout called\n"); + return gdbarch->core_xfer_x86_xsave_layout (gdbarch, readbuf, offset, len); +} + +void +set_gdbarch_core_xfer_x86_xsave_layout (struct gdbarch *gdbarch, + gdbarch_core_xfer_x86_xsave_layout_ftype core_xfer_x86_xsave_layout) +{ + gdbarch->core_xfer_x86_xsave_layout = core_xfer_x86_xsave_layout; +} + bool gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch) { diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c index 2f0b6509457..83df8a7fb0f 100644 --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -898,6 +898,57 @@ static int xsave_pkeys_offset[] = (xsave + xsave_pkeys_offset[regnum - I387_PKRU_REGNUM (tdep)]) +/* See i387-tdep.h. */ + +void +i387_set_xsave_layout (uint64_t xcr0, size_t xsave_size, + x86_xsave_layout *layout) +{ + layout->sizeof_xsave = xsave_size; + if (HAS_PKRU(xcr0) && xsave_size == 2696) + { + /* Intel CPUs supporting PKRU. */ + layout->avx_offset = 576; + layout->bndregs_offset = 960; + layout->bndcfg_offset = 1024; + layout->avx512_k_offset = 1088; + layout->avx512_zmm_h_offset = 1152; + layout->avx512_zmm_offset = 1664; + layout->pkru_offset = 2688; + } + else if (HAS_PKRU(xcr0) && xsave_size == 2440) + { + /* AMD Ryzen 9 CPUs supporting PKRU. */ + layout->avx_offset = 576; + layout->avx512_k_offset = 832; + layout->avx512_zmm_h_offset = 896; + layout->avx512_zmm_offset = 1408; + layout->pkru_offset = 2432; + } + else if (HAS_AVX512(xcr0) && xsave_size == 2688) + { + /* Intel CPUs supporting AVX512. */ + layout->avx_offset = 576; + layout->bndregs_offset = 960; + layout->bndcfg_offset = 1024; + layout->avx512_k_offset = 1088; + layout->avx512_zmm_h_offset = 1152; + layout->avx512_zmm_offset = 1664; + } + else if (HAS_MPX(xcr0) && xsave_size == 1088) + { + /* Intel CPUs supporting MPX. */ + layout->avx_offset = 576; + layout->bndregs_offset = 960; + layout->bndcfg_offset = 1024; + } + else if (HAS_AVX(xcr0) && xsave_size == 832) + { + /* Intel and AMD CPUs supporting AVX. */ + layout->avx_offset = 576; + } +} + /* Extract from XSAVE a bitset of the features that are available on the target, but which have not yet been enabled. */ diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h index 698ff2ee206..4e1403aa753 100644 --- a/gdb/i387-tdep.h +++ b/gdb/i387-tdep.h @@ -25,6 +25,7 @@ struct frame_info; struct regcache; struct type; struct ui_file; +struct x86_xsave_layout; /* Number of i387 floating point registers. */ #define I387_NUM_REGS 16 @@ -138,6 +139,12 @@ extern void i387_collect_fsave (const struct regcache *regcache, int regnum, extern void i387_supply_fxsave (struct regcache *regcache, int regnum, const void *fxsave); +/* Select an XSAVE layout based on the XCR0 bitmask and total XSAVE + extended state size. */ + +extern void i387_set_xsave_layout (uint64_t xcr0, size_t xsave_size, + x86_xsave_layout *layout); + /* Similar to i387_supply_fxsave, but use XSAVE extended state. */ extern void i387_supply_xsave (struct regcache *regcache, int regnum, -- 2.34.1