1 /* btest.c -- Test for libbacktrace library
2 Copyright (C) 2012-2021 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
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
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. */
42 #include "filenames.h"
44 #include "backtrace.h"
45 #include "backtrace-supported.h"
49 /* Test the backtrace function with non-inlined functions. */
51 static int test1 (void) __attribute__ ((noinline
, noclone
, unused
));
52 static int f2 (int) __attribute__ ((noinline
, noclone
));
53 static int f3 (int, int) __attribute__ ((noinline
, noclone
));
58 /* Returning a value here and elsewhere avoids a tailcall which
59 would mess up the backtrace. */
60 return f2 (__LINE__
) + 1;
66 return f3 (f1line
, __LINE__
) + 2;
70 f3 (int f1line
, int f2line
)
82 f3line
= __LINE__
+ 1;
83 i
= backtrace_full (state
, 0, callback_one
, error_callback_one
, &data
);
87 fprintf (stderr
, "test1: unexpected return value %d\n", i
);
94 "test1: not enough frames; got %zu, expected at least 3\n",
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");
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
));
120 return f12 (__LINE__
) + 1;
126 return f13 (f1line
, __LINE__
) + 2;
130 f13 (int f1line
, int f2line
)
142 f3line
= __LINE__
+ 1;
143 i
= backtrace_full (state
, 0, callback_one
, error_callback_one
, &data
);
147 fprintf (stderr
, "test2: unexpected return value %d\n", i
);
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");
163 /* Test the backtrace_simple function with non-inlined functions. */
165 static int test3 (void) __attribute__ ((noinline
, noclone
, unused
));
166 static int f22 (int) __attribute__ ((noinline
, noclone
));
167 static int f23 (int, int) __attribute__ ((noinline
, noclone
));
172 return f22 (__LINE__
) + 1;
178 return f23 (f1line
, __LINE__
) + 2;
182 f23 (int f1line
, int f2line
)
189 data
.addrs
= &addrs
[0];
194 f3line
= __LINE__
+ 1;
195 i
= backtrace_simple (state
, 0, callback_two
, error_callback_two
, &data
);
199 fprintf (stderr
, "test3: unexpected return value %d\n", i
);
214 for (j
= 0; j
< 3; ++j
)
216 i
= backtrace_pcinfo (state
, addrs
[j
], callback_one
,
217 error_callback_one
, &bdata
);
221 ("test3: unexpected return value "
222 "from backtrace_pcinfo %d\n"),
226 if (!bdata
.failed
&& bdata
.index
!= (size_t) (j
+ 1))
229 ("wrong number of calls from backtrace_pcinfo "
230 "got %u expected %d\n"),
231 (unsigned int) bdata
.index
, j
+ 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
);
243 for (j
= 0; j
< 3; ++j
)
245 struct symdata symdata
;
252 i
= backtrace_syminfo (state
, addrs
[j
], callback_three
,
253 error_callback_three
, &symdata
);
257 ("test3: [%d]: unexpected return value "
258 "from backtrace_syminfo %d\n"),
265 const char *expected
;
282 if (symdata
.name
== NULL
)
284 fprintf (stderr
, "test3: [%d]: NULL syminfo name\n", j
);
287 /* Use strncmp, not strcmp, because GCC might create a
289 else if (strncmp (symdata
.name
, expected
, strlen (expected
))
293 ("test3: [%d]: unexpected syminfo name "
294 "got %s expected %s\n"),
295 j
, symdata
.name
, expected
);
305 printf ("%s: backtrace_simple noinline\n", data
.failed
? "FAIL" : "PASS");
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
));
322 return f32 (__LINE__
) + 1;
328 return f33 (f1line
, __LINE__
) + 2;
332 f33 (int f1line
, int f2line
)
339 data
.addrs
= &addrs
[0];
344 f3line
= __LINE__
+ 1;
345 i
= backtrace_simple (state
, 0, callback_two
, error_callback_two
, &data
);
349 fprintf (stderr
, "test3: unexpected return value %d\n", i
);
363 i
= backtrace_pcinfo (state
, addrs
[0], callback_one
, error_callback_one
,
368 ("test4: unexpected return value "
369 "from backtrace_pcinfo %d\n"),
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
);
382 printf ("%s: backtrace_simple inline\n", data
.failed
? "FAIL" : "PASS");
390 static int test5 (void) __attribute__ ((unused
));
397 struct symdata symdata
;
399 uintptr_t addr
= (uintptr_t) &global
;
401 if (sizeof (global
) > 1)
409 i
= backtrace_syminfo (state
, addr
, callback_three
,
410 error_callback_three
, &symdata
);
414 "test5: unexpected return value from backtrace_syminfo %d\n",
421 if (symdata
.name
== NULL
)
423 fprintf (stderr
, "test5: NULL syminfo name\n");
426 else if (!(strncmp (symdata
.name
, "global", 6) == 0
427 && (symdata
.name
[6] == '\0'|| symdata
.name
[6] == '.')))
430 "test5: unexpected syminfo name got %s expected %s\n",
431 symdata
.name
, "global");
434 else if (symdata
.val
!= (uintptr_t) &global
)
437 "test5: unexpected syminfo value got %lx expected %lx\n",
438 (unsigned long) symdata
.val
,
439 (unsigned long) (uintptr_t) &global
);
442 else if (symdata
.size
!= sizeof (global
))
445 "test5: unexpected syminfo size got %lx expected %lx\n",
446 (unsigned long) symdata
.size
,
447 (unsigned long) sizeof (global
));
452 printf ("%s: backtrace_syminfo variable\n",
453 symdata
.failed
? "FAIL" : "PASS");
461 /* Check that are no files left open. */
464 check_open_files (void)
468 for (i
= 3; i
< 10; i
++)
473 "ERROR: descriptor %d still open after tests complete\n",
480 /* Run all the tests. */
483 main (int argc ATTRIBUTE_UNUSED
, char **argv
)
485 state
= backtrace_create_state (argv
[0], BACKTRACE_SUPPORTS_THREADS
,
486 error_callback_create
, NULL
);
488 #if BACKTRACE_SUPPORTED
493 #if BACKTRACE_SUPPORTS_DATA
500 exit (failures
? EXIT_FAILURE
: EXIT_SUCCESS
);