auto merge of #12602 : alexcrichton/rust/backtrace, r=brson

Whenever a failure happens, if a program is run with
`RUST_LOG=std::rt::backtrace` a backtrace will be printed to the task's stderr
handle. Stack traces are uncondtionally printed on double-failure and
rtabort!().

This ended up having a nontrivial implementation, and here's some highlights of
it:

* We're bundling libbacktrace for everything but OSX and Windows
* We use libgcc_s and its libunwind apis to get a backtrace of instruction
  pointers
* On OSX we use dladdr() to go from an instruction pointer to a symbol
* On unix that isn't OSX, we use libbacktrace to get symbols
* Windows, as usual, has an entirely separate implementation

Lots more fun details and comments can be found in the source itself.

Closes #10128
This commit is contained in:
bors 2014-03-13 01:11:39 -07:00
commit 12b2607572
47 changed files with 39814 additions and 101 deletions

View File

@ -55,7 +55,7 @@ HOST_CRATES := syntax rustc rustdoc fourcc hexfloat
CRATES := $(TARGET_CRATES) $(HOST_CRATES)
TOOLS := compiletest rustdoc rustc
DEPS_std := native:rustrt native:compiler-rt
DEPS_std := native:rustrt native:compiler-rt native:backtrace
DEPS_extra := std term sync serialize getopts collections time rand
DEPS_green := std rand native:context_switch
DEPS_rustuv := std native:uv native:uv_support

View File

@ -249,6 +249,73 @@ $$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS)
triple-runtime
$$(Q)cp $$(COMPRT_BUILD_DIR_$(1))/triple/runtime/libcompiler_rt.a $$(COMPRT_LIB_$(1))
################################################################################
# libbacktrace
#
# We use libbacktrace on linux to get symbols in backtraces, but only on linux.
# Elsewhere we use other system utilities, so this library is only built on
# linux.
################################################################################
BACKTRACE_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),backtrace)
BACKTRACE_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(BACKTRACE_NAME_$(1))
BACKTRACE_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/libbacktrace
ifeq ($$(findstring darwin,$$(OSTYPE_$(1))),darwin)
# We don't use this on platforms that aren't linux-based, so just make the file
# available, the compilation of libstd won't actually build it.
$$(BACKTRACE_LIB_$(1)):
touch $$@
else
ifeq ($$(CFG_WINDOWSY_$(1)),1)
$$(BACKTRACE_LIB_$(1)):
touch $$@
else
ifdef CFG_ENABLE_FAST_MAKE
BACKTRACE_DEPS := $(S)/.gitmodules
else
BACKTRACE_DEPS := $(wildcard $(S)src/libbacktrace/*)
endif
# We need to export CFLAGS because otherwise it doesn't pick up cross compile
# builds. If libbacktrace doesn't realize this, it will attempt to read 64-bit
# elf headers when compiled for a 32-bit system, yielding blank backtraces.
#
# This also removes the -Werror flag specifically to prevent errors during
# configuration.
#
# Down below you'll also see echos into the config.h generated by the
# ./configure script. This is done to force libbacktrace to *not* use the
# atomic/sync functionality because it pulls in unnecessary dependencies and we
# never use it anyway.
$$(BACKTRACE_BUILD_DIR_$(1))/Makefile: \
export CFLAGS:=$$(CFG_GCCISH_CFLAGS_$(1):-Werror=) \
-fno-stack-protector
$$(BACKTRACE_BUILD_DIR_$(1))/Makefile: export CC:=$$(CC_$(1))
$$(BACKTRACE_BUILD_DIR_$(1))/Makefile: export AR:=$$(AR_$(1))
$$(BACKTRACE_BUILD_DIR_$(1))/Makefile: export RANLIB:=$$(AR_$(1)) s
$$(BACKTRACE_BUILD_DIR_$(1))/Makefile: $$(BACKTRACE_DEPS) $$(MKFILE_DEPS)
$$(Q)rm -rf $$(BACKTRACE_BUILD_DIR_$(1))
$$(Q)mkdir -p $$(BACKTRACE_BUILD_DIR_$(1))
$$(Q)(cd $$(BACKTRACE_BUILD_DIR_$(1)) && \
$(S)src/libbacktrace/configure --target=$(1) --host=$(CFG_BUILD))
$$(Q)echo '#undef HAVE_ATOMIC_FUNCTIONS' >> \
$$(BACKTRACE_BUILD_DIR_$(1))/config.h
$$(Q)echo '#undef HAVE_SYNC_FUNCTIONS' >> \
$$(BACKTRACE_BUILD_DIR_$(1))/config.h
$$(BACKTRACE_LIB_$(1)): $$(BACKTRACE_BUILD_DIR_$(1))/Makefile $$(MKFILE_DEPS)
@$$(call E, make: libbacktrace)
$$(Q)$$(MAKE) -C $$(BACKTRACE_BUILD_DIR_$(1)) \
INCDIR=$(S)src/libbacktrace
$$(Q)cp $$(BACKTRACE_BUILD_DIR_$(1))/.libs/libbacktrace.a $$@
endif # endif for windowsy
endif # endif for darwin
endef
# Instantiate template for all stages/targets

View File

@ -240,6 +240,7 @@ tidy:
| grep '^$(S)src/libuv' -v \
| grep '^$(S)src/llvm' -v \
| grep '^$(S)src/gyp' -v \
| grep '^$(S)src/libbacktrace' -v \
| xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
$(Q)find $(S)src/etc -name '*.py' \
| xargs -n 10 $(CFG_PYTHON) $(S)src/etc/tidy.py
@ -266,6 +267,7 @@ tidy:
| grep '^$(S)src/etc' -v \
| grep '^$(S)src/doc' -v \
| grep '^$(S)src/compiler-rt' -v \
| grep '^$(S)src/libbacktrace' -v \
| xargs $(CFG_PYTHON) $(S)src/etc/check-binaries.py
endif

408
src/libbacktrace/ChangeLog Normal file
View File

@ -0,0 +1,408 @@
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.
2013-07-23 Alexander Monakov <amonakov@ispras.ru>
* elf.c (backtrace_initialize): Pass elf_fileline_fn to
dl_iterate_phdr callbacks.
2013-03-25 Ian Lance Taylor <iant@google.com>
* alloc.c: #include <sys/types.h>.
* mmap.c: Likewise.
2013-01-31 Ian Lance Taylor <iant@google.com>
* dwarf.c (read_function_info): Permit fvec parameter to be NULL.
(dwarf_lookup_pc): Don't use ddata->fvec if threaded.
2013-01-25 Jakub Jelinek <jakub@redhat.com>
PR other/56076
* dwarf.c (read_line_header): Don't crash if DW_AT_comp_dir
attribute was not seen.
2013-01-16 Ian Lance Taylor <iant@google.com>
* dwarf.c (struct unit): Add filename and abs_filename fields.
(build_address_map): Set new fields when reading unit.
(dwarf_lookup_pc): If we don't find an entry in the line table,
just return the main file name.
2013-01-14 Richard Sandiford <rdsandiford@googlemail.com>
Update copyright years.
2013-01-01 Ian Lance Taylor <iant@google.com>
PR bootstrap/54834
* Makefile.am (AM_CPPFLAGS): Remove -I ../gcc/include and -I
$(MULTIBUILDTOP)/../../gcc/include.
* Makefile.in: Rebuild.
2013-01-01 Ian Lance Taylor <iant@google.com>
PR other/55536
* mmap.c (backtrace_alloc): Don't call sync functions if not
threaded.
(backtrace_free): Likewise.
2012-12-12 John David Anglin <dave.anglin@nrc-cnrc.gc.ca>
* mmapio.c: Define MAP_FAILED if not defined.
2012-12-11 Jakub Jelinek <jakub@redhat.com>
PR bootstrap/54926
* Makefile.am (AM_CFLAGS): Remove -frandom-seed=$@.
* configure.ac: If --with-target-subdir, add -frandom-seed=$@
to EXTRA_FLAGS unconditionally, otherwise check whether the compiler
accepts it.
* Makefile.in: Regenerated.
* configure: Regenerated.
2012-12-07 Jakub Jelinek <jakub@redhat.com>
PR bootstrap/54926
* Makefile.am (AM_CFLAGS): Add -frandom-seed=$@.
* Makefile.in: Regenerated.
2012-11-20 Ian Lance Taylor <iant@google.com>
* dwarf.c (read_attribute): Always clear val.
2012-11-13 Ian Lance Taylor <iant@google.com>
PR other/55312
* configure.ac: Only add -Werror if building a target library.
* configure: Rebuild.
2012-11-12 Ian Lance Taylor <iant@google.com>
Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
Gerald Pfeifer <gerald@pfeifer.com>
* configure.ac: Check for getexecname.
* fileline.c: #include <errno.h>. Define getexecname if not
available.
(fileline_initialize): Try to find the executable in a few
different ways.
* print.c (error_callback): Only print the filename if it came
from the backtrace state.
* configure, config.h.in: Rebuild.
2012-10-29 Ian Lance Taylor <iant@google.com>
* mmap.c (backtrace_vector_release): Correct last patch: add
aligned, not size.
2012-10-29 Ian Lance Taylor <iant@google.com>
* mmap.c (backtrace_vector_release): Make sure freed block is
aligned on 8-byte boundary.
2012-10-26 Ian Lance Taylor <iant@google.com>
PR other/55087
* posix.c (backtrace_open): Add does_not_exist parameter.
* elf.c (phdr_callback): Do not warn if shared library could not
be opened.
* fileline.c (fileline_initialize): Update calls to
backtrace_open.
* internal.h (backtrace_open): Update declaration.
2012-10-26 Jack Howarth <howarth@bromo.med.uc.edu>
PR target/55061
* configure.ac: Check for _Unwind_GetIPInfo function declaration.
* configure: Regenerate.
2012-10-24 Ian Lance Taylor <iant@google.com>
PR target/55061
* configure.ac: Check whether -funwind-tables option works.
* configure: Rebuild.
2012-10-11 Ian Lance Taylor <iant@google.com>
* configure.ac: Do not use dl_iterate_phdr on Solaris 10.
* configure: Rebuild.
2012-10-10 Ian Lance Taylor <iant@google.com>
* elf.c: Rename all Elf typedefs to start with b_elf, and be all
lower case.
2012-10-10 Hans-Peter Nilsson <hp@bitrange.com>
* elf.c (elf_add_syminfo_data): Add casts to avoid warning.
2012-10-09 Ian Lance Taylor <iant@google.com>
* dwarf.c (dwarf_fileline): Add cast to avoid warning.
(backtrace_dwarf_add): Likewise.
2012-10-09 Ian Lance Taylor <iant@google.com>
Add support for tracing through shared libraries.
* configure.ac: Check for link.h and dl_iterate_phdr.
* elf.c: #include <link.h> if system has dl_iterate_phdr. #undef
ELF macros before #defining them.
(dl_phdr_info, dl_iterate_phdr): Define if system does not have
dl_iterate_phdr.
(struct elf_syminfo_data): Add next field.
(elf_initialize_syminfo): Initialize next field.
(elf_add_syminfo_data): New static function.
(elf_add): New static function, broken out of
backtrace_initialize. Call backtrace_dwarf_add instead of
backtrace_dwarf_initialize.
(struct phdr_data): Define.
(phdr_callback): New static function.
(backtrace_initialize): Call elf_add.
* dwarf.c (struct dwarf_data): Add next and base_address fields.
(add_unit_addr): Add base_address parameter. Change all callers.
(add_unit_ranges, build_address_map): Likewise.
(add_line): Add ddata parameter. Change all callers.
(read_line_program, add_function_range): Likewise.
(dwarf_lookup_pc): New static function, broken out of
dwarf_fileline.
(dwarf_fileline): Call dwarf_lookup_pc.
(build_dwarf_data): New static function.
(backtrace_dwarf_add): New function.
(backtrace_dwarf_initialize): Remove.
* internal.h (backtrace_dwarf_initialize): Don't declare.
(backtrace_dwarf_add): Declare.
* configure, config.h.in: Rebuild.
2012-10-04 Gerald Pfeifer <gerald@pfeifer.com>
* btest.c (f23): Avoid uninitialized variable warning.
2012-10-04 Ian Lance Taylor <iant@google.com>
* dwarf.c: If the system header files do not declare strnlen,
provide our own version.
2012-10-03 Ian Lance Taylor <iant@google.com>
* dwarf.c (read_uleb128): Fix overflow test.
(read_sleb128): Likewise.
(build_address_map): Don't change unit_buf.start.
2012-10-02 Uros Bizjak <ubizjak@gmail.com>
PR other/54761
* configure.ac (EXTRA_FLAGS): New.
* Makefile.am (AM_FLAGS): Add $(EXTRA_FLAGS).
* configure, Makefile.in: Regenerate.
2012-09-29 Ian Lance Taylor <iant@google.com>
PR other/54749
* fileline.c (fileline_initialize): Pass errnum as -1 when
reporting that we could not read executable information after a
previous failure.
2012-09-27 Ian Lance Taylor <iant@google.com>
PR bootstrap/54732
* configure.ac: Add no-dependencies to AM_INIT_AUTOMAKE.
* Makefile.am: Add dependencies for all objects.
* configure, aclocal.m4, Makefile.in: Rebuild.
2012-09-27 Ian Lance Taylor <iant@google.com>
PR other/54726
* elf.c (backtrace_initialize): Set *fileln_fn, not
state->fileln_fn.
2012-09-19 Ian Lance Taylor <iant@google.com>
* configure.ac: Only use GCC_CHECK_UNWIND_GETIPINFO when compiled
as a target library.
* configure: Rebuild.
2012-09-19 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
Ian Lance Taylor <iant@google.com>
* configure.ac (GCC_HEADER_STDINT): Invoke.
* backtrace.h: If we can't find <stdint.h>, use "gstdint.h".
* btest.c: Don't include <stdint.h>.
* dwarf.c: Likewise.
* configure, aclocal.m4, Makefile.in, config.h.in: Rebuild.
2012-09-18 Ian Lance Taylor <iant@google.com>
PR bootstrap/54623
* Makefile.am (AM_CPPFLAGS): Define.
(AM_CFLAGS): Remove -I options.
* Makefile.in: Rebuild.
2012-09-18 Ian Lance Taylor <iant@google.com>
* posix.c (O_BINARY): Define if not defined.
(backtrace_open): Pass O_BINARY to open. Only call fcntl if
HAVE_FCNTL is defined.
* configure.ac: Test for the fcntl function.
* configure, config.h.in: Rebuild.
2012-09-18 Ian Lance Taylor <iant@google.com>
* btest.c (test1, test2, test3, test4): Add the unused attribute.
2012-09-18 Ian Lance Taylor <iant@google.com>
* dwarf.c: Correct test of HAVE_DECL_STRNLEN.
2012-09-18 Ian Lance Taylor <iant@google.com>
* configure.ac: Add AC_USE_SYSTEM_EXTENSIONS.
* mmapio.c: Don't define _GNU_SOURCE.
* configure, config.h.in: Rebuild.
2012-09-18 Ian Lance Taylor <iant@google.com>
* configure.ac: Check whether strnlen is declared.
* dwarf.c: Declare strnlen if not declared.
* configure, config.h.in: Rebuild.
2012-09-18 Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
* fileline.c: Include <stdlib.h>.
* mmap.c: Likewise.
2012-09-17 Ian Lance Taylor <iant@google.com>
PR bootstrap/54611
* nounwind.c (backtrace_full): Rename from backtrace. Add state
parameter.
2012-09-17 Gerald Pfeifer <gerald@pfeifer.com>
PR bootstrap/54611
* nounwind.c (backtrace_simple): Add state parameter.
2012-09-17 Ian Lance Taylor <iant@google.com>
PR bootstrap/54609
* unknown.c (unknown_fileline): Add state parameter, remove
fileline_data parameter, name error_callback parameter.
(backtrace_initialize): Add state parameter.
2012-09-17 Ian Lance Taylor <iant@google.com>
* Initial implementation.

View File

@ -0,0 +1,126 @@
# Makefile.am -- Backtrace Makefile.
# Copyright (C) 2012-2014 Free Software Foundation, Inc.
# 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.
ACLOCAL_AMFLAGS = -I .. -I ../config
AM_CPPFLAGS = -I $(top_srcdir)/../include -I $(top_srcdir)/../libgcc \
-I ../libgcc
AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)
noinst_LTLIBRARIES = libbacktrace.la
libbacktrace_la_SOURCES = \
backtrace.h \
atomic.c \
dwarf.c \
fileline.c \
internal.h \
posix.c \
print.c \
state.c
BACKTRACE_FILES = \
backtrace.c \
simple.c \
nounwind.c
FORMAT_FILES = \
elf.c \
unknown.c
VIEW_FILES = \
read.c \
mmapio.c
ALLOC_FILES = \
alloc.c \
mmap.c
EXTRA_libbacktrace_la_SOURCES = \
$(BACKTRACE_FILES) \
$(FORMAT_FILES) \
$(VIEW_FILES) \
$(ALLOC_FILES)
libbacktrace_la_LIBADD = \
$(BACKTRACE_FILE) \
$(FORMAT_FILE) \
$(VIEW_FILE) \
$(ALLOC_FILE)
libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
# Testsuite.
check_PROGRAMS =
TESTS = $(check_PROGRAMS)
if NATIVE
btest_SOURCES = btest.c
btest_CFLAGS = $(AM_CFLAGS) -g -O
btest_LDADD = libbacktrace.la
check_PROGRAMS += btest
endif NATIVE
# We can't use automake's automatic dependency tracking, because it
# breaks when using bootstrap-lean. Automatic dependency tracking
# with GCC bootstrap will cause some of the objects to depend on
# header files in prev-gcc/include, e.g., stddef.h and stdarg.h. When
# using bootstrap-lean, prev-gcc is removed after each stage. When
# running "make install", those header files will be gone, causing the
# library to be rebuilt at install time. That may not succeed.
# These manual dependencies do not include dependencies on unwind.h,
# even though that is part of GCC, because where to find it depends on
# whether we are being built as a host library or a target library.
INCDIR = $(top_srcdir)/../include
alloc.lo: config.h backtrace.h internal.h
backtrace.lo: config.h backtrace.h
btest.lo: (INCDIR)/filenames.h backtrace.h backtrace-supported.h
dwarf.lo: config.h $(INCDIR)/dwarf2.h $(INCDIR)/dwarf2.def \
$(INCDIR)/filenames.h backtrace.h internal.h
elf.lo: config.h backtrace.h internal.h
fileline.lo: config.h backtrace.h internal.h
mmap.lo: config.h backtrace.h internal.h
mmapio.lo: config.h backtrace.h internal.h
nounwind.lo: config.h internal.h
posix.lo: config.h backtrace.h internal.h
print.lo: config.h backtrace.h internal.h
read.lo: config.h backtrace.h internal.h
simple.lo: config.h backtrace.h internal.h
state.lo: config.h backtrace.h backtrace-supported.h internal.h
unknown.lo: config.h backtrace.h internal.h

View File

@ -0,0 +1,730 @@
# Makefile.in generated by automake 1.11.1 from Makefile.am.
# @configure_input@
# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
# 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation,
# Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
# Makefile.am -- Backtrace Makefile.
# Copyright (C) 2012-2014 Free Software Foundation, Inc.
# 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.
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkglibexecdir = $(libexecdir)/@PACKAGE@
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
build_triplet = @build@
host_triplet = @host@
target_triplet = @target@
check_PROGRAMS = $(am__EXEEXT_1)
@NATIVE_TRUE@am__append_1 = btest
subdir = .
DIST_COMMON = README ChangeLog $(srcdir)/Makefile.in \
$(srcdir)/Makefile.am $(top_srcdir)/configure \
$(am__configure_deps) $(srcdir)/config.h.in \
$(srcdir)/../mkinstalldirs $(srcdir)/backtrace-supported.h.in
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
am__aclocal_m4_deps = $(top_srcdir)/../config/lead-dot.m4 \
$(top_srcdir)/../config/multi.m4 \
$(top_srcdir)/../config/override.m4 \
$(top_srcdir)/../config/stdint.m4 \
$(top_srcdir)/../config/unwind_ipinfo.m4 \
$(top_srcdir)/../config/warnings.m4 \
$(top_srcdir)/../libtool.m4 $(top_srcdir)/../ltoptions.m4 \
$(top_srcdir)/../ltsugar.m4 $(top_srcdir)/../ltversion.m4 \
$(top_srcdir)/../lt~obsolete.m4 $(top_srcdir)/configure.ac
am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
$(ACLOCAL_M4)
am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \
configure.lineno config.status.lineno
mkinstalldirs = $(SHELL) $(top_srcdir)/../mkinstalldirs
CONFIG_HEADER = config.h
CONFIG_CLEAN_FILES = backtrace-supported.h
CONFIG_CLEAN_VPATH_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
am__DEPENDENCIES_1 =
am_libbacktrace_la_OBJECTS = atomic.lo dwarf.lo fileline.lo posix.lo \
print.lo state.lo
libbacktrace_la_OBJECTS = $(am_libbacktrace_la_OBJECTS)
@NATIVE_TRUE@am__EXEEXT_1 = btest$(EXEEXT)
@NATIVE_TRUE@am_btest_OBJECTS = btest-btest.$(OBJEXT)
btest_OBJECTS = $(am_btest_OBJECTS)
@NATIVE_TRUE@btest_DEPENDENCIES = libbacktrace.la
btest_LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(btest_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
DEFAULT_INCLUDES = -I.@am__isrc@
depcomp =
am__depfiles_maybe =
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \
$(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \
--mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \
$(LDFLAGS) -o $@
SOURCES = $(libbacktrace_la_SOURCES) $(EXTRA_libbacktrace_la_SOURCES) \
$(btest_SOURCES)
MULTISRCTOP =
MULTIBUILDTOP =
MULTIDIRS =
MULTISUBDIR =
MULTIDO = true
MULTICLEAN = true
ETAGS = etags
CTAGS = ctags
am__tty_colors = \
red=; grn=; lgn=; blu=; std=
ACLOCAL = @ACLOCAL@
ALLOC_FILE = @ALLOC_FILE@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
AUTOHEADER = @AUTOHEADER@
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
BACKTRACE_FILE = @BACKTRACE_FILE@
BACKTRACE_SUPPORTED = @BACKTRACE_SUPPORTED@
BACKTRACE_SUPPORTS_THREADS = @BACKTRACE_SUPPORTS_THREADS@
BACKTRACE_USES_MALLOC = @BACKTRACE_USES_MALLOC@
CC = @CC@
CFLAGS = @CFLAGS@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DSYMUTIL = @DSYMUTIL@
DUMPBIN = @DUMPBIN@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
EXEEXT = @EXEEXT@
EXTRA_FLAGS = @EXTRA_FLAGS@
FGREP = @FGREP@
FORMAT_FILE = @FORMAT_FILE@
GREP = @GREP@
INSTALL = @INSTALL@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LD = @LD@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIPO = @LIPO@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAINT = @MAINT@
MAKEINFO = @MAKEINFO@
MKDIR_P = @MKDIR_P@
NM = @NM@
NMEDIT = @NMEDIT@
OBJDUMP = @OBJDUMP@
OBJEXT = @OBJEXT@
OTOOL = @OTOOL@
OTOOL64 = @OTOOL64@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_URL = @PACKAGE_URL@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
PIC_FLAG = @PIC_FLAG@
RANLIB = @RANLIB@
SED = @SED@
SET_MAKE = @SET_MAKE@
SHELL = @SHELL@
STRIP = @STRIP@
VERSION = @VERSION@
VIEW_FILE = @VIEW_FILE@
WARN_FLAGS = @WARN_FLAGS@
abs_builddir = @abs_builddir@
abs_srcdir = @abs_srcdir@
abs_top_builddir = @abs_top_builddir@
abs_top_srcdir = @abs_top_srcdir@
ac_ct_CC = @ac_ct_CC@
ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
am__leading_dot = @am__leading_dot@
am__tar = @am__tar@
am__untar = @am__untar@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
builddir = @builddir@
datadir = @datadir@
datarootdir = @datarootdir@
docdir = @docdir@
dvidir = @dvidir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
libtool_VERSION = @libtool_VERSION@
localedir = @localedir@
localstatedir = @localstatedir@
mandir = @mandir@
mkdir_p = @mkdir_p@
multi_basedir = @multi_basedir@
oldincludedir = @oldincludedir@
pdfdir = @pdfdir@
prefix = @prefix@
program_transform_name = @program_transform_name@
psdir = @psdir@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
srcdir = @srcdir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
top_build_prefix = @top_build_prefix@
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
ACLOCAL_AMFLAGS = -I .. -I ../config
AM_CPPFLAGS = -I $(top_srcdir)/../include -I $(top_srcdir)/../libgcc \
-I ../libgcc
AM_CFLAGS = $(EXTRA_FLAGS) $(WARN_FLAGS) $(PIC_FLAG)
noinst_LTLIBRARIES = libbacktrace.la
libbacktrace_la_SOURCES = \
backtrace.h \
atomic.c \
dwarf.c \
fileline.c \
internal.h \
posix.c \
print.c \
state.c
BACKTRACE_FILES = \
backtrace.c \
simple.c \
nounwind.c
FORMAT_FILES = \
elf.c \
unknown.c
VIEW_FILES = \
read.c \
mmapio.c
ALLOC_FILES = \
alloc.c \
mmap.c
EXTRA_libbacktrace_la_SOURCES = \
$(BACKTRACE_FILES) \
$(FORMAT_FILES) \
$(VIEW_FILES) \
$(ALLOC_FILES)
libbacktrace_la_LIBADD = \
$(BACKTRACE_FILE) \
$(FORMAT_FILE) \
$(VIEW_FILE) \
$(ALLOC_FILE)
libbacktrace_la_DEPENDENCIES = $(libbacktrace_la_LIBADD)
TESTS = $(check_PROGRAMS)
@NATIVE_TRUE@btest_SOURCES = btest.c
@NATIVE_TRUE@btest_CFLAGS = $(AM_CFLAGS) -g -O
@NATIVE_TRUE@btest_LDADD = libbacktrace.la
# We can't use automake's automatic dependency tracking, because it
# breaks when using bootstrap-lean. Automatic dependency tracking
# with GCC bootstrap will cause some of the objects to depend on
# header files in prev-gcc/include, e.g., stddef.h and stdarg.h. When
# using bootstrap-lean, prev-gcc is removed after each stage. When
# running "make install", those header files will be gone, causing the
# library to be rebuilt at install time. That may not succeed.
# These manual dependencies do not include dependencies on unwind.h,
# even though that is part of GCC, because where to find it depends on
# whether we are being built as a host library or a target library.
INCDIR = $(top_srcdir)/../include
all: config.h
$(MAKE) $(AM_MAKEFLAGS) all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
am--refresh:
@:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
@for dep in $?; do \
case '$(am__configure_deps)' in \
*$$dep*) \
echo ' cd $(srcdir) && $(AUTOMAKE) --foreign --ignore-deps'; \
$(am__cd) $(srcdir) && $(AUTOMAKE) --foreign --ignore-deps \
&& exit 0; \
exit 1;; \
esac; \
done; \
echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign --ignore-deps Makefile'; \
$(am__cd) $(top_srcdir) && \
$(AUTOMAKE) --foreign --ignore-deps Makefile
.PRECIOUS: Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
@case '$?' in \
*config.status*) \
echo ' $(SHELL) ./config.status'; \
$(SHELL) ./config.status;; \
*) \
echo ' cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe)'; \
cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe);; \
esac;
$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
$(SHELL) ./config.status --recheck
$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
$(am__cd) $(srcdir) && $(AUTOCONF)
$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
$(am__cd) $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS)
$(am__aclocal_m4_deps):
config.h: stamp-h1
@if test ! -f $@; then \
rm -f stamp-h1; \
$(MAKE) $(AM_MAKEFLAGS) stamp-h1; \
else :; fi
stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status
@rm -f stamp-h1
cd $(top_builddir) && $(SHELL) ./config.status config.h
$(srcdir)/config.h.in: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
($(am__cd) $(top_srcdir) && $(AUTOHEADER))
rm -f stamp-h1
touch $@
distclean-hdr:
-rm -f config.h stamp-h1
backtrace-supported.h: $(top_builddir)/config.status $(srcdir)/backtrace-supported.h.in
cd $(top_builddir) && $(SHELL) ./config.status $@
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" != "$$p" || dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libbacktrace.la: $(libbacktrace_la_OBJECTS) $(libbacktrace_la_DEPENDENCIES)
$(LINK) $(libbacktrace_la_OBJECTS) $(libbacktrace_la_LIBADD) $(LIBS)
clean-checkPROGRAMS:
@list='$(check_PROGRAMS)'; test -n "$$list" || exit 0; \
echo " rm -f" $$list; \
rm -f $$list || exit $$?; \
test -n "$(EXEEXT)" || exit 0; \
list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \
echo " rm -f" $$list; \
rm -f $$list
btest$(EXEEXT): $(btest_OBJECTS) $(btest_DEPENDENCIES)
@rm -f btest$(EXEEXT)
$(btest_LINK) $(btest_OBJECTS) $(btest_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
distclean-compile:
-rm -f *.tab.c
.c.o:
$(COMPILE) -c $<
.c.obj:
$(COMPILE) -c `$(CYGPATH_W) '$<'`
.c.lo:
$(LTCOMPILE) -c -o $@ $<
btest-btest.o: btest.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-btest.o `test -f 'btest.c' || echo '$(srcdir)/'`btest.c
btest-btest.obj: btest.c
$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(btest_CFLAGS) $(CFLAGS) -c -o btest-btest.obj `if test -f 'btest.c'; then $(CYGPATH_W) 'btest.c'; else $(CYGPATH_W) '$(srcdir)/btest.c'; fi`
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool config.lt
# GNU Make needs to see an explicit $(MAKE) variable in the command it
# runs to enable its job server during parallel builds. Hence the
# comments below.
all-multi:
$(MULTIDO) $(AM_MAKEFLAGS) DO=all multi-do # $(MAKE)
install-multi:
$(MULTIDO) $(AM_MAKEFLAGS) DO=install multi-do # $(MAKE)
mostlyclean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=mostlyclean multi-clean # $(MAKE)
clean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=clean multi-clean # $(MAKE)
distclean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=distclean multi-clean # $(MAKE)
maintainer-clean-multi:
$(MULTICLEAN) $(AM_MAKEFLAGS) DO=maintainer-clean multi-clean # $(MAKE)
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
mkid -fID $$unique
tags: TAGS
TAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
set x; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
shift; \
if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
test -n "$$unique" || unique=$$empty_fix; \
if test $$# -gt 0; then \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
"$$@" $$unique; \
else \
$(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$unique; \
fi; \
fi
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) '{ files[$$0] = 1; nonempty = 1; } \
END { if (nonempty) { for (i in files) print i; }; }'`; \
test -z "$(CTAGS_ARGS)$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& $(am__cd) $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) "$$here"
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
check-TESTS: $(TESTS)
@failed=0; all=0; xfail=0; xpass=0; skip=0; \
srcdir=$(srcdir); export srcdir; \
list=' $(TESTS) '; \
$(am__tty_colors); \
if test -n "$$list"; then \
for tst in $$list; do \
if test -f ./$$tst; then dir=./; \
elif test -f $$tst; then dir=; \
else dir="$(srcdir)/"; fi; \
if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
*[\ \ ]$$tst[\ \ ]*) \
xpass=`expr $$xpass + 1`; \
failed=`expr $$failed + 1`; \
col=$$red; res=XPASS; \
;; \
*) \
col=$$grn; res=PASS; \
;; \
esac; \
elif test $$? -ne 77; then \
all=`expr $$all + 1`; \
case " $(XFAIL_TESTS) " in \
*[\ \ ]$$tst[\ \ ]*) \
xfail=`expr $$xfail + 1`; \
col=$$lgn; res=XFAIL; \
;; \
*) \
failed=`expr $$failed + 1`; \
col=$$red; res=FAIL; \
;; \
esac; \
else \
skip=`expr $$skip + 1`; \
col=$$blu; res=SKIP; \
fi; \
echo "$${col}$$res$${std}: $$tst"; \
done; \
if test "$$all" -eq 1; then \
tests="test"; \
All=""; \
else \
tests="tests"; \
All="All "; \
fi; \
if test "$$failed" -eq 0; then \
if test "$$xfail" -eq 0; then \
banner="$$All$$all $$tests passed"; \
else \
if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
fi; \
else \
if test "$$xpass" -eq 0; then \
banner="$$failed of $$all $$tests failed"; \
else \
if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
fi; \
fi; \
dashes="$$banner"; \
skipped=""; \
if test "$$skip" -ne 0; then \
if test "$$skip" -eq 1; then \
skipped="($$skip test was not run)"; \
else \
skipped="($$skip tests were not run)"; \
fi; \
test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
dashes="$$skipped"; \
fi; \
report=""; \
if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
report="Please report to $(PACKAGE_BUGREPORT)"; \
test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
dashes="$$report"; \
fi; \
dashes=`echo "$$dashes" | sed s/./=/g`; \
if test "$$failed" -eq 0; then \
echo "$$grn$$dashes"; \
else \
echo "$$red$$dashes"; \
fi; \
echo "$$banner"; \
test -z "$$skipped" || echo "$$skipped"; \
test -z "$$report" || echo "$$report"; \
echo "$$dashes$$std"; \
test "$$failed" -eq 0; \
else :; fi
check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
$(MAKE) $(AM_MAKEFLAGS) check-TESTS
check: check-am
all-am: Makefile $(LTLIBRARIES) all-multi config.h
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
-test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am clean-multi
clean-am: clean-checkPROGRAMS clean-generic clean-libtool \
clean-noinstLTLIBRARIES mostlyclean-am
distclean: distclean-am distclean-multi
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-hdr distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
html: html-am
html-am:
info: info-am
info-am:
install-data-am:
install-dvi: install-dvi-am
install-dvi-am:
install-exec-am: install-multi
install-html: install-html-am
install-html-am:
install-info: install-info-am
install-info-am:
install-man:
install-pdf: install-pdf-am
install-pdf-am:
install-ps: install-ps-am
install-ps-am:
installcheck-am:
maintainer-clean: maintainer-clean-am maintainer-clean-multi
-rm -f $(am__CONFIG_DISTCLEAN_FILES)
-rm -rf $(top_srcdir)/autom4te.cache
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am mostlyclean-multi
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am:
.MAKE: all all-multi check-am clean-multi distclean-multi install-am \
install-multi install-strip maintainer-clean-multi \
mostlyclean-multi
.PHONY: CTAGS GTAGS all all-am all-multi am--refresh check check-TESTS \
check-am clean clean-checkPROGRAMS clean-generic clean-libtool \
clean-multi clean-noinstLTLIBRARIES ctags distclean \
distclean-compile distclean-generic distclean-hdr \
distclean-libtool distclean-multi distclean-tags dvi dvi-am \
html html-am info info-am install install-am install-data \
install-data-am install-dvi install-dvi-am install-exec \
install-exec-am install-html install-html-am install-info \
install-info-am install-man install-multi install-pdf \
install-pdf-am install-ps install-ps-am install-strip \
installcheck installcheck-am installdirs maintainer-clean \
maintainer-clean-generic maintainer-clean-multi mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool \
mostlyclean-multi pdf pdf-am ps ps-am tags uninstall \
uninstall-am
alloc.lo: config.h backtrace.h internal.h
backtrace.lo: config.h backtrace.h
btest.lo: (INCDIR)/filenames.h backtrace.h backtrace-supported.h
dwarf.lo: config.h $(INCDIR)/dwarf2.h $(INCDIR)/dwarf2.def \
$(INCDIR)/filenames.h backtrace.h internal.h
elf.lo: config.h backtrace.h internal.h
fileline.lo: config.h backtrace.h internal.h
mmap.lo: config.h backtrace.h internal.h
mmapio.lo: config.h backtrace.h internal.h
nounwind.lo: config.h internal.h
posix.lo: config.h backtrace.h internal.h
print.lo: config.h backtrace.h internal.h
read.lo: config.h backtrace.h internal.h
simple.lo: config.h backtrace.h internal.h
state.lo: config.h backtrace.h backtrace-supported.h internal.h
unknown.lo: config.h backtrace.h internal.h
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

23
src/libbacktrace/README Normal file
View File

@ -0,0 +1,23 @@
The libbacktrace library
Initially written by Ian Lance Taylor <iant@google.com>
The libbacktrace library may be linked into a program or library and
used to produce symbolic backtraces. Sample uses would be to print a
detailed backtrace when an error occurs or to gather detailed
profiling information.
The libbacktrace library is provided under a BSD license. See the
source files for the exact license text.
The public functions are declared and documented in the header file
backtrace.h, which should be #include'd by a user of the library.
Building libbacktrace will generate a file backtrace-supported.h,
which a user of the library may use to determine whether backtraces
will work. See the source file backtrace-supported.h.in for the
macros that it defines.
As of September 2012, libbacktrace only supports ELF executables with
DWARF debugging information. The library is written to make it
straightforward to add support for other object file and debugging
formats.

667
src/libbacktrace/aclocal.m4 vendored Normal file
View File

@ -0,0 +1,667 @@
# generated automatically by aclocal 1.11.1 -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
# 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
m4_if(m4_defn([AC_AUTOCONF_VERSION]), [2.64],,
[m4_warning([this file was generated for autoconf 2.64.
You have another version of autoconf. It may work, but is not guaranteed to.
If you have problems, you may need to regenerate the build system entirely.
To do so, use the procedure documented by the package, typically `autoreconf'.])])
# Copyright (C) 2002, 2003, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_AUTOMAKE_VERSION(VERSION)
# ----------------------------
# Automake X.Y traces this macro to ensure aclocal.m4 has been
# generated from the m4 files accompanying Automake X.Y.
# (This private macro should not be called outside this file.)
AC_DEFUN([AM_AUTOMAKE_VERSION],
[am__api_version='1.11'
dnl Some users find AM_AUTOMAKE_VERSION and mistake it for a way to
dnl require some minimum version. Point them to the right macro.
m4_if([$1], [1.11.1], [],
[AC_FATAL([Do not call $0, use AM_INIT_AUTOMAKE([$1]).])])dnl
])
# _AM_AUTOCONF_VERSION(VERSION)
# -----------------------------
# aclocal traces this macro to find the Autoconf version.
# This is a private macro too. Using m4_define simplifies
# the logic in aclocal, which can simply ignore this definition.
m4_define([_AM_AUTOCONF_VERSION], [])
# AM_SET_CURRENT_AUTOMAKE_VERSION
# -------------------------------
# Call AM_AUTOMAKE_VERSION and AM_AUTOMAKE_VERSION so they can be traced.
# This function is AC_REQUIREd by AM_INIT_AUTOMAKE.
AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION],
[AM_AUTOMAKE_VERSION([1.11.1])dnl
m4_ifndef([AC_AUTOCONF_VERSION],
[m4_copy([m4_PACKAGE_VERSION], [AC_AUTOCONF_VERSION])])dnl
_AM_AUTOCONF_VERSION(m4_defn([AC_AUTOCONF_VERSION]))])
# AM_AUX_DIR_EXPAND -*- Autoconf -*-
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets
# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to
# `$srcdir', `$srcdir/..', or `$srcdir/../..'.
#
# Of course, Automake must honor this variable whenever it calls a
# tool from the auxiliary directory. The problem is that $srcdir (and
# therefore $ac_aux_dir as well) can be either absolute or relative,
# depending on how configure is run. This is pretty annoying, since
# it makes $ac_aux_dir quite unusable in subdirectories: in the top
# source directory, any form will work fine, but in subdirectories a
# relative path needs to be adjusted first.
#
# $ac_aux_dir/missing
# fails when called from a subdirectory if $ac_aux_dir is relative
# $top_srcdir/$ac_aux_dir/missing
# fails if $ac_aux_dir is absolute,
# fails when called from a subdirectory in a VPATH build with
# a relative $ac_aux_dir
#
# The reason of the latter failure is that $top_srcdir and $ac_aux_dir
# are both prefixed by $srcdir. In an in-source build this is usually
# harmless because $srcdir is `.', but things will broke when you
# start a VPATH build or use an absolute $srcdir.
#
# So we could use something similar to $top_srcdir/$ac_aux_dir/missing,
# iff we strip the leading $srcdir from $ac_aux_dir. That would be:
# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"`
# and then we would define $MISSING as
# MISSING="\${SHELL} $am_aux_dir/missing"
# This will work as long as MISSING is not called from configure, because
# unfortunately $(top_srcdir) has no meaning in configure.
# However there are other variables, like CC, which are often used in
# configure, and could therefore not use this "fixed" $ac_aux_dir.
#
# Another solution, used here, is to always expand $ac_aux_dir to an
# absolute PATH. The drawback is that using absolute paths prevent a
# configured tree to be moved without reconfiguration.
AC_DEFUN([AM_AUX_DIR_EXPAND],
[dnl Rely on autoconf to set up CDPATH properly.
AC_PREREQ([2.50])dnl
# expand $ac_aux_dir to an absolute path
am_aux_dir=`cd $ac_aux_dir && pwd`
])
# AM_CONDITIONAL -*- Autoconf -*-
# Copyright (C) 1997, 2000, 2001, 2003, 2004, 2005, 2006, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 9
# AM_CONDITIONAL(NAME, SHELL-CONDITION)
# -------------------------------------
# Define a conditional.
AC_DEFUN([AM_CONDITIONAL],
[AC_PREREQ(2.52)dnl
ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])],
[$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl
AC_SUBST([$1_TRUE])dnl
AC_SUBST([$1_FALSE])dnl
_AM_SUBST_NOTMAKE([$1_TRUE])dnl
_AM_SUBST_NOTMAKE([$1_FALSE])dnl
m4_define([_AM_COND_VALUE_$1], [$2])dnl
if $2; then
$1_TRUE=
$1_FALSE='#'
else
$1_TRUE='#'
$1_FALSE=
fi
AC_CONFIG_COMMANDS_PRE(
[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then
AC_MSG_ERROR([[conditional "$1" was never defined.
Usually this means the macro was only invoked conditionally.]])
fi])])
# Do all the work for Automake. -*- Autoconf -*-
# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
# 2005, 2006, 2008, 2009 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 16
# This macro actually does too much. Some checks are only needed if
# your package does certain things. But this isn't really a big deal.
# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE])
# AM_INIT_AUTOMAKE([OPTIONS])
# -----------------------------------------------
# The call with PACKAGE and VERSION arguments is the old style
# call (pre autoconf-2.50), which is being phased out. PACKAGE
# and VERSION should now be passed to AC_INIT and removed from
# the call to AM_INIT_AUTOMAKE.
# We support both call styles for the transition. After
# the next Automake release, Autoconf can make the AC_INIT
# arguments mandatory, and then we can depend on a new Autoconf
# release and drop the old call support.
AC_DEFUN([AM_INIT_AUTOMAKE],
[AC_PREREQ([2.62])dnl
dnl Autoconf wants to disallow AM_ names. We explicitly allow
dnl the ones we care about.
m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl
AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl
AC_REQUIRE([AC_PROG_INSTALL])dnl
if test "`cd $srcdir && pwd`" != "`pwd`"; then
# Use -I$(srcdir) only when $(srcdir) != ., so that make's output
# is not polluted with repeated "-I."
AC_SUBST([am__isrc], [' -I$(srcdir)'])_AM_SUBST_NOTMAKE([am__isrc])dnl
# test to see if srcdir already configured
if test -f $srcdir/config.status; then
AC_MSG_ERROR([source directory already configured; run "make distclean" there first])
fi
fi
# test whether we have cygpath
if test -z "$CYGPATH_W"; then
if (cygpath --version) >/dev/null 2>/dev/null; then
CYGPATH_W='cygpath -w'
else
CYGPATH_W=echo
fi
fi
AC_SUBST([CYGPATH_W])
# Define the identity of the package.
dnl Distinguish between old-style and new-style calls.
m4_ifval([$2],
[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl
AC_SUBST([PACKAGE], [$1])dnl
AC_SUBST([VERSION], [$2])],
[_AM_SET_OPTIONS([$1])dnl
dnl Diagnose old-style AC_INIT with new-style AM_AUTOMAKE_INIT.
m4_if(m4_ifdef([AC_PACKAGE_NAME], 1)m4_ifdef([AC_PACKAGE_VERSION], 1), 11,,
[m4_fatal([AC_INIT should be called with package and version arguments])])dnl
AC_SUBST([PACKAGE], ['AC_PACKAGE_TARNAME'])dnl
AC_SUBST([VERSION], ['AC_PACKAGE_VERSION'])])dnl
_AM_IF_OPTION([no-define],,
[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package])
AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl
# Some tools Automake needs.
AC_REQUIRE([AM_SANITY_CHECK])dnl
AC_REQUIRE([AC_ARG_PROGRAM])dnl
AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version})
AM_MISSING_PROG(AUTOCONF, autoconf)
AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version})
AM_MISSING_PROG(AUTOHEADER, autoheader)
AM_MISSING_PROG(MAKEINFO, makeinfo)
AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
AC_REQUIRE([AM_PROG_INSTALL_STRIP])dnl
AC_REQUIRE([AM_PROG_MKDIR_P])dnl
# We need awk for the "check" target. The system "awk" is bad on
# some platforms.
AC_REQUIRE([AC_PROG_AWK])dnl
AC_REQUIRE([AC_PROG_MAKE_SET])dnl
AC_REQUIRE([AM_SET_LEADING_DOT])dnl
_AM_IF_OPTION([tar-ustar], [_AM_PROG_TAR([ustar])],
[_AM_IF_OPTION([tar-pax], [_AM_PROG_TAR([pax])],
[_AM_PROG_TAR([v7])])])
_AM_IF_OPTION([no-dependencies],,
[AC_PROVIDE_IFELSE([AC_PROG_CC],
[_AM_DEPENDENCIES(CC)],
[define([AC_PROG_CC],
defn([AC_PROG_CC])[_AM_DEPENDENCIES(CC)])])dnl
AC_PROVIDE_IFELSE([AC_PROG_CXX],
[_AM_DEPENDENCIES(CXX)],
[define([AC_PROG_CXX],
defn([AC_PROG_CXX])[_AM_DEPENDENCIES(CXX)])])dnl
AC_PROVIDE_IFELSE([AC_PROG_OBJC],
[_AM_DEPENDENCIES(OBJC)],
[define([AC_PROG_OBJC],
defn([AC_PROG_OBJC])[_AM_DEPENDENCIES(OBJC)])])dnl
])
_AM_IF_OPTION([silent-rules], [AC_REQUIRE([AM_SILENT_RULES])])dnl
dnl The `parallel-tests' driver may need to know about EXEEXT, so add the
dnl `am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen. This macro
dnl is hooked onto _AC_COMPILER_EXEEXT early, see below.
AC_CONFIG_COMMANDS_PRE(dnl
[m4_provide_if([_AM_COMPILER_EXEEXT],
[AM_CONDITIONAL([am__EXEEXT], [test -n "$EXEEXT"])])])dnl
])
dnl Hook into `_AC_COMPILER_EXEEXT' early to learn its expansion. Do not
dnl add the conditional right here, as _AC_COMPILER_EXEEXT may be further
dnl mangled by Autoconf and run in a shell conditional statement.
m4_define([_AC_COMPILER_EXEEXT],
m4_defn([_AC_COMPILER_EXEEXT])[m4_provide([_AM_COMPILER_EXEEXT])])
# When config.status generates a header, we must update the stamp-h file.
# This file resides in the same directory as the config header
# that is generated. The stamp files are numbered to have different names.
# Autoconf calls _AC_AM_CONFIG_HEADER_HOOK (when defined) in the
# loop where config.status creates the headers, so we can generate
# our stamp files there.
AC_DEFUN([_AC_AM_CONFIG_HEADER_HOOK],
[# Compute $1's index in $config_headers.
_am_arg=$1
_am_stamp_count=1
for _am_header in $config_headers :; do
case $_am_header in
$_am_arg | $_am_arg:* )
break ;;
* )
_am_stamp_count=`expr $_am_stamp_count + 1` ;;
esac
done
echo "timestamp for $_am_arg" >`AS_DIRNAME(["$_am_arg"])`/stamp-h[]$_am_stamp_count])
# Copyright (C) 2001, 2003, 2005, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_SH
# ------------------
# Define $install_sh.
AC_DEFUN([AM_PROG_INSTALL_SH],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
if test x"${install_sh}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
install_sh="\${SHELL} '$am_aux_dir/install-sh'" ;;
*)
install_sh="\${SHELL} $am_aux_dir/install-sh"
esac
fi
AC_SUBST(install_sh)])
# Add --enable-maintainer-mode option to configure. -*- Autoconf -*-
# From Jim Meyering
# Copyright (C) 1996, 1998, 2000, 2001, 2002, 2003, 2004, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 5
# AM_MAINTAINER_MODE([DEFAULT-MODE])
# ----------------------------------
# Control maintainer-specific portions of Makefiles.
# Default is to disable them, unless `enable' is passed literally.
# For symmetry, `disable' may be passed as well. Anyway, the user
# can override the default with the --enable/--disable switch.
AC_DEFUN([AM_MAINTAINER_MODE],
[m4_case(m4_default([$1], [disable]),
[enable], [m4_define([am_maintainer_other], [disable])],
[disable], [m4_define([am_maintainer_other], [enable])],
[m4_define([am_maintainer_other], [enable])
m4_warn([syntax], [unexpected argument to AM@&t@_MAINTAINER_MODE: $1])])
AC_MSG_CHECKING([whether to am_maintainer_other maintainer-specific portions of Makefiles])
dnl maintainer-mode's default is 'disable' unless 'enable' is passed
AC_ARG_ENABLE([maintainer-mode],
[ --][am_maintainer_other][-maintainer-mode am_maintainer_other make rules and dependencies not useful
(and sometimes confusing) to the casual installer],
[USE_MAINTAINER_MODE=$enableval],
[USE_MAINTAINER_MODE=]m4_if(am_maintainer_other, [enable], [no], [yes]))
AC_MSG_RESULT([$USE_MAINTAINER_MODE])
AM_CONDITIONAL([MAINTAINER_MODE], [test $USE_MAINTAINER_MODE = yes])
MAINT=$MAINTAINER_MODE_TRUE
AC_SUBST([MAINT])dnl
]
)
AU_DEFUN([jm_MAINTAINER_MODE], [AM_MAINTAINER_MODE])
# Fake the existence of programs that GNU maintainers use. -*- Autoconf -*-
# Copyright (C) 1997, 1999, 2000, 2001, 2003, 2004, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 6
# AM_MISSING_PROG(NAME, PROGRAM)
# ------------------------------
AC_DEFUN([AM_MISSING_PROG],
[AC_REQUIRE([AM_MISSING_HAS_RUN])
$1=${$1-"${am_missing_run}$2"}
AC_SUBST($1)])
# AM_MISSING_HAS_RUN
# ------------------
# Define MISSING if not defined so far and test if it supports --run.
# If it does, set am_missing_run to use it, otherwise, to nothing.
AC_DEFUN([AM_MISSING_HAS_RUN],
[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl
AC_REQUIRE_AUX_FILE([missing])dnl
if test x"${MISSING+set}" != xset; then
case $am_aux_dir in
*\ * | *\ *)
MISSING="\${SHELL} \"$am_aux_dir/missing\"" ;;
*)
MISSING="\${SHELL} $am_aux_dir/missing" ;;
esac
fi
# Use eval to expand $SHELL
if eval "$MISSING --run true"; then
am_missing_run="$MISSING --run "
else
am_missing_run=
AC_MSG_WARN([`missing' script is too old or missing])
fi
])
# Copyright (C) 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_MKDIR_P
# ---------------
# Check for `mkdir -p'.
AC_DEFUN([AM_PROG_MKDIR_P],
[AC_PREREQ([2.60])dnl
AC_REQUIRE([AC_PROG_MKDIR_P])dnl
dnl Automake 1.8 to 1.9.6 used to define mkdir_p. We now use MKDIR_P,
dnl while keeping a definition of mkdir_p for backward compatibility.
dnl @MKDIR_P@ is magic: AC_OUTPUT adjusts its value for each Makefile.
dnl However we cannot define mkdir_p as $(MKDIR_P) for the sake of
dnl Makefile.ins that do not define MKDIR_P, so we do our own
dnl adjustment using top_builddir (which is defined more often than
dnl MKDIR_P).
AC_SUBST([mkdir_p], ["$MKDIR_P"])dnl
case $mkdir_p in
[[\\/$]]* | ?:[[\\/]]*) ;;
*/*) mkdir_p="\$(top_builddir)/$mkdir_p" ;;
esac
])
# Helper functions for option handling. -*- Autoconf -*-
# Copyright (C) 2001, 2002, 2003, 2005, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 4
# _AM_MANGLE_OPTION(NAME)
# -----------------------
AC_DEFUN([_AM_MANGLE_OPTION],
[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])])
# _AM_SET_OPTION(NAME)
# ------------------------------
# Set option NAME. Presently that only means defining a flag for this option.
AC_DEFUN([_AM_SET_OPTION],
[m4_define(_AM_MANGLE_OPTION([$1]), 1)])
# _AM_SET_OPTIONS(OPTIONS)
# ----------------------------------
# OPTIONS is a space-separated list of Automake options.
AC_DEFUN([_AM_SET_OPTIONS],
[m4_foreach_w([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])])
# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET])
# -------------------------------------------
# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise.
AC_DEFUN([_AM_IF_OPTION],
[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])])
# Check to make sure that the build environment is sane. -*- Autoconf -*-
# Copyright (C) 1996, 1997, 2000, 2001, 2003, 2005, 2008
# Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 5
# AM_SANITY_CHECK
# ---------------
AC_DEFUN([AM_SANITY_CHECK],
[AC_MSG_CHECKING([whether build environment is sane])
# Just in case
sleep 1
echo timestamp > conftest.file
# Reject unsafe characters in $srcdir or the absolute working directory
# name. Accept space and tab only in the latter.
am_lf='
'
case `pwd` in
*[[\\\"\#\$\&\'\`$am_lf]]*)
AC_MSG_ERROR([unsafe absolute working directory name]);;
esac
case $srcdir in
*[[\\\"\#\$\&\'\`$am_lf\ \ ]]*)
AC_MSG_ERROR([unsafe srcdir value: `$srcdir']);;
esac
# Do `set' in a subshell so we don't clobber the current shell's
# arguments. Must try -L first in case configure is actually a
# symlink; some systems play weird games with the mod time of symlinks
# (eg FreeBSD returns the mod time of the symlink's containing
# directory).
if (
set X `ls -Lt "$srcdir/configure" conftest.file 2> /dev/null`
if test "$[*]" = "X"; then
# -L didn't work.
set X `ls -t "$srcdir/configure" conftest.file`
fi
rm -f conftest.file
if test "$[*]" != "X $srcdir/configure conftest.file" \
&& test "$[*]" != "X conftest.file $srcdir/configure"; then
# If neither matched, then we have a broken ls. This can happen
# if, for instance, CONFIG_SHELL is bash and it inherits a
# broken ls alias from the environment. This has actually
# happened. Such a system could not be considered "sane".
AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken
alias in your environment])
fi
test "$[2]" = conftest.file
)
then
# Ok.
:
else
AC_MSG_ERROR([newly created file is older than distributed files!
Check your system clock])
fi
AC_MSG_RESULT(yes)])
# Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# AM_PROG_INSTALL_STRIP
# ---------------------
# One issue with vendor `install' (even GNU) is that you can't
# specify the program used to strip binaries. This is especially
# annoying in cross-compiling environments, where the build's strip
# is unlikely to handle the host's binaries.
# Fortunately install-sh will honor a STRIPPROG variable, so we
# always use install-sh in `make install-strip', and initialize
# STRIPPROG with the value of the STRIP variable (set by the user).
AC_DEFUN([AM_PROG_INSTALL_STRIP],
[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl
# Installed binaries are usually stripped using `strip' when the user
# run `make install-strip'. However `strip' might not be the right
# tool to use in cross-compilation environments, therefore Automake
# will honor the `STRIP' environment variable to overrule this program.
dnl Don't test for $cross_compiling = yes, because it might be `maybe'.
if test "$cross_compiling" != no; then
AC_CHECK_TOOL([STRIP], [strip], :)
fi
INSTALL_STRIP_PROGRAM="\$(install_sh) -c -s"
AC_SUBST([INSTALL_STRIP_PROGRAM])])
# Copyright (C) 2006, 2008 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 2
# _AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Prevent Automake from outputting VARIABLE = @VARIABLE@ in Makefile.in.
# This macro is traced by Automake.
AC_DEFUN([_AM_SUBST_NOTMAKE])
# AM_SUBST_NOTMAKE(VARIABLE)
# ---------------------------
# Public sister of _AM_SUBST_NOTMAKE.
AC_DEFUN([AM_SUBST_NOTMAKE], [_AM_SUBST_NOTMAKE($@)])
# Check how to create a tarball. -*- Autoconf -*-
# Copyright (C) 2004, 2005 Free Software Foundation, Inc.
#
# This file is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# serial 2
# _AM_PROG_TAR(FORMAT)
# --------------------
# Check how to create a tarball in format FORMAT.
# FORMAT should be one of `v7', `ustar', or `pax'.
#
# Substitute a variable $(am__tar) that is a command
# writing to stdout a FORMAT-tarball containing the directory
# $tardir.
# tardir=directory && $(am__tar) > result.tar
#
# Substitute a variable $(am__untar) that extract such
# a tarball read from stdin.
# $(am__untar) < result.tar
AC_DEFUN([_AM_PROG_TAR],
[# Always define AMTAR for backward compatibility.
AM_MISSING_PROG([AMTAR], [tar])
m4_if([$1], [v7],
[am__tar='${AMTAR} chof - "$$tardir"'; am__untar='${AMTAR} xf -'],
[m4_case([$1], [ustar],, [pax],,
[m4_fatal([Unknown tar format])])
AC_MSG_CHECKING([how to create a $1 tar archive])
# Loop over all known methods to create a tar archive until one works.
_am_tools='gnutar m4_if([$1], [ustar], [plaintar]) pax cpio none'
_am_tools=${am_cv_prog_tar_$1-$_am_tools}
# Do not fold the above two line into one, because Tru64 sh and
# Solaris sh will not grok spaces in the rhs of `-'.
for _am_tool in $_am_tools
do
case $_am_tool in
gnutar)
for _am_tar in tar gnutar gtar;
do
AM_RUN_LOG([$_am_tar --version]) && break
done
am__tar="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$$tardir"'
am__tar_="$_am_tar --format=m4_if([$1], [pax], [posix], [$1]) -chf - "'"$tardir"'
am__untar="$_am_tar -xf -"
;;
plaintar)
# Must skip GNU tar: if it does not support --format= it doesn't create
# ustar tarball either.
(tar --version) >/dev/null 2>&1 && continue
am__tar='tar chf - "$$tardir"'
am__tar_='tar chf - "$tardir"'
am__untar='tar xf -'
;;
pax)
am__tar='pax -L -x $1 -w "$$tardir"'
am__tar_='pax -L -x $1 -w "$tardir"'
am__untar='pax -r'
;;
cpio)
am__tar='find "$$tardir" -print | cpio -o -H $1 -L'
am__tar_='find "$tardir" -print | cpio -o -H $1 -L'
am__untar='cpio -i -H $1 -d'
;;
none)
am__tar=false
am__tar_=false
am__untar=false
;;
esac
# If the value was cached, stop now. We just wanted to have am__tar
# and am__untar set.
test -n "${am_cv_prog_tar_$1}" && break
# tar/untar a dummy directory, and stop if the command works
rm -rf conftest.dir
mkdir conftest.dir
echo GrepMe > conftest.dir/file
AM_RUN_LOG([tardir=conftest.dir && eval $am__tar_ >conftest.tar])
rm -rf conftest.dir
if test -s conftest.tar; then
AM_RUN_LOG([$am__untar <conftest.tar])
grep GrepMe conftest.dir/file >/dev/null 2>&1 && break
fi
done
rm -rf conftest.dir
AC_CACHE_VAL([am_cv_prog_tar_$1], [am_cv_prog_tar_$1=$_am_tool])
AC_MSG_RESULT([$am_cv_prog_tar_$1])])
AC_SUBST([am__tar])
AC_SUBST([am__untar])
]) # _AM_PROG_TAR
m4_include([../config/lead-dot.m4])
m4_include([../config/multi.m4])
m4_include([../config/override.m4])
m4_include([../config/stdint.m4])
m4_include([../config/unwind_ipinfo.m4])
m4_include([../config/warnings.m4])
m4_include([../libtool.m4])
m4_include([../ltoptions.m4])
m4_include([../ltsugar.m4])
m4_include([../ltversion.m4])
m4_include([../lt~obsolete.m4])

