diff --git a/.directory b/.directory new file mode 100644 index 0000000000..08356bfd45 --- /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 0000000000..19b1b5bd9c --- /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 +# +# 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 0000000000..52fd399514 --- /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 +#include +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 0000000000..f718591b83 --- /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 + +#ifdef HAS_BFD_DL + #include + #include + #include + #include + #include + #include +#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::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 0000000000..8e5bbb0660 --- /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 +#include + +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 stack; +}; + +}; //namespace mlpack + +#endif \ No newline at end of file