• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..17-Oct-2021-

doc/H03-May-2022-

test/H17-Oct-2021-789493

test_package/H03-May-2022-6248

.clang-formatH A D17-Oct-202123 32

.travis.ymlH A D17-Oct-2021728 2622

BackwardConfig.cmakeH A D17-Oct-20217.7 KiB207183

README.mdH A D17-Oct-202113.7 KiB412293

backward.cppH A D17-Oct-2021757 334

backward.hppH A D17-Oct-2021126.2 KiB4,1722,993

builds.shH A D17-Oct-20211.3 KiB7866

conanfile.pyH A D17-Oct-20211.5 KiB4640

qt_attribution.jsonH A D17-Oct-2021467 1613

README.md

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