]> granicus.if.org Git - icinga2/commitdiff
Include source file name and line numbers in stack traces.
authorGunnar Beutner <gunnar.beutner@netways.de>
Thu, 6 Mar 2014 09:59:13 +0000 (10:59 +0100)
committerGunnar Beutner <gunnar.beutner@netways.de>
Thu, 6 Mar 2014 09:59:13 +0000 (10:59 +0100)
Fixes #5715

CMakeLists.txt
config.h.cmake
lib/base/stacktrace.cpp
lib/base/stacktrace.h

index 6b7b8c19da6b19e56af76a3dfc1fcf0a7a5a0b46..369700273d6eb8449e6f5991ed91331e4f79464c 100644 (file)
@@ -104,6 +104,7 @@ include(CheckLibraryExists)
 check_function_exists(vfork HAVE_VFORK)
 check_function_exists(backtrace_symbols HAVE_BACKTRACE_SYMBOLS)
 check_function_exists(pipe2 HAVE_PIPE2)
+check_function_exists(dladdr HAVE_DLADDR)
 check_library_exists(crypto BIO_f_zlib "" HAVE_BIOZLIB)
 
 include(GNUInstallDirs)
index cc80a2e04b6a8e8e352bcc47f53cb2fe89dfb4d2..68dec8472400b7034a5644b0c5916fcdb54e4814 100644 (file)
@@ -5,6 +5,7 @@
 #cmakedefine HAVE_BACKTRACE_SYMBOLS
 #cmakedefine HAVE_PIPE2
 #cmakedefine HAVE_VFORK
+#cmakedefine HAVE_DLADDR
 
 #define ICINGA_PREFIX "${CMAKE_INSTALL_PREFIX}"
 #define ICINGA_SYSCONFDIR "${CMAKE_INSTALL_FULL_SYSCONFDIR}"
index 4703a1b4392999b83d97fe603161f94db4f749be..624c1502c9bc0a37c454b1edc31bda83ca65a8c1 100644 (file)
@@ -20,6 +20,8 @@
 #include "base/stacktrace.h"
 #include "base/qstring.h"
 #include "base/utility.h"
+#include "base/convert.h"
+#include <boost/algorithm/string/trim.hpp>
 
 #ifdef HAVE_BACKTRACE_SYMBOLS
 #      include <execinfo.h>
@@ -97,6 +99,39 @@ void StackTrace::Initialize(void)
 #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.
  *
@@ -118,7 +153,7 @@ void StackTrace::Print(std::ostream& fp, int ignoreFrames) const
 
                char *sym_begin = strchr(messages[i], '(');
 
-               if (sym_begin != NULL) {
+               if (sym_begin) {
                        char *sym_end = strchr(sym_begin, '+');
 
                        if (sym_end != NULL) {
@@ -128,7 +163,23 @@ void StackTrace::Print(std::ostream& fp, int ignoreFrames) const
                                if (sym_demangled.IsEmpty())
                                        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 */
                        }
                }
 
index fcbdfb66fbc9dc4c61524ae53acb18c20c84f69a..e93825270d68483b1c3cd9a24c4a289a2e137151 100644 (file)
@@ -21,6 +21,7 @@
 #define STACKTRACE_H
 
 #include "base/i2-base.h"
+#include "base/qstring.h"
 #include <ostream>
 #include <boost/thread/once.hpp>
 
@@ -49,6 +50,7 @@ private:
        static boost::once_flag m_OnceFlag;
 
        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);