1627f7eb2Smrg /* allocfail.c -- Test for libbacktrace library
2*4c3eb207Smrg Copyright (C) 2018-2020 Free Software Foundation, Inc.
3627f7eb2Smrg
4627f7eb2Smrg Redistribution and use in source and binary forms, with or without
5627f7eb2Smrg modification, are permitted provided that the following conditions are
6627f7eb2Smrg met:
7627f7eb2Smrg
8627f7eb2Smrg (1) Redistributions of source code must retain the above copyright
9627f7eb2Smrg notice, this list of conditions and the following disclaimer.
10627f7eb2Smrg
11627f7eb2Smrg (2) Redistributions in binary form must reproduce the above copyright
12627f7eb2Smrg notice, this list of conditions and the following disclaimer in
13627f7eb2Smrg the documentation and/or other materials provided with the
14627f7eb2Smrg distribution.
15627f7eb2Smrg
16627f7eb2Smrg (3) The name of the author may not be used to
17627f7eb2Smrg endorse or promote products derived from this software without
18627f7eb2Smrg specific prior written permission.
19627f7eb2Smrg
20627f7eb2Smrg THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21627f7eb2Smrg IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22627f7eb2Smrg WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23627f7eb2Smrg DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
24627f7eb2Smrg INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25627f7eb2Smrg (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26627f7eb2Smrg SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27627f7eb2Smrg HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28627f7eb2Smrg STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
29627f7eb2Smrg IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30627f7eb2Smrg POSSIBILITY OF SUCH DAMAGE. */
31627f7eb2Smrg
32627f7eb2Smrg #include <assert.h>
33627f7eb2Smrg #include <stdio.h>
34627f7eb2Smrg #include <stdlib.h>
35627f7eb2Smrg #include <string.h>
36627f7eb2Smrg #include <unistd.h>
37627f7eb2Smrg
38627f7eb2Smrg #include "filenames.h"
39627f7eb2Smrg
40627f7eb2Smrg #include "backtrace.h"
41627f7eb2Smrg #include "backtrace-supported.h"
42627f7eb2Smrg
43627f7eb2Smrg #include "testlib.h"
44627f7eb2Smrg
45627f7eb2Smrg extern uint64_t get_nr_allocs (void);
46627f7eb2Smrg extern void set_fail_at_alloc (uint64_t);
47627f7eb2Smrg extern int at_fail_alloc_p (void);
48627f7eb2Smrg
49627f7eb2Smrg static int test1 (void) __attribute__ ((noinline, unused));
50627f7eb2Smrg static int f2 (int) __attribute__ ((noinline));
51627f7eb2Smrg static int f3 (int, int) __attribute__ ((noinline));
52627f7eb2Smrg
53627f7eb2Smrg static unsigned callback_errors = 0;
54627f7eb2Smrg
55627f7eb2Smrg static void
error_callback_full(void * vdata ATTRIBUTE_UNUSED,const char * msg ATTRIBUTE_UNUSED,int errnum ATTRIBUTE_UNUSED)56627f7eb2Smrg error_callback_full (void *vdata ATTRIBUTE_UNUSED,
57627f7eb2Smrg const char *msg ATTRIBUTE_UNUSED,
58627f7eb2Smrg int errnum ATTRIBUTE_UNUSED)
59627f7eb2Smrg {
60627f7eb2Smrg if (at_fail_alloc_p ())
61627f7eb2Smrg {
62627f7eb2Smrg set_fail_at_alloc (0);
63627f7eb2Smrg return;
64627f7eb2Smrg }
65627f7eb2Smrg
66627f7eb2Smrg callback_errors++;
67627f7eb2Smrg }
68627f7eb2Smrg
69627f7eb2Smrg static int
callback_full(void * vdata ATTRIBUTE_UNUSED,uintptr_t pc ATTRIBUTE_UNUSED,const char * filename ATTRIBUTE_UNUSED,int lineno ATTRIBUTE_UNUSED,const char * function ATTRIBUTE_UNUSED)70627f7eb2Smrg callback_full (void *vdata ATTRIBUTE_UNUSED, uintptr_t pc ATTRIBUTE_UNUSED,
71627f7eb2Smrg const char *filename ATTRIBUTE_UNUSED,
72627f7eb2Smrg int lineno ATTRIBUTE_UNUSED,
73627f7eb2Smrg const char *function ATTRIBUTE_UNUSED)
74627f7eb2Smrg {
75627f7eb2Smrg
76627f7eb2Smrg return 0;
77627f7eb2Smrg }
78627f7eb2Smrg
79627f7eb2Smrg static int
test1(void)80627f7eb2Smrg test1 (void)
81627f7eb2Smrg {
82627f7eb2Smrg return f2 (__LINE__) + 1;
83627f7eb2Smrg }
84627f7eb2Smrg
85627f7eb2Smrg static int
f2(int f1line)86627f7eb2Smrg f2 (int f1line)
87627f7eb2Smrg {
88627f7eb2Smrg return f3 (f1line, __LINE__) + 2;
89627f7eb2Smrg }
90627f7eb2Smrg
91627f7eb2Smrg static int
f3(int f1line ATTRIBUTE_UNUSED,int f2line ATTRIBUTE_UNUSED)92627f7eb2Smrg f3 (int f1line ATTRIBUTE_UNUSED, int f2line ATTRIBUTE_UNUSED)
93627f7eb2Smrg {
94627f7eb2Smrg int i;
95627f7eb2Smrg
96627f7eb2Smrg i = backtrace_full (state, 0, callback_full, error_callback_full, NULL);
97627f7eb2Smrg
98627f7eb2Smrg if (i != 0)
99627f7eb2Smrg {
100627f7eb2Smrg fprintf (stderr, "test1: unexpected return value %d\n", i);
101627f7eb2Smrg ++failures;
102627f7eb2Smrg }
103627f7eb2Smrg
104627f7eb2Smrg if (callback_errors)
105627f7eb2Smrg ++failures;
106627f7eb2Smrg
107627f7eb2Smrg return failures;
108627f7eb2Smrg }
109627f7eb2Smrg
110627f7eb2Smrg /* Run all the tests. */
111627f7eb2Smrg
112627f7eb2Smrg int
main(int argc,char ** argv)113627f7eb2Smrg main (int argc, char **argv)
114627f7eb2Smrg {
115627f7eb2Smrg uint64_t fail_at = 0;
116627f7eb2Smrg
117627f7eb2Smrg if (argc == 2)
118627f7eb2Smrg {
119627f7eb2Smrg fail_at = atoi (argv[1]);
120627f7eb2Smrg set_fail_at_alloc (fail_at);
121627f7eb2Smrg }
122627f7eb2Smrg
123627f7eb2Smrg state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
124627f7eb2Smrg error_callback_full, NULL);
125627f7eb2Smrg if (state == NULL)
126627f7eb2Smrg exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
127627f7eb2Smrg
128627f7eb2Smrg #if BACKTRACE_SUPPORTED
129627f7eb2Smrg test1 ();
130627f7eb2Smrg #endif
131627f7eb2Smrg
132627f7eb2Smrg if (argc == 1)
133627f7eb2Smrg fprintf (stderr, "%llu\n", (long long unsigned) get_nr_allocs ());
134627f7eb2Smrg
135627f7eb2Smrg exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
136627f7eb2Smrg }
137