Commit 77bcaa99 by Ian Lance Taylor

libbacktrace: support MiniDebugInfo

libbacktrace/ChangeLog: PR libbacktrace/93608 Add support for MiniDebugInfo. * elf.c (struct elf_view): Define. Replace most uses of backtrace_view with elf_view. (elf_get_view): New static functions. Replace most calls of backtrace_get_view with elf_get_view. (elf_release_view): New static functions. Replace most calls of backtrace_release_view with elf_release_view. (elf_uncompress_failed): Rename from elf_zlib_failed. Change all callers. (LZMA_STATES, LZMA_POS_STATES, LZMA_DIST_STATES): Define. (LZMA_DIST_SLOTS, LZMA_DIST_MODEL_START): Define. (LZMA_DIST_MODEL_END, LZMA_FULL_DISTANCES): Define. (LZMA_ALIGN_SIZE, LZMA_LEN_LOW_SYMBOLS): Define. (LZMA_LEN_MID_SYMBOLS, LZMA_LEN_HIGH_SYMBOLS): Define. (LZMA_LITERAL_CODERS_MAX, LZMA_LITERAL_CODER_SIZE): Define. (LZMA_PROB_IS_MATCH_LEN, LZMA_PROB_IS_REP_LEN): Define. (LZMA_PROB_IS_REP0_LEN, LZMA_PROB_IS_REP1_LEN): Define. (LZMA_PROB_IS_REP2_LEN, LZMA_PROB_IS_REP0_LONG_LEN): Define. (LZMA_PROB_DIST_SLOT_LEN, LZMA_PROB_DIST_SPECIAL_LEN): Define. (LZMA_PROB_DIST_ALIGN_LEN): Define. (LZMA_PROB_MATCH_LEN_CHOICE_LEN): Define. (LZMA_PROB_MATCH_LEN_CHOICE2_LEN): Define. (LZMA_PROB_MATCH_LEN_LOW_LEN): Define. (LZMA_PROB_MATCH_LEN_MID_LEN): Define. (LZMA_PROB_MATCH_LEN_HIGH_LEN): Define. (LZMA_PROB_REP_LEN_CHOICE_LEN): Define. (LZMA_PROB_REP_LEN_CHOICE2_LEN): Define. (LZMA_PROB_REP_LEN_LOW_LEN): Define. (LZMA_PROB_REP_LEN_MID_LEN): Define. (LZMA_PROB_REP_LEN_HIGH_LEN): Define. (LZMA_PROB_LITERAL_LEN): Define. (LZMA_PROB_IS_MATCH_OFFSET, LZMA_PROB_IS_REP_OFFSET): Define. (LZMA_PROB_IS_REP0_OFFSET, LZMA_PROB_IS_REP1_OFFSET): Define. (LZMA_PROB_IS_REP2_OFFSET): Define. (LZMA_PROB_IS_REP0_LONG_OFFSET): Define. (LZMA_PROB_DIST_SLOT_OFFSET): Define. (LZMA_PROB_DIST_SPECIAL_OFFSET): Define. (LZMA_PROB_DIST_ALIGN_OFFSET): Define. (LZMA_PROB_MATCH_LEN_CHOICE_OFFSET): Define. (LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET): Define. (LZMA_PROB_MATCH_LEN_LOW_OFFSET): Define. (LZMA_PROB_MATCH_LEN_MID_OFFSET): Define. (LZMA_PROB_MATCH_LEN_HIGH_OFFSET): Define. (LZMA_PROB_REP_LEN_CHOICE_OFFSET): Define. (LZMA_PROB_REP_LEN_CHOICE2_OFFSET): Define. (LZMA_PROB_REP_LEN_LOW_OFFSET): Define. (LZMA_PROB_REP_LEN_MID_OFFSET): Define. (LZMA_PROB_REP_LEN_HIGH_OFFSET): Define. (LZMA_PROB_LITERAL_OFFSET): Define. (LZMA_PROB_TOTAL_COUNT): Define. (LZMA_IS_MATCH, LZMA_IS_REP, LZMA_IS_REP0): Define. (LZMA_IS_REP1, LZMA_IS_REP2, LZMA_IS_REP0_LONG): Define. (LZMA_DIST_SLOT, LZMA_DIST_SPECIAL, LZMA_DIST_ALIGN): Define. (LZMA_MATCH_LEN_CHOICE, LZMA_MATCH_LEN_CHOICE2): Define. (LZMA_MATCH_LEN_LOW, LZMA_MATCH_LEN_MID): Define. (LZMA_MATCH_LEN_HIGH, LZMA_REP_LEN_CHOICE): Define. (LZMA_REP_LEN_CHOICE2, LZMA_REP_LEN_LOW): Define. (LZMA_REP_LEN_MID, LZMA_REP_LEN_HIGH, LZMA_LITERAL): Define. (elf_lzma_varint): New static function. (elf_lzma_range_normalize): New static function. (elf_lzma_bit, elf_lzma_integer): New static functions. (elf_lzma_reverse_integer): New static function. (elf_lzma_len, elf_uncompress_lzma_block): New static functions. (elf_uncompress_lzma): New static function. (backtrace_uncompress_lzma): New function. (elf_add): Add memory and memory_size parameters. Change all callers. Look for .gnu_debugdata section, and, if found, decompress it and use it for symbols and debug info. Permit the descriptor parameter to be -1. * internal.h (backtrace_uncompress_lzma): Declare. * mtest.c: New file. * xztest.c: New file. * configure.ac: Check for nm, xz, and comm programs. Check for liblzma library. (HAVE_MINIDEBUG): Define. * Makefile.am (mtest_SOURCES): Define. (mtest_CFLAGS, mtest_LDADD): Define. (TESTS): Add mtest_minidebug if HAVE_MINIDEBUG. (%_minidebug): New pattern rule, if HAVE_MINIDEBUG. (xztest_SOURCES, xztest_CFLAGS, xztest_LDADD): Define. (xztest_alloc_SOURCES, xztest_alloc_CFLAGS): Define (xztest_alloc_LDADD): Define. (BUILDTESTS): Add mtest, xztest, xztest_alloc. (CLEANFILES): Add files created by minidebug pattern. (btest.lo): Correct INCDIR reference. (mtest.lo, xztest.lo, ztest.lo): New targets. * configure: Regenerate. * config.h.in: Regenerate. * Makefile.in: Regenerate. Close #38
parent 2f5efbfa
......@@ -479,13 +479,61 @@ endif HAVE_DSYMUTIL
endif
mtest_SOURCES = mtest.c testlib.c
mtest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O
mtest_LDADD = libbacktrace.la
BUILDTESTS += mtest
if HAVE_MINIDEBUG
TESTS += mtest_minidebug
%_minidebug: %
$(NM) -D $< -P --defined-only | $(AWK) '{ print $$1 }' | sort > $<.dsyms
$(NM) $< -P --defined-only | $(AWK) '{ if ($$2 == "T" || $$2 == "t" || $$2 == "D") print $$1 }' | sort > $<.fsyms
$(COMM) -13 $<.dsyms $<.fsyms > $<.keepsyms
$(OBJCOPY) --only-keep-debug $< $<.dbg
$(OBJCOPY) -S --remove-section .gdb_index --remove-section .comment --keep-symbols=$<.keepsyms $<.dbg $<.mdbg
$(OBJCOPY) --strip-all --remove-section ..comment $< $<.strip
rm -f $<.mdbg.xz
$(XZ) $<.mdbg
$(OBJCOPY) --add-section .gnu_debugdata=$<.mdbg.xz $<.strip
mv $<.strip $@
endif HAVE_MINIDEBUG
endif NATIVE
if HAVE_ELF
xztest_SOURCES = xztest.c testlib.c
xztest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\"$(srcdir)\"
xztest_LDADD = libbacktrace.la
xztest_alloc_SOURCES = $(xztest_SOURCES)
xztest_alloc_CFLAGS = $(xztest_CFLAGS)
xztest_alloc_LDADD = libbacktrace_alloc.la
if HAVE_LIBLZMA
xztest_LDADD += -llzma
xztest_alloc_LDADD += -llzma
endif
xztest_LDADD += $(CLOCK_GETTIME_LINK)
xztest_alloc_LDADD += $(CLOCK_GETTIME_LINK)
BUILDTESTS += xztest xztest_alloc
endif HAVE_ELF
check_PROGRAMS += $(BUILDTESTS)
TESTS += $(BUILDTESTS)
CLEANFILES = $(TESTS) *.debug elf_for_test.c edtest2_build.c gen_edtest2_build
CLEANFILES = \
$(TESTS) *.debug elf_for_test.c edtest2_build.c gen_edtest2_build \
*.dsyms *.fsyms *.keepsyms *.dbg *.mdbg *.mdbg.xz *.strip
clean-local:
-rm -rf usr
......@@ -511,6 +559,7 @@ fileline.lo: config.h backtrace.h internal.h
macho.lo: config.h backtrace.h internal.h
mmap.lo: config.h backtrace.h internal.h
mmapio.lo: config.h backtrace.h internal.h
mtest.lo: backtrace.h backtrace-supported.h
nounwind.lo: config.h internal.h
pecoff.lo: config.h backtrace.h internal.h
posix.lo: config.h backtrace.h internal.h
......@@ -522,4 +571,6 @@ stest.lo: config.h backtrace.h internal.h
state.lo: config.h backtrace.h backtrace-supported.h internal.h
unknown.lo: config.h backtrace.h internal.h
xcoff.lo: config.h backtrace.h internal.h
xztest.lo: config.h backtrace.h backtrace-supported.h internal.h testlib.h
ztest.lo: config.h backtrace.h backtrace-supported.h internal.h testlib.h
......@@ -122,10 +122,10 @@ build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \
$(am__EXEEXT_12)
$(am__EXEEXT_14)
TESTS = $(am__append_4) $(am__append_7) $(am__append_9) \
$(am__append_12) $(am__append_13) $(am__append_20) \
$(am__EXEEXT_12)
$(am__append_25) $(am__EXEEXT_14)
@HAVE_ELF_TRUE@@HAVE_OBJCOPY_DEBUGLINK_TRUE@@NATIVE_TRUE@am__append_1 = libbacktrace_elf_for_test.la
@NATIVE_TRUE@am__append_2 = test_elf_32 test_elf_64 test_macho \
@NATIVE_TRUE@ test_xcoff_32 test_xcoff_64 test_pecoff \
......@@ -158,6 +158,11 @@ TESTS = $(am__append_4) $(am__append_7) $(am__append_9) \
@HAVE_DWARF5_TRUE@@NATIVE_TRUE@am__append_22 = dwarf5 dwarf5_alloc
@HAVE_DSYMUTIL_TRUE@@HAVE_DWARF5_TRUE@@NATIVE_TRUE@am__append_23 = dwarf5.dSYM \
@HAVE_DSYMUTIL_TRUE@@HAVE_DWARF5_TRUE@@NATIVE_TRUE@ dwarf5_alloc.dSYM
@NATIVE_TRUE@am__append_24 = mtest
@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@am__append_25 = mtest_minidebug
@HAVE_ELF_TRUE@@HAVE_LIBLZMA_TRUE@am__append_26 = -llzma
@HAVE_ELF_TRUE@@HAVE_LIBLZMA_TRUE@am__append_27 = -llzma
@HAVE_ELF_TRUE@am__append_28 = xztest xztest_alloc
subdir = .
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/config/lead-dot.m4 \
......@@ -262,9 +267,12 @@ libbacktrace_noformat_la_OBJECTS = \
@HAVE_COMPRESSED_DEBUG_TRUE@@NATIVE_TRUE@ ctesta_alloc$(EXEEXT)
@HAVE_DWARF5_TRUE@@NATIVE_TRUE@am__EXEEXT_11 = dwarf5$(EXEEXT) \
@HAVE_DWARF5_TRUE@@NATIVE_TRUE@ dwarf5_alloc$(EXEEXT)
am__EXEEXT_12 = $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \
@NATIVE_TRUE@am__EXEEXT_12 = mtest$(EXEEXT)
@HAVE_ELF_TRUE@am__EXEEXT_13 = xztest$(EXEEXT) xztest_alloc$(EXEEXT)
am__EXEEXT_14 = $(am__EXEEXT_4) $(am__EXEEXT_5) $(am__EXEEXT_6) \
$(am__EXEEXT_7) $(am__EXEEXT_8) $(am__EXEEXT_9) \
$(am__EXEEXT_10) $(am__EXEEXT_11)
$(am__EXEEXT_10) $(am__EXEEXT_11) $(am__EXEEXT_12) \
$(am__EXEEXT_13)
@NATIVE_TRUE@am_allocfail_OBJECTS = allocfail-allocfail.$(OBJEXT) \
@NATIVE_TRUE@ allocfail-testlib.$(OBJEXT)
allocfail_OBJECTS = $(am_allocfail_OBJECTS)
......@@ -382,6 +390,13 @@ edtest_alloc_OBJECTS = $(am_edtest_alloc_OBJECTS)
edtest_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(edtest_alloc_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
@NATIVE_TRUE@am_mtest_OBJECTS = mtest-mtest.$(OBJEXT) \
@NATIVE_TRUE@ mtest-testlib.$(OBJEXT)
mtest_OBJECTS = $(am_mtest_OBJECTS)
@NATIVE_TRUE@mtest_DEPENDENCIES = libbacktrace.la
mtest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(mtest_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
@NATIVE_TRUE@am_stest_OBJECTS = stest-stest.$(OBJEXT)
stest_OBJECTS = $(am_stest_OBJECTS)
@NATIVE_TRUE@stest_DEPENDENCIES = libbacktrace.la
......@@ -492,6 +507,23 @@ unittest_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
$(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
$(unittest_alloc_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o \
$@
@HAVE_ELF_TRUE@am_xztest_OBJECTS = xztest-xztest.$(OBJEXT) \
@HAVE_ELF_TRUE@ xztest-testlib.$(OBJEXT)
xztest_OBJECTS = $(am_xztest_OBJECTS)
@HAVE_ELF_TRUE@xztest_DEPENDENCIES = libbacktrace.la \
@HAVE_ELF_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
xztest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(xztest_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
@HAVE_ELF_TRUE@am__objects_12 = xztest_alloc-xztest.$(OBJEXT) \
@HAVE_ELF_TRUE@ xztest_alloc-testlib.$(OBJEXT)
@HAVE_ELF_TRUE@am_xztest_alloc_OBJECTS = $(am__objects_12)
xztest_alloc_OBJECTS = $(am_xztest_alloc_OBJECTS)
@HAVE_ELF_TRUE@xztest_alloc_DEPENDENCIES = libbacktrace_alloc.la \
@HAVE_ELF_TRUE@ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
xztest_alloc_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(xztest_alloc_CFLAGS) \
$(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
@HAVE_ELF_TRUE@@NATIVE_TRUE@am_ztest_OBJECTS = ztest-ztest.$(OBJEXT) \
@HAVE_ELF_TRUE@@NATIVE_TRUE@ ztest-testlib.$(OBJEXT)
ztest_OBJECTS = $(am_ztest_OBJECTS)
......@@ -501,11 +533,11 @@ ztest_OBJECTS = $(am_ztest_OBJECTS)
ztest_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CCLD) $(ztest_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
@HAVE_ELF_TRUE@@NATIVE_TRUE@am__objects_12 = \
@HAVE_ELF_TRUE@@NATIVE_TRUE@am__objects_13 = \
@HAVE_ELF_TRUE@@NATIVE_TRUE@ ztest_alloc-ztest.$(OBJEXT) \
@HAVE_ELF_TRUE@@NATIVE_TRUE@ ztest_alloc-testlib.$(OBJEXT)
@HAVE_ELF_TRUE@@NATIVE_TRUE@am_ztest_alloc_OBJECTS = \
@HAVE_ELF_TRUE@@NATIVE_TRUE@ $(am__objects_12)
@HAVE_ELF_TRUE@@NATIVE_TRUE@ $(am__objects_13)
ztest_alloc_OBJECTS = $(am_ztest_alloc_OBJECTS)
@HAVE_ELF_TRUE@@NATIVE_TRUE@ztest_alloc_DEPENDENCIES = \
@HAVE_ELF_TRUE@@NATIVE_TRUE@ libbacktrace_alloc.la \
......@@ -557,13 +589,14 @@ SOURCES = $(libbacktrace_la_SOURCES) $(EXTRA_libbacktrace_la_SOURCES) \
$(ctesta_alloc_SOURCES) $(ctestg_SOURCES) \
$(ctestg_alloc_SOURCES) $(dwarf5_SOURCES) \
$(dwarf5_alloc_SOURCES) $(edtest_SOURCES) \
$(edtest_alloc_SOURCES) $(stest_SOURCES) \
$(edtest_alloc_SOURCES) $(mtest_SOURCES) $(stest_SOURCES) \
$(stest_alloc_SOURCES) $(test_elf_32_SOURCES) \
$(test_elf_64_SOURCES) $(test_macho_SOURCES) \
$(test_pecoff_SOURCES) $(test_unknown_SOURCES) \
$(test_xcoff_32_SOURCES) $(test_xcoff_64_SOURCES) \
$(ttest_SOURCES) $(ttest_alloc_SOURCES) $(unittest_SOURCES) \
$(unittest_alloc_SOURCES) $(ztest_SOURCES) \
$(unittest_alloc_SOURCES) $(xztest_SOURCES) \
$(xztest_alloc_SOURCES) $(ztest_SOURCES) \
$(ztest_alloc_SOURCES)
am__can_run_installinfo = \
case $$AM_UPDATE_INFO_DIR in \
......@@ -786,6 +819,7 @@ BACKTRACE_USES_MALLOC = @BACKTRACE_USES_MALLOC@
CC = @CC@
CFLAGS = @CFLAGS@
CLOCK_GETTIME_LINK = @CLOCK_GETTIME_LINK@
COMM = @COMM@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
......@@ -844,6 +878,7 @@ STRIP = @STRIP@
VERSION = @VERSION@
VIEW_FILE = @VIEW_FILE@
WARN_FLAGS = @WARN_FLAGS@
XZ = @XZ@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
......@@ -952,7 +987,8 @@ libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
# Add a test to this variable if you want it to be built and run.
BUILDTESTS = $(am__append_2) $(am__append_10) $(am__append_11) \
$(am__append_16) $(am__append_17) $(am__append_18) \
$(am__append_21) $(am__append_22)
$(am__append_21) $(am__append_22) $(am__append_24) \
$(am__append_28)
# Add a file to this variable if you want it to be built for testing.
check_DATA = $(am__append_5) $(am__append_19) $(am__append_23)
......@@ -1077,7 +1113,21 @@ libbacktrace_TEST_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) -g
@HAVE_DWARF5_TRUE@@NATIVE_TRUE@dwarf5_alloc_SOURCES = $(dwarf5_SOURCES)
@HAVE_DWARF5_TRUE@@NATIVE_TRUE@dwarf5_alloc_CFLAGS = $(dwarf5_CFLAGS)
@HAVE_DWARF5_TRUE@@NATIVE_TRUE@dwarf5_alloc_LDADD = libbacktrace_alloc.la
CLEANFILES = $(TESTS) *.debug elf_for_test.c edtest2_build.c gen_edtest2_build
@NATIVE_TRUE@mtest_SOURCES = mtest.c testlib.c
@NATIVE_TRUE@mtest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -O
@NATIVE_TRUE@mtest_LDADD = libbacktrace.la
@HAVE_ELF_TRUE@xztest_SOURCES = xztest.c testlib.c
@HAVE_ELF_TRUE@xztest_CFLAGS = $(libbacktrace_TEST_CFLAGS) -DSRCDIR=\"$(srcdir)\"
@HAVE_ELF_TRUE@xztest_LDADD = libbacktrace.la $(am__append_26) \
@HAVE_ELF_TRUE@ $(CLOCK_GETTIME_LINK)
@HAVE_ELF_TRUE@xztest_alloc_SOURCES = $(xztest_SOURCES)
@HAVE_ELF_TRUE@xztest_alloc_CFLAGS = $(xztest_CFLAGS)
@HAVE_ELF_TRUE@xztest_alloc_LDADD = libbacktrace_alloc.la \
@HAVE_ELF_TRUE@ $(am__append_27) $(CLOCK_GETTIME_LINK)
CLEANFILES = \
$(TESTS) *.debug elf_for_test.c edtest2_build.c gen_edtest2_build \
*.dsyms *.fsyms *.keepsyms *.dbg *.mdbg *.mdbg.xz *.strip
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
......@@ -1262,6 +1312,10 @@ edtest_alloc$(EXEEXT): $(edtest_alloc_OBJECTS) $(edtest_alloc_DEPENDENCIES) $(EX
@rm -f edtest_alloc$(EXEEXT)
$(AM_V_CCLD)$(edtest_alloc_LINK) $(edtest_alloc_OBJECTS) $(edtest_alloc_LDADD) $(LIBS)
mtest$(EXEEXT): $(mtest_OBJECTS) $(mtest_DEPENDENCIES) $(EXTRA_mtest_DEPENDENCIES)
@rm -f mtest$(EXEEXT)
$(AM_V_CCLD)$(mtest_LINK) $(mtest_OBJECTS) $(mtest_LDADD) $(LIBS)
stest$(EXEEXT): $(stest_OBJECTS) $(stest_DEPENDENCIES) $(EXTRA_stest_DEPENDENCIES)
@rm -f stest$(EXEEXT)
$(AM_V_CCLD)$(stest_LINK) $(stest_OBJECTS) $(stest_LDADD) $(LIBS)
......@@ -1314,6 +1368,14 @@ unittest_alloc$(EXEEXT): $(unittest_alloc_OBJECTS) $(unittest_alloc_DEPENDENCIES
@rm -f unittest_alloc$(EXEEXT)
$(AM_V_CCLD)$(unittest_alloc_LINK) $(unittest_alloc_OBJECTS) $(unittest_alloc_LDADD) $(LIBS)
xztest$(EXEEXT): $(xztest_OBJECTS) $(xztest_DEPENDENCIES) $(EXTRA_xztest_DEPENDENCIES)
@rm -f xztest$(EXEEXT)
$(AM_V_CCLD)$(xztest_LINK) $(xztest_OBJECTS) $(xztest_LDADD) $(LIBS)
xztest_alloc$(EXEEXT): $(xztest_alloc_OBJECTS) $(xztest_alloc_DEPENDENCIES) $(EXTRA_xztest_alloc_DEPENDENCIES)
@rm -f xztest_alloc$(EXEEXT)
$(AM_V_CCLD)$(xztest_alloc_LINK) $(xztest_alloc_OBJECTS) $(xztest_alloc_LDADD) $(LIBS)
ztest$(EXEEXT): $(ztest_OBJECTS) $(ztest_DEPENDENCIES) $(EXTRA_ztest_DEPENDENCIES)
@rm -f ztest$(EXEEXT)
$(AM_V_CCLD)$(ztest_LINK) $(ztest_OBJECTS) $(ztest_LDADD) $(LIBS)
......@@ -1517,6 +1579,18 @@ edtest_alloc-testlib.o: testlib.c
edtest_alloc-testlib.obj: testlib.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(edtest_alloc_CFLAGS) $(CFLAGS) -c -o edtest_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
mtest-mtest.o: mtest.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mtest_CFLAGS) $(CFLAGS) -c -o mtest-mtest.o `test -f 'mtest.c' || echo '$(srcdir)/'`mtest.c
mtest-mtest.obj: mtest.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mtest_CFLAGS) $(CFLAGS) -c -o mtest-mtest.obj `if test -f 'mtest.c'; then $(CYGPATH_W) 'mtest.c'; else $(CYGPATH_W) '$(srcdir)/mtest.c'; fi`
mtest-testlib.o: testlib.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mtest_CFLAGS) $(CFLAGS) -c -o mtest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c
mtest-testlib.obj: testlib.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(mtest_CFLAGS) $(CFLAGS) -c -o mtest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
stest-stest.o: stest.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(stest_CFLAGS) $(CFLAGS) -c -o stest-stest.o `test -f 'stest.c' || echo '$(srcdir)/'`stest.c
......@@ -1661,6 +1735,30 @@ unittest_alloc-testlib.o: testlib.c
unittest_alloc-testlib.obj: testlib.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(unittest_alloc_CFLAGS) $(CFLAGS) -c -o unittest_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
xztest-xztest.o: xztest.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_CFLAGS) $(CFLAGS) -c -o xztest-xztest.o `test -f 'xztest.c' || echo '$(srcdir)/'`xztest.c
xztest-xztest.obj: xztest.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_CFLAGS) $(CFLAGS) -c -o xztest-xztest.obj `if test -f 'xztest.c'; then $(CYGPATH_W) 'xztest.c'; else $(CYGPATH_W) '$(srcdir)/xztest.c'; fi`
xztest-testlib.o: testlib.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_CFLAGS) $(CFLAGS) -c -o xztest-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c
xztest-testlib.obj: testlib.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_CFLAGS) $(CFLAGS) -c -o xztest-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
xztest_alloc-xztest.o: xztest.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_alloc_CFLAGS) $(CFLAGS) -c -o xztest_alloc-xztest.o `test -f 'xztest.c' || echo '$(srcdir)/'`xztest.c
xztest_alloc-xztest.obj: xztest.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_alloc_CFLAGS) $(CFLAGS) -c -o xztest_alloc-xztest.obj `if test -f 'xztest.c'; then $(CYGPATH_W) 'xztest.c'; else $(CYGPATH_W) '$(srcdir)/xztest.c'; fi`
xztest_alloc-testlib.o: testlib.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_alloc_CFLAGS) $(CFLAGS) -c -o xztest_alloc-testlib.o `test -f 'testlib.c' || echo '$(srcdir)/'`testlib.c
xztest_alloc-testlib.obj: testlib.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(xztest_alloc_CFLAGS) $(CFLAGS) -c -o xztest_alloc-testlib.obj `if test -f 'testlib.c'; then $(CYGPATH_W) 'testlib.c'; else $(CYGPATH_W) '$(srcdir)/testlib.c'; fi`
ztest-ztest.o: ztest.c
$(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(ztest_CFLAGS) $(CFLAGS) -c -o ztest-ztest.o `test -f 'ztest.c' || echo '$(srcdir)/'`ztest.c
......@@ -1957,6 +2055,13 @@ btest_gnudebuglink.log: btest_gnudebuglink
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
mtest_minidebug.log: mtest_minidebug
@p='mtest_minidebug'; \
b='mtest_minidebug'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
test_elf_32.log: test_elf_32$(EXEEXT)
@p='test_elf_32$(EXEEXT)'; \
b='test_elf_32'; \
......@@ -2139,6 +2244,27 @@ dwarf5_alloc.log: dwarf5_alloc$(EXEEXT)
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
mtest.log: mtest$(EXEEXT)
@p='mtest$(EXEEXT)'; \
b='mtest'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
xztest.log: xztest$(EXEEXT)
@p='xztest$(EXEEXT)'; \
b='xztest'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
xztest_alloc.log: xztest_alloc$(EXEEXT)
@p='xztest_alloc$(EXEEXT)'; \
b='xztest_alloc'; \
$(am__check_pre) $(LOG_DRIVER) --test-name "$$f" \
--log-file $$b.log --trs-file $$b.trs \
$(am__common_driver_flags) $(AM_LOG_DRIVER_FLAGS) $(LOG_DRIVER_FLAGS) -- $(LOG_COMPILE) \
"$$tst" $(AM_TESTS_FD_REDIRECT)
.test.log:
@p='$<'; \
$(am__set_b); \
......@@ -2349,6 +2475,18 @@ uninstall-am: uninstall-includeHEADERS uninstall-libLTLIBRARIES
@NATIVE_TRUE@ $<
@NATIVE_TRUE@ $(OBJCOPY) --strip-debug $< $@
@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@%_minidebug: %
@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@ $(NM) -D $< -P --defined-only | $(AWK) '{ print $$1 }' | sort > $<.dsyms
@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@ $(NM) $< -P --defined-only | $(AWK) '{ if ($$2 == "T" || $$2 == "t" || $$2 == "D") print $$1 }' | sort > $<.fsyms
@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@ $(COMM) -13 $<.dsyms $<.fsyms > $<.keepsyms
@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@ $(OBJCOPY) --only-keep-debug $< $<.dbg
@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@ $(OBJCOPY) -S --remove-section .gdb_index --remove-section .comment --keep-symbols=$<.keepsyms $<.dbg $<.mdbg
@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@ $(OBJCOPY) --strip-all --remove-section ..comment $< $<.strip
@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@ rm -f $<.mdbg.xz
@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@ $(XZ) $<.mdbg
@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@ $(OBJCOPY) --add-section .gnu_debugdata=$<.mdbg.xz $<.strip
@HAVE_MINIDEBUG_TRUE@@NATIVE_TRUE@ mv $<.strip $@
clean-local:
-rm -rf usr
......@@ -2373,6 +2511,7 @@ fileline.lo: config.h backtrace.h internal.h
macho.lo: config.h backtrace.h internal.h
mmap.lo: config.h backtrace.h internal.h
mmapio.lo: config.h backtrace.h internal.h
mtest.lo: backtrace.h backtrace-supported.h
nounwind.lo: config.h internal.h
pecoff.lo: config.h backtrace.h internal.h
posix.lo: config.h backtrace.h internal.h
......@@ -2384,6 +2523,8 @@ stest.lo: config.h backtrace.h internal.h
state.lo: config.h backtrace.h backtrace-supported.h internal.h
unknown.lo: config.h backtrace.h internal.h
xcoff.lo: config.h backtrace.h internal.h
xztest.lo: config.h backtrace.h backtrace-supported.h internal.h testlib.h
ztest.lo: config.h backtrace.h backtrace-supported.h internal.h testlib.h
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
......
......@@ -46,6 +46,9 @@
<sys/sysctl.h>. */
#undef HAVE_KERN_PROC_ARGS
/* Define if -llzma is available. */
#undef HAVE_LIBLZMA
/* Define to 1 if you have the <link.h> header file. */
#undef HAVE_LINK_H
......
......@@ -635,6 +635,16 @@ LTLIBOBJS
LIBOBJS
NATIVE_FALSE
NATIVE_TRUE
HAVE_LIBLZMA_FALSE
HAVE_LIBLZMA_TRUE
HAVE_MINIDEBUG_FALSE
HAVE_MINIDEBUG_TRUE
HAVE_COMM_FALSE
HAVE_COMM_TRUE
COMM
HAVE_XZ_FALSE
HAVE_XZ_TRUE
XZ
HAVE_DSYMUTIL_FALSE
HAVE_DSYMUTIL_TRUE
HAVE_OBJCOPY_DEBUGLINK_FALSE
......@@ -802,7 +812,8 @@ LIBS
CPPFLAGS
CPP
OBJCOPY
DSYMUTIL'
DSYMUTIL
NM'
# Initialize some variables set by options.
......@@ -1456,6 +1467,7 @@ Some influential environment variables:
CPP C preprocessor
OBJCOPY location of objcopy
DSYMUTIL location of dsymutil
NM location of nm
Use these variables to override the choices made by `configure' or to help
it to find libraries and programs with nonstandard names/locations.
......@@ -11269,7 +11281,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 11272 "configure"
#line 11284 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
......@@ -11375,7 +11387,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
#line 11378 "configure"
#line 11390 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
......@@ -12944,6 +12956,196 @@ else
fi
# Extract the first word of "nm", so it can be a program name with args.
set dummy nm; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_NM+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$NM"; then
ac_cv_prog_NM="$NM" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_NM="nm"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
NM=$ac_cv_prog_NM
if test -n "$NM"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $NM" >&5
$as_echo "$NM" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
# Extract the first word of "xz", so it can be a program name with args.
set dummy xz; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_XZ+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$XZ"; then
ac_cv_prog_XZ="$XZ" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_XZ="xz"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
XZ=$ac_cv_prog_XZ
if test -n "$XZ"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $XZ" >&5
$as_echo "$XZ" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if test "$XZ" != ""; then
HAVE_XZ_TRUE=
HAVE_XZ_FALSE='#'
else
HAVE_XZ_TRUE='#'
HAVE_XZ_FALSE=
fi
# Extract the first word of "comm", so it can be a program name with args.
set dummy comm; ac_word=$2
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
$as_echo_n "checking for $ac_word... " >&6; }
if ${ac_cv_prog_COMM+:} false; then :
$as_echo_n "(cached) " >&6
else
if test -n "$COMM"; then
ac_cv_prog_COMM="$COMM" # Let the user override the test.
else
as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
for as_dir in $PATH
do
IFS=$as_save_IFS
test -z "$as_dir" && as_dir=.
for ac_exec_ext in '' $ac_executable_extensions; do
if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
ac_cv_prog_COMM="comm"
$as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
break 2
fi
done
done
IFS=$as_save_IFS
fi
fi
COMM=$ac_cv_prog_COMM
if test -n "$COMM"; then
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $COMM" >&5
$as_echo "$COMM" >&6; }
else
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
$as_echo "no" >&6; }
fi
if test "$COMM" != ""; then
HAVE_COMM_TRUE=
HAVE_COMM_FALSE='#'
else
HAVE_COMM_TRUE='#'
HAVE_COMM_FALSE=
fi
if test "${with_target_subdir}" = "" -a "$FORMAT_FILE" = "elf.lo" -a "${OBJCOPY}" != "" -a "${NM}" != "" -a "${XZ}" != "" -a "${COMM}" != ""; then
HAVE_MINIDEBUG_TRUE=
HAVE_MINIDEBUG_FALSE='#'
else
HAVE_MINIDEBUG_TRUE='#'
HAVE_MINIDEBUG_FALSE=
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for lzma_auto_decoder in -llzma" >&5
$as_echo_n "checking for lzma_auto_decoder in -llzma... " >&6; }
if ${ac_cv_lib_lzma_lzma_auto_decoder+:} false; then :
$as_echo_n "(cached) " >&6
else
ac_check_lib_save_LIBS=$LIBS
LIBS="-llzma $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char lzma_auto_decoder ();
int
main ()
{
return lzma_auto_decoder ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"; then :
ac_cv_lib_lzma_lzma_auto_decoder=yes
else
ac_cv_lib_lzma_lzma_auto_decoder=no
fi
rm -f core conftest.err conftest.$ac_objext \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_lzma_lzma_auto_decoder" >&5
$as_echo "$ac_cv_lib_lzma_lzma_auto_decoder" >&6; }
if test "x$ac_cv_lib_lzma_lzma_auto_decoder" = xyes; then :
$as_echo "#define HAVE_LIBLZMA 1" >>confdefs.h
fi
if test "$ac_cv_lib_lzma_lzma_auto_decoder" = yes; then
HAVE_LIBLZMA_TRUE=
HAVE_LIBLZMA_FALSE='#'
else
HAVE_LIBLZMA_TRUE='#'
HAVE_LIBLZMA_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 ${libbacktrace_cv_sys_native+:} false; then :
......@@ -13160,6 +13362,22 @@ if test -z "${HAVE_DSYMUTIL_TRUE}" && test -z "${HAVE_DSYMUTIL_FALSE}"; then
as_fn_error $? "conditional \"HAVE_DSYMUTIL\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${HAVE_XZ_TRUE}" && test -z "${HAVE_XZ_FALSE}"; then
as_fn_error $? "conditional \"HAVE_XZ\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${HAVE_COMM_TRUE}" && test -z "${HAVE_COMM_FALSE}"; then
as_fn_error $? "conditional \"HAVE_COMM\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${HAVE_MINIDEBUG_TRUE}" && test -z "${HAVE_MINIDEBUG_FALSE}"; then
as_fn_error $? "conditional \"HAVE_MINIDEBUG\" was never defined.
Usually this means the macro was only invoked conditionally." "$LINENO" 5
fi
if test -z "${HAVE_LIBLZMA_TRUE}" && test -z "${HAVE_LIBLZMA_FALSE}"; then
as_fn_error $? "conditional \"HAVE_LIBLZMA\" 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
......
......@@ -508,6 +508,21 @@ AC_ARG_VAR(DSYMUTIL, [location of dsymutil])
AC_CHECK_PROG(DSYMUTIL, dsymutil, dsymutil)
AM_CONDITIONAL(HAVE_DSYMUTIL, test -n "${DSYMUTIL}")
AC_ARG_VAR(NM, [location of nm])
AC_CHECK_PROG(NM, nm, nm)
AC_CHECK_PROG(XZ, xz, xz)
AM_CONDITIONAL(HAVE_XZ, test "$XZ" != "")
AC_CHECK_PROG(COMM, comm, comm)
AM_CONDITIONAL(HAVE_COMM, test "$COMM" != "")
AM_CONDITIONAL(HAVE_MINIDEBUG,
test "${with_target_subdir}" = "" -a "$FORMAT_FILE" = "elf.lo" -a "${OBJCOPY}" != "" -a "${NM}" != "" -a "${XZ}" != "" -a "${COMM}" != "")
AC_CHECK_LIB([lzma], [lzma_auto_decoder],
[AC_DEFINE(HAVE_LIBLZMA, 1, [Define if -llzma is available.])])
AM_CONDITIONAL(HAVE_LIBLZMA, test "$ac_cv_lib_lzma_lzma_auto_decoder" = yes)
AC_CACHE_CHECK([whether tests can run],
[libbacktrace_cv_sys_native],
[AC_RUN_IFELSE([AC_LANG_PROGRAM([], [return 0;])],
......
......@@ -390,6 +390,14 @@ struct elf_syminfo_data
size_t count;
};
/* A view that works for either a file or memory. */
struct elf_view
{
struct backtrace_view view;
int release; /* If non-zero, must call backtrace_release_view. */
};
/* Information about PowerPC64 ELFv1 .opd section. */
struct elf_ppc64_opd_data
......@@ -401,9 +409,48 @@ struct elf_ppc64_opd_data
/* Size of the .opd section. */
size_t size;
/* Corresponding section view. */
struct backtrace_view view;
struct elf_view view;
};
/* Create a view of SIZE bytes from DESCRIPTOR/MEMORY at OFFSET. */
static int
elf_get_view (struct backtrace_state *state, int descriptor,
const unsigned char *memory, size_t memory_size, off_t offset,
uint64_t size, backtrace_error_callback error_callback,
void *data, struct elf_view *view)
{
if (memory == NULL)
{
view->release = 1;
return backtrace_get_view (state, descriptor, offset, size,
error_callback, data, &view->view);
}
else
{
if ((uint64_t) offset + size > (uint64_t) memory_size)
{
error_callback (data, "out of range for in-memory file", 0);
return 0;
}
view->view.data = (const void *) (memory + offset);
view->view.base = NULL;
view->view.len = size;
view->release = 0;
return 1;
}
}
/* Release a view read by elf_get_view. */
static void
elf_release_view (struct backtrace_state *state, struct elf_view *view,
backtrace_error_callback error_callback, void *data)
{
if (view->release)
backtrace_release_view (state, &view->view, error_callback, data);
}
/* Compute the CRC-32 of BUF/LEN. This uses the CRC used for
.gnu_debuglink files. */
......@@ -1035,7 +1082,7 @@ elf_open_debugfile_by_debuglink (struct backtrace_state *state,
when this code is compiled with -g. */
static void
elf_zlib_failed(void)
elf_uncompress_failed(void)
{
}
......@@ -1062,7 +1109,7 @@ elf_zlib_fetch (const unsigned char **ppin, const unsigned char *pinend,
if (unlikely (pinend - pin < 4))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -1192,7 +1239,7 @@ elf_zlib_inflate_table (unsigned char *codes, size_t codes_len,
{
if (unlikely (codes[i] >= 16))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -1229,7 +1276,7 @@ elf_zlib_inflate_table (unsigned char *codes, size_t codes_len,
if (unlikely (jcnt > (1U << j)))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -1249,7 +1296,7 @@ elf_zlib_inflate_table (unsigned char *codes, size_t codes_len,
if (unlikely ((val & ~HUFFMAN_VALUE_MASK) != 0))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -1265,7 +1312,7 @@ elf_zlib_inflate_table (unsigned char *codes, size_t codes_len,
{
if (unlikely (table[ind] != 0))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
table[ind] = tval;
......@@ -1353,7 +1400,7 @@ elf_zlib_inflate_table (unsigned char *codes, size_t codes_len,
}
if (unlikely (jcnt != 0))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
}
......@@ -1406,7 +1453,7 @@ elf_zlib_inflate_table (unsigned char *codes, size_t codes_len,
if (unlikely ((next_secondary & HUFFMAN_VALUE_MASK)
!= next_secondary))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -1424,7 +1471,7 @@ elf_zlib_inflate_table (unsigned char *codes, size_t codes_len,
if (unlikely ((tprimary & (1U << HUFFMAN_SECONDARY_SHIFT))
== 0))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
secondary = tprimary & HUFFMAN_VALUE_MASK;
......@@ -1432,7 +1479,7 @@ elf_zlib_inflate_table (unsigned char *codes, size_t codes_len,
& HUFFMAN_BITS_MASK);
if (unlikely (secondary_bits < j - 8))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
}
......@@ -1448,7 +1495,7 @@ elf_zlib_inflate_table (unsigned char *codes, size_t codes_len,
{
if (unlikely (table[secondary + 0x100 + ind] != 0))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
table[secondary + 0x100 + ind] = tval;
......@@ -1664,28 +1711,28 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
if (unlikely ((pin[0] & 0xf) != 8)) /* 8 is zlib encoding. */
{
/* Unknown compression method. */
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
if (unlikely ((pin[0] >> 4) > 7))
{
/* Window size too large. Other than this check, we don't
care about the window size. */
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
if (unlikely ((pin[1] & 0x20) != 0))
{
/* Stream expects a predefined dictionary, but we have no
dictionary. */
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
val = (pin[0] << 8) | pin[1];
if (unlikely (val % 31 != 0))
{
/* Header check failure. */
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
pin += 2;
......@@ -1722,7 +1769,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
if (unlikely (type == 3))
{
/* Invalid block type. */
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -1745,7 +1792,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
if (unlikely ((pinend - pin) < 4))
{
/* Missing length. */
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
len = pin[0] | (pin[1] << 8);
......@@ -1755,14 +1802,14 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
if (unlikely (len != lenc))
{
/* Corrupt data. */
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
if (unlikely (len > (unsigned int) (pinend - pin)
|| len > (unsigned int) (poutend - pout)))
{
/* Not enough space in buffers. */
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
memcpy (pout, pin, len);
......@@ -1812,7 +1859,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
if (unlikely (nlit > 286 || ndist > 30))
{
/* Values out of range. */
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -1977,7 +2024,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
a secondary table is never necessary. */
if (unlikely ((t & (1U << HUFFMAN_SECONDARY_SHIFT)) != 0))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -1997,7 +2044,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
if (unlikely (plen == plenbase))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -2010,7 +2057,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
bits -= 2;
if (unlikely ((unsigned int) (plenend - plen) < c))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -2045,7 +2092,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
bits -= 3;
if (unlikely ((unsigned int) (plenend - plen) < c))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -2091,7 +2138,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
bits -= 7;
if (unlikely ((unsigned int) (plenend - plen) < c))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -2100,7 +2147,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
}
else
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
}
......@@ -2110,7 +2157,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
plen = plenbase;
if (unlikely (plen[256] == 0))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -2162,7 +2209,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
{
if (unlikely (pout == poutend))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -2191,7 +2238,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
len = 258;
else if (unlikely (lit > 285))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
else
......@@ -2244,13 +2291,13 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
if (unlikely (pout == porigout))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
if (unlikely ((unsigned int) (poutend - pout) < len))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -2259,7 +2306,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
}
else if (unlikely (dist > 29))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
else
......@@ -2290,13 +2337,13 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
if (unlikely ((unsigned int) (pout - porigout) < dist))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
if (unlikely ((unsigned int) (poutend - pout) < len))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -2326,7 +2373,7 @@ elf_zlib_inflate (const unsigned char *pin, size_t sin, uint16_t *zdebug_table,
/* We should have filled the output buffer. */
if (unlikely (pout != poutend))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -2453,7 +2500,7 @@ elf_zlib_verify_checksum (const unsigned char *checkbytes,
if (unlikely ((s2 << 16) + s1 != cksum))
{
elf_zlib_failed ();
elf_uncompress_failed ();
return 0;
}
......@@ -2608,6 +2655,1311 @@ backtrace_uncompress_zdebug (struct backtrace_state *state,
return ret;
}
/* Number of LZMA states. */
#define LZMA_STATES (12)
/* Number of LZMA position states. The pb value of the property byte
is the number of bits to include in these states, and the maximum
value of pb is 4. */
#define LZMA_POS_STATES (16)
/* Number of LZMA distance states. These are used match distances
with a short match length: up to 4 bytes. */
#define LZMA_DIST_STATES (4)
/* Number of LZMA distance slots. LZMA uses six bits to encode larger
match lengths, so 1 << 6 possible probabilities. */
#define LZMA_DIST_SLOTS (64)
/* LZMA distances 0 to 3 are encoded directly, larger values use a
probability model. */
#define LZMA_DIST_MODEL_START (4)
/* The LZMA probability model ends at 14. */
#define LZMA_DIST_MODEL_END (14)
/* LZMA distance slots for distances less than 127. */
#define LZMA_FULL_DISTANCES (128)
/* LZMA uses four alignment bits. */
#define LZMA_ALIGN_SIZE (16)
/* LZMA match length is encoded with 4, 5, or 10 bits, some of which
are already known. */
#define LZMA_LEN_LOW_SYMBOLS (8)
#define LZMA_LEN_MID_SYMBOLS (8)
#define LZMA_LEN_HIGH_SYMBOLS (256)
/* LZMA literal encoding. */
#define LZMA_LITERAL_CODERS_MAX (16)
#define LZMA_LITERAL_CODER_SIZE (0x300)
/* LZMA is based on a large set of probabilities, each managed
independently. Each probability is an 11 bit number that we store
in a uint16_t. We use a single large array of probabilities. */
/* Lengths of entries in the LZMA probabilities array. The names used
here are copied from the Linux kernel implementation. */
#define LZMA_PROB_IS_MATCH_LEN (LZMA_STATES * LZMA_POS_STATES)
#define LZMA_PROB_IS_REP_LEN LZMA_STATES
#define LZMA_PROB_IS_REP0_LEN LZMA_STATES
#define LZMA_PROB_IS_REP1_LEN LZMA_STATES
#define LZMA_PROB_IS_REP2_LEN LZMA_STATES
#define LZMA_PROB_IS_REP0_LONG_LEN (LZMA_STATES * LZMA_POS_STATES)
#define LZMA_PROB_DIST_SLOT_LEN (LZMA_DIST_STATES * LZMA_DIST_SLOTS)
#define LZMA_PROB_DIST_SPECIAL_LEN (LZMA_FULL_DISTANCES - LZMA_DIST_MODEL_END)
#define LZMA_PROB_DIST_ALIGN_LEN LZMA_ALIGN_SIZE
#define LZMA_PROB_MATCH_LEN_CHOICE_LEN 1
#define LZMA_PROB_MATCH_LEN_CHOICE2_LEN 1
#define LZMA_PROB_MATCH_LEN_LOW_LEN (LZMA_POS_STATES * LZMA_LEN_LOW_SYMBOLS)
#define LZMA_PROB_MATCH_LEN_MID_LEN (LZMA_POS_STATES * LZMA_LEN_MID_SYMBOLS)
#define LZMA_PROB_MATCH_LEN_HIGH_LEN LZMA_LEN_HIGH_SYMBOLS
#define LZMA_PROB_REP_LEN_CHOICE_LEN 1
#define LZMA_PROB_REP_LEN_CHOICE2_LEN 1
#define LZMA_PROB_REP_LEN_LOW_LEN (LZMA_POS_STATES * LZMA_LEN_LOW_SYMBOLS)
#define LZMA_PROB_REP_LEN_MID_LEN (LZMA_POS_STATES * LZMA_LEN_MID_SYMBOLS)
#define LZMA_PROB_REP_LEN_HIGH_LEN LZMA_LEN_HIGH_SYMBOLS
#define LZMA_PROB_LITERAL_LEN \
(LZMA_LITERAL_CODERS_MAX * LZMA_LITERAL_CODER_SIZE)
/* Offsets into the LZMA probabilities array. This is mechanically
generated from the above lengths. */
#define LZMA_PROB_IS_MATCH_OFFSET 0
#define LZMA_PROB_IS_REP_OFFSET \
(LZMA_PROB_IS_MATCH_OFFSET + LZMA_PROB_IS_MATCH_LEN)
#define LZMA_PROB_IS_REP0_OFFSET \
(LZMA_PROB_IS_REP_OFFSET + LZMA_PROB_IS_REP_LEN)
#define LZMA_PROB_IS_REP1_OFFSET \
(LZMA_PROB_IS_REP0_OFFSET + LZMA_PROB_IS_REP0_LEN)
#define LZMA_PROB_IS_REP2_OFFSET \
(LZMA_PROB_IS_REP1_OFFSET + LZMA_PROB_IS_REP1_LEN)
#define LZMA_PROB_IS_REP0_LONG_OFFSET \
(LZMA_PROB_IS_REP2_OFFSET + LZMA_PROB_IS_REP2_LEN)
#define LZMA_PROB_DIST_SLOT_OFFSET \
(LZMA_PROB_IS_REP0_LONG_OFFSET + LZMA_PROB_IS_REP0_LONG_LEN)
#define LZMA_PROB_DIST_SPECIAL_OFFSET \
(LZMA_PROB_DIST_SLOT_OFFSET + LZMA_PROB_DIST_SLOT_LEN)
#define LZMA_PROB_DIST_ALIGN_OFFSET \
(LZMA_PROB_DIST_SPECIAL_OFFSET + LZMA_PROB_DIST_SPECIAL_LEN)
#define LZMA_PROB_MATCH_LEN_CHOICE_OFFSET \
(LZMA_PROB_DIST_ALIGN_OFFSET + LZMA_PROB_DIST_ALIGN_LEN)
#define LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET \
(LZMA_PROB_MATCH_LEN_CHOICE_OFFSET + LZMA_PROB_MATCH_LEN_CHOICE_LEN)
#define LZMA_PROB_MATCH_LEN_LOW_OFFSET \
(LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET + LZMA_PROB_MATCH_LEN_CHOICE2_LEN)
#define LZMA_PROB_MATCH_LEN_MID_OFFSET \
(LZMA_PROB_MATCH_LEN_LOW_OFFSET + LZMA_PROB_MATCH_LEN_LOW_LEN)
#define LZMA_PROB_MATCH_LEN_HIGH_OFFSET \
(LZMA_PROB_MATCH_LEN_MID_OFFSET + LZMA_PROB_MATCH_LEN_MID_LEN)
#define LZMA_PROB_REP_LEN_CHOICE_OFFSET \
(LZMA_PROB_MATCH_LEN_HIGH_OFFSET + LZMA_PROB_MATCH_LEN_HIGH_LEN)
#define LZMA_PROB_REP_LEN_CHOICE2_OFFSET \
(LZMA_PROB_REP_LEN_CHOICE_OFFSET + LZMA_PROB_REP_LEN_CHOICE_LEN)
#define LZMA_PROB_REP_LEN_LOW_OFFSET \
(LZMA_PROB_REP_LEN_CHOICE2_OFFSET + LZMA_PROB_REP_LEN_CHOICE2_LEN)
#define LZMA_PROB_REP_LEN_MID_OFFSET \
(LZMA_PROB_REP_LEN_LOW_OFFSET + LZMA_PROB_REP_LEN_LOW_LEN)
#define LZMA_PROB_REP_LEN_HIGH_OFFSET \
(LZMA_PROB_REP_LEN_MID_OFFSET + LZMA_PROB_REP_LEN_MID_LEN)
#define LZMA_PROB_LITERAL_OFFSET \
(LZMA_PROB_REP_LEN_HIGH_OFFSET + LZMA_PROB_REP_LEN_HIGH_LEN)
#define LZMA_PROB_TOTAL_COUNT \
(LZMA_PROB_LITERAL_OFFSET + LZMA_PROB_LITERAL_LEN)
/* Check that the number of LZMA probabilities is the same as the
Linux kernel implementation. */
#if LZMA_PROB_TOTAL_COUNT != 1846 + (1 << 4) * 0x300
#error Wrong number of LZMA probabilities
#endif
/* Expressions for the offset in the LZMA probabilities array of a
specific probability. */
#define LZMA_IS_MATCH(state, pos) \
(LZMA_PROB_IS_MATCH_OFFSET + (state) * LZMA_POS_STATES + (pos))
#define LZMA_IS_REP(state) \
(LZMA_PROB_IS_REP_OFFSET + (state))
#define LZMA_IS_REP0(state) \
(LZMA_PROB_IS_REP0_OFFSET + (state))
#define LZMA_IS_REP1(state) \
(LZMA_PROB_IS_REP1_OFFSET + (state))
#define LZMA_IS_REP2(state) \
(LZMA_PROB_IS_REP2_OFFSET + (state))
#define LZMA_IS_REP0_LONG(state, pos) \
(LZMA_PROB_IS_REP0_LONG_OFFSET + (state) * LZMA_POS_STATES + (pos))
#define LZMA_DIST_SLOT(dist, slot) \
(LZMA_PROB_DIST_SLOT_OFFSET + (dist) * LZMA_DIST_SLOTS + (slot))
#define LZMA_DIST_SPECIAL(dist) \
(LZMA_PROB_DIST_SPECIAL_OFFSET + (dist))
#define LZMA_DIST_ALIGN(dist) \
(LZMA_PROB_DIST_ALIGN_OFFSET + (dist))
#define LZMA_MATCH_LEN_CHOICE \
LZMA_PROB_MATCH_LEN_CHOICE_OFFSET
#define LZMA_MATCH_LEN_CHOICE2 \
LZMA_PROB_MATCH_LEN_CHOICE2_OFFSET
#define LZMA_MATCH_LEN_LOW(pos, sym) \
(LZMA_PROB_MATCH_LEN_LOW_OFFSET + (pos) * LZMA_LEN_LOW_SYMBOLS + (sym))
#define LZMA_MATCH_LEN_MID(pos, sym) \
(LZMA_PROB_MATCH_LEN_MID_OFFSET + (pos) * LZMA_LEN_MID_SYMBOLS + (sym))
#define LZMA_MATCH_LEN_HIGH(sym) \
(LZMA_PROB_MATCH_LEN_HIGH_OFFSET + (sym))
#define LZMA_REP_LEN_CHOICE \
LZMA_PROB_REP_LEN_CHOICE_OFFSET
#define LZMA_REP_LEN_CHOICE2 \
LZMA_PROB_REP_LEN_CHOICE2_OFFSET
#define LZMA_REP_LEN_LOW(pos, sym) \
(LZMA_PROB_REP_LEN_LOW_OFFSET + (pos) * LZMA_LEN_LOW_SYMBOLS + (sym))
#define LZMA_REP_LEN_MID(pos, sym) \
(LZMA_PROB_REP_LEN_MID_OFFSET + (pos) * LZMA_LEN_MID_SYMBOLS + (sym))
#define LZMA_REP_LEN_HIGH(sym) \
(LZMA_PROB_REP_LEN_HIGH_OFFSET + (sym))
#define LZMA_LITERAL(code, size) \
(LZMA_PROB_LITERAL_OFFSET + (code) * LZMA_LITERAL_CODER_SIZE + (size))
/* Read an LZMA varint from BUF, reading and updating *POFFSET,
setting *VAL. Returns 0 on error, 1 on success. */
static int
elf_lzma_varint (const unsigned char *compressed, size_t compressed_size,
size_t *poffset, uint64_t *val)
{
size_t off;
int i;
uint64_t v;
unsigned char b;
off = *poffset;
i = 0;
v = 0;
while (1)
{
if (unlikely (off >= compressed_size))
{
elf_uncompress_failed ();
return 0;
}
b = compressed[off];
v |= (b & 0x7f) << (i * 7);
++off;
if ((b & 0x80) == 0)
{
*poffset = off;
*val = v;
return 1;
}
++i;
if (unlikely (i >= 9))
{
elf_uncompress_failed ();
return 0;
}
}
}
/* Normalize the LZMA range decoder, pulling in an extra input byte if
needed. */
static void
elf_lzma_range_normalize (const unsigned char *compressed,
size_t compressed_size, size_t *poffset,
uint32_t *prange, uint32_t *pcode)
{
if (*prange < (1U << 24))
{
if (unlikely (*poffset >= compressed_size))
{
/* We assume this will be caught elsewhere. */
elf_uncompress_failed ();
return;
}
*prange <<= 8;
*pcode <<= 8;
*pcode += compressed[*poffset];
++*poffset;
}
}
/* Read and return a single bit from the LZMA stream, reading and
updating *PROB. Each bit comes from the range coder. */
static int
elf_lzma_bit (const unsigned char *compressed, size_t compressed_size,
uint16_t *prob, size_t *poffset, uint32_t *prange,
uint32_t *pcode)
{
uint32_t bound;
elf_lzma_range_normalize (compressed, compressed_size, poffset,
prange, pcode);
bound = (*prange >> 11) * (uint32_t) *prob;
if (*pcode < bound)
{
*prange = bound;
*prob += ((1U << 11) - *prob) >> 5;
return 0;
}
else
{
*prange -= bound;
*pcode -= bound;
*prob -= *prob >> 5;
return 1;
}
}
/* Read an integer of size BITS from the LZMA stream, most significant
bit first. The bits are predicted using PROBS. */
static uint32_t
elf_lzma_integer (const unsigned char *compressed, size_t compressed_size,
uint16_t *probs, uint32_t bits, size_t *poffset,
uint32_t *prange, uint32_t *pcode)
{
uint32_t sym;
uint32_t i;
sym = 1;
for (i = 0; i < bits; i++)
{
int bit;
bit = elf_lzma_bit (compressed, compressed_size, probs + sym, poffset,
prange, pcode);
sym <<= 1;
sym += bit;
}
return sym - (1 << bits);
}
/* Read an integer of size BITS from the LZMA stream, least
significant bit first. The bits are predicted using PROBS. */
static uint32_t
elf_lzma_reverse_integer (const unsigned char *compressed,
size_t compressed_size, uint16_t *probs,
uint32_t bits, size_t *poffset, uint32_t *prange,
uint32_t *pcode)
{
uint32_t sym;
uint32_t val;
uint32_t i;
sym = 1;
val = 0;
for (i = 0; i < bits; i++)
{
int bit;
bit = elf_lzma_bit (compressed, compressed_size, probs + sym, poffset,
prange, pcode);
sym <<= 1;
sym += bit;
val += bit << i;
}
return val;
}
/* Read a length from the LZMA stream. IS_REP picks either LZMA_MATCH
or LZMA_REP probabilities. */
static uint32_t
elf_lzma_len (const unsigned char *compressed, size_t compressed_size,
uint16_t *probs, int is_rep, unsigned int pos_state,
size_t *poffset, uint32_t *prange, uint32_t *pcode)
{
uint16_t *probs_choice;
uint16_t *probs_sym;
uint32_t bits;
uint32_t len;
probs_choice = probs + (is_rep
? LZMA_REP_LEN_CHOICE
: LZMA_MATCH_LEN_CHOICE);
if (elf_lzma_bit (compressed, compressed_size, probs_choice, poffset,
prange, pcode))
{
probs_choice = probs + (is_rep
? LZMA_REP_LEN_CHOICE2
: LZMA_MATCH_LEN_CHOICE2);
if (elf_lzma_bit (compressed, compressed_size, probs_choice,
poffset, prange, pcode))
{
probs_sym = probs + (is_rep
? LZMA_REP_LEN_HIGH (0)
: LZMA_MATCH_LEN_HIGH (0));
bits = 8;
len = 2 + 8 + 8;
}
else
{
probs_sym = probs + (is_rep
? LZMA_REP_LEN_MID (pos_state, 0)
: LZMA_MATCH_LEN_MID (pos_state, 0));
bits = 3;
len = 2 + 8;
}
}
else
{
probs_sym = probs + (is_rep
? LZMA_REP_LEN_LOW (pos_state, 0)
: LZMA_MATCH_LEN_LOW (pos_state, 0));
bits = 3;
len = 2;
}
len += elf_lzma_integer (compressed, compressed_size, probs_sym, bits,
poffset, prange, pcode);
return len;
}
/* Uncompress one LZMA block from a minidebug file. The compressed
data is at COMPRESSED + *POFFSET. Update *POFFSET. Store the data
into the memory at UNCOMPRESSED, size UNCOMPRESSED_SIZE. CHECK is
the stream flag from the xz header. Return 1 on successful
decompression. */
static int
elf_uncompress_lzma_block (const unsigned char *compressed,
size_t compressed_size, unsigned char check,
uint16_t *probs, unsigned char *uncompressed,
size_t uncompressed_size, size_t *poffset)
{
size_t off;
size_t block_header_offset;
size_t block_header_size;
unsigned char block_flags;
uint64_t header_compressed_size;
uint64_t header_uncompressed_size;
unsigned char lzma2_properties;
uint32_t computed_crc;
uint32_t stream_crc;
size_t uncompressed_offset;
size_t dict_start_offset;
unsigned int lc;
unsigned int lp;
unsigned int pb;
uint32_t range;
uint32_t code;
uint32_t lstate;
uint32_t dist[4];
off = *poffset;
block_header_offset = off;
/* Block header size is a single byte. */
if (unlikely (off >= compressed_size))
{
elf_uncompress_failed ();
return 0;
}
block_header_size = (compressed[off] + 1) * 4;
if (unlikely (off + block_header_size > compressed_size))
{
elf_uncompress_failed ();
return 0;
}
/* Block flags. */
block_flags = compressed[off + 1];
if (unlikely ((block_flags & 0x3c) != 0))
{
elf_uncompress_failed ();
return 0;
}
off += 2;
/* Optional compressed size. */
header_compressed_size = 0;
if ((block_flags & 0x40) != 0)
{
*poffset = off;
if (!elf_lzma_varint (compressed, compressed_size, poffset,
&header_compressed_size))
return 0;
off = *poffset;
}
/* Optional uncompressed size. */
header_uncompressed_size = 0;
if ((block_flags & 0x80) != 0)
{
*poffset = off;
if (!elf_lzma_varint (compressed, compressed_size, poffset,
&header_uncompressed_size))
return 0;
off = *poffset;
}
/* The recipe for creating a minidebug file is to run the xz program
with no arguments, so we expect exactly one filter: lzma2. */
if (unlikely ((block_flags & 0x3) != 0))
{
elf_uncompress_failed ();
return 0;
}
if (unlikely (off + 2 >= block_header_offset + block_header_size))
{
elf_uncompress_failed ();
return 0;
}
/* The filter ID for LZMA2 is 0x21. */
if (unlikely (compressed[off] != 0x21))
{
elf_uncompress_failed ();
return 0;
}
++off;
/* The size of the filter properties for LZMA2 is 1. */
if (unlikely (compressed[off] != 1))
{
elf_uncompress_failed ();
return 0;
}
++off;
lzma2_properties = compressed[off];
++off;
if (unlikely (lzma2_properties > 40))
{
elf_uncompress_failed ();
return 0;
}
/* The properties describe the dictionary size, but we don't care
what that is. */
/* Block header padding. */
if (unlikely (off + 4 > compressed_size))
{
elf_uncompress_failed ();
return 0;
}
off = (off + 3) &~ (size_t) 3;
if (unlikely (off + 4 > compressed_size))
{
elf_uncompress_failed ();
return 0;
}
/* Block header CRC. */
computed_crc = elf_crc32 (0, compressed + block_header_offset,
block_header_size - 4);
stream_crc = (compressed[off]
| (compressed[off + 1] << 8)
| (compressed[off + 2] << 16)
| (compressed[off + 3] << 24));
if (unlikely (computed_crc != stream_crc))
{
elf_uncompress_failed ();
return 0;
}
off += 4;
/* Read a sequence of LZMA2 packets. */
uncompressed_offset = 0;
dict_start_offset = 0;
lc = 0;
lp = 0;
pb = 0;
lstate = 0;
while (off < compressed_size)
{
unsigned char control;
range = 0xffffffff;
code = 0;
control = compressed[off];
++off;
if (unlikely (control == 0))
{
/* End of packets. */
break;
}
if (control == 1 || control >= 0xe0)
{
/* Reset dictionary to empty. */
dict_start_offset = uncompressed_offset;
}
if (control < 0x80)
{
size_t chunk_size;
/* The only valid values here are 1 or 2. A 1 means to
reset the dictionary (done above). Then we see an
uncompressed chunk. */
if (unlikely (control > 2))
{
elf_uncompress_failed ();
return 0;
}
/* An uncompressed chunk is a two byte size followed by
data. */
if (unlikely (off + 2 > compressed_size))
{
elf_uncompress_failed ();
return 0;
}
chunk_size = compressed[off] << 8;
chunk_size += compressed[off + 1];
++chunk_size;
off += 2;
if (unlikely (off + chunk_size > compressed_size))
{
elf_uncompress_failed ();
return 0;
}
if (unlikely (uncompressed_offset + chunk_size > uncompressed_size))
{
elf_uncompress_failed ();
return 0;
}
memcpy (uncompressed + uncompressed_offset, compressed + off,
chunk_size);
uncompressed_offset += chunk_size;
off += chunk_size;
}
else
{
size_t uncompressed_chunk_start;
size_t uncompressed_chunk_size;
size_t compressed_chunk_size;
size_t limit;
/* An LZMA chunk. This starts with an uncompressed size and
a compressed size. */
if (unlikely (off + 4 >= compressed_size))
{
elf_uncompress_failed ();
return 0;
}
uncompressed_chunk_start = uncompressed_offset;
uncompressed_chunk_size = (control & 0x1f) << 16;
uncompressed_chunk_size += compressed[off] << 8;
uncompressed_chunk_size += compressed[off + 1];
++uncompressed_chunk_size;
compressed_chunk_size = compressed[off + 2] << 8;
compressed_chunk_size += compressed[off + 3];
++compressed_chunk_size;
off += 4;
/* Bit 7 (0x80) is set.
Bits 6 and 5 (0x40 and 0x20) are as follows:
0: don't reset anything
1: reset state
2: reset state, read properties
3: reset state, read properties, reset dictionary (done above) */
if (control >= 0xc0)
{
unsigned char props;
/* Bit 6 is set, read properties. */
if (unlikely (off >= compressed_size))
{
elf_uncompress_failed ();
return 0;
}
props = compressed[off];
++off;
if (unlikely (props > (4 * 5 + 4) * 9 + 8))
{
elf_uncompress_failed ();
return 0;
}
pb = 0;
while (props >= 9 * 5)
{
props -= 9 * 5;
++pb;
}
lp = 0;
while (props > 9)
{
props -= 9;
++lp;
}
lc = props;
if (unlikely (lc + lp > 4))
{
elf_uncompress_failed ();
return 0;
}
}
if (control >= 0xa0)
{
size_t i;
/* Bit 5 or 6 is set, reset LZMA state. */
lstate = 0;
memset (&dist, 0, sizeof dist);
for (i = 0; i < LZMA_PROB_TOTAL_COUNT; i++)
probs[i] = 1 << 10;
range = 0xffffffff;
code = 0;
}
/* Read the range code. */
if (unlikely (off + 5 > compressed_size))
{
elf_uncompress_failed ();
return 0;
}
/* The byte at compressed[off] is ignored for some
reason. */
code = ((compressed[off + 1] << 24)
+ (compressed[off + 2] << 16)
+ (compressed[off + 3] << 8)
+ compressed[off + 4]);
off += 5;
/* This is the main LZMA decode loop. */
limit = off + compressed_chunk_size;
*poffset = off;
while (*poffset < limit)
{
unsigned int pos_state;
if (unlikely (uncompressed_offset
== (uncompressed_chunk_start
+ uncompressed_chunk_size)))
{
/* We've decompressed all the expected bytes. */
break;
}
pos_state = ((uncompressed_offset - dict_start_offset)
& ((1 << pb) - 1));
if (elf_lzma_bit (compressed, compressed_size,
probs + LZMA_IS_MATCH (lstate, pos_state),
poffset, &range, &code))
{
uint32_t len;
if (elf_lzma_bit (compressed, compressed_size,
probs + LZMA_IS_REP (lstate),
poffset, &range, &code))
{
int short_rep;
uint32_t next_dist;
/* Repeated match. */
short_rep = 0;
if (elf_lzma_bit (compressed, compressed_size,
probs + LZMA_IS_REP0 (lstate),
poffset, &range, &code))
{
if (elf_lzma_bit (compressed, compressed_size,
probs + LZMA_IS_REP1 (lstate),
poffset, &range, &code))
{
if (elf_lzma_bit (compressed, compressed_size,
probs + LZMA_IS_REP2 (lstate),
poffset, &range, &code))
{
next_dist = dist[3];
dist[3] = dist[2];
}
else
{
next_dist = dist[2];
}
dist[2] = dist[1];
}
else
{
next_dist = dist[1];
}
dist[1] = dist[0];
dist[0] = next_dist;
}
else
{
if (!elf_lzma_bit (compressed, compressed_size,
(probs
+ LZMA_IS_REP0_LONG (lstate,
pos_state)),
poffset, &range, &code))
short_rep = 1;
}
if (lstate < 7)
lstate = short_rep ? 9 : 8;
else
lstate = 11;
if (short_rep)
len = 1;
else
len = elf_lzma_len (compressed, compressed_size,
probs, 1, pos_state, poffset,
&range, &code);
}
else
{
uint32_t dist_state;
uint32_t dist_slot;
uint16_t *probs_dist;
/* Match. */
if (lstate < 7)
lstate = 7;
else
lstate = 10;
dist[3] = dist[2];
dist[2] = dist[1];
dist[1] = dist[0];
len = elf_lzma_len (compressed, compressed_size,
probs, 0, pos_state, poffset,
&range, &code);
if (len < 4 + 2)
dist_state = len - 2;
else
dist_state = 3;
probs_dist = probs + LZMA_DIST_SLOT (dist_state, 0);
dist_slot = elf_lzma_integer (compressed,
compressed_size,
probs_dist, 6,
poffset, &range,
&code);
if (dist_slot < LZMA_DIST_MODEL_START)
dist[0] = dist_slot;
else
{
uint32_t limit;
limit = (dist_slot >> 1) - 1;
dist[0] = 2 + (dist_slot & 1);
if (dist_slot < LZMA_DIST_MODEL_END)
{
dist[0] <<= limit;
probs_dist = (probs
+ LZMA_DIST_SPECIAL(dist[0]
- dist_slot
- 1));
dist[0] +=
elf_lzma_reverse_integer (compressed,
compressed_size,
probs_dist,
limit, poffset,
&range, &code);
}
else
{
uint32_t dist0;
uint32_t i;
dist0 = dist[0];
for (i = 0; i < limit - 4; i++)
{
uint32_t mask;
elf_lzma_range_normalize (compressed,
compressed_size,
poffset,
&range, &code);
range >>= 1;
code -= range;
mask = -(code >> 31);
code += range & mask;
dist0 <<= 1;
dist0 += mask + 1;
}
dist0 <<= 4;
probs_dist = probs + LZMA_DIST_ALIGN (0);
dist0 +=
elf_lzma_reverse_integer (compressed,
compressed_size,
probs_dist, 4,
poffset,
&range, &code);
dist[0] = dist0;
}
}
}
if (unlikely (uncompressed_offset
- dict_start_offset < dist[0] + 1))
{
elf_uncompress_failed ();
return 0;
}
if (unlikely (uncompressed_offset + len > uncompressed_size))
{
elf_uncompress_failed ();
return 0;
}
if (dist[0] == 0)
{
/* A common case, meaning repeat the last
character LEN times. */
memset (uncompressed + uncompressed_offset,
uncompressed[uncompressed_offset - 1],
len);
uncompressed_offset += len;
}
else if (dist[0] + 1 >= len)
{
memcpy (uncompressed + uncompressed_offset,
uncompressed + uncompressed_offset - dist[0] - 1,
len);
uncompressed_offset += len;
}
else
{
while (len > 0)
{
uint32_t copy;
copy = len < dist[0] + 1 ? len : dist[0] + 1;
memcpy (uncompressed + uncompressed_offset,
(uncompressed + uncompressed_offset
- dist[0] - 1),
copy);
len -= copy;
uncompressed_offset += copy;
}
}
}
else
{
unsigned char prev;
unsigned char low;
size_t high;
uint16_t *lit_probs;
unsigned int sym;
/* Literal value. */
if (uncompressed_offset > 0)
prev = uncompressed[uncompressed_offset - 1];
else
prev = 0;
low = prev >> (8 - lc);
high = (((uncompressed_offset - dict_start_offset)
& ((1 << lp) - 1))
<< lc);
lit_probs = probs + LZMA_LITERAL (low + high, 0);
if (lstate < 7)
sym = elf_lzma_integer (compressed, compressed_size,
lit_probs, 8, poffset, &range,
&code);
else
{
unsigned int match;
unsigned int bit;
unsigned int match_bit;
unsigned int idx;
sym = 1;
if (uncompressed_offset >= dist[0] + 1)
match = uncompressed[uncompressed_offset - dist[0] - 1];
else
match = 0;
match <<= 1;
bit = 0x100;
do
{
match_bit = match & bit;
match <<= 1;
idx = bit + match_bit + sym;
sym <<= 1;
if (elf_lzma_bit (compressed, compressed_size,
lit_probs + idx, poffset,
&range, &code))
{
++sym;
bit &= match_bit;
}
else
{
bit &= ~ match_bit;
}
}
while (sym < 0x100);
}
if (unlikely (uncompressed_offset >= uncompressed_size))
{
elf_uncompress_failed ();
return 0;
}
uncompressed[uncompressed_offset] = (unsigned char) sym;
++uncompressed_offset;
if (lstate <= 3)
lstate = 0;
else if (lstate <= 9)
lstate -= 3;
else
lstate -= 6;
}
}
elf_lzma_range_normalize (compressed, compressed_size, poffset,
&range, &code);
off = *poffset;
}
}
/* We have reached the end of the block. Pad to four byte
boundary. */
off = (off + 3) &~ (size_t) 3;
if (unlikely (off > compressed_size))
{
elf_uncompress_failed ();
return 0;
}
switch (check)
{
case 0:
/* No check. */
break;
case 1:
/* CRC32 */
if (unlikely (off + 4 > compressed_size))
{
elf_uncompress_failed ();
return 0;
}
computed_crc = elf_crc32 (0, uncompressed, uncompressed_offset);
stream_crc = (compressed[off]
| (compressed[off + 1] << 8)
| (compressed[off + 2] << 16)
| (compressed[off + 3] << 24));
if (computed_crc != stream_crc)
{
elf_uncompress_failed ();
return 0;
}
off += 4;
break;
case 4:
/* CRC64. We don't bother computing a CRC64 checksum. */
if (unlikely (off + 8 > compressed_size))
{
elf_uncompress_failed ();
return 0;
}
off += 8;
break;
case 10:
/* SHA. We don't bother computing a SHA checksum. */
if (unlikely (off + 32 > compressed_size))
{
elf_uncompress_failed ();
return 0;
}
off += 32;
break;
default:
elf_uncompress_failed ();
return 0;
}
*poffset = off;
return 1;
}
/* Uncompress LZMA data found in a minidebug file. The minidebug
format is described at
https://sourceware.org/gdb/current/onlinedocs/gdb/MiniDebugInfo.html.
Returns 0 on error, 1 on successful decompression. For this
function we return 0 on failure to decompress, as the calling code
will carry on in that case. */
static int
elf_uncompress_lzma (struct backtrace_state *state,
const unsigned char *compressed, size_t compressed_size,
backtrace_error_callback error_callback, void *data,
unsigned char **uncompressed, size_t *uncompressed_size)
{
size_t header_size;
size_t footer_size;
unsigned char check;
uint32_t computed_crc;
uint32_t stream_crc;
size_t offset;
size_t index_size;
size_t footer_offset;
size_t index_offset;
uint64_t index_compressed_size;
uint64_t index_uncompressed_size;
unsigned char *mem;
uint16_t *probs;
size_t compressed_block_size;
/* The format starts with a stream header and ends with a stream
footer. */
header_size = 12;
footer_size = 12;
if (unlikely (compressed_size < header_size + footer_size))
{
elf_uncompress_failed ();
return 0;
}
/* The stream header starts with a magic string. */
if (unlikely (memcmp (compressed, "\375" "7zXZ\0", 6) != 0))
{
elf_uncompress_failed ();
return 0;
}
/* Next come stream flags. The first byte is zero, the second byte
is the check. */
if (unlikely (compressed[6] != 0))
{
elf_uncompress_failed ();
return 0;
}
check = compressed[7];
if (unlikely ((check & 0xf8) != 0))
{
elf_uncompress_failed ();
return 0;
}
/* Next comes a CRC of the stream flags. */
computed_crc = elf_crc32 (0, compressed + 6, 2);
stream_crc = (compressed[8]
| (compressed[9] << 8)
| (compressed[10] << 16)
| (compressed[11] << 24));
if (unlikely (computed_crc != stream_crc))
{
elf_uncompress_failed ();
return 0;
}
/* Now that we've parsed the header, parse the footer, so that we
can get the uncompressed size. */
/* The footer ends with two magic bytes. */
offset = compressed_size;
if (unlikely (memcmp (compressed + offset - 2, "YZ", 2) != 0))
{
elf_uncompress_failed ();
return 0;
}
offset -= 2;
/* Before that are the stream flags, which should be the same as the
flags in the header. */
if (unlikely (compressed[offset - 2] != 0
|| compressed[offset - 1] != check))
{
elf_uncompress_failed ();
return 0;
}
offset -= 2;
/* Before that is the size of the index field, which precedes the
footer. */
index_size = (compressed[offset - 4]
| (compressed[offset - 3] << 8)
| (compressed[offset - 2] << 16)
| (compressed[offset - 1] << 24));
index_size = (index_size + 1) * 4;
offset -= 4;
/* Before that is a footer CRC. */
computed_crc = elf_crc32 (0, compressed + offset, 6);
stream_crc = (compressed[offset - 4]
| (compressed[offset - 3] << 8)
| (compressed[offset - 2] << 16)
| (compressed[offset - 1] << 24));
if (unlikely (computed_crc != stream_crc))
{
elf_uncompress_failed ();
return 0;
}
offset -= 4;
/* The index comes just before the footer. */
if (unlikely (offset < index_size + header_size))
{
elf_uncompress_failed ();
return 0;
}
footer_offset = offset;
offset -= index_size;
index_offset = offset;
/* The index starts with a zero byte. */
if (unlikely (compressed[offset] != 0))
{
elf_uncompress_failed ();
return 0;
}
++offset;
/* Next is the number of blocks. We expect zero blocks for an empty
stream, and otherwise a single block. */
if (unlikely (compressed[offset] == 0))
{
*uncompressed = NULL;
*uncompressed_size = 0;
return 1;
}
if (unlikely (compressed[offset] != 1))
{
elf_uncompress_failed ();
return 0;
}
++offset;
/* Next is the compressed size and the uncompressed size. */
if (!elf_lzma_varint (compressed, compressed_size, &offset,
&index_compressed_size))
return 0;
if (!elf_lzma_varint (compressed, compressed_size, &offset,
&index_uncompressed_size))
return 0;
/* Pad to a four byte boundary. */
offset = (offset + 3) &~ (size_t) 3;
/* Next is a CRC of the index. */
computed_crc = elf_crc32 (0, compressed + index_offset,
offset - index_offset);
stream_crc = (compressed[offset]
| (compressed[offset + 1] << 8)
| (compressed[offset + 2] << 16)
| (compressed[offset + 3] << 24));
if (unlikely (computed_crc != stream_crc))
{
elf_uncompress_failed ();
return 0;
}
offset += 4;
/* We should now be back at the footer. */
if (unlikely (offset != footer_offset))
{
elf_uncompress_failed ();
return 0;
}
/* Allocate space to hold the uncompressed data. If we succeed in
uncompressing the LZMA data, we never free this memory. */
mem = (unsigned char *) backtrace_alloc (state, index_uncompressed_size,
error_callback, data);
if (unlikely (mem == NULL))
return 0;
*uncompressed = mem;
*uncompressed_size = index_uncompressed_size;
/* Allocate space for probabilities. */
probs = ((uint16_t *)
backtrace_alloc (state,
LZMA_PROB_TOTAL_COUNT * sizeof (uint16_t),
error_callback, data));
if (unlikely (probs == NULL))
{
backtrace_free (state, mem, index_uncompressed_size, error_callback,
data);
return 0;
}
/* Uncompress the block, which follows the header. */
offset = 12;
if (!elf_uncompress_lzma_block (compressed, compressed_size, check, probs,
mem, index_uncompressed_size, &offset))
{
backtrace_free (state, mem, index_uncompressed_size, error_callback,
data);
return 0;
}
compressed_block_size = offset - 12;
if (unlikely (compressed_block_size
!= ((index_compressed_size + 3) &~ (size_t) 3)))
{
elf_uncompress_failed ();
backtrace_free (state, mem, index_uncompressed_size, error_callback,
data);
return 0;
}
offset = (offset + 3) &~ (size_t) 3;
if (unlikely (offset != index_offset))
{
elf_uncompress_failed ();
backtrace_free (state, mem, index_uncompressed_size, error_callback,
data);
return 0;
}
return 1;
}
/* This function is a hook for testing the LZMA support. It is only
used by tests. */
int
backtrace_uncompress_lzma (struct backtrace_state *state,
const unsigned char *compressed,
size_t compressed_size,
backtrace_error_callback error_callback,
void *data, unsigned char **uncompressed,
size_t *uncompressed_size)
{
return elf_uncompress_lzma (state, compressed, compressed_size,
error_callback, data, uncompressed,
uncompressed_size);
}
/* Add the backtrace data for one ELF file. Returns 1 on success,
0 on failure (in both cases descriptor is closed) or -1 if exe
is non-zero and the ELF file is ET_DYN, which tells the caller that
......@@ -2616,23 +3968,24 @@ backtrace_uncompress_zdebug (struct backtrace_state *state,
static int
elf_add (struct backtrace_state *state, const char *filename, int descriptor,
const unsigned char *memory, size_t memory_size,
uintptr_t base_address, backtrace_error_callback error_callback,
void *data, fileline *fileline_fn, int *found_sym, int *found_dwarf,
struct dwarf_data **fileline_entry, int exe, int debuginfo,
const char *with_buildid_data, uint32_t with_buildid_size)
{
struct backtrace_view ehdr_view;
struct elf_view ehdr_view;
b_elf_ehdr ehdr;
off_t shoff;
unsigned int shnum;
unsigned int shstrndx;
struct backtrace_view shdrs_view;
struct elf_view shdrs_view;
int shdrs_view_valid;
const b_elf_shdr *shdrs;
const b_elf_shdr *shstrhdr;
size_t shstr_size;
off_t shstr_off;
struct backtrace_view names_view;
struct elf_view names_view;
int names_view_valid;
const char *names;
unsigned int symtab_shndx;
......@@ -2640,31 +3993,36 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
unsigned int i;
struct debug_section_info sections[DEBUG_MAX];
struct debug_section_info zsections[DEBUG_MAX];
struct backtrace_view symtab_view;
struct elf_view symtab_view;
int symtab_view_valid;
struct backtrace_view strtab_view;
struct elf_view strtab_view;
int strtab_view_valid;
struct backtrace_view buildid_view;
struct elf_view buildid_view;
int buildid_view_valid;
const char *buildid_data;
uint32_t buildid_size;
struct backtrace_view debuglink_view;
struct elf_view debuglink_view;
int debuglink_view_valid;
const char *debuglink_name;
uint32_t debuglink_crc;
struct backtrace_view debugaltlink_view;
struct elf_view debugaltlink_view;
int debugaltlink_view_valid;
const char *debugaltlink_name;
const char *debugaltlink_buildid_data;
uint32_t debugaltlink_buildid_size;
struct elf_view gnu_debugdata_view;
int gnu_debugdata_view_valid;
size_t gnu_debugdata_size;
unsigned char *gnu_debugdata_uncompressed;
size_t gnu_debugdata_uncompressed_size;
off_t min_offset;
off_t max_offset;
off_t debug_size;
struct backtrace_view debug_view;
struct elf_view debug_view;
int debug_view_valid;
unsigned int using_debug_view;
uint16_t *zdebug_table;
struct backtrace_view split_debug_view[DEBUG_MAX];
struct elf_view split_debug_view[DEBUG_MAX];
unsigned char split_debug_view_valid[DEBUG_MAX];
struct elf_ppc64_opd_data opd_data, *opd;
struct dwarf_sections dwarf_sections;
......@@ -2689,17 +4047,19 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
debugaltlink_name = NULL;
debugaltlink_buildid_data = NULL;
debugaltlink_buildid_size = 0;
gnu_debugdata_view_valid = 0;
gnu_debugdata_size = 0;
debug_view_valid = 0;
memset (&split_debug_view_valid[0], 0, sizeof split_debug_view_valid);
opd = NULL;
if (!backtrace_get_view (state, descriptor, 0, sizeof ehdr, error_callback,
data, &ehdr_view))
if (!elf_get_view (state, descriptor, memory, memory_size, 0, sizeof ehdr,
error_callback, data, &ehdr_view))
goto fail;
memcpy (&ehdr, ehdr_view.data, sizeof ehdr);
memcpy (&ehdr, ehdr_view.view.data, sizeof ehdr);
backtrace_release_view (state, &ehdr_view, error_callback, data);
elf_release_view (state, &ehdr_view, error_callback, data);
if (ehdr.e_ident[EI_MAG0] != ELFMAG0
|| ehdr.e_ident[EI_MAG1] != ELFMAG1
......@@ -2747,14 +4107,14 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if ((shnum == 0 || shstrndx == SHN_XINDEX)
&& shoff != 0)
{
struct backtrace_view shdr_view;
struct elf_view shdr_view;
const b_elf_shdr *shdr;
if (!backtrace_get_view (state, descriptor, shoff, sizeof shdr,
error_callback, data, &shdr_view))
if (!elf_get_view (state, descriptor, memory, memory_size, shoff,
sizeof shdr, error_callback, data, &shdr_view))
goto fail;
shdr = (const b_elf_shdr *) shdr_view.data;
shdr = (const b_elf_shdr *) shdr_view.view.data;
if (shnum == 0)
shnum = shdr->sh_size;
......@@ -2778,7 +4138,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
shstrndx -= 0x100;
}
backtrace_release_view (state, &shdr_view, error_callback, data);
elf_release_view (state, &shdr_view, error_callback, data);
}
if (shnum == 0 || shstrndx == 0)
......@@ -2789,12 +4149,13 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
/* Read the section headers, skipping the first one. */
if (!backtrace_get_view (state, descriptor, shoff + sizeof (b_elf_shdr),
(shnum - 1) * sizeof (b_elf_shdr),
error_callback, data, &shdrs_view))
if (!elf_get_view (state, descriptor, memory, memory_size,
shoff + sizeof (b_elf_shdr),
(shnum - 1) * sizeof (b_elf_shdr),
error_callback, data, &shdrs_view))
goto fail;
shdrs_view_valid = 1;
shdrs = (const b_elf_shdr *) shdrs_view.data;
shdrs = (const b_elf_shdr *) shdrs_view.view.data;
/* Read the section names. */
......@@ -2802,11 +4163,11 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
shstr_size = shstrhdr->sh_size;
shstr_off = shstrhdr->sh_offset;
if (!backtrace_get_view (state, descriptor, shstr_off, shstrhdr->sh_size,
error_callback, data, &names_view))
if (!elf_get_view (state, descriptor, memory, memory_size, shstr_off,
shstrhdr->sh_size, error_callback, data, &names_view))
goto fail;
names_view_valid = 1;
names = (const char *) names_view.data;
names = (const char *) names_view.view.data;
symtab_shndx = 0;
dynsym_shndx = 0;
......@@ -2871,13 +4232,13 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
{
const b_elf_note *note;
if (!backtrace_get_view (state, descriptor, shdr->sh_offset,
shdr->sh_size, error_callback, data,
&buildid_view))
if (!elf_get_view (state, descriptor, memory, memory_size,
shdr->sh_offset, shdr->sh_size, error_callback,
data, &buildid_view))
goto fail;
buildid_view_valid = 1;
note = (const b_elf_note *) buildid_view.data;
note = (const b_elf_note *) buildid_view.view.data;
if (note->type == NT_GNU_BUILD_ID
&& note->namesz == 4
&& strncmp (note->name, "GNU", 4) == 0
......@@ -2905,13 +4266,13 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
const char *debuglink_data;
size_t crc_offset;
if (!backtrace_get_view (state, descriptor, shdr->sh_offset,
shdr->sh_size, error_callback, data,
&debuglink_view))
if (!elf_get_view (state, descriptor, memory, memory_size,
shdr->sh_offset, shdr->sh_size, error_callback,
data, &debuglink_view))
goto fail;
debuglink_view_valid = 1;
debuglink_data = (const char *) debuglink_view.data;
debuglink_data = (const char *) debuglink_view.view.data;
crc_offset = strnlen (debuglink_data, shdr->sh_size);
crc_offset = (crc_offset + 3) & ~3;
if (crc_offset + 4 <= shdr->sh_size)
......@@ -2927,13 +4288,13 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
const char *debugaltlink_data;
size_t debugaltlink_name_len;
if (!backtrace_get_view (state, descriptor, shdr->sh_offset,
shdr->sh_size, error_callback, data,
&debugaltlink_view))
if (!elf_get_view (state, descriptor, memory, memory_size,
shdr->sh_offset, shdr->sh_size, error_callback,
data, &debugaltlink_view))
goto fail;
debugaltlink_view_valid = 1;
debugaltlink_data = (const char *) debugaltlink_view.data;
debugaltlink_data = (const char *) debugaltlink_view.view.data;
debugaltlink_name = debugaltlink_data;
debugaltlink_name_len = strnlen (debugaltlink_data, shdr->sh_size);
if (debugaltlink_name_len < shdr->sh_size)
......@@ -2947,20 +4308,32 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
}
}
if (!gnu_debugdata_view_valid
&& strcmp (name, ".gnu_debugdata") == 0)
{
if (!elf_get_view (state, descriptor, memory, memory_size,
shdr->sh_offset, shdr->sh_size, error_callback,
data, &gnu_debugdata_view))
goto fail;
gnu_debugdata_size = shdr->sh_size;
gnu_debugdata_view_valid = 1;
}
/* Read the .opd section on PowerPC64 ELFv1. */
if (ehdr.e_machine == EM_PPC64
&& (ehdr.e_flags & EF_PPC64_ABI) < 2
&& shdr->sh_type == SHT_PROGBITS
&& strcmp (name, ".opd") == 0)
{
if (!backtrace_get_view (state, descriptor, shdr->sh_offset,
shdr->sh_size, error_callback, data,
&opd_data.view))
if (!elf_get_view (state, descriptor, memory, memory_size,
shdr->sh_offset, shdr->sh_size, error_callback,
data, &opd_data.view))
goto fail;
opd = &opd_data;
opd->addr = shdr->sh_addr;
opd->data = (const char *) opd_data.view.data;
opd->data = (const char *) opd_data.view.view.data;
opd->size = shdr->sh_size;
}
}
......@@ -2984,15 +4357,15 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
}
strtab_shdr = &shdrs[strtab_shndx - 1];
if (!backtrace_get_view (state, descriptor, symtab_shdr->sh_offset,
symtab_shdr->sh_size, error_callback, data,
&symtab_view))
if (!elf_get_view (state, descriptor, memory, memory_size,
symtab_shdr->sh_offset, symtab_shdr->sh_size,
error_callback, data, &symtab_view))
goto fail;
symtab_view_valid = 1;
if (!backtrace_get_view (state, descriptor, strtab_shdr->sh_offset,
strtab_shdr->sh_size, error_callback, data,
&strtab_view))
if (!elf_get_view (state, descriptor, memory, memory_size,
strtab_shdr->sh_offset, strtab_shdr->sh_size,
error_callback, data, &strtab_view))
goto fail;
strtab_view_valid = 1;
......@@ -3002,8 +4375,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
goto fail;
if (!elf_initialize_syminfo (state, base_address,
symtab_view.data, symtab_shdr->sh_size,
strtab_view.data, strtab_shdr->sh_size,
symtab_view.view.data, symtab_shdr->sh_size,
strtab_view.view.data, strtab_shdr->sh_size,
error_callback, data, sdata, opd))
{
backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
......@@ -3012,7 +4385,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
/* We no longer need the symbol table, but we hold on to the
string table permanently. */
backtrace_release_view (state, &symtab_view, error_callback, data);
elf_release_view (state, &symtab_view, error_callback, data);
symtab_view_valid = 0;
strtab_view_valid = 0;
......@@ -3021,9 +4394,9 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
elf_add_syminfo_data (state, sdata);
}
backtrace_release_view (state, &shdrs_view, error_callback, data);
elf_release_view (state, &shdrs_view, error_callback, data);
shdrs_view_valid = 0;
backtrace_release_view (state, &names_view, error_callback, data);
elf_release_view (state, &names_view, error_callback, data);
names_view_valid = 0;
/* If the debug info is in a separate file, read that one instead. */
......@@ -3038,19 +4411,17 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
{
int ret;
backtrace_release_view (state, &buildid_view, error_callback, data);
elf_release_view (state, &buildid_view, error_callback, data);
if (debuglink_view_valid)
backtrace_release_view (state, &debuglink_view, error_callback,
data);
elf_release_view (state, &debuglink_view, error_callback, data);
if (debugaltlink_view_valid)
backtrace_release_view (state, &debugaltlink_view, error_callback,
data);
ret = elf_add (state, "", d, base_address, error_callback, data,
fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL,
0);
elf_release_view (state, &debugaltlink_view, error_callback, data);
ret = elf_add (state, "", d, NULL, 0, base_address, error_callback,
data, fileline_fn, found_sym, found_dwarf, NULL, 0,
1, NULL, 0);
if (ret < 0)
backtrace_close (d, error_callback, data);
else
else if (descriptor >= 0)
backtrace_close (descriptor, error_callback, data);
return ret;
}
......@@ -3058,13 +4429,13 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (buildid_view_valid)
{
backtrace_release_view (state, &buildid_view, error_callback, data);
elf_release_view (state, &buildid_view, error_callback, data);
buildid_view_valid = 0;
}
if (opd)
{
backtrace_release_view (state, &opd->view, error_callback, data);
elf_release_view (state, &opd->view, error_callback, data);
opd = NULL;
}
......@@ -3079,17 +4450,15 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
{
int ret;
backtrace_release_view (state, &debuglink_view, error_callback,
data);
elf_release_view (state, &debuglink_view, error_callback, data);
if (debugaltlink_view_valid)
backtrace_release_view (state, &debugaltlink_view, error_callback,
data);
ret = elf_add (state, "", d, base_address, error_callback, data,
fileline_fn, found_sym, found_dwarf, NULL, 0, 1, NULL,
0);
elf_release_view (state, &debugaltlink_view, error_callback, data);
ret = elf_add (state, "", d, NULL, 0, base_address, error_callback,
data, fileline_fn, found_sym, found_dwarf, NULL, 0,
1, NULL, 0);
if (ret < 0)
backtrace_close (d, error_callback, data);
else
else if (descriptor >= 0)
backtrace_close(descriptor, error_callback, data);
return ret;
}
......@@ -3097,7 +4466,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (debuglink_view_valid)
{
backtrace_release_view (state, &debuglink_view, error_callback, data);
elf_release_view (state, &debuglink_view, error_callback, data);
debuglink_view_valid = 0;
}
......@@ -3112,12 +4481,11 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
{
int ret;
ret = elf_add (state, filename, d, base_address, error_callback, data,
fileline_fn, found_sym, found_dwarf, &fileline_altlink,
0, 1, debugaltlink_buildid_data,
debugaltlink_buildid_size);
backtrace_release_view (state, &debugaltlink_view, error_callback,
data);
ret = elf_add (state, filename, d, NULL, 0, base_address,
error_callback, data, fileline_fn, found_sym,
found_dwarf, &fileline_altlink, 0, 1,
debugaltlink_buildid_data, debugaltlink_buildid_size);
elf_release_view (state, &debugaltlink_view, error_callback, data);
debugaltlink_view_valid = 0;
if (ret < 0)
{
......@@ -3129,10 +4497,36 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (debugaltlink_view_valid)
{
backtrace_release_view (state, &debugaltlink_view, error_callback, data);
elf_release_view (state, &debugaltlink_view, error_callback, data);
debugaltlink_view_valid = 0;
}
if (gnu_debugdata_view_valid)
{
int ret;
ret = elf_uncompress_lzma (state,
((const unsigned char *)
gnu_debugdata_view.view.data),
gnu_debugdata_size, error_callback, data,
&gnu_debugdata_uncompressed,
&gnu_debugdata_uncompressed_size);
elf_release_view (state, &gnu_debugdata_view, error_callback, data);
gnu_debugdata_view_valid = 0;
if (ret)
{
ret = elf_add (state, filename, -1, gnu_debugdata_uncompressed,
gnu_debugdata_uncompressed_size, base_address,
error_callback, data, fileline_fn, found_sym,
found_dwarf, NULL, 0, 0, NULL, 0);
if (ret >= 0 && descriptor >= 0)
backtrace_close(descriptor, error_callback, data);
return ret;
}
}
/* Read all the debug sections in a single view, since they are
probably adjacent in the file. If any of sections are
uncompressed, we never release this view. */
......@@ -3165,8 +4559,11 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
}
if (min_offset == 0 || max_offset == 0)
{
if (!backtrace_close (descriptor, error_callback, data))
goto fail;
if (descriptor >= 0)
{
if (!backtrace_close (descriptor, error_callback, data))
goto fail;
}
return 1;
}
......@@ -3176,9 +4573,9 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (max_offset - min_offset < 0x20000000
|| max_offset - min_offset < debug_size + 0x10000)
{
if (!backtrace_get_view (state, descriptor, min_offset,
max_offset - min_offset,
error_callback, data, &debug_view))
if (!elf_get_view (state, descriptor, memory, memory_size, min_offset,
max_offset - min_offset, error_callback, data,
&debug_view))
goto fail;
debug_view_valid = 1;
}
......@@ -3196,24 +4593,28 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
else
continue;
if (!backtrace_get_view (state, descriptor, dsec->offset, dsec->size,
error_callback, data, &split_debug_view[i]))
if (!elf_get_view (state, descriptor, memory, memory_size,
dsec->offset, dsec->size, error_callback, data,
&split_debug_view[i]))
goto fail;
split_debug_view_valid[i] = 1;
if (sections[i].size != 0)
sections[i].data = ((const unsigned char *)
split_debug_view[i].data);
split_debug_view[i].view.data);
else
zsections[i].data = ((const unsigned char *)
split_debug_view[i].data);
split_debug_view[i].view.data);
}
}
/* We've read all we need from the executable. */
if (!backtrace_close (descriptor, error_callback, data))
goto fail;
descriptor = -1;
if (descriptor >= 0)
{
if (!backtrace_close (descriptor, error_callback, data))
goto fail;
descriptor = -1;
}
using_debug_view = 0;
if (debug_view_valid)
......@@ -3224,7 +4625,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
sections[i].data = NULL;
else
{
sections[i].data = ((const unsigned char *) debug_view.data
sections[i].data = ((const unsigned char *) debug_view.view.data
+ (sections[i].offset - min_offset));
++using_debug_view;
}
......@@ -3232,7 +4633,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (zsections[i].size == 0)
zsections[i].data = NULL;
else
zsections[i].data = ((const unsigned char *) debug_view.data
zsections[i].data = ((const unsigned char *) debug_view.view.data
+ (zsections[i].offset - min_offset));
}
}
......@@ -3269,8 +4670,8 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (split_debug_view_valid[i])
{
backtrace_release_view (state, &split_debug_view[i],
error_callback, data);
elf_release_view (state, &split_debug_view[i],
error_callback, data);
split_debug_view_valid[i] = 0;
}
}
......@@ -3309,8 +4710,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
--using_debug_view;
else if (split_debug_view_valid[i])
{
backtrace_release_view (state, &split_debug_view[i],
error_callback, data);
elf_release_view (state, &split_debug_view[i], error_callback, data);
split_debug_view_valid[i] = 0;
}
}
......@@ -3321,7 +4721,7 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
if (debug_view_valid && using_debug_view == 0)
{
backtrace_release_view (state, &debug_view, error_callback, data);
elf_release_view (state, &debug_view, error_callback, data);
debug_view_valid = 0;
}
......@@ -3344,30 +4744,31 @@ elf_add (struct backtrace_state *state, const char *filename, int descriptor,
fail:
if (shdrs_view_valid)
backtrace_release_view (state, &shdrs_view, error_callback, data);
elf_release_view (state, &shdrs_view, error_callback, data);
if (names_view_valid)
backtrace_release_view (state, &names_view, error_callback, data);
elf_release_view (state, &names_view, error_callback, data);
if (symtab_view_valid)
backtrace_release_view (state, &symtab_view, error_callback, data);
elf_release_view (state, &symtab_view, error_callback, data);
if (strtab_view_valid)
backtrace_release_view (state, &strtab_view, error_callback, data);
elf_release_view (state, &strtab_view, error_callback, data);
if (debuglink_view_valid)
backtrace_release_view (state, &debuglink_view, error_callback, data);
elf_release_view (state, &debuglink_view, error_callback, data);
if (debugaltlink_view_valid)
backtrace_release_view (state, &debugaltlink_view, error_callback, data);
elf_release_view (state, &debugaltlink_view, error_callback, data);
if (gnu_debugdata_view_valid)
elf_release_view (state, &gnu_debugdata_view, error_callback, data);
if (buildid_view_valid)
backtrace_release_view (state, &buildid_view, error_callback, data);
elf_release_view (state, &buildid_view, error_callback, data);
if (debug_view_valid)
backtrace_release_view (state, &debug_view, error_callback, data);
elf_release_view (state, &debug_view, error_callback, data);
for (i = 0; i < (int) DEBUG_MAX; ++i)
{
if (split_debug_view_valid[i])
backtrace_release_view (state, &split_debug_view[i],
error_callback, data);
elf_release_view (state, &split_debug_view[i], error_callback, data);
}
if (opd)
backtrace_release_view (state, &opd->view, error_callback, data);
if (descriptor != -1)
elf_release_view (state, &opd->view, error_callback, data);
if (descriptor >= 0)
backtrace_close (descriptor, error_callback, data);
return 0;
}
......@@ -3429,7 +4830,7 @@ phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
return 0;
}
if (elf_add (pd->state, filename, descriptor, info->dlpi_addr,
if (elf_add (pd->state, filename, descriptor, NULL, 0, info->dlpi_addr,
pd->error_callback, pd->data, &elf_fileline_fn, pd->found_sym,
&found_dwarf, NULL, 0, 0, NULL, 0))
{
......@@ -3458,7 +4859,7 @@ backtrace_initialize (struct backtrace_state *state, const char *filename,
fileline elf_fileline_fn = elf_nodebug;
struct phdr_data pd;
ret = elf_add (state, filename, descriptor, 0, error_callback, data,
ret = elf_add (state, filename, descriptor, NULL, 0, 0, error_callback, data,
&elf_fileline_fn, &found_sym, &found_dwarf, NULL, 1, 0, NULL,
0);
if (!ret)
......
......@@ -335,4 +335,13 @@ extern int backtrace_uncompress_zdebug (struct backtrace_state *,
unsigned char **uncompressed,
size_t *uncompressed_size);
/* A test-only hook for elf_uncompress_lzma. */
extern int backtrace_uncompress_lzma (struct backtrace_state *,
const unsigned char *compressed,
size_t compressed_size,
backtrace_error_callback, void *data,
unsigned char **uncompressed,
size_t *uncompressed_size);
#endif
/* mtest.c -- Minidebug test for libbacktrace library
Copyright (C) 2020 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. */
/* This program tests using libbacktrace with a program that uses the
minidebuginfo format in a .gnu_debugdata section. See
https://sourceware.org/gdb/current/onlinedocs/gdb/MiniDebugInfo.html
for a bit more information about minidebuginfo. What is relevant
for libbacktrace is that we have just a symbol table, with no debug
info, so we should be able to do a function backtrace, but we can't
do a file/line backtrace. */
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "backtrace.h"
#include "backtrace-supported.h"
#include "testlib.h"
static int test1 (void) __attribute__ ((noinline, noclone, unused));
static int f2 (int) __attribute__ ((noinline, noclone));
static int f3 (int, int) __attribute__ ((noinline, noclone));
/* Collected PC values. */
static uintptr_t addrs[20];
/* The backtrace callback function. This is like callback_one in
testlib.c, but it saves the PC also. */
static int
callback_mtest (void *vdata, uintptr_t pc, const char *filename, int lineno,
const char *function)
{
struct bdata *data = (struct bdata *) vdata;
if (data->index >= sizeof addrs / sizeof addrs[0])
{
fprintf (stderr, "callback_mtest: callback called too many times\n");
data->failed = 1;
return 1;
}
addrs[data->index] = pc;
return callback_one (vdata, pc, filename, lineno, function);
}
/* Test the backtrace function with non-inlined functions. (We don't
test with inlined functions because they won't work with minidebug
anyhow.) */
static int
test1 (void)
{
/* Returning a value here and elsewhere avoids a tailcall which
would mess up the backtrace. */
return f2 (__LINE__) + 1;
}
static int
f2 (int f1line)
{
return f3 (f1line, __LINE__) + 2;
}
static int
f3 (int f1line __attribute__ ((unused)), int f2line __attribute__ ((unused)))
{
struct info all[20];
struct bdata data;
int i;
size_t j;
data.all = &all[0];
data.index = 0;
data.max = 20;
data.failed = 0;
i = backtrace_full (state, 0, callback_mtest, 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;
}
/* When using minidebug we don't expect the function name here. */
for (j = 0; j < 3 && j < data.index; j++)
{
if (all[j].function == NULL)
{
struct symdata symdata;
symdata.name = NULL;
symdata.val = 0;
symdata.size = 0;
symdata.failed = 0;
i = backtrace_syminfo (state, addrs[j], callback_three,
error_callback_three, &symdata);
if (i == 0)
{
fprintf (stderr,
("test1: [%zu], unexpected return value from "
"backtrace_syminfo %d\n"),
j, i);
data.failed = 1;
}
else if (symdata.name == NULL)
{
fprintf (stderr, "test1: [%zu]: syminfo did not find name\n", j);
data.failed = 1;
}
else
all[j].function = strdup (symdata.name);
}
}
if (all[0].function == NULL)
{
fprintf (stderr, "test1: [0]: missing function name\n");
data.failed = 1;
}
else if (strcmp (all[0].function, "f3") != 0)
{
fprintf (stderr, "test1: [0]: got %s expected %s\n",
all[0].function, "f3");
data.failed = 1;
}
if (all[1].function == NULL)
{
fprintf (stderr, "test1: [1]: missing function name\n");
data.failed = 1;
}
else if (strcmp (all[1].function, "f2") != 0)
{
fprintf (stderr, "test1: [1]: got %s expected %s\n",
all[0].function, "f2");
data.failed = 1;
}
if (all[2].function == NULL)
{
fprintf (stderr, "test1: [2]: missing function name\n");
data.failed = 1;
}
else if (strcmp (all[2].function, "test1") != 0)
{
fprintf (stderr, "test1: [2]: got %s expected %s\n",
all[0].function, "test1");
data.failed = 1;
}
printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");
if (data.failed)
++failures;
return failures;
}
/* Test the backtrace_simple function with non-inlined functions. */
static int test3 (void) __attribute__ ((noinline, noclone, unused));
static int f22 (int) __attribute__ ((noinline, noclone));
static int f23 (int, int) __attribute__ ((noinline, noclone));
static int
test3 (void)
{
return f22 (__LINE__) + 1;
}
static int
f22 (int f1line)
{
return f23 (f1line, __LINE__) + 2;
}
static int
f23 (int f1line __attribute__ ((unused)), int f2line __attribute__ ((unused)))
{
uintptr_t addrs[20];
struct sdata data;
int i;
data.addrs = &addrs[0];
data.index = 0;
data.max = 20;
data.failed = 0;
i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
if (i != 0)
{
fprintf (stderr, "test3: unexpected return value %d\n", i);
data.failed = 1;
}
if (!data.failed)
{
int j;
for (j = 0; j < 3; ++j)
{
struct symdata symdata;
symdata.name = NULL;
symdata.val = 0;
symdata.size = 0;
symdata.failed = 0;
i = backtrace_syminfo (state, addrs[j], callback_three,
error_callback_three, &symdata);
if (i == 0)
{
fprintf (stderr,
("test3: [%d]: unexpected return value "
"from backtrace_syminfo %d\n"),
j, i);
symdata.failed = 1;
}
if (!symdata.failed)
{
const char *expected;
switch (j)
{
case 0:
expected = "f23";
break;
case 1:
expected = "f22";
break;
case 2:
expected = "test3";
break;
default:
assert (0);
}
if (symdata.name == NULL)
{
fprintf (stderr, "test3: [%d]: NULL syminfo name\n", j);
symdata.failed = 1;
}
/* Use strncmp, not strcmp, because GCC might create a
clone. */
else if (strncmp (symdata.name, expected, strlen (expected))
!= 0)
{
fprintf (stderr,
("test3: [%d]: unexpected syminfo name "
"got %s expected %s\n"),
j, symdata.name, expected);
symdata.failed = 1;
}
}
if (symdata.failed)
data.failed = 1;
}
}
printf ("%s: backtrace_simple noinline\n", data.failed ? "FAIL" : "PASS");
if (data.failed)
++failures;
return failures;
}
int test5 (void) __attribute__ ((unused));
int global = 1;
int
test5 (void)
{
struct symdata symdata;
int i;
uintptr_t addr = (uintptr_t) &global;
if (sizeof (global) > 1)
addr += 1;
symdata.name = NULL;
symdata.val = 0;
symdata.size = 0;
symdata.failed = 0;
i = backtrace_syminfo (state, addr, callback_three,
error_callback_three, &symdata);
if (i == 0)
{
fprintf (stderr,
"test5: unexpected return value from backtrace_syminfo %d\n",
i);
symdata.failed = 1;
}
if (!symdata.failed)
{
if (symdata.name == NULL)
{
fprintf (stderr, "test5: NULL syminfo name\n");
symdata.failed = 1;
}
else if (!(strncmp (symdata.name, "global", 6) == 0
&& (symdata.name[6] == '\0'|| symdata.name[6] == '.')))
{
fprintf (stderr,
"test5: unexpected syminfo name got %s expected %s\n",
symdata.name, "global");
symdata.failed = 1;
}
else if (symdata.val != (uintptr_t) &global)
{
fprintf (stderr,
"test5: unexpected syminfo value got %lx expected %lx\n",
(unsigned long) symdata.val,
(unsigned long) (uintptr_t) &global);
symdata.failed = 1;
}
else if (symdata.size != sizeof (global))
{
fprintf (stderr,
"test5: unexpected syminfo size got %lx expected %lx\n",
(unsigned long) symdata.size,
(unsigned long) sizeof (global));
symdata.failed = 1;
}
}
printf ("%s: backtrace_syminfo variable\n",
symdata.failed ? "FAIL" : "PASS");
if (symdata.failed)
++failures;
return failures;
}
int
main (int argc ATTRIBUTE_UNUSED, char **argv)
{
state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
error_callback_create, NULL);
#if BACKTRACE_SUPPORTED
test1 ();
test3 ();
#if BACKTRACE_SUPPORTS_DATA
test5 ();
#endif
#endif
exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
}
/* xztest.c -- Test for libbacktrace LZMA decoder.
Copyright (C) 2020 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 "config.h"
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef HAVE_LIBLZMA
#include <lzma.h>
#endif
#include "backtrace.h"
#include "backtrace-supported.h"
#include "internal.h"
#include "testlib.h"
#ifndef HAVE_CLOCK_GETTIME
typedef int xclockid_t;
static int
xclock_gettime (xclockid_t id ATTRIBUTE_UNUSED,
struct timespec *ts ATTRIBUTE_UNUSED)
{
errno = EINVAL;
return -1;
}
#define clockid_t xclockid_t
#define clock_gettime xclock_gettime
#undef CLOCK_REALTIME
#define CLOCK_REALTIME 0
#endif /* !defined(HAVE_CLOCK_GETTIME) */
#ifdef CLOCK_PROCESS_CPUTIME_ID
#define LIBLZMA_CLOCK_GETTIME_ARG CLOCK_PROCESS_CPUTIME_ID
#else
#define LIBLZMA_CLOCK_GETTIME_ARG CLOCK_REALTIME
#endif
/* Some tests for the local lzma inflation code. */
struct lzma_test
{
const char *name;
const char *uncompressed;
size_t uncompressed_len;
const char *compressed;
size_t compressed_len;
};
/* Error callback. */
static void
error_callback_compress (void *vdata 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);
}
static const struct lzma_test tests[] =
{
{
"empty",
"",
0,
("\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x00\x00\x00\x00"
"\x1c\xdf\x44\x21\x1f\xb6\xf3\x7d\x01\x00\x00\x00\x00\x04\x59\x5a"),
32,
},
{
"hello",
"hello, world\n",
0,
("\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21\x01"
"\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x0c\x68\x65\x6c\x6c\x6f"
"\x2c\x20\x77\x6f\x72\x6c\x64\x0a\x00\x00\x00\x00\x7b\x46\x5a\x81"
"\xc9\x12\xb8\xea\x00\x01\x25\x0d\x71\x19\xc4\xb6\x1f\xb6\xf3\x7d"
"\x01\x00\x00\x00\x00\x04\x59\x5a"),
72,
},
{
"goodbye",
"goodbye, world",
0,
("\xfd\x37\x7a\x58\x5a\x00\x00\x04\xe6\xd6\xb4\x46\x02\x00\x21\x01"
"\x16\x00\x00\x00\x74\x2f\xe5\xa3\x01\x00\x0d\x67\x6f\x6f\x64\x62"
"\x79\x65\x2c\x20\x77\x6f\x72\x6c\x64\x00\x00\x00\xf6\xf8\xa3\x33"
"\x8c\x4e\xc9\x68\x00\x01\x26\x0e\x08\x1b\xe0\x04\x1f\xb6\xf3\x7d"
"\x01\x00\x00\x00\x00\x04\x59\x5a"),
72,
},
};
/* Test the hand coded samples. */
static void
test_samples (struct backtrace_state *state)
{
size_t i;
for (i = 0; i < sizeof tests / sizeof tests[0]; ++i)
{
unsigned char *uncompressed;
size_t uncompressed_len;
uncompressed = NULL;
uncompressed_len = 0;
if (!backtrace_uncompress_lzma (state,
((const unsigned char *)
tests[i].compressed),
tests[i].compressed_len,
error_callback_compress, NULL,
&uncompressed, &uncompressed_len))
{
fprintf (stderr, "test %s: uncompress failed\n", tests[i].name);
++failures;
}
else
{
size_t v;
v = tests[i].uncompressed_len;
if (v == 0)
v = strlen (tests[i].uncompressed);
if (uncompressed_len != v)
{
fprintf (stderr,
"test %s: got uncompressed length %zu, want %zu\n",
tests[i].name, uncompressed_len, v);
++failures;
}
else if (memcmp (tests[i].uncompressed, uncompressed, v) != 0)
{
size_t j;
fprintf (stderr, "test %s: uncompressed data mismatch\n",
tests[i].name);
for (j = 0; j < v; ++j)
if (tests[i].uncompressed[j] != uncompressed[j])
fprintf (stderr, " %zu: got %#x want %#x\n", j,
uncompressed[j], tests[i].uncompressed[j]);
++failures;
}
else
printf ("PASS: lzma %s\n", tests[i].name);
backtrace_free (state, uncompressed, uncompressed_len,
error_callback_compress, NULL);
}
}
}
#if HAVE_LIBLZMA
/* Given a set of TRIALS timings, discard the lowest and highest
values and return the mean average of the rest. */
static size_t
average_time (const size_t *times, size_t trials)
{
size_t imax;
size_t max;
size_t imin;
size_t min;
size_t i;
size_t sum;
imin = 0;
imax = 0;
min = times[0];
max = times[0];
for (i = 1; i < trials; ++i)
{
if (times[i] < min)
{
imin = i;
min = times[i];
}
if (times[i] > max)
{
imax = i;
max = times[i];
}
}
sum = 0;
for (i = 0; i < trials; ++i)
{
if (i != imax && i != imin)
sum += times[i];
}
return sum / (trials - 2);
}
#endif
/* Test a larger text, if available. */
static void
test_large (struct backtrace_state *state ATTRIBUTE_UNUSED)
{
#if HAVE_LIBLZMA
unsigned char *orig_buf;
size_t orig_bufsize;
size_t i;
lzma_stream initial_stream = LZMA_STREAM_INIT;
lzma_stream stream;
unsigned char *compressed_buf;
size_t compressed_bufsize;
unsigned char *uncompressed_buf;
size_t uncompressed_bufsize;
unsigned char *spare_buf;
int r;
clockid_t cid;
struct timespec ts1;
struct timespec ts2;
size_t ctime;
size_t ztime;
const size_t trials = 16;
size_t ctimes[16];
size_t ztimes[16];
static const char * const names[] = {
"Isaac.Newton-Opticks.txt",
"../libgo/go/testdata/Isaac.Newton-Opticks.txt",
};
orig_buf = NULL;
orig_bufsize = 0;
uncompressed_buf = NULL;
compressed_buf = NULL;
for (i = 0; i < sizeof names / sizeof names[0]; ++i)
{
size_t len;
char *namebuf;
FILE *e;
struct stat st;
char *rbuf;
size_t got;
len = strlen (SRCDIR) + strlen (names[i]) + 2;
namebuf = malloc (len);
if (namebuf == NULL)
{
perror ("malloc");
goto fail;
}
snprintf (namebuf, len, "%s/%s", SRCDIR, names[i]);
e = fopen (namebuf, "r");
free (namebuf);
if (e == NULL)
continue;
if (fstat (fileno (e), &st) < 0)
{
perror ("fstat");
fclose (e);
continue;
}
rbuf = malloc (st.st_size);
if (rbuf == NULL)
{
perror ("malloc");
goto fail;
}
got = fread (rbuf, 1, st.st_size, e);
fclose (e);
if (got > 0)
{
orig_buf = (unsigned char *) rbuf;
orig_bufsize = got;
break;
}
free (rbuf);
}
if (orig_buf == NULL)
{
/* We couldn't find an input file. */
printf ("UNSUPPORTED: lzma large\n");
return;
}
stream = initial_stream;
r = lzma_easy_encoder (&stream, 6, LZMA_CHECK_CRC32);
if (r != LZMA_OK)
{
fprintf (stderr, "lzma_easy_encoder failed: %d\n", r);
goto fail;
}
compressed_bufsize = orig_bufsize + 100;
compressed_buf = malloc (compressed_bufsize);
if (compressed_buf == NULL)
{
perror ("malloc");
goto fail;
}
stream.next_in = orig_buf;
stream.avail_in = orig_bufsize;
stream.next_out = compressed_buf;
stream.avail_out = compressed_bufsize;
do
{
r = lzma_code (&stream, LZMA_FINISH);
if (r != LZMA_OK && r != LZMA_STREAM_END)
{
fprintf (stderr, "lzma_code failed: %d\n", r);
goto fail;
}
}
while (r != LZMA_STREAM_END);
compressed_bufsize = stream.total_out;
if (!backtrace_uncompress_lzma (state, (unsigned char *) compressed_buf,
compressed_bufsize,
error_callback_compress, NULL,
&uncompressed_buf, &uncompressed_bufsize))
{
fprintf (stderr, "lzma large: backtrace_uncompress_lzma failed\n");
goto fail;
}
if (uncompressed_bufsize != orig_bufsize)
{
fprintf (stderr,
"lzma large: got uncompressed length %zu, want %zu\n",
uncompressed_bufsize, orig_bufsize);
goto fail;
}
if (memcmp (uncompressed_buf, orig_buf, uncompressed_bufsize) != 0)
{
fprintf (stderr, "lzma large: uncompressed data mismatch\n");
goto fail;
}
printf ("PASS: lzma large\n");
spare_buf = malloc (orig_bufsize);
if (spare_buf == NULL)
{
perror ("malloc");
goto fail;
}
for (i = 0; i < trials; ++i)
{
cid = LIBLZMA_CLOCK_GETTIME_ARG;
if (clock_gettime (cid, &ts1) < 0)
{
if (errno == EINVAL)
return;
perror ("clock_gettime");
return;
}
if (!backtrace_uncompress_lzma (state,
(unsigned char *) compressed_buf,
compressed_bufsize,
error_callback_compress, NULL,
&uncompressed_buf,
&uncompressed_bufsize))
{
fprintf (stderr,
("lzma large: "
"benchmark backtrace_uncompress_lzma failed\n"));
return;
}
if (clock_gettime (cid, &ts2) < 0)
{
perror ("clock_gettime");
return;
}
ctime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
ctime += ts2.tv_nsec - ts1.tv_nsec;
ctimes[i] = ctime;
stream = initial_stream;
r = lzma_auto_decoder (&stream, UINT64_MAX, 0);
if (r != LZMA_OK)
{
fprintf (stderr, "lzma_stream_decoder failed: %d\n", r);
goto fail;
}
stream.next_in = compressed_buf;
stream.avail_in = compressed_bufsize;
stream.next_out = spare_buf;
stream.avail_out = orig_bufsize;
if (clock_gettime (cid, &ts1) < 0)
{
perror("clock_gettime");
return;
}
do
{
r = lzma_code (&stream, LZMA_FINISH);
if (r != LZMA_OK && r != LZMA_STREAM_END)
{
fprintf (stderr, "lzma_code failed: %d\n", r);
goto fail;
}
}
while (r != LZMA_STREAM_END);
if (clock_gettime (cid, &ts2) < 0)
{
perror ("clock_gettime");
return;
}
ztime = (ts2.tv_sec - ts1.tv_sec) * 1000000000;
ztime += ts2.tv_nsec - ts1.tv_nsec;
ztimes[i] = ztime;
}
/* Toss the highest and lowest times and average the rest. */
ctime = average_time (ctimes, trials);
ztime = average_time (ztimes, trials);
printf ("backtrace: %zu ns\n", ctime);
printf ("liblzma : %zu ns\n", ztime);
printf ("ratio : %g\n", (double) ztime / (double) ctime);
return;
fail:
printf ("FAIL: lzma large\n");
++failures;
if (orig_buf != NULL)
free (orig_buf);
if (compressed_buf != NULL)
free (compressed_buf);
if (uncompressed_buf != NULL)
free (uncompressed_buf);
#else /* !HAVE_LIBLZMA */
printf ("UNSUPPORTED: lzma large\n");
#endif /* !HAVE_LIBLZMA */
}
int
main (int argc ATTRIBUTE_UNUSED, char **argv)
{
struct backtrace_state *state;
state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
error_callback_create, NULL);
test_samples (state);
test_large (state);
exit (failures != 0 ? EXIT_FAILURE : EXIT_SUCCESS);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment