From patchwork Tue Jun 2 11:11:21 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schimpe, Christina" X-Patchwork-Id: 136294 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A58024BA2E0D for ; Tue, 2 Jun 2026 11:12:58 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org A58024BA2E0D Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=CecTGt2r X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) by sourceware.org (Postfix) with ESMTPS id 117584BA2E1C for ; Tue, 2 Jun 2026 11:11:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 117584BA2E1C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 117584BA2E1C Authentication-Results: sourceware.org; arc=none smtp.remote-ip=198.175.65.9 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1780398703; cv=none; b=s1A/qwuNI0TAcTSeHqv3tCdFh650hMnav55y1naMC4s6FqTKFF1X9SUAvJKU3HD8m6TWw2nCbhD64HH9VVOFO1hZoPkTisvSkBz8/dlh+cuiFitEfGhRLkJu0ZzEcZCKBjyYDo296C+7G4eT6icgtGX6K4MN4PzB3vtI0rzbbsw= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1780398703; c=relaxed/simple; bh=stnGir/zD4yV1jueFWMYzvy9lEfPyaPozR6ezzzDJhM=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=FJabiKI8YIU5TaaX3c4pkJJx9QBY+DAfEFqqbGjVb8aFPidmXun0cX+k4k0/GNMJnV0+og6Pe0uYOdSdDQhn9+gbUbzNk9/WRaR0VmQRW1dJjdW8+9eX5XJopzJWgHWJd6fZkRwBwd7XCPjMu8R4OqC4ZrLXlXeC4m399qd9x3g= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=CecTGt2r DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 117584BA2E1C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1780398703; x=1811934703; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=stnGir/zD4yV1jueFWMYzvy9lEfPyaPozR6ezzzDJhM=; b=CecTGt2rQJ2puZ/981naUtqS5YvbN6nBT017URhR4iTtP7/neINthybp zeYqLCmAmubqzWtkWbQLiA30cWwv8CIMnHfgT6xj10QOWq4GoWeKQOFPO /QbM7zdasByb6ZzcCb9HumQGW80J7qNt3D2TQ6YT/37CbhVNizG2jdkO0 +gpFBnmEwuUCR0T8Fpz2u7vp8a5xPJERSTLeG7pOwZqHgwP7Zb/yNtMjT x0cHLstQroON7nG9SVH49FPYtX5lC1aimfwgHmFf6qn9MkL5W0CYsXjbO dClMvDNMLCrMEILZGWjFUSgPdgopnesCxjbzRJfTLA9RZA9Il/TrFtPy5 w==; X-CSE-ConnectionGUID: 96G2g/vGTLu+68wyOfV4tg== X-CSE-MsgGUID: KrLYBqkqRn24wrtO3rbXUA== X-IronPort-AV: E=McAfee;i="6800,10657,11804"; a="103840257" X-IronPort-AV: E=Sophos;i="6.24,183,1774335600"; d="scan'208";a="103840257" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Jun 2026 04:11:42 -0700 X-CSE-ConnectionGUID: A2yt/k7sQZy0wW/T2g+hNA== X-CSE-MsgGUID: C4IUJBYwQCuywSCN0iDFmA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.24,183,1774335600"; d="scan'208";a="243989905" Received: from gkldtt-dev-004.igk.intel.com (HELO localhost) ([10.123.221.202]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Jun 2026 04:11:42 -0700 From: Christina Schimpe To: gdb-patches@sourceware.org Cc: hjl.tools@gmail.com, keiths@redhat.com Subject: [PATCH 1/2] gdb: add maintenance set/show gcore xml-target-description command Date: Tue, 2 Jun 2026 11:11:21 +0000 Message-Id: <20260602111122.3187712-2-christina.schimpe@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260602111122.3187712-1-christina.schimpe@intel.com> References: <20260602111122.3187712-1-christina.schimpe@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_BLOCKED, SPF_HELO_NONE, SPF_NONE, TXREP, URIBL_BLOCKED shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on 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 From: Felix Willgerodt This command will allow to enable/disable creating the NT_GDB_TDESC note in corefiles. While GDB writes and reads this node, there aren't really many other pieces of software that create this node (e.g. the Linux kernel doesn't). To be able to test the code path in GDB that is used when NT_GDB_TDESC is not there, add a maintenance command which tests can use to test both cases. Co-authored-by: Christina Schimpe Reviewed-By: Eli Zaretskii Reviewed-By: Keith Seitz --- gdb/NEWS | 6 ++++++ gdb/doc/gdb.texinfo | 7 +++++++ gdb/elf-none-tdep.c | 16 +++++++++------- gdb/fbsd-tdep.c | 15 +++++++++------ gdb/gcore.c | 40 ++++++++++++++++++++++++++++++++++++++++ gdb/gcore.h | 3 +++ gdb/linux-tdep.c | 15 +++++++++------ 7 files changed, 83 insertions(+), 19 deletions(-) diff --git a/gdb/NEWS b/gdb/NEWS index 7c8cf9af4c2..eef1924c9f0 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -97,6 +97,12 @@ AArch64 MinGW aarch64-*-mingw* * New commands +maintenance set/show gcore xml-target-description + With this command you can control whether or not the generate-core-file + command emits the NT_GDB_TDESC note. This is mainly useful for testing + how GDB handles corefiles without this note, as not all software that + creates corefiles generates it. + set local-environment show local-environment unset local-environment diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index a698b2b8451..636fd0d6b1f 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -42077,6 +42077,13 @@ buffer. Control whether @value{GDBN} will skip PAD packets when computing the packet history. +@kindex maint set gcore xml-target-description +@item maint set gcore xml-target-description +@kindex maint show gcore xml-target-description +@item maint show gcore xml-target-description +Control whether @value{GDBN} will create the NT_GDB_TDESC note when using +the @samp{generate-core-file} command. + @kindex maint info jit @item maint info jit Print information about JIT code objects loaded in the current inferior. diff --git a/gdb/elf-none-tdep.c b/gdb/elf-none-tdep.c index 0d063038f5e..f874ba9d4b9 100644 --- a/gdb/elf-none-tdep.c +++ b/gdb/elf-none-tdep.c @@ -109,13 +109,15 @@ elf_none_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, ¬e_data, note_size); } - - /* Include the target description when possible. Some architectures - allow for per-thread gdbarch so we should really be emitting a tdesc - per-thread, however, we don't currently support reading in a - per-thread tdesc, so just emit the tdesc for the signalled thread. */ - gdbarch = target_thread_architecture (signalled_thr->ptid); - gcore_elf_make_tdesc_note (gdbarch, obfd, ¬e_data, note_size); + if (maint_gcore_emit_xml_tdesc) + { + /* Include the target description when possible. Some architectures + allow for per-thread gdbarch so we should really be emitting a tdesc + per-thread, however, we don't currently support reading in a + per-thread tdesc, so just emit the tdesc for the signalled thread. */ + gdbarch = target_thread_architecture (signalled_thr->ptid); + gcore_elf_make_tdesc_note (gdbarch, obfd, ¬e_data, note_size); + } return note_data; } diff --git a/gdb/fbsd-tdep.c b/gdb/fbsd-tdep.c index 419f935ea72..d77395dbb45 100644 --- a/gdb/fbsd-tdep.c +++ b/gdb/fbsd-tdep.c @@ -762,12 +762,15 @@ fbsd_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) return NULL; } - /* Include the target description when possible. Some architectures - allow for per-thread gdbarch so we should really be emitting a tdesc - per-thread, however, we don't currently support reading in a - per-thread tdesc, so just emit the tdesc for the signalled thread. */ - gdbarch = target_thread_architecture (signalled_thr->ptid); - gcore_elf_make_tdesc_note (gdbarch, obfd, ¬e_data, note_size); + if (maint_gcore_emit_xml_tdesc) + { + /* Include the target description when possible. Some architectures + allow for per-thread gdbarch so we should really be emitting a tdesc + per-thread, however, we don't currently support reading in a + per-thread tdesc, so just emit the tdesc for the signalled thread. */ + gdbarch = target_thread_architecture (signalled_thr->ptid); + gcore_elf_make_tdesc_note (gdbarch, obfd, ¬e_data, note_size); + } return note_data; } diff --git a/gdb/gcore.c b/gdb/gcore.c index e50115370c7..03876969ae9 100644 --- a/gdb/gcore.c +++ b/gdb/gcore.c @@ -28,6 +28,7 @@ #include "completer.h" #include "gcore.h" #include "cli/cli-decode.h" +#include "cli/cli-cmds.h" #include #include "regcache.h" #include "regset.h" @@ -919,6 +920,24 @@ gcore_find_signalled_thread () return nullptr; } +/* When true, emit NT_GDB_TDESC. */ +bool maint_gcore_emit_xml_tdesc = true; + +/* Command lists for gcore maintenance commands. */ +struct cmd_list_element *maint_gcore_cmdlist; +struct cmd_list_element *maint_gcore_set_cmdlist; +struct cmd_list_element *maint_gcore_show_cmdlist; + +/* "Show" callback for "maint set gcore xml-target-description". */ +static void +show_gcore_xml_target_description (struct ui_file *file, int from_tty, + struct cmd_list_element *c, + const char *value) +{ + gdb_printf (file, _("Write NT_GDB_TDESC note into corefiles: %s.\n"), + value); +} + INIT_GDB_FILE (gcore) { cmd_list_element *generate_core_file_cmd @@ -928,4 +947,25 @@ Usage: generate-core-file [FILENAME]\n\ Argument is optional filename. Default filename is 'core.PROCESS_ID'.")); add_com_alias ("gcore", generate_core_file_cmd, class_files, 1); + + add_basic_prefix_cmd ("gcore", class_maintenance, + _("gcore maintenance commands."), + &maint_gcore_cmdlist, 0, &maintenancelist); + + add_setshow_prefix_cmd ("gcore", class_maintenance, + _("Set gcore specific variables."), + _("Show gcore specific variables."), + &maint_gcore_set_cmdlist, &maint_gcore_show_cmdlist, + &maintenance_set_cmdlist, &maintenance_show_cmdlist); + + add_setshow_boolean_cmd ("xml-target-description", class_obscure, + &maint_gcore_emit_xml_tdesc, _("\ +Set whether gcore emits a xml-target-description."), _("\ +Show whether gore emits a xml-target-description."), _("\ +By default, gcore emits the note NT_GDB_TDESC.\n\ +Disabling this setting will cause gcore to no longer emit this note."), + nullptr, + show_gcore_xml_target_description, + &maint_gcore_set_cmdlist, + &maint_gcore_show_cmdlist); } diff --git a/gdb/gcore.h b/gdb/gcore.h index 2431e123b60..2481bf0decc 100644 --- a/gdb/gcore.h +++ b/gdb/gcore.h @@ -37,4 +37,7 @@ extern bool objfile_find_memory_regions (struct target_ops *self, extern thread_info *gcore_find_signalled_thread (); +/* When true, emit NT_GDB_TDESC. */ +extern bool maint_gcore_emit_xml_tdesc; + #endif /* GDB_GCORE_H */ diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c index a7381677498..6bc4e55aa56 100644 --- a/gdb/linux-tdep.c +++ b/gdb/linux-tdep.c @@ -2495,12 +2495,15 @@ linux_make_corefile_notes (struct gdbarch *gdbarch, bfd *obfd, int *note_size) /* File mappings. */ linux_make_mappings_corefile_notes (gdbarch, obfd, note_data, note_size); - /* Include the target description when possible. Some architectures - allow for per-thread gdbarch so we should really be emitting a tdesc - per-thread, however, we don't currently support reading in a - per-thread tdesc, so just emit the tdesc for the signalled thread. */ - gdbarch = target_thread_architecture (signalled_thr->ptid); - gcore_elf_make_tdesc_note (gdbarch, obfd, ¬e_data, note_size); + if (maint_gcore_emit_xml_tdesc) + { + /* Include the target description when possible. Some architectures + allow for per-thread gdbarch so we should really be emitting a tdesc + per-thread, however, we don't currently support reading in a + per-thread tdesc, so just emit the tdesc for the signalled thread. */ + gdbarch = target_thread_architecture (signalled_thr->ptid); + gcore_elf_make_tdesc_note (gdbarch, obfd, ¬e_data, note_size); + } return note_data; } From patchwork Tue Jun 2 11:11:22 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Schimpe, Christina" X-Patchwork-Id: 136293 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 77FC64BA2E12 for ; Tue, 2 Jun 2026 11:12:57 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 77FC64BA2E12 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=KPR6SCjD X-Original-To: gdb-patches@sourceware.org Delivered-To: gdb-patches@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.9]) by sourceware.org (Postfix) with ESMTPS id 5F1554BA2E2C for ; Tue, 2 Jun 2026 11:11:50 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 5F1554BA2E2C Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 5F1554BA2E2C Authentication-Results: sourceware.org; arc=none smtp.remote-ip=198.175.65.9 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1780398718; cv=none; b=N9NE5HQiVImWRDHrqI/uzZyvcQB4DCjQTEwG2sEVy74Bq14ke0KpueXM57oxIE643zX4waxpkM63sAgbNI1vFoXCP9mryCNle8aRD137pL32xHlgevJ5nDhXTOo+whtk/OiTBBIY8idWWc0MYUxjatkKd4R+XxyA6CY8thnxZz4= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1780398718; c=relaxed/simple; bh=+Bl0V8357lQaYyUcnD9PGoTVWmOMcKcT3m8eCqZPwYE=; h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version; b=V+BexGePgTnJbACf8SPQel43HEC7VCGwhITS3gLvulDfLLF0NLryqQOxnwZCOWhasP4oJQd9AxREFe2lMKnL1ffLfUlInLUQRcDMpjUsaJ2EIanF1Z55D97m0Hsg6+Eu3sMXjD9Uh5Xm8/cxtKcP0f/ShSsytLpLnlezaRp65Q4= ARC-Authentication-Results: i=1; sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=KPR6SCjD DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 5F1554BA2E2C DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1780398710; x=1811934710; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+Bl0V8357lQaYyUcnD9PGoTVWmOMcKcT3m8eCqZPwYE=; b=KPR6SCjDmsfyHA6de7J6mvfPyjLJo068NfzBK59z9cLStKwwRzYD5miC oae5YYnBgAP6ahGmsEFgHxbyv8J5xudBTxNWRyKYEonLtd6QhiFXeZJS9 tRbnaBgSZM3qsFhS8UEzsMrujiL4sJAoN4QtLgKgvTWZOaESe8GNa0HQx RRErv3lYYgcrSfzglYRrqtITgx+w4pA6xMbFcJ7yWEfTCZLqVQqFEF2nL SpscJ/fyA+FS6leQS3efTtwFdimPuGdG+Waw1irfQUlTWj9n86qaEfDDE Rdf4EfWhvzf7EXwDiob7Tyu5aK49k+zwev7BlUg1AAJRLJtX5ywDfNHJG Q==; X-CSE-ConnectionGUID: ltEn4G3TQga4Rh/Lhh4q7Q== X-CSE-MsgGUID: k8+VdmDfTK+dTTmFTxG2aA== X-IronPort-AV: E=McAfee;i="6800,10657,11804"; a="103840268" X-IronPort-AV: E=Sophos;i="6.24,183,1774335600"; d="scan'208";a="103840268" Received: from orviesa007.jf.intel.com ([10.64.159.147]) by orvoesa101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Jun 2026 04:11:50 -0700 X-CSE-ConnectionGUID: 5UwjM4vJRkezVTAdJhwAAA== X-CSE-MsgGUID: Uu7rABaSRQaoO+a1I5GyRA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.24,183,1774335600"; d="scan'208";a="243989912" Received: from gkldtt-dev-004.igk.intel.com (HELO localhost) ([10.123.221.202]) by orviesa007-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 02 Jun 2026 04:11:49 -0700 From: Christina Schimpe To: gdb-patches@sourceware.org Cc: hjl.tools@gmail.com, keiths@redhat.com Subject: [PATCH 2/2] gdb, gdbserver: Add Intel APX register support Date: Tue, 2 Jun 2026 11:11:22 +0000 Message-Id: <20260602111122.3187712-3-christina.schimpe@intel.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20260602111122.3187712-1-christina.schimpe@intel.com> References: <20260602111122.3187712-1-christina.schimpe@intel.com> MIME-Version: 1.0 X-Spam-Status: No, score=-10.2 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, SPF_HELO_NONE, SPF_NONE, TXREP, URIBL_BLOCKED shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on 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 From: "H.J. Lu" Intel(R) Advanced Performance Extensions (APX) doubles the number of general-purpose registers (GPRs) from 16 to 32 (r16-r31). Those new 64-bit Extended GPRs (EGPRs) do not change the size of the XSAVE area, as they take up the space left behind by the deprecated MPX registers. In contrast to the legacy GPRS, EGPRs are not enabled by default in 64-bit mode but are xcr0 enabled based on APX_F Intel APX state. Define X86_XSTATE_APX_F to support this new configuration. Add gdb and gdbserver registers support for those new 64-bit EGPRs. Also add byte, word and dword pseudo register support. Co-authored-by: Christina Schimpe Reviewed-By: Eli Zaretskii --- gdb/NEWS | 4 + gdb/amd64-linux-tdep.c | 2 + gdb/amd64-tdep.c | 262 ++++++++++++++---- gdb/amd64-tdep.h | 2 + gdb/arch/amd64.c | 4 + gdb/arch/x86-linux-tdesc-features.c | 1 + gdb/doc/gdb.texinfo | 4 + gdb/features/Makefile | 1 + gdb/features/i386/64bit-apx.c | 29 ++ gdb/features/i386/64bit-apx.xml | 26 ++ gdb/i386-tdep.c | 32 ++- gdb/i386-tdep.h | 26 ++ gdb/i387-tdep.c | 105 ++++++- gdb/i387-tdep.h | 6 + gdb/nat/x86-xstate.c | 1 + gdb/target-debug.h | 1 + gdb/testsuite/gdb.arch/amd64-apx-corefile.exp | 87 ++++++ gdb/testsuite/gdb.arch/amd64-apx.c | 83 ++++++ gdb/testsuite/gdb.arch/amd64-apx.exp | 106 +++++++ gdb/testsuite/lib/gdb.exp | 59 ++++ gdbserver/i387-fp.cc | 43 +++ gdbserver/linux-x86-low.cc | 4 +- gdbsupport/x86-xstate.h | 12 +- 23 files changed, 838 insertions(+), 62 deletions(-) create mode 100644 gdb/features/i386/64bit-apx.c create mode 100644 gdb/features/i386/64bit-apx.xml create mode 100644 gdb/testsuite/gdb.arch/amd64-apx-corefile.exp create mode 100644 gdb/testsuite/gdb.arch/amd64-apx.c create mode 100644 gdb/testsuite/gdb.arch/amd64-apx.exp diff --git a/gdb/NEWS b/gdb/NEWS index eef1924c9f0..7b6169bd35f 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -83,6 +83,10 @@ * Support for native Thread Local Storage (TLS) variables on Windows. +* Support for Intel APX registers on amd64 GNU/Linux. + Support displaying and modifying Intel APX registers (Extended GPRs + $r16 - $r31) including byte, word and dword pseudo registers. + * Configure changes ** --with-babeltrace has been removed. The babeltrace library was diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index a5ac26654cf..814f1f77fa3 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -113,6 +113,8 @@ int amd64_linux_gregset_reg_offset[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, /* PKEYS register pkru */ -1, /* CET user mode register PL3_SSP. */ + -1, -1, -1, -1, -1, -1, -1, -1, /* r16 ... r31. */ + -1, -1, -1, -1, -1, -1, -1, -1, /* End of hardware registers */ 21 * 8, 22 * 8, /* fs_base and gs_base. */ diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 0d23abb3164..a74f94731e1 100755 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -61,6 +61,36 @@ /* Register information. */ +/* Number of general purpose registers without APX. */ +#define AMD64_NUM_GPRS 16 + +/* Number of lower byte registers without APX. */ +#define AMD64_NUM_LOWER_BYTE_REGS AMD64_NUM_GPRS + +/* Number of byte registers without APX. */ +#define AMD64_NUM_BYTE_REGS (AMD64_NUM_LOWER_BYTE_REGS + 4) + +/* Number of word registers without APX. */ +#define AMD64_NUM_WORD_REGS AMD64_NUM_GPRS + +/* Number of dword registers without APX. */ +#define AMD64_NUM_DWORD_REGS AMD64_NUM_GPRS + +/* Number of general purpose registers with APX. */ +#define AMD64_APX_NUM_GPRS 32 + +/* Number of APX lower byte registers. */ +#define AMD64_APX_NUM_LOWER_BYTE_REGS AMD64_APX_NUM_GPRS + +/* Number of APX byte registers. */ +#define AMD64_APX_NUM_BYTE_REGS (AMD64_APX_NUM_LOWER_BYTE_REGS + 4) + +/* Number of APX word registers. */ +#define AMD64_APX_NUM_WORD_REGS AMD64_APX_NUM_GPRS + +/* Number of APX dword registers. */ +#define AMD64_APX_NUM_DWORD_REGS AMD64_APX_NUM_GPRS + static const char * const amd64_register_names[] = { "rax", "rbx", "rcx", "rdx", "rsi", "rdi", "rbp", "rsp", @@ -87,6 +117,12 @@ static const char * const amd64_ymm_names[] = "ymm12", "ymm13", "ymm14", "ymm15" }; +static const char * const amd64_apx_names[] = +{ + "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31" +}; + static const char * const amd64_ymm_avx512_names[] = { "ymm16", "ymm17", "ymm18", "ymm19", @@ -252,7 +288,20 @@ static int amd64_dwarf_regmap[] = AMD64_K0_REGNUM + 0, AMD64_K0_REGNUM + 1, AMD64_K0_REGNUM + 2, AMD64_K0_REGNUM + 3, AMD64_K0_REGNUM + 4, AMD64_K0_REGNUM + 5, - AMD64_K0_REGNUM + 6, AMD64_K0_REGNUM + 7 + AMD64_K0_REGNUM + 6, AMD64_K0_REGNUM + 7, + + /* Reserved. */ + -1, -1, -1, -1, + + /* r16-r31. */ + AMD64_R16_REGNUM + 0, AMD64_R16_REGNUM + 1, + AMD64_R16_REGNUM + 2, AMD64_R16_REGNUM + 3, + AMD64_R16_REGNUM + 4, AMD64_R16_REGNUM + 5, + AMD64_R16_REGNUM + 6, AMD64_R16_REGNUM + 7, + AMD64_R16_REGNUM + 8, AMD64_R16_REGNUM + 9, + AMD64_R16_REGNUM + 10, AMD64_R16_REGNUM + 11, + AMD64_R16_REGNUM + 12, AMD64_R16_REGNUM + 13, + AMD64_R16_REGNUM + 14, AMD64_R16_REGNUM + 15 }; static const int amd64_dwarf_regmap_len = @@ -322,8 +371,19 @@ static const char * const amd64_byte_names[] = "ah", "bh", "ch", "dh" }; -/* Number of lower byte registers. */ -#define AMD64_NUM_LOWER_BYTE_REGS 16 +static_assert (ARRAY_SIZE (amd64_byte_names) == AMD64_NUM_BYTE_REGS); + +static const char * const amd64_apx_byte_names[] = +{ + "al", "bl", "cl", "dl", "sil", "dil", "bpl", "spl", + "r8l", "r9l", "r10l", "r11l", "r12l", "r13l", "r14l", "r15l", + "r16l", "r17l", "r18l", "r19l", "r20l", "r21l", "r22l", "r23l", + "r24l", "r25l", "r26l", "r27l", "r28l", "r29l", "r30l", "r31l", + "ah", "bh", "ch", "dh" +}; + +static_assert (ARRAY_SIZE (amd64_apx_byte_names) + == AMD64_APX_NUM_BYTE_REGS); /* Register names for word pseudo-registers. */ @@ -333,6 +393,19 @@ static const char * const amd64_word_names[] = "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w" }; +static_assert (ARRAY_SIZE (amd64_word_names) == AMD64_NUM_WORD_REGS); + +static const char * const amd64_apx_word_names[] = +{ + "ax", "bx", "cx", "dx", "si", "di", "bp", "", + "r8w", "r9w", "r10w", "r11w", "r12w", "r13w", "r14w", "r15w", + "r16w", "r17w", "r18w", "r19w", "r20w", "r21w", "r22w", "r23w", + "r24w", "r25w", "r26w", "r27w", "r28w", "r29w", "r30w", "r31w" +}; + +static_assert (ARRAY_SIZE (amd64_apx_word_names) + == AMD64_APX_NUM_WORD_REGS); + /* Register names for dword pseudo-registers. */ static const char * const amd64_dword_names[] = @@ -342,28 +415,90 @@ static const char * const amd64_dword_names[] = "eip" }; +static_assert (ARRAY_SIZE (amd64_dword_names) == AMD64_NUM_DWORD_REGS + 1); + +static const char * const amd64_apx_dword_names[] = +{ + "eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp", + "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", + "r16d", "r17d", "r18d", "r19d", "r20d", "r21d", "r22d", "r23d", + "r24d", "r25d", "r26d", "r27d", "r28d", "r29d", "r30d", "r31d", + "eip" +}; + +static_assert (ARRAY_SIZE (amd64_apx_dword_names) + == AMD64_APX_NUM_DWORD_REGS + 1); + /* Return the name of register REGNUM. */ static const char * amd64_pseudo_register_name (struct gdbarch *gdbarch, int regnum) { i386_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); - if (i386_byte_regnum_p (gdbarch, regnum)) - return amd64_byte_names[regnum - tdep->al_regnum]; - else if (i386_zmm_regnum_p (gdbarch, regnum)) + if (i386_zmm_regnum_p (gdbarch, regnum)) return amd64_zmm_names[regnum - tdep->zmm0_regnum]; else if (i386_ymm_regnum_p (gdbarch, regnum)) return amd64_ymm_names[regnum - tdep->ymm0_regnum]; else if (i386_ymm_avx512_regnum_p (gdbarch, regnum)) return amd64_ymm_avx512_names[regnum - tdep->ymm16_regnum]; - else if (i386_word_regnum_p (gdbarch, regnum)) - return amd64_word_names[regnum - tdep->ax_regnum]; else if (i386_dword_regnum_p (gdbarch, regnum)) - return amd64_dword_names[regnum - tdep->eax_regnum]; + return tdep->dword_names[regnum - tdep->eax_regnum]; else return i386_pseudo_register_name (gdbarch, regnum); } +/* Return the raw byte register number. *PART is set to 1 for high + byte register and 0 otherwise. */ + +static int +amd64_raw_byte_register (i386_gdbarch_tdep *tdep, int regnum, int *part) +{ + int gpnum = regnum - tdep->al_regnum; + + /* Extract (always little endian). */ + if (gpnum >= tdep->num_lower_byte_regs) + { + /* Special handling for AH, BH, CH, DH. */ + *part = 1; + gpnum -= tdep->num_lower_byte_regs; + } + else + { + *part = 0; + if (gpnum >= AMD64_NUM_GPRS) + { + gdb_assert (tdep->r16_regnum != -1); + gpnum += tdep->r16_regnum - 16; + } + } + return gpnum; +} + +/* Return the raw word register number. */ + +static int +amd64_raw_word_register (i386_gdbarch_tdep *tdep, int regnum) +{ + int gpnum = regnum - tdep->ax_regnum; + if (gpnum >= 16) + gpnum += tdep->r16_regnum - 16; + return gpnum; +} + +/* Return the raw dword register number. For x32, the last dword + register is EIP. */ + +static int +amd64_raw_dword_register (i386_gdbarch_tdep *tdep, int regnum) +{ + int gpnum = regnum - tdep->eax_regnum; + if (tdep->eip_regnum == gpnum) + return AMD64_RIP_REGNUM; + if (gpnum >= 16) + gpnum += tdep->r16_regnum - 16; + return gpnum; +} + static value * amd64_pseudo_register_read_value (gdbarch *gdbarch, const frame_info_ptr &next_frame, int regnum) @@ -372,23 +507,18 @@ amd64_pseudo_register_read_value (gdbarch *gdbarch, const frame_info_ptr &next_f if (i386_byte_regnum_p (gdbarch, regnum)) { - int gpnum = regnum - tdep->al_regnum; - - /* Extract (always little endian). */ - if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS) - { - gpnum -= AMD64_NUM_LOWER_BYTE_REGS; - - /* Special handling for AH, BH, CH, DH. */ - return pseudo_from_raw_part (next_frame, regnum, gpnum, 1); - } - else - return pseudo_from_raw_part (next_frame, regnum, gpnum, 0); + int part; + const int gpnum = amd64_raw_byte_register (tdep, regnum, &part); + return pseudo_from_raw_part (next_frame, regnum, gpnum, part); + } + else if (i386_word_regnum_p (gdbarch, regnum)) + { + const int gpnum = amd64_raw_word_register (tdep, regnum); + return pseudo_from_raw_part (next_frame, regnum, gpnum, 0); } else if (i386_dword_regnum_p (gdbarch, regnum)) { - int gpnum = regnum - tdep->eax_regnum; - + const int gpnum = amd64_raw_dword_register (tdep, regnum); return pseudo_from_raw_part (next_frame, regnum, gpnum, 0); } else @@ -403,19 +533,18 @@ amd64_pseudo_register_write (gdbarch *gdbarch, const frame_info_ptr &next_frame, if (i386_byte_regnum_p (gdbarch, regnum)) { - int gpnum = regnum - tdep->al_regnum; - - if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS) - { - gpnum -= AMD64_NUM_LOWER_BYTE_REGS; - pseudo_to_raw_part (next_frame, buf, gpnum, 1); - } - else - pseudo_to_raw_part (next_frame, buf, gpnum, 0); + int part; + const int gpnum = amd64_raw_byte_register (tdep, regnum, &part); + pseudo_to_raw_part (next_frame, buf, gpnum, part); + } + else if (i386_word_regnum_p (gdbarch, regnum)) + { + const int gpnum = amd64_raw_word_register (tdep, regnum); + pseudo_to_raw_part (next_frame, buf, gpnum, 0); } else if (i386_dword_regnum_p (gdbarch, regnum)) { - int gpnum = regnum - tdep->eax_regnum; + const int gpnum = amd64_raw_dword_register (tdep, regnum); pseudo_to_raw_part (next_frame, buf, gpnum, 0); } else @@ -432,17 +561,18 @@ amd64_ax_pseudo_register_collect (struct gdbarch *gdbarch, if (i386_byte_regnum_p (gdbarch, regnum)) { - int gpnum = regnum - tdep->al_regnum; - - if (gpnum >= AMD64_NUM_LOWER_BYTE_REGS) - ax_reg_mask (ax, gpnum - AMD64_NUM_LOWER_BYTE_REGS); - else - ax_reg_mask (ax, gpnum); + int part; + const int gpnum = amd64_raw_byte_register (tdep, regnum, &part); + ax_reg_mask (ax, gpnum); + } + else if (i386_word_regnum_p (gdbarch, regnum)) + { + const int gpnum = amd64_raw_word_register (tdep, regnum); + ax_reg_mask (ax, gpnum); } else if (i386_dword_regnum_p (gdbarch, regnum)) { - int gpnum = regnum - tdep->eax_regnum; - + const int gpnum = amd64_raw_dword_register (tdep, regnum); ax_reg_mask (ax, gpnum); } else @@ -3552,9 +3682,30 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch, if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.pl3_ssp") != nullptr) tdep->ssp_regnum = AMD64_PL3_SSP_REGNUM; - tdep->num_byte_regs = 20; - tdep->num_word_regs = 16; - tdep->num_dword_regs = 16; + if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.apx") != nullptr) + { + tdep->apx_register_names = amd64_apx_names; + tdep->num_apx_regs = 16; + tdep->r16_regnum = AMD64_R16_REGNUM; + tdep->byte_names = amd64_apx_byte_names; + tdep->word_names = amd64_apx_word_names; + tdep->dword_names = amd64_apx_dword_names; + tdep->num_lower_byte_regs = AMD64_APX_NUM_LOWER_BYTE_REGS; + tdep->num_byte_regs = AMD64_APX_NUM_BYTE_REGS; + tdep->num_word_regs = AMD64_APX_NUM_WORD_REGS; + tdep->num_dword_regs = AMD64_APX_NUM_DWORD_REGS; + } + else + { + tdep->byte_names = amd64_byte_names; + tdep->word_names = amd64_word_names; + tdep->dword_names = amd64_dword_names; + tdep->num_lower_byte_regs = AMD64_NUM_LOWER_BYTE_REGS; + tdep->num_byte_regs = AMD64_NUM_BYTE_REGS; + tdep->num_word_regs = AMD64_NUM_WORD_REGS; + tdep->num_dword_regs = AMD64_NUM_DWORD_REGS; + } + /* Avoid wiring in the MMX registers for now. */ tdep->num_mmx_regs = 0; @@ -3663,15 +3814,13 @@ static struct type * amd64_x32_pseudo_register_type (struct gdbarch *gdbarch, int regnum) { i386_gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + const int gpnum = regnum - tdep->eax_regnum; - switch (regnum - tdep->eax_regnum) - { - case AMD64_RBP_REGNUM: /* %ebp */ - case AMD64_RSP_REGNUM: /* %esp */ - return builtin_type (gdbarch)->builtin_data_ptr; - case AMD64_RIP_REGNUM: /* %eip */ - return builtin_type (gdbarch)->builtin_func_ptr; - } + if (gpnum == tdep->eip_regnum) /* %eip. */ + return builtin_type (gdbarch)->builtin_func_ptr; + else if (gpnum == AMD64_RBP_REGNUM /* %ebp. */ + || gpnum == AMD64_RSP_REGNUM) /* %esp. */ + return builtin_type (gdbarch)->builtin_data_ptr; return i386_pseudo_register_type (gdbarch, regnum); } @@ -3684,7 +3833,10 @@ amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch, amd64_init_abi (info, gdbarch, default_tdesc); - tdep->num_dword_regs = 17; + /* Set %eip to the last dword register. */ + tdep->eip_regnum = tdep->num_dword_regs; + /* Increment 1 for %eip. */ + tdep->num_dword_regs += 1; set_tdesc_pseudo_register_type (gdbarch, amd64_x32_pseudo_register_type); set_gdbarch_long_bit (gdbarch, 32); @@ -3706,12 +3858,14 @@ const struct target_desc * amd64_target_description (uint64_t xstate_bv, bool segments) { static const_target_desc_up amd64_tdescs \ - [2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*CET_U*/][2/*segments*/] = {}; + [2/*AVX*/][2/*AVX512*/][2/*PKRU*/][2/*CET_U*/][2/*APX*/] \ + [2/*segments*/] = {}; const_target_desc_up &tdesc = amd64_tdescs[(xstate_bv & X86_XSTATE_AVX) ? 1 : 0] [(xstate_bv & X86_XSTATE_AVX512) ? 1 : 0] [(xstate_bv & X86_XSTATE_PKRU) ? 1 : 0] [(xstate_bv & X86_XSTATE_CET_U) ? 1 : 0] + [(xstate_bv & X86_XSTATE_APX_F) ? 1 : 0] [segments ? 1 : 0]; if (tdesc == nullptr) diff --git a/gdb/amd64-tdep.h b/gdb/amd64-tdep.h index 3de28952cca..93b3cb61b17 100644 --- a/gdb/amd64-tdep.h +++ b/gdb/amd64-tdep.h @@ -82,6 +82,8 @@ enum amd64_regnum AMD64_ZMM31H_REGNUM = AMD64_ZMM0H_REGNUM + 31, AMD64_PKRU_REGNUM, AMD64_PL3_SSP_REGNUM, + AMD64_R16_REGNUM, + AMD64_R31_REGNUM = AMD64_R16_REGNUM + 15, AMD64_FSBASE_REGNUM, AMD64_GSBASE_REGNUM }; diff --git a/gdb/arch/amd64.c b/gdb/arch/amd64.c index d1a871dd6cb..3992bbf512e 100644 --- a/gdb/arch/amd64.c +++ b/gdb/arch/amd64.c @@ -23,6 +23,7 @@ #include "../features/i386/64bit-avx.c" #include "../features/i386/64bit-avx512.c" #include "../features/i386/64bit-core.c" +#include "../features/i386/64bit-apx.c" #include "../features/i386/64bit-linux.c" #include "../features/i386/64bit-segments.c" #include "../features/i386/64bit-sse.c" @@ -78,5 +79,8 @@ amd64_create_target_description (uint64_t xstate_bv, bool is_x32, regnum = create_feature_i386_32bit_ssp (tdesc.get (), regnum); } + if (xstate_bv & X86_XSTATE_APX_F) + regnum = create_feature_i386_64bit_apx (tdesc.get (), regnum); + return tdesc; } diff --git a/gdb/arch/x86-linux-tdesc-features.c b/gdb/arch/x86-linux-tdesc-features.c index 5d6ea7cc701..0191f326834 100644 --- a/gdb/arch/x86-linux-tdesc-features.c +++ b/gdb/arch/x86-linux-tdesc-features.c @@ -65,6 +65,7 @@ struct x86_xstate_feature { static constexpr x86_xstate_feature x86_linux_all_xstate_features[] = { /* Feature, i386, amd64, x32. */ + { X86_XSTATE_APX_F, false, true, true }, { X86_XSTATE_CET_U, false, true, true }, { X86_XSTATE_PKRU, true, true, true }, { X86_XSTATE_AVX512, true, true, true }, diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 636fd0d6b1f..da887665e19 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -50709,6 +50709,10 @@ amd64, 32 bits on amd64 with 32-bit pointer size (X32) and 32 bits on i386. Following the restriction of the Linux kernel, only @value{GDBN} for amd64 targets makes use of this feature for now. +The @samp{org.gnu.gdb.i386.apx} feature is optional. It should describe +16 Extended General Purpose registers (EGPRs) @samp{r16} - @samp{r31} with +64 bits each. All APX registers are valid only on amd64. + @node LoongArch Features @subsection LoongArch Features @cindex target descriptions, LoongArch Features diff --git a/gdb/features/Makefile b/gdb/features/Makefile index 161a7453d66..df716ab6c5e 100644 --- a/gdb/features/Makefile +++ b/gdb/features/Makefile @@ -231,6 +231,7 @@ FEATURE_XMLFILES = aarch64-core.xml \ i386/32bit-avx512.xml \ i386/32bit-segments.xml \ i386/32bit-ssp.xml \ + i386/64bit-apx.xml \ i386/64bit-avx512.xml \ i386/64bit-core.xml \ i386/64bit-segments.xml \ diff --git a/gdb/features/i386/64bit-apx.c b/gdb/features/i386/64bit-apx.c new file mode 100644 index 00000000000..34cd47131d1 --- /dev/null +++ b/gdb/features/i386/64bit-apx.c @@ -0,0 +1,29 @@ +/* THIS FILE IS GENERATED. -*- buffer-read-only: t -*- vi:set ro: + Original: 64bit-apx.xml */ + +#include "gdbsupport/tdesc.h" + +static int +create_feature_i386_64bit_apx (struct target_desc *result, long regnum) +{ + struct tdesc_feature *feature; + + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.apx"); + tdesc_create_reg (feature, "r16", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r17", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r18", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r19", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r20", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r21", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r22", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r23", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r24", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r25", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r26", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r27", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r28", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r29", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r30", regnum++, 1, NULL, 64, "int64"); + tdesc_create_reg (feature, "r31", regnum++, 1, NULL, 64, "int64"); + return regnum; +} diff --git a/gdb/features/i386/64bit-apx.xml b/gdb/features/i386/64bit-apx.xml new file mode 100644 index 00000000000..11a4ec67cae --- /dev/null +++ b/gdb/features/i386/64bit-apx.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index fa935b5fcdb..f36ce36793c 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -412,9 +412,9 @@ i386_pseudo_register_name (struct gdbarch *gdbarch, int regnum) else if (i386_zmm_regnum_p (gdbarch, regnum)) return i386_zmm_names[regnum - tdep->zmm0_regnum]; else if (i386_byte_regnum_p (gdbarch, regnum)) - return i386_byte_names[regnum - tdep->al_regnum]; + return tdep->byte_names[regnum - tdep->al_regnum]; else if (i386_word_regnum_p (gdbarch, regnum)) - return i386_word_names[regnum - tdep->ax_regnum]; + return tdep->word_names[regnum - tdep->ax_regnum]; internal_error (_("invalid regnum")); } @@ -8479,7 +8479,8 @@ i386_xcr0_from_tdesc (const struct target_desc *tdesc) const struct tdesc_feature *feature_core; const struct tdesc_feature *feature_sse, *feature_avx, - *feature_avx512, *feature_pkeys; + *feature_avx512, *feature_pkeys, + *feature_apx; /* Get core registers. */ feature_core = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.core"); @@ -8495,6 +8496,9 @@ i386_xcr0_from_tdesc (const struct target_desc *tdesc) /* Try AVX512 registers. */ feature_avx512 = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx512"); + /* Try APX registers. */ + feature_apx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.apx"); + /* Try PKEYS */ feature_pkeys = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.pkeys"); @@ -8522,6 +8526,9 @@ i386_xcr0_from_tdesc (const struct target_desc *tdesc) xcr0 |= X86_XSTATE_AVX512; } + if (feature_apx) + xcr0 |= X86_XSTATE_APX_F; + if (feature_pkeys) xcr0 |= X86_XSTATE_PKRU; @@ -8537,7 +8544,7 @@ i386_validate_tdesc_p (i386_gdbarch_tdep *tdep, const struct tdesc_feature *feature_sse, *feature_avx, *feature_avx512, *feature_pkeys, *feature_segments, - *feature_pl3_ssp; + *feature_pl3_ssp, *feature_apx; int i, num_regs, valid_p; if (! tdesc_has_registers (tdesc)) @@ -8557,6 +8564,9 @@ i386_validate_tdesc_p (i386_gdbarch_tdep *tdep, /* Try AVX512 registers. */ feature_avx512 = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.avx512"); + /* Try APX registers. */ + feature_apx = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.apx"); + /* Try segment base registers. */ feature_segments = tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments"); @@ -8641,6 +8651,18 @@ i386_validate_tdesc_p (i386_gdbarch_tdep *tdep, tdep->num_xmm_regs = 0; } + if (feature_apx + && tdep->r16_regnum != -1 + && tdep->apx_register_names != nullptr + && tdep->num_apx_regs > 0) + { + tdep->xcr0 |= X86_XSTATE_APX_F; + for (i = 0; i < tdep->num_apx_regs; i++) + valid_p &= tdesc_numbered_register (feature_apx, tdesc_data, + tdep->r16_regnum + i, + tdep->apx_register_names[i]); + } + num_regs = tdep->num_core_regs; for (i = 0; i < num_regs; i++) valid_p &= tdesc_numbered_register (feature_core, tdesc_data, i, @@ -8908,6 +8930,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->num_core_regs = I386_NUM_GREGS + I387_NUM_REGS; tdep->register_names = i386_register_names; + tdep->byte_names = i386_byte_names; + tdep->word_names = i386_word_names; tdep->num_byte_regs = 8; tdep->num_word_regs = 8; diff --git a/gdb/i386-tdep.h b/gdb/i386-tdep.h index d64d5241754..bdafd523834 100644 --- a/gdb/i386-tdep.h +++ b/gdb/i386-tdep.h @@ -108,6 +108,9 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base value >= 0. */ int al_regnum = -1; + /* Number of pseudo lower byte registers. Only used for AMD64. */ + int num_lower_byte_regs = 0; + /* Number of pseudo word registers. */ int num_word_regs = 0; @@ -121,9 +124,16 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base registers are supported. */ int eax_regnum = -1; + /* Register number for %eip. Set this to a value >= 0 in case of %eip + support. Only used for AMD64. */ + int eip_regnum = -1; + /* Number of core registers. */ int num_core_regs = 0; + /* Number of registers added in APX. Only used for AMD64. */ + int num_apx_regs = 0; + /* Number of SSE registers. */ int num_xmm_regs = 0; @@ -159,6 +169,15 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base supported. */ int ymm0h_regnum = -1; + /* Byte register names. */ + const char * const *byte_names = nullptr; + + /* Word register names. */ + const char * const *word_names = nullptr; + + /* Dword register names. Only used for AMD64. */ + const char * const *dword_names = nullptr; + /* Upper YMM register names. Only used for tdesc_numbered_register. */ const char * const *ymmh_register_names = nullptr; @@ -173,6 +192,13 @@ struct i386_gdbarch_tdep : gdbarch_tdep_base registers are supported. */ int zmm0h_regnum = -1; + /* Register number for %r16. Set this to a value >= 0 if r16-r31 + registers are supported. Only used for AMD64. */ + int r16_regnum = -1; + + /* r16-r31 register names. Only used for tdesc_numbered_register. */ + const char * const *apx_register_names = nullptr; + /* OpMask register names. */ const char * const *k_register_names = nullptr; diff --git a/gdb/i387-tdep.c b/gdb/i387-tdep.c index f33f5ad046e..2b58375eefb 100644 --- a/gdb/i387-tdep.c +++ b/gdb/i387-tdep.c @@ -818,6 +818,34 @@ static int xsave_xmm_avx512_offset[] = (xsave + (tdep)->xsave_layout.zmm_offset \ + xsave_xmm_avx512_offset[regnum - I387_XMM16_REGNUM (tdep)]) +/* At xsave_apx_egpr_offset[REGNUM] you'll find the relative offset + within the APX region of the XSAVE extended state where the GDB + registers r16 - r31 is stored. */ + +static int xsave_apx_egpr_offset[] = +{ + 0 * 8, /* r16...r31 registers. */ + 1 * 8, + 2 * 8, + 3 * 8, + 4 * 8, + 5 * 8, + 6 * 8, + 7 * 8, + 8 * 8, + 9 * 8, + 10 * 8, + 11 * 8, + 12 * 8, + 13 * 8, + 14 * 8, + 15 * 8 +}; + +#define XSAVE_APX_EGPR_ADDR(tdep, xsave, regnum) \ + (xsave + (tdep)->xsave_layout.apx_offset \ + + xsave_apx_egpr_offset[regnum - I387_R16_REGNUM (tdep)]) + /* At xsave_avx512_k_offset[REGNUM] you'll find the relative offset within the K region of the XSAVE extended state where the AVX512 opmask register K0 + REGNUM is stored. */ @@ -920,6 +948,7 @@ i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size, { /* Intel CPUs supporting PKRU. */ layout.avx_offset = 576; + layout.apx_offset = 960; layout.k_offset = 1088; layout.zmm_h_offset = 1152; layout.zmm_offset = 1664; @@ -938,6 +967,7 @@ i387_guess_xsave_layout (uint64_t xcr0, size_t xsave_size, { /* Intel CPUs supporting AVX512. */ layout.avx_offset = 576; + layout.apx_offset = 960; layout.k_offset = 1088; layout.zmm_h_offset = 1152; layout.zmm_offset = 1664; @@ -968,6 +998,7 @@ i387_fallback_xsave_layout (uint64_t xcr0) { /* Intel CPUs supporting PKRU. */ layout.avx_offset = 576; + layout.apx_offset = 960; layout.k_offset = 1088; layout.zmm_h_offset = 1152; layout.zmm_offset = 1664; @@ -978,6 +1009,7 @@ i387_fallback_xsave_layout (uint64_t xcr0) { /* Intel CPUs supporting AVX512. */ layout.avx_offset = 576; + layout.apx_offset = 960; layout.k_offset = 1088; layout.zmm_h_offset = 1152; layout.zmm_offset = 1664; @@ -1043,8 +1075,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, avx512_ymmh_avx512 = 0x40, avx512_xmm_avx512 = 0x80, pkeys = 0x100, + apx = 0x200, all = x87 | sse | avxh | avx512_k | avx512_zmm0_h | avx512_zmm16_h - | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys + | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys | apx } regclass; gdb_assert (regs != NULL); @@ -1053,6 +1086,9 @@ i387_supply_xsave (struct regcache *regcache, int regnum, if (regnum == -1) regclass = all; + else if (regnum >= I387_R16_REGNUM (tdep) + && regnum < I387_APX_END_REGNUM (tdep)) + regclass = apx; else if (regnum >= I387_PKRU_REGNUM (tdep) && regnum < I387_PKEYSEND_REGNUM (tdep)) regclass = pkeys; @@ -1099,6 +1135,13 @@ i387_supply_xsave (struct regcache *regcache, int regnum, case none: break; + case apx: + if ((clear_bv & X86_XSTATE_APX_F)) + regcache->raw_supply_zeroed (regnum); + else + regcache->raw_supply (regnum, XSAVE_APX_EGPR_ADDR (tdep, regs, regnum)); + return; + case pkeys: if ((clear_bv & X86_XSTATE_PKRU)) regcache->raw_supply_zeroed (regnum); @@ -1274,6 +1317,25 @@ i387_supply_xsave (struct regcache *regcache, int regnum, } } + /* Handle the APX register. */ + if ((tdep->xcr0 & X86_XSTATE_APX_F) != 0) + { + if ((clear_bv & X86_XSTATE_APX_F) != 0) + { + for (i = I387_R16_REGNUM (tdep); + i < I387_APX_END_REGNUM (tdep); + i++) + regcache->raw_supply_zeroed (i); + } + else + { + for (i = I387_R16_REGNUM (tdep); + i < I387_APX_END_REGNUM (tdep); + i++) + regcache->raw_supply (i, XSAVE_APX_EGPR_ADDR (tdep, regs, i)); + } + } + /* Handle the XMM registers. */ if ((tdep->xcr0 & X86_XSTATE_SSE)) { @@ -1432,8 +1494,9 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, avx512_ymmh_avx512 = 0x80, avx512_xmm_avx512 = 0x100, pkeys = 0x200, + apx = 0x400, all = x87 | sse | avxh | avx512_k | avx512_zmm0_h | avx512_zmm16_h - | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys + | avx512_ymmh_avx512 | avx512_xmm_avx512 | pkeys | apx } regclass; gdb_assert (tdep->st0_regnum >= I386_ST0_REGNUM); @@ -1441,6 +1504,9 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, if (regnum == -1) regclass = all; + else if (regnum >= I387_R16_REGNUM (tdep) + && regnum < I387_APX_END_REGNUM (tdep)) + regclass = apx; else if (regnum >= I387_PKRU_REGNUM (tdep) && regnum < I387_PKEYSEND_REGNUM (tdep)) regclass = pkeys; @@ -1505,6 +1571,14 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, seem justified at this point. */ if (clear_bv) { + if ((clear_bv & X86_XSTATE_APX_F)) + { + for (i = I387_R16_REGNUM (tdep); + i < I387_APX_END_REGNUM (tdep); + i++) + memset (XSAVE_APX_EGPR_ADDR (tdep, regs, i), 0, 8); + } + if ((clear_bv & X86_XSTATE_PKRU)) for (i = I387_PKRU_REGNUM (tdep); i < I387_PKEYSEND_REGNUM (tdep); i++) @@ -1571,6 +1645,23 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, if (regclass == all) { + /* Check if any APX registers are changed. */ + if ((tdep->xcr0 & X86_XSTATE_APX_F)) + { + for (i = I387_R16_REGNUM (tdep); + i < I387_APX_END_REGNUM (tdep); + i++) + { + regcache->raw_collect (i, raw); + p = XSAVE_APX_EGPR_ADDR (tdep, regs, i); + if (memcmp (raw, p, 8) != 0) + { + xstate_bv |= X86_XSTATE_APX_F; + memcpy (p, raw, 8); + } + } + } + /* Check if any PKEYS registers are changed. */ if ((tdep->xcr0 & X86_XSTATE_PKRU)) for (i = I387_PKRU_REGNUM (tdep); @@ -1723,6 +1814,16 @@ i387_collect_xsave (const struct regcache *regcache, int regnum, default: internal_error (_("invalid i387 regclass")); + case apx: + regcache->raw_collect (regnum, raw); + p = XSAVE_APX_EGPR_ADDR (tdep, regs, regnum); + if (memcmp (raw, p, 8)) + { + xstate_bv |= X86_XSTATE_APX_F; + memcpy (p, raw, 8); + } + break; + case pkeys: /* This is a PKEYS register. */ p = XSAVE_PKEYS_ADDR (tdep, regs, regnum); diff --git a/gdb/i387-tdep.h b/gdb/i387-tdep.h index 5d063502bce..f029c1e5119 100644 --- a/gdb/i387-tdep.h +++ b/gdb/i387-tdep.h @@ -37,6 +37,9 @@ struct x86_xsave_layout; #define I387_NUM_YMM_REGS(tdep) ((tdep)->num_ymm_regs) #define I387_YMM0H_REGNUM(tdep) ((tdep)->ymm0h_regnum) +#define I387_R16_REGNUM(tdep) ((tdep)->r16_regnum) +#define I387_NUM_APX_REGS(tdep) ((tdep)->num_apx_regs) + /* Set of constants used for 32 and 64-bit. */ #define I387_NUM_K_REGS 8 #define I387_NUM_PKEYS_REGS 1 @@ -75,6 +78,9 @@ struct x86_xsave_layout; #define I387_XMM_AVX512_END_REGNUM(tdep) \ (I387_XMM16_REGNUM (tdep) + I387_NUM_XMM_AVX512_REGS (tdep)) +#define I387_APX_END_REGNUM(tdep) \ + (I387_R16_REGNUM (tdep) + I387_NUM_APX_REGS (tdep)) + #define I387_PKEYSEND_REGNUM(tdep) \ (I387_PKRU_REGNUM (tdep) + I387_NUM_PKEYS_REGS) diff --git a/gdb/nat/x86-xstate.c b/gdb/nat/x86-xstate.c index c45570179a6..f0f0b00e859 100644 --- a/gdb/nat/x86-xstate.c +++ b/gdb/nat/x86-xstate.c @@ -56,6 +56,7 @@ x86_fetch_xsave_layout (uint64_t xcr0, int len) x86_xsave_layout layout; layout.sizeof_xsave = len; layout.avx_offset = xsave_feature_offset (xcr0, X86_XSTATE_AVX_ID); + layout.apx_offset = xsave_feature_offset (xcr0, X86_XSTATE_APX_F_ID); layout.k_offset = xsave_feature_offset (xcr0, X86_XSTATE_K_ID); layout.zmm_h_offset = xsave_feature_offset (xcr0, X86_XSTATE_ZMM_H_ID); layout.zmm_offset = xsave_feature_offset (xcr0, X86_XSTATE_ZMM_ID); diff --git a/gdb/target-debug.h b/gdb/target-debug.h index c86affbc838..949847b181c 100644 --- a/gdb/target-debug.h +++ b/gdb/target-debug.h @@ -380,6 +380,7 @@ target_debug_print_x86_xsave_layout (const x86_xsave_layout &layout) POFFS(zmm_h); POFFS(zmm); POFFS(pkru); + POFFS(apx); #undef POFFS diff --git a/gdb/testsuite/gdb.arch/amd64-apx-corefile.exp b/gdb/testsuite/gdb.arch/amd64-apx-corefile.exp new file mode 100644 index 00000000000..6b357a06395 --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-apx-corefile.exp @@ -0,0 +1,87 @@ +# Copyright 2024 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@gnu.org + +# Test apx corefiles. + +require allow_apx_tests + +standard_testfile amd64-apx.c + +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \ + {debug additional_flags=-mapxf}] } { + return -1 +} + +set nr_regs 16 +set egpr(1) r16 +set egpr(2) r17 +set egpr(3) r18 +set egpr(4) r19 +set egpr(5) r20 +set egpr(6) r21 +set egpr(7) r22 +set egpr(8) r23 +set egpr(9) r24 +set egpr(10) r25 +set egpr(11) r26 +set egpr(12) r27 +set egpr(13) r28 +set egpr(14) r29 +set egpr(15) r30 +set egpr(16) r31 + +proc test_apx_corefiles {setting} { + global egpr nr_regs + + clean_restart "$::testfile" + if { ![runto_main] } { + continue + } + + set line [gdb_get_line_number "break here"] + gdb_breakpoint $line + gdb_continue_to_breakpoint "break here" ".*$::srcfile:$line.*" + + gdb_test_no_output "maint set gcore xml-target-description ${setting}" + + set gcorefile "${::binfile}_${setting}.gcore" + if { ![gdb_gcore_cmd $gcorefile "save a corefile"] } { + return -1 + } + + # Now restart gdb and load the corefile. + clean_restart "$::testfile" + + gdb_test "core ${gcorefile}" \ + "Core was generated by .*" "re-load generated corefile" + + with_test_prefix "test egpr after corefile load" { + for { set r 1 } { $r <= $nr_regs } { incr r } { + set hexr [format %x [expr $r-1]] + gdb_test "print/z \$$egpr($r)" \ + "= 0x00000000${hexr}4${hexr}3${hexr}2${hexr}1" + } + } +} + +test_apx_corefiles "on" + +# Test the code path without the NT_GDB_TDESC note +with_test_prefix "no NT_GDB_TDESC" { + test_apx_corefiles "off" +} diff --git a/gdb/testsuite/gdb.arch/amd64-apx.c b/gdb/testsuite/gdb.arch/amd64-apx.c new file mode 100644 index 00000000000..35ce63ab482 --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-apx.c @@ -0,0 +1,83 @@ +/* Copyright 2024 Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + Test program for APX Extended GPRs (EGPRs). */ + +long data[] = { + 0x0000000004030201, + 0x0000000014131211, + 0x0000000024232221, + 0x0000000034333231, + 0x0000000044434241, + 0x0000000054535251, + 0x0000000064636261, + 0x0000000074737271, + 0x0000000084838281, + 0x0000000094939291, + 0x00000000a4a3a2a1, + 0x00000000b4b3b2b1, + 0x00000000c4c3c2c1, + 0x00000000d4d3d2d1, + 0x00000000e4e3e2e1, + 0x00000000f4f3f2f1, +}; + +int +main (int argc, char **argv) +{ + register long r16 asm ("r16"); + register long r17 asm ("r17"); + register long r18 asm ("r18"); + register long r19 asm ("r19"); + register long r20 asm ("r20"); + register long r21 asm ("r21"); + register long r22 asm ("r22"); + register long r23 asm ("r23"); + register long r24 asm ("r24"); + register long r25 asm ("r25"); + register long r26 asm ("r26"); + register long r27 asm ("r27"); + register long r28 asm ("r28"); + register long r29 asm ("r29"); + register long r30 asm ("r30"); + register long r31 asm ("r31"); + + asm ("mov 0(%0), %%r16\n\t" + "mov 8(%0), %%r17\n\t" + "mov 16(%0), %%r18\n\t" + "mov 24(%0), %%r19\n\t" + "mov 32(%0), %%r20\n\t" + "mov 40(%0), %%r21\n\t" + "mov 48(%0), %%r22\n\t" + "mov 56(%0), %%r23\n\t" + "mov 64(%0), %%r24\n\t" + "mov 72(%0), %%r25\n\t" + "mov 80(%0), %%r26\n\t" + "mov 88(%0), %%r27\n\t" + "mov 96(%0), %%r28\n\t" + "mov 104(%0), %%r29\n\t" + "mov 112(%0), %%r30\n\t" + "mov 120(%0), %%r31\n\t" + : /* no output operands */ + : "r" (data) + : "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23", + "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31"); + + asm ("nop"); /* break here */ + + return 0; +} diff --git a/gdb/testsuite/gdb.arch/amd64-apx.exp b/gdb/testsuite/gdb.arch/amd64-apx.exp new file mode 100644 index 00000000000..ab03e4e7b60 --- /dev/null +++ b/gdb/testsuite/gdb.arch/amd64-apx.exp @@ -0,0 +1,106 @@ +# Copyright 2024 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Please email any bugs, comments, and/or additions to this file to: +# bug-gdb@gnu.org + +# Test apx dword, word, byte and raw registers. + +set nr_regs 16 +set regs(1) r16 +set regs(2) r17 +set regs(3) r18 +set regs(4) r19 +set regs(5) r20 +set regs(6) r21 +set regs(7) r22 +set regs(8) r23 +set regs(9) r24 +set regs(10) r25 +set regs(11) r26 +set regs(12) r27 +set regs(13) r28 +set regs(14) r29 +set regs(15) r30 +set regs(16) r31 + +proc get_reg_val { type r } { + set hexr [format %x [expr $r-1]] + if { $type == "d"} { + return 0x${hexr}4${hexr}3${hexr}2${hexr}1 + } + if { $type == "w" } { + return 0x${hexr}2${hexr}1 + } + if { $type == "l" } { + return 0x${hexr}1 + } + if { $type == "" } { + return 0x00000000${hexr}4${hexr}3${hexr}2${hexr}1 + } +} + +proc check_reg_content { type } { + global nr_regs + global regs + + for { set r 1 } { $r <= $nr_regs } { incr r } { + set regval [get_reg_val $type $r] + gdb_test "print/z \$$regs($r)$type" "= $regval" + } +} + +require allow_apx_tests + +standard_testfile + +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile} \ + {debug additional_flags=-mapxf}] } { + return +} + +if { ![runto_main] } { + return +} + +set line [gdb_get_line_number "break here"] +gdb_breakpoint $line +gdb_continue_to_breakpoint "break here" ".*$srcfile:$line.*" + +# Run test for dword, word, byte pseudo registers, as well as raw registers. +set regtypes [list "d" "w" "l" ""] +set regtype_names [list "dword" "word" "byte" "raw"] + +# Check initial register content written by testprogram. +for { set i 0 } { $i < [llength $regtypes] } { incr i } { + set type [lindex $regtypes $i] + set type_name [lindex $regtype_names $i] + with_test_prefix "$type_name register" { + check_reg_content $type + } +} + +# Check writing registers with GDB. +for { set i 0 } { $i < [llength $regtypes] } { incr i } { + set type [lindex $regtypes $i] + set type_name [lindex $regtype_names $i] + with_test_prefix "$type_name register" { + for { set r 1 } { $r <= $nr_regs } { incr r } { + set val [expr $r + $i] + gdb_test_no_output "set var \$$regs($r)$type = $val" + gdb_test "print \$$regs($r)$type" "= $val" + } + } +} diff --git a/gdb/testsuite/lib/gdb.exp b/gdb/testsuite/lib/gdb.exp index c87876664f0..74b6b7ec6d0 100644 --- a/gdb/testsuite/lib/gdb.exp +++ b/gdb/testsuite/lib/gdb.exp @@ -4730,6 +4730,65 @@ gdb_caching_proc allow_lam_tests {} { return $allow_lam_tests } +# Run a test on the target to see if it supports APX. Return 1 if so, +# 0 if it does not. + +gdb_caching_proc allow_apx_tests {} { + global srcdir subdir gdb_prompt inferior_exited_re + + set me "allow_apx_tests" + if { ![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"] } { + verbose "$me: target does not support apx, returning 0" 2 + return 0 + } + + # Compile a test program. + set src { + int data[] = {12345}; + + int + main (int argc, char **argv) + { + asm ("mov 0(%0), %%r30\n\t" + : /* no output operands */ + : "r" (data)); + return 0; + } + } + set compile_flags "{additional_flags=-mapxf}" + if { ![gdb_simple_compile $me $src executable $compile_flags] } { + return 0 + } + + # No error message, compilation succeeded so now run it via gdb. + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + gdb_load "$obj" + gdb_run_cmd + gdb_expect { + -re ".*Illegal instruction.*${gdb_prompt} $" { + verbose -log "$me: apx hardware not detected." + set allow_apx_tests 0 + } + -re ".*$inferior_exited_re normally.*${gdb_prompt} $" { + verbose -log "$me: apx hardware detected." + set allow_apx_tests 1 + } + default { + warning "\n$me: default case taken." + set allow_apx_tests 0 + } + } + gdb_exit + remote_file build delete $obj + + verbose "$me: returning $allow_apx_tests" 2 + return $allow_apx_tests +} + + # Run a test on the target to see if it supports btrace hardware. Return 1 if so, # 0 if it does not. Based on 'check_vmx_hw_available' from the GCC testsuite. diff --git a/gdbserver/i387-fp.cc b/gdbserver/i387-fp.cc index 164b666979f..346f30c637b 100644 --- a/gdbserver/i387-fp.cc +++ b/gdbserver/i387-fp.cc @@ -23,6 +23,7 @@ /* Default to SSE. */ static uint64_t x86_xstate_bv = X86_XSTATE_SSE_MASK; +static const int num_apx_registers = 16; static const int num_avx512_k_registers = 8; static const int num_pkeys_registers = 1; @@ -116,6 +117,10 @@ public: unsigned char *ymmh_space () { return xsave () + xsave_layout.avx_offset; } + /* Memory address of 16 EGPR register values of 64 bits. */ + unsigned char *apx_space () + { return xsave () + xsave_layout.apx_offset; } + /* Memory address of 8 OpMask register values of 64 bits. */ unsigned char *k_space () { return xsave () + xsave_layout.k_offset; } @@ -312,6 +317,10 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) if ((clear_bv & X86_XSTATE_PKRU)) for (i = 0; i < num_pkeys_registers; i++) memset (fp->pkru_space () + i * 4, 0, 4); + + if (amd64 && (clear_bv & X86_XSTATE_APX_F) != 0) + for (i = 0; i < num_apx_registers; i++) + memset (fp->apx_space () + i * 8, 0, 8); } /* Check if any x87 registers are changed. */ @@ -465,6 +474,23 @@ i387_cache_to_xsave (struct regcache *regcache, void *buf) } } + /* Check if any APX registers are changed. */ + if (amd64 && (x86_xstate_bv & X86_XSTATE_APX_F)!= 0) + { + int r16_regnum = find_regno (regcache->tdesc, "r16"); + + for (i = 0; i < num_apx_registers; i++) + { + collect_register (regcache, i + r16_regnum, raw); + p = fp->apx_space () + i * 8; + if (memcmp (raw, p, 8) != 0) + { + xstate_bv |= X86_XSTATE_APX_F; + memcpy (p, raw, 8); + } + } + } + if (x86_xstate_bv & X86_XSTATE_X87) { collect_register_by_name (regcache, "fioff", raw); @@ -790,6 +816,23 @@ i387_xsave_to_cache (struct regcache *regcache, const void *buf) } } + if (amd64 && (x86_xstate_bv & X86_XSTATE_APX_F) != 0) + { + int r16_regnum = find_regno (regcache->tdesc, "r16"); + + if ((clear_bv & X86_XSTATE_APX_F) != 0) + { + for (i = 0; i < num_apx_registers; i++) + supply_register_zeroed (regcache, i + r16_regnum); + } + else + { + p = fp->apx_space (); + for (i = 0; i < num_apx_registers; i++) + supply_register (regcache, i + r16_regnum, p + i * 8); + } + } + if ((clear_bv & (X86_XSTATE_SSE | X86_XSTATE_AVX)) == (X86_XSTATE_SSE | X86_XSTATE_AVX)) { diff --git a/gdbserver/linux-x86-low.cc b/gdbserver/linux-x86-low.cc index 28a3d78f747..3c9c2e7c452 100644 --- a/gdbserver/linux-x86-low.cc +++ b/gdbserver/linux-x86-low.cc @@ -260,7 +260,9 @@ static const int x86_64_regmap[] = -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* pkru */ - -1 /* CET user mode register PL3_SSP. */ + -1, /* CET user mode register PL3_SSP. */ + -1, -1, -1, -1, -1, -1, -1, -1, /* r16...r31 (APX). */ + -1, -1, -1, -1, -1, -1, -1, -1, }; #define X86_64_NUM_REGS (sizeof (x86_64_regmap) / sizeof (x86_64_regmap[0])) diff --git a/gdbsupport/x86-xstate.h b/gdbsupport/x86-xstate.h index ee8660f8cb4..3602fa40cd9 100644 --- a/gdbsupport/x86-xstate.h +++ b/gdbsupport/x86-xstate.h @@ -29,11 +29,13 @@ #define X86_XSTATE_ZMM_ID 7 #define X86_XSTATE_PKRU_ID 9 #define X86_XSTATE_CET_U_ID 11 +#define X86_XSTATE_APX_F_ID 19 /* The extended state feature bits. */ #define X86_XSTATE_X87 (1ULL << X86_XSTATE_X87_ID) #define X86_XSTATE_SSE (1ULL << X86_XSTATE_SSE_ID) #define X86_XSTATE_AVX (1ULL << X86_XSTATE_AVX_ID) +#define X86_XSTATE_APX_F (1ULL << X86_XSTATE_APX_F_ID) /* AVX 512 adds three feature bits. All three must be enabled. */ #define X86_XSTATE_K (1ULL << X86_XSTATE_K_ID) @@ -53,6 +55,7 @@ struct x86_xsave_layout { int sizeof_xsave = 0; int avx_offset = 0; + int apx_offset = 0; int k_offset = 0; int zmm_h_offset = 0; int zmm_offset = 0; @@ -64,6 +67,7 @@ constexpr bool operator== (const x86_xsave_layout &lhs, { return lhs.sizeof_xsave == rhs.sizeof_xsave && lhs.avx_offset == rhs.avx_offset + && lhs.apx_offset == rhs.apx_offset && lhs.k_offset == rhs.k_offset && lhs.zmm_h_offset == rhs.zmm_h_offset && lhs.zmm_offset == rhs.zmm_offset @@ -81,14 +85,19 @@ constexpr bool operator!= (const x86_xsave_layout &lhs, #define X86_XSTATE_X87_MASK X86_XSTATE_X87 #define X86_XSTATE_SSE_MASK (X86_XSTATE_X87 | X86_XSTATE_SSE) #define X86_XSTATE_AVX_MASK (X86_XSTATE_SSE_MASK | X86_XSTATE_AVX) +#define X86_XSTATE_AVX_APX_MASK (X86_XSTATE_AVX_MASK | X86_XSTATE_APX_F) #define X86_XSTATE_AVX_AVX512_MASK (X86_XSTATE_AVX_MASK | X86_XSTATE_AVX512) +#define X86_XSTATE_AVX_AVX512_APX_MASK\ + (X86_XSTATE_AVX_AVX512_MASK | X86_XSTATE_APX_F) #define X86_XSTATE_AVX_AVX512_PKU_MASK (X86_XSTATE_AVX_MASK\ | X86_XSTATE_AVX512 | X86_XSTATE_PKRU) +#define X86_XSTATE_AVX_AVX512_PKU_APX_MASK\ + (X86_XSTATE_AVX_AVX512_PKU_MASK | X86_XSTATE_APX_F) /* Supported mask of state-component bitmap xstate_bv. The SDM defines xstate_bv as XCR0 | IA32_XSS. */ -#define X86_XSTATE_ALL_MASK (X86_XSTATE_AVX_AVX512_PKU_MASK\ +#define X86_XSTATE_ALL_MASK (X86_XSTATE_AVX_AVX512_PKU_APX_MASK\ | X86_XSTATE_CET_U) #define X86_XSTATE_SSE_SIZE 576 @@ -97,6 +106,7 @@ constexpr bool operator!= (const x86_xsave_layout &lhs, #define HAS_AVX(XCR0) (((XCR0) & X86_XSTATE_AVX) != 0) #define HAS_AVX512(XCR0) (((XCR0) & X86_XSTATE_AVX512) != 0) +#define HAS_APX(XCR0) (((XCR0) & X86_XSTATE_APX_F) != 0) #define HAS_PKRU(XCR0) (((XCR0) & X86_XSTATE_PKRU) != 0) /* Initial value for fctrl register, as defined in the X86 manual, and