aarch64 multi-arch support (part 2): siginfo fixup

Message ID 1441729817-17413-1-git-send-email-yao.qi@linaro.org
State New, archived
Headers

Commit Message

Yao Qi Sept. 8, 2015, 4:30 p.m. UTC
  This patch is to fixup the siginfo_t when aarch64 gdb or gdbserver
read from or write to the arm inferior.  It is to convert the
"struct siginfo_t" between aarch64(64-bit) and arm(32-bit), which is
quite mechanical.

Regression tested on aarch64-linux, both native and gdbserver. 

gdb/gdbserver:

2015-09-08  Yao Qi  <yao.qi@linaro.org>

	* linux-aarch64-low.c (aarch64_linux_siginfo_fixup): New
	function.
	(struct linux_target_ops the_low_target): Install
	aarch64_linux_siginfo_fixup.

gdb:

2015-09-08  Yao Qi  <yao.qi@linaro.org>

	* aarch64-linux-nat.c (aarch64_linux_siginfo_fixup): New function.
	(_initialize_aarch64_linux_nat): Call linux_nat_set_siginfo_fixup.
	* nat/aarch64-linux.c (aarch64_compat_siginfo_from_siginfo):
	New function.
	(aarch64_siginfo_from_compat_siginfo): New function.
	* nat/aarch64-linux.h: Include signal.h.
	(compat_int_t, compat_uptr_t, compat_time_t): Typedef.
	(compat_timer_t, compat_clock_t): Likewise.
	(struct compat_timeval): New.
	(union compat_sigval): New.
	(struct compat_siginfo): New.
	(cpt_si_pid, cpt_si_uid, cpt_si_timerid): New macros.
	(cpt_si_overrun, cpt_si_status, cpt_si_utime): Likewise.
	(cpt_si_stime, cpt_si_ptr, cpt_si_addr): Likewise.
	(cpt_si_band, cpt_si_fd): Likewise.
---
 gdb/aarch64-linux-nat.c           |  31 ++++++++++
 gdb/gdbserver/linux-aarch64-low.c |  23 +++++++-
 gdb/nat/aarch64-linux.c           | 117 ++++++++++++++++++++++++++++++++++++++
 gdb/nat/aarch64-linux.h           |  96 +++++++++++++++++++++++++++++++
 4 files changed, 266 insertions(+), 1 deletion(-)
  

Comments

Andrew Pinski Sept. 8, 2015, 4:38 p.m. UTC | #1
On Wed, Sep 9, 2015 at 12:30 AM, Yao Qi <qiyaoltc@gmail.com> wrote:
> This patch is to fixup the siginfo_t when aarch64 gdb or gdbserver
> read from or write to the arm inferior.  It is to convert the
> "struct siginfo_t" between aarch64(64-bit) and arm(32-bit), which is
> quite mechanical.
>
> Regression tested on aarch64-linux, both native and gdbserver.
>
> gdb/gdbserver:
>
> 2015-09-08  Yao Qi  <yao.qi@linaro.org>
>
>         * linux-aarch64-low.c (aarch64_linux_siginfo_fixup): New
>         function.
>         (struct linux_target_ops the_low_target): Install
>         aarch64_linux_siginfo_fixup.
>
> gdb:
>
> 2015-09-08  Yao Qi  <yao.qi@linaro.org>
>
>         * aarch64-linux-nat.c (aarch64_linux_siginfo_fixup): New function.
>         (_initialize_aarch64_linux_nat): Call linux_nat_set_siginfo_fixup.
>         * nat/aarch64-linux.c (aarch64_compat_siginfo_from_siginfo):
>         New function.
>         (aarch64_siginfo_from_compat_siginfo): New function.
>         * nat/aarch64-linux.h: Include signal.h.
>         (compat_int_t, compat_uptr_t, compat_time_t): Typedef.
>         (compat_timer_t, compat_clock_t): Likewise.
>         (struct compat_timeval): New.
>         (union compat_sigval): New.
>         (struct compat_siginfo): New.
>         (cpt_si_pid, cpt_si_uid, cpt_si_timerid): New macros.
>         (cpt_si_overrun, cpt_si_status, cpt_si_utime): Likewise.
>         (cpt_si_stime, cpt_si_ptr, cpt_si_addr): Likewise.
>         (cpt_si_band, cpt_si_fd): Likewise.
> ---
>  gdb/aarch64-linux-nat.c           |  31 ++++++++++
>  gdb/gdbserver/linux-aarch64-low.c |  23 +++++++-
>  gdb/nat/aarch64-linux.c           | 117 ++++++++++++++++++++++++++++++++++++++
>  gdb/nat/aarch64-linux.h           |  96 +++++++++++++++++++++++++++++++
>  4 files changed, 266 insertions(+), 1 deletion(-)
>
> diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
> index 673817e..d7ac19e 100644
> --- a/gdb/aarch64-linux-nat.c
> +++ b/gdb/aarch64-linux-nat.c
> @@ -543,6 +543,34 @@ aarch64_linux_read_description (struct target_ops *ops)
>    return tdesc_aarch64;
>  }
>
> +/* Convert a native/host siginfo object, into/from the siginfo in the
> +   layout of the inferiors' architecture.  Returns true if any
> +   conversion was done; false otherwise.  If DIRECTION is 1, then copy
> +   from INF to NATIVE.  If DIRECTION is 0, copy from NATIVE to
> +   INF.  */
> +
> +static int
> +aarch64_linux_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction)
> +{
> +  struct gdbarch *gdbarch = get_frame_arch (get_current_frame ());
> +
> +  /* Is the inferior 32-bit?  If so, then do fixup the siginfo
> +     object.  */
> +  if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
> +    {
> +      if (direction == 0)
> +       aarch64_compat_siginfo_from_siginfo ((struct compat_siginfo *) inf,
> +                                            native);
> +      else
> +       aarch64_siginfo_from_compat_siginfo (native,
> +                                            (struct compat_siginfo *) inf);
> +
> +      return 1;
> +    }

This might fix the issue I having with ILP32 and siginfo. Though it
might be still broken since time_t is 64bit for ILP32 (at least the
current definition).

Thanks,
Andrew

> +
> +  return 0;
> +}
> +
>  /* Returns the number of hardware watchpoints of type TYPE that we can
>     set.  Value is positive if we can set CNT watchpoints, zero if
>     setting watchpoints of type TYPE is not supported, and negative if
> @@ -850,4 +878,7 @@ _initialize_aarch64_linux_nat (void)
>    linux_nat_set_new_fork (t, aarch64_linux_new_fork);
>    linux_nat_set_forget_process (t, aarch64_forget_process);
>    linux_nat_set_prepare_to_resume (t, aarch64_linux_prepare_to_resume);
> +
> +  /* Add our siginfo layout converter.  */
> +  linux_nat_set_siginfo_fixup (t, aarch64_linux_siginfo_fixup);
>  }
> diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
> index aebf1e3..73b248c 100644
> --- a/gdb/gdbserver/linux-aarch64-low.c
> +++ b/gdb/gdbserver/linux-aarch64-low.c
> @@ -430,6 +430,27 @@ ps_get_thread_area (const struct ps_prochandle *ph,
>    return PS_OK;
>  }
>
> +/* Implementation of linux_target_ops method "siginfo_fixup".  */
> +
> +static int
> +aarch64_linux_siginfo_fixup (siginfo_t *native, void *inf, int direction)
> +{
> +  /* Is the inferior 32-bit?  If so, then fixup the siginfo object.  */
> +  if (!is_64bit_tdesc ())
> +    {
> +      if (direction == 0)
> +       aarch64_compat_siginfo_from_siginfo ((struct compat_siginfo *) inf,
> +                                            native);
> +      else
> +       aarch64_siginfo_from_compat_siginfo (native,
> +                                            (struct compat_siginfo *) inf);
> +
> +      return 1;
> +    }
> +
> +  return 0;
> +}
> +
>  /* Implementation of linux_target_ops method "linux_new_process".  */
>
>  static struct arch_process_info *
> @@ -581,7 +602,7 @@ struct linux_target_ops the_low_target =
>    aarch64_stopped_data_address,
>    NULL, /* collect_ptrace_register */
>    NULL, /* supply_ptrace_register */
> -  NULL, /* siginfo_fixup */
> +  aarch64_linux_siginfo_fixup,
>    aarch64_linux_new_process,
>    aarch64_linux_new_thread,
>    aarch64_linux_new_fork,
> diff --git a/gdb/nat/aarch64-linux.c b/gdb/nat/aarch64-linux.c
> index ba94b00..0634094 100644
> --- a/gdb/nat/aarch64-linux.c
> +++ b/gdb/nat/aarch64-linux.c
> @@ -78,3 +78,120 @@ aarch64_linux_new_thread (struct lwp_info *lwp)
>
>    lwp_set_arch_private_info (lwp, info);
>  }
> +
> +/* Convert native siginfo FROM to the siginfo in the layout of the
> +   inferior's architecture TO.  */
> +
> +void
> +aarch64_compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
> +{
> +  memset (to, 0, sizeof (*to));
> +
> +  to->si_signo = from->si_signo;
> +  to->si_errno = from->si_errno;
> +  to->si_code = from->si_code;
> +
> +  if (to->si_code == SI_TIMER)
> +    {
> +      to->cpt_si_timerid = from->si_timerid;
> +      to->cpt_si_overrun = from->si_overrun;
> +      to->cpt_si_ptr = (intptr_t) from->si_ptr;
> +    }
> +  else if (to->si_code == SI_USER)
> +    {
> +      to->cpt_si_pid = from->si_pid;
> +      to->cpt_si_uid = from->si_uid;
> +    }
> +  else if (to->si_code < 0)
> +    {
> +      to->cpt_si_pid = from->si_pid;
> +      to->cpt_si_uid = from->si_uid;
> +      to->cpt_si_ptr = (intptr_t) from->si_ptr;
> +    }
> +  else
> +    {
> +      switch (to->si_signo)
> +       {
> +       case SIGCHLD:
> +         to->cpt_si_pid = from->si_pid;
> +         to->cpt_si_uid = from->si_uid;
> +         to->cpt_si_status = from->si_status;
> +         to->cpt_si_utime = from->si_utime;
> +         to->cpt_si_stime = from->si_stime;
> +         break;
> +       case SIGILL:
> +       case SIGFPE:
> +       case SIGSEGV:
> +       case SIGBUS:
> +         to->cpt_si_addr = (intptr_t) from->si_addr;
> +         break;
> +       case SIGPOLL:
> +         to->cpt_si_band = from->si_band;
> +         to->cpt_si_fd = from->si_fd;
> +         break;
> +       default:
> +         to->cpt_si_pid = from->si_pid;
> +         to->cpt_si_uid = from->si_uid;
> +         to->cpt_si_ptr = (intptr_t) from->si_ptr;
> +         break;
> +       }
> +    }
> +}
> +
> +/* Convert inferior's architecture siginfo FROM to native siginfo TO.  */
> +
> +void
> +aarch64_siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
> +{
> +  memset (to, 0, sizeof (*to));
> +
> +  to->si_signo = from->si_signo;
> +  to->si_errno = from->si_errno;
> +  to->si_code = from->si_code;
> +
> +  if (to->si_code == SI_TIMER)
> +    {
> +      to->si_timerid = from->cpt_si_timerid;
> +      to->si_overrun = from->cpt_si_overrun;
> +      to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
> +    }
> +  else if (to->si_code == SI_USER)
> +    {
> +      to->si_pid = from->cpt_si_pid;
> +      to->si_uid = from->cpt_si_uid;
> +    }
> +  if (to->si_code < 0)
> +    {
> +      to->si_pid = from->cpt_si_pid;
> +      to->si_uid = from->cpt_si_uid;
> +      to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
> +    }
> +  else
> +    {
> +      switch (to->si_signo)
> +       {
> +       case SIGCHLD:
> +         to->si_pid = from->cpt_si_pid;
> +         to->si_uid = from->cpt_si_uid;
> +         to->si_status = from->cpt_si_status;
> +         to->si_utime = from->cpt_si_utime;
> +         to->si_stime = from->cpt_si_stime;
> +         break;
> +       case SIGILL:
> +       case SIGFPE:
> +       case SIGSEGV:
> +       case SIGBUS:
> +         to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
> +         break;
> +       case SIGPOLL:
> +         to->si_band = from->cpt_si_band;
> +         to->si_fd = from->cpt_si_fd;
> +         break;
> +       default:
> +         to->si_pid = from->cpt_si_pid;
> +         to->si_uid = from->cpt_si_uid;
> +         to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
> +         break;
> +       }
> +    }
> +}
> diff --git a/gdb/nat/aarch64-linux.h b/gdb/nat/aarch64-linux.h
> index 5cb432c..89eb4e3 100644
> --- a/gdb/nat/aarch64-linux.h
> +++ b/gdb/nat/aarch64-linux.h
> @@ -19,6 +19,102 @@
>  #ifndef AARCH64_LINUX_H
>  #define AARCH64_LINUX_H 1
>
> +#include <signal.h>
> +
> +typedef int compat_int_t;
> +typedef unsigned int compat_uptr_t;
> +
> +typedef int compat_time_t;
> +typedef int compat_timer_t;
> +typedef int compat_clock_t;
> +
> +struct compat_timeval
> +{
> +  compat_time_t tv_sec;
> +  int tv_usec;
> +};
> +
> +typedef union compat_sigval
> +{
> +  compat_int_t sival_int;
> +  compat_uptr_t sival_ptr;
> +} compat_sigval_t;
> +
> +typedef struct compat_siginfo
> +{
> +  int si_signo;
> +  int si_errno;
> +  int si_code;
> +
> +  union
> +  {
> +    int _pad[((128 / sizeof (int)) - 3)];
> +
> +    /* kill() */
> +    struct
> +    {
> +      unsigned int _pid;
> +      unsigned int _uid;
> +    } _kill;
> +
> +    /* POSIX.1b timers */
> +    struct
> +    {
> +      compat_timer_t _tid;
> +      int _overrun;
> +      compat_sigval_t _sigval;
> +    } _timer;
> +
> +    /* POSIX.1b signals */
> +    struct
> +    {
> +      unsigned int _pid;
> +      unsigned int _uid;
> +      compat_sigval_t _sigval;
> +    } _rt;
> +
> +    /* SIGCHLD */
> +    struct
> +    {
> +      unsigned int _pid;
> +      unsigned int _uid;
> +      int _status;
> +      compat_clock_t _utime;
> +      compat_clock_t _stime;
> +    } _sigchld;
> +
> +    /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
> +    struct
> +    {
> +      unsigned int _addr;
> +    } _sigfault;
> +
> +    /* SIGPOLL */
> +    struct
> +    {
> +      int _band;
> +      int _fd;
> +    } _sigpoll;
> +  } _sifields;
> +} compat_siginfo_t;
> +
> +#define cpt_si_pid _sifields._kill._pid
> +#define cpt_si_uid _sifields._kill._uid
> +#define cpt_si_timerid _sifields._timer._tid
> +#define cpt_si_overrun _sifields._timer._overrun
> +#define cpt_si_status _sifields._sigchld._status
> +#define cpt_si_utime _sifields._sigchld._utime
> +#define cpt_si_stime _sifields._sigchld._stime
> +#define cpt_si_ptr _sifields._rt._sigval.sival_ptr
> +#define cpt_si_addr _sifields._sigfault._addr
> +#define cpt_si_band _sifields._sigpoll._band
> +#define cpt_si_fd _sifields._sigpoll._fd
> +
> +void aarch64_siginfo_from_compat_siginfo (siginfo_t *to,
> +                                           compat_siginfo_t *from);
> +void aarch64_compat_siginfo_from_siginfo (compat_siginfo_t *to,
> +                                           siginfo_t *from);
> +
>  void aarch64_linux_prepare_to_resume (struct lwp_info *lwp);
>
>  void aarch64_linux_new_thread (struct lwp_info *lwp);
> --
> 1.9.1
>
  
Yao Qi Sept. 11, 2015, 8:39 a.m. UTC | #2
Andrew Pinski <pinskia@gmail.com> writes:

Hi Andrew,

> This might fix the issue I having with ILP32 and siginfo. Though it
> might be still broken since time_t is 64bit for ILP32 (at least the
> current definition).

You may need separate fixup functions for ILP32, like what we are doing
for x32 on amd64.  See amd64-linux-nat.c:amd64_linux_siginfo_fixup.

b.t.w, I find you create a remote branch for gdb-aarch64-ilp32, but I
don't take a look.  Out of my curiosity, what is its state now?  Is it
ready for submission recently?
  
Andrew Pinski Sept. 11, 2015, 9:44 a.m. UTC | #3
> On Sep 11, 2015, at 4:39 PM, Yao Qi <qiyaoltc@gmail.com> wrote:
> 
> Andrew Pinski <pinskia@gmail.com> writes:
> 
> Hi Andrew,
> 
>> This might fix the issue I having with ILP32 and siginfo. Though it
>> might be still broken since time_t is 64bit for ILP32 (at least the
>> current definition).
> 
> You may need separate fixup functions for ILP32, like what we are doing
> for x32 on amd64.  See amd64-linux-nat.c:amd64_linux_siginfo_fixup.
> 
> b.t.w, I find you create a remote branch for gdb-aarch64-ilp32, but I
> don't take a look.  Out of my curiosity, what is its state now?  Is it
> ready for submission recently?

