mirror of
https://github.com/tildearrow/furnace.git
synced 2024-12-22 16:30:26 +00:00
experiment with backward-cpp again
This commit is contained in:
parent
979cb63c5b
commit
914b5f7a88
9 changed files with 5511 additions and 0 deletions
|
@ -24,8 +24,10 @@ set(SYSTEM_SDL2_DEFAULT OFF)
|
||||||
|
|
||||||
if (ANDROID)
|
if (ANDROID)
|
||||||
set(USE_RTMIDI_DEFAULT OFF)
|
set(USE_RTMIDI_DEFAULT OFF)
|
||||||
|
set(USE_BACKWARD_DEFAULT OFF)
|
||||||
else()
|
else()
|
||||||
set(USE_RTMIDI_DEFAULT ON)
|
set(USE_RTMIDI_DEFAULT ON)
|
||||||
|
set(USE_BACKWARD_DEFAULT ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(PkgConfig)
|
find_package(PkgConfig)
|
||||||
|
@ -40,6 +42,7 @@ option(BUILD_GUI "Build the tracker (disable to build only a headless player)" $
|
||||||
option(USE_RTMIDI "Build with MIDI support using RtMidi." ${USE_RTMIDI_DEFAULT})
|
option(USE_RTMIDI "Build with MIDI support using RtMidi." ${USE_RTMIDI_DEFAULT})
|
||||||
option(USE_SDL2 "Build with SDL2. Required to build with GUI." ${USE_SDL2_DEFAULT})
|
option(USE_SDL2 "Build with SDL2. Required to build with GUI." ${USE_SDL2_DEFAULT})
|
||||||
option(USE_SNDFILE "Build with libsndfile. Required in order to work with audio files." ${USE_SNDFILE_DEFAULT})
|
option(USE_SNDFILE "Build with libsndfile. Required in order to work with audio files." ${USE_SNDFILE_DEFAULT})
|
||||||
|
option(USE_BACKWARD "Use backward-cpp to print a backtrace on crash/abort." ${USE_BACKWARD_DEFAULT})
|
||||||
option(WITH_JACK "Whether to build with JACK support. Auto-detects if JACK is available" ${WITH_JACK_DEFAULT})
|
option(WITH_JACK "Whether to build with JACK support. Auto-detects if JACK is available" ${WITH_JACK_DEFAULT})
|
||||||
option(SYSTEM_FMT "Use a system-installed version of fmt instead of the vendored one" OFF)
|
option(SYSTEM_FMT "Use a system-installed version of fmt instead of the vendored one" OFF)
|
||||||
option(SYSTEM_LIBSNDFILE "Use a system-installed version of libsndfile instead of the vendored one" OFF)
|
option(SYSTEM_LIBSNDFILE "Use a system-installed version of libsndfile instead of the vendored one" OFF)
|
||||||
|
@ -500,6 +503,10 @@ endif()
|
||||||
|
|
||||||
set(USED_SOURCES ${ENGINE_SOURCES} ${AUDIO_SOURCES} src/main.cpp)
|
set(USED_SOURCES ${ENGINE_SOURCES} ${AUDIO_SOURCES} src/main.cpp)
|
||||||
|
|
||||||
|
if (USE_BACKWARD)
|
||||||
|
list(APPEND USED_SOURCES src/backtrace.cpp)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (BUILD_GUI)
|
if (BUILD_GUI)
|
||||||
list(APPEND USED_SOURCES ${GUI_SOURCES})
|
list(APPEND USED_SOURCES ${GUI_SOURCES})
|
||||||
list(APPEND DEPENDENCIES_INCLUDE_DIRS
|
list(APPEND DEPENDENCIES_INCLUDE_DIRS
|
||||||
|
|
265
extern/backward/BackwardConfig.cmake
vendored
Normal file
265
extern/backward/BackwardConfig.cmake
vendored
Normal file
|
@ -0,0 +1,265 @@
|
||||||
|
#
|
||||||
|
# BackwardMacros.cmake
|
||||||
|
# Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# OPTIONS
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
set(STACK_WALKING_UNWIND TRUE CACHE BOOL
|
||||||
|
"Use compiler's unwind API")
|
||||||
|
set(STACK_WALKING_BACKTRACE FALSE CACHE BOOL
|
||||||
|
"Use backtrace from (e)glibc for stack walking")
|
||||||
|
set(STACK_WALKING_LIBUNWIND FALSE CACHE BOOL
|
||||||
|
"Use libunwind for stack walking")
|
||||||
|
|
||||||
|
set(STACK_DETAILS_AUTO_DETECT TRUE CACHE BOOL
|
||||||
|
"Auto detect backward's stack details dependencies")
|
||||||
|
|
||||||
|
set(STACK_DETAILS_BACKTRACE_SYMBOL FALSE CACHE BOOL
|
||||||
|
"Use backtrace from (e)glibc for symbols resolution")
|
||||||
|
set(STACK_DETAILS_DW FALSE CACHE BOOL
|
||||||
|
"Use libdw to read debug info")
|
||||||
|
set(STACK_DETAILS_BFD FALSE CACHE BOOL
|
||||||
|
"Use libbfd to read debug info")
|
||||||
|
set(STACK_DETAILS_DWARF FALSE CACHE BOOL
|
||||||
|
"Use libdwarf/libelf to read debug info")
|
||||||
|
|
||||||
|
if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR AND NOT DEFINED BACKWARD_TESTS)
|
||||||
|
# If this is a top level CMake project, we most lixely want the tests
|
||||||
|
set(BACKWARD_TESTS ON CACHE BOOL "Enable tests")
|
||||||
|
else()
|
||||||
|
set(BACKWARD_TESTS OFF CACHE BOOL "Enable tests")
|
||||||
|
endif()
|
||||||
|
###############################################################################
|
||||||
|
# CONFIGS
|
||||||
|
###############################################################################
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
|
||||||
|
if (STACK_WALKING_LIBUNWIND)
|
||||||
|
# libunwind works on the macOS without having to add special include
|
||||||
|
# paths or libraries
|
||||||
|
if (NOT APPLE)
|
||||||
|
find_path(LIBUNWIND_INCLUDE_DIR NAMES "libunwind.h")
|
||||||
|
find_library(LIBUNWIND_LIBRARY unwind)
|
||||||
|
|
||||||
|
if (LIBUNWIND_LIBRARY)
|
||||||
|
include(CheckSymbolExists)
|
||||||
|
check_symbol_exists(UNW_INIT_SIGNAL_FRAME libunwind.h HAVE_UNW_INIT_SIGNAL_FRAME)
|
||||||
|
if (NOT HAVE_UNW_INIT_SIGNAL_FRAME)
|
||||||
|
message(STATUS "libunwind does not support unwinding from signal handler frames")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(LIBUNWIND_INCLUDE_DIRS ${LIBUNWIND_INCLUDE_DIR})
|
||||||
|
set(LIBDWARF_LIBRARIES ${LIBUNWIND_LIBRARY})
|
||||||
|
find_package_handle_standard_args(libunwind DEFAULT_MSG
|
||||||
|
LIBUNWIND_LIBRARY LIBUNWIND_INCLUDE_DIR)
|
||||||
|
mark_as_advanced(LIBUNWIND_INCLUDE_DIR LIBUNWIND_LIBRARY)
|
||||||
|
list(APPEND _BACKWARD_LIBRARIES ${LIBUNWIND_LIBRARY})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Disable other unwinders if libunwind is found
|
||||||
|
set(STACK_WALKING_UNWIND FALSE)
|
||||||
|
set(STACK_WALKING_BACKTRACE FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (${STACK_DETAILS_AUTO_DETECT})
|
||||||
|
if(NOT CMAKE_VERSION VERSION_LESS 3.17)
|
||||||
|
set(_name_mismatched_arg NAME_MISMATCHED)
|
||||||
|
endif()
|
||||||
|
# find libdw
|
||||||
|
find_path(LIBDW_INCLUDE_DIR NAMES "elfutils/libdw.h" "elfutils/libdwfl.h")
|
||||||
|
find_library(LIBDW_LIBRARY dw)
|
||||||
|
# in case it's statically linked, look for all the possible dependencies
|
||||||
|
find_library(LIBELF_LIBRARY elf)
|
||||||
|
find_library(LIBPTHREAD_LIBRARY pthread)
|
||||||
|
find_library(LIBZ_LIBRARY z)
|
||||||
|
find_library(LIBBZ2_LIBRARY bz2)
|
||||||
|
find_library(LIBLZMA_LIBRARY lzma)
|
||||||
|
find_library(LIBZSTD_LIBRARY zstd)
|
||||||
|
set(LIBDW_INCLUDE_DIRS ${LIBDW_INCLUDE_DIR} )
|
||||||
|
set(LIBDW_LIBRARIES ${LIBDW_LIBRARY}
|
||||||
|
$<$<BOOL:${LIBELF_LIBRARY}>:${LIBELF_LIBRARY}>
|
||||||
|
$<$<BOOL:${LIBPTHREAD_LIBRARY}>:${LIBPTHREAD_LIBRARY}>
|
||||||
|
$<$<BOOL:${LIBZ_LIBRARY}>:${LIBZ_LIBRARY}>
|
||||||
|
$<$<BOOL:${LIBBZ2_LIBRARY}>:${LIBBZ2_LIBRARY}>
|
||||||
|
$<$<BOOL:${LIBLZMA_LIBRARY}>:${LIBLZMA_LIBRARY}>
|
||||||
|
$<$<BOOL:${LIBZSTD_LIBRARY}>:${LIBZSTD_LIBRARY}>)
|
||||||
|
find_package_handle_standard_args(libdw ${_name_mismatched_arg}
|
||||||
|
REQUIRED_VARS LIBDW_LIBRARY LIBDW_INCLUDE_DIR)
|
||||||
|
mark_as_advanced(LIBDW_INCLUDE_DIR LIBDW_LIBRARY)
|
||||||
|
|
||||||
|
# find libbfd
|
||||||
|
find_path(LIBBFD_INCLUDE_DIR NAMES "bfd.h")
|
||||||
|
find_path(LIBDL_INCLUDE_DIR NAMES "dlfcn.h")
|
||||||
|
find_library(LIBBFD_LIBRARY bfd)
|
||||||
|
find_library(LIBDL_LIBRARY dl)
|
||||||
|
set(LIBBFD_INCLUDE_DIRS ${LIBBFD_INCLUDE_DIR} ${LIBDL_INCLUDE_DIR})
|
||||||
|
set(LIBBFD_LIBRARIES ${LIBBFD_LIBRARY} ${LIBDL_LIBRARY})
|
||||||
|
find_package_handle_standard_args(libbfd ${_name_mismatched_arg}
|
||||||
|
REQUIRED_VARS LIBBFD_LIBRARY LIBBFD_INCLUDE_DIR
|
||||||
|
LIBDL_LIBRARY LIBDL_INCLUDE_DIR)
|
||||||
|
mark_as_advanced(LIBBFD_INCLUDE_DIR LIBBFD_LIBRARY
|
||||||
|
LIBDL_INCLUDE_DIR LIBDL_LIBRARY)
|
||||||
|
|
||||||
|
# find libdwarf
|
||||||
|
find_path(LIBDWARF_INCLUDE_DIR NAMES "libdwarf.h" PATH_SUFFIXES libdwarf)
|
||||||
|
find_path(LIBELF_INCLUDE_DIR NAMES "libelf.h")
|
||||||
|
find_path(LIBDL_INCLUDE_DIR NAMES "dlfcn.h")
|
||||||
|
find_library(LIBDWARF_LIBRARY dwarf)
|
||||||
|
find_library(LIBELF_LIBRARY elf)
|
||||||
|
find_library(LIBDL_LIBRARY dl)
|
||||||
|
set(LIBDWARF_INCLUDE_DIRS ${LIBDWARF_INCLUDE_DIR} ${LIBELF_INCLUDE_DIR} ${LIBDL_INCLUDE_DIR})
|
||||||
|
set(LIBDWARF_LIBRARIES ${LIBDWARF_LIBRARY} ${LIBELF_LIBRARY} ${LIBDL_LIBRARY})
|
||||||
|
find_package_handle_standard_args(libdwarf ${_name_mismatched_arg}
|
||||||
|
REQUIRED_VARS LIBDWARF_LIBRARY LIBDWARF_INCLUDE_DIR
|
||||||
|
LIBELF_LIBRARY LIBELF_INCLUDE_DIR
|
||||||
|
LIBDL_LIBRARY LIBDL_INCLUDE_DIR)
|
||||||
|
mark_as_advanced(LIBDWARF_INCLUDE_DIR LIBDWARF_LIBRARY
|
||||||
|
LIBELF_INCLUDE_DIR LIBELF_LIBRARY
|
||||||
|
LIBDL_INCLUDE_DIR LIBDL_LIBRARY)
|
||||||
|
|
||||||
|
if (LIBDW_FOUND)
|
||||||
|
LIST(APPEND _BACKWARD_INCLUDE_DIRS ${LIBDW_INCLUDE_DIRS})
|
||||||
|
LIST(APPEND _BACKWARD_LIBRARIES ${LIBDW_LIBRARIES})
|
||||||
|
set(STACK_DETAILS_DW TRUE)
|
||||||
|
set(STACK_DETAILS_BFD FALSE)
|
||||||
|
set(STACK_DETAILS_DWARF FALSE)
|
||||||
|
set(STACK_DETAILS_BACKTRACE_SYMBOL FALSE)
|
||||||
|
elseif(LIBBFD_FOUND)
|
||||||
|
LIST(APPEND _BACKWARD_INCLUDE_DIRS ${LIBBFD_INCLUDE_DIRS})
|
||||||
|
LIST(APPEND _BACKWARD_LIBRARIES ${LIBBFD_LIBRARIES})
|
||||||
|
|
||||||
|
# If we attempt to link against static bfd, make sure to link its dependencies, too
|
||||||
|
get_filename_component(bfd_lib_ext "${LIBBFD_LIBRARY}" EXT)
|
||||||
|
if (bfd_lib_ext STREQUAL "${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||||
|
list(APPEND _BACKWARD_LIBRARIES iberty z)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(STACK_DETAILS_DW FALSE)
|
||||||
|
set(STACK_DETAILS_BFD TRUE)
|
||||||
|
set(STACK_DETAILS_DWARF FALSE)
|
||||||
|
set(STACK_DETAILS_BACKTRACE_SYMBOL FALSE)
|
||||||
|
elseif(LIBDWARF_FOUND)
|
||||||
|
LIST(APPEND _BACKWARD_INCLUDE_DIRS ${LIBDWARF_INCLUDE_DIRS})
|
||||||
|
LIST(APPEND _BACKWARD_LIBRARIES ${LIBDWARF_LIBRARIES})
|
||||||
|
|
||||||
|
set(STACK_DETAILS_DW FALSE)
|
||||||
|
set(STACK_DETAILS_BFD FALSE)
|
||||||
|
set(STACK_DETAILS_DWARF TRUE)
|
||||||
|
set(STACK_DETAILS_BACKTRACE_SYMBOL FALSE)
|
||||||
|
else()
|
||||||
|
set(STACK_DETAILS_DW FALSE)
|
||||||
|
set(STACK_DETAILS_BFD FALSE)
|
||||||
|
set(STACK_DETAILS_DWARF FALSE)
|
||||||
|
set(STACK_DETAILS_BACKTRACE_SYMBOL TRUE)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if (STACK_DETAILS_DW)
|
||||||
|
LIST(APPEND _BACKWARD_LIBRARIES dw)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (STACK_DETAILS_BFD)
|
||||||
|
LIST(APPEND _BACKWARD_LIBRARIES bfd dl)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (STACK_DETAILS_DWARF)
|
||||||
|
LIST(APPEND _BACKWARD_LIBRARIES dwarf elf)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
macro(map_definitions var_prefix define_prefix)
|
||||||
|
foreach(def ${ARGN})
|
||||||
|
if (${${var_prefix}${def}})
|
||||||
|
LIST(APPEND _BACKWARD_DEFINITIONS "${define_prefix}${def}=1")
|
||||||
|
else()
|
||||||
|
LIST(APPEND _BACKWARD_DEFINITIONS "${define_prefix}${def}=0")
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
if (NOT _BACKWARD_DEFINITIONS)
|
||||||
|
map_definitions("STACK_WALKING_" "BACKWARD_HAS_" UNWIND LIBUNWIND BACKTRACE)
|
||||||
|
map_definitions("STACK_DETAILS_" "BACKWARD_HAS_" BACKTRACE_SYMBOL DW BFD DWARF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
list(APPEND _BACKWARD_LIBRARIES dbghelp psapi)
|
||||||
|
if(MINGW)
|
||||||
|
set(MINGW_MSVCR_LIBRARY "msvcr90$<$<CONFIG:DEBUG>:d>" CACHE STRING "Mingw MSVC runtime import library")
|
||||||
|
list(APPEND _BACKWARD_LIBRARIES ${MINGW_MSVCR_LIBRARY})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(BACKWARD_INCLUDE_DIR "${CMAKE_CURRENT_LIST_DIR}")
|
||||||
|
|
||||||
|
set(BACKWARD_HAS_EXTERNAL_LIBRARIES FALSE)
|
||||||
|
set(FIND_PACKAGE_REQUIRED_VARS BACKWARD_INCLUDE_DIR)
|
||||||
|
if(DEFINED _BACKWARD_LIBRARIES)
|
||||||
|
set(BACKWARD_HAS_EXTERNAL_LIBRARIES TRUE)
|
||||||
|
list(APPEND FIND_PACKAGE_REQUIRED_VARS _BACKWARD_LIBRARIES)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include(FindPackageHandleStandardArgs)
|
||||||
|
find_package_handle_standard_args(Backward
|
||||||
|
REQUIRED_VARS ${FIND_PACKAGE_REQUIRED_VARS}
|
||||||
|
)
|
||||||
|
list(APPEND _BACKWARD_INCLUDE_DIRS ${BACKWARD_INCLUDE_DIR})
|
||||||
|
|
||||||
|
# add_backward, optional bool argument; if passed and true, backward will be included as a system header
|
||||||
|
macro(add_backward target)
|
||||||
|
if ("${ARGN}")
|
||||||
|
target_include_directories(${target} SYSTEM PRIVATE ${BACKWARD_INCLUDE_DIRS})
|
||||||
|
else()
|
||||||
|
target_include_directories(${target} PRIVATE ${BACKWARD_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
set_property(TARGET ${target} APPEND PROPERTY COMPILE_DEFINITIONS ${BACKWARD_DEFINITIONS})
|
||||||
|
set_property(TARGET ${target} APPEND PROPERTY LINK_LIBRARIES ${BACKWARD_LIBRARIES})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
set(BACKWARD_INCLUDE_DIRS ${_BACKWARD_INCLUDE_DIRS} CACHE INTERNAL "_BACKWARD_INCLUDE_DIRS")
|
||||||
|
set(BACKWARD_DEFINITIONS ${_BACKWARD_DEFINITIONS} CACHE INTERNAL "BACKWARD_DEFINITIONS")
|
||||||
|
set(BACKWARD_LIBRARIES ${_BACKWARD_LIBRARIES} CACHE INTERNAL "BACKWARD_LIBRARIES")
|
||||||
|
mark_as_advanced(BACKWARD_INCLUDE_DIRS BACKWARD_DEFINITIONS BACKWARD_LIBRARIES)
|
||||||
|
|
||||||
|
# Expand each definition in BACKWARD_DEFINITIONS to its own cmake var and export
|
||||||
|
# to outer scope
|
||||||
|
foreach(var ${BACKWARD_DEFINITIONS})
|
||||||
|
string(REPLACE "=" ";" var_as_list ${var})
|
||||||
|
list(GET var_as_list 0 var_name)
|
||||||
|
list(GET var_as_list 1 var_value)
|
||||||
|
set(${var_name} ${var_value})
|
||||||
|
mark_as_advanced(${var_name})
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if (NOT TARGET Backward::Backward)
|
||||||
|
add_library(Backward::Backward INTERFACE IMPORTED)
|
||||||
|
set_target_properties(Backward::Backward PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${BACKWARD_INCLUDE_DIRS}"
|
||||||
|
INTERFACE_COMPILE_DEFINITIONS "${BACKWARD_DEFINITIONS}"
|
||||||
|
)
|
||||||
|
if(BACKWARD_HAS_EXTERNAL_LIBRARIES)
|
||||||
|
set_target_properties(Backward::Backward PROPERTIES
|
||||||
|
INTERFACE_LINK_LIBRARIES "${BACKWARD_LIBRARIES}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
endif()
|
139
extern/backward/CMakeLists.txt
vendored
Normal file
139
extern/backward/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,139 @@
|
||||||
|
#
|
||||||
|
# CMakeLists.txt
|
||||||
|
# Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
#
|
||||||
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
# of this software and associated documentation files (the "Software"), to deal
|
||||||
|
# in the Software without restriction, including without limitation the rights
|
||||||
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
# copies of the Software, and to permit persons to whom the Software is
|
||||||
|
# furnished to do so, subject to the following conditions:
|
||||||
|
#
|
||||||
|
# The above copyright notice and this permission notice shall be included in
|
||||||
|
# all copies or substantial portions of the Software.
|
||||||
|
#
|
||||||
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
# SOFTWARE.
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.0)
|
||||||
|
project(backward CXX)
|
||||||
|
|
||||||
|
# Introduce variables:
|
||||||
|
# * CMAKE_INSTALL_LIBDIR
|
||||||
|
# * CMAKE_INSTALL_BINDIR
|
||||||
|
# * CMAKE_INSTALL_INCLUDEDIR
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
include(BackwardConfig.cmake)
|
||||||
|
|
||||||
|
# check if compiler is nvcc or nvcc_wrapper
|
||||||
|
set(COMPILER_IS_NVCC false)
|
||||||
|
get_filename_component(COMPILER_NAME ${CMAKE_CXX_COMPILER} NAME)
|
||||||
|
if (COMPILER_NAME MATCHES "^nvcc")
|
||||||
|
set(COMPILER_IS_NVCC true)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (DEFINED ENV{OMPI_CXX} OR DEFINED ENV{MPICH_CXX})
|
||||||
|
if ( ($ENV{OMPI_CXX} MATCHES "nvcc") OR ($ENV{MPICH_CXX} MATCHES "nvcc") )
|
||||||
|
set(COMPILER_IS_NVCC true)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# set CXX standard
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
if (${COMPILER_IS_NVCC})
|
||||||
|
# GNU CXX extensions are not supported by nvcc
|
||||||
|
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# COMPILER FLAGS
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra")
|
||||||
|
if (NOT ${COMPILER_IS_NVCC})
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pedantic-errors")
|
||||||
|
endif()
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# BACKWARD OBJECT
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
add_library(backward_object OBJECT backward.cpp)
|
||||||
|
target_compile_definitions(backward_object PRIVATE ${BACKWARD_DEFINITIONS})
|
||||||
|
target_include_directories(backward_object PRIVATE ${BACKWARD_INCLUDE_DIRS})
|
||||||
|
set(BACKWARD_ENABLE $<TARGET_OBJECTS:backward_object> CACHE STRING
|
||||||
|
"Link with this object to setup backward automatically")
|
||||||
|
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# BACKWARD LIBRARY (Includes backward.cpp)
|
||||||
|
###############################################################################
|
||||||
|
option(BACKWARD_SHARED "Build dynamic backward-cpp shared lib" OFF)
|
||||||
|
|
||||||
|
if(BACKWARD_SHARED)
|
||||||
|
set(libtype SHARED)
|
||||||
|
endif()
|
||||||
|
add_library(backward ${libtype} backward.cpp)
|
||||||
|
target_compile_definitions(backward PUBLIC ${BACKWARD_DEFINITIONS})
|
||||||
|
target_include_directories(backward PUBLIC ${BACKWARD_INCLUDE_DIRS})
|
||||||
|
|
||||||
|
###############################################################################
|
||||||
|
# TESTS
|
||||||
|
###############################################################################
|
||||||
|
|
||||||
|
if(BACKWARD_TESTS)
|
||||||
|
enable_testing()
|
||||||
|
|
||||||
|
add_library(test_main OBJECT test/_test_main.cpp)
|
||||||
|
|
||||||
|
macro(backward_add_test src)
|
||||||
|
get_filename_component(name ${src} NAME_WE)
|
||||||
|
set(test_name "test_${name}")
|
||||||
|
|
||||||
|
add_executable(${test_name} ${src} ${ARGN} $<TARGET_OBJECTS:test_main>)
|
||||||
|
|
||||||
|
target_link_libraries(${test_name} PRIVATE Backward::Backward)
|
||||||
|
|
||||||
|
add_test(NAME ${name} COMMAND ${test_name})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Tests without backward.cpp
|
||||||
|
set(TESTS
|
||||||
|
test
|
||||||
|
stacktrace
|
||||||
|
rectrace
|
||||||
|
select_signals
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach(test ${TESTS})
|
||||||
|
backward_add_test(test/${test}.cpp)
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
# Tests with backward.cpp
|
||||||
|
set(TESTS
|
||||||
|
suicide
|
||||||
|
)
|
||||||
|
|
||||||
|
foreach(test ${TESTS})
|
||||||
|
backward_add_test(test/${test}.cpp ${BACKWARD_ENABLE})
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(
|
||||||
|
FILES "backward.hpp"
|
||||||
|
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
|
||||||
|
)
|
||||||
|
install(
|
||||||
|
FILES "BackwardConfig.cmake"
|
||||||
|
DESTINATION ${CMAKE_INSTALL_LIBDIR}/backward
|
||||||
|
)
|
21
extern/backward/LICENSE.txt
vendored
Normal file
21
extern/backward/LICENSE.txt
vendored
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
Copyright 2013 Google Inc. All Rights Reserved.
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
442
extern/backward/README.md
vendored
Normal file
442
extern/backward/README.md
vendored
Normal file
|
@ -0,0 +1,442 @@
|
||||||
|
Backward-cpp [![badge](https://img.shields.io/badge/conan.io-backward%2F1.3.0-green.svg?logo=data:image/png;base64%2CiVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAMAAAAolt3jAAAA1VBMVEUAAABhlctjlstkl8tlmMtlmMxlmcxmmcxnmsxpnMxpnM1qnc1sn85voM91oM11oc1xotB2oc56pNF6pNJ2ptJ8ptJ8ptN9ptN8p9N5qNJ9p9N9p9R8qtOBqdSAqtOAqtR%2BrNSCrNJ/rdWDrNWCsNWCsNaJs9eLs9iRvNuVvdyVv9yXwd2Zwt6axN6dxt%2Bfx%2BChyeGiyuGjyuCjyuGly%2BGlzOKmzOGozuKoz%2BKqz%2BOq0OOv1OWw1OWw1eWx1eWy1uay1%2Baz1%2Baz1%2Bez2Oe02Oe12ee22ujUGwH3AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfgBQkREyOxFIh/AAAAiklEQVQI12NgAAMbOwY4sLZ2NtQ1coVKWNvoc/Eq8XDr2wB5Ig62ekza9vaOqpK2TpoMzOxaFtwqZua2Bm4makIM7OzMAjoaCqYuxooSUqJALjs7o4yVpbowvzSUy87KqSwmxQfnsrPISyFzWeWAXCkpMaBVIC4bmCsOdgiUKwh3JojLgAQ4ZCE0AMm2D29tZwe6AAAAAElFTkSuQmCC)](http://www.conan.io/source/backward/1.3.0/Manu343726/testing)
|
||||||
|
============
|
||||||
|
|
||||||
|
Backward is a beautiful stack trace pretty printer for C++.
|
||||||
|
|
||||||
|
If you are bored to see this:
|
||||||
|
|
||||||
|
![default trace](doc/rude.png)
|
||||||
|
|
||||||
|
Backward will spice it up for you:
|
||||||
|
|
||||||
|
![pretty stackstrace](doc/pretty.png)
|
||||||
|
|
||||||
|
There is not much to say. Of course it will be able to display the code
|
||||||
|
snippets only if the source files are accessible (else see trace #4 in the
|
||||||
|
example).
|
||||||
|
|
||||||
|
All "Source" lines and code snippet prefixed by a pipe "|" are frames inline
|
||||||
|
the next frame.
|
||||||
|
You can see that for the trace #1 in the example, the function
|
||||||
|
`you_shall_not_pass()` was inlined in the function `...read2::do_test()` by the
|
||||||
|
compiler.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
#### Install backward.hpp
|
||||||
|
|
||||||
|
Backward is a header only library. So installing Backward is easy, simply drop
|
||||||
|
a copy of `backward.hpp` along with your other source files in your C++ project.
|
||||||
|
You can also use a git submodule or really any other way that best fits your
|
||||||
|
environment, as long as you can include `backward.hpp`.
|
||||||
|
|
||||||
|
#### Install backward.cpp
|
||||||
|
|
||||||
|
If you want Backward to automatically print a stack trace on most common fatal
|
||||||
|
errors (segfault, abort, un-handled exception...), simply add a copy of
|
||||||
|
`backward.cpp` to your project, and don't forget to tell your build system.
|
||||||
|
|
||||||
|
The code in `backward.cpp` is trivial anyway, you can simply copy what it's
|
||||||
|
doing at your convenience.
|
||||||
|
|
||||||
|
Note for [folly](https://github.com/facebook/folly) library users: must define `backward::SignalHandling sh;` after `folly::init(&argc, &argv);`.
|
||||||
|
|
||||||
|
## Configuration & Dependencies
|
||||||
|
|
||||||
|
### Integration with CMake
|
||||||
|
|
||||||
|
If you are using CMake and want to use its configuration abilities to save
|
||||||
|
you the trouble, you can easily integrate Backward, depending on how you obtained
|
||||||
|
the library.
|
||||||
|
|
||||||
|
#### As a subdirectory:
|
||||||
|
|
||||||
|
In this case you have a subdirectory containing the whole repository of Backward
|
||||||
|
(eg.: using git-submodules), in this case you can do:
|
||||||
|
|
||||||
|
```
|
||||||
|
add_subdirectory(/path/to/backward-cpp)
|
||||||
|
|
||||||
|
# This will add backward.cpp to your target
|
||||||
|
add_executable(mytarget mysource.cpp ${BACKWARD_ENABLE})
|
||||||
|
|
||||||
|
# This will add libraries, definitions and include directories needed by backward
|
||||||
|
# by setting each property on the target.
|
||||||
|
add_backward(mytarget)
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Modifying CMAKE_MODULE_PATH
|
||||||
|
|
||||||
|
In this case you can have Backward installed as a subdirectory:
|
||||||
|
|
||||||
|
```
|
||||||
|
list(APPEND CMAKE_MODULE_PATH /path/to/backward-cpp)
|
||||||
|
find_package(Backward)
|
||||||
|
|
||||||
|
# This will add libraries, definitions and include directories needed by backward
|
||||||
|
# through an IMPORTED target.
|
||||||
|
target_link_libraries(mytarget PUBLIC Backward::Backward)
|
||||||
|
```
|
||||||
|
|
||||||
|
Notice that this is equivalent to using the the approach that uses `add_subdirectory()`,
|
||||||
|
however it uses cmake's [imported target](https://cmake.org/Wiki/CMake/Tutorials/Exporting_and_Importing_Targets) mechanism.
|
||||||
|
|
||||||
|
#### Installation through a regular package manager
|
||||||
|
|
||||||
|
In this case you have obtained Backward through a package manager.
|
||||||
|
|
||||||
|
Packages currently available:
|
||||||
|
- [conda-forge](https://anaconda.org/conda-forge/backward-cpp)
|
||||||
|
|
||||||
|
```
|
||||||
|
find_package(Backward)
|
||||||
|
|
||||||
|
# This will add libraries, definitions and include directories needed by backward
|
||||||
|
# through an IMPORTED target.
|
||||||
|
target_link_libraries(mytarget PUBLIC Backward::Backward)
|
||||||
|
```
|
||||||
|
### Libraries to unwind the stack
|
||||||
|
|
||||||
|
On Linux and macOS, backtrace can back-trace or "walk" the stack using the
|
||||||
|
following libraries:
|
||||||
|
|
||||||
|
#### unwind
|
||||||
|
|
||||||
|
Unwind comes from libgcc, but there is an equivalent inside clang itself. With
|
||||||
|
unwind, the stacktrace is as accurate as it can possibly be, since this is
|
||||||
|
used by the C++ runtine in gcc/clang for stack unwinding on exception.
|
||||||
|
|
||||||
|
Normally libgcc is already linked to your program by default.
|
||||||
|
|
||||||
|
#### libunwind from the [libunwind project](https://github.com/libunwind/libunwind)
|
||||||
|
|
||||||
|
apt-get install binutils-dev (or equivalent)
|
||||||
|
|
||||||
|
Libunwind provides, in some cases, a more accurate stacktrace as it knows
|
||||||
|
to decode signal handler frames and lets us edit the context registers when
|
||||||
|
unwinding, allowing stack traces over bad function references.
|
||||||
|
|
||||||
|
For best results make sure you are using libunwind 1.3 or later, which added
|
||||||
|
`unw_init_local2` and support for handling signal frames.
|
||||||
|
|
||||||
|
CMake will warn you when configuring if your libunwind version doesn't support
|
||||||
|
signal frames.
|
||||||
|
|
||||||
|
On macOS clang provides a libunwind API compatible library as part of its
|
||||||
|
environment, so no third party libraries are necessary.
|
||||||
|
|
||||||
|
### Compile with debug info
|
||||||
|
|
||||||
|
You need to compile your project with generation of debug symbols enabled,
|
||||||
|
usually `-g` with clang++ and g++.
|
||||||
|
|
||||||
|
Note that you can use `-g` with any level of optimization, with modern debug
|
||||||
|
information encoding like DWARF, it only takes space in the binary (it's not
|
||||||
|
loaded in memory until your debugger or Backward makes use of it, don't worry),
|
||||||
|
and it doesn't impact the code generation (at least on GNU/Linux x86\_64 for
|
||||||
|
what I know).
|
||||||
|
|
||||||
|
If you are missing debug information, the stack trace will lack details about
|
||||||
|
your sources.
|
||||||
|
|
||||||
|
### Libraries to read the debug info
|
||||||
|
|
||||||
|
Backward supports pretty printed stack traces on GNU/Linux, macOS and Windows,
|
||||||
|
it will compile fine under other platforms but will not do anything. **Pull
|
||||||
|
requests are welcome :)**
|
||||||
|
|
||||||
|
Also, by default you will get a really basic stack trace, based on the
|
||||||
|
`backtrace_symbols` API:
|
||||||
|
|
||||||
|
![default trace](doc/nice.png)
|
||||||
|
|
||||||
|
You will need to install some dependencies to get the ultimate stack trace.
|
||||||
|
Three libraries are currently supported, the only difference is which one is the
|
||||||
|
easiest for you to install, so pick your poison:
|
||||||
|
|
||||||
|
#### libbfd from the [GNU/binutils](http://www.gnu.org/software/binutils/)
|
||||||
|
|
||||||
|
apt-get install binutils-dev (or equivalent)
|
||||||
|
|
||||||
|
And do not forget to link with the lib: `g++/clang++ -lbfd -ldl ...`
|
||||||
|
|
||||||
|
This library requires dynamic loading. Which is provided by the library `dl`.
|
||||||
|
Hence why we also link with `-ldl`.
|
||||||
|
|
||||||
|
Then define the following before every inclusion of `backward.hpp` (don't
|
||||||
|
forget to update `backward.cpp` as well):
|
||||||
|
|
||||||
|
#define BACKWARD_HAS_BFD 1
|
||||||
|
|
||||||
|
#### libdw from the [elfutils](https://fedorahosted.org/elfutils/)
|
||||||
|
|
||||||
|
apt-get install libdw-dev (or equivalent)
|
||||||
|
|
||||||
|
And do not forget to link with the lib and inform Backward to use it:
|
||||||
|
|
||||||
|
#define BACKWARD_HAS_DW 1
|
||||||
|
|
||||||
|
Of course you can simply add the define (`-DBACKWARD_HAS_...=1`) and the
|
||||||
|
linkage details in your build system and even auto-detect which library is
|
||||||
|
installed, it's up to you.
|
||||||
|
|
||||||
|
#### [libdwarf](https://sourceforge.net/projects/libdwarf/) and [libelf](http://www.mr511.de/software/english.html)
|
||||||
|
|
||||||
|
apt-get install libdwarf-dev (or equivalent)
|
||||||
|
|
||||||
|
And do not forget to link with the lib and inform Backward to use it:
|
||||||
|
|
||||||
|
#define BACKWARD_HAS_DWARF 1
|
||||||
|
|
||||||
|
There are several alternative implementations of libdwarf and libelf that
|
||||||
|
are API compatible so it's possible, although it hasn't been tested, to
|
||||||
|
replace the ones used when developing backward (in bold, below):
|
||||||
|
|
||||||
|
* **_libelf_** by [Michael "Tired" Riepe](http://www.mr511.de/software/english.html)
|
||||||
|
* **_libdwarf_** by [David Anderson](https://www.prevanders.net/dwarf.html)
|
||||||
|
* libelf from [elfutils](https://fedorahosted.org/elfutils/)
|
||||||
|
* libelf and libdwarf from FreeBSD's [ELF Tool Chain](https://sourceforge.net/p/elftoolchain/wiki/Home/) project
|
||||||
|
|
||||||
|
|
||||||
|
Of course you can simply add the define (`-DBACKWARD_HAS_...=1`) and the
|
||||||
|
linkage details in your build system and even auto-detect which library is
|
||||||
|
installed, it's up to you.
|
||||||
|
|
||||||
|
That's it, you are all set, you should be getting nice stack traces like the
|
||||||
|
one at the beginning of this document.
|
||||||
|
|
||||||
|
## API
|
||||||
|
|
||||||
|
If you don't want to limit yourself to the defaults offered by `backward.cpp`,
|
||||||
|
and you want to take some random stack traces for whatever reason and pretty
|
||||||
|
print them the way you love or you decide to send them all to your buddies over
|
||||||
|
the Internet, you will appreciate the simplicity of Backward's API.
|
||||||
|
|
||||||
|
### Stacktrace
|
||||||
|
|
||||||
|
The StackTrace class lets you take a "snapshot" of the current stack.
|
||||||
|
You can use it like this:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
using namespace backward;
|
||||||
|
StackTrace st; st.load_here(32);
|
||||||
|
Printer p; p.print(st);
|
||||||
|
```
|
||||||
|
|
||||||
|
The public methods are:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
class StackTrace { public:
|
||||||
|
// Take a snapshot of the current stack, with at most "trace_cnt_max"
|
||||||
|
// traces in it. The first trace is the most recent (ie the current
|
||||||
|
// frame). You can also provide a trace address to load_from() assuming
|
||||||
|
// the address is a valid stack frame (useful for signal handling traces).
|
||||||
|
// Both function return size().
|
||||||
|
size_t load_here(size_t trace_cnt_max)
|
||||||
|
size_t load_from(void* address, size_t trace_cnt_max)
|
||||||
|
|
||||||
|
// The number of traces loaded. This can be less than "trace_cnt_max".
|
||||||
|
size_t size() const
|
||||||
|
|
||||||
|
// A unique id for the thread in which the trace was taken. The value
|
||||||
|
// 0 means the stack trace comes from the main thread.
|
||||||
|
size_t thread_id() const
|
||||||
|
|
||||||
|
// Retrieve a trace by index. 0 is the most recent trace, size()-1 is
|
||||||
|
// the oldest one.
|
||||||
|
Trace operator[](size_t trace_idx)
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### TraceResolver
|
||||||
|
|
||||||
|
The `TraceResolver` does the heavy lifting, and intends to transform a simple
|
||||||
|
`Trace` from its address into a fully detailed `ResolvedTrace` with the
|
||||||
|
filename of the source, line numbers, inlined functions and so on.
|
||||||
|
|
||||||
|
You can use it like this:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
using namespace backward;
|
||||||
|
StackTrace st; st.load_here(32);
|
||||||
|
|
||||||
|
TraceResolver tr; tr.load_stacktrace(st);
|
||||||
|
for (size_t i = 0; i < st.size(); ++i) {
|
||||||
|
ResolvedTrace trace = tr.resolve(st[i]);
|
||||||
|
std::cout << "#" << i
|
||||||
|
<< " " << trace.object_filename
|
||||||
|
<< " " << trace.object_function
|
||||||
|
<< " [" << trace.addr << "]"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
The public methods are:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
class TraceResolver { public:
|
||||||
|
// Pre-load whatever is necessary from the stack trace.
|
||||||
|
template <class ST>
|
||||||
|
void load_stacktrace(ST&)
|
||||||
|
|
||||||
|
// Resolve a trace. It takes a ResolvedTrace, because a `Trace` is
|
||||||
|
// implicitly convertible to it.
|
||||||
|
ResolvedTrace resolve(ResolvedTrace t)
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### SnippetFactory
|
||||||
|
|
||||||
|
The SnippetFactory is a simple helper class to automatically load and cache
|
||||||
|
source files in order to extract code snippets.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
class SnippetFactory { public:
|
||||||
|
// A snippet is a list of line numbers and line contents.
|
||||||
|
typedef std::vector<std::pair<size_t, std::string> > lines_t;
|
||||||
|
|
||||||
|
// Return a snippet starting at line_start with up to context_size lines.
|
||||||
|
lines_t get_snippet(const std::string& filename,
|
||||||
|
size_t line_start, size_t context_size)
|
||||||
|
|
||||||
|
// Return a combined snippet from two different locations and combine them.
|
||||||
|
// context_size / 2 lines will be extracted from each location.
|
||||||
|
lines_t get_combined_snippet(
|
||||||
|
const std::string& filename_a, size_t line_a,
|
||||||
|
const std::string& filename_b, size_t line_b,
|
||||||
|
size_t context_size)
|
||||||
|
|
||||||
|
// Tries to return a unified snippet if the two locations from the same
|
||||||
|
// file are close enough to fit inside one context_size, else returns
|
||||||
|
// the equivalent of get_combined_snippet().
|
||||||
|
lines_t get_coalesced_snippet(const std::string& filename,
|
||||||
|
size_t line_a, size_t line_b, size_t context_size)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Printer
|
||||||
|
|
||||||
|
A simpler way to pretty print a stack trace to the terminal. It will
|
||||||
|
automatically resolve the traces for you:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
using namespace backward;
|
||||||
|
StackTrace st; st.load_here(32);
|
||||||
|
Printer p;
|
||||||
|
p.object = true;
|
||||||
|
p.color_mode = ColorMode::always;
|
||||||
|
p.address = true;
|
||||||
|
p.print(st, stderr);
|
||||||
|
```
|
||||||
|
|
||||||
|
You can set a few options:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
class Printer { public:
|
||||||
|
// Print a little snippet of code if possible.
|
||||||
|
bool snippet = true;
|
||||||
|
|
||||||
|
// Colorize the trace
|
||||||
|
// - ColorMode::automatic: Activate colors if possible. For example, when using a TTY on linux.
|
||||||
|
// - ColorMode::always: Always use colors.
|
||||||
|
// - ColorMode::never: Never use colors.
|
||||||
|
bool color_mode = ColorMode::automatic;
|
||||||
|
|
||||||
|
// Add the addresses of every source location to the trace.
|
||||||
|
bool address = false;
|
||||||
|
|
||||||
|
// Even if there is a source location, also prints the object
|
||||||
|
// from where the trace came from.
|
||||||
|
bool object = false;
|
||||||
|
|
||||||
|
// Resolve and print a stack trace to the given C FILE* object.
|
||||||
|
// On linux, if the FILE* object is attached to a TTY,
|
||||||
|
// color will be used if color_mode is set to automatic.
|
||||||
|
template <typename StackTrace>
|
||||||
|
FILE* print(StackTrace& st, FILE* fp = stderr);
|
||||||
|
|
||||||
|
// Resolve and print a stack trace to the given std::ostream object.
|
||||||
|
// Color will only be used if color_mode is set to always.
|
||||||
|
template <typename ST>
|
||||||
|
std::ostream& print(ST& st, std::ostream& os);
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
### SignalHandling
|
||||||
|
|
||||||
|
A simple helper class that registers for you the most common signals and other
|
||||||
|
callbacks to segfault, hardware exception, un-handled exception etc.
|
||||||
|
|
||||||
|
`backward.cpp` simply uses it like that:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
backward::SignalHandling sh;
|
||||||
|
```
|
||||||
|
|
||||||
|
Creating the object registers all the different signals and hooks. Destroying
|
||||||
|
this object doesn't do anything. It exposes only one method:
|
||||||
|
|
||||||
|
```c++
|
||||||
|
bool loaded() const // true if loaded with success
|
||||||
|
```
|
||||||
|
|
||||||
|
### Trace object
|
||||||
|
|
||||||
|
To keep the memory footprint of a loaded `StackTrace` on the low-side, there a
|
||||||
|
hierarchy of trace object, from a minimal `Trace `to a `ResolvedTrace`.
|
||||||
|
|
||||||
|
#### Simple trace
|
||||||
|
|
||||||
|
```c++
|
||||||
|
struct Trace {
|
||||||
|
void* addr; // address of the trace
|
||||||
|
size_t idx; // its index (0 == most recent)
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Resolved trace
|
||||||
|
|
||||||
|
A `ResolvedTrace` should contains a maximum of details about the location of
|
||||||
|
the trace in the source code. Note that not all fields might be set.
|
||||||
|
|
||||||
|
```c++
|
||||||
|
struct ResolvedTrace: public Trace {
|
||||||
|
|
||||||
|
struct SourceLoc {
|
||||||
|
std::string function;
|
||||||
|
std::string filename;
|
||||||
|
size_t line;
|
||||||
|
size_t col;
|
||||||
|
};
|
||||||
|
|
||||||
|
// In which binary object this trace is located.
|
||||||
|
std::string object_filename;
|
||||||
|
|
||||||
|
// The function in the object that contains the trace. This is not the same
|
||||||
|
// as source.function which can be an function inlined in object_function.
|
||||||
|
std::string object_function;
|
||||||
|
|
||||||
|
// The source location of this trace. It is possible for filename to be
|
||||||
|
// empty and for line/col to be invalid (value 0) if this information
|
||||||
|
// couldn't be deduced, for example if there is no debug information in the
|
||||||
|
// binary object.
|
||||||
|
SourceLoc source;
|
||||||
|
|
||||||
|
// An optional list of "inliners". All of these sources locations where
|
||||||
|
// inlined in the source location of the trace (the attribute right above).
|
||||||
|
// This is especially useful when you compile with optimizations turned on.
|
||||||
|
typedef std::vector<SourceLoc> source_locs_t;
|
||||||
|
source_locs_t inliners;
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contact and copyright
|
||||||
|
|
||||||
|
François-Xavier Bourlet <bombela@gmail.com>
|
||||||
|
|
||||||
|
Copyright 2013-2017 Google Inc. All Rights Reserved.
|
||||||
|
MIT License.
|
||||||
|
|
||||||
|
### Disclaimer
|
||||||
|
|
||||||
|
Although this project is owned by Google Inc. this is not a Google supported or
|
||||||
|
affiliated project.
|
42
extern/backward/backward.cpp
vendored
Normal file
42
extern/backward/backward.cpp
vendored
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
// Pick your poison.
|
||||||
|
//
|
||||||
|
// On GNU/Linux, you have few choices to get the most out of your stack trace.
|
||||||
|
//
|
||||||
|
// By default you get:
|
||||||
|
// - object filename
|
||||||
|
// - function name
|
||||||
|
//
|
||||||
|
// In order to add:
|
||||||
|
// - source filename
|
||||||
|
// - line and column numbers
|
||||||
|
// - source code snippet (assuming the file is accessible)
|
||||||
|
|
||||||
|
// Install one of the following libraries then uncomment one of the macro (or
|
||||||
|
// better, add the detection of the lib and the macro definition in your build
|
||||||
|
// system)
|
||||||
|
|
||||||
|
// - apt-get install libdw-dev ...
|
||||||
|
// - g++/clang++ -ldw ...
|
||||||
|
// #define BACKWARD_HAS_DW 1
|
||||||
|
|
||||||
|
// - apt-get install binutils-dev ...
|
||||||
|
// - g++/clang++ -lbfd ...
|
||||||
|
// #define BACKWARD_HAS_BFD 1
|
||||||
|
|
||||||
|
// - apt-get install libdwarf-dev ...
|
||||||
|
// - g++/clang++ -ldwarf ...
|
||||||
|
// #define BACKWARD_HAS_DWARF 1
|
||||||
|
|
||||||
|
// Regardless of the library you choose to read the debug information,
|
||||||
|
// for potentially more detailed stack traces you can use libunwind
|
||||||
|
// - apt-get install libunwind-dev
|
||||||
|
// - g++/clang++ -lunwind
|
||||||
|
// #define BACKWARD_HAS_LIBUNWIND 1
|
||||||
|
|
||||||
|
#include "backward.hpp"
|
||||||
|
|
||||||
|
namespace backward {
|
||||||
|
|
||||||
|
backward::SignalHandling sh;
|
||||||
|
|
||||||
|
} // namespace backward
|
4476
extern/backward/backward.hpp
vendored
Normal file
4476
extern/backward/backward.hpp
vendored
Normal file
File diff suppressed because it is too large
Load diff
77
extern/backward/builds.sh
vendored
Executable file
77
extern/backward/builds.sh
vendored
Executable file
|
@ -0,0 +1,77 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
COMPILERS_CXX98=`cat<<EOF
|
||||||
|
gcc-4.4
|
||||||
|
gcc-4.6
|
||||||
|
gcc-4.7
|
||||||
|
gcc-4.8
|
||||||
|
clang
|
||||||
|
EOF`
|
||||||
|
|
||||||
|
COMPILERS_CXX11=`cat<<EOF
|
||||||
|
gcc-4.7
|
||||||
|
gcc-4.8
|
||||||
|
clang
|
||||||
|
EOF`
|
||||||
|
|
||||||
|
|
||||||
|
function mkbuild() {
|
||||||
|
local compiler=$1
|
||||||
|
local lang=$2
|
||||||
|
local buildtype=$3
|
||||||
|
local builddir="$4"
|
||||||
|
export CC=$compiler
|
||||||
|
export CXX=`echo $compiler | sed -e 's/clang/clang++/' -e 's/gcc/g++/'`
|
||||||
|
export CXXFLAGS="-std=$lang"
|
||||||
|
echo "Creating $builddir"
|
||||||
|
mkdir $builddir 2>/dev/null
|
||||||
|
(
|
||||||
|
cd "$builddir"
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=$buildtype -DBACKWARD_TESTS=ON ..
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function build() {
|
||||||
|
local builddir=$1
|
||||||
|
shift
|
||||||
|
make -C "$builddir" $@
|
||||||
|
}
|
||||||
|
|
||||||
|
function dotest() {
|
||||||
|
local builddir=$1
|
||||||
|
shift
|
||||||
|
make -C "$builddir" test $@
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
function do_action() {
|
||||||
|
local lang=$1
|
||||||
|
local action=$2
|
||||||
|
shift 2
|
||||||
|
|
||||||
|
for compiler in $COMPILERS; do
|
||||||
|
local builddir="build_${lang}_${compiler}"
|
||||||
|
|
||||||
|
if [[ $action == "cmake" ]]; then
|
||||||
|
buildtype=$1
|
||||||
|
mkbuild $compiler $lang "$buildtype" "$builddir"
|
||||||
|
[[ $? != 0 ]] && exit
|
||||||
|
elif [[ $action == "make" ]]; then
|
||||||
|
build "$builddir" $@
|
||||||
|
[[ $? != 0 ]] && exit
|
||||||
|
elif [[ $action == "test" ]]; then
|
||||||
|
dotest "$builddir" $@
|
||||||
|
[[ $? != 0 ]] && exit
|
||||||
|
elif [[ $action == "clean" ]]; then
|
||||||
|
rm -r "$builddir"
|
||||||
|
else
|
||||||
|
echo "usage: $0 cmake [debug|release|relwithdbg]|make|test|clean"
|
||||||
|
exit 255
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
COMPILERS=$COMPILERS_CXX98
|
||||||
|
do_action c++98 $@
|
||||||
|
COMPILERS=$COMPILERS_CXX11
|
||||||
|
do_action c++11 $@
|
42
src/backtrace.cpp
Normal file
42
src/backtrace.cpp
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
// Pick your poison.
|
||||||
|
//
|
||||||
|
// On GNU/Linux, you have few choices to get the most out of your stack trace.
|
||||||
|
//
|
||||||
|
// By default you get:
|
||||||
|
// - object filename
|
||||||
|
// - function name
|
||||||
|
//
|
||||||
|
// In order to add:
|
||||||
|
// - source filename
|
||||||
|
// - line and column numbers
|
||||||
|
// - source code snippet (assuming the file is accessible)
|
||||||
|
|
||||||
|
// Install one of the following libraries then uncomment one of the macro (or
|
||||||
|
// better, add the detection of the lib and the macro definition in your build
|
||||||
|
// system)
|
||||||
|
|
||||||
|
// - apt-get install libdw-dev ...
|
||||||
|
// - g++/clang++ -ldw ...
|
||||||
|
// #define BACKWARD_HAS_DW 1
|
||||||
|
|
||||||
|
// - apt-get install binutils-dev ...
|
||||||
|
// - g++/clang++ -lbfd ...
|
||||||
|
// #define BACKWARD_HAS_BFD 1
|
||||||
|
|
||||||
|
// - apt-get install libdwarf-dev ...
|
||||||
|
// - g++/clang++ -ldwarf ...
|
||||||
|
// #define BACKWARD_HAS_DWARF 1
|
||||||
|
|
||||||
|
// Regardless of the library you choose to read the debug information,
|
||||||
|
// for potentially more detailed stack traces you can use libunwind
|
||||||
|
// - apt-get install libunwind-dev
|
||||||
|
// - g++/clang++ -lunwind
|
||||||
|
// #define BACKWARD_HAS_LIBUNWIND 1
|
||||||
|
|
||||||
|
#include "../extern/backward/backward.hpp"
|
||||||
|
|
||||||
|
namespace backward {
|
||||||
|
|
||||||
|
backward::SignalHandling sh;
|
||||||
|
|
||||||
|
} // namespace backward
|
Loading…
Reference in a new issue