update to 2.17
[platform/upstream/glibc.git] / debug / tst-backtrace5.c
1 /* Test backtrace and backtrace_symbols for signal frames, where a
2    system call was interrupted by a signal.
3    Copyright (C) 2011-2015 Free Software Foundation, Inc.
4    This file is part of the GNU C Library.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, see
18    <http://www.gnu.org/licenses/>.  */
19
20 #include <execinfo.h>
21 #include <search.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <signal.h>
27 #include <unistd.h>
28
29 #include "tst-backtrace.h"
30
31 #ifndef SIGACTION_FLAGS
32 # define SIGACTION_FLAGS 0
33 #endif
34
35 static int do_test (void);
36 #define TEST_FUNCTION do_test ()
37 #include "../test-skeleton.c"
38
39 /* The backtrace should include at least handle_signal, a signal
40    trampoline, read, 3 * fn, and do_test.  */
41 #define NUM_FUNCTIONS 7
42
43 void
44 handle_signal (int signum)
45 {
46   void *addresses[NUM_FUNCTIONS];
47   char **symbols;
48   int n;
49   int i;
50
51   /* Get the backtrace addresses.  */
52   n = backtrace (addresses, sizeof (addresses) / sizeof (addresses[0]));
53   printf ("Obtained backtrace with %d functions\n", n);
54   /*  Check that there are at least seven functions.  */
55   if (n < NUM_FUNCTIONS)
56     {
57       FAIL ();
58       return;
59     }
60   /* Convert them to symbols.  */
61   symbols = backtrace_symbols (addresses, n);
62   /* Check that symbols were obtained.  */
63   if (symbols == NULL)
64     {
65       FAIL ();
66       return;
67     }
68   for (i = 0; i < n; ++i)
69     printf ("Function %d: %s\n", i, symbols[i]);
70   /* Check that the function names obtained are accurate.  */
71   if (!match (symbols[0], "handle_signal"))
72     {
73       FAIL ();
74       return;
75     }
76   /* Do not check name for signal trampoline.  */
77   i = 2;
78   if (!match (symbols[i++], "read"))
79     {
80       /* Perhaps symbols[2] is __kernel_vsyscall?  */
81       if (!match (symbols[i++], "read"))
82         {
83           FAIL ();
84           return;
85         }
86     }
87   for (; i < n - 1; i++)
88     if (!match (symbols[i], "fn"))
89       {
90         FAIL ();
91         return;
92       }
93   /* Symbol names are not available for static functions, so we do not
94      check do_test.  */
95 }
96
97 NO_INLINE int
98 fn (int c, int flags)
99 {
100   pid_t parent_pid, child_pid;
101   int pipefd[2];
102   char r[1];
103   struct sigaction act;
104
105   if (c > 0)
106     {
107       fn (c - 1, flags);
108       return x;
109     }
110
111   memset (&act, 0, sizeof (act));
112   act.sa_handler = handle_signal;
113   act.sa_flags = flags;
114   sigemptyset (&act.sa_mask);
115   sigaction (SIGUSR1, &act, NULL);
116   parent_pid = getpid ();
117   if (pipe (pipefd) == -1)
118     abort ();
119
120   child_pid = fork ();
121   if (child_pid == (pid_t) -1)
122     abort ();
123   else if (child_pid == 0)
124     {
125       sleep (1);
126       kill (parent_pid, SIGUSR1);
127       _exit (0);
128     }
129
130   /* In the parent.  */
131   read (pipefd[0], r, 1);
132
133   return 0;
134 }
135
136 NO_INLINE static int
137 do_test (void)
138 {
139   fn (2, SIGACTION_FLAGS);
140   return ret;
141 }