elf.c (backtrace_initialize): Always set *fileline_fn.

* 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
This commit is contained in:
Ian Lance Taylor 2017-06-12 03:25:04 +00:00 committed by Ian Lance Taylor
parent 1e7a4be3a1
commit d1609a2326
11 changed files with 656 additions and 420 deletions

View File

@ -1,3 +1,19 @@
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.

View File

@ -89,7 +89,7 @@ TESTS = $(check_PROGRAMS)
if NATIVE
btest_SOURCES = btest.c
btest_SOURCES = btest.c testlib.c
btest_CFLAGS = $(AM_CFLAGS) -g -O
btest_LDADD = libbacktrace.la
@ -100,7 +100,7 @@ stest_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
@ -111,6 +111,16 @@ gen_edtest2_build: $(srcdir)/edtest2.c
$(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

View File

@ -83,8 +83,9 @@ POST_UNINSTALL = :
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 \
@ -115,19 +116,29 @@ am_libbacktrace_la_OBJECTS = atomic.lo dwarf.lo fileline.lo posix.lo \
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 =
@ -141,7 +152,8 @@ LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--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 =
@ -218,6 +230,7 @@ PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PIC_FLAG = @PIC_FLAG@
PTHREAD_CFLAGS = @PTHREAD_CFLAGS@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
@ -330,13 +343,16 @@ libbacktrace_la_LIBADD = \
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
@ -435,6 +451,9 @@ edtest$(EXEEXT): $(edtest_OBJECTS) $(edtest_DEPENDENCIES) $(EXTRA_edtest_DEPENDE
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)
@ -457,6 +476,24 @@ btest-btest.o: btest.c
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

View File

@ -43,237 +43,7 @@ POSSIBILITY OF SUCH DAMAGE. */
#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. */
@ -325,9 +95,9 @@ f3 (int f1line, int f2line)
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");
@ -377,9 +147,9 @@ f13 (int f1line, int f2line)
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");
@ -462,9 +232,9 @@ f23 (int f1line, int f2line)
}
}
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;
@ -600,9 +370,9 @@ f33 (int f1line, int f2line)
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;
@ -686,17 +456,6 @@ test5 (void)
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

View File

@ -604,6 +604,9 @@ LTLIBOBJS
LIBOBJS
NATIVE_FALSE
NATIVE_TRUE
HAVE_PTHREAD_FALSE
HAVE_PTHREAD_TRUE
PTHREAD_CFLAGS
BACKTRACE_USES_MALLOC
ALLOC_FILE
VIEW_FILE
@ -11131,7 +11134,7 @@ else
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
@ -11237,7 +11240,7 @@ else
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
@ -12458,6 +12461,42 @@ $as_echo "#define HAVE_GETEXECNAME 1" >>confdefs.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 :
@ -12620,6 +12659,10 @@ if test -z "${MAINTAINER_MODE_TRUE}" && test -z "${MAINTAINER_MODE_FALSE}"; 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

View File

@ -355,6 +355,23 @@ if test "$have_getexecname" = "yes"; then
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;])],

View File

@ -41,19 +41,7 @@ POSSIBILITY OF SUCH DAMAGE. */
#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));
@ -68,128 +56,6 @@ test1 (void)
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)
{
@ -232,17 +98,6 @@ 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)
{

View File

@ -962,18 +962,12 @@ backtrace_initialize (struct backtrace_state *state, int descriptor,
}
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;
}

234
libbacktrace/testlib.c Normal file
View File

@ -0,0 +1,234 @@
/* 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);
}

110
libbacktrace/testlib.h Normal file
View File

@ -0,0 +1,110 @@
/* 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) */

161
libbacktrace/ttest.c Normal file
View File

@ -0,0 +1,161 @@
/* 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);
}