Warning: That file was not part of the compilation database. It may have many parsing errors.

1/* btest.c -- Test for libbacktrace library
2 Copyright (C) 2012-2017 Free Software Foundation, Inc.
3 Written by Ian Lance Taylor, Google.
4
5Redistribution and use in source and binary forms, with or without
6modification, are permitted provided that the following conditions are
7met:
8
9 (1) Redistributions of source code must retain the above copyright
10 notice, this list of conditions and the following disclaimer.
11
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.
16
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.
20
21THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
30IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31POSSIBILITY OF SUCH DAMAGE. */
32
33/* This program tests the externally visible interfaces of the
34 libbacktrace library. */
35
36#include <assert.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40
41#include "filenames.h"
42
43#include "backtrace.h"
44#include "backtrace-supported.h"
45
46#include "testlib.h"
47
48/* Test the backtrace function with non-inlined functions. */
49
50static int test1 (void) __attribute__ ((noinline, unused));
51static int f2 (int) __attribute__ ((noinline));
52static int f3 (int, int) __attribute__ ((noinline));
53
54static int
55test1 (void)
56{
57 /* Returning a value here and elsewhere avoids a tailcall which
58 would mess up the backtrace. */
59 return f2 (__LINE__) + 1;
60}
61
62static int
63f2 (int f1line)
64{
65 return f3 (f1line, __LINE__) + 2;
66}
67
68static int
69f3 (int f1line, int f2line)
70{
71 struct info all[20];
72 struct bdata data;
73 int f3line;
74 int i;
75
76 data.all = &all[0];
77 data.index = 0;
78 data.max = 20;
79 data.failed = 0;
80
81 f3line = __LINE__ + 1;
82 i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
83
84 if (i != 0)
85 {
86 fprintf (stderr, "test1: unexpected return value %d\n", i);
87 data.failed = 1;
88 }
89
90 if (data.index < 3)
91 {
92 fprintf (stderr,
93 "test1: not enough frames; got %zu, expected at least 3\n",
94 data.index);
95 data.failed = 1;
96 }
97
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);
101
102 printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");
103
104 if (data.failed)
105 ++failures;
106
107 return failures;
108}
109
110/* Test the backtrace function with inlined functions. */
111
112static inline int test2 (void) __attribute__ ((always_inline, unused));
113static inline int f12 (int) __attribute__ ((always_inline));
114static inline int f13 (int, int) __attribute__ ((always_inline));
115
116static inline int
117test2 (void)
118{
119 return f12 (__LINE__) + 1;
120}
121
122static inline int
123f12 (int f1line)
124{
125 return f13 (f1line, __LINE__) + 2;
126}
127
128static inline int
129f13 (int f1line, int f2line)
130{
131 struct info all[20];
132 struct bdata data;
133 int f3line;
134 int i;
135
136 data.all = &all[0];
137 data.index = 0;
138 data.max = 20;
139 data.failed = 0;
140
141 f3line = __LINE__ + 1;
142 i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
143
144 if (i != 0)
145 {
146 fprintf (stderr, "test2: unexpected return value %d\n", i);
147 data.failed = 1;
148 }
149
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);
153
154 printf ("%s: backtrace_full inline\n", data.failed ? "FAIL" : "PASS");
155
156 if (data.failed)
157 ++failures;
158
159 return failures;
160}
161
162/* Test the backtrace_simple function with non-inlined functions. */
163
164static int test3 (void) __attribute__ ((noinline, unused));
165static int f22 (int) __attribute__ ((noinline));
166static int f23 (int, int) __attribute__ ((noinline));
167
168static int
169test3 (void)
170{
171 return f22 (__LINE__) + 1;
172}
173
174static int
175f22 (int f1line)
176{
177 return f23 (f1line, __LINE__) + 2;
178}
179
180static int
181f23 (int f1line, int f2line)
182{
183 uintptr_t addrs[20];
184 struct sdata data;
185 int f3line;
186 int i;
187
188 data.addrs = &addrs[0];
189 data.index = 0;
190 data.max = 20;
191 data.failed = 0;
192
193 f3line = __LINE__ + 1;
194 i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
195
196 if (i != 0)
197 {
198 fprintf (stderr, "test3: unexpected return value %d\n", i);
199 data.failed = 1;
200 }
201
202 if (!data.failed)
203 {
204 struct info all[20];
205 struct bdata bdata;
206 int j;
207
208 bdata.all = &all[0];
209 bdata.index = 0;
210 bdata.max = 20;
211 bdata.failed = 0;
212
213 for (j = 0; j < 3; ++j)
214 {
215 i = backtrace_pcinfo (state, addrs[j], callback_one,
216 error_callback_one, &bdata);
217 if (i != 0)
218 {
219 fprintf (stderr,
220 ("test3: unexpected return value "
221 "from backtrace_pcinfo %d\n"),
222 i);
223 bdata.failed = 1;
224 }
225 if (!bdata.failed && bdata.index != (size_t) (j + 1))
226 {
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;
232 }
233 }
234
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);
238
239 if (bdata.failed)
240 data.failed = 1;
241
242 for (j = 0; j < 3; ++j)
243 {
244 struct symdata symdata;
245
246 symdata.name = NULL;
247 symdata.val = 0;
248 symdata.size = 0;
249 symdata.failed = 0;
250
251 i = backtrace_syminfo (state, addrs[j], callback_three,
252 error_callback_three, &symdata);
253 if (i == 0)
254 {
255 fprintf (stderr,
256 ("test3: [%d]: unexpected return value "
257 "from backtrace_syminfo %d\n"),
258 j, i);
259 symdata.failed = 1;
260 }
261
262 if (!symdata.failed)
263 {
264 const char *expected;
265
266 switch (j)
267 {
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);
279 }
280
281 if (symdata.name == NULL)
282 {
283 fprintf (stderr, "test3: [%d]: NULL syminfo name\n", j);
284 symdata.failed = 1;
285 }
286 /* Use strncmp, not strcmp, because GCC might create a
287 clone. */
288 else if (strncmp (symdata.name, expected, strlen (expected))
289 != 0)
290 {
291 fprintf (stderr,
292 ("test3: [%d]: unexpected syminfo name "
293 "got %s expected %s\n"),
294 j, symdata.name, expected);
295 symdata.failed = 1;
296 }
297 }
298
299 if (symdata.failed)
300 data.failed = 1;
301 }
302 }
303
304 printf ("%s: backtrace_simple noinline\n", data.failed ? "FAIL" : "PASS");
305
306 if (data.failed)
307 ++failures;
308
309 return failures;
310}
311
312/* Test the backtrace_simple function with inlined functions. */
313
314static inline int test4 (void) __attribute__ ((always_inline, unused));
315static inline int f32 (int) __attribute__ ((always_inline));
316static inline int f33 (int, int) __attribute__ ((always_inline));
317
318static inline int
319test4 (void)
320{
321 return f32 (__LINE__) + 1;
322}
323
324static inline int
325f32 (int f1line)
326{
327 return f33 (f1line, __LINE__) + 2;
328}
329
330static inline int
331f33 (int f1line, int f2line)
332{
333 uintptr_t addrs[20];
334 struct sdata data;
335 int f3line;
336 int i;
337
338 data.addrs = &addrs[0];
339 data.index = 0;
340 data.max = 20;
341 data.failed = 0;
342
343 f3line = __LINE__ + 1;
344 i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
345
346 if (i != 0)
347 {
348 fprintf (stderr, "test3: unexpected return value %d\n", i);
349 data.failed = 1;
350 }
351
352 if (!data.failed)
353 {
354 struct info all[20];
355 struct bdata bdata;
356
357 bdata.all = &all[0];
358 bdata.index = 0;
359 bdata.max = 20;
360 bdata.failed = 0;
361
362 i = backtrace_pcinfo (state, addrs[0], callback_one, error_callback_one,
363 &bdata);
364 if (i != 0)
365 {
366 fprintf (stderr,
367 ("test4: unexpected return value "
368 "from backtrace_pcinfo %d\n"),
369 i);
370 bdata.failed = 1;
371 }
372
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);
376
377 if (bdata.failed)
378 data.failed = 1;
379 }
380
381 printf ("%s: backtrace_simple inline\n", data.failed ? "FAIL" : "PASS");
382
383 if (data.failed)
384 ++failures;
385
386 return failures;
387}
388
389static int test5 (void) __attribute__ ((unused));
390
391int global = 1;
392
393static int
394test5 (void)
395{
396 struct symdata symdata;
397 int i;
398 uintptr_t addr = (uintptr_t) &global;
399
400 if (sizeof (global) > 1)
401 addr += 1;
402
403 symdata.name = NULL;
404 symdata.val = 0;
405 symdata.size = 0;
406 symdata.failed = 0;
407
408 i = backtrace_syminfo (state, addr, callback_three,
409 error_callback_three, &symdata);
410 if (i == 0)
411 {
412 fprintf (stderr,
413 "test5: unexpected return value from backtrace_syminfo %d\n",
414 i);
415 symdata.failed = 1;
416 }
417
418 if (!symdata.failed)
419 {
420 if (symdata.name == NULL)
421 {
422 fprintf (stderr, "test5: NULL syminfo name\n");
423 symdata.failed = 1;
424 }
425 else if (strcmp (symdata.name, "global") != 0)
426 {
427 fprintf (stderr,
428 "test5: unexpected syminfo name got %s expected %s\n",
429 symdata.name, "global");
430 symdata.failed = 1;
431 }
432 else if (symdata.val != (uintptr_t) &global)
433 {
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;
439 }
440 else if (symdata.size != sizeof (global))
441 {
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;
447 }
448 }
449
450 printf ("%s: backtrace_syminfo variable\n",
451 symdata.failed ? "FAIL" : "PASS");
452
453 if (symdata.failed)
454 ++failures;
455
456 return failures;
457}
458
459/* Run all the tests. */
460
461int
462main (int argc ATTRIBUTE_UNUSED, char **argv)
463{
464 state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
465 error_callback_create, NULL);
466
467#if BACKTRACE_SUPPORTED
468 test1 ();
469 test2 ();
470 test3 ();
471 test4 ();
472#if BACKTRACE_SUPPORTS_DATA
473 test5 ();
474#endif
475#endif
476
477 exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
478}
479

Warning: That file was not part of the compilation database. It may have many parsing errors.