From: Peeter Joot <peeter.joot@lzlabs.com>
To: "gdb-patches@sourceware.org" <gdb-patches@sourceware.org>
Subject: review request: implementing DW_AT_endianity
Date: Fri, 06 Oct 2017 15:06:00 -0000 [thread overview]
Message-ID: <VI1PR0501MB28618180080787DD22117A459C710@VI1PR0501MB2861.eurprd05.prod.outlook.com> (raw)
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 <stdio.h>
#include <string.h>
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:
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 <peeter.joot@lzlabs.com>
+
+ * 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 <yao.qi@linaro.org>
* 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');
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
next reply other threads:[~2017-10-06 15:06 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-06 15:06 Peeter Joot [this message]
2017-10-06 21:18 ` Peeter Joot
2017-10-08 18:41 ` Simon Marchi
2017-10-09 9:11 ` Peeter Joot
2017-10-09 12:12 ` Simon Marchi
2017-10-10 18:16 ` Peeter Joot
2017-10-10 18:33 ` Simon Marchi
2017-10-10 18:38 ` Peeter Joot
2017-10-10 18:48 ` Simon Marchi
2017-10-10 19:38 ` Peeter Joot
2017-10-10 23:30 ` [PATCH] " Peeter Joot
2017-10-11 2:29 ` Peeter Joot
2017-10-12 20:23 ` Simon Marchi
2018-02-22 17:20 ` Tom Tromey
2018-02-22 17:39 ` Peeter Joot
2019-02-13 13:12 ` Tom Tromey
2019-02-13 14:11 ` Peeter Joot
2019-02-13 14:47 ` Pedro Alves
2019-02-13 16:19 ` Pedro Alves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=VI1PR0501MB28618180080787DD22117A459C710@VI1PR0501MB2861.eurprd05.prod.outlook.com \
--to=peeter.joot@lzlabs.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox