Add virtual destructor to tui_layout_base
[deliverable/binutils-gdb.git] / gdb / nat / amd64-linux-siginfo.c
index 36b55050ccd08028a452e7ff443db069c52d1be1..91460c02ca9a8a3333f7a8d70f7cf53f81c08c81 100644 (file)
@@ -1,6 +1,6 @@
 /* Low-level siginfo manipulation for amd64.
 
-   Copyright (C) 2002-2016 Free Software Foundation, Inc.
+   Copyright (C) 2002-2019 Free Software Foundation, Inc.
 
    This file is part of GDB.
 
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include <signal.h>
-#include "common-defs.h"
+#include "gdbsupport/common-defs.h"
 #include "amd64-linux-siginfo.h"
 
+#define GDB_SI_SIZE 128
+
+/* The types below define the most complete kernel siginfo types known
+   for the architecture, independent of the system/libc headers.  They
+   are named from a 64-bit kernel's perspective:
+
+   | layout | type                 |
+   |--------+----------------------|
+   | 64-bit | nat_siginfo_t        |
+   | 32-bit | compat_siginfo_t     |
+   | x32    | compat_x32_siginfo_t |
+*/
+
+#ifndef __ILP32__
+
+typedef int nat_int_t;
+typedef unsigned long nat_uptr_t;
+
+typedef int nat_time_t;
+typedef int nat_timer_t;
+
+/* For native 64-bit, clock_t in _sigchld is 64-bit.  */
+typedef long nat_clock_t;
+
+typedef union nat_sigval
+{
+  nat_int_t sival_int;
+  nat_uptr_t sival_ptr;
+} nat_sigval_t;
+
+typedef struct nat_siginfo
+{
+  int si_signo;
+  int si_errno;
+  int si_code;
+
+  union
+  {
+    int _pad[((128 / sizeof (int)) - 4)];
+    /* kill() */
+    struct
+    {
+      unsigned int _pid;
+      unsigned int _uid;
+    } _kill;
+
+    /* POSIX.1b timers */
+    struct
+    {
+      nat_timer_t _tid;
+      int _overrun;
+      nat_sigval_t _sigval;
+    } _timer;
+
+    /* POSIX.1b signals */
+    struct
+    {
+      unsigned int _pid;
+      unsigned int _uid;
+      nat_sigval_t _sigval;
+    } _rt;
+
+    /* SIGCHLD */
+    struct
+    {
+      unsigned int _pid;
+      unsigned int _uid;
+      int _status;
+      nat_clock_t _utime;
+      nat_clock_t _stime;
+    } _sigchld;
+
+    /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+    struct
+    {
+      nat_uptr_t _addr;
+      short int _addr_lsb;
+      struct
+      {
+       nat_uptr_t _lower;
+       nat_uptr_t _upper;
+      } si_addr_bnd;
+    } _sigfault;
+
+    /* SIGPOLL */
+    struct
+    {
+      int _band;
+      int _fd;
+    } _sigpoll;
+  } _sifields;
+} nat_siginfo_t;
+
+#endif /* __ILP32__ */
+
 /* These types below (compat_*) define a siginfo type that is layout
    compatible with the siginfo type exported by the 32-bit userspace
    support.  */
@@ -91,6 +186,12 @@ typedef struct compat_siginfo
     struct
     {
       unsigned int _addr;
+      short int _addr_lsb;
+      struct
+      {
+       unsigned int _lower;
+       unsigned int _upper;
+      } si_addr_bnd;
     } _sigfault;
 
     /* SIGPOLL */
@@ -152,6 +253,7 @@ typedef struct compat_x32_siginfo
     struct
     {
       unsigned int _addr;
+      unsigned int _addr_lsb;
     } _sigfault;
 
     /* SIGPOLL */
@@ -174,6 +276,7 @@ typedef struct compat_x32_siginfo
 #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_addr_lsb _sifields._sigfault._addr_lsb
 #define cpt_si_band _sifields._sigpoll._band
 #define cpt_si_fd _sifields._sigpoll._fd
 
@@ -187,59 +290,71 @@ typedef struct compat_x32_siginfo
 #define si_overrun si_timer2
 #endif
 
+/* The type of the siginfo object the kernel returns in
+   PTRACE_GETSIGINFO.  If gdb is built as a x32 program, we get a x32
+   siginfo.  */
+#ifdef __ILP32__
+typedef compat_x32_siginfo_t ptrace_siginfo_t;
+#else
+typedef nat_siginfo_t ptrace_siginfo_t;
+#endif
+
 /*  Convert the system provided siginfo into compatible siginfo.  */
 
 static void
-compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
+compat_siginfo_from_siginfo (compat_siginfo_t *to, const siginfo_t *from)
 {
+  ptrace_siginfo_t from_ptrace;
+
+  memcpy (&from_ptrace, from, sizeof (from_ptrace));
   memset (to, 0, sizeof (*to));
 
-  to->si_signo = from->si_signo;
-  to->si_errno = from->si_errno;
-  to->si_code = from->si_code;
+  to->si_signo = from_ptrace.si_signo;
+  to->si_errno = from_ptrace.si_errno;
+  to->si_code = from_ptrace.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;
+      to->cpt_si_timerid = from_ptrace.cpt_si_timerid;
+      to->cpt_si_overrun = from_ptrace.cpt_si_overrun;
+      to->cpt_si_ptr = from_ptrace.cpt_si_ptr;
     }
   else if (to->si_code == SI_USER)
     {
-      to->cpt_si_pid = from->si_pid;
-      to->cpt_si_uid = from->si_uid;
+      to->cpt_si_pid = from_ptrace.cpt_si_pid;
+      to->cpt_si_uid = from_ptrace.cpt_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;
+      to->cpt_si_pid = from_ptrace.cpt_si_pid;
+      to->cpt_si_uid = from_ptrace.cpt_si_uid;
+      to->cpt_si_ptr = from_ptrace.cpt_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;
+         to->cpt_si_pid = from_ptrace.cpt_si_pid;
+         to->cpt_si_uid = from_ptrace.cpt_si_uid;
+         to->cpt_si_status = from_ptrace.cpt_si_status;
+         to->cpt_si_utime = from_ptrace.cpt_si_utime;
+         to->cpt_si_stime = from_ptrace.cpt_si_stime;
          break;
        case SIGILL:
        case SIGFPE:
        case SIGSEGV:
        case SIGBUS:
-         to->cpt_si_addr = (intptr_t) from->si_addr;
+         to->cpt_si_addr = from_ptrace.cpt_si_addr;
          break;
        case SIGPOLL:
-         to->cpt_si_band = from->si_band;
-         to->cpt_si_fd = from->si_fd;
+         to->cpt_si_band = from_ptrace.cpt_si_band;
+         to->cpt_si_fd = from_ptrace.cpt_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;
+         to->cpt_si_pid = from_ptrace.cpt_si_pid;
+         to->cpt_si_uid = from_ptrace.cpt_si_uid;
+         to->cpt_si_ptr = from_ptrace.cpt_si_ptr;
          break;
        }
     }
@@ -248,215 +363,234 @@ compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
 /* Convert the compatible siginfo into system siginfo.  */
 
 static void
-siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
+siginfo_from_compat_siginfo (siginfo_t *to, const compat_siginfo_t *from)
 {
-  memset (to, 0, sizeof (*to));
+  ptrace_siginfo_t to_ptrace;
 
-  to->si_signo = from->si_signo;
-  to->si_errno = from->si_errno;
-  to->si_code = from->si_code;
+  memset (&to_ptrace, 0, sizeof (to_ptrace));
 
-  if (to->si_code == SI_TIMER)
+  to_ptrace.si_signo = from->si_signo;
+  to_ptrace.si_errno = from->si_errno;
+  to_ptrace.si_code = from->si_code;
+
+  if (to_ptrace.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;
+      to_ptrace.cpt_si_timerid = from->cpt_si_timerid;
+      to_ptrace.cpt_si_overrun = from->cpt_si_overrun;
+      to_ptrace.cpt_si_ptr = from->cpt_si_ptr;
     }
-  else if (to->si_code == SI_USER)
+  else if (to_ptrace.si_code == SI_USER)
     {
-      to->si_pid = from->cpt_si_pid;
-      to->si_uid = from->cpt_si_uid;
+      to_ptrace.cpt_si_pid = from->cpt_si_pid;
+      to_ptrace.cpt_si_uid = from->cpt_si_uid;
     }
-  if (to->si_code < 0)
+  if (to_ptrace.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;
+      to_ptrace.cpt_si_pid = from->cpt_si_pid;
+      to_ptrace.cpt_si_uid = from->cpt_si_uid;
+      to_ptrace.cpt_si_ptr = from->cpt_si_ptr;
     }
   else
     {
-      switch (to->si_signo)
+      switch (to_ptrace.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;
+         to_ptrace.cpt_si_pid = from->cpt_si_pid;
+         to_ptrace.cpt_si_uid = from->cpt_si_uid;
+         to_ptrace.cpt_si_status = from->cpt_si_status;
+         to_ptrace.cpt_si_utime = from->cpt_si_utime;
+         to_ptrace.cpt_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;
+         to_ptrace.cpt_si_addr = from->cpt_si_addr;
+         to_ptrace.cpt_si_addr_lsb = from->cpt_si_addr_lsb;
          break;
        case SIGPOLL:
-         to->si_band = from->cpt_si_band;
-         to->si_fd = from->cpt_si_fd;
+         to_ptrace.cpt_si_band = from->cpt_si_band;
+         to_ptrace.cpt_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;
+         to_ptrace.cpt_si_pid = from->cpt_si_pid;
+         to_ptrace.cpt_si_uid = from->cpt_si_uid;
+         to_ptrace.cpt_si_ptr = from->cpt_si_ptr;
          break;
        }
     }
+  memcpy (to, &to_ptrace, sizeof (to_ptrace));
 }
 
 /*  Convert the system provided siginfo into compatible x32 siginfo.  */
 
 static void
 compat_x32_siginfo_from_siginfo (compat_x32_siginfo_t *to,
-                                siginfo_t *from)
+                                const siginfo_t *from)
 {
+  ptrace_siginfo_t from_ptrace;
+
+  memcpy (&from_ptrace, from, sizeof (from_ptrace));
   memset (to, 0, sizeof (*to));
 
-  to->si_signo = from->si_signo;
-  to->si_errno = from->si_errno;
-  to->si_code = from->si_code;
+  to->si_signo = from_ptrace.si_signo;
+  to->si_errno = from_ptrace.si_errno;
+  to->si_code = from_ptrace.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;
+      to->cpt_si_timerid = from_ptrace.cpt_si_timerid;
+      to->cpt_si_overrun = from_ptrace.cpt_si_overrun;
+      to->cpt_si_ptr = from_ptrace.cpt_si_ptr;
     }
   else if (to->si_code == SI_USER)
     {
-      to->cpt_si_pid = from->si_pid;
-      to->cpt_si_uid = from->si_uid;
+      to->cpt_si_pid = from_ptrace.cpt_si_pid;
+      to->cpt_si_uid = from_ptrace.cpt_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;
+      to->cpt_si_pid = from_ptrace.cpt_si_pid;
+      to->cpt_si_uid = from_ptrace.cpt_si_uid;
+      to->cpt_si_ptr = from_ptrace.cpt_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;
-         memcpy (&to->cpt_si_utime, &from->si_utime,
+         to->cpt_si_pid = from_ptrace.cpt_si_pid;
+         to->cpt_si_uid = from_ptrace.cpt_si_uid;
+         to->cpt_si_status = from_ptrace.cpt_si_status;
+         memcpy (&to->cpt_si_utime, &from_ptrace.cpt_si_utime,
                  sizeof (to->cpt_si_utime));
-         memcpy (&to->cpt_si_stime, &from->si_stime,
+         memcpy (&to->cpt_si_stime, &from_ptrace.cpt_si_stime,
                  sizeof (to->cpt_si_stime));
          break;
        case SIGILL:
        case SIGFPE:
        case SIGSEGV:
        case SIGBUS:
-         to->cpt_si_addr = (intptr_t) from->si_addr;
+         to->cpt_si_addr = from_ptrace.cpt_si_addr;
          break;
        case SIGPOLL:
-         to->cpt_si_band = from->si_band;
-         to->cpt_si_fd = from->si_fd;
+         to->cpt_si_band = from_ptrace.cpt_si_band;
+         to->cpt_si_fd = from_ptrace.cpt_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;
+         to->cpt_si_pid = from_ptrace.cpt_si_pid;
+         to->cpt_si_uid = from_ptrace.cpt_si_uid;
+         to->cpt_si_ptr = from_ptrace.cpt_si_ptr;
          break;
        }
     }
 }
 
