diff options
-rw-r--r-- | gdb/ChangeLog | 12 | ||||
-rw-r--r-- | gdb/nat/amd64-linux-siginfo.c | 314 | ||||
-rw-r--r-- | gdb/nat/amd64-linux-siginfo.h | 16 |
3 files changed, 240 insertions, 102 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 56bdc79..3c97ac2 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,17 @@ 2016-02-02 Walfred Tedeschi <walfred.tedeschi@intel.com> + * 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. + +2016-02-02 Walfred Tedeschi <walfred.tedeschi@intel.com> + * linux-tdep.c (linux_get_siginfo_type): Add the _addr_bnd structure to the siginfo if extra_fields contains LINUX_SIGINFO_FIELD_ADDR_BND. diff --git a/gdb/nat/amd64-linux-siginfo.c b/gdb/nat/amd64-linux-siginfo.c index 36b5505..72b3042 100644 --- a/gdb/nat/amd64-linux-siginfo.c +++ b/gdb/nat/amd64-linux-siginfo.c @@ -21,6 +21,97 @@ #include "common-defs.h" #include "amd64-linux-siginfo.h" +/* The nat_* types below define the most complete kernel siginfo type + known for the architecture, independent of the system/libc headers. */ + +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))); + +/* Sanity check for the siginfo structure size. */ + +gdb_static_assert (sizeof (nat_siginfo_t) == sizeof (siginfo_t)); + /* 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 +182,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 +249,7 @@ typedef struct compat_x32_siginfo struct { unsigned int _addr; + unsigned int _addr_lsb; } _sigfault; /* SIGPOLL */ @@ -174,6 +272,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 @@ -192,54 +291,57 @@ typedef struct compat_x32_siginfo static void compat_siginfo_from_siginfo (compat_siginfo_t *to, siginfo_t *from) { + nat_siginfo_t from_nat; + + 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; } } @@ -250,57 +352,61 @@ 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; + 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)); } /* Convert the system provided siginfo into compatible x32 siginfo. */ @@ -309,119 +415,127 @@ static void compat_x32_siginfo_from_siginfo (compat_x32_siginfo_t *to, siginfo_t *from) { + nat_siginfo_t from_nat; + + 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; } } } + + + /* Convert the compatible x32 siginfo into system siginfo. */ 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; + memset (&to_nat, 0, sizeof (to_nat)); + to_nat.si_signo = from->si_signo; + to_nat.si_errno = from->si_errno; + to_nat.si_code = from->si_code; - if (to->si_code == SI_TIMER) + 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 a396966..5b29cbe 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. */ |