152
src/libbacktrace/alloc.c Normal file
View File

@ -0,0 +1,152 @@
/* alloc.c -- Memory allocation without mmap.
Copyright (C) 2012-2014 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
(1) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
(2) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
(3) The name of the author may not be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include "backtrace.h"
#include "internal.h"
/* Allocation routines to use on systems that do not support anonymous
mmap. This implementation just uses malloc, which means that the
backtrace functions may not be safely invoked from a signal
handler. */
/* Allocate memory like malloc. */
void *
backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED,
size_t size, backtrace_error_callback error_callback,
void *data)
{
void *ret;
ret = malloc (size);
if (ret == NULL)
error_callback (data, "malloc", errno);
return ret;
}
/* Free memory. */
void
backtrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED,
void *p, size_t size ATTRIBUTE_UNUSED,
backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
void *data ATTRIBUTE_UNUSED)
{
free (p);
}
/* Grow VEC by SIZE bytes. */
void *
backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED,
size_t size, backtrace_error_callback error_callback,
void *data, struct backtrace_vector *vec)
{
void *ret;
if (size > vec->alc)
{
size_t alc;
void *base;
if (vec->size == 0)
alc = 32 * size;
else if (vec->size >= 4096)
alc = vec->size + 4096;
else
alc = 2 * vec->size;
if (alc < vec->size + size)
alc = vec->size + size;
base = realloc (vec->base, alc);
if (base == NULL)
{
error_callback (data, "realloc", errno);
return NULL;
}
vec->base = base;
vec->alc = alc - vec->size;
}
ret = (char *) vec->base + vec->size;
vec->size += size;
vec->alc -= size;
return ret;
}
/* Finish the current allocation on VEC. */
void *
backtrace_vector_finish (struct backtrace_state *state,
struct backtrace_vector *vec,
backtrace_error_callback error_callback,
void *data)
{
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. */
int
backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED,
struct backtrace_vector *vec,
backtrace_error_callback error_callback,
void *data)
{
vec->base = realloc (vec->base, vec->size);
if (vec->base == NULL)
{
error_callback (data, "realloc", errno);
return 0;
}
vec->alc = 0;
return 1;
}

313
src/libbacktrace/ansidecl.h Normal file
View File

@ -0,0 +1,313 @@
/* ANSI and traditional C compatability macros
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001,
2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2013
Free Software Foundation, Inc.
This file is part of the GNU C Library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
/* ANSI and traditional C compatibility macros
ANSI C is assumed if __STDC__ is #defined.
Macro ANSI C definition Traditional C definition
----- ---- - ---------- ----------- - ----------
PTR `void *' `char *'
const not defined `'
volatile not defined `'
signed not defined `'
For ease of writing code which uses GCC extensions but needs to be
portable to other compilers, we provide the GCC_VERSION macro that
simplifies testing __GNUC__ and __GNUC_MINOR__ together, and various
wrappers around __attribute__. Also, __extension__ will be #defined
to nothing if it doesn't work. See below. */
#ifndef _ANSIDECL_H
#define _ANSIDECL_H 1
#ifdef __cplusplus
extern "C" {
#endif
/* Every source file includes this file,
so they will all get the switch for lint. */
/* LINTLIBRARY */
/* Using MACRO(x,y) in cpp #if conditionals does not work with some
older preprocessors. Thus we can't define something like this:
#define HAVE_GCC_VERSION(MAJOR, MINOR) \
(__GNUC__ > (MAJOR) || (__GNUC__ == (MAJOR) && __GNUC_MINOR__ >= (MINOR)))
and then test "#if HAVE_GCC_VERSION(2,7)".
So instead we use the macro below and test it against specific values. */
/* This macro simplifies testing whether we are using gcc, and if it
is of a particular minimum version. (Both major & minor numbers are
significant.) This macro will evaluate to 0 if we are not using
gcc at all. */
#ifndef GCC_VERSION
#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
#endif /* GCC_VERSION */
#if defined (__STDC__) || defined(__cplusplus) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(_WIN32)
/* All known AIX compilers implement these things (but don't always
define __STDC__). The RISC/OS MIPS compiler defines these things
in SVR4 mode, but does not define __STDC__. */
/* eraxxon@alumni.rice.edu: The Compaq C++ compiler, unlike many other
C++ compilers, does not define __STDC__, though it acts as if this
was so. (Verified versions: 5.7, 6.2, 6.3, 6.5) */
#define PTR void *
#undef const
#undef volatile
#undef signed
/* inline requires special treatment; it's in C99, and GCC >=2.7 supports
it too, but it's not in C89. */
#undef inline
#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) || (defined(__SUNPRO_C) && defined(__C99FEATURES__))
/* it's a keyword */
#else
# if GCC_VERSION >= 2007
# define inline __inline__ /* __inline__ prevents -pedantic warnings */
# else
# define inline /* nothing */
# endif
#endif
#else /* Not ANSI C. */
#define PTR char *
/* some systems define these in header files for non-ansi mode */
#undef const
#undef volatile
#undef signed
#undef inline
#define const
#define volatile
#define signed
#define inline
#endif /* ANSI C. */
/* Define macros for some gcc attributes. This permits us to use the
macros freely, and know that they will come into play for the
version of gcc in which they are supported. */
#if (GCC_VERSION < 2007)
# define __attribute__(x)
#endif
/* Attribute __malloc__ on functions was valid as of gcc 2.96. */
#ifndef ATTRIBUTE_MALLOC
# if (GCC_VERSION >= 2096)
# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
# else
# define ATTRIBUTE_MALLOC
# endif /* GNUC >= 2.96 */
#endif /* ATTRIBUTE_MALLOC */
/* Attributes on labels were valid as of gcc 2.93 and g++ 4.5. For
g++ an attribute on a label must be followed by a semicolon. */
#ifndef ATTRIBUTE_UNUSED_LABEL
# ifndef __cplusplus
# if GCC_VERSION >= 2093
# define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED
# else
# define ATTRIBUTE_UNUSED_LABEL
# endif
# else
# if GCC_VERSION >= 4005
# define ATTRIBUTE_UNUSED_LABEL ATTRIBUTE_UNUSED ;
# else
# define ATTRIBUTE_UNUSED_LABEL
# endif
# endif
#endif
/* Similarly to ARG_UNUSED below. Prior to GCC 3.4, the C++ frontend
couldn't parse attributes placed after the identifier name, and now
the entire compiler is built with C++. */
#ifndef ATTRIBUTE_UNUSED
#if GCC_VERSION >= 3004
# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#else
#define ATTRIBUTE_UNUSED
#endif
#endif /* ATTRIBUTE_UNUSED */
/* Before GCC 3.4, the C++ frontend couldn't parse attributes placed after the
identifier name. */
#if ! defined(__cplusplus) || (GCC_VERSION >= 3004)
# define ARG_UNUSED(NAME) NAME ATTRIBUTE_UNUSED
#else /* !__cplusplus || GNUC >= 3.4 */
# define ARG_UNUSED(NAME) NAME
#endif /* !__cplusplus || GNUC >= 3.4 */
#ifndef ATTRIBUTE_NORETURN
#define ATTRIBUTE_NORETURN __attribute__ ((__noreturn__))
#endif /* ATTRIBUTE_NORETURN */
/* Attribute `nonnull' was valid as of gcc 3.3. */
#ifndef ATTRIBUTE_NONNULL
# if (GCC_VERSION >= 3003)
# define ATTRIBUTE_NONNULL(m) __attribute__ ((__nonnull__ (m)))
# else
# define ATTRIBUTE_NONNULL(m)
# endif /* GNUC >= 3.3 */
#endif /* ATTRIBUTE_NONNULL */
/* Attribute `returns_nonnull' was valid as of gcc 4.9. */
#ifndef ATTRIBUTE_RETURNS_NONNULL
# if (GCC_VERSION >= 4009)
# define ATTRIBUTE_RETURNS_NONNULL __attribute__ ((__returns_nonnull__))
# else
# define ATTRIBUTE_RETURNS_NONNULL
# endif /* GNUC >= 4.9 */
#endif /* ATTRIBUTE_RETURNS_NONNULL */
/* Attribute `pure' was valid as of gcc 3.0. */
#ifndef ATTRIBUTE_PURE
# if (GCC_VERSION >= 3000)
# define ATTRIBUTE_PURE __attribute__ ((__pure__))
# else
# define ATTRIBUTE_PURE
# endif /* GNUC >= 3.0 */
#endif /* ATTRIBUTE_PURE */
/* Use ATTRIBUTE_PRINTF when the format specifier must not be NULL.
This was the case for the `printf' format attribute by itself
before GCC 3.3, but as of 3.3 we need to add the `nonnull'
attribute to retain this behavior. */
#ifndef ATTRIBUTE_PRINTF
#define ATTRIBUTE_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n))) ATTRIBUTE_NONNULL(m)
#define ATTRIBUTE_PRINTF_1 ATTRIBUTE_PRINTF(1, 2)
#define ATTRIBUTE_PRINTF_2 ATTRIBUTE_PRINTF(2, 3)
#define ATTRIBUTE_PRINTF_3 ATTRIBUTE_PRINTF(3, 4)
#define ATTRIBUTE_PRINTF_4 ATTRIBUTE_PRINTF(4, 5)
#define ATTRIBUTE_PRINTF_5 ATTRIBUTE_PRINTF(5, 6)
#endif /* ATTRIBUTE_PRINTF */
/* Use ATTRIBUTE_FPTR_PRINTF when the format attribute is to be set on
a function pointer. Format attributes were allowed on function
pointers as of gcc 3.1. */
#ifndef ATTRIBUTE_FPTR_PRINTF
# if (GCC_VERSION >= 3001)
# define ATTRIBUTE_FPTR_PRINTF(m, n) ATTRIBUTE_PRINTF(m, n)
# else
# define ATTRIBUTE_FPTR_PRINTF(m, n)
# endif /* GNUC >= 3.1 */
# define ATTRIBUTE_FPTR_PRINTF_1 ATTRIBUTE_FPTR_PRINTF(1, 2)
# define ATTRIBUTE_FPTR_PRINTF_2 ATTRIBUTE_FPTR_PRINTF(2, 3)
# define ATTRIBUTE_FPTR_PRINTF_3 ATTRIBUTE_FPTR_PRINTF(3, 4)
# define ATTRIBUTE_FPTR_PRINTF_4 ATTRIBUTE_FPTR_PRINTF(4, 5)
# define ATTRIBUTE_FPTR_PRINTF_5 ATTRIBUTE_FPTR_PRINTF(5, 6)
#endif /* ATTRIBUTE_FPTR_PRINTF */
/* Use ATTRIBUTE_NULL_PRINTF when the format specifier may be NULL. A
NULL format specifier was allowed as of gcc 3.3. */
#ifndef ATTRIBUTE_NULL_PRINTF
# if (GCC_VERSION >= 3003)
# define ATTRIBUTE_NULL_PRINTF(m, n) __attribute__ ((__format__ (__printf__, m, n)))
# else
# define ATTRIBUTE_NULL_PRINTF(m, n)
# endif /* GNUC >= 3.3 */
# define ATTRIBUTE_NULL_PRINTF_1 ATTRIBUTE_NULL_PRINTF(1, 2)
# define ATTRIBUTE_NULL_PRINTF_2 ATTRIBUTE_NULL_PRINTF(2, 3)
# define ATTRIBUTE_NULL_PRINTF_3 ATTRIBUTE_NULL_PRINTF(3, 4)
# define ATTRIBUTE_NULL_PRINTF_4 ATTRIBUTE_NULL_PRINTF(4, 5)
# define ATTRIBUTE_NULL_PRINTF_5 ATTRIBUTE_NULL_PRINTF(5, 6)
#endif /* ATTRIBUTE_NULL_PRINTF */
/* Attribute `sentinel' was valid as of gcc 3.5. */
#ifndef ATTRIBUTE_SENTINEL
# if (GCC_VERSION >= 3005)
# define ATTRIBUTE_SENTINEL __attribute__ ((__sentinel__))
# else
# define ATTRIBUTE_SENTINEL
# endif /* GNUC >= 3.5 */
#endif /* ATTRIBUTE_SENTINEL */
#ifndef ATTRIBUTE_ALIGNED_ALIGNOF
# if (GCC_VERSION >= 3000)
# define ATTRIBUTE_ALIGNED_ALIGNOF(m) __attribute__ ((__aligned__ (__alignof__ (m))))
# else
# define ATTRIBUTE_ALIGNED_ALIGNOF(m)
# endif /* GNUC >= 3.0 */
#endif /* ATTRIBUTE_ALIGNED_ALIGNOF */
/* Useful for structures whose layout must much some binary specification
regardless of the alignment and padding qualities of the compiler. */
#ifndef ATTRIBUTE_PACKED
# define ATTRIBUTE_PACKED __attribute__ ((packed))
#endif
/* Attribute `hot' and `cold' was valid as of gcc 4.3. */
#ifndef ATTRIBUTE_COLD
# if (GCC_VERSION >= 4003)
# define ATTRIBUTE_COLD __attribute__ ((__cold__))
# else
# define ATTRIBUTE_COLD
# endif /* GNUC >= 4.3 */
#endif /* ATTRIBUTE_COLD */
#ifndef ATTRIBUTE_HOT
# if (GCC_VERSION >= 4003)
# define ATTRIBUTE_HOT __attribute__ ((__hot__))
# else
# define ATTRIBUTE_HOT
# endif /* GNUC >= 4.3 */
#endif /* ATTRIBUTE_HOT */
/* We use __extension__ in some places to suppress -pedantic warnings
about GCC extensions. This feature didn't work properly before
gcc 2.8. */
#if GCC_VERSION < 2008
#define __extension__
#endif
/* This is used to declare a const variable which should be visible
outside of the current compilation unit. Use it as
EXPORTED_CONST int i = 1;
This is because the semantics of const are different in C and C++.
"extern const" is permitted in C but it looks strange, and gcc
warns about it when -Wc++-compat is not used. */
#ifdef __cplusplus
#define EXPORTED_CONST extern const
#else
#define EXPORTED_CONST const
#endif
/* Be conservative and only use enum bitfields with C++ or GCC.
FIXME: provide a complete autoconf test for buggy enum bitfields. */
#ifdef __cplusplus
#define ENUM_BITFIELD(TYPE) enum TYPE
#elif (GCC_VERSION > 2000)
#define ENUM_BITFIELD(TYPE) __extension__ enum TYPE
#else
#define ENUM_BITFIELD(TYPE) unsigned int
#endif
#ifdef __cplusplus
}
#endif
#endif /* ansidecl.h */

113
src/libbacktrace/atomic.c Normal file
View File

@ -0,0 +1,113 @@
/* atomic.c -- Support for atomic functions if not present.
Copyright (C) 2013-2014 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

View File

@ -0,0 +1,61 @@
/* backtrace-supported.h.in -- Whether stack backtrace is supported.
Copyright (C) 2012-2014 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. */
/* The file backtrace-supported.h.in is used by configure to generate
the file backtrace-supported.h. The file backtrace-supported.h may
be #include'd to see whether the backtrace library will be able to
get a backtrace and produce symbolic information. */
/* BACKTRACE_SUPPORTED will be #define'd as 1 if the backtrace library
should work, 0 if it will not. Libraries may #include this to make
other arrangements. */
#define BACKTRACE_SUPPORTED @BACKTRACE_SUPPORTED@
/* BACKTRACE_USES_MALLOC will be #define'd as 1 if the backtrace
library will call malloc as it works, 0 if it will call mmap
instead. This may be used to determine whether it is safe to call
the backtrace functions from a signal handler. In general this
only applies to calls like backtrace and backtrace_pcinfo. It does
not apply to backtrace_simple, which never calls malloc. It does
not apply to backtrace_print, which always calls fprintf and
therefore malloc. */
#define BACKTRACE_USES_MALLOC @BACKTRACE_USES_MALLOC@
/* BACKTRACE_SUPPORTS_THREADS will be #define'd as 1 if the backtrace
library is configured with threading support, 0 if not. If this is
0, the threaded parameter to backtrace_create_state must be passed
as 0. */
#define BACKTRACE_SUPPORTS_THREADS @BACKTRACE_SUPPORTS_THREADS@

View File

@ -0,0 +1,108 @@
/* backtrace.c -- Entry point for stack backtrace library.
Copyright (C) 2012-2014 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 "unwind.h"
#include "backtrace.h"
/* The main backtrace_full routine. */
/* Data passed through _Unwind_Backtrace. */
struct backtrace_data
{
/* Number of frames to skip. */
int skip;
/* Library state. */
struct backtrace_state *state;
/* Callback routine. */
backtrace_full_callback callback;
/* Error callback routine. */
backtrace_error_callback error_callback;
/* Data to pass to callback routines. */
void *data;
/* Value to return from backtrace_full. */
int ret;
};
/* Unwind library callback routine. This is passed to
_Unwind_Backtrace. */
static _Unwind_Reason_Code
unwind (struct _Unwind_Context *context, void *vdata)
{
struct backtrace_data *bdata = (struct backtrace_data *) vdata;
uintptr_t pc;
int ip_before_insn = 0;
#ifdef HAVE_GETIPINFO
pc = _Unwind_GetIPInfo (context, &ip_before_insn);
#else
pc = _Unwind_GetIP (context);
#endif
if (bdata->skip > 0)
{
--bdata->skip;
return _URC_NO_REASON;
}
if (!ip_before_insn)
--pc;
bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback,
bdata->error_callback, bdata->data);
if (bdata->ret != 0)
return _URC_END_OF_STACK;
return _URC_NO_REASON;
}
/* Get a stack backtrace. */
int
backtrace_full (struct backtrace_state *state, int skip,
backtrace_full_callback callback,
backtrace_error_callback error_callback, void *data)
{
struct backtrace_data bdata;
bdata.skip = skip + 1;
bdata.state = state;
bdata.callback = callback;
bdata.error_callback = error_callback;
bdata.data = data;
bdata.ret = 0;
_Unwind_Backtrace (unwind, &bdata);
return bdata.ret;
}

View File

@ -0,0 +1,199 @@
/* backtrace.h -- Public header file for stack backtrace library.
Copyright (C) 2012-2014 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
(1) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
(2) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
(3) The name of the author may not be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
#ifndef BACKTRACE_H
#define BACKTRACE_H
#include <stddef.h>
#include <stdio.h>
/* We want to get a definition for uintptr_t, but we still care about
systems that don't have <stdint.h>. */
#if defined(__GLIBC__) && __GLIBC__ >= 2
#include <stdint.h>
#elif defined(HAVE_STDINT_H)
#include <stdint.h>
#else
/* Systems that don't have <stdint.h> must provide gstdint.h, e.g.,
from GCC_HEADER_STDINT in configure.ac. */
#include "gstdint.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/* The backtrace state. This struct is intentionally not defined in
the public interface. */
struct backtrace_state;
/* The type of the error callback argument to backtrace functions.
This function, if not NULL, will be called for certain error cases.
The DATA argument is passed to the function that calls this one.
The MSG argument is an error message. The ERRNUM argument, if
greater than 0, holds an errno value. The MSG buffer may become
invalid after this function returns.
As a special case, the ERRNUM argument will be passed as -1 if no
debug info can be found for the executable, but the function
requires debug info (e.g., backtrace_full, backtrace_pcinfo). The
MSG in this case will be something along the lines of "no debug
info". Similarly, ERRNUM will be passed as -1 if there is no
symbol table, but the function requires a symbol table (e.g.,
backtrace_syminfo). This may be used as a signal that some other
approach should be tried. */
typedef void (*backtrace_error_callback) (void *data, const char *msg,
int errnum);
/* Create state information for the backtrace routines. This must be
called before any of the other routines, and its return value must
be passed to all of the other routines. FILENAME is the path name
of the executable file; if it is NULL the library will try
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 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. */
extern struct backtrace_state *backtrace_create_state (
const char *filename, int threaded,
backtrace_error_callback error_callback, void *data);
/* The type of the callback argument to the backtrace_full function.
DATA is the argument passed to backtrace_full. PC is the program
counter. FILENAME is the name of the file containing PC, or NULL
if not available. LINENO is the line number in FILENAME containing
PC, or 0 if not available. FUNCTION is the name of the function
containing PC, or NULL if not available. This should return 0 to
continuing tracing. The FILENAME and FUNCTION buffers may become
invalid after this function returns. */
typedef int (*backtrace_full_callback) (void *data, uintptr_t pc,
const char *filename, int lineno,
const char *function);
/* Get a full stack backtrace. SKIP is the number of frames to skip;
passing 0 will start the trace with the function calling
backtrace_full. DATA is passed to the callback routine. If any
call to CALLBACK returns a non-zero value, the stack backtrace
stops, and backtrace returns that value; this may be used to limit
the number of stack frames desired. If all calls to CALLBACK
return 0, backtrace returns 0. The backtrace_full function will
make at least one call to either CALLBACK or ERROR_CALLBACK. This
function requires debug info for the executable. */
extern int backtrace_full (struct backtrace_state *state, int skip,
backtrace_full_callback callback,
backtrace_error_callback error_callback,
void *data);
/* The type of the callback argument to the backtrace_simple function.
DATA is the argument passed to simple_backtrace. PC is the program
counter. This should return 0 to continue tracing. */
typedef int (*backtrace_simple_callback) (void *data, uintptr_t pc);
/* Get a simple backtrace. SKIP is the number of frames to skip, as
in backtrace. DATA is passed to the callback routine. If any call
to CALLBACK returns a non-zero value, the stack backtrace stops,
and backtrace_simple returns that value. Otherwise
backtrace_simple returns 0. The backtrace_simple function will
make at least one call to either CALLBACK or ERROR_CALLBACK. This
function does not require any debug info for the executable. */
extern int backtrace_simple (struct backtrace_state *state, int skip,
backtrace_simple_callback callback,
backtrace_error_callback error_callback,
void *data);
/* Print the current backtrace in a user readable format to a FILE.
SKIP is the number of frames to skip, as in backtrace_full. Any
error messages are printed to stderr. This function requires debug
info for the executable. */
extern void backtrace_print (struct backtrace_state *state, int skip, FILE *);
/* Given PC, a program counter in the current program, call the
callback function with filename, line number, and function name
information. This will normally call the callback function exactly
once. However, if the PC happens to describe an inlined call, and
the debugging information contains the necessary information, then
this may call the callback function multiple times. This will make
at least one call to either CALLBACK or ERROR_CALLBACK. This
returns the first non-zero value returned by CALLBACK, or 0. */
extern int backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,
backtrace_full_callback callback,
backtrace_error_callback error_callback,
void *data);
/* 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 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,
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);
#ifdef __cplusplus
} /* End extern "C". */
#endif
#endif

715
src/libbacktrace/btest.c Normal file
View File

@ -0,0 +1,715 @@
/* btest.c -- Test for libbacktrace library
Copyright (C) 2012-2014 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
(1) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
(2) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
(3) The name of the author may not be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
/* This program tests the externally visible interfaces of the
libbacktrace library. */
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "filenames.h"
#include "backtrace.h"
#include "backtrace-supported.h"
/* Portable attribute syntax. Actually some of these tests probably
won't work if the attributes are not recognized. */
#ifndef GCC_VERSION
# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
#endif
#if (GCC_VERSION < 2007)
# define __attribute__(x)
#endif
#ifndef ATTRIBUTE_UNUSED
# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#endif
/* Used to collect backtrace info. */
struct info
{
char *filename;
int lineno;
char *function;
};
/* Passed to backtrace callback function. */
struct bdata
{
struct info *all;
size_t index;
size_t max;
int failed;
};
/* Passed to backtrace_simple callback function. */
struct sdata
{
uintptr_t *addrs;
size_t index;
size_t max;
int failed;
};
/* Passed to backtrace_syminfo callback function. */
struct symdata
{
const char *name;
uintptr_t val, size;
int failed;
};
/* The backtrace state. */
static void *state;
/* The number of failures. */
static int failures;
/* Return the base name in a path. */
static const char *
base (const char *p)
{
const char *last;
const char *s;
last = NULL;
for (s = p; *s != '\0'; ++s)
{
if (IS_DIR_SEPARATOR (*s))
last = s + 1;
}
return last != NULL ? last : p;
}
/* Check an entry in a struct info array. */
static void
check (const char *name, int index, const struct info *all, int want_lineno,
const char *want_function, int *failed)
{
if (*failed)
return;
if (all[index].filename == NULL || all[index].function == NULL)
{
fprintf (stderr, "%s: [%d]: missing file name or function name\n",
name, index);
*failed = 1;
return;
}
if (strcmp (base (all[index].filename), "btest.c") != 0)
{
fprintf (stderr, "%s: [%d]: got %s expected test.c\n", name, index,
all[index].filename);
*failed = 1;
}
if (all[index].lineno != want_lineno)
{
fprintf (stderr, "%s: [%d]: got %d expected %d\n", name, index,
all[index].lineno, want_lineno);
*failed = 1;
}
if (strcmp (all[index].function, want_function) != 0)
{
fprintf (stderr, "%s: [%d]: got %s expected %s\n", name, index,
all[index].function, want_function);
*failed = 1;
}
}
/* The backtrace callback function. */
static int
callback_one (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
const char *filename, int lineno, const char *function)
{
struct bdata *data = (struct bdata *) vdata;
struct info *p;
if (data->index >= data->max)
{
fprintf (stderr, "callback_one: callback called too many times\n");
data->failed = 1;
return 1;
}
p = &data->all[data->index];
if (filename == NULL)
p->filename = NULL;
else
{
p->filename = strdup (filename);
assert (p->filename != NULL);
}
p->lineno = lineno;
if (function == NULL)
p->function = NULL;
else
{
p->function = strdup (function);
assert (p->function != NULL);
}
++data->index;
return 0;
}
/* An error callback passed to backtrace. */
static void
error_callback_one (void *vdata, const char *msg, int errnum)
{
struct bdata *data = (struct bdata *) vdata;
fprintf (stderr, "%s", msg);
if (errnum > 0)
fprintf (stderr, ": %s", strerror (errnum));
fprintf (stderr, "\n");
data->failed = 1;
}
/* The backtrace_simple callback function. */
static int
callback_two (void *vdata, uintptr_t pc)
{
struct sdata *data = (struct sdata *) vdata;
if (data->index >= data->max)
{
fprintf (stderr, "callback_two: callback called too many times\n");
data->failed = 1;
return 1;
}
data->addrs[data->index] = pc;
++data->index;
return 0;
}
/* An error callback passed to backtrace_simple. */
static void
error_callback_two (void *vdata, const char *msg, int errnum)
{
struct sdata *data = (struct sdata *) vdata;
fprintf (stderr, "%s", msg);
if (errnum > 0)
fprintf (stderr, ": %s", strerror (errnum));
fprintf (stderr, "\n");
data->failed = 1;
}
/* The backtrace_syminfo callback function. */
static void
callback_three (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED,
const char *symname, uintptr_t symval,
uintptr_t symsize)
{
struct symdata *data = (struct symdata *) vdata;
if (symname == NULL)
data->name = NULL;
else
{
data->name = strdup (symname);
assert (data->name != NULL);
}
data->val = symval;
data->size = symsize;
}
/* The backtrace_syminfo error callback function. */
static void
error_callback_three (void *vdata, const char *msg, int errnum)
{
struct symdata *data = (struct symdata *) vdata;
fprintf (stderr, "%s", msg);
if (errnum > 0)
fprintf (stderr, ": %s", strerror (errnum));
fprintf (stderr, "\n");
data->failed = 1;
}
/* Test the backtrace function with non-inlined functions. */
static int test1 (void) __attribute__ ((noinline, unused));
static int f2 (int) __attribute__ ((noinline));
static int f3 (int, int) __attribute__ ((noinline));
static int
test1 (void)
{
/* Returning a value here and elsewhere avoids a tailcall which
would mess up the backtrace. */
return f2 (__LINE__) + 1;
}
static int
f2 (int f1line)
{
return f3 (f1line, __LINE__) + 2;
}
static int
f3 (int f1line, int f2line)
{
struct info all[20];
struct bdata data;
int f3line;
int i;
data.all = &all[0];
data.index = 0;
data.max = 20;
data.failed = 0;
f3line = __LINE__ + 1;
i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
if (i != 0)
{
fprintf (stderr, "test1: unexpected return value %d\n", i);
data.failed = 1;
}
if (data.index < 3)
{
fprintf (stderr,
"test1: not enough frames; got %zu, expected at least 3\n",
data.index);
data.failed = 1;
}
check ("test1", 0, all, f3line, "f3", &data.failed);
check ("test1", 1, all, f2line, "f2", &data.failed);
check ("test1", 2, all, f1line, "test1", &data.failed);
printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS");
if (data.failed)
++failures;
return failures;
}
/* Test the backtrace function with inlined functions. */
static inline int test2 (void) __attribute__ ((always_inline, unused));
static inline int f12 (int) __attribute__ ((always_inline));
static inline int f13 (int, int) __attribute__ ((always_inline));
static inline int
test2 (void)
{
return f12 (__LINE__) + 1;
}
static inline int
f12 (int f1line)
{
return f13 (f1line, __LINE__) + 2;
}
static inline int
f13 (int f1line, int f2line)
{
struct info all[20];
struct bdata data;
int f3line;
int i;
data.all = &all[0];
data.index = 0;
data.max = 20;
data.failed = 0;
f3line = __LINE__ + 1;
i = backtrace_full (state, 0, callback_one, error_callback_one, &data);
if (i != 0)
{
fprintf (stderr, "test2: unexpected return value %d\n", i);
data.failed = 1;
}
check ("test2", 0, all, f3line, "f13", &data.failed);
check ("test2", 1, all, f2line, "f12", &data.failed);
check ("test2", 2, all, f1line, "test2", &data.failed);
printf ("%s: backtrace_full inline\n", data.failed ? "FAIL" : "PASS");
if (data.failed)
++failures;
return failures;
}
/* Test the backtrace_simple function with non-inlined functions. */
static int test3 (void) __attribute__ ((noinline, unused));
static int f22 (int) __attribute__ ((noinline));
static int f23 (int, int) __attribute__ ((noinline));
static int
test3 (void)
{
return f22 (__LINE__) + 1;
}
static int
f22 (int f1line)
{
return f23 (f1line, __LINE__) + 2;
}
static int
f23 (int f1line, int f2line)
{
uintptr_t addrs[20];
struct sdata data;
int f3line;
int i;
data.addrs = &addrs[0];
data.index = 0;
data.max = 20;
data.failed = 0;
f3line = __LINE__ + 1;
i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
if (i != 0)
{
fprintf (stderr, "test3: unexpected return value %d\n", i);
data.failed = 1;
}
if (!data.failed)
{
struct info all[20];
struct bdata bdata;
int j;
bdata.all = &all[0];
bdata.index = 0;
bdata.max = 20;
bdata.failed = 0;
for (j = 0; j < 3; ++j)
{
i = backtrace_pcinfo (state, addrs[j], callback_one,
error_callback_one, &bdata);
if (i != 0)
{
fprintf (stderr,
("test3: unexpected return value "
"from backtrace_pcinfo %d\n"),
i);
bdata.failed = 1;
}
if (!bdata.failed && bdata.index != (size_t) (j + 1))
{
fprintf (stderr,
("wrong number of calls from backtrace_pcinfo "
"got %u expected %d\n"),
(unsigned int) bdata.index, j + 1);
bdata.failed = 1;
}
}
check ("test3", 0, all, f3line, "f23", &bdata.failed);
check ("test3", 1, all, f2line, "f22", &bdata.failed);
check ("test3", 2, all, f1line, "test3", &bdata.failed);
if (bdata.failed)
data.failed = 1;
for (j = 0; j < 3; ++j)
{
struct symdata symdata;
symdata.name = NULL;
symdata.val = 0;
symdata.size = 0;
symdata.failed = 0;
i = backtrace_syminfo (state, addrs[j], callback_three,
error_callback_three, &symdata);
if (i == 0)
{
fprintf (stderr,
("test3: [%d]: unexpected return value "
"from backtrace_syminfo %d\n"),
j, i);
symdata.failed = 1;
}
if (!symdata.failed)
{
const char *expected;
switch (j)
{
case 0:
expected = "f23";
break;
case 1:
expected = "f22";
break;
case 2:
expected = "test3";
break;
default:
assert (0);
}
if (symdata.name == NULL)
{
fprintf (stderr, "test3: [%d]: NULL syminfo name\n", j);
symdata.failed = 1;
}
/* Use strncmp, not strcmp, because GCC might create a
clone. */
else if (strncmp (symdata.name, expected, strlen (expected))
!= 0)
{
fprintf (stderr,
("test3: [%d]: unexpected syminfo name "
"got %s expected %s\n"),
j, symdata.name, expected);
symdata.failed = 1;
}
}
if (symdata.failed)
data.failed = 1;
}
}
printf ("%s: backtrace_simple noinline\n", data.failed ? "FAIL" : "PASS");
if (data.failed)
++failures;
return failures;
}
/* Test the backtrace_simple function with inlined functions. */
static inline int test4 (void) __attribute__ ((always_inline, unused));
static inline int f32 (int) __attribute__ ((always_inline));
static inline int f33 (int, int) __attribute__ ((always_inline));
static inline int
test4 (void)
{
return f32 (__LINE__) + 1;
}
static inline int
f32 (int f1line)
{
return f33 (f1line, __LINE__) + 2;
}
static inline int
f33 (int f1line, int f2line)
{
uintptr_t addrs[20];
struct sdata data;
int f3line;
int i;
data.addrs = &addrs[0];
data.index = 0;
data.max = 20;
data.failed = 0;
f3line = __LINE__ + 1;
i = backtrace_simple (state, 0, callback_two, error_callback_two, &data);
if (i != 0)
{
fprintf (stderr, "test3: unexpected return value %d\n", i);
data.failed = 1;
}
if (!data.failed)
{
struct info all[20];
struct bdata bdata;
bdata.all = &all[0];
bdata.index = 0;
bdata.max = 20;
bdata.failed = 0;
i = backtrace_pcinfo (state, addrs[0], callback_one, error_callback_one,
&bdata);
if (i != 0)
{
fprintf (stderr,
("test4: unexpected return value "
"from backtrace_pcinfo %d\n"),
i);
bdata.failed = 1;
}
check ("test4", 0, all, f3line, "f33", &bdata.failed);
check ("test4", 1, all, f2line, "f32", &bdata.failed);
check ("test4", 2, all, f1line, "test4", &bdata.failed);
if (bdata.failed)
data.failed = 1;
}
printf ("%s: backtrace_simple inline\n", data.failed ? "FAIL" : "PASS");
if (data.failed)
++failures;
return failures;
}
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;
}
static void
error_callback_create (void *data ATTRIBUTE_UNUSED, const char *msg,
int errnum)
{
fprintf (stderr, "%s", msg);
if (errnum > 0)
fprintf (stderr, ": %s", strerror (errnum));
fprintf (stderr, "\n");
exit (EXIT_FAILURE);
}
/* Run all the tests. */
int
main (int argc ATTRIBUTE_UNUSED, char **argv)
{
state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS,
error_callback_create, NULL);
#if BACKTRACE_SUPPORTED
test1 ();
test2 ();
test3 ();
test4 ();
test5 ();
#endif
exit (failures ? EXIT_FAILURE : EXIT_SUCCESS);
}

1558
src/libbacktrace/config.guess vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,134 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* ELF size: 32 or 64 */
#undef BACKTRACE_ELF_SIZE
/* Define to 1 if you have the __atomic functions */
#undef HAVE_ATOMIC_FUNCTIONS
/* Define to 1 if you have the declaration of `strnlen', and to 0 if you
don't. */
#undef HAVE_DECL_STRNLEN
/* Define to 1 if you have the <dlfcn.h> header file. */
#undef HAVE_DLFCN_H
/* Define if dl_iterate_phdr is available. */
#undef HAVE_DL_ITERATE_PHDR
/* Define to 1 if you have the fcntl function */
#undef HAVE_FCNTL
/* Define if getexecname is available. */
#undef HAVE_GETEXECNAME
/* Define if _Unwind_GetIPInfo is available. */
#undef HAVE_GETIPINFO
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <link.h> header file. */
#undef HAVE_LINK_H
/* Define to 1 if you have the <memory.h> header file. */
#undef HAVE_MEMORY_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the __sync functions */
#undef HAVE_SYNC_FUNCTIONS
/* Define to 1 if you have the <sys/mman.h> header file. */
#undef HAVE_SYS_MMAN_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to the sub-directory in which libtool stores uninstalled libraries.
*/
#undef LT_OBJDIR
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* The size of `char', as computed by sizeof. */
#undef SIZEOF_CHAR
/* The size of `int', as computed by sizeof. */
#undef SIZEOF_INT
/* The size of `long', as computed by sizeof. */
#undef SIZEOF_LONG
/* The size of `short', as computed by sizeof. */
#undef SIZEOF_SHORT
/* The size of `void *', as computed by sizeof. */
#undef SIZEOF_VOID_P
/* Define to 1 if you have the ANSI C header files. */
#undef STDC_HEADERS
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable threading extensions on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Define to 1 if on MINIX. */
#undef _MINIX
/* Define to 2 if the system does not provide POSIX.1 features except with
this defined. */
#undef _POSIX_1_SOURCE
/* Define to 1 if you need to in order for `stat' and other things to work. */
#undef _POSIX_SOURCE

