diff options
author | Pedro Alves <palves@redhat.com> | 2009-02-06 23:06:58 +0000 |
---|---|---|
committer | Pedro Alves <palves@redhat.com> | 2009-02-06 23:06:58 +0000 |
commit | 5b009018d2759269b0fd192077a391c795ebfa97 (patch) | |
tree | 3f4af7bbb4672bf5a43fb7647b02f0fb9cbcda2f /gdb/linux-nat.c | |
parent | 4aa995e123f47a4aca553ae4ed4fdebe2d00e316 (diff) | |
download | gdb-5b009018d2759269b0fd192077a391c795ebfa97.zip gdb-5b009018d2759269b0fd192077a391c795ebfa97.tar.gz gdb-5b009018d2759269b0fd192077a391c795ebfa97.tar.bz2 |
* amd64-linux-nat.c (compat_int_t, compat_uptr_t, compat_time_t)
(compat_timer_t, compat_clock_t, struct compat_timeval)
(compat_sigval_t, compat_siginfo_t): New types.
(cpt_si_pid, cpt_si_uid, cpt_si_timerid, cpt_si_overrun)
(cpt_si_status, cpt_si_utime, cpt_si_stime, cpt_si_ptr)
(cpt_si_addr, cpt_si_band, cpt_si_fd): New defines.
(compat_siginfo_from_siginfo, siginfo_from_compat_siginfo)
(amd64_linux_siginfo_fixup): New.
* linux-nat.c (linux_nat_siginfo_fixup): New.
(siginfo_fixup): New.
(linux_xfer_siginfo): Use siginfo_fixup to convert between the
siginfo layout expected by ptrace and the siginfo layout of the
inferior.
(linux_nat_set_siginfo_fixup): New.
* linux-nat.h (linux_nat_set_siginfo_fixup): Declare.
Diffstat (limited to 'gdb/linux-nat.c')
-rw-r--r-- | gdb/linux-nat.c | 59 |
1 files changed, 57 insertions, 2 deletions
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c index 0b098a0..a54ebb4 100644 --- a/gdb/linux-nat.c +++ b/gdb/linux-nat.c @@ -205,6 +205,13 @@ static struct target_ops linux_ops_saved; /* The method to call, if any, when a new thread is attached. */ static void (*linux_nat_new_thread) (ptid_t); +/* The method to call, if any, when the siginfo object needs to be + converted between the layout returned by ptrace, and the layout in + the architecture of the inferior. */ +static int (*linux_nat_siginfo_fixup) (struct siginfo *, + gdb_byte *, + int); + /* The saved to_xfer_partial method, inherited from inf-ptrace.c. Called by our to_xfer_partial. */ static LONGEST (*super_xfer_partial) (struct target_ops *, @@ -3223,6 +3230,28 @@ linux_nat_mourn_inferior (struct target_ops *ops) linux_fork_mourn_inferior (); } +/* Convert a native/host siginfo object, into/from the siginfo in the + layout of the inferiors' architecture. */ + +static void +siginfo_fixup (struct siginfo *siginfo, gdb_byte *inf_siginfo, int direction) +{ + int done = 0; + + if (linux_nat_siginfo_fixup != NULL) + done = linux_nat_siginfo_fixup (siginfo, inf_siginfo, direction); + + /* If there was no callback, or the callback didn't do anything, + then just do a straight memcpy. */ + if (!done) + { + if (direction == 1) + memcpy (siginfo, inf_siginfo, sizeof (struct siginfo)); + else + memcpy (inf_siginfo, siginfo, sizeof (struct siginfo)); + } +} + static LONGEST linux_xfer_siginfo (struct target_ops *ops, enum target_object object, const char *annex, gdb_byte *readbuf, @@ -3232,6 +3261,7 @@ linux_xfer_siginfo (struct target_ops *ops, enum target_object object, LONGEST n; int pid; struct siginfo siginfo; + gdb_byte inf_siginfo[sizeof (struct siginfo)]; gdb_assert (object == TARGET_OBJECT_SIGNAL_INFO); gdb_assert (readbuf || writebuf); @@ -3248,14 +3278,26 @@ linux_xfer_siginfo (struct target_ops *ops, enum target_object object, if (errno != 0) return -1; + /* When GDB is built as a 64-bit application, ptrace writes into + SIGINFO an object with 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 need to convert it. GDB core always sees + the converted layout, so any read/write will have to be done + post-conversion. */ + siginfo_fixup (&siginfo, inf_siginfo, 0); + if (offset + len > sizeof (siginfo)) len = sizeof (siginfo) - offset; if (readbuf != NULL) - memcpy (readbuf, (char *)&siginfo + offset, len); + memcpy (readbuf, inf_siginfo + offset, len); else { - memcpy ((char *)&siginfo + offset, writebuf, len); + memcpy (inf_siginfo + offset, writebuf, len); + + /* Convert back to ptrace layout before flushing it out. */ + siginfo_fixup (&siginfo, inf_siginfo, 1); + errno = 0; ptrace (PTRACE_SETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, &siginfo); if (errno != 0) @@ -4720,6 +4762,19 @@ linux_nat_set_new_thread (struct target_ops *t, void (*new_thread) (ptid_t)) linux_nat_new_thread = new_thread; } +/* Register a method that converts a siginfo object between the layout + that ptrace returns, and the layout in the architecture of the + inferior. */ +void +linux_nat_set_siginfo_fixup (struct target_ops *t, + int (*siginfo_fixup) (struct siginfo *, + gdb_byte *, + int)) +{ + /* Save the pointer. */ + linux_nat_siginfo_fixup = siginfo_fixup; +} + /* Return the saved siginfo associated with PTID. */ struct siginfo * linux_nat_get_siginfo (ptid_t ptid) |