[PATCH V3 5/6] Adaptation of siginfo fixup for the new bnd fields.

Walfred Tedeschi walfred.tedeschi@intel.com
Mon Jan 18 08:26:00 GMT 2016


New bnds fields will be always present for x86 architecture.
Fixup for compatibility layer 32bits has to be fixed.

It was added the nat_siginfo to serving as intermediate step
between kernel provided siginfo and the fix up routine.

When executing compat_siginfo_from_siginfo or
compat_x32_siginfo_from_siginfo first the buffer read from the kernel are
converted into the nat_signfo for homogenization, then the fields of
nat_siginfo are use to set the compat and compat_x32 siginfo structures.

When executing  siginfo_from_compat_siginfo or
siginfo_from_compat_x32_siginfo the process happens in oposite order.

In doing this the fixups become more independent of the system underneath.

Caveat: No support for MPX on x32.

2015-01-15  Walfred Tedeschi  <walfred.tedeschi@intel.com>

gdb/ChangeLog:

	* amd64-linux-siginfo.c (nat_siginfo_t, nat_sigval_t, nat_timeval):
	New types.
	(compat_siginfo): New bound fields added.
	(compat_x32_siginfo): New field added.
	(cpt_si_addr_lsb): New define.
	(compat_siginfo_from_siginfo): Use nat_siginfo.
	(siginfo_from_compat_siginfo): Use nat_siginfo.
	(compat_x32_siginfo_from_siginfo): Likewise.
	(siginfo_from_compat_x32_siginfo): Likewise.

---
 gdb/nat/amd64-linux-siginfo.c | 312 ++++++++++++++++++++++++++++--------------
 gdb/nat/amd64-linux-siginfo.h |  16 ++-
 2 files changed, 226 insertions(+), 102 deletions(-)

diff --git a/gdb/nat/amd64-linux-siginfo.c b/gdb/nat/amd64-linux-siginfo.c
index 7045ff2..ac5c138 100644
--- a/gdb/nat/amd64-linux-siginfo.c
+++ b/gdb/nat/amd64-linux-siginfo.c
@@ -21,6 +21,93 @@
 #include "common-defs.h"
 #include "amd64-linux-siginfo.h"
 
+/* These types below (native_*) define a siginfo type that is layout
+   the most complete siginfo available for the architecture.  */
+
+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)));
+
 /* 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 +178,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 +245,7 @@ typedef struct compat_x32_siginfo
     struct
     {
       unsigned int _addr;
+      unsigned int _addr_lsb;
     } _sigfault;
 
     /* SIGPOLL */
@@ -174,6 +268,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
 
@@ -190,54 +285,58 @@ typedef struct compat_x32_siginfo
 static void
 compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
 {
+  nat_siginfo_t from_nat;
+
+  gdb_assert (sizeof (nat_siginfo_t) == sizeof (siginfo_t));
+  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;
 	}
     }
@@ -247,57 +346,62 @@ compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from)
 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;
+  gdb_assert (sizeof (nat_siginfo_t) == sizeof (siginfo_t));
+  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));
 }
 
 /*  Converts the system provided siginfo into compatible x32 siginfo.  */
@@ -305,56 +409,60 @@ static void
 compat_x32_siginfo_from_siginfo (compat_x32_siginfo_t *to,
 				 siginfo_t *from)
 {
+  nat_siginfo_t from_nat;
+
+  gdb_assert (sizeof (nat_siginfo_t) == sizeof (siginfo_t));
+  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;
 	}
     }
@@ -365,59 +473,63 @@ 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;
+  gdb_assert (sizeof (nat_siginfo_t) == sizeof (siginfo_t));
+  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;
-	  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
diff --git a/gdb/nat/amd64-linux-siginfo.h b/gdb/nat/amd64-linux-siginfo.h
index 11738fb..e6de70b 100644
--- a/gdb/nat/amd64-linux-siginfo.h
+++ b/gdb/nat/amd64-linux-siginfo.h
@@ -20,12 +20,24 @@
 #ifndef AMD64_LINUX_SIGINFO_H
 #define AMD64_LINUX_SIGINFO_H 1
 
-
 /* When GDB is built as a 64-bit application on linux, the
    PTRACE_GETSIGINFO data is always presented in 64-bit layout.  Since
    debugging a 32-bit inferior with a 64-bit GDB should look the same
    as debugging it with a 32-bit GDB, we do the 32-bit <-> 64-bit
-   conversion in-place ourselves.  */
+   conversion in-place ourselves.
+   In other to make this conversion independent of the system where gdb
+   is compiled the most complete version of the siginfo, named as native
+   siginfo, is used internally as an intermediate step.
+
+   Conversion using nat_siginfo is exemplified below:
+   compat_siginfo_from_siginfo or compat_x32_siginfo_from_siginfo
+
+      buffer (from the kernel) -> nat_siginfo -> 32 / X32 siginfo
+
+   siginfo_from_compat_x32_siginfo or siginfo_from_compat_siginfo
+
+     32 / X32 siginfo -> nat_siginfo -> buffer (to the kernel)  */
+
 
 /* Kind of siginfo fixup to be performed.  */
 
-- 
2.1.4



More information about the Gdb-patches mailing list