From 0abe8a8992948559d225ff120095e42a1a6a36f4 Mon Sep 17 00:00:00 2001 From: Yao Qi Date: Tue, 5 Sep 2017 09:54:53 +0100 Subject: [PATCH] Dynamically composite xml in reply to GDB GDBserver still uses pre-generated target descriptions in order to reply to GDB's query on target description (see xml-builtin-generated.c in GDBserver build directory). This patch teaches GDBserver to create XML contents according to the target descriptions rather than using pre-generated ones. First, change target feature c files to pass the feature xml file name to tdesc_create_feature, so that target description in GDBserver can record them, and create XML contents from these features in buffer, like ... ... and send this buffer back to GDB. Note that this patch reuses target_desc.xmltarget a little bit, which is to hold the XML contents dynamically generated in tdesc_get_features_xml. However, it is not xfree'ed in ~target_desc, because we can't tell it is from xstrdup or a literal string. Since we don't delete target_desc, there is no memory leak yet. After we change all target descriptions to the new style, target_desc.xmltarget is from xstrdup, then, we can safely xfree it in ~target_desc. gdb: 2017-09-05 Yao Qi * arch/tdesc.h (tdesc_create_feature): Add an argument xml. * target-descriptions.c (tdesc_create_feature): Likewise, and adjust code. * features/i386/32bit-avx.c: Re-generated. * features/i386/32bit-avx512.c: Re-generated. * features/i386/32bit-core.c: Re-generated. * features/i386/32bit-linux.c: Re-generated. * features/i386/32bit-mpx.c: Re-generated. * features/i386/32bit-pkeys.c: Re-generated. * features/i386/32bit-sse.c: Re-generated. gdb/gdbserver: 2017-09-05 Yao Qi * linux-x86-tdesc.c: Don't include . (i386_linux_read_description) [!IN_PROCESS_AGENT]: Call set_tdesc_architecture and set_tdesc_osabi. Remove code setting .xmltarget. * server.c (get_features_xml): Call tdesc_get_features_xml. * tdesc.c (set_tdesc_architecture): New function. (set_tdesc_osabi): New function. (tdesc_get_features_xml): New function. (tdesc_create_feature): Add an argument. * tdesc.h (struct target_desc) : New field. : New field. (~target_desc): xfree features, arch, and osabi. (target_desc::oerator==): Don't compare .xmltarget. [!IN_PROCESS_AGENT] (set_tdesc_architecture): Declare. (set_tdesc_osabi): Likewise. (tdesc_get_features_xml): Likewise. --- gdb/ChangeLog | 13 +++++++ gdb/arch/tdesc.h | 4 ++- gdb/features/i386/32bit-avx.c | 2 +- gdb/features/i386/32bit-avx512.c | 2 +- gdb/features/i386/32bit-core.c | 2 +- gdb/features/i386/32bit-linux.c | 2 +- gdb/features/i386/32bit-mpx.c | 2 +- gdb/features/i386/32bit-pkeys.c | 2 +- gdb/features/i386/32bit-sse.c | 2 +- gdb/gdbserver/ChangeLog | 19 ++++++++++ gdb/gdbserver/linux-x86-tdesc.c | 24 +++---------- gdb/gdbserver/server.c | 10 +++--- gdb/gdbserver/tdesc.c | 62 +++++++++++++++++++++++++++++++- gdb/gdbserver/tdesc.h | 34 +++++++++++++++--- gdb/target-descriptions.c | 9 +++-- 15 files changed, 150 insertions(+), 39 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 84135045ff..0ac42e480d 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,16 @@ +2017-09-05 Yao Qi + + * arch/tdesc.h (tdesc_create_feature): Add an argument xml. + * target-descriptions.c (tdesc_create_feature): Likewise, and + adjust code. + * features/i386/32bit-avx.c: Re-generated. + * features/i386/32bit-avx512.c: Re-generated. + * features/i386/32bit-core.c: Re-generated. + * features/i386/32bit-linux.c: Re-generated. + * features/i386/32bit-mpx.c: Re-generated. + * features/i386/32bit-pkeys.c: Re-generated. + * features/i386/32bit-sse.c: Re-generated. + 2017-09-05 Yao Qi * regformats/regdef.h (struct reg): Override operator == and !=. diff --git a/gdb/arch/tdesc.h b/gdb/arch/tdesc.h index 872df68bb4..bf50e24bd9 100644 --- a/gdb/arch/tdesc.h +++ b/gdb/arch/tdesc.h @@ -30,7 +30,9 @@ struct tdesc_type *tdesc_named_type (const struct tdesc_feature *feature, /* Return the created feature named NAME in target description TDESC. */ struct tdesc_feature *tdesc_create_feature (struct target_desc *tdesc, - const char *name); + const char *name, + const char *xml = nullptr); + /* Return the created vector tdesc_type named NAME in FEATURE. */ struct tdesc_type *tdesc_create_vector (struct tdesc_feature *feature, diff --git a/gdb/features/i386/32bit-avx.c b/gdb/features/i386/32bit-avx.c index 3a98936a0c..8a0c35655d 100644 --- a/gdb/features/i386/32bit-avx.c +++ b/gdb/features/i386/32bit-avx.c @@ -8,7 +8,7 @@ create_feature_i386_32bit_avx (struct target_desc *result, long regnum) { struct tdesc_feature *feature; - feature = tdesc_create_feature (result, "org.gnu.gdb.i386.avx"); + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.avx", "32bit-avx.xml"); tdesc_create_reg (feature, "ymm0h", regnum++, 1, NULL, 128, "uint128"); tdesc_create_reg (feature, "ymm1h", regnum++, 1, NULL, 128, "uint128"); tdesc_create_reg (feature, "ymm2h", regnum++, 1, NULL, 128, "uint128"); diff --git a/gdb/features/i386/32bit-avx512.c b/gdb/features/i386/32bit-avx512.c index b13e1d3308..82b20c5344 100644 --- a/gdb/features/i386/32bit-avx512.c +++ b/gdb/features/i386/32bit-avx512.c @@ -8,7 +8,7 @@ create_feature_i386_32bit_avx512 (struct target_desc *result, long regnum) { struct tdesc_feature *feature; - feature = tdesc_create_feature (result, "org.gnu.gdb.i386.avx512"); + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.avx512", "32bit-avx512.xml"); struct tdesc_type *field_type; field_type = tdesc_named_type (feature, "uint128"); tdesc_create_vector (feature, "v2ui128", field_type, 2); diff --git a/gdb/features/i386/32bit-core.c b/gdb/features/i386/32bit-core.c index ea6db935c0..ec903f3218 100644 --- a/gdb/features/i386/32bit-core.c +++ b/gdb/features/i386/32bit-core.c @@ -8,7 +8,7 @@ create_feature_i386_32bit_core (struct target_desc *result, long regnum) { struct tdesc_feature *feature; - feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core"); + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.core", "32bit-core.xml"); struct tdesc_type *field_type; struct tdesc_type *type; type = tdesc_create_flags (feature, "i386_eflags", 4); diff --git a/gdb/features/i386/32bit-linux.c b/gdb/features/i386/32bit-linux.c index 1ba932d795..136e3d71b4 100644 --- a/gdb/features/i386/32bit-linux.c +++ b/gdb/features/i386/32bit-linux.c @@ -8,7 +8,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"); + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.linux", "32bit-linux.xml"); regnum = 41; tdesc_create_reg (feature, "orig_eax", regnum++, 1, NULL, 32, "int"); return regnum; diff --git a/gdb/features/i386/32bit-mpx.c b/gdb/features/i386/32bit-mpx.c index f7d2ef052c..25a3fb145a 100644 --- a/gdb/features/i386/32bit-mpx.c +++ b/gdb/features/i386/32bit-mpx.c @@ -8,7 +8,7 @@ create_feature_i386_32bit_mpx (struct target_desc *result, long regnum) { struct tdesc_feature *feature; - feature = tdesc_create_feature (result, "org.gnu.gdb.i386.mpx"); + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.mpx", "32bit-mpx.xml"); struct tdesc_type *field_type; struct tdesc_type *type; type = tdesc_create_struct (feature, "br128"); diff --git a/gdb/features/i386/32bit-pkeys.c b/gdb/features/i386/32bit-pkeys.c index 89f1a5b3e0..4ad7649915 100644 --- a/gdb/features/i386/32bit-pkeys.c +++ b/gdb/features/i386/32bit-pkeys.c @@ -8,7 +8,7 @@ create_feature_i386_32bit_pkeys (struct target_desc *result, long regnum) { struct tdesc_feature *feature; - feature = tdesc_create_feature (result, "org.gnu.gdb.i386.pkeys"); + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.pkeys", "32bit-pkeys.xml"); tdesc_create_reg (feature, "pkru", regnum++, 1, NULL, 32, "uint32"); return regnum; } diff --git a/gdb/features/i386/32bit-sse.c b/gdb/features/i386/32bit-sse.c index 98f4cd061c..01b2058af6 100644 --- a/gdb/features/i386/32bit-sse.c +++ b/gdb/features/i386/32bit-sse.c @@ -8,7 +8,7 @@ create_feature_i386_32bit_sse (struct target_desc *result, long regnum) { struct tdesc_feature *feature; - feature = tdesc_create_feature (result, "org.gnu.gdb.i386.sse"); + feature = tdesc_create_feature (result, "org.gnu.gdb.i386.sse", "32bit-sse.xml"); struct tdesc_type *field_type; field_type = tdesc_named_type (feature, "ieee_single"); tdesc_create_vector (feature, "v4f", field_type, 4); diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 20a0c97911..595faf59fe 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,22 @@ +2017-09-05 Yao Qi + + * linux-x86-tdesc.c: Don't include . + (i386_linux_read_description) [!IN_PROCESS_AGENT]: Call + set_tdesc_architecture and set_tdesc_osabi. Remove code setting + .xmltarget. + * server.c (get_features_xml): Call tdesc_get_features_xml. + * tdesc.c (set_tdesc_architecture): New function. + (set_tdesc_osabi): New function. + (tdesc_get_features_xml): New function. + (tdesc_create_feature): Add an argument. + * tdesc.h (struct target_desc) : New field. + : New field. + (~target_desc): xfree features, arch, and osabi. + (target_desc::oerator==): Don't compare .xmltarget. + [!IN_PROCESS_AGENT] (set_tdesc_architecture): Declare. + (set_tdesc_osabi): Likewise. + (tdesc_get_features_xml): Likewise. + 2017-09-05 Yao Qi * linux-x86-tdesc.c: Include selftest.h. diff --git a/gdb/gdbserver/linux-x86-tdesc.c b/gdb/gdbserver/linux-x86-tdesc.c index 1f3dbaf9e2..3f63d8ee78 100644 --- a/gdb/gdbserver/linux-x86-tdesc.c +++ b/gdb/gdbserver/linux-x86-tdesc.c @@ -21,7 +21,6 @@ #include "tdesc.h" #include "linux-x86-tdesc.h" #include "x86-xstate.h" -#include #if defined __i386__ || !defined IN_PROCESS_AGENT #include "../features/i386/32bit-core.c" @@ -145,6 +144,11 @@ i386_linux_read_description (uint64_t xcr0) { *tdesc = new target_desc (); +#ifndef IN_PROCESS_AGENT + set_tdesc_architecture (*tdesc, "i386"); + set_tdesc_osabi (*tdesc, "GNU/Linux"); +#endif + long regnum = 0; if (xcr0 & X86_XSTATE_X87) @@ -172,24 +176,6 @@ i386_linux_read_description (uint64_t xcr0) #ifndef IN_PROCESS_AGENT static const char *expedite_regs_i386[] = { "ebp", "esp", "eip", NULL }; (*tdesc)->expedite_regs = expedite_regs_i386; - - if (xcr0 & X86_XSTATE_PKRU) - (*tdesc)->xmltarget = "i386-avx-mpx-avx512-pku-linux.xml"; - else if (xcr0 & X86_XSTATE_AVX512) - (*tdesc)->xmltarget = "i386-avx-avx512-linux.xml"; - else if ((xcr0 & X86_XSTATE_AVX_MPX_MASK) == X86_XSTATE_AVX_MPX_MASK) - (*tdesc)->xmltarget = "i386-avx-mpx-linux.xml"; - else if (xcr0 & X86_XSTATE_MPX) - (*tdesc)->xmltarget = "i386-mpx-linux.xml"; - else if (xcr0 & X86_XSTATE_AVX) - (*tdesc)->xmltarget = "i386-avx-linux.xml"; - else if (xcr0 & X86_XSTATE_SSE) - (*tdesc)->xmltarget = "i386-linux.xml"; - else if (xcr0 & X86_XSTATE_X87) - (*tdesc)->xmltarget = "i386-mmx-linux.xml"; - else - internal_error (__FILE__, __LINE__, - "unknown xcr0: %" PRIu64, xcr0); #endif } diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c index 7210d1ff9d..56c6393a4e 100644 --- a/gdb/gdbserver/server.c +++ b/gdb/gdbserver/server.c @@ -873,12 +873,14 @@ get_features_xml (const char *annex) This variable is set up from the auto-generated init_registers_... routine for the current target. */ - if (desc->xmltarget != NULL && strcmp (annex, "target.xml") == 0) + if (strcmp (annex, "target.xml") == 0) { - if (*desc->xmltarget == '@') - return desc->xmltarget + 1; + const char *ret = tdesc_get_features_xml ((target_desc*) desc); + + if (*ret == '@') + return ret + 1; else - annex = desc->xmltarget; + annex = ret; } #ifdef USE_XML diff --git a/gdb/gdbserver/tdesc.c b/gdb/gdbserver/tdesc.c index 4504c9bbc0..0b5096bbf7 100644 --- a/gdb/gdbserver/tdesc.c +++ b/gdb/gdbserver/tdesc.c @@ -61,6 +61,62 @@ current_target_desc (void) return current_process ()->tdesc; } + +void +set_tdesc_architecture (struct target_desc *target_desc, + const char *name) +{ + target_desc->arch = xstrdup (name); +} + +void +set_tdesc_osabi (struct target_desc *target_desc, const char *name) +{ + target_desc->osabi = xstrdup (name); +} + +/* Return a string which is of XML format, including XML target + description to be sent to GDB. */ + +const char * +tdesc_get_features_xml (target_desc *tdesc) +{ + /* Either .xmltarget or .features is not NULL. */ + gdb_assert (tdesc->xmltarget != NULL + || (tdesc->features != NULL + && tdesc->arch != NULL + && tdesc->osabi != NULL)); + + if (tdesc->xmltarget == NULL) + { + std::string buffer ("@"); + + buffer += ""; + buffer += ""; + buffer += ""; + buffer += tdesc->arch; + buffer += ""; + + buffer += ""; + buffer += tdesc->osabi; + buffer += ""; + + char *xml; + + for (int i = 0; VEC_iterate (char_ptr, tdesc->features, i, xml); i++) + { + buffer += ""; + } + + buffer += ""; + + tdesc->xmltarget = xstrdup (buffer.c_str ()); + } + + return tdesc->xmltarget; +} #endif struct tdesc_type @@ -69,8 +125,12 @@ struct tdesc_type /* See arch/tdesc.h. */ struct tdesc_feature * -tdesc_create_feature (struct target_desc *tdesc, const char *name) +tdesc_create_feature (struct target_desc *tdesc, const char *name, + const char *xml) { +#ifndef IN_PROCESS_AGENT + VEC_safe_push (char_ptr, tdesc->features, xstrdup (xml)); +#endif return tdesc; } diff --git a/gdb/gdbserver/tdesc.h b/gdb/gdbserver/tdesc.h index 49c82c6c16..fe3c78ff05 100644 --- a/gdb/gdbserver/tdesc.h +++ b/gdb/gdbserver/tdesc.h @@ -49,9 +49,21 @@ struct target_desc : tdesc_feature /* Defines what to return when looking for the "target.xml" file in response to qXfer:features:read. Its contents can either be verbatim XML code (prefixed with a '@') or else the name of the - actual XML file to be used in place of "target.xml". */ + actual XML file to be used in place of "target.xml". + + It can be NULL, then, its content is got from the following three + fields features, arch, and osabi in tdesc_get_features_xml. */ const char *xmltarget = NULL; + /* XML features in this target description. */ + VEC (char_ptr) *features = NULL; + + /* The value of element in the XML, replying GDB. */ + const char *arch = NULL; + + /* The value of element in the XML, replying GDB. */ + const char *osabi = NULL; + public: target_desc () : reg_defs (NULL), registers_size (0) @@ -65,6 +77,15 @@ public: for (i = 0; VEC_iterate (tdesc_reg_p, reg_defs, i, reg); i++) xfree (reg); VEC_free (tdesc_reg_p, reg_defs); + + xfree ((char *) arch); + xfree ((char *) osabi); + + char *f; + + for (i = 0; VEC_iterate (char_ptr, features, i, f); i++) + xfree (f); + VEC_free (char_ptr, features); } bool operator== (const target_desc &other) const @@ -96,9 +117,6 @@ public: if (other.expedite_regs[i] != NULL) return false; - if (strcmp (xmltarget, other.xmltarget) != 0) - return false; - return true; } @@ -123,4 +141,12 @@ void init_target_desc (struct target_desc *tdesc); const struct target_desc *current_target_desc (void); +#ifndef IN_PROCESS_AGENT +void set_tdesc_architecture (struct target_desc *target_desc, + const char *name); +void set_tdesc_osabi (struct target_desc *target_desc, const char *name); + +const char *tdesc_get_features_xml (struct target_desc *tdesc); +#endif + #endif /* TDESC_H */ diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c index f0ced66408..6135e0d99e 100644 --- a/gdb/target-descriptions.c +++ b/gdb/target-descriptions.c @@ -1750,7 +1750,8 @@ tdesc_add_enum_value (struct tdesc_type *type, int value, /* See arch/tdesc.h. */ struct tdesc_feature * -tdesc_create_feature (struct target_desc *tdesc, const char *name) +tdesc_create_feature (struct target_desc *tdesc, const char *name, + const char *xml) { struct tdesc_feature *new_feature = new tdesc_feature (name); @@ -2202,8 +2203,10 @@ public: printf_unfiltered ("{\n"); printf_unfiltered (" struct tdesc_feature *feature;\n"); - printf_unfiltered ("\n feature = tdesc_create_feature (result, \"%s\");\n", - e->name); + + printf_unfiltered + ("\n feature = tdesc_create_feature (result, \"%s\", \"%s\");\n", + e->name, lbasename (m_filename_after_features.c_str ())); } void visit_post (const tdesc_feature *e) override