public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 0/2] aarch64 couple big endian fixes
@ 2014-10-27  3:14 Victor Kamensky
  2014-10-27  3:14 ` [PATCH 2/2] aarch64: tramp_frame_start function need to read instrs correctly in be8 case Victor Kamensky
  2014-10-27  3:14 ` [PATCH 1/2] aarch64: handle big endian float registers correctly Victor Kamensky
  0 siblings, 2 replies; 4+ messages in thread
From: Victor Kamensky @ 2014-10-27  3:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Yao Qi, Andrew Pinski, victor.kamensky

Hi Folks,

Here are couple fixes for aarch64 (ARM 64bit) to address gdb testsuite
failures in aarch64 big endian case. Basically there were issue with
handling floating point registers and issue of going over signal frame.

After these fixes and couple other big endian related fixes 
in test cases themseves (will be posted separately), aarch64 big endian
passes gdb testsuite in par with little endian results.

Also I run x86_64 and ppc64 gdb and aarch64 little endian testsuites
before/after to check that there is any regression.

Thanks,
Victor

Victor Kamensky (2):
  aarch64: handle big endian float registers correctly
  aarch64: tramp_frame_start function need to read instrs correctly in
    be8 case

 gdb/aarch64-tdep.c | 57 ++++++++++++++++++++++++++++++++++--------------------
 gdb/tramp-frame.c  |  2 +-
 2 files changed, 37 insertions(+), 22 deletions(-)

-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] aarch64: handle big endian float registers correctly
  2014-10-27  3:14 [PATCH 0/2] aarch64 couple big endian fixes Victor Kamensky
  2014-10-27  3:14 ` [PATCH 2/2] aarch64: tramp_frame_start function need to read instrs correctly in be8 case Victor Kamensky
@ 2014-10-27  3:14 ` Victor Kamensky
  1 sibling, 0 replies; 4+ messages in thread
From: Victor Kamensky @ 2014-10-27  3:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Yao Qi, Andrew Pinski, victor.kamensky

In big endian case vreg memory is in big endian format and all
pseudo registers will be in big endian format. But all smaller
pseudo registers are at higher memory addresses (least siginificant
part of vreg memory).

Introduce reg_addr_in_vreg function would return correct address
of pseudo register memory depending on current target endianity.
aarch64_pseudo_read_value and aarch64_pseudo_write and other
functions use that function to get address within vreg to copy
into/from target pseudo register memory.

That fixes numerous floating point gdb testsuite failures on
aarch64 big endian target. For example gdb.base/structs.exp,
gdb.base/float.exp, gdb.base/call-ar-st.exp and many others.

gdb/ChangeLog:

2014-10-24  Victor Kamensky  <victor.kamensky@linaro.org>

	* aarch64-tdep.c (reg_addr_in_vreg): New function.
	(pass_in_v): Added type parameter. Use reg_addr_in_vreg
	to place memory in vreg depending on endianity and type
	size.
	(pass_in_v_or_stack): Pass type to pass_in_v function.
	(aarch64_push_dummy_call): Handle big endian case
	correctly.
	(aarch64_extract_return_value): Ditto.
	(aarch64_store_return_value): Ditto.
	(aarch64_pseudo_read_value): Ditto.
	(aarch64_pseudo_write): Ditto.
---
 gdb/aarch64-tdep.c | 57 ++++++++++++++++++++++++++++++++++--------------------
 1 file changed, 36 insertions(+), 21 deletions(-)

diff --git a/gdb/aarch64-tdep.c b/gdb/aarch64-tdep.c
index 1898f6b..959035e 100644
--- a/gdb/aarch64-tdep.c
+++ b/gdb/aarch64-tdep.c
@@ -1382,6 +1382,16 @@ pass_in_x (struct gdbarch *gdbarch, struct regcache *regcache,
     }
 }
 
