diff options
author | Peeter Joot <peeter.joot@lzlabs.com> | 2017-10-06 16:13:04 -0400 |
---|---|---|
committer | Tom Tromey <tromey@adacore.com> | 2019-11-21 11:48:59 -0700 |
commit | 34877895ca38f74ae31bd65a6916560020d9d62b (patch) | |
tree | c040b456c573621008afce8c847ceb3fa8bb37bd /gdb/dwarf2read.c | |
parent | b52696f9e567da157b152ae641f064507f993969 (diff) | |
download | gdb-34877895ca38f74ae31bd65a6916560020d9d62b.zip gdb-34877895ca38f74ae31bd65a6916560020d9d62b.tar.gz gdb-34877895ca38f74ae31bd65a6916560020d9d62b.tar.bz2 |
Adjust byte order variable display/change if DW_AT_endianity is present.
- Rationale:
It is possible for compilers to indicate the desired byte order
interpretation of scalar variables using the DWARF attribute:
DW_AT_endianity
A type flagged with this variable would typically use one of:
DW_END_big
DW_END_little
which instructs the debugger what the desired byte order interpretation
of the variable should be.
The GCC compiler (as of V6) has a mechanism for setting the desired byte
ordering of the fields within a structure or union. For, example, on a
little endian target, a structure declared as:
struct big {
int v;
short a[4];
} __attribute__( ( scalar_storage_order( "big-endian" ) ) );
could be used to ensure all the structure members have a big-endian
interpretation (the compiler would automatically insert byte swap
instructions before and after respective store and load instructions).
- To reproduce
GCC V8 is required to correctly emit DW_AT_endianity DWARF attributes
in all situations when the scalar_storage_order attribute is used.
A fix for (dwarf endianity instrumentation) for GCC V6-V7 can be found
in the URL field of the following PR:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82509
- Test-case:
A new test case (testsuite/gdb.base/endianity.*) is included with this
patch.
Manual testing for mixed endianity code has also been done with GCC V8.
See:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82509#c4
- Observed vs. expected:
Without this change, using scalar_storage_order that doesn't match the
target, such as
struct otherendian
{
int v;
} __attribute__( ( scalar_storage_order( "big-endian" ) ) );
would behave like the following on a little endian target:
Breakpoint 1 at 0x401135: file endianity.c, line 41.
(gdb) run
Starting program: /home/pjoot/freeware/t/a.out
Missing separate debuginfos, use: debuginfo-install glibc-2.17-292.el7.x86_64
Breakpoint 1, main () at endianity.c:41
41 struct otherendian o = {3};
(gdb) n
43 do_nothing (&o); /* START */
(gdb) p o
$1 = {v = 50331648}
(gdb) p /x
$2 = {v = 0x3000000}
whereas with this gdb enhancement we can access the variable with the user
specified endianity:
Breakpoint 1, main () at endianity.c:41
41 struct otherendian o = {3};
(gdb) p o
$1 = {v = 0}
(gdb) n
43 do_nothing (&o); /* START */
(gdb) p o
$2 = {v = 3}
(gdb) p o.v = 4
$3 = 4
(gdb) p o.v
$4 = 4
(gdb) x/4xb &o.v
0x7fffffffd90c: 0x00 0x00 0x00 0x04
(observe that the 4 byte int variable has a big endian representation in the
hex dump.)
gdb/ChangeLog
2019-11-21 Peeter Joot <peeter.joot@lzlabs.com>
Byte reverse display of variables with DW_END_big, DW_END_little
(DW_AT_endianity) dwarf attributes if different than the native
byte order.
* ada-lang.c (ada_value_binop):
Use type_byte_order instead of gdbarch_byte_order.
* ada-valprint.c (printstr):
(ada_val_print_string):
* ada-lang.c (value_pointer):
(ada_value_binop):
Use type_byte_order instead of gdbarch_byte_order.
* c-lang.c (c_get_string):
Use type_byte_order instead of gdbarch_byte_order.
* c-valprint.c (c_val_print_array):
Use type_byte_order instead of gdbarch_byte_order.
* cp-valprint.c (cp_print_class_member):
Use type_byte_order instead of gdbarch_byte_order.
* dwarf2loc.c (rw_pieced_value):
Use type_byte_order instead of gdbarch_byte_order.
* dwarf2read.c (read_base_type): Handle DW_END_big,
DW_END_little
* f-lang.c (f_get_encoding):
Use type_byte_order instead of gdbarch_byte_order.
* findvar.c (default_read_var_value):
Use type_byte_order instead of gdbarch_byte_order.
* gdbtypes.c (check_types_equal):
Require matching TYPE_ENDIANITY_NOT_DEFAULT if set.
(recursive_dump_type): Print TYPE_ENDIANITY_BIG,
and TYPE_ENDIANITY_LITTLE if set.
(type_byte_order): new function.
* gdbtypes.h (TYPE_ENDIANITY_NOT_DEFAULT): New macro.
(struct main_type) <flag_endianity_not_default>:
New field.
(type_byte_order): New function.
* infcmd.c (default_print_one_register_info):
Use type_byte_order instead of gdbarch_byte_order.
* p-lang.c (pascal_printstr):
Use type_byte_order instead of gdbarch_byte_order.
* p-valprint.c (pascal_val_print):
Use type_byte_order instead of gdbarch_byte_order.
* printcmd.c (print_scalar_formatted):
Use type_byte_order instead of gdbarch_byte_order.
* solib-darwin.c (darwin_current_sos):
Use type_byte_order instead of gdbarch_byte_order.
* solib-svr4.c (solib_svr4_r_ldsomap):
Use type_byte_order instead of gdbarch_byte_order.
* stap-probe.c (stap_modify_semaphore):
Use type_byte_order instead of gdbarch_byte_order.
* target-float.c (target_float_same_format_p):
Use type_byte_order instead of gdbarch_byte_order.
* valarith.c (scalar_binop):
(value_bit_index):
Use type_byte_order instead of gdbarch_byte_order.
* valops.c (value_cast):
Use type_byte_order instead of gdbarch_byte_order.
* valprint.c (generic_emit_char):
(generic_printstr):
(val_print_string):
Use type_byte_order instead of gdbarch_byte_order.
* value.c (unpack_long):
(unpack_bits_as_long):
(unpack_value_bitfield):
(modify_field):
(pack_long):
(pack_unsigned_long):
Use type_byte_order instead of gdbarch_byte_order.
* findvar.c (unsigned_pointer_to_address):
(signed_pointer_to_address):
(unsigned_address_to_pointer):
(address_to_signed_pointer):
(default_read_var_value):
(default_value_from_register):
Use type_byte_order instead of gdbarch_byte_order.
* gnu-v3-abi.c (gnuv3_make_method_ptr):
Use type_byte_order instead of gdbarch_byte_order.
* riscv-tdep.c (riscv_print_one_register_info):
Use type_byte_order instead of gdbarch_byte_order.
gdb/testsuite/ChangeLog
2019-11-21 Peeter Joot <peeter.joot@lzlabs.com>
* gdb.base/endianity.c: New test.
* gdb.base/endianity.exp: New file.
Change-Id: I4bd98c1b4508c2d7c5a5dbb15d7b7b1cb4e667e2
Diffstat (limited to 'gdb/dwarf2read.c')
-rw-r--r-- | gdb/dwarf2read.c | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 9178e0e..d89a541 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -17661,24 +17661,24 @@ 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; + gdbarch *arch; attr = dwarf2_attr (die, DW_AT_encoding, cu); if (attr != nullptr) - { - encoding = DW_UNSND (attr); - } + encoding = DW_UNSND (attr); attr = dwarf2_attr (die, DW_AT_byte_size, cu); if (attr != nullptr) - { - bits = DW_UNSND (attr) * TARGET_CHAR_BIT; - } + bits = DW_UNSND (attr) * TARGET_CHAR_BIT; name = dwarf2_name (die, cu); if (!name) - { - complaint (_("DW_AT_name missing from DW_TAG_base_type")); - } + complaint (_("DW_AT_name missing from DW_TAG_base_type")); + attr = dwarf2_attr (die, DW_AT_endianity, cu); + if (attr) + endianity = DW_UNSND (attr); + arch = get_objfile_arch (objfile); switch (encoding) { case DW_ATE_address: @@ -17729,8 +17729,6 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) break; case DW_ATE_UTF: { - gdbarch *arch = get_objfile_arch (objfile); - if (bits == 16) type = builtin_type (arch)->builtin_char16; else if (bits == 32) @@ -17757,6 +17755,18 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) maybe_set_alignment (cu, die, type); + switch (endianity) + { + case DW_END_big: + if (gdbarch_byte_order (arch) == BFD_ENDIAN_LITTLE) + TYPE_ENDIANITY_NOT_DEFAULT (type) = 1; + break; + case DW_END_little: + if (gdbarch_byte_order (arch) == BFD_ENDIAN_BIG) + TYPE_ENDIANITY_NOT_DEFAULT (type) = 1; + break; + } + return set_die_type (die, type, cu); } |