This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
[patch 8/9]#2 Fix $_siginfo content for multiple threads
- From: Jan Kratochvil <jan dot kratochvil at redhat dot com>
- To: gdb-patches at sourceware dot org
- Date: Mon, 30 Aug 2010 09:15:28 +0200
- Subject: [patch 8/9]#2 Fix $_siginfo content for multiple threads
series #2 of: http://sourceware.org/ml/gdb-patches/2010-07/msg00411.html
Hi,
here is a fix of $_siginfo to contain the real signal information. With the
various resubmits of signals across threads I found when I am interested in
$_siginfo it unfortunately contains incorrect information (commonly about
SIGSTOP).
Thanks,
Jan
gdb/
2010-08-30 Jan Kratochvil <jan.kratochvil@redhat.com>
* linux-nat.c (linux_xfer_siginfo): Remove variables pid, siginfo and
inf_siginfo. New variables siginfop, siginfop_len, gdbarch. Use
inferior_thread ()->stop_signal instead of ptrace. No longer call
siginfo_fixup.
gdb/testsuite/
2010-08-30 Jan Kratochvil <jan.kratochvil@redhat.com>
* gdb.threads/siginfo-threads.exp (handle SIGUSR1 nostop print pass)
(handle SIGUSR2 nostop print pass): Set them to stop.
(get pid, catch signal $sigcount, signal $sigcount si_signo)
(signal $sigcount si_code is SI_TKILL, signal $sigcount si_pid): New
tests.
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -4069,52 +4069,31 @@ linux_xfer_siginfo (struct target_ops *ops, enum target_object object,
const char *annex, gdb_byte *readbuf,
const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
{
- int pid;
- struct siginfo siginfo;
- gdb_byte inf_siginfo[MAX_SIGINFO_SIZE];
+ gdb_byte *siginfop;
+ size_t siginfop_len;
+ struct gdbarch *gdbarch;
gdb_assert (object == TARGET_OBJECT_SIGNAL_INFO);
gdb_assert (readbuf || writebuf);
- pid = GET_LWP (inferior_ptid);
- if (pid == 0)
- pid = GET_PID (inferior_ptid);
-
- if (offset > sizeof (siginfo))
+ if (! target_signal_siginfo_p (&inferior_thread ()->stop_signal))
return -1;
- errno = 0;
- ptrace (PTRACE_GETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, &siginfo);
- if (errno != 0)
- return -1;
+ gdbarch = target_thread_architecture (inferior_ptid);
+ siginfop = target_signal_siginfo_get (&inferior_thread ()->stop_signal,
+ gdbarch);
+ siginfop_len = target_signal_siginfo_len (gdbarch);
- /* 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,
- get_frame_arch (get_current_frame ()));
+ if (offset > siginfop_len)
+ return -1;
- if (offset + len > sizeof (siginfo))
- len = sizeof (siginfo) - offset;
+ if (offset + len > siginfop_len)
+ len = siginfop_len - offset;
if (readbuf != NULL)
- memcpy (readbuf, inf_siginfo + offset, len);
+ memcpy (readbuf, siginfop + offset, len);
else
- {
- memcpy (inf_siginfo + offset, writebuf, len);
-
- /* Convert back to ptrace layout before flushing it out. */
- siginfo_fixup (&siginfo, inf_siginfo, 1,
- get_frame_arch (get_current_frame ()));
-
- errno = 0;
- ptrace (PTRACE_SETSIGINFO, pid, (PTRACE_TYPE_ARG3) 0, &siginfo);
- if (errno != 0)
- return -1;
- }
+ memcpy (siginfop + offset, writebuf, len);
return len;
}
--- a/gdb/testsuite/gdb.threads/siginfo-threads.exp
+++ b/gdb/testsuite/gdb.threads/siginfo-threads.exp
@@ -29,8 +29,8 @@ if ![runto_main] {
# `nostop noprint pass' could in some cases report false PASS due to the
# (preempt 'handle') code path.
-gdb_test "handle SIGUSR1 nostop print pass" "Signal\[ \t\]+Stop\[ \t\]+Print\[ \t\]+Pass to program\[ \t\]+Description\r\nSIGUSR1\[ \t\]+No\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+User defined signal 1"
-gdb_test "handle SIGUSR2 nostop print pass" "Signal\[ \t\]+Stop\[ \t\]+Print\[ \t\]+Pass to program\[ \t\]+Description\r\nSIGUSR2\[ \t\]+No\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+User defined signal 2"
+gdb_test "handle SIGUSR1 stop print pass" "Signal\[ \t\]+Stop\[ \t\]+Print\[ \t\]+Pass to program\[ \t\]+Description\r\nSIGUSR1\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+User defined signal 1"
+gdb_test "handle SIGUSR2 stop print pass" "Signal\[ \t\]+Stop\[ \t\]+Print\[ \t\]+Pass to program\[ \t\]+Description\r\nSIGUSR2\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+Yes\[ \t\]+User defined signal 2"
gdb_breakpoint [gdb_get_line_number "break-at-exit"]
@@ -38,6 +38,67 @@ gdb_breakpoint [gdb_get_line_number "break-at-exit"]
# Ignore possible: Undefined set debug command: "lin-lwp 1" ...
gdb_test "set debug lin-lwp 1" ".*"
+set test "get pid"
+gdb_test_multiple "p getpid ()" $test {
+ -re " = (\[0-9\]+)\r\n$gdb_prompt $" {
+ set pid $expect_out(1,string)
+ pass $test
+ }
+}
+
+for {set sigcount 0} {$sigcount < 4} {incr sigcount} {
+ set test "catch signal $sigcount"
+ set sigusr ""
+ gdb_test_multiple "continue" $test {
+ -re "KLS: \[^\r\n\]*rt_tgsigqueueinfo" {
+ unsupported "Missing rt_tgsigqueueinfo kernel support"
+ set result -1
+ }
+ -re "Program received signal SIGUSR(\[12\]), User defined signal \[12\]\\.\r\n.*\r\n$gdb_prompt $" {
+ set sigusr $expect_out(1,string)
+ pass $test
+ }
+ }
+ if {$sigusr == ""} {
+ return -1
+ }
+
+ set test "signal $sigcount si_signo"
+ if {$sigusr == 1} {
+ set signo 10
+ } else {
+ set signo 12
+ }
+ gdb_test_multiple {p $_siginfo.si_signo} $test {
+ -re " = $signo\r\n$gdb_prompt $" {
+ pass $test
+ }
+ -re "Attempt to extract a component of a value that is not a structure\\.\r\n$gdb_prompt $" {
+ unsupported $test
+ }
+ }
+
+ set test "signal $sigcount si_code is SI_TKILL"
+ gdb_test_multiple {p $_siginfo.si_code} $test {
+ -re " = -6\r\n$gdb_prompt $" {
+ pass $test
+ }
+ -re "Attempt to extract a component of a value that is not a structure\\.\r\n$gdb_prompt $" {
+ unsupported $test
+ }
+ }
+
+ set test "signal $sigcount si_pid"
+ gdb_test_multiple {p $_siginfo._sifields._kill.si_pid} $test {
+ -re " = $pid\r\n$gdb_prompt $" {
+ pass $test
+ }
+ -re "Attempt to extract a component of a value that is not a structure\\.\r\n$gdb_prompt $" {
+ unsupported $test
+ }
+ }
+}
+
set test "continue to break-at-exit"
gdb_test_multiple "continue" $test {
-re "KLS: \[^\r\n\]*rt_tgsigqueueinfo" {