Add mlpack::backtrace for Ubuntu (C++, Clang).
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
[Dolphin]
|
||||
Timestamp=2016,2,24,21,12,46
|
||||
Version=3
|
||||
ViewMode=1
|
||||
@@ -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@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)
|
||||
@@ -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)
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user