From d5aa8f9089f246d21d3f53a941300682b6cf6565 Mon Sep 17 00:00:00 2001 From: Ernie Pasveer Date: Sat, 15 Apr 2023 12:36:28 -0500 Subject: [PATCH] rr: first attempt at adding RR support to Seer. --- notes/README.gdbserver | 21 ++++ src/SeerDebugDialog.cpp | 58 ++++++++++- src/SeerDebugDialog.h | 5 + src/SeerDebugDialog.ui | 219 ++++++++++++++++++++++++++++------------ src/SeerGdbWidget.cpp | 112 ++++++++++++++++---- src/SeerGdbWidget.h | 11 +- src/SeerMainWindow.cpp | 65 ++++++++++-- src/SeerMainWindow.h | 6 +- src/seergdb.cpp | 19 +++- 9 files changed, 417 insertions(+), 99 deletions(-) diff --git a/notes/README.gdbserver b/notes/README.gdbserver index 0cbfdb7..80ca8d0 100644 --- a/notes/README.gdbserver +++ b/notes/README.gdbserver @@ -21,3 +21,24 @@ Notes: o Execuable name is useless. o Symbol name is optional. +Notes (2); + + This will automatically stop in _start. Setting a breakpoint in 'main' from the gdb entry field + will not refresh the breakpoint list. However, this message is sent. So maybe it can be refreshed. + + =breakpoint-created,bkpt={ + number="1", + type="breakpoint", + disp="keep", + enabled="y", + addr="0x0000000000400c12", + func="main(int, char**)", + file="hellosegv.cpp", + fullname="/nas/erniep/Development/seer/tests/hellosegv/hellosegv.cpp", + line="7", + thread-groups=["i1"], + times="0", + original-location="main" + } + ^done + diff --git a/src/SeerDebugDialog.cpp b/src/SeerDebugDialog.cpp index 1d4ecff..173d03e 100644 --- a/src/SeerDebugDialog.cpp +++ b/src/SeerDebugDialog.cpp @@ -34,6 +34,7 @@ SeerDebugDialog::SeerDebugDialog (QWidget* parent) : QDialog(parent) { setNonStopMode(false); setAttachPid(0); setConnectHostPort(""); + setRRHostPort(""); setCoreFilename(""); setProjectFilename(""); @@ -72,6 +73,7 @@ SeerDebugDialog::SeerDebugDialog (QWidget* parent) : QDialog(parent) { QObject::connect(helpRunToolButton, &QToolButton::clicked, this, &SeerDebugDialog::handleHelpRunToolButtonClicked); QObject::connect(helpAttachToolButton, &QToolButton::clicked, this, &SeerDebugDialog::handleHelpAttachToolButtonClicked); QObject::connect(helpConnectToolButton, &QToolButton::clicked, this, &SeerDebugDialog::handleHelpConnectToolButtonClicked); + QObject::connect(helpRRToolButton, &QToolButton::clicked, this, &SeerDebugDialog::handleHelpRRToolButtonClicked); QObject::connect(helpCorefileToolButton, &QToolButton::clicked, this, &SeerDebugDialog::handleHelpCorefileToolButtonClicked); #if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)) @@ -251,6 +253,14 @@ QString SeerDebugDialog::connectHostPort () const { return connectProgramHostPortLineEdit->text(); } +void SeerDebugDialog::setRRHostPort (const QString& rrHostPort) { + rrHostPortLineEdit->setText(rrHostPort); +} + +QString SeerDebugDialog::rrHostPort () const { + return rrHostPortLineEdit->text(); +} + void SeerDebugDialog::setLaunchMode (const QString& mode) { if (mode == "start") { @@ -273,10 +283,14 @@ void SeerDebugDialog::setLaunchMode (const QString& mode) { runModeTabWidget->setCurrentIndex(2); - }else if (mode == "corefile") { + }else if (mode == "rr") { runModeTabWidget->setCurrentIndex(3); + }else if (mode == "corefile") { + + runModeTabWidget->setCurrentIndex(4); + }else if (mode == "") { runModeTabWidget->setCurrentIndex(0); @@ -313,6 +327,10 @@ QString SeerDebugDialog::launchMode () const { }else if (runModeTabWidget->currentIndex() == 3) { + return "rr"; + + }else if (runModeTabWidget->currentIndex() == 4) { + return "corefile"; } @@ -438,6 +456,7 @@ void SeerDebugDialog::loadProject (const QString& filename, bool notify) { QJsonObject startModeJson; QJsonObject attachModeJson; QJsonObject connectModeJson; + QJsonObject rrModeJson; QJsonObject corefileModeJson; QJsonArray preConnectCommands; QJsonArray postConnectCommands; @@ -453,6 +472,7 @@ void SeerDebugDialog::loadProject (const QString& filename, bool notify) { startModeJson = seerProjectJson.value("startmode").toObject(); attachModeJson = seerProjectJson.value("attachmode").toObject(); connectModeJson = seerProjectJson.value("connectmode").toObject(); + rrModeJson = seerProjectJson.value("rrmode").toObject(); corefileModeJson = seerProjectJson.value("corefilemode").toObject(); preConnectCommands = seerProjectJson.value("pregdbcommands").toArray(); postConnectCommands = seerProjectJson.value("postgdbcommands").toArray(); @@ -554,6 +574,14 @@ void SeerDebugDialog::loadProject (const QString& filename, bool notify) { setLaunchMode("connect"); } + // Load RR project. + if (rrModeJson.isEmpty() == false) { + + connectProgramHostPortLineEdit->setText(rrModeJson["rrserver"].toString()); + + setLaunchMode("rr"); + } + // Load COREFILE project. if (corefileModeJson.isEmpty() == false) { @@ -657,6 +685,16 @@ void SeerDebugDialog::handleSaveProjectToolButton () { seerProjectJson["connectmode"] = modeJson; } + // Save RR project. + if (launchMode() == "rr") { + + QJsonObject modeJson; + + modeJson["rrserver"] = rrHostPortLineEdit->text(); + + seerProjectJson["rrmode"] = modeJson; + } + // Save COREFILE project. if (launchMode() == "corefile") { @@ -734,8 +772,16 @@ void SeerDebugDialog::handleRunModeChanged (int id) { postCommandsPlainTextEdit->setPlaceholderText("gdb commands after \"connect\""); } - // ID == 3 COREFILE + // ID == 3 RR if (id == 3) { + executableSymbolNameLineEdit->setEnabled(true); + executableSymbolNameToolButton->setEnabled(true); + preCommandsPlainTextEdit->setPlaceholderText("gdb commands before \"connect\""); + postCommandsPlainTextEdit->setPlaceholderText("gdb commands after \"connect\""); + } + + // ID == 4 COREFILE + if (id == 4) { executableNameLineEdit->setEnabled(true); executableNameToolButton->setEnabled(true); executableSymbolNameLineEdit->setEnabled(true); @@ -777,6 +823,14 @@ void SeerDebugDialog::handleHelpConnectToolButtonClicked () { help->raise(); } +void SeerDebugDialog::handleHelpRRToolButtonClicked () { + + SeerHelpPageDialog* help = new SeerHelpPageDialog(this); + help->loadFile(":/seer/resources/help/RRDebugMode.md"); + help->show(); + help->raise(); +} + void SeerDebugDialog::handleHelpCorefileToolButtonClicked () { SeerHelpPageDialog* help = new SeerHelpPageDialog(this); diff --git a/src/SeerDebugDialog.h b/src/SeerDebugDialog.h index 6494bc6..01ef27b 100644 --- a/src/SeerDebugDialog.h +++ b/src/SeerDebugDialog.h @@ -53,6 +53,10 @@ class SeerDebugDialog : public QDialog, protected Ui::SeerDebugDialogForm { void setConnectHostPort (const QString& connectHostPort); QString connectHostPort () const; + // Connectect to a RR server. "rr". + void setRRHostPort (const QString& rrHostPort); + QString rrHostPort () const; + // Load a core file. "corefile". void setCoreFilename (const QString& coreFilename); QString coreFilename () const; @@ -83,6 +87,7 @@ class SeerDebugDialog : public QDialog, protected Ui::SeerDebugDialogForm { void handleHelpRunToolButtonClicked (); void handleHelpAttachToolButtonClicked (); void handleHelpConnectToolButtonClicked (); + void handleHelpRRToolButtonClicked (); void handleHelpCorefileToolButtonClicked (); protected: diff --git a/src/SeerDebugDialog.ui b/src/SeerDebugDialog.ui index 11f3dbf..712f0fe 100644 --- a/src/SeerDebugDialog.ui +++ b/src/SeerDebugDialog.ui @@ -6,15 +6,61 @@ 0 0 - 588 - 801 + 806 + 1040 Select Executable to Debug - - + + + + + + + + Working Directory + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop + + + + + + + + The working directory path to tell GDB. Default current directory. + + + The working directory path to tell GDB. Default current directory. + + + true + + + + + + + Open a dialog to select a path. + + + + + + + :/seer/resources/RelaxLightIcons/document-open.svg:/seer/resources/RelaxLightIcons/document-open.svg + + + + + + + + + Executable Name @@ -72,7 +118,17 @@ - + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + Symbol File Name @@ -130,53 +186,7 @@ - - - - - - - Working Directory - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop - - - - - - - - The working directory path to tell GDB. Default current directory. - - - The working directory path to tell GDB. Default current directory. - - - true - - - - - - - Open a dialog to select a path. - - - - - - - :/seer/resources/RelaxLightIcons/document-open.svg:/seer/resources/RelaxLightIcons/document-open.svg - - - - - - - - - + @@ -628,6 +638,101 @@ + + + RR + + + + + + + + + + Connect to a RR replay server. + + + + + + + Qt::Horizontal + + + + 248 + 20 + + + + + + + + Help for Connect launch method. + + + ... + + + + :/seer/resources/RelaxLightIcons/help-about.svg:/seer/resources/RelaxLightIcons/help-about.svg + + + + + + + + + + + RR replay server + + + + + + + + 100 + 0 + + + + How to access the remote gdbserver. + + + + + + host:port + + + true + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Corefile @@ -758,16 +863,6 @@ - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - executableNameGroupBox buttonBox diff --git a/src/SeerGdbWidget.cpp b/src/SeerGdbWidget.cpp index 4f5b4a2..72c18cc 100644 --- a/src/SeerGdbWidget.cpp +++ b/src/SeerGdbWidget.cpp @@ -36,7 +36,8 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) { _executableWorkingDirectory = ""; _executableBreakpointsFilename = ""; _executableBreakpointFunctionName = ""; - _executableHostPort = ""; + _executableConnectHostPort = ""; + _executableRRHostPort = ""; _executableCoreFilename = ""; _executablePid = 0; @@ -424,12 +425,20 @@ int SeerGdbWidget::executablePid () const { return _executablePid; } -void SeerGdbWidget::setExecutableHostPort (const QString& hostPort) { - _executableHostPort = hostPort; +void SeerGdbWidget::setExecutableConnectHostPort (const QString& connectHostPort) { + _executableConnectHostPort = connectHostPort; } -const QString& SeerGdbWidget::executableHostPort () const { - return _executableHostPort; +const QString& SeerGdbWidget::executableConnectHostPort () const { + return _executableConnectHostPort; +} + +void SeerGdbWidget::setExecutableRRHostPort (const QString& rrHostPort) { + _executableRRHostPort = rrHostPort; +} + +const QString& SeerGdbWidget::executableRRHostPort () const { + return _executableRRHostPort; } void SeerGdbWidget::setExecutableCoreFilename (const QString& coreFilename) { @@ -1024,20 +1033,12 @@ void SeerGdbWidget::handleGdbConnectExecutable () { deleteConsole(); } - //qDebug() << "Starting GdbConnect."; - // If gdb isn't running, start it. if (isGdbRuning() == false) { - emit changeWindowTitle(QString("%1 (pid=%2)").arg(executableHostPort()).arg(QGuiApplication::applicationPid())); + emit changeWindowTitle(QString("%1 (pid=%2)").arg(executableConnectHostPort()).arg(QGuiApplication::applicationPid())); startGdb(); - - /* Do not use for 'connect' mode. Possible too quick for a gdbserver/vdbg. - if (gdbAsyncMode()) { - handleGdbCommand("-gdb-set mi-async on"); // Turn on async mode so the 'interrupt' can happen. - } - */ } // Set dprint parameters. @@ -1048,7 +1049,7 @@ void SeerGdbWidget::handleGdbConnectExecutable () { setExecutablePid(0); // Connect to the remote gdbserver. - handleGdbCommand(QString("-target-select extended-remote %1").arg(executableHostPort())); + handleGdbCommand(QString("-target-select extended-remote %1").arg(executableConnectHostPort())); // Load ithe executable, if needed. if (newExecutableFlag() == true) { @@ -1079,12 +1080,75 @@ void SeerGdbWidget::handleGdbConnectExecutable () { handleGdbExecutablePostCommands(); QApplication::restoreOverrideCursor(); +} - //qDebug() << "Finishing GdbConnect."; +void SeerGdbWidget::handleGdbRRExecutable () { - // "-file-symbol-file %s" - // "-file-exec-file %s" - // "-target-download" + // Has a executable name been provided? + if (executableName() != "") { + + QMessageBox::warning(this, "Seer", + QString("The executable name can't be provided for 'rr' mode."), + QMessageBox::Ok); + return; + } + + QApplication::setOverrideCursor(Qt::BusyCursor); + + // Delete the old gdb and console if there is a new executable + if (newExecutableFlag() == true) { + killGdb(); + disconnectConsole(); + deleteConsole(); + } + + // If gdb isn't running, start it. + if (isGdbRuning() == false) { + + emit changeWindowTitle(QString("%1 (pid=%2)").arg(executableRRHostPort()).arg(QGuiApplication::applicationPid())); + + startGdb(); + } + + // Set dprint parameters. + resetDprintf(); + + // No console for 'connect' mode. + setExecutableLaunchMode("rr"); + setExecutablePid(0); + + // Connect to the remote gdbserver. + handleGdbCommand(QString("-target-select extended-remote %1").arg(executableRRHostPort())); + + // Load ithe executable, if needed. + if (newExecutableFlag() == true) { + handleGdbExecutablePreCommands(); // Run any 'pre' commands before program is loaded. + handleGdbExecutableName(); // Load the program into the gdb process. + handleGdbExecutableSources(); // Load the program source files. + handleGdbExecutableLoadBreakpoints(); // Set the program's breakpoints (if any) before running. + + setNewExecutableFlag(false); + } + + // Set or reset some things. + handleGdbExecutableWorkingDirectory(); // Set the program's working directory before running. + handleGdbAssemblyDisassemblyFlavor(); // Set the disassembly flavor to use. + handleGdbAssemblySymbolDemangling(); // Set the symbol demangling. + + if (assemblyShowAssemblyTabOnStartup()) { + editorManager()->showAssembly(); + } + + if (gdbHandleTerminatingException()) { + handleGdbCommand("-gdb-set unwind-on-terminating-exception on"); // Turn on terminating exceptions when gdb calls the program's functions. + }else{ + handleGdbCommand("-gdb-set unwind-on-terminating-exception off"); + } + + // Run any 'post' commands after program is loaded. + handleGdbExecutablePostCommands(); + + QApplication::restoreOverrideCursor(); } void SeerGdbWidget::handleGdbCoreFileExecutable () { @@ -1263,6 +1327,11 @@ void SeerGdbWidget::handleGdbRecordStart () { return; } + if (executableLaunchMode() == "rr") { + QMessageBox::warning(this, "Seer", QString("Record 'Start' not available in RR mode."), QMessageBox::Ok); + return; + } + setGdbRecordMode("full"); setGdbRecordDirection(""); } @@ -1273,6 +1342,11 @@ void SeerGdbWidget::handleGdbRecordStop () { return; } + if (executableLaunchMode() == "rr") { + QMessageBox::warning(this, "Seer", QString("Record 'Stop' not available in RR mode."), QMessageBox::Ok); + return; + } + setGdbRecordMode("stop"); setGdbRecordDirection(""); } diff --git a/src/SeerGdbWidget.h b/src/SeerGdbWidget.h index 91342d3..f9e607c 100644 --- a/src/SeerGdbWidget.h +++ b/src/SeerGdbWidget.h @@ -50,8 +50,11 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { void setExecutablePid (int pid); int executablePid () const; - void setExecutableHostPort (const QString& hostPort); - const QString& executableHostPort () const; + void setExecutableConnectHostPort (const QString& connectHostPort); + const QString& executableConnectHostPort () const; + + void setExecutableRRHostPort (const QString& rrHostPort); + const QString& executableRRHostPort () const; void setExecutableCoreFilename (const QString& coreFilename); const QString& executableCoreFilename () const; @@ -190,6 +193,7 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { void handleGdbRunExecutable (const QString& breakMode); void handleGdbAttachExecutable (); void handleGdbConnectExecutable (); + void handleGdbRRExecutable (); void handleGdbCoreFileExecutable (); void handleGdbShutdown (); void handleGdbRunToLine (QString fullname, int lineno); @@ -356,7 +360,8 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { QString _executableBreakpointsFilename; QString _executableBreakpointFunctionName; int _executablePid; - QString _executableHostPort; + QString _executableConnectHostPort; + QString _executableRRHostPort; QString _executableCoreFilename; QString _executableLaunchMode; QString _executableBreakMode; diff --git a/src/SeerMainWindow.cpp b/src/SeerMainWindow.cpp index 39e3ae9..2f66578 100644 --- a/src/SeerMainWindow.cpp +++ b/src/SeerMainWindow.cpp @@ -315,12 +315,20 @@ int SeerMainWindow::executablePid () const { return gdbWidget->executablePid(); } -void SeerMainWindow::setExecutableHostPort (const QString& executableHostPort) { - gdbWidget->setExecutableHostPort(executableHostPort); +void SeerMainWindow::setExecutableConnectHostPort (const QString& executableConnectHostPort) { + gdbWidget->setExecutableConnectHostPort(executableConnectHostPort); } -const QString& SeerMainWindow::executableHostPort () const { - return gdbWidget->executableHostPort(); +const QString& SeerMainWindow::executableConnectHostPort () const { + return gdbWidget->executableConnectHostPort(); +} + +void SeerMainWindow::setExecutableRRHostPort (const QString& executableRRHostPort) { + gdbWidget->setExecutableRRHostPort(executableRRHostPort); +} + +const QString& SeerMainWindow::executableRRHostPort () const { + return gdbWidget->executableRRHostPort(); } void SeerMainWindow::setExecutableCoreFilename (const QString& executableCoreFilename) { @@ -388,6 +396,13 @@ void SeerMainWindow::launchExecutable (const QString& launchMode, const QString& gdbWidget->handleGdbConnectExecutable(); + }else if (launchMode == "rr") { + + actionGdbRun->setVisible(false); + actionGdbStart->setVisible(false); + + gdbWidget->handleGdbRRExecutable(); + }else if (launchMode == "corefile") { actionGdbRun->setVisible(false); @@ -443,7 +458,8 @@ void SeerMainWindow::handleFileDebug () { dlg.setRandomizeStartAddress(executableRandomizeStartAddress()); dlg.setNonStopMode(executableNonStopMode()); dlg.setAttachPid(executablePid()); - dlg.setConnectHostPort(executableHostPort()); + dlg.setConnectHostPort(executableConnectHostPort()); + dlg.setRRHostPort(executableRRHostPort()); dlg.setCoreFilename(executableCoreFilename()); dlg.setLaunchMode(executableLaunchMode()); dlg.setBreakpointMode(executableBreakMode()); @@ -476,7 +492,8 @@ void SeerMainWindow::handleFileDebug () { setExecutableRandomizeStartAddress(dlg.randomizeStartAddress()); setExecutableNonStopMode(dlg.nonStopMode()); setExecutablePid(dlg.attachPid()); - setExecutableHostPort(dlg.connectHostPort()); + setExecutableConnectHostPort(dlg.connectHostPort()); + setExecutableRRHostPort(dlg.rrHostPort()); setExecutableCoreFilename(dlg.coreFilename()); setExecutablePreGdbCommands(dlg.preGdbCommands()); setExecutablePostGdbCommands(dlg.postGdbCommands()); @@ -990,7 +1007,7 @@ void SeerMainWindow::handleRunStatusChanged (SeerRunStatusIndicator::RunStatus s void SeerMainWindow::handleRecordSettingsChanged () { - if (gdbWidget->gdbRecordMode() == "stop") { + if (gdbWidget->gdbRecordMode() == "stop" || gdbWidget->gdbRecordMode() == "") { // Menu Control actionControlRecordStart->setEnabled(true); @@ -1002,6 +1019,7 @@ void SeerMainWindow::handleRecordSettingsChanged () { // Toolbar actionRecordProcess->setText("Record"); + actionRecordProcess->setEnabled(true); actionRecordDirection->setEnabled(false); actionRecordDirection->setIcon(QIcon(":/seer/resources/RelaxLightIcons/go-next.svg")); @@ -1034,6 +1052,39 @@ void SeerMainWindow::handleRecordSettingsChanged () { // Toolbar actionRecordProcess->setText("Recording"); + actionRecordProcess->setEnabled(true); + actionRecordDirection->setEnabled(true); + + }else if (gdbWidget->gdbRecordMode() == "rr") { + + // Menu Control + actionControlRecordStart->setEnabled(false); + actionControlRecordStop->setEnabled(false); + actionControlRecordForward->setEnabled(true); + actionControlRecordReverse->setEnabled(true); + + if (gdbWidget->gdbRecordDirection() == "") { + + actionControlRecordForward->setChecked(true); + actionRecordDirection->setIcon(QIcon(":/seer/resources/RelaxLightIcons/go-next.svg")); + + }else if (gdbWidget->gdbRecordDirection() == "--reverse") { + + actionControlRecordReverse->setChecked(true); + actionRecordDirection->setIcon(QIcon(":/seer/resources/RelaxLightIcons/go-previous.svg")); + + }else{ + + actionControlRecordForward->setChecked(false); + actionControlRecordReverse->setChecked(false); + actionRecordDirection->setIcon(QIcon(":/seer/resources/RelaxLightIcons/go-next.svg")); + + qDebug() << "Bad record direction of '" << gdbWidget->gdbRecordDirection() << "'"; + } + + // Toolbar + actionRecordProcess->setText("RR"); + actionRecordProcess->setEnabled(false); actionRecordDirection->setEnabled(true); }else{ diff --git a/src/SeerMainWindow.h b/src/SeerMainWindow.h index d2e59f5..63f2f0e 100644 --- a/src/SeerMainWindow.h +++ b/src/SeerMainWindow.h @@ -41,8 +41,10 @@ class SeerMainWindow : public QMainWindow, protected Ui::SeerMainWindowForm { bool executableNonStopMode () const; void setExecutablePid (int pid); int executablePid () const; - void setExecutableHostPort (const QString& executableHostPort); - const QString& executableHostPort () const; + void setExecutableConnectHostPort (const QString& executableConnectHostPort); + const QString& executableConnectHostPort () const; + void setExecutableRRHostPort (const QString& executableRRHostPort); + const QString& executableRRHostPort () const; void setExecutableCoreFilename (const QString& executableCoreFilename); const QString& executableCoreFilename () const; void setExecutablePreGdbCommands (const QStringList& preGdbCommands); diff --git a/src/seergdb.cpp b/src/seergdb.cpp index 818b13d..8ea8274 100644 --- a/src/seergdb.cpp +++ b/src/seergdb.cpp @@ -27,7 +27,7 @@ int main (int argc, char* argv[]) { QCoreApplication::setApplicationName("seergdb"); QCoreApplication::setOrganizationName("seergdb"); - QCoreApplication::setApplicationVersion(Seer::version() + " - Ernie Pasveer (c)2021"); + QCoreApplication::setApplicationVersion(Seer::version() + " - Ernie Pasveer (c)2021 - 2023"); // // Parse arguments. @@ -70,6 +70,9 @@ int main (int argc, char* argv[]) { QCommandLineOption connectOption(QStringList()<<"connect", QCoreApplication::translate("main", "Connect to a running process with gdbserver (local or remote). Manually start gdbserver first.\nPossible connection mediums are:\n host:port\n /dev/"), "medium"); parser.addOption(connectOption); + QCommandLineOption rrOption(QStringList()<<"rr", QCoreApplication::translate("main", "Connect to a running 'rr replay -s -k' session."), "port"); + parser.addOption(rrOption); + QCommandLineOption corefileOption(QStringList()<<"core", QCoreApplication::translate("main", "Load a corefile."), "corefile"); parser.addOption(corefileOption); @@ -113,7 +116,8 @@ int main (int argc, char* argv[]) { QString launchMode = "none"; QString breakMode = "none"; int executablePid = -1; - QString executableHostPort; + QString executableConnectHostPort; + QString executableRRHostPort; QString executableSymbolFilename; QString executableBreakpointsFilename; QString executableBreakpointFunctionName; @@ -169,7 +173,13 @@ int main (int argc, char* argv[]) { if (parser.isSet(connectOption)) { launchMode = "connect"; - executableHostPort = parser.value(connectOption); + executableConnectHostPort = parser.value(connectOption); + } + + if (parser.isSet(rrOption)) { + launchMode = "rr"; + + executableRRHostPort = parser.value(rrOption); } if (parser.isSet(corefileOption)) { @@ -247,7 +257,8 @@ int main (int argc, char* argv[]) { } seer.setExecutablePid(executablePid); - seer.setExecutableHostPort(executableHostPort); + seer.setExecutableConnectHostPort(executableConnectHostPort); + seer.setExecutableRRHostPort(executableRRHostPort); seer.setExecutableCoreFilename(executableCoreFilename); seer.setProjectFilename(projectFilename);