From patchwork Tue Jan 16 09:53:29 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Hayward X-Patchwork-Id: 25410 Received: (qmail 51524 invoked by alias); 16 Jan 2018 09:55:28 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 49788 invoked by uid 89); 16 Jan 2018 09:53:44 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LOTSOFHASH, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 spammy=UD:dtd, DOCTYPE, !DOCTYPE, fname X-HELO: EUR01-VE1-obe.outbound.protection.outlook.com Received: from mail-ve1eur01on0067.outbound.protection.outlook.com (HELO EUR01-VE1-obe.outbound.protection.outlook.com) (104.47.1.67) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 16 Jan 2018 09:53:33 +0000 Received: from AM3PR08MB0101.eurprd08.prod.outlook.com (10.160.211.19) by AM3PR08MB0103.eurprd08.prod.outlook.com (10.160.211.21) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.407.7; Tue, 16 Jan 2018 09:53:30 +0000 Received: from AM3PR08MB0101.eurprd08.prod.outlook.com ([fe80::11:d2e2:886:ac9d]) by AM3PR08MB0101.eurprd08.prod.outlook.com ([fe80::11:d2e2:886:ac9d%17]) with mapi id 15.20.0407.012; Tue, 16 Jan 2018 09:53:30 +0000 From: Alan Hayward To: "gdb-patches@sourceware.org" CC: nd Subject: [PATCH 4/6]: Create xml from target descriptions Date: Tue, 16 Jan 2018 09:53:29 +0000 Message-ID: <31767501-AFCF-4423-B2DD-B121924550D3@arm.com> References: In-Reply-To: authentication-results: spf=none (sender IP is ) smtp.mailfrom=Alan.Hayward@arm.com; x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; AM3PR08MB0103; 7:HvA0zbLm3z6/mifb7TCSTcPJvE15FWcghJk1/e0J4t/NdHnOA8Q64YLx9WSa+f+eeGGMGOtCUXwwR0G8esZTrSWLhqrsdykBEPa4pQJ5PCRXg0t03GlveZnr7NlwbNp9Ns1IMxfJeS67ValreRSN1QzcqJGBYdoIxyzVq35VMX1BGQ0Sl+FKeE09BwPc6EL0A3XY72WYwhuxT6MtfkEifXQI0tEk68beEAFLFRmHz2R7hIz6njDRQ8W5K38T69w3 x-ms-exchange-antispam-srfa-diagnostics: SSOS; x-ms-office365-filtering-correlation-id: bef60808-99ab-40fe-d571-08d55cc6ff61 x-ms-office365-filtering-ht: Tenant x-microsoft-antispam: UriScan:; BCL:0; PCL:0; RULEID:(7020095)(4652020)(5600026)(4604075)(3008032)(48565401081)(2017052603307)(7153060)(7193020); SRVR:AM3PR08MB0103; x-ms-traffictypediagnostic: AM3PR08MB0103: nodisclaimer: True x-microsoft-antispam-prvs: x-exchange-antispam-report-test: UriScan:(180628864354917); x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(6040470)(2401047)(8121501046)(5005006)(3231023)(944501161)(10201501046)(93006095)(93001095)(3002001)(6055026)(6041268)(20161123564045)(20161123560045)(20161123562045)(20161123558120)(201703131423095)(201702281528075)(20161123555045)(201703061421075)(201703061406153)(6072148)(201708071742011); SRVR:AM3PR08MB0103; BCL:0; PCL:0; RULEID:(100000803101)(100110400095); SRVR:AM3PR08MB0103; x-forefront-prvs: 0554B1F54F x-forefront-antispam-report: SFV:NSPM; SFS:(10009020)(376002)(39860400002)(366004)(39380400002)(346002)(396003)(199004)(189003)(377424004)(86362001)(575784001)(305945005)(72206003)(2906002)(7736002)(6916009)(4743002)(2950100002)(478600001)(106356001)(82746002)(105586002)(3846002)(6116002)(99286004)(3660700001)(36756003)(53936002)(83716003)(2351001)(66066001)(3280700002)(76176011)(5250100002)(33656002)(5640700003)(97736004)(68736007)(25786009)(2501003)(316002)(8936002)(5660300001)(6486002)(81166006)(8676002)(81156014)(14454004)(6512007)(102836004)(6436002)(2900100001)(59450400001)(4326008)(6506007)(26005); DIR:OUT; SFP:1101; SCL:1; SRVR:AM3PR08MB0103; H:AM3PR08MB0101.eurprd08.prod.outlook.com; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; received-spf: None (protection.outlook.com: arm.com does not designate permitted sender hosts) x-microsoft-antispam-message-info: sGzQUJ8o8TGukHOVgWCGJFt4uc8g0vddkYRmMOiXjYw1nQj3ijeveNvZDILKU00mr3Qb4thcWugVHBnNhA+mBA== spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM Content-ID: <35535D8B581CDC40BFB84B76E657F4B1@eurprd08.prod.outlook.com> MIME-Version: 1.0 X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-Network-Message-Id: bef60808-99ab-40fe-d571-08d55cc6ff61 X-MS-Exchange-CrossTenant-originalarrivaltime: 16 Jan 2018 09:53:30.0206 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM3PR08MB0103 X-IsSubscribed: yes This patch adds a print_xml_feature visitor class which turns a C target description into xml. Tests are added to maintenance_check_xml_descriptions which takes each pair of tested descriptions, turns them both into xml, then back again, and confirms the descriptions still match. I have added a new function void debug(const struct target_desc *) which simply prints a given target description out as xml. This follows the style of GCC which has debug functions for all major structure types (eg rtx). When debugging GCC I can usually take any tree or expression and just "call debug(x)" to get a nice dump of it, or sprinkle debug(x) calls through my failing code. I find this really useful, however I'm happy to remove (or rename) the function if people don't like it. Alan. 2018-01-16 Alan Hayward gdb/ * arch/tdesc.c (print_xml_feature::visit_post): Add xml parsing. (print_xml_feature::visit_pre): Likewise. (print_xml_feature::visit_post): Likewise. (print_xml_feature::visit): Likewise. (print_xml_feature::visit): Likewise. (print_xml_feature::visit): Likewise. (print_xml_feature::visit): Likewise. * arch/tdesc.h (print_xml_feature): Add new class. * regformats/regdat.sh: obtain xml. * target-descriptions.c (struct target_desc): Add xmltarget. (print_xml_feature::visit_pre): Add xml vistor. (tdesc_get_features_xml): Add function to get xml. (debug): Add target_desc debug function. (maintenance_check_xml_descriptions): Test xml generation. * target-descriptions.h (debug): Add declaration. * xml-tdesc.c (target_read_description_xml_string): Add function. * xml-tdesc.h (target_read_description_xml_string): Add declaration. gdbserver/ * tdesc.c (void target_desc::accept): Fill in function. (tdesc_get_features_xml): Remove old xml creation. (print_xml_feature::visit_pre): Add xml vistor. diff --git a/gdb/arch/tdesc.h b/gdb/arch/tdesc.h index 633853447d98c952cfed462939b486afd2738742..edd7de104973676fe69873ffe696e99eb77fbc84 100644 --- a/gdb/arch/tdesc.h +++ b/gdb/arch/tdesc.h @@ -359,4 +359,33 @@ void tdesc_create_reg (struct tdesc_feature *feature, const char *name, int regnum, int save_restore, const char *group, int bitsize, const char *type); +/* Return the tdesc in string XML format. */ + +const char *tdesc_get_features_xml (target_desc *tdesc); + +/* Print target description as xml. */ + +class print_xml_feature : public tdesc_element_visitor +{ +public: + print_xml_feature (std::string *buffer_) + : m_buffer (buffer_) + {} + + ~print_xml_feature () + {} + + void visit_pre (const target_desc *e) override; + void visit_post (const target_desc *e) override; + void visit_pre (const tdesc_feature *e) override; + void visit_post (const tdesc_feature *e) override; + void visit (const tdesc_type_builtin *type) override; + void visit (const tdesc_type_vector *type) override; + void visit (const tdesc_type_with_fields *type) override; + void visit (const tdesc_reg *reg) override; + +private: + std::string *m_buffer; +}; + #endif /* ARCH_TDESC_H */ diff --git a/gdb/arch/tdesc.c b/gdb/arch/tdesc.c index e6005a75a7264bba4cd177e4ec1efd90809e25c8..e43f37095d636cf680ce2b55c653deedd2c59eae 100644 --- a/gdb/arch/tdesc.c +++ b/gdb/arch/tdesc.c @@ -323,3 +323,138 @@ tdesc_add_enum_value (tdesc_type_with_fields *type, int value, tdesc_predefined_type (TDESC_TYPE_INT32), value, -1); } + + +void print_xml_feature::visit_post (const target_desc *e) +{ + *m_buffer += "\n"; +} + +void print_xml_feature::visit_pre (const tdesc_feature *e) +{ + *m_buffer += "name; + *m_buffer += "\">\n"; +} + +void print_xml_feature::visit_post (const tdesc_feature *e) +{ + *m_buffer += "\n"; +} + +void print_xml_feature::visit (const tdesc_type_builtin *type) +{ + error (_("xml output is not supported type \"%s\"."), type->name.c_str ()); +} + +void print_xml_feature::visit (const tdesc_type_vector *type) +{ + *m_buffer += "name; + *m_buffer += "\" type=\""; + *m_buffer += type->element_type->name; + *m_buffer += "\" count=\""; + *m_buffer += std::to_string (type->count); + *m_buffer += "\"/>\n"; +} + +void print_xml_feature::visit (const tdesc_type_with_fields *type) +{ + struct tdesc_type_field *f; + const static char *types[] = { "struct", "union", "flags", "enum" }; + + gdb_assert (type->kind >= TDESC_TYPE_STRUCT && type->kind <= TDESC_TYPE_ENUM); + *m_buffer += "<"; + *m_buffer += types[type->kind - TDESC_TYPE_STRUCT]; + + switch (type->kind) + { + case TDESC_TYPE_STRUCT: + case TDESC_TYPE_FLAGS: + *m_buffer += " id=\""; + *m_buffer += type->name; + if (type->size > 0) + { + *m_buffer += "\" size=\""; + *m_buffer += std::to_string (type->size); + } + *m_buffer += "\">\n"; + + for (const tdesc_type_field &f : type->fields) + { + *m_buffer += " name; + } + else + { + *m_buffer += "\" start=\""; + *m_buffer += std::to_string (f.start); + *m_buffer += "\" end=\""; + *m_buffer += std::to_string (f.end); + } + + *m_buffer += "\"/>\n"; + } + break; + + case TDESC_TYPE_ENUM: + *m_buffer += " id=\""; + *m_buffer += type->name; + *m_buffer += "\">\n"; + + for (const tdesc_type_field &f : type->fields) + { + *m_buffer += " \n"; + } + break; + + case TDESC_TYPE_UNION: + *m_buffer += " id=\""; + *m_buffer += type->name; + *m_buffer += "\">\n"; + + for (const tdesc_type_field &f : type->fields) + { + *m_buffer += " name; + *m_buffer += "\"/>\n"; + } + break; + + default: + error (_("xml output is not supported type \"%s\"."), + type->name.c_str ()); + } + + *m_buffer += "kind - TDESC_TYPE_STRUCT]; + *m_buffer += ">\n"; +} + +void print_xml_feature::visit (const tdesc_reg *reg) +{ + *m_buffer += "name; + *m_buffer += "\" bitsize=\""; + *m_buffer += std::to_string (reg->bitsize); + *m_buffer += "\" type=\""; + *m_buffer += reg->type; + *m_buffer += "\" regnum=\""; + *m_buffer += std::to_string (reg->target_regnum); + if (reg->group.length () > 0) + { + *m_buffer += "\" group=\""; + *m_buffer += reg->group; + } + *m_buffer += "\"/>\n"; +} diff --git a/gdb/gdbserver/tdesc.c b/gdb/gdbserver/tdesc.c index a96b3f07e7aff81f32a160d6498c8012d18bd0c7..08b896ba790a0bbf7a47f35952555e278830800c 100644 --- a/gdb/gdbserver/tdesc.c +++ b/gdb/gdbserver/tdesc.c @@ -31,7 +31,16 @@ target_desc::~target_desc () } void target_desc::accept (tdesc_element_visitor &v) const -{} +{ +#ifndef IN_PROCESS_AGENT + v.visit_pre (this); + + for (const tdesc_feature_up &feature : features) + feature->accept (v); + + v.visit_post (this); +#endif +} bool target_desc::operator== (const target_desc &other) const { @@ -158,30 +167,9 @@ tdesc_get_features_xml (target_desc *tdesc) if (tdesc->xmltarget == NULL) { - std::string buffer ("@"); - - buffer += ""; - buffer += ""; - buffer += ""; - buffer += tdesc->arch; - buffer += ""; - - if (tdesc->osabi != nullptr) - { - buffer += ""; - buffer += tdesc->osabi; - buffer += ""; - } - - for (const tdesc_feature_up &feature : tdesc->features) - { - buffer += "name; - buffer += "\"/>"; - } - - buffer += ""; - + std::string buffer (""); + print_xml_feature v (&buffer); + tdesc->accept (v); tdesc->xmltarget = xstrdup (buffer.c_str ()); } @@ -213,4 +201,24 @@ type *tdesc_type_vector::make_gdb_type (struct gdbarch *gdbarch) const type *tdesc_type_with_fields::make_gdb_type (struct gdbarch *gdbarch) const { error (_("Cannot create gdbtypes.")); -} \ No newline at end of file +} + +void print_xml_feature::visit_pre (const target_desc *e) +{ +#ifndef IN_PROCESS_AGENT + *m_buffer += "@\n"; + *m_buffer += "\n"; + *m_buffer += "\n"; + *m_buffer += ""; + *m_buffer += e->arch; + *m_buffer += "\n"; + + if (e->osabi != nullptr) + { + *m_buffer += ""; + *m_buffer += e->osabi; + *m_buffer += "\n"; + } +#endif + } + diff --git a/gdb/regformats/regdat.sh b/gdb/regformats/regdat.sh index 8341e11ba76031cc260d60fdc2071bc8a2188f8e..31312fae43dcd369d43e951ffa9e63af4bef450d 100755 --- a/gdb/regformats/regdat.sh +++ b/gdb/regformats/regdat.sh @@ -189,7 +189,7 @@ fi cat <expedite_regs = expedite_regs_${name}; - result->xmltarget = xmltarget_${name}; + tdesc_get_features_xml (result); #endif init_target_desc (result); diff --git a/gdb/target-descriptions.h b/gdb/target-descriptions.h index 759fd34a0fe31f84a8531c799e5a3556e768c604..2a177d5b003c1461d837d22cc4fd5d52c0482ccc 100644 --- a/gdb/target-descriptions.h +++ b/gdb/target-descriptions.h @@ -218,6 +218,8 @@ void tdesc_add_typed_bitfield (tdesc_type_with_fields *type, const char *field_n void tdesc_add_enum_value (tdesc_type_with_fields *type, int value, const char *name); +void debug (const struct target_desc *); + #if GDB_SELF_TEST namespace selftests { diff --git a/gdb/target-descriptions.c b/gdb/target-descriptions.c index cef65a8fe61e22362e0bc4e6dbd7e3c0a0f4d1b4..6787848b287414cd218ad62e274707d5b4b5a368 100644 --- a/gdb/target-descriptions.c +++ b/gdb/target-descriptions.c @@ -86,6 +86,8 @@ struct target_desc : tdesc_element /* The features associated with this target. */ std::vector features; + char *xmltarget = nullptr; + void accept (tdesc_element_visitor &v) const override { v.visit_pre (this); @@ -1622,6 +1624,44 @@ private: int m_next_regnum = 0; }; +void print_xml_feature::visit_pre (const target_desc *e) +{ + *m_buffer += "\n"; + *m_buffer += "\n"; + *m_buffer += "\n"; + *m_buffer += ""; + *m_buffer += tdesc_architecture (e)->printable_name; + *m_buffer += "\n"; + + if (e->osabi != GDB_OSABI_UNKNOWN) + { + *m_buffer += ""; + *m_buffer += gdbarch_osabi_name (tdesc_osabi (e)); + *m_buffer += "\n"; + } +} + +/* 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) +{ + if (tdesc->xmltarget == nullptr) + { + std::string buffer (""); + print_xml_feature v (&buffer); + tdesc->accept (v); + tdesc->xmltarget = xstrdup (buffer.c_str ()); + } + return tdesc->xmltarget; +} + +void debug (const struct target_desc *tdesc) +{ + printf_filtered (_("%s\n"), tdesc_get_features_xml ((target_desc*) tdesc)); +} + static void maint_print_c_tdesc_cmd (const char *args, int from_tty) { @@ -1715,7 +1755,34 @@ maintenance_check_xml_descriptions (const char *dir, int from_tty) = file_read_description_xml (tdesc_xml.data ()); if (tdesc == NULL || *tdesc != *e.second) - failed++; + { + printf_filtered ( _("Descriptions for %s do not match\n"), e.first); + failed++; + continue; + } + + /* Convert both descriptions to xml, and then back again. Confirm all + descriptions are identical. */ + + const char *xml = tdesc_get_features_xml ((target_desc *) tdesc); + const char *xml2 = tdesc_get_features_xml ((target_desc *) e.second); + const target_desc *t_trans = target_read_description_xml_string (xml); + const target_desc *t_trans2 = target_read_description_xml_string (xml2); + + if (t_trans == NULL || t_trans2 == NULL) + { + printf_filtered ( + _("Could not convert descriptions for %s back to xml (%p %p)\n"), + e.first, t_trans, t_trans2); + failed++; + } + else if (*tdesc != *t_trans || *tdesc != *t_trans2) + { + printf_filtered + (_("Translated descriptions for %s do not match (%d %d)\n"), + e.first, *tdesc == *t_trans, *tdesc == *t_trans2); + failed++; + } } printf_filtered (_("Tested %lu XML files, %d failed\n"), (long) selftests::xml_tdesc.size (), failed); diff --git a/gdb/xml-tdesc.h b/gdb/xml-tdesc.h index 8f0679707ad0f1e04d803f955f7fb98b4cc0c8c8..fee60e86dd10e1543b935c3cebce505d4dc828e2 100644 --- a/gdb/xml-tdesc.h +++ b/gdb/xml-tdesc.h @@ -44,5 +44,10 @@ const struct target_desc *target_read_description_xml (struct target_ops *); otherwise. */ gdb::optional target_fetch_description_xml (target_ops *ops); +/* Take an xml string, parse it, and return the parsed description. Does not + handle a string containing includes. */ + +const struct target_desc *target_read_description_xml_string (const char *); + #endif /* XML_TDESC_H */ diff --git a/gdb/xml-tdesc.c b/gdb/xml-tdesc.c index 9190d5f3c64ffdc6d7987d651527f597d695c5a6..f793f07c96847a3d61188fff1c5d63952cc37565 100644 --- a/gdb/xml-tdesc.c +++ b/gdb/xml-tdesc.c @@ -752,3 +752,12 @@ target_fetch_description_xml (struct target_ops *ops) return output; #endif } + +/* Take an xml string, parse it, and return the parsed description. Does not + handle a string containing includes. */ + +const struct target_desc * +target_read_description_xml_string (const char *xml_str) +{ + return tdesc_parse_xml (xml_str, nullptr, nullptr); +}