Patchwork review request: implementing DW_AT_endianity

login
register
mail settings
Submitter Peeter Joot
Date Oct. 10, 2017, 11:30 p.m.
Message ID <20171010233010.58471-1-peeter.joot@lzlabs.com>
Download mbox | patch
Permalink /patch/23467/
State New
Headers show

Comments

Peeter Joot - Oct. 10, 2017, 11:30 p.m.
* binutils/dwarf.c (read_and_display_attr_value): Handle
 DW_AT_endianity, DW_END_default, DW_END_big, DW_END_little
 * gdb/gdbtypes.h (global scope): define TYPE_ENDIANITY_BIG,
 TYPE_ENDIANITY_LITTLE.  New function: type_byte_order
 * 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.
 New function: type_byte_order.
 (recursive_dump_type): Print TYPE_ENDIANITY_BIG, and
 TYPE_ENDIANITY_LITTLE if set.
 (struct main_type): Add flag_endianity_big, flag_endianity_little
 * gdb/ada-lang.c (ada_value_binop)
 * gdb/ada-valprint.c (printstr, ada_val_print_string)
 * gdb/c-lang.c (c_get_string)
 * gdb/c-valprint.c (c_val_print_array)
 * gdb/cp-valprint.c (cp_print_class_member)
 * gdb/dwarf2loc.c (rw_pieced_value)
 * gdb/f-lang.c (f_get_encoding)
 * gdb/f-valprint.c (f_val_print)
 * gdb/findvar.c (default_read_var_value)
 * gdb/infcmd.c (default_print_one_register_info)
 * gdb/p-lang.c (pascal_printstr)
 * gdb/p-valprint.c (pascal_val_print)
 * gdb/printcmd.c (print_scalar_formatted, printf_decfloat)
 * gdb/python/py-value.c (valpy_nonzero)
 * gdb/solib-darwin.c (open_symbol_file_object)
 * gdb/solib-svr4.c (solib_svr4_r_brk)
 * gdb/stap-probe.c (stap_modify_semaphore)
 * gdb/valarith.c (value_args_as_decimal, scalar_binop, value_logical_not, value_neg)
 * gdb/valops.c (value_cast, value_one)
 * gdb/valprint.c (print_decimal_floating, generic_emit_char, generic_printstr, val_print_string)
 * gdb/value.c (value_as_address, unpack_long, unpack_bits_as_long, unpack_value_bitfield, modify_field, pack_long, pack_unsigned_long)
 use new helper function type_byte_order(, type) to replace gdbarch_byte_order (get_type_arch (type));
 * gdb/testsuite/gdb.base/endianity.c, gdb/testsuite/gdb.base/endianity.exp
 New test.  print a value in a struct with non-native endianity.
 Modify that value in a print statement and re-print the structure.
---
 ChangeLog                            |  5 ++++
 binutils/dwarf.c                     | 11 +++++++++
 gdb/ChangeLog                        | 37 ++++++++++++++++++++++++++++++
 gdb/ada-lang.c                       |  2 +-
 gdb/ada-valprint.c                   |  4 ++--
 gdb/c-lang.c                         |  2 +-
 gdb/c-valprint.c                     |  2 +-
 gdb/cp-valprint.c                    |  2 +-
 gdb/dwarf2loc.c                      |  5 ++--
 gdb/dwarf2read.c                     | 18 +++++++++++++++
 gdb/f-lang.c                         |  2 +-
 gdb/f-valprint.c                     |  2 +-
 gdb/findvar.c                        |  2 +-
 gdb/gdbtypes.c                       | 22 ++++++++++++++++++
 gdb/gdbtypes.h                       | 14 ++++++++++++
 gdb/infcmd.c                         |  2 +-
 gdb/p-lang.c                         |  2 +-
 gdb/p-valprint.c                     |  2 +-
 gdb/printcmd.c                       |  4 ++--
 gdb/python/py-value.c                |  2 +-
 gdb/solib-darwin.c                   |  5 ++--
 gdb/solib-svr4.c                     |  5 ++--
 gdb/stap-probe.c                     |  7 +++---
 gdb/testsuite/gdb.base/endianity.c   | 44 ++++++++++++++++++++++++++++++++++++
 gdb/testsuite/gdb.base/endianity.exp | 34 ++++++++++++++++++++++++++++
 gdb/valarith.c                       | 25 ++++++++++----------
 gdb/valops.c                         |  6 ++---
 gdb/valprint.c                       |  8 +++----
 gdb/value.c                          | 14 ++++++------
 29 files changed, 239 insertions(+), 51 deletions(-)
 create mode 100644 gdb/testsuite/gdb.base/endianity.c
 create mode 100644 gdb/testsuite/gdb.base/endianity.exp
Peeter Joot - Oct. 11, 2017, 2:29 a.m.
- ignore the binutils/dwarf.c change which I've now submitted separately to binutils@sourceware.

- also ignore the // break here comments, which I've also removed from my branch (left over from debuggin).
Simon Marchi - Oct. 12, 2017, 8:23 p.m.
Hi Peter,

Thanks for the update.  Your commit should include a message that summarizes what the
code does, the limitations, anything you think would be useful to a reader.

A few words about the ChangeLog.  First, we generally don't include the ChangeLog in the patch/diff
itself when sending it to the list.  The reason is that trying to apply the patch will almost
certainly result in a conflict.  Instead, we only include it in the commit message, and then put it
in the real ChangeLog file when pushing the code.

Second, each entry in the ChangeLog should be place in the ChangeLog closest to it in the hierarchy:

$ find binutils gdb -name ChangeLog | sort
binutils/ChangeLog
gdb/ChangeLog
gdb/doc/ChangeLog
gdb/gdbserver/ChangeLog
gdb/stubs/ChangeLog
gdb/testsuite/ChangeLog

For example, this entry:

	* gdb/ada-lang.c (ada_value_binop)

should go in gdb/ChangeLog, and omit the gdb/ part:

	* ada-lang.c (ada_value_binop): ...

Finally, make sure the lines start with a tab, and are not too long (74 columns).  Read this for more
details: https://sourceware.org/gdb/wiki/ContributionChecklist#Properly_Formatted_GNU_ChangeLog

See more comments below.  Once you addressed them, you can send a new version again with git-send-email,
make sure to pass --subject-prefix="PATCH v2".

On 2017-10-10 07:30 PM, Peeter Joot wrote:
>  * binutils/dwarf.c (read_and_display_attr_value): Handle
>  DW_AT_endianity, DW_END_default, DW_END_big, DW_END_little
>  * gdb/gdbtypes.h (global scope): define TYPE_ENDIANITY_BIG,
>  TYPE_ENDIANITY_LITTLE.  New function: type_byte_order

No need to say "global scope".  Here's how I would do it:

	* gdbtypes.h (TYPE_ENDIANITY_BIG): New macro.
	(TYPE_ENDIANITY_LITTLE): New macro.
	(struct main_type) <flag_endianity_big>: New field.
	<flag_endianity_little>: New field.
	(type_byte_order): New function.

You can also collapse multiple items that have the same message, but it is optional:

	* gdbtypes.h (TYPE_ENDIANITY_BIG, TYPE_ENDIANITY_LITTLE): New
	macros.
	(struct main_type) <flag_endianity_big, flag_endianity_little>:
	New fields.
	(type_byte_order): New function.

>  * 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.
>  New function: type_byte_order.
>  (recursive_dump_type): Print TYPE_ENDIANITY_BIG, and
>  TYPE_ENDIANITY_LITTLE if set.
>  (struct main_type): Add flag_endianity_big, flag_endianity_little

This last one should go in gdbtypes.h.

>  * gdb/ada-lang.c (ada_value_binop)

Each entry should have some text and finish with a period.  For example,

	* ada-lang.c (ada_value_binop): Use type_byte_order instead of
	gdbarch_byte_order.

>  * gdb/ada-valprint.c (printstr, ada_val_print_string)
>  * gdb/c-lang.c (c_get_string)
>  * gdb/c-valprint.c (c_val_print_array)
>  * gdb/cp-valprint.c (cp_print_class_member)
>  * gdb/dwarf2loc.c (rw_pieced_value)
>  * gdb/f-lang.c (f_get_encoding)
>  * gdb/f-valprint.c (f_val_print)
>  * gdb/findvar.c (default_read_var_value)
>  * gdb/infcmd.c (default_print_one_register_info)
>  * gdb/p-lang.c (pascal_printstr)
>  * gdb/p-valprint.c (pascal_val_print)
>  * gdb/printcmd.c (print_scalar_formatted, printf_decfloat)
>  * gdb/python/py-value.c (valpy_nonzero)
>  * gdb/solib-darwin.c (open_symbol_file_object)
>  * gdb/solib-svr4.c (solib_svr4_r_brk)
>  * gdb/stap-probe.c (stap_modify_semaphore)
>  * gdb/valarith.c (value_args_as_decimal, scalar_binop, value_logical_not, value_neg)
>  * gdb/valops.c (value_cast, value_one)
>  * gdb/valprint.c (print_decimal_floating, generic_emit_char, generic_printstr, val_print_string)
>  * gdb/value.c (value_as_address, unpack_long, unpack_bits_as_long, unpack_value_bitfield, modify_field, pack_long, pack_unsigned_long)
>  use new helper function type_byte_order(, type) to replace gdbarch_byte_order (get_type_arch (type));
>  * gdb/testsuite/gdb.base/endianity.c, gdb/testsuite/gdb.base/endianity.exp
>  New test.  print a value in a struct with non-native endianity.
>  Modify that value in a print statement and re-print the structure.

When adding a file, you can be brief and just say "New file.".

