This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH] aarch64 multi-arch support (part 2): siginfo fixup
- From: Andrew Pinski <pinskia at gmail dot com>
- To: Yao Qi <qiyaoltc at gmail dot com>
- Cc: "gdb-patches at sourceware dot org" <gdb-patches at sourceware dot org>
- Date: Wed, 9 Sep 2015 00:38:27 +0800
- Subject: Re: [PATCH] aarch64 multi-arch support (part 2): siginfo fixup
- Authentication-results: sourceware.org; auth=none
- References: <1441729817-17413-1-git-send-email-yao dot qi at linaro dot org>
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
>