From: bernhard@bwalle.de
To: ptxdist@pengutronix.de
Cc: Bernhard Walle <walle@corscience.de>
Subject: [ptxdist] [PATCH 2/2] os: Add execinfo::backtrace()
Date: Thu, 22 Mar 2012 13:49:03 +0100 [thread overview]
Message-ID: <1332420543-27500-2-git-send-email-bernhard@bwalle.de> (raw)
In-Reply-To: <1332420543-27500-1-git-send-email-bernhard@bwalle.de>
From: Bernhard Walle <walle@corscience.de>
Signed-off-by: Bernhard Walle <walle@corscience.de>
---
NEWS | 2 +-
csstdxx/CMakeLists.txt | 2 ++
csstdxx/os/execinfo.h | 53 ++++++++++++++++++++++++++++++++++
csstdxx/os/execinfo_linux.cpp | 64 +++++++++++++++++++++++++++++++++++++++++
examples/os/CMakeLists.txt | 4 +++
examples/os/backtrace.cpp | 27 +++++++++++++++++
tests/test_os.cpp | 7 +++++
tests/test_os.h | 2 ++
8 files changed, 160 insertions(+), 1 deletion(-)
create mode 100644 csstdxx/os/execinfo_linux.cpp
create mode 100644 examples/os/backtrace.cpp
diff --git a/NEWS b/NEWS
index 752220a..213cda4 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,6 @@
0.5.1
-----
- * os: Add execinfo::demangleCxxName().
+ * os: Add execinfo::demangleCxxName() and execinfo::backtrace().
0.5.0
-----
diff --git a/csstdxx/CMakeLists.txt b/csstdxx/CMakeLists.txt
index 71af070..d26c568 100644
--- a/csstdxx/CMakeLists.txt
+++ b/csstdxx/CMakeLists.txt
@@ -125,6 +125,8 @@ endif (WITH_SERIAL_BUS_ACCESS)
if (CMAKE_SYSTEM_NAME STREQUAL "Linux")
set(CSSTDXX_SRC ${CSSTDXX_SRC}
+ os/execinfo_linux.cpp
+
datetime/systemclock_linux.cpp
io/iotimer_linux.cpp
diff --git a/csstdxx/os/execinfo.h b/csstdxx/os/execinfo.h
index 49cc21f..7772f4e 100644
--- a/csstdxx/os/execinfo.h
+++ b/csstdxx/os/execinfo.h
@@ -55,6 +55,59 @@ namespace execinfo {
*/
std::string demangleCxxName(const char *name, bool *ok=NULL);
+/**
+ * \brief Returns a backtrace from the current stack
+ *
+ * It depends on the implementation how the backtrace looks like. Here's an example
+ * (x86_64, gcc, Linux):
+ *
+ * \verbatim
+/home/bwalle/devel/CSstdxx/CSstdxx/build/csstdxx/libcsstdxx.so.2(cs::os::execinfo::backtrace()+0x49) [0x7f8e7402594d]
+build/examples/os/backtrace(sigsegvhandler(int)+0x18) [0x400ccc]
+/lib/libc.so.6(+0x349f0) [0x7f8e72f819f0]
+build/examples/os/backtrace(foo(int)+0x1d) [0x400d2d]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(foo(int)+0x37) [0x400d47]
+build/examples/os/backtrace(main+0x28) [0x400d71]
+/lib/libc.so.6(__libc_start_main+0xed) [0x7f8e72f6e38d]
+build/examples/os/backtrace() [0x400bf9]
+\endverbatim
+ *
+ * As you see, the function names are demangled and there \b are function names.
+ * To get that on Linux/gcc, you must compile your application and all libraries
+ * from which a backtrace should be obtained with the <tt>-rdynamic</tt> command line
+ * parameter. This is the default for CMake.
+ *
+ * The example <tt>backtrace.cpp</tt> shows how to use backtrace to print something
+ * useful when the application receives a segmentation fault.
+ *
+ * \note Don't try to parse the output. Just use it for debugging.
+ *
+ * \return the backtrace as shown above on success or an empty string on failure.
+ * \since 0.5.1
+ * \ingroup os_execinfo
+ * \sa http://en.wikipedia.org/wiki/Name_mangling
+ */
+std::string backtrace();
+
} // namespace execinfo
} // namespace os
} // namespace cs
diff --git a/csstdxx/os/execinfo_linux.cpp b/csstdxx/os/execinfo_linux.cpp
new file mode 100644
index 0000000..5516292
--- /dev/null
+++ b/csstdxx/os/execinfo_linux.cpp
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) Corscience GmbH & Co. KG
+ *
+ * Projectname - Redmine:CSstdxx
+ * Module ID - os
+ */
+
+#include <csstdxx/config.h>
+#include <cstdlib>
+#include <sstream>
+#include <execinfo.h>
+
+#include "execinfo.h"
+
+#ifdef HAVE_CXXABI_H
+# include <cxxabi.h>
+#endif
+
+namespace cs {
+namespace os {
+namespace execinfo {
+
+#define BACKTRACE_MAX 100
+
+std::string backtrace()
+{
+ std::stringstream ss;
+
+ void *buffer[100];
+ int nptrs = ::backtrace(buffer, BACKTRACE_MAX);
+ if (nptrs == 0)
+ return std::string();
+
+ char **strings = backtrace_symbols(buffer, nptrs);
+ if (!strings)
+ return std::string();
+
+ for (int i = 0; i < nptrs; i++) {
+ // demangle names if possible
+ std::string line = strings[i];
+ size_t openBrace = line.find('(');
+ size_t plus = line.find('+', openBrace);
+
+ if ((openBrace == std::string::npos) || (plus == std::string::npos)) {
+ ss << line << std::endl;
+ continue;
+ }
+
+ std::string function = line.substr(openBrace+1, plus-openBrace-1);
+ function = demangleCxxName(function.c_str());
+
+ ss << line.substr(0, openBrace+1)
+ << function
+ << line.substr(plus) << std::endl;
+ }
+
+ free(strings);
+
+ return ss.str();
+}
+
+} // namespace execinfo
+} // namespace os
+} // namespace cs
diff --git a/examples/os/CMakeLists.txt b/examples/os/CMakeLists.txt
index e117fb7..4b20733 100644
--- a/examples/os/CMakeLists.txt
+++ b/examples/os/CMakeLists.txt
@@ -29,6 +29,10 @@ add_executable(c++filt c++filt.cpp)
target_link_libraries(c++filt csstdxx)
set(EXAMPLE_PROGRAMS ${EXAMPLE_PROGRAMS} c++filt)
+add_executable(backtrace backtrace.cpp)
+target_link_libraries(backtrace csstdxx)
+set(EXAMPLE_PROGRAMS ${EXAMPLE_PROGRAMS} backtrace)
+
if (INSTALL_CSSTDXX_EXAMPLES)
install(TARGETS ${EXAMPLE_PROGRAMS} DESTINATION bin/csstdxx)
endif (INSTALL_CSSTDXX_EXAMPLES)
diff --git a/examples/os/backtrace.cpp b/examples/os/backtrace.cpp
new file mode 100644
index 0000000..ca6bd9d
--- /dev/null
+++ b/examples/os/backtrace.cpp
@@ -0,0 +1,27 @@
+#include <csignal>
+#include <cstdio>
+#include <csstdxx/os.h>
+
+void sigsegvhandler(int signal)
+{
+ puts(cs::os::execinfo::backtrace().c_str());
+ _exit(1);
+}
+
+int foo(int x)
+{
+ if (x == 0) {
+ volatile int *p = NULL;
+ *p = 20;
+ return 0;
+ }
+ else
+ return foo(x-1);
+}
+
+int main(int argc, char *argv[])
+{
+ signal(SIGSEGV, sigsegvhandler);
+ foo(20);
+ return 0;
+}
diff --git a/tests/test_os.cpp b/tests/test_os.cpp
index 683e875..c36e719 100644
--- a/tests/test_os.cpp
+++ b/tests/test_os.cpp
@@ -477,6 +477,13 @@ void TestExecinfo::testCppDemangle()
CPPUNIT_ASSERT_EQUAL(std::string("blablubb"), result);
}
+void TestExecinfo::testBacktrace()
+{
+#ifdef __linux__
+ CPPUNIT_ASSERT(!execinfo::backtrace().empty());
+#endif
+}
+
} // namespace os
} // namespace cs
diff --git a/tests/test_os.h b/tests/test_os.h
index a95d0a9..58ba5d3 100644
--- a/tests/test_os.h
+++ b/tests/test_os.h
@@ -121,10 +121,12 @@ class TestExecinfo : public CppUnit::TestFixture
{
public:
void testCppDemangle();
+ void testBacktrace();
private:
CPPUNIT_TEST_SUITE(TestExecinfo);
CPPUNIT_TEST(testCppDemangle);
+ CPPUNIT_TEST(testBacktrace);
CPPUNIT_TEST_SUITE_END();
};
--
1.7.9.4
--
ptxdist mailing list
ptxdist@pengutronix.de
next prev parent reply other threads:[~2012-03-22 12:52 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-03-22 12:49 [ptxdist] [PATCH 1/2] os: Add execinfo::demangleCxxName() bernhard
2012-03-22 12:49 ` bernhard [this message]
2012-03-22 12:54 ` [ptxdist] [PATCH 2/2] os: Add execinfo::backtrace() Bernhard Walle
2012-03-24 9:53 ` Michael Olbrich
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1332420543-27500-2-git-send-email-bernhard@bwalle.de \
--to=bernhard@bwalle.de \
--cc=ptxdist@pengutronix.de \
--cc=walle@corscience.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox