#include "SeerMainWindow.h" #include "SeerDebugDialog.h" #include "SeerConfigDialog.h" #include "SeerArgumentsDialog.h" #include "SeerAboutDialog.h" #include "SeerUtl.h" #include #include #include #include #include #include #include #include #include SeerMainWindow::SeerMainWindow(QWidget* parent) : QMainWindow(parent) { // // Set up UI. // setupUi(this); // // Set up other parts of the UI. // // Add status bar indicator. SeerRunStatusIndicator* runStatus = new SeerRunStatusIndicator(this); statusBar()->addPermanentWidget(runStatus); // Add progress spin widget. QWidget* spacerWidget = new QWidget(this); spacerWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); toolBar->addWidget(spacerWidget); _progressIndicator = new QProgressIndicator(this); _progressIndicator->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred); _progressIndicator->setFixedWidth(96); _progressIndicator->setType(QProgressIndicator::ball_rotate); toolBar->addWidget(_progressIndicator); // // Set up Styles menu. // _styleMenuActionGroup = new QActionGroup(this); _styleMenuActionGroup->setExclusionPolicy(QActionGroup::ExclusionPolicy::Exclusive); _styleMenuActionGroup->setEnabled(true); _styleMenuActionGroup->setVisible(true); QStringList styles = QStyleFactory::keys(); for (int i = 0; i < styles.size(); i++) { QAction* styleAction = menuStyles->addAction(styles.at(i)); styleAction->setCheckable(true); _styleMenuActionGroup->addAction(styleAction); } // // Set up Interrupt menu. // QMenu* menuInterrupt = new QMenu(this); QAction* interruptAction = menuInterrupt->addAction("GDB Interrupt"); menuInterrupt->addSeparator(); QAction* interruptActionSIGINT = menuInterrupt->addAction("SIGINT"); QAction* interruptActionSIGKILL = menuInterrupt->addAction("SIGKILL"); QAction* interruptActionSIGFPE = menuInterrupt->addAction("SIGFPE"); QAction* interruptActionSIGSEGV = menuInterrupt->addAction("SIGSEGV"); QAction* interruptActionSIGUSR1 = menuInterrupt->addAction("SIGUSR1"); QAction* interruptActionSIGUSR2 = menuInterrupt->addAction("SIGUSR2"); actionInterruptProcess->setMenu(menuInterrupt); // Set the inital key settings. setKeySettings(SeerKeySettings::populate()); // Setup hidden Struct Visualizer. QShortcut* varVisualizerShotcut = new QShortcut(QKeySequence(tr("Alt+V")), this); QObject::connect(varVisualizerShotcut, &QShortcut::activated, this, &SeerMainWindow::handleViewStructVisualizer); // // Set up signals/slots. // QObject::connect(actionFileDebug, &QAction::triggered, this, &SeerMainWindow::handleFileDebug); QObject::connect(actionFileArguments, &QAction::triggered, this, &SeerMainWindow::handleFileArguments); QObject::connect(actionFileQuit, &QAction::triggered, this, &SeerMainWindow::handleFileQuit); QObject::connect(actionViewMemoryVisualizer, &QAction::triggered, this, &SeerMainWindow::handleViewMemoryVisualizer); QObject::connect(actionViewArrayVisualizer, &QAction::triggered, this, &SeerMainWindow::handleViewArrayVisualizer); QObject::connect(actionViewStructVisualizer, &QAction::triggered, this, &SeerMainWindow::handleViewVarVisualizer); QObject::connect(actionViewAssembly, &QAction::triggered, this, &SeerMainWindow::handleViewAssembly); QObject::connect(actionConsoleNormal, &QAction::triggered, this, &SeerMainWindow::handleViewConsoleNormal); QObject::connect(actionConsoleHidden, &QAction::triggered, this, &SeerMainWindow::handleViewConsoleHidden); QObject::connect(actionConsoleMinimized, &QAction::triggered, this, &SeerMainWindow::handleViewConsoleMinimized); QObject::connect(actionHelpAbout, &QAction::triggered, this, &SeerMainWindow::handleHelpAbout); QObject::connect(actionControlRun, &QAction::triggered, this, &SeerMainWindow::handleRunExecutable); QObject::connect(actionControlStart, &QAction::triggered, this, &SeerMainWindow::handleStartExecutable); QObject::connect(actionControlContinue, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbContinue); QObject::connect(actionControlNext, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbNext); QObject::connect(actionControlStep, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbStep); QObject::connect(actionControlNexti, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbNexti); QObject::connect(actionControlStepi, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbStepi); QObject::connect(actionControlFinish, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbFinish); QObject::connect(actionControlInterrupt, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbInterrupt); QObject::connect(actionSettingsConfiguration, &QAction::triggered, this, &SeerMainWindow::handleSettingsConfiguration); QObject::connect(actionSettingsSaveConfiguration, &QAction::triggered, this, &SeerMainWindow::handleSettingsSaveConfiguration); QObject::connect(actionGdbRun, &QAction::triggered, this, &SeerMainWindow::handleRunExecutable); QObject::connect(actionGdbStart, &QAction::triggered, this, &SeerMainWindow::handleStartExecutable); QObject::connect(_styleMenuActionGroup, &QActionGroup::triggered, this, &SeerMainWindow::handleStyleMenuChanged); QObject::connect(actionGdbContinue, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbContinue); QObject::connect(actionGdbNext, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbNext); QObject::connect(actionGdbStep, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbStep); QObject::connect(actionGdbFinish, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbFinish); QObject::connect(actionInterruptProcess, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbInterrupt); QObject::connect(actionMemoryVisualizer, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbMemoryVisualizer); QObject::connect(actionArrayVisualizer, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbArrayVisualizer); QObject::connect(actionStructVisualizer, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbVarVisualizer); QObject::connect(interruptAction, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbInterrupt); QObject::connect(interruptActionSIGINT, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbInterruptSIGINT); QObject::connect(interruptActionSIGKILL, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbInterruptSIGKILL); QObject::connect(interruptActionSIGFPE, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbInterruptSIGFPE); QObject::connect(interruptActionSIGSEGV, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbInterruptSIGSEGV); QObject::connect(interruptActionSIGUSR1, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbInterruptSIGUSR1); QObject::connect(interruptActionSIGUSR2, &QAction::triggered, gdbWidget, &SeerGdbWidget::handleGdbInterruptSIGUSR2); QObject::connect(gdbWidget->gdbMonitor(), &GdbMonitor::astrixTextOutput, runStatus, &SeerRunStatusIndicator::handleText); QObject::connect(gdbWidget->gdbMonitor(), &GdbMonitor::astrixTextOutput, this, &SeerMainWindow::handleText); QObject::connect(gdbWidget->gdbMonitor(), &GdbMonitor::caretTextOutput, this, &SeerMainWindow::handleText); QObject::connect(gdbWidget->editorManager(), &SeerEditorManagerWidget::showMessage, this, &SeerMainWindow::handleShowMessage); QObject::connect(runStatus, &SeerRunStatusIndicator::statusChanged, this, &SeerMainWindow::handleRunStatusChanged); QObject::connect(gdbWidget, &SeerGdbWidget::changeWindowTitle, this, &SeerMainWindow::handleChangeWindowTitle); QObject::connect(qApp, &QApplication::aboutToQuit, gdbWidget, &SeerGdbWidget::handleGdbShutdown); // Restore window settings. readSettings(); // Restore configuration settings. readConfigSettings(); // // Initialize contents. // handleShowMessage("Welcome to Seer. The All Knowing...", 3000); } SeerMainWindow::~SeerMainWindow() { } void SeerMainWindow::setExecutableName (const QString& executableName) { gdbWidget->setExecutableName(executableName); } const QString& SeerMainWindow::executableName () const { return gdbWidget->executableName(); } void SeerMainWindow::setExecutableArguments (const QString& executableArguments) { gdbWidget->setExecutableArguments(executableArguments); } void SeerMainWindow::setExecutableArguments (const QStringList& executableArguments) { // // Convert the list of arguments into a single argument string. // Be careful of arguments that contain a space. These need to be surrounded by // a "'" character to retain the argument grouping. // // ie: myprog 42.0 "This is a multi-worded argument" // // Has 2 arguments. Not 6. // QString arguments; for (auto arg : executableArguments) { if (arg.contains(' ')) { arg = "'" + arg + "'"; } if (arguments == "") { arguments = arg; }else{ arguments += " " + arg; } } setExecutableArguments(arguments); } const QString& SeerMainWindow::executableArguments () const { return gdbWidget->executableArguments(); } void SeerMainWindow::setExecutableWorkingDirectory (const QString& executableWorkingDirectory) { gdbWidget->setExecutableWorkingDirectory(executableWorkingDirectory); } const QString& SeerMainWindow::executableWorkingDirectory () const { return gdbWidget->executableWorkingDirectory(); } void SeerMainWindow::setExecutableBreakpointsFilename (const QString& breakpointsFilename) { gdbWidget->setExecutableBreakpointsFilename(breakpointsFilename); } const QString& SeerMainWindow::executableBreakpointsFilename () const { return gdbWidget->executableBreakpointsFilename(); } void SeerMainWindow::setExecutableBreakpointFunctionName (const QString& nameoraddress) { gdbWidget->setExecutableBreakpointFunctionName(nameoraddress); } const QString& SeerMainWindow::executableBreakpointFunctionName () const { return gdbWidget->executableBreakpointFunctionName(); } void SeerMainWindow::setExecutableShowAssemblyTab (bool flag) { gdbWidget->setAssemblyShowAssemblyTabOnStartup(flag); } bool SeerMainWindow::executableShowAssemblyTab () const { return gdbWidget->assemblyShowAssemblyTabOnStartup(); } void SeerMainWindow::setExecutableRandomizeStartAddress (bool flag) { gdbWidget->setGdbRandomizeStartAddress(flag); } bool SeerMainWindow::executableRandomizeStartAddress () const { return gdbWidget->gdbRandomizeStartAddress(); } void SeerMainWindow::setExecutablePid (int pid) { gdbWidget->setExecutablePid(pid); } int SeerMainWindow::executablePid () const { return gdbWidget->executablePid(); } void SeerMainWindow::setExecutableHostPort (const QString& executableHostPort) { gdbWidget->setExecutableHostPort(executableHostPort); } const QString& SeerMainWindow::executableHostPort () const { return gdbWidget->executableHostPort(); } void SeerMainWindow::setExecutableSerialBaud (int executableBaudRate) { gdbWidget->setExecutableSerialBaud(executableBaudRate); } int SeerMainWindow::executableSerialBaud () const { return gdbWidget->executableSerialBaud(); } void SeerMainWindow::setExecutableSerialParity (const QString& executableParity) { gdbWidget->setExecutableSerialParity(executableParity); } const QString& SeerMainWindow::executableSerialParity () const { return gdbWidget->executableSerialParity(); } void SeerMainWindow::setExecutableCoreFilename (const QString& executableCoreFilename) { gdbWidget->setExecutableCoreFilename(executableCoreFilename); } const QString& SeerMainWindow::executableCoreFilename () const { return gdbWidget->executableCoreFilename(); } void SeerMainWindow::launchExecutable (const QString& launchMode, const QString& breakMode) { if (launchMode == "run") { gdbWidget->handleGdbRunExecutable(breakMode); }else if (launchMode == "start") { gdbWidget->handleGdbRunExecutable(breakMode); }else if (launchMode == "attach") { gdbWidget->handleGdbAttachExecutable(); }else if (launchMode == "connect") { gdbWidget->handleGdbConnectExecutable(); }else if (launchMode == "corefile") { gdbWidget->handleGdbCoreFileExecutable(); }else if (launchMode == "none") { // If no mode, schedule the opening of the debug dialog. QTimer::singleShot(200, this, &SeerMainWindow::handleFileDebug); }else if (launchMode == "configdialog") { // Launch the config dialog. QTimer::singleShot(200, this, &SeerMainWindow::handleSettingsConfiguration); }else{ qWarning() << "Bad launchMode:" << launchMode; } } const QString& SeerMainWindow::executableLaunchMode () const { return gdbWidget->executableLaunchMode(); } const QString& SeerMainWindow::executableBreakMode () const { return gdbWidget->executableBreakMode(); } void SeerMainWindow::handleFileDebug () { SeerDebugDialog dlg(this); dlg.setExecutableName(executableName()); dlg.setExecutableWorkingDirectory(executableWorkingDirectory()); dlg.setExecutableArguments(executableArguments()); dlg.setBreakpointsFilename(executableBreakpointsFilename()); dlg.setBreakpointFunctionName(executableBreakpointFunctionName()); dlg.setShowAssemblyTab(executableShowAssemblyTab()); dlg.setRandomizeStartAddress(executableRandomizeStartAddress()); dlg.setAttachPid(executablePid()); dlg.setConnectHostPort(executableHostPort()); dlg.setConnectSerialBaud(executableSerialBaud()); dlg.setConnectSerialParity(executableSerialParity()); dlg.setCoreFilename(executableCoreFilename()); dlg.setLaunchMode(executableLaunchMode()); dlg.setBreakpointMode(executableBreakMode()); int ret = dlg.exec(); if (ret == 0) { return; } QString launchMode = dlg.launchMode(); QString breakMode = dlg.breakpointMode(); if (launchMode == "") { return; } setExecutableName(dlg.executableName()); setExecutableWorkingDirectory(dlg.executableWorkingDirectory()); setExecutableArguments(dlg.executableArguments()); setExecutableBreakpointsFilename(dlg.breakpointsFilename()); setExecutableBreakpointFunctionName(dlg.breakpointFunctionName()); setExecutableShowAssemblyTab(dlg.showAssemblyTab()); setExecutableRandomizeStartAddress(dlg.randomizeStartAddress()); setExecutablePid(dlg.attachPid()); setExecutableHostPort(dlg.connectHostPort()); setExecutableSerialBaud(dlg.connectSerialBaud()); setExecutableSerialParity(dlg.connectSerialParity()); setExecutableCoreFilename(dlg.coreFilename()); launchExecutable(launchMode, breakMode); } void SeerMainWindow::handleFileArguments () { SeerArgumentsDialog dlg(this); dlg.setExecutableArguments(executableArguments()); int ret = dlg.exec(); if (ret == 0) { return; } setExecutableArguments(dlg.executableArguments()); } void SeerMainWindow::handleFileQuit () { gdbWidget->handleGdbShutdown(); QCoreApplication::exit(0); } void SeerMainWindow::handleViewMemoryVisualizer () { gdbWidget->handleGdbMemoryVisualizer(); } void SeerMainWindow::handleViewArrayVisualizer () { gdbWidget->handleGdbArrayVisualizer(); } void SeerMainWindow::handleViewStructVisualizer () { gdbWidget->handleGdbStructVisualizer(); } void SeerMainWindow::handleViewVarVisualizer () { gdbWidget->handleGdbVarVisualizer(); } void SeerMainWindow::handleViewAssembly () { gdbWidget->editorManager()->showAssembly(); } void SeerMainWindow::handleViewConsoleNormal () { gdbWidget->setConsoleMode("normal"); } void SeerMainWindow::handleViewConsoleHidden () { gdbWidget->setConsoleMode("hidden"); } void SeerMainWindow::handleViewConsoleMinimized () { gdbWidget->setConsoleMode("minimized"); } void SeerMainWindow::handleSettingsConfiguration () { SeerConfigDialog dlg(this); dlg.setGdbProgram(gdbWidget->gdbProgram()); dlg.setGdbArguments(gdbWidget->gdbArguments()); dlg.setGdbAsyncMode(gdbWidget->gdbAsyncMode()); dlg.setGdbHandleTerminatingException(gdbWidget->gdbHandleTerminatingException()); dlg.setGdbRandomizeStartAddress(gdbWidget->gdbRandomizeStartAddress()); dlg.setGdbEnablePrettyPrinting(gdbWidget->gdbEnablePrettyPrinting()); dlg.setDprintfStyle(gdbWidget->dprintfStyle()); dlg.setDprintfFunction(gdbWidget->dprintfFunction()); dlg.setDprintfChannel(gdbWidget->dprintfChannel()); dlg.setEditorFont(gdbWidget->editorManager()->editorFont()); dlg.setEditorHighlighterSettings(gdbWidget->editorManager()->editorHighlighterSettings()); dlg.setEditorHighlighterEnabled(gdbWidget->editorManager()->editorHighlighterEnabled()); dlg.setSourceAlternateDirectories(gdbWidget->sourceAlternateDirectories()); dlg.setSourceIgnoreDirectories(gdbWidget->sourceIgnoreDirectories()); dlg.setSourceMiscFilePatterns(gdbWidget->sourceMiscFilePatterns()); dlg.setSourceSourceFilePatterns(gdbWidget->sourceSourceFilePatterns()); dlg.setSourceHeaderFilePatterns(gdbWidget->sourceHeaderFilePatterns()); dlg.setAssemblyShowAssemblyTabOnStartup(gdbWidget->assemblyShowAssemblyTabOnStartup()); dlg.setAssemblyKeepAssemblyTabOnTop(gdbWidget->assemblyKeepAssemblyTabOnTop()); dlg.setAssemblyDisassembyFlavor(gdbWidget->assemblyDisassembyFlavor()); dlg.setAssemblySymbolDemagling(gdbWidget->assemblySymbolDemagling()); dlg.setAssemblyRegisterFormat(gdbWidget->assemblyRegisterFormat()); dlg.setSeerConsoleMode(gdbWidget->consoleMode()); dlg.setSeerConsoleScrollLines(gdbWidget->consoleScrollLines()); dlg.setSeerRememberManualCommandCount(gdbWidget->rememberManualCommandCount()); dlg.setKeySettings(keySettings()); int ret = dlg.exec(); if (ret == 0) { return; } // Update the GdbWidget with the new settings. gdbWidget->setGdbProgram(dlg.gdbProgram()); gdbWidget->setGdbArguments(dlg.gdbArguments()); gdbWidget->setGdbAsyncMode(dlg.gdbAsyncMode()); gdbWidget->setGdbHandleTerminatingException(dlg.gdbHandleTerminatingException()); gdbWidget->setGdbRandomizeStartAddress(dlg.gdbRandomizeStartAddress()); gdbWidget->setGdbEnablePrettyPrinting(dlg.gdbEnablePrettyPrinting()); gdbWidget->setDprintfStyle(dlg.dprintfStyle()); gdbWidget->setDprintfFunction(dlg.dprintfFunction()); gdbWidget->setDprintfChannel(dlg.dprintfChannel()); gdbWidget->editorManager()->setEditorFont(dlg.editorFont()); gdbWidget->editorManager()->setEditorHighlighterSettings(dlg.editorHighlighterSettings()); gdbWidget->editorManager()->setEditorHighlighterEnabled(dlg.editorHighlighterEnabled()); gdbWidget->setSourceAlternateDirectories(dlg.sourceAlternateDirectories()); gdbWidget->setSourceIgnoreDirectories(dlg.sourceIgnoreDirectories()); gdbWidget->setSourceMiscFilePatterns(dlg.sourceMiscFilePatterns()); gdbWidget->setSourceSourceFilePatterns(dlg.sourceSourceFilePatterns()); gdbWidget->setSourceHeaderFilePatterns(dlg.sourceHeaderFilePatterns()); gdbWidget->setAssemblyShowAssemblyTabOnStartup(dlg.assemblyShowAssemblyTabOnStartup()); gdbWidget->setAssemblyKeepAssemblyTabOnTop(dlg.assemblyKeepAssemblyTabOnTop()); gdbWidget->setAssemblyDisassembyFlavor(dlg.assemblyDisassembyFlavor()); gdbWidget->setAssemblySymbolDemagling(dlg.assemblySymbolDemagling()); gdbWidget->setAssemblyRegisterFormat(dlg.assemblyRegisterFormat()); gdbWidget->setConsoleMode(dlg.seerConsoleMode()); gdbWidget->setConsoleScrollLines(dlg.seerConsoleScrollLines()); gdbWidget->setRememberManualCommandCount(dlg.seerRememberManualCommandCount()); // Clear history, if we need to. bool clearManualCommandHistory = dlg.seerClearManualCommandHistory(); if (clearManualCommandHistory) { gdbWidget->clearManualCommandHistory(); } // Reset the dprintf, in case it was changed. gdbWidget->resetDprintf(); // Set the key shortcuts. setKeySettings(dlg.keySettings()); } void SeerMainWindow::handleSettingsSaveConfiguration () { int result = QMessageBox::warning(this, "Seer - Settings", QString("Write the configuration settings?"), QMessageBox::Ok|QMessageBox::Cancel, QMessageBox::Cancel); if (result == QMessageBox::Cancel) { return; } writeConfigSettings(); gdbWidget->writeSettings(); QMessageBox::information(this, "Seer", "Saved."); } void SeerMainWindow::handleHelpAbout () { SeerAboutDialog dlg(this); dlg.exec(); } void SeerMainWindow::handleRunExecutable () { gdbWidget->handleGdbRunExecutable("none"); } void SeerMainWindow::handleStartExecutable () { QString breakfunction = gdbWidget->executableBreakpointFunctionName(); // No break function, attempt to stop in "main". if (breakfunction == "") { gdbWidget->handleGdbRunExecutable("inmain"); // Otherwise, attempt to stop in the function. }else{ gdbWidget->handleGdbRunExecutable("infunction"); } } void SeerMainWindow::handleStyleMenuChanged () { QAction* action = _styleMenuActionGroup->checkedAction(); if (action == 0) { return; } QApplication::setStyle(action->text()); } void SeerMainWindow::handleShowMessage (QString message, int time) { statusBar()->showMessage(message, time); } void SeerMainWindow::handleText (const QString& text) { if (text.startsWith("^error,msg=")) { // ^error,msg="The program is not being run." // ^error,msg="ptrace: No such process." //qDebug() << text; QString newtext = Seer::filterEscapes(text); // Filter escaped characters. // Filter out less important errors. if (newtext == "^error,msg=\"No registers.\"") { return; } if (newtext == "^error,msg=\"Selected thread is running.\"") { return; } // Display the error message. QString msg_text = Seer::parseFirst(text, "msg=", false); if (msg_text != "") { handleShowMessage(Seer::filterBookends(msg_text, '"', '"'), 3000); QMessageBox::warning(this, "Error.", Seer::filterEscapes(msg_text)); return; } }else if (text == "^running") { // Swallow this message. return; }else if (text == "^done") { return; }else if (text.startsWith("^done,files=[") && text.endsWith("]")) { return; }else if (text.startsWith("^done,shared-libraries=[") && text.endsWith("]")) { return; }else if (text.startsWith("^done,stack=[") && text.endsWith("]")) { return; }else if (text.startsWith("^done,variables=[") && text.endsWith("]")) { return; }else if (text.startsWith("^done,stack-args=[") && text.endsWith("]")) { return; }else if (text.startsWith("^done,BreakpointTable={") && text.endsWith("}")) { return; }else if (text.startsWith("^done,bkpt={") && text.endsWith("}")) { return; }else if (text.startsWith("^done,hw-awpt={")) { return; }else if (text.startsWith("^done,hw-rwpt={")) { return; }else if (text.startsWith("^done,wpt={")) { return; }else if (text.startsWith("^done,thread-ids={")) { return; }else if (text.startsWith("^done,new-thread-id=")) { return; }else if (text.startsWith("^done,threads=[")) { return; }else if (text.startsWith("^done,register-names=[") && text.endsWith("]")) { return; }else if (text.startsWith("^done,register-values=[") && text.endsWith("]")) { return; }else if (text.startsWith("^done,DataExpressionAdded={") && text.endsWith("}")) { return; }else if (text.startsWith("^done,DataExpressionDeleted={") && text.endsWith("}")) { return; }else if (text.startsWith("^done,DataExpressionTable={") && text.endsWith("}")) { return; }else if (text.startsWith("^done,symbols={") && text.endsWith("}")) { return; }else if (text.startsWith("^done,asm_insns=[")) { return; }else if (text.contains(QRegExp("^([0-9]+)\\^done"))) { return; }else if (text.contains(QRegExp("^([0-9]+)\\^done,value="))) { return; }else if (text.contains(QRegExp("^([0-9]+)\\^error,msg="))) { return; }else if (text.contains(QRegExp("^([0-9]+)\\^done,memory="))) { return; }else if (text == "^exit") { return; }else if (text.startsWith("*running,thread-id=\"")) { QString threadid_text = Seer::parseFirst(text, "thread-id=", '"', '"', false); handleShowMessage("Program started. Thread id: " + threadid_text, 3000); return; }else if (text.startsWith("^connected,frame=")) { //^connected,frame={level=\"0\",addr=\"0x00007f48351f80c1\",func=\"read\",args=[],from=\"/lib64/libc.so.6\",arch=\"i386:x86-64\"}" return; }else if (text.startsWith("*stopped")) { QString reason_text = Seer::parseFirst(text, "reason=", '"', '"', false); if (reason_text == "") { reason_text = "unknown"; } handleShowMessage("Program stopped. Reason: " + reason_text, 3000); if (reason_text == "signal-received") { //*stopped,reason="signal-received",signal-name="SIGSEGV",signal-meaning="Segmentation fault", ... QString signalname_text = Seer::parseFirst(text, "signal-name=", '"', '"', false); QMessageBox::warning(this, "Warning.", "Program encountered a '" + signalname_text + "' signal."); }else if (reason_text == "watchpoint-trigger") { //*stopped,reason="watchpoint-trigger",wpt={number="3",exp="i"},value={old="32767",new="42"},frame={addr="0x0000000000400d79",func="function1",args=[{name="text",value="\"Hello, World!\""}],file="function1.cpp",fullname="/home/erniep/Development/Peak/src/Seer/helloworld/function1.cpp",line="9",arch="i386:x86-64"},thread-id="1",stopped-threads="all",core="0" QString wpt_text = Seer::parseFirst(text, "wpt=", '{', '}', false); QString number_text = Seer::parseFirst(wpt_text, "number=", '"', '"', false); QString exp_text = Seer::parseFirst(wpt_text, "exp=", '"', '"', false); QString value_text = Seer::parseFirst(text, "value=", '{', '}', false); QString old_text = Seer::parseFirst(value_text, "old=", '"', '"', false); QString new_text = Seer::parseFirst(value_text, "new=", '"', '"', false); QMessageBox::information(this, "Note.", QString("Watchpoint triggered.\n\nNumber: %1\nExpression: %2\nOld value: %3\nNew value: %4").arg(number_text).arg(exp_text).arg(old_text).arg(new_text) ); }else if (reason_text == "read-watchpoint-trigger") { //*stopped,reason="read-watchpoint-trigger",hw-rwpt={number="5",exp="i"},value={value="42"},frame={addr="0x0000000000400d9a",func="function1",args=[{name="text",value="\"Hello, World!\""}],file="function1.cpp",fullname="/home/erniep/Development/Peak/src/Seer/helloworld/function1.cpp",line="11",arch="i386:x86-64"},thread-id="1",stopped-threads="all",core="4" QString hwwpt_text = Seer::parseFirst(text, "hw-rwpt=", '{', '}', false); QString number_text = Seer::parseFirst(hwwpt_text, "number=", '"', '"', false); QString exp_text = Seer::parseFirst(hwwpt_text, "exp=", '"', '"', false); QString value_text = Seer::parseFirst(text, "value=", '{', '}', false); QString value_text2 = Seer::parseFirst(value_text, "value=", '"', '"', false); QMessageBox::information(this, "Note.", QString("Watchpoint triggered.\n\nNumber: %1\nExpression: %2\nValue: %3").arg(number_text).arg(exp_text).arg(value_text2) ); }else if (reason_text == "access-watchpoint-trigger") { //*stopped,reason="access-watchpoint-trigger",hw-awpt={number="3",exp="v"},value={old="1",new="11"},frame={addr="0x000000000040059a",func="bar",args=[{name="v",value="11"}],file="helloonefile.cpp",fullname="/home/erniep/Development/Peak/src/Seer/helloonefile/helloonefile.cpp",line="15",arch="i386:x86-64"},thread-id="1",stopped-threads="all",core="3" QString hwawpt_text = Seer::parseFirst(text, "hw-awpt=", '{', '}', false); QString number_text = Seer::parseFirst(hwawpt_text, "number=", '"', '"', false); QString exp_text = Seer::parseFirst(hwawpt_text, "exp=", '"', '"', false); QString value_text = Seer::parseFirst(text, "value=", '{', '}', false); QString old_text = Seer::parseFirst(value_text, "old=", '"', '"', false); QString new_text = Seer::parseFirst(value_text, "new=", '"', '"', false); QMessageBox::information(this, "Note.", QString("Watchpoint triggered.\n\nNumber: %1\nExpression: %2\nOld value: %3\nNew value: %4").arg(number_text).arg(exp_text).arg(old_text).arg(new_text) ); }else if (reason_text == "watchpoint-scope") { //*stopped,reason="watchpoint-scope",wpnum="5", frame={func="callee3",args=[{name="strarg", value="0x11940 \"A string argument.\""}], file="../../../devo/gdb/testsuite/gdb.mi/basics.c", fullname="/home/foo/bar/devo/gdb/testsuite/gdb.mi/basics.c",line="18"} QString wpnum_text = Seer::parseFirst(text, "wpnum=", '"', '"', false); QMessageBox::information(this, "Note.", QString("Watchpoint went out of scope. Will be deleted.\n\nNumber: %1").arg(wpnum_text) ); }else if (reason_text == "exited-normally") { //*stopped,reason="exited-normally" QMessageBox::information(this, "Note.", "Program exited normally."); }else if (reason_text == "exited") { //*stopped,reason="exited",exit-code="01" QString exitcode_text = Seer::parseFirst(text, "exit-code=", '"', '"', false); QMessageBox::information(this, "Note.", "Program exited with code '" + exitcode_text +"'"); }else if (reason_text == "exited-signalled") { //*stopped,reason="exited-signalled",signal-name="SIGSEGV",signal-meaning="Segmentation fault" QString signalname_text = Seer::parseFirst(text, "signal-name=", '"', '"', false); QMessageBox::warning(this, "Error.", "Program exited abnormally.\n\nIt encountered a '" + signalname_text + "' signal."); }else if (reason_text == "unknown") { // Don't bother showing this. // Attaching to a pid will generate an unknown *stopped message that is useless. //qDebug() << "Text=" << text; //QMessageBox::warning(this, "Warning.", "Program encountered an unknown problem. See the Gdb output tab for messages."); } return; } qDebug() << text; } void SeerMainWindow::handleRunStatusChanged (SeerRunStatusIndicator::RunStatus status) { if (status == SeerRunStatusIndicator::RunStatus::Idle) { _progressIndicator->stop(); }else if (status == SeerRunStatusIndicator::RunStatus::Stopped) { _progressIndicator->stop(); }else if (status == SeerRunStatusIndicator::RunStatus::Running) { _progressIndicator->start(); }else{ _progressIndicator->stop(); } } void SeerMainWindow::handleChangeWindowTitle (QString title) { if (title == "") { setWindowTitle("Seer Debugger"); }else{ setWindowTitle("Seer Debugger - '" + title + "'"); } } void SeerMainWindow::writeSettings() { QSettings settings; settings.beginGroup("mainwindow"); { settings.setValue("size", size()); } settings.endGroup(); } void SeerMainWindow::readSettings() { QSettings settings; settings.beginGroup("mainwindow"); { resize(settings.value("size", QSize(1250, 1000)).toSize()); } settings.endGroup(); } void SeerMainWindow::writeConfigSettings () { QSettings settings; settings.beginGroup("gdb"); { settings.setValue("program", gdbWidget->gdbProgram()); settings.setValue("arguments", gdbWidget->gdbArguments()); settings.setValue("asyncmode", gdbWidget->gdbAsyncMode()); settings.setValue("handleterminatingexception", gdbWidget->gdbHandleTerminatingException()); settings.setValue("randomizestartaddress", gdbWidget->gdbRandomizeStartAddress()); settings.setValue("enableprettyprinting", gdbWidget->gdbEnablePrettyPrinting()); } settings.endGroup(); settings.beginGroup("printpoints"); { settings.setValue("style", gdbWidget->dprintfStyle()); settings.setValue("function", gdbWidget->dprintfFunction()); settings.setValue("channel", gdbWidget->dprintfChannel()); } settings.endGroup(); settings.beginGroup("editor"); { settings.setValue("font", gdbWidget->editorManager()->editorFont().toString()); settings.beginGroup("highlighter"); { settings.setValue("enabled", gdbWidget->editorManager()->editorHighlighterEnabled()); SeerHighlighterSettings highlighter = gdbWidget->editorManager()->editorHighlighterSettings(); QStringList keys = highlighter.keys(); for (int i=0; irememberManualCommandCount()); } settings.endGroup(); settings.beginWriteArray("shortcuts"); { SeerKeySettings keysettings = keySettings(); QStringList keys = keysettings.keys(); for (int i=0; isetGdbProgram(settings.value("program", "/usr/bin/gdb").toString()); gdbWidget->setGdbArguments(settings.value("arguments", "--interpreter=mi").toString()); gdbWidget->setGdbAsyncMode(settings.value("asyncmode", true).toBool()); gdbWidget->setGdbHandleTerminatingException(settings.value("handleterminatingexception", true).toBool()); gdbWidget->setGdbRandomizeStartAddress(settings.value("randomizestartaddress", false).toBool()); gdbWidget->setGdbEnablePrettyPrinting(settings.value("enableprettyprinting", true).toBool()); } settings.endGroup(); settings.beginGroup("printpoints"); { gdbWidget->setDprintfStyle(settings.value("style", "gdb").toString()); gdbWidget->setDprintfFunction(settings.value("function", "printf").toString()); gdbWidget->setDprintfChannel(settings.value("channel", "").toString()); } settings.endGroup(); settings.beginGroup("editor"); { QFont f; if (settings.contains("font")) { f.fromString(settings.value("font").toString()); }else{ f = QFont("Source Code Pro", 10); } gdbWidget->editorManager()->setEditorFont(f); settings.beginGroup("highlighter"); { gdbWidget->editorManager()->setEditorHighlighterEnabled(settings.value("enabled",true).toBool()); SeerHighlighterSettings highlighter = gdbWidget->editorManager()->editorHighlighterSettings(); QStringList keys = highlighter.keys(); for (int i=0; i()); } if (settings.contains("backgroundcolor")) { f.setBackground(settings.value("backgroundcolor").value()); } highlighter.add(keys[i], f); } settings.endGroup(); } if (settings.contains("suffixes")) { highlighter.setSourceSuffixes(settings.value("suffixes").toString()); } gdbWidget->editorManager()->setEditorHighlighterSettings(highlighter); } settings.endGroup(); } settings.endGroup(); settings.beginGroup("manualgdbcommands"); { gdbWidget->setRememberManualCommandCount(settings.value("remembercount", 10).toInt()); } settings.endGroup(); int size = settings.beginReadArray("shortcuts"); { SeerKeySettings keysettings = keySettings(); // Start with defaults. The add() will overwrite. for (int i = 0; i < size; ++i) { settings.setArrayIndex(i); QString name = settings.value("action").toString(); QKeySequence key = QKeySequence::fromString(settings.value("key").toString()); QString help = settings.value("help").toString(); keysettings.add(name, SeerKeySetting(name, key, help)); } setKeySettings(keysettings); } settings.endArray(); } void SeerMainWindow::resizeEvent (QResizeEvent* event) { // Write window settings. writeSettings(); QMainWindow::resizeEvent(event); } void SeerMainWindow::closeEvent (QCloseEvent* event) { event->accept(); QCoreApplication::exit(0); } void SeerMainWindow::setKeySettings (const SeerKeySettings& settings) { _keySettings = settings; refreshShortCuts(); } const SeerKeySettings SeerMainWindow::keySettings () const { return _keySettings; } void SeerMainWindow::refreshShortCuts () { if (_keySettings.has("Run")) { SeerKeySetting setting = _keySettings.get("Run"); actionGdbRun->setToolTip(setting._description); actionGdbRun->setText(setting._action + " (" + setting._sequence.toString() + ")"); actionControlRun->setShortcut(setting._sequence); } if (_keySettings.has("Start")) { SeerKeySetting setting = _keySettings.get("Start"); actionGdbStart->setToolTip(setting._description); actionGdbStart->setText(setting._action + " (" + setting._sequence.toString() + ")"); actionControlStart->setShortcut(setting._sequence); } if (_keySettings.has("Next")) { SeerKeySetting setting = _keySettings.get("Next"); actionGdbNext->setToolTip(setting._description); actionGdbNext->setText(setting._action + " (" + setting._sequence.toString() + ")"); actionControlNext->setShortcut(setting._sequence); } if (_keySettings.has("Nexti")) { SeerKeySetting setting = _keySettings.get("Nexti"); actionControlNexti->setShortcut(setting._sequence); } if (_keySettings.has("Step")) { SeerKeySetting setting = _keySettings.get("Step"); actionGdbStep->setToolTip(setting._description); actionGdbStep->setText(setting._action + " (" + setting._sequence.toString() + ")"); actionControlStep->setShortcut(setting._sequence); } if (_keySettings.has("Stepi")) { SeerKeySetting setting = _keySettings.get("Stepi"); actionControlStepi->setShortcut(setting._sequence); } if (_keySettings.has("Finish")) { SeerKeySetting setting = _keySettings.get("Finish"); actionGdbFinish->setToolTip(setting._description); actionGdbFinish->setText(setting._action + " (" + setting._sequence.toString() + ")"); actionControlFinish->setShortcut(setting._sequence); } if (_keySettings.has("Continue")) { SeerKeySetting setting = _keySettings.get("Continue"); actionGdbContinue->setToolTip(setting._description); actionGdbContinue->setText(setting._action + " (" + setting._sequence.toString() + ")"); actionControlContinue->setShortcut(setting._sequence); } if (_keySettings.has("Debug")) { SeerKeySetting setting = _keySettings.get("Debug"); actionFileDebug->setShortcut(setting._sequence); } if (_keySettings.has("Arguments")) { SeerKeySetting setting = _keySettings.get("Arguments"); actionFileArguments->setShortcut(setting._sequence); } if (_keySettings.has("Quit")) { SeerKeySetting setting = _keySettings.get("Quit"); actionFileQuit->setShortcut(setting._sequence); } gdbWidget->editorManager()->setEditorKeySettings(keySettings()); }