From b4570e4b3032f9f4a508dbacd8136f79cf42c249 Mon Sep 17 00:00:00 2001 From: Yao Qi Date: Tue, 5 Sep 2017 09:54:54 +0100 Subject: [PATCH] Convert amd64-linux target descriptions This patch changes amd64-linux target descriptions so that they can be dynamically generated in both GDB and GDBserver. gdb/gdbserver: 2017-09-05 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-09-05 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/ChangeLog | 11 ++ 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/ChangeLog | 25 +++++ gdb/gdbserver/Makefile.in | 4 + gdb/gdbserver/configure.srv | 3 +- gdb/gdbserver/linux-amd64-ipa.c | 56 ++++------- 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 ++------- 14 files changed, 375 insertions(+), 210 deletions(-) create mode 100644 gdb/arch/amd64.c create mode 100644 gdb/arch/amd64.h diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 9ac02daa7e..91c5b20f00 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,14 @@ +2017-09-05 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. + 2017-09-05 Yao Qi * amd64-linux-tdep.c: Don't include amd64-XXX-linux and diff --git a/gdb/Makefile.in b/gdb/Makefile.in index 2caa67437d..69e80fa138 100644 --- a/gdb/Makefile.in +++ b/gdb/Makefile.in @@ -763,6 +763,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 7afa012480..7fbd328cdd 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 0000000000..626733d6db --- /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 0000000000..0821a7c0f4 --- /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 1f263515fd..402d6babfd 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/ChangeLog b/gdb/gdbserver/ChangeLog index 30b4fec8e2..0efb7e129f 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,28 @@ +2017-09-05 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. + 2017-09-05 Yao Qi * configure.srv (srv_i386_linux_xmlfiles): Remove diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in index b552b69814..1bbe515629 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 946119c0cc..95649f4b85 100644 --- a/gdb/gdbserver/configure.srv +++ b/gdb/gdbserver/configure.srv @@ -365,7 +365,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" @@ -381,6 +381,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 683339b201..85d0d45374 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,37 @@ 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_AVX_AVX512: - return tdesc_x32_avx_avx512_linux; + return amd64_linux_read_description (X86_XSTATE_AVX_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 +276,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_avx_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 54be82f870..f09871ac36 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 558a25be86..aa5a8e9b59 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 (); selftests::register_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 (); + + selftests::register_test (selftests::tdesc::amd64_tdesc_test); +#endif } diff --git a/gdb/gdbserver/linux-x86-tdesc.c b/gdb/gdbserver/linux-x86-tdesc.c index d1e262c480..9eb61a7208 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 03bd1f16cf..a6dc33055b 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); -- 2.34.1