Use backward-cpp on Linux for nicer stack traces

alut-include-path
Lukas Werling 2017-03-21 18:34:50 +01:00
parent 22161ae561
commit 19b00b7862
9 changed files with 2698 additions and 2 deletions

View File

@ -293,6 +293,12 @@ endif()
if(UNIX AND NOT APPLE)
FINDLIB(X11_LIBRARIES X11)
set(Backward_DIR thirdparty/backward-cpp)
find_package(Backward)
if(Backward_FOUND)
set(HAVE_BACKWARD 1)
endif()
endif()
if (WIN32)
@ -1172,6 +1178,10 @@ if(NOT HEADLESS_ONLY)
set_target_properties(openclonk PROPERTIES COMPILE_DEFINITIONS WITH_QT_EDITOR)
qt5_use_modules(openclonk Widgets)
endif()
if(HAVE_BACKWARD)
add_backward(openclonk)
endif()
endif()
add_executable(openclonk-server
@ -1203,6 +1213,9 @@ endif()
if(USE_COCOA)
target_link_libraries(openclonk-server "-framework Cocoa")
endif()
if(HAVE_BACKWARD)
add_backward(openclonk-server)
endif()
if(GTK3_FOUND AND GTK3_gtksourceview_FOUND AND NOT HEADLESS_ONLY)
add_executable(mape ${MAPE_BASE_SOURCES} ${MAPE_SOURCES})

View File

@ -2,6 +2,9 @@
/* Generate minidumps on crash */
#cmakedefine HAVE_DBGHELP 1
/* Use backward-cpp to print stack traces on crash */
#cmakedefine HAVE_BACKWARD 1
/* Define to 1 if you have the <direct.h> header file. */
#cmakedefine HAVE_DIRECT_H 1

View File

@ -119,8 +119,12 @@ int main()
#include <sys/types.h>
#endif
#ifdef HAVE_SIGNAL_H
#ifdef HAVE_BACKWARD
#include <backward-cpp/backward.hpp>
#elif defined(HAVE_SIGNAL_H)
#include <signal.h>
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif
@ -209,7 +213,9 @@ int main (int argc, char * argv[])
printf("Do not run %s as root!\n", argc ? argv[0] : "this program");
return C4XRV_Failure;
}
#ifdef HAVE_SIGNAL_H
#ifdef HAVE_BACKWARD
backward::SignalHandling sh;
#elif defined(HAVE_SIGNAL_H)
struct sigaction sa;
sa.sa_sigaction = crash_handler;
sigemptyset(&sa.sa_mask);

View File

@ -0,0 +1,145 @@
#
# 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_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(BACKWARD_TESTS FALSE CACHE BOOL "Enable tests")
###############################################################################
# CONFIGS
###############################################################################
if (${STACK_DETAILS_AUTO_DETECT})
include(FindPackageHandleStandardArgs)
# find libdw
find_path(LIBDW_INCLUDE_DIR NAMES "elfutils/libdw.h" "elfutils/libdwfl.h")
find_library(LIBDW_LIBRARY dw)
set(LIBDW_INCLUDE_DIRS ${LIBDW_INCLUDE_DIR} )
set(LIBDW_LIBRARIES ${LIBDW_LIBRARY} )
find_package_handle_standard_args(libdw DEFAULT_MSG
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 DEFAULT_MSG
LIBBFD_LIBRARY LIBBFD_INCLUDE_DIR
LIBDL_LIBRARY LIBDL_INCLUDE_DIR)
mark_as_advanced(LIBBFD_INCLUDE_DIR LIBBFD_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_BACKTRACE_SYMBOL FALSE)
elseif(LIBBFD_FOUND)
LIST(APPEND _BACKWARD_INCLUDE_DIRS ${LIBBFD_INCLUDE_DIRS})
LIST(APPEND BACKWARD_LIBRARIES ${LIBBFD_LIBRARIES})
set(STACK_DETAILS_DW FALSE)
set(STACK_DETAILS_BFD TRUE)
set(STACK_DETAILS_BACKTRACE_SYMBOL FALSE)
else()
set(STACK_DETAILS_DW FALSE)
set(STACK_DETAILS_BFD 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()
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 BACKTRACE)
map_definitions("STACK_DETAILS_" "BACKWARD_HAS_" BACKTRACE_SYMBOL DW BFD)
endif()
foreach(def ${BACKWARD_DEFINITIONS})
message(STATUS "${def}")
endforeach()
find_path(BACKWARD_INCLUDE_DIR backward.hpp PATHS ${CMAKE_CURRENT_LIST_DIR})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Backward
REQUIRED_VARS
BACKWARD_INCLUDE_DIR
BACKWARD_LIBRARIES
)
list(APPEND _BACKWARD_INCLUDE_DIRS ${BACKWARD_INCLUDE_DIR})
macro(add_backward target)
target_include_directories(${target} PRIVATE ${_BACKWARD_INCLUDE_DIRS})
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)
if (NOT TARGET Backward::Backward)
add_library(Backward::Backward INTERFACE IMPORTED)
set_target_properties(Backward::Backward PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES "${_BACKWARD_INCLUDE_DIRS}"
INTERFACE_LINK_LIBRARIES "${BACKWARD_LIBRARIES}"
INTERFACE_COMPILE_DEFINITIONS "${BACKWARD_DEFINITIONS}"
)
endif()

View File

@ -0,0 +1,112 @@
#
# 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 2.8.12)
project(backward CXX)
include(BackwardConfig.cmake)
set(CMAKE_CXX_STANDARD_REQUIRED True)
set(CMAKE_CXX_STANDARD 11)
###############################################################################
# COMPILER FLAGS
###############################################################################
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -pedantic-errors")
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 SHARED 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_link_libraries(${test_name} PRIVATE Backward::Backward test_main)
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_PREFIX}/include
)
install(
FILES "BackwardConfig.cmake"
DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/backward
)

View 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.

378
thirdparty/backward-cpp/README.md vendored 100644
View File

@ -0,0 +1,378 @@
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) [![Build Status](https://travis-ci.org/bombela/backward-cpp.svg?branch=master)](https://travis-ci.org/cwbombela/backward-cpp)
============
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.
##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)
```
### 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 support pretty printed stack traces on GNU/Linux only, 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. Two
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 ...`
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.
That'ss 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 = false;
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 (only set a color when printing on a terminal)
bool color = true;
// Add the addresses of every source location to the trace.
bool address = false;
// Even if there is a source location, prints the object the trace comes
// from as well.
bool object = false;
// Resolve and print a stack trace. It takes a C FILE* object, only because
// it is possible to access the underalying OS-level file descriptor, which
// is then used to determine if the output is a terminal to print in color.
template <typename StackTrace>
FILE* print(StackTrace& st, FILE* os = stderr)
```
### 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 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.

View File

@ -0,0 +1,32 @@
// 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 library 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
#include "backward.hpp"
namespace backward {
backward::SignalHandling sh;
} // namespace backward

File diff suppressed because it is too large Load Diff