From 1ae978ab7720a8212b5c552de85b7add13cf52f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois-Xavier=20Bourlet?= Date: Thu, 14 Mar 2013 23:10:06 -0700 Subject: [PATCH] Initial import. --- CMakeLists.txt | 87 ++ LICENSE.txt | 20 + README.md | 331 ++++++ backward.cpp | 32 + backward.hpp | 2169 ++++++++++++++++++++++++++++++++++++++ doc/nice.png | Bin 0 -> 40904 bytes doc/pretty.png | Bin 0 -> 105498 bytes doc/rude.png | Bin 0 -> 6183 bytes test/_test_main.cpp | 46 + test/compile.cpp | 30 + test/divbyzero.cpp | 50 + test/fib.cpp | 61 ++ test/invalidread.cpp | 55 + test/invalidread2.cpp | 53 + test/minitrace.cpp | 45 + test/segfault.cpp | 46 + test/simplerecursive.cpp | 86 ++ test/smalltrace.cpp | 65 ++ test/suicide.cpp | 46 + test/test.hpp | 99 ++ 20 files changed, 3321 insertions(+) create mode 100644 CMakeLists.txt create mode 100644 LICENSE.txt create mode 100644 README.md create mode 100644 backward.cpp create mode 100644 backward.hpp create mode 100644 doc/nice.png create mode 100644 doc/pretty.png create mode 100644 doc/rude.png create mode 100644 test/_test_main.cpp create mode 100644 test/compile.cpp create mode 100644 test/divbyzero.cpp create mode 100644 test/fib.cpp create mode 100644 test/invalidread.cpp create mode 100644 test/invalidread2.cpp create mode 100644 test/minitrace.cpp create mode 100644 test/segfault.cpp create mode 100644 test/simplerecursive.cpp create mode 100644 test/smalltrace.cpp create mode 100644 test/suicide.cpp create mode 100644 test/test.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..7d6c792 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,87 @@ +# +# CMakeLists.txt +# Copyright © 2013 François-Xavier 'Bombela' Bourlet +# +# 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) +project(backward CXX) + +############################################################################### +# COMPILER FLAGS +############################################################################### + +if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_COMPILER_IS_GNUCXX) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra") + #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") +endif() + +include_directories(${CMAKE_SOURCE_DIR}/include) +enable_testing() + +############################################################################### +# TESTS +############################################################################### + +include_directories(${CMAKE_SOURCE_DIR}) + +add_library(test_main SHARED test/_test_main.cpp) + +macro(backward_add_test src src_dep definition) + get_filename_component(name ${src} NAME_WE) + set(test_name "test_${name}") + + add_executable(${test_name} ${src} ${src_dep}) + + set(_definition ${definition}) + if(_definition) + set_target_properties(${test_name} + PROPERTIES COMPILE_DEFINITIONS ${definition}) + endif() + + target_link_libraries(${test_name} dw bfd dl test_main) + add_test(${test_name} ${test_name}) +endmacro() + +set(TESTS + compile + minitrace + smalltrace + simplerecursive + fib + segfault + invalidread + suicide + divbyzero + ) + +foreach(test ${TESTS}) + backward_add_test(test/${test}.cpp "" "") +endforeach() + +set(TESTS + invalidread2 + ) + +set(some_definition "BACKWARD_HAS_BFD=1") +#set(some_definition "BACKWARD_NOTHING") +foreach(test ${TESTS}) + backward_add_test(test/${test}.cpp backward.cpp ${some_definition}) +endforeach() diff --git a/LICENSE.txt b/LICENSE.txt new file mode 100644 index 0000000..a496a5e --- /dev/null +++ b/LICENSE.txt @@ -0,0 +1,20 @@ +The MIT License (MIT) Copyright (c) 2013 François-Xavier Bourlet + + +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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..ffd124d --- /dev/null +++ b/README.md @@ -0,0 +1,331 @@ +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" line and code snippet prefixed by a pipe "|" are source code that +inlines the trace. +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 file in your C++ project. +You can also use a git submodule or really any other way that fit bests your +environment, as long as you can import `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's its +doing at your convenience. + +##Configuration & Dependencies + +### Compile with debug info + +You need to compile your project with the generation of the 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 (its 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 trace 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 easier +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. + +Thats it, you are all set, you should be getting nice stack trace like the one +at the beginning of this document. + +## API + +If you don't want to limit yourself to the default offered by `backward.cpp`, +that you want take random stack trace for whatever reason and pretty print them +the way you prefer or send to your buddies over the internet, you will +appreciate the simplicity of Backward's API. + +### Stacktrace + +The Stacktrace object let 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); +``` + +All 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. Index is the most recent trace, size()-1 + // is the older one. + Trace operator[](size_t trace_idx) +}; +``` + +### TraceResolver + +The `TraceResolver` does the heavy lifting, and intent to transform a simple +`Trace` from it's address onto a fully detailed `ResolvedTrace` with the +filename of the source, line numbers, inliners 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; +} +``` + +All the public methods are: + +```c++ +class TraceResolver { public: + // Pre-load whatever is necessary from the stacktrace. + template + void load_stacktrace(ST&) + + // Resolve a trace. It takes a ResolvedTrace, because a `Trace` or a + // `TraceWithLocals` are implicitly convertible to a ResolvedTrace. + 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 number and content of the line. + typedef std::vector > lines_t; + + // Return a snippet starting at line_start with as much as 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 location and combine them + // together. 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 an unified snippet if the two location 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 select 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 address on the trace to every source location. + 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 stacktrace. It takes a C FILE* object, for the only + // reason that 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 + 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` uses it simply 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) +}; +``` + +#### Trace with local variables + +This is not used for now, but it might be used to carry Traces with snapshotted +variables in the future. + +```c++ +struct TraceWithLocals: public Trace { + std::vector locals; // Locals variable and values. +}; +``` + +#### 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 TraceWithLocals { + + 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 contain 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 optionals list of "inliners". All the successive sources location + // from where the source location of the trace (the attribute right above) + // is inlined. It is especially useful when you compile with optimization. + typedef std::vector source_locs_t; + source_locs_t inliners; +}; +``` + +## Contact and copyright + +François-Xavier Bourlet . +MIT License. diff --git a/backward.cpp b/backward.cpp new file mode 100644 index 0000000..4c68284 --- /dev/null +++ b/backward.cpp @@ -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 diff --git a/backward.hpp b/backward.hpp new file mode 100644 index 0000000..612765f --- /dev/null +++ b/backward.hpp @@ -0,0 +1,2169 @@ +/* + * backward.hpp + * Copyright © 2013 François-Xavier 'Bombela' Bourlet + * + * 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. + */ + +#ifndef H_6B9572DA_A64B_49E6_B234_051480991C89 +#define H_6B9572DA_A64B_49E6_B234_051480991C89 + +#ifndef __cplusplus +# error "It's not going to compile without a C++ compiler..." +#endif + +#if defined(BACKWARD_CXX11) +#elif defined(BACKWARD_CXX98) +#else +# if __cplusplus >= 201103L +# define BACKWARD_CXX11 +# else +# define BACKWARD_CXX98 +# endif +#endif + +// You can define one of the following (or leave it to the auto-detection): +// +// #define BACKWARD_SYSTEM_LINUX +// - specialization for linux +// +// #define BACKWARD_SYSTEM_UNKNOWN +// - placebo implementation, does nothing. +// +#if defined(BACKWARD_SYSTEM_LINUX) +#elif defined(BACKWARD_SYSTEM_UNKNOWN) +#else +# if defined(__linux) +# define BACKWARD_SYSTEM_LINUX +# else +# define BACKWARD_SYSTEM_UNKNOWN +# endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(BACKWARD_SYSTEM_LINUX) + +// On linux, backtrace can back-trace or "walk" the stack using the following +// library: +// +// #define BACKWARD_HAS_UNWIND 1 +// - unwind comes from libgcc, but I saw 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. +// +// #define BACKWARD_HAS_BACKTRACE == 1 +// - backtrace seems to be a little bit more portable than libunwind, but on +// linux, it uses unwind anyway, but abstract away a tiny information that is +// sadly really important in order to get perfectly accurate stack traces. +// - backtrace is part of the (e)glib library. +// +// The default is: +// #define BACKWARD_HAS_UNWIND == 1 +// +# if BACKWARD_HAS_UNWIND == 1 +# elif BACKWARD_HAS_BACKTRACE == 1 +# else +# undef BACKWARD_HAS_UNWIND +# define BACKWARD_HAS_UNWIND 1 +# undef BACKWARD_HAS_BACKTRACE +# define BACKWARD_HAS_BACKTRACE 0 +# endif + +// On linux, backward can extract detailed information about a stack trace +// using one of the following library: +// +// #define BACKWARD_HAS_DW 1 +// - libdw gives you the most juicy details out of your stack traces: +// - object filename +// - function name +// - source filename +// - line and column numbers +// - source code snippet (assuming the file is accessible) +// - variables name and values (if not optimized out) +// - You need to link with the lib "dw": +// - apt-get install libdw-dev +// - g++/clang++ -ldw ... +// +// #define BACKWARD_HAS_BFD 1 +// - With libbfd, you get a fair about of details: +// - object filename +// - function name +// - source filename +// - line numbers +// - source code snippet (assuming the file is accessible) +// - You need to link with the lib "bfd": +// - apt-get install binutils-dev +// - g++/clang++ -lbfd ... +// +// #define BACKWARD_HAS_BACKTRACE_SYMBOL 1 +// - backtrace provides minimal details for a stack trace: +// - object filename +// - function name +// - backtrace is part of the (e)glib library. +// +// The default is: +// #define BACKWARD_HAS_BACKTRACE_SYMBOL == 1 +// +# if BACKWARD_HAS_DW == 1 +# elif BACKWARD_HAS_BFD == 1 +# elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1 +# else +# undef BACKWARD_HAS_DW +# define BACKWARD_HAS_DW 0 +# undef BACKWARD_HAS_BFD +# define BACKWARD_HAS_BFD 0 +# undef BACKWARD_HAS_BACKTRACE_SYMBOL +# define BACKWARD_HAS_BACKTRACE_SYMBOL 1 +# endif + + +# if BACKWARD_HAS_UNWIND == 1 +# include +# endif + +# include +# include +# include +# include +# include +# include +# include + +# if BACKWARD_HAS_BFD == 1 +# include +# ifndef _GNU_SOURCE +# define _GNU_SOURCE +# include +# undef _GNU_SOURCE +# else +# include +# endif +# endif + +# if BACKWARD_HAS_DW == 1 +# include +# include +# include +# endif + +# if (BACKWARD_HAS_BACKTRACE == 1) || (BACKWARD_HAS_BACKTRACE_SYMBOL == 1) + // then we shall rely on backtrace +# include +# endif + +#endif // defined(BACKWARD_SYSTEM_LINUX) + +#if defined(BACKWARD_CXX11) +# include +# include // for std::swap + namespace backward { + namespace details { + template + struct hashtable { + typedef std::unordered_map type; + }; + using std::move; + } // namespace details + } // namespace backward +#elif defined(BACKWARD_CXX98) +# include + namespace backward { + namespace details { + template + struct hashtable { + typedef std::map type; + }; + template + const T& move(const T& v) { return v; } + template + T& move(T& v) { return v; } + } // namespace details + } // namespace backward +#else +# error "Mmm if its not C++11 nor C++98... go play in the toaster." +#endif + +namespace backward { + +namespace system_tag { + struct linux_tag; // seems that I cannot call that "linux" because the name + // is already defined... so I am adding _tag everywhere. + struct unknown_tag; + +#if defined(BACKWARD_SYSTEM_LINUX) + typedef linux_tag current_tag; +#elif defined(BACKWARD_SYSTEM_UNKNOWN) + typedef unknown_tag current_tag; +#else +# error "May I please get my system defines?" +#endif +} // namespace system_tag + + +namespace stacktrace_tag { +#ifdef BACKWARD_SYSTEM_LINUX + struct unwind; + struct backtrace; + +# if BACKWARD_HAS_UNWIND == 1 + typedef unwind currnet; +# elif BACKWARD_HAS_BACKTRACE == 1 + typedef backtrace current; +# else +# error "I know it's difficult but you need to make a choice!" +# endif +#endif // BACKWARD_SYSTEM_LINUX +} // namespace stacktrace_tag + + +namespace trace_resolver_tag { +#ifdef BACKWARD_SYSTEM_LINUX + struct libdw; + struct libbfd; + struct backtrace_symbol; + +# if BACKWARD_HAS_DW == 1 + typedef libdw current; +# elif BACKWARD_HAS_BFD == 1 + typedef libbfd current; +# elif BACKWARD_HAS_BACKTRACE_SYMBOL == 1 + typedef backtrace_symbol current; +# else +# error "You shall not pass, until you know what you want." +# endif +#endif // BACKWARD_SYSTEM_LINUX +} // namespace trace_resolver_tag + +namespace details { + +template + struct rm_ptr { typedef T type; }; + +template + struct rm_ptr { typedef T type; }; + +template + struct rm_ptr { typedef const T type; }; + +template +struct deleter { + template + void operator()(U& ptr) const { + (*F)(ptr); + } +}; + +template +struct default_delete { + void operator()(T& ptr) const { + delete ptr; + } +}; + +template > +class handle { + struct dummy; + T _val; + bool _empty; + +#if defined(BACKWARD_CXX11) + handle(const handle&) = delete; + handle& operator=(const handle&) = delete; +#endif + +public: + ~handle() { + if (not _empty) { + Deleter()(_val); + } + } + + explicit handle(): _val(), _empty(true) {} + explicit handle(T val): _val(val), _empty(false) {} + +#if defined(BACKWARD_CXX11) + handle(handle&& from): _empty(true) { + swap(from); + } + handle& operator=(handle&& from) { + swap(from); return *this; + } +#else + explicit handle(const handle& from): _empty(true) { + // some sort of poor man's move semantic. + swap(const_cast(from)); + } + handle& operator=(const handle& from) { + // some sort of poor man's move semantic. + swap(const_cast(from)); return *this; + } +#endif + + void reset(T new_val) { + handle tmp(new_val); + swap(tmp); + } + operator const dummy*() const { + if (_empty) { + return 0; + } + return reinterpret_cast(_val); + } + T get() { + return _val; + } + T release() { + _empty = true; + return _val; + } + void swap(handle& b) { + using std::swap; + swap(b._val, _val); // can throw, we are safe here. + swap(b._empty, _empty); // should not throw: if you cannot swap two + // bools without throwing... It's a lost cause anyway! + } + + T operator->() { return _val; } + const T operator->() const { return _val; } + + typedef typename rm_ptr::type& ref_t; + ref_t operator*() { return *_val; } + const ref_t operator*() const { return *_val; } + ref_t operator[](size_t idx) { return _val[idx]; } + + // Watch out, we've got a badass over here + T* operator&() { + _empty = false; + return &_val; + } +}; + +} // namespace details + +/*************** A TRACE ***************/ + +struct Trace { + void* addr; + size_t idx; + + Trace(): + addr(0), idx(0) {} + + explicit Trace(void* addr, size_t idx): + addr(addr), idx(idx) {} +}; + +// Really simple, generic, and dumb representation of a variable. +// A variable has a name and can represent either: +// - a value (as a string) +// - a list of values (a list of strings) +// - a map of values (a list of variable) +class Variable { +public: + enum Kind { VALUE, LIST, MAP }; + + typedef std::vector list_t; + typedef std::vector map_t; + + std::string name; + Kind kind; + + Variable(Kind k): kind(k) { + switch (k) { + case VALUE: + new (&storage) std::string(); + break; + + case LIST: + new (&storage) list_t(); + break; + + case MAP: + new (&storage) map_t(); + break; + } + } + + std::string& value() { + return reinterpret_cast(storage); + } + list_t& list() { + return reinterpret_cast(storage); + } + map_t& map() { + return reinterpret_cast(storage); + } + + + const std::string& value() const { + return reinterpret_cast(storage); + } + const list_t& list() const { + return reinterpret_cast(storage); + } + const map_t& map() const { + return reinterpret_cast(storage); + } + +private: + // the C++98 style union for non-trivial objects, yes yes I know, its not + // aligned as good as it can be, blabla... Screw this. + union { + char s1[sizeof (std::string)]; + char s2[sizeof (list_t)]; + char s3[sizeof (map_t)]; + } storage; +}; + +struct TraceWithLocals: public Trace { + // Locals variable and values. + std::vector locals; + + TraceWithLocals(): Trace() {} + TraceWithLocals(const Trace& mini_trace): + Trace(mini_trace) {} +}; + +struct ResolvedTrace: public TraceWithLocals { + + struct SourceLoc { + std::string function; + std::string filename; + size_t line; + size_t col; + + SourceLoc(): line(0), col(0) {} + + bool operator==(const SourceLoc& b) const { + return function == b.function + and filename == b.filename + and line == b.line + and col == b.col; + } + + bool operator!=(const SourceLoc& b) const { + return not (*this == b); + } + }; + + // In which binary object this trace is located. + std::string object_filename; + + // The function in the object that contain 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 optionals list of "inliners". All the successive sources location + // from where the source location of the trace (the attribute right above) + // is inlined. It is especially useful when you compiled with optimization. + typedef std::vector source_locs_t; + source_locs_t inliners; + + ResolvedTrace(const Trace& mini_trace): + TraceWithLocals(mini_trace) {} + ResolvedTrace(const TraceWithLocals& mini_trace_with_locals): + TraceWithLocals(mini_trace_with_locals) {} +}; + +/*************** STACK TRACE ***************/ + +// default implemention. +template +class StackTraceImpl { +public: + size_t size() const { return 0; } + Trace operator[](size_t) { return Trace(); } + size_t load_here(size_t=0) { return 0; } + size_t load_from(void*, size_t=0) { return 0; } + size_t thread_id() const { return 0; } +}; + +#ifdef BACKWARD_SYSTEM_LINUX + +class StackTraceLinuxImplBase { +public: + StackTraceLinuxImplBase(): _thread_id(0), _skip(0) {} + + size_t thread_id() const { + return _thread_id; + } + +protected: + void load_thread_info() { + _thread_id = syscall(SYS_gettid); + if (_thread_id == (size_t) getpid()) { + // If the thread is the main one, let's hide that. + // I like to keep little secret sometimes. + _thread_id = 0; + } + } + + void skip_n_firsts(size_t n) { _skip = n; } + size_t skip_n_firsts() const { return _skip; } + +private: + size_t _thread_id; + size_t _skip; +}; + +class StackTraceLinuxImplHolder: public StackTraceLinuxImplBase { +public: + size_t size() const { + return _stacktrace.size() ? _stacktrace.size() - skip_n_firsts() : 0; + } + Trace operator[](size_t idx) { + if (idx >= size()) { + return Trace(); + } + return Trace(_stacktrace[idx + skip_n_firsts()], idx); + } + void** begin() { + if (size()) { + return &_stacktrace[skip_n_firsts()]; + } + return 0; + } + +protected: + std::vector _stacktrace; +}; + + +#if BACKWARD_HAS_UNWIND == 1 + +namespace details { + +template +class Unwinder { +public: + size_t operator()(F& f, size_t depth) { + _f = &f; + _index = -1; + _depth = depth; + _Unwind_Backtrace(&this->backtrace_trampoline, this); + return _index; + } + +private: + F* _f; + ssize_t _index; + size_t _depth; + + static _Unwind_Reason_Code backtrace_trampoline( + _Unwind_Context* ctx, void *self) { + return ((Unwinder*)self)->backtrace(ctx); + } + + _Unwind_Reason_Code backtrace(_Unwind_Context* ctx) { + if (_index >= 0 and static_cast(_index) >= _depth) + return _URC_END_OF_STACK; + + int ip_before_instruction = 0; + uintptr_t ip = _Unwind_GetIPInfo(ctx, &ip_before_instruction); + + if (not ip_before_instruction) { + ip -= 1; + } + + if (_index >= 0) { // ignore first frame. + (*_f)(_index, (void*)ip); + } + _index += 1; + return _URC_NO_REASON; + } +}; + +template +size_t unwind(F f, size_t depth) { + Unwinder unwinder; + return unwinder(f, depth); +} + +} // namespace details + + +template <> +class StackTraceImpl: public StackTraceLinuxImplHolder { +public: + __attribute__ ((noinline)) // TODO use some macro + size_t load_here(size_t depth=32) { + load_thread_info(); + if (depth == 0) { + return 0; + } + _stacktrace.resize(depth); + size_t trace_cnt = details::unwind(callback(*this), depth); + _stacktrace.resize(trace_cnt); + skip_n_firsts(0); + return size(); + } + size_t load_from(void* addr, size_t depth=32) { + load_here(depth + 8); + + for (size_t i = 0; i < _stacktrace.size(); ++i) { + if (_stacktrace[i] == addr) { + skip_n_firsts(i); + break; + } + } + + _stacktrace.resize(std::min(_stacktrace.size(), + skip_n_firsts() + depth)); + return size(); + } + +private: + struct callback { + StackTraceImpl& self; + callback(StackTraceImpl& self): self(self) {} + + void operator()(size_t idx, void* addr) { + self._stacktrace[idx] = addr; + } + }; +}; + + +#else // BACKWARD_HAS_UNWIND == 0 + +template <> +class StackTraceImpl: public StackTraceLinuxImplHolder { +public: + __attribute__ ((noinline)) // TODO use some macro + size_t load_here(size_t depth=32) { + load_thread_info(); + if (depth == 0) { + return 0; + } + _stacktrace.resize(depth + 1); + size_t trace_cnt = backtrace(&_stacktrace[0], _stacktrace.size()); + _stacktrace.resize(trace_cnt); + skip_n_firsts(1); + return size(); + } + + size_t load_from(void* addr, size_t depth=32) { + load_here(depth + 8); + + for (size_t i = 0; i < _stacktrace.size(); ++i) { + if (_stacktrace[i] == addr) { + skip_n_firsts(i); + _stacktrace[i] = (void*)( (uintptr_t)_stacktrace[i] + 1); + break; + } + } + + _stacktrace.resize(std::min(_stacktrace.size(), + skip_n_firsts() + depth)); + return size(); + } +}; + +#endif // BACKWARD_HAS_UNWIND +#endif // BACKWARD_SYSTEM_LINUX + +class StackTrace: + public StackTraceImpl {}; + +/*********** STACKTRACE WITH LOCALS ***********/ + +// default implemention. +template +class StackTraceWithLocalsImpl: + public StackTrace {}; + +#ifdef BACKWARD_SYSTEM_LINUX +#if BACKWARD_HAS_UNWIND +#if BACKWARD_HAS_DW + +template <> +class StackTraceWithLocalsImpl: + public StackTraceLinuxImplBase { +public: + __attribute__ ((noinline)) // TODO use some macro + size_t load_here(size_t depth=32) { + load_thread_info(); + if (depth == 0) { + return 0; + } + _stacktrace.resize(depth); + size_t trace_cnt = details::unwind(callback(*this), depth); + _stacktrace.resize(trace_cnt); + skip_n_firsts(0); + return size(); + } + size_t load_from(void* addr, size_t depth=32) { + load_here(depth + 8); + + for (size_t i = 0; i < _stacktrace.size(); ++i) { + if (_stacktrace[i].addr == addr) { + skip_n_firsts(i); + break; + } + } + _stacktrace.resize(std::min(_stacktrace.size(), + skip_n_firsts() + depth)); + return size(); + } + size_t size() const { + return _stacktrace.size() ? _stacktrace.size() - skip_n_firsts() : 0; + } + const TraceWithLocals& operator[](size_t idx) { + if (idx >= size()) { + return _nil_trace; + } + return _stacktrace[idx + skip_n_firsts()]; + } + +private: + std::vector _stacktrace; + TraceWithLocals _nil_trace; + + void resolve_trace(TraceWithLocals& trace) { + Variable v(Variable::VALUE); + v.name = "var"; + v.value() = "42"; + trace.locals.push_back(v); + } + + struct callback { + StackTraceWithLocalsImpl& self; + callback(StackTraceWithLocalsImpl& self): self(self) {} + + void operator()(size_t idx, void* addr) { + self._stacktrace[idx].addr = addr; + self.resolve_trace(self._stacktrace[idx]); + } + }; +}; + +#endif // BACKWARD_HAS_DW +#endif // BACKWARD_HAS_UNWIND +#endif // BACKWARD_SYSTEM_LINUX + +class StackTraceWithLocals: + public StackTraceWithLocalsImpl {}; + +/*************** TRACE RESOLVER ***************/ + +template +class TraceResolverImpl; + +#ifdef BACKWARD_SYSTEM_UNKNOWN + +template <> +class TraceResolverImpl { +public: + template + void load_stacktrace(ST&) {} + ResolvedTrace resolve(ResolvedTrace t) { + return t; + } +}; + +#endif + +#ifdef BACKWARD_SYSTEM_LINUX + +class TraceResolverLinuxImplBase { +protected: + std::string demangle(const char* funcname) { + using namespace details; + _demangle_buffer.reset( + abi::__cxa_demangle(funcname, _demangle_buffer.release(), + &_demangle_buffer_length, 0) + ); + if (_demangle_buffer) { + return _demangle_buffer.get(); + } + return funcname; + } + +private: + details::handle _demangle_buffer; + size_t _demangle_buffer_length; +}; + +template +class TraceResolverLinuxImpl; + +#if BACKWARD_HAS_BACKTRACE_SYMBOL == 1 + +template <> +class TraceResolverLinuxImpl: + public TraceResolverLinuxImplBase { +public: + template + void load_stacktrace(ST& st) { + using namespace details; + if (st.size() == 0) { + return; + } + _symbols.reset( + backtrace_symbols(st.begin(), st.size()) + ); + } + + ResolvedTrace resolve(ResolvedTrace trace) { + char* filename = _symbols[trace.idx]; + char* funcname = filename; + while (*funcname && *funcname != '(') { + funcname += 1; + } + trace.object_filename.assign(filename, funcname++); + char* funcname_end = funcname; + while (*funcname_end && *funcname_end != ')' && *funcname_end != '+') { + funcname_end += 1; + } + *funcname_end = '\0'; + trace.object_function = this->demangle(funcname); + trace.source.function = trace.object_function; // we cannot do better. + return trace; + } + +private: + details::handle _symbols; +}; + +#endif // BACKWARD_HAS_BACKTRACE_SYMBOL == 1 + +#if BACKWARD_HAS_BFD == 1 + +template <> +class TraceResolverLinuxImpl: + public TraceResolverLinuxImplBase { +public: + TraceResolverLinuxImpl(): _bfd_loaded(false) {} + + template + void load_stacktrace(ST&) {} + + ResolvedTrace resolve(ResolvedTrace trace) { + Dl_info symbol_info; + + // trace.addr is a virtual address in memory pointing to some code. + // Let's try to find from which loaded object it comes from. + // The loaded object can be yourself btw. + if (not dladdr(trace.addr, &symbol_info)) { + return trace; // dat broken trace... + } + + // Now we get in symbol_info: + // .dli_fname: + // pathname of the shared object that contains the address. + // .dli_fbase: + // where the object is loaded in memory. + // .dli_sname: + // the name of the nearest symbol to trace.addr, we expect a + // function name. + // .dli_saddr: + // the exact address corresponding to .dli_sname. + + if (symbol_info.dli_sname) { + trace.object_function = demangle(symbol_info.dli_sname); + } + + if (not symbol_info.dli_fname) { + return trace; + } + + trace.object_filename = symbol_info.dli_fname; + bfd_fileobject& fobj = load_object_with_bfd(symbol_info.dli_fname); + if (not fobj.handle) { + return trace; // sad, we couldn't load the object :( + } + + + find_sym_result* details_selected; // to be filled. + + // trace.addr is the next instruction to be executed after returning + // from the nested stack frame. In C++ this usually relate to the next + // statement right after the function call that leaded to a new stack + // frame. This is not usually what you want to see when printing out a + // stacktrace... + find_sym_result details_call_site = find_symbol_details(fobj, + trace.addr, symbol_info.dli_fbase); + details_selected = &details_call_site; + +#if BACKWARD_HAS_UNWIND == 0 + // ...this is why we also try to resolve the symbol that is right + // before the return address. If we are lucky enough, we will get the + // line of the function that was called. But if the code is optimized, + // we might get something absolutely not related since the compiler + // can reschedule the return address with inline functions and + // tail-call optimisation (among other things that I don't even know + // or cannot even dream about with my tiny limited brain). + find_sym_result details_adjusted_call_site = find_symbol_details(fobj, + (void*) (uintptr_t(trace.addr) - 1), + symbol_info.dli_fbase); + + // In debug mode, we should always get the right thing(TM). + if (details_call_site.found and details_adjusted_call_site.found) { + // Ok, we assume that details_adjusted_call_site is a better estimation. + details_selected = &details_adjusted_call_site; + trace.addr = (void*) (uintptr_t(trace.addr) - 1); + } + + if (details_selected == &details_call_site and details_call_site.found) { + // we have to re-resolve the symbol in order to reset some + // internal state in BFD... so we can call backtrace_inliners + // thereafter... + details_call_site = find_symbol_details(fobj, trace.addr, + symbol_info.dli_fbase); + } +#endif // BACKWARD_HAS_UNWIND + + if (details_selected->found) { + if (details_selected->filename) { + trace.source.filename = details_selected->filename; + } + trace.source.line = details_selected->line; + + if (details_selected->funcname) { + // this time we get the name of the function where the code is + // located, instead of the function were the address is + // located. In short, if the code was inlined, we get the + // function correspoding to the code. Else we already got in + // trace.function. + trace.source.function = demangle(details_selected->funcname); + + if (not symbol_info.dli_sname) { + // for the case dladdr failed to find the symbol name of + // the function, we might as well try to put something + // here. + trace.object_function = trace.source.function; + } + } + + // Maybe the source of the trace got inlined inside the function + // (trace.source.function). Let's see if we can get all the inlined + // calls along the way up to the initial call site. + trace.inliners = backtrace_inliners(fobj, *details_selected); + +#if 0 + if (trace.inliners.size() == 0) { + // Maybe the trace was not inlined... or maybe it was and we + // are lacking the debug information. Let's try to make the + // world better and see if we can get the line number of the + // function (trace.source.function) now. + // + // We will get the location of where the function start (to be + // exact: the first instruction that really start the + // function), not where the name of the function is defined. + // This can be quite far away from the name of the function + // btw. + // + // If the source of the function is the same as the source of + // the trace, we cannot say if the trace was really inlined or + // not. However, if the filename of the source is different + // between the function and the trace... we can declare it as + // an inliner. This is not 100% accurate, but better than + // nothing. + + if (symbol_info.dli_saddr) { + find_sym_result details = find_symbol_details(fobj, + symbol_info.dli_saddr, + symbol_info.dli_fbase); + + if (details.found) { + ResolvedTrace::SourceLoc diy_inliner; + diy_inliner.line = details.line; + if (details.filename) { + diy_inliner.filename = details.filename; + } + if (details.funcname) { + diy_inliner.function = demangle(details.funcname); + } else { + diy_inliner.function = trace.source.function; + } + if (diy_inliner != trace.source) { + trace.inliners.push_back(diy_inliner); + } + } + } + } +#endif + } + + return trace; + } + +private: + bool _bfd_loaded; + + typedef details::handle + > bfd_handle_t; + + typedef details::handle bfd_symtab_t; + + + struct bfd_fileobject { + bfd_handle_t handle; + bfd_vma base_addr; + bfd_symtab_t symtab; + bfd_symtab_t dynamic_symtab; + }; + + typedef typename details::hashtable::type + fobj_bfd_map_t; + fobj_bfd_map_t _fobj_bfd_map; + + bfd_fileobject& load_object_with_bfd(const std::string& filename_object) { + using namespace details; + + if (not _bfd_loaded) { + using namespace details; + bfd_init(); + _bfd_loaded = true; + } + + typename fobj_bfd_map_t::iterator it = + _fobj_bfd_map.find(filename_object); + if (it != _fobj_bfd_map.end()) { + return it->second; + } + + // this new object is empty for now. + bfd_fileobject& r = _fobj_bfd_map[filename_object]; + + // we do the work temporary in this one; + bfd_handle_t bfd_handle; + + int fd = open(filename_object.c_str(), O_RDONLY); + bfd_handle.reset( + bfd_fdopenr(filename_object.c_str(), "default", fd) + ); + if (not bfd_handle) { + close(fd); + return r; + } + + if (not bfd_check_format(bfd_handle.get(), bfd_object)) { + return r; // not an object? You lose. + } + + if ((bfd_get_file_flags(bfd_handle.get()) & HAS_SYMS) == 0) { + return r; // that's what happen when you forget to compile in debug. + } + + ssize_t symtab_storage_size = + bfd_get_symtab_upper_bound(bfd_handle.get()); + + ssize_t dyn_symtab_storage_size = + bfd_get_dynamic_symtab_upper_bound(bfd_handle.get()); + + if (symtab_storage_size <= 0 and dyn_symtab_storage_size <= 0) { + return r; // weird, is the file is corrupted? + } + + bfd_symtab_t symtab, dynamic_symtab; + ssize_t symcount = 0, dyn_symcount = 0; + + if (symtab_storage_size > 0) { + symtab.reset( + (bfd_symbol**) malloc(symtab_storage_size) + ); + symcount = bfd_canonicalize_symtab( + bfd_handle.get(), symtab.get() + ); + } + + if (dyn_symtab_storage_size > 0) { + dynamic_symtab.reset( + (bfd_symbol**) malloc(dyn_symtab_storage_size) + ); + dyn_symcount = bfd_canonicalize_dynamic_symtab( + bfd_handle.get(), dynamic_symtab.get() + ); + } + + + if (symcount <= 0 and dyn_symcount <= 0) { + return r; // damned, that's a stripped file that you got there! + } + + r.handle = move(bfd_handle); + r.symtab = move(symtab); + r.dynamic_symtab = move(dynamic_symtab); + return r; + } + + struct find_sym_result { + bool found; + const char* filename; + const char* funcname; + unsigned int line; + }; + + struct find_sym_context { + TraceResolverLinuxImpl* self; + bfd_fileobject* fobj; + void* addr; + void* base_addr; + find_sym_result result; + }; + + find_sym_result find_symbol_details(bfd_fileobject& fobj, void* addr, + void* base_addr) { + find_sym_context context; + context.self = this; + context.fobj = &fobj; + context.addr = addr; + context.base_addr = base_addr; + context.result.found = false; + bfd_map_over_sections(fobj.handle.get(), &find_in_section_trampoline, + (void*)&context); + return context.result; + } + + static void find_in_section_trampoline(bfd*, asection* section, + void* data) { + find_sym_context* context = static_cast(data); + context->self->find_in_section( + reinterpret_cast(context->addr), + reinterpret_cast(context->base_addr), + *context->fobj, + section, context->result + ); + } + + void find_in_section(bfd_vma addr, bfd_vma base_addr, + bfd_fileobject& fobj, asection* section, find_sym_result& result) + { + if (result.found) return; + + if ((bfd_get_section_flags(fobj.handle.get(), section) + & SEC_ALLOC) == 0) + return; // a debug section is never loaded automatically. + + bfd_vma sec_addr = bfd_get_section_vma(fobj.handle.get(), section); + bfd_size_type size = bfd_get_section_size(section); + + // are we in the boundaries of the section? + if (addr < sec_addr or addr >= sec_addr + size) { + addr -= base_addr; // oups, a relocated object, lets try again... + if (addr < sec_addr or addr >= sec_addr + size) { + return; + } + } + + if (not result.found and fobj.symtab) { + result.found = bfd_find_nearest_line(fobj.handle.get(), section, + fobj.symtab.get(), addr - sec_addr, &result.filename, + &result.funcname, &result.line); + } + + if (not result.found and fobj.dynamic_symtab) { + result.found = bfd_find_nearest_line(fobj.handle.get(), section, + fobj.dynamic_symtab.get(), addr - sec_addr, + &result.filename, &result.funcname, &result.line); + } + + } + + ResolvedTrace::source_locs_t backtrace_inliners(bfd_fileobject& fobj, + find_sym_result previous_result) { + // This function can be called ONLY after a SUCCESSFUL call to + // find_symbol_details. The state is global to the bfd_handle. + ResolvedTrace::source_locs_t results; + while (previous_result.found) { + find_sym_result result; + result.found = bfd_find_inliner_info(fobj.handle.get(), + &result.filename, &result.funcname, &result.line); + + if (result.found) /* and not ( + cstrings_eq(previous_result.filename, result.filename) + and cstrings_eq(previous_result.funcname, result.funcname) + and result.line == previous_result.line + )) */ { + ResolvedTrace::SourceLoc src_loc; + src_loc.line = result.line; + if (result.filename) { + src_loc.filename = result.filename; + } + if (result.funcname) { + src_loc.function = demangle(result.funcname); + } + results.push_back(src_loc); + } + previous_result = result; + } + return results; + } + + bool cstrings_eq(const char* a, const char* b) { + if (not a or not b) { + return false; + } + return strcmp(a, b) == 0; + } + +}; +#endif // BACKWARD_HAS_BFD == 1 + +#if BACKWARD_HAS_DW == 1 + +template <> +class TraceResolverLinuxImpl: + public TraceResolverLinuxImplBase { +public: + TraceResolverLinuxImpl(): _dwfl_handle_initialized(false) {} + + template + void load_stacktrace(ST&) {} + + ResolvedTrace resolve(ResolvedTrace trace) { + using namespace details; + + Dwarf_Addr trace_addr = (Dwarf_Addr) trace.addr; + + if (not _dwfl_handle_initialized) { + // initialize dwfl... + _dwfl_cb.reset(new Dwfl_Callbacks); + _dwfl_cb->find_elf = &dwfl_linux_proc_find_elf; + _dwfl_cb->find_debuginfo = &dwfl_standard_find_debuginfo; + _dwfl_cb->debuginfo_path = 0; + + _dwfl_handle.reset(dwfl_begin(_dwfl_cb.get())); + _dwfl_handle_initialized = true; + + if (not _dwfl_handle) { + return trace; + } + + // ...from the current process. + dwfl_report_begin(_dwfl_handle.get()); + int r = dwfl_linux_proc_report (_dwfl_handle.get(), getpid()); + dwfl_report_end(_dwfl_handle.get(), NULL, NULL); + if (r < 0) { + return trace; + } + } + + if (not _dwfl_handle) { + return trace; + } + + // find the module (binary object) that contains the trace's address. + // This is not using any debug information, but the addresses ranges of + // all the currently loaded binary object. + Dwfl_Module* mod = dwfl_addrmodule(_dwfl_handle.get(), trace_addr); + if (mod) { + // now that we found it, lets get the name of it, this will be the + // full path to the running binary or one of the loaded library. + const char* module_name = dwfl_module_info (mod, + 0, 0, 0, 0, 0, 0, 0); + if (module_name) { + trace.object_filename = module_name; + } + // We also look after the name of the symbol, equal or before this + // address. This is found by walking the symtab. We should get the + // symbol corresponding to the function (mangled) containing the + // address. If the code corresponding to the address was inlined, + // this is the name of the out-most inliner function. + const char* sym_name = dwfl_module_addrname(mod, trace_addr); + if (sym_name) { + trace.object_function = demangle(sym_name); + } + } + + // now let's get serious, and find out the source location (file and + // line number) of the address. + + // This function will look in .debug_aranges for the address and map it + // to the location of the compilation unit DIE in .debug_info and + // return it. + Dwarf_Addr mod_bias = 0; + Dwarf_Die* cudie = dwfl_module_addrdie(mod, trace_addr, &mod_bias); + +#if 1 + if (not cudie) { + // Sadly clang does not generate the section .debug_aranges, thus + // dwfl_module_addrdie will fail early. Clang doesn't either set + // the lowpc/highpc/range info for every compilation unit. + // + // So in order to save the world: + // for every compilation unit, we will iterate over every single + // DIEs. Normally functions should have a lowpc/highpc/range, which + // we will use to infer the compilation unit. + + // note that this is probably badly inefficient. + while ((cudie = dwfl_module_nextcu(mod, cudie, &mod_bias))) { + Dwarf_Die die_mem; + Dwarf_Die* fundie = find_fundie_by_pc(cudie, + trace_addr - mod_bias, &die_mem); + if (fundie) { + break; + } + } + } +#endif + +//#define BACKWARD_I_DO_NOT_RECOMMEND_TO_ENABLE_THIS_HORRIBLE_PIECE_OF_CODE +#ifdef BACKWARD_I_DO_NOT_RECOMMEND_TO_ENABLE_THIS_HORRIBLE_PIECE_OF_CODE + if (not cudie) { + // If it's still not enough, lets dive deeper in the shit, and try + // to save the world again: for every compilation unit, we will + // load the corresponding .debug_line section, and see if we can + // find our address in it. + + Dwarf_Addr cfi_bias; + Dwarf_CFI* cfi_cache = dwfl_module_eh_cfi(mod, &cfi_bias); + + Dwarf_Addr bias; + while ((cudie = dwfl_module_nextcu(mod, cudie, &bias))) { + if (dwarf_getsrc_die(cudie, trace_addr - bias)) { + + // ...but if we get a match, it might be a false positive + // because our (address - bias) might as well be valid in a + // different compilation unit. So we throw our last card on + // the table and lookup for the address into the .eh_frame + // section. + + handle frame; + dwarf_cfi_addrframe(cfi_cache, trace_addr - cfi_bias, &frame); + if (frame) { + break; + } + } + } + } +#endif + + if (not cudie) { + return trace; // this time we lost the game :/ + } + + // Now that we have a compilation unit DIE, this function will be able + // to load the corresponding section in .debug_line (if not already + // loaded) and hopefully find the source location mapped to our + // address. + Dwarf_Line* srcloc = dwarf_getsrc_die(cudie, trace_addr - mod_bias); + + if (srcloc) { + const char* srcfile = dwarf_linesrc(srcloc, 0, 0); + if (srcfile) { + trace.source.filename = srcfile; + } + int line = 0, col = 0; + dwarf_lineno(srcloc, &line); + dwarf_linecol(srcloc, &col); + trace.source.line = line; + trace.source.col = col; + } + + deep_first_search_by_pc(cudie, trace_addr - mod_bias, + inliners_search_cb(trace)); + if (trace.source.function.size() == 0) { + // fallback. + trace.source.function = trace.object_function; + } + + return trace; + } + +private: + typedef details::handle > + dwfl_handle_t; + details::handle > + _dwfl_cb; + dwfl_handle_t _dwfl_handle; + bool _dwfl_handle_initialized; + + // defined here because in C++98, template function cannot take locally + // defined types... grrr. + struct inliners_search_cb { + void operator()(Dwarf_Die* die) { + switch (dwarf_tag(die)) { + case DW_TAG_subprogram: + trace.source.function = dwarf_diename(die)?:""; + break; + + case DW_TAG_inlined_subroutine: + ResolvedTrace::SourceLoc sloc; + Dwarf_Attribute attr_mem; + + sloc.function = dwarf_diename(die)?:""; + sloc.filename = die_call_file(die)?:""; + + Dwarf_Word line = 0, col = 0; + dwarf_formudata(dwarf_attr(die, DW_AT_call_line, + &attr_mem), &line); + dwarf_formudata(dwarf_attr(die, DW_AT_call_column, + &attr_mem), &col); + sloc.line = line; + sloc.col = col; + + trace.inliners.push_back(sloc); + break; + }; + } + ResolvedTrace& trace; + inliners_search_cb(ResolvedTrace& t): trace(t) {} + }; + + + static bool die_has_pc(Dwarf_Die* die, Dwarf_Addr pc) { + Dwarf_Addr low, high; + + // continuous range + if (dwarf_hasattr(die, DW_AT_low_pc) and + dwarf_hasattr(die, DW_AT_high_pc)) { + if (dwarf_lowpc(die, &low) != 0) { + return false; + } + if (dwarf_highpc(die, &high) != 0) { + Dwarf_Attribute attr_mem; + Dwarf_Attribute* attr = dwarf_attr(die, DW_AT_high_pc, &attr_mem); + Dwarf_Word value; + if (dwarf_formudata(attr, &value) != 0) { + return false; + } + high = low + value; + } + return pc >= low and pc < high; + } + + // non-continuous range. + Dwarf_Addr base; + ptrdiff_t offset = 0; + while ((offset = dwarf_ranges(die, offset, &base, &low, &high)) > 0) { + if (pc >= low and pc < high) { + return true; + } + } + return false; + } + + static Dwarf_Die* find_fundie_by_pc(Dwarf_Die* parent_die, Dwarf_Addr pc, + Dwarf_Die* result) { + if (dwarf_child(parent_die, result) != 0) { + return 0; + } + + Dwarf_Die* die = result; + do { + switch (dwarf_tag(die)) { + case DW_TAG_subprogram: + case DW_TAG_inlined_subroutine: + if (die_has_pc(die, pc)) { + return result; + } + default: + bool declaration = false; + Dwarf_Attribute attr_mem; + dwarf_formflag(dwarf_attr(die, DW_AT_declaration, + &attr_mem), &declaration); + if (not declaration) { + // let's be curious and look deeper in the tree, + // function are not necessarily at the first level, but + // might be nested inside a namespace, structure etc. + Dwarf_Die die_mem; + Dwarf_Die* indie = find_fundie_by_pc(die, pc, &die_mem); + if (indie) { + *result = die_mem; + return result; + } + } + }; + } while (dwarf_siblingof(die, result) == 0); + return 0; + } + + template + static bool deep_first_search_by_pc(Dwarf_Die* parent_die, + Dwarf_Addr pc, CB cb) { + Dwarf_Die die_mem; + if (dwarf_child(parent_die, &die_mem) != 0) { + return false; + } + + bool branch_has_pc = false; + Dwarf_Die* die = &die_mem; + do { + bool declaration = false; + Dwarf_Attribute attr_mem; + dwarf_formflag(dwarf_attr(die, DW_AT_declaration, &attr_mem), &declaration); + if (not declaration) { + // let's be curious and look deeper in the tree, function are + // not necessarily at the first level, but might be nested + // inside a namespace, structure, a function, an inlined + // function etc. + branch_has_pc = deep_first_search_by_pc(die, pc, cb); + } + if (not branch_has_pc) { + branch_has_pc = die_has_pc(die, pc); + } + if (branch_has_pc) { + cb(die); + } + } while (dwarf_siblingof(die, &die_mem) == 0); + return branch_has_pc; + } + + static const char* die_call_file(Dwarf_Die *die) { + Dwarf_Attribute attr_mem; + Dwarf_Sword file_idx = 0; + + dwarf_formsdata(dwarf_attr(die, DW_AT_call_file, &attr_mem), + &file_idx); + + if (file_idx == 0) { + return 0; + } + + Dwarf_Die die_mem; + Dwarf_Die* cudie = dwarf_diecu(die, &die_mem, 0, 0); + if (not cudie) { + return 0; + } + + Dwarf_Files* files = 0; + size_t nfiles; + dwarf_getsrcfiles(cudie, &files, &nfiles); + if (not files) { + return 0; + } + + return dwarf_filesrc(files, file_idx, 0, 0); + } + +}; +#endif // BACKWARD_HAS_DW == 1 + +template<> +class TraceResolverImpl: + public TraceResolverLinuxImpl {}; + +#endif // BACKWARD_SYSTEM_LINUX + +class TraceResolver: + public TraceResolverImpl {}; + +/*************** CODE SNIPPET ***************/ + +class SourceFile { +public: + typedef std::vector > lines_t; + + SourceFile() {} + SourceFile(const std::string& path): _file(new std::ifstream(path.c_str())) {} + bool is_open() const { return _file->is_open(); } + + lines_t& get_lines(size_t line_start, size_t line_count, lines_t& lines) { + using namespace std; + // This function make uses of the dumbest algo ever: + // 1) seek(0) + // 2) read lines one by one and discard until line_start + // 3) read line one by one until line_start + line_count + // + // If you are getting snippets many time from the same file, it is + // somewhat a waste of CPU, feel free to benchmark and propose a + // better solution ;) + + _file->clear(); + _file->seekg(0); + string line; + size_t line_idx; + + for (line_idx = 1; line_idx < line_start; ++line_idx) { + getline(*_file, line); + if (not *_file) { + return lines; + } + } + + // think of it like a lambda in C++98 ;) + // but look, I will reuse it two times! + // What a good boy am I. + struct isspace { + bool operator()(char c) { + return std::isspace(c); + } + }; + + bool started = false; + for (; line_idx < line_start + line_count; ++line_idx) { + getline(*_file, line); + if (not *_file) { + return lines; + } + if (not started) { + if (std::find_if(line.begin(), line.end(), + not_isspace()) == line.end()) + continue; + started = true; + } + lines.push_back(make_pair(line_idx, line)); + } + + lines.erase( + std::find_if(lines.rbegin(), lines.rend(), + not_isempty()).base(), lines.end() + ); + return lines; + } + + lines_t get_lines(size_t line_start, size_t line_count) { + lines_t lines; + return get_lines(line_start, line_count, lines); + } + + // there is no find_if_not in C++98, lets do something crappy to + // workaround. + struct not_isspace { + bool operator()(char c) { + return not std::isspace(c); + } + }; + // and define this one here because C++98 is not happy with local defined + // struct passed to template functions, fuuuu. + struct not_isempty { + bool operator()(const lines_t::value_type& p) { + return not (std::find_if(p.second.begin(), p.second.end(), + not_isspace()) == p.second.end()); + } + }; + + void swap(SourceFile& b) { + _file.swap(b._file); + } + +#if defined(BACKWARD_CXX11) + SourceFile(SourceFile&& from): _file(0) { + swap(from); + } + SourceFile& operator=(SourceFile&& from) { + swap(from); return *this; + } +#else + explicit SourceFile(const SourceFile& from) { + // some sort of poor man's move semantic. + swap(const_cast(from)); + } + SourceFile& operator=(const SourceFile& from) { + // some sort of poor man's move semantic. + swap(const_cast(from)); return *this; + } +#endif + +private: + details::handle + > _file; + +#if defined(BACKWARD_CXX11) + SourceFile(const SourceFile&) = delete; + SourceFile& operator=(const SourceFile&) = delete; +#endif +}; + +class SnippetFactory { +public: + typedef SourceFile::lines_t lines_t; + + lines_t get_snippet(const std::string& filename, + size_t line_start, size_t context_size) { + + SourceFile& src_file = get_src_file(filename); + size_t start = line_start - context_size / 2; + return src_file.get_lines(start, context_size); + } + + 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) { + SourceFile& src_file_a = get_src_file(filename_a); + SourceFile& src_file_b = get_src_file(filename_b); + + lines_t lines = src_file_a.get_lines(line_a - context_size / 4, + context_size / 2); + src_file_b.get_lines(line_b - context_size / 4, context_size / 2, + lines); + return lines; + } + + lines_t get_coalesced_snippet(const std::string& filename, + size_t line_a, size_t line_b, size_t context_size) { + SourceFile& src_file = get_src_file(filename); + + using std::min; using std::max; + size_t a = min(line_a, line_b); + size_t b = max(line_a, line_b); + + if ((b - a) < (context_size / 3)) { + return src_file.get_lines((a + b - context_size + 1) / 2, + context_size); + } + + lines_t lines = src_file.get_lines(a - context_size / 4, + context_size / 2); + src_file.get_lines(b - context_size / 4, context_size / 2, lines); + return lines; + } + + +private: + typedef details::hashtable::type src_files_t; + src_files_t _src_files; + + SourceFile& get_src_file(const std::string& filename) { + src_files_t::iterator it = _src_files.find(filename); + if (it != _src_files.end()) { + return it->second; + } + SourceFile& new_src_file = _src_files[filename]; + new_src_file = SourceFile(filename); + return new_src_file; + } +}; + +/*************** PRINTER ***************/ + +#ifdef BACKWARD_SYSTEM_LINUX + +namespace Color { + enum type { + yellow = 33, + purple = 35, + reset = 39 + }; +} // namespace Color + +class Colorize { +public: + Colorize(std::FILE* os): + _os(os), _reset(false), _istty(false) {} + + void init() { + _istty = isatty(fileno(_os)); + } + + void set_color(Color::type ccode) { + if (not _istty) return; + + // I assume that the terminal can handle basic colors. Seriously I + // don't want to deal with all the termcap shit. + fprintf(_os, "\033[%im", static_cast(ccode)); + _reset = (ccode != Color::reset); + } + + ~Colorize() { + if (_reset) { + set_color(Color::reset); + } + } + +private: + std::FILE* _os; + bool _reset; + bool _istty; +}; + +#else // ndef BACKWARD_SYSTEM_LINUX + + +namespace Color { + enum type { + yellow = 0, + purple = 0, + reset = 0 + }; +} // namespace Color + +class Colorize { +public: + Colorize(std::FILE*) {} + void init(); + void set_color(Color::type) {} +}; + +#endif // BACKWARD_SYSTEM_LINUX + +class Printer { +public: + bool snippet; + bool color; + bool address; + bool object; + + Printer(): + snippet(true), + color(true), + address(false), + object(false) + {} + + template + FILE* print(StackTrace& st, FILE* os = stderr) { + using namespace std; + + Colorize colorize(os); + if (color) { + colorize.init(); + } + + fprintf(os, "Stack trace (most recent call last)"); + if (st.thread_id()) { + fprintf(os, " in thread %zi:\n", st.thread_id()); + } else { + fprintf(os, ":\n"); + } + + _resolver.load_stacktrace(st); + for (size_t trace_idx = st.size(); trace_idx > 0; --trace_idx) { + fprintf(os, "#%-2zi", trace_idx); + bool already_indented = true; + const ResolvedTrace trace = _resolver.resolve(st[trace_idx-1]); + + if (not trace.source.filename.size() or object) { + fprintf(os, " Object \"%s\", at %p, in %s\n", + trace.object_filename.c_str(), trace.addr, + trace.object_function.c_str()); + already_indented = false; + } + + if (trace.source.filename.size()) { + for (size_t inliner_idx = trace.inliners.size(); + inliner_idx > 0; --inliner_idx) { + if (not already_indented) { + fprintf(os, " "); + } + const ResolvedTrace::SourceLoc& inliner_loc + = trace.inliners[inliner_idx-1]; + print_source_loc(os, " | ", inliner_loc); + if (snippet) { + print_snippet(os, " | ", inliner_loc, + colorize, Color::purple, 5); + } + already_indented = false; + } + + if (not already_indented) { + fprintf(os, " "); + } + print_source_loc(os, " ", trace.source, trace.addr); + if (snippet) { + print_snippet(os, " ", trace.source, + colorize, Color::yellow, 7); + } + + if (trace.locals.size()) { + print_locals(os, " ", trace.locals); + } + } + } + return os; + } +private: + TraceResolver _resolver; + SnippetFactory _snippets; + + void print_snippet(FILE* os, const char* indent, + const ResolvedTrace::SourceLoc& source_loc, + Colorize& colorize, Color::type color_code, + int context_size) + { + using namespace std; + typedef SnippetFactory::lines_t lines_t; + + lines_t lines = _snippets.get_snippet(source_loc.filename, + source_loc.line, context_size); + + for (lines_t::const_iterator it = lines.begin(); + it != lines.end(); ++it) { + if (it-> first == source_loc.line) { + colorize.set_color(color_code); + fprintf(os, "%s>", indent); + } else { + fprintf(os, "%s ", indent); + } + fprintf(os, "%4li: %s\n", it->first, it->second.c_str()); + if (it-> first == source_loc.line) { + colorize.set_color(Color::reset); + } + } + } + + void print_source_loc(FILE* os, const char* indent, + const ResolvedTrace::SourceLoc& source_loc, + void* addr=0) { + fprintf(os, "%sSource \"%s\", line %zi, in %s", + indent, source_loc.filename.c_str(), source_loc.line, + source_loc.function.c_str()); + + if (address and addr != 0) { + fprintf(os, " [%p]\n", addr); + } else { + fprintf(os, "\n"); + } + } + + void print_var(FILE* os, const char* base_indent, int indent, + const Variable& var) { + fprintf(os, "%s%s: ", base_indent, var.name.c_str()); + switch (var.kind) { + case Variable::VALUE: + fprintf(os, "%s\n", var.value().c_str()); + break; + case Variable::LIST: + fprintf(os, "["); + for (size_t i = 0; i < var.list().size(); ++i) { + if (i > 0) { + fprintf(os, ", %s", var.list()[i].c_str()); + } + fprintf(os, "%s", var.list()[i].c_str()); + } + fprintf(os, "]\n"); + break; + case Variable::MAP: + fprintf(os, "{\n"); + for (size_t i = 0; i < var.map().size(); ++i) { + if (i > 0) { + fprintf(os, ",\n%s", base_indent); + } + print_var(os, base_indent, indent + 2, var.map()[i]); + } + fprintf(os, "]\n"); + break; + }; + } + + void print_locals(FILE* os, const char* indent, + const std::vector& locals) { + fprintf(os, "%sLocal variables:\n", indent); + for (size_t i = 0; i < locals.size(); ++i) { + if (i > 0) { + fprintf(os, ",\n%s", indent); + } + print_var(os, indent, 0, locals[i]); + } + } +}; + +/*************** SIGNALS HANDLING ***************/ + +#ifdef BACKWARD_SYSTEM_LINUX + +class SignalHandling { +public: + SignalHandling(): _loaded(false) { + // TODO: add a signal dedicated stack, so we can handle stack-overflow. + bool success = true; + const int signals[] = { + // default action: Core + SIGILL, + SIGABRT, + SIGFPE, + SIGSEGV, + SIGBUS, + + // I am not sure the following signals should be enabled by + // default: + + // default action: Term + SIGHUP, + SIGINT, + SIGPIPE, + SIGALRM, + SIGTERM, + SIGUSR1, + SIGUSR2, + SIGPOLL, + SIGPROF, + SIGVTALRM, + SIGIO, + SIGPWR, + + // default action: Core + SIGQUIT, + SIGSYS, + SIGTRAP, + SIGXCPU, + SIGXFSZ + }; + for (const int* sig = signals; + sig != signals + sizeof signals / sizeof *signals; ++sig) { + + struct sigaction action; + action.sa_flags = SA_SIGINFO; + sigemptyset(&action.sa_mask); + action.sa_sigaction = &sig_handler; + + int r = sigaction(*sig, &action, 0); + if (r < 0) success = false; + } + _loaded = success; + } + + bool loaded() const { return _loaded; } + +private: + bool _loaded; + + static void sig_handler(int, siginfo_t* info, void* _ctx) { + ucontext_t *uctx = (ucontext_t*) _ctx; + + StackTrace st; + void* error_addr = 0; +#ifdef REG_RIP // x86_64 + error_addr = reinterpret_cast(uctx->uc_mcontext.gregs[REG_RIP]); +#elif defined(REG_EIP) // x86_32 + error_addr = reinterpret_cast(uctx->uc_mcontext.gregs[REG_EIP]); +#else +# warning ":/ sorry, ain't know no nothing none not of your architecture!" +#endif + if (error_addr) { + st.load_from(error_addr, 32); + } else { + st.load_here(32); + } + + Printer printer; + printer.address = true; + printer.print(st, stderr); + + psiginfo(info, 0); + exit(EXIT_FAILURE); + } +}; + +#endif // BACKWARD_SYSTEM_LINUX + +#ifdef BACKWARD_SYSTEM_UNKNOWN + +class SignalHandling { +public: + SignalHandling() {} + bool init() { return false; } +}; + +#endif // BACKWARD_SYSTEM_UNKNOWN + +#if 0 +void crit_err_hdlr(int sig_num, siginfo_t * info, void * ucontext) +{ + void * array[50]; + void * caller_address; + char ** messages; + int size, i; + sig_ucontext_t * uc; + + uc = (sig_ucontext_t *)ucontext; + + /* Get the address at the time the signal was raised from the EIP (x86) */ + caller_address = (void *) uc->uc_mcontext.eip; + + fprintf(stderr, "signal %d (%s), address is %p from %p\n", + sig_num, strsignal(sig_num), info->si_addr, + (void *)caller_address); + + size = backtrace(array, 50); + + /* overwrite sigaction with caller's address */ + array[1] = caller_address; + + messages = backtrace_symbols(array, size); + + +void sig_handler(int sig, siginfo_t* info, void* _ctx) { +ucontext_t *context = (ucontext_t*) _ctx; + +psiginfo(info, "Shit hit the fan"); +exit(EXIT_FAILURE); +} + +using namespace std; + +void badass() { +cout << "baddass!" << endl; +((char*)&badass)[0] = 42; +} + +int main() { +struct sigaction action; +action.sa_flags = SA_SIGINFO; +sigemptyset(&action.sa_mask); +action.sa_sigaction = &sig_handler; +int r = sigaction(SIGSEGV, &action, 0); +if (r < 0) { err(errno, 0); } +r = sigaction(SIGILL, &action, 0); +if (r < 0) { err(errno, 0); } + +badass(); +return 0; +} + + +#endif + +// i want to get a stacktrace on: +// - abort +// - signals (segfault.. abort...) +// - exception +// - dont messup with gdb! +// - thread ID +// - helper for capturing stack trace inside exception +// propose a little magic wrapper to throw an exception adding a stacktrace, +// and propose a specific tool to get a stacktrace from an exception (if its +// available). +// - optional override __cxa_throw, then the specific magic tool could get +// the stacktrace. Might be possible to use a thread-local variable to do +// some shit. RTLD_DEEPBIND might do the tricks to override it on the fly. + +// maybe I can even get the last variables and theirs values? +// that might be possible. + +// print with code snippet +// print traceback demangled +// detect color stuff +// register all signals +// +// Seperate stacktrace (load and co function) +// than object extracting informations about a stack trace. + +// also public a simple function to print a stacktrace. + +// backtrace::StackTrace st; +// st.snapshot(); +// print(st); +// cout << st; + +} // namespace backward + +#endif /* H_GUARD */ diff --git a/doc/nice.png b/doc/nice.png new file mode 100644 index 0000000000000000000000000000000000000000..42147e5947b7fcfa852a571f47d9c36d9e31fcd5 GIT binary patch literal 40904 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 rm81GE!8#VGu$Pho_;sb6S@6FAF^e|a literal 0 HcmV?d00001 diff --git a/doc/pretty.png b/doc/pretty.png new file mode 100644 index 0000000000000000000000000000000000000000..f95d66ee0be9e821dcc7f97f05443ff5e889ee59 GIT binary patch literal 105498 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
I+M7TnYg*;R1m)mRSLg-afM&- zR!jsCSNb*PUXGej(G=_KUKy(}@jtYfv|6|j!WgW6k=)gJ_(UAI{-v{LZRS9yF~JUg z<>VH=UaRe}@~$|)+gSZ?T6%9Fj0mLQxW(z7Hz70MZ$A^p z?7upb`8>IXye+ddJ0_l95U`naWn^6c+fZvI>0}BDvPX4cimN;DnybsG^B#>!mRCEH z2$ZzX*-tw|Vy`O!cm9C^fGwE*PBNWG=xVuAg^ZAh^YdrsbAiY~u_w)fwpA}dg$vTy zpB`fmWFFmbl>+}*BX!u$|7l@1ly-4A2!vjlv7~5%HkpNODks8+as>v`wp*<_Sp3rY z)``A()&Ck~8cs@Lzf6`m%0t&28779d=c%G)TZ1EOFdqtfq6dafz}XVG1Z`AzU{FQQeBmWLNNGr@bRZx2FH`uWgmRx3?+WUzbmmOy+7{mG0&!>XQY( zSVG(#V?@i016XYv%3g9MH}npoE`N0i*^3dpU-@EYeB(IFfM~**Rd%B+V7jY5v(=+K z`Iug~Uhx%nUDR{?>AhxMsn(ottL!8+0rRy>deW;=w=WIflPq?Q*J9?r4Y4?3n*g8M z2CD6#lBI~6=8AEl{PjATQ30e=tLdY?*>UWz(;_tFj7N4!09mow$cGt!cL|$4qb71n zT=NqE3aZomi(4QRi(2Nzk&!PoQ9)8*4jh*5@KG(p9C|8uTLPH05pSL;Goyv5bxHwv zP`F0~Lo~}H7E`wCs^Xc?WhH9;$T%lNUX3rSrloo)4ZI8!5Zad+_ANdZCoSC>{y=L| zn$=+Fb3u}<(CRG?@_B?^DMr9|i(MbU2ts4hiAp!CcDKUk&Z*=OVg3t|1zRSL$(G{rza>5Xh@jw1gWK5hPieJjs_@{UIaOWfp;JS?y~5>>ouEk{>eu(7zsmN`Mo)_5lv1frVBcmvuCmGi zZ7XUQw|5~kBi~Q~1ghpzngg)`d1R!>R@xgz=o5~r7eNRH8m(0Ms=4H5Ock>S;hTwG z7}c_4!_M8ke;tqia~5u zojiyu-7VS$<|um%+5&;8_%Dc`Ee~Nxe0GW)Z@X5~ZLsEY(N?Y_329bMhAmbLZ>O%< z4|wgZ6~7vu%v&7&&&H>tQP&n;X_P#~u!TDJwm$amPnI(%kFvSqN$aP*x#q)bcTen) zh)O10hF#BQM2ju-fI*c1W!`^9ecD9?O_ghlm)pvFaLO+?3o40lLG8ZJn1z^K;F;?R ziyB!`U(+jTOKs`F^<$C8yPnANbG-BMLMWfH_LbjlQUKYFd$G3}M}rvP){#;@M)jSd^_kX z0?yt!iBMp~-Br$|xstfG!C_n$SuOYhLjJ+bQMykLLq#a6P+R7s%ndw)oA30WAn zdaCttItMZqnot8rIK6N$+hg8JD2;5dtq(v!93K1_4x z3Upk|DXBLaLOl!4VGwEFfwF%vT+%gXXfSI0-wKR1v&7XvTEPQMI*jvfN>1E|aZ-%Z zKfGmk7oa<)F%hm_V*-x6Db?m`R(jv@PVWU0Tk8H^=ijpR&>L_WO!&I)KHG~+Oymy; v(a?zH)V#iTUDE_pl>evVh+X#kdWOrkiKUwOU6pygijSwMs;5$~WE1^A1DQmn literal 0 HcmV?d00001 diff --git a/test/_test_main.cpp b/test/_test_main.cpp new file mode 100644 index 0000000..578176b --- /dev/null +++ b/test/_test_main.cpp @@ -0,0 +1,46 @@ +/* + * _test_main.cpp + * Copyright © 2013 François-Xavier 'Bombela' Bourlet + * + * 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. + */ + +#include "test.hpp" +#include + +test::test_registry_t test::test_registry; +using namespace test; + +int main() +{ + size_t failed_test_cnt = 0; + for (test_registry_t::iterator test = test_registry.begin(); + test != test_registry.end(); ++test) { + printf("-- running test case: %s\n", (*test)->name); + const bool success = (*test)->run(); + if (not success) { + printf("\n-- test case failed: %s\n", (*test)->name); + failed_test_cnt += 1; + } else { + printf("\n-- test case success: %s\n", (*test)->name); + } + } + //printf("-- %zi/%zi test(s) case failed\n", failed_test_cnt, test_registry.size()); + return failed_test_cnt != 0; +} diff --git a/test/compile.cpp b/test/compile.cpp new file mode 100644 index 0000000..d6be65a --- /dev/null +++ b/test/compile.cpp @@ -0,0 +1,30 @@ +/* + * test/compile.cpp + * Copyright © 2013 François-Xavier 'Bombela' Bourlet + * + * 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. + */ + +#include +#include "test/test.hpp" +#include "backward.hpp" + +TEST(i_can_compile) { + printf("Wow, I'am compiled!\n"); +} diff --git a/test/divbyzero.cpp b/test/divbyzero.cpp new file mode 100644 index 0000000..b31e6c6 --- /dev/null +++ b/test/divbyzero.cpp @@ -0,0 +1,50 @@ +/* + * test/divbyzero.cpp + * Copyright © 2013 François-Xavier 'Bombela' Bourlet + * + * 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. + */ + +//#define BACKWARD_SYSTEN_UNKNOWN +//#define BACKWARD_HAS_UNWIND 0 +//#define BACKWARD_CXX98 + +#include "backward.hpp" + +#include +#include "test/test.hpp" + +using namespace backward; + +volatile int zero = 0; + +int divide_by_zero() +{ + std::cout << "And the wild black hole appears..." << std::endl; + int v = 42 / zero; + return v; +} + +TEST (invalid_read) +{ + SignalHandling sh; + std::cout << std::boolalpha << "sh.loaded() == " << sh.loaded() << std::endl; + int v = divide_by_zero(); + std::cout << "v=" << v << std::endl; +} diff --git a/test/fib.cpp b/test/fib.cpp new file mode 100644 index 0000000..9b9f2e5 --- /dev/null +++ b/test/fib.cpp @@ -0,0 +1,61 @@ +/* + * test/fib.cpp + * Copyright © 2013 François-Xavier 'Bombela' Bourlet + * + * 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. + */ + +//#define BACKWARD_SYSTEN_UNKNOWN +//#define BACKWARD_HAS_UNWIND 1 +//#define BACKWARD_CXX98 +#include "backward.hpp" +#include +#include "test/test.hpp" + +using namespace backward; + +int some_counter; + +void end_of_our_journey(StackTrace& st) { + if (not st.size()) { + st.load_here(); + } +} + +int fib(StackTrace& st, int level) { + if (level == 2) { + return 1; + } + if (level <= 1) { + end_of_our_journey(st); + return 0; + } + return fib(st, level - 1) + fib(st, level - 2); +} + +TEST (fibrecursive) { + StackTrace st; + const int input = 6; + int r = fib(st, input); + + std::cout << "fib(" << input << ") == " << r << std::endl; + + Printer printer; + printer.print(st, stdout); +} diff --git a/test/invalidread.cpp b/test/invalidread.cpp new file mode 100644 index 0000000..22654d3 --- /dev/null +++ b/test/invalidread.cpp @@ -0,0 +1,55 @@ +/* + * test/invalidread.cpp + * Copyright © 2013 François-Xavier 'Bombela' Bourlet + * + * 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. + */ + +//#define BACKWARD_SYSTEM_UNKNOWN + +//#define BACKWARD_HAS_UNWIND 1 +//#define BACKWARD_HAS_BACKTRACE 1 + +//#define BACKWARD_HAS_DW 1 +//#define BACKWARD_HAS_BFD 1 +//#define BACKWARD_HAS_BACKTRACE_SYMBOL 1 + +//#define BACKWARD_CXX98 + +#include "backward.hpp" + +#include +#include "test/test.hpp" + +using namespace backward; + +int you_shall_not_pass() +{ + char* ptr = (char*)42; + int v = *ptr; + return v; +} + +TEST (invalid_read) +{ + SignalHandling sh; + std::cout << std::boolalpha << "sh.loaded() == " << sh.loaded() << std::endl; + int v = you_shall_not_pass(); + std::cout << "v=" << v << std::endl; +} diff --git a/test/invalidread2.cpp b/test/invalidread2.cpp new file mode 100644 index 0000000..d74cc6f --- /dev/null +++ b/test/invalidread2.cpp @@ -0,0 +1,53 @@ +/* + * test/invalidread.cpp + * Copyright © 2013 François-Xavier 'Bombela' Bourlet + * + * 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. + */ + +//#define BACKWARD_SYSTEM_UNKNOWN + +//#define BACKWARD_HAS_UNWIND 1 +//#define BACKWARD_HAS_BACKTRACE 1 + +//#define BACKWARD_HAS_DW 1 +//#define BACKWARD_HAS_BFD 1 +//#define BACKWARD_HAS_BACKTRACE_SYMBOL 1 + +//#define BACKWARD_CXX98 + +#include "backward.hpp" + +#include +#include "test/test.hpp" + +using namespace backward; + +int you_shall_not_pass() +{ + char* ptr = (char*)42; + int v = *ptr; + return v; +} + +TEST(invalid_read2) +{ + int v = you_shall_not_pass(); + std::cout << "v=" << v << std::endl; +} diff --git a/test/minitrace.cpp b/test/minitrace.cpp new file mode 100644 index 0000000..6cc8e92 --- /dev/null +++ b/test/minitrace.cpp @@ -0,0 +1,45 @@ +/* + * test/minitrace.cpp + * Copyright © 2013 François-Xavier 'Bombela' Bourlet + * + * 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. + */ + +//#define BACKWARD_SYSTEN_UNKNOWN +//#define BACKWARD_HAS_BFD 0 +//#define BACKWARD_CXX98 + +#include "backward.hpp" + +#include +#include "test/test.hpp" + +using namespace backward; + +void collect_trace(StackTrace& st) { + st.load_here(); +} + +TEST (minitrace) { + StackTrace st; + collect_trace(st); + + Printer printer; + printer.print(st, stdout); +} diff --git a/test/segfault.cpp b/test/segfault.cpp new file mode 100644 index 0000000..88f6e76 --- /dev/null +++ b/test/segfault.cpp @@ -0,0 +1,46 @@ +/* + * test/segfault.cpp + * Copyright © 2013 François-Xavier 'Bombela' Bourlet + * + * 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. + */ + +//#define BACKWARD_SYSTEN_UNKNOWN +//#define BACKWARD_HAS_UNWIND 0 +//#define BACKWARD_CXX98 + +#include "backward.hpp" + +#include +#include "test/test.hpp" + +using namespace backward; + +void badass_function() +{ + char* ptr = (char*)42; + *ptr = 42; +} + +TEST (invalid_write) +{ + SignalHandling sh; + std::cout << std::boolalpha << "sh.loaded() == " << sh.loaded() << std::endl; + badass_function(); +} diff --git a/test/simplerecursive.cpp b/test/simplerecursive.cpp new file mode 100644 index 0000000..782b20d --- /dev/null +++ b/test/simplerecursive.cpp @@ -0,0 +1,86 @@ +/* + * test/simplerecursive.cpp + * Copyright © 2013 François-Xavier 'Bombela' Bourlet + * + * 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. + */ + +//#define BACKWARD_HAS_UNWIND 1 +//#define BACKWARD_SYSTEN_UNKNOWN +#define BACKWARD_HAS_DW 1 +//#define BACKWARD_HAS_BFD 1 +//#define BACKWARD_HAS_BACKTRACE_SYMBOL 1 +//#define BACKWARD_HAS_BACKTRACE 1 +//#define BACKWARD_CXX98 +#include "backward.hpp" +#include +#include "test/test.hpp" + +using namespace backward; + +int some_counter; + +typedef StackTraceWithLocals stacktrace_t; + +void end_of_our_journey(stacktrace_t& st) { + if (not st.size()) { + st.load_here(); + } +} + +int rec(stacktrace_t& st, int level) { + if (level <= 1) { + end_of_our_journey(st); + return 0; + } + return rec(st, level - 1); +} + +namespace toto { + +namespace titi { + + struct foo { + + union bar { + __attribute__((noinline)) + static int trampoline(stacktrace_t& st, int level) { + return rec(st, level); + } + }; + }; + +} // namespace titi + +} // namespace toto + +TEST (simplerecursive) { + { // lexical scope. + stacktrace_t st; + const int input = 3; + int r = toto::titi::foo::bar::trampoline(st, input); + + std::cout << "rec(" << input << ") == " << r << std::endl; + + Printer printer; + // printer.address = true; + printer.object = true; + printer.print(st, stdout); + } +} diff --git a/test/smalltrace.cpp b/test/smalltrace.cpp new file mode 100644 index 0000000..ccf5122 --- /dev/null +++ b/test/smalltrace.cpp @@ -0,0 +1,65 @@ +/* + * test/smalltrace.cpp + * Copyright © 2013 François-Xavier 'Bombela' Bourlet + * + * 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. + */ + +//#define BACKWARD_SYSTEN_UNKNOWN +//#define BACKWARD_HAS_UNWIND 0 +//#define BACKWARD_HAS_DW 1 +#define BACKWARD_HAS_BFD 1 +//#define BACKWARD_CXX98 + +#include "backward.hpp" + +#include +#include "test/test.hpp" + +using namespace backward; + +void d(StackTrace& st) +{ + st.load_here(); +} + +void c(StackTrace& st) +{ + return d(st); +} + +void b(StackTrace& st) +{ + return c(st); +} + +__attribute__ ((noinline)) +void a(StackTrace& st) +{ + return b(st); +} + +TEST (smalltrace) +{ + StackTrace st; + a(st); + + Printer printer; + printer.print(st, stdout); +} diff --git a/test/suicide.cpp b/test/suicide.cpp new file mode 100644 index 0000000..4bddf10 --- /dev/null +++ b/test/suicide.cpp @@ -0,0 +1,46 @@ +/* + * test/suicide.cpp + * Copyright © 2013 François-Xavier 'Bombela' Bourlet + * + * 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. + */ + +//#define BACKWARD_SYSTEN_UNKNOWN +//#define BACKWARD_HAS_UNWIND 0 +//#define BACKWARD_CXX98 + +#include "backward.hpp" + +#include +#include "test/test.hpp" + +using namespace backward; + +void abort_abort_I_repeat_abort_abort() +{ + std::cout << "Jumping off the boat!" << std::endl; + abort(); +} + +TEST (invalid_read) +{ + SignalHandling sh; + std::cout << std::boolalpha << "sh.loaded() == " << sh.loaded() << std::endl; + abort_abort_I_repeat_abort_abort(); +} diff --git a/test/test.hpp b/test/test.hpp new file mode 100644 index 0000000..998a0f0 --- /dev/null +++ b/test/test.hpp @@ -0,0 +1,99 @@ +/* + * test/test.hpp + * Copyright © 2013 François-Xavier 'Bombela' Bourlet + * + * 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. + */ + +#pragma once +#ifndef H_54E531F7_9154_454B_BEB9_257408429470 +#define H_54E531F7_9154_454B_BEB9_257408429470 + +#include +#include +#include +#include + +namespace test { + +struct AssertFailedError {}; + +void assert_fail ( + const char* filename, + int line, + const char* err_msg) { + + const char* basename = filename + strlen(filename); + while (basename != filename && *basename != '/') { + basename -= 1; + } + basename += 1; + + printf("!! assertion failed:\n\tat: %s:%i\n\t%s\n", + basename, line, err_msg); + throw AssertFailedError(); +} + +struct TestBase { + const char* name; + virtual ~TestBase() {} + TestBase(const char*); + virtual void do_test() = 0; + + bool run() { + try { + do_test(); + return true; + } catch(const AssertFailedError&) { + } catch(const std::exception& e) { + printf("/!\\ Exception: %s\n", e.what()); + } catch(...) { + printf("/!\\ Unknown exception\n"); + } + return false; + } +}; + +typedef std::vector test_registry_t; +extern test_registry_t test_registry; + +TestBase::TestBase(const char* n): name(n) { + test_registry.push_back(this); +} + +} // namespace test + +#define ASSERT(expr) \ + (expr) ? static_cast(0) \ + : ::test::assert_fail( \ + __FILE__, __LINE__, "assertion: " #expr) + +#define ASSERT_EQ(a, b) \ + (a == b) ? static_cast(0) \ + : ::test::assert_fail( \ + __FILE__, __LINE__, "err: " #a " != " #b) + +#define TEST(name) \ + struct TEST_##name: ::test::TestBase { \ + TEST_##name(): TestBase(#name) {} \ + void do_test(); \ + } TEST_##name; \ + void TEST_##name::do_test() + +#endif /* H_GUARD */