* elf.c (backtrace_initialize): Always set *fileline_fn.
* ttest.c: New file.
* btest.c: Move support functions into testlib.c. Change calls to
check to pass file name.
* testlib.c: New file, copied from (part of) btest.c.
* testlib.h: New file, declarations for testlib.c.
* edtest.c: Use testlib.h and testlib.c.
* configure.ac: Test for -pthread, set HAVE_PTHREAD conditional.
* Makefile.am (btest_SOURCES): Add testlib.c.
(edtest_SOURCES): Likewise.
(CHECK_PROGRAMS): Add ttest if HAVE_PTHREAD.
(ttest_SOURCES, ttest_CFLAGS, ttest_LDADD): Define.
* configure, Makefile.in: Rebuild.
From-SVN: r249111
+2017-06-11 Ian Lance Taylor <iant@golang.org>
+
+ * elf.c (backtrace_initialize): Always set *fileline_fn.
+ * ttest.c: New file.
+ * btest.c: Move support functions into testlib.c. Change calls to
+ check to pass file name.
+ * testlib.c: New file, copied from (part of) btest.c.
+ * testlib.h: New file, declarations for testlib.c.
+ * edtest.c: Use testlib.h and testlib.c.
+ * configure.ac: Test for -pthread, set HAVE_PTHREAD conditional.
+ * Makefile.am (btest_SOURCES): Add testlib.c.
+ (edtest_SOURCES): Likewise.
+ (CHECK_PROGRAMS): Add ttest if HAVE_PTHREAD.
+ (ttest_SOURCES, ttest_CFLAGS, ttest_LDADD): Define.
+ * configure, Makefile.in: Rebuild.
+
2017-05-19 Than McIntosh <thanm@google.com>
* dwarf.c (free_line_header): Don't free dirs if dirs_count == 0.
if NATIVE
-btest_SOURCES = btest.c
+btest_SOURCES = btest.c testlib.c
btest_CFLAGS = $(AM_CFLAGS) -g -O
btest_LDADD = libbacktrace.la
check_PROGRAMS += stest
-edtest_SOURCES = edtest.c edtest2_build.c
+edtest_SOURCES = edtest.c edtest2_build.c testlib.c
edtest_LDADD = libbacktrace.la
check_PROGRAMS += edtest
$(SHELL) $(srcdir)/../move-if-change tmp-edtest2_build.c edtest2_build.c
echo timestamp > $@
+if HAVE_PTHREAD
+
+check_PROGRAMS += ttest
+
+ttest_SOURCES = ttest.c testlib.c
+ttest_CFLAGS = -pthread
+ttest_LDADD = libbacktrace.la
+
+endif HAVE_PTHREAD
+
endif NATIVE
# We can't use automake's automatic dependency tracking, because it
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
-check_PROGRAMS = $(am__EXEEXT_1)
+check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2)
@NATIVE_TRUE@am__append_1 = btest stest edtest
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__append_2 = ttest
subdir = .
DIST_COMMON = README ChangeLog $(srcdir)/Makefile.in \
$(srcdir)/Makefile.am $(top_srcdir)/configure \
libbacktrace_la_OBJECTS = $(am_libbacktrace_la_OBJECTS)
@NATIVE_TRUE@am__EXEEXT_1 = btest$(EXEEXT) stest$(EXEEXT) \
@NATIVE_TRUE@ edtest$(EXEEXT)
-@NATIVE_TRUE@am_btest_OBJECTS = btest-btest.$(OBJEXT)
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am__EXEEXT_2 = ttest$(EXEEXT)
+@NATIVE_TRUE@am_btest_OBJECTS = btest-btest.$(OBJEXT) \
+@NATIVE_TRUE@ btest-testlib.$(OBJEXT)
btest_OBJECTS = $(am_btest_OBJECTS)
@NATIVE_TRUE@btest_DEPENDENCIES = libbacktrace.la
btest_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(btest_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
@NATIVE_TRUE@am_edtest_OBJECTS = edtest.$(OBJEXT) \
-@NATIVE_TRUE@ edtest2_build.$(OBJEXT)
+@NATIVE_TRUE@ edtest2_build.$(OBJEXT) testlib.$(OBJEXT)
edtest_OBJECTS = $(am_edtest_OBJECTS)
@NATIVE_TRUE@edtest_DEPENDENCIES = libbacktrace.la
@NATIVE_TRUE@am_stest_OBJECTS = stest.$(OBJEXT)
stest_OBJECTS = $(am_stest_OBJECTS)
@NATIVE_TRUE@stest_DEPENDENCIES = libbacktrace.la
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@am_ttest_OBJECTS = \
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ ttest-ttest.$(OBJEXT) \
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ ttest-testlib.$(OBJEXT)
+ttest_OBJECTS = $(am_ttest_OBJECTS)
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_DEPENDENCIES = libbacktrace.la
+ttest_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
+ --mode=link $(CCLD) $(ttest_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
+ $(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp =
am__depfiles_maybe =
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libbacktrace_la_SOURCES) $(EXTRA_libbacktrace_la_SOURCES) \
- $(btest_SOURCES) $(edtest_SOURCES) $(stest_SOURCES)
+ $(btest_SOURCES) $(edtest_SOURCES) $(stest_SOURCES) \
+ $(ttest_SOURCES)
MULTISRCTOP =
MULTIBUILDTOP =
MULTIDIRS =
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PIC_FLAG = @PIC_FLAG@
+PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
TESTS = $(check_PROGRAMS)
-@NATIVE_TRUE@btest_SOURCES = btest.c
+@NATIVE_TRUE@btest_SOURCES = btest.c testlib.c
@NATIVE_TRUE@btest_CFLAGS = $(AM_CFLAGS) -g -O
@NATIVE_TRUE@btest_LDADD = libbacktrace.la
@NATIVE_TRUE@stest_SOURCES = stest.c
@NATIVE_TRUE@stest_LDADD = libbacktrace.la
-@NATIVE_TRUE@edtest_SOURCES = edtest.c edtest2_build.c
+@NATIVE_TRUE@edtest_SOURCES = edtest.c edtest2_build.c testlib.c
@NATIVE_TRUE@edtest_LDADD = libbacktrace.la
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_SOURCES = ttest.c testlib.c
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_CFLAGS = -pthread
+@HAVE_PTHREAD_TRUE@@NATIVE_TRUE@ttest_LDADD = libbacktrace.la
# We can't use automake's automatic dependency tracking, because it
# breaks when using bootstrap-lean. Automatic dependency tracking
stest$(EXEEXT): $(stest_OBJECTS) $(stest_DEPENDENCIES) $(EXTRA_stest_DEPENDENCIES)
@rm -f stest$(EXEEXT)
$(LINK) $(stest_OBJECTS) $(stest_LDADD) $(LIBS)
+ttest$(EXEEXT): $(ttest_OBJECTS) $(ttest_DEPENDENCIES) $(EXTRA_ttest_DEPENDENCIES)
+ @rm -f ttest$(EXEEXT)
+ $(ttest_LINK) $(ttest_OBJECTS) $(ttest_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
btest-btest.obj: btest.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`
+btest-testlib.o: testlib.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c
+
+btest-testlib.obj: testlib.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
+
+ttest-ttest.o: ttest.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_CFLAGS) $(CFLAGS) -c -o ttest-ttest.o `test -f 'ttest.c' || echo '$(srcdir)/'`ttest.c
+
+ttest-ttest.obj: ttest.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_CFLAGS) $(CFLAGS) -c -o ttest-ttest.obj `if test -f 'ttest.c'; then $(CYGPATH_W) 'ttest.c'; else $(CYGPATH_W) '$(srcdir)/ttest.c'; fi`
+
+ttest-testlib.o: testlib.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_CFLAGS) $(CFLAGS) -c -o ttest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c
+
+ttest-testlib.obj: testlib.c
+ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ttest_CFLAGS) $(CFLAGS) -c -o ttest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
+
mostlyclean-libtool:
-rm -f *.lo
#include "backtrace.h"
#include "backtrace-supported.h"
-/* Portable attribute syntax. Actually some of these tests probably
- won't work if the attributes are not recognized. */
-
-#ifndef GCC_VERSION
-# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
-#endif
-
-#if (GCC_VERSION < 2007)
-# define __attribute__(x)
-#endif
-
-#ifndef ATTRIBUTE_UNUSED
-# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
-#endif
-
-/* Used to collect backtrace info. */
-
-struct info
-{
- char *filename;
- int lineno;
- char *function;
-};
-
-/* Passed to backtrace callback function. */
-
-struct bdata
-{
- struct info *all;
- size_t index;
- size_t max;
- int failed;
-};
-
-/* Passed to backtrace_simple callback function. */
-
-struct sdata
-{
- uintptr_t *addrs;
- size_t index;
- size_t max;
- int failed;
-};
-
-/* Passed to backtrace_syminfo callback function. */
-
-struct symdata
-{
- const char *name;
- uintptr_t val, size;
- int failed;
-};
-
-/* The backtrace state. */
-
-static void *state;
-
-/* The number of failures. */
-
-static int failures;
-
-/* Return the base name in a path. */
-
-static const char *
-base (const char *p)
-{
- const char *last;
- const char *s;
-
- last = NULL;
- for (s = p; *s != '\0'; ++s)
- {
- if (IS_DIR_SEPARATOR (*s))
- last = s + 1;
- }
- return last != NULL ? last : p;
-}
-
-/* Check an entry in a struct info array. */
-
-static void
-check (const char *name, int index, const struct info *all, int want_lineno,
- const char *want_function, int *failed)
-{
- if (*failed)
- return;
- if (all[index].filename == NULL || all[index].function == NULL)
- {
- fprintf (stderr, "%s: [%d]: missing file name or function name\n",
- name, index);
- *failed = 1;
- return;
- }
- if (strcmp (base (all[index].filename), "btest.c") != 0)
- {
- fprintf (stderr, "%s: [%d]: got %s expected test.c\n", name, index,
- all[index].filename);
- *failed = 1;
- }
- if (all[index].lineno != want_lineno)
- {
- fprintf (stderr, "%s: [%d]: got %d expected %d\n", name, index,
- all[index].lineno, want_lineno);
- *failed = 1;
- }
- if (strcmp (all[index].function, want_function) != 0)
- {
- fprintf (stderr, "%s: [%d]: got %s expected %s\n", name, index,
- all[index].function, want_function);
- *failed = 1;
- }
-}
-
-/* The backtrace callback function. */
-
-static int
-callback_one (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
- const char *filename, int lineno, const char *function)
-{
- struct bdata *data = (struct bdata *) vdata;
- struct info *p;
-
- if (data->index >= data->max)
- {
- fprintf (stderr, "callback_one: callback called too many times\n");
- data->failed = 1;
- return 1;
- }
-
- p = &data->all[data->index];
- if (filename == NULL)
- p->filename = NULL;
- else
- {
- p->filename = strdup (filename);
- assert (p->filename != NULL);
- }
- p->lineno = lineno;
- if (function == NULL)
- p->function = NULL;
- else
- {
- p->function = strdup (function);
- assert (p->function != NULL);
- }
- ++data->index;
-
- return 0;
-}
-
-/* An error callback passed to backtrace. */
-
-static void
-error_callback_one (void *vdata, const char *msg, int errnum)
-{
- struct bdata *data = (struct bdata *) vdata;
-
- fprintf (stderr, "%s", msg);
- if (errnum > 0)
- fprintf (stderr, ": %s", strerror (errnum));
- fprintf (stderr, "\n");
- data->failed = 1;
-}
-
-/* The backtrace_simple callback function. */
-
-static int
-callback_two (void *vdata, uintptr_t pc)
-{
- struct sdata *data = (struct sdata *) vdata;
-
- if (data->index >= data->max)
- {
- fprintf (stderr, "callback_two: callback called too many times\n");
- data->failed = 1;
- return 1;
- }
-
- data->addrs[data->index] = pc;
- ++data->index;
-
- return 0;
-}
-
-/* An error callback passed to backtrace_simple. */
-
-static void
-error_callback_two (void *vdata, const char *msg, int errnum)
-{
- struct sdata *data = (struct sdata *) vdata;
-
- fprintf (stderr, "%s", msg);
- if (errnum > 0)
- fprintf (stderr, ": %s", strerror (errnum));
- fprintf (stderr, "\n");
- data->failed = 1;
-}
-
-/* The backtrace_syminfo callback function. */
-
-static void
-callback_three (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
- const char *symname, uintptr_t symval,
- uintptr_t symsize)
-{
- struct symdata *data = (struct symdata *) vdata;
-
- if (symname == NULL)
- data->name = NULL;
- else
- {
- data->name = strdup (symname);
- assert (data->name != NULL);
- }
- data->val = symval;
- data->size = symsize;
-}
-
-/* The backtrace_syminfo error callback function. */
-
-static void
-error_callback_three (void *vdata, const char *msg, int errnum)
-{
- struct symdata *data = (struct symdata *) vdata;
-
- fprintf (stderr, "%s", msg);
- if (errnum > 0)
- fprintf (stderr, ": %s", strerror (errnum));
- fprintf (stderr, "\n");
- data->failed = 1;
-}
+#include "testlib.h"
/* Test the backtrace function with non-inlined functions. */
data.failed = 1;
}
- check ("test1", 0, all, f3line, "f3", &data.failed);
- check ("test1", 1, all, f2line, "f2", &data.failed);
- check ("test1", 2, all, f1line, "test1", &data.failed);
+ check ("test1", 0, all, f3line, "f3", "btest.c", &data.failed);
+ check ("test1", 1, all, f2line, "f2", "btest.c", &data.failed);
+ check ("test1", 2, all, f1line, "test1", "btest.c", &data.failed);
printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");
data.failed = 1;
}
- check ("test2", 0, all, f3line, "f13", &data.failed);
- check ("test2", 1, all, f2line, "f12", &data.failed);
- check ("test2", 2, all, f1line, "test2", &data.failed);
+ check ("test2", 0, all, f3line, "f13", "btest.c", &data.failed);
+ check ("test2", 1, all, f2line, "f12", "btest.c", &data.failed);
+ check ("test2", 2, all, f1line, "test2", "btest.c", &data.failed);
printf ("%s: backtrace_full inline\n", data.failed ? "FAIL" : "PASS");
}
}
- check ("test3", 0, all, f3line, "f23", &bdata.failed);
- check ("test3", 1, all, f2line, "f22", &bdata.failed);
- check ("test3", 2, all, f1line, "test3", &bdata.failed);
+ check ("test3", 0, all, f3line, "f23", "btest.c", &bdata.failed);
+ check ("test3", 1, all, f2line, "f22", "btest.c", &bdata.failed);
+ check ("test3", 2, all, f1line, "test3", "btest.c", &bdata.failed);
if (bdata.failed)
data.failed = 1;
bdata.failed = 1;
}
- check ("test4", 0, all, f3line, "f33", &bdata.failed);
- check ("test4", 1, all, f2line, "f32", &bdata.failed);
- check ("test4", 2, all, f1line, "test4", &bdata.failed);
+ check ("test4", 0, all, f3line, "f33", "btest.c", &bdata.failed);
+ check ("test4", 1, all, f2line, "f32", "btest.c", &bdata.failed);
+ check ("test4", 2, all, f1line, "test4", "btest.c", &bdata.failed);
if (bdata.failed)
data.failed = 1;
return failures;
}
-static void
-error_callback_create (void *data ATTRIBUTE_UNUSED, const char *msg,
- int errnum)
-{
- fprintf (stderr, "%s", msg);
- if (errnum > 0)
- fprintf (stderr, ": %s", strerror (errnum));
- fprintf (stderr, "\n");
- exit (EXIT_FAILURE);
-}
-
/* Run all the tests. */
int
LIBOBJS
NATIVE_FALSE
NATIVE_TRUE
+HAVE_PTHREAD_FALSE
+HAVE_PTHREAD_TRUE
+PTHREAD_CFLAGS
BACKTRACE_USES_MALLOC
ALLOC_FILE
VIEW_FILE
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11134 "configure"
+#line 11137 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11240 "configure"
+#line 11243 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -pthread is supported" >&5
+$as_echo_n "checking whether -pthread is supported... " >&6; }
+if test "${libgo_cv_lib_pthread+set}" = set; then :
+ $as_echo_n "(cached) " >&6
+else
+ CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -pthread"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+int i;
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ libgo_cv_lib_pthread=yes
+else
+ libgo_cv_lib_pthread=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+CFLAGS=$CFLAGS_hold
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libgo_cv_lib_pthread" >&5
+$as_echo "$libgo_cv_lib_pthread" >&6; }
+PTHREAD_CFLAGS=
+if test "$libgo_cv_lib_pthread" = yes; then
+ PTHREAD_CFLAGS=-pthread
+fi
+
+
+ if test "$libgo_cv_lib_pthread" = yes; then
+ HAVE_PTHREAD_TRUE=
+ HAVE_PTHREAD_FALSE='#'
+else
+ HAVE_PTHREAD_TRUE='#'
+ HAVE_PTHREAD_FALSE=
+fi
+
+
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether tests can run" >&5
$as_echo_n "checking whether tests can run... " >&6; }
if test "${libbacktrace_cv_sys_native+set}" = set; then :
as_fn_error "conditional \"MAINTAINER_MODE\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
+if test -z "${HAVE_PTHREAD_TRUE}" && test -z "${HAVE_PTHREAD_FALSE}"; then
+ as_fn_error "conditional \"HAVE_PTHREAD\" was never defined.
+Usually this means the macro was only invoked conditionally." "$LINENO" 5
+fi
if test -z "${NATIVE_TRUE}" && test -z "${NATIVE_FALSE}"; then
as_fn_error "conditional \"NATIVE\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
AC_DEFINE(HAVE_GETEXECNAME, 1, [Define if getexecname is available.])
fi
+dnl Test whether the compiler supports the -pthread option.
+AC_CACHE_CHECK([whether -pthread is supported],
+[libgo_cv_lib_pthread],
+[CFLAGS_hold=$CFLAGS
+CFLAGS="$CFLAGS -pthread"
+AC_COMPILE_IFELSE([[int i;]],
+[libgo_cv_lib_pthread=yes],
+[libgo_cv_lib_pthread=no])
+CFLAGS=$CFLAGS_hold])
+PTHREAD_CFLAGS=
+if test "$libgo_cv_lib_pthread" = yes; then
+ PTHREAD_CFLAGS=-pthread
+fi
+AC_SUBST(PTHREAD_CFLAGS)
+
+AM_CONDITIONAL(HAVE_PTHREAD, test "$libgo_cv_lib_pthread" = yes)
+
AC_CACHE_CHECK([whether tests can run],
[libbacktrace_cv_sys_native],
[AC_RUN_IFELSE([AC_LANG_PROGRAM([], [return 0;])],
#include "backtrace-supported.h"
#include "internal.h"
-#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__)
-# define IS_DIR_SEPARATOR(c) ((c) == '/' || (c) == '\\')
-#else
-# define IS_DIR_SEPARATOR(c) ((c) == '/')
-#endif
-
-/* The backtrace state. */
-
-static void *state;
-
-/* The number of failures. */
-
-int failures = 0;
+#include "testlib.h"
static int test1 (void) __attribute__ ((noinline, unused));
static int test1 (void) __attribute__ ((noinline, unused));
return f2 (__LINE__) + 1;
}
-/* Used to collect backtrace info. */
-
-struct info
-{
- char *filename;
- int lineno;
- char *function;
-};
-
-/* Return the base name in a path. */
-
-static const char *
-base (const char *p)
-{
- const char *last;
- const char *s;
-
- last = NULL;
- for (s = p; *s != '\0'; ++s)
- {
- if (IS_DIR_SEPARATOR (*s))
- last = s + 1;
- }
- return last != NULL ? last : p;
-}
-
-/* Check an entry in a struct info array. */
-
-static void
-check (const char *name, int index, const struct info *all, int want_lineno,
- const char *want_function, const char *want_file, int *failed)
-{
- if (*failed)
- return;
- if (all[index].filename == NULL || all[index].function == NULL)
- {
- fprintf (stderr, "%s: [%d]: missing file name or function name\n",
- name, index);
- *failed = 1;
- return;
- }
- if (strcmp (base (all[index].filename), want_file) != 0)
- {
- fprintf (stderr, "%s: [%d]: got %s expected %s\n", name, index,
- all[index].filename, want_file);
- *failed = 1;
- }
- if (all[index].lineno != want_lineno)
- {
- fprintf (stderr, "%s: [%d]: got %d expected %d\n", name, index,
- all[index].lineno, want_lineno);
- *failed = 1;
- }
- if (strcmp (all[index].function, want_function) != 0)
- {
- fprintf (stderr, "%s: [%d]: got %s expected %s\n", name, index,
- all[index].function, want_function);
- *failed = 1;
- }
-}
-
-/* Passed to backtrace callback function. */
-
-struct bdata
-{
- struct info *all;
- size_t index;
- size_t max;
- int failed;
-};
-
-/* An error callback passed to backtrace. */
-
-static void
-error_callback_one (void *vdata, const char *msg, int errnum)
-{
- struct bdata *data = (struct bdata *) vdata;
-
- fprintf (stderr, "%s", msg);
- if (errnum > 0)
- fprintf (stderr, ": %s", strerror (errnum));
- fprintf (stderr, "\n");
- data->failed = 1;
-}
-
-/* The backtrace callback function. */
-
-static int
-callback_one (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
- const char *filename, int lineno, const char *function)
-{
- struct bdata *data = (struct bdata *) vdata;
- struct info *p;
-
- if (data->index >= data->max)
- {
- fprintf (stderr, "callback_one: callback called too many times\n");
- data->failed = 1;
- return 1;
- }
-
- p = &data->all[data->index];
- if (filename == NULL)
- p->filename = NULL;
- else
- {
- p->filename = strdup (filename);
- assert (p->filename != NULL);
- }
- p->lineno = lineno;
- if (function == NULL)
- p->function = NULL;
- else
- {
- p->function = strdup (function);
- assert (p->function != NULL);
- }
- ++data->index;
-
- return 0;
-}
-
int
f3 (int f1line, int f2line)
{
return failures;
}
-static void
-error_callback_create (void *data ATTRIBUTE_UNUSED, const char *msg,
- int errnum)
-{
- fprintf (stderr, "%s", msg);
- if (errnum > 0)
- fprintf (stderr, ": %s", strerror (errnum));
- fprintf (stderr, "\n");
- exit (EXIT_FAILURE);
-}
-
int
main (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
{
}
if (!state->threaded)
- {
- if (state->fileline_fn == NULL || state->fileline_fn == elf_nodebug)
- *fileline_fn = elf_fileline_fn;
- }
+ *fileline_fn = state->fileline_fn;
else
- {
- fileline current_fn;
+ *fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
- current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
- if (current_fn == NULL || current_fn == elf_nodebug)
- *fileline_fn = elf_fileline_fn;
- }
+ if (*fileline_fn == NULL || *fileline_fn == elf_nodebug)
+ *fileline_fn = elf_fileline_fn;
return 1;
}
--- /dev/null
+/* testlib.c -- test functions for libbacktrace library
+ Copyright (C) 2012-2017 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ (1) Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ (2) Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ (3) The name of the author may not be used to
+ endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE. */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "filenames.h"
+
+#include "backtrace.h"
+
+#include "testlib.h"
+
+/* The backtrace state. */
+
+void *state;
+
+/* The number of failures. */
+
+int failures;
+
+/* Return the base name in a path. */
+
+const char *
+base (const char *p)
+{
+ const char *last;
+ const char *s;
+
+ last = NULL;
+ for (s = p; *s != '\0'; ++s)
+ {
+ if (IS_DIR_SEPARATOR (*s))
+ last = s + 1;
+ }
+ return last != NULL ? last : p;
+}
+
+/* Check an entry in a struct info array. */
+
+void
+check (const char *name, int index, const struct info *all, int want_lineno,
+ const char *want_function, const char *want_file, int *failed)
+{
+ if (*failed)
+ return;
+ if (all[index].filename == NULL || all[index].function == NULL)
+ {
+ fprintf (stderr, "%s: [%d]: missing file name or function name\n",
+ name, index);
+ *failed = 1;
+ return;
+ }
+ if (strcmp (base (all[index].filename), want_file) != 0)
+ {
+ fprintf (stderr, "%s: [%d]: got %s expected %s\n", name, index,
+ all[index].filename, want_file);
+ *failed = 1;
+ }
+ if (all[index].lineno != want_lineno)
+ {
+ fprintf (stderr, "%s: [%d]: got %d expected %d\n", name, index,
+ all[index].lineno, want_lineno);
+ *failed = 1;
+ }
+ if (strcmp (all[index].function, want_function) != 0)
+ {
+ fprintf (stderr, "%s: [%d]: got %s expected %s\n", name, index,
+ all[index].function, want_function);
+ *failed = 1;
+ }
+}
+
+/* The backtrace callback function. */
+
+int
+callback_one (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
+ const char *filename, int lineno, const char *function)
+{
+ struct bdata *data = (struct bdata *) vdata;
+ struct info *p;
+
+ if (data->index >= data->max)
+ {
+ fprintf (stderr, "callback_one: callback called too many times\n");
+ data->failed = 1;
+ return 1;
+ }
+
+ p = &data->all[data->index];
+ if (filename == NULL)
+ p->filename = NULL;
+ else
+ {
+ p->filename = strdup (filename);
+ assert (p->filename != NULL);
+ }
+ p->lineno = lineno;
+ if (function == NULL)
+ p->function = NULL;
+ else
+ {
+ p->function = strdup (function);
+ assert (p->function != NULL);
+ }
+ ++data->index;
+
+ return 0;
+}
+
+/* An error callback passed to backtrace. */
+
+void
+error_callback_one (void *vdata, const char *msg, int errnum)
+{
+ struct bdata *data = (struct bdata *) vdata;
+
+ fprintf (stderr, "%s", msg);
+ if (errnum > 0)
+ fprintf (stderr, ": %s", strerror (errnum));
+ fprintf (stderr, "\n");
+ data->failed = 1;
+}
+
+/* The backtrace_simple callback function. */
+
+int
+callback_two (void *vdata, uintptr_t pc)
+{
+ struct sdata *data = (struct sdata *) vdata;
+
+ if (data->index >= data->max)
+ {
+ fprintf (stderr, "callback_two: callback called too many times\n");
+ data->failed = 1;
+ return 1;
+ }
+
+ data->addrs[data->index] = pc;
+ ++data->index;
+
+ return 0;
+}
+
+/* An error callback passed to backtrace_simple. */
+
+void
+error_callback_two (void *vdata, const char *msg, int errnum)
+{
+ struct sdata *data = (struct sdata *) vdata;
+
+ fprintf (stderr, "%s", msg);
+ if (errnum > 0)
+ fprintf (stderr, ": %s", strerror (errnum));
+ fprintf (stderr, "\n");
+ data->failed = 1;
+}
+
+/* The backtrace_syminfo callback function. */
+
+void
+callback_three (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
+ const char *symname, uintptr_t symval,
+ uintptr_t symsize)
+{
+ struct symdata *data = (struct symdata *) vdata;
+
+ if (symname == NULL)
+ data->name = NULL;
+ else
+ {
+ data->name = strdup (symname);
+ assert (data->name != NULL);
+ }
+ data->val = symval;
+ data->size = symsize;
+}
+
+/* The backtrace_syminfo error callback function. */
+
+void
+error_callback_three (void *vdata, const char *msg, int errnum)
+{
+ struct symdata *data = (struct symdata *) vdata;
+
+ fprintf (stderr, "%s", msg);
+ if (errnum > 0)
+ fprintf (stderr, ": %s", strerror (errnum));
+ fprintf (stderr, "\n");
+ data->failed = 1;
+}
+
+/* The backtrace_create_state error callback function. */
+
+void
+error_callback_create (void *data ATTRIBUTE_UNUSED, const char *msg,
+ int errnum)
+{
+ fprintf (stderr, "%s", msg);
+ if (errnum > 0)
+ fprintf (stderr, ": %s", strerror (errnum));
+ fprintf (stderr, "\n");
+ exit (EXIT_FAILURE);
+}
--- /dev/null
+/* testlib.h -- Header for test functions for libbacktrace library
+ Copyright (C) 2012-2017 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ (1) Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ (2) Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ (3) The name of the author may not be used to
+ endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE. */
+
+#ifndef LIBBACKTRACE_TESTLIB_H
+#define LIBBACKTRACE_TESTLIB_H
+
+/* Portable attribute syntax. Actually some of these tests probably
+ won't work if the attributes are not recognized. */
+
+#ifndef GCC_VERSION
+# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+#endif
+
+#if (GCC_VERSION < 2007)
+# define __attribute__(x)
+#endif
+
+#ifndef ATTRIBUTE_UNUSED
+# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
+#endif
+
+/* Used to collect backtrace info. */
+
+struct info
+{
+ char *filename;
+ int lineno;
+ char *function;
+};
+
+/* Passed to backtrace callback function. */
+
+struct bdata
+{
+ struct info *all;
+ size_t index;
+ size_t max;
+ int failed;
+};
+
+/* Passed to backtrace_simple callback function. */
+
+struct sdata
+{
+ uintptr_t *addrs;
+ size_t index;
+ size_t max;
+ int failed;
+};
+
+/* Passed to backtrace_syminfo callback function. */
+
+struct symdata
+{
+ const char *name;
+ uintptr_t val, size;
+ int failed;
+};
+
+/* The backtrace state. */
+
+extern void *state;
+
+/* The number of failures. */
+
+extern int failures;
+
+extern const char *base (const char *p);
+extern void check (const char *name, int index, const struct info *all,
+ int want_lineno, const char *want_function,
+ const char *want_file, int *failed);
+extern int callback_one (void *, uintptr_t, const char *, int, const char *);
+extern void error_callback_one (void *, const char *, int);
+extern int callback_two (void *, uintptr_t);
+extern void error_callback_two (void *, const char *, int);
+extern void callback_three (void *, uintptr_t, const char *, uintptr_t,
+ uintptr_t);
+extern void error_callback_three (void *, const char *, int);
+extern void error_callback_create (void *, const char *, int);
+
+#endif /* !defined(LIBBACKTRACE_TESTLIB_H) */
--- /dev/null
+/* ttest.c -- Test for libbacktrace library
+ Copyright (C) 2017 Free Software Foundation, Inc.
+ Written by Ian Lance Taylor, Google.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ (1) Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ (2) Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ (3) The name of the author may not be used to
+ endorse or promote products derived from this software without
+ specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE. */
+
+/* Test using the libbacktrace library from multiple threads. */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <pthread.h>
+
+#include "filenames.h"
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+
+#include "testlib.h"
+
+static int f2 (int) __attribute__ ((noinline));
+static int f3 (int, int) __attribute__ ((noinline));
+
+/* Test that a simple backtrace works. This is called via
+ pthread_create. It returns the number of failures, as void *. */
+
+static void *
+test1_thread (void *arg ATTRIBUTE_UNUSED)
+{
+ /* Returning a value here and elsewhere avoids a tailcall which
+ would mess up the backtrace. */
+ return (void *) (uintptr_t) (f2 (__LINE__) - 2);
+}
+
+static int
+f2 (int f1line)
+{
+ return f3 (f1line, __LINE__) + 2;
+}
+
+static int
+f3 (int f1line, int f2line)
+{
+ struct info all[20];
+ struct bdata data;
+ int f3line;
+ int i;
+
+ data.all = &all[0];
+ data.index = 0;
+ data.max = 20;
+ data.failed = 0;
+
+ f3line = __LINE__ + 1;
+ i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
+
+ if (i != 0)
+ {
+ fprintf (stderr, "test1: unexpected return value %d\n", i);
+ data.failed = 1;
+ }
+
+ if (data.index < 3)
+ {
+ fprintf (stderr,
+ "test1: not enough frames; got %zu, expected at least 3\n",
+ data.index);
+ data.failed = 1;
+ }
+
+ check ("test1", 0, all, f3line, "f3", "ttest.c", &data.failed);
+ check ("test1", 1, all, f2line, "f2", "ttest.c", &data.failed);
+ check ("test1", 2, all, f1line, "test1_thread", "ttest.c", &data.failed);
+
+ return data.failed;
+}
+
+/* Run the test with 10 threads simultaneously. */
+
+#define THREAD_COUNT 10
+
+static void test1 (void) __attribute__ ((unused));
+
+static void
+test1 (void)
+{
+ pthread_t atid[THREAD_COUNT];
+ int i;
+ int errnum;
+ int this_fail;
+ void *ret;
+
+ for (i = 0; i < THREAD_COUNT; i++)
+ {
+ errnum = pthread_create (&atid[i], NULL, test1_thread, NULL);
+ if (errnum != 0)
+ {
+ fprintf (stderr, "pthread_create %d: %s\n", i, strerror (errnum));
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ this_fail = 0;
+ for (i = 0; i < THREAD_COUNT; i++)
+ {
+ errnum = pthread_join (atid[i], &ret);
+ if (errnum != 0)
+ {
+ fprintf (stderr, "pthread_join %d: %s\n", i, strerror (errnum));
+ exit (EXIT_FAILURE);
+ }
+ this_fail += (int) (uintptr_t) ret;
+ }
+
+ printf ("%s: threaded backtrace_full noinline\n", this_fail > 0 ? "FAIL" : "PASS");
+
+ failures += this_fail;
+}
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv)
+{
+ state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
+ error_callback_create, NULL);
+
+#if BACKTRACE_SUPPORTED
+#if BACKTRACE_SUPPORTS_THREADS
+ test1 ();
+#endif
+#endif
+
+ exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
+}