[mlpack-git] master: Add mlpack::backtrace for Ubuntu (C++, Clang). (e671aa8)
gitdub at mlpack.org
gitdub at mlpack.org
Wed Feb 24 15:22:10 EST 2016
Repository : https://github.com/mlpack/mlpack
On branch : master
Link : https://github.com/mlpack/mlpack/compare/fd84f3a2e53592d723a8e8a76dadb8aa76820913...1a9c41a86be1fa1dcc5c3b90dd959c2255c3bb8e
>---------------------------------------------------------------
commit e671aa8479cb80927319edfb53a640b9dbfc0c8b
Author: krajekg at gmail.com <krajekg at gmail.com>
Date: Wed Feb 24 21:22:10 2016 +0100
Add mlpack::backtrace for Ubuntu (C++, Clang).
>---------------------------------------------------------------
e671aa8479cb80927319edfb53a640b9dbfc0c8b
.directory | 4 +
CMake/FindBfd.cmake | 89 ++++++++++++++++++
CMake/FindLibDL.cmake | 32 +++++++
src/mlpack/core/util/backtrace.cpp | 183 +++++++++++++++++++++++++++++++++++++
src/mlpack/core/util/backtrace.hpp | 95 +++++++++++++++++++
5 files changed, 403 insertions(+)
diff --git a/.directory b/.directory
new file mode 100644
index 0000000..08356bf
--- /dev/null
+++ b/.directory
@@ -0,0 +1,4 @@
+[Dolphin]
+Timestamp=2016,2,24,21,12,46
+Version=3
+ViewMode=1
diff --git a/CMake/FindBfd.cmake b/CMake/FindBfd.cmake
new file mode 100644
index 0000000..19b1b5b
--- /dev/null
+++ b/CMake/FindBfd.cmake
@@ -0,0 +1,89 @@
+# - Try to find libbfd
+# Once done this will define
+#
+# LIBBFD_FOUND - system has libbfd
+# LIBBFD_INCLUDE_DIRS - the libbfd include directory
+# LIBBFD_LIBRARIES - Link these to use libbfd
+# LIBBFD_DEFINITIONS - Compiler switches required for using libbfd
+#
+# Based on:
+#
+# Copyright (c) 2008 Bernhard Walle <bernhard.walle at gmx.de>
+#
+# Redistribution and use is allowed according to the terms of the New
+# BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+#
+
+
+if (LIBBFD_LIBRARIES AND LIBBFD_INCLUDE_DIRS)
+ set (LIBBFD_FIND_QUIETLY TRUE)
+endif (LIBBFD_LIBRARIES AND LIBBFD_INCLUDE_DIRS)
+
+find_path (LIBBFD_INCLUDE_DIRS
+ NAMES
+ bfd.h
+ dis-asm.h
+ PATHS
+ /usr/include
+ /usr/local/include
+ /opt/local/include
+ /opt/include
+ ENV CPATH)
+
+# Ugly, yes ugly...
+find_library (LIBBFD_BFD_LIBRARY
+ NAMES
+ bfd
+ PATHS
+ /usr/lib
+ /usr/lib64
+ /usr/local/lib
+ /usr/local/lib64
+ /usr/include
+ /opt/local/lib
+ /opt/usr/lib64
+ ENV LIBRARY_PATH
+ ENV LD_LIBRARY_PATH)
+
+#find_library (LIBBFD_IBERTY_LIBRARY
+# NAMES
+# iberty
+# PATHS
+# /usr/lib
+# /usr/lib64
+# /usr/local/lib
+# /usr/local/lib64
+# /usr/include
+# /opt/local/lib
+# /opt/usr/lib64
+# ENV LIBRARY_PATH
+# ENV LD_LIBRARY_PATH)
+
+#find_library (LIBBFD_OPCODES_LIBRARY
+# NAMES
+# opcodes
+# PATHS
+# /usr/lib
+# /usr/lib64
+# /usr/local/lib
+# /usr/local/lib64
+# /usr/include
+# /opt/local/lib
+# /opt/usr/lib64
+# ENV LIBRARY_PATH
+# ENV LD_LIBRARY_PATH)
+
+
+include (FindPackageHandleStandardArgs)
+
+
+# handle the QUIETLY and REQUIRED arguments and set LIBBFD_FOUND to TRUE if all listed variables are TRUE
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIBBFD DEFAULT_MSG
+ LIBBFD_BFD_LIBRARY
+# LIBBFD_IBERTY_LIBRARY
+# LIBBFD_OPCODES_LIBRARY
+ LIBBFD_INCLUDE_DIRS)
+
+set(LIBBFD_LIBRARIES "${LIBBFD_BFD_LIBRARY}")
+mark_as_advanced(LIBBFD_INCLUDE_DIRS LIBBFD_LIBRARIES)
\ No newline at end of file
diff --git a/CMake/FindLibDL.cmake b/CMake/FindLibDL.cmake
new file mode 100644
index 0000000..52fd399
--- /dev/null
+++ b/CMake/FindLibDL.cmake
@@ -0,0 +1,32 @@
+# - Try to find libdl
+# Once done this will define
+#
+# LIBDL_FOUND - system has libdl
+# LIBDL_INCLUDE_DIRS - the libdl include directory
+# LIBDL_LIBRARIES - Link these to use libdl
+# LIBDL_NEEDS_UNDERSCORE - If extern "C" symbols are prefixed (BSD/Apple)
+#
+
+find_path (LIBDL_INCLUDE_DIRS NAMES dlfcn.h)
+find_library (LIBDL_LIBRARIES NAMES dl)
+include (FindPackageHandleStandardArgs)
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LibDL DEFAULT_MSG
+ LIBDL_LIBRARIES
+ LIBDL_INCLUDE_DIRS)
+
+SET(CMAKE_REQUIRED_LIBRARIES dl)
+INCLUDE(CheckCSourceRuns)
+CHECK_C_SOURCE_RUNS("#include <dlfcn.h>
+#include <stdlib.h>
+void testfunc() {}
+int main() {
+ testfunc();
+ if (dlsym(0, \"_testfunc\") != (void*)0) {
+ return EXIT_SUCCESS;
+ } else {
+ return EXIT_FAILURE;
+ }
+}" LIBDL_NEEDS_UNDERSCORE)
+
+mark_as_advanced(LIBDL_INCLUDE_DIRS LIBDL_LIBRARIES LIBDL_NEEDS_UNDERSCORE)
\ No newline at end of file
diff --git a/src/mlpack/core/util/backtrace.cpp b/src/mlpack/core/util/backtrace.cpp
new file mode 100644
index 0000000..f718591
--- /dev/null
+++ b/src/mlpack/core/util/backtrace.cpp
@@ -0,0 +1,183 @@
+/**
+ * @file backtrace.cpp
+ * @author Grzegorz Krajewski
+ *
+ * Implementation of the Backtrace class.
+ *
+ * This file is part of mlpack 2.0.1.
+ *
+ * mlpack is free software; you may redstribute it and/or modify it under the
+ * terms of the 3-clause BSD license. You should have received a copy of the
+ * 3-clause BSD license along with mlpack. If not, see
+ * http://www.opensource.org/licenses/BSD-3-Clause for more information.
+ */
+
+#include <sstream>
+
+#ifdef HAS_BFD_DL
+ #include <execinfo.h>
+ #include <signal.h>
+ #include <unistd.h>
+ #include <cxxabi.h>
+ #include <bfd.h>
+ #include <dlfcn.h>
+#endif
+
+#include "prefixedoutstream.hpp"
+#include "backtrace.hpp"
+#include "log.hpp"
+
+// Easier to read Backtrace::DecodeAddress().
+#ifdef HAS_BFD_DL
+ #define TRACE_CONDITION_1 (!dladdr(trace[i], &addressHandler))
+ #define FIND_LINE (bfd_find_nearest_line(abfd, text, syms, offset, &frame.file, &frame.function, &frame.line) && frame.file)
+#endif
+
+using namespace mlpack;
+
+// Initialize Backtrace static inctances.
+Backtrace::Frames Backtrace::frame;
+std::vector<Backtrace::Frames> Backtrace::stack;
+
+// Binary File Descriptor objects.
+bfd* abfd = 0; // Descriptor datastructure.
+asymbol **syms = 0; // Symbols datastructure.
+asection *text = 0; // Strings datastructure.
+
+Backtrace::Backtrace(int maxDepth)
+{
+ frame.address = NULL;
+ frame.function = "0";
+ frame.file = "0";
+ frame.line = 0;
+
+ stack.clear();
+#ifdef HAS_BFD_DL
+ GetAddress(maxDepth);
+#endif
+}
+
+#ifdef HAS_BFD_DL
+void Backtrace::GetAddress(int maxDepth)
+{
+ void* trace[maxDepth];
+ int stackDepth = backtrace(trace, maxDepth);
+
+ // Skip first stack frame (points to Backtrace::Backtrace).
+ for (int i = 1; i < stackDepth; i++)
+ {
+ Dl_info addressHandler;
+
+ //No backtrace will be printed if no compile flags: -g -rdynamic
+ if(TRACE_CONDITION_1)
+ {
+ return ;
+ }
+
+ frame.address = addressHandler.dli_saddr;
+
+ DecodeAddress((long)frame.address);
+ }
+}
+
+void Backtrace::DecodeAddress(long addr)
+{
+ // Check to see if there is anything to descript. If it doesn't, we'll
+ // dump running program.
+ if (!abfd)
+ {
+ char ename[1024];
+ int l = readlink("/proc/self/exe",ename,sizeof(ename));
+ if (l == -1)
+ {
+ perror("Failed to open executable!\n");
+ return;
+ }
+ ename[l] = 0;
+
+ bfd_init();
+
+ abfd = bfd_openr(ename, 0);
+ if (!abfd)
+ {
+ perror("bfd_openr failed: ");
+ return;
+ }
+
+ bfd_check_format(abfd,bfd_object);
+
+ unsigned storage_needed = bfd_get_symtab_upper_bound(abfd);
+ syms = (asymbol **) malloc(storage_needed);
+
+ text = bfd_get_section_by_name(abfd, ".text");
+ }
+
+ long offset = addr - text->vma;
+
+ if (offset > 0)
+ {
+ if(FIND_LINE)
+ {
+ DemangleFunction();
+ // Save retrieved informations.
+ stack.push_back(frame);
+ }
+ }
+}
+
+void Backtrace::DemangleFunction()
+{
+ int status;
+ char* tmp = abi::__cxa_demangle(frame.function, 0, 0, &status);
+
+ // If demangling is successful, reallocate 'frame.function' pointer to
+ // demangled name. Else if 'status != 0', leave 'frame.function as it is.
+ if (status == 0)
+ {
+ frame.function = tmp;
+ }
+}
+#else
+void Backtrace::GetAddress(int /* maxDepth */) { }
+void Backtrace::DecodeAddress(long /* address */) { }
+void Backtrace::DemangleFunction() { }
+#endif
+
+std::string Backtrace::ToString()
+{
+ std::string stackStr;
+
+#ifdef HAS_BFD_DL
+ std::ostringstream lineOss;
+ std::ostringstream it;
+
+ if(stack.size() <= 0)
+ {
+ stackStr = "Cannot give backtrace because program was compiled";
+ stackStr += " without: -g -rdynamic\nFor a backtrace,";
+ stackStr += " recompile with: -g -rdynamic.\n";
+
+ return stackStr;
+ }
+
+ for(unsigned int i = 0; i < stack.size(); i++)
+ {
+ frame = stack[i];
+
+ lineOss << frame.line;
+ it << i + 1;
+
+ stackStr += "[bt]: (" + it.str() + ") "
+ + frame.file + ":"
+ + frame.function + ":"
+ + lineOss.str() + "\n";
+
+ lineOss.str("");
+ it.str("");
+ }
+#else
+ stackStr = "[bt]: No backtrace for this OS. Work in progress.";
+#endif
+
+ return stackStr;
+}
\ No newline at end of file
diff --git a/src/mlpack/core/util/backtrace.hpp b/src/mlpack/core/util/backtrace.hpp
new file mode 100644
index 0000000..8e5bbb0
--- /dev/null
+++ b/src/mlpack/core/util/backtrace.hpp
@@ -0,0 +1,95 @@
+/**
+ * @file backtrace.hpp
+ * @author Grzegorz Krajewski
+ *
+ * Definition of the Backtrace class.
+ *
+ * This file is part of mlpack 2.0.1.
+ *
+ * mlpack is free software; you may redstribute it and/or modify it under the
+ * terms of the 3-clause BSD license. You should have received a copy of the
+ * 3-clause BSD license along with mlpack. If not, see
+ * http://www.opensource.org/licenses/BSD-3-Clause for more information.
+ */
+#ifndef __MLPACK_CORE_UTIL_BACKTRACE_HPP
+#define __MLPACK_CORE_UTIL_BACKTRACE_HPP
+
+#include <string>
+#include <vector>
+
+namespace mlpack {
+
+/**
+ * Provides a backtrace.
+ *
+ * The Backtrace class retrieve addresses of each called function from the
+ * stack and decode file name, function & line number. Retrieved informations
+ * can be printed in form:
+ *
+ * @code
+ * [b]: (count) /directory/to/file.cpp:function(args):line_number
+ * @endcode
+ *
+ * Backtrace is printed always when Log::Assert failed.
+ * An example is given below.
+ *
+ * @code
+ * if (!someImportantCondition())
+ * {
+ * Log::Fatal << "someImportantCondition() is not satisfied! Terminating.";
+ * Log::Fatal << std::endl;
+ * }
+ * @endcode
+ *
+ * @note Log::Assert will not be shown when compiling in non-debug mode.
+ *
+ * @see PrefixedOutStream, Log
+ */
+class Backtrace
+{
+ public:
+ /**
+ * Constructor initialize fields and call GetAddress to retrieve addresses
+ * for each frame of backtrace.
+ *
+ * @param maxDepth Maximum depth of backtrace. Default 32 steps.
+ */
+ Backtrace(int maxDepth = 32);
+
+ //! Returns string of backtrace.
+ std::string ToString();
+
+ private:
+ /**
+ * Gets addresses of each called function from the stack.
+ *
+ * @param maxDepth Maximum depth of backtrace. Default 32 steps.
+ */
+ static void GetAddress(int maxDepth);
+
+ /**
+ * Decodes file name, function & line number.
+ *
+ * @param address Address of traced frame.
+ */
+ static void DecodeAddress(long address);
+
+ //! Demangles function name.
+ static void DemangleFunction();
+
+ //! Backtrace datastructure.
+ struct Frames
+ {
+ void *address;
+ const char* function;
+ const char* file;
+ unsigned line;
+ } static frame;
+
+ //! A vector for all the backtrace information.
+ static std::vector<Frames> stack;
+};
+
+}; //namespace mlpack
+
+#endif
\ No newline at end of file
More information about the mlpack-git
mailing list