1*7304104dSAndroid Build Coastguard Worker /* Test child for parent backtrace test.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2013, 2016 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker
5*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker it under the terms of the GNU General Public License as published by
7*7304104dSAndroid Build Coastguard Worker the Free Software Foundation; either version 3 of the License, or
8*7304104dSAndroid Build Coastguard Worker (at your option) any later version.
9*7304104dSAndroid Build Coastguard Worker
10*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
11*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
12*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13*7304104dSAndroid Build Coastguard Worker GNU General Public License for more details.
14*7304104dSAndroid Build Coastguard Worker
15*7304104dSAndroid Build Coastguard Worker You should have received a copy of the GNU General Public License
16*7304104dSAndroid Build Coastguard Worker along with this program. If not, see <http://www.gnu.org/licenses/>. */
17*7304104dSAndroid Build Coastguard Worker
18*7304104dSAndroid Build Coastguard Worker /* Command line syntax: ./backtrace-child [--ptraceme|--gencore]
19*7304104dSAndroid Build Coastguard Worker --ptraceme will call ptrace (PTRACE_TRACEME) in the two threads.
20*7304104dSAndroid Build Coastguard Worker --gencore will call abort () at its end.
21*7304104dSAndroid Build Coastguard Worker Main thread will signal SIGUSR2. Other thread will signal SIGUSR1.
22*7304104dSAndroid Build Coastguard Worker There used to be a difference between x86_64 and other architectures.
23*7304104dSAndroid Build Coastguard Worker To test getting a signal at the very first instruction of a function:
24*7304104dSAndroid Build Coastguard Worker PC will get changed to function 'jmp' by backtrace.c function
25*7304104dSAndroid Build Coastguard Worker prepare_thread. Then SIGUSR2 will be signalled to backtrace-child
26*7304104dSAndroid Build Coastguard Worker which will invoke function sigusr2.
27*7304104dSAndroid Build Coastguard Worker This is all done so that signal interrupts execution of the very first
28*7304104dSAndroid Build Coastguard Worker instruction of a function. Properly handled unwind should not slip into
29*7304104dSAndroid Build Coastguard Worker the previous unrelated function.
30*7304104dSAndroid Build Coastguard Worker The tested functionality is arch-independent but the code reproducing it
31*7304104dSAndroid Build Coastguard Worker has to be arch-specific.
32*7304104dSAndroid Build Coastguard Worker On non-x86_64:
33*7304104dSAndroid Build Coastguard Worker sigusr2 gets called by normal function call from function stdarg.
34*7304104dSAndroid Build Coastguard Worker On any arch then sigusr2 calls raise (SIGUSR1) for --ptraceme.
35*7304104dSAndroid Build Coastguard Worker abort () is called otherwise, expected for --gencore core dump.
36*7304104dSAndroid Build Coastguard Worker
37*7304104dSAndroid Build Coastguard Worker Expected x86_64 output:
38*7304104dSAndroid Build Coastguard Worker TID 10276:
39*7304104dSAndroid Build Coastguard Worker # 0 0x7f7ab61e9e6b raise
40*7304104dSAndroid Build Coastguard Worker # 1 0x7f7ab661af47 - 1 main
41*7304104dSAndroid Build Coastguard Worker # 2 0x7f7ab5e3bb45 - 1 __libc_start_main
42*7304104dSAndroid Build Coastguard Worker # 3 0x7f7ab661aa09 - 1 _start
43*7304104dSAndroid Build Coastguard Worker TID 10278:
44*7304104dSAndroid Build Coastguard Worker # 0 0x7f7ab61e9e6b raise
45*7304104dSAndroid Build Coastguard Worker # 1 0x7f7ab661ab3c - 1 sigusr2
46*7304104dSAndroid Build Coastguard Worker # 2 0x7f7ab5e4fa60 __restore_rt
47*7304104dSAndroid Build Coastguard Worker # 3 0x7f7ab661ab47 jmp
48*7304104dSAndroid Build Coastguard Worker # 4 0x7f7ab661ac92 - 1 stdarg
49*7304104dSAndroid Build Coastguard Worker # 5 0x7f7ab661acba - 1 backtracegen
50*7304104dSAndroid Build Coastguard Worker # 6 0x7f7ab661acd1 - 1 start
51*7304104dSAndroid Build Coastguard Worker # 7 0x7f7ab61e2c53 - 1 start_thread
52*7304104dSAndroid Build Coastguard Worker # 8 0x7f7ab5f0fdbd - 1 __clone
53*7304104dSAndroid Build Coastguard Worker
54*7304104dSAndroid Build Coastguard Worker Expected non-x86_64 (i386) output; __kernel_vsyscall are skipped if found:
55*7304104dSAndroid Build Coastguard Worker TID 10408:
56*7304104dSAndroid Build Coastguard Worker # 0 0xf779f430 __kernel_vsyscall
57*7304104dSAndroid Build Coastguard Worker # 1 0xf7771466 - 1 raise
58*7304104dSAndroid Build Coastguard Worker # 2 0xf77c1d07 - 1 main
59*7304104dSAndroid Build Coastguard Worker # 3 0xf75bd963 - 1 __libc_start_main
60*7304104dSAndroid Build Coastguard Worker # 4 0xf77c1761 - 1 _start
61*7304104dSAndroid Build Coastguard Worker TID 10412:
62*7304104dSAndroid Build Coastguard Worker # 0 0xf779f430 __kernel_vsyscall
63*7304104dSAndroid Build Coastguard Worker # 1 0xf7771466 - 1 raise
64*7304104dSAndroid Build Coastguard Worker # 2 0xf77c18f4 - 1 sigusr2
65*7304104dSAndroid Build Coastguard Worker # 3 0xf77c1a10 - 1 stdarg
66*7304104dSAndroid Build Coastguard Worker # 4 0xf77c1a2c - 1 backtracegen
67*7304104dSAndroid Build Coastguard Worker # 5 0xf77c1a48 - 1 start
68*7304104dSAndroid Build Coastguard Worker # 6 0xf77699da - 1 start_thread
69*7304104dSAndroid Build Coastguard Worker # 7 0xf769bbfe - 1 __clone
70*7304104dSAndroid Build Coastguard Worker
71*7304104dSAndroid Build Coastguard Worker But the raise jmp patching was unreliable. It depends on the CFI for the raise()
72*7304104dSAndroid Build Coastguard Worker function in glibc to be the same as for the jmp() function. This is not always
73*7304104dSAndroid Build Coastguard Worker the case. Some newer glibc versions rewrote raise() and now the CFA is calculated
74*7304104dSAndroid Build Coastguard Worker differently. So we disable raise jmp patching everywhere.
75*7304104dSAndroid Build Coastguard Worker */
76*7304104dSAndroid Build Coastguard Worker
77*7304104dSAndroid Build Coastguard Worker #ifdef __x86_64__
78*7304104dSAndroid Build Coastguard Worker /* #define RAISE_JMP_PATCHING 1 */
79*7304104dSAndroid Build Coastguard Worker #endif
80*7304104dSAndroid Build Coastguard Worker
81*7304104dSAndroid Build Coastguard Worker #include <config.h>
82*7304104dSAndroid Build Coastguard Worker #include <assert.h>
83*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
84*7304104dSAndroid Build Coastguard Worker #include <errno.h>
85*7304104dSAndroid Build Coastguard Worker #include <string.h>
86*7304104dSAndroid Build Coastguard Worker #include <pthread.h>
87*7304104dSAndroid Build Coastguard Worker #include <stdio.h>
88*7304104dSAndroid Build Coastguard Worker #include <unistd.h>
89*7304104dSAndroid Build Coastguard Worker
90*7304104dSAndroid Build Coastguard Worker #ifndef __linux__
91*7304104dSAndroid Build Coastguard Worker
92*7304104dSAndroid Build Coastguard Worker int
main(int argc,char ** argv)93*7304104dSAndroid Build Coastguard Worker main (int argc __attribute__ ((unused)), char **argv)
94*7304104dSAndroid Build Coastguard Worker {
95*7304104dSAndroid Build Coastguard Worker fprintf (stderr, "%s: Unwinding not supported for this architecture\n",
96*7304104dSAndroid Build Coastguard Worker argv[0]);
97*7304104dSAndroid Build Coastguard Worker return 77;
98*7304104dSAndroid Build Coastguard Worker }
99*7304104dSAndroid Build Coastguard Worker
100*7304104dSAndroid Build Coastguard Worker #else /* __linux__ */
101*7304104dSAndroid Build Coastguard Worker #include <sys/ptrace.h>
102*7304104dSAndroid Build Coastguard Worker #include <signal.h>
103*7304104dSAndroid Build Coastguard Worker
104*7304104dSAndroid Build Coastguard Worker #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5)
105*7304104dSAndroid Build Coastguard Worker #define NOINLINE_NOCLONE __attribute__ ((noinline, noclone))
106*7304104dSAndroid Build Coastguard Worker #else
107*7304104dSAndroid Build Coastguard Worker #define NOINLINE_NOCLONE __attribute__ ((noinline))
108*7304104dSAndroid Build Coastguard Worker #endif
109*7304104dSAndroid Build Coastguard Worker
110*7304104dSAndroid Build Coastguard Worker #define NORETURN __attribute__ ((noreturn))
111*7304104dSAndroid Build Coastguard Worker #define UNUSED __attribute__ ((unused))
112*7304104dSAndroid Build Coastguard Worker #define USED __attribute__ ((used))
113*7304104dSAndroid Build Coastguard Worker
114*7304104dSAndroid Build Coastguard Worker static int ptraceme, gencore;
115*7304104dSAndroid Build Coastguard Worker
116*7304104dSAndroid Build Coastguard Worker /* Execution will arrive here from jmp by an artificial ptrace-spawn signal. */
117*7304104dSAndroid Build Coastguard Worker
118*7304104dSAndroid Build Coastguard Worker static NOINLINE_NOCLONE void
sigusr2(int signo)119*7304104dSAndroid Build Coastguard Worker sigusr2 (int signo)
120*7304104dSAndroid Build Coastguard Worker {
121*7304104dSAndroid Build Coastguard Worker assert (signo == SIGUSR2);
122*7304104dSAndroid Build Coastguard Worker if (! gencore)
123*7304104dSAndroid Build Coastguard Worker {
124*7304104dSAndroid Build Coastguard Worker raise (SIGUSR1);
125*7304104dSAndroid Build Coastguard Worker /* Do not return as stack may be invalid due to ptrace-patched PC to the
126*7304104dSAndroid Build Coastguard Worker jmp function. */
127*7304104dSAndroid Build Coastguard Worker pthread_exit (NULL);
128*7304104dSAndroid Build Coastguard Worker /* Not reached. */
129*7304104dSAndroid Build Coastguard Worker abort ();
130*7304104dSAndroid Build Coastguard Worker }
131*7304104dSAndroid Build Coastguard Worker /* Here we dump the core for --gencore. */
132*7304104dSAndroid Build Coastguard Worker raise (SIGABRT);
133*7304104dSAndroid Build Coastguard Worker /* Avoid tail call optimization for the raise call. */
134*7304104dSAndroid Build Coastguard Worker asm volatile ("");
135*7304104dSAndroid Build Coastguard Worker }
136*7304104dSAndroid Build Coastguard Worker
137*7304104dSAndroid Build Coastguard Worker static NOINLINE_NOCLONE void
dummy1(void)138*7304104dSAndroid Build Coastguard Worker dummy1 (void)
139*7304104dSAndroid Build Coastguard Worker {
140*7304104dSAndroid Build Coastguard Worker asm volatile ("");
141*7304104dSAndroid Build Coastguard Worker }
142*7304104dSAndroid Build Coastguard Worker
143*7304104dSAndroid Build Coastguard Worker #ifdef RAISE_JMP_PATCHING
144*7304104dSAndroid Build Coastguard Worker static NOINLINE_NOCLONE USED void
jmp(void)145*7304104dSAndroid Build Coastguard Worker jmp (void)
146*7304104dSAndroid Build Coastguard Worker {
147*7304104dSAndroid Build Coastguard Worker /* Not reached, signal will get ptrace-spawn to jump into sigusr2. */
148*7304104dSAndroid Build Coastguard Worker abort ();
149*7304104dSAndroid Build Coastguard Worker }
150*7304104dSAndroid Build Coastguard Worker #endif
151*7304104dSAndroid Build Coastguard Worker
152*7304104dSAndroid Build Coastguard Worker static NOINLINE_NOCLONE void
dummy2(void)153*7304104dSAndroid Build Coastguard Worker dummy2 (void)
154*7304104dSAndroid Build Coastguard Worker {
155*7304104dSAndroid Build Coastguard Worker asm volatile ("");
156*7304104dSAndroid Build Coastguard Worker }
157*7304104dSAndroid Build Coastguard Worker
158*7304104dSAndroid Build Coastguard Worker static NOINLINE_NOCLONE NORETURN void
stdarg(int f UNUSED,...)159*7304104dSAndroid Build Coastguard Worker stdarg (int f UNUSED, ...)
160*7304104dSAndroid Build Coastguard Worker {
161*7304104dSAndroid Build Coastguard Worker sighandler_t sigusr2_orig = signal (SIGUSR2, sigusr2);
162*7304104dSAndroid Build Coastguard Worker assert (sigusr2_orig == SIG_DFL);
163*7304104dSAndroid Build Coastguard Worker errno = 0;
164*7304104dSAndroid Build Coastguard Worker if (ptraceme)
165*7304104dSAndroid Build Coastguard Worker {
166*7304104dSAndroid Build Coastguard Worker long l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
167*7304104dSAndroid Build Coastguard Worker assert (l == 0);
168*7304104dSAndroid Build Coastguard Worker }
169*7304104dSAndroid Build Coastguard Worker #ifdef RAISE_JMP_PATCHING
170*7304104dSAndroid Build Coastguard Worker if (! gencore)
171*7304104dSAndroid Build Coastguard Worker {
172*7304104dSAndroid Build Coastguard Worker /* Execution will get PC patched into function jmp. */
173*7304104dSAndroid Build Coastguard Worker raise (SIGUSR1);
174*7304104dSAndroid Build Coastguard Worker }
175*7304104dSAndroid Build Coastguard Worker #endif
176*7304104dSAndroid Build Coastguard Worker sigusr2 (SIGUSR2);
177*7304104dSAndroid Build Coastguard Worker /* Not reached. */
178*7304104dSAndroid Build Coastguard Worker abort ();
179*7304104dSAndroid Build Coastguard Worker }
180*7304104dSAndroid Build Coastguard Worker
181*7304104dSAndroid Build Coastguard Worker static NOINLINE_NOCLONE void
dummy3(void)182*7304104dSAndroid Build Coastguard Worker dummy3 (void)
183*7304104dSAndroid Build Coastguard Worker {
184*7304104dSAndroid Build Coastguard Worker asm volatile ("");
185*7304104dSAndroid Build Coastguard Worker }
186*7304104dSAndroid Build Coastguard Worker
187*7304104dSAndroid Build Coastguard Worker static NOINLINE_NOCLONE void
backtracegen(void)188*7304104dSAndroid Build Coastguard Worker backtracegen (void)
189*7304104dSAndroid Build Coastguard Worker {
190*7304104dSAndroid Build Coastguard Worker stdarg (1);
191*7304104dSAndroid Build Coastguard Worker /* Here should be no instruction after the stdarg call as it is noreturn
192*7304104dSAndroid Build Coastguard Worker function. It must be stdarg so that it is a call and not jump (jump as
193*7304104dSAndroid Build Coastguard Worker a tail-call). */
194*7304104dSAndroid Build Coastguard Worker }
195*7304104dSAndroid Build Coastguard Worker
196*7304104dSAndroid Build Coastguard Worker static NOINLINE_NOCLONE void
dummy4(void)197*7304104dSAndroid Build Coastguard Worker dummy4 (void)
198*7304104dSAndroid Build Coastguard Worker {
199*7304104dSAndroid Build Coastguard Worker asm volatile ("");
200*7304104dSAndroid Build Coastguard Worker }
201*7304104dSAndroid Build Coastguard Worker
202*7304104dSAndroid Build Coastguard Worker static void *
start(void * arg UNUSED)203*7304104dSAndroid Build Coastguard Worker start (void *arg UNUSED)
204*7304104dSAndroid Build Coastguard Worker {
205*7304104dSAndroid Build Coastguard Worker backtracegen ();
206*7304104dSAndroid Build Coastguard Worker /* Not reached. */
207*7304104dSAndroid Build Coastguard Worker abort ();
208*7304104dSAndroid Build Coastguard Worker }
209*7304104dSAndroid Build Coastguard Worker
210*7304104dSAndroid Build Coastguard Worker int
main(int argc UNUSED,char ** argv)211*7304104dSAndroid Build Coastguard Worker main (int argc UNUSED, char **argv)
212*7304104dSAndroid Build Coastguard Worker {
213*7304104dSAndroid Build Coastguard Worker setbuf (stdout, NULL);
214*7304104dSAndroid Build Coastguard Worker assert (*argv++);
215*7304104dSAndroid Build Coastguard Worker ptraceme = (*argv && strcmp (*argv, "--ptraceme") == 0);
216*7304104dSAndroid Build Coastguard Worker argv += ptraceme;
217*7304104dSAndroid Build Coastguard Worker gencore = (*argv && strcmp (*argv, "--gencore") == 0);
218*7304104dSAndroid Build Coastguard Worker argv += gencore;
219*7304104dSAndroid Build Coastguard Worker assert (!*argv);
220*7304104dSAndroid Build Coastguard Worker /* These dummy* functions are there so that each of their surrounding
221*7304104dSAndroid Build Coastguard Worker functions has some unrelated code around. The purpose of some of the
222*7304104dSAndroid Build Coastguard Worker tests is verify unwinding the very first / after the very last instruction
223*7304104dSAndroid Build Coastguard Worker does not inappropriately slip into the unrelated code around. */
224*7304104dSAndroid Build Coastguard Worker dummy1 ();
225*7304104dSAndroid Build Coastguard Worker dummy2 ();
226*7304104dSAndroid Build Coastguard Worker dummy3 ();
227*7304104dSAndroid Build Coastguard Worker dummy4 ();
228*7304104dSAndroid Build Coastguard Worker if (gencore)
229*7304104dSAndroid Build Coastguard Worker printf ("%ld\n", (long) getpid ());
230*7304104dSAndroid Build Coastguard Worker pthread_t thread;
231*7304104dSAndroid Build Coastguard Worker int i = pthread_create (&thread, NULL, start, NULL);
232*7304104dSAndroid Build Coastguard Worker // pthread_* functions do not set errno.
233*7304104dSAndroid Build Coastguard Worker assert (i == 0);
234*7304104dSAndroid Build Coastguard Worker if (ptraceme)
235*7304104dSAndroid Build Coastguard Worker {
236*7304104dSAndroid Build Coastguard Worker errno = 0;
237*7304104dSAndroid Build Coastguard Worker long l = ptrace (PTRACE_TRACEME, 0, NULL, NULL);
238*7304104dSAndroid Build Coastguard Worker assert (l == 0);
239*7304104dSAndroid Build Coastguard Worker }
240*7304104dSAndroid Build Coastguard Worker if (gencore)
241*7304104dSAndroid Build Coastguard Worker pthread_join (thread, NULL);
242*7304104dSAndroid Build Coastguard Worker else
243*7304104dSAndroid Build Coastguard Worker raise (SIGUSR2);
244*7304104dSAndroid Build Coastguard Worker return 0;
245*7304104dSAndroid Build Coastguard Worker }
246*7304104dSAndroid Build Coastguard Worker
247*7304104dSAndroid Build Coastguard Worker #endif /* ! __linux__ */
248*7304104dSAndroid Build Coastguard Worker
249