Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a portable/standard-compliant way to get filenames and linenumbers in a stack trace?

I've just read

How to generate a stacktrace when my gcc C++ app crashes

which is pretty old by now (5 years). Some answers suggest solutions allowing you to get, for every stack frame, the name of the function and an offset (within the stack I guess). But what I (and may others) really need is the source filename and line number where the call was made (assuming the code was compiled with debug information). One of the answers linked to a part of glibc which does this (libSegfault; see files in this directory - segfault.c, backtracesyms.c, backtracesymsfd.c) - so it is possible.

My questions are:

  • Can this information be extracted in a platform-independent fashion, or one that conforms to some standard (POSIX??)
  • Why doesn't libunwind support this? (I think it doesn't, after looking through ther website)
  • Does this necessarily depend on your compiler's C/C++ standard library (for C/C++ apps, at least)?

Notes:

  • You may assume the binary has debugging info, so in the case of C/C++ it was compiled with -g; of course, in a proper library we would check whether debug info is available or not.
like image 818
einpoklum Avatar asked Nov 22 '16 21:11

einpoklum


1 Answers

Adding to @EmployedRussian's valid answer - there is now a multi-platform library which does this:

Boost StackTrace

And just to illustrate what a trace looks like, if you were to write:

// This following definition may be necessary to ensure you can get
// line numbers included in the stack trace; see:
// https://stackoverflow.com/questions/3899870/
// for details
//
#define BOOST_STACKTRACE_USE_ADDR2LINE

#include <boost/stacktrace.hpp>

// ... somewhere inside the `bar(int)` function that is called recursively:
std::cout << boost::stacktrace::stacktrace();

you might get something like (on Linux for example):

0# bar(int) at /path/to/source/file.cpp:70
1# bar(int) at /path/to/source/file.cpp:70
2# bar(int) at /path/to/source/file.cpp:70
3# bar(int) at /path/to/source/file.cpp:70
4# main at /path/to/main.cpp:93
5# __libc_start_main in /lib/x86_64-linux-gnu/libc.so.6
6# _start
like image 150
einpoklum Avatar answered Oct 13 '22 01:10

einpoklum