From 9cf12d57c58a82cfe3e6fee26d1ea55dfe49f9c4 Mon Sep 17 00:00:00 2001 From: Pedro Alves Date: Tue, 26 Jul 2016 19:35:40 +0100 Subject: Fix PR gdb/20287 - x32 and "gdb_static_assert (sizeof (nat_siginfo_t) == sizeof (siginfo_t))" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Building an x32 gdb trips on a static assertion: In file included from .../src/gdb/common/common-defs.h:71:0, from .../src/gdb/nat/amd64-linux-siginfo.c:21: .../src/gdb/common/gdb_assert.h:26:66: error: size of array ‘never_defined_just_used_for_checking’ is negative extern int never_defined_just_used_for_checking[(expr) ? 1 : -1] ^ .../src/gdb/nat/amd64-linux-siginfo.c:113:1: note: in expansion of macro ‘gdb_static_assert’ gdb_static_assert (sizeof (nat_siginfo_t) == sizeof (siginfo_t)); ^ The problem is that the way nat_siginfo_t is defined, it can only match the host's siginfo_t object when gdb is built as a 64-bit program. Several bits of nat_siginfo_t are off: - nat_siginfo_t's _pad field's definition is: int _pad[((128 / sizeof (int)) - 4)]; while /usr/include/bits/siginfo.h has: # define __SI_MAX_SIZE 128 # if __WORDSIZE == 64 # define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 4) # else # define __SI_PAD_SIZE ((__SI_MAX_SIZE / sizeof (int)) - 3) # endif and __WORDSIZE == 32 for x32. This is what causes the size of nat_siginfo_t to be wrong and the assertion to fail. - the nat_clock_t type is incorrect for 64-bit. We have this: /* For native 64-bit, clock_t in _sigchld is 64bit aligned at 4 bytes. */ typedef long __attribute__ ((__aligned__ (4))) nat_clock_t; however, /usr/include/bits/siginfo.h has: # if defined __x86_64__ && __WORDSIZE == 32 /* si_utime and si_stime must be 4 byte aligned for x32 to match the kernel. We align siginfo_t to 8 bytes so that si_utime and si_stime are actually aligned to 8 bytes since their offsets are multiple of 8 bytes. */ typedef __clock_t __attribute__ ((__aligned__ (4))) __sigchld_clock_t; # define __SI_ALIGNMENT __attribute__ ((__aligned__ (8))) # else typedef __clock_t __sigchld_clock_t; # define __SI_ALIGNMENT # endif So we're currently forcing 4-byte alignment on clock_t, when it should only be so for x32, not 64-bit. The fix: - Leaves nat_siginfo_t strictly for the 64-bit ABI. - Adds a new typedef for the siginfo type that ptrace uses (ptrace_siginfo_t). An x32 gdb always gets/sets an x32 siginfo_t type with PTRACE_GETSIGINFO/PTRACE_SETSIGINFO. - Uses this new ptrace_siginfo_t type instead of nat_siginfo_t as the intermediate conversion type. gdb/ChangeLog: 2016-07-26 Pedro Alves * amd64-linux-nat.c (amd64_linux_siginfo_fixup): Rename 'native' parameter to 'ptrace'. * nat/amd64-linux-siginfo.c (GDB_SI_SIZE): New define. (nat_uptr_t): New an unsigned long. (nat_clock_t): Remove attribute __aligned__. (struct nat_timeval): Delete. (nat_siginfo_t): Remove attribute __aligned__. (ptrace_siginfo_t): Define. (compat_siginfo_from_siginfo, siginfo_from_compat_siginfo) (compat_x32_siginfo_from_siginfo) (siginfo_from_compat_x32_siginfo): Make 'from' parameter const. Convert through a ptrace_siginfo_t instead of a nat_siginfo_t. Remove casts. (amd64_linux_siginfo_fixup_common): Rename 'native' parameter to 'ptrace'. Remove static assertions. (top level): New static assertions. gdb/gdbserver/ChangeLog: 2016-07-26 Pedro Alves * linux-x86-low.c (x86_siginfo_fixup): Rename 'native' parameter to 'ptrace'. --- gdb/gdbserver/linux-x86-low.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'gdb/gdbserver/linux-x86-low.c') diff --git a/gdb/gdbserver/linux-x86-low.c b/gdb/gdbserver/linux-x86-low.c index 5080decbbd8..4e6dbce6a49 100644 --- a/gdb/gdbserver/linux-x86-low.c +++ b/gdb/gdbserver/linux-x86-low.c @@ -624,14 +624,14 @@ x86_debug_reg_state (pid_t pid) as debugging it with a 32-bit GDBSERVER, we do the 32-bit <-> 64-bit conversion in-place ourselves. */ -/* Convert a native/host siginfo object, into/from the siginfo in the +/* Convert a ptrace/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 - from INF to NATIVE. If DIRECTION is 0, copy from NATIVE to + from INF to PTRACE. If DIRECTION is 0, copy from PTRACE to INF. */ static int -x86_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction) +x86_siginfo_fixup (siginfo_t *ptrace, gdb_byte *inf, int direction) { #ifdef __x86_64__ unsigned int machine; @@ -640,11 +640,11 @@ x86_siginfo_fixup (siginfo_t *native, gdb_byte *inf, int direction) /* Is the inferior 32-bit? If so, then fixup the siginfo object. */ if (!is_64bit_tdesc ()) - return amd64_linux_siginfo_fixup_common (native, inf, direction, + return amd64_linux_siginfo_fixup_common (ptrace, inf, direction, FIXUP_32); /* No fixup for native x32 GDB. */ else if (!is_elf64 && sizeof (void *) == 8) - return amd64_linux_siginfo_fixup_common (native, inf, direction, + return amd64_linux_siginfo_fixup_common (ptrace, inf, direction, FIXUP_X32); #endif -- cgit v1.2.1