It works as I don't get any more failures than expected. And yes it is ready for submitting, I just have not done it yet. 

Thanks,
Andrew

> 
> -- 
> Yao (齐尧)
  
Yao Qi Sept. 15, 2015, 9:28 a.m. UTC | #4
Yao Qi <qiyaoltc@gmail.com> writes:

> gdb/gdbserver:
>
> 2015-09-08  Yao Qi  <yao.qi@linaro.org>
>
> 	* linux-aarch64-low.c (aarch64_linux_siginfo_fixup): New
> 	function.
> 	(struct linux_target_ops the_low_target): Install
> 	aarch64_linux_siginfo_fixup.
>
> gdb:
>
> 2015-09-08  Yao Qi  <yao.qi@linaro.org>
>
> 	* aarch64-linux-nat.c (aarch64_linux_siginfo_fixup): New function.
> 	(_initialize_aarch64_linux_nat): Call linux_nat_set_siginfo_fixup.
> 	* nat/aarch64-linux.c (aarch64_compat_siginfo_from_siginfo):
> 	New function.
> 	(aarch64_siginfo_from_compat_siginfo): New function.
> 	* nat/aarch64-linux.h: Include signal.h.
> 	(compat_int_t, compat_uptr_t, compat_time_t): Typedef.
> 	(compat_timer_t, compat_clock_t): Likewise.
> 	(struct compat_timeval): New.
> 	(union compat_sigval): New.
> 	(struct compat_siginfo): New.
> 	(cpt_si_pid, cpt_si_uid, cpt_si_timerid): New macros.
> 	(cpt_si_overrun, cpt_si_status, cpt_si_utime): Likewise.
> 	(cpt_si_stime, cpt_si_ptr, cpt_si_addr): Likewise.
> 	(cpt_si_band, cpt_si_fd): Likewise.