1793
src/libbacktrace/config.sub vendored Executable file

File diff suppressed because it is too large Load Diff

15156
src/libbacktrace/configure vendored Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,391 @@
# configure.ac -- Backtrace configure script.
# Copyright (C) 2012-2014 Free Software Foundation, Inc.
# 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.
AC_PREREQ(2.64)
AC_INIT(package-unused, version-unused,, libbacktrace)
AC_CONFIG_SRCDIR(backtrace.h)
AC_CONFIG_HEADER(config.h)
AC_CANONICAL_SYSTEM
target_alias=${target_alias-$host_alias}
AC_USE_SYSTEM_EXTENSIONS
libtool_VERSION=1:0:0
AC_SUBST(libtool_VERSION)
# 1.11.1: Require that version of automake.
# foreign: Don't require README, INSTALL, NEWS, etc.
# no-define: Don't define PACKAGE and VERSION.
# no-dependencies: Don't generate automatic dependencies.
# (because it breaks when using bootstrap-lean, since some of the
# headers are gone at "make install" time).
# -Wall: Issue all automake warnings.
# -Wno-portability: Don't warn about constructs supported by GNU make.
# (because GCC requires GNU make anyhow).
AM_INIT_AUTOMAKE([1.11.1 foreign no-dist no-define no-dependencies -Wall -Wno-portability])
AM_MAINTAINER_MODE
AC_ARG_WITH(target-subdir,
[ --with-target-subdir=SUBDIR Configuring in a subdirectory for target])
# We must force CC to /not/ be precious variables; otherwise
# the wrong, non-multilib-adjusted value will be used in multilibs.
# As a side effect, we have to subst CFLAGS ourselves.
m4_rename([_AC_ARG_VAR_PRECIOUS],[backtrace_PRECIOUS])
m4_define([_AC_ARG_VAR_PRECIOUS],[])
AC_PROG_CC
m4_rename_force([backtrace_PRECIOUS],[_AC_ARG_VAR_PRECIOUS])
AC_SUBST(CFLAGS)
AC_PROG_RANLIB
AC_PROG_AWK
case "$AWK" in
"") AC_MSG_ERROR([can't build without awk]) ;;
esac
LT_INIT([disable-shared])
AM_PROG_LIBTOOL
backtrace_supported=yes
if test -n "${with_target_subdir}"; then
# We are compiling a GCC library. We can assume that the unwind
# library exists.
AM_ENABLE_MULTILIB(, ..)
BACKTRACE_FILE="backtrace.lo simple.lo"
else
AC_CHECK_HEADER([unwind.h],
[AC_CHECK_FUNC([_Unwind_Backtrace],
[BACKTRACE_FILE="backtrace.lo simple.lo"],
[BACKTRACE_FILE="nounwind.lo"
backtrace_supported=no])],
[BACKTRACE_FILE="nounwind.lo"
backtrace_supported=no])
fi
AC_SUBST(BACKTRACE_FILE)
EXTRA_FLAGS=
if test -n "${with_target_subdir}"; then
EXTRA_FLAGS="-funwind-tables -frandom-seed=\$@"
else
AC_CACHE_CHECK([for -funwind-tables option],
[libbacktrace_cv_c_unwind_tables],
[CFLAGS_hold="$CFLAGS"
CFLAGS="$CFLAGS -funwind-tables"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([static int f() { return 0; }], [return f();])],
[libbacktrace_cv_c_unwind_tables=yes],
[libbacktrace_cv_c_unwind_tables=no])
CFLAGS="$CFLAGS_hold"])
if test "$libbacktrace_cv_c_unwind_tables" = "yes"; then
EXTRA_FLAGS=-funwind-tables
fi
AC_CACHE_CHECK([for -frandom-seed=string option],
[libbacktrace_cv_c_random_seed_string],
[CFLAGS_hold="$CFLAGS"
CFLAGS="$CFLAGS -frandom-seed=conftest.lo"
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([], [return 0;])],
[libbacktrace_cv_c_random_seed_string=yes],
[libbacktrace_cv_c_random_seed_string=no])
CFLAGS="$CFLAGS_hold"])
if test "$libbacktrace_cv_c_random_seed_string" = "yes"; then
EXTRA_FLAGS="$EXTRA_FLAGS -frandom-seed=\$@"
fi
fi
AC_SUBST(EXTRA_FLAGS)
ACX_PROG_CC_WARNING_OPTS([-W -Wall -Wwrite-strings -Wstrict-prototypes \
-Wmissing-prototypes -Wold-style-definition \
-Wmissing-format-attribute -Wcast-qual],
[WARN_FLAGS])
if test -n "${with_target_subdir}"; then
WARN_FLAGS="$WARN_FLAGS -Werror"
fi
AC_SUBST(WARN_FLAGS)
if test -n "${with_target_subdir}"; then
GCC_CHECK_UNWIND_GETIPINFO
else
ac_save_CFFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -Werror-implicit-function-declaration"
AC_MSG_CHECKING([for _Unwind_GetIPInfo])
AC_LINK_IFELSE(
[AC_LANG_PROGRAM(
[#include "unwind.h"
struct _Unwind_Context *context;
int ip_before_insn = 0;],
[return _Unwind_GetIPInfo (context, &ip_before_insn);])],
[have_unwind_getipinfo=yes], [have_unwind_getipinfo=no])
CFLAGS="$ac_save_CFLAGS"
AC_MSG_RESULT([$have_unwind_getipinfo])
if test "$have_unwind_getipinfo" = "yes"; then
AC_DEFINE(HAVE_GETIPINFO, 1, [Define if _Unwind_GetIPInfo is available.])
fi
fi
# When building as a target library, shared libraries may want to link
# this in. We don't want to provide another shared library to
# complicate dependencies. Instead, we just compile with -fPIC.
PIC_FLAG=
if test -n "${with_target_subdir}"; then
PIC_FLAG=-fPIC
fi
# Similarly, use -fPIC with --enable-host-shared:
AC_ARG_ENABLE(host-shared,
[AS_HELP_STRING([--enable-host-shared],
[build host code as shared libraries])],
[PIC_FLAG=-fPIC], [])
AC_SUBST(PIC_FLAG)
# Test for __sync support.
AC_CACHE_CHECK([__sync extensions],
[libbacktrace_cv_sys_sync],
[if test -n "${with_target_subdir}"; then
libbacktrace_cv_sys_sync=yes
else
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([int i;],
[__sync_bool_compare_and_swap (&i, i, i);
__sync_lock_test_and_set (&i, 1);
__sync_lock_release (&i);])],
[libbacktrace_cv_sys_sync=yes],
[libbacktrace_cv_sys_sync=no])
fi])
BACKTRACE_SUPPORTS_THREADS=0
if test "$libbacktrace_cv_sys_sync" = "yes"; then
BACKTRACE_SUPPORTS_THREADS=1
AC_DEFINE([HAVE_SYNC_FUNCTIONS], 1,
[Define to 1 if you have the __sync functions])
fi
AC_SUBST(BACKTRACE_SUPPORTS_THREADS)
# Test for __atomic support.
AC_CACHE_CHECK([__atomic extensions],
[libbacktrace_cv_sys_atomic],
[if test -n "${with_target_subdir}"; then
libbacktrace_cv_sys_atomic=yes
else
AC_LINK_IFELSE(
[AC_LANG_PROGRAM([int i;],
[__atomic_load_n (&i, __ATOMIC_ACQUIRE);
__atomic_store_n (&i, 1, __ATOMIC_RELEASE);])],
[libbacktrace_cv_sys_atomic=yes],
[libbacktrace_cv_sys_atomic=no])
fi])
if test "$libbacktrace_cv_sys_atomic" = "yes"; then
AC_DEFINE([HAVE_ATOMIC_FUNCTIONS], 1,
[Define to 1 if you have the __atomic functions])
fi
# The library needs to be able to read the executable itself. Compile
# a file to determine the executable format. The awk script
# filetype.awk prints out the file type.
AC_CACHE_CHECK([output filetype],
[libbacktrace_cv_sys_filetype],
[filetype=
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([int i;], [int j;])],
[filetype=`${AWK} -f $srcdir/filetype.awk conftest.$ac_objext`],
[AC_MSG_FAILURE([compiler failed])])
libbacktrace_cv_sys_filetype=$filetype])
# Match the file type to decide what files to compile.
FORMAT_FILE=
case "$libbacktrace_cv_sys_filetype" in
elf*) FORMAT_FILE="elf.lo" ;;
*) AC_MSG_WARN([could not determine output file type])
FORMAT_FILE="unknown.lo"
backtrace_supported=no
;;
esac
AC_SUBST(FORMAT_FILE)
# ELF defines.
elfsize=
case "$libbacktrace_cv_sys_filetype" in
elf32) elfsize=32 ;;
elf64) elfsize=64 ;;
esac
AC_DEFINE_UNQUOTED([BACKTRACE_ELF_SIZE], [$elfsize], [ELF size: 32 or 64])
BACKTRACE_SUPPORTED=0
if test "$backtrace_supported" = "yes"; then
BACKTRACE_SUPPORTED=1
fi
AC_SUBST(BACKTRACE_SUPPORTED)
GCC_HEADER_STDINT(gstdint.h)
AC_CHECK_HEADERS(sys/mman.h)
if test "$ac_cv_header_sys_mman_h" = "no"; then
have_mmap=no
else
if test -n "${with_target_subdir}"; then
# When built as a GCC target library, we can't do a link test. We
# simply assume that if we have mman.h, we have mmap.
have_mmap=yes
else
AC_CHECK_FUNC(mmap, [have_mmap=yes], [have_mmap=no])
fi
fi
if test "$have_mmap" = "no"; then
VIEW_FILE=read.lo
ALLOC_FILE=alloc.lo
else
VIEW_FILE=mmapio.lo
AC_PREPROC_IFELSE([
#include <sys/mman.h>
#if !defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
#error no MAP_ANONYMOUS
#endif
], [ALLOC_FILE=mmap.lo], [ALLOC_FILE=alloc.lo])
fi
AC_SUBST(VIEW_FILE)
AC_SUBST(ALLOC_FILE)
BACKTRACE_USES_MALLOC=0
if test "$ALLOC_FILE" = "alloc.lo"; then
BACKTRACE_USES_MALLOC=1
fi
AC_SUBST(BACKTRACE_USES_MALLOC)
# Check for dl_iterate_phdr.
AC_CHECK_HEADERS(link.h)
if test "$ac_cv_header_link_h" = "no"; then
have_dl_iterate_phdr=no
else
if test -n "${with_target_subdir}"; then
# When built as a GCC target library, we can't do a link test.
AC_EGREP_HEADER([dl_iterate_phdr], [link.h], [have_dl_iterate_phdr=yes],
[have_dl_iterate_phdr=no])
case "${host}" in
*-*-solaris2.10*)
# Avoid dl_iterate_phdr on Solaris 10, where it is in the
# header file but is only in -ldl.
have_dl_iterate_phdr=no ;;
esac
else
AC_CHECK_FUNC([dl_iterate_phdr], [have_dl_iterate_phdr=yes],
[have_dl_iterate_phdr=no])
fi
fi
if test "$have_dl_iterate_phdr" = "yes"; then
AC_DEFINE(HAVE_DL_ITERATE_PHDR, 1, [Define if dl_iterate_phdr is available.])
fi
# Check for the fcntl function.
if test -n "${with_target_subdir}"; then
case "${host}" in
*-*-mingw*) have_fcntl=no ;;
*) have_fcntl=yes ;;
esac
else
AC_CHECK_FUNC(fcntl, [have_fcntl=yes], [have_fcntl=no])
fi
if test "$have_fcntl" = "yes"; then
AC_DEFINE([HAVE_FCNTL], 1,
[Define to 1 if you have the fcntl function])
fi
AC_CHECK_DECLS(strnlen)
# Check for getexecname function.
if test -n "${with_target_subdir}"; then
case "${host}" in
*-*-solaris2*) have_getexecname=yes ;;
*) have_getexecname=no ;;
esac
else
AC_CHECK_FUNC(getexecname, [have_getexecname=yes], [have_getexecname=no])
fi
if test "$have_getexecname" = "yes"; then
AC_DEFINE(HAVE_GETEXECNAME, 1, [Define if getexecname is available.])
fi
AC_CACHE_CHECK([whether tests can run],
[libbacktrace_cv_sys_native],
[AC_RUN_IFELSE([AC_LANG_PROGRAM([], [return 0;])],
[libbacktrace_cv_sys_native=yes],
[libbacktrace_cv_sys_native=no],
[libbacktrace_cv_sys_native=no])])
AM_CONDITIONAL(NATIVE, test "$libbacktrace_cv_sys_native" = "yes")
if test "${multilib}" = "yes"; then
multilib_arg="--enable-multilib"
else
multilib_arg=
fi
AC_CONFIG_FILES(Makefile backtrace-supported.h)
# We need multilib support, but only if configuring for the target.
AC_CONFIG_COMMANDS([default],
[if test -n "$CONFIG_FILES"; then
if test -n "${with_target_subdir}"; then
# Multilibs need MULTISUBDIR defined correctly in certain makefiles so
# that multilib installs will end up installed in the correct place.
# The testsuite needs it for multilib-aware ABI baseline files.
# To work around this not being passed down from config-ml.in ->
# srcdir/Makefile.am -> srcdir/{src,libsupc++,...}/Makefile.am, manually
# append it here. Only modify Makefiles that have just been created.
#
# Also, get rid of this simulated-VPATH thing that automake does.
cat > vpsed << \_EOF
s!`test -f '$<' || echo '$(srcdir)/'`!!
_EOF
for i in $SUBDIRS; do
case $CONFIG_FILES in
*${i}/Makefile*)
#echo "Adding MULTISUBDIR to $i/Makefile"
sed -f vpsed $i/Makefile > tmp
grep '^MULTISUBDIR =' Makefile >> tmp
mv tmp $i/Makefile
;;
esac
done
rm vpsed
fi
fi
],
[
# Variables needed in config.status (file generation) which aren't already
# passed by autoconf.
SUBDIRS="$SUBDIRS"
])
AC_OUTPUT

3021
src/libbacktrace/dwarf.c Normal file

File diff suppressed because it is too large Load Diff

688
src/libbacktrace/dwarf2.def Normal file
View File

