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

Andrew Pinski pinskia@gmail.com
Tue Sep 8 16:38:00 GMT 2015


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
>



More information about the Gdb-patches mailing list