From patchwork Mon Jul 10 13:55:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Yao Qi X-Patchwork-Id: 21516 Received: (qmail 53338 invoked by alias); 10 Jul 2017 13:56:49 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 40859 invoked by uid 89); 10 Jul 2017 13:56:23 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.4 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy=3352 X-HELO: mail-it0-f67.google.com Received: from mail-it0-f67.google.com (HELO mail-it0-f67.google.com) (209.85.214.67) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 10 Jul 2017 13:56:14 +0000 Received: by mail-it0-f67.google.com with SMTP id k3so13337755ita.3 for ; Mon, 10 Jul 2017 06:56:13 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=DTkm+5+E7vtZNKmSSN0wikeeTi2lrPimjWKwFtKX0vc=; b=Zo9N8TJqPV2iiEmQzIQok+qLKtDAhHs1UhgXdcgQX1SYKZSq9bmJslIxg+cadfvdeO NpOgO8Uj9Ze4ymjUY/ves9PtZTNEa6+PpzsY7NOPbyQ0u+T5l5LuGef1TD8VcHgelPAC I2bcHd/VkM01WFK89pqlutqhLm4Q3XdyzV+yLbpmVrLQH//xyTStCTEHAT3tB35goLe+ w1ZKYjVk3WLxQ98c1S9h7xim/3augq6sM2EbAat3guNkZTe19VeNqdrNhdwDn07qziFR q6mgVxalQr6mUvbJmCLJeDP1ydnlJDJXvSkgWvlwvnXZHsVJ9E1xKnseYYmujUKBd/SX iJDw== X-Gm-Message-State: AIVw111Snzj8QZ5x+z82ibSAZJOVh6KiYVwLb0LieAgB4vDAXpSSqSop X3cQSUmRsKYEZn6n X-Received: by 10.36.104.83 with SMTP id v80mr11872662itb.97.1499694971406; Mon, 10 Jul 2017 06:56:11 -0700 (PDT) Received: from E107787-LIN.cambridge.arm.com (static.42.136.251.148.clients.your-server.de. [148.251.136.42]) by smtp.gmail.com with ESMTPSA id v96sm5973996ioi.50.2017.07.10.06.56.10 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Mon, 10 Jul 2017 06:56:10 -0700 (PDT) From: Yao Qi X-Google-Original-From: Yao Qi To: gdb-patches@sourceware.org Subject: [PATCH 23/26] Convert amd64-linux target descriptions Date: Mon, 10 Jul 2017 14:55:37 +0100 Message-Id: <1499694940-23564-24-git-send-email-yao.qi@linaro.org> In-Reply-To: <1499694940-23564-1-git-send-email-yao.qi@linaro.org> References: <1499694940-23564-1-git-send-email-yao.qi@linaro.org> X-IsSubscribed: yes This patch changes amd64-linux target descriptions so that they can be dynamically generated in both GDB and GDBserver. gdb/gdbserver: 2017-06-09 Yao Qi * Makefile.in (arch-amd64.o): New rule. * configure.srv: Append arch-amd64.o. * linux-amd64-ipa.c: Include common/x86-xstate.h. (get_ipa_tdesc): Call amd64_linux_read_description. (initialize_low_tracepoint): Don't call init_registers_x32_XXX and init_registers_amd64_XXX. * linux-x86-low.c (x86_linux_read_description): Call amd64_linux_read_description. (x86_get_ipa_tdesc_idx): Call amd64_get_ipa_tdesc_idx. (initialize_low_arch): Don't call init_registers_x32_XXX and init_registers_amd64_XXX. * linux-x86-tdesc-selftest.c: Declare init_registers_amd64_XXX and tdesc_amd64_XXX. [__x86_64__] (amd64_tdesc_test): New function. (initialize_low_tdesc) [__x86_64__]: Call init_registers_x32_XXX and init_registers_amd64_XXX. * linux-x86-tdesc.c: Include arch/amd64.h. (xcr0_to_tdesc_idx): New function. (i386_linux_read_description): New function. (amd64_get_ipa_tdesc_idx): New function. * linux-x86-tdesc.h (amd64_get_ipa_tdesc_idx): Declare. (amd64_get_ipa_tdesc): Declare. gdb: 2017-07-03 Yao Qi * amd64-linux-tdep.c: Include arch/amd64.h. Don't include features/i386/*.c. (amd64_linux_read_description): Call amd64_create_target_description. * arch/amd64.c: New file. * arch/amd64.h: New file. * configure.tgt (x86_64-*-linux*): Append amd64.o. * Makefile.in (ALL_64_TARGET_OBS): Append amd64.o. --- gdb/Makefile.in | 1 + gdb/amd64-linux-tdep.c | 44 +---------- gdb/arch/amd64.c | 71 ++++++++++++++++++ gdb/arch/amd64.h | 21 ++++++ gdb/configure.tgt | 2 +- gdb/gdbserver/Makefile.in | 4 + gdb/gdbserver/configure.srv | 3 +- gdb/gdbserver/linux-amd64-ipa.c | 55 ++++++-------- gdb/gdbserver/linux-x86-low.c | 86 +++------------------- gdb/gdbserver/linux-x86-tdesc-selftest.c | 90 +++++++++++++++++++++++ gdb/gdbserver/linux-x86-tdesc.c | 122 ++++++++++++++++++++++++++----- gdb/gdbserver/linux-x86-tdesc.h | 49 ++----------- 12 files changed, 339 insertions(+), 209 deletions(-) create mode 100644 gdb/arch/amd64.c create mode 100644 gdb/arch/amd64.h diff --git a/gdb/Makefile.in b/gdb/Makefile.in index c9af3f6..0bb383a 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -761,6 +761,7 @@ ALL_64_TARGET_OBS = \ alpha-nbsd-tdep.o \ alpha-obsd-tdep.o \ alpha-tdep.o \ + amd64.o \ amd64-darwin-tdep.o \ amd64-dicos-tdep.o \ amd64-fbsd-tdep.o \ diff --git a/gdb/amd64-linux-tdep.c b/gdb/amd64-linux-tdep.c index 903c88b..2ce6ca7 100644 --- a/gdb/amd64-linux-tdep.c +++ b/gdb/amd64-linux-tdep.c @@ -39,19 +39,9 @@ #include "solib-svr4.h" #include "xml-syscall.h" #include "glibc-tdep.h" +#include "arch/amd64.h" #include "target-descriptions.h" -#include "features/i386/64bit-avx.c" -#include "features/i386/64bit-avx512.c" -#include "features/i386/64bit-core.c" -#include "features/i386/64bit-linux.c" -#include "features/i386/64bit-mpx.c" -#include "features/i386/64bit-pkeys.c" -#include "features/i386/64bit-segments.c" -#include "features/i386/64bit-sse.c" - -#include "features/i386/x32-core.c" - /* The syscall's XML filename for i386. */ #define XML_SYSCALL_FILENAME_AMD64 "syscalls/amd64-linux.xml" @@ -1599,37 +1589,7 @@ amd64_linux_read_description (uint64_t xcr0_features_bit, bool is_x32) } if (*tdesc == NULL) - { - *tdesc = allocate_target_description (); - - set_tdesc_architecture (*tdesc, - is_x32 ? "i386:x64-32" : "i386:x86-64"); - - set_tdesc_osabi (*tdesc, osabi_from_tdesc_string ("GNU/Linux")); - - long regnum = 0; - - if (is_x32) - regnum = create_feature_i386_x32_core (*tdesc, regnum); - else - regnum = create_feature_i386_64bit_core (*tdesc, regnum); - - regnum = create_feature_i386_64bit_sse (*tdesc, regnum); - regnum = create_feature_i386_64bit_linux (*tdesc, regnum); - regnum = create_feature_i386_64bit_segments (*tdesc, regnum); - - if (xcr0_features_bit & X86_XSTATE_AVX) - regnum = create_feature_i386_64bit_avx (*tdesc, regnum); - - if ((xcr0_features_bit & X86_XSTATE_MPX) && !is_x32) - regnum = create_feature_i386_64bit_mpx (*tdesc, regnum); - - if (xcr0_features_bit & X86_XSTATE_AVX512) - regnum = create_feature_i386_64bit_avx512 (*tdesc, regnum); - - if ((xcr0_features_bit & X86_XSTATE_PKRU) && !is_x32) - regnum = create_feature_i386_64bit_pkeys (*tdesc, regnum); - } + *tdesc = amd64_create_target_description (xcr0_features_bit, is_x32); return *tdesc; } diff --git a/gdb/arch/amd64.c b/gdb/arch/amd64.c new file mode 100644 index 0000000..626733d --- /dev/null +++ b/gdb/arch/amd64.c @@ -0,0 +1,71 @@ +/* Copyright (C) 2017 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 . */ + +#include "amd64.h" +#include "x86-xstate.h" +#include + +#include "../features/i386/64bit-avx.c" +#include "../features/i386/64bit-avx512.c" +#include "../features/i386/64bit-core.c" +#include "../features/i386/64bit-linux.c" +#include "../features/i386/64bit-mpx.c" +#include "../features/i386/64bit-pkeys.c" +#include "../features/i386/64bit-segments.c" +#include "../features/i386/64bit-sse.c" + +#include "../features/i386/x32-core.c" + +/* Create amd64 target descriptions according to XCR0. If IS_X32 is + true, create the x32 ones. */ + +target_desc * +amd64_create_target_description (uint64_t xcr0, bool is_x32) +{ + target_desc *tdesc = allocate_target_description (); + +#ifndef IN_PROCESS_AGENT + set_tdesc_architecture (tdesc, is_x32 ? "i386:x64-32" : "i386:x86-64"); + + set_tdesc_osabi (tdesc, "GNU/Linux"); +#endif + + long regnum = 0; + + if (is_x32) + regnum = create_feature_i386_x32_core (tdesc, regnum); + else + regnum = create_feature_i386_64bit_core (tdesc, regnum); + + regnum = create_feature_i386_64bit_sse (tdesc, regnum); + regnum = create_feature_i386_64bit_linux (tdesc, regnum); + regnum = create_feature_i386_64bit_segments (tdesc, regnum); + + if (xcr0 & X86_XSTATE_AVX) + regnum = create_feature_i386_64bit_avx (tdesc, regnum); + + if ((xcr0 & X86_XSTATE_MPX) && !is_x32) + regnum = create_feature_i386_64bit_mpx (tdesc, regnum); + + if (xcr0 & X86_XSTATE_AVX512) + regnum = create_feature_i386_64bit_avx512 (tdesc, regnum); + + if ((xcr0 & X86_XSTATE_PKRU) && !is_x32) + regnum = create_feature_i386_64bit_pkeys (tdesc, regnum); + + return tdesc; +} diff --git a/gdb/arch/amd64.h b/gdb/arch/amd64.h new file mode 100644 index 0000000..0821a7c --- /dev/null +++ b/gdb/arch/amd64.h @@ -0,0 +1,21 @@ +/* Copyright (C) 2017 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 . */ + +#include "tdesc.h" +#include + +target_desc *amd64_create_target_description (uint64_t xcr0, bool is_x32); diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 1f263515..402d6ba 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -678,7 +678,7 @@ x86_64-*-elf*) ;; x86_64-*-linux*) # Target: GNU/Linux x86-64 - gdb_target_obs="amd64-tdep.o amd64-linux-tdep.o i386-tdep.o \ + gdb_target_obs="amd64-tdep.o amd64-linux-tdep.o amd64.o i386-tdep.o \ i387-tdep.o i386.o i386-linux-tdep.o glibc-tdep.o \ solib-svr4.o symfile-mem.o linux-tdep.o linux-record.o" build_gdbserver=yes diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index 5f9b2fe..5cc4220 100644 --- a/gdb/gdbserver/Makefile.in +++ b/gdb/gdbserver/Makefile.in @@ -532,6 +532,10 @@ arch-i386.o: ../arch/i386.c $(COMPILE) $< $(POSTCOMPILE) +arch-amd64.o: ../arch/amd64.c + $(COMPILE) $< + $(POSTCOMPILE) + # Rules for objects that go in the in-process agent. %-ipa.o: %-generated.c diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv index 55985d6..05cc99e 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -364,7 +364,7 @@ case "${target}" in ;; x86_64-*-linux*) srv_regobj="$srv_amd64_linux_regobj $srv_i386_linux_regobj" srv_tgtobj="$srv_linux_obj linux-x86-low.o x86-low.o x86-dregs.o i387-fp.o" - srv_tgtobj="${srv_tgtobj} arch-i386.o" + srv_tgtobj="${srv_tgtobj} arch-i386.o arch-amd64.o" srv_tgtobj="${srv_tgtobj} linux-x86-tdesc.o" srv_tgtobj="${srv_tgtobj} linux-btrace.o x86-linux.o" srv_tgtobj="${srv_tgtobj} x86-linux-dregs.o" @@ -380,6 +380,7 @@ case "${target}" in ipa_obj="${ipa_amd64_linux_regobj}" fi ipa_obj="${ipa_obj} linux-amd64-ipa.o linux-x86-tdesc-ipa.o" + ipa_obj="${ipa_obj} amd64-ipa.o" ;; x86_64-*-mingw*) srv_regobj="$srv_amd64_regobj" srv_tgtobj="x86-low.o x86-dregs.o i387-fp.o win32-low.o win32-i386-low.o" diff --git a/gdb/gdbserver/linux-amd64-ipa.c b/gdb/gdbserver/linux-amd64-ipa.c index 67f36c2..1d56093 100644 --- a/gdb/gdbserver/linux-amd64-ipa.c +++ b/gdb/gdbserver/linux-amd64-ipa.c @@ -22,6 +22,7 @@ #include #include "tracepoint.h" #include "linux-x86-tdesc.h" +#include "common/x86-xstate.h" /* Defined in auto-generated file amd64-linux.c. */ void init_registers_amd64_linux (void); @@ -174,38 +175,38 @@ supply_static_tracepoint_registers (struct regcache *regcache, const struct target_desc * get_ipa_tdesc (int idx) { + if (idx >= X86_TDESC_LAST) + { + internal_error (__FILE__, __LINE__, + "unknown ipa tdesc index: %d", idx); + } + #if defined __ILP32__ switch (idx) { case X86_TDESC_SSE: - return tdesc_x32_linux; + return amd64_linux_read_description (X86_XSTATE_SSE_MASK, true); case X86_TDESC_AVX: return tdesc_x32_avx_linux; + return amd64_linux_read_description (X86_XSTATE_AVX_MASK, true); case X86_TDESC_AVX512: - return tdesc_x32_avx512_linux; + return amd64_linux_read_description (X86_XSTATE_AVX512_MASK, true); default: break; } #else - switch (idx) - { - case X86_TDESC_SSE: - return tdesc_amd64_linux; - case X86_TDESC_AVX: - return tdesc_amd64_avx_linux; - case X86_TDESC_MPX: - return tdesc_amd64_mpx_linux; - case X86_TDESC_AVX_MPX: - return tdesc_amd64_avx_mpx_linux; - case X86_TDESC_AVX_MPX_AVX512_PKU: - return tdesc_amd64_avx_mpx_avx512_pku_linux; - case X86_TDESC_AVX_AVX512: - return tdesc_amd64_avx_avx512_linux; - default: - internal_error (__FILE__, __LINE__, - "unknown ipa tdesc index: %d", idx); - return tdesc_amd64_linux; - } + /* Map the tdesc index to xcr0 mask. */ + uint64_t idx2mask[X86_TDESC_LAST] = { + X86_XSTATE_X87_MASK, + X86_XSTATE_SSE_MASK, + X86_XSTATE_AVX_MASK, + X86_XSTATE_MPX_MASK, + X86_XSTATE_AVX_MPX_MASK, + X86_XSTATE_AVX_AVX512_MASK, + X86_XSTATE_AVX_MPX_AVX512_PKU_MASK, + }; + + return amd64_linux_read_description (idx2mask[idx], false); #endif internal_error (__FILE__, __LINE__, @@ -276,16 +277,4 @@ alloc_jump_pad_buffer (size_t size) void initialize_low_tracepoint (void) { -#if defined __ILP32__ - init_registers_x32_linux (); - init_registers_x32_avx_linux (); - init_registers_x32_avx512_linux (); -#else - init_registers_amd64_linux (); - init_registers_amd64_avx_linux (); - init_registers_amd64_mpx_linux (); - init_registers_amd64_avx_mpx_linux (); - init_registers_amd64_avx_avx512_linux (); - init_registers_amd64_avx_mpx_avx512_pku_linux (); -#endif } diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c index 54be82f..f09871a 100644 --- a/gdb/gdbserver/linux-x86-low.c +++ b/gdb/gdbserver/linux-x86-low.c @@ -817,58 +817,17 @@ x86_linux_read_description (void) if (machine == EM_X86_64) { #ifdef __x86_64__ - if (is_elf64) - { - if (xcr0_features) - { - switch (xcr0 & X86_XSTATE_ALL_MASK) - { - case X86_XSTATE_AVX_MPX_AVX512_PKU_MASK: - return tdesc_amd64_avx_mpx_avx512_pku_linux; - - case X86_XSTATE_AVX_AVX512_MASK: - return tdesc_amd64_avx_avx512_linux; - - case X86_XSTATE_AVX_MPX_MASK: - return tdesc_amd64_avx_mpx_linux; - - case X86_XSTATE_MPX_MASK: - return tdesc_amd64_mpx_linux; - - case X86_XSTATE_AVX_MASK: - return tdesc_amd64_avx_linux; + const target_desc *tdesc = NULL; - default: - return tdesc_amd64_linux; - } - } - else - return tdesc_amd64_linux; - } - else + if (xcr0_features) { - if (xcr0_features) - { - switch (xcr0 & X86_XSTATE_ALL_MASK) - { - case X86_XSTATE_AVX_MPX_AVX512_PKU_MASK: - /* No x32 MPX and PKU, fall back to avx_avx512. */ - return tdesc_x32_avx_avx512_linux; - - case X86_XSTATE_AVX_AVX512_MASK: - return tdesc_x32_avx_avx512_linux; - - case X86_XSTATE_MPX_MASK: /* No MPX on x32. */ - case X86_XSTATE_AVX_MASK: - return tdesc_x32_avx_linux; - - default: - return tdesc_x32_linux; - } - } - else - return tdesc_x32_linux; + tdesc = amd64_linux_read_description (xcr0 & X86_XSTATE_ALL_MASK, + !is_elf64); } + + if (tdesc == NULL) + tdesc = amd64_linux_read_description (X86_XSTATE_SSE_MASK, !is_elf64); + return tdesc; #endif } else @@ -2881,19 +2840,7 @@ x86_get_ipa_tdesc_idx (void) const struct target_desc *tdesc = regcache->tdesc; #ifdef __x86_64__ - if (tdesc == tdesc_amd64_linux || tdesc == tdesc_amd64_linux_no_xml - || tdesc == tdesc_x32_linux) - return X86_TDESC_SSE; - if (tdesc == tdesc_amd64_avx_linux || tdesc == tdesc_x32_avx_linux) - return X86_TDESC_AVX; - if (tdesc == tdesc_amd64_mpx_linux) - return X86_TDESC_MPX; - if (tdesc == tdesc_amd64_avx_mpx_linux) - return X86_TDESC_AVX_MPX; - if (tdesc == tdesc_amd64_avx_mpx_avx512_pku_linux || tdesc == tdesc_x32_avx_avx512_linux) - return X86_TDESC_AVX_MPX_AVX512_PKU; - if (tdesc == tdesc_amd64_avx_avx512_linux) - return X86_TDESC_AVX_AVX512; + return amd64_get_ipa_tdesc_idx (tdesc); #endif if (tdesc == tdesc_i386_linux_no_xml) @@ -2953,19 +2900,10 @@ initialize_low_arch (void) { /* Initialize the Linux target descriptions. */ #ifdef __x86_64__ - init_registers_amd64_linux (); - init_registers_amd64_avx_linux (); - init_registers_amd64_mpx_linux (); - init_registers_amd64_avx_mpx_linux (); - init_registers_amd64_avx_avx512_linux (); - init_registers_amd64_avx_mpx_avx512_pku_linux (); - - init_registers_x32_linux (); - init_registers_x32_avx_linux (); - init_registers_x32_avx_avx512_linux (); - tdesc_amd64_linux_no_xml = XNEW (struct target_desc); - copy_target_description (tdesc_amd64_linux_no_xml, tdesc_amd64_linux); + copy_target_description (tdesc_amd64_linux_no_xml, + amd64_linux_read_description (X86_XSTATE_SSE_MASK, + false)); tdesc_amd64_linux_no_xml->xmltarget = xmltarget_amd64_linux_no_xml; #endif diff --git a/gdb/gdbserver/linux-x86-tdesc-selftest.c b/gdb/gdbserver/linux-x86-tdesc-selftest.c index dfb566b..6859834 100644 --- a/gdb/gdbserver/linux-x86-tdesc-selftest.c +++ b/gdb/gdbserver/linux-x86-tdesc-selftest.c @@ -49,6 +49,46 @@ extern const struct target_desc *tdesc_i386_avx_mpx_avx512_pku_linux; void init_registers_i386_mpx_linux (void); extern const struct target_desc *tdesc_i386_mpx_linux; +#ifdef __x86_64__ + +/* Defined in auto-generated file amd64-linux.c. */ +void init_registers_amd64_linux (void); +extern const struct target_desc *tdesc_amd64_linux; + +/* Defined in auto-generated file amd64-avx-linux.c. */ +void init_registers_amd64_avx_linux (void); +extern const struct target_desc *tdesc_amd64_avx_linux; + +/* Defined in auto-generated file amd64-avx-avx512-linux.c. */ +void init_registers_amd64_avx_avx512_linux (void); +extern const struct target_desc *tdesc_amd64_avx_avx512_linux; + +/* Defined in auto-generated file amd64-avx-mpx-avx512-pku-linux.c. */ +void init_registers_amd64_avx_mpx_avx512_pku_linux (void); +extern const struct target_desc *tdesc_amd64_avx_mpx_avx512_pku_linux; + +/* Defined in auto-generated file amd64-avx-mpx-linux.c. */ +void init_registers_amd64_avx_mpx_linux (void); +extern const struct target_desc *tdesc_amd64_avx_mpx_linux; + +/* Defined in auto-generated file amd64-mpx-linux.c. */ +void init_registers_amd64_mpx_linux (void); +extern const struct target_desc *tdesc_amd64_mpx_linux; + +/* Defined in auto-generated file x32-linux.c. */ +void init_registers_x32_linux (void); +extern const struct target_desc *tdesc_x32_linux; + +/* Defined in auto-generated file x32-avx-linux.c. */ +void init_registers_x32_avx_linux (void); +extern const struct target_desc *tdesc_x32_avx_linux; + +/* Defined in auto-generated file x32-avx-avx512-linux.c. */ +void init_registers_x32_avx_avx512_linux (void); +extern const struct target_desc *tdesc_x32_avx_avx512_linux; + +#endif + namespace selftests { namespace tdesc { static void @@ -75,6 +115,41 @@ i386_tdesc_test () SELF_CHECK (*tdesc == *elem.tdesc); } } + +#ifdef __x86_64__ + +static void +amd64_tdesc_test () +{ + struct + { + unsigned int mask; + const target_desc *tdesc[2]; + } tdesc_tests[] = { + { X86_XSTATE_SSE_MASK, { tdesc_amd64_linux, tdesc_x32_linux } }, + { X86_XSTATE_AVX_MASK, { tdesc_amd64_avx_linux, tdesc_x32_avx_linux } }, + { X86_XSTATE_MPX_MASK, { tdesc_amd64_mpx_linux, tdesc_x32_avx_linux } }, + { X86_XSTATE_AVX_MPX_MASK, { tdesc_amd64_avx_mpx_linux, + tdesc_x32_avx_linux } }, + { X86_XSTATE_AVX_AVX512_MASK, { tdesc_amd64_avx_avx512_linux, + tdesc_x32_avx_avx512_linux } }, + { X86_XSTATE_AVX_MPX_AVX512_PKU_MASK, + { tdesc_amd64_avx_mpx_avx512_pku_linux, tdesc_x32_avx_avx512_linux } }, + }; + + for (auto &elem : tdesc_tests) + { + for (int i = 0; i < 2; i++) + { + const target_desc *tdesc = amd64_linux_read_description (elem.mask, + i); + + SELF_CHECK (*tdesc == *elem.tdesc[i]); + } + } +} + +#endif } } // namespace selftests @@ -90,4 +165,19 @@ initialize_low_tdesc () init_registers_i386_avx_mpx_avx512_pku_linux (); register_self_test (selftests::tdesc::i386_tdesc_test); + +#ifdef __x86_64__ + init_registers_x32_linux (); + init_registers_x32_avx_linux (); + init_registers_x32_avx_avx512_linux (); + + init_registers_amd64_linux (); + init_registers_amd64_avx_linux (); + init_registers_amd64_mpx_linux (); + init_registers_amd64_avx_mpx_linux (); + init_registers_amd64_avx_avx512_linux (); + init_registers_amd64_avx_mpx_avx512_pku_linux (); + + register_self_test (selftests::tdesc::amd64_tdesc_test); +#endif } diff --git a/gdb/gdbserver/linux-x86-tdesc.c b/gdb/gdbserver/linux-x86-tdesc.c index d1e262c..9eb61a7 100644 --- a/gdb/gdbserver/linux-x86-tdesc.c +++ b/gdb/gdbserver/linux-x86-tdesc.c @@ -22,36 +22,68 @@ #include "linux-x86-tdesc.h" #include "arch/i386.h" #include "common/x86-xstate.h" +#ifdef __x86_64__ +#include "arch/amd64.h" +#endif -static struct target_desc *i386_tdescs[X86_TDESC_LAST] = { }; +/* Return the right x86_linux_tdesc index for a given XCR0. Return + X86_TDESC_LAST if can't find a match. */ -#if defined __i386__ || !defined IN_PROCESS_AGENT - -/* Return the target description according to XCR0. */ - -const struct target_desc * -i386_linux_read_description (uint64_t xcr0) +static enum x86_linux_tdesc +xcr0_to_tdesc_idx (uint64_t xcr0, bool is_x32) { - struct target_desc **tdesc = NULL; - if (xcr0 & X86_XSTATE_PKRU) - tdesc = &i386_tdescs[X86_TDESC_AVX_MPX_AVX512_PKU]; + { + if (is_x32) + { + /* No x32 MPX and PKU, fall back to avx_avx512. */ + return X86_TDESC_AVX_AVX512; + } + else + return X86_TDESC_AVX_MPX_AVX512_PKU; + } else if (xcr0 & X86_XSTATE_AVX512) - tdesc = &i386_tdescs[X86_TDESC_AVX_AVX512]; + return X86_TDESC_AVX_AVX512; else if ((xcr0 & X86_XSTATE_AVX_MPX_MASK) == X86_XSTATE_AVX_MPX_MASK) - tdesc = &i386_tdescs[X86_TDESC_AVX_MPX]; + { + if (is_x32) /* No MPX on x32. */ + return X86_TDESC_AVX; + else + return X86_TDESC_AVX_MPX; + } else if (xcr0 & X86_XSTATE_MPX) - tdesc = &i386_tdescs[X86_TDESC_MPX]; + { + if (is_x32) /* No MPX on x32. */ + return X86_TDESC_AVX; + else + return X86_TDESC_MPX; + } else if (xcr0 & X86_XSTATE_AVX) - tdesc = &i386_tdescs[X86_TDESC_AVX]; + return X86_TDESC_AVX; else if (xcr0 & X86_XSTATE_SSE) - tdesc = &i386_tdescs[X86_TDESC_SSE]; + return X86_TDESC_SSE; else if (xcr0 & X86_XSTATE_X87) - tdesc = &i386_tdescs[X86_TDESC_MMX]; + return X86_TDESC_MMX; + else + return X86_TDESC_LAST; +} - if (tdesc == NULL) +static struct target_desc *i386_tdescs[X86_TDESC_LAST] = { }; + +#if defined __i386__ || !defined IN_PROCESS_AGENT + +/* Return the target description according to XCR0. */ + +const struct target_desc * +i386_linux_read_description (uint64_t xcr0) +{ + enum x86_linux_tdesc idx = xcr0_to_tdesc_idx (xcr0, false); + + if (idx == X86_TDESC_LAST) return NULL; + struct target_desc **tdesc = &i386_tdescs[idx]; + if (*tdesc == NULL) { *tdesc = i386_create_target_description (xcr0); @@ -68,7 +100,44 @@ i386_linux_read_description (uint64_t xcr0) } #endif +#ifdef __x86_64__ + +static target_desc *amd64_tdescs[X86_TDESC_LAST] = { }; +static target_desc *x32_tdescs[X86_TDESC_LAST] = { }; + +const struct target_desc * +amd64_linux_read_description (uint64_t xcr0, bool is_x32) +{ + enum x86_linux_tdesc idx = xcr0_to_tdesc_idx (xcr0, is_x32); + + if (idx == X86_TDESC_LAST) + return NULL; + + struct target_desc **tdesc = NULL; + + if (is_x32) + tdesc = &x32_tdescs[idx]; + else + tdesc = &amd64_tdescs[idx]; + + if (*tdesc == NULL) + { + *tdesc = amd64_create_target_description (xcr0, is_x32); + + init_target_desc (*tdesc); + +#ifndef IN_PROCESS_AGENT + static const char *expedite_regs_amd64[] = { "rbp", "rsp", "rip", NULL }; + (*tdesc)->expedite_regs = expedite_regs_amd64; +#endif + } + return *tdesc; +} + +#endif + #ifndef IN_PROCESS_AGENT + int i386_get_ipa_tdesc_idx (const struct target_desc *tdesc) { @@ -82,4 +151,23 @@ i386_get_ipa_tdesc_idx (const struct target_desc *tdesc) return X86_TDESC_MMX; } +#if defined __x86_64__ +int +amd64_get_ipa_tdesc_idx (const struct target_desc *tdesc) +{ + for (int i = 0; i < X86_TDESC_LAST; i++) + { + if (tdesc == amd64_tdescs[i]) + return i; + } + for (int i = 0; i < X86_TDESC_LAST; i++) + { + if (tdesc == x32_tdescs[i]) + return i; + } + + return X86_TDESC_SSE; +} + +#endif #endif diff --git a/gdb/gdbserver/linux-x86-tdesc.h b/gdb/gdbserver/linux-x86-tdesc.h index 03bd1f1..a6dc330 100644 --- a/gdb/gdbserver/linux-x86-tdesc.h +++ b/gdb/gdbserver/linux-x86-tdesc.h @@ -33,52 +33,19 @@ enum x86_linux_tdesc { X86_TDESC_LAST = 7, }; -#ifdef __x86_64__ - -#if defined __LP64__ || !defined IN_PROCESS_AGENT -/* Defined in auto-generated file amd64-linux.c. */ -void init_registers_amd64_linux (void); -extern const struct target_desc *tdesc_amd64_linux; - -/* Defined in auto-generated file amd64-avx-linux.c. */ -void init_registers_amd64_avx_linux (void); -extern const struct target_desc *tdesc_amd64_avx_linux; - -/* Defined in auto-generated file amd64-avx-avx512-linux.c. */ -void init_registers_amd64_avx_avx512_linux (void); -extern const struct target_desc *tdesc_amd64_avx_avx512_linux; - -/* Defined in auto-generated file amd64-avx-mpx-avx512-pku-linux.c. */ -void init_registers_amd64_avx_mpx_avx512_pku_linux (void); -extern const struct target_desc *tdesc_amd64_avx_mpx_avx512_pku_linux; - -/* Defined in auto-generated file amd64-avx-mpx-linux.c. */ -void init_registers_amd64_avx_mpx_linux (void); -extern const struct target_desc *tdesc_amd64_avx_mpx_linux; - -/* Defined in auto-generated file amd64-mpx-linux.c. */ -void init_registers_amd64_mpx_linux (void); -extern const struct target_desc *tdesc_amd64_mpx_linux; +#if defined __i386__ || !defined IN_PROCESS_AGENT +int i386_get_ipa_tdesc_idx (const struct target_desc *tdesc); #endif -#if defined __ILP32__ || !defined IN_PROCESS_AGENT -/* Defined in auto-generated file x32-linux.c. */ -void init_registers_x32_linux (void); -extern const struct target_desc *tdesc_x32_linux; - -/* Defined in auto-generated file x32-avx-linux.c. */ -void init_registers_x32_avx_linux (void); -extern const struct target_desc *tdesc_x32_avx_linux; - -/* Defined in auto-generated file x32-avx-avx512-linux.c. */ -void init_registers_x32_avx_avx512_linux (void); -extern const struct target_desc *tdesc_x32_avx_avx512_linux; +#if defined __x86_64__ && !defined IN_PROCESS_AGENT +int amd64_get_ipa_tdesc_idx (const struct target_desc *tdesc); #endif -#endif +const struct target_desc *i386_get_ipa_tdesc (int idx); -#if defined __i386__ || !defined IN_PROCESS_AGENT -int i386_get_ipa_tdesc_idx (const struct target_desc *tdesc); +#ifdef __x86_64__ +const struct target_desc *amd64_linux_read_description (uint64_t xcr0, + bool is_x32); #endif const struct target_desc *i386_linux_read_description (uint64_t xcr0);