File r889778.diff of Package kdebase4-runtime
Subject: Dr Konqi fixes for more useful backtraces
From: wstephenson@suse.de
Bug:
Patch-upstream: 889778
--- drkonqi/backtracegdb.h (revision 0)
+++ drkonqi/backtracegdb.h (revision 889778)
@@ -0,0 +1,56 @@
+/*****************************************************************
+ * drkonqi - The KDE Crash Handler
+ *
+ * Copyright (C) 2000-2003 Hans Petter Bieker <bieker@kde.org>
+ * Copyright (C) 2008 Lubos Lunak <l.lunak@kde.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************/
+
+#ifndef BACKTRACEGDB_H
+#define BACKTRACEGDB_H
+
+#include "backtrace.h"
+
+class BackTraceGdb : public BackTrace
+{
+ Q_OBJECT
+
+public:
+ BackTraceGdb(const KrashConfig *krashconf, QObject *parent);
+ ~BackTraceGdb();
+
+protected:
+ virtual QString processDebuggerOutput( QString bt );
+ virtual bool usefulDebuggerOutput( QString bt );
+private:
+ void processBacktrace( int index );
+ bool usefulBacktrace( int index );
+ QStringList removeLines( QStringList list, const QRegExp& regexp );
+ QStringList removeFirstLine( QStringList list, const QRegExp& regexp );
+ bool prettyKcrashHandler( int index );
+ QStringList common; // the first part gdb output, before any backtraces
+ QList< QStringList > backtraces; // backtraces, more if there are more threads
+ int backtraceWithCrash; // index of the thread in which the crash happened
+};
+
+#endif
--- drkonqi/krashconf.cpp (revision 889777)
+++ drkonqi/krashconf.cpp (revision 889778)
@@ -101,15 +101,15 @@ void KrashConfig :: readConfig()
QString configname = config.readEntry("ConfigName",
QString("enduser"));
- QString debuggername = config.readEntry("Debugger",
+ m_debuggerName = config.readEntry("Debugger",
QString("gdb"));
- KConfig debuggers(QString::fromLatin1("debuggers/%1rc").arg(debuggername),
+ KConfig debuggers(QString::fromLatin1("debuggers/%1rc").arg(m_debuggerName),
KConfig::NoGlobals, "appdata" );
const KConfigGroup generalGroup = debuggers.group("General");
- m_debugger = generalGroup.readPathEntry("Exec", QString());
- m_debuggerBatch = generalGroup.readPathEntry("ExecBatch", QString());
+ m_debuggerCommand = generalGroup.readPathEntry("Exec", QString());
+ m_debuggerBatchCommand = generalGroup.readPathEntry("ExecBatch", QString());
m_tryExec = generalGroup.readPathEntry("TryExec", QString());
m_backtraceCommand = generalGroup.readEntry("BacktraceCommand");
m_removeFromBacktraceRegExp = generalGroup.readEntry("RemoveFromBacktraceRegExp");
--- drkonqi/backtrace.cpp (revision 889777)
+++ drkonqi/backtrace.cpp (revision 889778)
@@ -47,6 +47,7 @@ BackTrace::BackTrace(const KrashConfig *
m_krashconf(krashconf), m_temp(0)
{
m_proc = new KProcess;
+ m_proc->setEnv( "LC_ALL", "C" ); // force C locale
}
BackTrace::~BackTrace()
@@ -83,7 +84,7 @@ void BackTrace::start()
m_temp->flush();
// start the debugger
- QString str = m_krashconf->debuggerBatch();
+ QString str = m_krashconf->debuggerBatchCommand();
m_krashconf->expandString(str, KrashConfig::ExpansionUsageShell, m_temp->fileName());
*m_proc << KShell::splitArgs(str);
@@ -122,60 +123,14 @@ void BackTrace::slotProcessExited(int ex
// start it again
::kill(m_krashconf->pid(), SIGCONT);
- if (((exitStatus == QProcess::NormalExit) && (exitCode == 0)) &&
- usefulBacktrace())
+ if (exitStatus != QProcess::NormalExit || exitCode != 0)
{
- processBacktrace();
- emit done(m_strBt);
+ emit someError();
+ return;
}
+ m_strBt = processDebuggerOutput( m_strBt );
+ if( m_krashconf->disableChecks() || usefulDebuggerOutput( m_strBt ))
+ emit done(m_strBt);
else
emit someError();
}
-
-// analyze backtrace for usefulness
-bool BackTrace::usefulBacktrace()
-{
- // remove crap
- if( !m_krashconf->removeFromBacktraceRegExp().isEmpty())
- m_strBt.replace(QRegExp( m_krashconf->removeFromBacktraceRegExp()), QString());
-
- if( m_krashconf->disableChecks())
- return true;
- // prepend and append newline, so that regexps like '\nwhatever\n' work on all lines
- QString strBt = '\n' + m_strBt + '\n';
- // how many " ?? " in the bt ?
- int unknown = 0;
- if( !m_krashconf->invalidStackFrameRegExp().isEmpty())
- unknown = strBt.count( QRegExp( m_krashconf->invalidStackFrameRegExp()));
- // how many stack frames in the bt ?
- int frames = 0;
- if( !m_krashconf->frameRegExp().isEmpty())
- frames = strBt.count( QRegExp( m_krashconf->frameRegExp()));
- else
- frames = strBt.count('\n');
- bool tooShort = false;
- if( !m_krashconf->neededInValidBacktraceRegExp().isEmpty())
- tooShort = ( strBt.indexOf( QRegExp( m_krashconf->neededInValidBacktraceRegExp())) == -1 );
- return !m_strBt.isNull() && !tooShort && (unknown < frames);
-}
-
-// remove stack frames added because of KCrash
-void BackTrace::processBacktrace()
-{
- if( !m_krashconf->kcrashRegExp().isEmpty())
- {
- QRegExp kcrashregexp( m_krashconf->kcrashRegExp());
- int pos = kcrashregexp.indexIn( m_strBt );
- if( pos >= 0 )
- {
- int len = kcrashregexp.matchedLength();
- if( m_strBt[ pos ] == '\n' )
- {
- ++pos;
- --len;
- }
- m_strBt.remove( pos, len );
- m_strBt.insert( pos, QLatin1String( "[KCrash handler]\n" ));
- }
- }
-}
--- drkonqi/krashconf.h (revision 889777)
+++ drkonqi/krashconf.h (revision 889778)
@@ -57,8 +57,9 @@ public Q_SLOTS:
void registerDebuggingApplication(const QString& launchName);
public:
- QString debugger() const { return m_debugger; }
- QString debuggerBatch() const { return m_debuggerBatch; }
+ QString debuggerName() const { return m_debuggerName; }
+ QString debuggerCommand() const { return m_debuggerCommand; }
+ QString debuggerBatchCommand() const { return m_debuggerBatchCommand; }
QString tryExec() const { return m_tryExec; }
QString backtraceCommand() const { return m_backtraceCommand; }
QString removeFromBacktraceRegExp() const { return m_removeFromBacktraceRegExp; }
@@ -67,7 +68,7 @@ public:
QString neededInValidBacktraceRegExp() const { return m_neededInValidBacktraceRegExp; }
QString kcrashRegExp() const { return m_kcrashRegExp; }
bool showBacktrace() const { return m_showbacktrace; }
- bool showDebugger() const { return m_showdebugger && !m_debugger.isNull(); }
+ bool showDebugger() const { return m_showdebugger && !m_debuggerCommand.isNull(); }
bool showBugReport() const { return m_showbugreport; }
bool disableChecks() const { return m_disablechecks; }
const KAboutData *aboutData() const { return m_aboutData; }
@@ -105,8 +106,9 @@ private:
QString m_errorDescriptionText;
QString m_execname;
- QString m_debugger;
- QString m_debuggerBatch;
+ QString m_debuggerName;
+ QString m_debuggerCommand;
+ QString m_debuggerBatchCommand;
QString m_tryExec;
QString m_backtraceCommand;
QString m_removeFromBacktraceRegExp;
--- drkonqi/debugger.cpp (revision 889777)
+++ drkonqi/debugger.cpp (revision 889778)
@@ -43,7 +43,7 @@
#include <ktextbrowser.h>
#include <ktemporaryfile.h>
-#include "backtrace.h"
+#include "backtracegdb.h"
#include "krashconf.h"
#include "debugger.moc"
@@ -209,6 +209,16 @@ void KrashDebugger :: startDebugger()
m_status->setText( i18n( "Backtrace will not be created."));
return;
}
+
+ if(m_krashconf->debuggerName() == "gdb" )
+ m_proctrace = new BackTraceGdb(m_krashconf, this);
+ else
+ {
+ m_backtrace->setPlainText( i18n( "Unknown or no debugger found." ));
+ m_status->setText( i18n( "Backtrace will not be created."));
+ return;
+ }
+
if( !msg.isEmpty())
{
m_prependText += msg + '\n';
@@ -216,8 +226,6 @@ void KrashDebugger :: startDebugger()
}
m_status->setText(i18n("Loading symbols..."));
- m_proctrace = new BackTrace(m_krashconf, this);
-
connect(m_proctrace, SIGNAL(append(const QString &)),
SLOT(slotAppend(const QString &)));
connect(m_proctrace, SIGNAL(done(const QString&)), SLOT(slotDone(const QString&)));
--- drkonqi/backtrace.h (revision 889777)
+++ drkonqi/backtrace.h (revision 889778)
@@ -53,11 +53,13 @@ protected Q_SLOTS:
void slotProcessExited(int exitCode, QProcess::ExitStatus exitStatus);
void slotReadInput();
+protected:
+ virtual QString processDebuggerOutput( QString bt ) = 0;
+ virtual bool usefulDebuggerOutput( QString bt ) = 0;
+ const KrashConfig * const m_krashconf;
+
private:
- bool usefulBacktrace();
- void processBacktrace();
KProcess *m_proc;
- const KrashConfig *m_krashconf;
KTemporaryFile *m_temp;
QString m_strBt;
QByteArray m_output;
--- drkonqi/debuggers/gdbrc (revision 889777)
+++ drkonqi/debuggers/gdbrc (revision 889778)
@@ -123,11 +123,7 @@ Comment[xh]=Text based debugger evela kw
Comment[zh_CN]=在 Konsole 中调用文字界面的 GNU 调试器
Comment[zh_TW]=在 Konsole 的文字型除錯器
Exec=konsole -e gdb -nw %execname %pid
-ExecBatch=gdb -nw -n -batch -x %tempfile %execname %pid
+ExecBatch=gdb -nw -n -batch -x %tempfile -p %pid
+#ExecBatch=gdb -nw -n -batch -x %tempfile %execname %pid
TryExec=gdb
-BacktraceCommand=thread\nthread apply all bt
-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]+
-NeededInValidBacktraceRegExp=\\n#5
-KCrashRegExp=\\n0x[0123456789abcdefABCDEF]+.*<signal handler called>[ ]*\\n
+BacktraceCommand=set width 200\nthread\nthread apply all bt
--- drkonqi/toplevel.cpp (revision 889777)
+++ drkonqi/toplevel.cpp (revision 889778)
@@ -36,7 +36,7 @@
#include <kmessagebox.h>
#include <kapplication.h>
-#include "backtrace.h"
+#include "backtracegdb.h"
#include "drbugreport.h"
#include "debugger.h"
#include "krashconf.h"
@@ -181,7 +181,11 @@ void Toplevel :: slotUser1()
QApplication::setOverrideCursor ( Qt::WaitCursor );
// generate the backtrace
- BackTrace *backtrace = new BackTrace(m_krashconf, this);
+ BackTrace *backtrace;
+ if(m_krashconf->debuggerName() == "gdb" )
+ backtrace = new BackTraceGdb(m_krashconf, this);
+ else
+ return;
connect(backtrace, SIGNAL(someError()), SLOT(slotBacktraceSomeError()));
connect(backtrace, SIGNAL(done(const QString &)),
SLOT(slotBacktraceDone(const QString &)));
@@ -200,7 +204,7 @@ void Toplevel :: slotUser1()
void Toplevel :: slotUser2()
{
- QString str = m_krashconf->debugger();
+ QString str = m_krashconf->debuggerCommand();
m_krashconf->expandString(str, KrashConfig::ExpansionUsageShell);
KProcess proc;
--- drkonqi/backtracegdb.cpp (revision 0)
+++ drkonqi/backtracegdb.cpp (revision 889778)
@@ -0,0 +1,219 @@
+/*****************************************************************
+ * drkonqi - The KDE Crash Handler
+ *
+ * Copyright (C) 2000-2003 Hans Petter Bieker <bieker@kde.org>
+ * Copyright (C) 2008 Lubos Lunak <l.lunak@kde.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *****************************************************************/
+
+#include "backtracegdb.h"
+
+#include <QRegExp>
+
+#include <KProcess>
+#include <KDebug>
+#include <KStandardDirs>
+#include <KMessageBox>
+#include <KLocale>
+#include <ktemporaryfile.h>
+#include <KShell>
+
+#include <signal.h>
+
+#include "krashconf.h"
+#include "backtracegdb.moc"
+
+BackTraceGdb::BackTraceGdb(const KrashConfig *krashconf, QObject *parent)
+ : BackTrace(krashconf,parent)
+ , backtraceWithCrash( 0 )
+{
+}
+
+BackTraceGdb::~BackTraceGdb()
+{
+}
+
+QString BackTraceGdb::processDebuggerOutput( QString bt )
+{
+ QStringList lines = bt.split( '\n' );
+ // read the common part until backtraces are found (either line starting with
+ // something like 'Thread 1 (Thread 0xb5d3f8e0 (LWP 25088)):' or directly the first
+ // backtrace line like '#0 0xffffe430 in __kernel_vsyscall ()'
+ QRegExp threadheading( "Thread [0-9]+\\s+\\(Thread 0x[0-9a-f]+\\s+\\(LWP [0-9]+\\)\\):" );
+ QRegExp backtracestart( "#0 .*" );
+ while( !lines.isEmpty()
+ && !threadheading.exactMatch( lines.first()) && !backtracestart.exactMatch( lines.first()))
+ {
+ common.append( lines.takeFirst());
+ }
+ // current gdb seems to have a bug in 'thread apply all bt' in that the backtrace
+ // has the '#0 ...' frame again appended, so when the backtraces have thread headings,
+ // do not use '#0 ...' for detecting the start of a backtrace at all
+ bool hasthreadheadings = threadheading.exactMatch( lines.first());
+ // read backtraces per thread
+ while( !lines.isEmpty())
+ {
+ QStringList backtrace;
+ backtrace.append( lines.takeFirst());
+ while( !lines.isEmpty() && !threadheading.exactMatch( lines.first())
+ && (hasthreadheadings || !backtracestart.exactMatch( lines.first())))
+ {
+ backtrace.append( lines.takeFirst());
+ }
+ backtraces.append( backtrace );
+ }
+ // remove some not very useful lines like '(no debugging symbols)', etc.
+ common = removeLines( common, QRegExp( ".*\\(no debugging symbols found\\).*" ));
+ common = removeLines( common, QRegExp( "\\[Thread debugging using libthread_db enabled\\]" ));
+ common = removeLines( common, QRegExp( "\\[New Thread 0x[0-9a-f]+\\s+\\(LWP [0-9]+\\)\\]" ));
+ // remove the line that shows where the process is at the moment '0xffffe430 in __kernel_vsyscall ()',
+ // gdb prints that automatically, but it will be later visible again in the backtrace
+ common = removeFirstLine( common, QRegExp( "0x[0-9a-f]+\\s+in .*\\(\\)" ));
+ // it is obvious which thread is current when there is only one
+ if( backtraces.count() == 1 )
+ common = removeLines( common, QRegExp( "\\[Current thread is [0-9]+\\s+\\(process [0-9]+\\)\\]" ));
+ for( int i = 0;
+ i < backtraces.count();
+ ++i )
+ processBacktrace( i );
+
+ QString ret = common.join( "\n" );
+ foreach( const QStringList& bt, backtraces )
+ ret += '\n' + bt.join( "\n" );
+ ret += '\n';
+ return ret;
+}
+
+void BackTraceGdb::processBacktrace( int index )
+{
+ QStringList& bt = backtraces[ index ];
+ if( prettyKcrashHandler( index ))
+ backtraceWithCrash = index; // this is the important backtrace
+ // gdb workaround - (v6.8 at least) - 'thread apply all bt' writes
+ // the #0 stack frame again at the end
+ for( int i = bt.count() - 1;
+ i >= 0;
+ --i )
+ {
+ if( bt[ i ].isEmpty())
+ continue;
+ QRegExp fakebacktracestart( "#0 .*" );
+ if( fakebacktracestart.exactMatch( bt[ i ] ))
+ bt.removeAt( i );
+ break;
+ }
+}
+
+bool BackTraceGdb::usefulDebuggerOutput( QString /*bt - use already done parsing*/ )
+{
+ if( common.isEmpty() || backtraces.isEmpty())
+ return false;
+ if( !usefulBacktrace( backtraceWithCrash ))
+ return false;
+ // ignore other backtraces from other threads as hopefully irrelevant
+ return true;
+}
+
+bool BackTraceGdb::usefulBacktrace( int index )
+{
+ QStringList& bt = backtraces[ index ];
+ QRegExp backtracestart( "#[0-9]+ .*" ); // not #0, probably replaces by [KCrash...]
+ int start = bt.indexOf( backtracestart );
+ if( start < 0 )
+ return false;
+ int end = bt.count() - 1;
+ while( end >= 0 && bt[ end ].isEmpty())
+ --end;
+ int frames = end - start + 1;
+ // topmost items must mean something, otherwise the backtrace is not very usable,
+ // which means ok is:
+ // - no ?? at all in first 3 items (or all of them, if there are less than 3 frames)
+ QRegExp unknown( "#[0-9]+\\s+0x[0-9a-f]+\\s+in\\s+\\?\\?\\s+.*" );
+ bool ok = false;
+ if( frames >= 3 && !unknown.exactMatch( bt[ start ] ) && !unknown.exactMatch( bt[ start + 1 ] )
+ && !unknown.exactMatch( bt[ start + 2 ] ))
+ {
+ ok = true;
+ }
+ // - only one frame, must be valid
+ if( frames == 1 && !unknown.exactMatch( bt[ start ] ))
+ ok = true;
+ // - only two frames, must be both valid
+ if( frames == 2 && !unknown.exactMatch( bt[ start ] ) && !unknown.exactMatch( bt[ start + 1 ] ))
+ ok = true;
+ // - 1st item is ?? but 4 following ones are okay (can be e.g. with a jump to NULL function pointer)
+ if( frames >= 5 && unknown.exactMatch( bt[ start ] ) && !unknown.exactMatch( bt[ start + 1 ] )
+ && !unknown.exactMatch( bt[ start + 2 ] ) && !unknown.exactMatch( bt[ start + 3 ]))
+ {
+ ok = true;
+ }
+ if( !ok )
+ return false;
+ return true;
+}
+
+QStringList BackTraceGdb::removeLines( QStringList list, const QRegExp& regexp )
+{
+ for( QStringList::Iterator it = list.begin();
+ it != list.end();
+ )
+ {
+ if( regexp.exactMatch( *it ))
+ it = list.erase( it );
+ else
+ ++it;
+ }
+ return list;
+}
+
+QStringList BackTraceGdb::removeFirstLine( QStringList list, const QRegExp& regexp )
+{
+ for( int i = 0;
+ i < list.count();
+ ++i )
+ {
+ if( regexp.exactMatch( list[ i ] ))
+ {
+ list.removeAt( i );
+ break;
+ }
+ }
+ return list;
+}
+
+// replace the stack frames from KCrash with '[KCrash handler]'
+bool BackTraceGdb::prettyKcrashHandler( int index )
+{
+ QStringList& bt = backtraces[ index ];
+ QRegExp backtracestart( "#[0-9]+ .*" );
+ QRegExp sighandler( "#[0-9]+\\s+<signal handler called>.*" );
+ int start = bt.indexOf( backtracestart );
+ int sigpos = bt.indexOf( sighandler );
+ if( sigpos >= 0 && start >= 0 )
+ {
+ bt.erase( bt.begin() + start, bt.begin() + sigpos + 1 );
+ bt.insert( start, "[KCrash Handler]" );
+ return true;
+ }
+ return false;
+}
--- drkonqi/CMakeLists.txt (revision 889777)
+++ drkonqi/CMakeLists.txt (revision 889778)
@@ -10,6 +10,7 @@ set(drkonqi_SRCS
krashadaptor.cpp
drbugreport.cpp
backtrace.cpp
+ backtracegdb.cpp
toplevel.cpp )
kde4_add_executable(drkonqi ${drkonqi_SRCS})
Index: drkonqi/backtracegdb.h
===================================================================
Property changes on: drkonqi/backtracegdb.h
___________________________________________________________________
Added: svn:mime-type
+ text/x-chdr
Added: svn:keywords
+ Author Date Id Revision
Added: svn:mergeinfo
Added: svn:eol-style
+ native
Index: drkonqi/krashconf.cpp
===================================================================
Index: drkonqi/backtrace.cpp
===================================================================
Index: drkonqi/krashconf.h
===================================================================
Index: drkonqi/debugger.cpp
===================================================================
Index: drkonqi/backtrace.h
===================================================================
Index: drkonqi/debuggers/gdbrc
===================================================================
Index: drkonqi/toplevel.cpp
===================================================================
Index: drkonqi/backtracegdb.cpp
===================================================================
Property changes on: drkonqi/backtracegdb.cpp
___________________________________________________________________
Added: svn:mime-type
+ text/x-c++src
Added: svn:keywords
+ Author Date Id Revision
Added: svn:mergeinfo
Added: svn:eol-style
+ native
Index: drkonqi/CMakeLists.txt
===================================================================