* 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