@ -0,0 +1,688 @@
/* -*- c -*-
Declarations and definitions of codes relating to the DWARF2 and
DWARF3 symbolic debugging information formats.
Copyright (C) 1992, 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002,
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
Written by Gary Funck (gary@intrepid.com) The Ada Joint Program
Office (AJPO), Florida State University and Silicon Graphics Inc.
provided support for this effort -- June 21, 1995.
Derived from the DWARF 1 implementation written by Ron Guilmette
(rfg@netcom.com), November 1990.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* This file is derived from the DWARF specification (a public document)
Revision 2.0.0 (July 27, 1993) developed by the UNIX International
Programming Languages Special Interest Group (UI/PLSIG) and distributed
by UNIX International. Copies of this specification are available from
UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054.
This file also now contains definitions from the DWARF 3 specification
published Dec 20, 2005, available from: http://dwarf.freestandards.org.
This file also now contains definitions from the DWARF 4
specification, available from: http://dwarfstd.org/ */
/* This file declares various DWARF-related constants using a set of
macros which can be redefined by the including file.
The macros are in sections. Each section corresponds to a single
set of DWARF constants and has a corresponding key. The key is
used in all the macro names.
The sections are TAG (for DW_TAG_ constants), FORM (DW_FORM_), AT
(DW_AT_), OP (DW_OP_), ATE (DW_ATE_), and CFA (DW_CFA_).
Using TAG as an example, the following macros may be used for each
key:
DW_FIRST_TAG(name, value) - Introduce the first DW_TAG constant.
DW_TAG(name, value) - Define a subsequent constant.
DW_TAG_DUP(name, value) - Define a subsequent constant whose value
is a duplicate of some other constant. Not all keys use the _DUP
macro form. If more than one name shares a value, then the base
(DW_TAG) form will be the preferred name and DW_TAG_DUP will hold
any alternate names.
DW_END_TAG - Invoked at the end of the DW_TAG constants. */
DW_FIRST_TAG (DW_TAG_padding, 0x00)
DW_TAG (DW_TAG_array_type, 0x01)
DW_TAG (DW_TAG_class_type, 0x02)
DW_TAG (DW_TAG_entry_point, 0x03)
DW_TAG (DW_TAG_enumeration_type, 0x04)
DW_TAG (DW_TAG_formal_parameter, 0x05)
DW_TAG (DW_TAG_imported_declaration, 0x08)
DW_TAG (DW_TAG_label, 0x0a)
DW_TAG (DW_TAG_lexical_block, 0x0b)
DW_TAG (DW_TAG_member, 0x0d)
DW_TAG (DW_TAG_pointer_type, 0x0f)
DW_TAG (DW_TAG_reference_type, 0x10)
DW_TAG (DW_TAG_compile_unit, 0x11)
DW_TAG (DW_TAG_string_type, 0x12)
DW_TAG (DW_TAG_structure_type, 0x13)
DW_TAG (DW_TAG_subroutine_type, 0x15)
DW_TAG (DW_TAG_typedef, 0x16)
DW_TAG (DW_TAG_union_type, 0x17)
DW_TAG (DW_TAG_unspecified_parameters, 0x18)
DW_TAG (DW_TAG_variant, 0x19)
DW_TAG (DW_TAG_common_block, 0x1a)
DW_TAG (DW_TAG_common_inclusion, 0x1b)
DW_TAG (DW_TAG_inheritance, 0x1c)
DW_TAG (DW_TAG_inlined_subroutine, 0x1d)
DW_TAG (DW_TAG_module, 0x1e)
DW_TAG (DW_TAG_ptr_to_member_type, 0x1f)
DW_TAG (DW_TAG_set_type, 0x20)
DW_TAG (DW_TAG_subrange_type, 0x21)
DW_TAG (DW_TAG_with_stmt, 0x22)
DW_TAG (DW_TAG_access_declaration, 0x23)
DW_TAG (DW_TAG_base_type, 0x24)
DW_TAG (DW_TAG_catch_block, 0x25)
DW_TAG (DW_TAG_const_type, 0x26)
DW_TAG (DW_TAG_constant, 0x27)
DW_TAG (DW_TAG_enumerator, 0x28)
DW_TAG (DW_TAG_file_type, 0x29)
DW_TAG (DW_TAG_friend, 0x2a)
DW_TAG (DW_TAG_namelist, 0x2b)
DW_TAG (DW_TAG_namelist_item, 0x2c)
DW_TAG (DW_TAG_packed_type, 0x2d)
DW_TAG (DW_TAG_subprogram, 0x2e)
DW_TAG (DW_TAG_template_type_param, 0x2f)
DW_TAG (DW_TAG_template_value_param, 0x30)
DW_TAG (DW_TAG_thrown_type, 0x31)
DW_TAG (DW_TAG_try_block, 0x32)
DW_TAG (DW_TAG_variant_part, 0x33)
DW_TAG (DW_TAG_variable, 0x34)
DW_TAG (DW_TAG_volatile_type, 0x35)
/* DWARF 3. */
DW_TAG (DW_TAG_dwarf_procedure, 0x36)
DW_TAG (DW_TAG_restrict_type, 0x37)
DW_TAG (DW_TAG_interface_type, 0x38)
DW_TAG (DW_TAG_namespace, 0x39)
DW_TAG (DW_TAG_imported_module, 0x3a)
DW_TAG (DW_TAG_unspecified_type, 0x3b)
DW_TAG (DW_TAG_partial_unit, 0x3c)
DW_TAG (DW_TAG_imported_unit, 0x3d)
DW_TAG (DW_TAG_condition, 0x3f)
DW_TAG (DW_TAG_shared_type, 0x40)
/* DWARF 4. */
DW_TAG (DW_TAG_type_unit, 0x41)
DW_TAG (DW_TAG_rvalue_reference_type, 0x42)
DW_TAG (DW_TAG_template_alias, 0x43)
DW_TAG_DUP (DW_TAG_lo_user, 0x4080)
DW_TAG_DUP (DW_TAG_hi_user, 0xffff)
/* SGI/MIPS Extensions. */
DW_TAG (DW_TAG_MIPS_loop, 0x4081)
/* HP extensions. See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz . */
DW_TAG (DW_TAG_HP_array_descriptor, 0x4090)
DW_TAG (DW_TAG_HP_Bliss_field, 0x4091)
DW_TAG (DW_TAG_HP_Bliss_field_set, 0x4092)
/* GNU extensions. */
DW_TAG (DW_TAG_format_label, 0x4101) /* For FORTRAN 77 and Fortran 90. */
DW_TAG (DW_TAG_function_template, 0x4102) /* For C++. */
DW_TAG (DW_TAG_class_template, 0x4103) /* For C++. */
DW_TAG (DW_TAG_GNU_BINCL, 0x4104)
DW_TAG (DW_TAG_GNU_EINCL, 0x4105)
/* Template template parameter.
See http://gcc.gnu.org/wiki/TemplateParmsDwarf . */
DW_TAG (DW_TAG_GNU_template_template_param, 0x4106)
/* Template parameter pack extension, specified at
http://wiki.dwarfstd.org/index.php?title=C%2B%2B0x:_Variadic_templates
The values of these two TAGS are in the DW_TAG_GNU_* space until the tags
are properly part of DWARF 5. */
DW_TAG (DW_TAG_GNU_template_parameter_pack, 0x4107)
DW_TAG (DW_TAG_GNU_formal_parameter_pack, 0x4108)
/* The GNU call site extension, specified at
http://www.dwarfstd.org/ShowIssue.php?issue=100909.2&type=open .
The values of these two TAGS are in the DW_TAG_GNU_* space until the tags
are properly part of DWARF 5. */
DW_TAG (DW_TAG_GNU_call_site, 0x4109)
DW_TAG (DW_TAG_GNU_call_site_parameter, 0x410a)
/* Extensions for UPC. See: http://dwarfstd.org/doc/DWARF4.pdf. */
DW_TAG (DW_TAG_upc_shared_type, 0x8765)
DW_TAG (DW_TAG_upc_strict_type, 0x8766)
DW_TAG (DW_TAG_upc_relaxed_type, 0x8767)
/* PGI (STMicroelectronics) extensions. No documentation available. */
DW_TAG (DW_TAG_PGI_kanji_type, 0xA000)
DW_TAG (DW_TAG_PGI_interface_block, 0xA020)
DW_END_TAG
DW_FIRST_FORM (DW_FORM_addr, 0x01)
DW_FORM (DW_FORM_block2, 0x03)
DW_FORM (DW_FORM_block4, 0x04)
DW_FORM (DW_FORM_data2, 0x05)
DW_FORM (DW_FORM_data4, 0x06)
DW_FORM (DW_FORM_data8, 0x07)
DW_FORM (DW_FORM_string, 0x08)
DW_FORM (DW_FORM_block, 0x09)
DW_FORM (DW_FORM_block1, 0x0a)
DW_FORM (DW_FORM_data1, 0x0b)
DW_FORM (DW_FORM_flag, 0x0c)
DW_FORM (DW_FORM_sdata, 0x0d)
DW_FORM (DW_FORM_strp, 0x0e)
DW_FORM (DW_FORM_udata, 0x0f)
DW_FORM (DW_FORM_ref_addr, 0x10)
DW_FORM (DW_FORM_ref1, 0x11)
DW_FORM (DW_FORM_ref2, 0x12)
DW_FORM (DW_FORM_ref4, 0x13)
DW_FORM (DW_FORM_ref8, 0x14)
DW_FORM (DW_FORM_ref_udata, 0x15)
DW_FORM (DW_FORM_indirect, 0x16)
/* DWARF 4. */
DW_FORM (DW_FORM_sec_offset, 0x17)
DW_FORM (DW_FORM_exprloc, 0x18)
DW_FORM (DW_FORM_flag_present, 0x19)
DW_FORM (DW_FORM_ref_sig8, 0x20)
/* Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. */
DW_FORM (DW_FORM_GNU_addr_index, 0x1f01)
DW_FORM (DW_FORM_GNU_str_index, 0x1f02)
/* Extensions for DWZ multifile.
See http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open . */
DW_FORM (DW_FORM_GNU_ref_alt, 0x1f20)
DW_FORM (DW_FORM_GNU_strp_alt, 0x1f21)
DW_END_FORM
DW_FIRST_AT (DW_AT_sibling, 0x01)
DW_AT (DW_AT_location, 0x02)
DW_AT (DW_AT_name, 0x03)
DW_AT (DW_AT_ordering, 0x09)
DW_AT (DW_AT_subscr_data, 0x0a)
DW_AT (DW_AT_byte_size, 0x0b)
DW_AT (DW_AT_bit_offset, 0x0c)
DW_AT (DW_AT_bit_size, 0x0d)
DW_AT (DW_AT_element_list, 0x0f)
DW_AT (DW_AT_stmt_list, 0x10)
DW_AT (DW_AT_low_pc, 0x11)
DW_AT (DW_AT_high_pc, 0x12)
DW_AT (DW_AT_language, 0x13)
DW_AT (DW_AT_member, 0x14)
DW_AT (DW_AT_discr, 0x15)
DW_AT (DW_AT_discr_value, 0x16)
DW_AT (DW_AT_visibility, 0x17)
DW_AT (DW_AT_import, 0x18)
DW_AT (DW_AT_string_length, 0x19)
DW_AT (DW_AT_common_reference, 0x1a)
DW_AT (DW_AT_comp_dir, 0x1b)
DW_AT (DW_AT_const_value, 0x1c)
DW_AT (DW_AT_containing_type, 0x1d)
DW_AT (DW_AT_default_value, 0x1e)
DW_AT (DW_AT_inline, 0x20)
DW_AT (DW_AT_is_optional, 0x21)
DW_AT (DW_AT_lower_bound, 0x22)
DW_AT (DW_AT_producer, 0x25)
DW_AT (DW_AT_prototyped, 0x27)
DW_AT (DW_AT_return_addr, 0x2a)
DW_AT (DW_AT_start_scope, 0x2c)
DW_AT (DW_AT_bit_stride, 0x2e)
DW_AT (DW_AT_upper_bound, 0x2f)
DW_AT (DW_AT_abstract_origin, 0x31)
DW_AT (DW_AT_accessibility, 0x32)
DW_AT (DW_AT_address_class, 0x33)
DW_AT (DW_AT_artificial, 0x34)
DW_AT (DW_AT_base_types, 0x35)
DW_AT (DW_AT_calling_convention, 0x36)
DW_AT (DW_AT_count, 0x37)
DW_AT (DW_AT_data_member_location, 0x38)
DW_AT (DW_AT_decl_column, 0x39)
DW_AT (DW_AT_decl_file, 0x3a)
DW_AT (DW_AT_decl_line, 0x3b)
DW_AT (DW_AT_declaration, 0x3c)
DW_AT (DW_AT_discr_list, 0x3d)
DW_AT (DW_AT_encoding, 0x3e)
DW_AT (DW_AT_external, 0x3f)
DW_AT (DW_AT_frame_base, 0x40)
DW_AT (DW_AT_friend, 0x41)
DW_AT (DW_AT_identifier_case, 0x42)
DW_AT (DW_AT_macro_info, 0x43)
DW_AT (DW_AT_namelist_items, 0x44)
DW_AT (DW_AT_priority, 0x45)
DW_AT (DW_AT_segment, 0x46)
DW_AT (DW_AT_specification, 0x47)
DW_AT (DW_AT_static_link, 0x48)
DW_AT (DW_AT_type, 0x49)
DW_AT (DW_AT_use_location, 0x4a)
DW_AT (DW_AT_variable_parameter, 0x4b)
DW_AT (DW_AT_virtuality, 0x4c)
DW_AT (DW_AT_vtable_elem_location, 0x4d)
/* DWARF 3 values. */
DW_AT (DW_AT_allocated, 0x4e)
DW_AT (DW_AT_associated, 0x4f)
DW_AT (DW_AT_data_location, 0x50)
DW_AT (DW_AT_byte_stride, 0x51)
DW_AT (DW_AT_entry_pc, 0x52)
DW_AT (DW_AT_use_UTF8, 0x53)
DW_AT (DW_AT_extension, 0x54)
DW_AT (DW_AT_ranges, 0x55)
DW_AT (DW_AT_trampoline, 0x56)
DW_AT (DW_AT_call_column, 0x57)
DW_AT (DW_AT_call_file, 0x58)
DW_AT (DW_AT_call_line, 0x59)
DW_AT (DW_AT_description, 0x5a)
DW_AT (DW_AT_binary_scale, 0x5b)
DW_AT (DW_AT_decimal_scale, 0x5c)
DW_AT (DW_AT_small, 0x5d)
DW_AT (DW_AT_decimal_sign, 0x5e)
DW_AT (DW_AT_digit_count, 0x5f)
DW_AT (DW_AT_picture_string, 0x60)
DW_AT (DW_AT_mutable, 0x61)
DW_AT (DW_AT_threads_scaled, 0x62)
DW_AT (DW_AT_explicit, 0x63)
DW_AT (DW_AT_object_pointer, 0x64)
DW_AT (DW_AT_endianity, 0x65)
DW_AT (DW_AT_elemental, 0x66)
DW_AT (DW_AT_pure, 0x67)
DW_AT (DW_AT_recursive, 0x68)
/* DWARF 4. */
DW_AT (DW_AT_signature, 0x69)
DW_AT (DW_AT_main_subprogram, 0x6a)
DW_AT (DW_AT_data_bit_offset, 0x6b)
DW_AT (DW_AT_const_expr, 0x6c)
DW_AT (DW_AT_enum_class, 0x6d)
DW_AT (DW_AT_linkage_name, 0x6e)
DW_AT_DUP (DW_AT_lo_user, 0x2000) /* Implementation-defined range start. */
DW_AT_DUP (DW_AT_hi_user, 0x3fff) /* Implementation-defined range end. */
/* SGI/MIPS extensions. */
DW_AT (DW_AT_MIPS_fde, 0x2001)
DW_AT (DW_AT_MIPS_loop_begin, 0x2002)
DW_AT (DW_AT_MIPS_tail_loop_begin, 0x2003)
DW_AT (DW_AT_MIPS_epilog_begin, 0x2004)
DW_AT (DW_AT_MIPS_loop_unroll_factor, 0x2005)
DW_AT (DW_AT_MIPS_software_pipeline_depth, 0x2006)
DW_AT (DW_AT_MIPS_linkage_name, 0x2007)
DW_AT (DW_AT_MIPS_stride, 0x2008)
DW_AT (DW_AT_MIPS_abstract_name, 0x2009)
DW_AT (DW_AT_MIPS_clone_origin, 0x200a)
DW_AT (DW_AT_MIPS_has_inlines, 0x200b)
/* HP extensions. */
DW_AT (DW_AT_HP_block_index, 0x2000)
DW_AT_DUP (DW_AT_HP_unmodifiable, 0x2001) /* Same as DW_AT_MIPS_fde. */
DW_AT_DUP (DW_AT_HP_prologue, 0x2005) /* Same as DW_AT_MIPS_loop_unroll. */
DW_AT_DUP (DW_AT_HP_epilogue, 0x2008) /* Same as DW_AT_MIPS_stride. */
DW_AT (DW_AT_HP_actuals_stmt_list, 0x2010)
DW_AT (DW_AT_HP_proc_per_section, 0x2011)
DW_AT (DW_AT_HP_raw_data_ptr, 0x2012)
DW_AT (DW_AT_HP_pass_by_reference, 0x2013)
DW_AT (DW_AT_HP_opt_level, 0x2014)
DW_AT (DW_AT_HP_prof_version_id, 0x2015)
DW_AT (DW_AT_HP_opt_flags, 0x2016)
DW_AT (DW_AT_HP_cold_region_low_pc, 0x2017)
DW_AT (DW_AT_HP_cold_region_high_pc, 0x2018)
DW_AT (DW_AT_HP_all_variables_modifiable, 0x2019)
DW_AT (DW_AT_HP_linkage_name, 0x201a)
DW_AT (DW_AT_HP_prof_flags, 0x201b) /* In comp unit of procs_info for -g. */
DW_AT (DW_AT_HP_unit_name, 0x201f)
DW_AT (DW_AT_HP_unit_size, 0x2020)
DW_AT (DW_AT_HP_widened_byte_size, 0x2021)
DW_AT (DW_AT_HP_definition_points, 0x2022)
DW_AT (DW_AT_HP_default_location, 0x2023)
DW_AT (DW_AT_HP_is_result_param, 0x2029)
/* GNU extensions. */
DW_AT (DW_AT_sf_names, 0x2101)
DW_AT (DW_AT_src_info, 0x2102)
DW_AT (DW_AT_mac_info, 0x2103)
DW_AT (DW_AT_src_coords, 0x2104)
DW_AT (DW_AT_body_begin, 0x2105)
DW_AT (DW_AT_body_end, 0x2106)
DW_AT (DW_AT_GNU_vector, 0x2107)
/* Thread-safety annotations.
See http://gcc.gnu.org/wiki/ThreadSafetyAnnotation . */
DW_AT (DW_AT_GNU_guarded_by, 0x2108)
DW_AT (DW_AT_GNU_pt_guarded_by, 0x2109)
DW_AT (DW_AT_GNU_guarded, 0x210a)
DW_AT (DW_AT_GNU_pt_guarded, 0x210b)
DW_AT (DW_AT_GNU_locks_excluded, 0x210c)
DW_AT (DW_AT_GNU_exclusive_locks_required, 0x210d)
DW_AT (DW_AT_GNU_shared_locks_required, 0x210e)
/* One-definition rule violation detection.
See http://gcc.gnu.org/wiki/DwarfSeparateTypeInfo . */
DW_AT (DW_AT_GNU_odr_signature, 0x210f)
/* Template template argument name.
See http://gcc.gnu.org/wiki/TemplateParmsDwarf . */
DW_AT (DW_AT_GNU_template_name, 0x2110)
/* The GNU call site extension.
See http://www.dwarfstd.org/ShowIssue.php?issue=100909.2&type=open . */
DW_AT (DW_AT_GNU_call_site_value, 0x2111)
DW_AT (DW_AT_GNU_call_site_data_value, 0x2112)
DW_AT (DW_AT_GNU_call_site_target, 0x2113)
DW_AT (DW_AT_GNU_call_site_target_clobbered, 0x2114)
DW_AT (DW_AT_GNU_tail_call, 0x2115)
DW_AT (DW_AT_GNU_all_tail_call_sites, 0x2116)
DW_AT (DW_AT_GNU_all_call_sites, 0x2117)
DW_AT (DW_AT_GNU_all_source_call_sites, 0x2118)
/* Section offset into .debug_macro section. */
DW_AT (DW_AT_GNU_macros, 0x2119)
/* Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. */
DW_AT (DW_AT_GNU_dwo_name, 0x2130)
DW_AT (DW_AT_GNU_dwo_id, 0x2131)
DW_AT (DW_AT_GNU_ranges_base, 0x2132)
DW_AT (DW_AT_GNU_addr_base, 0x2133)
DW_AT (DW_AT_GNU_pubnames, 0x2134)
DW_AT (DW_AT_GNU_pubtypes, 0x2135)
/* Attribute for discriminator.
See http://gcc.gnu.org/wiki/Discriminator */
DW_AT (DW_AT_GNU_discriminator, 0x2136)
/* VMS extensions. */
DW_AT (DW_AT_VMS_rtnbeg_pd_address, 0x2201)
/* GNAT extensions. */
/* GNAT descriptive type.
See http://gcc.gnu.org/wiki/DW_AT_GNAT_descriptive_type . */
DW_AT (DW_AT_use_GNAT_descriptive_type, 0x2301)
DW_AT (DW_AT_GNAT_descriptive_type, 0x2302)
/* UPC extension. */
DW_AT (DW_AT_upc_threads_scaled, 0x3210)
/* PGI (STMicroelectronics) extensions. */
DW_AT (DW_AT_PGI_lbase, 0x3a00)
DW_AT (DW_AT_PGI_soffset, 0x3a01)
DW_AT (DW_AT_PGI_lstride, 0x3a02)
DW_END_AT
DW_FIRST_OP (DW_OP_addr, 0x03)
DW_OP (DW_OP_deref, 0x06)
DW_OP (DW_OP_const1u, 0x08)
DW_OP (DW_OP_const1s, 0x09)
DW_OP (DW_OP_const2u, 0x0a)
DW_OP (DW_OP_const2s, 0x0b)
DW_OP (DW_OP_const4u, 0x0c)
DW_OP (DW_OP_const4s, 0x0d)
DW_OP (DW_OP_const8u, 0x0e)
DW_OP (DW_OP_const8s, 0x0f)
DW_OP (DW_OP_constu, 0x10)
DW_OP (DW_OP_consts, 0x11)
DW_OP (DW_OP_dup, 0x12)
DW_OP (DW_OP_drop, 0x13)
DW_OP (DW_OP_over, 0x14)
DW_OP (DW_OP_pick, 0x15)
DW_OP (DW_OP_swap, 0x16)
DW_OP (DW_OP_rot, 0x17)
DW_OP (DW_OP_xderef, 0x18)
DW_OP (DW_OP_abs, 0x19)
DW_OP (DW_OP_and, 0x1a)
DW_OP (DW_OP_div, 0x1b)
DW_OP (DW_OP_minus, 0x1c)
DW_OP (DW_OP_mod, 0x1d)
DW_OP (DW_OP_mul, 0x1e)
DW_OP (DW_OP_neg, 0x1f)
DW_OP (DW_OP_not, 0x20)
DW_OP (DW_OP_or, 0x21)
DW_OP (DW_OP_plus, 0x22)
DW_OP (DW_OP_plus_uconst, 0x23)
DW_OP (DW_OP_shl, 0x24)
DW_OP (DW_OP_shr, 0x25)
DW_OP (DW_OP_shra, 0x26)
DW_OP (DW_OP_xor, 0x27)
DW_OP (DW_OP_bra, 0x28)
DW_OP (DW_OP_eq, 0x29)
DW_OP (DW_OP_ge, 0x2a)
DW_OP (DW_OP_gt, 0x2b)
DW_OP (DW_OP_le, 0x2c)
DW_OP (DW_OP_lt, 0x2d)
DW_OP (DW_OP_ne, 0x2e)
DW_OP (DW_OP_skip, 0x2f)
DW_OP (DW_OP_lit0, 0x30)
DW_OP (DW_OP_lit1, 0x31)
DW_OP (DW_OP_lit2, 0x32)
DW_OP (DW_OP_lit3, 0x33)
DW_OP (DW_OP_lit4, 0x34)
DW_OP (DW_OP_lit5, 0x35)
DW_OP (DW_OP_lit6, 0x36)
DW_OP (DW_OP_lit7, 0x37)
DW_OP (DW_OP_lit8, 0x38)
DW_OP (DW_OP_lit9, 0x39)
DW_OP (DW_OP_lit10, 0x3a)
DW_OP (DW_OP_lit11, 0x3b)
DW_OP (DW_OP_lit12, 0x3c)
DW_OP (DW_OP_lit13, 0x3d)
DW_OP (DW_OP_lit14, 0x3e)
DW_OP (DW_OP_lit15, 0x3f)
DW_OP (DW_OP_lit16, 0x40)
DW_OP (DW_OP_lit17, 0x41)
DW_OP (DW_OP_lit18, 0x42)
DW_OP (DW_OP_lit19, 0x43)
DW_OP (DW_OP_lit20, 0x44)
DW_OP (DW_OP_lit21, 0x45)
DW_OP (DW_OP_lit22, 0x46)
DW_OP (DW_OP_lit23, 0x47)
DW_OP (DW_OP_lit24, 0x48)
DW_OP (DW_OP_lit25, 0x49)
DW_OP (DW_OP_lit26, 0x4a)
DW_OP (DW_OP_lit27, 0x4b)
DW_OP (DW_OP_lit28, 0x4c)
DW_OP (DW_OP_lit29, 0x4d)
DW_OP (DW_OP_lit30, 0x4e)
DW_OP (DW_OP_lit31, 0x4f)
DW_OP (DW_OP_reg0, 0x50)
DW_OP (DW_OP_reg1, 0x51)
DW_OP (DW_OP_reg2, 0x52)
DW_OP (DW_OP_reg3, 0x53)
DW_OP (DW_OP_reg4, 0x54)
DW_OP (DW_OP_reg5, 0x55)
DW_OP (DW_OP_reg6, 0x56)
DW_OP (DW_OP_reg7, 0x57)
DW_OP (DW_OP_reg8, 0x58)
DW_OP (DW_OP_reg9, 0x59)
DW_OP (DW_OP_reg10, 0x5a)
DW_OP (DW_OP_reg11, 0x5b)
DW_OP (DW_OP_reg12, 0x5c)
DW_OP (DW_OP_reg13, 0x5d)
DW_OP (DW_OP_reg14, 0x5e)
DW_OP (DW_OP_reg15, 0x5f)
DW_OP (DW_OP_reg16, 0x60)
DW_OP (DW_OP_reg17, 0x61)
DW_OP (DW_OP_reg18, 0x62)
DW_OP (DW_OP_reg19, 0x63)
DW_OP (DW_OP_reg20, 0x64)
DW_OP (DW_OP_reg21, 0x65)
DW_OP (DW_OP_reg22, 0x66)
DW_OP (DW_OP_reg23, 0x67)
DW_OP (DW_OP_reg24, 0x68)
DW_OP (DW_OP_reg25, 0x69)
DW_OP (DW_OP_reg26, 0x6a)
DW_OP (DW_OP_reg27, 0x6b)
DW_OP (DW_OP_reg28, 0x6c)
DW_OP (DW_OP_reg29, 0x6d)
DW_OP (DW_OP_reg30, 0x6e)
DW_OP (DW_OP_reg31, 0x6f)
DW_OP (DW_OP_breg0, 0x70)
DW_OP (DW_OP_breg1, 0x71)
DW_OP (DW_OP_breg2, 0x72)
DW_OP (DW_OP_breg3, 0x73)
DW_OP (DW_OP_breg4, 0x74)
DW_OP (DW_OP_breg5, 0x75)
DW_OP (DW_OP_breg6, 0x76)
DW_OP (DW_OP_breg7, 0x77)
DW_OP (DW_OP_breg8, 0x78)
DW_OP (DW_OP_breg9, 0x79)
DW_OP (DW_OP_breg10, 0x7a)
DW_OP (DW_OP_breg11, 0x7b)
DW_OP (DW_OP_breg12, 0x7c)
DW_OP (DW_OP_breg13, 0x7d)
DW_OP (DW_OP_breg14, 0x7e)
DW_OP (DW_OP_breg15, 0x7f)
DW_OP (DW_OP_breg16, 0x80)
DW_OP (DW_OP_breg17, 0x81)
DW_OP (DW_OP_breg18, 0x82)
DW_OP (DW_OP_breg19, 0x83)
DW_OP (DW_OP_breg20, 0x84)
DW_OP (DW_OP_breg21, 0x85)
DW_OP (DW_OP_breg22, 0x86)
DW_OP (DW_OP_breg23, 0x87)
DW_OP (DW_OP_breg24, 0x88)
DW_OP (DW_OP_breg25, 0x89)
DW_OP (DW_OP_breg26, 0x8a)
DW_OP (DW_OP_breg27, 0x8b)
DW_OP (DW_OP_breg28, 0x8c)
DW_OP (DW_OP_breg29, 0x8d)
DW_OP (DW_OP_breg30, 0x8e)
DW_OP (DW_OP_breg31, 0x8f)
DW_OP (DW_OP_regx, 0x90)
DW_OP (DW_OP_fbreg, 0x91)
DW_OP (DW_OP_bregx, 0x92)
DW_OP (DW_OP_piece, 0x93)
DW_OP (DW_OP_deref_size, 0x94)
DW_OP (DW_OP_xderef_size, 0x95)
DW_OP (DW_OP_nop, 0x96)
/* DWARF 3 extensions. */
DW_OP (DW_OP_push_object_address, 0x97)
DW_OP (DW_OP_call2, 0x98)
DW_OP (DW_OP_call4, 0x99)
DW_OP (DW_OP_call_ref, 0x9a)
DW_OP (DW_OP_form_tls_address, 0x9b)
DW_OP (DW_OP_call_frame_cfa, 0x9c)
DW_OP (DW_OP_bit_piece, 0x9d)
/* DWARF 4 extensions. */
DW_OP (DW_OP_implicit_value, 0x9e)
DW_OP (DW_OP_stack_value, 0x9f)
DW_OP_DUP (DW_OP_lo_user, 0xe0) /* Implementation-defined range start. */
DW_OP_DUP (DW_OP_hi_user, 0xff) /* Implementation-defined range end. */
/* GNU extensions. */
DW_OP (DW_OP_GNU_push_tls_address, 0xe0)
/* The following is for marking variables that are uninitialized. */
DW_OP (DW_OP_GNU_uninit, 0xf0)
DW_OP (DW_OP_GNU_encoded_addr, 0xf1)
/* The GNU implicit pointer extension.
See http://www.dwarfstd.org/ShowIssue.php?issue=100831.1&type=open . */
DW_OP (DW_OP_GNU_implicit_pointer, 0xf2)
/* The GNU entry value extension.
See http://www.dwarfstd.org/ShowIssue.php?issue=100909.1&type=open . */
DW_OP (DW_OP_GNU_entry_value, 0xf3)
/* The GNU typed stack extension.
See http://www.dwarfstd.org/doc/040408.1.html . */
DW_OP (DW_OP_GNU_const_type, 0xf4)
DW_OP (DW_OP_GNU_regval_type, 0xf5)
DW_OP (DW_OP_GNU_deref_type, 0xf6)
DW_OP (DW_OP_GNU_convert, 0xf7)
DW_OP (DW_OP_GNU_reinterpret, 0xf9)
/* The GNU parameter ref extension. */
DW_OP (DW_OP_GNU_parameter_ref, 0xfa)
/* Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFission. */
DW_OP (DW_OP_GNU_addr_index, 0xfb)
DW_OP (DW_OP_GNU_const_index, 0xfc)
/* HP extensions. */
DW_OP_DUP (DW_OP_HP_unknown, 0xe0) /* Ouch, the same as GNU_push_tls_address. */
DW_OP (DW_OP_HP_is_value, 0xe1)
DW_OP (DW_OP_HP_fltconst4, 0xe2)
DW_OP (DW_OP_HP_fltconst8, 0xe3)
DW_OP (DW_OP_HP_mod_range, 0xe4)
DW_OP (DW_OP_HP_unmod_range, 0xe5)
DW_OP (DW_OP_HP_tls, 0xe6)
/* PGI (STMicroelectronics) extensions. */
DW_OP (DW_OP_PGI_omp_thread_num, 0xf8)
DW_END_OP
DW_FIRST_ATE (DW_ATE_void, 0x0)
DW_ATE (DW_ATE_address, 0x1)
DW_ATE (DW_ATE_boolean, 0x2)
DW_ATE (DW_ATE_complex_float, 0x3)
DW_ATE (DW_ATE_float, 0x4)
DW_ATE (DW_ATE_signed, 0x5)
DW_ATE (DW_ATE_signed_char, 0x6)
DW_ATE (DW_ATE_unsigned, 0x7)
DW_ATE (DW_ATE_unsigned_char, 0x8)
/* DWARF 3. */
DW_ATE (DW_ATE_imaginary_float, 0x9)
DW_ATE (DW_ATE_packed_decimal, 0xa)
DW_ATE (DW_ATE_numeric_string, 0xb)
DW_ATE (DW_ATE_edited, 0xc)
DW_ATE (DW_ATE_signed_fixed, 0xd)
DW_ATE (DW_ATE_unsigned_fixed, 0xe)
DW_ATE (DW_ATE_decimal_float, 0xf)
/* DWARF 4. */
DW_ATE (DW_ATE_UTF, 0x10)
DW_ATE_DUP (DW_ATE_lo_user, 0x80)
DW_ATE_DUP (DW_ATE_hi_user, 0xff)
/* HP extensions. */
DW_ATE (DW_ATE_HP_float80, 0x80) /* Floating-point (80 bit). */
DW_ATE (DW_ATE_HP_complex_float80, 0x81) /* Complex floating-point (80 bit). */
DW_ATE (DW_ATE_HP_float128, 0x82) /* Floating-point (128 bit). */
DW_ATE (DW_ATE_HP_complex_float128, 0x83) /* Complex fp (128 bit). */
DW_ATE (DW_ATE_HP_floathpintel, 0x84) /* Floating-point (82 bit IA64). */
DW_ATE (DW_ATE_HP_imaginary_float80, 0x85)
DW_ATE (DW_ATE_HP_imaginary_float128, 0x86)
DW_ATE (DW_ATE_HP_VAX_float, 0x88) /* F or G floating. */
DW_ATE (DW_ATE_HP_VAX_float_d, 0x89) /* D floating. */
DW_ATE (DW_ATE_HP_packed_decimal, 0x8a) /* Cobol. */
DW_ATE (DW_ATE_HP_zoned_decimal, 0x8b) /* Cobol. */
DW_ATE (DW_ATE_HP_edited, 0x8c) /* Cobol. */
DW_ATE (DW_ATE_HP_signed_fixed, 0x8d) /* Cobol. */
DW_ATE (DW_ATE_HP_unsigned_fixed, 0x8e) /* Cobol. */
DW_ATE (DW_ATE_HP_VAX_complex_float, 0x8f) /* F or G floating complex. */
DW_ATE (DW_ATE_HP_VAX_complex_float_d, 0x90) /* D floating complex. */
DW_END_ATE
DW_FIRST_CFA (DW_CFA_advance_loc, 0x40)
DW_CFA (DW_CFA_offset, 0x80)
DW_CFA (DW_CFA_restore, 0xc0)
DW_CFA (DW_CFA_nop, 0x00)
DW_CFA (DW_CFA_set_loc, 0x01)
DW_CFA (DW_CFA_advance_loc1, 0x02)
DW_CFA (DW_CFA_advance_loc2, 0x03)
DW_CFA (DW_CFA_advance_loc4, 0x04)
DW_CFA (DW_CFA_offset_extended, 0x05)
DW_CFA (DW_CFA_restore_extended, 0x06)
DW_CFA (DW_CFA_undefined, 0x07)
DW_CFA (DW_CFA_same_value, 0x08)
DW_CFA (DW_CFA_register, 0x09)
DW_CFA (DW_CFA_remember_state, 0x0a)
DW_CFA (DW_CFA_restore_state, 0x0b)
DW_CFA (DW_CFA_def_cfa, 0x0c)
DW_CFA (DW_CFA_def_cfa_register, 0x0d)
DW_CFA (DW_CFA_def_cfa_offset, 0x0e)
/* DWARF 3. */
DW_CFA (DW_CFA_def_cfa_expression, 0x0f)
DW_CFA (DW_CFA_expression, 0x10)
DW_CFA (DW_CFA_offset_extended_sf, 0x11)
DW_CFA (DW_CFA_def_cfa_sf, 0x12)
DW_CFA (DW_CFA_def_cfa_offset_sf, 0x13)
DW_CFA (DW_CFA_val_offset, 0x14)
DW_CFA (DW_CFA_val_offset_sf, 0x15)
DW_CFA (DW_CFA_val_expression, 0x16)
DW_CFA (DW_CFA_lo_user, 0x1c)
DW_CFA (DW_CFA_hi_user, 0x3f)
/* SGI/MIPS specific. */
DW_CFA (DW_CFA_MIPS_advance_loc8, 0x1d)
/* GNU extensions. */
DW_CFA (DW_CFA_GNU_window_save, 0x2d)
DW_CFA (DW_CFA_GNU_args_size, 0x2e)
DW_CFA (DW_CFA_GNU_negative_offset_extended, 0x2f)
DW_END_CFA

426
src/libbacktrace/dwarf2.h Normal file
View File

@ -0,0 +1,426 @@
/* Declarations and definitions of codes relating to the DWARF2 and
DWARF3 symbolic debugging information formats.
Copyright (C) 1992, 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002,
2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
Free Software Foundation, Inc.
Written by Gary Funck (gary@intrepid.com) The Ada Joint Program
Office (AJPO), Florida State University and Silicon Graphics Inc.
provided support for this effort -- June 21, 1995.
Derived from the DWARF 1 implementation written by Ron Guilmette
(rfg@netcom.com), November 1990.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* This file is derived from the DWARF specification (a public document)
Revision 2.0.0 (July 27, 1993) developed by the UNIX International
Programming Languages Special Interest Group (UI/PLSIG) and distributed
by UNIX International. Copies of this specification are available from
UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054.
This file also now contains definitions from the DWARF 3 specification
published Dec 20, 2005, available from: http://dwarf.freestandards.org. */
#ifndef _DWARF2_H
#define _DWARF2_H
#define DW_TAG(name, value) , name = value
#define DW_TAG_DUP(name, value) , name = value
#define DW_FORM(name, value) , name = value
#define DW_AT(name, value) , name = value
#define DW_AT_DUP(name, value) , name = value
#define DW_OP(name, value) , name = value
#define DW_OP_DUP(name, value) , name = value
#define DW_ATE(name, value) , name = value
#define DW_ATE_DUP(name, value) , name = value
#define DW_CFA(name, value) , name = value
#define DW_FIRST_TAG(name, value) enum dwarf_tag { \
name = value
#define DW_END_TAG };
#define DW_FIRST_FORM(name, value) enum dwarf_form { \
name = value
#define DW_END_FORM };
#define DW_FIRST_AT(name, value) enum dwarf_attribute { \
name = value
#define DW_END_AT };
#define DW_FIRST_OP(name, value) enum dwarf_location_atom { \
name = value
#define DW_END_OP };
#define DW_FIRST_ATE(name, value) enum dwarf_type { \
name = value
#define DW_END_ATE };
#define DW_FIRST_CFA(name, value) enum dwarf_call_frame_info { \
name = value
#define DW_END_CFA };
#include "dwarf2.def"
#undef DW_FIRST_TAG
#undef DW_END_TAG
#undef DW_FIRST_FORM
#undef DW_END_FORM
#undef DW_FIRST_AT
#undef DW_END_AT
#undef DW_FIRST_OP
#undef DW_END_OP
#undef DW_FIRST_ATE
#undef DW_END_ATE
#undef DW_FIRST_CFA
#undef DW_END_CFA
#undef DW_TAG
#undef DW_TAG_DUP
#undef DW_FORM
#undef DW_AT
#undef DW_AT_DUP
#undef DW_OP
#undef DW_OP_DUP
#undef DW_ATE
#undef DW_ATE_DUP
#undef DW_CFA
/* Flag that tells whether entry has a child or not. */
#define DW_children_no 0
#define DW_children_yes 1
#define DW_AT_stride_size DW_AT_bit_stride /* Note: The use of DW_AT_stride_size is deprecated. */
#define DW_AT_stride DW_AT_byte_stride /* Note: The use of DW_AT_stride is deprecated. */
/* Decimal sign encodings. */
enum dwarf_decimal_sign_encoding
{
/* DWARF 3. */
DW_DS_unsigned = 0x01,
DW_DS_leading_overpunch = 0x02,
DW_DS_trailing_overpunch = 0x03,
DW_DS_leading_separate = 0x04,
DW_DS_trailing_separate = 0x05
};
/* Endianity encodings. */
enum dwarf_endianity_encoding
{
/* DWARF 3. */
DW_END_default = 0x00,
DW_END_big = 0x01,
DW_END_little = 0x02,
DW_END_lo_user = 0x40,
DW_END_hi_user = 0xff
};
/* Array ordering names and codes. */
enum dwarf_array_dim_ordering
{
DW_ORD_row_major = 0,
DW_ORD_col_major = 1
};
/* Access attribute. */
enum dwarf_access_attribute
{
DW_ACCESS_public = 1,
DW_ACCESS_protected = 2,
DW_ACCESS_private = 3
};
/* Visibility. */
enum dwarf_visibility_attribute
{
DW_VIS_local = 1,
DW_VIS_exported = 2,
DW_VIS_qualified = 3
};
/* Virtuality. */
enum dwarf_virtuality_attribute
{
DW_VIRTUALITY_none = 0,
DW_VIRTUALITY_virtual = 1,
DW_VIRTUALITY_pure_virtual = 2
};
/* Case sensitivity. */
enum dwarf_id_case
{
DW_ID_case_sensitive = 0,
DW_ID_up_case = 1,
DW_ID_down_case = 2,
DW_ID_case_insensitive = 3
};
/* Calling convention. */
enum dwarf_calling_convention
{
DW_CC_normal = 0x1,
DW_CC_program = 0x2,
DW_CC_nocall = 0x3,
DW_CC_lo_user = 0x40,
DW_CC_hi_user = 0xff,
DW_CC_GNU_renesas_sh = 0x40,
DW_CC_GNU_borland_fastcall_i386 = 0x41,
/* This DW_CC_ value is not currently generated by any toolchain. It is
used internally to GDB to indicate OpenCL C functions that have been
compiled with the IBM XL C for OpenCL compiler and use a non-platform
calling convention for passing OpenCL C vector types. This value may
be changed freely as long as it does not conflict with any other DW_CC_
value defined here. */
DW_CC_GDB_IBM_OpenCL = 0xff
};
/* Inline attribute. */
enum dwarf_inline_attribute
{
DW_INL_not_inlined = 0,
DW_INL_inlined = 1,
DW_INL_declared_not_inlined = 2,
DW_INL_declared_inlined = 3
};
/* Discriminant lists. */
enum dwarf_discrim_list
{
DW_DSC_label = 0,
DW_DSC_range = 1
};
/* Line number opcodes. */
enum dwarf_line_number_ops
{
DW_LNS_extended_op = 0,
DW_LNS_copy = 1,
DW_LNS_advance_pc = 2,
DW_LNS_advance_line = 3,
DW_LNS_set_file = 4,
DW_LNS_set_column = 5,
DW_LNS_negate_stmt = 6,
DW_LNS_set_basic_block = 7,
DW_LNS_const_add_pc = 8,
DW_LNS_fixed_advance_pc = 9,
/* DWARF 3. */
DW_LNS_set_prologue_end = 10,
DW_LNS_set_epilogue_begin = 11,
DW_LNS_set_isa = 12
};
/* Line number extended opcodes. */
enum dwarf_line_number_x_ops
{
DW_LNE_end_sequence = 1,
DW_LNE_set_address = 2,
DW_LNE_define_file = 3,
DW_LNE_set_discriminator = 4,
/* HP extensions. */
DW_LNE_HP_negate_is_UV_update = 0x11,
DW_LNE_HP_push_context = 0x12,
DW_LNE_HP_pop_context = 0x13,
DW_LNE_HP_set_file_line_column = 0x14,
DW_LNE_HP_set_routine_name = 0x15,
DW_LNE_HP_set_sequence = 0x16,
DW_LNE_HP_negate_post_semantics = 0x17,
DW_LNE_HP_negate_function_exit = 0x18,
DW_LNE_HP_negate_front_end_logical = 0x19,
DW_LNE_HP_define_proc = 0x20,
DW_LNE_HP_source_file_correlation = 0x80,
DW_LNE_lo_user = 0x80,
DW_LNE_hi_user = 0xff
};
/* Sub-opcodes for DW_LNE_HP_source_file_correlation. */
enum dwarf_line_number_hp_sfc_ops
{
DW_LNE_HP_SFC_formfeed = 1,
DW_LNE_HP_SFC_set_listing_line = 2,
DW_LNE_HP_SFC_associate = 3
};
/* Type codes for location list entries.
Extension for Fission. See http://gcc.gnu.org/wiki/DebugFission. */
enum dwarf_location_list_entry_type
{
DW_LLE_GNU_end_of_list_entry = 0,
DW_LLE_GNU_base_address_selection_entry = 1,
DW_LLE_GNU_start_end_entry = 2,
DW_LLE_GNU_start_length_entry = 3
};
#define DW_CIE_ID 0xffffffff
#define DW64_CIE_ID 0xffffffffffffffffULL
#define DW_CIE_VERSION 1
#define DW_CFA_extended 0
#define DW_CHILDREN_no 0x00
#define DW_CHILDREN_yes 0x01
#define DW_ADDR_none 0
/* Source language names and codes. */
enum dwarf_source_language
{
DW_LANG_C89 = 0x0001,
DW_LANG_C = 0x0002,
DW_LANG_Ada83 = 0x0003,
DW_LANG_C_plus_plus = 0x0004,
DW_LANG_Cobol74 = 0x0005,
DW_LANG_Cobol85 = 0x0006,
DW_LANG_Fortran77 = 0x0007,
DW_LANG_Fortran90 = 0x0008,
DW_LANG_Pascal83 = 0x0009,
DW_LANG_Modula2 = 0x000a,
/* DWARF 3. */
DW_LANG_Java = 0x000b,
DW_LANG_C99 = 0x000c,
DW_LANG_Ada95 = 0x000d,
DW_LANG_Fortran95 = 0x000e,
DW_LANG_PLI = 0x000f,
DW_LANG_ObjC = 0x0010,
DW_LANG_ObjC_plus_plus = 0x0011,
DW_LANG_UPC = 0x0012,
DW_LANG_D = 0x0013,
/* DWARF 4. */
DW_LANG_Python = 0x0014,
/* DWARF 5. */
DW_LANG_Go = 0x0016,
DW_LANG_lo_user = 0x8000, /* Implementation-defined range start. */
DW_LANG_hi_user = 0xffff, /* Implementation-defined range start. */
/* MIPS. */
DW_LANG_Mips_Assembler = 0x8001,
/* UPC. */
DW_LANG_Upc = 0x8765,
/* HP extensions. */
DW_LANG_HP_Bliss = 0x8003,
DW_LANG_HP_Basic91 = 0x8004,
DW_LANG_HP_Pascal91 = 0x8005,
DW_LANG_HP_IMacro = 0x8006,
DW_LANG_HP_Assembler = 0x8007
};
/* Names and codes for macro information. */
enum dwarf_macinfo_record_type
{
DW_MACINFO_define = 1,
DW_MACINFO_undef = 2,
DW_MACINFO_start_file = 3,
DW_MACINFO_end_file = 4,
DW_MACINFO_vendor_ext = 255
};
/* Names and codes for new style macro information. */
enum dwarf_macro_record_type
{
DW_MACRO_GNU_define = 1,
DW_MACRO_GNU_undef = 2,
DW_MACRO_GNU_start_file = 3,
DW_MACRO_GNU_end_file = 4,
DW_MACRO_GNU_define_indirect = 5,
DW_MACRO_GNU_undef_indirect = 6,
DW_MACRO_GNU_transparent_include = 7,
/* Extensions for DWZ multifile.
See http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open . */
DW_MACRO_GNU_define_indirect_alt = 8,
DW_MACRO_GNU_undef_indirect_alt = 9,
DW_MACRO_GNU_transparent_include_alt = 10,
DW_MACRO_GNU_lo_user = 0xe0,
DW_MACRO_GNU_hi_user = 0xff
};
/* @@@ For use with GNU frame unwind information. */
#define DW_EH_PE_absptr 0x00
#define DW_EH_PE_omit 0xff
#define DW_EH_PE_uleb128 0x01
#define DW_EH_PE_udata2 0x02
#define DW_EH_PE_udata4 0x03
#define DW_EH_PE_udata8 0x04
#define DW_EH_PE_sleb128 0x09
#define DW_EH_PE_sdata2 0x0A
#define DW_EH_PE_sdata4 0x0B
#define DW_EH_PE_sdata8 0x0C
#define DW_EH_PE_signed 0x08
#define DW_EH_PE_pcrel 0x10
#define DW_EH_PE_textrel 0x20
#define DW_EH_PE_datarel 0x30
#define DW_EH_PE_funcrel 0x40
#define DW_EH_PE_aligned 0x50
#define DW_EH_PE_indirect 0x80
/* Codes for the debug sections in a dwarf package (.dwp) file.
Extensions for Fission. See http://gcc.gnu.org/wiki/DebugFissionDWP. */
enum dwarf_sect
{
DW_SECT_INFO = 1,
DW_SECT_TYPES = 2,
DW_SECT_ABBREV = 3,
DW_SECT_LINE = 4,
DW_SECT_LOC = 5,
DW_SECT_STR_OFFSETS = 6,
DW_SECT_MACINFO = 7,
DW_SECT_MACRO = 8,
DW_SECT_MAX = 8
};
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Return the name of a DW_TAG_ constant, or NULL if the value is not
recognized. */
extern const char *get_DW_TAG_name (unsigned int tag);
/* Return the name of a DW_AT_ constant, or NULL if the value is not
recognized. */
extern const char *get_DW_AT_name (unsigned int attr);
/* Return the name of a DW_FORM_ constant, or NULL if the value is not
recognized. */
extern const char *get_DW_FORM_name (unsigned int form);
/* Return the name of a DW_OP_ constant, or NULL if the value is not
recognized. */
extern const char *get_DW_OP_name (unsigned int op);
/* Return the name of a DW_ATE_ constant, or NULL if the value is not
recognized. */
extern const char *get_DW_ATE_name (unsigned int enc);
/* Return the name of a DW_CFA_ constant, or NULL if the value is not
recognized. */
extern const char *get_DW_CFA_name (unsigned int opc);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _DWARF2_H */

976
src/libbacktrace/elf.c Normal file
View File

@ -0,0 +1,976 @@
/* elf.c -- Get debug data from an ELF file for backtraces.
Copyright (C) 2012-2014 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 <stdlib.h>
#include <string.h>
#include <sys/types.h>
#ifdef HAVE_DL_ITERATE_PHDR
#include <link.h>
#endif
#include "backtrace.h"
#include "internal.h"
#ifndef HAVE_DL_ITERATE_PHDR
/* Dummy version of dl_iterate_phdr for systems that don't have it. */
#define dl_phdr_info x_dl_phdr_info
#define dl_iterate_phdr x_dl_iterate_phdr
struct dl_phdr_info
{
uintptr_t dlpi_addr;
const char *dlpi_name;
};
static int
dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
size_t, void *) ATTRIBUTE_UNUSED,
void *data ATTRIBUTE_UNUSED)
{
return 0;
}
#endif /* ! defined (HAVE_DL_ITERATE_PHDR) */
/* The configure script must tell us whether we are 32-bit or 64-bit
ELF. We could make this code test and support either possibility,
but there is no point. This code only works for the currently
running executable, which means that we know the ELF mode at
configure mode. */
#if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64
#error "Unknown BACKTRACE_ELF_SIZE"
#endif
/* <link.h> might #include <elf.h> which might define our constants
with slightly different values. Undefine them to be safe. */
#undef EI_NIDENT
#undef EI_MAG0
#undef EI_MAG1
#undef EI_MAG2
#undef EI_MAG3
#undef EI_CLASS
#undef EI_DATA
#undef EI_VERSION
#undef ELF_MAG0
#undef ELF_MAG1
#undef ELF_MAG2
#undef ELF_MAG3
#undef ELFCLASS32
#undef ELFCLASS64
#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. */
typedef uint16_t b_elf_half; /* Elf_Half. */
typedef uint32_t b_elf_word; /* Elf_Word. */
typedef int32_t b_elf_sword; /* Elf_Sword. */
#if BACKTRACE_ELF_SIZE == 32
typedef uint32_t b_elf_addr; /* Elf_Addr. */
typedef uint32_t b_elf_off; /* Elf_Off. */
typedef uint32_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */
#else
typedef uint64_t b_elf_addr; /* Elf_Addr. */
typedef uint64_t b_elf_off; /* Elf_Off. */
typedef uint64_t b_elf_xword; /* Elf_Xword. */
typedef int64_t b_elf_sxword; /* Elf_Sxword. */
typedef uint64_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */
#endif
/* Data structures and associated constants. */
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
b_elf_half e_type; /* Identifies object file type */
b_elf_half e_machine; /* Specifies required architecture */
b_elf_word e_version; /* Identifies object file version */
b_elf_addr e_entry; /* Entry point virtual address */
b_elf_off e_phoff; /* Program header table file offset */
b_elf_off e_shoff; /* Section header table file offset */
b_elf_word e_flags; /* Processor-specific flags */
b_elf_half e_ehsize; /* ELF header size in bytes */
b_elf_half e_phentsize; /* Program header table entry size */
b_elf_half e_phnum; /* Program header table entry count */
b_elf_half e_shentsize; /* Section header table entry size */
b_elf_half e_shnum; /* Section header table entry count */
b_elf_half e_shstrndx; /* Section header string table index */
} b_elf_ehdr; /* Elf_Ehdr. */
#define EI_MAG0 0
#define EI_MAG1 1
#define EI_MAG2 2
#define EI_MAG3 3
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define ELFMAG0 0x7f
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
#define ELFCLASS32 1
#define ELFCLASS64 2
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
#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 */
b_elf_wxword sh_flags; /* Miscellaneous section attributes */
b_elf_addr sh_addr; /* Section virtual addr at execution */
b_elf_off sh_offset; /* Section file offset */
b_elf_wxword sh_size; /* Size of section in bytes */
b_elf_word sh_link; /* Index of another section */
b_elf_word sh_info; /* Additional section information */
b_elf_wxword sh_addralign; /* Section alignment */
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 */
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_DYNSYM 11
#if BACKTRACE_ELF_SIZE == 32
typedef struct
{
b_elf_word st_name; /* Symbol name, index in string tbl */
b_elf_addr st_value; /* Symbol value */
b_elf_word st_size; /* Symbol size */
unsigned char st_info; /* Symbol binding and type */
unsigned char st_other; /* Visibility and other data */
b_elf_half st_shndx; /* Symbol section index */
} b_elf_sym; /* Elf_Sym. */
#else /* BACKTRACE_ELF_SIZE != 32 */
typedef struct
{
b_elf_word st_name; /* Symbol name, index in string tbl */
unsigned char st_info; /* Symbol binding and type */
unsigned char st_other; /* Visibility and other data */
b_elf_half st_shndx; /* Symbol section index */
b_elf_addr st_value; /* Symbol value */
b_elf_xword st_size; /* Symbol size */
} b_elf_sym; /* Elf_Sym. */
#endif /* BACKTRACE_ELF_SIZE != 32 */
#define STT_OBJECT 1
#define STT_FUNC 2
/* An index of ELF 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 elf_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 ELF symbol. */
struct elf_symbol
{
/* The name of the symbol. */
const char *name;
/* The address of the symbol. */
uintptr_t address;
/* The size of the symbol. */
size_t size;
};
/* Information to pass to elf_syminfo. */
struct elf_syminfo_data
{
/* Symbols for the next module. */
struct elf_syminfo_data *next;
/* The ELF symbols, sorted by address. */
struct elf_symbol *symbols;
/* The number of symbols. */
size_t count;
};
/* A dummy callback function used when we can't find any debug info. */
static int
elf_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 ELF executable", -1);
return 0;
}
/* A dummy callback function used when we can't find a symbol
table. */
static void
elf_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 ELF executable", -1);
}
/* Compare struct elf_symbol for qsort. */
static int
elf_symbol_compare (const void *v1, const void *v2)
{
const struct elf_symbol *e1 = (const struct elf_symbol *) v1;
const struct elf_symbol *e2 = (const struct elf_symbol *) v2;
if (e1->address < e2->address)
return -1;
else if (e1->address > e2->address)
return 1;
else
return 0;
}
/* 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
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 addr;
addr = *key;
if (addr < entry->address)
return -1;
else if (addr >= entry->address + entry->size)
return 1;
else
return 0;
}
/* Initialize the symbol table info for elf_syminfo. */
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,
void *data, struct elf_syminfo_data *sdata)
{
size_t sym_count;
const b_elf_sym *sym;
size_t elf_symbol_count;
size_t elf_symbol_size;
struct elf_symbol *elf_symbols;
size_t i;
unsigned int j;
sym_count = symtab_size / sizeof (b_elf_sym);
/* We only care about function symbols. Count them. */
sym = (const b_elf_sym *) symtab_data;
elf_symbol_count = 0;
for (i = 0; i < sym_count; ++i, ++sym)
{
int info;
info = sym->st_info & 0xf;
if ((info == STT_FUNC || info == STT_OBJECT)
&& sym->st_shndx != SHN_UNDEF)
++elf_symbol_count;
}
elf_symbol_size = elf_symbol_count * sizeof (struct elf_symbol);
elf_symbols = ((struct elf_symbol *)
backtrace_alloc (state, elf_symbol_size, error_callback,
data));
if (elf_symbols == NULL)
return 0;
sym = (const b_elf_sym *) symtab_data;
j = 0;
for (i = 0; i < sym_count; ++i, ++sym)
{
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)
{
error_callback (data, "symbol string index out of range", 0);
backtrace_free (state, elf_symbols, elf_symbol_size, error_callback,
data);
return 0;
}
elf_symbols[j].name = (const char *) strtab + sym->st_name;
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);
sdata->next = NULL;
sdata->symbols = elf_symbols;
sdata->count = elf_symbol_count;
return 1;
}
/* Add EDATA to the list in STATE. */
static void
elf_add_syminfo_data (struct backtrace_state *state,
struct elf_syminfo_data *edata)
{
if (!state->threaded)
{
struct elf_syminfo_data **pp;
for (pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
*pp != NULL;
pp = &(*pp)->next)
;
*pp = edata;
}
else
{
while (1)
{
struct elf_syminfo_data **pp;
pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
while (1)
{
struct elf_syminfo_data *p;
p = backtrace_atomic_load_pointer (pp);
if (p == NULL)
break;
pp = &p->next;
}
if (__sync_bool_compare_and_swap (pp, NULL, edata))
break;
}
}
}
/* Return the symbol name and value for an ADDR. */
static void
elf_syminfo (struct backtrace_state *state, uintptr_t addr,
backtrace_syminfo_callback callback,
backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
void *data)
{
struct elf_syminfo_data *edata;
struct elf_symbol *sym = NULL;
if (!state->threaded)
{
for (edata = (struct elf_syminfo_data *) state->syminfo_data;
edata != NULL;
edata = edata->next)
{
sym = ((struct elf_symbol *)
bsearch (&addr, edata->symbols, edata->count,
sizeof (struct elf_symbol), elf_symbol_search));
if (sym != NULL)
break;
}
}
else
{
struct elf_syminfo_data **pp;
pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
while (1)
{
edata = backtrace_atomic_load_pointer (pp);
if (edata == NULL)
break;
sym = ((struct elf_symbol *)
bsearch (&addr, edata->symbols, edata->count,
sizeof (struct elf_symbol), elf_symbol_search));
if (sym != NULL)
break;
pp = &edata->next;
}
}
if (sym == NULL)
callback (data, addr, NULL, 0, 0);
else
callback (data, addr, sym->name, sym->address, sym->size);
}
/* Add the backtrace data for one ELF file. Returns 1 on success,
0 on failure (in both cases descriptor is closed) or -1 if exe
is non-zero and the ELF file is ET_DYN, which tells the caller that
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, int exe)
{
struct backtrace_view ehdr_view;
b_elf_ehdr ehdr;
off_t shoff;
unsigned int shnum;
unsigned int shstrndx;
struct backtrace_view shdrs_view;
int shdrs_view_valid;
const b_elf_shdr *shdrs;
const b_elf_shdr *shstrhdr;
size_t shstr_size;
off_t shstr_off;
struct backtrace_view names_view;
int names_view_valid;
const char *names;
unsigned int symtab_shndx;
unsigned int dynsym_shndx;
unsigned int i;
struct debug_section_info sections[DEBUG_MAX];
struct backtrace_view symtab_view;
int symtab_view_valid;
struct backtrace_view strtab_view;
int strtab_view_valid;
off_t min_offset;
off_t max_offset;
struct backtrace_view debug_view;
int debug_view_valid;
*found_sym = 0;
*found_dwarf = 0;
shdrs_view_valid = 0;
names_view_valid = 0;
symtab_view_valid = 0;
strtab_view_valid = 0;
debug_view_valid = 0;
if (!backtrace_get_view (state, descriptor, 0, sizeof ehdr, error_callback,
data, &ehdr_view))
goto fail;
memcpy (&ehdr, ehdr_view.data, sizeof ehdr);
backtrace_release_view (state, &ehdr_view, error_callback, data);
if (ehdr.e_ident[EI_MAG0] != ELFMAG0
|| ehdr.e_ident[EI_MAG1] != ELFMAG1
|| ehdr.e_ident[EI_MAG2] != ELFMAG2
|| ehdr.e_ident[EI_MAG3] != ELFMAG3)
{
error_callback (data, "executable file is not ELF", 0);
goto fail;
}
if (ehdr.e_ident[EI_VERSION] != EV_CURRENT)
{
error_callback (data, "executable file is unrecognized ELF version", 0);
goto fail;
}
#if BACKTRACE_ELF_SIZE == 32
#define BACKTRACE_ELFCLASS ELFCLASS32
#else
#define BACKTRACE_ELFCLASS ELFCLASS64
#endif
if (ehdr.e_ident[EI_CLASS] != BACKTRACE_ELFCLASS)
{
error_callback (data, "executable file is unexpected ELF class", 0);
goto fail;
}
if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB
&& ehdr.e_ident[EI_DATA] != ELFDATA2MSB)
{
error_callback (data, "executable file has unknown endianness", 0);
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;
if ((shnum == 0 || shstrndx == SHN_XINDEX)
&& shoff != 0)
{
struct backtrace_view shdr_view;
const b_elf_shdr *shdr;
if (!backtrace_get_view (state, descriptor, shoff, sizeof shdr,
error_callback, data, &shdr_view))
goto fail;
shdr = (const b_elf_shdr *) shdr_view.data;
if (shnum == 0)
shnum = shdr->sh_size;
if (shstrndx == SHN_XINDEX)
{
shstrndx = shdr->sh_link;
/* Versions of the GNU binutils between 2.12 and 2.18 did
not handle objects with more than SHN_LORESERVE sections
correctly. All large section indexes were offset by
0x100. There is more information at
http://sourceware.org/bugzilla/show_bug.cgi?id-5900 .
Fortunately these object files are easy to detect, as the
GNU binutils always put the section header string table
near the end of the list of sections. Thus if the
section header string table index is larger than the
number of sections, then we know we have to subtract
0x100 to get the real section index. */
if (shstrndx >= shnum && shstrndx >= SHN_LORESERVE + 0x100)
shstrndx -= 0x100;
}
backtrace_release_view (state, &shdr_view, error_callback, data);
}
/* To translate PC to file/line when using DWARF, we need to find
the .debug_info and .debug_line sections. */
/* Read the section headers, skipping the first one. */
if (!backtrace_get_view (state, descriptor, shoff + sizeof (b_elf_shdr),
(shnum - 1) * sizeof (b_elf_shdr),
error_callback, data, &shdrs_view))
goto fail;
shdrs_view_valid = 1;
shdrs = (const b_elf_shdr *) shdrs_view.data;
/* Read the section names. */
shstrhdr = &shdrs[shstrndx - 1];
shstr_size = shstrhdr->sh_size;
shstr_off = shstrhdr->sh_offset;
if (!backtrace_get_view (state, descriptor, shstr_off, shstr_size,
error_callback, data, &names_view))
goto fail;
names_view_valid = 1;
names = (const char *) names_view.data;
symtab_shndx = 0;
dynsym_shndx = 0;
memset (sections, 0, sizeof sections);
/* Look for the symbol table. */
for (i = 1; i < shnum; ++i)
{
const b_elf_shdr *shdr;
unsigned int sh_name;
const char *name;
int j;
shdr = &shdrs[i - 1];
if (shdr->sh_type == SHT_SYMTAB)
symtab_shndx = i;
else if (shdr->sh_type == SHT_DYNSYM)
dynsym_shndx = i;
sh_name = shdr->sh_name;
if (sh_name >= shstr_size)
{
error_callback (data, "ELF section name out of range", 0);
goto fail;
}
name = names + sh_name;
for (j = 0; j < (int) DEBUG_MAX; ++j)
{
if (strcmp (name, debug_section_names[j]) == 0)
{
sections[j].offset = shdr->sh_offset;
sections[j].size = shdr->sh_size;
break;
}
}
}
if (symtab_shndx == 0)
symtab_shndx = dynsym_shndx;
if (symtab_shndx != 0)
{
const b_elf_shdr *symtab_shdr;
unsigned int strtab_shndx;
const b_elf_shdr *strtab_shdr;
struct elf_syminfo_data *sdata;
symtab_shdr = &shdrs[symtab_shndx - 1];
strtab_shndx = symtab_shdr->sh_link;
if (strtab_shndx >= shnum)
{
error_callback (data,
"ELF symbol table strtab link out of range", 0);
goto fail;
}
strtab_shdr = &shdrs[strtab_shndx - 1];
if (!backtrace_get_view (state, descriptor, symtab_shdr->sh_offset,
symtab_shdr->sh_size, error_callback, data,
&symtab_view))
goto fail;
symtab_view_valid = 1;
if (!backtrace_get_view (state, descriptor, strtab_shdr->sh_offset,
strtab_shdr->sh_size, error_callback, data,
&strtab_view))
goto fail;
strtab_view_valid = 1;
sdata = ((struct elf_syminfo_data *)
backtrace_alloc (state, sizeof *sdata, error_callback, data));
if (sdata == NULL)
goto fail;
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))
{
backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
goto fail;
}
/* We no longer need the symbol table, but we hold on to the
string table permanently. */
backtrace_release_view (state, &symtab_view, error_callback, data);
*found_sym = 1;
elf_add_syminfo_data (state, sdata);
}
/* FIXME: Need to handle compressed debug sections. */
backtrace_release_view (state, &shdrs_view, error_callback, data);
shdrs_view_valid = 0;
backtrace_release_view (state, &names_view, error_callback, data);
names_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 = elf_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,
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,
ehdr.e_ident[EI_DATA] == ELFDATA2MSB,
error_callback, data, fileline_fn))
goto fail;
*found_dwarf = 1;
return 1;
fail:
if (shdrs_view_valid)
backtrace_release_view (state, &shdrs_view, error_callback, data);
if (names_view_valid)
backtrace_release_view (state, &names_view, error_callback, data);
if (symtab_view_valid)
backtrace_release_view (state, &symtab_view, error_callback, data);
if (strtab_view_valid)
backtrace_release_view (state, &strtab_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;
}
/* Data passed to phdr_callback. */
struct phdr_data
{
struct backtrace_state *state;
backtrace_error_callback error_callback;
void *data;
fileline *fileline_fn;
int *found_sym;
int *found_dwarf;
int exe_descriptor;
};
/* Callback passed to dl_iterate_phdr. Load debug info from shared
libraries. */
static int
phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
void *pdata)
{
struct phdr_data *pd = (struct phdr_data *) pdata;
int descriptor;
int does_not_exist;
fileline elf_fileline_fn;
int found_dwarf;
/* 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;
}
if (elf_add (pd->state, descriptor, info->dlpi_addr, pd->error_callback,
pd->data, &elf_fileline_fn, pd->found_sym, &found_dwarf, 0))
{
if (found_dwarf)
{
*pd->found_dwarf = 1;
*pd->fileline_fn = elf_fileline_fn;
}
}
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 elf_fileline_fn;
struct phdr_data pd;
ret = elf_add (state, descriptor, 0, error_callback, data, &elf_fileline_fn,
&found_sym, &found_dwarf, 1);
if (!ret)
return 0;
pd.state = state;
pd.error_callback = error_callback;
pd.data = data;
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);
if (!state->threaded)
{
if (found_sym)
state->syminfo_fn = elf_syminfo;
else if (state->syminfo_fn == NULL)
state->syminfo_fn = elf_nosyms;
}
else
{
if (found_sym)
backtrace_atomic_store_pointer (&state->syminfo_fn, elf_syminfo);
else
__sync_bool_compare_and_swap (&state->syminfo_fn, NULL, elf_nosyms);
}
if (!state->threaded)
{
if (state->fileline_fn == NULL || state->fileline_fn == elf_nodebug)
*fileline_fn = elf_fileline_fn;
}
else
{
fileline current_fn;
current_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
if (current_fn == NULL || current_fn == elf_nodebug)
*fileline_fn = elf_fileline_fn;
}
return 1;
}

194
src/libbacktrace/fileline.c Normal file
View File

@ -0,0 +1,194 @@
/* fileline.c -- Get file and line number information in a backtrace.
Copyright (C) 2012-2014 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 <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
#include "backtrace.h"
#include "internal.h"
#ifndef HAVE_GETEXECNAME
#define getexecname() NULL
#endif
/* Initialize the fileline information from the executable. Returns 1
on success, 0 on failure. */
static int
fileline_initialize (struct backtrace_state *state,
backtrace_error_callback error_callback, void *data)
{
int failed;
fileline fileline_fn;
int pass;
int called_error_callback;
int descriptor;
if (!state->threaded)
failed = state->fileline_initialization_failed;
else
failed = backtrace_atomic_load_int (&state->fileline_initialization_failed);
if (failed)
{
error_callback (data, "failed to read executable information", -1);
return 0;
}
if (!state->threaded)
fileline_fn = state->fileline_fn;
else
fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn);
if (fileline_fn != NULL)
return 1;
/* We have not initialized the information. Do it now. */
descriptor = -1;
called_error_callback = 0;
for (pass = 0; pass < 4; ++pass)
{
const char *filename;
int does_not_exist;
switch (pass)
{
case 0:
filename = state->filename;
break;
case 1:
filename = getexecname ();
break;
case 2:
filename = "/proc/self/exe";
break;
case 3:
filename = "/proc/curproc/file";
break;
default:
abort ();
}
if (filename == NULL)
continue;
descriptor = backtrace_open (filename, error_callback, data,
&does_not_exist);
if (descriptor < 0 && !does_not_exist)
{
called_error_callback = 1;
break;
}
if (descriptor >= 0)
break;
}
if (descriptor < 0)
{
if (!called_error_callback)
{
if (state->filename != NULL)
error_callback (data, state->filename, ENOENT);
else
error_callback (data,
"libbacktrace could not find executable to open",
0);
}
failed = 1;
}
if (!failed)
{
if (!backtrace_initialize (state, descriptor, error_callback, data,
&fileline_fn))
failed = 1;
}
if (failed)
{
if (!state->threaded)
state->fileline_initialization_failed = 1;
else
backtrace_atomic_store_int (&state->fileline_initialization_failed, 1);
return 0;
}
if (!state->threaded)
state->fileline_fn = fileline_fn;
else
{
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;
}
/* Given a PC, find the file name, line number, and function name. */
int
backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc,
backtrace_full_callback callback,
backtrace_error_callback error_callback, void *data)
{
if (!fileline_initialize (state, error_callback, data))
return 0;
if (state->fileline_initialization_failed)
return 0;
return state->fileline_fn (state, pc, callback, error_callback, data);
}
/* Given a PC, find the symbol for it, and its value. */
int
backtrace_syminfo (struct backtrace_state *state, uintptr_t pc,
backtrace_syminfo_callback callback,
backtrace_error_callback error_callback, void *data)
{
if (!fileline_initialize (state, error_callback, data))
return 0;
if (state->fileline_initialization_failed)
return 0;
state->syminfo_fn (state, pc, callback, error_callback, data);
return 1;
}

View File

@ -0,0 +1,97 @@
/* Macros for taking apart, interpreting and processing file names.
These are here because some non-Posix (a.k.a. DOSish) systems have
drive letter brain-damage at the beginning of an absolute file name,
use forward- and back-slash in path names interchangeably, and
some of them have case-insensitive file names.
Copyright 2000, 2001, 2007, 2010 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
#ifndef FILENAMES_H
#define FILENAMES_H
#include "hashtab.h" /* for hashval_t */
#ifdef __cplusplus
extern "C" {
#endif
#if defined(__MSDOS__) || defined(_WIN32) || defined(__OS2__) || defined (__CYGWIN__)
# ifndef HAVE_DOS_BASED_FILE_SYSTEM
# define HAVE_DOS_BASED_FILE_SYSTEM 1
# endif
# ifndef HAVE_CASE_INSENSITIVE_FILE_SYSTEM
# define HAVE_CASE_INSENSITIVE_FILE_SYSTEM 1
# endif
# define HAS_DRIVE_SPEC(f) HAS_DOS_DRIVE_SPEC (f)
# define IS_DIR_SEPARATOR(c) IS_DOS_DIR_SEPARATOR (c)
# define IS_ABSOLUTE_PATH(f) IS_DOS_ABSOLUTE_PATH (f)
#else /* not DOSish */
# if defined(__APPLE__)
# ifndef HAVE_CASE_INSENSITIVE_FILE_SYSTEM
# define HAVE_CASE_INSENSITIVE_FILE_SYSTEM 1
# endif
# endif /* __APPLE__ */
# define HAS_DRIVE_SPEC(f) (0)
# define IS_DIR_SEPARATOR(c) IS_UNIX_DIR_SEPARATOR (c)
# define IS_ABSOLUTE_PATH(f) IS_UNIX_ABSOLUTE_PATH (f)
#endif
#define IS_DIR_SEPARATOR_1(dos_based, c) \
(((c) == '/') \
|| (((c) == '\\') && (dos_based)))
#define HAS_DRIVE_SPEC_1(dos_based, f) \
((f)[0] && ((f)[1] == ':') && (dos_based))
/* Remove the drive spec from F, assuming HAS_DRIVE_SPEC (f).
The result is a pointer to the remainder of F. */
#define STRIP_DRIVE_SPEC(f) ((f) + 2)
#define IS_DOS_DIR_SEPARATOR(c) IS_DIR_SEPARATOR_1 (1, c)
#define IS_DOS_ABSOLUTE_PATH(f) IS_ABSOLUTE_PATH_1 (1, f)
#define HAS_DOS_DRIVE_SPEC(f) HAS_DRIVE_SPEC_1 (1, f)
#define IS_UNIX_DIR_SEPARATOR(c) IS_DIR_SEPARATOR_1 (0, c)
#define IS_UNIX_ABSOLUTE_PATH(f) IS_ABSOLUTE_PATH_1 (0, f)
/* Note that when DOS_BASED is true, IS_ABSOLUTE_PATH accepts d:foo as
well, although it is only semi-absolute. This is because the users
of IS_ABSOLUTE_PATH want to know whether to prepend the current
working directory to a file name, which should not be done with a
name like d:foo. */
#define IS_ABSOLUTE_PATH_1(dos_based, f) \
(IS_DIR_SEPARATOR_1 (dos_based, (f)[0]) \
|| HAS_DRIVE_SPEC_1 (dos_based, f))
extern int filename_cmp (const char *s1, const char *s2);
#define FILENAME_CMP(s1, s2) filename_cmp(s1, s2)
extern int filename_ncmp (const char *s1, const char *s2,
size_t n);
extern hashval_t filename_hash (const void *s);
extern int filename_eq (const void *s1, const void *s2);
#ifdef __cplusplus
}
#endif
#endif /* FILENAMES_H */

View File

@ -0,0 +1,3 @@
# An awk script to determine the type of a file.
/\177ELF\001/ { if (NR == 1) { print "elf32"; exit } }
/\177ELF\002/ { if (NR == 1) { print "elf64"; exit } }

View File

@ -0,0 +1,47 @@
/* generated for gcc (GCC) 4.8.2 20140206 (prerelease) */
#ifndef GCC_GENERATED_STDINT_H
#define GCC_GENERATED_STDINT_H 1
#include <sys/types.h>
#include <stdint.h>
/* glibc uses these symbols as guards to prevent redefinitions. */
#ifdef __int8_t_defined
#define _INT8_T
#define _INT16_T
#define _INT32_T
#endif
#ifdef __uint32_t_defined
#define _UINT32_T
#endif
/* Some systems have guard macros to prevent redefinitions, define them. */
#ifndef _INT8_T
#define _INT8_T
#endif
#ifndef _INT16_T
#define _INT16_T
#endif
#ifndef _INT32_T
#define _INT32_T
#endif
#ifndef _UINT8_T
#define _UINT8_T
#endif
#ifndef _UINT16_T
#define _UINT16_T
#endif
#ifndef _UINT32_T
#define _UINT32_T
#endif
/* system headers have good uint64_t and int64_t */
#ifndef _INT64_T
#define _INT64_T
#endif
#ifndef _UINT64_T
#define _UINT64_T
#endif
#endif /* GCC_GENERATED_STDINT_H */

209
src/libbacktrace/hashtab.h Normal file
View File

@ -0,0 +1,209 @@
/* An expandable hash tables datatype.
Copyright (C) 1999, 2000, 2002, 2003, 2004, 2005, 2009, 2010
Free Software Foundation, Inc.
Contributed by Vladimir Makarov (vmakarov@cygnus.com).
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA. */
/* This package implements basic hash table functionality. It is possible
to search for an entry, create an entry and destroy an entry.
Elements in the table are generic pointers.
The size of the table is not fixed; if the occupancy of the table
grows too high the hash table will be expanded.
The abstract data implementation is based on generalized Algorithm D
from Knuth's book "The art of computer programming". Hash table is
expanded by creation of new hash table and transferring elements from
the old table to the new table. */
#ifndef __HASHTAB_H__
#define __HASHTAB_H__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
#include "ansidecl.h"
#ifndef GTY
#define GTY(X)
#endif
/* The type for a hash code. */
typedef unsigned int hashval_t;
/* Callback function pointer types. */
/* Calculate hash of a table entry. */
typedef hashval_t (*htab_hash) (const void *);
/* Compare a table entry with a possible entry. The entry already in
the table always comes first, so the second element can be of a
different type (but in this case htab_find and htab_find_slot
cannot be used; instead the variants that accept a hash value
must be used). */
typedef int (*htab_eq) (const void *, const void *);
/* Cleanup function called whenever a live element is removed from
the hash table. */
typedef void (*htab_del) (void *);
/* Function called by htab_traverse for each live element. The first
arg is the slot of the element (which can be passed to htab_clear_slot
if desired), the second arg is the auxiliary pointer handed to
htab_traverse. Return 1 to continue scan, 0 to stop. */
typedef int (*htab_trav) (void **, void *);
/* Memory-allocation function, with the same functionality as calloc().
Iff it returns NULL, the hash table implementation will pass an error
code back to the user, so if your code doesn't handle errors,
best if you use xcalloc instead. */
typedef void *(*htab_alloc) (size_t, size_t);
/* We also need a free() routine. */
typedef void (*htab_free) (void *);
/* Memory allocation and deallocation; variants which take an extra
argument. */
typedef void *(*htab_alloc_with_arg) (void *, size_t, size_t);
typedef void (*htab_free_with_arg) (void *, void *);
/* This macro defines reserved value for empty table entry. */
#define HTAB_EMPTY_ENTRY ((PTR) 0)
/* This macro defines reserved value for table entry which contained
a deleted element. */
#define HTAB_DELETED_ENTRY ((PTR) 1)
/* Hash tables are of the following type. The structure
(implementation) of this type is not needed for using the hash
tables. All work with hash table should be executed only through
functions mentioned below. The size of this structure is subject to
change. */
struct GTY(()) htab {
/* Pointer to hash function. */
htab_hash hash_f;
/* Pointer to comparison function. */
htab_eq eq_f;
/* Pointer to cleanup function. */
htab_del del_f;
/* Table itself. */
void ** GTY ((use_param, length ("%h.size"))) entries;
/* Current size (in entries) of the hash table. */
size_t size;
/* Current number of elements including also deleted elements. */
size_t n_elements;
/* Current number of deleted elements in the table. */
size_t n_deleted;
/* The following member is used for debugging. Its value is number
of all calls of `htab_find_slot' for the hash table. */
unsigned int searches;
/* The following member is used for debugging. Its value is number
of collisions fixed for time of work with the hash table. */
unsigned int collisions;
/* Pointers to allocate/free functions. */
htab_alloc alloc_f;
htab_free free_f;
/* Alternate allocate/free functions, which take an extra argument. */
void * GTY((skip)) alloc_arg;
htab_alloc_with_arg alloc_with_arg_f;
htab_free_with_arg free_with_arg_f;
/* Current size (in entries) of the hash table, as an index into the
table of primes. */
unsigned int size_prime_index;
};
typedef struct htab *htab_t;
/* An enum saying whether we insert into the hash table or not. */
enum insert_option {NO_INSERT, INSERT};
/* The prototypes of the package functions. */
extern htab_t htab_create_alloc (size_t, htab_hash,
htab_eq, htab_del,
htab_alloc, htab_free);
extern htab_t htab_create_alloc_ex (size_t, htab_hash,
htab_eq, htab_del,
void *, htab_alloc_with_arg,
htab_free_with_arg);
extern htab_t htab_create_typed_alloc (size_t, htab_hash, htab_eq, htab_del,
htab_alloc, htab_alloc, htab_free);
/* Backward-compatibility functions. */
extern htab_t htab_create (size_t, htab_hash, htab_eq, htab_del);
extern htab_t htab_try_create (size_t, htab_hash, htab_eq, htab_del);
extern void htab_set_functions_ex (htab_t, htab_hash,
htab_eq, htab_del,
void *, htab_alloc_with_arg,
htab_free_with_arg);
extern void htab_delete (htab_t);
extern void htab_empty (htab_t);
extern void * htab_find (htab_t, const void *);
extern void ** htab_find_slot (htab_t, const void *, enum insert_option);
extern void * htab_find_with_hash (htab_t, const void *, hashval_t);
extern void ** htab_find_slot_with_hash (htab_t, const void *,
hashval_t, enum insert_option);
extern void htab_clear_slot (htab_t, void **);
extern void htab_remove_elt (htab_t, void *);
extern void htab_remove_elt_with_hash (htab_t, void *, hashval_t);
extern void htab_traverse (htab_t, htab_trav, void *);
extern void htab_traverse_noresize (htab_t, htab_trav, void *);
extern size_t htab_size (htab_t);
extern size_t htab_elements (htab_t);
extern double htab_collisions (htab_t);
/* A hash function for pointers. */
extern htab_hash htab_hash_pointer;
/* An equality function for pointers. */
extern htab_eq htab_eq_pointer;
/* A hash function for null-terminated strings. */
extern hashval_t htab_hash_string (const void *);
/* An iterative hash function for arbitrary data. */
extern hashval_t iterative_hash (const void *, size_t, hashval_t);
/* Shorthand for hashing something with an intrinsic size. */
#define iterative_hash_object(OB,INIT) iterative_hash (&OB, sizeof (OB), INIT)
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __HASHTAB_H */

