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/value.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/value.c')
-rw-r--r-- | gdb/value.c | 12 |
1 files changed, 6 insertions, 6 deletions
diff --git a/gdb/value.c b/gdb/value.c index 47e647a..35a7a5c 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -2737,7 +2737,7 @@ value_as_address (struct value *val) LONGEST unpack_long (struct type *type, const gdb_byte *valaddr) { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); + enum bfd_endian byte_order = type_byte_order (type); enum type_code code = TYPE_CODE (type); int len = TYPE_LENGTH (type); int nosign = TYPE_UNSIGNED (type); @@ -3100,7 +3100,7 @@ static LONGEST unpack_bits_as_long (struct type *field_type, const gdb_byte *valaddr, LONGEST bitpos, LONGEST bitsize) { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (field_type)); + enum bfd_endian byte_order = type_byte_order (field_type); ULONGEST val; ULONGEST valmask; int lsbcount; @@ -3209,7 +3209,7 @@ unpack_value_bitfield (struct value *dest_val, int dst_bit_offset; struct type *field_type = value_type (dest_val); - byte_order = gdbarch_byte_order (get_type_arch (field_type)); + byte_order = type_byte_order (field_type); /* First, unpack and sign extend the bitfield as if it was wholly valid. Optimized out/unavailable bits are read as zero, but @@ -3269,7 +3269,7 @@ void modify_field (struct type *type, gdb_byte *addr, LONGEST fieldval, LONGEST bitpos, LONGEST bitsize) { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); + enum bfd_endian byte_order = type_byte_order (type); ULONGEST oword; ULONGEST mask = (ULONGEST) -1 >> (8 * sizeof (ULONGEST) - bitsize); LONGEST bytesize; @@ -3315,7 +3315,7 @@ modify_field (struct type *type, gdb_byte *addr, void pack_long (gdb_byte *buf, struct type *type, LONGEST num) { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); + enum bfd_endian byte_order = type_byte_order (type); LONGEST len; type = check_typedef (type); @@ -3363,7 +3363,7 @@ pack_unsigned_long (gdb_byte *buf, struct type *type, ULONGEST num) type = check_typedef (type); len = TYPE_LENGTH (type); - byte_order = gdbarch_byte_order (get_type_arch (type)); + byte_order = type_byte_order (type); switch (TYPE_CODE (type)) { |