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 | |
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')
-rw-r--r-- | gdb/ChangeLog | 79 | ||||
-rw-r--r-- | gdb/ada-lang.c | 4 | ||||
-rw-r--r-- | gdb/ada-valprint.c | 4 | ||||
-rw-r--r-- | gdb/c-lang.c | 2 | ||||
-rw-r--r-- | gdb/c-valprint.c | 3 | ||||
-rw-r--r-- | gdb/cp-valprint.c | 2 | ||||
-rw-r--r-- | gdb/dwarf2loc.c | 2 | ||||
-rw-r--r-- | gdb/dwarf2read.c | 32 | ||||
-rw-r--r-- | gdb/f-lang.c | 2 | ||||
-rw-r--r-- | gdb/findvar.c | 12 | ||||
-rw-r--r-- | gdb/gdbtypes.c | 23 | ||||
-rw-r--r-- | gdb/gdbtypes.h | 13 | ||||
-rw-r--r-- | gdb/gnu-v3-abi.c | 2 | ||||
-rw-r--r-- | gdb/infcmd.c | 2 | ||||
-rw-r--r-- | gdb/p-lang.c | 2 | ||||
-rw-r--r-- | gdb/p-valprint.c | 2 | ||||
-rw-r--r-- | gdb/printcmd.c | 2 | ||||
-rw-r--r-- | gdb/riscv-tdep.c | 2 | ||||
-rw-r--r-- | gdb/solib-darwin.c | 2 | ||||
-rw-r--r-- | gdb/solib-svr4.c | 2 | ||||
-rw-r--r-- | gdb/stap-probe.c | 7 | ||||
-rw-r--r-- | gdb/target-float.c | 6 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/endianity.c | 45 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/endianity.exp | 40 | ||||
-rw-r--r-- | gdb/valarith.c | 10 | ||||
-rw-r--r-- | gdb/valops.c | 2 | ||||
-rw-r--r-- | gdb/valprint.c | 6 | ||||
-rw-r--r-- | gdb/value.c | 12 |
29 files changed, 269 insertions, 58 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 57e8f6b..0249048 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,82 @@ +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. + 2019-11-21 Simon Marchi <simon.marchi@polymtl.ca> * top.c (current_ui_gdb_stdout_ptr): Spell out by hand. diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c index 2935df5..36001ef 100644 --- a/gdb/ada-lang.c +++ b/gdb/ada-lang.c @@ -4546,7 +4546,7 @@ value_pointer (struct value *value, struct type *type) addr = value_address (value); gdbarch_address_to_pointer (gdbarch, type, buf, addr); - addr = extract_unsigned_integer (buf, len, gdbarch_byte_order (gdbarch)); + addr = extract_unsigned_integer (buf, len, type_byte_order (type)); return addr; } @@ -9678,7 +9678,7 @@ ada_value_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) val = allocate_value (type1); store_unsigned_integer (value_contents_raw (val), TYPE_LENGTH (value_type (val)), - gdbarch_byte_order (get_type_arch (type1)), v); + type_byte_order (type1), v); return val; } diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c index 5ab0365..4bb9247 100644 --- a/gdb/ada-valprint.c +++ b/gdb/ada-valprint.c @@ -476,7 +476,7 @@ printstr (struct ui_file *stream, struct type *elttype, const gdb_byte *string, unsigned int length, int force_ellipses, int type_len, const struct value_print_options *options) { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (elttype)); + enum bfd_endian byte_order = type_byte_order (elttype); unsigned int i; unsigned int things_printed = 0; int in_quotes = 0; @@ -719,7 +719,7 @@ ada_val_print_string (struct type *type, const gdb_byte *valaddr, struct value *original_value, const struct value_print_options *options) { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); + enum bfd_endian byte_order = type_byte_order (type); struct type *elttype = TYPE_TARGET_TYPE (type); unsigned int eltlen; unsigned int len; diff --git a/gdb/c-lang.c b/gdb/c-lang.c index 74e3f73..1de44f7 100644 --- a/gdb/c-lang.c +++ b/gdb/c-lang.c @@ -245,7 +245,7 @@ c_get_string (struct value *value, gdb::unique_xmalloc_ptr<gdb_byte> *buffer, struct type *element_type = TYPE_TARGET_TYPE (type); int req_length = *length; enum bfd_endian byte_order - = gdbarch_byte_order (get_type_arch (type)); + = type_byte_order (type); if (element_type == NULL) goto error; diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c index c4306f1..58675f6 100644 --- a/gdb/c-valprint.c +++ b/gdb/c-valprint.c @@ -247,8 +247,7 @@ c_val_print_array (struct type *type, const gdb_byte *valaddr, { LONGEST low_bound, high_bound; int eltlen, len; - struct gdbarch *gdbarch = get_type_arch (type); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + enum bfd_endian byte_order = type_byte_order (type); unsigned int i = 0; /* Number of characters printed. */ if (!get_array_bounds (type, &low_bound, &high_bound)) diff --git a/gdb/cp-valprint.c b/gdb/cp-valprint.c index 04be4dc..e445d42 100644 --- a/gdb/cp-valprint.c +++ b/gdb/cp-valprint.c @@ -740,7 +740,7 @@ void cp_print_class_member (const gdb_byte *valaddr, struct type *type, struct ui_file *stream, const char *prefix) { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); + enum bfd_endian byte_order = type_byte_order (type); /* VAL is a byte offset into the structure type SELF_TYPE. Find the name of the field for that offset and diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index c8ba029..e25ee66 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -1601,7 +1601,7 @@ rw_pieced_value (struct value *v, struct value *from) bits_to_skip += (8 * value_offset (value_parent (v)) + value_bitpos (v)); if (from != NULL - && (gdbarch_byte_order (get_type_arch (value_type (from))) + && (type_byte_order (value_type (from)) == BFD_ENDIAN_BIG)) { /* Use the least significant bits of FROM. */ 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); } diff --git a/gdb/f-lang.c b/gdb/f-lang.c index 7f241c6..fd4ad0f 100644 --- a/gdb/f-lang.c +++ b/gdb/f-lang.c @@ -59,7 +59,7 @@ f_get_encoding (struct type *type) encoding = target_charset (get_type_arch (type)); break; case 4: - if (gdbarch_byte_order (get_type_arch (type)) == BFD_ENDIAN_BIG) + if (type_byte_order (type) == BFD_ENDIAN_BIG) encoding = "UTF-32BE"; else encoding = "UTF-32LE"; diff --git a/gdb/findvar.c b/gdb/findvar.c index bbfd689..95cc58d 100644 --- a/gdb/findvar.c +++ b/gdb/findvar.c @@ -309,7 +309,7 @@ CORE_ADDR unsigned_pointer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf) { - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + enum bfd_endian byte_order = type_byte_order (type); return extract_unsigned_integer (buf, TYPE_LENGTH (type), byte_order); } @@ -318,7 +318,7 @@ CORE_ADDR signed_pointer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf) { - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + enum bfd_endian byte_order = type_byte_order (type); return extract_signed_integer (buf, TYPE_LENGTH (type), byte_order); } @@ -329,7 +329,7 @@ void unsigned_address_to_pointer (struct gdbarch *gdbarch, struct type *type, gdb_byte *buf, CORE_ADDR addr) { - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + enum bfd_endian byte_order = type_byte_order (type); store_unsigned_integer (buf, TYPE_LENGTH (type), byte_order, addr); } @@ -338,7 +338,7 @@ void address_to_signed_pointer (struct gdbarch *gdbarch, struct type *type, gdb_byte *buf, CORE_ADDR addr) { - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + enum bfd_endian byte_order = type_byte_order (type); store_signed_integer (buf, TYPE_LENGTH (type), byte_order, addr); } @@ -620,7 +620,7 @@ default_read_var_value (struct symbol *var, const struct block *var_block, /* Put the constant back in target format. */ v = allocate_value (type); store_signed_integer (value_contents_raw (v), TYPE_LENGTH (type), - gdbarch_byte_order (get_type_arch (type)), + type_byte_order (type), (LONGEST) SYMBOL_VALUE (var)); VALUE_LVAL (v) = not_lval; return v; @@ -840,7 +840,7 @@ default_value_from_register (struct gdbarch *gdbarch, struct type *type, an integral number of registers. Otherwise, you need to do some fiddling with the last register copied here for little endian machines. */ - if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG + if (type_byte_order (type) == BFD_ENDIAN_BIG && len < register_size (gdbarch, regnum)) /* Big-endian, and we want less than full size. */ set_value_offset (value, register_size (gdbarch, regnum) - len); diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index fd1c765..31c1a7b 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -3616,6 +3616,7 @@ 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_NOT_DEFAULT (type1) != TYPE_ENDIANITY_NOT_DEFAULT (type2) || TYPE_VARARGS (type1) != TYPE_VARARGS (type2) || TYPE_VECTOR (type1) != TYPE_VECTOR (type2) || TYPE_NOTTEXT (type1) != TYPE_NOTTEXT (type2) @@ -4669,6 +4670,10 @@ recursive_dump_type (struct type *type, int spaces) { puts_filtered (" TYPE_NOSIGN"); } + if (TYPE_ENDIANITY_NOT_DEFAULT (type)) + { + puts_filtered (" TYPE_ENDIANITY_NOT_DEFAULT"); + } if (TYPE_STUB (type)) { puts_filtered (" TYPE_STUB"); @@ -5617,3 +5622,21 @@ _initialize_gdbtypes (void) show_strict_type_checking, &setchecklist, &showchecklist); } + +/* See gdbtypes.h. */ +enum bfd_endian +type_byte_order (const struct type *type) +{ + bfd_endian byteorder = gdbarch_byte_order (get_type_arch (type)); + if (TYPE_ENDIANITY_NOT_DEFAULT (type)) + { + if (byteorder == BFD_ENDIAN_BIG) + return BFD_ENDIAN_LITTLE; + else if (byteorder == BFD_ENDIAN_LITTLE) + return BFD_ENDIAN_BIG; + else + return BFD_ENDIAN_UNKNOWN; + } + + return byteorder; +} diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index 6d6ff59..8fc770c 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -219,6 +219,12 @@ DEF_ENUM_FLAGS_TYPE (enum type_instance_flag_value, type_instance_flags); #define TYPE_NOSIGN(t) (TYPE_MAIN_TYPE (t)->flag_nosign) +/* * A compiler may supply dwarf instrumentation + that indicates the desired endian interpretation of the variable + differs from the native endian representation. */ + +#define TYPE_ENDIANITY_NOT_DEFAULT(t) (TYPE_MAIN_TYPE (t)->flag_endianity_not_default) + /* * 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 *)). */ @@ -701,6 +707,7 @@ 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_not_default : 1; /* * True if this type was declared with "class" rather than "struct". */ @@ -2146,6 +2153,12 @@ extern int type_not_allocated (const struct type *type); extern int type_not_associated (const struct type *type); +/* * When the type includes explicit byte ordering, return that. + Otherwise, the byte ordering from gdbarch_byte_order for + get_type_arch is returned. */ + +extern enum bfd_endian type_byte_order (const struct type *type); + /* A flag to enable printing of debugging information of C++ overloading. */ diff --git a/gdb/gnu-v3-abi.c b/gdb/gnu-v3-abi.c index 2533a94..2a5486c 100644 --- a/gdb/gnu-v3-abi.c +++ b/gdb/gnu-v3-abi.c @@ -678,7 +678,7 @@ gnuv3_make_method_ptr (struct type *type, gdb_byte *contents, { struct gdbarch *gdbarch = get_type_arch (type); int size = TYPE_LENGTH (builtin_type (gdbarch)->builtin_data_ptr); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + enum bfd_endian byte_order = type_byte_order (type); /* FIXME drow/2006-12-24: The adjustment of "this" is currently always zero, since the method pointer is of the correct type. diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 5ca9933..eb18efa 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -2216,7 +2216,7 @@ default_print_one_register_info (struct ui_file *file, { struct value_print_options opts; const gdb_byte *valaddr = value_contents_for_printing (val); - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (regtype)); + enum bfd_endian byte_order = type_byte_order (regtype); get_user_print_options (&opts); opts.deref_ref = 1; diff --git a/gdb/p-lang.c b/gdb/p-lang.c index 0cf1c6c..33cb6e6 100644 --- a/gdb/p-lang.c +++ b/gdb/p-lang.c @@ -230,7 +230,7 @@ pascal_printstr (struct ui_file *stream, struct type *type, const char *encoding, int force_ellipses, const struct value_print_options *options) { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); + enum bfd_endian byte_order = type_byte_order (type); unsigned int i; unsigned int things_printed = 0; int in_quotes = 0; diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c index 10612f3..c465d14 100644 --- a/gdb/p-valprint.c +++ b/gdb/p-valprint.c @@ -67,7 +67,7 @@ pascal_val_print (struct type *type, const struct value_print_options *options) { struct gdbarch *gdbarch = get_type_arch (type); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + enum bfd_endian byte_order = type_byte_order (type); unsigned int i = 0; /* Number of characters printed */ unsigned len; struct type *elttype; diff --git a/gdb/printcmd.c b/gdb/printcmd.c index 323a5d0..0251d46 100644 --- a/gdb/printcmd.c +++ b/gdb/printcmd.c @@ -356,7 +356,7 @@ print_scalar_formatted (const gdb_byte *valaddr, struct type *type, { struct gdbarch *gdbarch = get_type_arch (type); unsigned int len = TYPE_LENGTH (type); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + enum bfd_endian byte_order = type_byte_order (type); /* String printing should go through val_print_scalar_formatted. */ gdb_assert (options->format != 's'); diff --git a/gdb/riscv-tdep.c b/gdb/riscv-tdep.c index 810b834..d262b7d 100644 --- a/gdb/riscv-tdep.c +++ b/gdb/riscv-tdep.c @@ -688,7 +688,7 @@ riscv_print_one_register_info (struct gdbarch *gdbarch, { struct value_print_options opts; const gdb_byte *valaddr = value_contents_for_printing (val); - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (regtype)); + enum bfd_endian byte_order = type_byte_order (regtype); get_user_print_options (&opts); opts.deref_ref = 1; diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c index 286e385..969bfd5 100644 --- a/gdb/solib-darwin.c +++ b/gdb/solib-darwin.c @@ -223,7 +223,7 @@ static struct so_list * darwin_current_sos (void) { struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; - enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); + enum bfd_endian byte_order = type_byte_order (ptr_type); int ptr_len = TYPE_LENGTH (ptr_type); unsigned int image_info_size; struct so_list *head = NULL; diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 27299ff..de76557 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -897,7 +897,7 @@ solib_svr4_r_ldsomap (struct svr4_info *info) { struct link_map_offsets *lmo = svr4_fetch_link_map_offsets (); struct type *ptr_type = builtin_type (target_gdbarch ())->builtin_data_ptr; - enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ()); + enum bfd_endian byte_order = type_byte_order (ptr_type); ULONGEST version = 0; try diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c index ea206cb..ba92779 100644 --- a/gdb/stap-probe.c +++ b/gdb/stap-probe.c @@ -1435,8 +1435,8 @@ stap_modify_semaphore (CORE_ADDR address, int set, struct gdbarch *gdbarch) return; } - value = extract_unsigned_integer (bytes, TYPE_LENGTH (type), - gdbarch_byte_order (gdbarch)); + enum bfd_endian byte_order = type_byte_order (type); + value = extract_unsigned_integer (bytes, TYPE_LENGTH (type), byte_order); /* Note that we explicitly don't worry about overflow or underflow. */ if (set) @@ -1444,8 +1444,7 @@ stap_modify_semaphore (CORE_ADDR address, int set, struct gdbarch *gdbarch) else --value; - store_unsigned_integer (bytes, TYPE_LENGTH (type), - gdbarch_byte_order (gdbarch), value); + store_unsigned_integer (bytes, TYPE_LENGTH (type), byte_order, value); if (target_write_memory (address, bytes, TYPE_LENGTH (type)) != 0) warning (_("Could not write the value of a SystemTap semaphore.")); diff --git a/gdb/target-float.c b/gdb/target-float.c index 4ef3505..caa6943 100644 --- a/gdb/target-float.c +++ b/gdb/target-float.c @@ -1753,7 +1753,7 @@ match_endianness (const gdb_byte *from, const struct type *type, gdb_byte *to) #define OPPOSITE_BYTE_ORDER BFD_ENDIAN_BIG #endif - if (gdbarch_byte_order (get_type_arch (type)) == OPPOSITE_BYTE_ORDER) + if (type_byte_order (type) == OPPOSITE_BYTE_ORDER) for (i = 0; i < len; i++) to[i] = from[len - i - 1]; else @@ -2160,8 +2160,8 @@ target_float_same_format_p (const struct type *type1, case TYPE_CODE_DECFLOAT: return (TYPE_LENGTH (type1) == TYPE_LENGTH (type2) - && (gdbarch_byte_order (get_type_arch (type1)) - == gdbarch_byte_order (get_type_arch (type2)))); + && (type_byte_order (type1) + == type_byte_order (type2))); default: gdb_assert_not_reached ("unexpected type code"); diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 1685525..d4c42bd 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-11-21 Peeter Joot <peeter.joot@lzlabs.com> + + * gdb.base/endianity.c: New test. + * gdb.base/endianity.exp: New file. + 2019-11-21 Lukas Durfina <ldurfina@tachyum.com> * gdb.arch/amd64-eval.exp: Skip test if target is not x86-64. diff --git a/gdb/testsuite/gdb.base/endianity.c b/gdb/testsuite/gdb.base/endianity.c new file mode 100644 index 0000000..5ab090d --- /dev/null +++ b/gdb/testsuite/gdb.base/endianity.c @@ -0,0 +1,45 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2019 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/* This tests the handling of dwarf attributes: + DW_AT_endianity, DW_END_big, and DW_END_little. */ +struct otherendian +{ + int v; + short w; +} +#if defined __GNUC__ && (__GNUC__ >= 6) +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +__attribute__( ( scalar_storage_order( "big-endian" ) ) ) +#else +__attribute__( ( scalar_storage_order( "little-endian" ) ) ) +#endif +#endif +; + +void +do_nothing (struct otherendian *c) +{ +} + +int +main (void) +{ + struct otherendian o = {3,2}; + + do_nothing (&o); /* START */ +} diff --git a/gdb/testsuite/gdb.base/endianity.exp b/gdb/testsuite/gdb.base/endianity.exp new file mode 100644 index 0000000..80df012 --- /dev/null +++ b/gdb/testsuite/gdb.base/endianity.exp @@ -0,0 +1,40 @@ +# Copyright 2019 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +standard_testfile .c + +if { [prepare_for_testing "failed to prepare" ${testfile} ${srcfile}] } { + return -1 +} + +set bp_location [gdb_get_line_number "START"] +if ![runto "endianity.c:$bp_location" ] then { + fail "couldn't run to start" + return -1 +} + +gdb_test "print o" "= {v = 3, w = 2}" "print o before assignment" + +gdb_test "print o.v = 4" "= 4" +gdb_test "print o.w = 3" "= 3" + +# scalar_storage_order requires gcc >= 6 +if { ([test_compiler_info {gcc-[0-5]-*}] || ![test_compiler_info gcc*]) } { + setup_xfail "*-*-*" +} +gdb_test "x/x &o.v" "0x04000000" +gdb_test "x/xh &o.w" "0x0300" + +gdb_test "print o" "= {v = 4, w = 3}" "print o after assignment" diff --git a/gdb/valarith.c b/gdb/valarith.c index 7f1b24f..ea999b5 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -988,7 +988,7 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) val = allocate_value (result_type); store_signed_integer (value_contents_raw (val), TYPE_LENGTH (result_type), - gdbarch_byte_order (get_type_arch (result_type)), + type_byte_order (result_type), v); } else @@ -1136,8 +1136,7 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) val = allocate_value (result_type); store_unsigned_integer (value_contents_raw (val), TYPE_LENGTH (value_type (val)), - gdbarch_byte_order - (get_type_arch (result_type)), + type_byte_order (result_type), v); } else @@ -1266,8 +1265,7 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op) val = allocate_value (result_type); store_signed_integer (value_contents_raw (val), TYPE_LENGTH (value_type (val)), - gdbarch_byte_order - (get_type_arch (result_type)), + type_byte_order (result_type), v); } } @@ -1712,7 +1710,7 @@ value_bit_index (struct type *type, const gdb_byte *valaddr, int index) return -1; rel_index = index - low_bound; word = extract_unsigned_integer (valaddr + (rel_index / TARGET_CHAR_BIT), 1, - gdbarch_byte_order (gdbarch)); + type_byte_order (type)); rel_index %= TARGET_CHAR_BIT; if (gdbarch_bits_big_endian (gdbarch)) rel_index = TARGET_CHAR_BIT - 1 - rel_index; diff --git a/gdb/valops.c b/gdb/valops.c index bfdd781..4597e99 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -483,7 +483,7 @@ value_cast (struct type *type, struct value *arg2) if (code2 == TYPE_CODE_PTR) longest = extract_unsigned_integer (value_contents (arg2), TYPE_LENGTH (type2), - gdbarch_byte_order (get_type_arch (type2))); + type_byte_order (type2)); else longest = value_as_long (arg2); return value_from_longest (to_type, convert_to_boolean ? diff --git a/gdb/valprint.c b/gdb/valprint.c index e0eb8e1..ced0dbc 100644 --- a/gdb/valprint.c +++ b/gdb/valprint.c @@ -2402,7 +2402,7 @@ generic_emit_char (int c, struct type *type, struct ui_file *stream, int quoter, const char *encoding) { enum bfd_endian byte_order - = gdbarch_byte_order (get_type_arch (type)); + = type_byte_order (type); gdb_byte *c_buf; int need_escape = 0; @@ -2722,7 +2722,7 @@ generic_printstr (struct ui_file *stream, struct type *type, int quote_char, int c_style_terminator, const struct value_print_options *options) { - enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type)); + enum bfd_endian byte_order = type_byte_order (type); unsigned int i; int width = TYPE_LENGTH (type); int finished = 0; @@ -2834,7 +2834,7 @@ val_print_string (struct type *elttype, const char *encoding, int bytes_read; gdb::unique_xmalloc_ptr<gdb_byte> buffer; /* Dynamically growable fetch buffer. */ struct gdbarch *gdbarch = get_type_arch (elttype); - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + enum bfd_endian byte_order = type_byte_order (elttype); int width = TYPE_LENGTH (elttype); /* First we need to figure out the limit on the number of characters we are 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)) { |