> ---
>  ChangeLog                            |  5 ++++
>  binutils/dwarf.c                     | 11 +++++++++
>  gdb/ChangeLog                        | 37 ++++++++++++++++++++++++++++++
>  gdb/ada-lang.c                       |  2 +-
>  gdb/ada-valprint.c                   |  4 ++--
>  gdb/c-lang.c                         |  2 +-
>  gdb/c-valprint.c                     |  2 +-
>  gdb/cp-valprint.c                    |  2 +-
>  gdb/dwarf2loc.c                      |  5 ++--
>  gdb/dwarf2read.c                     | 18 +++++++++++++++
>  gdb/f-lang.c                         |  2 +-
>  gdb/f-valprint.c                     |  2 +-
>  gdb/findvar.c                        |  2 +-
>  gdb/gdbtypes.c                       | 22 ++++++++++++++++++
>  gdb/gdbtypes.h                       | 14 ++++++++++++
>  gdb/infcmd.c                         |  2 +-
>  gdb/p-lang.c                         |  2 +-
>  gdb/p-valprint.c                     |  2 +-
>  gdb/printcmd.c                       |  4 ++--
>  gdb/python/py-value.c                |  2 +-
>  gdb/solib-darwin.c                   |  5 ++--
>  gdb/solib-svr4.c                     |  5 ++--
>  gdb/stap-probe.c                     |  7 +++---
>  gdb/testsuite/gdb.base/endianity.c   | 44 ++++++++++++++++++++++++++++++++++++
>  gdb/testsuite/gdb.base/endianity.exp | 34 ++++++++++++++++++++++++++++
>  gdb/valarith.c                       | 25 ++++++++++----------
>  gdb/valops.c                         |  6 ++---
>  gdb/valprint.c                       |  8 +++----
>  gdb/value.c                          | 14 ++++++------
>  29 files changed, 239 insertions(+), 51 deletions(-)
>  create mode 100644 gdb/testsuite/gdb.base/endianity.c
>  create mode 100644 gdb/testsuite/gdb.base/endianity.exp
> 
> diff --git a/ChangeLog b/ChangeLog
> index b5c224ecc9..a0a2c8fe52 100644
> --- a/ChangeLog
> +++ b/ChangeLog
> @@ -1,3 +1,8 @@
> +2017-10-06  Peeter Joot  <peeter.joot@lzlabs.com>
> +
> + * binutils/dwarf.c (read_and_display_attr_value): Handle
> + DW_AT_endianity, DW_END_default, DW_END_big, DW_END_little
> +
>  2017-09-15  Nick Clifton  <nickc@redhat.com>
>  
>  	* src-release.sh (LZIPPROG): New define.  Provides the name of the
> diff --git a/binutils/dwarf.c b/binutils/dwarf.c
> index 91f95ff068..e79fd5e4b4 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 18224e0305..6719cbace5 100644
> --- a/gdb/ChangeLog
> +++ b/gdb/ChangeLog
> @@ -1,3 +1,40 @@
> +2017-10-06  Peeter Joot  <peeter.joot@lzlabs.com>
> +
> + * gdb/gdbtypes.h (global scope): define TYPE_ENDIANITY_BIG,
> + TYPE_ENDIANITY_LITTLE.  New function: type_byte_order
> + * 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.
> + New function: type_byte_order.
> + (recursive_dump_type): Print TYPE_ENDIANITY_BIG, and
> + TYPE_ENDIANITY_LITTLE if set.
> + (struct main_type): Add flag_endianity_big, flag_endianity_little
> + * gdb/ada-lang.c (ada_value_binop)
> + * gdb/ada-valprint.c (printstr, ada_val_print_string)
> + * gdb/c-lang.c (c_get_string)
> + * gdb/c-valprint.c (c_val_print_array)
> + * gdb/cp-valprint.c (cp_print_class_member)
> + * gdb/dwarf2loc.c (rw_pieced_value)
> + * gdb/f-lang.c (f_get_encoding)
> + * gdb/f-valprint.c (f_val_print)
> + * gdb/findvar.c (default_read_var_value)
> + * gdb/infcmd.c (default_print_one_register_info)
> + * gdb/p-lang.c (pascal_printstr)
> + * gdb/p-valprint.c (pascal_val_print)
> + * gdb/printcmd.c (print_scalar_formatted, printf_decfloat)
> + * gdb/python/py-value.c (valpy_nonzero)
> + * gdb/solib-darwin.c (open_symbol_file_object)
> + * gdb/solib-svr4.c (solib_svr4_r_brk)
> + * gdb/stap-probe.c (stap_modify_semaphore)
> + * gdb/valarith.c (value_args_as_decimal, scalar_binop, value_logical_not, value_neg)
> + * gdb/valops.c (value_cast, value_one)
> + * gdb/valprint.c (print_decimal_floating, generic_emit_char, generic_printstr, val_print_string)
> + * gdb/value.c (value_as_address, unpack_long, unpack_bits_as_long, unpack_value_bitfield, modify_field, pack_long, pack_unsigned_long)
> + use new helper function type_byte_order(, type) to replace gdbarch_byte_order (get_type_arch (type));
> + * gdb/testsuite/gdb.base/endianity.c, gdb/testsuite/gdb.base/endianity.exp
> + New test.  print a value in a struct with non-native endianity.
> + Modify that value in a print statement and re-print the structure.
> +
>  2017-10-06  Yao Qi  <yao.qi@linaro.org>
>  
>  	* Makefile.in (ALL_64_TARGET_OBS): Replace aarch64-insn.o with
> diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
> index 1a0c769594..cfe0d39e81 100644
> --- a/gdb/ada-lang.c
> +++ b/gdb/ada-lang.c
> @@ -9761,7 +9761,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 (NULL, type1), v);
>    return val;
>  }
>  
> diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
> index 8095eede72..0584745d14 100644
> --- a/gdb/ada-valprint.c
> +++ b/gdb/ada-valprint.c
> @@ -442,7 +442,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 (NULL, elttype);
>    unsigned int i;
>    unsigned int things_printed = 0;
>    int in_quotes = 0;
> @@ -683,7 +683,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 (NULL, 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 f86e26ed5f..b6b863df4c 100644
> --- a/gdb/c-lang.c
> +++ b/gdb/c-lang.c
> @@ -243,7 +243,7 @@ c_get_string (struct value *value, 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 (NULL, type);
>  
>    if (element_type == NULL)
>      goto error;
> diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c
> index 653fed657a..767fa73907 100644
> --- a/gdb/c-valprint.c
> +++ b/gdb/c-valprint.c
> @@ -246,7 +246,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 (gdbarch, type);

Here, gdbarch is only used for passing here, so you could pass NULL instead
and remove the gdbarch variable.

>        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 fb9bfd904f..a94391b8ef 100644
> --- a/gdb/cp-valprint.c
> +++ b/gdb/cp-valprint.c
> @@ -755,7 +755,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 (NULL, 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 c485eaf8b0..9ea85f497f 100644
> --- a/gdb/dwarf2loc.c
> +++ b/gdb/dwarf2loc.c
> @@ -1773,8 +1773,9 @@ rw_pieced_value (struct value *v, struct value *from)
>    struct piece_closure *c
>      = (struct piece_closure *) value_computed_closure (v);
>    gdb::byte_vector buffer;
> +  struct gdbarch *gdbarch = get_type_arch (value_type (v));
>    int bits_big_endian
> -    = gdbarch_bits_big_endian (get_type_arch (value_type (v)));
> +    = gdbarch_bits_big_endian (gdbarch);
>  
>    if (from != NULL)
>      {
> @@ -1797,7 +1798,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 (gdbarch, value_type (from))
>  	      == BFD_ENDIAN_BIG))
>  	{
>  	  /* Use the least significant bits of FROM.  */
> diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
> index 1b15adced6..0883bf1b0f 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);
> @@ -15252,6 +15253,11 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
>        complaint (&symfile_complaints,
>  		 _("DW_AT_name missing from DW_TAG_base_type"));
>      }
> +  attr = dwarf2_attr (die, DW_AT_endianity, cu);
> +  if (attr)
> +    {
> +      endianity = DW_UNSND (attr); // break here

Remove the comment and the curly braces.

> +    }
>  
>    switch (encoding)
>      {
> @@ -15330,6 +15336,18 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu)
>    if (name && strcmp (name, "char") == 0)
>      TYPE_NOSIGN (type) = 1;
>  
> +  TYPE_ENDIANITY_BIG (type) = 0;
> +  TYPE_ENDIANITY_LITTLE (type) = 0;

This shouldn't be necessary, as it's assumed that the type object is
zero-ed out (see alloc_type).

> +  switch (endianity)
> +    {
> +      case DW_END_big:
> +        TYPE_ENDIANITY_BIG (type) = 1; // break here
> +        break;
> +      case DW_END_little:
> +        TYPE_ENDIANITY_LITTLE (type) = 1; // break here

Remove comments.

> +        break;
> +    }
> +
>    return set_die_type (die, type, cu);
>  }
>  
> diff --git a/gdb/f-lang.c b/gdb/f-lang.c
> index 073d5291f7..79ea9ff8c1 100644
> --- a/gdb/f-lang.c
> +++ b/gdb/f-lang.c
> @@ -55,7 +55,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 (NULL, type) == BFD_ENDIAN_BIG)
>  	encoding = "UTF-32BE";
>        else
>  	encoding = "UTF-32LE";
> diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c
> index 5bcab9d525..6e6c001c30 100644
> --- a/gdb/f-valprint.c
> +++ b/gdb/f-valprint.c
> @@ -215,7 +215,7 @@ f_val_print (struct type *type, int embedded_offset,
>  	     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 (gdbarch, type);
>    int printed_field = 0; /* Number of fields printed.  */
>    struct type *elttype;
>    CORE_ADDR addr;
> diff --git a/gdb/findvar.c b/gdb/findvar.c
> index 2bc2095bf7..f980f1cbf8 100644
> --- a/gdb/findvar.c
> +++ b/gdb/findvar.c
> @@ -622,7 +622,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 (NULL, type),
>  			    (LONGEST) SYMBOL_VALUE (var));
>        VALUE_LVAL (v) = not_lval;
>        return v;
> diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
> index 73d445361d..5519ca5372 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");
> @@ -5401,3 +5411,15 @@ _initialize_gdbtypes (void)
>  			   show_strict_type_checking,
>  			   &setchecklist, &showchecklist);
>  }
> +
> +enum bfd_endian
> +type_byte_order (struct gdbarch * gdbarch, struct type *type)

Remove the space after *.

Add a comment above this definition:

/* See gdbtypes.h.  */

