Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* PATCH: Convert siginfo for x32 in gdbserver
@ 2012-04-12 17:21 H.J. Lu
  2012-04-12 20:14 ` Pedro Alves
  2012-04-12 20:27 ` H.J. Lu
  0 siblings, 2 replies; 5+ messages in thread
From: H.J. Lu @ 2012-04-12 17:21 UTC (permalink / raw)
  To: GDB; +Cc: Pedro Alves

Hi,

X32 siginfo is different from ia32 siginfo and x86-64 siginfo.  X32
siginfo has 32bit pointers and 64bit clock_t.  This patch adds x32
support to x86_siginfo_fixup.  OK to install?

Thanks.

H.J.
---
    	* linux-x86-low.c (compat_x32_clock_t): New.
    	(compat_x32_siginfo_t): Likewise.
    	(compat_x32_siginfo_from_siginfo): Likewise.
    	(siginfo_from_compat_x32_siginfo): Likewise.
    	(x86_siginfo_fixup): Call compat_x32_siginfo_from_siginfo
    	and siginfo_from_compat_x32_siginfo for x32.

diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index a686666..bca98cb 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -780,6 +780,67 @@ typedef struct compat_siginfo
   } _sifields;
 } compat_siginfo_t;
 
+/* For x32, clock_t in _sigchld is 64bit aligned at 4 bytes.  */
+typedef long __attribute__ ((__aligned__ (4))) compat_x32_clock_t;
+
+typedef struct compat_x32_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_x32_clock_t _utime;
+      compat_x32_clock_t _stime;
+    } _sigchld;
+
+    /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+    struct
+    {
+      unsigned int _addr;
+    } _sigfault;
+
+    /* SIGPOLL */
+    struct
+    {
+      int _band;
+      int _fd;
+    } _sigpoll;
+  } _sifields;
+} compat_x32_siginfo_t __attribute__ ((__aligned__ (8)));
+
 #define cpt_si_pid _sifields._kill._pid
 #define cpt_si_uid _sifields._kill._uid
 #define cpt_si_timerid _sifields._timer._tid
@@ -913,6 +974,120 @@ siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
     }
 }
 
+static void
+compat_x32_siginfo_from_siginfo (compat_x32_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;
+	}
+    }
+}
+
+static void
+siginfo_from_compat_x32_siginfo (siginfo_t *to,
+				 compat_x32_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;
+    }
+  else 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;
+	}
+    }
+}
+
 #endif /* __x86_64__ */
 
 /* Convert a native/host siginfo object, into/from the siginfo in the
@@ -938,6 +1113,21 @@ x86_siginfo_fixup (siginfo_t *native, void *inf, int direction)
 
       return 1;
     }
+  /* No fixup for native x32 GDB.  */
+  else if (sizeof (void *) == 8)
+    {
+      if (sizeof (siginfo_t) != sizeof (compat_siginfo_t))
+	fatal ("unexpected difference in siginfo");
+
+      if (direction == 0)
+	compat_x32_siginfo_from_siginfo ((struct compat_x32_siginfo *) inf,
+					 native);
+      else
+	siginfo_from_compat_x32_siginfo (native,
+					 (struct compat_x32_siginfo *) inf);
+
+      return 1;
+    }
 #endif
 
   return 0;


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: Convert siginfo for x32 in gdbserver
  2012-04-12 17:21 PATCH: Convert siginfo for x32 in gdbserver H.J. Lu
@ 2012-04-12 20:14 ` Pedro Alves
  2012-04-12 20:58   ` H.J. Lu
  2012-04-12 20:27 ` H.J. Lu
  1 sibling, 1 reply; 5+ messages in thread
From: Pedro Alves @ 2012-04-12 20:14 UTC (permalink / raw)
  To: H.J. Lu; +Cc: H.J. Lu, GDB

On 04/12/2012 06:20 PM, H.J. Lu wrote:

>  /* Convert a native/host siginfo object, into/from the siginfo in the
> @@ -938,6 +1113,21 @@ x86_siginfo_fixup (siginfo_t *native, void *inf, int direction)
>  
>        return 1;
>      }
> +  /* No fixup for native x32 GDB.  */
> +  else if (sizeof (void *) == 8)


I'm confused.  Isn't this _also_ reached when both the inferior and gdbserver are 64-bit?
There should also be no fixup then.

> +    {
> +      if (sizeof (siginfo_t) != sizeof (compat_siginfo_t))


      if (sizeof (siginfo_t) != sizeof (compat_x32_siginfo_t))

> +	fatal ("unexpected difference in siginfo");
> +
> +      if (direction == 0)
> +	compat_x32_siginfo_from_siginfo ((struct compat_x32_siginfo *) inf,
> +					 native);
> +      else
> +	siginfo_from_compat_x32_siginfo (native,
> +					 (struct compat_x32_siginfo *) inf);
> +
> +      return 1;
> +    }
>  #endif
>  



-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: Convert siginfo for x32 in gdbserver
  2012-04-12 17:21 PATCH: Convert siginfo for x32 in gdbserver H.J. Lu
  2012-04-12 20:14 ` Pedro Alves
@ 2012-04-12 20:27 ` H.J. Lu
  2012-04-12 21:26   ` Pedro Alves
  1 sibling, 1 reply; 5+ messages in thread
From: H.J. Lu @ 2012-04-12 20:27 UTC (permalink / raw)
  To: GDB, Pedro Alves

On Thu, Apr 12, 2012 at 10:20:00AM -0700, H.J. Lu wrote:
> Hi,
> 
> X32 siginfo is different from ia32 siginfo and x86-64 siginfo.  X32
> siginfo has 32bit pointers and 64bit clock_t.  This patch adds x32
> support to x86_siginfo_fixup.  OK to install?
> 

Here is an updated patch.  We need to convert siginfo for x32 only if
the inferior isn't 64-bit and our point size is 64bit.  OK to install?

Thanks.

H.J.
--
	* linux-x86-low.c (compat_x32_clock_t): New.
	(compat_x32_siginfo_t): Likewise.
	(compat_x32_siginfo_from_siginfo): Likewise.
	(siginfo_from_compat_x32_siginfo): Likewise.
	(linux_is_elf64): Likewise.
	(x86_siginfo_fixup): Call compat_x32_siginfo_from_siginfo
	and siginfo_from_compat_x32_siginfo for x32.
	(x86_arch_setup): Set linux_is_elf64.

diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c
index 3dcae00..1c466af 100644
--- a/gdb/gdbserver/linux-x86-low.c
+++ b/gdb/gdbserver/linux-x86-low.c
@@ -776,6 +776,67 @@ typedef struct compat_siginfo
   } _sifields;
 } compat_siginfo_t;
 
+/* For x32, clock_t in _sigchld is 64bit aligned at 4 bytes.  */
+typedef long __attribute__ ((__aligned__ (4))) compat_x32_clock_t;
+
+typedef struct compat_x32_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_x32_clock_t _utime;
+      compat_x32_clock_t _stime;
+    } _sigchld;
+
+    /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+    struct
+    {
+      unsigned int _addr;
+    } _sigfault;
+
+    /* SIGPOLL */
+    struct
+    {
+      int _band;
+      int _fd;
+    } _sigpoll;
+  } _sifields;
+} compat_x32_siginfo_t __attribute__ ((__aligned__ (8)));
+
 #define cpt_si_pid _sifields._kill._pid
 #define cpt_si_uid _sifields._kill._uid
 #define cpt_si_timerid _sifields._timer._tid
@@ -909,6 +970,122 @@ siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from)
     }
 }
 
+static void
+compat_x32_siginfo_from_siginfo (compat_x32_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;
+	}
+    }
+}
+
+static void
+siginfo_from_compat_x32_siginfo (siginfo_t *to,
+				 compat_x32_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;
+    }
+  else 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;
+	}
+    }
+}
+
+/* Is this process 64-bit?  */
+static int linux_is_elf64;
 #endif /* __x86_64__ */
 
 /* Convert a native/host siginfo object, into/from the siginfo in the
@@ -934,6 +1111,21 @@ x86_siginfo_fixup (siginfo_t *native, void *inf, int direction)
 
       return 1;
     }
+  /* No fixup for native x32 GDB.  */
+  else if (!linux_is_elf64 && sizeof (void *) == 8)
+    {
+      if (sizeof (siginfo_t) != sizeof (compat_x32_siginfo_t))
+	fatal ("unexpected difference in siginfo");
+
+      if (direction == 0)
+	compat_x32_siginfo_from_siginfo ((struct compat_x32_siginfo *) inf,
+					 native);
+      else
+	siginfo_from_compat_x32_siginfo (native,
+					 (struct compat_x32_siginfo *) inf);
+
+      return 1;
+    }
 #endif
 
   return 0;
