]> git.ipfire.org Git - thirdparty/gcc.git/blame - libbacktrace/btest.c
* doc/extend.texi (Common Function Attributes): Clarify
[thirdparty/gcc.git] / libbacktrace / btest.c
CommitLineData
ecd3459e 1/* btest.c -- Test for libbacktrace library
fbd26352 2 Copyright (C) 2012-2019 Free Software Foundation, Inc.
ecd3459e 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
75c399ef 10 notice, this list of conditions and the following disclaimer.
ecd3459e 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
75c399ef 15 distribution.
16
ecd3459e 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>
ecd3459e 37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
902288bc 40#include <unistd.h>
ecd3459e 41
42#include "filenames.h"
43
44#include "backtrace.h"
45#include "backtrace-supported.h"
46
3be33b09 47#include "testlib.h"
ecd3459e 48
49/* Test the backtrace function with non-inlined functions. */
50
1cd00d9e 51static int test1 (void) __attribute__ ((noinline, noclone, unused));
52static int f2 (int) __attribute__ ((noinline, noclone));
53static int f3 (int, int) __attribute__ ((noinline, noclone));
ecd3459e 54
55static int
56test1 (void)
57{
58 /* Returning a value here and elsewhere avoids a tailcall which
59 would mess up the backtrace. */
60 return f2 (__LINE__) + 1;
61}
62
63static int
64f2 (int f1line)
65{
66 return f3 (f1line, __LINE__) + 2;
67}
68
69static int
70f3 (int f1line, int f2line)
71{
72 struct info all[20];
73 struct bdata data;
74 int f3line;
75 int i;
76
77 data.all = &all[0];
78 data.index = 0;
79 data.max = 20;
80 data.failed = 0;
81
82 f3line = __LINE__ + 1;
83 i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
84
85 if (i != 0)
86 {
87 fprintf (stderr, "test1: unexpected return value %d\n", i);
88 data.failed = 1;
89 }
90
881a0840 91 if (data.index < 3)
92 {
93 fprintf (stderr,
94 "test1: not enough frames; got %zu, expected at least 3\n",
95 data.index);
96 data.failed = 1;
97 }
98
3be33b09 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);
ecd3459e 102
103 printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");
104
105 if (data.failed)
106 ++failures;
107
108 return failures;
109}
110
111/* Test the backtrace function with inlined functions. */
112
d48b4b14 113static inline int test2 (void) __attribute__ ((always_inline, unused));
ecd3459e 114static inline int f12 (int) __attribute__ ((always_inline));
115static inline int f13 (int, int) __attribute__ ((always_inline));
116
117static inline int
118test2 (void)
119{
120 return f12 (__LINE__) + 1;
121}
122
123static inline int
124f12 (int f1line)
125{
126 return f13 (f1line, __LINE__) + 2;
127}
128
129static inline int
130f13 (int f1line, int f2line)
131{
132 struct info all[20];
133 struct bdata data;
134 int f3line;
135 int i;
136
137 data.all = &all[0];
138 data.index = 0;
139 data.max = 20;
140 data.failed = 0;
141
142 f3line = __LINE__ + 1;
143 i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
144
145 if (i != 0)
146 {
147 fprintf (stderr, "test2: unexpected return value %d\n", i);
148 data.failed = 1;
149 }
150
3be33b09 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);
ecd3459e 154
155 printf ("%s: backtrace_full inline\n", data.failed ? "FAIL" : "PASS");
156
157 if (data.failed)
158 ++failures;
159
160 return failures;
161}
162
163/* Test the backtrace_simple function with non-inlined functions. */
164
1cd00d9e 165static int test3 (void) __attribute__ ((noinline, noclone, unused));
166static int f22 (int) __attribute__ ((noinline, noclone));
167static int f23 (int, int) __attribute__ ((noinline, noclone));
ecd3459e 168
169static int
170test3 (void)
171{
172 return f22 (__LINE__) + 1;
173}
174
175static int
176f22 (int f1line)
177{
178 return f23 (f1line, __LINE__) + 2;
179}
180
181static int
182f23 (int f1line, int f2line)
183{
184 uintptr_t addrs[20];
185 struct sdata data;
186 int f3line;
187 int i;
188
189 data.addrs = &addrs[0];
190 data.index = 0;
191 data.max = 20;
192 data.failed = 0;
193
194 f3line = __LINE__ + 1;
195 i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
196
197 if (i != 0)
198 {
199 fprintf (stderr, "test3: unexpected return value %d\n", i);
200 data.failed = 1;
201 }
202
203 if (!data.failed)
204 {
205 struct info all[20];
206 struct bdata bdata;
207 int j;
208
209 bdata.all = &all[0];
210 bdata.index = 0;
211 bdata.max = 20;
212 bdata.failed = 0;
213
214 for (j = 0; j < 3; ++j)
215 {
216 i = backtrace_pcinfo (state, addrs[j], callback_one,
217 error_callback_one, &bdata);
218 if (i != 0)
219 {
220 fprintf (stderr,
221 ("test3: unexpected return value "
222 "from backtrace_pcinfo %d\n"),
223 i);
224 bdata.failed = 1;
225 }
226 if (!bdata.failed && bdata.index != (size_t) (j + 1))
227 {
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;
233 }
75c399ef 234 }
ecd3459e 235
3be33b09 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);
ecd3459e 239
240 if (bdata.failed)
241 data.failed = 1;
242
243 for (j = 0; j < 3; ++j)
244 {
245 struct symdata symdata;
246
247 symdata.name = NULL;
248 symdata.val = 0;
32ccb438 249 symdata.size = 0;
ecd3459e 250 symdata.failed = 0;
251
252 i = backtrace_syminfo (state, addrs[j], callback_three,
253 error_callback_three, &symdata);
254 if (i == 0)
255 {
256 fprintf (stderr,
257 ("test3: [%d]: unexpected return value "
258 "from backtrace_syminfo %d\n"),
259 j, i);
260 symdata.failed = 1;
261 }
262
263 if (!symdata.failed)
264 {
265 const char *expected;
266
267 switch (j)
268 {
269 case 0:
270 expected = "f23";
271 break;
272 case 1:
273 expected = "f22";
274 break;
275 case 2:
276 expected = "test3";
277 break;
fd88e799 278 default:
ecd3459e 279 assert (0);
280 }
281
282 if (symdata.name == NULL)
283 {
284 fprintf (stderr, "test3: [%d]: NULL syminfo name\n", j);
285 symdata.failed = 1;
286 }
287 /* Use strncmp, not strcmp, because GCC might create a
288 clone. */
289 else if (strncmp (symdata.name, expected, strlen (expected))
290 != 0)
291 {
292 fprintf (stderr,
293 ("test3: [%d]: unexpected syminfo name "
294 "got %s expected %s\n"),
295 j, symdata.name, expected);
296 symdata.failed = 1;
297 }
298 }
299
300 if (symdata.failed)
301 data.failed = 1;
302 }
303 }
304
305 printf ("%s: backtrace_simple noinline\n", data.failed ? "FAIL" : "PASS");
306
307 if (data.failed)
308 ++failures;
309
310 return failures;
311}
312
313/* Test the backtrace_simple function with inlined functions. */
314
d48b4b14 315static inline int test4 (void) __attribute__ ((always_inline, unused));
ecd3459e 316static inline int f32 (int) __attribute__ ((always_inline));
317static inline int f33 (int, int) __attribute__ ((always_inline));
318
319static inline int
320test4 (void)
321{
322 return f32 (__LINE__) + 1;
323}
324
325static inline int
326f32 (int f1line)
327{
328 return f33 (f1line, __LINE__) + 2;
329}
330
331static inline int
332f33 (int f1line, int f2line)
333{
334 uintptr_t addrs[20];
335 struct sdata data;
336 int f3line;
337 int i;
338
339 data.addrs = &addrs[0];
340 data.index = 0;
341 data.max = 20;
342 data.failed = 0;
343
344 f3line = __LINE__ + 1;
345 i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
346
347 if (i != 0)
348 {
349 fprintf (stderr, "test3: unexpected return value %d\n", i);
350 data.failed = 1;
351 }
352
353 if (!data.failed)
354 {
355 struct info all[20];
356 struct bdata bdata;
357
358 bdata.all = &all[0];
359 bdata.index = 0;
360 bdata.max = 20;
361 bdata.failed = 0;
362
363 i = backtrace_pcinfo (state, addrs[0], callback_one, error_callback_one,
364 &bdata);
365 if (i != 0)
366 {
367 fprintf (stderr,
368 ("test4: unexpected return value "
369 "from backtrace_pcinfo %d\n"),
370 i);
371 bdata.failed = 1;
372 }
373
3be33b09 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);
ecd3459e 377
378 if (bdata.failed)
379 data.failed = 1;
380 }
381
382 printf ("%s: backtrace_simple inline\n", data.failed ? "FAIL" : "PASS");
383
384 if (data.failed)
385 ++failures;
386
387 return failures;
388}
389
673716e3 390static int test5 (void) __attribute__ ((unused));
48ee217e 391
d4cc0c47 392int global = 1;
393
394static int
395test5 (void)
396{
397 struct symdata symdata;
398 int i;
32ccb438 399 uintptr_t addr = (uintptr_t) &global;
400
401 if (sizeof (global) > 1)
402 addr += 1;
d4cc0c47 403
404 symdata.name = NULL;
405 symdata.val = 0;
32ccb438 406 symdata.size = 0;
d4cc0c47 407 symdata.failed = 0;
408
32ccb438 409 i = backtrace_syminfo (state, addr, callback_three,
d4cc0c47 410 error_callback_three, &symdata);
411 if (i == 0)
412 {
413 fprintf (stderr,
414 "test5: unexpected return value from backtrace_syminfo %d\n",
415 i);
416 symdata.failed = 1;
417 }
418
419 if (!symdata.failed)
420 {
421 if (symdata.name == NULL)
422 {
423 fprintf (stderr, "test5: NULL syminfo name\n");
424 symdata.failed = 1;
425 }
a0f72275 426 else if (!(strncmp (symdata.name, "global", 6) == 0
427 && (symdata.name[6] == '\0'|| symdata.name[6] == '.')))
d4cc0c47 428 {
429 fprintf (stderr,
430 "test5: unexpected syminfo name got %s expected %s\n",
431 symdata.name, "global");
432 symdata.failed = 1;
433 }
32ccb438 434 else if (symdata.val != (uintptr_t) &global)
435 {
436 fprintf (stderr,
437 "test5: unexpected syminfo value got %lx expected %lx\n",
438 (unsigned long) symdata.val,
439 (unsigned long) (uintptr_t) &global);
440 symdata.failed = 1;
441 }
442 else if (symdata.size != sizeof (global))
443 {
444 fprintf (stderr,
445 "test5: unexpected syminfo size got %lx expected %lx\n",
446 (unsigned long) symdata.size,
447 (unsigned long) sizeof (global));
448 symdata.failed = 1;
449 }
d4cc0c47 450 }
451
452 printf ("%s: backtrace_syminfo variable\n",
453 symdata.failed ? "FAIL" : "PASS");
454
455 if (symdata.failed)
456 ++failures;
457
458 return failures;
459}
460
902288bc 461/* Check that are no files left open. */
462
463static void
464check_open_files (void)
465{
466 int i;
467
468 for (i = 3; i < 10; i++)
469 {
470 if (close (i) == 0)
471 {
472 fprintf (stderr,
473 "ERROR: descriptor %d still open after tests complete\n",
474 i);
475 ++failures;
476 }
477 }
478}
479
ecd3459e 480/* Run all the tests. */
481
482int
483main (int argc ATTRIBUTE_UNUSED, char **argv)
484{
485 state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
486 error_callback_create, NULL);
487
488#if BACKTRACE_SUPPORTED
489 test1 ();
490 test2 ();
491 test3 ();
492 test4 ();
48ee217e 493#if BACKTRACE_SUPPORTS_DATA
d4cc0c47 494 test5 ();
48ee217e 495#endif
ecd3459e 496#endif
497
902288bc 498 check_open_files ();
499
ecd3459e 500 exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
501}