From patchwork Mon Oct 9 18:36:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Baldwin X-Patchwork-Id: 77302 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 9D6C1385E00F for ; Mon, 9 Oct 2023 18:37:01 +0000 (GMT) X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mail.baldwin.cx (bigwig.baldwin.cx [66.216.25.90]) by sourceware.org (Postfix) with ESMTPS id 29E443858C39 for ; Mon, 9 Oct 2023 18:36:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 29E443858C39 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.baldwin.net (unknown [98.47.15.113]) by mail.baldwin.cx (Postfix) with ESMTPSA id 735A01A84E24; Mon, 9 Oct 2023 14:36:40 -0400 (EDT) From: John Baldwin To: gdb-patches@sourceware.org Cc: Willgerodt@sourceware.org, Felix , George@sourceware.org, Jini Susan , Simon Marchi Subject: [RFC 02/13] i387-tdep: Add function to read XSAVE layout from NT_X86_CPUID Date: Mon, 9 Oct 2023 11:36:04 -0700 Message-ID: <20231009183617.24862-3-jhb@FreeBSD.org> X-Mailer: git-send-email 2.41.0 In-Reply-To: <20231009183617.24862-1-jhb@FreeBSD.org> References: <20231009183617.24862-1-jhb@FreeBSD.org> MIME-Version: 1.0 X-Greylist: Sender succeeded SMTP AUTH, not delayed by milter-greylist-4.6.4 (mail.baldwin.cx [0.0.0.0]); Mon, 09 Oct 2023 14:36:41 -0400 (EDT) X-Virus-Scanned: clamav-milter 0.103.1 at mail.baldwin.cx X-Virus-Status: Clean X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, FORGED_SPF_HELO, GIT_PATCH_0, KAM_DMARC_STATUS, KHOP_HELO_FCRDNS, SPF_HELO_PASS, SPF_SOFTFAIL, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gdb-patches-bounces+patchwork=sourceware.org@sourceware.org This can be used by x86 arches to determine the XSAVE layout instead of guessing based on the XCR0 mask and XSAVE register note size. --- gdb/i387-tdep.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++ gdb/i387-tdep.h | 8 +++ 2 files changed, 140 insertions(+) diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c index 47667da21c7..1eac2b6bd2a 100644 --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -26,6 +26,8 @@ #include "target-float.h" #include "value.h" +#include + #include "i386-tdep.h" #include "i387-tdep.h" #include "gdbsupport/x86-xstate.h" @@ -987,6 +989,136 @@ i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size, return true; } +/* Parse a reg-x86-cpuid pseudo section building a hash table mapping + cpuid leaves to their results. */ + +struct cpuid_key +{ + cpuid_key (uint32_t _leaf, uint32_t _subleaf) + : leaf(_leaf), subleaf(_subleaf) + {} + + uint32_t leaf; + uint32_t subleaf; + + constexpr bool operator== (const cpuid_key &other) const + { return (leaf == other.leaf && subleaf == other.subleaf); } +}; + +namespace std +{ +template<> +struct hash +{ + size_t operator() (const cpuid_key &key) const + { + return key.leaf ^ (key.subleaf << 1); + } +}; +} + +struct cpuid_values +{ + cpuid_values (uint32_t _eax, uint32_t _ebx, uint32_t _ecx, uint32_t _edx) + : eax(_eax), ebx(_ebx), ecx(_ecx), edx(_edx) + {} + + uint32_t eax; + uint32_t ebx; + uint32_t ecx; + uint32_t edx; +}; + +typedef std::unordered_map cpuid_map; + +static cpuid_map +i387_parse_cpuid_from_core (bfd *bfd) +{ + asection *section = bfd_get_section_by_name (bfd, ".reg-x86-cpuid"); + if (section == nullptr) + return {}; + + size_t size = bfd_section_size (section); + if (size == 0 || (size % (6 * 4)) != 0) + return {}; + + char contents[size]; + if (!bfd_get_section_contents (bfd, section, contents, 0, size)) + { + warning (_("Couldn't read `.reg-x86-cpuid' section in core file.")); + return {}; + } + + cpuid_map map; + size_t index = 0; + while (index < size) + { + uint32_t leaf = bfd_get_32 (bfd, contents + index); + uint32_t count = bfd_get_32 (bfd, contents + index + 4); + uint32_t eax = bfd_get_32 (bfd, contents + index + 8); + uint32_t ebx = bfd_get_32 (bfd, contents + index + 12); + uint32_t ecx = bfd_get_32 (bfd, contents + index + 16); + uint32_t edx = bfd_get_32 (bfd, contents + index + 20); + + if (map.count (cpuid_key (leaf, count)) != 0) + { + warning (_("Duplicate cpuid leaf %#x,%#x"), leaf, count); + return {}; + } + map.emplace (cpuid_key (leaf, count), + cpuid_values (eax, ebx, ecx, edx)); + + index += 6 * 4; + } + + return map; +} + +/* Fetch the offset of a specific XSAVE extended region. */ + +static int +xsave_feature_offset (cpuid_map &map, uint64_t xcr0, int feature) +{ + if ((xcr0 & (1ULL << feature)) == 0) + return 0; + + return map.at (cpuid_key (0xd, feature)).ebx; +} + +/* See i387-tdep.h. */ + +bool +i387_read_xsave_layout_from_core (bfd *bfd, uint64_t xcr0, size_t xsave_size, + x86_xsave_layout &layout) +{ + cpuid_map map = i387_parse_cpuid_from_core (bfd); + if (map.empty ()) + return false; + + try + { + layout.sizeof_xsave = xsave_size; + layout.avx_offset = xsave_feature_offset (map, xcr0, + X86_XSTATE_AVX_ID); + layout.bndregs_offset = xsave_feature_offset (map, xcr0, + X86_XSTATE_BNDREGS_ID); + layout.bndcfg_offset = xsave_feature_offset (map, xcr0, + X86_XSTATE_BNDCFG_ID); + layout.k_offset = xsave_feature_offset (map, xcr0, + X86_XSTATE_K_ID); + layout.zmm_h_offset = xsave_feature_offset (map, xcr0, + X86_XSTATE_ZMM_H_ID); + layout.zmm_offset = xsave_feature_offset (map, xcr0, X86_XSTATE_ZMM_ID); + layout.pkru_offset = xsave_feature_offset (map, xcr0, X86_XSTATE_PKRU_ID); + } + catch (const std::out_of_range &) + { + return false; + } + + return true; +} + /* 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 e149e30e52e..b16b9a60b67 100644 --- a/gdb/i387-tdep.h +++ b/gdb/i387-tdep.h @@ -147,6 +147,14 @@ extern void i387_supply_fxsave (struct regcache *regcache, int regnum, extern bool i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size, x86_xsave_layout &layout); +/* Determine the XSAVE layout from the `reg-x86-cpuid` section in a + core dump. Returns true on sucess, or false if a layout can not be + read. */ + +extern bool i387_read_xsave_layout_from_core (bfd *bfd, 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,