[PR c++/80290] recycle tinst garbage sooner
[official-gcc.git] / libbacktrace / btest.c
blob1348d54da509d4daed4697d93b43239ea64639b5
1 /* btest.c -- Test for libbacktrace library
2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Google.
5 Redistribution and use in source and binary forms, with or without
6 modification, are permitted provided that the following conditions are
7 met:
9 (1) Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
12 (2) Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in
14 the documentation and/or other materials provided with the
15 distribution.
17 (3) The name of the author may not be used to
18 endorse or promote products derived from this software without
19 specific prior written permission.
21 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30 IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 POSSIBILITY OF SUCH DAMAGE. */
33 /* This program tests the externally visible interfaces of the
34 libbacktrace library. */
36 #include <assert.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <unistd.h>
42 #include "filenames.h"
44 #include "backtrace.h"
45 #include "backtrace-supported.h"
47 #include "testlib.h"
49 /* Test the backtrace function with non-inlined functions. */
51 static int test1 (void) __attribute__ ((noinline, unused));
52 static int f2 (int) __attribute__ ((noinline));
53 static int f3 (int, int) __attribute__ ((noinline));
55 static int
56 test1 (void)
58 /* Returning a value here and elsewhere avoids a tailcall which
59 would mess up the backtrace. */
60 return f2 (__LINE__) + 1;
63 static int
64 f2 (int f1line)
66 return f3 (f1line, __LINE__) + 2;
69 static int
70 f3 (int f1line, int f2line)
72 struct info all[20];
73 struct bdata data;
74 int f3line;
75 int i;
77 data.all = &all[0];
78 data.index = 0;
79 data.max = 20;
80 data.failed = 0;
82 f3line = __LINE__ + 1;
83 i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
85 if (i != 0)
87 fprintf (stderr, "test1: unexpected return value %d\n", i);
88 data.failed = 1;
91 if (data.index < 3)
93 fprintf (stderr,
94 "test1: not enough frames; got %zu, expected at least 3\n",
95 data.index);
96 data.failed = 1;
99 check ("test1", 0, all, f3line, "f3", "btest.c", &data.failed);
100 check ("test1", 1, all, f2line, "f2", "btest.c", &data.failed);
101 check ("test1", 2, all, f1line, "test1", "btest.c", &data.failed);
103 printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");
105 if (data.failed)
106 ++failures;
108 return failures;
111 /* Test the backtrace function with inlined functions. */
113 static inline int test2 (void) __attribute__ ((always_inline, unused));
114 static inline int f12 (int) __attribute__ ((always_inline));
115 static inline int f13 (int, int) __attribute__ ((always_inline));
117 static inline int
118 test2 (void)
120 return f12 (__LINE__) + 1;
123 static inline int
124 f12 (int f1line)
126 return f13 (f1line, __LINE__) + 2;
129 static inline int
130 f13 (int f1line, int f2line)
132 struct info all[20];
133 struct bdata data;
134 int f3line;
135 int i;
137 data.all = &all[0];
138 data.index = 0;
139 data.max = 20;
140 data.failed = 0;
142 f3line = __LINE__ + 1;
143 i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
145 if (i != 0)
147 fprintf (stderr, "test2: unexpected return value %d\n", i);
148 data.failed = 1;
151 check ("test2", 0, all, f3line, "f13", "btest.c", &data.failed);
152 check ("test2", 1, all, f2line, "f12", "btest.c", &data.failed);
153 check ("test2", 2, all, f1line, "test2", "btest.c", &data.failed);
155 printf ("%s: backtrace_full inline\n", data.failed ? "FAIL" : "PASS");
157 if (data.failed)
158 ++failures;
160 return failures;
163 /* Test the backtrace_simple function with non-inlined functions. */
165 static int test3 (void) __attribute__ ((noinline, unused));
166 static int f22 (int) __attribute__ ((noinline));
167 static int f23 (int, int) __attribute__ ((noinline));
169 static int
170 test3 (void)
172 return f22 (__LINE__) + 1;
175 static int
176 f22 (int f1line)
178 return f23 (f1line, __LINE__) + 2;
181 static int
182 f23 (int f1line, int f2line)
184 uintptr_t addrs[20];
185 struct sdata data;
186 int f3line;
187 int i;
189 data.addrs = &addrs[0];
190 data.index = 0;
191 data.max = 20;
192 data.failed = 0;
194 f3line = __LINE__ + 1;
195 i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
197 if (i != 0)
199 fprintf (stderr, "test3: unexpected return value %d\n", i);
200 data.failed = 1;
203 if (!data.failed)
205 struct info all[20];
206 struct bdata bdata;
207 int j;
209 bdata.all = &all[0];
210 bdata.index = 0;
211 bdata.max = 20;
212 bdata.failed = 0;
214 for (j = 0; j < 3; ++j)
216 i = backtrace_pcinfo (state, addrs[j], callback_one,
217 error_callback_one, &bdata);
218 if (i != 0)
220 fprintf (stderr,
221 ("test3: unexpected return value "
222 "from backtrace_pcinfo %d\n"),
224 bdata.failed = 1;
226 if (!bdata.failed && bdata.index != (size_t) (j + 1))
228 fprintf (stderr,
229 ("wrong number of calls from backtrace_pcinfo "
230 "got %u expected %d\n"),
231 (unsigned int) bdata.index, j + 1);
232 bdata.failed = 1;
236 check ("test3", 0, all, f3line, "f23", "btest.c", &bdata.failed);
237 check ("test3", 1, all, f2line, "f22", "btest.c", &bdata.failed);
238 check ("test3", 2, all, f1line, "test3", "btest.c", &bdata.failed);
240 if (bdata.failed)
241 data.failed = 1;
243 for (j = 0; j < 3; ++j)
245 struct symdata symdata;
247 symdata.name = NULL;
248 symdata.val = 0;
249 symdata.size = 0;
250 symdata.failed = 0;
252 i = backtrace_syminfo (state, addrs[j], callback_three,
253 error_callback_three, &symdata);
254 if (i == 0)
256 fprintf (stderr,
257 ("test3: [%d]: unexpected return value "
258 "from backtrace_syminfo %d\n"),
259 j, i);
260 symdata.failed = 1;
263 if (!symdata.failed)
265 const char *expected;
267 switch (j)
269 case 0:
270 expected = "f23";
271 break;
272 case 1:
273 expected = "f22";
274 break;
275 case 2:
276 expected = "test3";
277 break;
278 default:
279 assert (0);
282 if (symdata.name == NULL)
284 fprintf (stderr, "test3: [%d]: NULL syminfo name\n", j);
285 symdata.failed = 1;
287 /* Use strncmp, not strcmp, because GCC might create a
288 clone. */
289 else if (strncmp (symdata.name, expected, strlen (expected))
290 != 0)
292 fprintf (stderr,
293 ("test3: [%d]: unexpected syminfo name "
294 "got %s expected %s\n"),
295 j, symdata.name, expected);
296 symdata.failed = 1;
300 if (symdata.failed)
301 data.failed = 1;
305 printf ("%s: backtrace_simple noinline\n", data.failed ? "FAIL" : "PASS");
307 if (data.failed)
308 ++failures;
310 return failures;
313 /* Test the backtrace_simple function with inlined functions. */
315 static inline int test4 (void) __attribute__ ((always_inline, unused));
316 static inline int f32 (int) __attribute__ ((always_inline));
317 static inline int f33 (int, int) __attribute__ ((always_inline));
319 static inline int
320 test4 (void)
322 return f32 (__LINE__) + 1;
325 static inline int
326 f32 (int f1line)
328 return f33 (f1line, __LINE__) + 2;
331 static inline int
332 f33 (int f1line, int f2line)
334 uintptr_t addrs[20];
335 struct sdata data;
336 int f3line;
337 int i;
339 data.addrs = &addrs[0];
340 data.index = 0;
341 data.max = 20;
342 data.failed = 0;
344 f3line = __LINE__ + 1;
345 i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
347 if (i != 0)
349 fprintf (stderr, "test3: unexpected return value %d\n", i);
350 data.failed = 1;
353 if (!data.failed)
355 struct info all[20];
356 struct bdata bdata;
358 bdata.all = &all[0];
359 bdata.index = 0;
360 bdata.max = 20;
361 bdata.failed = 0;
363 i = backtrace_pcinfo (state, addrs[0], callback_one, error_callback_one,
364 &bdata);
365 if (i != 0)
367 fprintf (stderr,
368 ("test4: unexpected return value "
369 "from backtrace_pcinfo %d\n"),
371 bdata.failed = 1;
374 check ("test4", 0, all, f3line, "f33", "btest.c", &bdata.failed);
375 check ("test4", 1, all, f2line, "f32", "btest.c", &bdata.failed);
376 check ("test4", 2, all, f1line, "test4", "btest.c", &bdata.failed);
378 if (bdata.failed)
379 data.failed = 1;
382 printf ("%s: backtrace_simple inline\n", data.failed ? "FAIL" : "PASS");
384 if (data.failed)
385 ++failures;
387 return failures;
390 static int test5 (void) __attribute__ ((unused));
392 int global = 1;
394 static int
395 test5 (void)
397 struct symdata symdata;
398 int i;
399 uintptr_t addr = (uintptr_t) &global;
401 if (sizeof (global) > 1)
402 addr += 1;
404 symdata.name = NULL;
405 symdata.val = 0;
406 symdata.size = 0;
407 symdata.failed = 0;
409 i = backtrace_syminfo (state, addr, callback_three,
410 error_callback_three, &symdata);
411 if (i == 0)
413 fprintf (stderr,
414 "test5: unexpected return value from backtrace_syminfo %d\n",
416 symdata.failed = 1;
419 if (!symdata.failed)
421 if (symdata.name == NULL)
423 fprintf (stderr, "test5: NULL syminfo name\n");
424 symdata.failed = 1;
426 else if (strcmp (symdata.name, "global") != 0)
428 fprintf (stderr,
429 "test5: unexpected syminfo name got %s expected %s\n",
430 symdata.name, "global");
431 symdata.failed = 1;
433 else if (symdata.val != (uintptr_t) &global)
435 fprintf (stderr,
436 "test5: unexpected syminfo value got %lx expected %lx\n",
437 (unsigned long) symdata.val,
438 (unsigned long) (uintptr_t) &global);
439 symdata.failed = 1;
441 else if (symdata.size != sizeof (global))
443 fprintf (stderr,
444 "test5: unexpected syminfo size got %lx expected %lx\n",
445 (unsigned long) symdata.size,
446 (unsigned long) sizeof (global));
447 symdata.failed = 1;
451 printf ("%s: backtrace_syminfo variable\n",
452 symdata.failed ? "FAIL" : "PASS");
454 if (symdata.failed)
455 ++failures;
457 return failures;
460 /* Check that are no files left open. */
462 static void
463 check_open_files (void)
465 int i;
467 for (i = 3; i < 10; i++)
469 if (close (i) == 0)
471 fprintf (stderr,
472 "ERROR: descriptor %d still open after tests complete\n",
474 ++failures;
479 /* Run all the tests. */
482 main (int argc ATTRIBUTE_UNUSED, char **argv)
484 state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
485 error_callback_create, NULL);
487 #if BACKTRACE_SUPPORTED
488 test1 ();
489 test2 ();
490 test3 ();
491 test4 ();
492 #if BACKTRACE_SUPPORTS_DATA
493 test5 ();
494 #endif
495 #endif
497 check_open_files ();
499 exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);