520
src/libbacktrace/install-sh Executable file
View File

@ -0,0 +1,520 @@
#!/bin/sh
# install - install a program, script, or datafile
scriptversion=2009-04-28.21; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# `make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
nl='
'
IFS=" "" $nl"
# set DOITPROG to echo to test this script
# Don't use :- since 4.3BSD and earlier shells don't like it.
doit=${DOITPROG-}
if test -z "$doit"; then
doit_exec=exec
else
doit_exec=$doit
fi
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_glob='?'
initialize_posix_glob='
test "$posix_glob" != "?" || {
if (set -f) 2>/dev/null; then
posix_glob=
else
posix_glob=:
fi
}
'
posix_mkdir=
# Desired mode of installed file.
mode=0755
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
no_target_directory=
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve the last data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-s $stripprog installed files.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *' '* | *'
'* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-s) stripcmd=$stripprog;;
-t) dst_arg=$2
shift;;
-T) no_target_directory=true;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call `install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
trap '(exit $?); exit' 1 2 13 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names starting with `-'.
case $src in
-*) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# Protect names starting with `-'.
case $dst in
-*) dst=./$dst;;
esac
# If destination is a directory, append the input filename; won't work
# if double slashes aren't ignored.
if test -d "$dst"; then
if test -n "$no_target_directory"; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dst=$dstdir/`basename "$src"`
dstdir_status=0
else
# Prefer dirname, but fall back on a substitute if dirname fails.
dstdir=`
(dirname "$dst") 2>/dev/null ||
expr X"$dst" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
X"$dst" : 'X\(//\)[^/]' \| \
X"$dst" : 'X\(//\)$' \| \
X"$dst" : 'X\(/\)' \| . 2>/dev/null ||
echo X"$dst" |
sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
s//\1/
q
}
/^X\(\/\/\)[^/].*/{
s//\1/
q
}
/^X\(\/\/\)$/{
s//\1/
q
}
/^X\(\/\).*/{
s//\1/
q
}
s/.*/./; q'
`
test -d "$dstdir"
dstdir_status=$?
fi
fi
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# Create intermediate dirs using mode 755 as modified by the umask.
# This is like FreeBSD 'install' as of 1997-10-28.
umask=`umask`
case $stripcmd.$umask in
# Optimize common cases.
*[2367][2367]) mkdir_umask=$umask;;
.*0[02][02] | .[02][02] | .[02]) mkdir_umask=22;;
*[0-7])
mkdir_umask=`expr $umask + 22 \
- $umask % 100 % 40 + $umask % 20 \
- $umask % 10 % 4 + $umask % 2
`;;
*) mkdir_umask=$umask,go-w;;
esac
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
case $umask in
*[123567][0-7][0-7])
# POSIX mkdir -p sets u+wx bits regardless of umask, which
# is incompatible with FreeBSD 'install' when (umask & 300) != 0.
;;
*)
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap 'ret=$?; rmdir "$tmpdir/d" "$tmpdir" 2>/dev/null; exit $ret' 0
if (umask $mkdir_umask &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/d") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writeable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
ls_ld_tmpdir=`ls -ld "$tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/d" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- 2>/dev/null
fi
trap '' 0;;
esac;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# The umask is ridiculous, or mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
-*) prefix='./';;
*) prefix='';;
esac
eval "$initialize_posix_glob"
oIFS=$IFS
IFS=/
$posix_glob set -f
set fnord $dstdir
shift
$posix_glob set +f
IFS=$oIFS
prefixes=
for d
do
test -z "$d" && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask=$mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=$dstdir/_inst.$$_
rmtmp=$dstdir/_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask && $doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
eval "$initialize_posix_glob" &&
$posix_glob set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
$posix_glob set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd -f "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd -f "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'write-file-hooks 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC"
# time-stamp-end: "; # UTC"
# End:

287
src/libbacktrace/internal.h Normal file
View File

@ -0,0 +1,287 @@
/* internal.h -- Internal header file for stack backtrace library.
Copyright (C) 2012-2014 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
(1) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
(2) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
(3) The name of the author may not be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
#ifndef BACKTRACE_INTERNAL_H
#define BACKTRACE_INTERNAL_H
/* We assume that <sys/types.h> and "backtrace.h" have already been
included. */
#ifndef GCC_VERSION
# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
#endif
#if (GCC_VERSION < 2007)
# define __attribute__(x)
#endif
#ifndef ATTRIBUTE_UNUSED
# define ATTRIBUTE_UNUSED __attribute__ ((__unused__))
#endif
#ifndef ATTRIBUTE_MALLOC
# if (GCC_VERSION >= 2096)
# define ATTRIBUTE_MALLOC __attribute__ ((__malloc__))
# else
# define ATTRIBUTE_MALLOC
# endif
#endif
#ifndef HAVE_SYNC_FUNCTIONS
/* Define out the sync functions. These should never be called if
they are not available. */
#define __sync_bool_compare_and_swap(A, B, C) (abort(), 1)
#define __sync_lock_test_and_set(A, B) (abort(), 0)
#define __sync_lock_release(A) abort()
#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(), 0)
#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. */
typedef int (*fileline) (struct backtrace_state *state, uintptr_t pc,
backtrace_full_callback callback,
backtrace_error_callback error_callback, void *data);
/* The type of the function that collects symbol information. This is
like backtrace_syminfo. */
typedef void (*syminfo) (struct backtrace_state *state, uintptr_t pc,
backtrace_syminfo_callback callback,
backtrace_error_callback error_callback, void *data);
/* What the backtrace state pointer points to. */
struct backtrace_state
{
/* The name of the executable. */
const char *filename;
/* Non-zero if threaded. */
int threaded;
/* The master lock for fileline_fn, fileline_data, syminfo_fn,
syminfo_data, fileline_initialization_failed and everything the
data pointers point to. */
void *lock;
/* The function that returns file/line information. */
fileline fileline_fn;
/* The data to pass to FILELINE_FN. */
void *fileline_data;
/* The function that returns symbol information. */
syminfo syminfo_fn;
/* The data to pass to SYMINFO_FN. */
void *syminfo_data;
/* Whether initializing the file/line information failed. */
int fileline_initialization_failed;
/* The lock for the freelist. */
int lock_alloc;
/* The freelist when using mmap. */
struct backtrace_freelist_struct *freelist;
};
/* Open a file for reading. Returns -1 on error. If DOES_NOT_EXIST
is not NULL, *DOES_NOT_EXIST will be set to 0 normally and set to 1
if the file does not exist. If the file does not exist and
DOES_NOT_EXIST is not NULL, the function will return -1 and will
not call ERROR_CALLBACK. On other errors, or if DOES_NOT_EXIST is
NULL, the function will call ERROR_CALLBACK before returning. */
extern int backtrace_open (const char *filename,
backtrace_error_callback error_callback,
void *data,
int *does_not_exist);
/* A view of the contents of a file. This supports mmap when
available. A view will remain in memory even after backtrace_close
is called on the file descriptor from which the view was
obtained. */
struct backtrace_view
{
/* The data that the caller requested. */
const void *data;
/* The base of the view. */
void *base;
/* The total length of the view. */
size_t len;
};
/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. Store the
result in *VIEW. Returns 1 on success, 0 on error. */
extern int backtrace_get_view (struct backtrace_state *state, int descriptor,
off_t offset, size_t size,
backtrace_error_callback error_callback,
void *data, struct backtrace_view *view);
/* Release a view created by backtrace_get_view. */
extern void backtrace_release_view (struct backtrace_state *state,
struct backtrace_view *view,
backtrace_error_callback error_callback,
void *data);
/* Close a file opened by backtrace_open. Returns 1 on success, 0 on
error. */
extern int backtrace_close (int descriptor,
backtrace_error_callback error_callback,
void *data);
/* Allocate memory. This is like malloc. */
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. */
extern void backtrace_free (struct backtrace_state *state, void *mem,
size_t size,
backtrace_error_callback error_callback,
void *data);
/* A growable vector of some struct. This is used for more efficient
allocation when we don't know the final size of some group of data
that we want to represent as an array. */
struct backtrace_vector
{
/* The base of the vector. */
void *base;
/* The number of bytes in the vector. */
size_t size;
/* The number of bytes available at the current allocation. */
size_t alc;
};
/* Grow VEC by SIZE bytes. Return a pointer to the newly allocated
bytes. Note that this may move the entire vector to a new memory
location. Returns NULL on failure. */
extern void *backtrace_vector_grow (struct backtrace_state *state, size_t size,
backtrace_error_callback error_callback,
void *data,
struct backtrace_vector *vec);
/* Finish the current allocation on VEC. Prepare to start a new
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,
backtrace_error_callback error_callback,
void *data);
/* 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,
backtrace_error_callback error_callback,
void *data);
/* Read initial debug data from a descriptor, and set the
fileline_data, syminfo_fn, and syminfo_data fields of STATE.
Return the fileln_fn field in *FILELN_FN--this is done this way so
that the synchronization code is only implemented once. This is
called after the descriptor has first been opened. It will close
the descriptor if it is no longer needed. Returns 1 on success, 0
on error. There will be multiple implementations of this function,
for different file formats. Each system will compile the
appropriate one. */
extern int backtrace_initialize (struct backtrace_state *state,
int descriptor,
backtrace_error_callback error_callback,
void *data,
fileline *fileline_fn);
/* Add file/line information for a DWARF module. */
extern int backtrace_dwarf_add (struct backtrace_state *state,
uintptr_t base_address,
const unsigned char* dwarf_info,
size_t dwarf_info_size,
const unsigned char *dwarf_line,
size_t dwarf_line_size,
const unsigned char *dwarf_abbrev,
size_t dwarf_abbrev_size,
const unsigned char *dwarf_ranges,
size_t dwarf_range_size,
const unsigned char *dwarf_str,
size_t dwarf_str_size,
int is_bigendian,
backtrace_error_callback error_callback,
void *data, fileline *fileline_fn);
#endif

8636
src/libbacktrace/ltmain.sh Normal file

File diff suppressed because it is too large Load Diff

271
src/libbacktrace/mmap.c Normal file
View File

@ -0,0 +1,271 @@
/* mmap.c -- Memory allocation with mmap.
Copyright (C) 2012-2014 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
(1) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
(2) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
(3) The name of the author may not be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
#include "config.h"
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/mman.h>
#include "backtrace.h"
#include "internal.h"
/* Memory allocation on systems that provide anonymous mmap. This
permits the backtrace functions to be invoked from a signal
handler, assuming that mmap is async-signal safe. */
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
/* A list of free memory blocks. */
struct backtrace_freelist_struct
{
/* Next on list. */
struct backtrace_freelist_struct *next;
/* Size of this block, including this structure. */
size_t size;
};
/* Free memory allocated by backtrace_alloc. */
static void
backtrace_free_locked (struct backtrace_state *state, void *addr, size_t size)
{
/* Just leak small blocks. We don't have to be perfect. */
if (size >= sizeof (struct backtrace_freelist_struct))
{
struct backtrace_freelist_struct *p;
p = (struct backtrace_freelist_struct *) addr;
p->next = state->freelist;
p->size = size;
state->freelist = p;
}
}
/* Allocate memory like malloc. */
void *
backtrace_alloc (struct backtrace_state *state,
size_t size, backtrace_error_callback error_callback,
void *data)
{
void *ret;
int locked;
struct backtrace_freelist_struct **pp;
size_t pagesize;
size_t asksize;
void *page;
ret = NULL;
/* If we can acquire the lock, then see if there is space on the
free list. If we can't acquire the lock, drop straight into
using mmap. __sync_lock_test_and_set returns the old state of
the lock, so we have acquired it if it returns 0. */
if (!state->threaded)
locked = 1;
else
locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0;
if (locked)
{
for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next)
{
if ((*pp)->size >= size)
{
struct backtrace_freelist_struct *p;
p = *pp;
*pp = p->next;
/* Round for alignment; we assume that no type we care about
is more than 8 bytes. */
size = (size + 7) & ~ (size_t) 7;
if (size < p->size)
backtrace_free_locked (state, (char *) p + size,
p->size - size);
ret = (void *) p;
break;
}
}
if (state->threaded)
__sync_lock_release (&state->lock_alloc);
}
if (ret == NULL)
{
/* Allocate a new page. */
pagesize = getpagesize ();
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);
else
{
size = (size + 7) & ~ (size_t) 7;
if (size < asksize)
backtrace_free (state, (char *) page + size, asksize - size,
error_callback, data);
ret = page;
}
}
return ret;
}
/* Free memory allocated by backtrace_alloc. */
void
backtrace_free (struct backtrace_state *state, void *addr, size_t size,
backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
void *data ATTRIBUTE_UNUSED)
{
int locked;
/* 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
have acquired it if it returns 0. */
if (!state->threaded)
locked = 1;
else
locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0;
if (locked)
{
backtrace_free_locked (state, addr, size);
if (state->threaded)
__sync_lock_release (&state->lock_alloc);
}
}
/* Grow VEC by SIZE bytes. */
void *
backtrace_vector_grow (struct backtrace_state *state,size_t size,
backtrace_error_callback error_callback,
void *data, struct backtrace_vector *vec)
{
void *ret;
if (size > vec->alc)
{
size_t pagesize;
size_t alc;
void *base;
pagesize = getpagesize ();
alc = vec->size + size;
if (vec->size == 0)
alc = 16 * size;
else if (alc < pagesize)
{
alc *= 2;
if (alc > pagesize)
alc = pagesize;
}
else
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);
}
vec->base = base;
vec->alc = alc - vec->size;
}
ret = (char *) vec->base + vec->size;
vec->size += size;
vec->alc -= size;
return ret;
}
/* Finish the current allocation on 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. */
int
backtrace_vector_release (struct backtrace_state *state,
struct backtrace_vector *vec,
backtrace_error_callback error_callback,
void *data)
{
size_t size;
size_t alc;
size_t aligned;
/* Make sure that the block that we free is aligned on an 8-byte
boundary. */
size = vec->size;
alc = vec->alc;
aligned = (size + 7) & ~ (size_t) 7;
alc -= aligned - size;
backtrace_free (state, (char *) vec->base + aligned, alc,
error_callback, data);
vec->alc = 0;
return 1;
}

100
src/libbacktrace/mmapio.c Normal file
View File

@ -0,0 +1,100 @@
/* mmapio.c -- File views using mmap.
Copyright (C) 2012-2014 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
(1) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
(2) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
(3) The name of the author may not be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
#include "config.h"
#include <errno.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
#include "backtrace.h"
#include "internal.h"
#ifndef MAP_FAILED
#define MAP_FAILED ((void *)-1)
#endif
/* This file implements file views and memory allocation when mmap is
available. */
/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. */
int
backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
int descriptor, off_t offset, size_t size,
backtrace_error_callback error_callback,
void *data, struct backtrace_view *view)
{
size_t pagesize;
unsigned int inpage;
off_t pageoff;
void *map;
pagesize = getpagesize ();
inpage = offset % pagesize;
pageoff = offset - inpage;
size += inpage;
size = (size + (pagesize - 1)) & ~ (pagesize - 1);
map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff);
if (map == MAP_FAILED)
{
error_callback (data, "mmap", errno);
return 0;
}
view->data = (char *) map + inpage;
view->base = map;
view->len = size;
return 1;
}
/* Release a view read by backtrace_get_view. */
void
backtrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED,
struct backtrace_view *view,
backtrace_error_callback error_callback,
void *data)
{
union {
const void *cv;
void *v;
} const_cast;
const_cast.cv = view->base;
if (munmap (const_cast.v, view->len) < 0)
error_callback (data, "munmap", errno);
}

View File

@ -0,0 +1,66 @@
/* backtrace.c -- Entry point for stack backtrace library.
Copyright (C) 2012-2014 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 "internal.h"
/* This source file is compiled if the unwind library is not
available. */
int
backtrace_full (struct backtrace_state *state ATTRIBUTE_UNUSED,
int skip ATTRIBUTE_UNUSED,
backtrace_full_callback callback ATTRIBUTE_UNUSED,
backtrace_error_callback error_callback, void *data)
{
error_callback (data,
"no stack trace because unwind library not available",
0);
return 0;
}
int
backtrace_simple (struct backtrace_state *state ATTRIBUTE_UNUSED,
int skip ATTRIBUTE_UNUSED,
backtrace_simple_callback callback ATTRIBUTE_UNUSED,
backtrace_error_callback error_callback, void *data)
{
error_callback (data,
"no stack trace because unwind library not available",
0);
return 0;
}

100
src/libbacktrace/posix.c Normal file
View File

@ -0,0 +1,100 @@
/* posix.c -- POSIX file I/O routines for the backtrace library.
Copyright (C) 2012-2014 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
(1) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
(2) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
(3) The name of the author may not be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
#include "config.h"
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "backtrace.h"
#include "internal.h"
#ifndef O_BINARY
#define O_BINARY 0
#endif
#ifndef O_CLOEXEC
#define O_CLOEXEC 0
#endif
#ifndef FD_CLOEXEC
#define FD_CLOEXEC 1
#endif
/* Open a file for reading. */
int
backtrace_open (const char *filename, backtrace_error_callback error_callback,
void *data, int *does_not_exist)
{
int descriptor;
if (does_not_exist != NULL)
*does_not_exist = 0;
descriptor = open (filename, O_RDONLY | O_BINARY | O_CLOEXEC);
if (descriptor < 0)
{
if (does_not_exist != NULL && errno == ENOENT)
*does_not_exist = 1;
else
error_callback (data, filename, errno);
return -1;
}
#ifdef HAVE_FCNTL
/* Set FD_CLOEXEC just in case the kernel does not support
O_CLOEXEC. It doesn't matter if this fails for some reason.
FIXME: At some point it should be safe to only do this if
O_CLOEXEC == 0. */
fcntl (descriptor, F_SETFD, FD_CLOEXEC);
#endif
return descriptor;
}
/* Close DESCRIPTOR. */
int
backtrace_close (int descriptor, backtrace_error_callback error_callback,
void *data)
{
if (close (descriptor) < 0)
{
error_callback (data, "close", errno);
return 0;
}
return 1;
}

92
src/libbacktrace/print.c Normal file
View File

@ -0,0 +1,92 @@
/* print.c -- Print the current backtrace.
Copyright (C) 2012-2014 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 <string.h>
#include <sys/types.h>
#include "backtrace.h"
#include "internal.h"
/* Passed to callbacks. */
struct print_data
{
struct backtrace_state *state;
FILE *f;
};
/* Print one level of a backtrace. */
static int
print_callback (void *data, uintptr_t pc, const char *filename, int lineno,
const char *function)
{
struct print_data *pdata = (struct print_data *) data;
fprintf (pdata->f, "0x%lx %s\n\t%s:%d\n",
(unsigned long) pc,
function == NULL ? "???" : function,
filename == NULL ? "???" : filename,
lineno);
return 0;
}
/* Print errors to stderr. */
static void
error_callback (void *data, const char *msg, int errnum)
{
struct print_data *pdata = (struct print_data *) data;
if (pdata->state->filename != NULL)
fprintf (stderr, "%s: ", pdata->state->filename);
fprintf (stderr, "libbacktrace: %s", msg);
if (errnum > 0)
fprintf (stderr, ": %s", strerror (errnum));
fputc ('\n', stderr);
}
/* Print a backtrace. */
void
backtrace_print (struct backtrace_state *state, int skip, FILE *f)
{
struct print_data data;
data.state = state;
data.f = f;
backtrace_full (state, skip + 1, print_callback, error_callback,
(void *) &data);
}

96
src/libbacktrace/read.c Normal file
View File

@ -0,0 +1,96 @@
/* read.c -- File views without mmap.
Copyright (C) 2012-2014 Free Software Foundation, Inc.
Written by Ian Lance Taylor, Google.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
(1) Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
(2) Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in
the documentation and/or other materials provided with the
distribution.
(3) The name of the author may not be used to
endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. */
#include "config.h"
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
#include "backtrace.h"
#include "internal.h"
/* This file implements file views when mmap is not available. */
/* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. */
int
backtrace_get_view (struct backtrace_state *state, int descriptor,
off_t offset, size_t size,
backtrace_error_callback error_callback,
void *data, struct backtrace_view *view)
{
ssize_t got;
if (lseek (descriptor, offset, SEEK_SET) < 0)
{
error_callback (data, "lseek", errno);
return 0;
}
view->base = backtrace_alloc (state, size, error_callback, data);
if (view->base == NULL)
return 0;
view->data = view->base;
view->len = size;
got = read (descriptor, view->base, size);
if (got < 0)
{
error_callback (data, "read", errno);
free (view->base);
return 0;
}
if ((size_t) got < size)
{
error_callback (data, "file too short", 0);
free (view->base);
return 0;
}
return 1;
}
/* Release a view read by backtrace_get_view. */
void
backtrace_release_view (struct backtrace_state *state,
struct backtrace_view *view,
backtrace_error_callback error_callback,
void *data)
{
backtrace_free (state, view->base, view->len, error_callback, data);
view->data = NULL;
view->base = NULL;
}

108
src/libbacktrace/simple.c Normal file
View File

@ -0,0 +1,108 @@
/* simple.c -- The backtrace_simple function.
Copyright (C) 2012-2014 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 "unwind.h"
#include "backtrace.h"
/* The simple_backtrace routine. */
/* Data passed through _Unwind_Backtrace. */
struct backtrace_simple_data
{
/* Number of frames to skip. */
int skip;
/* Library state. */
struct backtrace_state *state;
/* Callback routine. */
backtrace_simple_callback callback;
/* Error callback routine. */
backtrace_error_callback error_callback;
/* Data to pass to callback routine. */
void *data;
/* Value to return from backtrace. */
int ret;
};
/* Unwind library callback routine. This is passd to
_Unwind_Backtrace. */
static _Unwind_Reason_Code
simple_unwind (struct _Unwind_Context *context, void *vdata)
{
struct backtrace_simple_data *bdata = (struct backtrace_simple_data *) vdata;
uintptr_t pc;
int ip_before_insn = 0;
#ifdef HAVE_GETIPINFO
pc = _Unwind_GetIPInfo (context, &ip_before_insn);
#else
pc = _Unwind_GetIP (context);
#endif
if (bdata->skip > 0)
{
--bdata->skip;
return _URC_NO_REASON;
}
if (!ip_before_insn)
--pc;
bdata->ret = bdata->callback (bdata->data, pc);
if (bdata->ret != 0)
return _URC_END_OF_STACK;
return _URC_NO_REASON;
}
/* Get a simple stack backtrace. */
int
backtrace_simple (struct backtrace_state *state, int skip,
backtrace_simple_callback callback,
backtrace_error_callback error_callback, void *data)
{
struct backtrace_simple_data bdata;
bdata.skip = skip + 1;
bdata.state = state;
bdata.callback = callback;
bdata.error_callback = error_callback;
bdata.data = data;
bdata.ret = 0;
_Unwind_Backtrace (simple_unwind, &bdata);
return bdata.ret;
}

72
src/libbacktrace/state.c Normal file
View File

@ -0,0 +1,72 @@
/* state.c -- Create the backtrace state.
Copyright (C) 2012-2014 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 <string.h>
#include <sys/types.h>
#include "backtrace.h"
#include "backtrace-supported.h"
#include "internal.h"
/* Create the backtrace state. This will then be passed to all the
other routines. */
struct backtrace_state *
backtrace_create_state (const char *filename, int threaded,
backtrace_error_callback error_callback,
void *data)
{
struct backtrace_state init_state;
struct backtrace_state *state;
#ifndef HAVE_SYNC_FUNCTIONS
if (threaded)
{
error_callback (data, "backtrace library does not support threads", 0);
return NULL;
}
#endif
memset (&init_state, 0, sizeof init_state);
init_state.filename = filename;
init_state.threaded = threaded;
state = ((struct backtrace_state *)
backtrace_alloc (&init_state, sizeof *state, error_callback, data));
if (state == NULL)
return NULL;
*state = init_state;
return state;
}

View File

@ -0,0 +1,64 @@
/* unknown.c -- used when backtrace configury does not know file format.
Copyright (C) 2012-2014 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 "internal.h"
/* A trivial routine that always fails to find fileline data. */
static int
unknown_fileline (struct backtrace_state *state ATTRIBUTE_UNUSED,
uintptr_t pc, backtrace_full_callback callback,
backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
void *data)
{
return callback (data, pc, NULL, 0, NULL);
}
/* Initialize the backtrace data when we don't know how to read the
debug info. */
int
backtrace_initialize (struct backtrace_state *state ATTRIBUTE_UNUSED,
int descriptor ATTRIBUTE_UNUSED,
backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
void *data ATTRIBUTE_UNUSED, fileline *fileline_fn)
{
state->fileline_data = NULL;
*fileline_fn = unknown_fileline;
return 1;
}

714
src/libstd/rt/backtrace.rs Normal file
View File

@ -0,0 +1,714 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[allow(non_camel_case_types)];
use char::Char;
use container::Container;
use from_str::from_str;
use io::{IoResult, Writer};
use iter::Iterator;
use option::{Some, None};
use result::{Ok, Err};
use str::StrSlice;
pub use self::imp::write;
// This function is defined in this module so that the way to enable logging of
// backtraces has the word 'backtrace' in it: std::rt::backtrace.
pub fn log_enabled() -> bool {
log_enabled!(::logging::DEBUG)
}
#[cfg(target_word_size = "64")] static HEX_WIDTH: uint = 18;
#[cfg(target_word_size = "32")] static HEX_WIDTH: uint = 10;
// All rust symbols are in theory lists of "::"-separated identifiers. Some
// assemblers, however, can't handle these characters in symbol names. To get
// around this, we use C++-style mangling. The mangling method is:
//
// 1. Prefix the symbol with "_ZN"
// 2. For each element of the path, emit the length plus the element
// 3. End the path with "E"
//
// For example, "_ZN4testE" => "test" and "_ZN3foo3bar" => "foo::bar".
//
// We're the ones printing our backtraces, so we can't rely on anything else to
// demangle our symbols. It's *much* nicer to look at demangled symbols, so
// this function is implemented to give us nice pretty output.
//
// Note that this demangler isn't quite as fancy as it could be. We have lots
// of other information in our symbols like hashes, version, type information,
// etc. Additionally, this doesn't handle glue symbols at all.
fn demangle(writer: &mut Writer, s: &str) -> IoResult<()> {
// First validate the symbol. If it doesn't look like anything we're
// expecting, we just print it literally. Note that we must handle non-rust
// symbols because we could have any function in the backtrace.
let mut valid = true;
if s.len() > 4 && s.starts_with("_ZN") && s.ends_with("E") {
let mut chars = s.slice(3, s.len() - 1).chars();
while valid {
let mut i = 0;
for c in chars {
if c.is_digit() {
i = i * 10 + c as uint - '0' as uint;
} else {
break
}
}
if i == 0 {
valid = chars.next().is_none();
break
} else if chars.by_ref().take(i - 1).len() != i - 1 {
valid = false;
}
}
} else {
valid = false;
}
// Alright, let's do this.
if !valid {
try!(writer.write_str(s));
} else {
let mut s = s.slice_from(3);
let mut first = true;
while s.len() > 1 {
if !first {
try!(writer.write_str("::"));
} else {
first = false;
}
let mut rest = s;
while rest.char_at(0).is_digit() {
rest = rest.slice_from(1);
}
let i: uint = from_str(s.slice_to(s.len() - rest.len())).unwrap();
try!(writer.write_str(rest.slice_to(i)));
s = rest.slice_from(i);
}
}
Ok(())
}
/// Backtrace support built on libgcc with some extra OS-specific support
///
/// Some methods of getting a backtrace:
///
/// * The backtrace() functions on unix. It turns out this doesn't work very
/// well for green threads on OSX, and the address to symbol portion of it
/// suffers problems that are described below.
///
/// * Using libunwind. This is more difficult than it sounds because libunwind
/// isn't installed everywhere by default. It's also a bit of a hefty library,
/// so possibly not the best option. When testing, libunwind was excellent at
/// getting both accurate backtraces and accurate symbols across platforms.
/// This route was not chosen in favor of the next option, however.
///
/// * We're already using libgcc_s for exceptions in rust (triggering task
/// unwinding and running destructors on the stack), and it turns out that it
/// conveniently comes with a function that also gives us a backtrace. All of
/// these functions look like _Unwind_*, but it's not quite the full
/// repertoire of the libunwind API. Due to it already being in use, this was
/// the chosen route of getting a backtrace.
///
/// After choosing libgcc_s for backtraces, the sad part is that it will only
/// give us a stack trace of instruction pointers. Thankfully these instruction
/// pointers are accurate (they work for green and native threads), but it's
/// then up to us again to figure out how to translate these addresses to
/// symbols. As with before, we have a few options. Before, that, a little bit
/// of an interlude about symbols. This is my very limited knowledge about
/// symbol tables, and this information is likely slightly wrong, but the
/// general idea should be correct.
///
/// When talking about symbols, it's helpful to know a few things about where
/// symbols are located. Some symbols are located in the dynamic symbol table
/// of the executable which in theory means that they're available for dynamic
/// linking and lookup. Other symbols end up only in the local symbol table of
/// the file. This loosely corresponds to pub and priv functions in Rust.
///
/// Armed with this knowledge, we know that our solution for address to symbol
/// translation will need to consult both the local and dynamic symbol tables.
/// With that in mind, here's our options of translating an address to
/// a symbol.
///
/// * Use dladdr(). The original backtrace()-based idea actually uses dladdr()
/// behind the scenes to translate, and this is why backtrace() was not used.
/// Conveniently, this method works fantastically on OSX. It appears dladdr()
/// uses magic to consult the local symbol table, or we're putting everything
/// in the dynamic symbol table anyway. Regardless, for OSX, this is the
/// method used for translation. It's provided by the system and easy to do.o
///
/// Sadly, all other systems have a dladdr() implementation that does not
/// consult the local symbol table. This means that most functions are blank
/// because they don't have symbols. This means that we need another solution.
///
/// * Use unw_get_proc_name(). This is part of the libunwind api (not the
/// libgcc_s version of the libunwind api), but involves taking a dependency
/// to libunwind. We may pursue this route in the future if we bundle
/// libunwind, but libunwind was unwieldy enough that it was not chosen at
/// this time to provide this functionality.
///
/// * Shell out to a utility like `readelf`. Crazy though it may sound, it's a
/// semi-reasonable solution. The stdlib already knows how to spawn processes,
/// so in theory it could invoke readelf, parse the output, and consult the
/// local/dynamic symbol tables from there. This ended up not getting chosen
/// due to the craziness of the idea plus the advent of the next option.
///
/// * Use `libbacktrace`. It turns out that this is a small library bundled in
/// the gcc repository which provides backtrace and symbol translation
/// functionality. All we really need from it is the backtrace functionality,
/// and we only really need this on everything that's not OSX, so this is the
/// chosen route for now.
///
/// In summary, the current situation uses libgcc_s to get a trace of stack
/// pointers, and we use dladdr() or libbacktrace to translate these addresses
/// to symbols. This is a bit of a hokey implementation as-is, but it works for
/// all unix platforms we support right now, so it at least gets the job done.
#[cfg(unix)]
mod imp {
use c_str::CString;
use cast;
use io::{IoResult, IoError, Writer};
use libc;
use option::{Some, None, Option};
use result::{Ok, Err};
use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
use uw = rt::libunwind;
struct Context<'a> {
idx: int,
writer: &'a mut Writer,
last_error: Option<IoError>,
}
#[inline(never)] // if we know this is a function call, we can skip it when
// tracing
pub fn write(w: &mut Writer) -> IoResult<()> {
// When using libbacktrace, we use some necessary global state, so we
// need to prevent more than one thread from entering this block. This
// is semi-reasonable in terms of printing anyway, and we know that all
// I/O done here is blocking I/O, not green I/O, so we don't have to
// worry about this being a native vs green mutex.
static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
let _g = unsafe { LOCK.lock() };
try!(writeln!(w, "stack backtrace:"));
let mut cx = Context { writer: w, last_error: None, idx: 0 };
return match unsafe {
uw::_Unwind_Backtrace(trace_fn,
&mut cx as *mut Context as *libc::c_void)
} {
uw::_URC_NO_REASON => {
match cx.last_error {
Some(err) => Err(err),
None => Ok(())
}
}
_ => Ok(()),
};
extern fn trace_fn(ctx: *uw::_Unwind_Context,
arg: *libc::c_void) -> uw::_Unwind_Reason_Code {
let cx: &mut Context = unsafe { cast::transmute(arg) };
let ip = unsafe { uw::_Unwind_GetIP(ctx) as *libc::c_void };
// dladdr() on osx gets whiny when we use FindEnclosingFunction, and
// it appears to work fine without it, so we only use
// FindEnclosingFunction on non-osx platforms. In doing so, we get a
// slightly more accurate stack trace in the process.
//
// This is often because failure involves the last instruction of a
// function being "call std::rt::begin_unwind", with no ret
// instructions after it. This means that the return instruction
// pointer points *outside* of the calling function, and by
// unwinding it we go back to the original function.
let ip = if cfg!(target_os = "macos") {
ip
} else {
unsafe { uw::_Unwind_FindEnclosingFunction(ip) }
};
// Don't print out the first few frames (they're not user frames)
cx.idx += 1;
if cx.idx <= 0 { return uw::_URC_NO_REASON }
// Don't print ginormous backtraces
if cx.idx > 100 {
match write!(cx.writer, " ... <frames omitted>\n") {
Ok(()) => {}
Err(e) => { cx.last_error = Some(e); }
}
return uw::_URC_FAILURE
}
// Once we hit an error, stop trying to print more frames
if cx.last_error.is_some() { return uw::_URC_FAILURE }
match print(cx.writer, cx.idx, ip) {
Ok(()) => {}
Err(e) => { cx.last_error = Some(e); }
}
// keep going
return uw::_URC_NO_REASON
}
}
#[cfg(target_os = "macos")]
fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> {
use intrinsics;
struct Dl_info {
dli_fname: *libc::c_char,
dli_fbase: *libc::c_void,
dli_sname: *libc::c_char,
dli_saddr: *libc::c_void,
}
extern {
fn dladdr(addr: *libc::c_void,
info: *mut Dl_info) -> libc::c_int;
}
let mut info: Dl_info = unsafe { intrinsics::init() };
if unsafe { dladdr(addr, &mut info) == 0 } {
output(w, idx,addr, None)
} else {
output(w, idx, addr, Some(unsafe {
CString::new(info.dli_sname, false)
}))
}
}
#[cfg(not(target_os = "macos"))]
fn print(w: &mut Writer, idx: int, addr: *libc::c_void) -> IoResult<()> {
use container::Container;
use iter::Iterator;
use os;
use path::GenericPath;
use ptr::RawPtr;
use ptr;
use vec::{ImmutableVector, MutableVector};
////////////////////////////////////////////////////////////////////////
// libbacktrace.h API
////////////////////////////////////////////////////////////////////////
type backtrace_syminfo_callback =
extern "C" fn(data: *mut libc::c_void,
pc: libc::uintptr_t,
symname: *libc::c_char,
symval: libc::uintptr_t,
symsize: libc::uintptr_t);
type backtrace_error_callback =
extern "C" fn(data: *mut libc::c_void,
msg: *libc::c_char,
errnum: libc::c_int);
enum backtrace_state {}
#[link(name = "backtrace", kind = "static")]
extern {
fn backtrace_create_state(filename: *libc::c_char,
threaded: libc::c_int,
error: backtrace_error_callback,
data: *mut libc::c_void)
-> *mut backtrace_state;
fn backtrace_syminfo(state: *mut backtrace_state,
addr: libc::uintptr_t,
cb: backtrace_syminfo_callback,
error: backtrace_error_callback,
data: *mut libc::c_void) -> libc::c_int;
}
////////////////////////////////////////////////////////////////////////
// helper callbacks
////////////////////////////////////////////////////////////////////////
extern fn error_cb(_data: *mut libc::c_void, _msg: *libc::c_char,
_errnum: libc::c_int) {
// do nothing for now
}
extern fn syminfo_cb(data: *mut libc::c_void,
_pc: libc::uintptr_t,
symname: *libc::c_char,
_symval: libc::uintptr_t,
_symsize: libc::uintptr_t) {
let slot = data as *mut *libc::c_char;
unsafe { *slot = symname; }
}
// The libbacktrace API supports creating a state, but it does not
// support destroying a state. I personally take this to mean that a
// state is meant to be created and then live forever.
//
// I would love to register an at_exit() handler which cleans up this
// state, but libbacktrace provides no way to do so.
//
// With these constraints, this function has a statically cached state
// that is calculated the first time this is requested. Remember that
// backtracing all happens serially (one global lock).
//
// An additionally oddity in this function is that we initialize the
// filename via self_exe_name() to pass to libbacktrace. It turns out
// that on linux libbacktrace seamlessly gets the filename of the
// current executable, but this fails on freebsd. by always providing
// it, we make sure that libbacktrace never has a reason to not look up
// the symbols. The libbacktrace API also states that the filename must
// be in "permanent memory", so we copy it to a static and then use the
// static as the pointer.
unsafe fn init_state() -> *mut backtrace_state {
static mut STATE: *mut backtrace_state = 0 as *mut backtrace_state;
static mut LAST_FILENAME: [libc::c_char, ..256] = [0, ..256];
if !STATE.is_null() { return STATE }
let selfname = if cfg!(target_os = "freebsd") {
os::self_exe_name()
} else {
None
};
let filename = match selfname {
Some(path) => {
let bytes = path.as_vec();
if bytes.len() < LAST_FILENAME.len() {
let i = bytes.iter();
for (slot, val) in LAST_FILENAME.mut_iter().zip(i) {
*slot = *val as libc::c_char;
}
LAST_FILENAME.as_ptr()
} else {
ptr::null()
}
}
None => ptr::null(),
};
STATE = backtrace_create_state(filename, 0, error_cb,
ptr::mut_null());
return STATE
}
////////////////////////////////////////////////////////////////////////
// translation
////////////////////////////////////////////////////////////////////////
// backtrace errors are currently swept under the rug, only I/O
// errors are reported
let state = unsafe { init_state() };
if state.is_null() {
return output(w, idx, addr, None)
}
let mut data = 0 as *libc::c_char;
let data_addr = &mut data as *mut *libc::c_char;
let ret = unsafe {
backtrace_syminfo(state, addr as libc::uintptr_t,
syminfo_cb, error_cb,
data_addr as *mut libc::c_void)
};
if ret == 0 || data.is_null() {
output(w, idx, addr, None)
} else {
output(w, idx, addr, Some(unsafe { CString::new(data, false) }))
}
}
// Finally, after all that work above, we can emit a symbol.
fn output(w: &mut Writer, idx: int, addr: *libc::c_void,
s: Option<CString>) -> IoResult<()> {
try!(write!(w, " {:2}: {:2$} - ", idx, addr, super::HEX_WIDTH));
match s.as_ref().and_then(|c| c.as_str()) {
Some(string) => try!(super::demangle(w, string)),
None => try!(write!(w, "<unknown>")),
}
w.write(['\n' as u8])
}
}
/// As always, windows has something very different than unix, we mainly want
/// to avoid having to depend too much on libunwind for windows.
///
/// If you google around, you'll find a fair bit of references to built-in
/// functions to get backtraces on windows. It turns out that most of these are
/// in an external library called dbghelp. I was unable to find this library
/// via `-ldbghelp`, but it is apparently normal to do the `dlopen` equivalent
/// of it.
///
/// You'll also find that there's a function called CaptureStackBackTrace
/// mentioned frequently (which is also easy to use), but sadly I didn't have a
/// copy of that function in my mingw install (maybe it was broken?). Instead,
/// this takes the route of using StackWalk64 in order to walk the stack.
#[cfg(windows)]
#[allow(dead_code, uppercase_variables)]
mod imp {
use c_str::CString;
use container::Container;
use io::{IoResult, Writer};
use iter::Iterator;
use libc;
use mem;
use ops::Drop;
use option::{Some, None};
use path::Path;
use result::{Ok, Err};
use str::StrSlice;
use unstable::dynamic_lib::DynamicLibrary;
use intrinsics;
use unstable::mutex::{StaticNativeMutex, NATIVE_MUTEX_INIT};
use vec::ImmutableVector;
extern "system" {
fn GetCurrentProcess() -> libc::HANDLE;
fn GetCurrentThread() -> libc::HANDLE;
fn RtlCaptureContext(ctx: *mut arch::CONTEXT);
}
type SymFromAddrFn =
extern "system" fn(libc::HANDLE, u64, *mut u64,
*mut SYMBOL_INFO) -> libc::BOOL;
type SymInitializeFn =
extern "system" fn(libc::HANDLE, *libc::c_void,
libc::BOOL) -> libc::BOOL;
type SymCleanupFn =
extern "system" fn(libc::HANDLE) -> libc::BOOL;
type StackWalk64Fn =
extern "system" fn(libc::DWORD, libc::HANDLE, libc::HANDLE,
*mut STACKFRAME64, *mut arch::CONTEXT,
*libc::c_void, *libc::c_void,
*libc::c_void, *libc::c_void) -> libc::BOOL;
static MAX_SYM_NAME: uint = 2000;
static IMAGE_FILE_MACHINE_I386: libc::DWORD = 0x014c;
static IMAGE_FILE_MACHINE_IA64: libc::DWORD = 0x0200;
static IMAGE_FILE_MACHINE_AMD64: libc::DWORD = 0x8664;
#[packed]
struct SYMBOL_INFO {
SizeOfStruct: libc::c_ulong,
TypeIndex: libc::c_ulong,
Reserved: [u64, ..2],
Index: libc::c_ulong,
Size: libc::c_ulong,
ModBase: u64,
Flags: libc::c_ulong,
Value: u64,
Address: u64,
Register: libc::c_ulong,
Scope: libc::c_ulong,
Tag: libc::c_ulong,
NameLen: libc::c_ulong,
MaxNameLen: libc::c_ulong,
// note that windows has this as 1, but it basically just means that
// the name is inline at the end of the struct. For us, we just bump
// the struct size up to MAX_SYM_NAME.
Name: [libc::c_char, ..MAX_SYM_NAME],
}
#[repr(C)]
enum ADDRESS_MODE {
AddrMode1616,
AddrMode1632,
AddrModeReal,
AddrModeFlat,
}
struct ADDRESS64 {
Offset: u64,
Segment: u16,
Mode: ADDRESS_MODE,
}
struct STACKFRAME64 {
AddrPC: ADDRESS64,
AddrReturn: ADDRESS64,
AddrFrame: ADDRESS64,
AddrStack: ADDRESS64,
AddrBStore: ADDRESS64,
FuncTableEntry: *libc::c_void,
Params: [u64, ..4],
Far: libc::BOOL,
Virtual: libc::BOOL,
Reserved: [u64, ..3],
KdHelp: KDHELP64,
}
struct KDHELP64 {
Thread: u64,
ThCallbackStack: libc::DWORD,
ThCallbackBStore: libc::DWORD,
NextCallback: libc::DWORD,
FramePointer: libc::DWORD,
KiCallUserMode: u64,
KeUserCallbackDispatcher: u64,
SystemRangeStart: u64,
KiUserExceptionDispatcher: u64,
StackBase: u64,
StackLimit: u64,
Reserved: [u64, ..5],
}
#[cfg(target_arch = "x86")]
mod arch {
use libc;
static MAXIMUM_SUPPORTED_EXTENSION: uint = 512;
pub struct CONTEXT {
ContextFlags: libc::DWORD,
Dr0: libc::DWORD,
Dr1: libc::DWORD,
Dr2: libc::DWORD,
Dr3: libc::DWORD,
Dr6: libc::DWORD,
Dr7: libc::DWORD,
FloatSave: FLOATING_SAVE_AREA,
SegGs: libc::DWORD,
SegFs: libc::DWORD,
SegEs: libc::DWORD,
SegDs: libc::DWORD,
Edi: libc::DWORD,
Esi: libc::DWORD,
Ebx: libc::DWORD,
Edx: libc::DWORD,
Ecx: libc::DWORD,
Eax: libc::DWORD,
Ebp: libc::DWORD,
Eip: libc::DWORD,
SegCs: libc::DWORD,
EFlags: libc::DWORD,
Esp: libc::DWORD,
SegSs: libc::DWORD,
ExtendedRegisters: [u8, ..MAXIMUM_SUPPORTED_EXTENSION],
}
pub struct FLOATING_SAVE_AREA {
ControlWord: libc::DWORD,
StatusWord: libc::DWORD,
TagWord: libc::DWORD,
ErrorOffset: libc::DWORD,
ErrorSelector: libc::DWORD,
DataOffset: libc::DWORD,
DataSelector: libc::DWORD,
RegisterArea: [u8, ..80],
Cr0NpxState: libc::DWORD,
}
pub fn init_frame(frame: &mut super::STACKFRAME64,
ctx: &CONTEXT) -> libc::DWORD {
frame.AddrPC.Offset = ctx.Eip as u64;
frame.AddrPC.Mode = super::AddrModeFlat;
frame.AddrStack.Offset = ctx.Esp as u64;
frame.AddrStack.Mode = super::AddrModeFlat;
frame.AddrFrame.Offset = ctx.Ebp as u64;
frame.AddrFrame.Mode = super::AddrModeFlat;
super::IMAGE_FILE_MACHINE_I386
}
}
struct Cleanup {
handle: libc::HANDLE,
SymCleanup: SymCleanupFn,
}
impl Drop for Cleanup {
fn drop(&mut self) { (self.SymCleanup)(self.handle); }
}
pub fn write(w: &mut Writer) -> IoResult<()> {
// According to windows documentation, all dbghelp functions are
// single-threaded.
static mut LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
let _g = unsafe { LOCK.lock() };
// Open up dbghelp.dll, we don't link to it explicitly because it can't
// always be found. Additionally, it's nice having fewer dependencies.
let path = Path::new("dbghelp.dll");
let lib = match DynamicLibrary::open(Some(&path)) {
Ok(lib) => lib,
Err(..) => return Ok(()),
};
macro_rules! sym( ($e:expr, $t:ident) => (
match unsafe { lib.symbol::<$t>($e) } {
Ok(f) => f,
Err(..) => return Ok(())
}
) )
// Fetch the symbols necessary from dbghelp.dll
let SymFromAddr = sym!("SymFromAddr", SymFromAddrFn);
let SymInitialize = sym!("SymInitialize", SymInitializeFn);
let SymCleanup = sym!("SymCleanup", SymCleanupFn);
let StackWalk64 = sym!("StackWalk64", StackWalk64Fn);
// Allocate necessary structures for doing the stack walk
let process = unsafe { GetCurrentProcess() };
let thread = unsafe { GetCurrentThread() };
let mut context: arch::CONTEXT = unsafe { intrinsics::init() };
unsafe { RtlCaptureContext(&mut context); }
let mut frame: STACKFRAME64 = unsafe { intrinsics::init() };
let image = arch::init_frame(&mut frame, &context);
// Initialize this process's symbols
let ret = SymInitialize(process, 0 as *libc::c_void, libc::TRUE);
if ret != libc::TRUE { return Ok(()) }
let _c = Cleanup { handle: process, SymCleanup: SymCleanup };
// And now that we're done with all the setup, do the stack walking!
let mut i = 0;
try!(write!(w, "stack backtrace:\n"));
while StackWalk64(image, process, thread, &mut frame, &mut context,
0 as *libc::c_void, 0 as *libc::c_void,
0 as *libc::c_void, 0 as *libc::c_void) == libc::TRUE{
let addr = frame.AddrPC.Offset;
if addr == frame.AddrReturn.Offset || addr == 0 ||
frame.AddrReturn.Offset == 0 { break }
i += 1;
try!(write!(w, " {:2}: {:#2$x}", i, addr, super::HEX_WIDTH));
let mut info: SYMBOL_INFO = unsafe { intrinsics::init() };
info.MaxNameLen = MAX_SYM_NAME as libc::c_ulong;
info.SizeOfStruct = (mem::size_of::<SYMBOL_INFO>() -
info.Name.len() + 1) as libc::c_ulong;
let mut displacement = 0u64;
let ret = SymFromAddr(process, addr as u64, &mut displacement,
&mut info);
if ret == libc::TRUE {
try!(write!(w, " - "));
let cstr = unsafe { CString::new(info.Name.as_ptr(), false) };
let bytes = cstr.as_bytes();
match cstr.as_str() {
Some(s) => try!(super::demangle(w, s)),
None => try!(w.write(bytes.slice_to(bytes.len() - 1))),
}
}
try!(w.write(['\n' as u8]));
}
Ok(())
}
}
#[cfg(test)]
mod test {
use prelude::*;
use io::MemWriter;
use str;
#[test]
fn demangle() {
macro_rules! t( ($a:expr, $b:expr) => ({
let mut m = MemWriter::new();
super::demangle(&mut m, $a);
assert_eq!(str::from_utf8_owned(m.unwrap()).unwrap(), $b.to_owned());
}) )
t!("test", "test");
t!("_ZN4testE", "test");
t!("_ZN4test", "_ZN4test");
t!("_ZN4test1a2bcE", "test::a::bc");
}
}

156
src/libstd/rt/libunwind.rs Normal file
View File

@ -0,0 +1,156 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Unwind library interface
#[allow(non_camel_case_types)];
#[allow(dead_code)]; // these are just bindings
use libc;
#[cfg(not(target_arch = "arm"))]
#[repr(C)]
pub enum _Unwind_Action
{
_UA_SEARCH_PHASE = 1,
_UA_CLEANUP_PHASE = 2,
_UA_HANDLER_FRAME = 4,
_UA_FORCE_UNWIND = 8,
_UA_END_OF_STACK = 16,
}
#[cfg(target_arch = "arm")]
#[repr(C)]
pub enum _Unwind_State
{
_US_VIRTUAL_UNWIND_FRAME = 0,
_US_UNWIND_FRAME_STARTING = 1,
_US_UNWIND_FRAME_RESUME = 2,
_US_ACTION_MASK = 3,
_US_FORCE_UNWIND = 8,
_US_END_OF_STACK = 16
}
#[repr(C)]
pub enum _Unwind_Reason_Code {
_URC_NO_REASON = 0,
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
_URC_FATAL_PHASE2_ERROR = 2,
_URC_FATAL_PHASE1_ERROR = 3,
_URC_NORMAL_STOP = 4,
_URC_END_OF_STACK = 5,
_URC_HANDLER_FOUND = 6,
_URC_INSTALL_CONTEXT = 7,
_URC_CONTINUE_UNWIND = 8,
_URC_FAILURE = 9, // used only by ARM EABI
}
pub type _Unwind_Exception_Class = u64;
pub type _Unwind_Word = libc::uintptr_t;
#[cfg(target_arch = "x86")]
pub static unwinder_private_data_size: int = 5;
#[cfg(target_arch = "x86_64")]
pub static unwinder_private_data_size: int = 2;
#[cfg(target_arch = "arm")]
pub static unwinder_private_data_size: int = 20;
pub struct _Unwind_Exception {
exception_class: _Unwind_Exception_Class,
exception_cleanup: _Unwind_Exception_Cleanup_Fn,
private: [_Unwind_Word, ..unwinder_private_data_size],
}
pub enum _Unwind_Context {}
pub type _Unwind_Exception_Cleanup_Fn =
extern "C" fn(unwind_code: _Unwind_Reason_Code,
exception: *_Unwind_Exception);
pub type _Unwind_Trace_Fn =
extern "C" fn(ctx: *_Unwind_Context,
arg: *libc::c_void) -> _Unwind_Reason_Code;
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "win32")]
#[link(name = "gcc_s")]
extern {}
#[cfg(target_os = "android")]
#[link(name = "gcc")]
extern {}
extern "C" {
pub fn _Unwind_RaiseException(exception: *_Unwind_Exception)
-> _Unwind_Reason_Code;
pub fn _Unwind_DeleteException(exception: *_Unwind_Exception);
pub fn _Unwind_Backtrace(trace: _Unwind_Trace_Fn,
trace_argument: *libc::c_void)
-> _Unwind_Reason_Code;
#[cfg(not(target_os = "android"))]
pub fn _Unwind_GetIP(ctx: *_Unwind_Context) -> libc::uintptr_t;
#[cfg(not(target_os = "android"))]
pub fn _Unwind_FindEnclosingFunction(pc: *libc::c_void) -> *libc::c_void;
}
// On android, the function _Unwind_GetIP is a macro, and this is the expansion
// of the macro. This is all copy/pasted directly from the header file with the
// definition of _Unwind_GetIP.
#[cfg(target_os = "android")]
pub unsafe fn _Unwind_GetIP(ctx: *_Unwind_Context) -> libc::uintptr_t {
#[repr(C)]
enum _Unwind_VRS_Result {
_UVRSR_OK = 0,
_UVRSR_NOT_IMPLEMENTED = 1,
_UVRSR_FAILED = 2,
}
#[repr(C)]
enum _Unwind_VRS_RegClass {
_UVRSC_CORE = 0,
_UVRSC_VFP = 1,
_UVRSC_FPA = 2,
_UVRSC_WMMXD = 3,
_UVRSC_WMMXC = 4,
}
#[repr(C)]
enum _Unwind_VRS_DataRepresentation {
_UVRSD_UINT32 = 0,
_UVRSD_VFPX = 1,
_UVRSD_FPAX = 2,
_UVRSD_UINT64 = 3,
_UVRSD_FLOAT = 4,
_UVRSD_DOUBLE = 5,
}
type _Unwind_Word = libc::c_uint;
extern {
fn _Unwind_VRS_Get(ctx: *_Unwind_Context,
klass: _Unwind_VRS_RegClass,
word: _Unwind_Word,
repr: _Unwind_VRS_DataRepresentation,
data: *mut libc::c_void) -> _Unwind_VRS_Result;
}
let mut val: _Unwind_Word = 0;
let ptr = &mut val as *mut _Unwind_Word;
let _ = _Unwind_VRS_Get(ctx, _UVRSC_CORE, 15, _UVRSD_UINT32,
ptr as *mut libc::c_void);
(val & !1) as libc::uintptr_t
}
// This function also doesn't exist on android, so make it a no-op
#[cfg(target_os = "android")]
pub unsafe fn _Unwind_FindEnclosingFunction(pc: *libc::c_void) -> *libc::c_void{
pc
}

View File

@ -119,6 +119,12 @@ mod thread_local_storage;
/// Stack unwinding
pub mod unwind;
/// The interface to libunwind that rust is using.
mod libunwind;
/// Simple backtrace functionality (to print on failure)
pub mod backtrace;
/// Just stuff
mod util;

View File

@ -65,99 +65,14 @@ use option::{Some, None, Option};
use prelude::drop;
use ptr::RawPtr;
use result::{Err, Ok};
use rt::backtrace;
use rt::local::Local;
use rt::task::Task;
use str::Str;
use task::TaskResult;
use intrinsics;
use uw = self::libunwind;
#[allow(dead_code)]
mod libunwind {
//! Unwind library interface
#[allow(non_camel_case_types)];
#[allow(dead_code)]; // these are just bindings
use libc::{uintptr_t};
#[cfg(not(target_arch = "arm"))]
#[repr(C)]
pub enum _Unwind_Action
{
_UA_SEARCH_PHASE = 1,
_UA_CLEANUP_PHASE = 2,
_UA_HANDLER_FRAME = 4,
_UA_FORCE_UNWIND = 8,
_UA_END_OF_STACK = 16,
}
#[cfg(target_arch = "arm")]
#[repr(C)]
pub enum _Unwind_State
{
_US_VIRTUAL_UNWIND_FRAME = 0,
_US_UNWIND_FRAME_STARTING = 1,
_US_UNWIND_FRAME_RESUME = 2,
_US_ACTION_MASK = 3,
_US_FORCE_UNWIND = 8,
_US_END_OF_STACK = 16
}
#[repr(C)]
pub enum _Unwind_Reason_Code {
_URC_NO_REASON = 0,
_URC_FOREIGN_EXCEPTION_CAUGHT = 1,
_URC_FATAL_PHASE2_ERROR = 2,
_URC_FATAL_PHASE1_ERROR = 3,
_URC_NORMAL_STOP = 4,
_URC_END_OF_STACK = 5,
_URC_HANDLER_FOUND = 6,
_URC_INSTALL_CONTEXT = 7,
_URC_CONTINUE_UNWIND = 8,
_URC_FAILURE = 9, // used only by ARM EABI
}
pub type _Unwind_Exception_Class = u64;
pub type _Unwind_Word = uintptr_t;
#[cfg(target_arch = "x86")]
pub static unwinder_private_data_size: int = 5;
#[cfg(target_arch = "x86_64")]
pub static unwinder_private_data_size: int = 2;
#[cfg(target_arch = "arm")]
pub static unwinder_private_data_size: int = 20;
pub struct _Unwind_Exception {
exception_class: _Unwind_Exception_Class,
exception_cleanup: _Unwind_Exception_Cleanup_Fn,
private: [_Unwind_Word, ..unwinder_private_data_size],
}
pub enum _Unwind_Context {}
pub type _Unwind_Exception_Cleanup_Fn = extern "C" fn(unwind_code: _Unwind_Reason_Code,
exception: *_Unwind_Exception);
#[cfg(target_os = "linux")]
#[cfg(target_os = "freebsd")]
#[cfg(target_os = "win32")]
#[link(name = "gcc_s")]
extern {}
#[cfg(target_os = "android")]
#[link(name = "gcc")]
extern {}
extern "C" {
pub fn _Unwind_RaiseException(exception: *_Unwind_Exception) -> _Unwind_Reason_Code;
pub fn _Unwind_DeleteException(exception: *_Unwind_Exception);
}
}
use uw = rt::libunwind;
pub struct Unwinder {
priv unwinding: bool,
@ -282,7 +197,7 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
#[doc(hidden)]
#[allow(visible_private_types)]
pub mod eabi {
use uw = super::libunwind;
use uw = rt::libunwind;
use libc::c_int;
extern "C" {
@ -336,7 +251,7 @@ pub mod eabi {
#[cfg(target_arch = "arm", not(test))]
#[allow(visible_private_types)]
pub mod eabi {
use uw = super::libunwind;
use uw = rt::libunwind;
use libc::c_int;
extern "C" {
@ -480,6 +395,10 @@ fn begin_unwind_inner(msg: ~Any, file: &'static str, line: uint) -> ! {
Some(t) => t,
None => {
rterrln!("failed at '{}', {}:{}", msg_s, file, line);
if backtrace::log_enabled() {
let mut err = ::rt::util::Stderr;
let _err = backtrace::write(&mut err);
}
unsafe { intrinsics::abort() }
}
};
@ -499,6 +418,9 @@ fn begin_unwind_inner(msg: ~Any, file: &'static str, line: uint) -> ! {
let _err = format_args!(|args| ::fmt::writeln(stderr, args),
"task '{}' failed at '{}', {}:{}",
n, msg_s, file, line);
if backtrace::log_enabled() {
let _err = backtrace::write(stderr);
}
task = Local::take();
match mem::replace(&mut task.stderr, Some(stderr)) {
@ -513,6 +435,10 @@ fn begin_unwind_inner(msg: ~Any, file: &'static str, line: uint) -> ! {
None => {
rterrln!("task '{}' failed at '{}', {}:{}", n, msg_s,
file, line);
if backtrace::log_enabled() {
let mut err = ::rt::util::Stderr;
let _err = backtrace::write(&mut err);
}
}
}
}
@ -525,6 +451,13 @@ fn begin_unwind_inner(msg: ~Any, file: &'static str, line: uint) -> ! {
// unwinding or otherwise exiting the task cleanly.
rterrln!("task failed during unwinding (double-failure - total drag!)")
rterrln!("rust must abort now. so sorry.");
// Don't print the backtrace twice (it would have already been
// printed if logging was enabled).
if !backtrace::log_enabled() {
let mut err = ::rt::util::Stderr;
let _err = backtrace::write(&mut err);
}
unsafe { intrinsics::abort() }
}
}

View File

@ -12,6 +12,7 @@ use container::Container;
use fmt;
use from_str::FromStr;
use io::IoResult;
use io;
use iter::Iterator;
use libc;
use option::{Some, None, Option};
@ -70,20 +71,20 @@ pub fn default_sched_threads() -> uint {
}
}
pub fn dumb_println(args: &fmt::Arguments) {
use io;
pub struct Stderr;
struct Stderr;
impl io::Writer for Stderr {
fn write(&mut self, data: &[u8]) -> IoResult<()> {
unsafe {
libc::write(libc::STDERR_FILENO,
data.as_ptr() as *libc::c_void,
data.len() as libc::size_t);
}
Ok(()) // yes, we're lying
impl io::Writer for Stderr {
fn write(&mut self, data: &[u8]) -> IoResult<()> {
unsafe {
libc::write(libc::STDERR_FILENO,
data.as_ptr() as *libc::c_void,
data.len() as libc::size_t);
}
Ok(()) // yes, we're lying
}
}
pub fn dumb_println(args: &fmt::Arguments) {
let mut w = Stderr;
let _ = fmt::writeln(&mut w as &mut io::Writer, args);
}
@ -140,6 +141,10 @@ memory and partly incapable of presentation to others.",
rterrln!("{}", "");
rterrln!("fatal runtime error: {}", msg);
{
let mut err = Stderr;
let _err = ::rt::backtrace::write(&mut err);
}
abort();
fn abort() -> ! {

View File

@ -0,0 +1,110 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// ignore-fast this is executing itself
#[no_uv];
extern crate native;
use std::os;
use std::io::process::{Process, ProcessConfig};
use std::unstable::finally::Finally;
use std::str;
#[start]
fn start(argc: int, argv: **u8) -> int { native::start(argc, argv, main) }
#[inline(never)]
fn foo() {
fail!()
}
#[inline(never)]
fn double() {
(|| {
fail!("once");
}).finally(|| {
fail!("twice");
})
}
fn runtest(me: &str) {
let mut env = os::env();
match env.iter().position(|&(ref s, _)| "RUST_LOG" == *s) {
Some(i) => { env.remove(i); }
None => {}
}
env.push((~"RUST_LOG", ~"std::rt::backtrace"));
// Make sure that the stack trace is printed
let mut p = Process::configure(ProcessConfig {
program: me,
args: [~"fail"],
env: Some(env.as_slice()),
.. ProcessConfig::new()
}).unwrap();
let out = p.wait_with_output();
assert!(!out.status.success());
let s = str::from_utf8(out.error).unwrap();
assert!(s.contains("stack backtrace") && s.contains("foo::h"),
"bad output: {}", s);
// Make sure the stack trace is *not* printed
let mut p = Process::configure(ProcessConfig {
program: me,
args: [~"fail"],
.. ProcessConfig::new()
}).unwrap();
let out = p.wait_with_output();
assert!(!out.status.success());
let s = str::from_utf8(out.error).unwrap();
assert!(!s.contains("stack backtrace") && !s.contains("foo::h"),
"bad output2: {}", s);
// Make sure a stack trace is printed
let mut p = Process::configure(ProcessConfig {
program: me,
args: [~"double-fail"],
.. ProcessConfig::new()
}).unwrap();
let out = p.wait_with_output();
assert!(!out.status.success());
let s = str::from_utf8(out.error).unwrap();
assert!(s.contains("stack backtrace") && s.contains("double::h"),
"bad output3: {}", s);
// Make sure a stack trace isn't printed too many times
let mut p = Process::configure(ProcessConfig {
program: me,
args: [~"double-fail"],
env: Some(env.as_slice()),
.. ProcessConfig::new()
}).unwrap();
let out = p.wait_with_output();
assert!(!out.status.success());
let s = str::from_utf8(out.error).unwrap();
let mut i = 0;
for _ in range(0, 2) {
i += s.slice_from(i + 10).find_str("stack backtrace").unwrap() + 10;
}
assert!(s.slice_from(i + 10).find_str("stack backtrace").is_none(),
"bad output4: {}", s);
}
fn main() {
let args = os::args();
if args.len() >= 2 && args[1].as_slice() == "fail" {
foo();
} else if args.len() >= 2 && args[1].as_slice() == "double-fail" {
double();
} else {
runtest(args[0]);
}
}