1Backward-cpp [![badge](https://img.shields.io/badge/conan.io-backward%2F1.3.0-green.svg?logo=data:image/png;base64%2CiVBORw0KGgoAAAANSUhEUgAAAA4AAAAOCAMAAAAolt3jAAAA1VBMVEUAAABhlctjlstkl8tlmMtlmMxlmcxmmcxnmsxpnMxpnM1qnc1sn85voM91oM11oc1xotB2oc56pNF6pNJ2ptJ8ptJ8ptN9ptN8p9N5qNJ9p9N9p9R8qtOBqdSAqtOAqtR%2BrNSCrNJ/rdWDrNWCsNWCsNaJs9eLs9iRvNuVvdyVv9yXwd2Zwt6axN6dxt%2Bfx%2BChyeGiyuGjyuCjyuGly%2BGlzOKmzOGozuKoz%2BKqz%2BOq0OOv1OWw1OWw1eWx1eWy1uay1%2Baz1%2Baz1%2Bez2Oe02Oe12ee22ujUGwH3AAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfgBQkREyOxFIh/AAAAiklEQVQI12NgAAMbOwY4sLZ2NtQ1coVKWNvoc/Eq8XDr2wB5Ig62ekza9vaOqpK2TpoMzOxaFtwqZua2Bm4makIM7OzMAjoaCqYuxooSUqJALjs7o4yVpbowvzSUy87KqSwmxQfnsrPISyFzWeWAXCkpMaBVIC4bmCsOdgiUKwh3JojLgAQ4ZCE0AMm2D29tZwe6AAAAAElFTkSuQmCC)](http://www.conan.io/source/backward/1.3.0/Manu343726/testing) [![Build Status](https://travis-ci.org/bombela/backward-cpp.svg?branch=master)](https://travis-ci.org/bombela/backward-cpp) 2============ 3 4Backward is a beautiful stack trace pretty printer for C++. 5 6If you are bored to see this: 7 8![default trace](doc/rude.png) 9 10Backward will spice it up for you: 11 12![pretty stackstrace](doc/pretty.png) 13 14There is not much to say. Of course it will be able to display the code 15snippets only if the source files are accessible (else see trace #4 in the 16example). 17 18All "Source" lines and code snippet prefixed by a pipe "|" are frames inline 19the next frame. 20You can see that for the trace #1 in the example, the function 21`you_shall_not_pass()` was inlined in the function `...read2::do_test()` by the 22compiler. 23 24## Installation 25 26#### Install backward.hpp 27 28Backward is a header only library. So installing Backward is easy, simply drop 29a copy of `backward.hpp` along with your other source files in your C++ project. 30You can also use a git submodule or really any other way that best fits your 31environment, as long as you can include `backward.hpp`. 32 33#### Install backward.cpp 34 35If you want Backward to automatically print a stack trace on most common fatal 36errors (segfault, abort, un-handled exception...), simply add a copy of 37`backward.cpp` to your project, and don't forget to tell your build system. 38 39The code in `backward.cpp` is trivial anyway, you can simply copy what it's 40doing at your convenience. 41 42## Configuration & Dependencies 43 44### Integration with CMake 45 46If you are using CMake and want to use its configuration abilities to save 47you the trouble, you can easily integrate Backward, depending on how you obtained 48the library. 49 50#### As a subdirectory: 51 52In this case you have a subdirectory containing the whole repository of Backward 53(eg.: using git-submodules), in this case you can do: 54 55``` 56add_subdirectory(/path/to/backward-cpp) 57 58# This will add backward.cpp to your target 59add_executable(mytarget mysource.cpp ${BACKWARD_ENABLE}) 60 61# This will add libraries, definitions and include directories needed by backward 62# by setting each property on the target. 63add_backward(mytarget) 64``` 65 66#### Modifying CMAKE_MODULE_PATH 67 68In this case you can have Backward installed as a subdirectory: 69 70``` 71list(APPEND CMAKE_MODULE_PATH /path/to/backward-cpp) 72find_package(Backward) 73 74# This will add libraries, definitions and include directories needed by backward 75# through an IMPORTED target. 76target_link_libraries(mytarget PUBLIC Backward::Backward) 77``` 78 79Notice that this is equivalent to using the the approach that uses `add_subdirectory()`, 80however it uses cmake's [imported target](https://cmake.org/Wiki/CMake/Tutorials/Exporting_and_Importing_Targets) mechanism. 81 82#### Installation through a regular package manager 83 84In this case you have obtained Backward through a package manager. 85 86Packages currently available: 87- [conda-forge](https://anaconda.org/conda-forge/backward-cpp) 88 89``` 90find_package(Backward) 91 92# This will add libraries, definitions and include directories needed by backward 93# through an IMPORTED target. 94target_link_libraries(mytarget PUBLIC Backward::Backward) 95``` 96 97### Compile with debug info 98 99You need to compile your project with generation of debug symbols enabled, 100usually `-g` with clang++ and g++. 101 102Note that you can use `-g` with any level of optimization, with modern debug 103information encoding like DWARF, it only takes space in the binary (it's not 104loaded in memory until your debugger or Backward makes use of it, don't worry), 105and it doesn't impact the code generation (at least on GNU/Linux x86\_64 for 106what I know). 107 108If you are missing debug information, the stack trace will lack details about 109your sources. 110 111### Libraries to read the debug info 112 113Backward support pretty printed stack traces on GNU/Linux only, it will compile 114fine under other platforms but will not do anything. **Pull requests are 115welcome :)** 116 117Also, by default you will get a really basic stack trace, based on the 118`backtrace_symbols` API: 119 120![default trace](doc/nice.png) 121 122You will need to install some dependencies to get the ultimate stack trace. Two 123libraries are currently supported, the only difference is which one is the 124easiest for you to install, so pick your poison: 125 126#### libbfd from the [GNU/binutils](http://www.gnu.org/software/binutils/) 127 128 apt-get install binutils-dev (or equivalent) 129 130And do not forget to link with the lib: `g++/clang++ -lbfd -ldl ...` 131 132This library requires dynamic loading. Which is provided by the library `dl`. 133Hence why we also link with `-ldl`. 134 135Then define the following before every inclusion of `backward.hpp` (don't 136forget to update `backward.cpp` as well): 137 138 #define BACKWARD_HAS_BFD 1 139 140#### libdw from the [elfutils](https://fedorahosted.org/elfutils/) 141 142 apt-get install libdw-dev (or equivalent) 143 144And do not forget to link with the lib and inform Backward to use it: 145 146 #define BACKWARD_HAS_DW 1 147 148Of course you can simply add the define (`-DBACKWARD_HAS_...=1`) and the 149linkage details in your build system and even auto-detect which library is 150installed, it's up to you. 151 152#### [libdwarf](https://sourceforge.net/projects/libdwarf/) and [libelf](http://www.mr511.de/software/english.html) 153 154 apt-get install libdwarf-dev (or equivalent) 155 156And do not forget to link with the lib and inform Backward to use it: 157 158 #define BACKWARD_HAS_DWARF 1 159 160There are several alternative implementations of libdwarf and libelf that 161are API compatible so it's possible, although it hasn't been tested, to 162replace the ones used when developing backward (in bold, below): 163 164* **_libelf_** by [Michael "Tired" Riepe](http://www.mr511.de/software/english.html) 165* **_libdwarf_** by [David Anderson](https://www.prevanders.net/dwarf.html) 166* libelf from [elfutils](https://fedorahosted.org/elfutils/) 167* libelf and libdwarf from FreeBSD's [ELF Tool Chain](https://sourceforge.net/p/elftoolchain/wiki/Home/) project 168 169 170Of course you can simply add the define (`-DBACKWARD_HAS_...=1`) and the 171linkage details in your build system and even auto-detect which library is 172installed, it's up to you. 173 174That's it, you are all set, you should be getting nice stack traces like the 175one at the beginning of this document. 176 177## API 178 179If you don't want to limit yourself to the defaults offered by `backward.cpp`, 180and you want to take some random stack traces for whatever reason and pretty 181print them the way you love or you decide to send them all to your buddies over 182the Internet, you will appreciate the simplicity of Backward's API. 183 184### Stacktrace 185 186The StackTrace class lets you take a "snapshot" of the current stack. 187You can use it like this: 188 189```c++ 190using namespace backward; 191StackTrace st; st.load_here(32); 192Printer p; p.print(st); 193``` 194 195The public methods are: 196 197```c++ 198class StackTrace { public: 199 // Take a snapshot of the current stack, with at most "trace_cnt_max" 200 // traces in it. The first trace is the most recent (ie the current 201 // frame). You can also provide a trace address to load_from() assuming 202 // the address is a valid stack frame (useful for signal handling traces). 203 // Both function return size(). 204 size_t load_here(size_t trace_cnt_max) 205 size_t load_from(void* address, size_t trace_cnt_max) 206 207 // The number of traces loaded. This can be less than "trace_cnt_max". 208 size_t size() const 209 210 // A unique id for the thread in which the trace was taken. The value 211 // 0 means the stack trace comes from the main thread. 212 size_t thread_id() const 213 214 // Retrieve a trace by index. 0 is the most recent trace, size()-1 is 215 // the oldest one. 216 Trace operator[](size_t trace_idx) 217}; 218``` 219 220### TraceResolver 221 222The `TraceResolver` does the heavy lifting, and intends to transform a simple 223`Trace` from its address into a fully detailed `ResolvedTrace` with the 224filename of the source, line numbers, inlined functions and so on. 225 226You can use it like this: 227 228```c++ 229using namespace backward; 230StackTrace st; st.load_here(32); 231 232TraceResolver tr; tr.load_stacktrace(st); 233for (size_t i = 0; i < st.size(); ++i) { 234 ResolvedTrace trace = tr.resolve(st[i]); 235 std::cout << "#" << i 236 << " " << trace.object_filename 237 << " " << trace.object_function 238 << " [" << trace.addr << "]" 239 << std::endl; 240} 241``` 242 243The public methods are: 244 245```c++ 246class TraceResolver { public: 247 // Pre-load whatever is necessary from the stack trace. 248 template <class ST> 249 void load_stacktrace(ST&) 250 251 // Resolve a trace. It takes a ResolvedTrace, because a `Trace` is 252 // implicitly convertible to it. 253 ResolvedTrace resolve(ResolvedTrace t) 254}; 255``` 256 257### SnippetFactory 258 259The SnippetFactory is a simple helper class to automatically load and cache 260source files in order to extract code snippets. 261 262```c++ 263class SnippetFactory { public: 264 // A snippet is a list of line numbers and line contents. 265 typedef std::vector<std::pair<size_t, std::string> > lines_t; 266 267 // Return a snippet starting at line_start with up to context_size lines. 268 lines_t get_snippet(const std::string& filename, 269 size_t line_start, size_t context_size) 270 271 // Return a combined snippet from two different locations and combine them. 272 // context_size / 2 lines will be extracted from each location. 273 lines_t get_combined_snippet( 274 const std::string& filename_a, size_t line_a, 275 const std::string& filename_b, size_t line_b, 276 size_t context_size) 277 278 // Tries to return a unified snippet if the two locations from the same 279 // file are close enough to fit inside one context_size, else returns 280 // the equivalent of get_combined_snippet(). 281 lines_t get_coalesced_snippet(const std::string& filename, 282 size_t line_a, size_t line_b, size_t context_size) 283``` 284 285### Printer 286 287A simpler way to pretty print a stack trace to the terminal. It will 288automatically resolve the traces for you: 289 290```c++ 291using namespace backward; 292StackTrace st; st.load_here(32); 293Printer p; 294p.object = true; 295p.color_mode = ColorMode::always; 296p.address = true; 297p.print(st, stderr); 298``` 299 300You can set a few options: 301 302```c++ 303class Printer { public: 304 // Print a little snippet of code if possible. 305 bool snippet = true; 306 307 // Colorize the trace 308 // - ColorMode::automatic: Activate colors if possible. For example, when using a TTY on linux. 309 // - ColorMode::always: Always use colors. 310 // - ColorMode::never: Never use colors. 311 bool color_mode = ColorMode::automatic; 312 313 // Add the addresses of every source location to the trace. 314 bool address = false; 315 316 // Even if there is a source location, also prints the object 317 // from where the trace came from. 318 bool object = false; 319 320 // Resolve and print a stack trace to the given C FILE* object. 321 // On linux, if the FILE* object is attached to a TTY, 322 // color will be used if color_mode is set to automatic. 323 template <typename StackTrace> 324 FILE* print(StackTrace& st, FILE* fp = stderr); 325 326 // Resolve and print a stack trace to the given std::ostream object. 327 // Color will only be used if color_mode is set to always. 328 template <typename ST> 329 std::ostream& print(ST& st, std::ostream& os); 330``` 331 332 333### SignalHandling 334 335A simple helper class that registers for you the most common signals and other 336callbacks to segfault, hardware exception, un-handled exception etc. 337 338`backward.cpp` simply uses it like that: 339 340```c++ 341backward::SignalHandling sh; 342``` 343 344Creating the object registers all the different signals and hooks. Destroying 345this object doesn't do anything. It exposes only one method: 346 347```c++ 348bool loaded() const // true if loaded with success 349``` 350 351### Trace object 352 353To keep the memory footprint of a loaded `StackTrace` on the low-side, there a 354hierarchy of trace object, from a minimal `Trace `to a `ResolvedTrace`. 355 356#### Simple trace 357 358```c++ 359struct Trace { 360 void* addr; // address of the trace 361 size_t idx; // its index (0 == most recent) 362}; 363``` 364 365#### Resolved trace 366 367A `ResolvedTrace` should contains a maximum of details about the location of 368the trace in the source code. Note that not all fields might be set. 369 370```c++ 371struct ResolvedTrace: public Trace { 372 373 struct SourceLoc { 374 std::string function; 375 std::string filename; 376 size_t line; 377 size_t col; 378 }; 379 380 // In which binary object this trace is located. 381 std::string object_filename; 382 383 // The function in the object that contains the trace. This is not the same 384 // as source.function which can be an function inlined in object_function. 385 std::string object_function; 386 387 // The source location of this trace. It is possible for filename to be 388 // empty and for line/col to be invalid (value 0) if this information 389 // couldn't be deduced, for example if there is no debug information in the 390 // binary object. 391 SourceLoc source; 392 393 // An optional list of "inliners". All of these sources locations where 394 // inlined in the source location of the trace (the attribute right above). 395 // This is especially useful when you compile with optimizations turned on. 396 typedef std::vector<SourceLoc> source_locs_t; 397 source_locs_t inliners; 398}; 399``` 400 401## Contact and copyright 402 403François-Xavier Bourlet <bombela@gmail.com> 404 405Copyright 2013-2017 Google Inc. All Rights Reserved. 406MIT License. 407 408### Disclaimer 409 410Although this project is owned by Google Inc. this is not a Google supported or 411affiliated project. 412