+static gdb_byte * reg_addr_in_vreg (struct gdbarch *gdbarch,
+				    gdb_byte *vreg_addr,
+				    size_t size)
+{
+  gdb_byte *ret = vreg_addr;
+  if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG)
+    ret = vreg_addr + (V_REGISTER_SIZE - size);
+  return ret;
+}
+
 /* Attempt to marshall a value in a V register.  Return 1 if
    successful, or 0 if insufficient registers are available.  This
    function, unlike the equivalent pass_in_x() function does not
@@ -1391,17 +1401,21 @@ static int
 pass_in_v (struct gdbarch *gdbarch,
 	   struct regcache *regcache,
 	   struct aarch64_call_info *info,
+	   struct type *type,
 	   const bfd_byte *buf)
 {
   if (info->nsrn < 8)
     {
-      enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+      bfd_byte xbuf[V_REGISTER_SIZE];
+      int len = TYPE_LENGTH (type);
+      int copy_len = len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len;
       int regnum = AARCH64_V0_REGNUM + info->nsrn;
 
       info->argnum++;
       info->nsrn++;
 
-      regcache_cooked_write (regcache, regnum, buf);
+      memcpy (reg_addr_in_vreg (gdbarch, xbuf, copy_len), buf, copy_len);
+      regcache_cooked_write (regcache, regnum, xbuf);
       if (aarch64_debug)
 	fprintf_unfiltered (gdb_stdlog, "arg %d in %s\n",
 			    info->argnum,
@@ -1491,7 +1505,7 @@ pass_in_v_or_stack (struct gdbarch *gdbarch,
 		    struct type *type,
 		    const bfd_byte *buf)
 {
-  if (!pass_in_v (gdbarch, regcache, info, buf))
+  if (!pass_in_v (gdbarch, regcache, info, type, buf))
     pass_on_stack (info, type, buf);
 }
 
@@ -1616,8 +1630,8 @@ aarch64_push_dummy_call (struct gdbarch *gdbarch, struct value *function,
 	      struct type *target_type =
 		check_typedef (TYPE_TARGET_TYPE (arg_type));
 
-	      pass_in_v (gdbarch, regcache, &info, buf);
-	      pass_in_v (gdbarch, regcache, &info,
+	      pass_in_v (gdbarch, regcache, &info, target_type, buf);
+	      pass_in_v (gdbarch, regcache, &info, target_type,
 			 buf + TYPE_LENGTH (target_type));
 	    }
 	  else
@@ -1925,7 +1939,7 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
       int len = TYPE_LENGTH (type);
 
       regcache_cooked_read (regs, AARCH64_V0_REGNUM, buf);
-      memcpy (valbuf, buf, len);
+      memcpy (valbuf, reg_addr_in_vreg (gdbarch, buf, len), len);
     }
   else if (TYPE_CODE (type) == TYPE_CODE_INT
 	   || TYPE_CODE (type) == TYPE_CODE_CHAR
@@ -1961,10 +1975,10 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
       int len = TYPE_LENGTH (target_type);
 
       regcache_cooked_read (regs, regno, buf);
-      memcpy (valbuf, buf, len);
+      memcpy (valbuf, reg_addr_in_vreg (gdbarch, buf, len), len);
       valbuf += len;
       regcache_cooked_read (regs, regno + 1, buf);
-      memcpy (valbuf, buf, len);
+      memcpy (valbuf, reg_addr_in_vreg (gdbarch, buf, len), len);
       valbuf += len;
     }
   else if (is_hfa (type))
@@ -1986,7 +2000,7 @@ aarch64_extract_return_value (struct type *type, struct regcache *regs,
 				gdbarch_register_name (gdbarch, regno));
 	  regcache_cooked_read (regs, regno, buf);
 
-	  memcpy (valbuf, buf, len);
+	  memcpy (valbuf, reg_addr_in_vreg (gdbarch, buf, len), len);
 	  valbuf += len;
 	}
     }
@@ -2058,8 +2072,9 @@ aarch64_store_return_value (struct type *type, struct regcache *regs,
     {
       bfd_byte buf[V_REGISTER_SIZE];
       int len = TYPE_LENGTH (type);
+      int copy_len = len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len;
 
-      memcpy (buf, valbuf, len > V_REGISTER_SIZE ? V_REGISTER_SIZE : len);
+      memcpy (reg_addr_in_vreg (gdbarch, buf, copy_len), valbuf, copy_len);
       regcache_cooked_write (regs, AARCH64_V0_REGNUM, buf);
     }
   else if (TYPE_CODE (type) == TYPE_CODE_INT
@@ -2113,7 +2128,7 @@ aarch64_store_return_value (struct type *type, struct regcache *regs,
 				i + 1,
 				gdbarch_register_name (gdbarch, regno));
 
-	  memcpy (tmpbuf, valbuf, len);
+	  memcpy (reg_addr_in_vreg (gdbarch, tmpbuf, len), valbuf, len);
 	  regcache_cooked_write (regs, regno, tmpbuf);
 	  valbuf += len;
 	}
@@ -2360,7 +2375,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
 	mark_value_bytes_unavailable (result_value, 0,
 				      TYPE_LENGTH (value_type (result_value)));
       else
-	memcpy (buf, reg_buf, Q_REGISTER_SIZE);
+	memcpy (buf, reg_addr_in_vreg (gdbarch, reg_buf, Q_REGISTER_SIZE), Q_REGISTER_SIZE);
       return result_value;
     }
 
@@ -2375,7 +2390,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
 	mark_value_bytes_unavailable (result_value, 0,
 				      TYPE_LENGTH (value_type (result_value)));
       else
-	memcpy (buf, reg_buf, D_REGISTER_SIZE);
+	memcpy (buf, reg_addr_in_vreg (gdbarch, reg_buf, D_REGISTER_SIZE), D_REGISTER_SIZE);
       return result_value;
     }
 
@@ -2386,7 +2401,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
 
       v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_S0_REGNUM;
       status = regcache_raw_read (regcache, v_regnum, reg_buf);
-      memcpy (buf, reg_buf, S_REGISTER_SIZE);
+      memcpy (buf, reg_addr_in_vreg (gdbarch, reg_buf, S_REGISTER_SIZE), S_REGISTER_SIZE);
       return result_value;
     }
 
@@ -2401,7 +2416,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
 	mark_value_bytes_unavailable (result_value, 0,
 				      TYPE_LENGTH (value_type (result_value)));
       else
-	memcpy (buf, reg_buf, H_REGISTER_SIZE);
+	memcpy (buf, reg_addr_in_vreg (gdbarch, reg_buf, H_REGISTER_SIZE), H_REGISTER_SIZE);
       return result_value;
     }
 
@@ -2416,7 +2431,7 @@ aarch64_pseudo_read_value (struct gdbarch *gdbarch,
 	mark_value_bytes_unavailable (result_value, 0,
 				      TYPE_LENGTH (value_type (result_value)));
       else
-	memcpy (buf, reg_buf, B_REGISTER_SIZE);
+	memcpy (buf, reg_addr_in_vreg (gdbarch, reg_buf, B_REGISTER_SIZE), B_REGISTER_SIZE);
       return result_value;
     }
 
@@ -2445,7 +2460,7 @@ aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
       unsigned v_regnum;
 
       v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_Q0_REGNUM;
-      memcpy (reg_buf, buf, Q_REGISTER_SIZE);
+      memcpy (reg_addr_in_vreg (gdbarch, reg_buf, Q_REGISTER_SIZE), buf, Q_REGISTER_SIZE);
       regcache_raw_write (regcache, v_regnum, reg_buf);
       return;
     }
@@ -2456,7 +2471,7 @@ aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
       unsigned v_regnum;
 
       v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_D0_REGNUM;
-      memcpy (reg_buf, buf, D_REGISTER_SIZE);
+      memcpy (reg_addr_in_vreg (gdbarch, reg_buf, D_REGISTER_SIZE), buf, D_REGISTER_SIZE);
       regcache_raw_write (regcache, v_regnum, reg_buf);
       return;
     }
@@ -2466,7 +2481,7 @@ aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
       unsigned v_regnum;
 
       v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_S0_REGNUM;
-      memcpy (reg_buf, buf, S_REGISTER_SIZE);
+      memcpy (reg_addr_in_vreg (gdbarch, reg_buf, S_REGISTER_SIZE), buf, S_REGISTER_SIZE);
       regcache_raw_write (regcache, v_regnum, reg_buf);
       return;
     }
@@ -2477,7 +2492,7 @@ aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
       unsigned v_regnum;
 
       v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_H0_REGNUM;
-      memcpy (reg_buf, buf, H_REGISTER_SIZE);
+      memcpy (reg_addr_in_vreg (gdbarch, reg_buf, H_REGISTER_SIZE), buf, H_REGISTER_SIZE);
       regcache_raw_write (regcache, v_regnum, reg_buf);
       return;
     }
@@ -2488,7 +2503,7 @@ aarch64_pseudo_write (struct gdbarch *gdbarch, struct regcache *regcache,
       unsigned v_regnum;
 
       v_regnum = AARCH64_V0_REGNUM + regnum - AARCH64_B0_REGNUM;
-      memcpy (reg_buf, buf, B_REGISTER_SIZE);
+      memcpy (reg_addr_in_vreg (gdbarch, reg_buf, B_REGISTER_SIZE), buf, B_REGISTER_SIZE);
       regcache_raw_write (regcache, v_regnum, reg_buf);
       return;
     }
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/2] aarch64: tramp_frame_start function need to read instrs correctly in be8 case
  2014-10-27  3:14 [PATCH 0/2] aarch64 couple big endian fixes Victor Kamensky
@ 2014-10-27  3:14 ` Victor Kamensky
  2014-10-29  6:07   ` Yao Qi
  2014-10-27  3:14 ` [PATCH 1/2] aarch64: handle big endian float registers correctly Victor Kamensky
  1 sibling, 1 reply; 4+ messages in thread
From: Victor Kamensky @ 2014-10-27  3:14 UTC (permalink / raw)
  To: gdb-patches; +Cc: Yao Qi, Andrew Pinski, victor.kamensky

tramp_frame_start function needs to read instructions in
gdbarch_byte_order_for_code byte order, because in case aarch64_be,
even data is big endian, instructions are still little endian.
Currently function uses gdbarch_byte_order which would be
big endian in aarch64_be case.

Because of this issue pretty much all tests that involve backtrace
of stack with signal frame are failing on aarch64_be target.

Fix is to change gdbarch_byte_order to gdbarch_byte_order_for_code,
when passed to extract_unsigned_integer that reads instruction.

gdb/ChangeLog:

2014-10-24  Victor Kamensky  <victor.kamensky@linaro.org>
	* gdb/tramp-frame.c (tramp_frame_start): Use
	gdbarch_byte_order_for_code to read aarch64 instruction.
---
 gdb/tramp-frame.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/gdb/tramp-frame.c b/gdb/tramp-frame.c
index 0fd6ddc..41dcd94 100644
--- a/gdb/tramp-frame.c
+++ b/gdb/tramp-frame.c
@@ -83,7 +83,7 @@ tramp_frame_start (const struct tramp_frame *tramp,
 		   struct frame_info *this_frame, CORE_ADDR pc)
 {
   struct gdbarch *gdbarch = get_frame_arch (this_frame);
-  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order_for_code (gdbarch);
   int ti;
 
   /* Search through the trampoline for one that matches the
-- 
1.8.1.4

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 2/2] aarch64: tramp_frame_start function need to read instrs correctly in be8 case
  2014-10-27  3:14 ` [PATCH 2/2] aarch64: tramp_frame_start function need to read instrs correctly in be8 case Victor Kamensky
@ 2014-10-29  6:07   ` Yao Qi
  0 siblings, 0 replies; 4+ messages in thread
From: Yao Qi @ 2014-10-29  6:07 UTC (permalink / raw)
  To: Victor Kamensky; +Cc: gdb-patches, Andrew Pinski

Victor Kamensky <victor.kamensky@linaro.org> writes:

Looks the problem this patch fixes isn't arch specific.  This problem
exists for a while, but is exposed by your configuration (data
endianness != instruction endianness).  gdbarch_byte_order_for_code must
be used for reading instructions.

> gdb/ChangeLog:
>
> 2014-10-24  Victor Kamensky  <victor.kamensky@linaro.org>

An empty line here is needed.

> 	* gdb/tramp-frame.c (tramp_frame_start): Use
> 	gdbarch_byte_order_for_code to read aarch64 instruction.
> ---
>  gdb/tramp-frame.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/gdb/tramp-frame.c b/gdb/tramp-frame.c
> index 0fd6ddc..41dcd94 100644
> --- a/gdb/tramp-frame.c
> +++ b/gdb/tramp-frame.c
> @@ -83,7 +83,7 @@ tramp_frame_start (const struct tramp_frame *tramp,
>  		   struct frame_info *this_frame, CORE_ADDR pc)
>  {
>    struct gdbarch *gdbarch = get_frame_arch (this_frame);
> -  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
> +  enum bfd_endian byte_order = gdbarch_byte_order_for_code (gdbarch);
>    int ti;

Please rename variable byte_order to byte_order_for_code.

OK with these changes.

-- 
Yao (齐尧)

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2014-10-29  6:07 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-10-27  3:14 [PATCH 0/2] aarch64 couple big endian fixes Victor Kamensky
2014-10-27  3:14 ` [PATCH 2/2] aarch64: tramp_frame_start function need to read instrs correctly in be8 case Victor Kamensky
2014-10-29  6:07   ` Yao Qi
2014-10-27  3:14 ` [PATCH 1/2] aarch64: handle big endian float registers correctly Victor Kamensky

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).