mirror of https://github.com/Icinga/icinga2.git
parent
ac3cbfe801
commit
f8a2ddc464
|
@ -104,6 +104,7 @@ include(CheckLibraryExists)
|
||||||
check_function_exists(vfork HAVE_VFORK)
|
check_function_exists(vfork HAVE_VFORK)
|
||||||
check_function_exists(backtrace_symbols HAVE_BACKTRACE_SYMBOLS)
|
check_function_exists(backtrace_symbols HAVE_BACKTRACE_SYMBOLS)
|
||||||
check_function_exists(pipe2 HAVE_PIPE2)
|
check_function_exists(pipe2 HAVE_PIPE2)
|
||||||
|
check_function_exists(dladdr HAVE_DLADDR)
|
||||||
check_library_exists(crypto BIO_f_zlib "" HAVE_BIOZLIB)
|
check_library_exists(crypto BIO_f_zlib "" HAVE_BIOZLIB)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
#cmakedefine HAVE_BACKTRACE_SYMBOLS
|
#cmakedefine HAVE_BACKTRACE_SYMBOLS
|
||||||
#cmakedefine HAVE_PIPE2
|
#cmakedefine HAVE_PIPE2
|
||||||
#cmakedefine HAVE_VFORK
|
#cmakedefine HAVE_VFORK
|
||||||
|
#cmakedefine HAVE_DLADDR
|
||||||
|
|
||||||
#define ICINGA_PREFIX "${CMAKE_INSTALL_PREFIX}"
|
#define ICINGA_PREFIX "${CMAKE_INSTALL_PREFIX}"
|
||||||
#define ICINGA_SYSCONFDIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}"
|
#define ICINGA_SYSCONFDIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}"
|
||||||
|
|
|
@ -20,6 +20,8 @@
|
||||||
#include "base/stacktrace.h"
|
#include "base/stacktrace.h"
|
||||||
#include "base/qstring.h"
|
#include "base/qstring.h"
|
||||||
#include "base/utility.h"
|
#include "base/utility.h"
|
||||||
|
#include "base/convert.h"
|
||||||
|
#include <boost/algorithm/string/trim.hpp>
|
||||||
|
|
||||||
#ifdef HAVE_BACKTRACE_SYMBOLS
|
#ifdef HAVE_BACKTRACE_SYMBOLS
|
||||||
# include <execinfo.h>
|
# include <execinfo.h>
|
||||||
|
@ -97,6 +99,39 @@ void StackTrace::Initialize(void)
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Looks up source file name and line number information for the specified
|
||||||
|
* ELF executable and RVA.
|
||||||
|
*
|
||||||
|
* @param exe The ELF file.
|
||||||
|
* @param rva The RVA.
|
||||||
|
* @returns Source file and line number.
|
||||||
|
*/
|
||||||
|
String StackTrace::Addr2Line(const String& exe, uintptr_t rva)
|
||||||
|
{
|
||||||
|
#ifndef _WIN32
|
||||||
|
std::ostringstream msgbuf;
|
||||||
|
msgbuf << "addr2line -s -e " << exe << " " << std::hex << rva;
|
||||||
|
|
||||||
|
String args = msgbuf.str();
|
||||||
|
|
||||||
|
FILE *fp = popen(args.CStr(), "r");
|
||||||
|
|
||||||
|
if (!fp)
|
||||||
|
return "RVA: " + Convert::ToString(rva);
|
||||||
|
|
||||||
|
char buffer[512];
|
||||||
|
fgets(buffer, sizeof(buffer), fp);
|
||||||
|
|
||||||
|
String line = buffer;
|
||||||
|
boost::algorithm::trim_right(line);
|
||||||
|
|
||||||
|
return line;
|
||||||
|
#else /* _WIN32 */
|
||||||
|
return String();
|
||||||
|
#endif /* _WIN32 */
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Prints a stacktrace to the specified stream.
|
* Prints a stacktrace to the specified stream.
|
||||||
*
|
*
|
||||||
|
@ -118,7 +153,7 @@ void StackTrace::Print(std::ostream& fp, int ignoreFrames) const
|
||||||
|
|
||||||
char *sym_begin = strchr(messages[i], '(');
|
char *sym_begin = strchr(messages[i], '(');
|
||||||
|
|
||||||
if (sym_begin != NULL) {
|
if (sym_begin) {
|
||||||
char *sym_end = strchr(sym_begin, '+');
|
char *sym_end = strchr(sym_begin, '+');
|
||||||
|
|
||||||
if (sym_end != NULL) {
|
if (sym_end != NULL) {
|
||||||
|
@ -128,7 +163,23 @@ void StackTrace::Print(std::ostream& fp, int ignoreFrames) const
|
||||||
if (sym_demangled.IsEmpty())
|
if (sym_demangled.IsEmpty())
|
||||||
sym_demangled = "<unknown function>";
|
sym_demangled = "<unknown function>";
|
||||||
|
|
||||||
message = String(messages[i], sym_begin) + ": " + sym_demangled + " (" + String(sym_end);
|
String path = String(messages[i], sym_begin);
|
||||||
|
|
||||||
|
size_t slashp = path.RFind("/");
|
||||||
|
|
||||||
|
if (slashp != String::NPos)
|
||||||
|
path = path.SubStr(slashp + 1);
|
||||||
|
|
||||||
|
message = path + ": " + sym_demangled + " (" + String(sym_end);
|
||||||
|
|
||||||
|
#ifdef HAVE_DLADDR
|
||||||
|
Dl_info dli;
|
||||||
|
|
||||||
|
if (dladdr(m_Frames[i], &dli) > 0) {
|
||||||
|
uintptr_t rva = reinterpret_cast<uintptr_t>(m_Frames[i]) - reinterpret_cast<uintptr_t>(dli.dli_fbase);
|
||||||
|
message += " (" + Addr2Line(dli.dli_fname, rva) + ")";
|
||||||
|
}
|
||||||
|
#endif /* HAVE_DLADDR */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#define STACKTRACE_H
|
#define STACKTRACE_H
|
||||||
|
|
||||||
#include "base/i2-base.h"
|
#include "base/i2-base.h"
|
||||||
|
#include "base/qstring.h"
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <boost/thread/once.hpp>
|
#include <boost/thread/once.hpp>
|
||||||
|
|
||||||
|
@ -49,6 +50,7 @@ private:
|
||||||
static boost::once_flag m_OnceFlag;
|
static boost::once_flag m_OnceFlag;
|
||||||
|
|
||||||
static void Initialize(void);
|
static void Initialize(void);
|
||||||
|
static String Addr2Line(const String& exe, uintptr_t rva);
|
||||||
};
|
};
|
||||||
|
|
||||||
I2_BASE_API std::ostream& operator<<(std::ostream& stream, const StackTrace& trace);
|
I2_BASE_API std::ostream& operator<<(std::ostream& stream, const StackTrace& trace);
|
||||||
|
|
Loading…
Reference in New Issue