114f5a3b0Smrg /* testlib.c -- test functions for libbacktrace library
2*b1e83836Smrg Copyright (C) 2012-2022 Free Software Foundation, Inc.
314f5a3b0Smrg Written by Ian Lance Taylor, Google.
414f5a3b0Smrg
514f5a3b0Smrg Redistribution and use in source and binary forms, with or without
614f5a3b0Smrg modification, are permitted provided that the following conditions are
714f5a3b0Smrg met:
814f5a3b0Smrg
914f5a3b0Smrg (1) Redistributions of source code must retain the above copyright
1014f5a3b0Smrg notice, this list of conditions and the following disclaimer.
1114f5a3b0Smrg
1214f5a3b0Smrg (2) Redistributions in binary form must reproduce the above copyright
1314f5a3b0Smrg notice, this list of conditions and the following disclaimer in
1414f5a3b0Smrg the documentation and/or other materials provided with the
1514f5a3b0Smrg distribution.
1614f5a3b0Smrg
1714f5a3b0Smrg (3) The name of the author may not be used to
1814f5a3b0Smrg endorse or promote products derived from this software without
1914f5a3b0Smrg specific prior written permission.
2014f5a3b0Smrg
2114f5a3b0Smrg THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
2214f5a3b0Smrg IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
2314f5a3b0Smrg WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2414f5a3b0Smrg DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
2514f5a3b0Smrg INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
2614f5a3b0Smrg (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
2714f5a3b0Smrg SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2814f5a3b0Smrg HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
2914f5a3b0Smrg STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
3014f5a3b0Smrg IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3114f5a3b0Smrg POSSIBILITY OF SUCH DAMAGE. */
3214f5a3b0Smrg
3314f5a3b0Smrg #include <assert.h>
3414f5a3b0Smrg #include <stdio.h>
3514f5a3b0Smrg #include <stdlib.h>
3614f5a3b0Smrg #include <string.h>
3714f5a3b0Smrg
3814f5a3b0Smrg #include "filenames.h"
3914f5a3b0Smrg
4014f5a3b0Smrg #include "backtrace.h"
4114f5a3b0Smrg
4214f5a3b0Smrg #include "testlib.h"
4314f5a3b0Smrg
4414f5a3b0Smrg /* The backtrace state. */
4514f5a3b0Smrg
4614f5a3b0Smrg void *state;
4714f5a3b0Smrg
4814f5a3b0Smrg /* The number of failures. */
4914f5a3b0Smrg
5014f5a3b0Smrg int failures;
5114f5a3b0Smrg
5214f5a3b0Smrg /* Return the base name in a path. */
5314f5a3b0Smrg
5414f5a3b0Smrg const char *
base(const char * p)5514f5a3b0Smrg base (const char *p)
5614f5a3b0Smrg {
5714f5a3b0Smrg const char *last;
5814f5a3b0Smrg const char *s;
5914f5a3b0Smrg
6014f5a3b0Smrg last = NULL;
6114f5a3b0Smrg for (s = p; *s != '\0'; ++s)
6214f5a3b0Smrg {
6314f5a3b0Smrg if (IS_DIR_SEPARATOR (*s))
6414f5a3b0Smrg last = s + 1;
6514f5a3b0Smrg }
6614f5a3b0Smrg return last != NULL ? last : p;
6714f5a3b0Smrg }
6814f5a3b0Smrg
6914f5a3b0Smrg /* Check an entry in a struct info array. */
7014f5a3b0Smrg
7114f5a3b0Smrg void
check(const char * name,int index,const struct info * all,int want_lineno,const char * want_function,const char * want_file,int * failed)7214f5a3b0Smrg check (const char *name, int index, const struct info *all, int want_lineno,
7314f5a3b0Smrg const char *want_function, const char *want_file, int *failed)
7414f5a3b0Smrg {
7514f5a3b0Smrg if (*failed)
7614f5a3b0Smrg return;
7714f5a3b0Smrg if (all[index].filename == NULL || all[index].function == NULL)
7814f5a3b0Smrg {
7914f5a3b0Smrg fprintf (stderr, "%s: [%d]: missing file name or function name\n",
8014f5a3b0Smrg name, index);
8114f5a3b0Smrg *failed = 1;
8214f5a3b0Smrg return;
8314f5a3b0Smrg }
8414f5a3b0Smrg if (strcmp (base (all[index].filename), want_file) != 0)
8514f5a3b0Smrg {
8614f5a3b0Smrg fprintf (stderr, "%s: [%d]: got %s expected %s\n", name, index,
8714f5a3b0Smrg all[index].filename, want_file);
8814f5a3b0Smrg *failed = 1;
8914f5a3b0Smrg }
9014f5a3b0Smrg if (all[index].lineno != want_lineno)
9114f5a3b0Smrg {
9214f5a3b0Smrg fprintf (stderr, "%s: [%d]: got %d expected %d\n", name, index,
9314f5a3b0Smrg all[index].lineno, want_lineno);
9414f5a3b0Smrg *failed = 1;
9514f5a3b0Smrg }
9614f5a3b0Smrg if (strcmp (all[index].function, want_function) != 0)
9714f5a3b0Smrg {
9814f5a3b0Smrg fprintf (stderr, "%s: [%d]: got %s expected %s\n", name, index,
9914f5a3b0Smrg all[index].function, want_function);
10014f5a3b0Smrg *failed = 1;
10114f5a3b0Smrg }
10214f5a3b0Smrg }
10314f5a3b0Smrg
10414f5a3b0Smrg /* The backtrace callback function. */
10514f5a3b0Smrg
10614f5a3b0Smrg int
callback_one(void * vdata,uintptr_t pc ATTRIBUTE_UNUSED,const char * filename,int lineno,const char * function)10714f5a3b0Smrg callback_one (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
10814f5a3b0Smrg const char *filename, int lineno, const char *function)
10914f5a3b0Smrg {
11014f5a3b0Smrg struct bdata *data = (struct bdata *) vdata;
11114f5a3b0Smrg struct info *p;
11214f5a3b0Smrg
11314f5a3b0Smrg if (data->index >= data->max)
11414f5a3b0Smrg {
11514f5a3b0Smrg fprintf (stderr, "callback_one: callback called too many times\n");
11614f5a3b0Smrg data->failed = 1;
11714f5a3b0Smrg return 1;
11814f5a3b0Smrg }
11914f5a3b0Smrg
12014f5a3b0Smrg p = &data->all[data->index];
12114f5a3b0Smrg if (filename == NULL)
12214f5a3b0Smrg p->filename = NULL;
12314f5a3b0Smrg else
12414f5a3b0Smrg {
12514f5a3b0Smrg p->filename = strdup (filename);
12614f5a3b0Smrg assert (p->filename != NULL);
12714f5a3b0Smrg }
12814f5a3b0Smrg p->lineno = lineno;
12914f5a3b0Smrg if (function == NULL)
13014f5a3b0Smrg p->function = NULL;
13114f5a3b0Smrg else
13214f5a3b0Smrg {
13314f5a3b0Smrg p->function = strdup (function);
13414f5a3b0Smrg assert (p->function != NULL);
13514f5a3b0Smrg }
13614f5a3b0Smrg ++data->index;
13714f5a3b0Smrg
13814f5a3b0Smrg return 0;
13914f5a3b0Smrg }
14014f5a3b0Smrg
14114f5a3b0Smrg /* An error callback passed to backtrace. */
14214f5a3b0Smrg
14314f5a3b0Smrg void
error_callback_one(void * vdata,const char * msg,int errnum)14414f5a3b0Smrg error_callback_one (void *vdata, const char *msg, int errnum)
14514f5a3b0Smrg {
14614f5a3b0Smrg struct bdata *data = (struct bdata *) vdata;
14714f5a3b0Smrg
14814f5a3b0Smrg fprintf (stderr, "%s", msg);
14914f5a3b0Smrg if (errnum > 0)
15014f5a3b0Smrg fprintf (stderr, ": %s", strerror (errnum));
15114f5a3b0Smrg fprintf (stderr, "\n");
15214f5a3b0Smrg data->failed = 1;
15314f5a3b0Smrg }
15414f5a3b0Smrg
15514f5a3b0Smrg /* The backtrace_simple callback function. */
15614f5a3b0Smrg
15714f5a3b0Smrg int
callback_two(void * vdata,uintptr_t pc)15814f5a3b0Smrg callback_two (void *vdata, uintptr_t pc)
15914f5a3b0Smrg {
16014f5a3b0Smrg struct sdata *data = (struct sdata *) vdata;
16114f5a3b0Smrg
16214f5a3b0Smrg if (data->index >= data->max)
16314f5a3b0Smrg {
16414f5a3b0Smrg fprintf (stderr, "callback_two: callback called too many times\n");
16514f5a3b0Smrg data->failed = 1;
16614f5a3b0Smrg return 1;
16714f5a3b0Smrg }
16814f5a3b0Smrg
16914f5a3b0Smrg data->addrs[data->index] = pc;
17014f5a3b0Smrg ++data->index;
17114f5a3b0Smrg
17214f5a3b0Smrg return 0;
17314f5a3b0Smrg }
17414f5a3b0Smrg
17514f5a3b0Smrg /* An error callback passed to backtrace_simple. */
17614f5a3b0Smrg
17714f5a3b0Smrg void
error_callback_two(void * vdata,const char * msg,int errnum)17814f5a3b0Smrg error_callback_two (void *vdata, const char *msg, int errnum)
17914f5a3b0Smrg {
18014f5a3b0Smrg struct sdata *data = (struct sdata *) vdata;
18114f5a3b0Smrg
18214f5a3b0Smrg fprintf (stderr, "%s", msg);
18314f5a3b0Smrg if (errnum > 0)
18414f5a3b0Smrg fprintf (stderr, ": %s", strerror (errnum));
18514f5a3b0Smrg fprintf (stderr, "\n");
18614f5a3b0Smrg data->failed = 1;
18714f5a3b0Smrg }
18814f5a3b0Smrg
18914f5a3b0Smrg /* The backtrace_syminfo callback function. */
19014f5a3b0Smrg
19114f5a3b0Smrg void
callback_three(void * vdata,uintptr_t pc ATTRIBUTE_UNUSED,const char * symname,uintptr_t symval,uintptr_t symsize)19214f5a3b0Smrg callback_three (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
19314f5a3b0Smrg const char *symname, uintptr_t symval,
19414f5a3b0Smrg uintptr_t symsize)
19514f5a3b0Smrg {
19614f5a3b0Smrg struct symdata *data = (struct symdata *) vdata;
19714f5a3b0Smrg
19814f5a3b0Smrg if (symname == NULL)
19914f5a3b0Smrg data->name = NULL;
20014f5a3b0Smrg else
20114f5a3b0Smrg {
20214f5a3b0Smrg data->name = strdup (symname);
20314f5a3b0Smrg assert (data->name != NULL);
20414f5a3b0Smrg }
20514f5a3b0Smrg data->val = symval;
20614f5a3b0Smrg data->size = symsize;
20714f5a3b0Smrg }
20814f5a3b0Smrg
20914f5a3b0Smrg /* The backtrace_syminfo error callback function. */
21014f5a3b0Smrg
21114f5a3b0Smrg void
error_callback_three(void * vdata,const char * msg,int errnum)21214f5a3b0Smrg error_callback_three (void *vdata, const char *msg, int errnum)
21314f5a3b0Smrg {
21414f5a3b0Smrg struct symdata *data = (struct symdata *) vdata;
21514f5a3b0Smrg
21614f5a3b0Smrg fprintf (stderr, "%s", msg);
21714f5a3b0Smrg if (errnum > 0)
21814f5a3b0Smrg fprintf (stderr, ": %s", strerror (errnum));
21914f5a3b0Smrg fprintf (stderr, "\n");
22014f5a3b0Smrg data->failed = 1;
22114f5a3b0Smrg }
22214f5a3b0Smrg
22314f5a3b0Smrg /* The backtrace_create_state error callback function. */
22414f5a3b0Smrg
22514f5a3b0Smrg void
error_callback_create(void * data ATTRIBUTE_UNUSED,const char * msg,int errnum)22614f5a3b0Smrg error_callback_create (void *data ATTRIBUTE_UNUSED, const char *msg,
22714f5a3b0Smrg int errnum)
22814f5a3b0Smrg {
22914f5a3b0Smrg fprintf (stderr, "%s", msg);
23014f5a3b0Smrg if (errnum > 0)
23114f5a3b0Smrg fprintf (stderr, ": %s", strerror (errnum));
23214f5a3b0Smrg fprintf (stderr, "\n");
23314f5a3b0Smrg exit (EXIT_FAILURE);
23414f5a3b0Smrg }
235