Patch is pushed in.
  

Patch

diff --git a/gdb/aarch64-linux-nat.c b/gdb/aarch64-linux-nat.c
index 673817e..d7ac19e 100644
--- a/gdb/aarch64-linux-nat.c
+++ b/gdb/aarch64-linux-nat.c
@@ -543,6 +543,34 @@  aarch64_linux_read_description (struct target_ops *ops)
   return tdesc_aarch64;
 }
 
+/* Convert a native/host siginfo object, into/from the siginfo in the
+   layout of the inferiors' architecture.  Returns true if any
+   conversion was done; false otherwise.  If DIRECTION is 1, then copy
+   from INF to NATIVE.  If DIRECTION is 0, copy from NATIVE to
+   INF.  */
+
+static int
+aarch64_linux_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction)
+{
+  struct gdbarch *gdbarch = get_frame_arch (get_current_frame ());
+
+  /* Is the inferior 32-bit?  If so, then do fixup the siginfo
+     object.  */
+  if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
+    {
+      if (direction == 0)
+	aarch64_compat_siginfo_from_siginfo ((struct compat_siginfo *) inf,
+					     native);
+      else
+	aarch64_siginfo_from_compat_siginfo (native,
+					     (struct compat_siginfo *) inf);
+
+      return 1;
+    }
+
+  return 0;
+}
+
 /* Returns the number of hardware watchpoints of type TYPE that we can
    set.  Value is positive if we can set CNT watchpoints, zero if
    setting watchpoints of type TYPE is not supported, and negative if
@@ -850,4 +878,7 @@  _initialize_aarch64_linux_nat (void)
   linux_nat_set_new_fork (t, aarch64_linux_new_fork);
   linux_nat_set_forget_process (t, aarch64_forget_process);
   linux_nat_set_prepare_to_resume (t, aarch64_linux_prepare_to_resume);
+
+  /* Add our siginfo layout converter.  */
+  linux_nat_set_siginfo_fixup (t, aarch64_linux_siginfo_fixup);
 }
diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index aebf1e3..73b248c 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -430,6 +430,27 @@  ps_get_thread_area (const struct ps_prochandle *ph,
   return PS_OK;
 }
 
+/* Implementation of linux_target_ops method "siginfo_fixup".  */
+
+static int
+aarch64_linux_siginfo_fixup (siginfo_t *native, void *inf, int direction)
+{
+  /* Is the inferior 32-bit?  If so, then fixup the siginfo object.  */
+  if (!is_64bit_tdesc ())
+    {
+      if (direction == 0)
+	aarch64_compat_siginfo_from_siginfo ((struct compat_siginfo *) inf,
+					     native);
+      else
+	aarch64_siginfo_from_compat_siginfo (native,
+					     (struct compat_siginfo *) inf);
+
+      return 1;
+    }
+
+  return 0;
+}
+
 /* Implementation of linux_target_ops method "linux_new_process".  */
 
 static struct arch_process_info *
@@ -581,7 +602,7 @@  struct linux_target_ops the_low_target =
   aarch64_stopped_data_address,
   NULL, /* collect_ptrace_register */
   NULL, /* supply_ptrace_register */
-  NULL, /* siginfo_fixup */
+  aarch64_linux_siginfo_fixup,
   aarch64_linux_new_process,
   aarch64_linux_new_thread,
   aarch64_linux_new_fork,
diff --git a/gdb/nat/aarch64-linux.c b/gdb/nat/aarch64-linux.c
index ba94b00..0634094 100644
--- a/gdb/nat/aarch64-linux.c
+++ b/gdb/nat/aarch64-linux.c
@@ -78,3 +78,120 @@  aarch64_linux_new_thread (struct lwp_info *lwp)
 
   lwp_set_arch_private_info (lwp, info);
 }
+
+/* Convert native siginfo FROM to the siginfo in the layout of the
+   inferior's architecture TO.  */
+
+void
+aarch64_compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
+{
+  memset (to, 0, sizeof (*to));
+
+  to->si_signo = from->si_signo;
+  to->si_errno = from->si_errno;
+  to->si_code = from->si_code;
+
+  if (to->si_code == SI_TIMER)
+    {
+      to->cpt_si_timerid = from->si_timerid;
+      to->cpt_si_overrun = from->si_overrun;
+      to->cpt_si_ptr = (intptr_t) from->si_ptr;
+    }
+  else if (to->si_code == SI_USER)
+    {
+      to->cpt_si_pid = from->si_pid;
+      to->cpt_si_uid = from->si_uid;
+    }
+  else if (to->si_code < 0)
+    {
+      to->cpt_si_pid = from->si_pid;
+      to->cpt_si_uid = from->si_uid;
+      to->cpt_si_ptr = (intptr_t) from->si_ptr;
+    }
+  else
+    {
+      switch (to->si_signo)
+	{
+	case SIGCHLD:
+	  to->cpt_si_pid = from->si_pid;
+	  to->cpt_si_uid = from->si_uid;
+	  to->cpt_si_status = from->si_status;
+	  to->cpt_si_utime = from->si_utime;
+	  to->cpt_si_stime = from->si_stime;
+	  break;
+	case SIGILL:
+	case SIGFPE:
+	case SIGSEGV:
+	case SIGBUS:
+	  to->cpt_si_addr = (intptr_t) from->si_addr;
+	  break;
+	case SIGPOLL:
+	  to->cpt_si_band = from->si_band;
+	  to->cpt_si_fd = from->si_fd;
+	  break;
+	default:
+	  to->cpt_si_pid = from->si_pid;
+	  to->cpt_si_uid = from->si_uid;
+	  to->cpt_si_ptr = (intptr_t) from->si_ptr;
+	  break;
+	}
+    }
+}
+
+/* Convert inferior's architecture siginfo FROM to native siginfo TO.  */
+
+void
+aarch64_siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
+{
+  memset (to, 0, sizeof (*to));
+
+  to->si_signo = from->si_signo;
+  to->si_errno = from->si_errno;
+  to->si_code = from->si_code;
+
+  if (to->si_code == SI_TIMER)
+    {
+      to->si_timerid = from->cpt_si_timerid;
+      to->si_overrun = from->cpt_si_overrun;
+      to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
+    }
+  else if (to->si_code == SI_USER)
+    {
+      to->si_pid = from->cpt_si_pid;
+      to->si_uid = from->cpt_si_uid;
+    }
+  if (to->si_code < 0)
+    {
+      to->si_pid = from->cpt_si_pid;
+      to->si_uid = from->cpt_si_uid;
+      to->si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
+    }
+  else
+    {
+      switch (to->si_signo)
+	{
+	case SIGCHLD:
+	  to->si_pid = from->cpt_si_pid;
+	  to->si_uid = from->cpt_si_uid;
+	  to->si_status = from->cpt_si_status;
+	  to->si_utime = from->cpt_si_utime;
+	  to->si_stime = from->cpt_si_stime;
+	  break;
+	case SIGILL:
+	case SIGFPE:
+	case SIGSEGV:
+	case SIGBUS:
+	  to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
+	  break;
+	case SIGPOLL:
+	  to->si_band = from->cpt_si_band;
+	  to->si_fd = from->cpt_si_fd;
+	  break;
+	default:
+	  to->si_pid = from->cpt_si_pid;
+	  to->si_uid = from->cpt_si_uid;
+	  to->si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
+	  break;
+	}
+    }
+}
diff --git a/gdb/nat/aarch64-linux.h b/gdb/nat/aarch64-linux.h
index 5cb432c..89eb4e3 100644
--- a/gdb/nat/aarch64-linux.h
+++ b/gdb/nat/aarch64-linux.h
@@ -19,6 +19,102 @@ 
 #ifndef AARCH64_LINUX_H
 #define AARCH64_LINUX_H 1
 
