#include "SeerGdbWidget.h" #include "SeerLogWidget.h" #include "SeerTildeEqualAmpersandLogWidget.h" #include "SeerCaretAsteriskLogWidget.h" #include "SeerConsoleWidget.h" #include "SeerBreakpointsBrowserWidget.h" #include "SeerWatchpointsBrowserWidget.h" #include "SeerMemoryVisualizerWidget.h" #include "SeerUtl.h" #include #include #include #include #include #include #include #include SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) { _executableName = ""; _executableArguments = ""; _executableWorkingDirectory = ""; _executablePid = -1; _gdbMonitor = 0; _gdbProcess = 0; _consoleWidget = 0; setupUi(this); // Setup the widgets QFont font; font.setFamily("monospace [Consolas]"); font.setFixedPitch(true); font.setStyleHint(QFont::TypeWriter); SeerBreakpointsBrowserWidget* breakpointsBrowserWidget = new SeerBreakpointsBrowserWidget(this); SeerWatchpointsBrowserWidget* watchpointsBrowserWidget = new SeerWatchpointsBrowserWidget(this); SeerTildeEqualAmpersandLogWidget* gdbOutputLog = new SeerTildeEqualAmpersandLogWidget(this); SeerCaretAsteriskLogWidget* seerOutputLog = new SeerCaretAsteriskLogWidget(this); logsTabWidget->addTab(breakpointsBrowserWidget, "Breakpoints"); logsTabWidget->addTab(watchpointsBrowserWidget, "Watchpoints"); logsTabWidget->addTab(gdbOutputLog, "GDB output"); logsTabWidget->addTab(seerOutputLog, "Seer output"); logsTabWidget->setCurrentIndex(0); manualCommandComboBox->setFont(font); manualCommandComboBox->setEditable(true); manualCommandComboBox->lineEdit()->setPlaceholderText("Manually enter a gdb/mi command..."); manualCommandComboBox->lineEdit()->setToolTip("Manually enter a gdb/mi command."); manualCommandComboBox->lineEdit()->setClearButtonEnabled(true); // Create the gdb process. _gdbProcess = new QProcess(this); // Create the gdb monitor. _gdbMonitor = new GdbMonitor(this); _gdbMonitor->setProcess(_gdbProcess); // Connect things. QObject::connect(manualCommandComboBox->lineEdit(), &QLineEdit::returnPressed, this, &SeerGdbWidget::handleExecute); QObject::connect(_gdbProcess, &QProcess::readyReadStandardOutput, _gdbMonitor, &GdbMonitor::handleReadyReadStandardOutput); QObject::connect(_gdbProcess, &QProcess::readyReadStandardError, _gdbMonitor, &GdbMonitor::handleReadyReadStandardError); //QObject::connect(_gdbProcess, static_cast(&QProcess::finished), _gdbMonitor, &GdbMonitor::handleFinished); // ??? Do we care about the gdb process ending? For now, terminate Seer. QObject::connect(_gdbMonitor, &GdbMonitor::tildeTextOutput, gdbOutputLog, &SeerTildeEqualAmpersandLogWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::equalTextOutput, gdbOutputLog, &SeerTildeEqualAmpersandLogWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::ampersandTextOutput, gdbOutputLog, &SeerTildeEqualAmpersandLogWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, seerOutputLog, &SeerCaretAsteriskLogWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::astrixTextOutput, seerOutputLog, &SeerCaretAsteriskLogWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::astrixTextOutput, editorManagerWidget, &SeerEditorManagerWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, editorManagerWidget, &SeerEditorManagerWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, sourceLibraryManagerWidget->sourceBrowserWidget(), &SeerSourceBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, sourceLibraryManagerWidget->sharedLibraryBrowserWidget(), &SeerSharedLibraryBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, stackManagerWidget->stackFramesBrowserWidget(), &SeerStackFramesBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, stackManagerWidget->stackLocalsBrowserWidget(), &SeerStackLocalsBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, stackManagerWidget->stackArgumentsBrowserWidget(), &SeerStackArgumentsBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, threadManagerWidget->threadIdsBrowserWidget(), &SeerThreadIdsBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, breakpointsBrowserWidget, &SeerBreakpointsBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, watchpointsBrowserWidget, &SeerWatchpointsBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, variableManagerWidget->registerValuesBrowserWidget(), &SeerRegisterValuesBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, variableManagerWidget->variableTrackerBrowserWidget(), &SeerVariableTrackerBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, variableManagerWidget->variableLoggerBrowserWidget(), &SeerVariableLoggerBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::astrixTextOutput, watchpointsBrowserWidget, &SeerWatchpointsBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::astrixTextOutput, this, &SeerGdbWidget::handleText); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::refreshBreakpointsList, this, &SeerGdbWidget::handleGdbBreakpointWatchpointList); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::refreshStackFrames, this, &SeerGdbWidget::handleGdbStackListFrames); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::insertBreakpoint, this, &SeerGdbWidget::handleGdbBreakpointInsert); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::deleteBreakpoints, this, &SeerGdbWidget::handleGdbBreakpointDelete); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::enableBreakpoints, this, &SeerGdbWidget::handleGdbBreakpointEnable); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::disableBreakpoints, this, &SeerGdbWidget::handleGdbBreakpointDisable); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::runToLine, this, &SeerGdbWidget::handleGdbRunToLine); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::addVariableExpression, this, &SeerGdbWidget::handleGdbDataAddExpression); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::refreshVariableValues, this, &SeerGdbWidget::handleGdbDataListValues); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::addMemoryVisualize, this, &SeerGdbWidget::handleGdbMemoryAddExpression); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::evaluateVariableExpression, this, &SeerGdbWidget::handleGdbDataEvaluateExpression); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::evaluateVariableExpression, variableManagerWidget->variableLoggerBrowserWidget(), &SeerVariableLoggerBrowserWidget::handleEvaluateVariableExpression); QObject::connect(sourceLibraryManagerWidget->sourceBrowserWidget(), &SeerSourceBrowserWidget::refreshSourceList, this, &SeerGdbWidget::handleGdbExecutableSources); QObject::connect(sourceLibraryManagerWidget->sourceBrowserWidget(), &SeerSourceBrowserWidget::selectedFile, editorManagerWidget, &SeerEditorManagerWidget::handleOpenFile); QObject::connect(sourceLibraryManagerWidget->sharedLibraryBrowserWidget(), &SeerSharedLibraryBrowserWidget::refreshSharedLibraryList, this, &SeerGdbWidget::handleGdbExecutableSharedLibraries); QObject::connect(stackManagerWidget->stackFramesBrowserWidget(), &SeerStackFramesBrowserWidget::refreshStackFrames, this, &SeerGdbWidget::handleGdbStackListFrames); QObject::connect(stackManagerWidget->stackLocalsBrowserWidget(), &SeerStackLocalsBrowserWidget::refreshStackLocals, this, &SeerGdbWidget::handleGdbStackListLocals); QObject::connect(stackManagerWidget->stackFramesBrowserWidget(), &SeerStackFramesBrowserWidget::selectedFrame, this, &SeerGdbWidget::handleGdbStackSelectFrame); QObject::connect(stackManagerWidget->stackArgumentsBrowserWidget(), &SeerStackArgumentsBrowserWidget::refreshStackArguments, this, &SeerGdbWidget::handleGdbStackListArguments); QObject::connect(stackManagerWidget->stackFramesBrowserWidget(), &SeerStackFramesBrowserWidget::selectedFile, editorManagerWidget, &SeerEditorManagerWidget::handleOpenFile); QObject::connect(variableManagerWidget->variableTrackerBrowserWidget(), &SeerVariableTrackerBrowserWidget::refreshVariableValues, this, &SeerGdbWidget::handleGdbDataListExpressions); QObject::connect(variableManagerWidget->variableTrackerBrowserWidget(), &SeerVariableTrackerBrowserWidget::refreshVariableNames, this, &SeerGdbWidget::handleGdbDataListValues); QObject::connect(variableManagerWidget->variableTrackerBrowserWidget(), &SeerVariableTrackerBrowserWidget::addVariableExpression, this, &SeerGdbWidget::handleGdbDataAddExpression); QObject::connect(variableManagerWidget->variableTrackerBrowserWidget(), &SeerVariableTrackerBrowserWidget::deleteVariableExpressions, this, &SeerGdbWidget::handleGdbDataDeleteExpressions); QObject::connect(variableManagerWidget->variableLoggerBrowserWidget(), &SeerVariableLoggerBrowserWidget::evaluateVariableExpression, this, &SeerGdbWidget::handleGdbDataEvaluateExpression); QObject::connect(variableManagerWidget->registerValuesBrowserWidget(), &SeerRegisterValuesBrowserWidget::refreshRegisterNames, this, &SeerGdbWidget::handleGdbRegisterListNames); QObject::connect(variableManagerWidget->registerValuesBrowserWidget(), &SeerRegisterValuesBrowserWidget::refreshRegisterValues, this, &SeerGdbWidget::handleGdbRegisterListValues); QObject::connect(threadManagerWidget->threadIdsBrowserWidget(), &SeerThreadIdsBrowserWidget::refreshThreadIds, this, &SeerGdbWidget::handleGdbThreadListIds); QObject::connect(threadManagerWidget->threadIdsBrowserWidget(), &SeerThreadIdsBrowserWidget::selectedThread, this, &SeerGdbWidget::handleGdbThreadSelectId); QObject::connect(threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::refreshThreadFrames, this, &SeerGdbWidget::handleGdbThreadListFrames); QObject::connect(threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::selectedFile, editorManagerWidget, &SeerEditorManagerWidget::handleOpenFile); QObject::connect(breakpointsBrowserWidget, &SeerBreakpointsBrowserWidget::refreshBreakpointsList, this, &SeerGdbWidget::handleGdbBreakpointWatchpointList); QObject::connect(breakpointsBrowserWidget, &SeerBreakpointsBrowserWidget::deleteBreakpoints, this, &SeerGdbWidget::handleGdbBreakpointDelete); QObject::connect(breakpointsBrowserWidget, &SeerBreakpointsBrowserWidget::enableBreakpoints, this, &SeerGdbWidget::handleGdbBreakpointEnable); QObject::connect(breakpointsBrowserWidget, &SeerBreakpointsBrowserWidget::disableBreakpoints, this, &SeerGdbWidget::handleGdbBreakpointDisable); QObject::connect(breakpointsBrowserWidget, &SeerBreakpointsBrowserWidget::insertBreakpoint, this, &SeerGdbWidget::handleGdbBreakpointInsert); QObject::connect(breakpointsBrowserWidget, &SeerBreakpointsBrowserWidget::selectedFile, editorManagerWidget, &SeerEditorManagerWidget::handleOpenFile); QObject::connect(watchpointsBrowserWidget, &SeerWatchpointsBrowserWidget::refreshWatchpointsList, this, &SeerGdbWidget::handleGdbBreakpointWatchpointList); QObject::connect(watchpointsBrowserWidget, &SeerWatchpointsBrowserWidget::deleteWatchpoints, this, &SeerGdbWidget::handleGdbWatchpointDelete); QObject::connect(watchpointsBrowserWidget, &SeerWatchpointsBrowserWidget::enableWatchpoints, this, &SeerGdbWidget::handleGdbWatchpointEnable); QObject::connect(watchpointsBrowserWidget, &SeerWatchpointsBrowserWidget::disableWatchpoints, this, &SeerGdbWidget::handleGdbWatchpointDisable); QObject::connect(watchpointsBrowserWidget, &SeerWatchpointsBrowserWidget::insertWatchpoint, this, &SeerGdbWidget::handleGdbWatchpointInsert); QObject::connect(watchpointsBrowserWidget, &SeerWatchpointsBrowserWidget::selectedFile, editorManagerWidget, &SeerEditorManagerWidget::handleOpenFile); QObject::connect(this, &SeerGdbWidget::stoppingPointReached, stackManagerWidget->stackFramesBrowserWidget(), &SeerStackFramesBrowserWidget::handleStoppingPointReached); QObject::connect(this, &SeerGdbWidget::stoppingPointReached, stackManagerWidget->stackLocalsBrowserWidget(), &SeerStackLocalsBrowserWidget::handleStoppingPointReached); QObject::connect(this, &SeerGdbWidget::stoppingPointReached, stackManagerWidget->stackArgumentsBrowserWidget(), &SeerStackArgumentsBrowserWidget::handleStoppingPointReached); QObject::connect(this, &SeerGdbWidget::stoppingPointReached, threadManagerWidget->threadIdsBrowserWidget(), &SeerThreadIdsBrowserWidget::handleStoppingPointReached); QObject::connect(this, &SeerGdbWidget::stoppingPointReached, threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::handleStoppingPointReached); QObject::connect(this, &SeerGdbWidget::stoppingPointReached, variableManagerWidget->registerValuesBrowserWidget(), &SeerRegisterValuesBrowserWidget::handleStoppingPointReached); QObject::connect(this, &SeerGdbWidget::stoppingPointReached, variableManagerWidget->variableTrackerBrowserWidget(), &SeerVariableTrackerBrowserWidget::handleStoppingPointReached); QObject::connect(this, &SeerGdbWidget::stoppingPointReached, breakpointsBrowserWidget, &SeerBreakpointsBrowserWidget::handleStoppingPointReached); QObject::connect(this, &SeerGdbWidget::stoppingPointReached, watchpointsBrowserWidget, &SeerWatchpointsBrowserWidget::handleStoppingPointReached); } SeerGdbWidget::~SeerGdbWidget () { deleteConsole(); if (_gdbMonitor) { delete _gdbMonitor; } if (_gdbProcess) { _gdbProcess->kill(); _gdbProcess->waitForFinished(); delete _gdbProcess; } } GdbMonitor* SeerGdbWidget::gdbMonitor () { return _gdbMonitor; } QProcess* SeerGdbWidget::gdbProcess () { return _gdbProcess; } void SeerGdbWidget::setExecutableName (const QString& executableName) { _executableName = executableName; } const QString& SeerGdbWidget::executableName () const { return _executableName; } void SeerGdbWidget::setExecutableArguments (const QString& executableArguments) { _executableArguments = executableArguments; } const QString& SeerGdbWidget::executableArguments () const { return _executableArguments; } void SeerGdbWidget::setExecutableWorkingDirectory (const QString& executableWorkingDirectory) { _executableWorkingDirectory = executableWorkingDirectory; } const QString& SeerGdbWidget::executableWorkingDirectory () const { return _executableWorkingDirectory; } void SeerGdbWidget::setExecutablePid (int pid) { _executablePid = pid; } int SeerGdbWidget::executablePid () const { return _executablePid; } void SeerGdbWidget::setExecutableHostPort (const QString& hostPort) { _executableHostPort = hostPort; } const QString& SeerGdbWidget::executableHostPort () const { return _executableHostPort; } void SeerGdbWidget::setExecutableCoreFilename (const QString& coreFilename) { _executableCoreFilename = coreFilename; } const QString& SeerGdbWidget::executableCoreFilename () const { return _executableCoreFilename; } void SeerGdbWidget::setExecutableLaunchMode (const QString& launchMode) { _executableLaunchMode = launchMode; } const QString& SeerGdbWidget::executableLaunchMode () const { return _executableLaunchMode; } void SeerGdbWidget::handleText (const QString& text) { if (text.startsWith("*running,thread-id=\"all\"")) { }else if (text.startsWith("*stopped,reason=\"breakpoint-hit\"")) { emit stoppingPointReached(); }else if (text.startsWith("*stopped,reason=\"watchpoint-trigger\"")) { emit stoppingPointReached(); }else if (text.startsWith("*stopped,reason=\"read-watchpoint-trigger\"")) { emit stoppingPointReached(); }else if (text.startsWith("*stopped,reason=\"access-watchpoint-trigger\"")) { emit stoppingPointReached(); }else if (text.startsWith("*stopped,reason=\"watchpoint-scope\"")) { emit stoppingPointReached(); }else if (text.startsWith("*stopped,hw-awpt={")) { emit stoppingPointReached(); }else if (text.startsWith("*stopped,reason=\"end-stepping-range\"")) { emit stoppingPointReached(); }else if (text.startsWith("*stopped,reason=\"function-finished\"")) { emit stoppingPointReached(); }else if (text.startsWith("*stopped,reason=\"location-reached\"")) { emit stoppingPointReached(); }else if (text.startsWith("*stopped,reason=\"signal-received\"")) { emit stoppingPointReached(); }else if (text.startsWith("*stopped,reason=\"exited-normally\"")) { emit stoppingPointReached(); }else if (text.startsWith("*stopped,reason=\"exited-signalled\"")) { emit stoppingPointReached(); }else if (text.startsWith("*stopped,reason=\"exited\"")) { emit stoppingPointReached(); }else{ // All other text is ignored by this widget. } } void SeerGdbWidget::handleExecute () { //qDebug() << __PRETTY_FUNCTION__ << ":" << "QComboBox: " << manualCommandComboBox->currentText(); QString command = manualCommandComboBox->currentText(); manualCommandComboBox->clearEditText(); handleGdbCommand(command); } void SeerGdbWidget::handleGdbCommand (const QString& command) { if (_gdbProcess->state() == QProcess::NotRunning) { QMessageBox::warning(this, "Seer", QString("The executable has not been started yet or has already exited.\n\n") + "(" + command + ")", QMessageBox::Ok); return; } QString str = command + "\n"; // Ensure there's a trailing RETURN. QByteArray bytes = str.toUtf8(); // 8-bit Unicode Transformation Format _gdbProcess->write(bytes); // Send the data into the stdin stream of the bash child process } void SeerGdbWidget::handleGdbExit () { handleGdbCommand("-gdb-exit"); } void SeerGdbWidget::handleGdbRunExecutable () { // Has a executable name been provided? if (executableName() == "") { QMessageBox::warning(this, "Seer", QString("The executable name has not been provided.\n\nUse File->Debug..."), QMessageBox::Ok); return; } // Delete old console. deleteConsole(); // Kill previous gdb, if any. if (isGdbRuning() == true) { killGdb(); } // If gdb isn't running, start it. if (isGdbRuning() == false) { startGdb(); handleGdbCommand("-gdb-set mi-async on"); // Turn on async mode so the 'interrupt' can happen. } // Create a new console. createConsole(); setExecutableLaunchMode("run"); handleGdbExecutableName(); // Load the program into the gdb process. handleGdbExecutableSources(); // Load the program source files. handleGdbExecutableSharedLibraries(); // Load the program shared libraries. handleGdbExecutableArguments(); // Set the program's arguments before running. handleGdbExecutableWorkingDirectory(); // Set the program's working directory before running. handleGdbTtyDeviceName(); // Set the program's tty device for stdin and stdout. handleGdbCommand("-exec-run"); } void SeerGdbWidget::handleGdbStartExecutable () { // Has a executable name been provided? if (executableName() == "") { QMessageBox::warning(this, "Seer", QString("The executable name has not been provided.\n\nUse File->Debug..."), QMessageBox::Ok); return; } // Delete old console. deleteConsole(); // Kill previous gdb, if any. if (isGdbRuning() == true) { killGdb(); } // If gdb isn't running, start it. if (isGdbRuning() == false) { startGdb(); handleGdbCommand("-gdb-set mi-async on"); // Turn on async mode so the 'interrupt' can happen. } // Create a new console. createConsole(); setExecutableLaunchMode("start"); handleGdbExecutableName(); // Load the program into the gdb process. handleGdbExecutableSources(); // Load the program source files. handleGdbExecutableSharedLibraries(); // Load the program shared libraries. handleGdbExecutableArguments(); // Set the program's arguments before running. handleGdbExecutableWorkingDirectory(); // Set the program's working directory before running. handleGdbTtyDeviceName(); // Set the program's tty device for stdin and stdout. handleGdbCommand("-exec-run --start"); } void SeerGdbWidget::handleGdbAttachExecutable () { // Has a executable name been provided? if (executableName() == "") { QMessageBox::warning(this, "Seer", QString("The executable name has not been provided.\n\nUse File->Debug..."), QMessageBox::Ok); return; } // Delete old console. deleteConsole(); // Kill previous gdb, if any. if (isGdbRuning() == true) { killGdb(); } // If gdb isn't running, start it. if (isGdbRuning() == false) { startGdb(); handleGdbCommand("-gdb-set mi-async on"); // Turn on async mode so the 'interrupt' can happen. } // Create a new console. createConsole(); setExecutableLaunchMode("attach"); handleGdbExecutableName(); // Load the program into the gdb process. handleGdbExecutableSources(); // Load the program source files. handleGdbExecutableSharedLibraries(); // Load the program shared libraries. handleGdbTtyDeviceName(); // Set the program's tty device for stdin and stdout. handleGdbCommand(QString("-target-attach %1").arg(executablePid())); } void SeerGdbWidget::handleGdbConnectExecutable () { // Has a executable name been provided? if (executableName() == "") { QMessageBox::warning(this, "Seer", QString("The executable name has not been provided.\n\nUse File->Debug..."), QMessageBox::Ok); return; } // Delete old console. deleteConsole(); // Kill previous gdb, if any. if (isGdbRuning() == true) { killGdb(); } // If gdb isn't running, start it. if (isGdbRuning() == false) { startGdb(); handleGdbCommand("-gdb-set mi-async on"); // Turn on async mode so the 'interrupt' can happen. } // Create a new console. createConsole(); setExecutableLaunchMode("connect"); handleGdbTtyDeviceName(); // Set the program's tty device for stdin and stdout. handleGdbCommand(QString("-target-select extended-remote %1").arg(executableHostPort())); handleGdbExecutableName(); // Load the program into the gdb process. handleGdbExecutableSources(); // Load the program source files. handleGdbExecutableSharedLibraries(); // Load the program shared libraries. handleGdbCommand("-target-download"); // "-file-symbol-file %s" // "-file-exec-file %s" // "-target-download" } void SeerGdbWidget::handleGdbCoreFileExecutable () { // Has a executable name been provided? if (executableName() == "") { QMessageBox::warning(this, "Seer", QString("The executable name has not been provided.\n\nUse File->Debug..."), QMessageBox::Ok); return; } // Delete old console. deleteConsole(); // Kill previous gdb, if any. if (isGdbRuning() == true) { killGdb(); } // If gdb isn't running, start it. if (isGdbRuning() == false) { startGdb(); handleGdbCommand("-gdb-set mi-async on"); // Turn on async mode so the 'interrupt' can happen. } // Create a new console. createConsole(); setExecutableLaunchMode("corefile"); handleGdbExecutableName(); // Load the program into the gdb process. handleGdbExecutableSources(); // Load the program source files. handleGdbExecutableSharedLibraries(); // Load the program shared libraries. handleGdbTtyDeviceName(); // Set the program's tty device for stdin and stdout. handleGdbCommand(QString("-target-select core %1").arg(executableCoreFilename())); } void SeerGdbWidget::handleGdbRunToLine (QString fullname, int lineno) { if (executableLaunchMode() == "") { return; } QString command = "-exec-until " + fullname + ":" + QString::number(lineno); handleGdbCommand(command); } void SeerGdbWidget::handleGdbNext () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-exec-next"); } void SeerGdbWidget::handleGdbStep () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-exec-step"); } void SeerGdbWidget::handleGdbFinish () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-exec-finish"); } void SeerGdbWidget::handleGdbContinue () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-exec-continue"); } void SeerGdbWidget::handleGdbInterrupt () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-exec-interrupt"); } void SeerGdbWidget::handleGdbExecutableSources () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-file-list-exec-source-files"); } void SeerGdbWidget::handleGdbExecutableSharedLibraries () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-file-list-shared-libraries"); } void SeerGdbWidget::handleGdbExecutableName () { if (executableLaunchMode() == "") { return; } handleGdbCommand(QString("-file-exec-and-symbols ") + executableName()); } void SeerGdbWidget::handleGdbExecutableArguments () { if (executableLaunchMode() == "") { return; } handleGdbCommand(QString("-exec-arguments ") + executableArguments()); } void SeerGdbWidget::handleGdbExecutableWorkingDirectory () { if (executableLaunchMode() == "") { return; } if (executableWorkingDirectory() != "") { handleGdbCommand(QString("-environment-cd ") + executableWorkingDirectory()); } } void SeerGdbWidget::handleGdbTtyDeviceName () { if (_consoleWidget->ttyDeviceName() != "") { //qDebug() << __PRETTY_FUNCTION__ << "Setting TTY name to" << _consoleWidget->ttyDeviceName(); handleGdbCommand(QString("-inferior-tty-set ") + _consoleWidget->ttyDeviceName()); } } void SeerGdbWidget::handleGdbStackListFrames () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-stack-list-frames"); } void SeerGdbWidget::handleGdbStackSelectFrame (int frameno) { if (executableLaunchMode() == "") { return; } handleGdbCommand(QString("-stack-select-frame %1").arg(frameno)); emit stoppingPointReached(); } void SeerGdbWidget::handleGdbStackListLocals () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-stack-list-variables --all-values"); } void SeerGdbWidget::handleGdbStackListArguments () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-stack-list-arguments --all-values"); } void SeerGdbWidget::handleGdbBreakpointWatchpointList () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-break-list"); } void SeerGdbWidget::handleGdbBreakpointDelete (QString breakpoints) { if (executableLaunchMode() == "") { return; } handleGdbCommand("-break-delete " + breakpoints); handleGdbBreakpointWatchpointList(); } void SeerGdbWidget::handleGdbBreakpointEnable (QString breakpoints) { if (executableLaunchMode() == "") { return; } handleGdbCommand("-break-enable " + breakpoints); handleGdbBreakpointWatchpointList(); } void SeerGdbWidget::handleGdbBreakpointDisable (QString breakpoints) { if (executableLaunchMode() == "") { return; } handleGdbCommand("-break-disable " + breakpoints); handleGdbBreakpointWatchpointList(); } void SeerGdbWidget::handleGdbBreakpointInsert (QString breakpoint) { if (executableLaunchMode() == "") { return; } handleGdbCommand("-break-insert " + breakpoint); handleGdbBreakpointWatchpointList(); } void SeerGdbWidget::handleGdbWatchpointDelete (QString watchpoints) { if (executableLaunchMode() == "") { return; } handleGdbCommand("-break-delete " + watchpoints); handleGdbBreakpointWatchpointList(); } void SeerGdbWidget::handleGdbWatchpointEnable (QString watchpoints) { if (executableLaunchMode() == "") { return; } handleGdbCommand("-break-enable " + watchpoints); handleGdbBreakpointWatchpointList(); } void SeerGdbWidget::handleGdbWatchpointDisable (QString watchpoints) { if (executableLaunchMode() == "") { return; } handleGdbCommand("-break-disable " + watchpoints); handleGdbBreakpointWatchpointList(); } void SeerGdbWidget::handleGdbWatchpointInsert (QString watchpoint) { if (executableLaunchMode() == "") { return; } handleGdbCommand("-break-watch " + watchpoint); handleGdbBreakpointWatchpointList(); } void SeerGdbWidget::handleGdbThreadListIds () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-thread-list-ids"); } void SeerGdbWidget::handleGdbThreadListFrames () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-thread-info"); } void SeerGdbWidget::handleGdbThreadSelectId (int threadid) { if (executableLaunchMode() == "") { return; } handleGdbCommand(QString("-thread-select %1").arg(threadid)); emit stoppingPointReached(); } void SeerGdbWidget::handleGdbRegisterListNames () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-data-list-register-names"); } void SeerGdbWidget::handleGdbRegisterListValues () { if (executableLaunchMode() == "") { return; } handleGdbCommand("-data-list-register-values N"); } void SeerGdbWidget::handleGdbDataEvaluateExpression (int expressionid, QString expression) { if (executableLaunchMode() == "") { return; } handleGdbCommand(QString::number(expressionid) + "-data-evaluate-expression \"" + expression + "\""); } void SeerGdbWidget::handleGdbDataListValues () { if (executableLaunchMode() == "") { return; } for (int i=0; i<_dataExpressionId.size(); i++) { handleGdbCommand(QString::number(_dataExpressionId[i]) + "-data-evaluate-expression \"" + _dataExpressionName[i] + "\""); } } void SeerGdbWidget::handleGdbDataListExpressions () { if (executableLaunchMode() == "") { return; } // ^done,DataExpressionTable={ // entry={id="2",expression="a"}, // entry={id="3",expression="i"} // } QString text; text += "^done,DataExpressionTable={"; for (int i=0; i<_dataExpressionId.size(); i++) { if (i != 0) { text += ","; } text += "entry={id=\"" + QString::number(_dataExpressionId[i]) + "\",expression=\"" + _dataExpressionName[i] + "\"}"; } text += "}"; gdbMonitor()->handleTextOutput(text); } void SeerGdbWidget::handleGdbDataAddExpression (QString expression) { if (executableLaunchMode() == "") { return; } // Is this one already present? // ??? Emit an error? if (_dataExpressionName.indexOf(expression) >= 0) { return; } // Add it to our list of variables. _dataExpressionName.push_back(expression); _dataExpressionId.push_back(Seer::createID()); // ^done,DataExpressionAdded={ // id="2", // expression="a" // } QString text = QString("^done,DataExpressionAdded={id=\"%1\",expression=\"%2\"}").arg(_dataExpressionId.back()).arg(_dataExpressionName.back()); //qDebug() << __PRETTY_FUNCTION__ << ":" << text; gdbMonitor()->handleTextOutput(text); } void SeerGdbWidget::handleGdbDataDeleteExpressions (QString expressionids) { if (executableLaunchMode() == "") { return; } // ^done,DataExpressionDeleted={ // entry={id="2", expression="a"}, // entry={id="3", expression="a"} // } QString text; text += "^done,DataExpressionDeleted={"; if (expressionids == "*") { bool first = true; for (int i=0; i<_dataExpressionId.size(); i++) { if (first == false) { text += ","; } text += "entry={id=\"" + QString::number(_dataExpressionId[i]) + "\",expression=\"" + _dataExpressionName[i] + "\"}"; first = false; } _dataExpressionId.clear(); _dataExpressionName.clear(); }else{ QStringList ids = expressionids.split(' ', QString::SkipEmptyParts); bool first = true; for (int i=0; ihandleTextOutput(text); } void SeerGdbWidget::handleGdbMemoryAddExpression (QString expression) { Q_UNUSED(expression); if (executableLaunchMode() == "") { return; } SeerMemoryVisualizerWidget* w = new SeerMemoryVisualizerWidget(0); w->show(); // Connect things. QObject::connect(_gdbMonitor, &GdbMonitor::astrixTextOutput, w, &SeerMemoryVisualizerWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, w, &SeerMemoryVisualizerWidget::handleText); QObject::connect(w, &SeerMemoryVisualizerWidget::evaluateVariableExpression, this, &SeerGdbWidget::handleGdbDataEvaluateExpression); QObject::connect(w, &SeerMemoryVisualizerWidget::evaluateMemoryExpression, this, &SeerGdbWidget::handleGdbMemoryEvaluateExpression); // Tell the visualizer what variable to use. w->setVariableName(expression); } void SeerGdbWidget::handleGdbMemoryEvaluateExpression (int expressionid, QString address, int count) { if (executableLaunchMode() == "") { return; } handleGdbCommand(QString::number(expressionid) + "-data-read-memory-bytes " + address + " " + QString::number(count)); } void SeerGdbWidget::handleFinished (int exitCode, QProcess::ExitStatus exitStatus) { Q_UNUSED(exitCode); Q_UNUSED(exitStatus); // For now, terminate Seer. qApp->exit(); } bool SeerGdbWidget::isGdbRuning () const { if (_gdbProcess->state() == QProcess::NotRunning) { return false; } return true; } void SeerGdbWidget::startGdb () { // Don't do anything, if already running. if (isGdbRuning()) { qDebug() << __PRETTY_FUNCTION__ << ":" << "Already running"; return; } // Build the gdb argument list. QStringList args; args << "-nh" << "--interpreter=mi"; // Give the gdb process the argument list. _gdbProcess->setArguments(args); // Set the gdb program name to use. _gdbProcess->setProgram("/usr/bin/gdb"); // Start the gdb process. _gdbProcess->start(); } void SeerGdbWidget::killGdb () { // Don't do anything, if already running. if (isGdbRuning() == false) { return; } // Kill the process. _gdbProcess->kill(); // Wait for it to end. _gdbProcess->waitForFinished(); // Sanity check. if (isGdbRuning()) { qDebug() << __PRETTY_FUNCTION__ << ":" << "Is running but shouldn't be."; } // Clear the launch mode. setExecutableLaunchMode(""); } void SeerGdbWidget::createConsole () { deleteConsole(); // Delete old console, if any. if (_consoleWidget == 0) { _consoleWidget = new SeerConsoleWidget(0); _consoleWidget->setWindowFlags(Qt::Window | Qt::WindowMinimizeButtonHint | Qt::WindowMaximizeButtonHint); _consoleWidget->show(); } } void SeerGdbWidget::deleteConsole () { if (_consoleWidget) { delete _consoleWidget; _consoleWidget = 0; } }