> +{
> +  if (TYPE_ENDIANITY_BIG (type))
> +    return BFD_ENDIAN_BIG;
> +  else if (TYPE_ENDIANITY_LITTLE (type))
> +    return BFD_ENDIAN_LITTLE;
> +  if (!gdbarch)
> +    gdbarch = get_type_arch (type);
> +  return gdbarch_byte_order (gdbarch);

To simplify the API, I think we could omit passing the gdbarch, and
always call get_type_arch.  It's not very costly, and would avoid having
to pass NULL at many places.

> +}
> diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
> index 009cea90d9..28ff20c6d9 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

"archetectures"

> + * 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. */

Remove the stars at the beginning of each line, finish with two spaces:

/* Mixed endian architectures 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.  */

For consistency with what's around, add an empty line before the macro
(although I'm not entirely sure what's the rule for that).

> +#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. */

Same here.

> +#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".  */
> @@ -1951,4 +1963,6 @@ extern int type_not_allocated (const struct type *type);
>  
>  extern int type_not_associated (const struct type *type);
>  
> +extern enum bfd_endian type_byte_order (struct gdbarch *, struct type *type);

Add a comment above this declaration to describe what it does.

> +
>  #endif /* GDBTYPES_H */
> diff --git a/gdb/infcmd.c b/gdb/infcmd.c
> index 187c71f344..d31a9c8ddd 100644
> --- a/gdb/infcmd.c
> +++ b/gdb/infcmd.c
> @@ -2364,7 +2364,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 (NULL, regtype);
>  
>        get_user_print_options (&opts);
>        opts.deref_ref = 1;
> diff --git a/gdb/p-lang.c b/gdb/p-lang.c
> index 439a3772cb..ec2df7f29a 100644
> --- a/gdb/p-lang.c
> +++ b/gdb/p-lang.c
> @@ -218,7 +218,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 (NULL, 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 d12b63638b..7941b0875f 100644
> --- a/gdb/p-valprint.c
> +++ b/gdb/p-valprint.c
> @@ -66,7 +66,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 (gdbarch, type);
>    unsigned int i = 0;	/* Number of characters printed */
>    unsigned len;
>    LONGEST low_bound, high_bound;
> diff --git a/gdb/printcmd.c b/gdb/printcmd.c
> index a8743f1f71..0e027f1b0b 100644
> --- a/gdb/printcmd.c
> +++ b/gdb/printcmd.c
> @@ -354,7 +354,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 (gdbarch, type);
>  
>    /* String printing should go through val_print_scalar_formatted.  */
>    gdb_assert (options->format != 's');
> @@ -2299,7 +2299,7 @@ printf_decfloat (struct ui_file *stream, const char *format,
>    /* Parameter data.  */
>    struct type *param_type = value_type (value);
>    struct gdbarch *gdbarch = get_type_arch (param_type);
> -  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> +  enum bfd_endian byte_order = type_byte_order (NULL, param_type);
>  
>    /* DFP output data.  */
>    struct value *dfp_value = NULL;
> diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
> index cbbb9362ec..60683b906a 100644
> --- a/gdb/python/py-value.c
> +++ b/gdb/python/py-value.c
> @@ -1322,7 +1322,7 @@ valpy_nonzero (PyObject *self)
>        else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
>  	nonzero = !decimal_is_zero (value_contents (self_value->value),
>  				 TYPE_LENGTH (type),
> -				 gdbarch_byte_order (get_type_arch (type)));
> +				 type_byte_order (NULL, type));
>        else
>  	/* All other values are True.  */
>  	nonzero = 1;
> diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
> index 04bbf86cf1..c6ca869860 100644
> --- a/gdb/solib-darwin.c
> +++ b/gdb/solib-darwin.c
> @@ -232,8 +232,9 @@ open_symbol_file_object (void *from_ttyp)
>  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 ());
> +  struct gdbarch *gdbarch = target_gdbarch ();
> +  struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
> +  enum bfd_endian byte_order = type_byte_order (gdbarch, 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 405de37aa5..24e523116c 100644
> --- a/gdb/solib-svr4.c
> +++ b/gdb/solib-svr4.c
> @@ -920,9 +920,10 @@ solib_svr4_r_brk (struct svr4_info *info)
>  static CORE_ADDR
>  solib_svr4_r_ldsomap (struct svr4_info *info)
>  {
> +  struct gdbarch *gdbarch = target_gdbarch ();
>    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 ());
> +  struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
> +  enum bfd_endian byte_order = type_byte_order (gdbarch, ptr_type);
>    ULONGEST version = 0;
>  
>    TRY
> diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
> index 6fa0d20280..ea51d1ae49 100644
> --- a/gdb/stap-probe.c
> +++ b/gdb/stap-probe.c
> @@ -1403,8 +1403,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 (gdbarch, type);
> +  value = extract_unsigned_integer (bytes, TYPE_LENGTH (type), byte_order);
>    /* Note that we explicitly don't worry about overflow or
>       underflow.  */
>    if (set)
> @@ -1412,8 +1412,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/testsuite/gdb.base/endianity.c b/gdb/testsuite/gdb.base/endianity.c
> new file mode 100644
> index 0000000000..330395a970
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/endianity.c
> @@ -0,0 +1,44 @@
> +/* This testcase is part of GDB, the GNU debugger.
> +
> +   Copyright 2017 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;

Remove one space at the beginning of this line.

> +}
> +#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};
> +
> +  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 0000000000..e125838dfd
> --- /dev/null
> +++ b/gdb/testsuite/gdb.base/endianity.exp
> @@ -0,0 +1,34 @@
> +# Copyright 2017 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 {

Add a fail message, like

  fail "couldn't run to start"

> +  return -1
> +}
> +
> +gdb_test "print o" "= {v = 3}"
> +
> +gdb_test "print o.v = 4" "= 4"
> +
> +# expect this to fail if compiled with < gcc6.
> +gdb_test "x/x &o.v" "0x04000000"

You can check the compiler version with test_compiler_info, look
in the testsuite for examples.  If the compiler is not gcc or is
gcc < 6, then you want to call setup_xfail.

Alternatively, you could add a check at the beginning of the .exp
file, and skip the file altogether if the compiler doesn't support
endianity attributes.  You can call "untested" with a message, and
return.

> +
> +gdb_test "print o" "= {v = 4}"

We want each test to have a unique name.  If you omit the test name
(third argument to gdb_test), it will default to the command.  Since
you have two "print o", there will be duplicates.

I suggest always giving a name to tests, like:

  gdb_test "print o" "= {v = 3}" "print o before assignment"

> diff --git a/gdb/valarith.c b/gdb/valarith.c
> index ede60e4b68..bcb0372830 100644
> --- a/gdb/valarith.c
> +++ b/gdb/valarith.c
> @@ -873,13 +873,13 @@ value_args_as_decimal (struct value *arg1, struct value *arg2,
>  
>    if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
>      {
> -      *byte_order_x = gdbarch_byte_order (get_type_arch (type1));
> +      *byte_order_x = type_byte_order (NULL, type1);
>        *len_x = TYPE_LENGTH (type1);
>        memcpy (x, value_contents (arg1), *len_x);
>      }
>    else if (is_integral_type (type1))
>      {
> -      *byte_order_x = gdbarch_byte_order (get_type_arch (type2));
> +      *byte_order_x = type_byte_order (NULL, type2);
>        *len_x = TYPE_LENGTH (type2);
>        if (TYPE_UNSIGNED (type1))
>  	decimal_from_ulongest (value_as_long (arg1), x, *len_x, *byte_order_x);
> @@ -895,13 +895,13 @@ value_args_as_decimal (struct value *arg1, struct value *arg2,
>  
>    if (TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
>      {
> -      *byte_order_y = gdbarch_byte_order (get_type_arch (type2));
> +      *byte_order_y = type_byte_order (NULL, type2);
>        *len_y = TYPE_LENGTH (type2);
>        memcpy (y, value_contents (arg2), *len_y);
>      }
>    else if (is_integral_type (type2))
>      {
> -      *byte_order_y = gdbarch_byte_order (get_type_arch (type1));
> +      *byte_order_y = type_byte_order (NULL, type1);
>        *len_y = TYPE_LENGTH (type1);
>        if (TYPE_UNSIGNED (type2))
>  	decimal_from_ulongest (value_as_long (arg2), y, *len_y, *byte_order_y);
> @@ -930,6 +930,7 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
>  
>    type1 = check_typedef (value_type (arg1));
>    type2 = check_typedef (value_type (arg2));
> +  struct gdbarch *gdbarch = get_type_arch (type1);
>  
>    if ((TYPE_CODE (type1) != TYPE_CODE_FLT
>         && TYPE_CODE (type1) != TYPE_CODE_DECFLOAT
> @@ -959,7 +960,7 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
>  	result_type = type1;
>  
>        len_v = TYPE_LENGTH (result_type);
> -      byte_order_v = gdbarch_byte_order (get_type_arch (result_type));
> +      byte_order_v = type_byte_order (gdbarch, result_type);
>  
>        value_args_as_decimal (arg1, arg2, v1, &len_v1, &byte_order_v1,
>  					 v2, &len_v2, &byte_order_v2);
> @@ -1084,7 +1085,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 (gdbarch, result_type),
>  			    v);
>      }
>    else
> @@ -1232,8 +1233,8 @@ 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
> +				    (gdbarch, result_type),
>  				  v);
>  	}
>        else
> @@ -1362,8 +1363,8 @@ 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
> +				  (gdbarch, result_type),
>  				v);
>  	}
>      }
> @@ -1518,7 +1519,7 @@ value_logical_not (struct value *arg1)
>      return 0 == value_as_double (arg1);
>    else if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
>      return decimal_is_zero (value_contents (arg1), TYPE_LENGTH (type1),
> -			    gdbarch_byte_order (get_type_arch (type1)));
> +			    type_byte_order (NULL, type1));
>  
>    len = TYPE_LENGTH (type1);
>    p = value_contents (arg1);
> @@ -1774,7 +1775,7 @@ value_neg (struct value *arg1)
>  
>        memcpy (decbytes, value_contents (arg1), len);
>  
> -      if (gdbarch_byte_order (get_type_arch (type)) == BFD_ENDIAN_LITTLE)
> +      if (type_byte_order (NULL, type) == BFD_ENDIAN_LITTLE)
>  	decbytes[len-1] = decbytes[len - 1] | 0x80;
>        else
>  	decbytes[0] = decbytes[0] | 0x80;
> diff --git a/gdb/valops.c b/gdb/valops.c
> index de4544cd29..c12cd17b2e 100644
> --- a/gdb/valops.c
> +++ b/gdb/valops.c
> @@ -466,7 +466,7 @@ value_cast (struct type *type, struct value *arg2)
>      return value_from_double (to_type, value_as_double (arg2));
>    else if (code1 == TYPE_CODE_DECFLOAT && scalar)
>      {
> -      enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
> +      enum bfd_endian byte_order = type_byte_order (NULL, type);
>        int dec_len = TYPE_LENGTH (type);
>        gdb_byte dec[16];
>  
> @@ -502,7 +502,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 (NULL, type2));
>        else
>          longest = value_as_long (arg2);
>        return value_from_longest (to_type, convert_to_boolean ?
> @@ -870,7 +870,7 @@ value_one (struct type *type)
>  
>    if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
>      {
> -      enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
> +      enum bfd_endian byte_order = type_byte_order (NULL, type);
>        gdb_byte v[16];
>  
>        decimal_from_string (v, TYPE_LENGTH (type), byte_order, "1");
> diff --git a/gdb/valprint.c b/gdb/valprint.c
> index ca0c4768c9..73b7306fab 100644
> --- a/gdb/valprint.c
> +++ b/gdb/valprint.c
> @@ -1471,7 +1471,7 @@ void
>  print_decimal_floating (const gdb_byte *valaddr, struct type *type,
>  			struct ui_file *stream)
>  {
> -  enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
> +  enum bfd_endian byte_order = type_byte_order (NULL, type);
>    unsigned len = TYPE_LENGTH (type);
>  
>    std::string str = decimal_to_string (valaddr, len, byte_order);
> @@ -2478,7 +2478,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 (NULL, type);
>    gdb_byte *buf;
>    int need_escape = 0;
>  
> @@ -2799,7 +2799,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 (NULL, type);
>    unsigned int i;
>    int width = TYPE_LENGTH (type);
>    struct cleanup *cleanup;
> @@ -2918,7 +2918,7 @@ val_print_string (struct type *elttype, const char *encoding,
>    gdb_byte *buffer = NULL;	/* Dynamically growable fetch buffer.  */
>    struct cleanup *old_chain = NULL;	/* Top of the old cleanup chain.  */
>    struct gdbarch *gdbarch = get_type_arch (elttype);
> -  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> +  enum bfd_endian byte_order = type_byte_order (gdbarch, 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 90423ed002..82e0065256 100644
> --- a/gdb/value.c
> +++ b/gdb/value.c
> @@ -2900,7 +2900,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 (NULL, type);
>    enum type_code code = TYPE_CODE (type);
>    int len = TYPE_LENGTH (type);
>    int nosign = TYPE_UNSIGNED (type);
> @@ -2949,7 +2949,7 @@ unpack_long (struct type *type, const gdb_byte *valaddr)
>  DOUBLEST
>  unpack_double (struct type *type, const gdb_byte *valaddr, int *invp)
>  {
> -  enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
> +  enum bfd_endian byte_order = type_byte_order (NULL, type);
>    enum type_code code;
>    int len;
>    int nosign;
> @@ -3305,7 +3305,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 (NULL, field_type);
>    ULONGEST val;
>    ULONGEST valmask;
>    int lsbcount;
> @@ -3411,7 +3411,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 (NULL, field_type);
>  
>    /* First, unpack and sign extend the bitfield as if it was wholly
>       valid.  Optimized out/unavailable bits are read as zero, but
> @@ -3471,7 +3471,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 (NULL, type);
>    ULONGEST oword;
>    ULONGEST mask = (ULONGEST) -1 >> (8 * sizeof (ULONGEST) - bitsize);
>    LONGEST bytesize;
> @@ -3517,7 +3517,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 (NULL, type);
>    LONGEST len;
>  
>    type = check_typedef (type);
> @@ -3558,7 +3558,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 (NULL, type);
>  
>    switch (TYPE_CODE (type))
>      {
> 

Thanks,

Simon

Patch

diff --git a/ChangeLog b/ChangeLog
index b5c224ecc9..a0a2c8fe52 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@ 
+2017-10-06  Peeter Joot  <peeter.joot@lzlabs.com>
+
+ * binutils/dwarf.c (read_and_display_attr_value): Handle
+ DW_AT_endianity, DW_END_default, DW_END_big, DW_END_little
+
 2017-09-15  Nick Clifton  <nickc@redhat.com>
 
 	* src-release.sh (LZIPPROG): New define.  Provides the name of the
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index 91f95ff068..e79fd5e4b4 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 18224e0305..6719cbace5 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,40 @@ 
+2017-10-06  Peeter Joot  <peeter.joot@lzlabs.com>
+
+ * gdb/gdbtypes.h (global scope): define TYPE_ENDIANITY_BIG,
+ TYPE_ENDIANITY_LITTLE.  New function: type_byte_order
+ * 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.
+ New function: type_byte_order.
+ (recursive_dump_type): Print TYPE_ENDIANITY_BIG, and
+ TYPE_ENDIANITY_LITTLE if set.
+ (struct main_type): Add flag_endianity_big, flag_endianity_little
+ * gdb/ada-lang.c (ada_value_binop)
+ * gdb/ada-valprint.c (printstr, ada_val_print_string)
+ * gdb/c-lang.c (c_get_string)
+ * gdb/c-valprint.c (c_val_print_array)
+ * gdb/cp-valprint.c (cp_print_class_member)
+ * gdb/dwarf2loc.c (rw_pieced_value)
+ * gdb/f-lang.c (f_get_encoding)
+ * gdb/f-valprint.c (f_val_print)
+ * gdb/findvar.c (default_read_var_value)
+ * gdb/infcmd.c (default_print_one_register_info)
+ * gdb/p-lang.c (pascal_printstr)
+ * gdb/p-valprint.c (pascal_val_print)
+ * gdb/printcmd.c (print_scalar_formatted, printf_decfloat)
+ * gdb/python/py-value.c (valpy_nonzero)
+ * gdb/solib-darwin.c (open_symbol_file_object)
+ * gdb/solib-svr4.c (solib_svr4_r_brk)
+ * gdb/stap-probe.c (stap_modify_semaphore)
+ * gdb/valarith.c (value_args_as_decimal, scalar_binop, value_logical_not, value_neg)
+ * gdb/valops.c (value_cast, value_one)
+ * gdb/valprint.c (print_decimal_floating, generic_emit_char, generic_printstr, val_print_string)
+ * gdb/value.c (value_as_address, unpack_long, unpack_bits_as_long, unpack_value_bitfield, modify_field, pack_long, pack_unsigned_long)
+ use new helper function type_byte_order(, type) to replace gdbarch_byte_order (get_type_arch (type));
+ * gdb/testsuite/gdb.base/endianity.c, gdb/testsuite/gdb.base/endianity.exp
+ New test.  print a value in a struct with non-native endianity.
+ Modify that value in a print statement and re-print the structure.
+
 2017-10-06  Yao Qi  <yao.qi@linaro.org>
 
 	* Makefile.in (ALL_64_TARGET_OBS): Replace aarch64-insn.o with
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 1a0c769594..cfe0d39e81 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -9761,7 +9761,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 (NULL, type1), v);
   return val;
 }
 
diff --git a/gdb/ada-valprint.c b/gdb/ada-valprint.c
index 8095eede72..0584745d14 100644
--- a/gdb/ada-valprint.c
+++ b/gdb/ada-valprint.c
@@ -442,7 +442,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 (NULL, elttype);
   unsigned int i;
   unsigned int things_printed = 0;
   int in_quotes = 0;
@@ -683,7 +683,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 (NULL, 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 f86e26ed5f..b6b863df4c 100644
--- a/gdb/c-lang.c
+++ b/gdb/c-lang.c
@@ -243,7 +243,7 @@  c_get_string (struct value *value, 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 (NULL, type);
 
   if (element_type == NULL)
     goto error;
diff --git a/gdb/c-valprint.c b/gdb/c-valprint.c
index 653fed657a..767fa73907 100644
--- a/gdb/c-valprint.c
+++ b/gdb/c-valprint.c
@@ -246,7 +246,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 (gdbarch, 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 fb9bfd904f..a94391b8ef 100644
--- a/gdb/cp-valprint.c
+++ b/gdb/cp-valprint.c
@@ -755,7 +755,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 (NULL, 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 c485eaf8b0..9ea85f497f 100644
--- a/gdb/dwarf2loc.c
+++ b/gdb/dwarf2loc.c
@@ -1773,8 +1773,9 @@  rw_pieced_value (struct value *v, struct value *from)
   struct piece_closure *c
     = (struct piece_closure *) value_computed_closure (v);
   gdb::byte_vector buffer;
+  struct gdbarch *gdbarch = get_type_arch (value_type (v));
   int bits_big_endian
-    = gdbarch_bits_big_endian (get_type_arch (value_type (v)));
+    = gdbarch_bits_big_endian (gdbarch);
 
   if (from != NULL)
     {
@@ -1797,7 +1798,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 (gdbarch, value_type (from))
 	      == BFD_ENDIAN_BIG))
 	{
 	  /* Use the least significant bits of FROM.  */
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 1b15adced6..0883bf1b0f 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);
@@ -15252,6 +15253,11 @@  read_base_type (struct die_info *die, struct dwarf2_cu *cu)
       complaint (&symfile_complaints,
 		 _("DW_AT_name missing from DW_TAG_base_type"));
     }
+  attr = dwarf2_attr (die, DW_AT_endianity, cu);
+  if (attr)
+    {
+      endianity = DW_UNSND (attr); // break here
+    }
 
   switch (encoding)
     {
@@ -15330,6 +15336,18 @@  read_base_type (struct die_info *die, struct dwarf2_cu *cu)
   if (name && strcmp (name, "char") == 0)
     TYPE_NOSIGN (type) = 1;
 
+  TYPE_ENDIANITY_BIG (type) = 0;
+  TYPE_ENDIANITY_LITTLE (type) = 0;
+  switch (endianity)
+    {
+      case DW_END_big:
+        TYPE_ENDIANITY_BIG (type) = 1; // break here
+        break;
+      case DW_END_little:
+        TYPE_ENDIANITY_LITTLE (type) = 1; // break here
+        break;
+    }
+
   return set_die_type (die, type, cu);
 }
 
diff --git a/gdb/f-lang.c b/gdb/f-lang.c
index 073d5291f7..79ea9ff8c1 100644
--- a/gdb/f-lang.c
+++ b/gdb/f-lang.c
@@ -55,7 +55,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 (NULL, type) == BFD_ENDIAN_BIG)
 	encoding = "UTF-32BE";
       else
 	encoding = "UTF-32LE";
diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c
index 5bcab9d525..6e6c001c30 100644
--- a/gdb/f-valprint.c
+++ b/gdb/f-valprint.c
@@ -215,7 +215,7 @@  f_val_print (struct type *type, int embedded_offset,
 	     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 (gdbarch, type);
   int printed_field = 0; /* Number of fields printed.  */
   struct type *elttype;
   CORE_ADDR addr;
diff --git a/gdb/findvar.c b/gdb/findvar.c
index 2bc2095bf7..f980f1cbf8 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -622,7 +622,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 (NULL, type),
 			    (LONGEST) SYMBOL_VALUE (var));
       VALUE_LVAL (v) = not_lval;
       return v;
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 73d445361d..5519ca5372 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");
@@ -5401,3 +5411,15 @@  _initialize_gdbtypes (void)
 			   show_strict_type_checking,
 			   &setchecklist, &showchecklist);
 }
+
+enum bfd_endian
+type_byte_order (struct gdbarch * gdbarch, struct type *type)
+{
+  if (TYPE_ENDIANITY_BIG (type))
+    return BFD_ENDIAN_BIG;
+  else if (TYPE_ENDIANITY_LITTLE (type))
+    return BFD_ENDIAN_LITTLE;
+  if (!gdbarch)
+    gdbarch = get_type_arch (type);
+  return gdbarch_byte_order (gdbarch);
+}
diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h
index 009cea90d9..28ff20c6d9 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".  */
@@ -1951,4 +1963,6 @@  extern int type_not_allocated (const struct type *type);
 
 extern int type_not_associated (const struct type *type);
 