@@ -1138,6 +1330,7 @@ x86_arch_setup (void)
       /* Amd64 has 16 xmm regs.  */
       num_xmm_registers = 16;
 
+      linux_is_elf64 = is_elf64;
       x86_linux_update_xmltarget ();
       return;
     }


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: Convert siginfo for x32 in gdbserver
  2012-04-12 20:14 ` Pedro Alves
@ 2012-04-12 20:58   ` H.J. Lu
  0 siblings, 0 replies; 5+ messages in thread
From: H.J. Lu @ 2012-04-12 20:58 UTC (permalink / raw)
  To: Pedro Alves; +Cc: GDB

On Thu, Apr 12, 2012 at 12:40 PM, Pedro Alves <palves@redhat.com> wrote:
> On 04/12/2012 06:20 PM, H.J. Lu wrote:
>
>>  /* Convert a native/host siginfo object, into/from the siginfo in the
>> @@ -938,6 +1113,21 @@ x86_siginfo_fixup (siginfo_t *native, void *inf, int direction)
>>
>>        return 1;
>>      }
>> +  /* No fixup for native x32 GDB.  */
>> +  else if (sizeof (void *) == 8)
>
>
> I'm confused.  Isn't this _also_ reached when both the inferior and gdbserver are 64-bit?
> There should also be no fixup then.

Oops.  I need to check the inferior isn't 64-bit.

>> +    {
>> +      if (sizeof (siginfo_t) != sizeof (compat_siginfo_t))
>
>
>      if (sizeof (siginfo_t) != sizeof (compat_x32_siginfo_t))
>

Fixed.   I posted an updated patch.

Thanks.

-- 
H.J.


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: PATCH: Convert siginfo for x32 in gdbserver
  2012-04-12 20:27 ` H.J. Lu
@ 2012-04-12 21:26   ` Pedro Alves
  0 siblings, 0 replies; 5+ messages in thread
From: Pedro Alves @ 2012-04-12 21:26 UTC (permalink / raw)
  To: H.J. Lu; +Cc: H.J. Lu, GDB

On 04/12/2012 09:25 PM, H.J. Lu wrote:

> +/* Is this process 64-bit?  */
> +static int linux_is_elf64;
>  #endif /* __x86_64__ */
>  
>  /* Convert a native/host siginfo object, into/from the siginfo in the
> @@ -934,6 +1111,21 @@ x86_siginfo_fixup (siginfo_t *native, void *inf, int direction)
>  
>        return 1;
>      }
> +  /* No fixup for native x32 GDB.  */
> +  else if (!linux_is_elf64 && sizeof (void *) == 8)
> +    {
> +      if (sizeof (siginfo_t) != sizeof (compat_x32_siginfo_t))
> +	fatal ("unexpected difference in siginfo");
> +
> +      if (direction == 0)
> +	compat_x32_siginfo_from_siginfo ((struct compat_x32_siginfo *) inf,
> +					 native);
> +      else
> +	siginfo_from_compat_x32_siginfo (native,
> +					 (struct compat_x32_siginfo *) inf);
> +
> +      return 1;
> +    }
>  #endif
>  
>    return 0;
> @@ -1138,6 +1330,7 @@ x86_arch_setup (void)
>        /* Amd64 has 16 xmm regs.  */
>        num_xmm_registers = 16;
>  
> +      linux_is_elf64 = is_elf64;
>        x86_linux_update_xmltarget ();
>        return;
>      }


This new global is buggy in that in extended-remote mode (gdbserver --multi):
you can start a 64-bit inferior, kill it, then start a 32-bit inferior.
So clear it also in the 32-bit inferior case.  Okay with that change.

This new flag should be made a per-inferior flag, probably as a
new process->private->is_elf64 flag, but the status quo is that
there are other similar globals, so I'm okay with a new one,
and I'll fix them all in the ongoing multi-process+multi-arch
series.

Thanks.

-- 
Pedro Alves


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2012-04-12 20:58 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-12 17:21 PATCH: Convert siginfo for x32 in gdbserver H.J. Lu
2012-04-12 20:14 ` Pedro Alves
2012-04-12 20:58   ` H.J. Lu
2012-04-12 20:27 ` H.J. Lu
2012-04-12 21:26   ` Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox