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
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. */
41 #include "filenames.h"
43 #include "backtrace.h"
44 #include "backtrace-supported.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
));
57 /* Returning a value here and elsewhere avoids a tailcall which
58 would mess up the backtrace. */
59 return f2 (__LINE__
) + 1;
65 return f3 (f1line
, __LINE__
) + 2;
69 f3 (int f1line
, int f2line
)
81 f3line
= __LINE__
+ 1;
82 i
= backtrace_full (state
, 0, callback_one
, error_callback_one
, &data
);
86 fprintf (stderr
, "test1: unexpected return value %d\n", i
);
93 "test1: not enough frames; got %zu, expected at least 3\n",
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");
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
));
119 return f12 (__LINE__
) + 1;
125 return f13 (f1line
, __LINE__
) + 2;
129 f13 (int f1line
, int f2line
)
141 f3line
= __LINE__
+ 1;
142 i
= backtrace_full (state
, 0, callback_one
, error_callback_one
, &data
);
146 fprintf (stderr
, "test2: unexpected return value %d\n", i
);
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");
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
));
171 return f22 (__LINE__
) + 1;
177 return f23 (f1line
, __LINE__
) + 2;
181 f23 (int f1line
, int f2line
)
188 data
.addrs
= &addrs
[0];
193 f3line
= __LINE__
+ 1;
194 i
= backtrace_simple (state
, 0, callback_two
, error_callback_two
, &data
);
198 fprintf (stderr
, "test3: unexpected return value %d\n", i
);
213 for (j
= 0; j
< 3; ++j
)
215 i
= backtrace_pcinfo (state
, addrs
[j
], callback_one
,
216 error_callback_one
, &bdata
);
220 ("test3: unexpected return value "
221 "from backtrace_pcinfo %d\n"),
225 if (!bdata
.failed
&& bdata
.index
!= (size_t) (j
+ 1))
228 ("wrong number of calls from backtrace_pcinfo "
229 "got %u expected %d\n"),
230 (unsigned int) bdata
.index
, j
+ 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
);
242 for (j
= 0; j
< 3; ++j
)
244 struct symdata symdata
;
251 i
= backtrace_syminfo (state
, addrs
[j
], callback_three
,
252 error_callback_three
, &symdata
);
256 ("test3: [%d]: unexpected return value "
257 "from backtrace_syminfo %d\n"),
264 const char *expected
;
281 if (symdata
.name
== NULL
)
283 fprintf (stderr
, "test3: [%d]: NULL syminfo name\n", j
);
286 /* Use strncmp, not strcmp, because GCC might create a
288 else if (strncmp (symdata
.name
, expected
, strlen (expected
))
292 ("test3: [%d]: unexpected syminfo name "
293 "got %s expected %s\n"),
294 j
, symdata
.name
, expected
);
304 printf ("%s: backtrace_simple noinline\n", data
.failed
? "FAIL" : "PASS");
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
));
321 return f32 (__LINE__
) + 1;
327 return f33 (f1line
, __LINE__
) + 2;
331 f33 (int f1line
, int f2line
)
338 data
.addrs
= &addrs
[0];
343 f3line
= __LINE__
+ 1;
344 i
= backtrace_simple (state
, 0, callback_two
, error_callback_two
, &data
);
348 fprintf (stderr
, "test3: unexpected return value %d\n", i
);
362 i
= backtrace_pcinfo (state
, addrs
[0], callback_one
, error_callback_one
,
367 ("test4: unexpected return value "
368 "from backtrace_pcinfo %d\n"),
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
);
381 printf ("%s: backtrace_simple inline\n", data
.failed
? "FAIL" : "PASS");
389 static int test5 (void) __attribute__ ((unused
));
396 struct symdata symdata
;
398 uintptr_t addr
= (uintptr_t) &global
;
400 if (sizeof (global
) > 1)
408 i
= backtrace_syminfo (state
, addr
, callback_three
,
409 error_callback_three
, &symdata
);
413 "test5: unexpected return value from backtrace_syminfo %d\n",
420 if (symdata
.name
== NULL
)
422 fprintf (stderr
, "test5: NULL syminfo name\n");
425 else if (strcmp (symdata
.name
, "global") != 0)
428 "test5: unexpected syminfo name got %s expected %s\n",
429 symdata
.name
, "global");
432 else if (symdata
.val
!= (uintptr_t) &global
)
435 "test5: unexpected syminfo value got %lx expected %lx\n",
436 (unsigned long) symdata
.val
,
437 (unsigned long) (uintptr_t) &global
);
440 else if (symdata
.size
!= sizeof (global
))
443 "test5: unexpected syminfo size got %lx expected %lx\n",
444 (unsigned long) symdata
.size
,
445 (unsigned long) sizeof (global
));
450 printf ("%s: backtrace_syminfo variable\n",
451 symdata
.failed
? "FAIL" : "PASS");
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
472 #if BACKTRACE_SUPPORTS_DATA
477 exit (failures
? EXIT_FAILURE
: EXIT_SUCCESS
);