+extern enum bfd_endian type_byte_order (struct gdbarch *, struct type *type);
+
 #endif /* GDBTYPES_H */
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 187c71f344..d31a9c8ddd 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -2364,7 +2364,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 (NULL, regtype);
 
       get_user_print_options (&opts);
       opts.deref_ref = 1;
diff --git a/gdb/p-lang.c b/gdb/p-lang.c
index 439a3772cb..ec2df7f29a 100644
--- a/gdb/p-lang.c
+++ b/gdb/p-lang.c
@@ -218,7 +218,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 (NULL, 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 d12b63638b..7941b0875f 100644
--- a/gdb/p-valprint.c
+++ b/gdb/p-valprint.c
@@ -66,7 +66,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 (gdbarch, type);
   unsigned int i = 0;	/* Number of characters printed */
   unsigned len;
   LONGEST low_bound, high_bound;
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index a8743f1f71..0e027f1b0b 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -354,7 +354,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 (gdbarch, type);
 
   /* String printing should go through val_print_scalar_formatted.  */
   gdb_assert (options->format != 's');
@@ -2299,7 +2299,7 @@  printf_decfloat (struct ui_file *stream, const char *format,
   /* Parameter data.  */
   struct type *param_type = value_type (value);
   struct gdbarch *gdbarch = get_type_arch (param_type);
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  enum bfd_endian byte_order = type_byte_order (NULL, param_type);
 
   /* DFP output data.  */
   struct value *dfp_value = NULL;
diff --git a/gdb/python/py-value.c b/gdb/python/py-value.c
index cbbb9362ec..60683b906a 100644
--- a/gdb/python/py-value.c
+++ b/gdb/python/py-value.c
@@ -1322,7 +1322,7 @@  valpy_nonzero (PyObject *self)
       else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
 	nonzero = !decimal_is_zero (value_contents (self_value->value),
 				 TYPE_LENGTH (type),
-				 gdbarch_byte_order (get_type_arch (type)));
+				 type_byte_order (NULL, type));
       else
 	/* All other values are True.  */
 	nonzero = 1;
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index 04bbf86cf1..c6ca869860 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -232,8 +232,9 @@  open_symbol_file_object (void *from_ttyp)
 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 ());
