443 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
		
		
			
		
	
	
			443 lines
		
	
	
		
			15 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| 
								 | 
							
								Backward-cpp [](http://www.conan.io/source/backward/1.3.0/Manu343726/testing)
							 | 
						||
| 
								 | 
							
								============
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Backward is a beautiful stack trace pretty printer for C++.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If you are bored to see this:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Backward will spice it up for you:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								There is not much to say. Of course it will be able to display the code
							 | 
						||
| 
								 | 
							
								snippets only if the source files are accessible (else see trace #4 in the
							 | 
						||
| 
								 | 
							
								example).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								All "Source" lines and code snippet prefixed by a pipe "|" are frames inline
							 | 
						||
| 
								 | 
							
								the next frame.
							 | 
						||
| 
								 | 
							
								You can see that for the trace #1 in the example, the function
							 | 
						||
| 
								 | 
							
								`you_shall_not_pass()` was inlined in the function `...read2::do_test()` by the
							 | 
						||
| 
								 | 
							
								compiler.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Installation
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Install backward.hpp
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Backward is a header only library. So installing Backward is easy, simply drop
							 | 
						||
| 
								 | 
							
								a copy of `backward.hpp` along with your other source files in your C++ project.
							 | 
						||
| 
								 | 
							
								You can also use a git submodule or really any other way that best fits your
							 | 
						||
| 
								 | 
							
								environment, as long as you can include `backward.hpp`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Install backward.cpp
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If you want Backward to automatically print a stack trace on most common fatal
							 | 
						||
| 
								 | 
							
								errors (segfault, abort, un-handled exception...), simply add a copy of
							 | 
						||
| 
								 | 
							
								`backward.cpp` to your project, and don't forget to tell your build system.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The code in `backward.cpp` is trivial anyway, you can simply copy what it's
							 | 
						||
| 
								 | 
							
								doing at your convenience. 
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Note for [folly](https://github.com/facebook/folly) library users: must define `backward::SignalHandling sh;` after `folly::init(&argc, &argv);`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Configuration & Dependencies
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Integration with CMake
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If you are using CMake and want to use its configuration abilities to save
							 | 
						||
| 
								 | 
							
								you the trouble, you can easily integrate Backward, depending on how you obtained
							 | 
						||
| 
								 | 
							
								the library.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### As a subdirectory:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In this case you have a subdirectory containing the whole repository of Backward
							 | 
						||
| 
								 | 
							
								(eg.: using git-submodules), in this case you can do:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								add_subdirectory(/path/to/backward-cpp)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# This will add backward.cpp to your target
							 | 
						||
| 
								 | 
							
								add_executable(mytarget mysource.cpp ${BACKWARD_ENABLE})
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# This will add libraries, definitions and include directories needed by backward
							 | 
						||
| 
								 | 
							
								# by setting each property on the target.
							 | 
						||
| 
								 | 
							
								add_backward(mytarget)
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Modifying CMAKE_MODULE_PATH
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In this case you can have Backward installed as a subdirectory:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								list(APPEND CMAKE_MODULE_PATH /path/to/backward-cpp)
							 | 
						||
| 
								 | 
							
								find_package(Backward)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# This will add libraries, definitions and include directories needed by backward
							 | 
						||
| 
								 | 
							
								# through an IMPORTED target.
							 | 
						||
| 
								 | 
							
								target_link_libraries(mytarget PUBLIC Backward::Backward)
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Notice that this is equivalent to using the the approach that uses `add_subdirectory()`,
							 | 
						||
| 
								 | 
							
								however it uses cmake's [imported target](https://cmake.org/Wiki/CMake/Tutorials/Exporting_and_Importing_Targets) mechanism.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Installation through a regular package manager
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								In this case you have obtained Backward through a package manager.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Packages currently available:
							 | 
						||
| 
								 | 
							
								- [conda-forge](https://anaconda.org/conda-forge/backward-cpp)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								find_package(Backward)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								# This will add libraries, definitions and include directories needed by backward
							 | 
						||
| 
								 | 
							
								# through an IMPORTED target.
							 | 
						||
| 
								 | 
							
								target_link_libraries(mytarget PUBLIC Backward::Backward)
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								### Libraries to unwind the stack
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								On Linux and macOS, backtrace can back-trace or "walk" the stack using the
							 | 
						||
| 
								 | 
							
								following libraries:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### unwind
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Unwind comes from libgcc, but there is an equivalent inside clang itself. With
							 | 
						||
| 
								 | 
							
								unwind, the stacktrace is as accurate as it can possibly be, since this is
							 | 
						||
| 
								 | 
							
								used by the C++ runtine in gcc/clang for stack unwinding on exception.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Normally libgcc is already linked to your program by default.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### libunwind from the [libunwind project](https://github.com/libunwind/libunwind)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									apt-get install binutils-dev (or equivalent)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Libunwind provides, in some cases, a more accurate stacktrace as it knows
							 | 
						||
| 
								 | 
							
								to decode signal handler frames and lets us edit the context registers when
							 | 
						||
| 
								 | 
							
								unwinding, allowing stack traces over bad function references.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								For best results make sure you are using libunwind 1.3 or later, which added
							 | 
						||
| 
								 | 
							
								`unw_init_local2` and support for handling signal frames.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								CMake will warn you when configuring if your libunwind version doesn't support
							 | 
						||
| 
								 | 
							
								signal frames.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								On macOS clang provides a libunwind API compatible library as part of its
							 | 
						||
| 
								 | 
							
								environment, so no third party libraries are necessary.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Compile with debug info
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								You need to compile your project with generation of debug symbols enabled,
							 | 
						||
| 
								 | 
							
								usually `-g` with clang++ and g++.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Note that you can use `-g` with any level of optimization, with modern debug
							 | 
						||
| 
								 | 
							
								information encoding like DWARF, it only takes space in the binary (it's not
							 | 
						||
| 
								 | 
							
								loaded in memory until your debugger or Backward makes use of it, don't worry),
							 | 
						||
| 
								 | 
							
								and it doesn't impact the code generation (at least on GNU/Linux x86\_64 for
							 | 
						||
| 
								 | 
							
								what I know).
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If you are missing debug information, the stack trace will lack details about
							 | 
						||
| 
								 | 
							
								your sources.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Libraries to read the debug info
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Backward supports pretty printed stack traces on GNU/Linux, macOS and Windows,
							 | 
						||
| 
								 | 
							
								it will compile fine under other platforms but will not do anything. **Pull
							 | 
						||
| 
								 | 
							
								requests are welcome :)**
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Also, by default you will get a really basic stack trace, based on the
							 | 
						||
| 
								 | 
							
								`backtrace_symbols` API:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								You will need to install some dependencies to get the ultimate stack trace.
							 | 
						||
| 
								 | 
							
								Three libraries are currently supported, the only difference is which one is the
							 | 
						||
| 
								 | 
							
								easiest for you to install, so pick your poison:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### libbfd from the [GNU/binutils](http://www.gnu.org/software/binutils/)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									apt-get install binutils-dev (or equivalent)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								And do not forget to link with the lib: `g++/clang++ -lbfd -ldl ...`
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								This library requires dynamic loading. Which is provided by the library `dl`.
							 | 
						||
| 
								 | 
							
								Hence why we also link with `-ldl`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Then define the following before every inclusion of `backward.hpp` (don't
							 | 
						||
| 
								 | 
							
								forget to update `backward.cpp` as well):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									#define BACKWARD_HAS_BFD 1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### libdw from the [elfutils](https://fedorahosted.org/elfutils/)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									apt-get install libdw-dev (or equivalent)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								And do not forget to link with the lib and inform Backward to use it:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									#define BACKWARD_HAS_DW 1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Of course you can simply add the define (`-DBACKWARD_HAS_...=1`) and the
							 | 
						||
| 
								 | 
							
								linkage details in your build system and even auto-detect which library is
							 | 
						||
| 
								 | 
							
								installed, it's up to you.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### [libdwarf](https://sourceforge.net/projects/libdwarf/) and [libelf](http://www.mr511.de/software/english.html)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									apt-get install libdwarf-dev (or equivalent)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								And do not forget to link with the lib and inform Backward to use it:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									#define BACKWARD_HAS_DWARF 1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								There are several alternative implementations of libdwarf and libelf that
							 | 
						||
| 
								 | 
							
								are API compatible so it's possible, although it hasn't been tested, to
							 | 
						||
| 
								 | 
							
								replace the ones used when developing backward (in bold, below):
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								* **_libelf_** by [Michael "Tired" Riepe](http://www.mr511.de/software/english.html)
							 | 
						||
| 
								 | 
							
								* **_libdwarf_** by [David Anderson](https://www.prevanders.net/dwarf.html)
							 | 
						||
| 
								 | 
							
								* libelf from [elfutils](https://fedorahosted.org/elfutils/)
							 | 
						||
| 
								 | 
							
								* libelf and libdwarf from FreeBSD's [ELF Tool Chain](https://sourceforge.net/p/elftoolchain/wiki/Home/) project
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Of course you can simply add the define (`-DBACKWARD_HAS_...=1`) and the
							 | 
						||
| 
								 | 
							
								linkage details in your build system and even auto-detect which library is
							 | 
						||
| 
								 | 
							
								installed, it's up to you.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								That's it, you are all set, you should be getting nice stack traces like the
							 | 
						||
| 
								 | 
							
								one at the beginning of this document.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## API
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								If you don't want to limit yourself to the defaults offered by `backward.cpp`,
							 | 
						||
| 
								 | 
							
								and you want to take some random stack traces for whatever reason and pretty
							 | 
						||
| 
								 | 
							
								print them the way you love or you decide to send them all to your buddies over
							 | 
						||
| 
								 | 
							
								the Internet, you will appreciate the simplicity of Backward's API.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Stacktrace
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The StackTrace class lets you take a "snapshot" of the current stack.
							 | 
						||
| 
								 | 
							
								You can use it like this:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```c++
							 | 
						||
| 
								 | 
							
								using namespace backward;
							 | 
						||
| 
								 | 
							
								StackTrace st; st.load_here(32);
							 | 
						||
| 
								 | 
							
								Printer p; p.print(st);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The public methods are:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```c++
							 | 
						||
| 
								 | 
							
								class StackTrace { public:
							 | 
						||
| 
								 | 
							
									// Take a snapshot of the current stack, with at most "trace_cnt_max"
							 | 
						||
| 
								 | 
							
									// traces in it. The first trace is the most recent (ie the current
							 | 
						||
| 
								 | 
							
									// frame). You can also provide a trace address to load_from() assuming
							 | 
						||
| 
								 | 
							
									// the address is a valid stack frame (useful for signal handling traces).
							 | 
						||
| 
								 | 
							
									// Both function return size().
							 | 
						||
| 
								 | 
							
									size_t load_here(size_t trace_cnt_max)
							 | 
						||
| 
								 | 
							
									size_t load_from(void* address, size_t trace_cnt_max)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// The number of traces loaded. This can be less than "trace_cnt_max".
							 | 
						||
| 
								 | 
							
									size_t size() const
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// A unique id for the thread in which the trace was taken. The value
							 | 
						||
| 
								 | 
							
									// 0 means the stack trace comes from the main thread.
							 | 
						||
| 
								 | 
							
									size_t thread_id() const
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Retrieve a trace by index. 0 is the most recent trace, size()-1 is
							 | 
						||
| 
								 | 
							
									// the oldest one.
							 | 
						||
| 
								 | 
							
									Trace operator[](size_t trace_idx)
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### TraceResolver
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The `TraceResolver` does the heavy lifting, and intends to transform a simple
							 | 
						||
| 
								 | 
							
								`Trace` from its address into a fully detailed `ResolvedTrace` with the
							 | 
						||
| 
								 | 
							
								filename of the source, line numbers, inlined functions and so on.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								You can use it like this:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```c++
							 | 
						||
| 
								 | 
							
								using namespace backward;
							 | 
						||
| 
								 | 
							
								StackTrace st; st.load_here(32);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								TraceResolver tr; tr.load_stacktrace(st);
							 | 
						||
| 
								 | 
							
								for (size_t i = 0; i < st.size(); ++i) {
							 | 
						||
| 
								 | 
							
									ResolvedTrace trace = tr.resolve(st[i]);
							 | 
						||
| 
								 | 
							
									std::cout << "#" << i
							 | 
						||
| 
								 | 
							
										<< " " << trace.object_filename
							 | 
						||
| 
								 | 
							
										<< " " << trace.object_function
							 | 
						||
| 
								 | 
							
										<< " [" << trace.addr << "]"
							 | 
						||
| 
								 | 
							
									<< std::endl;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The public methods are:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```c++
							 | 
						||
| 
								 | 
							
								class TraceResolver { public:
							 | 
						||
| 
								 | 
							
									// Pre-load whatever is necessary from the stack trace.
							 | 
						||
| 
								 | 
							
									template <class ST>
							 | 
						||
| 
								 | 
							
										void load_stacktrace(ST&)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Resolve a trace. It takes a ResolvedTrace, because a `Trace` is
							 | 
						||
| 
								 | 
							
									// implicitly convertible to it.
							 | 
						||
| 
								 | 
							
									ResolvedTrace resolve(ResolvedTrace t)
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### SnippetFactory
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								The SnippetFactory is a simple helper class to automatically load and cache
							 | 
						||
| 
								 | 
							
								source files in order to extract code snippets.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```c++
							 | 
						||
| 
								 | 
							
								class SnippetFactory { public:
							 | 
						||
| 
								 | 
							
									// A snippet is a list of line numbers and line contents.
							 | 
						||
| 
								 | 
							
									typedef std::vector<std::pair<size_t, std::string> > lines_t;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Return a snippet starting at line_start with up to context_size lines.
							 | 
						||
| 
								 | 
							
									lines_t get_snippet(const std::string& filename,
							 | 
						||
| 
								 | 
							
											size_t line_start, size_t context_size)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Return a combined snippet from two different locations and combine them.
							 | 
						||
| 
								 | 
							
									// context_size / 2 lines will be extracted from each location.
							 | 
						||
| 
								 | 
							
									lines_t get_combined_snippet(
							 | 
						||
| 
								 | 
							
											const std::string& filename_a, size_t line_a,
							 | 
						||
| 
								 | 
							
											const std::string& filename_b, size_t line_b,
							 | 
						||
| 
								 | 
							
											size_t context_size)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Tries to return a unified snippet if the two locations from the same
							 | 
						||
| 
								 | 
							
									// file are close enough to fit inside one context_size, else returns
							 | 
						||
| 
								 | 
							
									// the equivalent of get_combined_snippet().
							 | 
						||
| 
								 | 
							
									lines_t get_coalesced_snippet(const std::string& filename,
							 | 
						||
| 
								 | 
							
											size_t line_a, size_t line_b, size_t context_size)
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Printer
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								A simpler way to pretty print a stack trace to the terminal. It will
							 | 
						||
| 
								 | 
							
								automatically resolve the traces for you:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```c++
							 | 
						||
| 
								 | 
							
								using namespace backward;
							 | 
						||
| 
								 | 
							
								StackTrace st; st.load_here(32);
							 | 
						||
| 
								 | 
							
								Printer p;
							 | 
						||
| 
								 | 
							
								p.object = true;
							 | 
						||
| 
								 | 
							
								p.color_mode = ColorMode::always;
							 | 
						||
| 
								 | 
							
								p.address = true;
							 | 
						||
| 
								 | 
							
								p.print(st, stderr);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								You can set a few options:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```c++
							 | 
						||
| 
								 | 
							
								class Printer { public:
							 | 
						||
| 
								 | 
							
									// Print a little snippet of code if possible.
							 | 
						||
| 
								 | 
							
									bool snippet = true;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Colorize the trace
							 | 
						||
| 
								 | 
							
									//  - ColorMode::automatic: Activate colors if possible. For example, when using a TTY on linux.
							 | 
						||
| 
								 | 
							
									//  - ColorMode::always: Always use colors.
							 | 
						||
| 
								 | 
							
									//  - ColorMode::never: Never use colors.
							 | 
						||
| 
								 | 
							
									bool color_mode = ColorMode::automatic;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Add the addresses of every source location to the trace.
							 | 
						||
| 
								 | 
							
									bool address = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Even if there is a source location, also prints the object
							 | 
						||
| 
								 | 
							
									// from where the trace came from.
							 | 
						||
| 
								 | 
							
									bool object = false;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Resolve and print a stack trace to the given C FILE* object.
							 | 
						||
| 
								 | 
							
									// On linux, if the FILE* object is attached to a TTY,
							 | 
						||
| 
								 | 
							
									// color will be used if color_mode is set to automatic.
							 | 
						||
| 
								 | 
							
									template <typename StackTrace>
							 | 
						||
| 
								 | 
							
										FILE* print(StackTrace& st, FILE* fp = stderr);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// Resolve and print a stack trace to the given std::ostream object.
							 | 
						||
| 
								 | 
							
									// Color will only be used if color_mode is set to always. 
							 | 
						||
| 
								 | 
							
									template <typename ST>
							 | 
						||
| 
								 | 
							
										std::ostream& print(ST& st, std::ostream& os);
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### SignalHandling
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								A simple helper class that registers for you the most common signals and other
							 | 
						||
| 
								 | 
							
								callbacks to segfault, hardware exception, un-handled exception etc.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								`backward.cpp` simply uses it like that:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```c++
							 | 
						||
| 
								 | 
							
								backward::SignalHandling sh;
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Creating the object registers all the different signals and hooks. Destroying
							 | 
						||
| 
								 | 
							
								this object doesn't do anything. It exposes only one method:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```c++
							 | 
						||
| 
								 | 
							
								bool loaded() const // true if loaded with success
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Trace object
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								To keep the memory footprint of a loaded `StackTrace` on the low-side, there a
							 | 
						||
| 
								 | 
							
								hierarchy of trace object, from a minimal `Trace `to a `ResolvedTrace`.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Simple trace
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```c++
							 | 
						||
| 
								 | 
							
								struct Trace {
							 | 
						||
| 
								 | 
							
									void*  addr; // address of the trace
							 | 
						||
| 
								 | 
							
									size_t idx;  // its index (0 == most recent)
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#### Resolved trace
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								A `ResolvedTrace` should contains a maximum of details about the location of
							 | 
						||
| 
								 | 
							
								the trace in the source code. Note that not all fields might be set.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								```c++
							 | 
						||
| 
								 | 
							
								struct ResolvedTrace: public Trace {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									struct SourceLoc {
							 | 
						||
| 
								 | 
							
										std::string function;
							 | 
						||
| 
								 | 
							
										std::string filename;
							 | 
						||
| 
								 | 
							
										size_t      line;
							 | 
						||
| 
								 | 
							
										size_t      col;
							 | 
						||
| 
								 | 
							
									};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// In which binary object this trace is located.
							 | 
						||
| 
								 | 
							
									std::string                    object_filename;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// The function in the object that contains the trace. This is not the same
							 | 
						||
| 
								 | 
							
									// as source.function which can be an function inlined in object_function.
							 | 
						||
| 
								 | 
							
									std::string                    object_function;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// The source location of this trace. It is possible for filename to be
							 | 
						||
| 
								 | 
							
									// empty and for line/col to be invalid (value 0) if this information
							 | 
						||
| 
								 | 
							
									// couldn't be deduced, for example if there is no debug information in the
							 | 
						||
| 
								 | 
							
									// binary object.
							 | 
						||
| 
								 | 
							
									SourceLoc                      source;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									// An optional list of "inliners". All of these sources locations where
							 | 
						||
| 
								 | 
							
									// inlined in the source location of the trace (the attribute right above).
							 | 
						||
| 
								 | 
							
									// This is especially useful when you compile with optimizations turned on.
							 | 
						||
| 
								 | 
							
									typedef std::vector<SourceLoc> source_locs_t;
							 | 
						||
| 
								 | 
							
									source_locs_t                  inliners;
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								```
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								## Contact and copyright
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								François-Xavier Bourlet <bombela@gmail.com>
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Copyright 2013-2017 Google Inc. All Rights Reserved.
							 | 
						||
| 
								 | 
							
								MIT License.
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								### Disclaimer
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Although this project is owned by Google Inc. this is not a Google supported or
							 | 
						||
| 
								 | 
							
								affiliated project.
							 |