* PATCH: Support x32 siginfo_t conversion @ 2012-05-11 19:21 H.J. Lu 2012-05-11 20:11 ` Mark Kettenis 0 siblings, 1 reply; 6+ messages in thread From: H.J. Lu @ 2012-05-11 19:21 UTC (permalink / raw) To: GDB Hi, This patch implements x32 siginfo_t conversion. Tested on Linux/x86-64. OK to install? Thanks. H.J. -- * amd64-linux-nat.c (compat_x32_clock_t): New. (compat_x32_siginfo_t): Likewise. (compat_x32_siginfo_from_siginfo): Likewise. (siginfo_from_compat_x32_siginfo): Likewise. (amd64_linux_siginfo_fixup): Call compat_x32_siginfo_from_siginfo and siginfo_from_compat_x32_siginfo for x32. diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c index 3be8404..97c9a49 100644 --- a/gdb/amd64-linux-nat.c +++ b/gdb/amd64-linux-nat.c @@ -591,6 +591,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 @@ -724,6 +785,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; + } + 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; + } + } +} + /* Convert a native/host 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 @@ -747,6 +922,20 @@ amd64_linux_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction) return 1; } + /* No fixup for native x32 GDB. */ + else if (gdbarch_addr_bit (gdbarch) == 32 && sizeof (void *) == 8) + { + gdb_assert (sizeof (siginfo_t) == sizeof (compat_x32_siginfo_t)); + + 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; + } else return 0; } ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PATCH: Support x32 siginfo_t conversion 2012-05-11 19:21 PATCH: Support x32 siginfo_t conversion H.J. Lu @ 2012-05-11 20:11 ` Mark Kettenis 2012-05-11 20:55 ` H.J. Lu 0 siblings, 1 reply; 6+ messages in thread From: Mark Kettenis @ 2012-05-11 20:11 UTC (permalink / raw) To: hjl.tools; +Cc: gdb-patches > Date: Fri, 11 May 2012 12:21:33 -0700 > From: "H.J. Lu" <hongjiu.lu@intel.com> > > Hi, > > This patch implements x32 siginfo_t conversion. Tested on Linux/x86-64. > OK to install? > > Thanks. > > > H.J. > -- > * amd64-linux-nat.c (compat_x32_clock_t): New. > (compat_x32_siginfo_t): Likewise. > (compat_x32_siginfo_from_siginfo): Likewise. > (siginfo_from_compat_x32_siginfo): Likewise. > (amd64_linux_siginfo_fixup): Call compat_x32_siginfo_from_siginfo > and siginfo_from_compat_x32_siginfo for x32. > > diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c > index 3be8404..97c9a49 100644 > --- a/gdb/amd64-linux-nat.c > +++ b/gdb/amd64-linux-nat.c > @@ -591,6 +591,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; Sorry, but that isn't acceptable. Is your X32 ABI really that broken? > +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))); Same here. I don't think you need alignment here, even with the broken ABI. If it really is too late to fix the X32 ABI, you'll have to write this portably by splitting _utime and _stime into two 32-bit variables and write code that correctly sets the upper and lower 32-bits. > + > #define cpt_si_pid _sifields._kill._pid > #define cpt_si_uid _sifields._kill._uid > #define cpt_si_timerid _sifields._timer._tid > @@ -724,6 +785,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; > + } > + 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; > + } > + } > +} > + > /* Convert a native/host 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 > @@ -747,6 +922,20 @@ amd64_linux_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction) > > return 1; > } > + /* No fixup for native x32 GDB. */ > + else if (gdbarch_addr_bit (gdbarch) == 32 && sizeof (void *) == 8) > + { > + gdb_assert (sizeof (siginfo_t) == sizeof (compat_x32_siginfo_t)); > + > + 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; > + } > else > return 0; > } > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PATCH: Support x32 siginfo_t conversion 2012-05-11 20:11 ` Mark Kettenis @ 2012-05-11 20:55 ` H.J. Lu 2012-05-12 21:16 ` Mark Kettenis 0 siblings, 1 reply; 6+ messages in thread From: H.J. Lu @ 2012-05-11 20:55 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches On Fri, May 11, 2012 at 1:11 PM, Mark Kettenis <mark.kettenis@xs4all.nl> wrote: >> Date: Fri, 11 May 2012 12:21:33 -0700 >> From: "H.J. Lu" <hongjiu.lu@intel.com> >> >> Hi, >> >> This patch implements x32 siginfo_t conversion. Tested on Linux/x86-64. >> OK to install? >> >> Thanks. >> >> >> H.J. >> -- >> * amd64-linux-nat.c (compat_x32_clock_t): New. >> (compat_x32_siginfo_t): Likewise. >> (compat_x32_siginfo_from_siginfo): Likewise. >> (siginfo_from_compat_x32_siginfo): Likewise. >> (amd64_linux_siginfo_fixup): Call compat_x32_siginfo_from_siginfo >> and siginfo_from_compat_x32_siginfo for x32. >> >> diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c >> index 3be8404..97c9a49 100644 >> --- a/gdb/amd64-linux-nat.c >> +++ b/gdb/amd64-linux-nat.c >> @@ -591,6 +591,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; > > Sorry, but that isn't acceptable. > > Is your X32 ABI really that broken? > >> +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))); > > Same here. I don't think you need alignment here, even with the broken ABI. > > If it really is too late to fix the X32 ABI, you'll have to write this > portably by splitting _utime and _stime into two 32-bit variables and > write code that correctly sets the upper and lower 32-bits. > > X32 ABI choice is done on purpose. X32 siginfo_t has typedef long __attribute__ ((__aligned__ (4))) compat_x32_clock_t; typedef struct compat_x32_siginfo { int si_signo; int si_errno; int si_code; union { ... /* SIGCHLD */ struct { unsigned int _pid; unsigned int _uid; int _status; compat_x32_clock_t _utime; compat_x32_clock_t _stime; } _sigchld; ... } compat_x32_siginfo_t __attribute__ ((__aligned__ (8))); struct info is aligned at 8 bytes and type of _utime/_stime is aligned at 4 bytes. However, _utime offset is 3 * 4 + 3 * 4 == 24 bytes. So in reality, the addresses of _utime/_stime are 8 bytes aligned. There are no needs to split _utime and _stime into two 32-bit variables since their addresses are 64bits aligned. Thanks. -- H.J. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PATCH: Support x32 siginfo_t conversion 2012-05-11 20:55 ` H.J. Lu @ 2012-05-12 21:16 ` Mark Kettenis 2012-05-12 23:16 ` H.J. Lu 0 siblings, 1 reply; 6+ messages in thread From: Mark Kettenis @ 2012-05-12 21:16 UTC (permalink / raw) To: hjl.tools; +Cc: gdb-patches [-- Warning: decoded text below may be mangled, UTF-8 assumed --] [-- Attachment #1: Type: text/plain, Size: 4432 bytes --] > Date: Fri, 11 May 2012 13:55:29 -0700 > From: "H.J. Lu" <hjl.tools@gmail.com> > > On Fri, May 11, 2012 at 1:11 PM, Mark Kettenis <mark.kettenis@xs4all.nl> wrote: > >> Date: Fri, 11 May 2012 12:21:33 -0700 > >> From: "H.J. Lu" <hongjiu.lu@intel.com> > >> > >> Hi, > >> > >> This patch implements x32 siginfo_t conversion. Tested on Linux/x86-64. > >> OK to install? > >> > >> Thanks. > >> > >> > >> H.J. > >> -- > >> * amd64-linux-nat.c (compat_x32_clock_t): New. > >> (compat_x32_siginfo_t): Likewise. > >> (compat_x32_siginfo_from_siginfo): Likewise. > >> (siginfo_from_compat_x32_siginfo): Likewise. > >> (amd64_linux_siginfo_fixup): Call compat_x32_siginfo_from_siginfo > >> and siginfo_from_compat_x32_siginfo for x32. > >> > >> diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c > >> index 3be8404..97c9a49 100644 > >> --- a/gdb/amd64-linux-nat.c > >> +++ b/gdb/amd64-linux-nat.c > >> @@ -591,6 +591,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; > > > > Sorry, but that isn't acceptable. > > > > Is your X32 ABI really that broken? > > > >> +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))); > > > > Same here. I don't think you need alignment here, even with the broken ABI. > > > > If it really is too late to fix the X32 ABI, you'll have to write this > > portably by splitting _utime and _stime into two 32-bit variables and > > write code that correctly sets the upper and lower 32-bits. > > > > > > X32 ABI choice is done on purpose. X32 siginfo_t has > > typedef long __attribute__ ((__aligned__ (4))) compat_x32_clock_t; > > typedef struct compat_x32_siginfo > { > int si_signo; > int si_errno; > int si_code; > > union > { > ... > /* SIGCHLD */ > struct > { > unsigned int _pid; > unsigned int _uid; > int _status; > compat_x32_clock_t _utime; > compat_x32_clock_t _stime; > } _sigchld; > ... > } compat_x32_siginfo_t __attribute__ ((__aligned__ (8))); > > struct info is aligned at 8 bytes and type of _utime/_stime is aligned > at 4 bytes. However, _utime offset is 3 * 4 + 3 * 4 == 24 bytes. So > in reality, the addresses of _utime/_stime are 8 bytes aligned. There > are no needs to split _utime and _stime into two 32-bit variables > since their addresses are 64bits aligned. But there is no way you can easily express that syntax with standard C syntax[1]. That's why you had to resort to using GCC's __attribute__ syntax. For GDB you'll have to figure out a way to do this without using __attribute__ ((__aligned__ (...))). My recommendation would be to define a compat_x32 structure just for SIGCHLD (without using a union) and use the normal 32-bit comap structure for all the other conversions. Cheers, Mark [1] Well there is in C11, but you can't rely on that being properly implemented for at least another 5 years or so. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PATCH: Support x32 siginfo_t conversion 2012-05-12 21:16 ` Mark Kettenis @ 2012-05-12 23:16 ` H.J. Lu 2012-05-13 2:25 ` H.J. Lu 0 siblings, 1 reply; 6+ messages in thread From: H.J. Lu @ 2012-05-12 23:16 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches On Sat, May 12, 2012 at 2:16 PM, Mark Kettenis <mark.kettenis@xs4all.nl> wrote: >> Date: Fri, 11 May 2012 13:55:29 -0700 >> From: "H.J. Lu" <hjl.tools@gmail.com> >> >> On Fri, May 11, 2012 at 1:11 PM, Mark Kettenis <mark.kettenis@xs4all.nl> wrote: >> >> Date: Fri, 11 May 2012 12:21:33 -0700 >> >> From: "H.J. Lu" <hongjiu.lu@intel.com> >> >> >> >> Hi, >> >> >> >> This patch implements x32 siginfo_t conversion. Tested on Linux/x86-64. >> >> OK to install? >> >> >> >> Thanks. >> >> >> >> >> >> H.J. >> >> -- >> >> * amd64-linux-nat.c (compat_x32_clock_t): New. >> >> (compat_x32_siginfo_t): Likewise. >> >> (compat_x32_siginfo_from_siginfo): Likewise. >> >> (siginfo_from_compat_x32_siginfo): Likewise. >> >> (amd64_linux_siginfo_fixup): Call compat_x32_siginfo_from_siginfo >> >> and siginfo_from_compat_x32_siginfo for x32. >> >> >> >> diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c >> >> index 3be8404..97c9a49 100644 >> >> --- a/gdb/amd64-linux-nat.c >> >> +++ b/gdb/amd64-linux-nat.c >> >> @@ -591,6 +591,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; >> > >> > Sorry, but that isn't acceptable. >> > >> > Is your X32 ABI really that broken? >> > >> >> +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))); >> > >> > Same here. I don't think you need alignment here, even with the broken ABI. >> > >> > If it really is too late to fix the X32 ABI, you'll have to write this >> > portably by splitting _utime and _stime into two 32-bit variables and >> > write code that correctly sets the upper and lower 32-bits. >> > >> > >> >> X32 ABI choice is done on purpose. X32 siginfo_t has >> >> typedef long __attribute__ ((__aligned__ (4))) compat_x32_clock_t; >> >> typedef struct compat_x32_siginfo >> { >> int si_signo; >> int si_errno; >> int si_code; >> >> union >> { >> ... >> /* SIGCHLD */ >> struct >> { >> unsigned int _pid; >> unsigned int _uid; >> int _status; >> compat_x32_clock_t _utime; >> compat_x32_clock_t _stime; >> } _sigchld; >> ... >> } compat_x32_siginfo_t __attribute__ ((__aligned__ (8))); >> >> struct info is aligned at 8 bytes and type of _utime/_stime is aligned >> at 4 bytes. However, _utime offset is 3 * 4 + 3 * 4 == 24 bytes. So >> in reality, the addresses of _utime/_stime are 8 bytes aligned. There >> are no needs to split _utime and _stime into two 32-bit variables >> since their addresses are 64bits aligned. > > But there is no way you can easily express that syntax with standard C > syntax[1]. That's why you had to resort to using GCC's __attribute__ > syntax. For GDB you'll have to figure out a way to do this without > using __attribute__ ((__aligned__ (...))). > > My recommendation would be to define a compat_x32 structure just for > SIGCHLD (without using a union) and use the normal 32-bit comap > structure for all the other conversions. > This is in amd64-linux-nat.c. All native Linux/amd64 compilers support __attribute__ ((__aligned__ (...))). In any case, I will use a struct with 2 ints. Thanks. -- H.J. ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: PATCH: Support x32 siginfo_t conversion 2012-05-12 23:16 ` H.J. Lu @ 2012-05-13 2:25 ` H.J. Lu 0 siblings, 0 replies; 6+ messages in thread From: H.J. Lu @ 2012-05-13 2:25 UTC (permalink / raw) To: Mark Kettenis; +Cc: gdb-patches On Sat, May 12, 2012 at 4:15 PM, H.J. Lu <hjl.tools@gmail.com> wrote: > On Sat, May 12, 2012 at 2:16 PM, Mark Kettenis <mark.kettenis@xs4all.nl> wrote: >>> Date: Fri, 11 May 2012 13:55:29 -0700 >>> From: "H.J. Lu" <hjl.tools@gmail.com> >>> >>> On Fri, May 11, 2012 at 1:11 PM, Mark Kettenis <mark.kettenis@xs4all.nl> wrote: >>> >> Date: Fri, 11 May 2012 12:21:33 -0700 >>> >> From: "H.J. Lu" <hongjiu.lu@intel.com> >>> >> >>> >> Hi, >>> >> >>> >> This patch implements x32 siginfo_t conversion. Tested on Linux/x86-64. >>> >> OK to install? >>> >> >>> >> Thanks. >>> >> >>> >> >>> >> H.J. >>> >>> X32 ABI choice is done on purpose. X32 siginfo_t has >>> >>> typedef long __attribute__ ((__aligned__ (4))) compat_x32_clock_t; >>> >>> typedef struct compat_x32_siginfo >>> { >>> int si_signo; >>> int si_errno; >>> int si_code; >>> >>> union >>> { >>> ... >>> /* SIGCHLD */ >>> struct >>> { >>> unsigned int _pid; >>> unsigned int _uid; >>> int _status; >>> compat_x32_clock_t _utime; >>> compat_x32_clock_t _stime; >>> } _sigchld; >>> ... >>> } compat_x32_siginfo_t __attribute__ ((__aligned__ (8))); >>> >>> struct info is aligned at 8 bytes and type of _utime/_stime is aligned >>> at 4 bytes. However, _utime offset is 3 * 4 + 3 * 4 == 24 bytes. So >>> in reality, the addresses of _utime/_stime are 8 bytes aligned. There >>> are no needs to split _utime and _stime into two 32-bit variables >>> since their addresses are 64bits aligned. >> >> But there is no way you can easily express that syntax with standard C >> syntax[1]. That's why you had to resort to using GCC's __attribute__ >> syntax. For GDB you'll have to figure out a way to do this without >> using __attribute__ ((__aligned__ (...))). >> >> My recommendation would be to define a compat_x32 structure just for >> SIGCHLD (without using a union) and use the normal 32-bit comap >> structure for all the other conversions. >> > > This is in amd64-linux-nat.c. All native Linux/amd64 compilers support > __attribute__ ((__aligned__ (...))). In any case, I will use a struct with > 2 ints. > > Thanks. > Here is the updated patch. OK to install? Thanks. -- H.J. --- diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c index 5ebba3a..bc28d54 100644 --- a/gdb/amd64-linux-nat.c +++ b/gdb/amd64-linux-nat.c @@ -591,6 +591,71 @@ typedef struct compat_siginfo } _sifields; } compat_siginfo_t; +/* For x32, clock_t in _sigchld is 64bit aligned at 4 bytes. */ +typedef struct compat_x32_clock +{ + int lower; + int upper; +} 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; + #define cpt_si_pid _sifields._kill._pid #define cpt_si_uid _sifields._kill._uid #define cpt_si_timerid _sifields._timer._tid @@ -724,6 +789,124 @@ 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; + memcpy (&to->cpt_si_utime, &from->si_utime, + sizeof (to->cpt_si_utime)); + memcpy (&to->cpt_si_stime, &from->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; + 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; + } + 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; + memcpy (&to->si_utime, &from->cpt_si_utime, + sizeof (to->si_utime)); + memcpy (&to->si_stime, &from->cpt_si_stime, + sizeof (to->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; + } + } +} + /* Convert a native/host 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 @@ -733,9 +916,10 @@ siginfo_from_compat_siginfo (siginfo_t *to, compat_siginfo_t *from) static int amd64_linux_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction) { + struct gdbarch *gdbarch = get_frame_arch (get_current_frame ()); /* Is the inferior 32-bit? If so, then do fixup the siginfo object. */ - if (gdbarch_addr_bit (get_frame_arch (get_current_frame ())) == 32) + if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32) { gdb_assert (sizeof (siginfo_t) == sizeof (compat_siginfo_t)); @@ -746,6 +930,20 @@ amd64_linux_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction) return 1; } + /* No fixup for native x32 GDB. */ + else if (gdbarch_addr_bit (gdbarch) == 32 && sizeof (void *) == 8) + { + gdb_assert (sizeof (siginfo_t) == sizeof (compat_x32_siginfo_t)); + + 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; + } else return 0; } ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2012-05-13 2:25 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-05-11 19:21 PATCH: Support x32 siginfo_t conversion H.J. Lu 2012-05-11 20:11 ` Mark Kettenis 2012-05-11 20:55 ` H.J. Lu 2012-05-12 21:16 ` Mark Kettenis 2012-05-12 23:16 ` H.J. Lu 2012-05-13 2:25 ` H.J. Lu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox