Branch: master

71be0ee5 2014-03-28 18:54:47 Timothy Pearson
Extract and include any pertinent SCM metadata from the crashed application in its crash report
M CMakeLists.txt
M ConfigureChecks.cmake
M config.h.cmake
M drkonqi/CMakeLists.txt
M drkonqi/backtrace.cpp
M drkonqi/debuggers/gdbrc
M drkonqi/krashconf.cpp
M drkonqi/krashconf.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 40a7925..367a749 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -88,6 +88,7 @@
 option( WITH_HAL "Enable HAL support" OFF )
 option( WITH_TDEHWLIB "Enable TDE hardware library support" ${WITH_ALL_OPTIONS} )
 option( WITH_UPOWER "Enable UPOWER support" ${WITH_ALL_OPTIONS} )
+option( WITH_ELFICON "Enable ELF embedded metadata support" ${WITH_ALL_OPTIONS} )
 option( WITH_GCC_VISIBILITY "Enable fvisibility and fvisibility-inlines-hidden" ${WITH_ALL_OPTIONS} )
 
 ##### options comments ##########################
diff --git a/ConfigureChecks.cmake b/ConfigureChecks.cmake
index 87b8145..4fa14ed 100644
--- a/ConfigureChecks.cmake
+++ b/ConfigureChecks.cmake
@@ -311,3 +311,15 @@
   endif( )
 
 endif( )
+
+# check for libr
+if( WITH_ELFICON )
+  pkg_search_module( LIBR libr )
+  if( NOT LIBR_FOUND )
+      message(FATAL_ERROR "\nelficon support was requested, but libr was not found on your system" )
+  endif( NOT LIBR_FOUND )
+  if( NOT "${LIBR_VERSION}" STREQUAL "0.6.0" )
+      message(FATAL_ERROR "\nelficon support was requested, but the libr version on your system may not be compatible with TDE" )
+  endif( NOT "${LIBR_VERSION}" STREQUAL "0.6.0" )
+  set( HAVE_ELFICON 1 )
+endif( )
\ No newline at end of file
diff --git a/config.h.cmake b/config.h.cmake
index b6dbf19..503a76c 100644
--- a/config.h.cmake
+++ b/config.h.cmake
@@ -33,6 +33,9 @@
 // libart
 #cmakedefine HAVE_LIBART 1
 
+// libr
+#cmakedefine HAVE_ELFICON 1
+
 // tdm, tdeioslave
 #cmakedefine HAVE_TERMIOS_H 1
 
diff --git a/drkonqi/CMakeLists.txt b/drkonqi/CMakeLists.txt
index 502ba5e..47866c4 100644
--- a/drkonqi/CMakeLists.txt
+++ b/drkonqi/CMakeLists.txt
@@ -18,6 +18,7 @@
   ${CMAKE_BINARY_DIR}
   ${TDE_INCLUDE_DIR}
   ${TQT_INCLUDE_DIRS}
+  ${LIBR_INCLUDEDIR}
 )
 
 link_directories(
diff --git a/drkonqi/backtrace.cpp b/drkonqi/backtrace.cpp
index 61ae813..95bc0e0 100644
--- a/drkonqi/backtrace.cpp
+++ b/drkonqi/backtrace.cpp
@@ -25,6 +25,8 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *****************************************************************/
 
+#include "config.h"
+
 #include <tqfile.h>
 #include <tqregexp.h>
 
@@ -35,6 +37,16 @@
 #include <tdelocale.h>
 #include <tdetempfile.h>
 #include <tdehardwaredevices.h>
+
+#ifdef HAVE_ELFICON
+	// Elven things
+	extern "C" {
+		#include <libr.h>
+		#include <libr-icons.h>
+	}
+	#include <tqfileinfo.h>
+	#include <tdeio/tdelficon.h>
+#endif // HAVE_ELFICON
 
 #include "krashconf.h"
 #include "backtrace.h"
@@ -199,8 +211,16 @@
   TQString strBt = '\n' + m_strBt + '\n';
   // how many " ?? " in the bt ?
   int unknown = 0;
-  if( !m_krashconf->invalidStackFrameRegExp().isEmpty())
-    unknown = strBt.contains( TQRegExp( m_krashconf->invalidStackFrameRegExp()));
+  if( !m_krashconf->invalidStackFrameRegExp().isEmpty()) {
+    int isfPos = strBt.find( TQRegExp( m_krashconf->invalidStackFrameRegExp()));
+    int islPos = strBt.find( m_krashconf->infoSharedLibraryHeader());
+    if ((isfPos >=0) && (isfPos < islPos)) {
+      unknown = true;
+    }
+    else {
+      unknown = false;
+    }
+  }
   // how many stack frames in the bt ?
   int frames = 0;
   if( !m_krashconf->frameRegExp().isEmpty())
@@ -278,6 +298,64 @@
 		}
 	}
 
+#ifdef HAVE_ELFICON
+	m_strBt.append("\n==== (tdemetainfo) application version information ====\n");
+
+	// Extract embedded SCM metadata from the crashed application
+	TQString crashedExec = TDEStandardDirs::findExe(m_krashconf->execName());
+	if (crashedExec.startsWith("/")) {
+		libr_file *handle = NULL;
+		libr_access_t access = LIBR_READ;
+	
+		if((handle = libr_open(const_cast<char*>(crashedExec.ascii()), access)) == NULL) {
+			kdWarning() << "failed to open file" << crashedExec << endl;
+		}
+		else {
+			TQString scmModule = elf_get_resource(handle, ".metadata_scmmodule");
+			TQString scmRevision = elf_get_resource(handle, ".metadata_scmrevision");
+			if (scmRevision != "") {
+				m_strBt.append(TQString("%1:\t%2:%3\n").arg(TQFileInfo(crashedExec).fileName()).arg(scmModule).arg(scmRevision));
+			}
+		}
+
+		libr_close(handle);
+	}
+
+	m_strBt.append("\n==== (tdemetainfo) library version information ====\n");
+
+	// Extract embedded SCM metadata from shared libraries
+	int islPos = m_strBt.find( m_krashconf->infoSharedLibraryHeader());
+	TQString infoSharedLibraryText = m_strBt.mid(islPos);
+	TQTextStream infoSharedLibraryTextStream(&infoSharedLibraryText, IO_ReadOnly);
+	infoSharedLibraryTextStream.readLine();	// Skip info header x1
+	infoSharedLibraryTextStream.readLine();	// Skip info header x2
+	TQString infoSharedLibraryLine = infoSharedLibraryTextStream.readLine();
+	while (infoSharedLibraryLine != TQString::null) {
+		TQStringList libraryInfoList = TQStringList::split(" ", infoSharedLibraryLine, false);
+		if (libraryInfoList.count() > 0) {
+			TQString libraryName = libraryInfoList[libraryInfoList.count()-1];
+			if (libraryName.startsWith("/")) {
+				libr_file *handle = NULL;
+				libr_access_t access = LIBR_READ;
+			
+				if((handle = libr_open(const_cast<char*>(libraryName.ascii()), access)) == NULL) {
+					kdWarning() << "failed to open file" << libraryName << endl;
+				}
+				else {
+					TQString scmModule = elf_get_resource(handle, ".metadata_scmmodule");
+					TQString scmRevision = elf_get_resource(handle, ".metadata_scmrevision");
+					if (scmRevision != "") {
+						m_strBt.append(TQString("%1:\t%2:%3\n").arg(TQFileInfo(libraryName).fileName()).arg(scmModule).arg(scmRevision));
+					}
+				}
+
+				libr_close(handle);
+			}
+		}
+		infoSharedLibraryLine = infoSharedLibraryTextStream.readLine();
+	}
+#endif // HAVE_ELFICON
+
 	// Append potentially important hardware information
 	m_strBt.append("\n==== (tdehwlib) hardware information ====\n");
 	TDEHardwareDevices *hwdevices = TDEGlobal::hardwareDevices();