+
+
+
 /* Convert the compatible x32 siginfo into system siginfo.  */
 static void
 siginfo_from_compat_x32_siginfo (siginfo_t *to,
-                                compat_x32_siginfo_t *from)
+                                const compat_x32_siginfo_t *from)
 {
-  memset (to, 0, sizeof (*to));
+  ptrace_siginfo_t to_ptrace;
 
-  to->si_signo = from->si_signo;
-  to->si_errno = from->si_errno;
-  to->si_code = from->si_code;
+  memset (&to_ptrace, 0, sizeof (to_ptrace));
+  to_ptrace.si_signo = from->si_signo;
+  to_ptrace.si_errno = from->si_errno;
+  to_ptrace.si_code = from->si_code;
 
-  if (to->si_code == SI_TIMER)
+  if (to_ptrace.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;
+      to_ptrace.cpt_si_timerid = from->cpt_si_timerid;
+      to_ptrace.cpt_si_overrun = from->cpt_si_overrun;
+      to_ptrace.cpt_si_ptr = from->cpt_si_ptr;
     }
-  else if (to->si_code == SI_USER)
+  else if (to_ptrace.si_code == SI_USER)
     {
-      to->si_pid = from->cpt_si_pid;
-      to->si_uid = from->cpt_si_uid;
+      to_ptrace.cpt_si_pid = from->cpt_si_pid;
+      to_ptrace.cpt_si_uid = from->cpt_si_uid;
     }
-  if (to->si_code < 0)
+  if (to_ptrace.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;
+      to_ptrace.cpt_si_pid = from->cpt_si_pid;
+      to_ptrace.cpt_si_uid = from->cpt_si_uid;
+      to_ptrace.cpt_si_ptr = from->cpt_si_ptr;
     }
   else
     {
-      switch (to->si_signo)
+      switch (to_ptrace.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;
-         memcpy (&to->si_utime, &from->cpt_si_utime,
-                 sizeof (to->si_utime));
-         memcpy (&to->si_stime, &from->cpt_si_stime,
-                 sizeof (to->si_stime));
+         to_ptrace.cpt_si_pid = from->cpt_si_pid;
+         to_ptrace.cpt_si_uid = from->cpt_si_uid;
+         to_ptrace.cpt_si_status = from->cpt_si_status;
+         memcpy (&to_ptrace.cpt_si_utime, &from->cpt_si_utime,
+                 sizeof (to_ptrace.cpt_si_utime));
+         memcpy (&to_ptrace.cpt_si_stime, &from->cpt_si_stime,
+                 sizeof (to_ptrace.cpt_si_stime));
          break;
        case SIGILL:
        case SIGFPE:
        case SIGSEGV:
        case SIGBUS:
-         to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
+         to_ptrace.cpt_si_addr = from->cpt_si_addr;
          break;
        case SIGPOLL:
-         to->si_band = from->cpt_si_band;
-         to->si_fd = from->cpt_si_fd;
+         to_ptrace.cpt_si_band = from->cpt_si_band;
+         to_ptrace.cpt_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;
+         to_ptrace.cpt_si_pid = from->cpt_si_pid;
+         to_ptrace.cpt_si_uid = from->cpt_si_uid;
+         to_ptrace.cpt_si_ptr = from->cpt_si_ptr;
          break;
        }
     }
+  memcpy (to, &to_ptrace, sizeof (to_ptrace));
 }
 
-/* Convert a native/host siginfo object, into/from the siginfo in the
+/* Convert a ptrace 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, then copy from NATIVE to INF.  */
+   from INF to PTRACE.  If DIRECTION is 0, then copy from NATIVE to
+   INF.  */
 
 int
-amd64_linux_siginfo_fixup_common (siginfo_t *native, gdb_byte *inf,
+amd64_linux_siginfo_fixup_common (siginfo_t *ptrace, gdb_byte *inf,
                                  int direction,
                                  enum amd64_siginfo_fixup_mode mode)
 {
   if (mode == FIXUP_32)
     {
-      gdb_assert (sizeof (siginfo_t) == sizeof (compat_siginfo_t));
-
       if (direction == 0)
-       compat_siginfo_from_siginfo ((struct compat_siginfo *) inf, native);
+       compat_siginfo_from_siginfo ((struct compat_siginfo *) inf, ptrace);
       else
-       siginfo_from_compat_siginfo (native, (struct compat_siginfo *) inf);
+       siginfo_from_compat_siginfo (ptrace, (struct compat_siginfo *) inf);
 
       return 1;
     }
   else if (mode == FIXUP_X32)
     {
-      gdb_assert (sizeof (siginfo_t) == sizeof (compat_x32_siginfo_t));
-
       if (direction == 0)
        compat_x32_siginfo_from_siginfo ((struct compat_x32_siginfo *) inf,
-                                        native);
+                                        ptrace);
       else
-       siginfo_from_compat_x32_siginfo (native,
+       siginfo_from_compat_x32_siginfo (ptrace,
                                         (struct compat_x32_siginfo *) inf);
 
       return 1;
     }
   return 0;
 }
+
+/* Sanity check for the siginfo structure sizes.  */
+
+gdb_static_assert (sizeof (siginfo_t) == GDB_SI_SIZE);
+#ifndef __ILP32__
+gdb_static_assert (sizeof (nat_siginfo_t) == GDB_SI_SIZE);
+#endif
+gdb_static_assert (sizeof (compat_x32_siginfo_t) == GDB_SI_SIZE);
+gdb_static_assert (sizeof (compat_siginfo_t) == GDB_SI_SIZE);
+gdb_static_assert (sizeof (ptrace_siginfo_t) == GDB_SI_SIZE);
This page took 0.034048 seconds and 4 git commands to generate.