Add "maint check xml-descriptions" to test builtin xml target descriptions
Now, GDB is able to dynamically create i386-linux target descriptions from features, instead of using pre-generated target descriptions. These pre-generated target descriptions are no longer used by GDB (note that they are still used by GDBserver). This patch add a new maint command "maint check xml-descriptions" to test dynamically generated tdesc are identical to these generated from xml files. gdb: 2017-07-26 Yao Qi <yao.qi@linaro.org> * cli/cli-cmds.c (maintenancechecklist): New variable. * gdbcmd.h (maintenancechecklist): Declare it. * i386-linux-tdep.c (_initialize_i386_linux_tdep) [GDB_SELF_TEST]: Call i386_linux_read_description with different masks. * maint.c (maintenance_check_command): New function. (_initialize_maint_cmds): Call add_prefix_cmd. * target-descriptions.c (tdesc_reg): override operator != and ==. (tdesc_type): Likewise. (tdesc_feature): Likewise. (target_desc): Likewise. [GDB_SELF_TEST] (selftests::record_xml_tdesc): New function. (maintenance_check_xml_descriptions): New function. (_initialize_target_descriptions) Add command "xml-descriptions". * target-descriptions.h (selftests::record_xml_tdesc): Declare. gdb/testsuite: 2017-07-26 Yao Qi <yao.qi@linaro.org> * gdb.gdb/unittest.exp: Invoke command "maintenance check xml-descriptions". gdb/doc: 2017-07-26 Yao Qi <yao.qi@linaro.org> * gdb.texinfo (Maintenance Commands): Document command "maint check xml-descriptions".
This commit is contained in:
parent
ea03d0d3c3
commit
27d41eac62
@ -1,3 +1,20 @@
|
||||
2017-07-26 Yao Qi <yao.qi@linaro.org>
|
||||
|
||||
* cli/cli-cmds.c (maintenancechecklist): New variable.
|
||||
* gdbcmd.h (maintenancechecklist): Declare it.
|
||||
* i386-linux-tdep.c (_initialize_i386_linux_tdep) [GDB_SELF_TEST]:
|
||||
Call i386_linux_read_description with different masks.
|
||||
* maint.c (maintenance_check_command): New function.
|
||||
(_initialize_maint_cmds): Call add_prefix_cmd.
|
||||
* target-descriptions.c (tdesc_reg): override operator != and ==.
|
||||
(tdesc_type): Likewise.
|
||||
(tdesc_feature): Likewise.
|
||||
(target_desc): Likewise.
|
||||
[GDB_SELF_TEST] (selftests::record_xml_tdesc): New function.
|
||||
(maintenance_check_xml_descriptions): New function.
|
||||
(_initialize_target_descriptions) Add command "xml-descriptions".
|
||||
* target-descriptions.h (selftests::record_xml_tdesc): Declare.
|
||||
|
||||
2017-07-26 Yao Qi <yao.qi@linaro.org>
|
||||
|
||||
* i386-linux-tdep.c: Don't include features/i386/i386-*linux.c.
|
||||
|
@ -168,6 +168,10 @@ struct cmd_list_element *maintenanceinfolist;
|
||||
|
||||
struct cmd_list_element *maintenanceprintlist;
|
||||
|
||||
/* Chain containing all defined "maintenance check" subcommands. */
|
||||
|
||||
struct cmd_list_element *maintenancechecklist;
|
||||
|
||||
struct cmd_list_element *setprintlist;
|
||||
|
||||
struct cmd_list_element *showprintlist;
|
||||
|
@ -1,3 +1,8 @@
|
||||
2017-07-26 Yao Qi <yao.qi@linaro.org>
|
||||
|
||||
* gdb.texinfo (Maintenance Commands): Document command
|
||||
"maint check xml-descriptions".
|
||||
|
||||
2017-07-26 Yao Qi <yao.qi@linaro.org>
|
||||
|
||||
* gdb.texinfo (Maintenance Commands): Document optional
|
||||
|
@ -34698,6 +34698,11 @@ The created source file is built into @value{GDBN} when @value{GDBN} is
|
||||
built again. This command is used by developers after they add or
|
||||
modify XML target descriptions.
|
||||
|
||||
@kindex maint check xml-descriptions
|
||||
@item maint check xml-descriptions @var{dir}
|
||||
Check that the target descriptions dynamically created by @value{GDBN}
|
||||
equal the descriptions created from XML files found in @var{dir}.
|
||||
|
||||
@kindex maint print dummy-frames
|
||||
@item maint print dummy-frames
|
||||
Prints the contents of @value{GDBN}'s internal dummy-frame stack.
|
||||
|
@ -95,6 +95,10 @@ extern struct cmd_list_element *maintenanceinfolist;
|
||||
|
||||
extern struct cmd_list_element *maintenanceprintlist;
|
||||
|
||||
/* Chain containing all defined "maintenance check" subcommands. */
|
||||
|
||||
extern struct cmd_list_element *maintenancechecklist;
|
||||
|
||||
/* Chain containing all defined "maintenance set" subcommands. */
|
||||
|
||||
extern struct cmd_list_element *maintenance_set_cmdlist;
|
||||
|
@ -1116,4 +1116,28 @@ _initialize_i386_linux_tdep (void)
|
||||
{
|
||||
gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_LINUX,
|
||||
i386_linux_init_abi);
|
||||
|
||||
#if GDB_SELF_TEST
|
||||
struct
|
||||
{
|
||||
const char *xml;
|
||||
uint64_t mask;
|
||||
} xml_masks[] = {
|
||||
{ "i386/i386-linux.xml", X86_XSTATE_SSE_MASK },
|
||||
{ "i386/i386-mmx-linux.xml", X86_XSTATE_X87_MASK },
|
||||
{ "i386/i386-avx-linux.xml", X86_XSTATE_AVX_MASK },
|
||||
{ "i386/i386-mpx-linux.xml", X86_XSTATE_MPX_MASK },
|
||||
{ "i386/i386-avx-mpx-linux.xml", X86_XSTATE_AVX_MPX_MASK },
|
||||
{ "i386/i386-avx-avx512-linux.xml", X86_XSTATE_AVX_AVX512_MASK },
|
||||
{ "i386/i386-avx-mpx-avx512-pku-linux.xml",
|
||||
X86_XSTATE_AVX_MPX_AVX512_PKU_MASK },
|
||||
};
|
||||
|
||||
for (auto &a : xml_masks)
|
||||
{
|
||||
auto tdesc = i386_linux_read_description (a.mask);
|
||||
|
||||
selftests::record_xml_tdesc (a.xml, tdesc);
|
||||
}
|
||||
#endif /* GDB_SELF_TEST */
|
||||
}
|
||||
|
18
gdb/maint.c
18
gdb/maint.c
@ -178,6 +178,19 @@ maintenance_info_command (char *arg, int from_tty)
|
||||
gdb_stdout);
|
||||
}
|
||||
|
||||
/* The "maintenance check" command is defined as a prefix, with
|
||||
allow_unknown 0. Therefore, its own definition is called only for
|
||||
"maintenance check" with no args. */
|
||||
|
||||
static void
|
||||
maintenance_check_command (char *arg, int from_tty)
|
||||
{
|
||||
printf_unfiltered (_("\"maintenance check\" must be followed "
|
||||
"by the name of a check command.\n"));
|
||||
help_list (maintenancechecklist, "maintenance check ", all_commands,
|
||||
gdb_stdout);
|
||||
}
|
||||
|
||||
/* Mini tokenizing lexer for 'maint info sections' command. */
|
||||
|
||||
static int
|
||||
@ -1104,6 +1117,11 @@ Print the internal architecture configuration.\n\
|
||||
Takes an optional file parameter."),
|
||||
&maintenanceprintlist);
|
||||
|
||||
add_prefix_cmd ("check", class_maintenance, maintenance_check_command, _("\
|
||||
Commands for checking internal gdb state."),
|
||||
&maintenancechecklist, "maintenance check ", 0,
|
||||
&maintenancelist);
|
||||
|
||||
add_cmd ("translate-address", class_maintenance,
|
||||
maintenance_translate_address,
|
||||
_("Translate a section name and address to a symbol."),
|
||||
|
@ -35,6 +35,8 @@
|
||||
#include "hashtab.h"
|
||||
#include "inferior.h"
|
||||
#include <algorithm>
|
||||
#include "completer.h"
|
||||
#include "readline/tilde.h" /* tilde_expand */
|
||||
|
||||
/* The interface to visit different elements of target description. */
|
||||
|
||||
@ -134,6 +136,20 @@ typedef struct tdesc_reg : tdesc_element
|
||||
v.visit (this);
|
||||
}
|
||||
|
||||
bool operator== (const tdesc_reg &other) const
|
||||
{
|
||||
return (streq (name, other.name)
|
||||
&& target_regnum == other.target_regnum
|
||||
&& save_restore == other.save_restore
|
||||
&& bitsize == other.bitsize
|
||||
&& (group == other.group || streq (group, other.group))
|
||||
&& streq (type, other.type));
|
||||
}
|
||||
|
||||
bool operator!= (const tdesc_reg &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
} *tdesc_reg_p;
|
||||
DEF_VEC_P(tdesc_reg_p);
|
||||
|
||||
@ -248,6 +264,15 @@ typedef struct tdesc_type : tdesc_element
|
||||
v.visit (this);
|
||||
}
|
||||
|
||||
bool operator== (const tdesc_type &other) const
|
||||
{
|
||||
return (streq (name, other.name) && kind == other.kind);
|
||||
}
|
||||
|
||||
bool operator!= (const tdesc_type &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
} *tdesc_type_p;
|
||||
DEF_VEC_P(tdesc_type_p);
|
||||
|
||||
@ -312,6 +337,54 @@ typedef struct tdesc_feature : tdesc_element
|
||||
|
||||
v.visit_post (this);
|
||||
}
|
||||
|
||||
bool operator== (const tdesc_feature &other) const
|
||||
{
|
||||
if (strcmp (name, other.name) != 0)
|
||||
return false;
|
||||
|
||||
if (VEC_length (tdesc_reg_p, registers)
|
||||
!= VEC_length (tdesc_reg_p, other.registers))
|
||||
return false;
|
||||
|
||||
struct tdesc_reg *reg;
|
||||
|
||||
for (int ix = 0;
|
||||
VEC_iterate (tdesc_reg_p, registers, ix, reg);
|
||||
ix++)
|
||||
{
|
||||
tdesc_reg *reg2
|
||||
= VEC_index (tdesc_reg_p, other.registers, ix);
|
||||
|
||||
if (reg != reg2 && *reg != *reg2)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (VEC_length (tdesc_type_p, types)
|
||||
!= VEC_length (tdesc_type_p, other.types))
|
||||
return false;
|
||||
|
||||
tdesc_type *type;
|
||||
|
||||
for (int ix = 0;
|
||||
VEC_iterate (tdesc_type_p, types, ix, type);
|
||||
ix++)
|
||||
{
|
||||
tdesc_type *type2
|
||||
= VEC_index (tdesc_type_p, other.types, ix);
|
||||
|
||||
if (type != type2 && *type != *type2)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!= (const tdesc_feature &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
} *tdesc_feature_p;
|
||||
DEF_VEC_P(tdesc_feature_p);
|
||||
|
||||
@ -382,6 +455,39 @@ struct target_desc : tdesc_element
|
||||
|
||||
v.visit_post (this);
|
||||
}
|
||||
|
||||
bool operator== (const target_desc &other) const
|
||||
{
|
||||
if (arch != other.arch)
|
||||
return false;
|
||||
|
||||
if (osabi != other.osabi)
|
||||
return false;
|
||||
|
||||
if (VEC_length (tdesc_feature_p, features)
|
||||
!= VEC_length (tdesc_feature_p, other.features))
|
||||
return false;
|
||||
|
||||
struct tdesc_feature *feature;
|
||||
|
||||
for (int ix = 0;
|
||||
VEC_iterate (tdesc_feature_p, features, ix, feature);
|
||||
ix++)
|
||||
{
|
||||
struct tdesc_feature *feature2
|
||||
= VEC_index (tdesc_feature_p, other.features, ix);
|
||||
|
||||
if (feature != feature2 && *feature != *feature2)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator!= (const target_desc &other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
/* Per-architecture data associated with a target description. The
|
||||
@ -2213,6 +2319,50 @@ maint_print_c_tdesc_cmd (char *args, int from_tty)
|
||||
}
|
||||
}
|
||||
|
||||
namespace selftests {
|
||||
|
||||
static std::vector<std::pair<const char*, const target_desc *>> xml_tdesc;
|
||||
|
||||
#if GDB_SELF_TEST
|
||||
|
||||
/* See target-descritpions.h. */
|
||||
|
||||
void
|
||||
record_xml_tdesc (const char *xml_file, const struct target_desc *tdesc)
|
||||
{
|
||||
xml_tdesc.emplace_back (xml_file, tdesc);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Check that the target descriptions created dynamically by
|
||||
architecture-specific code equal the descriptions created from XML files
|
||||
found in the specified directory DIR. */
|
||||
|
||||
static void
|
||||
maintenance_check_xml_descriptions (char *dir, int from_tty)
|
||||
{
|
||||
if (dir == NULL)
|
||||
error (_("Missing dir name"));
|
||||
|
||||
gdb::unique_xmalloc_ptr<char> dir1 (tilde_expand (dir));
|
||||
std::string feature_dir (dir1.get ());
|
||||
unsigned int failed = 0;
|
||||
|
||||
for (auto const &e : selftests::xml_tdesc)
|
||||
{
|
||||
std::string tdesc_xml = (feature_dir + SLASH_STRING + e.first);
|
||||
const target_desc *tdesc
|
||||
= file_read_description_xml (tdesc_xml.data ());
|
||||
|
||||
if (tdesc == NULL || *tdesc != *e.second)
|
||||
failed++;
|
||||
}
|
||||
printf_filtered (_("Tested %lu XML files, %d failed\n"),
|
||||
(long) selftests::xml_tdesc.size (), failed);
|
||||
}
|
||||
|
||||
/* Provide a prototype to silence -Wmissing-prototypes. */
|
||||
extern initialize_file_ftype _initialize_target_descriptions;
|
||||
|
||||
@ -2253,4 +2403,14 @@ GDB will read the description from the target."),
|
||||
add_cmd ("c-tdesc", class_maintenance, maint_print_c_tdesc_cmd, _("\
|
||||
Print the current target description as a C source file."),
|
||||
&maintenanceprintlist);
|
||||
|
||||
cmd_list_element *cmd;
|
||||
|
||||
cmd = add_cmd ("xml-descriptions", class_maintenance,
|
||||
maintenance_check_xml_descriptions, _("\
|
||||
Check the target descriptions created in GDB equal the descriptions\n\
|
||||
created from XML files in the directory.\n\
|
||||
The parameter is the directory name."),
|
||||
&maintenancechecklist);
|
||||
set_cmd_completer (cmd, filename_completer);
|
||||
}
|
||||
|
@ -253,4 +253,16 @@ void tdesc_create_reg (struct tdesc_feature *feature, const char *name,
|
||||
int regnum, int save_restore, const char *group,
|
||||
int bitsize, const char *type);
|
||||
|
||||
#if GDB_SELF_TEST
|
||||
namespace selftests {
|
||||
|
||||
/* Record that XML_FILE should generate a target description that equals
|
||||
TDESC, to be verified by the "maintenance check xml-descriptions"
|
||||
command. */
|
||||
|
||||
void record_xml_tdesc (const char *xml_file,
|
||||
const struct target_desc *tdesc);
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* TARGET_DESCRIPTIONS_H */
|
||||
|
@ -1,3 +1,8 @@
|
||||
2017-07-26 Yao Qi <yao.qi@linaro.org>
|
||||
|
||||
* gdb.gdb/unittest.exp: Invoke command
|
||||
"maintenance check xml-descriptions".
|
||||
|
||||
2017-07-24 Andreas Arnez <arnez@linux.vnet.ibm.com>
|
||||
|
||||
* gdb.arch/s390-vregs.exp: Calculate parameters to hex128 in the
|
||||
|
@ -15,3 +15,8 @@
|
||||
|
||||
gdb_start
|
||||
gdb_test "maintenance selftest" "Ran $decimal unit tests, 0 failed"
|
||||
|
||||
if { ![is_remote host] } {
|
||||
gdb_test "maintenance check xml-descriptions ${srcdir}/../features" \
|
||||
"Tested $decimal XML files, 0 failed"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user