diff --git a/drkonqi/debuggers/gdbrc b/drkonqi/debuggers/gdbrc
index 1aa1f8c..28e804e 100644
--- a/drkonqi/debuggers/gdbrc
+++ b/drkonqi/debuggers/gdbrc
@@ -158,7 +158,7 @@
 Exec=konsole -e gdb -nw %execname %pid
 ExecBatch=gdb -nw -n -batch -x %tempfile %execname %pid
 TryExec=gdb
-BacktraceCommand=echo \\n\necho ==== (gdb) bt ====\\n\nbt\necho \\n\\n\necho ==== (gdb) bt full ====\\n\nbt full\necho\\n\\n\necho ==== (gdb) info thread ====\\n\ninfo thread\necho\\n\\n\necho ==== (gdb) thread apply all bt ====\\n\nthread apply all bt
+BacktraceCommand=echo \\n\necho ==== (gdb) bt ====\\n\nbt\necho \\n\\n\necho ==== (gdb) bt full ====\\n\nbt full\necho\\n\\n\necho ==== (gdb) info thread ====\\n\ninfo thread\necho\\n\\n\necho ==== (gdb) thread apply all bt ====\\n\nthread apply all bt\necho\\n\\n\necho ==== (gdb) info sharedlibrary ====\\n\ninfo sharedlibrary
 RemoveFromBacktraceRegExp=\(no debugging symbols found\)\.\.\.\\n?
 InvalidStackFrameRegExp=\\n#[0-9]+\\s+0x[0-9A-Fa-f]+ \w* \?\?
 FrameRegExp=\\n#[0-9]+\\s+0x[0-9A-Fa-f]+
@@ -166,3 +166,4 @@
 TDECrashRegExp=\\n#0[ ]*0x[0123456789abcdefABCDEF]+.*<signal handler called>[ ]*\\n
 TDECrashRegExpSingle=\\n0x[0123456789abcdefABCDEF][^\\n]*\\n
 ThreadRegExp=\\nThread [0123456789]
+InfoSharedLibraryHeader= ==== (gdb) info sharedlibrary ====
\ No newline at end of file
diff --git a/drkonqi/krashconf.cpp b/drkonqi/krashconf.cpp
index 84bbfee..12c8064 100644
--- a/drkonqi/krashconf.cpp
+++ b/drkonqi/krashconf.cpp
@@ -113,6 +113,7 @@
   m_kcrashRegExp = debuggers.readEntry("TDECrashRegExp");
   m_kcrashRegExpSingle = debuggers.readEntry("TDECrashRegExpSingle");
   m_threadRegExp = debuggers.readEntry("ThreadRegExp");
+  m_infoSharedLibraryHeader = debuggers.readEntry("InfoSharedLibraryHeader");
 
   TDEConfig preset(TQString::fromLatin1("presets/%1rc").arg(configname),
                  true, false, "appdata");
diff --git a/drkonqi/krashconf.h b/drkonqi/krashconf.h
index 074cfce..d3d27e1 100644
--- a/drkonqi/krashconf.h
+++ b/drkonqi/krashconf.h
@@ -68,6 +68,7 @@
   TQString kcrashRegExp() const { return m_kcrashRegExp; }
   TQString kcrashRegExpSingle() const { return m_kcrashRegExpSingle; }
   TQString threadRegExp() const { return m_threadRegExp; }
+  TQString infoSharedLibraryHeader() const { return m_infoSharedLibraryHeader; }
   bool showBacktrace() const { return m_showbacktrace; };
   bool showDebugger() const { return m_showdebugger && !m_debugger.isNull(); };
   bool showBugReport() const { return m_showbugreport; };
@@ -112,6 +113,7 @@
   TQString m_kcrashRegExp;
   TQString m_kcrashRegExpSingle;
   TQString m_threadRegExp;
+  TQString m_infoSharedLibraryHeader;
 };
 
 #endif