+  struct gdbarch *gdbarch = target_gdbarch ();
+  struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
+  enum bfd_endian byte_order = type_byte_order (gdbarch, 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 405de37aa5..24e523116c 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -920,9 +920,10 @@  solib_svr4_r_brk (struct svr4_info *info)
 static CORE_ADDR
 solib_svr4_r_ldsomap (struct svr4_info *info)
 {
+  struct gdbarch *gdbarch = target_gdbarch ();
   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 ());
+  struct type *ptr_type = builtin_type (gdbarch)->builtin_data_ptr;
+  enum bfd_endian byte_order = type_byte_order (gdbarch, ptr_type);
   ULONGEST version = 0;
 
   TRY
diff --git a/gdb/stap-probe.c b/gdb/stap-probe.c
index 6fa0d20280..ea51d1ae49 100644
--- a/gdb/stap-probe.c
+++ b/gdb/stap-probe.c
@@ -1403,8 +1403,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 (gdbarch, type);
+  value = extract_unsigned_integer (bytes, TYPE_LENGTH (type), byte_order);
   /* Note that we explicitly don't worry about overflow or
      underflow.  */
   if (set)
@@ -1412,8 +1412,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/testsuite/gdb.base/endianity.c b/gdb/testsuite/gdb.base/endianity.c
new file mode 100644
index 0000000000..330395a970
--- /dev/null
+++ b/gdb/testsuite/gdb.base/endianity.c
@@ -0,0 +1,44 @@ 
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2017 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;
+}
+#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};
+
+  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 0000000000..e125838dfd
--- /dev/null
+++ b/gdb/testsuite/gdb.base/endianity.exp
@@ -0,0 +1,34 @@ 
+# Copyright 2017 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 {
+  return -1
+}
+
+gdb_test "print o" "= {v = 3}"
+
+gdb_test "print o.v = 4" "= 4"
+
+# expect this to fail if compiled with < gcc6.
+gdb_test "x/x &o.v" "0x04000000"
+
+gdb_test "print o" "= {v = 4}"
diff --git a/gdb/valarith.c b/gdb/valarith.c
index ede60e4b68..bcb0372830 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -873,13 +873,13 @@  value_args_as_decimal (struct value *arg1, struct value *arg2,
 
   if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
     {
-      *byte_order_x = gdbarch_byte_order (get_type_arch (type1));
+      *byte_order_x = type_byte_order (NULL, type1);
       *len_x = TYPE_LENGTH (type1);
       memcpy (x, value_contents (arg1), *len_x);
     }
   else if (is_integral_type (type1))
     {
-      *byte_order_x = gdbarch_byte_order (get_type_arch (type2));
+      *byte_order_x = type_byte_order (NULL, type2);
       *len_x = TYPE_LENGTH (type2);
       if (TYPE_UNSIGNED (type1))
 	decimal_from_ulongest (value_as_long (arg1), x, *len_x, *byte_order_x);
@@ -895,13 +895,13 @@  value_args_as_decimal (struct value *arg1, struct value *arg2,
 
   if (TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
     {
-      *byte_order_y = gdbarch_byte_order (get_type_arch (type2));
+      *byte_order_y = type_byte_order (NULL, type2);
       *len_y = TYPE_LENGTH (type2);
       memcpy (y, value_contents (arg2), *len_y);
     }
   else if (is_integral_type (type2))
     {
-      *byte_order_y = gdbarch_byte_order (get_type_arch (type1));
+      *byte_order_y = type_byte_order (NULL, type1);
       *len_y = TYPE_LENGTH (type1);
       if (TYPE_UNSIGNED (type2))
 	decimal_from_ulongest (value_as_long (arg2), y, *len_y, *byte_order_y);
@@ -930,6 +930,7 @@  scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
 
   type1 = check_typedef (value_type (arg1));
   type2 = check_typedef (value_type (arg2));
+  struct gdbarch *gdbarch = get_type_arch (type1);
 
   if ((TYPE_CODE (type1) != TYPE_CODE_FLT
        && TYPE_CODE (type1) != TYPE_CODE_DECFLOAT
@@ -959,7 +960,7 @@  scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
 	result_type = type1;
 
       len_v = TYPE_LENGTH (result_type);
-      byte_order_v = gdbarch_byte_order (get_type_arch (result_type));
+      byte_order_v = type_byte_order (gdbarch, result_type);
 
       value_args_as_decimal (arg1, arg2, v1, &len_v1, &byte_order_v1,
 					 v2, &len_v2, &byte_order_v2);
@@ -1084,7 +1085,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 (gdbarch, result_type),
 			    v);
     }
   else
@@ -1232,8 +1233,8 @@  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
+				    (gdbarch, result_type),
 				  v);
 	}
       else
@@ -1362,8 +1363,8 @@  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
+				  (gdbarch, result_type),
 				v);
 	}
     }
