├── .gitignore ├── CMakeLists.txt ├── README.md ├── auxincl ├── dwarf2.h └── filenames.h ├── examples └── bt.c └── libbacktrace ├── ChangeLog ├── README ├── alloc.c ├── atomic.c ├── backtrace-supported.h.in ├── backtrace.c ├── backtrace.h ├── btest.c ├── config.h.in.cmake ├── dwarf.c ├── elf.c ├── fileline.c ├── internal.h ├── mmap.c ├── mmapio.c ├── nounwind.c ├── posix.c ├── print.c ├── read.c ├── simple.c ├── sort.c ├── state.c ├── stest.c └── unknown.c /.gitignore: -------------------------------------------------------------------------------- 1 | backtrace-supported.h 2 | config.h 3 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | # CMakeLists.txt -- libbacktrace CMake build script 2 | # Contributed by Alexander Monakov, ISP RAS 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions are 6 | # met: 7 | # 8 | # (1) Redistributions of source code must retain the above copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # 11 | # (2) Redistributions in binary form must reproduce the above copyright 12 | # notice, this list of conditions and the following disclaimer in 13 | # the documentation and/or other materials provided with the 14 | # distribution. 15 | # 16 | # (3) The name of the author may not be used to 17 | # endorse or promote products derived from this software without 18 | # specific prior written permission. 19 | # 20 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | # DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 24 | # INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | # SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | # HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 | # STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 | # IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | # POSSIBILITY OF SUCH DAMAGE. */ 31 | 32 | cmake_minimum_required (VERSION 2.8) 33 | cmake_policy (VERSION 2.8) 34 | 35 | project (libbacktrace) 36 | 37 | set (BACKTRACE_SUPPORTED 1) 38 | 39 | include (CheckSymbolExists) 40 | check_symbol_exists (_Unwind_Backtrace unwind.h HAVE_BACKTRACE) 41 | check_symbol_exists (_Unwind_GetIPInfo unwind.h HAVE_GETIPINFO) 42 | 43 | if (HAVE_BACKTRACE) 44 | set (BACKTRACE_FILE libbacktrace/backtrace.c libbacktrace/simple.c) 45 | else () 46 | set (BACKTRACE_FILE libbacktrace/nounwind.c) 47 | set (BACKTRACE_SUPPORTED 0) 48 | message (STATUS "_Unwind_Backtrace() not found. Disabling Backtrace support.") 49 | endif () 50 | 51 | include (CheckCCompilerFlag) 52 | check_c_compiler_flag ("-funwind-tables" FLAG_UNWIND_TABLES) 53 | if (FLAG_UNWIND_TABLES) 54 | add_definitions ("-funwind-tables") 55 | endif () 56 | 57 | # Adjust warnings 58 | if (CMAKE_COMPILER_IS_GNUCC) 59 | add_definitions ("-Wno-switch -Wno-enum-compare") 60 | endif () 61 | 62 | check_c_source_compiles ( 63 | "int i; 64 | int main() { 65 | __sync_bool_compare_and_swap (&i, i, i); 66 | __sync_lock_test_and_set (&i, 1); 67 | __sync_lock_release (&i);}" 68 | HAVE_SYNC_FUNCTIONS) 69 | 70 | if (HAVE_SYNC_FUNCTIONS) 71 | set (BACKTRACE_SUPPORTS_THREADS 1) 72 | else () 73 | set (BACKTRACE_SUPPORTS_THREADS 0) 74 | endif () 75 | 76 | if (CMAKE_EXECUTABLE_FORMAT STREQUAL "ELF") 77 | set (FORMAT_FILE libbacktrace/elf.c libbacktrace/dwarf.c) 78 | math (EXPR BACKTRACE_ELF_SIZE 8*${CMAKE_C_SIZEOF_DATA_PTR}) 79 | else () 80 | set (FORMAT_FILE libbacktrace/unknown.c) 81 | set (BACKTRACE_SUPPORTED 0) 82 | message (STATUS "Executable format is not ELF. Disabling Backtrace support.") 83 | endif () 84 | 85 | check_symbol_exists (mmap sys/mman.h HAVE_MMAP) 86 | 87 | if (HAVE_MMAP) 88 | set (VIEW_FILE libbacktrace/mmapio.c) 89 | check_symbol_exists (MAP_ANONYMOUS sys/mman.h HAVE_MMAP_ANONYMOUS) 90 | check_symbol_exists (MAP_ANON sys/mman.h HAVE_MMAP_ANON) 91 | if (HAVE_MMAP_ANONYMOUS AND HAVE_MMAP_ANON) 92 | set (ALLOC_FILE libbacktrace/mmap.c) 93 | else () 94 | set (ALLOC_FILE libbacktrace/alloc.c) 95 | endif () 96 | else () 97 | set (VIEW_FILE libbacktrace/read.c) 98 | set (ALLOC_FILE libbacktrace/alloc.c) 99 | endif () 100 | 101 | if (ALLOC_FILE STREQUAL "libbacktrace/alloc.c") 102 | set (BACKTRACE_USES_MALLOC 1) 103 | else () 104 | set (BACKTRACE_USES_MALLOC 0) 105 | endif () 106 | 107 | add_definitions (-D_GNU_SOURCE) 108 | set (CMAKE_REQUIRED_DEFINITIONS ${CMAKE_REQUIRED_DEFINITIONS} -D_GNU_SOURCE) 109 | check_symbol_exists (dl_iterate_phdr link.h HAVE_DL_ITERATE_PHDR) 110 | 111 | include (CheckFunctionExists) 112 | check_function_exists (fcntl HAVE_FCNTL) 113 | 114 | check_function_exists (strnlen HAVE_DECL_STRNLEN) 115 | 116 | check_function_exists (getexecname HAVE_GETEXECNAME) 117 | 118 | include (CheckIncludeFile) 119 | check_include_file (dwarf.h HAVE_DWARF_H) 120 | check_include_file (libdwarf/dwarf.h HAVE_LIBDWARF_DWARF_H) 121 | if (NOT HAVE_DWARF_H AND NOT HAVE_LIBDWARF_DWARF_H) 122 | set (FORMAT_FILE unknown.c) 123 | set (BACKTRACE_SUPPORTED 0) 124 | message (STATUS "libdwarf not found. Disabling Backtrace support.") 125 | endif () 126 | 127 | configure_file (libbacktrace/backtrace-supported.h.in backtrace-supported.h) 128 | 129 | configure_file (libbacktrace/config.h.in.cmake config.h) 130 | 131 | include_directories (BEFORE 132 | ${CMAKE_CURRENT_BINARY_DIR} 133 | ) 134 | include_directories ( 135 | auxincl 136 | libbacktrace 137 | ) 138 | 139 | # Add target library 140 | add_library ("backtrace" SHARED 141 | ${BACKTRACE_FILE} 142 | ${FORMAT_FILE} 143 | ${VIEW_FILE} 144 | ${ALLOC_FILE} 145 | libbacktrace/atomic.c 146 | libbacktrace/fileline.c 147 | libbacktrace/posix.c 148 | libbacktrace/print.c 149 | libbacktrace/sort.c 150 | libbacktrace/state.c 151 | ) 152 | set_target_properties (backtrace PROPERTIES 153 | COMPILE_FLAGS "${CMAKE_SHARED_LIBRARY_C_FLAGS}" 154 | ) 155 | 156 | # Install 157 | install (FILES "libbacktrace/backtrace.h" "${CMAKE_CURRENT_BINARY_DIR}/backtrace-supported.h" DESTINATION "include/libbacktrace") 158 | install (TARGETS "backtrace" DESTINATION "lib") 159 | 160 | # Tests 161 | set (ENABLE_LIBBACKTRACE_TEST false CACHE BOOL "Enable libbacktrace testing") 162 | if (ENABLE_LIBBACKTRACE_TEST) 163 | enable_testing () 164 | add_executable (btest libbacktrace/btest.c) 165 | set_property (SOURCE libbacktrace/btest.c PROPERTY COMPILE_FLAGS "-g") 166 | target_link_libraries (btest backtrace) 167 | add_test (test-libbacktrace btest) 168 | add_executable (stest libbacktrace/stest.c) 169 | set_property (SOURCE libbacktrace/stest.c PROPERTY COMPILE_FLAGS "-g") 170 | target_link_libraries (stest backtrace) 171 | add_test (test-libbacktrace-sort stest) 172 | endif () 173 | 174 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | **UPDATE:** Ian Lance Taylor has now made a standalone version of his excellent libbacktrace available on GitHub! It is available here: https://github.com/ianlancetaylor/libbacktrace 2 | 3 | **Please use ILT's repository.** The only reason why you may find the current repository valuable is it uses CMake while TLT's repository uses automake/autoconf. 4 | 5 | This is a standalone version of libbacktrace. 6 | 7 | libbacktrace prints stack traces. 8 | 9 | libbacktrace was originally writen by Ian Lance Taylor as part of GCC. 10 | 11 | Building libbacktrace requires CMake. 12 | 13 | How to build with ninja: 14 | 15 | mkdir build 16 | cd build/ 17 | cmake -GNinja -DENABLE_LIBBACKTRACE_TEST=true path/to/libbacktrace/source 18 | ninja 19 | 20 | How to build with make: 21 | 22 | mkdir build 23 | cd build/ 24 | cmake -G'Unix Makefiles' -DENABLE_LIBBACKTRACE_TEST=true path/to/libbacktrace/source 25 | make 26 | 27 | How to run the tests: 28 | 29 | ctest 30 | -------------------------------------------------------------------------------- /auxincl/dwarf2.h: -------------------------------------------------------------------------------- 1 | /* dwarf2.h -- minimal GCC dwarf2.h replacement for libbacktrace 2 | Contributed by Alexander Monakov, ISP RAS 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | (1) Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | (2) Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in 13 | the documentation and/or other materials provided with the 14 | distribution. 15 | 16 | (3) The name of the author may not be used to 17 | endorse or promote products derived from this software without 18 | specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 24 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | POSSIBILITY OF SUCH DAMAGE. */ 31 | 32 | #ifndef BACKTRACE_AUX_DWARF2_H 33 | #define BACKTRACE_AUX_DWARF2_H 34 | 35 | /* Use the system header for the bulk of the definitions. */ 36 | #ifdef HAVE_LIBDWARF_DWARF_H 37 | #include 38 | #else 39 | #include 40 | #endif 41 | 42 | /* Provide stub enum tags. */ 43 | enum dwarf_attribute {_dummy_dwarf_attribute}; 44 | enum dwarf_form {_dummy_dwarf_form}; 45 | enum dwarf_tag {_dummy_dwarf_tag}; 46 | 47 | /* Define potentially missing enum values. */ 48 | #define DW_FORM_GNU_addr_index 0x1f01 49 | #define DW_FORM_GNU_str_index 0x1f02 50 | 51 | #define DW_FORM_GNU_ref_alt 0x1f20 52 | #define DW_FORM_GNU_strp_alt 0x1f21 53 | 54 | #define DW_LNS_extended_op 0 55 | 56 | #endif 57 | 58 | -------------------------------------------------------------------------------- /auxincl/filenames.h: -------------------------------------------------------------------------------- 1 | /* filenames.h -- minimal GCC filenames.h replacement for libbacktrace 2 | Contributed by Alexander Monakov, ISP RAS 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are 6 | met: 7 | 8 | (1) Redistributions of source code must retain the above copyright 9 | notice, this list of conditions and the following disclaimer. 10 | 11 | (2) Redistributions in binary form must reproduce the above copyright 12 | notice, this list of conditions and the following disclaimer in 13 | the documentation and/or other materials provided with the 14 | distribution. 15 | 16 | (3) The name of the author may not be used to 17 | endorse or promote products derived from this software without 18 | specific prior written permission. 19 | 20 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 22 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 23 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 24 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 25 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 28 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 29 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 | POSSIBILITY OF SUCH DAMAGE. */ 31 | 32 | #ifndef BACKTRACE_AUX_FILENAMES_H 33 | #define BACKTRACE_AUX_FILENAMES_H 34 | 35 | /* Assume POSIX paths. */ 36 | 37 | #define IS_DIR_SEPARATOR(c) ((c) == '/') 38 | #define IS_ABSOLUTE_PATH(f) ((f)[0] == '/') 39 | 40 | #endif 41 | 42 | -------------------------------------------------------------------------------- /examples/bt.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | struct bt_ctx { 6 | struct backtrace_state *state; 7 | int error; 8 | }; 9 | 10 | static void error_callback(void *data, const char *msg, int errnum) 11 | { 12 | struct bt_ctx *ctx = data; 13 | fprintf(stderr, "ERROR: %s (%d)", msg, errnum); 14 | ctx->error = 1; 15 | } 16 | 17 | static void syminfo_callback (void *data, uintptr_t pc, const char *symname, uintptr_t symval, uintptr_t symsize) 18 | { 19 | //struct bt_ctx *ctx = data; 20 | if (symname) { 21 | printf("%lx %s ??:0\n", (unsigned long)pc, symname); 22 | } else { 23 | printf("%lx ?? ??:0\n", (unsigned long)pc); 24 | } 25 | } 26 | 27 | static int full_callback(void *data, uintptr_t pc, const char *filename, int lineno, const char *function) 28 | { 29 | struct bt_ctx *ctx = data; 30 | if (function) { 31 | printf("%lx %s %s:%d\n", (unsigned long)pc, function, filename?filename:"??", lineno); 32 | } else { 33 | backtrace_syminfo (ctx->state, pc, syminfo_callback, error_callback, data); 34 | } 35 | return 0; 36 | } 37 | 38 | static int simple_callback(void *data, uintptr_t pc) 39 | { 40 | struct bt_ctx *ctx = data; 41 | backtrace_pcinfo(ctx->state, pc, full_callback, error_callback, data); 42 | return 0; 43 | } 44 | 45 | static inline void bt(struct backtrace_state *state) 46 | { 47 | struct bt_ctx ctx = {state, 0}; 48 | backtrace_print(state, 0, stdout); 49 | backtrace_simple(state, 0, simple_callback, error_callback, &ctx); 50 | } 51 | 52 | int main(int argc, char *argv[]) 53 | { 54 | struct backtrace_state *state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS, error_callback, NULL); 55 | bt(state); 56 | return 0; 57 | } 58 | -------------------------------------------------------------------------------- /libbacktrace/ChangeLog: -------------------------------------------------------------------------------- 1 | 2014-10-23 Ian Lance Taylor 2 | 3 | * internal.h (backtrace_atomic_load_pointer) [no atomic or sync]: 4 | Fix to return void *. 5 | 6 | 2014-05-08 Ian Lance Taylor 7 | 8 | * mmap.c (backtrace_free): If freeing a large aligned block of 9 | memory, call munmap rather than holding onto it. 10 | (backtrace_vector_grow): When growing a vector, double the number 11 | of pages requested. When releasing the old version of a grown 12 | vector, pass the correct size to backtrace_free. 13 | 14 | 2014-03-07 Ian Lance Taylor 15 | 16 | * sort.c (backtrace_qsort): Use middle element as pivot. 17 | 18 | 2014-03-06 Ian Lance Taylor 19 | 20 | * sort.c: New file. 21 | * stest.c: New file. 22 | * internal.h (backtrace_qsort): Declare. 23 | * dwarf.c (read_abbrevs): Call backtrace_qsort instead of qsort. 24 | (read_line_info, read_function_entry): Likewise. 25 | (read_function_info, build_dwarf_data): Likewise. 26 | * elf.c (elf_initialize_syminfo): Likewise. 27 | * Makefile.am (libbacktrace_la_SOURCES): Add sort.c. 28 | (stest_SOURCES, stest_LDADD): Define. 29 | (check_PROGRAMS): Add stest. 30 | 31 | 2014-02-07 Misty De Meo 32 | 33 | PR target/58710 34 | * configure.ac: Use AC_LINK_IFELSE in check for 35 | _Unwind_GetIPInfo. 36 | * configure: Regenerate. 37 | 38 | 2014-01-02 Richard Sandiford 39 | 40 | Update copyright years 41 | 42 | 2013-12-06 Jakub Jelinek 43 | 44 | * elf.c (ET_DYN): Undefine and define again. 45 | (elf_add): Add exe argument, if true and ehdr.e_type is ET_DYN, 46 | return early -1 without closing the descriptor. 47 | (struct phdr_data): Add exe_descriptor. 48 | (phdr_callback): If pd->exe_descriptor is not -1, for very first 49 | call if dlpi_name is NULL just call elf_add with the exe_descriptor, 50 | otherwise backtrace_close the exe_descriptor if not -1. Adjust 51 | call to elf_add. 52 | (backtrace_initialize): Adjust call to elf_add. If it returns 53 | -1, set pd.exe_descriptor to descriptor, otherwise set it to -1. 54 | 55 | 2013-12-05 Ian Lance Taylor 56 | 57 | * alloc.c (backtrace_vector_finish): Add error_callback and data 58 | parameters. Call backtrace_vector_release. Return address base. 59 | * mmap.c (backtrace_vector_finish): Add error_callback and data 60 | parameters. Return address base. 61 | * dwarf.c (read_function_info): Get new address base from 62 | backtrace_vector_finish. 63 | * internal.h (backtrace_vector_finish): Update declaration. 64 | 65 | 2013-11-27 Ian Lance Taylor 66 | 67 | * dwarf.c (find_address_ranges): New static function, broken out 68 | of build_address_map. 69 | (build_address_map): Call it. 70 | * btest.c (check): Check for missing filename or function, rather 71 | than crashing. 72 | (f3): Check that enough frames were returned. 73 | 74 | 2013-11-19 Jakub Jelinek 75 | 76 | * backtrace.h (backtrace_syminfo_callback): Add symsize argument. 77 | * elf.c (elf_syminfo): Pass 0 or sym->size to the callback as 78 | last argument. 79 | * btest.c (struct symdata): Add size field. 80 | (callback_three): Add symsize argument. Copy it to the data->size 81 | field. 82 | (f23): Set symdata.size to 0. 83 | (test5): Likewise. If sizeof (int) > 1, lookup address of 84 | ((uintptr_t) &global) + 1. Verify symdata.val and symdata.size 85 | values. 86 | 87 | * atomic.c: Include sys/types.h. 88 | 89 | 2013-11-18 Ian Lance Taylor 90 | 91 | * configure.ac: Check for support of __atomic extensions. 92 | * internal.h: Declare or #define atomic functions for use in 93 | backtrace code. 94 | * atomic.c: New file. 95 | * dwarf.c (dwarf_lookup_pc): Use atomic functions. 96 | (dwarf_fileline, backtrace_dwarf_add): Likewise. 97 | * elf.c (elf_add_syminfo_data, elf_syminfo): Likewise. 98 | (backtrace_initialize): Likewise. 99 | * fileline.c (fileline_initialize): Likewise. 100 | * Makefile.am (libbacktrace_la_SOURCES): Add atomic.c. 101 | * configure, config.h.in, Makefile.in: Rebuild. 102 | 103 | 2013-11-18 Jakub Jelinek 104 | 105 | * elf.c (SHN_UNDEF): Define. 106 | (elf_initialize_syminfo): Add base_address argument. Ignore symbols 107 | with st_shndx == SHN_UNDEF. Add base_address to address fields. 108 | (elf_add): Adjust caller. 109 | 110 | * elf.c (phdr_callback): Process info->dlpi_addr == 0 normally. 111 | 112 | 2013-11-16 Ian Lance Taylor 113 | 114 | * backtrace.h (backtrace_create_state): Correct comment about 115 | threading. 116 | 117 | 2013-11-15 Ian Lance Taylor 118 | 119 | * backtrace.h (backtrace_syminfo): Update comment and parameter 120 | name to take any address, not just a PC value. 121 | * elf.c (STT_OBJECT): Define. 122 | (elf_nosyms): Rename parameter pc to addr. 123 | (elf_symbol_search): Rename local variable pc to addr. 124 | (elf_initialize_syminfo): Add STT_OBJECT symbols to elf_symbols. 125 | (elf_syminfo): Rename parameter pc to addr. 126 | * btest.c (global): New global variable. 127 | (test5): New test. 128 | (main): Call test5. 129 | 130 | 2013-10-17 Ian Lance Taylor 131 | 132 | * elf.c (elf_add): Don't get the wrong offsets if a debug section 133 | is missing. 134 | 135 | 2013-10-15 David Malcolm 136 | 137 | * configure.ac: Add --enable-host-shared, setting up 138 | pre-existing PIC_FLAG variable within Makefile.am et al. 139 | * configure: Regenerate. 140 | 141 | 2013-09-20 Alan Modra 142 | 143 | * configure: Regenerate. 144 | 145 | 2013-07-23 Alexander Monakov 146 | 147 | * elf.c (elf_syminfo): Loop over the elf_syminfo_data chain. 148 | 149 | 2013-07-23 Alexander Monakov 150 | 151 | * elf.c (backtrace_initialize): Pass elf_fileline_fn to 152 | dl_iterate_phdr callbacks. 153 | 154 | 2013-03-25 Ian Lance Taylor 155 | 156 | * alloc.c: #include . 157 | * mmap.c: Likewise. 158 | 159 | 2013-01-31 Ian Lance Taylor 160 | 161 | * dwarf.c (read_function_info): Permit fvec parameter to be NULL. 162 | (dwarf_lookup_pc): Don't use ddata->fvec if threaded. 163 | 164 | 2013-01-25 Jakub Jelinek 165 | 166 | PR other/56076 167 | * dwarf.c (read_line_header): Don't crash if DW_AT_comp_dir 168 | attribute was not seen. 169 | 170 | 2013-01-16 Ian Lance Taylor 171 | 172 | * dwarf.c (struct unit): Add filename and abs_filename fields. 173 | (build_address_map): Set new fields when reading unit. 174 | (dwarf_lookup_pc): If we don't find an entry in the line table, 175 | just return the main file name. 176 | 177 | 2013-01-14 Richard Sandiford 178 | 179 | Update copyright years. 180 | 181 | 2013-01-01 Ian Lance Taylor 182 | 183 | PR bootstrap/54834 184 | * Makefile.am (AM_CPPFLAGS): Remove -I ../gcc/include and -I 185 | $(MULTIBUILDTOP)/../../gcc/include. 186 | * Makefile.in: Rebuild. 187 | 188 | 2013-01-01 Ian Lance Taylor 189 | 190 | PR other/55536 191 | * mmap.c (backtrace_alloc): Don't call sync functions if not 192 | threaded. 193 | (backtrace_free): Likewise. 194 | 195 | 2012-12-12 John David Anglin 196 | 197 | * mmapio.c: Define MAP_FAILED if not defined. 198 | 199 | 2012-12-11 Jakub Jelinek 200 | 201 | PR bootstrap/54926 202 | * Makefile.am (AM_CFLAGS): Remove -frandom-seed=$@. 203 | * configure.ac: If --with-target-subdir, add -frandom-seed=$@ 204 | to EXTRA_FLAGS unconditionally, otherwise check whether the compiler 205 | accepts it. 206 | * Makefile.in: Regenerated. 207 | * configure: Regenerated. 208 | 209 | 2012-12-07 Jakub Jelinek 210 | 211 | PR bootstrap/54926 212 | * Makefile.am (AM_CFLAGS): Add -frandom-seed=$@. 213 | * Makefile.in: Regenerated. 214 | 215 | 2012-11-20 Ian Lance Taylor 216 | 217 | * dwarf.c (read_attribute): Always clear val. 218 | 219 | 2012-11-13 Ian Lance Taylor 220 | 221 | PR other/55312 222 | * configure.ac: Only add -Werror if building a target library. 223 | * configure: Rebuild. 224 | 225 | 2012-11-12 Ian Lance Taylor 226 | Rainer Orth 227 | Gerald Pfeifer 228 | 229 | * configure.ac: Check for getexecname. 230 | * fileline.c: #include . Define getexecname if not 231 | available. 232 | (fileline_initialize): Try to find the executable in a few 233 | different ways. 234 | * print.c (error_callback): Only print the filename if it came 235 | from the backtrace state. 236 | * configure, config.h.in: Rebuild. 237 | 238 | 2012-10-29 Ian Lance Taylor 239 | 240 | * mmap.c (backtrace_vector_release): Correct last patch: add 241 | aligned, not size. 242 | 243 | 2012-10-29 Ian Lance Taylor 244 | 245 | * mmap.c (backtrace_vector_release): Make sure freed block is 246 | aligned on 8-byte boundary. 247 | 248 | 2012-10-26 Ian Lance Taylor 249 | 250 | PR other/55087 251 | * posix.c (backtrace_open): Add does_not_exist parameter. 252 | * elf.c (phdr_callback): Do not warn if shared library could not 253 | be opened. 254 | * fileline.c (fileline_initialize): Update calls to 255 | backtrace_open. 256 | * internal.h (backtrace_open): Update declaration. 257 | 258 | 2012-10-26 Jack Howarth 259 | 260 | PR target/55061 261 | * configure.ac: Check for _Unwind_GetIPInfo function declaration. 262 | * configure: Regenerate. 263 | 264 | 2012-10-24 Ian Lance Taylor 265 | 266 | PR target/55061 267 | * configure.ac: Check whether -funwind-tables option works. 268 | * configure: Rebuild. 269 | 270 | 2012-10-11 Ian Lance Taylor 271 | 272 | * configure.ac: Do not use dl_iterate_phdr on Solaris 10. 273 | * configure: Rebuild. 274 | 275 | 2012-10-10 Ian Lance Taylor 276 | 277 | * elf.c: Rename all Elf typedefs to start with b_elf, and be all 278 | lower case. 279 | 280 | 2012-10-10 Hans-Peter Nilsson 281 | 282 | * elf.c (elf_add_syminfo_data): Add casts to avoid warning. 283 | 284 | 2012-10-09 Ian Lance Taylor 285 | 286 | * dwarf.c (dwarf_fileline): Add cast to avoid warning. 287 | (backtrace_dwarf_add): Likewise. 288 | 289 | 2012-10-09 Ian Lance Taylor 290 | 291 | Add support for tracing through shared libraries. 292 | * configure.ac: Check for link.h and dl_iterate_phdr. 293 | * elf.c: #include if system has dl_iterate_phdr. #undef 294 | ELF macros before #defining them. 295 | (dl_phdr_info, dl_iterate_phdr): Define if system does not have 296 | dl_iterate_phdr. 297 | (struct elf_syminfo_data): Add next field. 298 | (elf_initialize_syminfo): Initialize next field. 299 | (elf_add_syminfo_data): New static function. 300 | (elf_add): New static function, broken out of 301 | backtrace_initialize. Call backtrace_dwarf_add instead of 302 | backtrace_dwarf_initialize. 303 | (struct phdr_data): Define. 304 | (phdr_callback): New static function. 305 | (backtrace_initialize): Call elf_add. 306 | * dwarf.c (struct dwarf_data): Add next and base_address fields. 307 | (add_unit_addr): Add base_address parameter. Change all callers. 308 | (add_unit_ranges, build_address_map): Likewise. 309 | (add_line): Add ddata parameter. Change all callers. 310 | (read_line_program, add_function_range): Likewise. 311 | (dwarf_lookup_pc): New static function, broken out of 312 | dwarf_fileline. 313 | (dwarf_fileline): Call dwarf_lookup_pc. 314 | (build_dwarf_data): New static function. 315 | (backtrace_dwarf_add): New function. 316 | (backtrace_dwarf_initialize): Remove. 317 | * internal.h (backtrace_dwarf_initialize): Don't declare. 318 | (backtrace_dwarf_add): Declare. 319 | * configure, config.h.in: Rebuild. 320 | 321 | 2012-10-04 Gerald Pfeifer 322 | 323 | * btest.c (f23): Avoid uninitialized variable warning. 324 | 325 | 2012-10-04 Ian Lance Taylor 326 | 327 | * dwarf.c: If the system header files do not declare strnlen, 328 | provide our own version. 329 | 330 | 2012-10-03 Ian Lance Taylor 331 | 332 | * dwarf.c (read_uleb128): Fix overflow test. 333 | (read_sleb128): Likewise. 334 | (build_address_map): Don't change unit_buf.start. 335 | 336 | 2012-10-02 Uros Bizjak 337 | 338 | PR other/54761 339 | * configure.ac (EXTRA_FLAGS): New. 340 | * Makefile.am (AM_FLAGS): Add $(EXTRA_FLAGS). 341 | * configure, Makefile.in: Regenerate. 342 | 343 | 2012-09-29 Ian Lance Taylor 344 | 345 | PR other/54749 346 | * fileline.c (fileline_initialize): Pass errnum as -1 when 347 | reporting that we could not read executable information after a 348 | previous failure. 349 | 350 | 2012-09-27 Ian Lance Taylor 351 | 352 | PR bootstrap/54732 353 | * configure.ac: Add no-dependencies to AM_INIT_AUTOMAKE. 354 | * Makefile.am: Add dependencies for all objects. 355 | * configure, aclocal.m4, Makefile.in: Rebuild. 356 | 357 | 2012-09-27 Ian Lance Taylor 358 | 359 | PR other/54726 360 | * elf.c (backtrace_initialize): Set *fileln_fn, not 361 | state->fileln_fn. 362 | 363 | 2012-09-19 Ian Lance Taylor 364 | 365 | * configure.ac: Only use GCC_CHECK_UNWIND_GETIPINFO when compiled 366 | as a target library. 367 | * configure: Rebuild. 368 | 369 | 2012-09-19 Rainer Orth 370 | Ian Lance Taylor 371 | 372 | * configure.ac (GCC_HEADER_STDINT): Invoke. 373 | * backtrace.h: If we can't find , use "gstdint.h". 374 | * btest.c: Don't include . 375 | * dwarf.c: Likewise. 376 | * configure, aclocal.m4, Makefile.in, config.h.in: Rebuild. 377 | 378 | 2012-09-18 Ian Lance Taylor 379 | 380 | PR bootstrap/54623 381 | * Makefile.am (AM_CPPFLAGS): Define. 382 | (AM_CFLAGS): Remove -I options. 383 | * Makefile.in: Rebuild. 384 | 385 | 2012-09-18 Ian Lance Taylor 386 | 387 | * posix.c (O_BINARY): Define if not defined. 388 | (backtrace_open): Pass O_BINARY to open. Only call fcntl if 389 | HAVE_FCNTL is defined. 390 | * configure.ac: Test for the fcntl function. 391 | * configure, config.h.in: Rebuild. 392 | 393 | 2012-09-18 Ian Lance Taylor 394 | 395 | * btest.c (test1, test2, test3, test4): Add the unused attribute. 396 | 397 | 2012-09-18 Ian Lance Taylor 398 | 399 | * dwarf.c: Correct test of HAVE_DECL_STRNLEN. 400 | 401 | 2012-09-18 Ian Lance Taylor 402 | 403 | * configure.ac: Add AC_USE_SYSTEM_EXTENSIONS. 404 | * mmapio.c: Don't define _GNU_SOURCE. 405 | * configure, config.h.in: Rebuild. 406 | 407 | 2012-09-18 Ian Lance Taylor 408 | 409 | * configure.ac: Check whether strnlen is declared. 410 | * dwarf.c: Declare strnlen if not declared. 411 | * configure, config.h.in: Rebuild. 412 | 413 | 2012-09-18 Rainer Orth 414 | 415 | * fileline.c: Include . 416 | * mmap.c: Likewise. 417 | 418 | 2012-09-17 Ian Lance Taylor 419 | 420 | PR bootstrap/54611 421 | * nounwind.c (backtrace_full): Rename from backtrace. Add state 422 | parameter. 423 | 424 | 2012-09-17 Gerald Pfeifer 425 | 426 | PR bootstrap/54611 427 | * nounwind.c (backtrace_simple): Add state parameter. 428 | 429 | 2012-09-17 Ian Lance Taylor 430 | 431 | PR bootstrap/54609 432 | * unknown.c (unknown_fileline): Add state parameter, remove 433 | fileline_data parameter, name error_callback parameter. 434 | (backtrace_initialize): Add state parameter. 435 | 436 | 2012-09-17 Ian Lance Taylor 437 | 438 | * Initial implementation. 439 | -------------------------------------------------------------------------------- /libbacktrace/README: -------------------------------------------------------------------------------- 1 | The libbacktrace library 2 | Initially written by Ian Lance Taylor 3 | 4 | The libbacktrace library may be linked into a program or library and 5 | used to produce symbolic backtraces. Sample uses would be to print a 6 | detailed backtrace when an error occurs or to gather detailed 7 | profiling information. 8 | 9 | The libbacktrace library is provided under a BSD license. See the 10 | source files for the exact license text. 11 | 12 | The public functions are declared and documented in the header file 13 | backtrace.h, which should be #include'd by a user of the library. 14 | 15 | Building libbacktrace will generate a file backtrace-supported.h, 16 | which a user of the library may use to determine whether backtraces 17 | will work. See the source file backtrace-supported.h.in for the 18 | macros that it defines. 19 | 20 | As of September 2012, libbacktrace only supports ELF executables with 21 | DWARF debugging information. The library is written to make it 22 | straightforward to add support for other object file and debugging 23 | formats. 24 | -------------------------------------------------------------------------------- /libbacktrace/alloc.c: -------------------------------------------------------------------------------- 1 | /* alloc.c -- Memory allocation without mmap. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #include "backtrace.h" 40 | #include "internal.h" 41 | 42 | /* Allocation routines to use on systems that do not support anonymous 43 | mmap. This implementation just uses malloc, which means that the 44 | backtrace functions may not be safely invoked from a signal 45 | handler. */ 46 | 47 | /* Allocate memory like malloc. */ 48 | 49 | void * 50 | backtrace_alloc (struct backtrace_state *state ATTRIBUTE_UNUSED, 51 | size_t size, backtrace_error_callback error_callback, 52 | void *data) 53 | { 54 | void *ret; 55 | 56 | ret = malloc (size); 57 | if (ret == NULL) 58 | error_callback (data, "malloc", errno); 59 | return ret; 60 | } 61 | 62 | /* Free memory. */ 63 | 64 | void 65 | backtrace_free (struct backtrace_state *state ATTRIBUTE_UNUSED, 66 | void *p, size_t size ATTRIBUTE_UNUSED, 67 | backtrace_error_callback error_callback ATTRIBUTE_UNUSED, 68 | void *data ATTRIBUTE_UNUSED) 69 | { 70 | free (p); 71 | } 72 | 73 | /* Grow VEC by SIZE bytes. */ 74 | 75 | void * 76 | backtrace_vector_grow (struct backtrace_state *state ATTRIBUTE_UNUSED, 77 | size_t size, backtrace_error_callback error_callback, 78 | void *data, struct backtrace_vector *vec) 79 | { 80 | void *ret; 81 | 82 | if (size > vec->alc) 83 | { 84 | size_t alc; 85 | void *base; 86 | 87 | if (vec->size == 0) 88 | alc = 32 * size; 89 | else if (vec->size >= 4096) 90 | alc = vec->size + 4096; 91 | else 92 | alc = 2 * vec->size; 93 | 94 | if (alc < vec->size + size) 95 | alc = vec->size + size; 96 | 97 | base = realloc (vec->base, alc); 98 | if (base == NULL) 99 | { 100 | error_callback (data, "realloc", errno); 101 | return NULL; 102 | } 103 | 104 | vec->base = base; 105 | vec->alc = alc - vec->size; 106 | } 107 | 108 | ret = (char *) vec->base + vec->size; 109 | vec->size += size; 110 | vec->alc -= size; 111 | return ret; 112 | } 113 | 114 | /* Finish the current allocation on VEC. */ 115 | 116 | void * 117 | backtrace_vector_finish (struct backtrace_state *state, 118 | struct backtrace_vector *vec, 119 | backtrace_error_callback error_callback, 120 | void *data) 121 | { 122 | void *ret; 123 | 124 | /* With this allocator we call realloc in backtrace_vector_grow, 125 | which means we can't easily reuse the memory here. So just 126 | release it. */ 127 | if (!backtrace_vector_release (state, vec, error_callback, data)) 128 | return NULL; 129 | ret = vec->base; 130 | vec->base = NULL; 131 | vec->size = 0; 132 | vec->alc = 0; 133 | return ret; 134 | } 135 | 136 | /* Release any extra space allocated for VEC. */ 137 | 138 | int 139 | backtrace_vector_release (struct backtrace_state *state ATTRIBUTE_UNUSED, 140 | struct backtrace_vector *vec, 141 | backtrace_error_callback error_callback, 142 | void *data) 143 | { 144 | vec->base = realloc (vec->base, vec->size); 145 | if (vec->base == NULL) 146 | { 147 | error_callback (data, "realloc", errno); 148 | return 0; 149 | } 150 | vec->alc = 0; 151 | return 1; 152 | } 153 | -------------------------------------------------------------------------------- /libbacktrace/atomic.c: -------------------------------------------------------------------------------- 1 | /* atomic.c -- Support for atomic functions if not present. 2 | Copyright (C) 2013-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | 37 | #include "backtrace.h" 38 | #include "backtrace-supported.h" 39 | #include "internal.h" 40 | 41 | /* This file holds implementations of the atomic functions that are 42 | used if the host compiler has the sync functions but not the atomic 43 | functions, as is true of versions of GCC before 4.7. */ 44 | 45 | #if !defined (HAVE_ATOMIC_FUNCTIONS) && defined (HAVE_SYNC_FUNCTIONS) 46 | 47 | /* Do an atomic load of a pointer. */ 48 | 49 | void * 50 | backtrace_atomic_load_pointer (void *arg) 51 | { 52 | void **pp; 53 | void *p; 54 | 55 | pp = (void **) arg; 56 | p = *pp; 57 | while (!__sync_bool_compare_and_swap (pp, p, p)) 58 | p = *pp; 59 | return p; 60 | } 61 | 62 | /* Do an atomic load of an int. */ 63 | 64 | int 65 | backtrace_atomic_load_int (int *p) 66 | { 67 | int i; 68 | 69 | i = *p; 70 | while (!__sync_bool_compare_and_swap (p, i, i)) 71 | i = *p; 72 | return i; 73 | } 74 | 75 | /* Do an atomic store of a pointer. */ 76 | 77 | void 78 | backtrace_atomic_store_pointer (void *arg, void *p) 79 | { 80 | void **pp; 81 | void *old; 82 | 83 | pp = (void **) arg; 84 | old = *pp; 85 | while (!__sync_bool_compare_and_swap (pp, old, p)) 86 | old = *pp; 87 | } 88 | 89 | /* Do an atomic store of a size_t value. */ 90 | 91 | void 92 | backtrace_atomic_store_size_t (size_t *p, size_t v) 93 | { 94 | size_t old; 95 | 96 | old = *p; 97 | while (!__sync_bool_compare_and_swap (p, old, v)) 98 | old = *p; 99 | } 100 | 101 | /* Do an atomic store of a int value. */ 102 | 103 | void 104 | backtrace_atomic_store_int (int *p, int v) 105 | { 106 | size_t old; 107 | 108 | old = *p; 109 | while (!__sync_bool_compare_and_swap (p, old, v)) 110 | old = *p; 111 | } 112 | 113 | #endif 114 | -------------------------------------------------------------------------------- /libbacktrace/backtrace-supported.h.in: -------------------------------------------------------------------------------- 1 | /* backtrace-supported.h.in -- Whether stack backtrace is supported. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | /* The file backtrace-supported.h.in is used by configure to generate 34 | the file backtrace-supported.h. The file backtrace-supported.h may 35 | be #include'd to see whether the backtrace library will be able to 36 | get a backtrace and produce symbolic information. */ 37 | 38 | 39 | /* BACKTRACE_SUPPORTED will be #define'd as 1 if the backtrace library 40 | should work, 0 if it will not. Libraries may #include this to make 41 | other arrangements. */ 42 | 43 | #define BACKTRACE_SUPPORTED @BACKTRACE_SUPPORTED@ 44 | 45 | /* BACKTRACE_USES_MALLOC will be #define'd as 1 if the backtrace 46 | library will call malloc as it works, 0 if it will call mmap 47 | instead. This may be used to determine whether it is safe to call 48 | the backtrace functions from a signal handler. In general this 49 | only applies to calls like backtrace and backtrace_pcinfo. It does 50 | not apply to backtrace_simple, which never calls malloc. It does 51 | not apply to backtrace_print, which always calls fprintf and 52 | therefore malloc. */ 53 | 54 | #define BACKTRACE_USES_MALLOC @BACKTRACE_USES_MALLOC@ 55 | 56 | /* BACKTRACE_SUPPORTS_THREADS will be #define'd as 1 if the backtrace 57 | library is configured with threading support, 0 if not. If this is 58 | 0, the threaded parameter to backtrace_create_state must be passed 59 | as 0. */ 60 | 61 | #define BACKTRACE_SUPPORTS_THREADS @BACKTRACE_SUPPORTS_THREADS@ 62 | -------------------------------------------------------------------------------- /libbacktrace/backtrace.c: -------------------------------------------------------------------------------- 1 | /* backtrace.c -- Entry point for stack backtrace library. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include "unwind.h" 36 | #include "backtrace.h" 37 | 38 | /* The main backtrace_full routine. */ 39 | 40 | /* Data passed through _Unwind_Backtrace. */ 41 | 42 | struct backtrace_data 43 | { 44 | /* Number of frames to skip. */ 45 | int skip; 46 | /* Library state. */ 47 | struct backtrace_state *state; 48 | /* Callback routine. */ 49 | backtrace_full_callback callback; 50 | /* Error callback routine. */ 51 | backtrace_error_callback error_callback; 52 | /* Data to pass to callback routines. */ 53 | void *data; 54 | /* Value to return from backtrace_full. */ 55 | int ret; 56 | }; 57 | 58 | /* Unwind library callback routine. This is passed to 59 | _Unwind_Backtrace. */ 60 | 61 | static _Unwind_Reason_Code 62 | unwind (struct _Unwind_Context *context, void *vdata) 63 | { 64 | struct backtrace_data *bdata = (struct backtrace_data *) vdata; 65 | uintptr_t pc; 66 | int ip_before_insn = 0; 67 | 68 | #ifdef HAVE_GETIPINFO 69 | pc = _Unwind_GetIPInfo (context, &ip_before_insn); 70 | #else 71 | pc = _Unwind_GetIP (context); 72 | #endif 73 | 74 | if (bdata->skip > 0) 75 | { 76 | --bdata->skip; 77 | return _URC_NO_REASON; 78 | } 79 | 80 | if (!ip_before_insn) 81 | --pc; 82 | 83 | bdata->ret = backtrace_pcinfo (bdata->state, pc, bdata->callback, 84 | bdata->error_callback, bdata->data); 85 | if (bdata->ret != 0) 86 | return _URC_END_OF_STACK; 87 | 88 | return _URC_NO_REASON; 89 | } 90 | 91 | /* Get a stack backtrace. */ 92 | 93 | int 94 | backtrace_full (struct backtrace_state *state, int skip, 95 | backtrace_full_callback callback, 96 | backtrace_error_callback error_callback, void *data) 97 | { 98 | struct backtrace_data bdata; 99 | 100 | bdata.skip = skip + 1; 101 | bdata.state = state; 102 | bdata.callback = callback; 103 | bdata.error_callback = error_callback; 104 | bdata.data = data; 105 | bdata.ret = 0; 106 | _Unwind_Backtrace (unwind, &bdata); 107 | return bdata.ret; 108 | } 109 | -------------------------------------------------------------------------------- /libbacktrace/backtrace.h: -------------------------------------------------------------------------------- 1 | /* backtrace.h -- Public header file for stack backtrace library. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #ifndef BACKTRACE_H 34 | #define BACKTRACE_H 35 | 36 | #include 37 | #include 38 | 39 | /* We want to get a definition for uintptr_t, but we still care about 40 | systems that don't have . */ 41 | #if defined(__GLIBC__) && __GLIBC__ >= 2 42 | 43 | #include 44 | 45 | #elif defined(HAVE_STDINT_H) 46 | 47 | #include 48 | 49 | #else 50 | 51 | /* Systems that don't have must provide gstdint.h, e.g., 52 | from GCC_HEADER_STDINT in configure.ac. */ 53 | #include "gstdint.h" 54 | 55 | #endif 56 | 57 | #ifdef __cplusplus 58 | extern "C" { 59 | #endif 60 | 61 | /* The backtrace state. This struct is intentionally not defined in 62 | the public interface. */ 63 | 64 | struct backtrace_state; 65 | 66 | /* The type of the error callback argument to backtrace functions. 67 | This function, if not NULL, will be called for certain error cases. 68 | The DATA argument is passed to the function that calls this one. 69 | The MSG argument is an error message. The ERRNUM argument, if 70 | greater than 0, holds an errno value. The MSG buffer may become 71 | invalid after this function returns. 72 | 73 | As a special case, the ERRNUM argument will be passed as -1 if no 74 | debug info can be found for the executable, but the function 75 | requires debug info (e.g., backtrace_full, backtrace_pcinfo). The 76 | MSG in this case will be something along the lines of "no debug 77 | info". Similarly, ERRNUM will be passed as -1 if there is no 78 | symbol table, but the function requires a symbol table (e.g., 79 | backtrace_syminfo). This may be used as a signal that some other 80 | approach should be tried. */ 81 | 82 | typedef void (*backtrace_error_callback) (void *data, const char *msg, 83 | int errnum); 84 | 85 | /* Create state information for the backtrace routines. This must be 86 | called before any of the other routines, and its return value must 87 | be passed to all of the other routines. FILENAME is the path name 88 | of the executable file; if it is NULL the library will try 89 | system-specific path names. If not NULL, FILENAME must point to a 90 | permanent buffer. If THREADED is non-zero the state may be 91 | accessed by multiple threads simultaneously, and the library will 92 | use appropriate atomic operations. If THREADED is zero the state 93 | may only be accessed by one thread at a time. This returns a state 94 | pointer on success, NULL on error. If an error occurs, this will 95 | call the ERROR_CALLBACK routine. */ 96 | 97 | extern struct backtrace_state *backtrace_create_state ( 98 | const char *filename, int threaded, 99 | backtrace_error_callback error_callback, void *data); 100 | 101 | /* The type of the callback argument to the backtrace_full function. 102 | DATA is the argument passed to backtrace_full. PC is the program 103 | counter. FILENAME is the name of the file containing PC, or NULL 104 | if not available. LINENO is the line number in FILENAME containing 105 | PC, or 0 if not available. FUNCTION is the name of the function 106 | containing PC, or NULL if not available. This should return 0 to 107 | continuing tracing. The FILENAME and FUNCTION buffers may become 108 | invalid after this function returns. */ 109 | 110 | typedef int (*backtrace_full_callback) (void *data, uintptr_t pc, 111 | const char *filename, int lineno, 112 | const char *function); 113 | 114 | /* Get a full stack backtrace. SKIP is the number of frames to skip; 115 | passing 0 will start the trace with the function calling 116 | backtrace_full. DATA is passed to the callback routine. If any 117 | call to CALLBACK returns a non-zero value, the stack backtrace 118 | stops, and backtrace returns that value; this may be used to limit 119 | the number of stack frames desired. If all calls to CALLBACK 120 | return 0, backtrace returns 0. The backtrace_full function will 121 | make at least one call to either CALLBACK or ERROR_CALLBACK. This 122 | function requires debug info for the executable. */ 123 | 124 | extern int backtrace_full (struct backtrace_state *state, int skip, 125 | backtrace_full_callback callback, 126 | backtrace_error_callback error_callback, 127 | void *data); 128 | 129 | /* The type of the callback argument to the backtrace_simple function. 130 | DATA is the argument passed to simple_backtrace. PC is the program 131 | counter. This should return 0 to continue tracing. */ 132 | 133 | typedef int (*backtrace_simple_callback) (void *data, uintptr_t pc); 134 | 135 | /* Get a simple backtrace. SKIP is the number of frames to skip, as 136 | in backtrace. DATA is passed to the callback routine. If any call 137 | to CALLBACK returns a non-zero value, the stack backtrace stops, 138 | and backtrace_simple returns that value. Otherwise 139 | backtrace_simple returns 0. The backtrace_simple function will 140 | make at least one call to either CALLBACK or ERROR_CALLBACK. This 141 | function does not require any debug info for the executable. */ 142 | 143 | extern int backtrace_simple (struct backtrace_state *state, int skip, 144 | backtrace_simple_callback callback, 145 | backtrace_error_callback error_callback, 146 | void *data); 147 | 148 | /* Print the current backtrace in a user readable format to a FILE. 149 | SKIP is the number of frames to skip, as in backtrace_full. Any 150 | error messages are printed to stderr. This function requires debug 151 | info for the executable. */ 152 | 153 | extern void backtrace_print (struct backtrace_state *state, int skip, FILE *); 154 | 155 | /* Given PC, a program counter in the current program, call the 156 | callback function with filename, line number, and function name 157 | information. This will normally call the callback function exactly 158 | once. However, if the PC happens to describe an inlined call, and 159 | the debugging information contains the necessary information, then 160 | this may call the callback function multiple times. This will make 161 | at least one call to either CALLBACK or ERROR_CALLBACK. This 162 | returns the first non-zero value returned by CALLBACK, or 0. */ 163 | 164 | extern int backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc, 165 | backtrace_full_callback callback, 166 | backtrace_error_callback error_callback, 167 | void *data); 168 | 169 | /* The type of the callback argument to backtrace_syminfo. DATA and 170 | PC are the arguments passed to backtrace_syminfo. SYMNAME is the 171 | name of the symbol for the corresponding code. SYMVAL is the 172 | value and SYMSIZE is the size of the symbol. SYMNAME will be NULL 173 | if no error occurred but the symbol could not be found. */ 174 | 175 | typedef void (*backtrace_syminfo_callback) (void *data, uintptr_t pc, 176 | const char *symname, 177 | uintptr_t symval, 178 | uintptr_t symsize); 179 | 180 | /* Given ADDR, an address or program counter in the current program, 181 | call the callback information with the symbol name and value 182 | describing the function or variable in which ADDR may be found. 183 | This will call either CALLBACK or ERROR_CALLBACK exactly once. 184 | This returns 1 on success, 0 on failure. This function requires 185 | the symbol table but does not require the debug info. Note that if 186 | the symbol table is present but ADDR could not be found in the 187 | table, CALLBACK will be called with a NULL SYMNAME argument. 188 | Returns 1 on success, 0 on error. */ 189 | 190 | extern int backtrace_syminfo (struct backtrace_state *state, uintptr_t addr, 191 | backtrace_syminfo_callback callback, 192 | backtrace_error_callback error_callback, 193 | void *data); 194 | 195 | #ifdef __cplusplus 196 | } /* End extern "C". */ 197 | #endif 198 | 199 | #endif 200 | -------------------------------------------------------------------------------- /libbacktrace/btest.c: -------------------------------------------------------------------------------- 1 | /* btest.c -- Test for libbacktrace library 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | /* This program tests the externally visible interfaces of the 34 | libbacktrace library. */ 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include "filenames.h" 42 | 43 | #include "backtrace.h" 44 | #include "backtrace-supported.h" 45 | 46 | /* Portable attribute syntax. Actually some of these tests probably 47 | won't work if the attributes are not recognized. */ 48 | 49 | #ifndef GCC_VERSION 50 | # define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) 51 | #endif 52 | 53 | #if (GCC_VERSION < 2007) 54 | # define __attribute__(x) 55 | #endif 56 | 57 | #ifndef ATTRIBUTE_UNUSED 58 | # define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) 59 | #endif 60 | 61 | /* Used to collect backtrace info. */ 62 | 63 | struct info 64 | { 65 | char *filename; 66 | int lineno; 67 | char *function; 68 | }; 69 | 70 | /* Passed to backtrace callback function. */ 71 | 72 | struct bdata 73 | { 74 | struct info *all; 75 | size_t index; 76 | size_t max; 77 | int failed; 78 | }; 79 | 80 | /* Passed to backtrace_simple callback function. */ 81 | 82 | struct sdata 83 | { 84 | uintptr_t *addrs; 85 | size_t index; 86 | size_t max; 87 | int failed; 88 | }; 89 | 90 | /* Passed to backtrace_syminfo callback function. */ 91 | 92 | struct symdata 93 | { 94 | const char *name; 95 | uintptr_t val, size; 96 | int failed; 97 | }; 98 | 99 | /* The backtrace state. */ 100 | 101 | static void *state; 102 | 103 | /* The number of failures. */ 104 | 105 | static int failures; 106 | 107 | /* Return the base name in a path. */ 108 | 109 | static const char * 110 | base (const char *p) 111 | { 112 | const char *last; 113 | const char *s; 114 | 115 | last = NULL; 116 | for (s = p; *s != '\0'; ++s) 117 | { 118 | if (IS_DIR_SEPARATOR (*s)) 119 | last = s + 1; 120 | } 121 | return last != NULL ? last : p; 122 | } 123 | 124 | /* Check an entry in a struct info array. */ 125 | 126 | static void 127 | check (const char *name, int index, const struct info *all, int want_lineno, 128 | const char *want_function, int *failed) 129 | { 130 | if (*failed) 131 | return; 132 | if (all[index].filename == NULL || all[index].function == NULL) 133 | { 134 | fprintf (stderr, "%s: [%d]: missing file name or function name\n", 135 | name, index); 136 | *failed = 1; 137 | return; 138 | } 139 | if (strcmp (base (all[index].filename), "btest.c") != 0) 140 | { 141 | fprintf (stderr, "%s: [%d]: got %s expected test.c\n", name, index, 142 | all[index].filename); 143 | *failed = 1; 144 | } 145 | if (all[index].lineno != want_lineno) 146 | { 147 | fprintf (stderr, "%s: [%d]: got %d expected %d\n", name, index, 148 | all[index].lineno, want_lineno); 149 | *failed = 1; 150 | } 151 | if (strcmp (all[index].function, want_function) != 0) 152 | { 153 | fprintf (stderr, "%s: [%d]: got %s expected %s\n", name, index, 154 | all[index].function, want_function); 155 | *failed = 1; 156 | } 157 | } 158 | 159 | /* The backtrace callback function. */ 160 | 161 | static int 162 | callback_one (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED, 163 | const char *filename, int lineno, const char *function) 164 | { 165 | struct bdata *data = (struct bdata *) vdata; 166 | struct info *p; 167 | 168 | if (data->index >= data->max) 169 | { 170 | fprintf (stderr, "callback_one: callback called too many times\n"); 171 | data->failed = 1; 172 | return 1; 173 | } 174 | 175 | p = &data->all[data->index]; 176 | if (filename == NULL) 177 | p->filename = NULL; 178 | else 179 | { 180 | p->filename = strdup (filename); 181 | assert (p->filename != NULL); 182 | } 183 | p->lineno = lineno; 184 | if (function == NULL) 185 | p->function = NULL; 186 | else 187 | { 188 | p->function = strdup (function); 189 | assert (p->function != NULL); 190 | } 191 | ++data->index; 192 | 193 | return 0; 194 | } 195 | 196 | /* An error callback passed to backtrace. */ 197 | 198 | static void 199 | error_callback_one (void *vdata, const char *msg, int errnum) 200 | { 201 | struct bdata *data = (struct bdata *) vdata; 202 | 203 | fprintf (stderr, "%s", msg); 204 | if (errnum > 0) 205 | fprintf (stderr, ": %s", strerror (errnum)); 206 | fprintf (stderr, "\n"); 207 | data->failed = 1; 208 | } 209 | 210 | /* The backtrace_simple callback function. */ 211 | 212 | static int 213 | callback_two (void *vdata, uintptr_t pc) 214 | { 215 | struct sdata *data = (struct sdata *) vdata; 216 | 217 | if (data->index >= data->max) 218 | { 219 | fprintf (stderr, "callback_two: callback called too many times\n"); 220 | data->failed = 1; 221 | return 1; 222 | } 223 | 224 | data->addrs[data->index] = pc; 225 | ++data->index; 226 | 227 | return 0; 228 | } 229 | 230 | /* An error callback passed to backtrace_simple. */ 231 | 232 | static void 233 | error_callback_two (void *vdata, const char *msg, int errnum) 234 | { 235 | struct sdata *data = (struct sdata *) vdata; 236 | 237 | fprintf (stderr, "%s", msg); 238 | if (errnum > 0) 239 | fprintf (stderr, ": %s", strerror (errnum)); 240 | fprintf (stderr, "\n"); 241 | data->failed = 1; 242 | } 243 | 244 | /* The backtrace_syminfo callback function. */ 245 | 246 | static void 247 | callback_three (void *vdata, uintptr_t pc ATTRIBUTE_UNUSED, 248 | const char *symname, uintptr_t symval, 249 | uintptr_t symsize) 250 | { 251 | struct symdata *data = (struct symdata *) vdata; 252 | 253 | if (symname == NULL) 254 | data->name = NULL; 255 | else 256 | { 257 | data->name = strdup (symname); 258 | assert (data->name != NULL); 259 | } 260 | data->val = symval; 261 | data->size = symsize; 262 | } 263 | 264 | /* The backtrace_syminfo error callback function. */ 265 | 266 | static void 267 | error_callback_three (void *vdata, const char *msg, int errnum) 268 | { 269 | struct symdata *data = (struct symdata *) vdata; 270 | 271 | fprintf (stderr, "%s", msg); 272 | if (errnum > 0) 273 | fprintf (stderr, ": %s", strerror (errnum)); 274 | fprintf (stderr, "\n"); 275 | data->failed = 1; 276 | } 277 | 278 | /* Test the backtrace function with non-inlined functions. */ 279 | 280 | static int test1 (void) __attribute__ ((noinline, unused)); 281 | static int f2 (int) __attribute__ ((noinline)); 282 | static int f3 (int, int) __attribute__ ((noinline)); 283 | 284 | static int 285 | test1 (void) 286 | { 287 | /* Returning a value here and elsewhere avoids a tailcall which 288 | would mess up the backtrace. */ 289 | return f2 (__LINE__) + 1; 290 | } 291 | 292 | static int 293 | f2 (int f1line) 294 | { 295 | return f3 (f1line, __LINE__) + 2; 296 | } 297 | 298 | static int 299 | f3 (int f1line, int f2line) 300 | { 301 | struct info all[20]; 302 | struct bdata data; 303 | int f3line; 304 | int i; 305 | 306 | data.all = &all[0]; 307 | data.index = 0; 308 | data.max = 20; 309 | data.failed = 0; 310 | 311 | f3line = __LINE__ + 1; 312 | i = backtrace_full (state, 0, callback_one, error_callback_one, &data); 313 | 314 | if (i != 0) 315 | { 316 | fprintf (stderr, "test1: unexpected return value %d\n", i); 317 | data.failed = 1; 318 | } 319 | 320 | if (data.index < 3) 321 | { 322 | fprintf (stderr, 323 | "test1: not enough frames; got %zu, expected at least 3\n", 324 | data.index); 325 | data.failed = 1; 326 | } 327 | 328 | check ("test1", 0, all, f3line, "f3", &data.failed); 329 | check ("test1", 1, all, f2line, "f2", &data.failed); 330 | check ("test1", 2, all, f1line, "test1", &data.failed); 331 | 332 | printf ("%s: backtrace_full noinline\n", data.failed ? "FAIL" : "PASS"); 333 | 334 | if (data.failed) 335 | ++failures; 336 | 337 | return failures; 338 | } 339 | 340 | /* Test the backtrace function with inlined functions. */ 341 | 342 | static inline int test2 (void) __attribute__ ((always_inline, unused)); 343 | static inline int f12 (int) __attribute__ ((always_inline)); 344 | static inline int f13 (int, int) __attribute__ ((always_inline)); 345 | 346 | static inline int 347 | test2 (void) 348 | { 349 | return f12 (__LINE__) + 1; 350 | } 351 | 352 | static inline int 353 | f12 (int f1line) 354 | { 355 | return f13 (f1line, __LINE__) + 2; 356 | } 357 | 358 | static inline int 359 | f13 (int f1line, int f2line) 360 | { 361 | struct info all[20]; 362 | struct bdata data; 363 | int f3line; 364 | int i; 365 | 366 | data.all = &all[0]; 367 | data.index = 0; 368 | data.max = 20; 369 | data.failed = 0; 370 | 371 | f3line = __LINE__ + 1; 372 | i = backtrace_full (state, 0, callback_one, error_callback_one, &data); 373 | 374 | if (i != 0) 375 | { 376 | fprintf (stderr, "test2: unexpected return value %d\n", i); 377 | data.failed = 1; 378 | } 379 | 380 | check ("test2", 0, all, f3line, "f13", &data.failed); 381 | check ("test2", 1, all, f2line, "f12", &data.failed); 382 | check ("test2", 2, all, f1line, "test2", &data.failed); 383 | 384 | printf ("%s: backtrace_full inline\n", data.failed ? "FAIL" : "PASS"); 385 | 386 | if (data.failed) 387 | ++failures; 388 | 389 | return failures; 390 | } 391 | 392 | /* Test the backtrace_simple function with non-inlined functions. */ 393 | 394 | static int test3 (void) __attribute__ ((noinline, unused)); 395 | static int f22 (int) __attribute__ ((noinline)); 396 | static int f23 (int, int) __attribute__ ((noinline)); 397 | 398 | static int 399 | test3 (void) 400 | { 401 | return f22 (__LINE__) + 1; 402 | } 403 | 404 | static int 405 | f22 (int f1line) 406 | { 407 | return f23 (f1line, __LINE__) + 2; 408 | } 409 | 410 | static int 411 | f23 (int f1line, int f2line) 412 | { 413 | uintptr_t addrs[20]; 414 | struct sdata data; 415 | int f3line; 416 | int i; 417 | 418 | data.addrs = &addrs[0]; 419 | data.index = 0; 420 | data.max = 20; 421 | data.failed = 0; 422 | 423 | f3line = __LINE__ + 1; 424 | i = backtrace_simple (state, 0, callback_two, error_callback_two, &data); 425 | 426 | if (i != 0) 427 | { 428 | fprintf (stderr, "test3: unexpected return value %d\n", i); 429 | data.failed = 1; 430 | } 431 | 432 | if (!data.failed) 433 | { 434 | struct info all[20]; 435 | struct bdata bdata; 436 | int j; 437 | 438 | bdata.all = &all[0]; 439 | bdata.index = 0; 440 | bdata.max = 20; 441 | bdata.failed = 0; 442 | 443 | for (j = 0; j < 3; ++j) 444 | { 445 | i = backtrace_pcinfo (state, addrs[j], callback_one, 446 | error_callback_one, &bdata); 447 | if (i != 0) 448 | { 449 | fprintf (stderr, 450 | ("test3: unexpected return value " 451 | "from backtrace_pcinfo %d\n"), 452 | i); 453 | bdata.failed = 1; 454 | } 455 | if (!bdata.failed && bdata.index != (size_t) (j + 1)) 456 | { 457 | fprintf (stderr, 458 | ("wrong number of calls from backtrace_pcinfo " 459 | "got %u expected %d\n"), 460 | (unsigned int) bdata.index, j + 1); 461 | bdata.failed = 1; 462 | } 463 | } 464 | 465 | check ("test3", 0, all, f3line, "f23", &bdata.failed); 466 | check ("test3", 1, all, f2line, "f22", &bdata.failed); 467 | check ("test3", 2, all, f1line, "test3", &bdata.failed); 468 | 469 | if (bdata.failed) 470 | data.failed = 1; 471 | 472 | for (j = 0; j < 3; ++j) 473 | { 474 | struct symdata symdata; 475 | 476 | symdata.name = NULL; 477 | symdata.val = 0; 478 | symdata.size = 0; 479 | symdata.failed = 0; 480 | 481 | i = backtrace_syminfo (state, addrs[j], callback_three, 482 | error_callback_three, &symdata); 483 | if (i == 0) 484 | { 485 | fprintf (stderr, 486 | ("test3: [%d]: unexpected return value " 487 | "from backtrace_syminfo %d\n"), 488 | j, i); 489 | symdata.failed = 1; 490 | } 491 | 492 | if (!symdata.failed) 493 | { 494 | const char *expected; 495 | 496 | switch (j) 497 | { 498 | case 0: 499 | expected = "f23"; 500 | break; 501 | case 1: 502 | expected = "f22"; 503 | break; 504 | case 2: 505 | expected = "test3"; 506 | break; 507 | default: 508 | assert (0); 509 | } 510 | 511 | if (symdata.name == NULL) 512 | { 513 | fprintf (stderr, "test3: [%d]: NULL syminfo name\n", j); 514 | symdata.failed = 1; 515 | } 516 | /* Use strncmp, not strcmp, because GCC might create a 517 | clone. */ 518 | else if (strncmp (symdata.name, expected, strlen (expected)) 519 | != 0) 520 | { 521 | fprintf (stderr, 522 | ("test3: [%d]: unexpected syminfo name " 523 | "got %s expected %s\n"), 524 | j, symdata.name, expected); 525 | symdata.failed = 1; 526 | } 527 | } 528 | 529 | if (symdata.failed) 530 | data.failed = 1; 531 | } 532 | } 533 | 534 | printf ("%s: backtrace_simple noinline\n", data.failed ? "FAIL" : "PASS"); 535 | 536 | if (data.failed) 537 | ++failures; 538 | 539 | return failures; 540 | } 541 | 542 | /* Test the backtrace_simple function with inlined functions. */ 543 | 544 | static inline int test4 (void) __attribute__ ((always_inline, unused)); 545 | static inline int f32 (int) __attribute__ ((always_inline)); 546 | static inline int f33 (int, int) __attribute__ ((always_inline)); 547 | 548 | static inline int 549 | test4 (void) 550 | { 551 | return f32 (__LINE__) + 1; 552 | } 553 | 554 | static inline int 555 | f32 (int f1line) 556 | { 557 | return f33 (f1line, __LINE__) + 2; 558 | } 559 | 560 | static inline int 561 | f33 (int f1line, int f2line) 562 | { 563 | uintptr_t addrs[20]; 564 | struct sdata data; 565 | int f3line; 566 | int i; 567 | 568 | data.addrs = &addrs[0]; 569 | data.index = 0; 570 | data.max = 20; 571 | data.failed = 0; 572 | 573 | f3line = __LINE__ + 1; 574 | i = backtrace_simple (state, 0, callback_two, error_callback_two, &data); 575 | 576 | if (i != 0) 577 | { 578 | fprintf (stderr, "test3: unexpected return value %d\n", i); 579 | data.failed = 1; 580 | } 581 | 582 | if (!data.failed) 583 | { 584 | struct info all[20]; 585 | struct bdata bdata; 586 | 587 | bdata.all = &all[0]; 588 | bdata.index = 0; 589 | bdata.max = 20; 590 | bdata.failed = 0; 591 | 592 | i = backtrace_pcinfo (state, addrs[0], callback_one, error_callback_one, 593 | &bdata); 594 | if (i != 0) 595 | { 596 | fprintf (stderr, 597 | ("test4: unexpected return value " 598 | "from backtrace_pcinfo %d\n"), 599 | i); 600 | bdata.failed = 1; 601 | } 602 | 603 | check ("test4", 0, all, f3line, "f33", &bdata.failed); 604 | check ("test4", 1, all, f2line, "f32", &bdata.failed); 605 | check ("test4", 2, all, f1line, "test4", &bdata.failed); 606 | 607 | if (bdata.failed) 608 | data.failed = 1; 609 | } 610 | 611 | printf ("%s: backtrace_simple inline\n", data.failed ? "FAIL" : "PASS"); 612 | 613 | if (data.failed) 614 | ++failures; 615 | 616 | return failures; 617 | } 618 | 619 | int global = 1; 620 | 621 | static int 622 | test5 (void) 623 | { 624 | struct symdata symdata; 625 | int i; 626 | uintptr_t addr = (uintptr_t) &global; 627 | 628 | if (sizeof (global) > 1) 629 | addr += 1; 630 | 631 | symdata.name = NULL; 632 | symdata.val = 0; 633 | symdata.size = 0; 634 | symdata.failed = 0; 635 | 636 | i = backtrace_syminfo (state, addr, callback_three, 637 | error_callback_three, &symdata); 638 | if (i == 0) 639 | { 640 | fprintf (stderr, 641 | "test5: unexpected return value from backtrace_syminfo %d\n", 642 | i); 643 | symdata.failed = 1; 644 | } 645 | 646 | if (!symdata.failed) 647 | { 648 | if (symdata.name == NULL) 649 | { 650 | fprintf (stderr, "test5: NULL syminfo name\n"); 651 | symdata.failed = 1; 652 | } 653 | else if (strcmp (symdata.name, "global") != 0) 654 | { 655 | fprintf (stderr, 656 | "test5: unexpected syminfo name got %s expected %s\n", 657 | symdata.name, "global"); 658 | symdata.failed = 1; 659 | } 660 | else if (symdata.val != (uintptr_t) &global) 661 | { 662 | fprintf (stderr, 663 | "test5: unexpected syminfo value got %lx expected %lx\n", 664 | (unsigned long) symdata.val, 665 | (unsigned long) (uintptr_t) &global); 666 | symdata.failed = 1; 667 | } 668 | else if (symdata.size != sizeof (global)) 669 | { 670 | fprintf (stderr, 671 | "test5: unexpected syminfo size got %lx expected %lx\n", 672 | (unsigned long) symdata.size, 673 | (unsigned long) sizeof (global)); 674 | symdata.failed = 1; 675 | } 676 | } 677 | 678 | printf ("%s: backtrace_syminfo variable\n", 679 | symdata.failed ? "FAIL" : "PASS"); 680 | 681 | if (symdata.failed) 682 | ++failures; 683 | 684 | return failures; 685 | } 686 | 687 | static void 688 | error_callback_create (void *data ATTRIBUTE_UNUSED, const char *msg, 689 | int errnum) 690 | { 691 | fprintf (stderr, "%s", msg); 692 | if (errnum > 0) 693 | fprintf (stderr, ": %s", strerror (errnum)); 694 | fprintf (stderr, "\n"); 695 | exit (EXIT_FAILURE); 696 | } 697 | 698 | /* Run all the tests. */ 699 | 700 | int 701 | main (int argc ATTRIBUTE_UNUSED, char **argv) 702 | { 703 | state = backtrace_create_state (argv[0], BACKTRACE_SUPPORTS_THREADS, 704 | error_callback_create, NULL); 705 | 706 | #if BACKTRACE_SUPPORTED 707 | test1 (); 708 | test2 (); 709 | test3 (); 710 | test4 (); 711 | test5 (); 712 | #endif 713 | 714 | exit (failures ? EXIT_FAILURE : EXIT_SUCCESS); 715 | } 716 | -------------------------------------------------------------------------------- /libbacktrace/config.h.in.cmake: -------------------------------------------------------------------------------- 1 | /* ELF size: 32 or 64 */ 2 | #define BACKTRACE_ELF_SIZE @BACKTRACE_ELF_SIZE@ 3 | 4 | /* Define to 1 if you have the declaration of `strnlen', and to 0 if you 5 | don't. */ 6 | #cmakedefine HAVE_DECL_STRNLEN 1 7 | 8 | /* Define if dl_iterate_phdr is available. */ 9 | #cmakedefine HAVE_DL_ITERATE_PHDR 1 10 | 11 | /* Define to 1 if you have the fcntl function */ 12 | #cmakedefine HAVE_FCNTL 1 13 | 14 | /* Define if getexecname is available. */ 15 | #cmakedefine HAVE_GETEXECNAME 1 16 | 17 | /* Define if _Unwind_GetIPInfo is available. */ 18 | #cmakedefine HAVE_GETIPINFO 1 19 | 20 | /* Define to 1 if you have the __sync functions */ 21 | #cmakedefine HAVE_SYNC_FUNCTIONS 1 22 | 23 | /* Define to 1 if dwarf.h is in the libdwarf folder */ 24 | #cmakedefine HAVE_LIBDWARF_DWARF_H 1 25 | 26 | -------------------------------------------------------------------------------- /libbacktrace/elf.c: -------------------------------------------------------------------------------- 1 | /* elf.c -- Get debug data from an ELF file for backtraces. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #ifdef HAVE_DL_ITERATE_PHDR 40 | #include 41 | #endif 42 | 43 | #include "backtrace.h" 44 | #include "internal.h" 45 | 46 | #ifndef HAVE_DL_ITERATE_PHDR 47 | 48 | /* Dummy version of dl_iterate_phdr for systems that don't have it. */ 49 | 50 | #define dl_phdr_info x_dl_phdr_info 51 | #define dl_iterate_phdr x_dl_iterate_phdr 52 | 53 | struct dl_phdr_info 54 | { 55 | uintptr_t dlpi_addr; 56 | const char *dlpi_name; 57 | }; 58 | 59 | static int 60 | dl_iterate_phdr (int (*callback) (struct dl_phdr_info *, 61 | size_t, void *) ATTRIBUTE_UNUSED, 62 | void *data ATTRIBUTE_UNUSED) 63 | { 64 | return 0; 65 | } 66 | 67 | #endif /* ! defined (HAVE_DL_ITERATE_PHDR) */ 68 | 69 | /* The configure script must tell us whether we are 32-bit or 64-bit 70 | ELF. We could make this code test and support either possibility, 71 | but there is no point. This code only works for the currently 72 | running executable, which means that we know the ELF mode at 73 | configure mode. */ 74 | 75 | #if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64 76 | #error "Unknown BACKTRACE_ELF_SIZE" 77 | #endif 78 | 79 | /* might #include which might define our constants 80 | with slightly different values. Undefine them to be safe. */ 81 | 82 | #undef EI_NIDENT 83 | #undef EI_MAG0 84 | #undef EI_MAG1 85 | #undef EI_MAG2 86 | #undef EI_MAG3 87 | #undef EI_CLASS 88 | #undef EI_DATA 89 | #undef EI_VERSION 90 | #undef ELF_MAG0 91 | #undef ELF_MAG1 92 | #undef ELF_MAG2 93 | #undef ELF_MAG3 94 | #undef ELFCLASS32 95 | #undef ELFCLASS64 96 | #undef ELFDATA2LSB 97 | #undef ELFDATA2MSB 98 | #undef EV_CURRENT 99 | #undef ET_DYN 100 | #undef SHN_LORESERVE 101 | #undef SHN_XINDEX 102 | #undef SHN_UNDEF 103 | #undef SHT_SYMTAB 104 | #undef SHT_STRTAB 105 | #undef SHT_DYNSYM 106 | #undef STT_OBJECT 107 | #undef STT_FUNC 108 | 109 | /* Basic types. */ 110 | 111 | typedef uint16_t b_elf_half; /* Elf_Half. */ 112 | typedef uint32_t b_elf_word; /* Elf_Word. */ 113 | typedef int32_t b_elf_sword; /* Elf_Sword. */ 114 | 115 | #if BACKTRACE_ELF_SIZE == 32 116 | 117 | typedef uint32_t b_elf_addr; /* Elf_Addr. */ 118 | typedef uint32_t b_elf_off; /* Elf_Off. */ 119 | 120 | typedef uint32_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */ 121 | 122 | #else 123 | 124 | typedef uint64_t b_elf_addr; /* Elf_Addr. */ 125 | typedef uint64_t b_elf_off; /* Elf_Off. */ 126 | typedef uint64_t b_elf_xword; /* Elf_Xword. */ 127 | typedef int64_t b_elf_sxword; /* Elf_Sxword. */ 128 | 129 | typedef uint64_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */ 130 | 131 | #endif 132 | 133 | /* Data structures and associated constants. */ 134 | 135 | #define EI_NIDENT 16 136 | 137 | typedef struct { 138 | unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */ 139 | b_elf_half e_type; /* Identifies object file type */ 140 | b_elf_half e_machine; /* Specifies required architecture */ 141 | b_elf_word e_version; /* Identifies object file version */ 142 | b_elf_addr e_entry; /* Entry point virtual address */ 143 | b_elf_off e_phoff; /* Program header table file offset */ 144 | b_elf_off e_shoff; /* Section header table file offset */ 145 | b_elf_word e_flags; /* Processor-specific flags */ 146 | b_elf_half e_ehsize; /* ELF header size in bytes */ 147 | b_elf_half e_phentsize; /* Program header table entry size */ 148 | b_elf_half e_phnum; /* Program header table entry count */ 149 | b_elf_half e_shentsize; /* Section header table entry size */ 150 | b_elf_half e_shnum; /* Section header table entry count */ 151 | b_elf_half e_shstrndx; /* Section header string table index */ 152 | } b_elf_ehdr; /* Elf_Ehdr. */ 153 | 154 | #define EI_MAG0 0 155 | #define EI_MAG1 1 156 | #define EI_MAG2 2 157 | #define EI_MAG3 3 158 | #define EI_CLASS 4 159 | #define EI_DATA 5 160 | #define EI_VERSION 6 161 | 162 | #define ELFMAG0 0x7f 163 | #define ELFMAG1 'E' 164 | #define ELFMAG2 'L' 165 | #define ELFMAG3 'F' 166 | 167 | #define ELFCLASS32 1 168 | #define ELFCLASS64 2 169 | 170 | #define ELFDATA2LSB 1 171 | #define ELFDATA2MSB 2 172 | 173 | #define EV_CURRENT 1 174 | 175 | #define ET_DYN 3 176 | 177 | typedef struct { 178 | b_elf_word sh_name; /* Section name, index in string tbl */ 179 | b_elf_word sh_type; /* Type of section */ 180 | b_elf_wxword sh_flags; /* Miscellaneous section attributes */ 181 | b_elf_addr sh_addr; /* Section virtual addr at execution */ 182 | b_elf_off sh_offset; /* Section file offset */ 183 | b_elf_wxword sh_size; /* Size of section in bytes */ 184 | b_elf_word sh_link; /* Index of another section */ 185 | b_elf_word sh_info; /* Additional section information */ 186 | b_elf_wxword sh_addralign; /* Section alignment */ 187 | b_elf_wxword sh_entsize; /* Entry size if section holds table */ 188 | } b_elf_shdr; /* Elf_Shdr. */ 189 | 190 | #define SHN_UNDEF 0x0000 /* Undefined section */ 191 | #define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */ 192 | #define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */ 193 | 194 | #define SHT_SYMTAB 2 195 | #define SHT_STRTAB 3 196 | #define SHT_DYNSYM 11 197 | 198 | #if BACKTRACE_ELF_SIZE == 32 199 | 200 | typedef struct 201 | { 202 | b_elf_word st_name; /* Symbol name, index in string tbl */ 203 | b_elf_addr st_value; /* Symbol value */ 204 | b_elf_word st_size; /* Symbol size */ 205 | unsigned char st_info; /* Symbol binding and type */ 206 | unsigned char st_other; /* Visibility and other data */ 207 | b_elf_half st_shndx; /* Symbol section index */ 208 | } b_elf_sym; /* Elf_Sym. */ 209 | 210 | #else /* BACKTRACE_ELF_SIZE != 32 */ 211 | 212 | typedef struct 213 | { 214 | b_elf_word st_name; /* Symbol name, index in string tbl */ 215 | unsigned char st_info; /* Symbol binding and type */ 216 | unsigned char st_other; /* Visibility and other data */ 217 | b_elf_half st_shndx; /* Symbol section index */ 218 | b_elf_addr st_value; /* Symbol value */ 219 | b_elf_xword st_size; /* Symbol size */ 220 | } b_elf_sym; /* Elf_Sym. */ 221 | 222 | #endif /* BACKTRACE_ELF_SIZE != 32 */ 223 | 224 | #define STT_OBJECT 1 225 | #define STT_FUNC 2 226 | 227 | /* An index of ELF sections we care about. */ 228 | 229 | enum debug_section 230 | { 231 | DEBUG_INFO, 232 | DEBUG_LINE, 233 | DEBUG_ABBREV, 234 | DEBUG_RANGES, 235 | DEBUG_STR, 236 | DEBUG_MAX 237 | }; 238 | 239 | /* Names of sections, indexed by enum elf_section. */ 240 | 241 | static const char * const debug_section_names[DEBUG_MAX] = 242 | { 243 | ".debug_info", 244 | ".debug_line", 245 | ".debug_abbrev", 246 | ".debug_ranges", 247 | ".debug_str" 248 | }; 249 | 250 | /* Information we gather for the sections we care about. */ 251 | 252 | struct debug_section_info 253 | { 254 | /* Section file offset. */ 255 | off_t offset; 256 | /* Section size. */ 257 | size_t size; 258 | /* Section contents, after read from file. */ 259 | const unsigned char *data; 260 | }; 261 | 262 | /* Information we keep for an ELF symbol. */ 263 | 264 | struct elf_symbol 265 | { 266 | /* The name of the symbol. */ 267 | const char *name; 268 | /* The address of the symbol. */ 269 | uintptr_t address; 270 | /* The size of the symbol. */ 271 | size_t size; 272 | }; 273 | 274 | /* Information to pass to elf_syminfo. */ 275 | 276 | struct elf_syminfo_data 277 | { 278 | /* Symbols for the next module. */ 279 | struct elf_syminfo_data *next; 280 | /* The ELF symbols, sorted by address. */ 281 | struct elf_symbol *symbols; 282 | /* The number of symbols. */ 283 | size_t count; 284 | }; 285 | 286 | /* A dummy callback function used when we can't find any debug info. */ 287 | 288 | static int 289 | elf_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED, 290 | uintptr_t pc ATTRIBUTE_UNUSED, 291 | backtrace_full_callback callback ATTRIBUTE_UNUSED, 292 | backtrace_error_callback error_callback, void *data) 293 | { 294 | error_callback (data, "no debug info in ELF executable", -1); 295 | return 0; 296 | } 297 | 298 | /* A dummy callback function used when we can't find a symbol 299 | table. */ 300 | 301 | static void 302 | elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED, 303 | uintptr_t addr ATTRIBUTE_UNUSED, 304 | backtrace_syminfo_callback callback ATTRIBUTE_UNUSED, 305 | backtrace_error_callback error_callback, void *data) 306 | { 307 | error_callback (data, "no symbol table in ELF executable", -1); 308 | } 309 | 310 | /* Compare struct elf_symbol for qsort. */ 311 | 312 | static int 313 | elf_symbol_compare (const void *v1, const void *v2) 314 | { 315 | const struct elf_symbol *e1 = (const struct elf_symbol *) v1; 316 | const struct elf_symbol *e2 = (const struct elf_symbol *) v2; 317 | 318 | if (e1->address < e2->address) 319 | return -1; 320 | else if (e1->address > e2->address) 321 | return 1; 322 | else 323 | return 0; 324 | } 325 | 326 | /* Compare an ADDR against an elf_symbol for bsearch. We allocate one 327 | extra entry in the array so that this can look safely at the next 328 | entry. */ 329 | 330 | static int 331 | elf_symbol_search (const void *vkey, const void *ventry) 332 | { 333 | const uintptr_t *key = (const uintptr_t *) vkey; 334 | const struct elf_symbol *entry = (const struct elf_symbol *) ventry; 335 | uintptr_t addr; 336 | 337 | addr = *key; 338 | if (addr < entry->address) 339 | return -1; 340 | else if (addr >= entry->address + entry->size) 341 | return 1; 342 | else 343 | return 0; 344 | } 345 | 346 | /* Initialize the symbol table info for elf_syminfo. */ 347 | 348 | static int 349 | elf_initialize_syminfo (struct backtrace_state *state, 350 | uintptr_t base_address, 351 | const unsigned char *symtab_data, size_t symtab_size, 352 | const unsigned char *strtab, size_t strtab_size, 353 | backtrace_error_callback error_callback, 354 | void *data, struct elf_syminfo_data *sdata) 355 | { 356 | size_t sym_count; 357 | const b_elf_sym *sym; 358 | size_t elf_symbol_count; 359 | size_t elf_symbol_size; 360 | struct elf_symbol *elf_symbols; 361 | size_t i; 362 | unsigned int j; 363 | 364 | sym_count = symtab_size / sizeof (b_elf_sym); 365 | 366 | /* We only care about function symbols. Count them. */ 367 | sym = (const b_elf_sym *) symtab_data; 368 | elf_symbol_count = 0; 369 | for (i = 0; i < sym_count; ++i, ++sym) 370 | { 371 | int info; 372 | 373 | info = sym->st_info & 0xf; 374 | if ((info == STT_FUNC || info == STT_OBJECT) 375 | && sym->st_shndx != SHN_UNDEF) 376 | ++elf_symbol_count; 377 | } 378 | 379 | elf_symbol_size = elf_symbol_count * sizeof (struct elf_symbol); 380 | elf_symbols = ((struct elf_symbol *) 381 | backtrace_alloc (state, elf_symbol_size, error_callback, 382 | data)); 383 | if (elf_symbols == NULL) 384 | return 0; 385 | 386 | sym = (const b_elf_sym *) symtab_data; 387 | j = 0; 388 | for (i = 0; i < sym_count; ++i, ++sym) 389 | { 390 | int info; 391 | 392 | info = sym->st_info & 0xf; 393 | if (info != STT_FUNC && info != STT_OBJECT) 394 | continue; 395 | if (sym->st_shndx == SHN_UNDEF) 396 | continue; 397 | if (sym->st_name >= strtab_size) 398 | { 399 | error_callback (data, "symbol string index out of range", 0); 400 | backtrace_free (state, elf_symbols, elf_symbol_size, error_callback, 401 | data); 402 | return 0; 403 | } 404 | elf_symbols[j].name = (const char *) strtab + sym->st_name; 405 | elf_symbols[j].address = sym->st_value + base_address; 406 | elf_symbols[j].size = sym->st_size; 407 | ++j; 408 | } 409 | 410 | backtrace_qsort (elf_symbols, elf_symbol_count, sizeof (struct elf_symbol), 411 | elf_symbol_compare); 412 | 413 | sdata->next = NULL; 414 | sdata->symbols = elf_symbols; 415 | sdata->count = elf_symbol_count; 416 | 417 | return 1; 418 | } 419 | 420 | /* Add EDATA to the list in STATE. */ 421 | 422 | static void 423 | elf_add_syminfo_data (struct backtrace_state *state, 424 | struct elf_syminfo_data *edata) 425 | { 426 | if (!state->threaded) 427 | { 428 | struct elf_syminfo_data **pp; 429 | 430 | for (pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data; 431 | *pp != NULL; 432 | pp = &(*pp)->next) 433 | ; 434 | *pp = edata; 435 | } 436 | else 437 | { 438 | while (1) 439 | { 440 | struct elf_syminfo_data **pp; 441 | 442 | pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data; 443 | 444 | while (1) 445 | { 446 | struct elf_syminfo_data *p; 447 | 448 | p = backtrace_atomic_load_pointer (pp); 449 | 450 | if (p == NULL) 451 | break; 452 | 453 | pp = &p->next; 454 | } 455 | 456 | if (__sync_bool_compare_and_swap (pp, NULL, edata)) 457 | break; 458 | } 459 | } 460 | } 461 | 462 | /* Return the symbol name and value for an ADDR. */ 463 | 464 | static void 465 | elf_syminfo (struct backtrace_state *state, uintptr_t addr, 466 | backtrace_syminfo_callback callback, 467 | backtrace_error_callback error_callback ATTRIBUTE_UNUSED, 468 | void *data) 469 | { 470 | struct elf_syminfo_data *edata; 471 | struct elf_symbol *sym = NULL; 472 | 473 | if (!state->threaded) 474 | { 475 | for (edata = (struct elf_syminfo_data *) state->syminfo_data; 476 | edata != NULL; 477 | edata = edata->next) 478 | { 479 | sym = ((struct elf_symbol *) 480 | bsearch (&addr, edata->symbols, edata->count, 481 | sizeof (struct elf_symbol), elf_symbol_search)); 482 | if (sym != NULL) 483 | break; 484 | } 485 | } 486 | else 487 | { 488 | struct elf_syminfo_data **pp; 489 | 490 | pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data; 491 | while (1) 492 | { 493 | edata = backtrace_atomic_load_pointer (pp); 494 | if (edata == NULL) 495 | break; 496 | 497 | sym = ((struct elf_symbol *) 498 | bsearch (&addr, edata->symbols, edata->count, 499 | sizeof (struct elf_symbol), elf_symbol_search)); 500 | if (sym != NULL) 501 | break; 502 | 503 | pp = &edata->next; 504 | } 505 | } 506 | 507 | if (sym == NULL) 508 | callback (data, addr, NULL, 0, 0); 509 | else 510 | callback (data, addr, sym->name, sym->address, sym->size); 511 | } 512 | 513 | /* Add the backtrace data for one ELF file. Returns 1 on success, 514 | 0 on failure (in both cases descriptor is closed) or -1 if exe 515 | is non-zero and the ELF file is ET_DYN, which tells the caller that 516 | elf_add will need to be called on the descriptor again after 517 | base_address is determined. */ 518 | 519 | static int 520 | elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address, 521 | backtrace_error_callback error_callback, void *data, 522 | fileline *fileline_fn, int *found_sym, int *found_dwarf, int exe) 523 | { 524 | struct backtrace_view ehdr_view; 525 | b_elf_ehdr ehdr; 526 | off_t shoff; 527 | unsigned int shnum; 528 | unsigned int shstrndx; 529 | struct backtrace_view shdrs_view; 530 | int shdrs_view_valid; 531 | const b_elf_shdr *shdrs; 532 | const b_elf_shdr *shstrhdr; 533 | size_t shstr_size; 534 | off_t shstr_off; 535 | struct backtrace_view names_view; 536 | int names_view_valid; 537 | const char *names; 538 | unsigned int symtab_shndx; 539 | unsigned int dynsym_shndx; 540 | unsigned int i; 541 | struct debug_section_info sections[DEBUG_MAX]; 542 | struct backtrace_view symtab_view; 543 | int symtab_view_valid; 544 | struct backtrace_view strtab_view; 545 | int strtab_view_valid; 546 | off_t min_offset; 547 | off_t max_offset; 548 | struct backtrace_view debug_view; 549 | int debug_view_valid; 550 | 551 | *found_sym = 0; 552 | *found_dwarf = 0; 553 | 554 | shdrs_view_valid = 0; 555 | names_view_valid = 0; 556 | symtab_view_valid = 0; 557 | strtab_view_valid = 0; 558 | debug_view_valid = 0; 559 | 560 | if (!backtrace_get_view (state, descriptor, 0, sizeof ehdr, error_callback, 561 | data, &ehdr_view)) 562 | goto fail; 563 | 564 | memcpy (&ehdr, ehdr_view.data, sizeof ehdr); 565 | 566 | backtrace_release_view (state, &ehdr_view, error_callback, data); 567 | 568 | if (ehdr.e_ident[EI_MAG0] != ELFMAG0 569 | || ehdr.e_ident[EI_MAG1] != ELFMAG1 570 | || ehdr.e_ident[EI_MAG2] != ELFMAG2 571 | || ehdr.e_ident[EI_MAG3] != ELFMAG3) 572 | { 573 | error_callback (data, "executable file is not ELF", 0); 574 | goto fail; 575 | } 576 | if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) 577 | { 578 | error_callback (data, "executable file is unrecognized ELF version", 0); 579 | goto fail; 580 | } 581 | 582 | #if BACKTRACE_ELF_SIZE == 32 583 | #define BACKTRACE_ELFCLASS ELFCLASS32 584 | #else 585 | #define BACKTRACE_ELFCLASS ELFCLASS64 586 | #endif 587 | 588 | if (ehdr.e_ident[EI_CLASS] != BACKTRACE_ELFCLASS) 589 | { 590 | error_callback (data, "executable file is unexpected ELF class", 0); 591 | goto fail; 592 | } 593 | 594 | if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB 595 | && ehdr.e_ident[EI_DATA] != ELFDATA2MSB) 596 | { 597 | error_callback (data, "executable file has unknown endianness", 0); 598 | goto fail; 599 | } 600 | 601 | /* If the executable is ET_DYN, it is either a PIE, or we are running 602 | directly a shared library with .interp. We need to wait for 603 | dl_iterate_phdr in that case to determine the actual base_address. */ 604 | if (exe && ehdr.e_type == ET_DYN) 605 | return -1; 606 | 607 | shoff = ehdr.e_shoff; 608 | shnum = ehdr.e_shnum; 609 | shstrndx = ehdr.e_shstrndx; 610 | 611 | if ((shnum == 0 || shstrndx == SHN_XINDEX) 612 | && shoff != 0) 613 | { 614 | struct backtrace_view shdr_view; 615 | const b_elf_shdr *shdr; 616 | 617 | if (!backtrace_get_view (state, descriptor, shoff, sizeof shdr, 618 | error_callback, data, &shdr_view)) 619 | goto fail; 620 | 621 | shdr = (const b_elf_shdr *) shdr_view.data; 622 | 623 | if (shnum == 0) 624 | shnum = shdr->sh_size; 625 | 626 | if (shstrndx == SHN_XINDEX) 627 | { 628 | shstrndx = shdr->sh_link; 629 | 630 | /* Versions of the GNU binutils between 2.12 and 2.18 did 631 | not handle objects with more than SHN_LORESERVE sections 632 | correctly. All large section indexes were offset by 633 | 0x100. There is more information at 634 | http://sourceware.org/bugzilla/show_bug.cgi?id-5900 . 635 | Fortunately these object files are easy to detect, as the 636 | GNU binutils always put the section header string table 637 | near the end of the list of sections. Thus if the 638 | section header string table index is larger than the 639 | number of sections, then we know we have to subtract 640 | 0x100 to get the real section index. */ 641 | if (shstrndx >= shnum && shstrndx >= SHN_LORESERVE + 0x100) 642 | shstrndx -= 0x100; 643 | } 644 | 645 | backtrace_release_view (state, &shdr_view, error_callback, data); 646 | } 647 | 648 | /* To translate PC to file/line when using DWARF, we need to find 649 | the .debug_info and .debug_line sections. */ 650 | 651 | /* Read the section headers, skipping the first one. */ 652 | 653 | if (!backtrace_get_view (state, descriptor, shoff + sizeof (b_elf_shdr), 654 | (shnum - 1) * sizeof (b_elf_shdr), 655 | error_callback, data, &shdrs_view)) 656 | goto fail; 657 | shdrs_view_valid = 1; 658 | shdrs = (const b_elf_shdr *) shdrs_view.data; 659 | 660 | /* Read the section names. */ 661 | 662 | shstrhdr = &shdrs[shstrndx - 1]; 663 | shstr_size = shstrhdr->sh_size; 664 | shstr_off = shstrhdr->sh_offset; 665 | 666 | if (!backtrace_get_view (state, descriptor, shstr_off, shstr_size, 667 | error_callback, data, &names_view)) 668 | goto fail; 669 | names_view_valid = 1; 670 | names = (const char *) names_view.data; 671 | 672 | symtab_shndx = 0; 673 | dynsym_shndx = 0; 674 | 675 | memset (sections, 0, sizeof sections); 676 | 677 | /* Look for the symbol table. */ 678 | for (i = 1; i < shnum; ++i) 679 | { 680 | const b_elf_shdr *shdr; 681 | unsigned int sh_name; 682 | const char *name; 683 | int j; 684 | 685 | shdr = &shdrs[i - 1]; 686 | 687 | if (shdr->sh_type == SHT_SYMTAB) 688 | symtab_shndx = i; 689 | else if (shdr->sh_type == SHT_DYNSYM) 690 | dynsym_shndx = i; 691 | 692 | sh_name = shdr->sh_name; 693 | if (sh_name >= shstr_size) 694 | { 695 | error_callback (data, "ELF section name out of range", 0); 696 | goto fail; 697 | } 698 | 699 | name = names + sh_name; 700 | 701 | for (j = 0; j < (int) DEBUG_MAX; ++j) 702 | { 703 | if (strcmp (name, debug_section_names[j]) == 0) 704 | { 705 | sections[j].offset = shdr->sh_offset; 706 | sections[j].size = shdr->sh_size; 707 | break; 708 | } 709 | } 710 | } 711 | 712 | if (symtab_shndx == 0) 713 | symtab_shndx = dynsym_shndx; 714 | if (symtab_shndx != 0) 715 | { 716 | const b_elf_shdr *symtab_shdr; 717 | unsigned int strtab_shndx; 718 | const b_elf_shdr *strtab_shdr; 719 | struct elf_syminfo_data *sdata; 720 | 721 | symtab_shdr = &shdrs[symtab_shndx - 1]; 722 | strtab_shndx = symtab_shdr->sh_link; 723 | if (strtab_shndx >= shnum) 724 | { 725 | error_callback (data, 726 | "ELF symbol table strtab link out of range", 0); 727 | goto fail; 728 | } 729 | strtab_shdr = &shdrs[strtab_shndx - 1]; 730 | 731 | if (!backtrace_get_view (state, descriptor, symtab_shdr->sh_offset, 732 | symtab_shdr->sh_size, error_callback, data, 733 | &symtab_view)) 734 | goto fail; 735 | symtab_view_valid = 1; 736 | 737 | if (!backtrace_get_view (state, descriptor, strtab_shdr->sh_offset, 738 | strtab_shdr->sh_size, error_callback, data, 739 | &strtab_view)) 740 | goto fail; 741 | strtab_view_valid = 1; 742 | 743 | sdata = ((struct elf_syminfo_data *) 744 | backtrace_alloc (state, sizeof *sdata, error_callback, data)); 745 | if (sdata == NULL) 746 | goto fail; 747 | 748 | if (!elf_initialize_syminfo (state, base_address, 749 | symtab_view.data, symtab_shdr->sh_size, 750 | strtab_view.data, strtab_shdr->sh_size, 751 | error_callback, data, sdata)) 752 | { 753 | backtrace_free (state, sdata, sizeof *sdata, error_callback, data); 754 | goto fail; 755 | } 756 | 757 | /* We no longer need the symbol table, but we hold on to the 758 | string table permanently. */ 759 | backtrace_release_view (state, &symtab_view, error_callback, data); 760 | 761 | *found_sym = 1; 762 | 763 | elf_add_syminfo_data (state, sdata); 764 | } 765 | 766 | /* FIXME: Need to handle compressed debug sections. */ 767 | 768 | backtrace_release_view (state, &shdrs_view, error_callback, data); 769 | shdrs_view_valid = 0; 770 | backtrace_release_view (state, &names_view, error_callback, data); 771 | names_view_valid = 0; 772 | 773 | /* Read all the debug sections in a single view, since they are 774 | probably adjacent in the file. We never release this view. */ 775 | 776 | min_offset = 0; 777 | max_offset = 0; 778 | for (i = 0; i < (int) DEBUG_MAX; ++i) 779 | { 780 | off_t end; 781 | 782 | if (sections[i].size == 0) 783 | continue; 784 | if (min_offset == 0 || sections[i].offset < min_offset) 785 | min_offset = sections[i].offset; 786 | end = sections[i].offset + sections[i].size; 787 | if (end > max_offset) 788 | max_offset = end; 789 | } 790 | if (min_offset == 0 || max_offset == 0) 791 | { 792 | if (!backtrace_close (descriptor, error_callback, data)) 793 | goto fail; 794 | *fileline_fn = elf_nodebug; 795 | return 1; 796 | } 797 | 798 | if (!backtrace_get_view (state, descriptor, min_offset, 799 | max_offset - min_offset, 800 | error_callback, data, &debug_view)) 801 | goto fail; 802 | debug_view_valid = 1; 803 | 804 | /* We've read all we need from the executable. */ 805 | if (!backtrace_close (descriptor, error_callback, data)) 806 | goto fail; 807 | descriptor = -1; 808 | 809 | for (i = 0; i < (int) DEBUG_MAX; ++i) 810 | { 811 | if (sections[i].size == 0) 812 | sections[i].data = NULL; 813 | else 814 | sections[i].data = ((const unsigned char *) debug_view.data 815 | + (sections[i].offset - min_offset)); 816 | } 817 | 818 | if (!backtrace_dwarf_add (state, base_address, 819 | sections[DEBUG_INFO].data, 820 | sections[DEBUG_INFO].size, 821 | sections[DEBUG_LINE].data, 822 | sections[DEBUG_LINE].size, 823 | sections[DEBUG_ABBREV].data, 824 | sections[DEBUG_ABBREV].size, 825 | sections[DEBUG_RANGES].data, 826 | sections[DEBUG_RANGES].size, 827 | sections[DEBUG_STR].data, 828 | sections[DEBUG_STR].size, 829 | ehdr.e_ident[EI_DATA] == ELFDATA2MSB, 830 | error_callback, data, fileline_fn)) 831 | goto fail; 832 | 833 | *found_dwarf = 1; 834 | 835 | return 1; 836 | 837 | fail: 838 | if (shdrs_view_valid) 839 | backtrace_release_view (state, &shdrs_view, error_callback, data); 840 | if (names_view_valid) 841 | backtrace_release_view (state, &names_view, error_callback, data); 842 | if (symtab_view_valid) 843 | backtrace_release_view (state, &symtab_view, error_callback, data); 844 | if (strtab_view_valid) 845 | backtrace_release_view (state, &strtab_view, error_callback, data); 846 | if (debug_view_valid) 847 | backtrace_release_view (state, &debug_view, error_callback, data); 848 | if (descriptor != -1) 849 | backtrace_close (descriptor, error_callback, data); 850 | return 0; 851 | } 852 | 853 | /* Data passed to phdr_callback. */ 854 | 855 | struct phdr_data 856 | { 857 | struct backtrace_state *state; 858 | backtrace_error_callback error_callback; 859 | void *data; 860 | fileline *fileline_fn; 861 | int *found_sym; 862 | int *found_dwarf; 863 | int exe_descriptor; 864 | }; 865 | 866 | /* Callback passed to dl_iterate_phdr. Load debug info from shared 867 | libraries. */ 868 | 869 | static int 870 | phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED, 871 | void *pdata) 872 | { 873 | struct phdr_data *pd = (struct phdr_data *) pdata; 874 | int descriptor; 875 | int does_not_exist; 876 | fileline elf_fileline_fn; 877 | int found_dwarf; 878 | 879 | /* There is not much we can do if we don't have the module name, 880 | unless executable is ET_DYN, where we expect the very first 881 | phdr_callback to be for the PIE. */ 882 | if (info->dlpi_name == NULL || info->dlpi_name[0] == '\0') 883 | { 884 | if (pd->exe_descriptor == -1) 885 | return 0; 886 | descriptor = pd->exe_descriptor; 887 | pd->exe_descriptor = -1; 888 | } 889 | else 890 | { 891 | if (pd->exe_descriptor != -1) 892 | { 893 | backtrace_close (pd->exe_descriptor, pd->error_callback, pd->data); 894 | pd->exe_descriptor = -1; 895 | } 896 | 897 | descriptor = backtrace_open (info->dlpi_name, pd->error_callback, 898 | pd->data, &does_not_exist); 899 | if (descriptor < 0) 900 | return 0; 901 | } 902 | 903 | if (elf_add (pd->state, descriptor, info->dlpi_addr, pd->error_callback, 904 | pd->data, &elf_fileline_fn, pd->found_sym, &found_dwarf, 0)) 905 | { 906 | if (found_dwarf) 907 | { 908 | *pd->found_dwarf = 1; 909 | *pd->fileline_fn = elf_fileline_fn; 910 | } 911 | } 912 | 913 | return 0; 914 | } 915 | 916 | /* Initialize the backtrace data we need from an ELF executable. At 917 | the ELF level, all we need to do is find the debug info 918 | sections. */ 919 | 920 | int 921 | backtrace_initialize (struct backtrace_state *state, int descriptor, 922 | backtrace_error_callback error_callback, 923 | void *data, fileline *fileline_fn) 924 | { 925 | int ret; 926 | int found_sym; 927 | int found_dwarf; 928 | fileline elf_fileline_fn; 929 | struct phdr_data pd; 930 | 931 | ret = elf_add (state, descriptor, 0, error_callback, data, &elf_fileline_fn, 932 | &found_sym, &found_dwarf, 1); 933 | if (!ret) 934 | return 0; 935 | 936 | pd.state = state; 937 | pd.error_callback = error_callback; 938 | pd.data = data; 939 | pd.fileline_fn = &elf_fileline_fn; 940 | pd.found_sym = &found_sym; 941 | pd.found_dwarf = &found_dwarf; 942 | pd.exe_descriptor = ret < 0 ? descriptor : -1; 943 | 944 | dl_iterate_phdr (phdr_callback, (void *) &pd); 945 | 946 | if (!state->threaded) 947 | { 948 | if (found_sym) 949 | state->syminfo_fn = elf_syminfo; 950 | else if (state->syminfo_fn == NULL) 951 | state->syminfo_fn = elf_nosyms; 952 | } 953 | else 954 | { 955 | if (found_sym) 956 | backtrace_atomic_store_pointer (&state->syminfo_fn, elf_syminfo); 957 | else 958 | __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, elf_nosyms); 959 | } 960 | 961 | if (!state->threaded) 962 | { 963 | if (state->fileline_fn == NULL || state->fileline_fn == elf_nodebug) 964 | *fileline_fn = elf_fileline_fn; 965 | } 966 | else 967 | { 968 | fileline current_fn; 969 | 970 | current_fn = backtrace_atomic_load_pointer (&state->fileline_fn); 971 | if (current_fn == NULL || current_fn == elf_nodebug) 972 | *fileline_fn = elf_fileline_fn; 973 | } 974 | 975 | return 1; 976 | } 977 | -------------------------------------------------------------------------------- /libbacktrace/fileline.c: -------------------------------------------------------------------------------- 1 | /* fileline.c -- Get file and line number information in a backtrace. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include "backtrace.h" 42 | #include "internal.h" 43 | 44 | #ifndef HAVE_GETEXECNAME 45 | #define getexecname() NULL 46 | #endif 47 | 48 | /* Initialize the fileline information from the executable. Returns 1 49 | on success, 0 on failure. */ 50 | 51 | static int 52 | fileline_initialize (struct backtrace_state *state, 53 | backtrace_error_callback error_callback, void *data) 54 | { 55 | int failed; 56 | fileline fileline_fn; 57 | int pass; 58 | int called_error_callback; 59 | int descriptor; 60 | 61 | if (!state->threaded) 62 | failed = state->fileline_initialization_failed; 63 | else 64 | failed = backtrace_atomic_load_int (&state->fileline_initialization_failed); 65 | 66 | if (failed) 67 | { 68 | error_callback (data, "failed to read executable information", -1); 69 | return 0; 70 | } 71 | 72 | if (!state->threaded) 73 | fileline_fn = state->fileline_fn; 74 | else 75 | fileline_fn = backtrace_atomic_load_pointer (&state->fileline_fn); 76 | if (fileline_fn != NULL) 77 | return 1; 78 | 79 | /* We have not initialized the information. Do it now. */ 80 | 81 | descriptor = -1; 82 | called_error_callback = 0; 83 | for (pass = 0; pass < 4; ++pass) 84 | { 85 | const char *filename; 86 | int does_not_exist; 87 | 88 | switch (pass) 89 | { 90 | case 0: 91 | filename = state->filename; 92 | break; 93 | case 1: 94 | filename = getexecname (); 95 | break; 96 | case 2: 97 | filename = "/proc/self/exe"; 98 | break; 99 | case 3: 100 | filename = "/proc/curproc/file"; 101 | break; 102 | default: 103 | abort (); 104 | } 105 | 106 | if (filename == NULL) 107 | continue; 108 | 109 | descriptor = backtrace_open (filename, error_callback, data, 110 | &does_not_exist); 111 | if (descriptor < 0 && !does_not_exist) 112 | { 113 | called_error_callback = 1; 114 | break; 115 | } 116 | if (descriptor >= 0) 117 | break; 118 | } 119 | 120 | if (descriptor < 0) 121 | { 122 | if (!called_error_callback) 123 | { 124 | if (state->filename != NULL) 125 | error_callback (data, state->filename, ENOENT); 126 | else 127 | error_callback (data, 128 | "libbacktrace could not find executable to open", 129 | 0); 130 | } 131 | failed = 1; 132 | } 133 | 134 | if (!failed) 135 | { 136 | if (!backtrace_initialize (state, descriptor, error_callback, data, 137 | &fileline_fn)) 138 | failed = 1; 139 | } 140 | 141 | if (failed) 142 | { 143 | if (!state->threaded) 144 | state->fileline_initialization_failed = 1; 145 | else 146 | backtrace_atomic_store_int (&state->fileline_initialization_failed, 1); 147 | return 0; 148 | } 149 | 150 | if (!state->threaded) 151 | state->fileline_fn = fileline_fn; 152 | else 153 | { 154 | backtrace_atomic_store_pointer (&state->fileline_fn, fileline_fn); 155 | 156 | /* Note that if two threads initialize at once, one of the data 157 | sets may be leaked. */ 158 | } 159 | 160 | return 1; 161 | } 162 | 163 | /* Given a PC, find the file name, line number, and function name. */ 164 | 165 | int 166 | backtrace_pcinfo (struct backtrace_state *state, uintptr_t pc, 167 | backtrace_full_callback callback, 168 | backtrace_error_callback error_callback, void *data) 169 | { 170 | if (!fileline_initialize (state, error_callback, data)) 171 | return 0; 172 | 173 | if (state->fileline_initialization_failed) 174 | return 0; 175 | 176 | return state->fileline_fn (state, pc, callback, error_callback, data); 177 | } 178 | 179 | /* Given a PC, find the symbol for it, and its value. */ 180 | 181 | int 182 | backtrace_syminfo (struct backtrace_state *state, uintptr_t pc, 183 | backtrace_syminfo_callback callback, 184 | backtrace_error_callback error_callback, void *data) 185 | { 186 | if (!fileline_initialize (state, error_callback, data)) 187 | return 0; 188 | 189 | if (state->fileline_initialization_failed) 190 | return 0; 191 | 192 | state->syminfo_fn (state, pc, callback, error_callback, data); 193 | return 1; 194 | } 195 | -------------------------------------------------------------------------------- /libbacktrace/internal.h: -------------------------------------------------------------------------------- 1 | /* internal.h -- Internal header file for stack backtrace library. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #ifndef BACKTRACE_INTERNAL_H 34 | #define BACKTRACE_INTERNAL_H 35 | 36 | /* We assume that and "backtrace.h" have already been 37 | included. */ 38 | 39 | #ifndef GCC_VERSION 40 | # define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) 41 | #endif 42 | 43 | #if (GCC_VERSION < 2007) 44 | # define __attribute__(x) 45 | #endif 46 | 47 | #ifndef ATTRIBUTE_UNUSED 48 | # define ATTRIBUTE_UNUSED __attribute__ ((__unused__)) 49 | #endif 50 | 51 | #ifndef ATTRIBUTE_MALLOC 52 | # if (GCC_VERSION >= 2096) 53 | # define ATTRIBUTE_MALLOC __attribute__ ((__malloc__)) 54 | # else 55 | # define ATTRIBUTE_MALLOC 56 | # endif 57 | #endif 58 | 59 | #ifndef HAVE_SYNC_FUNCTIONS 60 | 61 | /* Define out the sync functions. These should never be called if 62 | they are not available. */ 63 | 64 | #define __sync_bool_compare_and_swap(A, B, C) (abort(), 1) 65 | #define __sync_lock_test_and_set(A, B) (abort(), 0) 66 | #define __sync_lock_release(A) abort() 67 | 68 | #endif /* !defined (HAVE_SYNC_FUNCTIONS) */ 69 | 70 | #ifdef HAVE_ATOMIC_FUNCTIONS 71 | 72 | /* We have the atomic builtin functions. */ 73 | 74 | #define backtrace_atomic_load_pointer(p) \ 75 | __atomic_load_n ((p), __ATOMIC_ACQUIRE) 76 | #define backtrace_atomic_load_int(p) \ 77 | __atomic_load_n ((p), __ATOMIC_ACQUIRE) 78 | #define backtrace_atomic_store_pointer(p, v) \ 79 | __atomic_store_n ((p), (v), __ATOMIC_RELEASE) 80 | #define backtrace_atomic_store_size_t(p, v) \ 81 | __atomic_store_n ((p), (v), __ATOMIC_RELEASE) 82 | #define backtrace_atomic_store_int(p, v) \ 83 | __atomic_store_n ((p), (v), __ATOMIC_RELEASE) 84 | 85 | #else /* !defined (HAVE_ATOMIC_FUNCTIONS) */ 86 | #ifdef HAVE_SYNC_FUNCTIONS 87 | 88 | /* We have the sync functions but not the atomic functions. Define 89 | the atomic ones in terms of the sync ones. */ 90 | 91 | extern void *backtrace_atomic_load_pointer (void *); 92 | extern int backtrace_atomic_load_int (int *); 93 | extern void backtrace_atomic_store_pointer (void *, void *); 94 | extern void backtrace_atomic_store_size_t (size_t *, size_t); 95 | extern void backtrace_atomic_store_int (int *, int); 96 | 97 | #else /* !defined (HAVE_SYNC_FUNCTIONS) */ 98 | 99 | /* We have neither the sync nor the atomic functions. These will 100 | never be called. */ 101 | 102 | #define backtrace_atomic_load_pointer(p) (abort(), (void *) NULL) 103 | #define backtrace_atomic_load_int(p) (abort(), 0) 104 | #define backtrace_atomic_store_pointer(p, v) abort() 105 | #define backtrace_atomic_store_size_t(p, v) abort() 106 | #define backtrace_atomic_store_int(p, v) abort() 107 | 108 | #endif /* !defined (HAVE_SYNC_FUNCTIONS) */ 109 | #endif /* !defined (HAVE_ATOMIC_FUNCTIONS) */ 110 | 111 | /* The type of the function that collects file/line information. This 112 | is like backtrace_pcinfo. */ 113 | 114 | typedef int (*fileline) (struct backtrace_state *state, uintptr_t pc, 115 | backtrace_full_callback callback, 116 | backtrace_error_callback error_callback, void *data); 117 | 118 | /* The type of the function that collects symbol information. This is 119 | like backtrace_syminfo. */ 120 | 121 | typedef void (*syminfo) (struct backtrace_state *state, uintptr_t pc, 122 | backtrace_syminfo_callback callback, 123 | backtrace_error_callback error_callback, void *data); 124 | 125 | /* What the backtrace state pointer points to. */ 126 | 127 | struct backtrace_state 128 | { 129 | /* The name of the executable. */ 130 | const char *filename; 131 | /* Non-zero if threaded. */ 132 | int threaded; 133 | /* The master lock for fileline_fn, fileline_data, syminfo_fn, 134 | syminfo_data, fileline_initialization_failed and everything the 135 | data pointers point to. */ 136 | void *lock; 137 | /* The function that returns file/line information. */ 138 | fileline fileline_fn; 139 | /* The data to pass to FILELINE_FN. */ 140 | void *fileline_data; 141 | /* The function that returns symbol information. */ 142 | syminfo syminfo_fn; 143 | /* The data to pass to SYMINFO_FN. */ 144 | void *syminfo_data; 145 | /* Whether initializing the file/line information failed. */ 146 | int fileline_initialization_failed; 147 | /* The lock for the freelist. */ 148 | int lock_alloc; 149 | /* The freelist when using mmap. */ 150 | struct backtrace_freelist_struct *freelist; 151 | }; 152 | 153 | /* Open a file for reading. Returns -1 on error. If DOES_NOT_EXIST 154 | is not NULL, *DOES_NOT_EXIST will be set to 0 normally and set to 1 155 | if the file does not exist. If the file does not exist and 156 | DOES_NOT_EXIST is not NULL, the function will return -1 and will 157 | not call ERROR_CALLBACK. On other errors, or if DOES_NOT_EXIST is 158 | NULL, the function will call ERROR_CALLBACK before returning. */ 159 | extern int backtrace_open (const char *filename, 160 | backtrace_error_callback error_callback, 161 | void *data, 162 | int *does_not_exist); 163 | 164 | /* A view of the contents of a file. This supports mmap when 165 | available. A view will remain in memory even after backtrace_close 166 | is called on the file descriptor from which the view was 167 | obtained. */ 168 | 169 | struct backtrace_view 170 | { 171 | /* The data that the caller requested. */ 172 | const void *data; 173 | /* The base of the view. */ 174 | void *base; 175 | /* The total length of the view. */ 176 | size_t len; 177 | }; 178 | 179 | /* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. Store the 180 | result in *VIEW. Returns 1 on success, 0 on error. */ 181 | extern int backtrace_get_view (struct backtrace_state *state, int descriptor, 182 | off_t offset, size_t size, 183 | backtrace_error_callback error_callback, 184 | void *data, struct backtrace_view *view); 185 | 186 | /* Release a view created by backtrace_get_view. */ 187 | extern void backtrace_release_view (struct backtrace_state *state, 188 | struct backtrace_view *view, 189 | backtrace_error_callback error_callback, 190 | void *data); 191 | 192 | /* Close a file opened by backtrace_open. Returns 1 on success, 0 on 193 | error. */ 194 | 195 | extern int backtrace_close (int descriptor, 196 | backtrace_error_callback error_callback, 197 | void *data); 198 | 199 | /* Sort without using memory. */ 200 | 201 | extern void backtrace_qsort (void *base, size_t count, size_t size, 202 | int (*compar) (const void *, const void *)); 203 | 204 | /* Allocate memory. This is like malloc. */ 205 | 206 | extern void *backtrace_alloc (struct backtrace_state *state, size_t size, 207 | backtrace_error_callback error_callback, 208 | void *data) ATTRIBUTE_MALLOC; 209 | 210 | /* Free memory allocated by backtrace_alloc. */ 211 | 212 | extern void backtrace_free (struct backtrace_state *state, void *mem, 213 | size_t size, 214 | backtrace_error_callback error_callback, 215 | void *data); 216 | 217 | /* A growable vector of some struct. This is used for more efficient 218 | allocation when we don't know the final size of some group of data 219 | that we want to represent as an array. */ 220 | 221 | struct backtrace_vector 222 | { 223 | /* The base of the vector. */ 224 | void *base; 225 | /* The number of bytes in the vector. */ 226 | size_t size; 227 | /* The number of bytes available at the current allocation. */ 228 | size_t alc; 229 | }; 230 | 231 | /* Grow VEC by SIZE bytes. Return a pointer to the newly allocated 232 | bytes. Note that this may move the entire vector to a new memory 233 | location. Returns NULL on failure. */ 234 | 235 | extern void *backtrace_vector_grow (struct backtrace_state *state, size_t size, 236 | backtrace_error_callback error_callback, 237 | void *data, 238 | struct backtrace_vector *vec); 239 | 240 | /* Finish the current allocation on VEC. Prepare to start a new 241 | allocation. The finished allocation will never be freed. Returns 242 | a pointer to the base of the finished entries, or NULL on 243 | failure. */ 244 | 245 | extern void* backtrace_vector_finish (struct backtrace_state *state, 246 | struct backtrace_vector *vec, 247 | backtrace_error_callback error_callback, 248 | void *data); 249 | 250 | /* Release any extra space allocated for VEC. This may change 251 | VEC->base. Returns 1 on success, 0 on failure. */ 252 | 253 | extern int backtrace_vector_release (struct backtrace_state *state, 254 | struct backtrace_vector *vec, 255 | backtrace_error_callback error_callback, 256 | void *data); 257 | 258 | /* Read initial debug data from a descriptor, and set the 259 | fileline_data, syminfo_fn, and syminfo_data fields of STATE. 260 | Return the fileln_fn field in *FILELN_FN--this is done this way so 261 | that the synchronization code is only implemented once. This is 262 | called after the descriptor has first been opened. It will close 263 | the descriptor if it is no longer needed. Returns 1 on success, 0 264 | on error. There will be multiple implementations of this function, 265 | for different file formats. Each system will compile the 266 | appropriate one. */ 267 | 268 | extern int backtrace_initialize (struct backtrace_state *state, 269 | int descriptor, 270 | backtrace_error_callback error_callback, 271 | void *data, 272 | fileline *fileline_fn); 273 | 274 | /* Add file/line information for a DWARF module. */ 275 | 276 | extern int backtrace_dwarf_add (struct backtrace_state *state, 277 | uintptr_t base_address, 278 | const unsigned char* dwarf_info, 279 | size_t dwarf_info_size, 280 | const unsigned char *dwarf_line, 281 | size_t dwarf_line_size, 282 | const unsigned char *dwarf_abbrev, 283 | size_t dwarf_abbrev_size, 284 | const unsigned char *dwarf_ranges, 285 | size_t dwarf_range_size, 286 | const unsigned char *dwarf_str, 287 | size_t dwarf_str_size, 288 | int is_bigendian, 289 | backtrace_error_callback error_callback, 290 | void *data, fileline *fileline_fn); 291 | 292 | #endif 293 | -------------------------------------------------------------------------------- /libbacktrace/mmap.c: -------------------------------------------------------------------------------- 1 | /* mmap.c -- Memory allocation with mmap. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | 42 | #include "backtrace.h" 43 | #include "internal.h" 44 | 45 | /* Memory allocation on systems that provide anonymous mmap. This 46 | permits the backtrace functions to be invoked from a signal 47 | handler, assuming that mmap is async-signal safe. */ 48 | 49 | #ifndef MAP_ANONYMOUS 50 | #define MAP_ANONYMOUS MAP_ANON 51 | #endif 52 | 53 | /* A list of free memory blocks. */ 54 | 55 | struct backtrace_freelist_struct 56 | { 57 | /* Next on list. */ 58 | struct backtrace_freelist_struct *next; 59 | /* Size of this block, including this structure. */ 60 | size_t size; 61 | }; 62 | 63 | /* Free memory allocated by backtrace_alloc. */ 64 | 65 | static void 66 | backtrace_free_locked (struct backtrace_state *state, void *addr, size_t size) 67 | { 68 | /* Just leak small blocks. We don't have to be perfect. */ 69 | if (size >= sizeof (struct backtrace_freelist_struct)) 70 | { 71 | struct backtrace_freelist_struct *p; 72 | 73 | p = (struct backtrace_freelist_struct *) addr; 74 | p->next = state->freelist; 75 | p->size = size; 76 | state->freelist = p; 77 | } 78 | } 79 | 80 | /* Allocate memory like malloc. */ 81 | 82 | void * 83 | backtrace_alloc (struct backtrace_state *state, 84 | size_t size, backtrace_error_callback error_callback, 85 | void *data) 86 | { 87 | void *ret; 88 | int locked; 89 | struct backtrace_freelist_struct **pp; 90 | size_t pagesize; 91 | size_t asksize; 92 | void *page; 93 | 94 | ret = NULL; 95 | 96 | /* If we can acquire the lock, then see if there is space on the 97 | free list. If we can't acquire the lock, drop straight into 98 | using mmap. __sync_lock_test_and_set returns the old state of 99 | the lock, so we have acquired it if it returns 0. */ 100 | 101 | if (!state->threaded) 102 | locked = 1; 103 | else 104 | locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0; 105 | 106 | if (locked) 107 | { 108 | for (pp = &state->freelist; *pp != NULL; pp = &(*pp)->next) 109 | { 110 | if ((*pp)->size >= size) 111 | { 112 | struct backtrace_freelist_struct *p; 113 | 114 | p = *pp; 115 | *pp = p->next; 116 | 117 | /* Round for alignment; we assume that no type we care about 118 | is more than 8 bytes. */ 119 | size = (size + 7) & ~ (size_t) 7; 120 | if (size < p->size) 121 | backtrace_free_locked (state, (char *) p + size, 122 | p->size - size); 123 | 124 | ret = (void *) p; 125 | 126 | break; 127 | } 128 | } 129 | 130 | if (state->threaded) 131 | __sync_lock_release (&state->lock_alloc); 132 | } 133 | 134 | if (ret == NULL) 135 | { 136 | /* Allocate a new page. */ 137 | 138 | pagesize = getpagesize (); 139 | asksize = (size + pagesize - 1) & ~ (pagesize - 1); 140 | page = mmap (NULL, asksize, PROT_READ | PROT_WRITE, 141 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); 142 | if (page == NULL) 143 | error_callback (data, "mmap", errno); 144 | else 145 | { 146 | size = (size + 7) & ~ (size_t) 7; 147 | if (size < asksize) 148 | backtrace_free (state, (char *) page + size, asksize - size, 149 | error_callback, data); 150 | 151 | ret = page; 152 | } 153 | } 154 | 155 | return ret; 156 | } 157 | 158 | /* Free memory allocated by backtrace_alloc. */ 159 | 160 | void 161 | backtrace_free (struct backtrace_state *state, void *addr, size_t size, 162 | backtrace_error_callback error_callback ATTRIBUTE_UNUSED, 163 | void *data ATTRIBUTE_UNUSED) 164 | { 165 | int locked; 166 | 167 | /* If we are freeing a large aligned block, just release it back to 168 | the system. This case arises when growing a vector for a large 169 | binary with lots of debug info. Calling munmap here may cause us 170 | to call mmap again if there is also a large shared library; we 171 | just live with that. */ 172 | if (size >= 16 * 4096) 173 | { 174 | size_t pagesize; 175 | 176 | pagesize = getpagesize (); 177 | if (((uintptr_t) addr & (pagesize - 1)) == 0 178 | && (size & (pagesize - 1)) == 0) 179 | { 180 | /* If munmap fails for some reason, just add the block to 181 | the freelist. */ 182 | if (munmap (addr, size) == 0) 183 | return; 184 | } 185 | } 186 | 187 | /* If we can acquire the lock, add the new space to the free list. 188 | If we can't acquire the lock, just leak the memory. 189 | __sync_lock_test_and_set returns the old state of the lock, so we 190 | have acquired it if it returns 0. */ 191 | 192 | if (!state->threaded) 193 | locked = 1; 194 | else 195 | locked = __sync_lock_test_and_set (&state->lock_alloc, 1) == 0; 196 | 197 | if (locked) 198 | { 199 | backtrace_free_locked (state, addr, size); 200 | 201 | if (state->threaded) 202 | __sync_lock_release (&state->lock_alloc); 203 | } 204 | } 205 | 206 | /* Grow VEC by SIZE bytes. */ 207 | 208 | void * 209 | backtrace_vector_grow (struct backtrace_state *state,size_t size, 210 | backtrace_error_callback error_callback, 211 | void *data, struct backtrace_vector *vec) 212 | { 213 | void *ret; 214 | 215 | if (size > vec->alc) 216 | { 217 | size_t pagesize; 218 | size_t alc; 219 | void *base; 220 | 221 | pagesize = getpagesize (); 222 | alc = vec->size + size; 223 | if (vec->size == 0) 224 | alc = 16 * size; 225 | else if (alc < pagesize) 226 | { 227 | alc *= 2; 228 | if (alc > pagesize) 229 | alc = pagesize; 230 | } 231 | else 232 | { 233 | alc *= 2; 234 | alc = (alc + pagesize - 1) & ~ (pagesize - 1); 235 | } 236 | base = backtrace_alloc (state, alc, error_callback, data); 237 | if (base == NULL) 238 | return NULL; 239 | if (vec->base != NULL) 240 | { 241 | memcpy (base, vec->base, vec->size); 242 | backtrace_free (state, vec->base, vec->size + vec->alc, 243 | error_callback, data); 244 | } 245 | vec->base = base; 246 | vec->alc = alc - vec->size; 247 | } 248 | 249 | ret = (char *) vec->base + vec->size; 250 | vec->size += size; 251 | vec->alc -= size; 252 | return ret; 253 | } 254 | 255 | /* Finish the current allocation on VEC. */ 256 | 257 | void * 258 | backtrace_vector_finish ( 259 | struct backtrace_state *state ATTRIBUTE_UNUSED, 260 | struct backtrace_vector *vec, 261 | backtrace_error_callback error_callback ATTRIBUTE_UNUSED, 262 | void *data ATTRIBUTE_UNUSED) 263 | { 264 | void *ret; 265 | 266 | ret = vec->base; 267 | vec->base = (char *) vec->base + vec->size; 268 | vec->size = 0; 269 | return ret; 270 | } 271 | 272 | /* Release any extra space allocated for VEC. */ 273 | 274 | int 275 | backtrace_vector_release (struct backtrace_state *state, 276 | struct backtrace_vector *vec, 277 | backtrace_error_callback error_callback, 278 | void *data) 279 | { 280 | size_t size; 281 | size_t alc; 282 | size_t aligned; 283 | 284 | /* Make sure that the block that we free is aligned on an 8-byte 285 | boundary. */ 286 | size = vec->size; 287 | alc = vec->alc; 288 | aligned = (size + 7) & ~ (size_t) 7; 289 | alc -= aligned - size; 290 | 291 | backtrace_free (state, (char *) vec->base + aligned, alc, 292 | error_callback, data); 293 | vec->alc = 0; 294 | return 1; 295 | } 296 | -------------------------------------------------------------------------------- /libbacktrace/mmapio.c: -------------------------------------------------------------------------------- 1 | /* mmapio.c -- File views using mmap. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "backtrace.h" 41 | #include "internal.h" 42 | 43 | #ifndef MAP_FAILED 44 | #define MAP_FAILED ((void *)-1) 45 | #endif 46 | 47 | /* This file implements file views and memory allocation when mmap is 48 | available. */ 49 | 50 | /* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. */ 51 | 52 | int 53 | backtrace_get_view (struct backtrace_state *state ATTRIBUTE_UNUSED, 54 | int descriptor, off_t offset, size_t size, 55 | backtrace_error_callback error_callback, 56 | void *data, struct backtrace_view *view) 57 | { 58 | size_t pagesize; 59 | unsigned int inpage; 60 | off_t pageoff; 61 | void *map; 62 | 63 | pagesize = getpagesize (); 64 | inpage = offset % pagesize; 65 | pageoff = offset - inpage; 66 | 67 | size += inpage; 68 | size = (size + (pagesize - 1)) & ~ (pagesize - 1); 69 | 70 | map = mmap (NULL, size, PROT_READ, MAP_PRIVATE, descriptor, pageoff); 71 | if (map == MAP_FAILED) 72 | { 73 | error_callback (data, "mmap", errno); 74 | return 0; 75 | } 76 | 77 | view->data = (char *) map + inpage; 78 | view->base = map; 79 | view->len = size; 80 | 81 | return 1; 82 | } 83 | 84 | /* Release a view read by backtrace_get_view. */ 85 | 86 | void 87 | backtrace_release_view (struct backtrace_state *state ATTRIBUTE_UNUSED, 88 | struct backtrace_view *view, 89 | backtrace_error_callback error_callback, 90 | void *data) 91 | { 92 | union { 93 | const void *cv; 94 | void *v; 95 | } const_cast; 96 | 97 | const_cast.cv = view->base; 98 | if (munmap (const_cast.v, view->len) < 0) 99 | error_callback (data, "munmap", errno); 100 | } 101 | -------------------------------------------------------------------------------- /libbacktrace/nounwind.c: -------------------------------------------------------------------------------- 1 | /* backtrace.c -- Entry point for stack backtrace library. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | 37 | #include "backtrace.h" 38 | 39 | #include "internal.h" 40 | 41 | /* This source file is compiled if the unwind library is not 42 | available. */ 43 | 44 | int 45 | backtrace_full (struct backtrace_state *state ATTRIBUTE_UNUSED, 46 | int skip ATTRIBUTE_UNUSED, 47 | backtrace_full_callback callback ATTRIBUTE_UNUSED, 48 | backtrace_error_callback error_callback, void *data) 49 | { 50 | error_callback (data, 51 | "no stack trace because unwind library not available", 52 | 0); 53 | return 0; 54 | } 55 | 56 | int 57 | backtrace_simple (struct backtrace_state *state ATTRIBUTE_UNUSED, 58 | int skip ATTRIBUTE_UNUSED, 59 | backtrace_simple_callback callback ATTRIBUTE_UNUSED, 60 | backtrace_error_callback error_callback, void *data) 61 | { 62 | error_callback (data, 63 | "no stack trace because unwind library not available", 64 | 0); 65 | return 0; 66 | } 67 | -------------------------------------------------------------------------------- /libbacktrace/posix.c: -------------------------------------------------------------------------------- 1 | /* posix.c -- POSIX file I/O routines for the backtrace library. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | #include "backtrace.h" 42 | #include "internal.h" 43 | 44 | #ifndef O_BINARY 45 | #define O_BINARY 0 46 | #endif 47 | 48 | #ifndef O_CLOEXEC 49 | #define O_CLOEXEC 0 50 | #endif 51 | 52 | #ifndef FD_CLOEXEC 53 | #define FD_CLOEXEC 1 54 | #endif 55 | 56 | /* Open a file for reading. */ 57 | 58 | int 59 | backtrace_open (const char *filename, backtrace_error_callback error_callback, 60 | void *data, int *does_not_exist) 61 | { 62 | int descriptor; 63 | 64 | if (does_not_exist != NULL) 65 | *does_not_exist = 0; 66 | 67 | descriptor = open (filename, O_RDONLY | O_BINARY | O_CLOEXEC); 68 | if (descriptor < 0) 69 | { 70 | if (does_not_exist != NULL && errno == ENOENT) 71 | *does_not_exist = 1; 72 | else 73 | error_callback (data, filename, errno); 74 | return -1; 75 | } 76 | 77 | #ifdef HAVE_FCNTL 78 | /* Set FD_CLOEXEC just in case the kernel does not support 79 | O_CLOEXEC. It doesn't matter if this fails for some reason. 80 | FIXME: At some point it should be safe to only do this if 81 | O_CLOEXEC == 0. */ 82 | fcntl (descriptor, F_SETFD, FD_CLOEXEC); 83 | #endif 84 | 85 | return descriptor; 86 | } 87 | 88 | /* Close DESCRIPTOR. */ 89 | 90 | int 91 | backtrace_close (int descriptor, backtrace_error_callback error_callback, 92 | void *data) 93 | { 94 | if (close (descriptor) < 0) 95 | { 96 | error_callback (data, "close", errno); 97 | return 0; 98 | } 99 | return 1; 100 | } 101 | -------------------------------------------------------------------------------- /libbacktrace/print.c: -------------------------------------------------------------------------------- 1 | /* print.c -- Print the current backtrace. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | #include 37 | #include 38 | 39 | #include "backtrace.h" 40 | #include "internal.h" 41 | 42 | /* Passed to callbacks. */ 43 | 44 | struct print_data 45 | { 46 | struct backtrace_state *state; 47 | FILE *f; 48 | }; 49 | 50 | /* Print one level of a backtrace. */ 51 | 52 | static int 53 | print_callback (void *data, uintptr_t pc, const char *filename, int lineno, 54 | const char *function) 55 | { 56 | struct print_data *pdata = (struct print_data *) data; 57 | 58 | fprintf (pdata->f, "0x%lx %s\n\t%s:%d\n", 59 | (unsigned long) pc, 60 | function == NULL ? "???" : function, 61 | filename == NULL ? "???" : filename, 62 | lineno); 63 | return 0; 64 | } 65 | 66 | /* Print errors to stderr. */ 67 | 68 | static void 69 | error_callback (void *data, const char *msg, int errnum) 70 | { 71 | struct print_data *pdata = (struct print_data *) data; 72 | 73 | if (pdata->state->filename != NULL) 74 | fprintf (stderr, "%s: ", pdata->state->filename); 75 | fprintf (stderr, "libbacktrace: %s", msg); 76 | if (errnum > 0) 77 | fprintf (stderr, ": %s", strerror (errnum)); 78 | fputc ('\n', stderr); 79 | } 80 | 81 | /* Print a backtrace. */ 82 | 83 | void 84 | backtrace_print (struct backtrace_state *state, int skip, FILE *f) 85 | { 86 | struct print_data data; 87 | 88 | data.state = state; 89 | data.f = f; 90 | backtrace_full (state, skip + 1, print_callback, error_callback, 91 | (void *) &data); 92 | } 93 | -------------------------------------------------------------------------------- /libbacktrace/read.c: -------------------------------------------------------------------------------- 1 | /* read.c -- File views without mmap. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "backtrace.h" 41 | #include "internal.h" 42 | 43 | /* This file implements file views when mmap is not available. */ 44 | 45 | /* Create a view of SIZE bytes from DESCRIPTOR at OFFSET. */ 46 | 47 | int 48 | backtrace_get_view (struct backtrace_state *state, int descriptor, 49 | off_t offset, size_t size, 50 | backtrace_error_callback error_callback, 51 | void *data, struct backtrace_view *view) 52 | { 53 | ssize_t got; 54 | 55 | if (lseek (descriptor, offset, SEEK_SET) < 0) 56 | { 57 | error_callback (data, "lseek", errno); 58 | return 0; 59 | } 60 | 61 | view->base = backtrace_alloc (state, size, error_callback, data); 62 | if (view->base == NULL) 63 | return 0; 64 | view->data = view->base; 65 | view->len = size; 66 | 67 | got = read (descriptor, view->base, size); 68 | if (got < 0) 69 | { 70 | error_callback (data, "read", errno); 71 | free (view->base); 72 | return 0; 73 | } 74 | 75 | if ((size_t) got < size) 76 | { 77 | error_callback (data, "file too short", 0); 78 | free (view->base); 79 | return 0; 80 | } 81 | 82 | return 1; 83 | } 84 | 85 | /* Release a view read by backtrace_get_view. */ 86 | 87 | void 88 | backtrace_release_view (struct backtrace_state *state, 89 | struct backtrace_view *view, 90 | backtrace_error_callback error_callback, 91 | void *data) 92 | { 93 | backtrace_free (state, view->base, view->len, error_callback, data); 94 | view->data = NULL; 95 | view->base = NULL; 96 | } 97 | -------------------------------------------------------------------------------- /libbacktrace/simple.c: -------------------------------------------------------------------------------- 1 | /* simple.c -- The backtrace_simple function. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include "unwind.h" 36 | #include "backtrace.h" 37 | 38 | /* The simple_backtrace routine. */ 39 | 40 | /* Data passed through _Unwind_Backtrace. */ 41 | 42 | struct backtrace_simple_data 43 | { 44 | /* Number of frames to skip. */ 45 | int skip; 46 | /* Library state. */ 47 | struct backtrace_state *state; 48 | /* Callback routine. */ 49 | backtrace_simple_callback callback; 50 | /* Error callback routine. */ 51 | backtrace_error_callback error_callback; 52 | /* Data to pass to callback routine. */ 53 | void *data; 54 | /* Value to return from backtrace. */ 55 | int ret; 56 | }; 57 | 58 | /* Unwind library callback routine. This is passd to 59 | _Unwind_Backtrace. */ 60 | 61 | static _Unwind_Reason_Code 62 | simple_unwind (struct _Unwind_Context *context, void *vdata) 63 | { 64 | struct backtrace_simple_data *bdata = (struct backtrace_simple_data *) vdata; 65 | uintptr_t pc; 66 | int ip_before_insn = 0; 67 | 68 | #ifdef HAVE_GETIPINFO 69 | pc = _Unwind_GetIPInfo (context, &ip_before_insn); 70 | #else 71 | pc = _Unwind_GetIP (context); 72 | #endif 73 | 74 | if (bdata->skip > 0) 75 | { 76 | --bdata->skip; 77 | return _URC_NO_REASON; 78 | } 79 | 80 | if (!ip_before_insn) 81 | --pc; 82 | 83 | bdata->ret = bdata->callback (bdata->data, pc); 84 | 85 | if (bdata->ret != 0) 86 | return _URC_END_OF_STACK; 87 | 88 | return _URC_NO_REASON; 89 | } 90 | 91 | /* Get a simple stack backtrace. */ 92 | 93 | int 94 | backtrace_simple (struct backtrace_state *state, int skip, 95 | backtrace_simple_callback callback, 96 | backtrace_error_callback error_callback, void *data) 97 | { 98 | struct backtrace_simple_data bdata; 99 | 100 | bdata.skip = skip + 1; 101 | bdata.state = state; 102 | bdata.callback = callback; 103 | bdata.error_callback = error_callback; 104 | bdata.data = data; 105 | bdata.ret = 0; 106 | _Unwind_Backtrace (simple_unwind, &bdata); 107 | return bdata.ret; 108 | } 109 | -------------------------------------------------------------------------------- /libbacktrace/sort.c: -------------------------------------------------------------------------------- 1 | /* sort.c -- Sort without allocating memory 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | #include 37 | 38 | #include "backtrace.h" 39 | #include "internal.h" 40 | 41 | /* The GNU glibc version of qsort allocates memory, which we must not 42 | do if we are invoked by a signal handler. So provide our own 43 | sort. */ 44 | 45 | static void 46 | swap (char *a, char *b, size_t size) 47 | { 48 | size_t i; 49 | 50 | for (i = 0; i < size; i++, a++, b++) 51 | { 52 | char t; 53 | 54 | t = *a; 55 | *a = *b; 56 | *b = t; 57 | } 58 | } 59 | 60 | void 61 | backtrace_qsort (void *basearg, size_t count, size_t size, 62 | int (*compar) (const void *, const void *)) 63 | { 64 | char *base = (char *) basearg; 65 | size_t i; 66 | size_t mid; 67 | 68 | tail_recurse: 69 | if (count < 2) 70 | return; 71 | 72 | /* The symbol table and DWARF tables, which is all we use this 73 | routine for, tend to be roughly sorted. Pick the middle element 74 | in the array as our pivot point, so that we are more likely to 75 | cut the array in half for each recursion step. */ 76 | swap (base, base + (count / 2) * size, size); 77 | 78 | mid = 0; 79 | for (i = 1; i < count; i++) 80 | { 81 | if ((*compar) (base, base + i * size) > 0) 82 | { 83 | ++mid; 84 | if (i != mid) 85 | swap (base + mid * size, base + i * size, size); 86 | } 87 | } 88 | 89 | if (mid > 0) 90 | swap (base, base + mid * size, size); 91 | 92 | /* Recurse with the smaller array, loop with the larger one. That 93 | ensures that our maximum stack depth is log count. */ 94 | if (2 * mid < count) 95 | { 96 | backtrace_qsort (base, mid, size, compar); 97 | base += (mid + 1) * size; 98 | count -= mid + 1; 99 | goto tail_recurse; 100 | } 101 | else 102 | { 103 | backtrace_qsort (base + (mid + 1) * size, count - (mid + 1), 104 | size, compar); 105 | count = mid; 106 | goto tail_recurse; 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /libbacktrace/state.c: -------------------------------------------------------------------------------- 1 | /* state.c -- Create the backtrace state. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | #include 37 | 38 | #include "backtrace.h" 39 | #include "backtrace-supported.h" 40 | #include "internal.h" 41 | 42 | /* Create the backtrace state. This will then be passed to all the 43 | other routines. */ 44 | 45 | struct backtrace_state * 46 | backtrace_create_state (const char *filename, int threaded, 47 | backtrace_error_callback error_callback, 48 | void *data) 49 | { 50 | struct backtrace_state init_state; 51 | struct backtrace_state *state; 52 | 53 | #ifndef HAVE_SYNC_FUNCTIONS 54 | if (threaded) 55 | { 56 | error_callback (data, "backtrace library does not support threads", 0); 57 | return NULL; 58 | } 59 | #endif 60 | 61 | memset (&init_state, 0, sizeof init_state); 62 | init_state.filename = filename; 63 | init_state.threaded = threaded; 64 | 65 | state = ((struct backtrace_state *) 66 | backtrace_alloc (&init_state, sizeof *state, error_callback, data)); 67 | if (state == NULL) 68 | return NULL; 69 | *state = init_state; 70 | 71 | return state; 72 | } 73 | -------------------------------------------------------------------------------- /libbacktrace/stest.c: -------------------------------------------------------------------------------- 1 | /* stest.c -- Test for libbacktrace internal sort function 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | #include "backtrace.h" 41 | #include "internal.h" 42 | 43 | /* Test the local qsort implementation. */ 44 | 45 | #define MAX 10 46 | 47 | struct test 48 | { 49 | size_t count; 50 | int input[MAX]; 51 | int output[MAX]; 52 | }; 53 | 54 | static struct test tests[] = 55 | { 56 | { 57 | 10, 58 | { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 59 | { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 } 60 | }, 61 | { 62 | 9, 63 | { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 64 | { 1, 2, 3, 4, 5, 6, 7, 8, 9 } 65 | }, 66 | { 67 | 10, 68 | { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 }, 69 | { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 70 | }, 71 | { 72 | 9, 73 | { 9, 8, 7, 6, 5, 4, 3, 2, 1 }, 74 | { 1, 2, 3, 4, 5, 6, 7, 8, 9 }, 75 | }, 76 | { 77 | 10, 78 | { 2, 4, 6, 8, 10, 1, 3, 5, 7, 9 }, 79 | { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }, 80 | }, 81 | { 82 | 5, 83 | { 4, 5, 3, 1, 2 }, 84 | { 1, 2, 3, 4, 5 }, 85 | }, 86 | { 87 | 5, 88 | { 1, 1, 1, 1, 1 }, 89 | { 1, 1, 1, 1, 1 }, 90 | }, 91 | { 92 | 5, 93 | { 1, 1, 2, 1, 1 }, 94 | { 1, 1, 1, 1, 2 }, 95 | }, 96 | { 97 | 5, 98 | { 2, 1, 1, 1, 1 }, 99 | { 1, 1, 1, 1, 2 }, 100 | }, 101 | }; 102 | 103 | static int 104 | compare (const void *a, const void *b) 105 | { 106 | const int *ai = (const int *) a; 107 | const int *bi = (const int *) b; 108 | 109 | return *ai - *bi; 110 | } 111 | 112 | int 113 | main (int argc ATTRIBUTE_UNUSED, char **argv ATTRIBUTE_UNUSED) 114 | { 115 | int failures; 116 | size_t i; 117 | int a[MAX]; 118 | 119 | failures = 0; 120 | for (i = 0; i < sizeof tests / sizeof tests[0]; i++) 121 | { 122 | memcpy (a, tests[i].input, tests[i].count * sizeof (int)); 123 | backtrace_qsort (a, tests[i].count, sizeof (int), compare); 124 | if (memcmp (a, tests[i].output, tests[i].count * sizeof (int)) != 0) 125 | { 126 | size_t j; 127 | 128 | fprintf (stderr, "test %d failed:", (int) i); 129 | for (j = 0; j < tests[i].count; j++) 130 | fprintf (stderr, " %d", a[j]); 131 | fprintf (stderr, "\n"); 132 | ++failures; 133 | } 134 | } 135 | 136 | exit (failures > 0 ? EXIT_FAILURE : EXIT_SUCCESS); 137 | } 138 | -------------------------------------------------------------------------------- /libbacktrace/unknown.c: -------------------------------------------------------------------------------- 1 | /* unknown.c -- used when backtrace configury does not know file format. 2 | Copyright (C) 2012-2014 Free Software Foundation, Inc. 3 | Written by Ian Lance Taylor, Google. 4 | 5 | Redistribution and use in source and binary forms, with or without 6 | modification, are permitted provided that the following conditions are 7 | met: 8 | 9 | (1) Redistributions of source code must retain the above copyright 10 | notice, this list of conditions and the following disclaimer. 11 | 12 | (2) Redistributions in binary form must reproduce the above copyright 13 | notice, this list of conditions and the following disclaimer in 14 | the documentation and/or other materials provided with the 15 | distribution. 16 | 17 | (3) The name of the author may not be used to 18 | endorse or promote products derived from this software without 19 | specific prior written permission. 20 | 21 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 | DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 | INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 | HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 | STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 30 | IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 | POSSIBILITY OF SUCH DAMAGE. */ 32 | 33 | #include "config.h" 34 | 35 | #include 36 | 37 | #include "backtrace.h" 38 | #include "internal.h" 39 | 40 | /* A trivial routine that always fails to find fileline data. */ 41 | 42 | static int 43 | unknown_fileline (struct backtrace_state *state ATTRIBUTE_UNUSED, 44 | uintptr_t pc, backtrace_full_callback callback, 45 | backtrace_error_callback error_callback ATTRIBUTE_UNUSED, 46 | void *data) 47 | 48 | { 49 | return callback (data, pc, NULL, 0, NULL); 50 | } 51 | 52 | /* Initialize the backtrace data when we don't know how to read the 53 | debug info. */ 54 | 55 | int 56 | backtrace_initialize (struct backtrace_state *state ATTRIBUTE_UNUSED, 57 | int descriptor ATTRIBUTE_UNUSED, 58 | backtrace_error_callback error_callback ATTRIBUTE_UNUSED, 59 | void *data ATTRIBUTE_UNUSED, fileline *fileline_fn) 60 | { 61 | state->fileline_data = NULL; 62 | *fileline_fn = unknown_fileline; 63 | return 1; 64 | } 65 | --------------------------------------------------------------------------------