summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJose Fonseca <jfonseca@vmware.com>2016-01-27 12:33:53 +0000
committerJose Fonseca <jfonseca@vmware.com>2016-01-27 12:33:53 +0000
commit8f654894d52a70291d6da17c4394e16507b77a79 (patch)
treeb6f012861dbcc35fe4455ee33419ab4356c39388
parente11395e9a4afddfc68b40facb1007dd303ee24f6 (diff)
libbacktrace: Update.
To git commit f1717362de1e56fe1ffab540289d7d0c6ed48b20, svn+ssh://gcc.gnu.org/svn/gcc/trunk@232055. Fixes #419.
-rw-r--r--thirdparty/libbacktrace/CMakeLists.txt21
-rw-r--r--thirdparty/libbacktrace/ChangeLog278
-rw-r--r--thirdparty/libbacktrace/alloc.c30
-rw-r--r--thirdparty/libbacktrace/atomic.c113
-rw-r--r--thirdparty/libbacktrace/backtrace-supported.h.in7
-rw-r--r--thirdparty/libbacktrace/backtrace.c27
-rw-r--r--thirdparty/libbacktrace/backtrace.h36
-rw-r--r--thirdparty/libbacktrace/btest.c99
-rw-r--r--thirdparty/libbacktrace/config.h.in.cmake3
-rw-r--r--thirdparty/libbacktrace/dwarf.c439
-rw-r--r--thirdparty/libbacktrace/elf.c155
-rw-r--r--thirdparty/libbacktrace/fileline.c42
-rw-r--r--thirdparty/libbacktrace/internal.h70
-rw-r--r--thirdparty/libbacktrace/mmap.c53
-rw-r--r--thirdparty/libbacktrace/mmapio.c2
-rw-r--r--thirdparty/libbacktrace/nounwind.c2
-rw-r--r--thirdparty/libbacktrace/pecoff.c937
-rw-r--r--thirdparty/libbacktrace/posix.c4
-rw-r--r--thirdparty/libbacktrace/print.c2
-rw-r--r--thirdparty/libbacktrace/read.c2
-rw-r--r--thirdparty/libbacktrace/simple.c2
-rw-r--r--thirdparty/libbacktrace/sort.c108
-rw-r--r--thirdparty/libbacktrace/state.c2
-rw-r--r--thirdparty/libbacktrace/stest.c137
-rw-r--r--thirdparty/libbacktrace/unknown.c2
25 files changed, 2222 insertions, 351 deletions
diff --git a/thirdparty/libbacktrace/CMakeLists.txt b/thirdparty/libbacktrace/CMakeLists.txt
index 2a4a685e..3fc54306 100644
--- a/thirdparty/libbacktrace/CMakeLists.txt
+++ b/thirdparty/libbacktrace/CMakeLists.txt
@@ -66,6 +66,13 @@ check_c_source_compiles (
__sync_lock_release (&i);}"
HAVE_SYNC_FUNCTIONS)
+check_c_source_compiles (
+ "int i;
+ int main() {
+ __atomic_load_n (&i, __ATOMIC_ACQUIRE);
+ __atomic_store_n (&i, i, __ATOMIC_RELEASE);}"
+ HAVE_ATOMIC_FUNCTIONS)
+
if (HAVE_SYNC_FUNCTIONS)
set (BACKTRACE_SUPPORTS_THREADS 1)
else ()
@@ -75,10 +82,12 @@ endif ()
if (CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF")
set (FORMAT_FILE elf.c dwarf.c)
math (EXPR BACKTRACE_ELF_SIZE 8*${CMAKE_C_SIZEOF_DATA_PTR})
+ set (BACKTRACE_SUPPORTS_DATA 1)
else ()
set (FORMAT_FILE unknown.c)
set (BACKTRACE_SUPPORTED 0)
message (STATUS "Executable format is not ELF. Disabling Backtrace support.")
+ set (BACKTRACE_SUPPORTS_DATA 0)
endif ()
check_symbol_exists (mmap sys/mman.h HAVE_MMAP)
@@ -88,9 +97,9 @@ if (HAVE_MMAP)
check_symbol_exists (MAP_ANONYMOUS sys/mman.h HAVE_MMAP_ANONYMOUS)
check_symbol_exists (MAP_ANON sys/mman.h HAVE_MMAP_ANON)
if (HAVE_MMAP_ANONYMOUS AND HAVE_MMAP_ANON)
- set (ALLOC_FILE mmap.c)
+ set (ALLOC_FILE mmap.c)
else ()
- set (ALLOC_FILE alloc.c)
+ set (ALLOC_FILE alloc.c)
endif ()
else ()
set (VIEW_FILE read.c)
@@ -137,10 +146,12 @@ add_convenience_library (backtrace EXCLUDE_FROM_ALL
${FORMAT_FILE}
${VIEW_FILE}
${ALLOC_FILE}
+ atomic.c
fileline.c
posix.c
print.c
state.c
+ sort.c
)
add_executable (btest btest.c)
@@ -148,3 +159,9 @@ set_target_properties (btest PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS_DEBUG}")
target_link_libraries (btest backtrace)
add_dependencies (check btest)
add_test (libbacktrace_btest btest)
+
+add_executable (stest stest.c)
+set_target_properties (stest PROPERTIES COMPILE_FLAGS "${CMAKE_C_FLAGS_DEBUG}")
+target_link_libraries (stest backtrace)
+add_dependencies (check stest)
+add_test (libbacktrace_stest stest)
diff --git a/thirdparty/libbacktrace/ChangeLog b/thirdparty/libbacktrace/ChangeLog
index d6f7205f..2afa4705 100644
--- a/thirdparty/libbacktrace/ChangeLog
+++ b/thirdparty/libbacktrace/ChangeLog
@@ -1,3 +1,275 @@
+2016-01-04 Jakub Jelinek <jakub@redhat.com>
+
+ Update copyright years.
+
+2015-12-18 Andris Pavenis <andris.pavenis@iki.fi>
+
+ * configure.ac: Specify that DJGPP do not have mmap even when sys/mman.h exists
+ * configure: Regenerate
+
+2015-12-09 John David Anglin <danglin@gcc.gnu.org>
+
+ PR 68115/libfortran
+ * configure.ac: Set libbacktrace_cv_sys_sync to no on hppa*-*-hpux*.
+ * configure: Regenerate.
+ * elf.c (backtrace_initialize): Cast __sync_bool_compare_and_swap call
+ to void.
+
+2015-09-17 Ian Lance Taylor <iant@google.com>
+
+ * posix.c (backtrace_open): Cast second argument of open() to int.
+
+2015-09-11 Ian Lance Taylor <iant@google.com>
+
+ * Makefile.am (backtrace.lo): Depend on internal.h.
+ (sort.lo, stest.lo): Add explicit dependencies.
+ * Makefile.in: Rebuild.
+
+2015-09-09 Hans-Peter Nilsson <hp@axis.com>
+
+ * backtrace.c: #include <sys/types.h>.
+
+2015-09-08 Ian Lance Taylor <iant@google.com>
+
+ PR other/67457
+ * backtrace.c: #include "internal.h".
+ (struct backtrace_data): Add can_alloc field.
+ (unwind): If can_alloc is false, don't try to get file/line
+ information.
+ (backtrace_full): Set can_alloc field in bdata.
+ * alloc.c (backtrace_alloc): Don't call error_callback if it is
+ NULL.
+ * mmap.c (backtrace_alloc): Likewise.
+ * internal.h: Update comments for backtrace_alloc and
+ backtrace_free.
+
+2015-09-08 Ian Lance Taylor <iant@google.com>
+
+ PR other/67457
+ * mmap.c (backtrace_alloc): Correct test for mmap failure.
+
+2015-08-31 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * configure.ac: For spu-*-* targets, set have_fcntl to no.
+ * configure: Regenerate.
+
+2015-08-27 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * configure.ac: Remove [disable-shared] argument to LT_INIT.
+ Remove setting PIC_FLAG when building as target library.
+ * configure: Regenerate.
+
+2015-08-26 Hans-Peter Nilsson <hp@axis.com>
+
+ * configure.ac: Only compile with -fPIC if the target
+ supports it.
+ * configure: Regenerate.
+
+2015-08-24 Ulrich Weigand <Ulrich.Weigand@de.ibm.com>
+
+ * configure.ac: Set have_mmap to no on spu-*-* targets.
+ * configure: Regenerate.
+
+2015-08-13 Ian Lance Taylor <iant@google.com>
+
+ * dwarf.c (read_function_entry): Add vec_inlined parameter.
+ Change all callers.
+
+2015-06-11 Martin Sebor <msebor@redhat.com>
+
+ PR sanitizer/65479
+ * dwarf.c (struct line): Add new field idx.
+ (line_compare): Use it.
+ (add_line): Set it.
+ (read_line_info): Reset it.
+
+2015-05-29 Tristan Gingold <gingold@adacore.com>
+
+ * pecoff.c: New file.
+ * Makefile.am (FORMAT_FILES): Add pecoff.c and dependencies.
+ * Makefile.in: Regenerate.
+ * filetype.awk: Detect pecoff.
+ * configure.ac: Define BACKTRACE_SUPPORTS_DATA on elf platforms.
+ Add pecoff.
+ * btest.c (test5): Test enabled only if BACKTRACE_SUPPORTS_DATA is
+ true.
+ * backtrace-supported.h.in (BACKTRACE_SUPPORTS_DATA): Define.
+ * configure: Regenerate.
+ * pecoff.c: New file.
+
+2015-05-13 Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>
+
+ * Makefile.in: Regenerated with automake-1.11.6.
+ * aclocal.m4: Likewise.
+ * configure: Likewise.
+
+2015-01-24 Matthias Klose <doko@ubuntu.com>
+
+ * configure.ac: Move AM_ENABLE_MULTILIB before AC_PROG_CC.
+ * configure: Regenerate.
+
+2015-01-05 Jakub Jelinek <jakub@redhat.com>
+
+ Update copyright years.
+
+2014-11-21 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR bootstrap/63784
+ * configure: Regenerated.
+
+2014-11-11 David Malcolm <dmalcolm@redhat.com>
+
+ * ChangeLog.jit: New.
+
+2014-11-11 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org>
+
+ PR target/63610
+ * configure: Regenerate.
+
+2014-10-23 Ian Lance Taylor <iant@google.com>
+
+ * internal.h (backtrace_atomic_load_pointer) [no atomic or sync]:
+ Fix to return void *.
+
+2014-05-08 Ian Lance Taylor <iant@google.com>
+
+ * mmap.c (backtrace_free): If freeing a large aligned block of
+ memory, call munmap rather than holding onto it.
+ (backtrace_vector_grow): When growing a vector, double the number
+ of pages requested. When releasing the old version of a grown
+ vector, pass the correct size to backtrace_free.
+
+2014-03-07 Ian Lance Taylor <iant@google.com>
+
+ * sort.c (backtrace_qsort): Use middle element as pivot.
+
+2014-03-06 Ian Lance Taylor <iant@google.com>
+
+ * sort.c: New file.
+ * stest.c: New file.
+ * internal.h (backtrace_qsort): Declare.
+ * dwarf.c (read_abbrevs): Call backtrace_qsort instead of qsort.
+ (read_line_info, read_function_entry): Likewise.
+ (read_function_info, build_dwarf_data): Likewise.
+ * elf.c (elf_initialize_syminfo): Likewise.
+ * Makefile.am (libbacktrace_la_SOURCES): Add sort.c.
+ (stest_SOURCES, stest_LDADD): Define.
+ (check_PROGRAMS): Add stest.
+
+2014-02-07 Misty De Meo <misty@brew.sh>
+
+ PR target/58710
+ * configure.ac: Use AC_LINK_IFELSE in check for
+ _Unwind_GetIPInfo.
+ * configure: Regenerate.
+
+2014-01-02 Richard Sandiford <rdsandiford@googlemail.com>
+
+ Update copyright years
+
+2013-12-06 Jakub Jelinek <jakub@redhat.com>
+
+ * elf.c (ET_DYN): Undefine and define again.
+ (elf_add): Add exe argument, if true and ehdr.e_type is ET_DYN,
+ return early -1 without closing the descriptor.
+ (struct phdr_data): Add exe_descriptor.
+ (phdr_callback): If pd->exe_descriptor is not -1, for very first
+ call if dlpi_name is NULL just call elf_add with the exe_descriptor,
+ otherwise backtrace_close the exe_descriptor if not -1. Adjust
+ call to elf_add.
+ (backtrace_initialize): Adjust call to elf_add. If it returns
+ -1, set pd.exe_descriptor to descriptor, otherwise set it to -1.
+
+2013-12-05 Ian Lance Taylor <iant@google.com>
+
+ * alloc.c (backtrace_vector_finish): Add error_callback and data
+ parameters. Call backtrace_vector_release. Return address base.
+ * mmap.c (backtrace_vector_finish): Add error_callback and data
+ parameters. Return address base.
+ * dwarf.c (read_function_info): Get new address base from
+ backtrace_vector_finish.
+ * internal.h (backtrace_vector_finish): Update declaration.
+
+2013-11-27 Ian Lance Taylor <iant@google.com>
+
+ * dwarf.c (find_address_ranges): New static function, broken out
+ of build_address_map.
+ (build_address_map): Call it.
+ * btest.c (check): Check for missing filename or function, rather
+ than crashing.
+ (f3): Check that enough frames were returned.
+
+2013-11-19 Jakub Jelinek <jakub@redhat.com>
+
+ * backtrace.h (backtrace_syminfo_callback): Add symsize argument.
+ * elf.c (elf_syminfo): Pass 0 or sym->size to the callback as
+ last argument.
+ * btest.c (struct symdata): Add size field.
+ (callback_three): Add symsize argument. Copy it to the data->size
+ field.
+ (f23): Set symdata.size to 0.
+ (test5): Likewise. If sizeof (int) > 1, lookup address of
+ ((uintptr_t) &global) + 1. Verify symdata.val and symdata.size
+ values.
+
+ * atomic.c: Include sys/types.h.
+
+2013-11-18 Ian Lance Taylor <iant@google.com>
+
+ * configure.ac: Check for support of __atomic extensions.
+ * internal.h: Declare or #define atomic functions for use in
+ backtrace code.
+ * atomic.c: New file.
+ * dwarf.c (dwarf_lookup_pc): Use atomic functions.
+ (dwarf_fileline, backtrace_dwarf_add): Likewise.
+ * elf.c (elf_add_syminfo_data, elf_syminfo): Likewise.
+ (backtrace_initialize): Likewise.
+ * fileline.c (fileline_initialize): Likewise.
+ * Makefile.am (libbacktrace_la_SOURCES): Add atomic.c.
+ * configure, config.h.in, Makefile.in: Rebuild.
+
+2013-11-18 Jakub Jelinek <jakub@redhat.com>
+
+ * elf.c (SHN_UNDEF): Define.
+ (elf_initialize_syminfo): Add base_address argument. Ignore symbols
+ with st_shndx == SHN_UNDEF. Add base_address to address fields.
+ (elf_add): Adjust caller.
+
+ * elf.c (phdr_callback): Process info->dlpi_addr == 0 normally.
+
+2013-11-16 Ian Lance Taylor <iant@google.com>
+
+ * backtrace.h (backtrace_create_state): Correct comment about
+ threading.
+
+2013-11-15 Ian Lance Taylor <iant@google.com>
+
+ * backtrace.h (backtrace_syminfo): Update comment and parameter
+ name to take any address, not just a PC value.
+ * elf.c (STT_OBJECT): Define.
+ (elf_nosyms): Rename parameter pc to addr.
+ (elf_symbol_search): Rename local variable pc to addr.
+ (elf_initialize_syminfo): Add STT_OBJECT symbols to elf_symbols.
+ (elf_syminfo): Rename parameter pc to addr.
+ * btest.c (global): New global variable.
+ (test5): New test.
+ (main): Call test5.
+
+2013-10-17 Ian Lance Taylor <iant@google.com>
+
+ * elf.c (elf_add): Don't get the wrong offsets if a debug section
+ is missing.
+
+2013-10-15 David Malcolm <dmalcolm@redhat.com>
+
+ * configure.ac: Add --enable-host-shared, setting up
+ pre-existing PIC_FLAG variable within Makefile.am et al.
+ * configure: Regenerate.
+
+2013-09-20 Alan Modra <amodra@gmail.com>
+
+ * configure: Regenerate.
+
2013-07-23 Alexander Monakov <amonakov@ispras.ru>
* elf.c (elf_syminfo): Loop over the elf_syminfo_data chain.
@@ -292,3 +564,9 @@
2012-09-17 Ian Lance Taylor <iant@google.com>
* Initial implementation.
+
+Copyright (C) 2012-2016 Free Software Foundation, Inc.
+
+Copying and distribution of this file, with or without modification,
+are permitted in any medium without royalty provided the copyright
+notice and this notice are preserved.
diff --git a/thirdparty/libbacktrace/alloc.c b/thirdparty/libbacktrace/alloc.c
index d0796737..a9f07a01 100644
--- a/thirdparty/libbacktrace/alloc.c
+++ b/thirdparty/libbacktrace/alloc.c
@@ -1,5 +1,5 @@
/* alloc.c -- Memory allocation without mmap.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -44,7 +44,8 @@ POSSIBILITY OF SUCH DAMAGE. */
backtrace functions may not be safely invoked from a signal
handler. */
-/* Allocate memory like malloc. */
+/* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't
+ report an error. */
void *
backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
@@ -55,7 +56,10 @@ backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
ret = malloc (size);
if (ret == NULL)
- error_callback (data, "malloc", errno);
+ {
+ if (error_callback)
+ error_callback (data, "malloc", errno);
+ }
return ret;
}
@@ -113,12 +117,24 @@ backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED,
/* Finish the current allocation on VEC. */
-void
-backtrace_vector_finish (struct backtrace_state *state ATTRIBUTE_UNUSED,
- struct backtrace_vector *vec)
+void *
+backtrace_vector_finish (struct backtrace_state *state,
+ struct backtrace_vector *vec,
+ backtrace_error_callback error_callback,
+ void *data)
{
- vec->base = (char *) vec->base + vec->size;
+ void *ret;
+
+ /* With this allocator we call realloc in backtrace_vector_grow,
+ which means we can't easily reuse the memory here. So just
+ release it. */
+ if (!backtrace_vector_release (state, vec, error_callback, data))
+ return NULL;
+ ret = vec->base;
+ vec->base = NULL;
vec->size = 0;
+ vec->alc = 0;
+ return ret;
}
/* Release any extra space allocated for VEC. */
diff --git a/thirdparty/libbacktrace/atomic.c b/thirdparty/libbacktrace/atomic.c
new file mode 100644
index 00000000..cb0ad029
--- /dev/null
+++ b/thirdparty/libbacktrace/atomic.c
@@ -0,0 +1,113 @@
+/* atomic.c -- Support for atomic functions if not present.
+ Copyright (C) 2013-2016 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 <sys/types.h>
+
+#include "backtrace.h"
+#include "backtrace-supported.h"
+#include "internal.h"
+
+/* This file holds implementations of the atomic functions that are
+ used if the host compiler has the sync functions but not the atomic
+ functions, as is true of versions of GCC before 4.7. */
+
+#if !defined (HAVE_ATOMIC_FUNCTIONS) && defined (HAVE_SYNC_FUNCTIONS)
+
+/* Do an atomic load of a pointer. */
+
+void *
+backtrace_atomic_load_pointer (void *arg)
+{
+ void **pp;
+ void *p;
+
+ pp = (void **) arg;
+ p = *pp;
+ while (!__sync_bool_compare_and_swap (pp, p, p))
+ p = *pp;
+ return p;
+}
+
+/* Do an atomic load of an int. */
+
+int
+backtrace_atomic_load_int (int *p)
+{
+ int i;
+
+ i = *p;
+ while (!__sync_bool_compare_and_swap (p, i, i))
+ i = *p;
+ return i;
+}
+
+/* Do an atomic store of a pointer. */
+
+void
+backtrace_atomic_store_pointer (void *arg, void *p)
+{
+ void **pp;
+ void *old;
+
+ pp = (void **) arg;
+ old = *pp;
+ while (!__sync_bool_compare_and_swap (pp, old, p))
+ old = *pp;
+}
+
+/* Do an atomic store of a size_t value. */
+
+void
+backtrace_atomic_store_size_t (size_t *p, size_t v)
+{
+ size_t old;
+
+ old = *p;
+ while (!__sync_bool_compare_and_swap (p, old, v))
+ old = *p;
+}
+
+/* Do an atomic store of a int value. */
+
+void
+backtrace_atomic_store_int (int *p, int v)
+{
+ size_t old;
+
+ old = *p;
+ while (!__sync_bool_compare_and_swap (p, old, v))
+ old = *p;
+}
+
+#endif
diff --git a/thirdparty/libbacktrace/backtrace-supported.h.in b/thirdparty/libbacktrace/backtrace-supported.h.in
index c615f640..ab34199f 100644
--- a/thirdparty/libbacktrace/backtrace-supported.h.in
+++ b/thirdparty/libbacktrace/backtrace-supported.h.in
@@ -1,5 +1,5 @@
/* backtrace-supported.h.in -- Whether stack backtrace is supported.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -59,3 +59,8 @@ POSSIBILITY OF SUCH DAMAGE. */
as 0. */
#define BACKTRACE_SUPPORTS_THREADS @BACKTRACE_SUPPORTS_THREADS@
+
+/* BACKTRACE_SUPPORTS_DATA will be #defined'd as 1 if the backtrace_syminfo
+ will work for variables. It will always work for functions. */
+
+#define BACKTRACE_SUPPORTS_DATA @BACKTRACE_SUPPORTS_DATA@
diff --git a/thirdparty/libbacktrace/backtrace.c b/thirdparty/libbacktrace/backtrace.c
index 428f53a2..b89bf554 100644
--- a/thirdparty/libbacktrace/backtrace.c
+++ b/thirdparty/libbacktrace/backtrace.c
@@ -1,5 +1,5 @@
/* backtrace.c -- Entry point for stack backtrace library.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -32,8 +32,11 @@ POSSIBILITY OF SUCH DAMAGE. */
#include "config.h"
+#include <sys/types.h>
+
#include "unwind.h"
#include "backtrace.h"
+#include "internal.h"
/* The main backtrace_full routine. */
@@ -53,6 +56,8 @@ struct backtrace_data
void *data;
/* Value to return from backtrace_full. */
int ret;
+ /* Whether there is any memory available. */
+ int can_alloc;
};
/* Unwind library callback routine. This is passed to
@@ -80,8 +85,11 @@ unwind (struct _Unwind_Context *context, void *vdata)
if (!ip_before_insn)
--pc;
- bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback,
- bdata->error_callback, bdata->data);
+ if (!bdata->can_alloc)
+ bdata->ret = bdata->callback (bdata->data, pc, NULL, 0, NULL);
+ else
+ bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback,
+ bdata->error_callback, bdata->data);
if (bdata->ret != 0)
return _URC_END_OF_STACK;
@@ -96,6 +104,7 @@ backtrace_full (struct backtrace_state *state, int skip,
backtrace_error_callback error_callback, void *data)
{
struct backtrace_data bdata;
+ void *p;
bdata.skip = skip + 1;
bdata.state = state;
@@ -103,6 +112,18 @@ backtrace_full (struct backtrace_state *state, int skip,
bdata.error_callback = error_callback;
bdata.data = data;
bdata.ret = 0;
+
+ /* If we can't allocate any memory at all, don't try to produce
+ file/line information. */
+ p = backtrace_alloc (state, 4096, NULL, NULL);
+ if (p == NULL)
+ bdata.can_alloc = 0;
+ else
+ {
+ backtrace_free (state, p, 4096, NULL, NULL);
+ bdata.can_alloc = 1;
+ }
+
_Unwind_Backtrace (unwind, &bdata);
return bdata.ret;
}
diff --git a/thirdparty/libbacktrace/backtrace.h b/thirdparty/libbacktrace/backtrace.h
index da16e3d7..d209219d 100644
--- a/thirdparty/libbacktrace/backtrace.h
+++ b/thirdparty/libbacktrace/backtrace.h
@@ -1,5 +1,5 @@
/* backtrace.h -- Public header file for stack backtrace library.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -89,8 +89,7 @@ typedef void (*backtrace_error_callback) (void *data, const char *msg,
system-specific path names. If not NULL, FILENAME must point to a
permanent buffer. If THREADED is non-zero the state may be
accessed by multiple threads simultaneously, and the library will
- use appropriate locks (this requires that the library be configured
- with --enable-backtrace-threads). If THREADED is zero the state
+ use appropriate atomic operations. If THREADED is zero the state
may only be accessed by one thread at a time. This returns a state
pointer on success, NULL on error. If an error occurs, this will
call the ERROR_CALLBACK routine. */
@@ -170,24 +169,25 @@ extern int backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,
/* The type of the callback argument to backtrace_syminfo. DATA and
PC are the arguments passed to backtrace_syminfo. SYMNAME is the
name of the symbol for the corresponding code. SYMVAL is the
- value. SYMNAME will be NULL if no error occurred but the symbol
- could not be found. */
+ value and SYMSIZE is the size of the symbol. SYMNAME will be NULL
+ if no error occurred but the symbol could not be found. */
typedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc,
const char *symname,
- uintptr_t symval);
-
-/* Given PC, a program counter in the current program, call the
- callback information with the symbol name and value describing the
- function in which PC may be found. This will call either CALLBACK
- or ERROR_CALLBACK exactly once. This returns 1 on success, 0 on
- failure. This function requires the symbol table but does not
- require the debug info. Note that if the symbol table is present
- but PC could not be found in the table, CALLBACK will be called
- with a NULL SYMNAME argument. Returns 1 on success, 0 on
- error. */
-
-extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
+ uintptr_t symval,
+ uintptr_t symsize);
+
+/* Given ADDR, an address or program counter in the current program,
+ call the callback information with the symbol name and value
+ describing the function or variable in which ADDR may be found.
+ This will call either CALLBACK or ERROR_CALLBACK exactly once.
+ This returns 1 on success, 0 on failure. This function requires
+ the symbol table but does not require the debug info. Note that if
+ the symbol table is present but ADDR could not be found in the
+ table, CALLBACK will be called with a NULL SYMNAME argument.
+ Returns 1 on success, 0 on error. */
+
+extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t addr,
backtrace_syminfo_callback callback,
backtrace_error_callback error_callback,
void *data);
diff --git a/thirdparty/libbacktrace/btest.c b/thirdparty/libbacktrace/btest.c
index cc647b8d..0506d2b1 100644
--- a/thirdparty/libbacktrace/btest.c
+++ b/thirdparty/libbacktrace/btest.c
@@ -1,5 +1,5 @@
/* btest.c -- Test for libbacktrace library
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -92,7 +92,7 @@ struct sdata
struct symdata
{
const char *name;
- uintptr_t val;
+ uintptr_t val, size;
int failed;
};
@@ -129,6 +129,13 @@ check (const char *name, int index, const struct info *all, int want_lineno,
{
if (*failed)
return;
+ if (all[index].filename == NULL || all[index].function == NULL)
+ {
+ fprintf (stderr, "%s: [%d]: missing file name or function name\n",
+ name, index);
+ *failed = 1;
+ return;
+ }
if (strcmp (base (all[index].filename), "btest.c") != 0)
{
fprintf (stderr, "%s: [%d]: got %s expected test.c\n", name, index,
@@ -238,7 +245,8 @@ error_callback_two (void *vdata, const char *msg, int errnum)
static void
callback_three (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
- const char *symname, uintptr_t symval)
+ const char *symname, uintptr_t symval,
+ uintptr_t symsize)
{
struct symdata *data = (struct symdata *) vdata;
@@ -250,6 +258,7 @@ callback_three (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
assert (data->name != NULL);
}
data->val = symval;
+ data->size = symsize;
}
/* The backtrace_syminfo error callback function. */
@@ -308,6 +317,14 @@ f3 (int f1line, int f2line)
data.failed = 1;
}
+ if (data.index < 3)
+ {
+ fprintf (stderr,
+ "test1: not enough frames; got %zu, expected at least 3\n",
+ data.index);
+ data.failed = 1;
+ }
+
check ("test1", 0, all, f3line, "f3", &data.failed);
check ("test1", 1, all, f2line, "f2", &data.failed);
check ("test1", 2, all, f1line, "test1", &data.failed);
@@ -458,6 +475,7 @@ f23 (int f1line, int f2line)
symdata.name = NULL;
symdata.val = 0;
+ symdata.size = 0;
symdata.failed = 0;
i = backtrace_syminfo (state, addrs[j], callback_three,
@@ -598,6 +616,78 @@ f33 (int f1line, int f2line)
return failures;
}
+#if BACKTRACE_SUPPORTS_DATA
+
+int global = 1;
+
+static 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 (strcmp (symdata.name, "global") != 0)
+ {
+ 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;
+}
+
+#endif /* BACKTRACE_SUPPORTS_DATA */
+
static void
error_callback_create (void *data ATTRIBUTE_UNUSED, const char *msg,
int errnum)
@@ -622,6 +712,9 @@ main (int argc ATTRIBUTE_UNUSED, char **argv)
test2 ();
test3 ();
test4 ();
+#if BACKTRACE_SUPPORTS_DATA
+ test5 ();
+#endif
#endif
exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
diff --git a/thirdparty/libbacktrace/config.h.in.cmake b/thirdparty/libbacktrace/config.h.in.cmake
index 4ac13266..876ea359 100644
--- a/thirdparty/libbacktrace/config.h.in.cmake
+++ b/thirdparty/libbacktrace/config.h.in.cmake
@@ -1,6 +1,9 @@
/* ELF size: 32 or 64 */
#define BACKTRACE_ELF_SIZE @BACKTRACE_ELF_SIZE@
+/* Define to 1 if you have the __atomic functions */
+#cmakedefine HAVE_ATOMIC_FUNCTIONS 1
+
/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
don't. */
#cmakedefine HAVE_DECL_STRNLEN 1
diff --git a/thirdparty/libbacktrace/dwarf.c b/thirdparty/libbacktrace/dwarf.c
index 501afe55..55b8d7dc 100644
--- a/thirdparty/libbacktrace/dwarf.c
+++ b/thirdparty/libbacktrace/dwarf.c
@@ -1,5 +1,5 @@
/* dwarf.c -- Get file/line information from DWARF for backtraces.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -211,6 +211,10 @@ struct line
const char *filename;
/* Line number. */
int lineno;
+ /* Index of the object in the original array read from the DWARF
+ section, before it has been sorted. The index makes it possible
+ to use Quicksort and maintain stability. */
+ int idx;
};
/* A growable vector of line number information. This is used while
@@ -940,9 +944,10 @@ unit_addrs_search (const void *vkey, const void *ventry)
return 0;
}
-/* Sort the line vector by PC. We want a stable sort here. We know
- that the pointers are into the same array, so it is safe to compare
- them directly. */
+/* Sort the line vector by PC. We want a stable sort here to maintain
+ the order of lines for the same PC values. Since the sequence is
+ being sorted in place, their addresses cannot be relied on to
+ maintain stability. That is the purpose of the index member. */
static int
line_compare (const void *v1, const void *v2)
@@ -954,9 +959,9 @@ line_compare (const void *v1, const void *v2)
return -1;
else if (ln1->pc > ln2->pc)
return 1;
- else if (ln1 < ln2)
+ else if (ln1->idx < ln2->idx)
return -1;
- else if (ln1 > ln2)
+ else if (ln1->idx > ln2->idx)
return 1;
else
return 0;
@@ -1134,8 +1139,8 @@ read_abbrevs (struct backtrace_state *state, uint64_t abbrev_offset,
++num_abbrevs;
}
- qsort (abbrevs->abbrevs, abbrevs->num_abbrevs, sizeof (struct abbrev),
- abbrev_compare);
+ backtrace_qsort (abbrevs->abbrevs, abbrevs->num_abbrevs,
+ sizeof (struct abbrev), abbrev_compare);
return 1;
@@ -1235,54 +1240,24 @@ add_unit_ranges (struct backtrace_state *state, uintptr_t base_address,
return 1;
}
-/* Build a mapping from address ranges to the compilation units where
- the line number information for that range can be found. Returns 1
- on success, 0 on failure. */
+/* Find the address range covered by a compilation unit, reading from
+ UNIT_BUF and adding values to U. Returns 1 if all data could be
+ read, 0 if there is some error. */
static int
-build_address_map (struct backtrace_state *state, uintptr_t base_address,
- const unsigned char *dwarf_info, size_t dwarf_info_size,
- const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
- const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
- const unsigned char *dwarf_str, size_t dwarf_str_size,
- int is_bigendian, backtrace_error_callback error_callback,
- void *data, struct unit_addrs_vector *addrs)
+find_address_ranges (struct backtrace_state *state, uintptr_t base_address,
+ struct dwarf_buf *unit_buf,
+ const unsigned char *dwarf_str, size_t dwarf_str_size,
+ const unsigned char *dwarf_ranges,
+ size_t dwarf_ranges_size,
+ int is_bigendian, backtrace_error_callback error_callback,
+ void *data, struct unit *u,
+ struct unit_addrs_vector *addrs)
{
- struct dwarf_buf info;
- struct abbrevs abbrevs;
-
- memset (&addrs->vec, 0, sizeof addrs->vec);
- addrs->count = 0;
-
- /* Read through the .debug_info section. FIXME: Should we use the
- .debug_aranges section? gdb and addr2line don't use it, but I'm
- not sure why. */
-
- info.name = ".debug_info";
- info.start = dwarf_info;
- info.buf = dwarf_info;
- info.left = dwarf_info_size;
- info.is_bigendian = is_bigendian;
- info.error_callback = error_callback;
- info.data = data;
- info.reported_underflow = 0;
-
- memset (&abbrevs, 0, sizeof abbrevs);
- while (info.left > 0)
+ while (unit_buf->left > 0)
{
- const unsigned char *unit_data_start;
- uint64_t len;
- int is_dwarf64;
- struct dwarf_buf unit_buf;
- int version;
- uint64_t abbrev_offset;
- const struct abbrev *abbrev;
- int addrsize;
- const unsigned char *unit_data;
- size_t unit_data_len;
- size_t unit_data_offset;
uint64_t code;
- size_t i;
+ const struct abbrev *abbrev;
uint64_t lowpc;
int have_lowpc;
uint64_t highpc;
@@ -1290,57 +1265,15 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
int highpc_is_relative;
uint64_t ranges;
int have_ranges;
- uint64_t lineoff;
- int have_lineoff;
- const char *filename;
- const char *comp_dir;
-
- if (info.reported_underflow)
- goto fail;
-
- unit_data_start = info.buf;
-
- is_dwarf64 = 0;
- len = read_uint32 (&info);
- if (len == 0xffffffff)
- {
- len = read_uint64 (&info);
- is_dwarf64 = 1;
- }
-
- unit_buf = info;
- unit_buf.left = len;
-
- if (!advance (&info, len))
- goto fail;
-
- version = read_uint16 (&unit_buf);
- if (version < 2 || version > 4)
- {
- dwarf_buf_error (&unit_buf, "unrecognized DWARF version");
- goto fail;
- }
-
- abbrev_offset = read_offset (&unit_buf, is_dwarf64);
- if (!read_abbrevs (state, abbrev_offset, dwarf_abbrev, dwarf_abbrev_size,
- is_bigendian, error_callback, data, &abbrevs))
- goto fail;
-
- addrsize = read_byte (&unit_buf);
-
- unit_data = unit_buf.buf;
- unit_data_len = unit_buf.left;
- unit_data_offset = unit_buf.buf - unit_data_start;
+ size_t i;
- /* We only look at the first attribute in the compilation unit.
- In practice this will be a DW_TAG_compile_unit which will
- tell us the PC range and where to find the line number
- information. */
+ code = read_uleb128 (unit_buf);
+ if (code == 0)
+ return 1;
- code = read_uleb128 (&unit_buf);
- abbrev = lookup_abbrev (&abbrevs, code, error_callback, data);
+ abbrev = lookup_abbrev (&u->abbrevs, code, error_callback, data);
if (abbrev == NULL)
- goto fail;
+ return 0;
lowpc = 0;
have_lowpc = 0;
@@ -1349,18 +1282,14 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
highpc_is_relative = 0;
ranges = 0;
have_ranges = 0;
- lineoff = 0;
- have_lineoff = 0;
- filename = NULL;
- comp_dir = NULL;
for (i = 0; i < abbrev->num_attrs; ++i)
{
struct attr_val val;
- if (!read_attribute (abbrev->attrs[i].form, &unit_buf, is_dwarf64,
- version, addrsize, dwarf_str, dwarf_str_size,
- &val))
- goto fail;
+ if (!read_attribute (abbrev->attrs[i].form, unit_buf,
+ u->is_dwarf64, u->version, u->addrsize,
+ dwarf_str, dwarf_str_size, &val))
+ return 0;
switch (abbrev->attrs[i].name)
{
@@ -1371,6 +1300,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
have_lowpc = 1;
}
break;
+
case DW_AT_high_pc:
if (val.encoding == ATTR_VAL_ADDRESS)
{
@@ -1384,6 +1314,7 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
highpc_is_relative = 1;
}
break;
+
case DW_AT_ranges:
if (val.encoding == ATTR_VAL_UINT
|| val.encoding == ATTR_VAL_REF_SECTION)
@@ -1392,73 +1323,46 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
have_ranges = 1;
}
break;
+
case DW_AT_stmt_list:
- if (val.encoding == ATTR_VAL_UINT
- || val.encoding == ATTR_VAL_REF_SECTION)
- {
- lineoff = val.u.uint;
- have_lineoff = 1;
- }
+ if (abbrev->tag == DW_TAG_compile_unit
+ && (val.encoding == ATTR_VAL_UINT
+ || val.encoding == ATTR_VAL_REF_SECTION))
+ u->lineoff = val.u.uint;
break;
+
case DW_AT_name:
- if (val.encoding == ATTR_VAL_STRING)
- filename = val.u.string;
+ if (abbrev->tag == DW_TAG_compile_unit
+ && val.encoding == ATTR_VAL_STRING)
+ u->filename = val.u.string;
break;
+
case DW_AT_comp_dir:
- if (val.encoding == ATTR_VAL_STRING)
- comp_dir = val.u.string;
+ if (abbrev->tag == DW_TAG_compile_unit
+ && val.encoding == ATTR_VAL_STRING)
+ u->comp_dir = val.u.string;
break;
+
default:
break;
}
}
- if (unit_buf.reported_underflow)
- goto fail;
-
- if (((have_lowpc && have_highpc) || have_ranges) && have_lineoff)
+ if (abbrev->tag == DW_TAG_compile_unit
+ || abbrev->tag == DW_TAG_subprogram)
{
- struct unit *u;
- struct unit_addrs a;
-
- u = ((struct unit *)
- backtrace_alloc (state, sizeof *u, error_callback, data));
- if (u == NULL)
- goto fail;
- u->unit_data = unit_data;
- u->unit_data_len = unit_data_len;
- u->unit_data_offset = unit_data_offset;
- u->version = version;
- u->is_dwarf64 = is_dwarf64;
- u->addrsize = addrsize;
- u->filename = filename;
- u->comp_dir = comp_dir;
- u->abs_filename = NULL;
- u->lineoff = lineoff;
- u->abbrevs = abbrevs;
- memset (&abbrevs, 0, sizeof abbrevs);
-
- /* The actual line number mappings will be read as
- needed. */
- u->lines = NULL;
- u->lines_count = 0;
- u->function_addrs = NULL;
- u->function_addrs_count = 0;
-
if (have_ranges)
{
if (!add_unit_ranges (state, base_address, u, ranges, lowpc,
is_bigendian, dwarf_ranges,
- dwarf_ranges_size, error_callback, data,
- addrs))
- {
- free_abbrevs (state, &u->abbrevs, error_callback, data);
- backtrace_free (state, u, sizeof *u, error_callback, data);
- goto fail;
- }
+ dwarf_ranges_size, error_callback,
+ data, addrs))
+ return 0;
}
- else
+ else if (have_lowpc && have_highpc)
{
+ struct unit_addrs a;
+
if (highpc_is_relative)
highpc += lowpc;
a.low = lowpc;
@@ -1467,17 +1371,146 @@ build_address_map (struct backtrace_state *state, uintptr_t base_address,
if (!add_unit_addr (state, base_address, a, error_callback, data,
addrs))
- {
- free_abbrevs (state, &u->abbrevs, error_callback, data);
- backtrace_free (state, u, sizeof *u, error_callback, data);
- goto fail;
- }
+ return 0;
}
+
+ /* If we found the PC range in the DW_TAG_compile_unit, we
+ can stop now. */
+ if (abbrev->tag == DW_TAG_compile_unit
+ && (have_ranges || (have_lowpc && have_highpc)))
+ return 1;
}
- else
+
+ if (abbrev->has_children)
+ {
+ if (!find_address_ranges (state, base_address, unit_buf,
+ dwarf_str, dwarf_str_size,
+ dwarf_ranges, dwarf_ranges_size,
+ is_bigendian, error_callback, data,
+ u, addrs))
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
+/* Build a mapping from address ranges to the compilation units where
+ the line number information for that range can be found. Returns 1
+ on success, 0 on failure. */
+
+static int
+build_address_map (struct backtrace_state *state, uintptr_t base_address,
+ const unsigned char *dwarf_info, size_t dwarf_info_size,
+ const unsigned char *dwarf_abbrev, size_t dwarf_abbrev_size,
+ const unsigned char *dwarf_ranges, size_t dwarf_ranges_size,
+ const unsigned char *dwarf_str, size_t dwarf_str_size,
+ int is_bigendian, backtrace_error_callback error_callback,
+ void *data, struct unit_addrs_vector *addrs)
+{
+ struct dwarf_buf info;
+ struct abbrevs abbrevs;
+
+ memset (&addrs->vec, 0, sizeof addrs->vec);
+ addrs->count = 0;
+
+ /* Read through the .debug_info section. FIXME: Should we use the
+ .debug_aranges section? gdb and addr2line don't use it, but I'm
+ not sure why. */
+
+ info.name = ".debug_info";
+ info.start = dwarf_info;
+ info.buf = dwarf_info;
+ info.left = dwarf_info_size;
+ info.is_bigendian = is_bigendian;
+ info.error_callback = error_callback;
+ info.data = data;
+ info.reported_underflow = 0;
+
+ memset (&abbrevs, 0, sizeof abbrevs);
+ while (info.left > 0)
+ {
+ const unsigned char *unit_data_start;
+ uint64_t len;
+ int is_dwarf64;
+ struct dwarf_buf unit_buf;
+ int version;
+ uint64_t abbrev_offset;
+ int addrsize;
+ struct unit *u;
+
+ if (info.reported_underflow)
+ goto fail;
+
+ unit_data_start = info.buf;
+
+ is_dwarf64 = 0;
+ len = read_uint32 (&info);
+ if (len == 0xffffffff)
+ {
+ len = read_uint64 (&info);
+ is_dwarf64 = 1;
+ }
+
+ unit_buf = info;
+ unit_buf.left = len;
+
+ if (!advance (&info, len))
+ goto fail;
+
+ version = read_uint16 (&unit_buf);
+ if (version < 2 || version > 4)
{
- free_abbrevs (state, &abbrevs, error_callback, data);
- memset (&abbrevs, 0, sizeof abbrevs);
+ dwarf_buf_error (&unit_buf, "unrecognized DWARF version");
+ goto fail;
+ }
+
+ abbrev_offset = read_offset (&unit_buf, is_dwarf64);
+ if (!read_abbrevs (state, abbrev_offset, dwarf_abbrev, dwarf_abbrev_size,
+ is_bigendian, error_callback, data, &abbrevs))
+ goto fail;
+
+ addrsize = read_byte (&unit_buf);
+
+ u = ((struct unit *)
+ backtrace_alloc (state, sizeof *u, error_callback, data));
+ if (u == NULL)
+ goto fail;
+ u->unit_data = unit_buf.buf;
+ u->unit_data_len = unit_buf.left;
+ u->unit_data_offset = unit_buf.buf - unit_data_start;
+ u->version = version;
+ u->is_dwarf64 = is_dwarf64;
+ u->addrsize = addrsize;
+ u->filename = NULL;
+ u->comp_dir = NULL;
+ u->abs_filename = NULL;
+ u->lineoff = 0;
+ u->abbrevs = abbrevs;
+ memset (&abbrevs, 0, sizeof abbrevs);
+
+ /* The actual line number mappings will be read as needed. */
+ u->lines = NULL;
+ u->lines_count = 0;
+ u->function_addrs = NULL;
+ u->function_addrs_count = 0;
+
+ if (!find_address_ranges (state, base_address, &unit_buf,
+ dwarf_str, dwarf_str_size,
+ dwarf_ranges, dwarf_ranges_size,
+ is_bigendian, error_callback, data,
+ u, addrs))
+ {
+ free_abbrevs (state, &u->abbrevs, error_callback, data);
+ backtrace_free (state, u, sizeof *u, error_callback, data);
+ goto fail;
+ }
+
+ if (unit_buf.reported_underflow)
+ {
+ free_abbrevs (state, &u->abbrevs, error_callback, data);
+ backtrace_free (state, u, sizeof *u, error_callback, data);
+ goto fail;
}
}
if (info.reported_underflow)
@@ -1523,6 +1556,7 @@ add_line (struct backtrace_state *state, struct dwarf_data *ddata,
ln->filename = filename;
ln->lineno = lineno;
+ ln->idx = vec->count;
++vec->count;
@@ -1983,12 +2017,13 @@ read_line_info (struct backtrace_state *state, struct dwarf_data *ddata,
ln->pc = (uintptr_t) -1;
ln->filename = NULL;
ln->lineno = 0;
+ ln->idx = 0;
if (!backtrace_vector_release (state, &vec.vec, error_callback, data))
goto fail;
ln = (struct line *) vec.vec.base;
- qsort (ln, vec.count, sizeof (struct line), line_compare);
+ backtrace_qsort (ln, vec.count, sizeof (struct line), line_compare);
*lines = ln;
*lines_count = vec.count;
@@ -2215,7 +2250,8 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
struct unit *u, uint64_t base, struct dwarf_buf *unit_buf,
const struct line_header *lhdr,
backtrace_error_callback error_callback, void *data,
- struct function_vector *vec)
+ struct function_vector *vec_function,
+ struct function_vector *vec_inlined)
{
while (unit_buf->left > 0)
{
@@ -2223,6 +2259,7 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
const struct abbrev *abbrev;
int is_function;
struct function *function;
+ struct function_vector *vec;
size_t i;
uint64_t lowpc;
int have_lowpc;
@@ -2244,6 +2281,11 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
|| abbrev->tag == DW_TAG_entry_point
|| abbrev->tag == DW_TAG_inlined_subroutine);
+ if (abbrev->tag == DW_TAG_inlined_subroutine)
+ vec = vec_inlined;
+ else
+ vec = vec_function;
+
function = NULL;
if (is_function)
{
@@ -2423,7 +2465,8 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
if (!is_function)
{
if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,
- error_callback, data, vec))
+ error_callback, data, vec_function,
+ vec_inlined))
return 0;
}
else
@@ -2436,7 +2479,8 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
memset (&fvec, 0, sizeof fvec);
if (!read_function_entry (state, ddata, u, base, unit_buf, lhdr,
- error_callback, data, &fvec))
+ error_callback, data, vec_function,
+ &fvec))
return 0;
if (fvec.count > 0)
@@ -2448,9 +2492,9 @@ read_function_entry (struct backtrace_state *state, struct dwarf_data *ddata,
return 0;
faddrs = (struct function_addrs *) fvec.vec.base;
- qsort (faddrs, fvec.count,
- sizeof (struct function_addrs),
- function_addrs_compare);
+ backtrace_qsort (faddrs, fvec.count,
+ sizeof (struct function_addrs),
+ function_addrs_compare);
function->function_addrs = faddrs;
function->function_addrs_count = fvec.count;
@@ -2500,31 +2544,35 @@ read_function_info (struct backtrace_state *state, struct dwarf_data *ddata,
while (unit_buf.left > 0)
{
if (!read_function_entry (state, ddata, u, 0, &unit_buf, lhdr,
- error_callback, data, pfvec))
+ error_callback, data, pfvec, pfvec))
return;
}
if (pfvec->count == 0)
return;
- addrs = (struct function_addrs *) pfvec->vec.base;
addrs_count = pfvec->count;
if (fvec == NULL)
{
if (!backtrace_vector_release (state, &lvec.vec, error_callback, data))
return;
+ addrs = (struct function_addrs *) pfvec->vec.base;
}
else
{
/* Finish this list of addresses, but leave the remaining space in
the vector available for the next function unit. */
- backtrace_vector_finish (state, &fvec->vec);
+ addrs = ((struct function_addrs *)
+ backtrace_vector_finish (state, &fvec->vec,
+ error_callback, data));
+ if (addrs == NULL)
+ return;
fvec->count = 0;
}
- qsort (addrs, addrs_count, sizeof (struct function_addrs),
- function_addrs_compare);
+ backtrace_qsort (addrs, addrs_count, sizeof (struct function_addrs),
+ function_addrs_compare);
*ret_addrs = addrs;
*ret_addrs_count = addrs_count;
@@ -2643,12 +2691,7 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
&& pc < (entry - 1)->high)
{
if (state->threaded)
- {
- /* Use __sync_bool_compare_and_swap to do a
- load-acquire. */
- while (!__sync_bool_compare_and_swap (&u->lines, lines, lines))
- lines = u->lines;
- }
+ lines = (struct line *) backtrace_atomic_load_pointer (&u->lines);
if (lines != (struct line *) (uintptr_t) -1)
break;
@@ -2659,13 +2702,8 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
lines = u->lines;
}
- /* Do a load-acquire of u->lines. */
if (state->threaded)
- {
- /* Use __sync_bool_compare_and_swap to do an atomic load. */
- while (!__sync_bool_compare_and_swap (&u->lines, lines, lines))
- lines = u->lines;
- }
+ lines = backtrace_atomic_load_pointer (&u->lines);
new_data = 0;
if (lines == NULL)
@@ -2713,12 +2751,11 @@ dwarf_lookup_pc (struct backtrace_state *state, struct dwarf_data *ddata,
}
else
{
- __sync_bool_compare_and_swap (&u->lines_count, 0, count);
- __sync_bool_compare_and_swap (&u->function_addrs, NULL,
- function_addrs);
- __sync_bool_compare_and_swap (&u->function_addrs_count, 0,
- function_addrs_count);
- __sync_bool_compare_and_swap (&u->lines, NULL, lines);
+ backtrace_atomic_store_size_t (&u->lines_count, count);
+ backtrace_atomic_store_pointer (&u->function_addrs, function_addrs);
+ backtrace_atomic_store_size_t (&u->function_addrs_count,
+ function_addrs_count);
+ backtrace_atomic_store_pointer (&u->lines, lines);
}
}
@@ -2849,11 +2886,7 @@ dwarf_fileline (struct backtrace_state *state, uintptr_t pc,
pp = (struct dwarf_data **) (void *) &state->fileline_data;
while (1)
{
- ddata = *pp;
- /* Atomic load. */
- while (!__sync_bool_compare_and_swap (pp, ddata, ddata))
- ddata = *pp;
-
+ ddata = backtrace_atomic_load_pointer (pp);
if (ddata == NULL)
break;
@@ -2906,7 +2939,8 @@ build_dwarf_data (struct backtrace_state *state,
return NULL;
addrs = (struct unit_addrs *) addrs_vec.vec.base;
addrs_count = addrs_vec.count;
- qsort (addrs, addrs_count, sizeof (struct unit_addrs), unit_addrs_compare);
+ backtrace_qsort (addrs, addrs_count, sizeof (struct unit_addrs),
+ unit_addrs_compare);
fdata = ((struct dwarf_data *)
backtrace_alloc (state, sizeof (struct dwarf_data),
@@ -2985,10 +3019,7 @@ backtrace_dwarf_add (struct backtrace_state *state,
{
struct dwarf_data *p;
- /* Atomic load. */
- p = *pp;
- while (!__sync_bool_compare_and_swap (pp, p, p))
- p = *pp;
+ p = backtrace_atomic_load_pointer (pp);
if (p == NULL)
break;
diff --git a/thirdparty/libbacktrace/elf.c b/thirdparty/libbacktrace/elf.c
index c1dbc549..05cc5c04 100644
--- a/thirdparty/libbacktrace/elf.c
+++ b/thirdparty/libbacktrace/elf.c
@@ -1,5 +1,5 @@
/* elf.c -- Get debug data from an ELF file for backtraces.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -96,11 +96,14 @@ dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
#undef ELFDATA2LSB
#undef ELFDATA2MSB
#undef EV_CURRENT
+#undef ET_DYN
#undef SHN_LORESERVE
#undef SHN_XINDEX
+#undef SHN_UNDEF
#undef SHT_SYMTAB
#undef SHT_STRTAB
#undef SHT_DYNSYM
+#undef STT_OBJECT
#undef STT_FUNC
/* Basic types. */
@@ -169,6 +172,8 @@ typedef struct {
#define EV_CURRENT 1
+#define ET_DYN 3
+
typedef struct {
b_elf_word sh_name; /* Section name, index in string tbl */
b_elf_word sh_type; /* Type of section */
@@ -182,6 +187,7 @@ typedef struct {
b_elf_wxword sh_entsize; /* Entry size if section holds table */
} b_elf_shdr; /* Elf_Shdr. */
+#define SHN_UNDEF 0x0000 /* Undefined section */
#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */
#define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */
@@ -215,6 +221,7 @@ typedef struct
#endif /* BACKTRACE_ELF_SIZE != 32 */
+#define STT_OBJECT 1
#define STT_FUNC 2
/* An index of ELF sections we care about. */
@@ -293,7 +300,7 @@ elf_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
static void
elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
- uintptr_t pc ATTRIBUTE_UNUSED,
+ uintptr_t addr ATTRIBUTE_UNUSED,
backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
backtrace_error_callback error_callback, void *data)
{
@@ -316,7 +323,7 @@ elf_symbol_compare (const void *v1, const void *v2)
return 0;
}
-/* Compare a PC against an elf_symbol for bsearch. We allocate one
+/* Compare an ADDR against an elf_symbol for bsearch. We allocate one
extra entry in the array so that this can look safely at the next
entry. */
@@ -325,12 +332,12 @@ elf_symbol_search (const void *vkey, const void *ventry)
{
const uintptr_t *key = (const uintptr_t *) vkey;
const struct elf_symbol *entry = (const struct elf_symbol *) ventry;
- uintptr_t pc;
+ uintptr_t addr;
- pc = *key;
- if (pc < entry->address)
+ addr = *key;
+ if (addr < entry->address)
return -1;
- else if (pc >= entry->address + entry->size)
+ else if (addr >= entry->address + entry->size)
return 1;
else
return 0;
@@ -340,6 +347,7 @@ elf_symbol_search (const void *vkey, const void *ventry)
static int
elf_initialize_syminfo (struct backtrace_state *state,
+ uintptr_t base_address,
const unsigned char *symtab_data, size_t symtab_size,
const unsigned char *strtab, size_t strtab_size,
backtrace_error_callback error_callback,
@@ -360,7 +368,11 @@ elf_initialize_syminfo (struct backtrace_state *state,
elf_symbol_count = 0;
for (i = 0; i < sym_count; ++i, ++sym)
{
- if ((sym->st_info & 0xf) == STT_FUNC)
+ int info;
+
+ info = sym->st_info & 0xf;
+ if ((info == STT_FUNC || info == STT_OBJECT)
+ && sym->st_shndx != SHN_UNDEF)
++elf_symbol_count;
}
@@ -375,7 +387,12 @@ elf_initialize_syminfo (struct backtrace_state *state,
j = 0;
for (i = 0; i < sym_count; ++i, ++sym)
{
- if ((sym->st_info & 0xf) != STT_FUNC)
+ int info;
+
+ info = sym->st_info & 0xf;
+ if (info != STT_FUNC && info != STT_OBJECT)
+ continue;
+ if (sym->st_shndx == SHN_UNDEF)
continue;
if (sym->st_name >= strtab_size)
{
@@ -385,13 +402,13 @@ elf_initialize_syminfo (struct backtrace_state *state,
return 0;
}
elf_symbols[j].name = (const char *) strtab + sym->st_name;
- elf_symbols[j].address = sym->st_value;
+ elf_symbols[j].address = sym->st_value + base_address;
elf_symbols[j].size = sym->st_size;
++j;
}
- qsort (elf_symbols, elf_symbol_count, sizeof (struct elf_symbol),
- elf_symbol_compare);
+ backtrace_qsort (elf_symbols, elf_symbol_count, sizeof (struct elf_symbol),
+ elf_symbol_compare);
sdata->next = NULL;
sdata->symbols = elf_symbols;
@@ -428,10 +445,7 @@ elf_add_syminfo_data (struct backtrace_state *state,
{
struct elf_syminfo_data *p;
- /* Atomic load. */
- p = *pp;
- while (!__sync_bool_compare_and_swap (pp, p, p))
- p = *pp;
+ p = backtrace_atomic_load_pointer (pp);
if (p == NULL)
break;
@@ -445,10 +459,10 @@ elf_add_syminfo_data (struct backtrace_state *state,
}
}
-/* Return the symbol name and value for a PC. */
+/* Return the symbol name and value for an ADDR. */
static void
-elf_syminfo (struct backtrace_state *state, uintptr_t pc,
+elf_syminfo (struct backtrace_state *state, uintptr_t addr,
backtrace_syminfo_callback callback,
backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
void *data)
@@ -463,7 +477,7 @@ elf_syminfo (struct backtrace_state *state, uintptr_t pc,
edata = edata->next)
{
sym = ((struct elf_symbol *)
- bsearch (&pc, edata->symbols, edata->count,
+ bsearch (&addr, edata->symbols, edata->count,
sizeof (struct elf_symbol), elf_symbol_search));
if (sym != NULL)
break;
@@ -476,16 +490,12 @@ elf_syminfo (struct backtrace_state *state, uintptr_t pc,
pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
while (1)
{
- edata = *pp;
- /* Atomic load. */
- while (!__sync_bool_compare_and_swap (pp, edata, edata))
- edata = *pp;
-
+ edata = backtrace_atomic_load_pointer (pp);
if (edata == NULL)
break;
sym = ((struct elf_symbol *)
- bsearch (&pc, edata->symbols, edata->count,
+ bsearch (&addr, edata->symbols, edata->count,
sizeof (struct elf_symbol), elf_symbol_search));
if (sym != NULL)
break;
@@ -495,17 +505,21 @@ elf_syminfo (struct backtrace_state *state, uintptr_t pc,
}
if (sym == NULL)
- callback (data, pc, NULL, 0);
+ callback (data, addr, NULL, 0, 0);
else
- callback (data, pc, sym->name, sym->address);
+ callback (data, addr, sym->name, sym->address, sym->size);
}
-/* Add the backtrace data for one ELF file. */
+/* 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
+ elf_add will need to be called on the descriptor again after
+ base_address is determined. */
static int
elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
backtrace_error_callback error_callback, void *data,
- fileline *fileline_fn, int *found_sym, int *found_dwarf)
+ fileline *fileline_fn, int *found_sym, int *found_dwarf, int exe)
{
struct backtrace_view ehdr_view;
b_elf_ehdr ehdr;
@@ -584,6 +598,12 @@ elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
goto fail;
}
+ /* If the executable is ET_DYN, it is either a PIE, or we are running
+ directly a shared library with .interp. We need to wait for
+ dl_iterate_phdr in that case to determine the actual base_address. */
+ if (exe && ehdr.e_type == ET_DYN)
+ return -1;
+
shoff = ehdr.e_shoff;
shnum = ehdr.e_shnum;
shstrndx = ehdr.e_shstrndx;
@@ -725,7 +745,7 @@ elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
if (sdata == NULL)
goto fail;
- if (!elf_initialize_syminfo (state,
+ if (!elf_initialize_syminfo (state, base_address,
symtab_view.data, symtab_shdr->sh_size,
strtab_view.data, strtab_shdr->sh_size,
error_callback, data, sdata))
@@ -759,6 +779,8 @@ elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
{
off_t end;
+ if (sections[i].size == 0)
+ continue;
if (min_offset == 0 || sections[i].offset < min_offset)
min_offset = sections[i].offset;
end = sections[i].offset + sections[i].size;
@@ -785,8 +807,13 @@ elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
descriptor = -1;
for (i = 0; i < (int) DEBUG_MAX; ++i)
- sections[i].data = ((const unsigned char *) debug_view.data
- + (sections[i].offset - min_offset));
+ {
+ if (sections[i].size == 0)
+ sections[i].data = NULL;
+ else
+ sections[i].data = ((const unsigned char *) debug_view.data
+ + (sections[i].offset - min_offset));
+ }
if (!backtrace_dwarf_add (state, base_address,
sections[DEBUG_INFO].data,
@@ -833,6 +860,7 @@ struct phdr_data
fileline *fileline_fn;
int *found_sym;
int *found_dwarf;
+ int exe_descriptor;
};
/* Callback passed to dl_iterate_phdr. Load debug info from shared
@@ -848,21 +876,32 @@ phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
fileline elf_fileline_fn;
int found_dwarf;
- /* There is not much we can do if we don't have the module name. If
- the base address is 0, this is probably the executable, which we
- already loaded. */
- if (info->dlpi_name == NULL
- || info->dlpi_name[0] == '\0'
- || info->dlpi_addr == 0)
- return 0;
+ /* There is not much we can do if we don't have the module name,
+ unless executable is ET_DYN, where we expect the very first
+ phdr_callback to be for the PIE. */
+ if (info->dlpi_name == NULL || info->dlpi_name[0] == '\0')
+ {
+ if (pd->exe_descriptor == -1)
+ return 0;
+ descriptor = pd->exe_descriptor;
+ pd->exe_descriptor = -1;
+ }
+ else
+ {
+ if (pd->exe_descriptor != -1)
+ {
+ backtrace_close (pd->exe_descriptor, pd->error_callback, pd->data);
+ pd->exe_descriptor = -1;
+ }
- descriptor = backtrace_open (info->dlpi_name, pd->error_callback, pd->data,
- &does_not_exist);
- if (descriptor < 0)
- return 0;
+ descriptor = backtrace_open (info->dlpi_name, pd->error_callback,
+ pd->data, &does_not_exist);
+ if (descriptor < 0)
+ return 0;
+ }
if (elf_add (pd->state, descriptor, info->dlpi_addr, pd->error_callback,
- pd->data, &elf_fileline_fn, pd->found_sym, &found_dwarf))
+ pd->data, &elf_fileline_fn, pd->found_sym, &found_dwarf, 0))
{
if (found_dwarf)
{
@@ -883,14 +922,15 @@ backtrace_initialize (struct backtrace_state *state, int descriptor,
backtrace_error_callback error_callback,
void *data, fileline *fileline_fn)
{
+ int ret;
int found_sym;
int found_dwarf;
- syminfo elf_syminfo_fn;
fileline elf_fileline_fn;
struct phdr_data pd;
- if (!elf_add (state, descriptor, 0, error_callback, data, &elf_fileline_fn,
- &found_sym, &found_dwarf))
+ ret = elf_add (state, descriptor, 0, error_callback, data, &elf_fileline_fn,
+ &found_sym, &found_dwarf, 1);
+ if (!ret)
return 0;
pd.state = state;
@@ -899,21 +939,24 @@ backtrace_initialize (struct backtrace_state *state, int descriptor,
pd.fileline_fn = &elf_fileline_fn;
pd.found_sym = &found_sym;
pd.found_dwarf = &found_dwarf;
+ pd.exe_descriptor = ret < 0 ? descriptor : -1;
dl_iterate_phdr (phdr_callback, (void *) &pd);
- elf_syminfo_fn = found_sym ? elf_syminfo : elf_nosyms;
if (!state->threaded)
{
- if (state->syminfo_fn == NULL || found_sym)
- state->syminfo_fn = elf_syminfo_fn;
+ if (found_sym)
+ state->syminfo_fn = elf_syminfo;
+ else if (state->syminfo_fn == NULL)
+ state->syminfo_fn = elf_nosyms;
}
else
{
- __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, elf_syminfo_fn);
if (found_sym)
- __sync_bool_compare_and_swap (&state->syminfo_fn, elf_nosyms,
- elf_syminfo_fn);
+ backtrace_atomic_store_pointer (&state->syminfo_fn, elf_syminfo);
+ else
+ (void) __sync_bool_compare_and_swap (&state->syminfo_fn, NULL,
+ elf_nosyms);
}
if (!state->threaded)
@@ -925,11 +968,7 @@ backtrace_initialize (struct backtrace_state *state, int descriptor,
{
fileline current_fn;
- /* Atomic load. */
- current_fn = state->fileline_fn;
- while (!__sync_bool_compare_and_swap (&state->fileline_fn, current_fn,
- current_fn))
- current_fn = state->fileline_fn;
+ current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
if (current_fn == NULL || current_fn == elf_nodebug)
*fileline_fn = elf_fileline_fn;
}
diff --git a/thirdparty/libbacktrace/fileline.c b/thirdparty/libbacktrace/fileline.c
index e5c39be8..27ebbedc 100644
--- a/thirdparty/libbacktrace/fileline.c
+++ b/thirdparty/libbacktrace/fileline.c
@@ -1,5 +1,5 @@
/* fileline.c -- Get file and line number information in a backtrace.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -58,15 +58,10 @@ fileline_initialize (struct backtrace_state *state,
int called_error_callback;
int descriptor;
- failed = state->fileline_initialization_failed;
-
- if (state->threaded)
- {
- /* Use __sync_bool_compare_and_swap to do an atomic load. */
- while (!__sync_bool_compare_and_swap
- (&state->fileline_initialization_failed, failed, failed))
- failed = state->fileline_initialization_failed;
- }
+ if (!state->threaded)
+ failed = state->fileline_initialization_failed;
+ else
+ failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);
if (failed)
{
@@ -74,13 +69,10 @@ fileline_initialize (struct backtrace_state *state,
return 0;
}
- fileline_fn = state->fileline_fn;
- if (state->threaded)
- {
- while (!__sync_bool_compare_and_swap (&state->fileline_fn, fileline_fn,
- fileline_fn))
- fileline_fn = state->fileline_fn;
- }
+ if (!state->threaded)
+ fileline_fn = state->fileline_fn;
+ else
+ fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
if (fileline_fn != NULL)
return 1;
@@ -151,8 +143,7 @@ fileline_initialize (struct backtrace_state *state,
if (!state->threaded)
state->fileline_initialization_failed = 1;
else
- __sync_bool_compare_and_swap (&state->fileline_initialization_failed,
- 0, failed);
+ backtrace_atomic_store_int (&state->fileline_initialization_failed, 1);
return 0;
}
@@ -160,15 +151,10 @@ fileline_initialize (struct backtrace_state *state,
state->fileline_fn = fileline_fn;
else
{
- __sync_bool_compare_and_swap (&state->fileline_fn, NULL, fileline_fn);
-
- /* At this point we know that state->fileline_fn is not NULL.
- Either we stored our value, or some other thread stored its
- value. If some other thread stored its value, we leak the
- one we just initialized. Either way, state->fileline_fn is
- initialized. The compare_and_swap is a full memory barrier,
- so we should have full access to that value even if it was
- created by another thread. */
+ backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn);
+
+ /* Note that if two threads initialize at once, one of the data
+ sets may be leaked. */
}
return 1;
diff --git a/thirdparty/libbacktrace/internal.h b/thirdparty/libbacktrace/internal.h
index 1ea664a0..73728da3 100644
--- a/thirdparty/libbacktrace/internal.h
+++ b/thirdparty/libbacktrace/internal.h
@@ -1,5 +1,5 @@
/* internal.h -- Internal header file for stack backtrace library.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -65,7 +65,48 @@ POSSIBILITY OF SUCH DAMAGE. */
#define __sync_lock_test_and_set(A, B) (abort(), 0)
#define __sync_lock_release(A) abort()
-#endif /* !defined(HAVE_SYNC_FUNCTIONS) */
+#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
+
+#ifdef HAVE_ATOMIC_FUNCTIONS
+
+/* We have the atomic builtin functions. */
+
+#define backtrace_atomic_load_pointer(p) \
+ __atomic_load_n ((p), __ATOMIC_ACQUIRE)
+#define backtrace_atomic_load_int(p) \
+ __atomic_load_n ((p), __ATOMIC_ACQUIRE)
+#define backtrace_atomic_store_pointer(p, v) \
+ __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+#define backtrace_atomic_store_size_t(p, v) \
+ __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+#define backtrace_atomic_store_int(p, v) \
+ __atomic_store_n ((p), (v), __ATOMIC_RELEASE)
+
+#else /* !defined (HAVE_ATOMIC_FUNCTIONS) */
+#ifdef HAVE_SYNC_FUNCTIONS
+
+/* We have the sync functions but not the atomic functions. Define
+ the atomic ones in terms of the sync ones. */
+
+extern void *backtrace_atomic_load_pointer (void *);
+extern int backtrace_atomic_load_int (int *);
+extern void backtrace_atomic_store_pointer (void *, void *);
+extern void backtrace_atomic_store_size_t (size_t *, size_t);
+extern void backtrace_atomic_store_int (int *, int);
+
+#else /* !defined (HAVE_SYNC_FUNCTIONS) */
+
+/* We have neither the sync nor the atomic functions. These will
+ never be called. */
+
+#define backtrace_atomic_load_pointer(p) (abort(), (void *) NULL)
+#define backtrace_atomic_load_int(p) (abort(), 0)
+#define backtrace_atomic_store_pointer(p, v) abort()
+#define backtrace_atomic_store_size_t(p, v) abort()
+#define backtrace_atomic_store_int(p, v) abort()
+
+#endif /* !defined (HAVE_SYNC_FUNCTIONS) */
+#endif /* !defined (HAVE_ATOMIC_FUNCTIONS) */
/* The type of the function that collects file/line information. This
is like backtrace_pcinfo. */
@@ -155,13 +196,20 @@ extern int backtrace_close (int descriptor,
backtrace_error_callback error_callback,
void *data);
-/* Allocate memory. This is like malloc. */
+/* Sort without using memory. */
+
+extern void backtrace_qsort (void *base, size_t count, size_t size,
+ int (*compar) (const void *, const void *));
+
+/* Allocate memory. This is like malloc. If ERROR_CALLBACK is NULL,
+ this does not report an error, it just returns NULL. */
extern void *backtrace_alloc (struct backtrace_state *state, size_t size,
backtrace_error_callback error_callback,
void *data) ATTRIBUTE_MALLOC;
-/* Free memory allocated by backtrace_alloc. */
+/* Free memory allocated by backtrace_alloc. If ERROR_CALLBACK is
+ NULL, this does not report an error. */
extern void backtrace_free (struct backtrace_state *state, void *mem,
size_t size,
@@ -192,13 +240,17 @@ extern void *backtrace_vector_grow (struct backtrace_state *state, size_t size,
struct backtrace_vector *vec);
/* Finish the current allocation on VEC. Prepare to start a new
- allocation. The finished allocation will never be freed. */
+ allocation. The finished allocation will never be freed. Returns
+ a pointer to the base of the finished entries, or NULL on
+ failure. */
-extern void backtrace_vector_finish (struct backtrace_state *state,
- struct backtrace_vector *vec);
+extern void* backtrace_vector_finish (struct backtrace_state *state,
+ struct backtrace_vector *vec,
+ backtrace_error_callback error_callback,
+ void *data);
-/* Release any extra space allocated for VEC. Returns 1 on success, 0
- on failure. */
+/* Release any extra space allocated for VEC. This may change
+ VEC->base. Returns 1 on success, 0 on failure. */
extern int backtrace_vector_release (struct backtrace_state *state,
struct backtrace_vector *vec,
diff --git a/thirdparty/libbacktrace/mmap.c b/thirdparty/libbacktrace/mmap.c
index 04aae85e..0ed4802d 100644
--- a/thirdparty/libbacktrace/mmap.c
+++ b/thirdparty/libbacktrace/mmap.c
@@ -1,5 +1,5 @@
/* mmap.c -- Memory allocation with mmap.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -77,7 +77,8 @@ backtrace_free_locked (struct backtrace_state *state, void *addr, size_t size)
}
}
-/* Allocate memory like malloc. */
+/* Allocate memory like malloc. If ERROR_CALLBACK is NULL, don't
+ report an error. */
void *
backtrace_alloc (struct backtrace_state *state,
@@ -139,8 +140,11 @@ backtrace_alloc (struct backtrace_state *state,
asksize = (size + pagesize - 1) & ~ (pagesize - 1);
page = mmap (NULL, asksize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (page == NULL)
- error_callback (data, "mmap", errno);
+ if (page == MAP_FAILED)
+ {
+ if (error_callback)
+ error_callback (data, "mmap", errno);
+ }
else
{
size = (size + 7) & ~ (size_t) 7;
@@ -164,6 +168,26 @@ backtrace_free (struct backtrace_state *state, void *addr, size_t size,
{
int locked;
+ /* If we are freeing a large aligned block, just release it back to
+ the system. This case arises when growing a vector for a large
+ binary with lots of debug info. Calling munmap here may cause us
+ to call mmap again if there is also a large shared library; we
+ just live with that. */
+ if (size >= 16 * 4096)
+ {
+ size_t pagesize;
+
+ pagesize = getpagesize ();
+ if (((uintptr_t) addr & (pagesize - 1)) == 0
+ && (size & (pagesize - 1)) == 0)
+ {
+ /* If munmap fails for some reason, just add the block to
+ the freelist. */
+ if (munmap (addr, size) == 0)
+ return;
+ }
+ }
+
/* If we can acquire the lock, add the new space to the free list.
If we can't acquire the lock, just leak the memory.
__sync_lock_test_and_set returns the old state of the lock, so we
@@ -209,14 +233,18 @@ backtrace_vector_grow (struct backtrace_state *state,size_t size,
alc = pagesize;
}
else
- alc = (alc + pagesize - 1) & ~ (pagesize - 1);
+ {
+ alc *= 2;
+ alc = (alc + pagesize - 1) & ~ (pagesize - 1);
+ }
base = backtrace_alloc (state, alc, error_callback, data);
if (base == NULL)
return NULL;
if (vec->base != NULL)
{
memcpy (base, vec->base, vec->size);
- backtrace_free (state, vec->base, vec->alc, error_callback, data);
+ backtrace_free (state, vec->base, vec->size + vec->alc,
+ error_callback, data);
}
vec->base = base;
vec->alc = alc - vec->size;
@@ -230,12 +258,19 @@ backtrace_vector_grow (struct backtrace_state *state,size_t size,
/* Finish the current allocation on VEC. */
-void
-backtrace_vector_finish (struct backtrace_state *state ATTRIBUTE_UNUSED,
- struct backtrace_vector *vec)
+void *
+backtrace_vector_finish (
+ struct backtrace_state *state ATTRIBUTE_UNUSED,
+ struct backtrace_vector *vec,
+ backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED)
{
+ void *ret;
+
+ ret = vec->base;
vec->base = (char *) vec->base + vec->size;
vec->size = 0;
+ return ret;
}
/* Release any extra space allocated for VEC. */
diff --git a/thirdparty/libbacktrace/mmapio.c b/thirdparty/libbacktrace/mmapio.c
index 60c68c66..dfdaf6fa 100644
--- a/thirdparty/libbacktrace/mmapio.c
+++ b/thirdparty/libbacktrace/mmapio.c
@@ -1,5 +1,5 @@
/* mmapio.c -- File views using mmap.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/libbacktrace/nounwind.c b/thirdparty/libbacktrace/nounwind.c
index 5c8e23c9..448a2049 100644
--- a/thirdparty/libbacktrace/nounwind.c
+++ b/thirdparty/libbacktrace/nounwind.c
@@ -1,5 +1,5 @@
/* backtrace.c -- Entry point for stack backtrace library.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/libbacktrace/pecoff.c b/thirdparty/libbacktrace/pecoff.c
new file mode 100644
index 00000000..c7d32aa6
--- /dev/null
+++ b/thirdparty/libbacktrace/pecoff.c
@@ -0,0 +1,937 @@
+/* pecoff.c -- Get debug data from a PE/COFFF file for backtraces.
+ Copyright (C) 2015-2016 Free Software Foundation, Inc.
+ Adapted from elf.c by Tristan Gingold, AdaCore.
+
+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 <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* Coff file header. */
+
+typedef struct {
+ uint16_t machine;
+ uint16_t number_of_sections;
+ uint32_t time_date_stamp;
+ uint32_t pointer_to_symbol_table;
+ uint32_t number_of_symbols;
+ uint16_t size_of_optional_header;
+ uint16_t characteristics;
+} b_coff_file_header;
+
+/* Coff optional header. */
+
+typedef struct {
+ uint16_t magic;
+ uint8_t major_linker_version;
+ uint8_t minor_linker_version;
+ uint32_t size_of_code;
+ uint32_t size_of_initialized_data;
+ uint32_t size_of_uninitialized_data;
+ uint32_t address_of_entry_point;
+ uint32_t base_of_code;
+ union {
+ struct {
+ uint32_t base_of_data;
+ uint32_t image_base;
+ } pe;
+ struct {
+ uint64_t image_base;
+ } pep;
+ } u;
+} b_coff_optional_header;
+
+/* Values of magic in optional header. */
+
+#define PE_MAGIC 0x10b /* PE32 executable. */
+#define PEP_MAGIC 0x20b /* PE32+ executable (for 64bit targets). */
+
+/* Coff section header. */
+
+typedef struct {
+ char name[8];
+ uint32_t virtual_size;
+ uint32_t virtual_address;
+ uint32_t size_of_raw_data;
+ uint32_t pointer_to_raw_data;
+ uint32_t pointer_to_relocations;
+ uint32_t pointer_to_line_numbers;
+ uint16_t number_of_relocations;
+ uint16_t number_of_line_numbers;
+ uint32_t characteristics;
+} b_coff_section_header;
+
+/* Coff symbol name. */
+
+typedef union {
+ char short_name[8];
+ struct {
+ unsigned char zeroes[4];
+ unsigned char off[4];
+ } long_name;
+} b_coff_name;
+
+/* Coff symbol (external representation which is unaligned). */
+
+typedef struct {
+ b_coff_name name;
+ unsigned char value[4];
+ unsigned char section_number[2];
+ unsigned char type[2];
+ unsigned char storage_class;
+ unsigned char number_of_aux_symbols;
+} b_coff_external_symbol;
+
+/* Symbol types. */
+
+#define N_TBSHFT 4 /* Shift for the derived type. */
+#define IMAGE_SYM_DTYPE_FUNCTION 2 /* Function derived type. */
+
+/* Size of a coff symbol. */
+
+#define SYM_SZ 18
+
+/* Coff symbol, internal representation (aligned). */
+
+typedef struct {
+ const char *name;
+ uint32_t value;
+ int16_t sec;
+ uint16_t type;
+ uint16_t sc;
+} b_coff_internal_symbol;
+
+/* An index of sections we care about. */
+
+enum debug_section
+{
+ DEBUG_INFO,
+ DEBUG_LINE,
+ DEBUG_ABBREV,
+ DEBUG_RANGES,
+ DEBUG_STR,
+ DEBUG_MAX
+};
+
+/* Names of sections, indexed by enum debug_section. */
+
+static const char * const debug_section_names[DEBUG_MAX] =
+{
+ ".debug_info",
+ ".debug_line",
+ ".debug_abbrev",
+ ".debug_ranges",
+ ".debug_str"
+};
+
+/* Information we gather for the sections we care about. */
+
+struct debug_section_info
+{
+ /* Section file offset. */
+ off_t offset;
+ /* Section size. */
+ size_t size;
+ /* Section contents, after read from file. */
+ const unsigned char *data;
+};
+
+/* Information we keep for an coff symbol. */
+
+struct coff_symbol
+{
+ /* The name of the symbol. */
+ const char *name;
+ /* The address of the symbol. */
+ uintptr_t address;
+};
+
+/* Information to pass to coff_syminfo. */
+
+struct coff_syminfo_data
+{
+ /* Symbols for the next module. */
+ struct coff_syminfo_data *next;
+ /* The COFF symbols, sorted by address. */
+ struct coff_symbol *symbols;
+ /* The number of symbols. */
+ size_t count;
+};
+
+/* A dummy callback function used when we can't find any debug info. */
+
+static int
+coff_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
+ uintptr_t pc ATTRIBUTE_UNUSED,
+ backtrace_full_callback callback ATTRIBUTE_UNUSED,
+ backtrace_error_callback error_callback, void *data)
+{
+ error_callback (data, "no debug info in PE/COFF executable", -1);
+ return 0;
+}
+
+/* A dummy callback function used when we can't find a symbol
+ table. */
+
+static void
+coff_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
+ uintptr_t addr ATTRIBUTE_UNUSED,
+ backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
+ backtrace_error_callback error_callback, void *data)
+{
+ error_callback (data, "no symbol table in PE/COFF executable", -1);
+}
+
+/* Read a potentially unaligned 4 byte word at P, using native endianness. */
+
+static uint32_t
+coff_read4 (const unsigned char *p)
+{
+ uint32_t res;
+
+ memcpy (&res, p, 4);
+ return res;
+}
+
+/* Read a potentially unaligned 2 byte word at P, using native endianness.
+ All 2 byte word in symbols are always aligned, but for coherency all
+ fields are declared as char arrays. */
+
+static uint16_t
+coff_read2 (const unsigned char *p)
+{
+ uint16_t res;
+
+ memcpy (&res, p, sizeof (res));
+ return res;
+}
+
+/* Return the length (without the trailing 0) of a COFF short name. */
+
+static size_t
+coff_short_name_len (const char *name)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ if (name[i] == 0)
+ return i;
+ return 8;
+}
+
+/* Return true iff COFF short name CNAME is the same as NAME (a NUL-terminated
+ string). */
+
+static int
+coff_short_name_eq (const char *name, const char *cname)
+{
+ int i;
+
+ for (i = 0; i < 8; i++)
+ {
+ if (name[i] != cname[i])
+ return 0;
+ if (name[i] == 0)
+ return 1;
+ }
+ return name[8] == 0;
+}
+
+/* Return true iff NAME is the same as string at offset OFF. */
+
+static int
+coff_long_name_eq (const char *name, unsigned int off,
+ struct backtrace_view *str_view)
+{
+ if (off >= str_view->len)
+ return 0;
+ return strcmp (name, (const char *)str_view->data + off) == 0;
+}
+
+/* Compare struct coff_symbol for qsort. */
+
+static int
+coff_symbol_compare (const void *v1, const void *v2)
+{
+ const struct coff_symbol *e1 = (const struct coff_symbol *) v1;
+ const struct coff_symbol *e2 = (const struct coff_symbol *) v2;
+
+ if (e1->address < e2->address)
+ return -1;
+ else if (e1->address > e2->address)
+ return 1;
+ else
+ return 0;
+}
+
+/* Convert SYM to internal (and aligned) format ISYM, using string table
+ from STRTAB and STRTAB_SIZE, and number of sections SECTS_NUM.
+ Return -1 in case of error (invalid section number or string index). */
+
+static int
+coff_expand_symbol (b_coff_internal_symbol *isym,
+ const b_coff_external_symbol *sym,
+ uint16_t sects_num,
+ const unsigned char *strtab, size_t strtab_size)
+{
+ isym->type = coff_read2 (sym->type);
+ isym->sec = coff_read2 (sym->section_number);
+ isym->sc = sym->storage_class;
+
+ if (isym->sec > 0 && (uint16_t) isym->sec > sects_num)
+ return -1;
+ if (sym->name.short_name[0] != 0)
+ isym->name = sym->name.short_name;
+ else
+ {
+ uint32_t off = coff_read4 (sym->name.long_name.off);
+
+ if (off >= strtab_size)
+ return -1;
+ isym->name = (const char *) strtab + off;
+ }
+ return 0;
+}
+
+/* Return true iff SYM is a defined symbol for a function. Data symbols
+ aren't considered because they aren't easily identified (same type as
+ section names, presence of symbols defined by the linker script). */
+
+static int
+coff_is_function_symbol (const b_coff_internal_symbol *isym)
+{
+ return (isym->type >> N_TBSHFT) == IMAGE_SYM_DTYPE_FUNCTION
+ && isym->sec > 0;
+}
+
+/* Initialize the symbol table info for coff_syminfo. */
+
+static int
+coff_initialize_syminfo (struct backtrace_state *state,
+ uintptr_t base_address,
+ const b_coff_section_header *sects, size_t sects_num,
+ const b_coff_external_symbol *syms, size_t syms_size,
+ const unsigned char *strtab, size_t strtab_size,
+ backtrace_error_callback error_callback,
+ void *data, struct coff_syminfo_data *sdata)
+{
+ size_t syms_count;
+ char *coff_symstr;
+ size_t coff_symstr_len;
+ size_t coff_symbol_count;
+ size_t coff_symbol_size;
+ struct coff_symbol *coff_symbols;
+ struct coff_symbol *coff_sym;
+ char *coff_str;
+ size_t i;
+
+ syms_count = syms_size / SYM_SZ;
+
+ /* We only care about function symbols. Count them. Also count size of
+ strings for in-symbol names. */
+ coff_symbol_count = 0;
+ coff_symstr_len = 0;
+ for (i = 0; i < syms_count; ++i)
+ {
+ const b_coff_external_symbol *asym = &syms[i];
+ b_coff_internal_symbol isym;
+
+ if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size) < 0)
+ {
+ error_callback (data, "invalid section or offset in coff symbol", 0);
+ return 0;
+ }
+ if (coff_is_function_symbol (&isym))
+ {
+ ++coff_symbol_count;
+ if (asym->name.short_name[0] != 0)
+ coff_symstr_len += coff_short_name_len (asym->name.short_name) + 1;
+ }
+
+ i += asym->number_of_aux_symbols;
+ }
+
+ coff_symbol_size = (coff_symbol_count + 1) * sizeof (struct coff_symbol);
+ coff_symbols = ((struct coff_symbol *)
+ backtrace_alloc (state, coff_symbol_size, error_callback,
+ data));
+ if (coff_symbols == NULL)
+ return 0;
+
+ /* Allocate memory for symbols strings. */
+ if (coff_symstr_len > 0)
+ {
+ coff_symstr = ((char *)
+ backtrace_alloc (state, coff_symstr_len, error_callback,
+ data));
+ if (coff_symstr == NULL)
+ {
+ backtrace_free (state, coff_symbols, coff_symbol_size,
+ error_callback, data);
+ return 0;
+ }
+ }
+ else
+ coff_symstr = NULL;
+
+ /* Copy symbols. */
+ coff_sym = coff_symbols;
+ coff_str = coff_symstr;
+ for (i = 0; i < syms_count; ++i)
+ {
+ const b_coff_external_symbol *asym = &syms[i];
+ b_coff_internal_symbol isym;
+
+ if (coff_expand_symbol (&isym, asym, sects_num, strtab, strtab_size))
+ {
+ /* Should not fail, as it was already tested in the previous
+ loop. */
+ abort ();
+ }
+ if (coff_is_function_symbol (&isym))
+ {
+ const char *name;
+ int16_t secnum;
+
+ if (asym->name.short_name[0] != 0)
+ {
+ size_t len = coff_short_name_len (isym.name);
+ name = coff_str;
+ memcpy (coff_str, isym.name, len);
+ coff_str[len] = 0;
+ coff_str += len + 1;
+ }
+ else
+ name = isym.name;
+
+ /* Strip leading '_'. */
+ if (name[0] == '_')
+ name++;
+
+ /* Symbol value is section relative, so we need to read the address
+ of its section. */
+ secnum = coff_read2 (asym->section_number);
+
+ coff_sym->name = name;
+ coff_sym->address = (coff_read4 (asym->value)
+ + sects[secnum - 1].virtual_address
+ + base_address);
+ coff_sym++;
+ }
+
+ i += asym->number_of_aux_symbols;
+ }
+
+ /* End of symbols marker. */
+ coff_sym->name = NULL;
+ coff_sym->address = -1;
+
+ backtrace_qsort (coff_symbols, coff_symbol_count,
+ sizeof (struct coff_symbol), coff_symbol_compare);
+
+ sdata->next = NULL;
+ sdata->symbols = coff_symbols;
+ sdata->count = coff_symbol_count;
+
+ return 1;
+}
+
+/* Add EDATA to the list in STATE. */
+
+static void
+coff_add_syminfo_data (struct backtrace_state *state,
+ struct coff_syminfo_data *sdata)
+{
+ if (!state->threaded)
+ {
+ struct coff_syminfo_data **pp;
+
+ for (pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
+ *pp != NULL;
+ pp = &(*pp)->next)
+ ;
+ *pp = sdata;
+ }
+ else
+ {
+ while (1)
+ {
+ struct coff_syminfo_data **pp;
+
+ pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
+
+ while (1)
+ {
+ struct coff_syminfo_data *p;
+
+ p = backtrace_atomic_load_pointer (pp);
+
+ if (p == NULL)
+ break;
+
+ pp = &p->next;
+ }
+
+ if (__sync_bool_compare_and_swap (pp, NULL, sdata))
+ break;
+ }
+ }
+}
+
+/* Compare an ADDR against an elf_symbol for bsearch. We allocate one
+ extra entry in the array so that this can look safely at the next
+ entry. */
+
+static int
+coff_symbol_search (const void *vkey, const void *ventry)
+{
+ const uintptr_t *key = (const uintptr_t *) vkey;
+ const struct coff_symbol *entry = (const struct coff_symbol *) ventry;
+ uintptr_t addr;
+
+ addr = *key;
+ if (addr < entry->address)
+ return -1;
+ else if (addr >= entry[1].address)
+ return 1;
+ else
+ return 0;
+}
+
+/* Return the symbol name and value for an ADDR. */
+
+static void
+coff_syminfo (struct backtrace_state *state, uintptr_t addr,
+ backtrace_syminfo_callback callback,
+ backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
+ void *data)
+{
+ struct coff_syminfo_data *sdata;
+ struct coff_symbol *sym = NULL;
+
+ if (!state->threaded)
+ {
+ for (sdata = (struct coff_syminfo_data *) state->syminfo_data;
+ sdata != NULL;
+ sdata = sdata->next)
+ {
+ sym = ((struct coff_symbol *)
+ bsearch (&addr, sdata->symbols, sdata->count,
+ sizeof (struct coff_symbol), coff_symbol_search));
+ if (sym != NULL)
+ break;
+ }
+ }
+ else
+ {
+ struct coff_syminfo_data **pp;
+
+ pp = (struct coff_syminfo_data **) (void *) &state->syminfo_data;
+ while (1)
+ {
+ sdata = backtrace_atomic_load_pointer (pp);
+ if (sdata == NULL)
+ break;
+
+ sym = ((struct coff_symbol *)
+ bsearch (&addr, sdata->symbols, sdata->count,
+ sizeof (struct coff_symbol), coff_symbol_search));
+ if (sym != NULL)
+ break;
+
+ pp = &sdata->next;
+ }
+ }
+
+ if (sym == NULL)
+ callback (data, addr, NULL, 0, 0);
+ else
+ callback (data, addr, sym->name, sym->address, 0);
+}
+
+/* Add the backtrace data for one PE/COFF file. Returns 1 on success,
+ 0 on failure (in both cases descriptor is closed). */
+
+static int
+coff_add (struct backtrace_state *state, int descriptor,
+ backtrace_error_callback error_callback, void *data,
+ fileline *fileline_fn, int *found_sym, int *found_dwarf)
+{
+ struct backtrace_view fhdr_view;
+ off_t fhdr_off;
+ int magic_ok;
+ b_coff_file_header fhdr;
+ off_t opt_sects_off;
+ size_t opt_sects_size;
+ unsigned int sects_num;
+ struct backtrace_view sects_view;
+ int sects_view_valid;
+ const b_coff_optional_header *opt_hdr;
+ const b_coff_section_header *sects;
+ struct backtrace_view str_view;
+ int str_view_valid;
+ size_t str_size;
+ off_t str_off;
+ struct backtrace_view syms_view;
+ off_t syms_off;
+ size_t syms_size;
+ int syms_view_valid;
+ unsigned int syms_num;
+ unsigned int i;
+ struct debug_section_info sections[DEBUG_MAX];
+ off_t min_offset;
+ off_t max_offset;
+ struct backtrace_view debug_view;
+ int debug_view_valid;
+ uintptr_t image_base;
+
+ *found_sym = 0;
+ *found_dwarf = 0;
+
+ sects_view_valid = 0;
+ syms_view_valid = 0;
+ str_view_valid = 0;
+ debug_view_valid = 0;
+
+ /* Map the MS-DOS stub (if any) and extract file header offset. */
+ if (!backtrace_get_view (state, descriptor, 0, 0x40, error_callback,
+ data, &fhdr_view))
+ goto fail;
+
+ {
+ const char *vptr = (const char *)fhdr_view.data;
+
+ if (vptr[0] == 'M' && vptr[1] == 'Z')
+ memcpy (&fhdr_off, vptr + 0x3c, 4);
+ else
+ fhdr_off = 0;
+ }
+
+ backtrace_release_view (state, &fhdr_view, error_callback, data);
+
+ /* Map the coff file header. */
+ if (!backtrace_get_view (state, descriptor, fhdr_off,
+ sizeof (b_coff_file_header) + 4,
+ error_callback, data, &fhdr_view))
+ goto fail;
+
+ if (fhdr_off != 0)
+ {
+ const char *magic = (const char *) fhdr_view.data;
+ magic_ok = memcmp (magic, "PE\0", 4) == 0;
+ fhdr_off += 4;
+
+ memcpy (&fhdr, fhdr_view.data + 4, sizeof fhdr);
+ }
+ else
+ {
+ memcpy (&fhdr, fhdr_view.data, sizeof fhdr);
+ /* TODO: test fhdr.machine for coff but non-PE platforms. */
+ magic_ok = 0;
+ }
+ backtrace_release_view (state, &fhdr_view, error_callback, data);
+
+ if (!magic_ok)
+ {
+ error_callback (data, "executable file is not COFF", 0);
+ goto fail;
+ }
+
+ sects_num = fhdr.number_of_sections;
+ syms_num = fhdr.number_of_symbols;
+
+ opt_sects_off = fhdr_off + sizeof (fhdr);
+ opt_sects_size = (fhdr.size_of_optional_header
+ + sects_num * sizeof (b_coff_section_header));
+
+ /* To translate PC to file/line when using DWARF, we need to find
+ the .debug_info and .debug_line sections. */
+
+ /* Read the optional header and the section headers. */
+
+ if (!backtrace_get_view (state, descriptor, opt_sects_off, opt_sects_size,
+ error_callback, data, &sects_view))
+ goto fail;
+ sects_view_valid = 1;
+ opt_hdr = (const b_coff_optional_header *) sects_view.data;
+ sects = (const b_coff_section_header *)
+ (sects_view.data + fhdr.size_of_optional_header);
+
+ if (fhdr.size_of_optional_header > sizeof (*opt_hdr))
+ {
+ if (opt_hdr->magic == PE_MAGIC)
+ image_base = opt_hdr->u.pe.image_base;
+ else if (opt_hdr->magic == PEP_MAGIC)
+ image_base = opt_hdr->u.pep.image_base;
+ else
+ {
+ error_callback (data, "bad magic in PE optional header", 0);
+ goto fail;
+ }
+ }
+ else
+ image_base = 0;
+
+ /* Read the symbol table and the string table. */
+
+ if (fhdr.pointer_to_symbol_table == 0)
+ {
+ /* No symbol table, no string table. */
+ str_off = 0;
+ str_size = 0;
+ syms_num = 0;
+ syms_size = 0;
+ }
+ else
+ {
+ /* Symbol table is followed by the string table. The string table
+ starts with its length (on 4 bytes).
+ Map the symbol table and the length of the string table. */
+ syms_off = fhdr.pointer_to_symbol_table;
+ syms_size = syms_num * SYM_SZ;
+
+ if (!backtrace_get_view (state, descriptor, syms_off, syms_size + 4,
+ error_callback, data, &syms_view))
+ goto fail;
+ syms_view_valid = 1;
+
+ memcpy (&str_size, syms_view.data + syms_size, 4);
+
+ str_off = syms_off + syms_size;
+
+ if (str_size > 4)
+ {
+ /* Map string table (including the length word). */
+
+ if (!backtrace_get_view (state, descriptor, str_off, str_size,
+ error_callback, data, &str_view))
+ goto fail;
+ str_view_valid = 1;
+ }
+ }
+
+ memset (sections, 0, sizeof sections);
+
+ /* Look for the symbol table. */
+ for (i = 0; i < sects_num; ++i)
+ {
+ const b_coff_section_header *s = sects + i;
+ unsigned int str_off;
+ int j;
+
+ if (s->name[0] == '/')
+ {
+ /* Extended section name. */
+ str_off = atoi (s->name + 1);
+ }
+ else
+ str_off = 0;
+
+ for (j = 0; j < (int) DEBUG_MAX; ++j)
+ {
+ const char *dbg_name = debug_section_names[j];
+ int match;
+
+ if (str_off != 0)
+ match = coff_long_name_eq (dbg_name, str_off, &str_view);
+ else
+ match = coff_short_name_eq (dbg_name, s->name);
+ if (match)
+ {
+ sections[j].offset = s->pointer_to_raw_data;
+ sections[j].size = s->virtual_size <= s->size_of_raw_data ?
+ s->virtual_size : s->size_of_raw_data;
+ break;
+ }
+ }
+ }
+
+ if (syms_num != 0)
+ {
+ struct coff_syminfo_data *sdata;
+
+ sdata = ((struct coff_syminfo_data *)
+ backtrace_alloc (state, sizeof *sdata, error_callback, data));
+ if (sdata == NULL)
+ goto fail;
+
+ if (!coff_initialize_syminfo (state, image_base,
+ sects, sects_num,
+ syms_view.data, syms_size,
+ str_view.data, str_size,
+ error_callback, data, sdata))
+ {
+ backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
+ goto fail;
+ }
+
+ *found_sym = 1;
+
+ coff_add_syminfo_data (state, sdata);
+ }
+
+ backtrace_release_view (state, &sects_view, error_callback, data);
+ sects_view_valid = 0;
+ backtrace_release_view (state, &syms_view, error_callback, data);
+ syms_view_valid = 0;
+
+ /* Read all the debug sections in a single view, since they are
+ probably adjacent in the file. We never release this view. */
+
+ min_offset = 0;
+ max_offset = 0;
+ for (i = 0; i < (int) DEBUG_MAX; ++i)
+ {
+ off_t end;
+
+ if (sections[i].size == 0)
+ continue;
+ if (min_offset == 0 || sections[i].offset < min_offset)
+ min_offset = sections[i].offset;
+ end = sections[i].offset + sections[i].size;
+ if (end > max_offset)
+ max_offset = end;
+ }
+ if (min_offset == 0 || max_offset == 0)
+ {
+ if (!backtrace_close (descriptor, error_callback, data))
+ goto fail;
+ *fileline_fn = coff_nodebug;
+ return 1;
+ }
+
+ if (!backtrace_get_view (state, descriptor, min_offset,
+ max_offset - min_offset,
+ error_callback, data, &debug_view))
+ goto fail;
+ debug_view_valid = 1;
+
+ /* We've read all we need from the executable. */
+ if (!backtrace_close (descriptor, error_callback, data))
+ goto fail;
+ descriptor = -1;
+
+ for (i = 0; i < (int) DEBUG_MAX; ++i)
+ {
+ if (sections[i].size == 0)
+ sections[i].data = NULL;
+ else
+ sections[i].data = ((const unsigned char *) debug_view.data
+ + (sections[i].offset - min_offset));
+ }
+
+ if (!backtrace_dwarf_add (state, /* base_address */ 0,
+ sections[DEBUG_INFO].data,
+ sections[DEBUG_INFO].size,
+ sections[DEBUG_LINE].data,
+ sections[DEBUG_LINE].size,
+ sections[DEBUG_ABBREV].data,
+ sections[DEBUG_ABBREV].size,
+ sections[DEBUG_RANGES].data,
+ sections[DEBUG_RANGES].size,
+ sections[DEBUG_STR].data,
+ sections[DEBUG_STR].size,
+ 0, /* FIXME */
+ error_callback, data, fileline_fn))
+ goto fail;
+
+ *found_dwarf = 1;
+
+ return 1;
+
+ fail:
+ if (sects_view_valid)
+ backtrace_release_view (state, &sects_view, error_callback, data);
+ if (str_view_valid)
+ backtrace_release_view (state, &str_view, error_callback, data);
+ if (syms_view_valid)
+ backtrace_release_view (state, &syms_view, error_callback, data);
+ if (debug_view_valid)
+ backtrace_release_view (state, &debug_view, error_callback, data);
+ if (descriptor != -1)
+ backtrace_close (descriptor, error_callback, data);
+ return 0;
+}
+
+/* Initialize the backtrace data we need from an ELF executable. At
+ the ELF level, all we need to do is find the debug info
+ sections. */
+
+int
+backtrace_initialize (struct backtrace_state *state, int descriptor,
+ backtrace_error_callback error_callback,
+ void *data, fileline *fileline_fn)
+{
+ int ret;
+ int found_sym;
+ int found_dwarf;
+ fileline coff_fileline_fn;
+
+ ret = coff_add (state, descriptor, error_callback, data,
+ &coff_fileline_fn, &found_sym, &found_dwarf);
+ if (!ret)
+ return 0;
+
+ if (!state->threaded)
+ {
+ if (found_sym)
+ state->syminfo_fn = coff_syminfo;
+ else if (state->syminfo_fn == NULL)
+ state->syminfo_fn = coff_nosyms;
+ }
+ else
+ {
+ if (found_sym)
+ backtrace_atomic_store_pointer (&state->syminfo_fn, coff_syminfo);
+ else
+ __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, coff_nosyms);
+ }
+
+ if (!state->threaded)
+ {
+ if (state->fileline_fn == NULL || state->fileline_fn == coff_nodebug)
+ *fileline_fn = coff_fileline_fn;
+ }
+ else
+ {
+ fileline current_fn;
+
+ current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
+ if (current_fn == NULL || current_fn == coff_nodebug)
+ *fileline_fn = coff_fileline_fn;
+ }
+
+ return 1;
+}
diff --git a/thirdparty/libbacktrace/posix.c b/thirdparty/libbacktrace/posix.c
index be0a1a55..09f5e95a 100644
--- a/thirdparty/libbacktrace/posix.c
+++ b/thirdparty/libbacktrace/posix.c
@@ -1,5 +1,5 @@
/* posix.c -- POSIX file I/O routines for the backtrace library.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
@@ -64,7 +64,7 @@ backtrace_open (const char *filename, backtrace_error_callback error_callback,
if (does_not_exist != NULL)
*does_not_exist = 0;
- descriptor = open (filename, O_RDONLY | O_BINARY | O_CLOEXEC);
+ descriptor = open (filename, (int) (O_RDONLY | O_BINARY | O_CLOEXEC));
if (descriptor < 0)
{
if (does_not_exist != NULL && errno == ENOENT)
diff --git a/thirdparty/libbacktrace/print.c b/thirdparty/libbacktrace/print.c
index c8cc2989..74c8fcbe 100644
--- a/thirdparty/libbacktrace/print.c
+++ b/thirdparty/libbacktrace/print.c
@@ -1,5 +1,5 @@
/* print.c -- Print the current backtrace.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/libbacktrace/read.c b/thirdparty/libbacktrace/read.c
index d6e648e5..7f0317c3 100644
--- a/thirdparty/libbacktrace/read.c
+++ b/thirdparty/libbacktrace/read.c
@@ -1,5 +1,5 @@
/* read.c -- File views without mmap.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/libbacktrace/simple.c b/thirdparty/libbacktrace/simple.c
index b03f039f..018773a7 100644
--- a/thirdparty/libbacktrace/simple.c
+++ b/thirdparty/libbacktrace/simple.c
@@ -1,5 +1,5 @@
/* simple.c -- The backtrace_simple function.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/libbacktrace/sort.c b/thirdparty/libbacktrace/sort.c
new file mode 100644
index 00000000..68a7df65
--- /dev/null
+++ b/thirdparty/libbacktrace/sort.c
@@ -0,0 +1,108 @@
+/* sort.c -- Sort without allocating memory
+ Copyright (C) 2012-2016 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 <stddef.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* The GNU glibc version of qsort allocates memory, which we must not
+ do if we are invoked by a signal handler. So provide our own
+ sort. */
+
+static void
+swap (char *a, char *b, size_t size)
+{
+ size_t i;
+
+ for (i = 0; i < size; i++, a++, b++)
+ {
+ char t;
+
+ t = *a;
+ *a = *b;
+ *b = t;
+ }
+}
+
+void
+backtrace_qsort (void *basearg, size_t count, size_t size,
+ int (*compar) (const void *, const void *))
+{
+ char *base = (char *) basearg;
+ size_t i;
+ size_t mid;
+
+ tail_recurse:
+ if (count < 2)
+ return;
+
+ /* The symbol table and DWARF tables, which is all we use this
+ routine for, tend to be roughly sorted. Pick the middle element
+ in the array as our pivot point, so that we are more likely to
+ cut the array in half for each recursion step. */
+ swap (base, base + (count / 2) * size, size);
+
+ mid = 0;
+ for (i = 1; i < count; i++)
+ {
+ if ((*compar) (base, base + i * size) > 0)
+ {
+ ++mid;
+ if (i != mid)
+ swap (base + mid * size, base + i * size, size);
+ }
+ }
+
+ if (mid > 0)
+ swap (base, base + mid * size, size);
+
+ /* Recurse with the smaller array, loop with the larger one. That
+ ensures that our maximum stack depth is log count. */
+ if (2 * mid < count)
+ {
+ backtrace_qsort (base, mid, size, compar);
+ base += (mid + 1) * size;
+ count -= mid + 1;
+ goto tail_recurse;
+ }
+ else
+ {
+ backtrace_qsort (base + (mid + 1) * size, count - (mid + 1),
+ size, compar);
+ count = mid;
+ goto tail_recurse;
+ }
+}
diff --git a/thirdparty/libbacktrace/state.c b/thirdparty/libbacktrace/state.c
index 03bba481..93420d9c 100644
--- a/thirdparty/libbacktrace/state.c
+++ b/thirdparty/libbacktrace/state.c
@@ -1,5 +1,5 @@
/* state.c -- Create the backtrace state.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
diff --git a/thirdparty/libbacktrace/stest.c b/thirdparty/libbacktrace/stest.c
new file mode 100644
index 00000000..55ec31d1
--- /dev/null
+++ b/thirdparty/libbacktrace/stest.c
@@ -0,0 +1,137 @@
+/* stest.c -- Test for libbacktrace internal sort function
+ Copyright (C) 2012-2016 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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#include "backtrace.h"
+#include "internal.h"
+
+/* Test the local qsort implementation. */
+
+#define MAX 10
+
+struct test
+{
+ size_t count;
+ int input[MAX];
+ int output[MAX];
+};
+
+static struct test tests[] =
+ {
+ {
+ 10,
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
+ },
+ {
+ 9,
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9 }
+ },
+ {
+ 10,
+ { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
+ },
+ {
+ 9,
+ { 9, 8, 7, 6, 5, 4, 3, 2, 1 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9 },
+ },
+ {
+ 10,
+ { 2, 4, 6, 8, 10, 1, 3, 5, 7, 9 },
+ { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 },
+ },
+ {
+ 5,
+ { 4, 5, 3, 1, 2 },
+ { 1, 2, 3, 4, 5 },
+ },
+ {
+ 5,
+ { 1, 1, 1, 1, 1 },
+ { 1, 1, 1, 1, 1 },
+ },
+ {
+ 5,
+ { 1, 1, 2, 1, 1 },
+ { 1, 1, 1, 1, 2 },
+ },
+ {
+ 5,
+ { 2, 1, 1, 1, 1 },
+ { 1, 1, 1, 1, 2 },
+ },
+ };
+
+static int
+compare (const void *a, const void *b)
+{
+ const int *ai = (const int *) a;
+ const int *bi = (const int *) b;
+
+ return *ai - *bi;
+}
+
+int
+main (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED)
+{
+ int failures;
+ size_t i;
+ int a[MAX];
+
+ failures = 0;
+ for (i = 0; i < sizeof tests / sizeof tests[0]; i++)
+ {
+ memcpy (a, tests[i].input, tests[i].count * sizeof (int));
+ backtrace_qsort (a, tests[i].count, sizeof (int), compare);
+ if (memcmp (a, tests[i].output, tests[i].count * sizeof (int)) != 0)
+ {
+ size_t j;
+
+ fprintf (stderr, "test %d failed:", (int) i);
+ for (j = 0; j < tests[i].count; j++)
+ fprintf (stderr, " %d", a[j]);
+ fprintf (stderr, "\n");
+ ++failures;
+ }
+ }
+
+ exit (failures > 0 ? EXIT_FAILURE : EXIT_SUCCESS);
+}
diff --git a/thirdparty/libbacktrace/unknown.c b/thirdparty/libbacktrace/unknown.c
index d9a3ac75..8d06c315 100644
--- a/thirdparty/libbacktrace/unknown.c
+++ b/thirdparty/libbacktrace/unknown.c
@@ -1,5 +1,5 @@
/* unknown.c -- used when backtrace configury does not know file format.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
+ Copyright (C) 2012-2016 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without