]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
Adjust byte order variable display/change if DW_AT_endianity is present.
authorPeeter Joot <peeter.joot@lzlabs.com>
Fri, 6 Oct 2017 20:13:04 +0000 (16:13 -0400)
committerTom Tromey <tromey@adacore.com>
Thu, 21 Nov 2019 18:48:59 +0000 (11:48 -0700)
- 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

29 files changed:
gdb/ChangeLog
gdb/ada-lang.c
gdb/ada-valprint.c
gdb/c-lang.c
gdb/c-valprint.c
gdb/cp-valprint.c
gdb/dwarf2loc.c
gdb/dwarf2read.c
gdb/f-lang.c
gdb/findvar.c
gdb/gdbtypes.c
gdb/gdbtypes.h
gdb/gnu-v3-abi.c
gdb/infcmd.c
gdb/p-lang.c
gdb/p-valprint.c
gdb/printcmd.c
gdb/riscv-tdep.c
gdb/solib-darwin.c
gdb/solib-svr4.c
gdb/stap-probe.c
gdb/target-float.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/endianity.c [new file with mode: 0644]
gdb/testsuite/gdb.base/endianity.exp [new file with mode: 0644]
gdb/valarith.c
gdb/valops.c
gdb/valprint.c
gdb/value.c

index 57e8f6b43fd5498d843b681696762f7af6ef4a3a..02490485838a19c90859e4dbcbaf9b96385edede 100644 (file)
@@ -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.
index 2935df52a24b6d455672ea64d9235149e06fdf3e..36001ef323568495dc53e63053deb2f31e6ae1f2 100644 (file)
@@ -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;
 }
 
index 5ab036571a3da2a6b8d05637a51a93d5af850d75..4bb9247f519fce1ef565a9f26732d20bce24863c 100644 (file)
@@ -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;
index 74e3f7311996755386b4a0f0db514bebb0be15bd..1de44f7efb5b3f178d5a047890da91dea2aa868d 100644 (file)
@@ -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;
index c4306f1488f15af88abb2f44c4b732630235effb..58675f6d9dffe08bfbde968c9a6ff2821a1f1e6e 100644 (file)
@@ -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))
index 04be4dc83b7fdbc845a85274269f4c5f037a73d4..e445d42d3fa98f2ca4d9a1e88cc6e6105ee9a88f 100644 (file)
@@ -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
index c8ba0290a02eb548beaf29b68d1552ac23b359e5..e25ee6680b46ab046c6afdbd74944a6dcb7425ab 100644 (file)
@@ -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.  */
index 9178e0eb940c932828fe69ae03c7c679d503d0b9..d89a54138be2dd26dc4a4456f6c2263a3d5c9b1d 100644 (file)
@@ -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);
 }
 
index 7f241c62784bef13642f17ab6bac6d0186842b19..fd4ad0f1411bcba917a01d8ea5c765473efbe2e0 100644 (file)
@@ -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";
index bbfd68995d367ef52cfff76ce3933dbbdafb1497..95cc58d83f8011f86cf4e9776edc42244ddc0523 100644 (file)
@@ -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);
index fd1c765fed02095bb6396779f310bb68633fd0d9..31c1a7b732b1627077a3b1dcd566875b4e8b1829 100644 (file)
@@ -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;
+}
index 6d6ff59950fb34946914cb95d79e8c55b13963d6..8fc770c5d39ce26033b802b06640002811be14b1 100644 (file)
@@ -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.  */
 
index 2533a948649eb00584659f109a45c60890abc301..2a5486c8a10e39426c2b70cea52981b5f5eba85b 100644 (file)
@@ -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.
index 5ca9933b56c6dc7008ec39917b89c2dd0e801867..eb18efab513bf9c917a9b25bd5d640f15e9b96f6 100644 (file)
@@ -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;
index 0cf1c6c16ca614da5f77737d357c5199c9b445ae..33cb6e635d81fce07215b2128f1c84dfc57127b2 100644 (file)
@@ -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;
index 10612f3babe8ad82121136229f39d7790fcbb408..c465d1455b42842fb09f1b27d64e2a36e0f0d2d2 100644 (file)
@@ -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;
index 323a5d05eb7aafc731d56cf4855c77b6333b0dd6..0251d465bd9df922847bfef7b3e34e2e1437444d 100644 (file)
@@ -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');
index 810b834463430c87b03b8ba6ed4a37da56024e40..d262b7d07e7fae3647515e4ba1c78089ad9e7873 100644 (file)
@@ -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;
index 286e38558f20331e5af8847da792eed2adc2752e..969bfd529bc20acf039d8d328f4d5b86eb362aea 100644 (file)
@@ -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;
index 27299ffca05d347076884d14e7ee2a410334c5ef..de765576d0b7fda28028b4899a79ccffb16f4fae 100644 (file)
@@ -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
index ea206cbb80f3016db7e30e65db751892b7cd7415..ba927790a5d6bb1aa33dbdf3d136dc9bf2c3954d 100644 (file)
@@ -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."));
index 4ef3505b067233485ccc8e53c904670e1ba354fc..caa6943395016cb19e9dcef1a3bdb5375fc1d7bb 100644 (file)
@@ -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");
index 1685525a3007b02aab97a25599d2646e100d5862..d4c42bd6afc31f295dbdb6135e7eb7f8c57f81da 100644 (file)
@@ -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 (file)
index 0000000..5ab090d
--- /dev/null
@@ -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 (file)
index 0000000..80df012
--- /dev/null
@@ -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"
index 7f1b24fd539cd8883a24f16d506957544f3788c1..ea999b5ba71a3a876e2f44f75f95b55225094b83 100644 (file)
@@ -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;
index bfdd781aa96821dd94ea09ed070b1a288f9aa538..4597e99a0691dbbdc3bd413142f990ede4a31b22 100644 (file)
@@ -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 ?
index e0eb8e1839789b25bb0618f7ab18395983488db7..ced0dbcd0a60c3bcef4e97c3b10e51c60a3e0633 100644 (file)
@@ -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
index 47e647afb4c420e0f8fafce15f9085dabd583c33..35a7a5cdce3d894f0b2d55653bbfe111c993b46f 100644 (file)
@@ -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))
     {