]> granicus.if.org Git - strace/commitdiff
Enhance parser of struct sigevent
authorDmitry V. Levin <ldv@altlinux.org>
Wed, 16 Sep 2015 16:31:43 +0000 (16:31 +0000)
committerDmitry V. Levin <ldv@altlinux.org>
Thu, 17 Sep 2015 13:22:57 +0000 (13:22 +0000)
* print_sigevent.c (print_sigevent): Always print names
of struct_sigevent fields along with their values.
Print signal name of sigev_signo for those sigev_notify values
that require valid signal numbers.
* tests/timer_create.c: New file.
* tests/timer_create.test: New test.
* tests/Makefile.am (check_PROGRAMS): Add timer_create.
(TESTS): Add timer_create.test.
* tests/.gitignore: Add timer_create.

print_sigevent.c
tests/.gitignore
tests/Makefile.am
tests/timer_create.c [new file with mode: 0644]
tests/timer_create.test [new file with mode: 0755]

index f752120b498d98b72e39213e04847aa46eee7bbb..5454486b6cf2592f615fe3982c16da8cd75d7733 100644 (file)
@@ -43,32 +43,56 @@ MPERS_PRINTER_DECL(void, print_sigevent)(struct tcb *tcp, const long addr)
 {
        struct_sigevent sev;
 
-       if (!umove_or_printaddr(tcp, addr, &sev)) {
-               tprintf("{%#lx, ", (unsigned long) sev.sigev_value.sival_ptr);
-               if (sev.sigev_notify == SIGEV_SIGNAL)
-                       tprintf("%s, ", signame(sev.sigev_signo));
-               else
-                       tprintf("%u, ", sev.sigev_signo);
-               printxval(sigev_value, sev.sigev_notify, "SIGEV_???");
-               tprints(", ");
-               if (sev.sigev_notify == SIGEV_THREAD_ID)
-#if defined(HAVE_STRUCT_SIGEVENT__SIGEV_UN__PAD)
-                       /* _pad[0] is the _tid field which might not be
-                          present in the userlevel definition of the
-                          struct.  */
-                       tprintf("{%d}", sev._sigev_un._pad[0]);
-#elif defined(HAVE_STRUCT_SIGEVENT___PAD)
-                       tprintf("{%d}", sev.__pad[0]);
+       if (umove_or_printaddr(tcp, addr, &sev))
+               return;
+
+       tprints("{");
+       if (sev.sigev_value.sival_ptr)
+               tprintf("sigev_value={int=%d, ptr=%#lx}, ",
+                       sev.sigev_value.sival_int,
+                       (unsigned long) sev.sigev_value.sival_ptr);
+
+       tprints("sigev_signo=");
+       switch (sev.sigev_notify) {
+       case SIGEV_SIGNAL:
+       case SIGEV_THREAD:
+       case SIGEV_THREAD_ID:
+               tprints(signame(sev.sigev_signo));
+               break;
+       default:
+               tprintf("%u", sev.sigev_signo);
+       }
+
+       tprints(", sigev_notify=");
+       printxval(sigev_value, sev.sigev_notify, "SIGEV_???");
+
+       switch (sev.sigev_notify) {
+       case SIGEV_THREAD_ID:
+#ifndef sigev_notify_thread_id
+               /*
+                * _pad[0] is the _tid field which might not be
+                * present in the userlevel definition of the struct.
+                */
+# if defined HAVE_STRUCT_SIGEVENT__SIGEV_UN__PAD
+#  define sigev_notify_thread_id _sigev_un._pad[0]
+# elif defined HAVE_STRUCT_SIGEVENT___PAD
+#  define sigev_notify_thread_id __pad[0]
+# endif
+#endif
+
+#ifdef sigev_notify_thread_id
+               tprintf(", sigev_notify_thread_id=%d",
+                       sev.sigev_notify_thread_id);
 #else
 # warning unfamiliar struct sigevent => incomplete SIGEV_THREAD_ID decoding
-                       tprints("{...}");
 #endif
-               else if (sev.sigev_notify == SIGEV_THREAD)
-                       tprintf("{%#lx, %#lx}",
-                               (unsigned long) sev.sigev_notify_function,
-                               (unsigned long) sev.sigev_notify_attributes);
-               else
-                       tprints("{...}");
-               tprints("}");
+               break;
+       case SIGEV_THREAD:
+               tprints(", sigev_notify_function=");
+               printaddr((unsigned long) sev.sigev_notify_function);
+               tprints(", sigev_notify_attributes=");
+               printaddr((unsigned long) sev.sigev_notify_attributes);
+               break;
        }
+       tprints("}");
 }
index 6f3aefecb4ec79d504cfe847ed9fd4b751b0ca89..d0f0633ec1e6aed8587bcfd6dc945f09c12d9a53 100644 (file)
@@ -48,6 +48,7 @@ stat32
 statfs
 sysinfo
 time
+timer_create
 times
 times-fail
 uid
index dbe4310e35fac162974de9407b61a9c56beb1004..7a219d326e435e330472599b847fc5243758b3fe 100644 (file)
@@ -61,6 +61,7 @@ check_PROGRAMS = \
        statfs \
        sysinfo \
        time \
+       timer_create \
        times \
        times-fail \
        uid \
@@ -143,6 +144,7 @@ TESTS = \
        ppoll.test \
        sun_path.test \
        time.test \
+       timer_create.test \
        times.test \
        times-fail.test \
        umovestr.test \
diff --git a/tests/timer_create.c b/tests/timer_create.c
new file mode 100644 (file)
index 0000000..05e6f0a
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2015 Dmitry V. Levin <ldv@altlinux.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <stdio.h>
+#include <signal.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+
+#ifdef __NR_timer_create
+
+int
+main(void)
+{
+       int tid[4] = {};
+       struct sigevent sev = {
+               .sigev_notify = SIGEV_NONE,
+               .sigev_signo = 0xfacefeed,
+               .sigev_value.sival_ptr =
+                       (void *) (unsigned long) 0xdeadbeefbadc0ded
+       };
+
+       if (syscall(__NR_timer_create, CLOCK_REALTIME, &sev, &tid[0]))
+               return 77;
+       printf("timer_create(CLOCK_REALTIME, {sigev_value={int=%d, ptr=%p}"
+              ", sigev_signo=%u, sigev_notify=SIGEV_NONE}"
+              ", [%d]) = 0\n",
+              sev.sigev_value.sival_int,
+              sev.sigev_value.sival_ptr,
+              sev.sigev_signo, tid[0]);
+
+       sev.sigev_notify = SIGEV_SIGNAL;
+       sev.sigev_signo = SIGALRM;
+       if (syscall(__NR_timer_create, CLOCK_MONOTONIC, &sev, &tid[1]))
+               return 77;
+       printf("timer_create(CLOCK_MONOTONIC, {sigev_value={int=%d, ptr=%p}"
+              ", sigev_signo=SIGALRM, sigev_notify=SIGEV_SIGNAL}"
+              ", [%d]) = 0\n",
+              sev.sigev_value.sival_int,
+              sev.sigev_value.sival_ptr, tid[1]);
+
+       sev.sigev_notify = SIGEV_THREAD;
+       sev.sigev_notify_function =
+               (void *) (unsigned long) 0xdeadbeefbadc0ded;
+       sev.sigev_notify_attributes =
+               (void *) (unsigned long) 0xcafef00dfacefeed;
+       if (syscall(__NR_timer_create, CLOCK_REALTIME, &sev, &tid[2]))
+               return 77;
+       printf("timer_create(CLOCK_REALTIME, {sigev_value={int=%d, ptr=%p}"
+              ", sigev_signo=SIGALRM, sigev_notify=SIGEV_THREAD"
+              ", sigev_notify_function=%p, sigev_notify_attributes=%p}"
+              ", [%d]) = 0\n",
+              sev.sigev_value.sival_int,
+              sev.sigev_value.sival_ptr,
+              sev.sigev_notify_function,
+              sev.sigev_notify_attributes,
+              tid[2]);
+
+#ifndef sigev_notify_thread_id
+# if defined HAVE_STRUCT_SIGEVENT__SIGEV_UN__PAD
+#  define sigev_notify_thread_id _sigev_un._pad[0]
+# elif defined HAVE_STRUCT_SIGEVENT___PAD
+#  define sigev_notify_thread_id __pad[0]
+# endif
+#endif /* !sigev_notify_thread_id */
+
+#ifdef sigev_notify_thread_id
+# ifndef SIGEV_THREAD_ID
+#  define SIGEV_THREAD_ID 4
+# endif
+       sev.sigev_notify = SIGEV_THREAD_ID;
+       sev.sigev_notify_thread_id = getpid();
+       if (syscall(__NR_timer_create, CLOCK_MONOTONIC, &sev, &tid[3]))
+               return 77;
+       printf("timer_create(CLOCK_MONOTONIC, {sigev_value={int=%d, ptr=%p}"
+              ", sigev_signo=SIGALRM, sigev_notify=SIGEV_THREAD_ID"
+              ", sigev_notify_thread_id=%d}"
+              ", [%d]) = 0\n",
+              sev.sigev_value.sival_int,
+              sev.sigev_value.sival_ptr,
+              sev.sigev_notify_thread_id,
+              tid[3]);
+#endif /* sigev_notify_thread_id */
+
+       puts("+++ exited with 0 +++");
+       return 0;
+}
+
+#else
+
+int
+main(void)
+{
+       return 77;
+}
+
+#endif
diff --git a/tests/timer_create.test b/tests/timer_create.test
new file mode 100755 (executable)
index 0000000..ffab9f9
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+# Check timer_create syscall decoding.
+
+. "${srcdir=.}/init.sh"
+
+run_prog > /dev/null
+OUT="$LOG.out"
+run_strace -e timer_create $args > "$OUT"
+match_diff "$OUT" "$LOG"
+rm -f "$OUT"
+
+exit 0