aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYao Qi <yao.qi@linaro.org>2017-05-07 22:56:43 +0100
committerYao Qi <yao.qi@linaro.org>2017-06-20 11:34:11 +0100
commit33054362625814f457a18e88686761225237600a (patch)
tree5b11120afe8075c9f8b1a2e02cda190cf8dc6953
parentbc551008e618bdb990177fef8ebe0fff73c7478d (diff)
downloadgdb-33054362625814f457a18e88686761225237600a.zip
gdb-33054362625814f457a18e88686761225237600a.tar.gz
gdb-33054362625814f457a18e88686761225237600a.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. This patch also adds a unit test to make sure dynamically generated tdesc are identical to these generated from xml files. gdb: 2017-04-27 Yao Qi <yao.qi@linaro.org> * i386-linux-tdep.c (i386_linux_read_description): Generate target description if it doesn't exist. [GDB_SELF_TEST] (i386_linux_read_description_test): New unit test. (_initialize_i386_linux_tdep) [GDB_SELF_TEST]: Register unit test.
-rw-r--r--gdb/features/i386/32bit-linux.c1
-rw-r--r--gdb/features/i386/32bit-sse.c1
-rw-r--r--gdb/i386-linux-tdep.c83
-rw-r--r--gdb/target-descriptions.c11
4 files changed, 62 insertions, 34 deletions
diff --git a/gdb/features/i386/32bit-linux.c b/gdb/features/i386/32bit-linux.c
index 3f7bfe7..ff90d40 100644
--- a/gdb/features/i386/32bit-linux.c
+++ b/gdb/features/i386/32bit-linux.c
@@ -11,6 +11,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 9aa7d3e..08c3948 100644
--- a/gdb/features/i386/32bit-sse.c
+++ b/gdb/features/i386/32bit-sse.c
@@ -63,6 +63,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 d0ecb1a..26bc577 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. */
@@ -681,27 +682,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. */
@@ -1090,13 +1114,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 10f3be1..13468e5 100644
--- a/gdb/target-descriptions.c
+++ b/gdb/target-descriptions.c
@@ -2097,6 +2097,12 @@ public:
void visit (const tdesc_reg *reg) override
{
+ if (reg->target_regnum > next_regnum)
+ {
+ printf_unfiltered (" regnum = %ld;\n", reg->target_regnum);
+ next_regnum = reg->target_regnum;
+ }
+
printf_unfiltered (" tdesc_create_reg (feature, \"%s\", regnum++, %d, ",
reg->name, reg->save_restore);
if (reg->group)
@@ -2104,8 +2110,13 @@ public:
else
printf_unfiltered ("NULL, ");
printf_unfiltered ("%d, \"%s\");\n", reg->bitsize, reg->type);
+
+ next_regnum++;
}
+private:
+ /* The register number to use for the next register we see. */
+ int next_regnum = 0;
};
static void