#include "common-defs.h"
 #include "amd64-linux-siginfo.h"
 
+/* The nat_* types below define the most complete kernel siginfo type
+   known for the architecture, independent of the system/libc headers.  */
+
+typedef int nat_int_t;
+typedef void* nat_uptr_t;
+
+typedef int nat_time_t;
+typedef int nat_timer_t;
+
+/* For native 64-bit, clock_t in _sigchld is 64bit aligned at 4 bytes.  */
+typedef long __attribute__ ((__aligned__ (4))) nat_clock_t;
+
+struct nat_timeval
+{
+  nat_time_t tv_sec;
+  int tv_usec;
+};
+
+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 __attribute__ ((__aligned__ (8)));
+
+/*  Sanity check for the siginfo structure size.  */
+
+gdb_static_assert (sizeof (nat_siginfo_t) == sizeof (siginfo_t));
+
 /* These types below (compat_*) define a siginfo type that is layout
    compatible with the siginfo type exported by the 32-bit userspace
    support.  */
     struct
     {
       unsigned int _addr;
+      short int _addr_lsb;
+      struct
+      {
+       unsigned int _lower;
+       unsigned int _upper;
+      } si_addr_bnd;
     } _sigfault;
 
     /* SIGPOLL */
     struct
     {
       unsigned int _addr;
+      unsigned int _addr_lsb;
     } _sigfault;
 
     /* SIGPOLL */
 #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
 
 static void
 compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
 {
+  nat_siginfo_t from_nat;
+
+  memcpy (&from_nat, from, sizeof (from_nat));
   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_nat.si_signo;
+  to->si_errno = from_nat.si_errno;
+  to->si_code = from_nat.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_nat.cpt_si_timerid;
+      to->cpt_si_overrun = from_nat.cpt_si_overrun;
+      to->cpt_si_ptr = (intptr_t) from_nat.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_nat.cpt_si_pid;
+      to->cpt_si_uid = from_nat.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_nat.cpt_si_pid;
+      to->cpt_si_uid = from_nat.cpt_si_uid;
+      to->cpt_si_ptr = (intptr_t) from_nat.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_nat.cpt_si_pid;
+         to->cpt_si_uid = from_nat.cpt_si_uid;
+         to->cpt_si_status = from_nat.cpt_si_status;
+         to->cpt_si_utime = from_nat.cpt_si_utime;
+         to->cpt_si_stime = from_nat.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 = (intptr_t) from_nat.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_nat.cpt_si_band;
+         to->cpt_si_fd = from_nat.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_nat.cpt_si_pid;
+         to->cpt_si_uid = from_nat.cpt_si_uid;
+         to->cpt_si_ptr = (intptr_t) from_nat.cpt_si_ptr;
          break;
        }
     }
 static void
 siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
 {
-  memset (to, 0, sizeof (*to));
+  nat_siginfo_t to_nat;
 
-  to->si_signo = from->si_signo;
-  to->si_errno = from->si_errno;
-  to->si_code = from->si_code;
+  memset (&to_nat, 0, sizeof (to_nat));
 
-  if (to->si_code == SI_TIMER)
+  to_nat.si_signo = from->si_signo;
+  to_nat.si_errno = from->si_errno;
+  to_nat.si_code = from->si_code;
+
+  if (to_nat.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_nat.cpt_si_timerid = from->cpt_si_timerid;
+      to_nat.cpt_si_overrun = from->cpt_si_overrun;
+      to_nat.cpt_si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
     }
-  else if (to->si_code == SI_USER)
+  else if (to_nat.si_code == SI_USER)
     {
-      to->si_pid = from->cpt_si_pid;
-      to->si_uid = from->cpt_si_uid;
+      to_nat.cpt_si_pid = from->cpt_si_pid;
+      to_nat.cpt_si_uid = from->cpt_si_uid;
     }
-  if (to->si_code < 0)
+  if (to_nat.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_nat.cpt_si_pid = from->cpt_si_pid;
+      to_nat.cpt_si_uid = from->cpt_si_uid;
+      to_nat.cpt_si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
     }
   else
     {
-      switch (to->si_signo)
+      switch (to_nat.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_nat.cpt_si_pid = from->cpt_si_pid;
+         to_nat.cpt_si_uid = from->cpt_si_uid;
+         to_nat.cpt_si_status = from->cpt_si_status;
+         to_nat.cpt_si_utime = from->cpt_si_utime;
+         to_nat.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_nat.cpt_si_addr = (void *) (intptr_t) from->cpt_si_addr;
+         to_nat.cpt_si_addr_lsb = (short) from->cpt_si_addr_lsb;
          break;
        case SIGPOLL:
-         to->si_band = from->cpt_si_band;
-         to->si_fd = from->cpt_si_fd;
+         to_nat.cpt_si_band = from->cpt_si_band;
+         to_nat.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_nat.cpt_si_pid = from->cpt_si_pid;
+         to_nat.cpt_si_uid = from->cpt_si_uid;
+         to_nat.cpt_si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
          break;
        }
     }
+  memcpy (to, &to_nat, sizeof (to_nat));
 }
 
 /*  Convert the system provided siginfo into compatible x32 siginfo.  */
 compat_x32_siginfo_from_siginfo (compat_x32_siginfo_t *to,
                                 siginfo_t *from)
 {
+  nat_siginfo_t from_nat;
+
+  memcpy (&from_nat, from, sizeof (from_nat));
   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_nat.si_signo;
+  to->si_errno = from_nat.si_errno;
+  to->si_code = from_nat.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_nat.cpt_si_timerid;
+      to->cpt_si_overrun = from_nat.cpt_si_overrun;
+      to->cpt_si_ptr = (intptr_t) from_nat.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_nat.cpt_si_pid;
+      to->cpt_si_uid = from_nat.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_nat.cpt_si_pid;
+      to->cpt_si_uid = from_nat.cpt_si_uid;
+      to->cpt_si_ptr = (intptr_t) from_nat.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_nat.cpt_si_pid;
+         to->cpt_si_uid = from_nat.cpt_si_uid;
+         to->cpt_si_status = from_nat.cpt_si_status;
+         memcpy (&to->cpt_si_utime, &from_nat.cpt_si_utime,
                  sizeof (to->cpt_si_utime));
-         memcpy (&to->cpt_si_stime, &from->si_stime,
+         memcpy (&to->cpt_si_stime, &from_nat.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 = (intptr_t) from_nat.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_nat.cpt_si_band;
+         to->cpt_si_fd = from_nat.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_nat.cpt_si_pid;
+         to->cpt_si_uid = from_nat.cpt_si_uid;
+         to->cpt_si_ptr = (intptr_t) from_nat.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)
 {
-  memset (to, 0, sizeof (*to));
+  nat_siginfo_t to_nat;
 
-  to->si_signo = from->si_signo;
-  to->si_errno = from->si_errno;
-  to->si_code = from->si_code;
+  memset (&to_nat, 0, sizeof (to_nat));
+  to_nat.si_signo = from->si_signo;
+  to_nat.si_errno = from->si_errno;
+  to_nat.si_code = from->si_code;
 
-  if (to->si_code == SI_TIMER)
+  if (to_nat.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_nat.cpt_si_timerid = from->cpt_si_timerid;
+      to_nat.cpt_si_overrun = from->cpt_si_overrun;
+      to_nat.cpt_si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
     }
-  else if (to->si_code == SI_USER)
+  else if (to_nat.si_code == SI_USER)
     {
-      to->si_pid = from->cpt_si_pid;
-      to->si_uid = from->cpt_si_uid;
+      to_nat.cpt_si_pid = from->cpt_si_pid;
+      to_nat.cpt_si_uid = from->cpt_si_uid;
     }
-  if (to->si_code < 0)
+  if (to_nat.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_nat.cpt_si_pid = from->cpt_si_pid;
+      to_nat.cpt_si_uid = from->cpt_si_uid;
+      to_nat.cpt_si_ptr = (void *) (intptr_t) from->cpt_si_ptr;
     }
   else
     {
-      switch (to->si_signo)
+      switch (to_nat.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_nat.cpt_si_pid = from->cpt_si_pid;
+         to_nat.cpt_si_uid = from->cpt_si_uid;
+         to_nat.cpt_si_status = from->cpt_si_status;
+         memcpy (&to_nat.cpt_si_utime, &from->cpt_si_utime,
+                 sizeof (to_nat.cpt_si_utime));
+         memcpy (&to_nat.cpt_si_stime, &from->cpt_si_stime,
+                 sizeof (to_nat.cpt_si_stime));
          break;
        case SIGILL:
        case SIGFPE:
        case SIGSEGV:
        case SIGBUS:
-         to->si_addr = (void *) (intptr_t) from->cpt_si_addr;
+         to_nat.cpt_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;
+         to_nat.cpt_si_band = from->cpt_si_band;
+         to_nat.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_nat.cpt_si_pid = from->cpt_si_pid;
+         to_nat.cpt_si_uid = from->cpt_si_uid;
+         to_nat.cpt_si_ptr = (void* ) (intptr_t) from->cpt_si_ptr;
          break;
        }
     }
+  memcpy (to, &to_nat, sizeof (to_nat));
 }
 
 /* Convert a native/host siginfo object, into/from the siginfo in the