diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 14 | ||||
-rw-r--r-- | gdb/features/i386/32bit-linux.c | 1 | ||||
-rw-r--r-- | gdb/features/i386/32bit-sse.c | 1 | ||||
-rw-r--r-- | gdb/i386-linux-tdep.c | 83 | ||||
-rw-r--r-- | gdb/target-descriptions.c | 47 |
5 files changed, 112 insertions, 34 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 0f4ec46..77c74f2 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,19 @@ 2017-07-26 Yao Qi <yao.qi@linaro.org> + * i386-linux-tdep.c: Don't include features/i386/i386-*linux.c. + Include features/i386/32bit-*.c. + (i386_linux_read_description): Generate target description if it + doesn't exist. + (_initialize_i386_linux_tdep): Don't call _initialize_tdesc_i386 + functions. + * features/i386/32bit-linux.c: Re-generated. + * features/i386/32bit-sse.c: Likewise. + * target-descriptions.c (print_c_feature::visit): Print code to + set register number if needed. + (print_c_feature) <m_next_regnum>: New field. + +2017-07-26 Yao Qi <yao.qi@linaro.org> + * features/Makefile (CFILES): Rename with TDESC_CFILES. (FEATURE_XMLFILES): New. (FEATURE_CFILES): New. diff --git a/gdb/features/i386/32bit-linux.c b/gdb/features/i386/32bit-linux.c index 686a2f1..1b50882 100644 --- a/gdb/features/i386/32bit-linux.c +++ b/gdb/features/i386/32bit-linux.c @@ -9,6 +9,7 @@ create_feature_i386_32bit_linux (struct target_desc *result, long regnum) struct tdesc_feature *feature; feature = tdesc_create_feature (result, "org.gnu.gdb.i386.linux"); + regnum = 41; tdesc_create_reg (feature, "orig_eax", regnum++, 1, NULL, 32, "int"); return regnum; } diff --git a/gdb/features/i386/32bit-sse.c b/gdb/features/i386/32bit-sse.c index 032623e..c0684fb 100644 --- a/gdb/features/i386/32bit-sse.c +++ b/gdb/features/i386/32bit-sse.c @@ -61,6 +61,7 @@ create_feature_i386_32bit_sse (struct target_desc *result, long regnum) tdesc_add_flag (type, 12, "PM"); tdesc_add_flag (type, 15, "FZ"); + regnum = 32; tdesc_create_reg (feature, "xmm0", regnum++, 1, NULL, 128, "vec128"); tdesc_create_reg (feature, "xmm1", regnum++, 1, NULL, 128, "vec128"); tdesc_create_reg (feature, "xmm2", regnum++, 1, NULL, 128, "vec128"); diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c index e986d6f..4c0f597 100644 --- a/gdb/i386-linux-tdep.c +++ b/gdb/i386-linux-tdep.c @@ -45,13 +45,14 @@ #include "record-full.h" #include "linux-record.h" -#include "features/i386/i386-linux.c" -#include "features/i386/i386-mmx-linux.c" -#include "features/i386/i386-mpx-linux.c" -#include "features/i386/i386-avx-mpx-linux.c" -#include "features/i386/i386-avx-linux.c" -#include "features/i386/i386-avx-avx512-linux.c" -#include "features/i386/i386-avx-mpx-avx512-pku-linux.c" + +#include "features/i386/32bit-core.c" +#include "features/i386/32bit-sse.c" +#include "features/i386/32bit-linux.c" +#include "features/i386/32bit-avx.c" +#include "features/i386/32bit-mpx.c" +#include "features/i386/32bit-avx512.c" +#include "features/i386/32bit-pkeys.c" /* Return non-zero, when the register is in the corresponding register group. Put the LINUX_ORIG_EAX register in the system group. */ @@ -683,27 +684,50 @@ i386_linux_core_read_xcr0 (bfd *abfd) const struct target_desc * i386_linux_read_description (uint64_t xcr0) { - switch ((xcr0 & X86_XSTATE_ALL_MASK)) + if (xcr0 == 0) + return NULL; + + static struct target_desc *i386_linux_tdescs \ + [2/*X87*/][2/*SSE*/][2/*AVX*/][2/*MPX*/][2/*AVX512*/][2/*PKRU*/] = {}; + struct target_desc **tdesc; + + tdesc = &i386_linux_tdescs[(xcr0 & X86_XSTATE_X87) ? 1 : 0] + [(xcr0 & X86_XSTATE_SSE) ? 1 : 0] + [(xcr0 & X86_XSTATE_AVX) ? 1 : 0] + [(xcr0 & X86_XSTATE_MPX) ? 1 : 0] + [(xcr0 & X86_XSTATE_AVX512) ? 1 : 0] + [(xcr0 & X86_XSTATE_PKRU) ? 1 : 0]; + + if (*tdesc == NULL) { - case X86_XSTATE_AVX_MPX_AVX512_PKU_MASK: - return tdesc_i386_avx_mpx_avx512_pku_linux; - case X86_XSTATE_AVX_AVX512_MASK: - return tdesc_i386_avx_avx512_linux; - case X86_XSTATE_MPX_MASK: - return tdesc_i386_mpx_linux; - case X86_XSTATE_AVX_MPX_MASK: - return tdesc_i386_avx_mpx_linux; - case X86_XSTATE_AVX_MASK: - return tdesc_i386_avx_linux; - case X86_XSTATE_SSE_MASK: - return tdesc_i386_linux; - case X86_XSTATE_X87_MASK: - return tdesc_i386_mmx_linux; - default: - break; + *tdesc = allocate_target_description (); + set_tdesc_architecture (*tdesc, bfd_scan_arch ("i386")); + set_tdesc_osabi (*tdesc, osabi_from_tdesc_string ("GNU/Linux")); + + long regnum = 0; + + if (xcr0 & X86_XSTATE_X87) + regnum = create_feature_i386_32bit_core (*tdesc, regnum); + + if (xcr0 & X86_XSTATE_SSE) + regnum = create_feature_i386_32bit_sse (*tdesc, regnum); + + regnum = create_feature_i386_32bit_linux (*tdesc, regnum); + + if (xcr0 & X86_XSTATE_AVX) + regnum = create_feature_i386_32bit_avx (*tdesc, regnum); + + if (xcr0 & X86_XSTATE_MPX) + regnum = create_feature_i386_32bit_mpx (*tdesc, regnum); + + if (xcr0 & X86_XSTATE_AVX512) + regnum = create_feature_i386_32bit_avx512 (*tdesc, regnum); + + if (xcr0 & X86_XSTATE_PKRU) + regnum = create_feature_i386_32bit_pkeys (*tdesc, regnum); } - return NULL; + return *tdesc; } /* Get Linux/x86 target description from core dump. */ @@ -1092,13 +1116,4 @@ _initialize_i386_linux_tdep (void) { gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_LINUX, i386_linux_init_abi); - - /* Initialize the Linux target description. */ - initialize_tdesc_i386_linux (); - initialize_tdesc_i386_mmx_linux (); - initialize_tdesc_i386_avx_linux (); - initialize_tdesc_i386_mpx_linux (); - initialize_tdesc_i386_avx_mpx_linux (); - initialize_tdesc_i386_avx_avx512_linux (); - initialize_tdesc_i386_avx_mpx_avx512_pku_linux (); } diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c index 5fd07ef..333cbd8 100644 --- a/gdb/target-descriptions.c +++ b/gdb/target-descriptions.c @@ -2104,6 +2104,48 @@ public: void visit (const tdesc_reg *reg) override { + /* Most "reg" in XML target descriptions don't have "regnum" + attribute, so the register number is allocated sequentially. + In case that reg has "regnum" attribute, register number + should be set by that explicitly. */ + + if (reg->target_regnum < m_next_regnum) + { + /* The integrity check, it can catch some errors on register + number collision, like this, + + <reg name="x0" bitsize="32"/> + <reg name="x1" bitsize="32"/> + <reg name="x2" bitsize="32"/> + <reg name="x3" bitsize="32"/> + <reg name="ps" bitsize="32" regnum="3"/> + + but it also has false negatives. The target description + below is correct, + + <reg name="x1" bitsize="32" regnum="1"/> + <reg name="x3" bitsize="32" regnum="3"/> + <reg name="x2" bitsize="32" regnum="2"/> + <reg name="x4" bitsize="32" regnum="4"/> + + but it is not a good practice, so still error on this, + and also print the message so that it can be saved in the + generated c file. */ + + printf_unfiltered ("ERROR: \"regnum\" attribute %ld ", + reg->target_regnum); + printf_unfiltered ("is not the largest number (%d).\n", + m_next_regnum); + error (_("\"regnum\" attribute %ld is not the largest number (%d)."), + reg->target_regnum, m_next_regnum); + } + + if (reg->target_regnum > m_next_regnum) + { + printf_unfiltered (" regnum = %ld;\n", reg->target_regnum); + m_next_regnum = reg->target_regnum; + } + printf_unfiltered (" tdesc_create_reg (feature, \"%s\", regnum++, %d, ", reg->name, reg->save_restore); if (reg->group) @@ -2111,8 +2153,13 @@ public: else printf_unfiltered ("NULL, "); printf_unfiltered ("%d, \"%s\");\n", reg->bitsize, reg->type); + + m_next_regnum++; } +private: + /* The register number to use for the next register we see. */ + int m_next_regnum = 0; }; static void |