aboutsummaryrefslogtreecommitdiff
path: root/gdb/i386-linux-tdep.c
diff options
context:
space:
mode:
authorYao Qi <yao.qi@linaro.org>2017-07-26 14:39:54 +0100
committerYao Qi <yao.qi@linaro.org>2017-07-26 14:39:54 +0100
commitea03d0d3c32b22aeddfeb139a4a515f7e5961347 (patch)
tree93bd39d275e82ffe4e66a7ca209540aa031c29f9 /gdb/i386-linux-tdep.c
parent25aa13e522c595cbdbb3868f1daa434a17ba2ab2 (diff)
downloadgdb-ea03d0d3c32b22aeddfeb139a4a515f7e5961347.zip
gdb-ea03d0d3c32b22aeddfeb139a4a515f7e5961347.tar.gz
gdb-ea03d0d3c32b22aeddfeb139a4a515f7e5961347.tar.bz2
Lazily and dynamically create i386-linux target descriptions
Instead of using pre-generated target descriptions, this patch changes GDB to lazily and dynamically create target descriptions according to the target hardware capability (xcr0 in i386). This support any combination of target features. Some reg in target description has "regnum" attribute, so its register number is got from the attribute value instead from sequential allocation. <reg name="xmm0" bitsize="128" type="vec128" regnum="32"/> when target description is created, it should match the regnum, so this patch adds a new field m_next_regnum to track it, if attribute number is greater than the m_next_regnum, print the code to set register number explicitly. gdb: 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.
Diffstat (limited to 'gdb/i386-linux-tdep.c')
-rw-r--r--gdb/i386-linux-tdep.c83
1 files changed, 49 insertions, 34 deletions
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 ();
}