+#include <signal.h>
+
+typedef int compat_int_t;
+typedef unsigned int compat_uptr_t;
+
+typedef int compat_time_t;
+typedef int compat_timer_t;
+typedef int compat_clock_t;
+
+struct compat_timeval
+{
+  compat_time_t tv_sec;
+  int tv_usec;
+};
+
+typedef union compat_sigval
+{
+  compat_int_t sival_int;
+  compat_uptr_t sival_ptr;
+} compat_sigval_t;
+
+typedef struct compat_siginfo
+{
+  int si_signo;
+  int si_errno;
+  int si_code;
+
+  union
+  {
+    int _pad[((128 / sizeof (int)) - 3)];
+
+    /* kill() */
+    struct
+    {
+      unsigned int _pid;
+      unsigned int _uid;
+    } _kill;
+
+    /* POSIX.1b timers */
+    struct
+    {
+      compat_timer_t _tid;
+      int _overrun;
+      compat_sigval_t _sigval;
+    } _timer;
+
+    /* POSIX.1b signals */
+    struct
+    {
+      unsigned int _pid;
+      unsigned int _uid;
+      compat_sigval_t _sigval;
+    } _rt;
+
+    /* SIGCHLD */
+    struct
+    {
+      unsigned int _pid;
+      unsigned int _uid;
+      int _status;
+      compat_clock_t _utime;
+      compat_clock_t _stime;
+    } _sigchld;
+
+    /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+    struct
+    {
+      unsigned int _addr;
+    } _sigfault;
+
+    /* SIGPOLL */
+    struct
+    {
+      int _band;
+      int _fd;
+    } _sigpoll;
+  } _sifields;
+} compat_siginfo_t;
+
+#define cpt_si_pid _sifields._kill._pid
+#define cpt_si_uid _sifields._kill._uid
+#define cpt_si_timerid _sifields._timer._tid
+#define cpt_si_overrun _sifields._timer._overrun
+#define cpt_si_status _sifields._sigchld._status
+#define cpt_si_utime _sifields._sigchld._utime
+#define cpt_si_stime _sifields._sigchld._stime
+#define cpt_si_ptr _sifields._rt._sigval.sival_ptr
+#define cpt_si_addr _sifields._sigfault._addr
+#define cpt_si_band _sifields._sigpoll._band
+#define cpt_si_fd _sifields._sigpoll._fd
+
+void aarch64_siginfo_from_compat_siginfo (siginfo_t *to,
+					    compat_siginfo_t *from);
+void aarch64_compat_siginfo_from_siginfo (compat_siginfo_t *to,
+					    siginfo_t *from);
+
 void aarch64_linux_prepare_to_resume (struct lwp_info *lwp);
 
 void aarch64_linux_new_thread (struct lwp_info *lwp);