@@ -1518,7 +1519,7 @@  value_logical_not (struct value *arg1)
     return 0 == value_as_double (arg1);
   else if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
     return decimal_is_zero (value_contents (arg1), TYPE_LENGTH (type1),
-			    gdbarch_byte_order (get_type_arch (type1)));
+			    type_byte_order (NULL, type1));
 
   len = TYPE_LENGTH (type1);
   p = value_contents (arg1);
@@ -1774,7 +1775,7 @@  value_neg (struct value *arg1)
 
       memcpy (decbytes, value_contents (arg1), len);
 
-      if (gdbarch_byte_order (get_type_arch (type)) == BFD_ENDIAN_LITTLE)
+      if (type_byte_order (NULL, type) == BFD_ENDIAN_LITTLE)
 	decbytes[len-1] = decbytes[len - 1] | 0x80;
       else
 	decbytes[0] = decbytes[0] | 0x80;
diff --git a/gdb/valops.c b/gdb/valops.c
index de4544cd29..c12cd17b2e 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -466,7 +466,7 @@  value_cast (struct type *type, struct value *arg2)
     return value_from_double (to_type, value_as_double (arg2));
   else if (code1 == TYPE_CODE_DECFLOAT && scalar)
     {
-      enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
+      enum bfd_endian byte_order = type_byte_order (NULL, type);
       int dec_len = TYPE_LENGTH (type);
       gdb_byte dec[16];
 
@@ -502,7 +502,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 (NULL, type2));
       else
         longest = value_as_long (arg2);
       return value_from_longest (to_type, convert_to_boolean ?
@@ -870,7 +870,7 @@  value_one (struct type *type)
 
   if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
     {
-      enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
+      enum bfd_endian byte_order = type_byte_order (NULL, type);
       gdb_byte v[16];
 
       decimal_from_string (v, TYPE_LENGTH (type), byte_order, "1");
diff --git a/gdb/valprint.c b/gdb/valprint.c
index ca0c4768c9..73b7306fab 100644
--- a/gdb/valprint.c
+++ b/gdb/valprint.c
@@ -1471,7 +1471,7 @@  void
 print_decimal_floating (const gdb_byte *valaddr, struct type *type,
 			struct ui_file *stream)
 {
-  enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
+  enum bfd_endian byte_order = type_byte_order (NULL, type);
   unsigned len = TYPE_LENGTH (type);
 
   std::string str = decimal_to_string (valaddr, len, byte_order);
@@ -2478,7 +2478,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 (NULL, type);
   gdb_byte *buf;
   int need_escape = 0;
 
@@ -2799,7 +2799,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 (NULL, type);
   unsigned int i;
   int width = TYPE_LENGTH (type);
   struct cleanup *cleanup;
@@ -2918,7 +2918,7 @@  val_print_string (struct type *elttype, const char *encoding,
   gdb_byte *buffer = NULL;	/* Dynamically growable fetch buffer.  */
   struct cleanup *old_chain = NULL;	/* Top of the old cleanup chain.  */
   struct gdbarch *gdbarch = get_type_arch (elttype);
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  enum bfd_endian byte_order = type_byte_order (gdbarch, 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 90423ed002..82e0065256 100644
--- a/gdb/value.c
+++ b/gdb/value.c
@@ -2900,7 +2900,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 (NULL, type);
   enum type_code code = TYPE_CODE (type);
   int len = TYPE_LENGTH (type);
   int nosign = TYPE_UNSIGNED (type);
@@ -2949,7 +2949,7 @@  unpack_long (struct type *type, const gdb_byte *valaddr)
 DOUBLEST
 unpack_double (struct type *type, const gdb_byte *valaddr, int *invp)
 {
-  enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
+  enum bfd_endian byte_order = type_byte_order (NULL, type);
   enum type_code code;
   int len;
   int nosign;
@@ -3305,7 +3305,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 (NULL, field_type);
   ULONGEST val;
   ULONGEST valmask;
   int lsbcount;
@@ -3411,7 +3411,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 (NULL, field_type);
 
   /* First, unpack and sign extend the bitfield as if it was wholly
      valid.  Optimized out/unavailable bits are read as zero, but
@@ -3471,7 +3471,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 (NULL, type);
   ULONGEST oword;
   ULONGEST mask = (ULONGEST) -1 >> (8 * sizeof (ULONGEST) - bitsize);
   LONGEST bytesize;
@@ -3517,7 +3517,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 (NULL, type);
   LONGEST len;
 
   type = check_typedef (type);
@@ -3558,7 +3558,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 (NULL, type);
 
   switch (TYPE_CODE (type))
     {