From patchwork Fri Oct 6 15:05:50 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peeter Joot X-Patchwork-Id: 23381 Received: (qmail 71547 invoked by alias); 6 Oct 2017 15:06:07 -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 71535 invoked by uid 89); 6 Oct 2017 15:06:07 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-21.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, HTML_MESSAGE, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS autolearn=ham version=3.3.2 spammy=bv, nv, Mixed, H*c:alternative X-HELO: EUR01-VE1-obe.outbound.protection.outlook.com Received: from mail-ve1eur01on0130.outbound.protection.outlook.com (HELO EUR01-VE1-obe.outbound.protection.outlook.com) (104.47.1.130) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 06 Oct 2017 15:05:55 +0000 Received: from VI1PR0501MB2861.eurprd05.prod.outlook.com (10.172.11.151) by VI1PR0501MB2862.eurprd05.prod.outlook.com (10.172.12.7) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.77.7; Fri, 6 Oct 2017 15:05:50 +0000 Received: from VI1PR0501MB2861.eurprd05.prod.outlook.com ([fe80::1105:ec3d:d331:ab8e]) by VI1PR0501MB2861.eurprd05.prod.outlook.com ([fe80::1105:ec3d:d331:ab8e%16]) with mapi id 15.20.0077.016; Fri, 6 Oct 2017 15:05:50 +0000 From: Peeter Joot To: "gdb-patches@sourceware.org" Subject: review request: implementing DW_AT_endianity Date: Fri, 6 Oct 2017 15:05:50 +0000 Message-ID: authentication-results: spf=none (sender IP is ) smtp.mailfrom=peeter.joot@lzlabs.com; x-ms-publictraffictype: Email x-microsoft-exchange-diagnostics: 1; VI1PR0501MB2862; 6:JBXt7dMfU03gFPAE/JP0uodJdWLos0YrGgQF6yKz/zhRCoG0l0EdjxdfS7sj2nRoD5YT8EHgMepphxDoUpinXnx2VoSMHlchq2d1NPQ1Q4huO1JRfA9lQgunxGhAlmOxLxgVk6eGVv4Aq6hvpIpK9qm6MK9Vnd4d+TM9KskS/aroRI24TKrCFpjG4tbxuJqSUDWvaLpScxed6c+PzLuSBhWewT+a+mXe1g/PR3lOuGt9A8tT+qwHQ0Mq3/EyCKecHevz/h52lL58seqiiDuag4FT9HIA7RcMvRRzcPgGxPwTBvHBkH4lsuRCQeNGijBQm47teIPfeiyoMtMhvOr3pA==; 5:Bwdm1neMTJyfqJAdLg2BpMehdMKwlgLg11IRDSStCszbeZxKlrC5spq2InnGDBkmDCWgjUhpiwTkGUReA9Mo7K1++a4h/ykGJ625mQkr99mTx7cHeHRxEInwbGQ1ZbgA6JbCgu5ZGqj1+YFihH/FdA==; 24:QSyTLNJhpnnAKB0Jb/Qu139Kj3FRuSgrCwYhxovWHmpEbSzFhVGCo6gtgp6Z6HSgrMeh8jM0CtwtMFwLWIlYGx+dsdLC+jbBYilRYzNeFRM=; 7:Z4SBDPn+Wfo9ww55fHP4DtZp+WqcEiRON/jXSbD8raHsyA1wINdMqAWVWmvo2x9phRcczg+MnoiE50XXd+NCyZXX85RIWzjEAtF8EXJoXBo4gowoLgjIQoSGDnI1sAJtOIlmVFBwtGKYu6/5V/sK9JGRJ6BY2xJNSAR25zbqTI+/Gvwj9JF3ItZqFPHET8Dna4VK2Nwd4yBMyIlrnbZ4dlB6Sydt6v67ibGOIhkUNRo= x-ms-exchange-antispam-srfa-diagnostics: SSOS; x-ms-office365-filtering-correlation-id: 1d779281-a054-47d7-8eaa-08d50ccbbb6c x-microsoft-antispam: UriScan:; BCL:0; PCL:0; RULEID:(22001)(2017030254152)(2017052603199)(201703131423075)(201703031133081)(201702281549075); SRVR:VI1PR0501MB2862; x-ms-traffictypediagnostic: VI1PR0501MB2862: x-exchange-antispam-report-test: UriScan:(788757137089); x-microsoft-antispam-prvs: x-exchange-antispam-report-cfa-test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(5005006)(8121501046)(93006095)(93001095)(100000703101)(100105400095)(3002001)(10201501046)(6041248)(20161123562025)(20161123558100)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(20161123555025)(20161123560025)(20161123564025)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:VI1PR0501MB2862; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:VI1PR0501MB2862; x-forefront-prvs: 0452022BE1 x-forefront-antispam-report: SFV:NSPM; SFS:(10019020)(6009001)(376002)(346002)(377424004)(189002)(54534003)(199003)(5250100002)(74316002)(189998001)(86362001)(33656002)(50986999)(2906002)(2900100001)(81156014)(66066001)(81166006)(3280700002)(97736004)(6436002)(8936002)(7736002)(6506006)(8676002)(54896002)(19627405001)(7696004)(99286003)(9686003)(316002)(3846002)(105586002)(14454004)(55016002)(2501003)(5640700003)(25786009)(3660700001)(2351001)(6116002)(102836003)(54356999)(5660300001)(101416001)(53936002)(68736007)(478600001)(6916009)(106356001)(6606003); DIR:OUT; SFP:1102; SCL:1; SRVR:VI1PR0501MB2862; H:VI1PR0501MB2861.eurprd05.prod.outlook.com; FPR:; SPF:None; PTR:InfoNoRecords; MX:1; A:1; LANG:en; received-spf: None (protection.outlook.com: lzlabs.com does not designate permitted sender hosts) spamdiagnosticoutput: 1:99 spamdiagnosticmetadata: NSPM MIME-Version: 1.0 X-OriginatorOrg: lzlabs.com X-MS-Exchange-CrossTenant-originalarrivaltime: 06 Oct 2017 15:05:50.3735 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: be5a2f53-aa84-427c-8fbd-c2d71558a7a8 X-MS-Exchange-Transport-CrossTenantHeadersStamped: VI1PR0501MB2862 I've implemented support in gdb for DW_AT_endianity, DW_END_bigendian, and DW_END_littleendian, and would like to ask for gdb community review of this change. Purpose: gcc6+ supports mixed endian attributes on structures and unions, and flags these dwarf instrumentation of these structure members with DW_END_... attributes. As intel appears to have introduced these dwarf flags into the standard, I expect their compiler and debugger also supports them. However, gdb does not. The following example, compiled on a little endian system, is an example of this attribute use: #include #include struct big { int v; short a[4]; } __attribute__( ( scalar_storage_order( "big-endian" ) ) ); struct little { int v; short a[4]; } __attribute__( ( scalar_storage_order( "little-endian" ) ) ); struct native { int v; short a[4]; }; int main() { struct big b = {3, {1, 2, 3, 4}}; struct native n = {3, {1, 2, 3, 4}}; struct little l = {3, {1, 2, 3, 4}}; int cb = memcmp( &b, &n, sizeof( b ) ); int cl = memcmp( &l, &n, sizeof( l ) ); printf( "%d %d %d: big %s native. little %s native\n", b.v, n.v, l.v, cb == 0 ? "==" : "!=", cl == 0 ? "==" : "!=" ); return 0; } Running this produces the expected result, and the endianness of the underlying stores can be seen in a debugger session: Breakpoint 1, main () at test.c:20 20 struct big b = {3, {1, 2, 3, 4}}; (gdb) n 21 struct native n = {3, {1, 2, 3, 4}}; (gdb) n 22 struct little l = {3, {1, 2, 3, 4}}; (gdb) n 23 int cb = memcmp( &b, &n, sizeof( b ) ); (gdb) p b $1 = {v = 50331648, a = {256, 512, 768, 1024}} (gdb) p n $2 = {v = 3, a = {1, 2, 3, 4}} (gdb) p l $3 = {v = 3, a = {1, 2, 3, 4}} (gdb) x/4x &b 0x7fffffffd96c: 0x03000000 0x02000100 0x04000300 0x00000000 (gdb) x/4x &l 0x7fffffffd954: 0x00000003 0x00020001 0x00040003 0x00000003 (gdb) x/4x &n 0x7fffffffd960: 0x00000003 0x00020001 0x00040003 0x03000000 (gdb) n 24 int cl = memcmp( &l, &n, sizeof( l ) ); (gdb) 26 printf( "%d %d %d: big %s native. little %s native\n", b.v, n.v, l.v, (gdb) n 3 3 3: big != native. little == native 28 return 0; This debugger session also shows that gdb currently ignores the DW_END_bigendian (and littleendian) attributes, showing the internal representation of the data instead of what the values that memory represents. It turns out that propagating the DW_AT_endianity dwarf attributes to the gdb print_scalar_formatted function is fairly straightforward, which allows gdb to display the results in a user-friendly way regardless of the endian attributes: On behalf of my employer (LzLabs), I would like to contribute this change to to the gdb project. For a small change like this, it is not clear FSF copyright assignment is required, as I see the following in your CONTRIBUTIONS document: "Small changes can be accepted without a copyright assignment form on file.". What counts as small? If assignment is required, I have approval from company management and legal to formally go through that process. Before figuring out how that assignment process works, I wanted to first ensure the changes I've made would be acceptable for contribution, and make any review driven updates required. --- Peeter diff --git a/binutils/dwarf.c b/binutils/dwarf.c index 91f95ff..e79fd5e 100644 --- a/binutils/dwarf.c +++ b/binutils/dwarf.c @@ -2283,6 +2283,17 @@ read_and_display_attr_value (unsigned long attribute, } break; + case DW_AT_endianity: + printf ("\t"); + switch (uvalue) + { + case DW_END_default: printf ("(default)"); break; + case DW_END_big: printf ("(big)"); break; + case DW_END_little: printf ("(little)"); break; + default: printf (_("(unknown endianity)")); break; + } + break; + case DW_AT_virtuality: printf ("\t"); switch (uvalue) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 18224e0..66a8eaf 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,19 @@ +2017-10-06 Peeter Joot + + * gdb/gdbtypes.h (global scope): define TYPE_ENDIANITY_BIG, + TYPE_ENDIANITY_LITTLE. + * binutils/dwarf.c (read_and_display_attr_value): Handle + DW_AT_endianity, DW_END_default, DW_END_big, DW_END_little + * gdb/dwarf2read.c (read_base_type): Handle DW_END_big, DW_END_little + * gdb/gdbtypes.c (check_types_equal): Require matching + TYPE_ENDIANITY_BIG, and TYPE_ENDIANITY_LITTLE if set. + (recursive_dump_type): Print TYPE_ENDIANITY_BIG, and + TYPE_ENDIANITY_LITTLE if set. + (struct main_type): Add flag_endianity_big, flag_endianity_little + * gdb/printcmd.c (print_scalar_formatted): Use compiler supplied + endianness instead of arch endianness if TYPE_ENDIANITY_BIG or + TYPE_ENDIANITY_LITTLE is set. + 2017-10-06 Yao Qi * Makefile.in (ALL_64_TARGET_OBS): Replace aarch64-insn.o with diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 1b15adc..fa2889b 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -15234,6 +15234,7 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) struct type *type; struct attribute *attr; int encoding = 0, bits = 0; + int endianity = 0; const char *name; attr = dwarf2_attr (die, DW_AT_encoding, cu); @@ -15330,6 +15331,21 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) if (name && strcmp (name, "char") == 0) TYPE_NOSIGN (type) = 1; + attr = dwarf2_attr (die, DW_AT_endianity, cu); + if ( attr ) + { + endianity = DW_UNSND (attr); + switch (endianity) + { + case DW_END_big: + TYPE_ENDIANITY_BIG (type) = 1; + break; + case DW_END_little: + TYPE_ENDIANITY_LITTLE (type) = 1; + break; + } + } + return set_die_type (die, type, cu); } diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index 73d4453..43f553b 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -3423,6 +3423,8 @@ check_types_equal (struct type *type1, struct type *type2, || TYPE_LENGTH (type1) != TYPE_LENGTH (type2) || TYPE_UNSIGNED (type1) != TYPE_UNSIGNED (type2) || TYPE_NOSIGN (type1) != TYPE_NOSIGN (type2) + || TYPE_ENDIANITY_BIG (type1) != TYPE_ENDIANITY_BIG (type2) + || TYPE_ENDIANITY_LITTLE (type1) != TYPE_ENDIANITY_LITTLE (type2) || TYPE_VARARGS (type1) != TYPE_VARARGS (type2) || TYPE_VECTOR (type1) != TYPE_VECTOR (type2) || TYPE_NOTTEXT (type1) != TYPE_NOTTEXT (type2) @@ -4460,6 +4462,14 @@ recursive_dump_type (struct type *type, int spaces) { puts_filtered (" TYPE_NOSIGN"); } + if (TYPE_ENDIANITY_BIG (type)) + { + puts_filtered (" TYPE_ENDIANITY_BIG"); + } + if (TYPE_ENDIANITY_LITTLE (type)) + { + puts_filtered (" TYPE_ENDIANITY_LITTLE"); + } if (TYPE_STUB (type)) { puts_filtered (" TYPE_STUB"); diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 009cea9..074aa2c 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -210,6 +210,16 @@ DEF_ENUM_FLAGS_TYPE (enum type_instance_flag_value, type_instance_flags); #define TYPE_NOSIGN(t) (TYPE_MAIN_TYPE (t)->flag_nosign) +/* * Mixed endian archetectures can supply dwarf instrumentation + * that indicates the desired endian interpretation of the variable. + * This indicates that the interpretation should be big-endian + * even if the cpu is running in little endian mode. */ +#define TYPE_ENDIANITY_BIG(t) (TYPE_MAIN_TYPE (t)->flag_endianity_big) + +/* * The type has a little endian interpretation even if the cpu + * is running in big endian mode. */ +#define TYPE_ENDIANITY_LITTLE(t) (TYPE_MAIN_TYPE (t)->flag_endianity_little) + /* * This appears in a type's flags word if it is a stub type (e.g., if someone referenced a type that wasn't defined in a source file via (struct sir_not_appearing_in_this_film *)). */ @@ -616,6 +626,8 @@ struct main_type unsigned int flag_gnu_ifunc : 1; unsigned int flag_fixed_instance : 1; unsigned int flag_objfile_owned : 1; + unsigned int flag_endianity_big : 1; + unsigned int flag_endianity_little : 1; /* * True if this type was declared with "class" rather than "struct". */ diff --git a/gdb/printcmd.c b/gdb/printcmd.c index a8743f1..e714283 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -356,6 +356,15 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type, unsigned int len = TYPE_LENGTH (type); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + if ( TYPE_ENDIANITY_BIG (type) ) + { + byte_order = BFD_ENDIAN_BIG; + } + if ( TYPE_ENDIANITY_LITTLE (type) ) + { + byte_order = BFD_ENDIAN_LITTLE; + } + /* String printing should go through val_print_scalar_formatted. */ gdb_assert (options->format != 's');