From: bernhard@bwalle.de
To: ptxdist@pengutronix.de
Cc: Bernhard Walle <walle@corscience.de>
Subject: [ptxdist] [PATCH 1/2] os: Add execinfo::demangleCxxName()
Date: Thu, 22 Mar 2012 13:49:02 +0100 [thread overview]
Message-ID: <1332420543-27500-1-git-send-email-bernhard@bwalle.de> (raw)
From: Bernhard Walle <walle@corscience.de>
Signed-off-by: Bernhard Walle <walle@corscience.de>
---
CMakeLists.txt | 5 ++++
NEWS | 4 +++
csstdxx/CMakeLists.txt | 1 +
csstdxx/config.h.in | 2 ++
csstdxx/os.h | 1 +
csstdxx/os/execinfo.h | 62 ++++++++++++++++++++++++++++++++++++++++
csstdxx/os/execinfo_common.cpp | 49 +++++++++++++++++++++++++++++++
csstdxx/os/os.doxy | 3 ++
examples/os/CMakeLists.txt | 4 +++
examples/os/c++filt.cpp | 13 +++++++++
tests/test_os.cpp | 19 ++++++++++++
tests/test_os.h | 11 +++++++
12 files changed, 174 insertions(+)
create mode 100644 csstdxx/os/execinfo.h
create mode 100644 csstdxx/os/execinfo_common.cpp
create mode 100644 examples/os/c++filt.cpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 0aa43eb..63de09d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -159,6 +159,11 @@ unset(CMAKE_REQUIRED_DEFINITIONS)
check_symbol_exists(readdir_r "dirent.h" HAVE_READDIR_R)
check_symbol_exists(getpwuid_r "pwd.h" HAVE_GETPWUID_R)
+include(CheckCXXSymbolExists)
+check_include_file_cxx("cxxabi.h" HAVE_CXXABI_H)
+if (HAVE_CXXABI_H)
+ check_cxx_symbol_exists(abi::__cxa_demangle "cxxabi.h" HAVE_ABI_CXA_DEMANGLE)
+endif (HAVE_CXXABI_H)
include (CheckTypeExistsCXX)
diff --git a/NEWS b/NEWS
index 440305b..752220a 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,7 @@
+0.5.1
+-----
+ * os: Add execinfo::demangleCxxName().
+
0.5.0
-----
* concurrent: Add MutexLocker::unlock().
diff --git a/csstdxx/CMakeLists.txt b/csstdxx/CMakeLists.txt
index bfd5c57..71af070 100644
--- a/csstdxx/CMakeLists.txt
+++ b/csstdxx/CMakeLists.txt
@@ -61,6 +61,7 @@ set(CSSTDXX_SRC
io/lockfile_common.cpp
os/fileutils.cpp
+ os/execinfo_common.cpp
process/atexitexecuter.cpp
)
diff --git a/csstdxx/config.h.in b/csstdxx/config.h.in
index 0a8304d..ecf135f 100644
--- a/csstdxx/config.h.in
+++ b/csstdxx/config.h.in
@@ -76,6 +76,8 @@
#cmakedefine HAVE_OPEN64_LFS
#cmakedefine HAVE_READDIR_R
#cmakedefine HAVE_GETPWUID_R
+#cmakedefine HAVE_CXXABI_H
+#cmakedefine HAVE_ABI_CXA_DEMANGLE
#cmakedefine WITH_SERIAL_BUS_ACCESS
#cmakedefine HAVE_CLOCK_GETTIME
diff --git a/csstdxx/os.h b/csstdxx/os.h
index d7ceefe..389c4bb 100644
--- a/csstdxx/os.h
+++ b/csstdxx/os.h
@@ -14,5 +14,6 @@
#include <csstdxx/os/tempfile.h>
#include <csstdxx/os/fileutils.h>
#include <csstdxx/os/process.h>
+#include <csstdxx/os/execinfo.h>
#endif /* CSSTDXX_CSSTDXX_OS_H_ */
diff --git a/csstdxx/os/execinfo.h b/csstdxx/os/execinfo.h
new file mode 100644
index 0000000..49cc21f
--- /dev/null
+++ b/csstdxx/os/execinfo.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) Corscience GmbH & Co. KG
+ *
+ * Projectname - Redmine:CSstdxx
+ * Module ID - os
+ */
+
+#ifndef CSSTDXX_OS_EXECINFO_H_
+#define CSSTDXX_OS_EXECINFO_H_
+
+#include <string>
+
+namespace cs {
+namespace os {
+namespace execinfo {
+
+/**
+ * \brief Demangles a C++ identifier
+ *
+ * Sometimes C++ identifiers appear with name mangling applied, for example
+ * in that piece of code, at least on Linux/gcc (the standard doesn't say anything
+ * about what the type information string should look like):
+ *
+ * \code
+ * #include <typeinfo>
+ *
+ * struct Vehicle {
+ * virtual ~Vehicle() {} // the type should have RTTI
+ * };
+ *
+ * struct Car : public Vehicle {};
+ *
+ * Vehicle *v = new Car;
+ * std::cout << "v is a " << typeid(*v).name() << std::endl;
+ * \endcode
+ *
+ * On Linux, this prints <tt>"3Car"</tt> instead of just <tt>"Car"</tt>. While that
+ * can be decoded simply by looking at the name, there are situations where
+ * the names are more complex.
+ *
+ * On the commandline on Linux you can use <tt>c++filt</tt> to demangle such names.
+ * Programmatically there are different compiler-specific APIs to decode them.
+ * cs::os::execinfo::demangleCxxName() is a wrapper around them.
+ *
+ * \note Currently this function is implemented when libstdc++ is used (independent
+ * of the operating system). Tested with clang and gcc on Linux.
+ *
+ * \param[in] name the name that should be demangled
+ * \param[out] ok if not NULL, then this variable will be set to \c true on success
+ * or to \c false on failure.
+ * \return the demangled name on success or \p name on failure.
+ * \since 0.5.1
+ * \ingroup os_execinfo
+ * \sa http://en.wikipedia.org/wiki/Name_mangling
+ */
+std::string demangleCxxName(const char *name, bool *ok=NULL);
+
+} // namespace execinfo
+} // namespace os
+} // namespace cs
+
+#endif /* CSSTDXX_OS_EXECINFO_H_ */
diff --git a/csstdxx/os/execinfo_common.cpp b/csstdxx/os/execinfo_common.cpp
new file mode 100644
index 0000000..e9bee8a
--- /dev/null
+++ b/csstdxx/os/execinfo_common.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) Corscience GmbH & Co. KG
+ *
+ * Projectname - Redmine:CSstdxx
+ * Module ID - os
+ */
+
+#include <csstdxx/config.h>
+#include <cstdlib>
+#include "execinfo.h"
+
+#ifdef HAVE_CXXABI_H
+# include <cxxabi.h>
+#endif
+
+namespace cs {
+namespace os {
+namespace execinfo {
+
+#if defined(HAVE_ABI_CXA_DEMANGLE)
+std::string demangleCxxName(const char *name, bool *ok)
+{
+ int status;
+ char* result = abi::__cxa_demangle(name, NULL, 0, &status);
+ if (result && status == 0) {
+ if (ok)
+ *ok = true;
+ std::string resultString(result);
+ free(result);
+ return resultString;
+ }
+ else {
+ if (ok)
+ *ok = false;
+ return std::string(name);
+ }
+}
+#else
+std::string demangleCxxName(const char *name, bool *ok)
+{
+ if (ok)
+ *ok = false;
+ return std::string();
+}
+#endif
+
+} // namespace execinfo
+} // namespace os
+} // namespace cs
diff --git a/csstdxx/os/os.doxy b/csstdxx/os/os.doxy
index 4b9838e..57d5336 100644
--- a/csstdxx/os/os.doxy
+++ b/csstdxx/os/os.doxy
@@ -15,6 +15,9 @@
\defgroup os_process Process utilities
\ingroup os
+\defgroup os_execinfo Runtime execution information
+\ingroup os
+
*/
// vim: set ft=doxygen:
diff --git a/examples/os/CMakeLists.txt b/examples/os/CMakeLists.txt
index d96de60..e117fb7 100644
--- a/examples/os/CMakeLists.txt
+++ b/examples/os/CMakeLists.txt
@@ -25,6 +25,10 @@ add_executable(tempfile tempfile.cpp)
target_link_libraries(tempfile csstdxx)
set(EXAMPLE_PROGRAMS ${EXAMPLE_PROGRAMS} tempfile)
+add_executable(c++filt c++filt.cpp)
+target_link_libraries(c++filt csstdxx)
+set(EXAMPLE_PROGRAMS ${EXAMPLE_PROGRAMS} c++filt)
+
if (INSTALL_CSSTDXX_EXAMPLES)
install(TARGETS ${EXAMPLE_PROGRAMS} DESTINATION bin/csstdxx)
endif (INSTALL_CSSTDXX_EXAMPLES)
diff --git a/examples/os/c++filt.cpp b/examples/os/c++filt.cpp
new file mode 100644
index 0000000..6a36e32
--- /dev/null
+++ b/examples/os/c++filt.cpp
@@ -0,0 +1,13 @@
+#include <iostream>
+#include <csstdxx/os.h>
+
+int main(int argc, char *argv[])
+{
+ if (argc != 2) {
+ std::cerr << "Usage: c++filt <symbol>" << std::endl;
+ return -1;
+ }
+
+ std::cout << cs::os::execinfo::demangleCxxName(argv[1]) << std::endl;
+ return 0;
+}
diff --git a/tests/test_os.cpp b/tests/test_os.cpp
index 29fa1db..683e875 100644
--- a/tests/test_os.cpp
+++ b/tests/test_os.cpp
@@ -458,6 +458,25 @@ void TestProcess::testExec()
CPPUNIT_ASSERT(execute("bladoesnotexist", StringVector()) != 0);
}
+//
+// TestExecinfo
+//
+
+void TestExecinfo::testCppDemangle()
+{
+#ifdef __linux__
+ bool ok;
+ std::string result = execinfo::demangleCxxName("_ZN7QWidget8x11EventEP7_XEvent", &ok);
+ CPPUNIT_ASSERT(ok);
+ CPPUNIT_ASSERT_EQUAL(std::string("QWidget::x11Event(_XEvent*)"), result);
+#endif
+
+ // that must work on any platform
+ result = execinfo::demangleCxxName("blablubb", &ok);
+ CPPUNIT_ASSERT(!ok);
+ CPPUNIT_ASSERT_EQUAL(std::string("blablubb"), result);
+}
+
} // namespace os
} // namespace cs
diff --git a/tests/test_os.h b/tests/test_os.h
index 24e8984..a95d0a9 100644
--- a/tests/test_os.h
+++ b/tests/test_os.h
@@ -117,6 +117,17 @@ private:
CPPUNIT_TEST_SUITE_END();
};
+class TestExecinfo : public CppUnit::TestFixture
+{
+public:
+ void testCppDemangle();
+
+private:
+ CPPUNIT_TEST_SUITE(TestExecinfo);
+ CPPUNIT_TEST(testCppDemangle);
+ CPPUNIT_TEST_SUITE_END();
+};
+
} // namespace os
} // namespace cs
--
1.7.9.4
--
ptxdist mailing list
ptxdist@pengutronix.de
next 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 bernhard [this message]
2012-03-22 12:49 ` [ptxdist] [PATCH 2/2] os: Add execinfo::backtrace() bernhard
2012-03-22 12:54 ` 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-1-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