* config.gcc (i386, x86_64): Add extra objects.
[official-gcc.git] / libbacktrace / btest.c
blob30d9e14526cf69d29e250d5f62b9619dc5d823e9
1 /* btest.c -- Test for libbacktrace library
2 Copyright (C) 2012-2017 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>
41 #include "filenames.h"
43 #include "backtrace.h"
44 #include "backtrace-supported.h"
46 #include "testlib.h"
48 /* Test the backtrace function with non-inlined functions. */
50 static int test1 (void) __attribute__ ((noinline, unused));
51 static int f2 (int) __attribute__ ((noinline));
52 static int f3 (int, int) __attribute__ ((noinline));
54 static int
55 test1 (void)
57 /* Returning a value here and elsewhere avoids a tailcall which
58 would mess up the backtrace. */
59 return f2 (__LINE__) + 1;
62 static int
63 f2 (int f1line)
65 return f3 (f1line, __LINE__) + 2;
68 static int
69 f3 (int f1line, int f2line)
71 struct info all[20];
72 struct bdata data;
73 int f3line;
74 int i;
76 data.all = &all[0];
77 data.index = 0;
78 data.max = 20;
79 data.failed = 0;
81 f3line = __LINE__ + 1;
82 i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
84 if (i != 0)
86 fprintf (stderr, "test1: unexpected return value %d\n", i);
87 data.failed = 1;
90 if (data.index < 3)
92 fprintf (stderr,
93 "test1: not enough frames; got %zu, expected at least 3\n",
94 data.index);
95 data.failed = 1;
98 check ("test1", 0, all, f3line, "f3", "btest.c", &data.failed);
99 check ("test1", 1, all, f2line, "f2", "btest.c", &data.failed);
100 check ("test1", 2, all, f1line, "test1", "btest.c", &data.failed);
102 printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");
104 if (data.failed)
105 ++failures;
107 return failures;
110 /* Test the backtrace function with inlined functions. */
112 static inline int test2 (void) __attribute__ ((always_inline, unused));
113 static inline int f12 (int) __attribute__ ((always_inline));
114 static inline int f13 (int, int) __attribute__ ((always_inline));
116 static inline int
117 test2 (void)
119 return f12 (__LINE__) + 1;
122 static inline int
123 f12 (int f1line)
125 return f13 (f1line, __LINE__) + 2;
128 static inline int
129 f13 (int f1line, int f2line)
131 struct info all[20];
132 struct bdata data;
133 int f3line;
134 int i;
136 data.all = &all[0];
137 data.index = 0;
138 data.max = 20;
139 data.failed = 0;
141 f3line = __LINE__ + 1;
142 i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
144 if (i != 0)
146 fprintf (stderr, "test2: unexpected return value %d\n", i);
147 data.failed = 1;
150 check ("test2", 0, all, f3line, "f13", "btest.c", &data.failed);
151 check ("test2", 1, all, f2line, "f12", "btest.c", &data.failed);
152 check ("test2", 2, all, f1line, "test2", "btest.c", &data.failed);
154 printf ("%s: backtrace_full inline\n", data.failed ? "FAIL" : "PASS");
156 if (data.failed)
157 ++failures;
159 return failures;
162 /* Test the backtrace_simple function with non-inlined functions. */
164 static int test3 (void) __attribute__ ((noinline, unused));
165 static int f22 (int) __attribute__ ((noinline));
166 static int f23 (int, int) __attribute__ ((noinline));
168 static int
169 test3 (void)
171 return f22 (__LINE__) + 1;
174 static int
175 f22 (int f1line)
177 return f23 (f1line, __LINE__) + 2;
180 static int
181 f23 (int f1line, int f2line)
183 uintptr_t addrs[20];
184 struct sdata data;
185 int f3line;
186 int i;
188 data.addrs = &addrs[0];
189 data.index = 0;
190 data.max = 20;
191 data.failed = 0;
193 f3line = __LINE__ + 1;
194 i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
196 if (i != 0)
198 fprintf (stderr, "test3: unexpected return value %d\n", i);
199 data.failed = 1;
202 if (!data.failed)
204 struct info all[20];
205 struct bdata bdata;
206 int j;
208 bdata.all = &all[0];
209 bdata.index = 0;
210 bdata.max = 20;
211 bdata.failed = 0;
213 for (j = 0; j < 3; ++j)
215 i = backtrace_pcinfo (state, addrs[j], callback_one,
216 error_callback_one, &bdata);
217 if (i != 0)
219 fprintf (stderr,
220 ("test3: unexpected return value "
221 "from backtrace_pcinfo %d\n"),
223 bdata.failed = 1;
225 if (!bdata.failed && bdata.index != (size_t) (j + 1))
227 fprintf (stderr,
228 ("wrong number of calls from backtrace_pcinfo "
229 "got %u expected %d\n"),
230 (unsigned int) bdata.index, j + 1);
231 bdata.failed = 1;
235 check ("test3", 0, all, f3line, "f23", "btest.c", &bdata.failed);
236 check ("test3", 1, all, f2line, "f22", "btest.c", &bdata.failed);
237 check ("test3", 2, all, f1line, "test3", "btest.c", &bdata.failed);
239 if (bdata.failed)
240 data.failed = 1;
242 for (j = 0; j < 3; ++j)
244 struct symdata symdata;
246 symdata.name = NULL;
247 symdata.val = 0;
248 symdata.size = 0;
249 symdata.failed = 0;
251 i = backtrace_syminfo (state, addrs[j], callback_three,
252 error_callback_three, &symdata);
253 if (i == 0)
255 fprintf (stderr,
256 ("test3: [%d]: unexpected return value "
257 "from backtrace_syminfo %d\n"),
258 j, i);
259 symdata.failed = 1;
262 if (!symdata.failed)
264 const char *expected;
266 switch (j)
268 case 0:
269 expected = "f23";
270 break;
271 case 1:
272 expected = "f22";
273 break;
274 case 2:
275 expected = "test3";
276 break;
277 default:
278 assert (0);
281 if (symdata.name == NULL)
283 fprintf (stderr, "test3: [%d]: NULL syminfo name\n", j);
284 symdata.failed = 1;
286 /* Use strncmp, not strcmp, because GCC might create a
287 clone. */
288 else if (strncmp (symdata.name, expected, strlen (expected))
289 != 0)
291 fprintf (stderr,
292 ("test3: [%d]: unexpected syminfo name "
293 "got %s expected %s\n"),
294 j, symdata.name, expected);
295 symdata.failed = 1;
299 if (symdata.failed)
300 data.failed = 1;
304 printf ("%s: backtrace_simple noinline\n", data.failed ? "FAIL" : "PASS");
306 if (data.failed)
307 ++failures;
309 return failures;
312 /* Test the backtrace_simple function with inlined functions. */
314 static inline int test4 (void) __attribute__ ((always_inline, unused));
315 static inline int f32 (int) __attribute__ ((always_inline));
316 static inline int f33 (int, int) __attribute__ ((always_inline));
318 static inline int
319 test4 (void)
321 return f32 (__LINE__) + 1;
324 static inline int
325 f32 (int f1line)
327 return f33 (f1line, __LINE__) + 2;
330 static inline int
331 f33 (int f1line, int f2line)
333 uintptr_t addrs[20];
334 struct sdata data;
335 int f3line;
336 int i;
338 data.addrs = &addrs[0];
339 data.index = 0;
340 data.max = 20;
341 data.failed = 0;
343 f3line = __LINE__ + 1;
344 i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
346 if (i != 0)
348 fprintf (stderr, "test3: unexpected return value %d\n", i);
349 data.failed = 1;
352 if (!data.failed)
354 struct info all[20];
355 struct bdata bdata;
357 bdata.all = &all[0];
358 bdata.index = 0;
359 bdata.max = 20;
360 bdata.failed = 0;
362 i = backtrace_pcinfo (state, addrs[0], callback_one, error_callback_one,
363 &bdata);
364 if (i != 0)
366 fprintf (stderr,
367 ("test4: unexpected return value "
368 "from backtrace_pcinfo %d\n"),
370 bdata.failed = 1;
373 check ("test4", 0, all, f3line, "f33", "btest.c", &bdata.failed);
374 check ("test4", 1, all, f2line, "f32", "btest.c", &bdata.failed);
375 check ("test4", 2, all, f1line, "test4", "btest.c", &bdata.failed);
377 if (bdata.failed)
378 data.failed = 1;
381 printf ("%s: backtrace_simple inline\n", data.failed ? "FAIL" : "PASS");
383 if (data.failed)
384 ++failures;
386 return failures;
389 static int test5 (void) __attribute__ ((unused));
391 int global = 1;
393 static int
394 test5 (void)
396 struct symdata symdata;
397 int i;
398 uintptr_t addr = (uintptr_t) &global;
400 if (sizeof (global) > 1)
401 addr += 1;
403 symdata.name = NULL;
404 symdata.val = 0;
405 symdata.size = 0;
406 symdata.failed = 0;
408 i = backtrace_syminfo (state, addr, callback_three,
409 error_callback_three, &symdata);
410 if (i == 0)
412 fprintf (stderr,
413 "test5: unexpected return value from backtrace_syminfo %d\n",
415 symdata.failed = 1;
418 if (!symdata.failed)
420 if (symdata.name == NULL)
422 fprintf (stderr, "test5: NULL syminfo name\n");
423 symdata.failed = 1;
425 else if (strcmp (symdata.name, "global") != 0)
427 fprintf (stderr,
428 "test5: unexpected syminfo name got %s expected %s\n",
429 symdata.name, "global");
430 symdata.failed = 1;
432 else if (symdata.val != (uintptr_t) &global)
434 fprintf (stderr,
435 "test5: unexpected syminfo value got %lx expected %lx\n",
436 (unsigned long) symdata.val,
437 (unsigned long) (uintptr_t) &global);
438 symdata.failed = 1;
440 else if (symdata.size != sizeof (global))
442 fprintf (stderr,
443 "test5: unexpected syminfo size got %lx expected %lx\n",
444 (unsigned long) symdata.size,
445 (unsigned long) sizeof (global));
446 symdata.failed = 1;
450 printf ("%s: backtrace_syminfo variable\n",
451 symdata.failed ? "FAIL" : "PASS");
453 if (symdata.failed)
454 ++failures;
456 return failures;
459 /* Run all the tests. */
462 main (int argc ATTRIBUTE_UNUSED, char **argv)
464 state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
465 error_callback_create, NULL);
467 #if BACKTRACE_SUPPORTED
468 test1 ();
469 test2 ();
470 test3 ();
471 test4 ();
472 #if BACKTRACE_SUPPORTS_DATA
473 test5 ();
474 #endif
475 #endif
477 exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);