diff --git a/CHANGELOG.md b/CHANGELOG.md index 3c431570..e34b4977 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ * Source all files in ~/.config/seergdb/scripts/ on startup. * Fixed regression handling ignoring of system header files. * Fixed regression when adding commands to a breakpoint. +* Refactored/improved Printpoints. Added 'help' to the + Printpoint create dialog. ## [2.4] - 2024-03-18 * Changed main icon to a more license friendly one. diff --git a/src/SeerConfigDialog.cpp b/src/SeerConfigDialog.cpp index aa4521ee..a20adf8a 100644 --- a/src/SeerConfigDialog.cpp +++ b/src/SeerConfigDialog.cpp @@ -230,36 +230,6 @@ bool SeerConfigDialog::gdbEnablePrettyPrinting () const { return _gdbConfigPage->gdbEnablePrettyPrinting(); } -void SeerConfigDialog::setDprintfStyle (const QString& style) { - - _gdbConfigPage->setDprintfStyle(style); -} - -QString SeerConfigDialog::dprintfStyle () const { - - return _gdbConfigPage->dprintfStyle(); -} - -void SeerConfigDialog::setDprintfFunction (const QString& function) { - - _gdbConfigPage->setDprintfFunction(function); -} - -QString SeerConfigDialog::dprintfFunction () const { - - return _gdbConfigPage->dprintfFunction(); -} - -void SeerConfigDialog::setDprintfChannel (const QString& channel) { - - _gdbConfigPage->setDprintfChannel(channel); -} - -QString SeerConfigDialog::dprintfChannel () const { - - return _gdbConfigPage->dprintfChannel(); -} - void SeerConfigDialog::setEditorFont (const QFont& font) { _editorConfigPage->setEditorFont(font); diff --git a/src/SeerConfigDialog.h b/src/SeerConfigDialog.h index 22b5a209..75911de9 100644 --- a/src/SeerConfigDialog.h +++ b/src/SeerConfigDialog.h @@ -61,15 +61,6 @@ class SeerConfigDialog : public QDialog, protected Ui::SeerConfigDialogForm { void setGdbEnablePrettyPrinting (bool flag); bool gdbEnablePrettyPrinting () const; - void setDprintfStyle (const QString& style); - QString dprintfStyle () const; - - void setDprintfFunction (const QString& function); - QString dprintfFunction () const; - - void setDprintfChannel (const QString& channel); - QString dprintfChannel () const; - // Editor settings. void setEditorFont (const QFont& font); const QFont& editorFont () const; diff --git a/src/SeerEditorManagerWidget.cpp b/src/SeerEditorManagerWidget.cpp index 457677f2..14a0b430 100644 --- a/src/SeerEditorManagerWidget.cpp +++ b/src/SeerEditorManagerWidget.cpp @@ -1179,10 +1179,10 @@ void SeerEditorManagerWidget::handleInsertBreakpoint (QString breakpoint) { emit insertBreakpoint (breakpoint); } -void SeerEditorManagerWidget::handleInsertPrintpoint (QString printpoint) { +void SeerEditorManagerWidget::handleInsertPrintpoint (QString type, QString function, QString channel, QString parameters) { // rethrow - emit insertPrintpoint (printpoint); + emit insertPrintpoint (type, function, channel, parameters); } void SeerEditorManagerWidget::handleDeleteBreakpoints (QString breakpoints) { diff --git a/src/SeerEditorManagerWidget.h b/src/SeerEditorManagerWidget.h index 0ae1959c..b02dca59 100644 --- a/src/SeerEditorManagerWidget.h +++ b/src/SeerEditorManagerWidget.h @@ -71,7 +71,7 @@ class SeerEditorManagerWidget : public QWidget, protected Ui::SeerEditorManagerW void handleOpenFile (const QString& file, const QString& fullname, int lineno); void handleOpenAddress (const QString& address); void handleInsertBreakpoint (QString breakpoint); - void handleInsertPrintpoint (QString printpoint); + void handleInsertPrintpoint (QString type, QString function, QString channel, QString parameters); void handleDeleteBreakpoints (QString breakpoints); void handleEnableBreakpoints (QString breakpoints); void handleDisableBreakpoints (QString breakpoints); @@ -101,7 +101,7 @@ class SeerEditorManagerWidget : public QWidget, protected Ui::SeerEditorManagerW void refreshBreakpointsList (); void refreshStackFrames (); void insertBreakpoint (QString breakpoint); - void insertPrintpoint (QString printpoint); + void insertPrintpoint (QString type, QString function, QString channel, QString parameters); void deleteBreakpoints (QString breakpoints); void enableBreakpoints (QString breakpoints); void disableBreakpoints (QString breakpoints); diff --git a/src/SeerEditorWidgetSource.h b/src/SeerEditorWidgetSource.h index c0292479..4e1fae57 100644 --- a/src/SeerEditorWidgetSource.h +++ b/src/SeerEditorWidgetSource.h @@ -102,7 +102,7 @@ class SeerEditorWidgetSourceArea : public SeerPlainTextEdit { signals: void insertBreakpoint (QString breakpoint); - void insertPrintpoint (QString printpoint); + void insertPrintpoint (QString type, QString function, QString channel, QString parameters); void deleteBreakpoints (QString breakpoints); void enableBreakpoints (QString breakpoints); void disableBreakpoints (QString breakpoints); diff --git a/src/SeerEditorWidgetSourceAreas.cpp b/src/SeerEditorWidgetSourceAreas.cpp index 71b659b3..994d7430 100644 --- a/src/SeerEditorWidgetSourceAreas.cpp +++ b/src/SeerEditorWidgetSourceAreas.cpp @@ -1259,8 +1259,19 @@ void SeerEditorWidgetSourceArea::showContextMenu (const QPoint& pos, const QPoin return; } + // Build a printpoint specification. + QString type = dlg.dprintfType(); + QString function = dlg.dprintfFunction(); + QString channel = dlg.dprintfChannel(); + QString parameters = dlg.printpointParameters(); + + // If nothing, just return. + if (parameters == "" || type == "") { + return; + } + // Emit the create breakpoint signal. - emit insertPrintpoint(dlg.printpointText()); + emit insertPrintpoint(type, function, channel, parameters); return; } diff --git a/src/SeerGdbConfigPage.cpp b/src/SeerGdbConfigPage.cpp index 13b5b568..23ee5b1a 100644 --- a/src/SeerGdbConfigPage.cpp +++ b/src/SeerGdbConfigPage.cpp @@ -9,8 +9,7 @@ SeerGdbConfigPage::SeerGdbConfigPage(QWidget* parent) : QWidget(parent) { setupUi(this); // Connect things. - QObject::connect(gdbProgramToolButton, &QToolButton::clicked, this, &SeerGdbConfigPage::handleGdbProgramToolButton); - QObject::connect(styleButtonGroup, QOverload::of(&QButtonGroup::idClicked), this, &SeerGdbConfigPage::handleDprintfButtonGroup); + QObject::connect(gdbProgramToolButton, &QToolButton::clicked, this, &SeerGdbConfigPage::handleGdbProgramToolButton); // Setup the defaults. reset(); @@ -89,53 +88,6 @@ void SeerGdbConfigPage::setGdbEnablePrettyPrinting (bool flag) { gdbEnablePrettyPrintingCheckBox->setChecked(flag); } -QString SeerGdbConfigPage::dprintfStyle () const { - - if (styleGdbRadioButton->isChecked()) { - return "gdb"; - }else if (styleCallRadioButton->isChecked()) { - return "call"; - }else if (styleAgentRadioButton->isChecked()) { - return "agent"; - }else{ - return ""; - } -} - -QString SeerGdbConfigPage::dprintfFunction () const { - - return functionLineEdit->text(); -} - -QString SeerGdbConfigPage::dprintfChannel () const { - - return channelLineEdit->text(); -} - -void SeerGdbConfigPage::setDprintfStyle (const QString& style) { - - if (style == "gdb") { - styleGdbRadioButton->setChecked(true); - }else if (style == "call") { - styleCallRadioButton->setChecked(true); - }else if (style == "agent") { - styleAgentRadioButton->setChecked(true); - }else{ - } - - handleDprintfButtonGroup(); -} - -void SeerGdbConfigPage::setDprintfFunction (const QString& function) { - - functionLineEdit->setText(function); -} - -void SeerGdbConfigPage::setDprintfChannel (const QString& channel) { - - channelLineEdit->setText(channel); -} - void SeerGdbConfigPage::reset () { setGdbProgram("/usr/bin/gdb"); @@ -145,10 +97,6 @@ void SeerGdbConfigPage::reset () { setGdbHandleTerminatingException(true); setGdbRandomizeStartAddress(false); setGdbEnablePrettyPrinting(true); - - setDprintfStyle("gdb"); - setDprintfFunction("printf"); - setDprintfChannel(""); } void SeerGdbConfigPage::handleGdbProgramToolButton () { @@ -160,14 +108,3 @@ void SeerGdbConfigPage::handleGdbProgramToolButton () { } } -void SeerGdbConfigPage::handleDprintfButtonGroup () { - - functionLineEdit->setEnabled(false); - channelLineEdit->setEnabled(false); - - if (styleCallRadioButton->isChecked()) { - functionLineEdit->setEnabled(true); - channelLineEdit->setEnabled(true); - } -} - diff --git a/src/SeerGdbConfigPage.h b/src/SeerGdbConfigPage.h index fc67dd6c..fdc0f569 100644 --- a/src/SeerGdbConfigPage.h +++ b/src/SeerGdbConfigPage.h @@ -28,18 +28,9 @@ class SeerGdbConfigPage : public QWidget, protected Ui::SeerGdbConfigPage { void setGdbRandomizeStartAddress (bool flag); void setGdbEnablePrettyPrinting (bool flag); - QString dprintfStyle () const; - QString dprintfFunction () const; - QString dprintfChannel () const; - - void setDprintfStyle (const QString& style); - void setDprintfFunction (const QString& function); - void setDprintfChannel (const QString& channel); - void reset (); protected slots: void handleGdbProgramToolButton (); - void handleDprintfButtonGroup (); }; diff --git a/src/SeerGdbConfigPage.ui b/src/SeerGdbConfigPage.ui index 34ecad1c..e22df451 100644 --- a/src/SeerGdbConfigPage.ui +++ b/src/SeerGdbConfigPage.ui @@ -6,8 +6,8 @@ 0 0 - 792 - 870 + 603 + 470 @@ -20,142 +20,6 @@ 0 - - - - Printpoint/Dprintf Settings - - - - - - Style - - - - - - - Printpoint output goes the Gdb Ouput tab. - - - gdb - - - styleButtonGroup - - - - - - - Printpoint output goes to the Seer Console. - - - call - - - styleButtonGroup - - - - - - - Printpoint output is handled by the gdbserver. - - - agent - - - styleButtonGroup - - - - - - - Qt::Horizontal - - - - 561 - 20 - - - - - - - - Function - - - - - - - Channel - - - - - - - The name of a function in your program to use. - - - true - - - - - - - The channel value, if required by the function. - - - true - - - - - - - - - - <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> -<html><head><meta name="qrichtext" content="1" /><style type="text/css"> -p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Specify an alternate gdb program and alternate gdb flags. </span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Changing many of these require saving the new configuration and restarting Seer to take effect</span>.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note, Seer relies on the &quot;mi&quot; interpreter that is built into gdb. If a different debugger is used, it must provide that. So, usually, the &quot;--interpreter=mi&quot; argument is a must.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Async mode allows all gdb actions to happen in the background. This allows interrupting of a running program possible. Note, this is disabled for 'connect' mode as background commands may overwhelm the gdbserver.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Non-stop mode, when turned on, will allow other threads to continue to run while another thread reaches a breakpoint.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The gdb debugger normally starts the process at the same address each time. The program's start address can be randomized.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A terminating-exception can happen when gdb is asked to call a function in your program. Like printing the return value from a function. If the function throws an exception, gdb can handle it by suppressing the exception or allowing the program to terminate. See:</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace'; color:#24292f; background-color:transparent;"> unwind-on-terminating-exception on|off</span></p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enabling pretty-printing allows gdb to present certain variables (like std::string) in a pleasing way. Otherwise, the contents of the variables are presented in their full description. (See gdb 'pretty-printing'). Once enabled, it can not be turned off for the Seer session.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Printpoints use the 'dprintf' command available in gdb. The output of 'dprintf' can be sent to the Seer Console ('call') or the GDB output tab ('gdb'). A value of 'agent' is meant for use with a gdbserver.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">'Function' specifies what function to use when the style is 'call'. Typically it is 'printf'. Your program must provide the function. Most programs have 'printf' linked in. </p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">'Channel' specifies the alternate channel to use when the style is 'call'. For example, if 'Function' is &quot;fprintf&quot;, the 'Channel' would be the value to pass to the first argument of the 'fprintf' call. eg: &quot;fp&quot;. Again, your program needs to provied the channel variable.</p> -<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> - - - @@ -267,16 +131,43 @@ p, li { white-space: pre-wrap; } + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><meta charset="utf-8" /><style type="text/css"> +p, li { white-space: pre-wrap; } +hr { height: 1px; border-width: 0; } +li.unchecked::marker { content: "\2610"; } +li.checked::marker { content: "\2612"; } +</style></head><body style=" font-family:'Noto Sans'; font-size:10pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Specify an alternate gdb program and alternate gdb flags. </span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-weight:600;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-weight:600;">Changing many of these require saving the new configuration and restarting Seer to take effect</span>.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Note, Seer relies on the &quot;mi&quot; interpreter that is built into gdb. If a different debugger is used, it must provide that. So, usually, the &quot;--interpreter=mi&quot; argument is a must.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Async mode allows all gdb actions to happen in the background. This allows interrupting of a running program possible. Note, this is disabled for 'connect' mode as background commands may overwhelm the gdbserver.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Non-stop mode, when turned on, will allow other threads to continue to run while another thread reaches a breakpoint.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">The gdb debugger normally starts the process at the same address each time. The program's start address can be randomized.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">A terminating-exception can happen when gdb is asked to call a function in your program. Like printing the return value from a function. If the function throws an exception, gdb can handle it by suppressing the exception or allowing the program to terminate. See:</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'ui-monospace,SFMono-Regular,SF Mono,Menlo,Consolas,Liberation Mono,monospace'; color:#24292f; background-color:transparent;"> unwind-on-terminating-exception on|off</span></p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;">Enabling pretty-printing allows gdb to present certain variables (like std::string) in a pleasing way. Otherwise, the contents of the variables are presented in their full description. (See gdb 'pretty-printing'). Once enabled, it can not be turned off for the Seer session.</p> +<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html> + + + gdbGroupBox textBrowser - printPointGroupBox - - - diff --git a/src/SeerGdbWidget.cpp b/src/SeerGdbWidget.cpp index 338c1027..a0bfba8d 100644 --- a/src/SeerGdbWidget.cpp +++ b/src/SeerGdbWidget.cpp @@ -327,6 +327,7 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) { QObject::connect(_printpointsBrowserWidget, &SeerPrintpointsBrowserWidget::insertPrintpoint, this, &SeerGdbWidget::handleGdbPrintpointInsert); QObject::connect(_printpointsBrowserWidget, &SeerPrintpointsBrowserWidget::addBreakpointCondition, this, &SeerGdbWidget::handleGdbBreakpointCondition); QObject::connect(_printpointsBrowserWidget, &SeerPrintpointsBrowserWidget::addBreakpointIgnore, this, &SeerGdbWidget::handleGdbBreakpointIgnore); + QObject::connect(_printpointsBrowserWidget, &SeerPrintpointsBrowserWidget::addBreakpointCommand, this, &SeerGdbWidget::handleGdbBreakpointCommand); QObject::connect(this, &SeerGdbWidget::stoppingPointReached, stackManagerWidget->stackFramesBrowserWidget(), &SeerStackFramesBrowserWidget::handleStoppingPointReached); QObject::connect(this, &SeerGdbWidget::stoppingPointReached, stackManagerWidget->stackLocalsBrowserWidget(), &SeerStackLocalsBrowserWidget::handleStoppingPointReached); @@ -665,36 +666,6 @@ QString SeerGdbWidget::gdbRecordDirection () const { return _gdbRecordDirection; } -void SeerGdbWidget::setDprintfStyle (const QString& style) { - - _dprintfStyle = style; -} - -QString SeerGdbWidget::dprintfStyle () const { - - return _dprintfStyle; -} - -void SeerGdbWidget::setDprintfFunction (const QString& function) { - - _dprintfFunction = function; -} - -QString SeerGdbWidget::dprintfFunction () const { - - return _dprintfFunction; -} - -void SeerGdbWidget::setDprintfChannel (const QString& channel) { - - _dprintfChannel = channel; -} - -QString SeerGdbWidget::dprintfChannel () const { - - return _dprintfChannel; -} - SeerEditorManagerWidget* SeerGdbWidget::editorManager () { return editorManagerWidget; @@ -975,9 +946,6 @@ void SeerGdbWidget::handleGdbRunExecutable (const QString& breakMode) { handleGdbSourceScripts(); } - // Set dprint parameters. - resetDprintf(); - // Create a new console. // Set the program's tty device for stdin and stdout. createConsole(); @@ -1112,9 +1080,6 @@ void SeerGdbWidget::handleGdbAttachExecutable () { handleGdbSourceScripts(); } - // Set dprint parameters. - resetDprintf(); - // No console for 'attach' mode. setExecutableLaunchMode("attach"); setGdbRecordMode(""); @@ -1188,9 +1153,6 @@ void SeerGdbWidget::handleGdbConnectExecutable () { handleGdbSourceScripts(); } - // Set dprint parameters. - resetDprintf(); - // No console for 'connect' mode. setExecutableLaunchMode("connect"); setGdbRecordMode(""); @@ -1286,9 +1248,6 @@ void SeerGdbWidget::handleGdbRRExecutable () { } } - // Set dprint parameters. - resetDprintf(); - // Set the launch mode. setExecutableLaunchMode("rr"); setGdbRecordMode("rr"); @@ -1402,9 +1361,6 @@ void SeerGdbWidget::handleGdbCoreFileExecutable () { handleGdbSourceScripts(); } - // Set dprint parameters. - resetDprintf(); - // No console for 'core' mode. setExecutableLaunchMode("corefile"); setGdbRecordMode(""); @@ -1769,7 +1725,9 @@ void SeerGdbWidget::handleGdbExecutableFunctions (int id, const QString& functio //qDebug() << id << functionRegex; + QApplication::setOverrideCursor(Qt::BusyCursor); handleGdbCommand(QString("%1-symbol-info-functions --name %2").arg(id).arg(functionRegex)); + QApplication::restoreOverrideCursor(); } void SeerGdbWidget::handleGdbExecutableTypes (int id, const QString& typeRegex) { @@ -2035,6 +1993,18 @@ void SeerGdbWidget::handleGdbBreakpointIgnore (QString breakpoint, QString count handleGdbGenericpointList(); } +void SeerGdbWidget::handleGdbBreakpointCommand (QString breakpoint, QString command) { + + if (executableLaunchMode() == "") { + return; + } + + qDebug().noquote() << "XXX: " << breakpoint << command; + + handleGdbCommand("-break-commands " + breakpoint + " \"" + command + "\""); + handleGdbGenericpointList(); +} + void SeerGdbWidget::handleGdbBreakpointCommands (QString breakpoint, QStringList commands) { if (executableLaunchMode() == "") { @@ -2186,13 +2156,17 @@ void SeerGdbWidget::handleGdbPrintpointDisable (QString printpoints) { handleGdbGenericpointList(); } -void SeerGdbWidget::handleGdbPrintpointInsert (QString printpoint) { +void SeerGdbWidget::handleGdbPrintpointInsert (QString type, QString function, QString channel, QString parameters) { if (executableLaunchMode() == "") { return; } - handleGdbCommand("-dprintf-insert " + printpoint); + handleGdbCommand("-gdb-set dprintf-style " + type); + handleGdbCommand("-gdb-set dprintf-function " + function); + handleGdbCommand("-gdb-set dprintf-channel " + channel); + + handleGdbCommand("-dprintf-insert " + parameters); handleGdbGenericpointList(); } @@ -3094,17 +3068,6 @@ void SeerGdbWidget::readSettings () { } settings.endGroup(); } -void SeerGdbWidget::resetDprintf () { - - if (isGdbRuning() == false) { - return; - } - - handleGdbCommand("-gdb-set dprintf-style " + dprintfStyle()); - handleGdbCommand("-gdb-set dprintf-function " + dprintfFunction()); - handleGdbCommand("-gdb-set dprintf-channel " + dprintfChannel()); -} - bool SeerGdbWidget::isGdbRuning () const { if (_gdbProcess->state() == QProcess::NotRunning) { diff --git a/src/SeerGdbWidget.h b/src/SeerGdbWidget.h index 28fa96de..b08d371a 100644 --- a/src/SeerGdbWidget.h +++ b/src/SeerGdbWidget.h @@ -107,15 +107,6 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { void setGdbRecordDirection (const QString& direction); QString gdbRecordDirection () const; - void setDprintfStyle (const QString& style); - QString dprintfStyle () const; - - void setDprintfFunction (const QString& function); - QString dprintfFunction () const; - - void setDprintfChannel (const QString& channel); - QString dprintfChannel () const; - void setConsoleMode (const QString& mode); QString consoleMode () const; @@ -202,9 +193,6 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { void writeSettings (); void readSettings (); - // Printpoints - void resetDprintf (); - public slots: void handleLogsTabMoved (int from, int to); void handleLogsTabChanged (int index); @@ -276,6 +264,7 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { void handleGdbBreakpointInsert (QString breakpoint); void handleGdbBreakpointCondition (QString breakpoint, QString condition); void handleGdbBreakpointIgnore (QString breakpoint, QString count); + void handleGdbBreakpointCommand (QString breakpoint, QString commands); void handleGdbBreakpointCommands (QString breakpoint, QStringList commands); void handleGdbBreakpointReload (QStringList breakpointsText); void handleGdbWatchpointReload (QStringList watchpointsText); @@ -291,7 +280,7 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { void handleGdbPrintpointDelete (QString breakpoints); void handleGdbPrintpointEnable (QString breakpoints); void handleGdbPrintpointDisable (QString breakpoints); - void handleGdbPrintpointInsert (QString printpoint); + void handleGdbPrintpointInsert (QString type, QString function, QString channel, QString parameters); void handleGdbThreadListFrames (); void handleGdbThreadListIds (); void handleGdbThreadListGroups (); @@ -382,9 +371,6 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { bool _gdbEnablePrettyPrinting; QString _gdbRecordMode; QString _gdbRecordDirection; - QString _dprintfStyle; - QString _dprintfFunction; - QString _dprintfChannel; bool _assemblyShowAssemblyTabOnStartup; QString _assemblyDisassemblyFlavor; QString _assemblySymbolDemangling; diff --git a/src/SeerMainWindow.cpp b/src/SeerMainWindow.cpp index a6d6e486..deb3b78d 100644 --- a/src/SeerMainWindow.cpp +++ b/src/SeerMainWindow.cpp @@ -668,9 +668,6 @@ void SeerMainWindow::handleSettingsConfiguration () { 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.setEditorTabSize(gdbWidget->editorManager()->editorTabSize()); dlg.setEditorHighlighterSettings(gdbWidget->editorManager()->editorHighlighterSettings()); @@ -714,9 +711,6 @@ void SeerMainWindow::handleSettingsConfiguration () { 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()->setEditorTabSize(dlg.editorTabSize()); gdbWidget->editorManager()->setEditorHighlighterSettings(dlg.editorHighlighterSettings()); @@ -748,9 +742,6 @@ void SeerMainWindow::handleSettingsConfiguration () { gdbWidget->clearManualCommandHistory(); } - // Reset the dprintf, in case it was changed. - gdbWidget->resetDprintf(); - // Set the key shortcuts. setKeySettings(dlg.keySettings()); } @@ -1284,12 +1275,6 @@ void SeerMainWindow::writeConfigSettings () { settings.setValue("gdbarguments", gdbWidget->rrGdbArguments()); } 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()); @@ -1366,12 +1351,6 @@ void SeerMainWindow::readConfigSettings () { gdbWidget->setRRGdbArguments(settings.value("gdbarguments", "").toString()); } 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; diff --git a/src/SeerPrintpointCreateDialog.cpp b/src/SeerPrintpointCreateDialog.cpp index 8e60fa3e..ee73cf29 100644 --- a/src/SeerPrintpointCreateDialog.cpp +++ b/src/SeerPrintpointCreateDialog.cpp @@ -1,4 +1,5 @@ #include "SeerPrintpointCreateDialog.h" +#include "SeerHelpPageDialog.h" #include SeerPrintpointCreateDialog::SeerPrintpointCreateDialog (QWidget* parent) : QDialog(parent) { @@ -26,10 +27,16 @@ SeerPrintpointCreateDialog::SeerPrintpointCreateDialog (QWidget* parent) : QDial setFormat(""); setArguments(""); + setDPrintfType ("gdb"); + setDPrintfFunction (""); + setDPrintfChannel (""); + // Connect things. - QObject::connect(conditionalCheckBox, &QCheckBox::clicked, conditionalLineEdit, &QLineEdit::setEnabled); - QObject::connect(ignoreCountCheckBox, &QCheckBox::clicked, ignoreCountLineEdit, &QLineEdit::setEnabled); - QObject::connect(threadIdCheckBox, &QCheckBox::clicked, threadIdLineEdit, &QLineEdit::setEnabled); + QObject::connect(conditionalCheckBox, &QCheckBox::clicked, conditionalLineEdit, &QLineEdit::setEnabled); + QObject::connect(ignoreCountCheckBox, &QCheckBox::clicked, ignoreCountLineEdit, &QLineEdit::setEnabled); + QObject::connect(threadIdCheckBox, &QCheckBox::clicked, threadIdLineEdit, &QLineEdit::setEnabled); + QObject::connect(typeButtonGroup, &QButtonGroup::buttonClicked, this, &SeerPrintpointCreateDialog::handleDprintfTypeChanged); + QObject::connect(typeHelpToolButton, &QToolButton::clicked, this, &SeerPrintpointCreateDialog::handleHelpToolButtonClicked); } SeerPrintpointCreateDialog::~SeerPrintpointCreateDialog () { @@ -158,7 +165,72 @@ QString SeerPrintpointCreateDialog::arguments () const { return argumentsLineEdit->text(); } -QString SeerPrintpointCreateDialog::printpointText () const { +QString SeerPrintpointCreateDialog::dprintfType () const { + + if (typeGdbRadioButton->isChecked()) { + return "gdb"; + }else if (typeCallRadioButton->isChecked()) { + return "call"; + }else if (typeAgentRadioButton->isChecked()) { + return "agent"; + } + + // Default. + return "gdb"; +} + +QString SeerPrintpointCreateDialog::dprintfFunction () const { + + if (dprintfType() == "gdb") { + return ""; + } + + return dprintfFunctionLineEdit->text(); +} + +QString SeerPrintpointCreateDialog::dprintfChannel () const { + + if (dprintfType() == "gdb") { + return ""; + } + + return dprintfChannelLineEdit->text(); +} + +void SeerPrintpointCreateDialog::setDPrintfType (const QString& text) { + + if (text == "gdb") { + typeGdbRadioButton->setChecked(true); + dprintfFunctionLineEdit->setEnabled(false); + dprintfChannelLineEdit->setEnabled(false); + return; + }else if (text == "call") { + typeCallRadioButton->setChecked(true); + dprintfFunctionLineEdit->setEnabled(true); + dprintfChannelLineEdit->setEnabled(true); + return; + }else if (text == "agent") { + typeAgentRadioButton->setChecked(true); + dprintfFunctionLineEdit->setEnabled(false); + dprintfChannelLineEdit->setEnabled(false); + return; + } + + // Default. + typeGdbRadioButton->setChecked(true); + dprintfFunctionLineEdit->setEnabled(false); + dprintfChannelLineEdit->setEnabled(false); +} + +void SeerPrintpointCreateDialog::setDPrintfFunction (const QString& text) { + dprintfFunctionLineEdit->setText(text); +} + +void SeerPrintpointCreateDialog::setDPrintfChannel (const QString& text) { + dprintfChannelLineEdit->setText(text); +} + +QString SeerPrintpointCreateDialog::printpointParameters () const { // Build a printpoint specification. // @@ -234,3 +306,15 @@ QString SeerPrintpointCreateDialog::printpointText () const { return printpointParameters; } +void SeerPrintpointCreateDialog::handleDprintfTypeChanged () { + setDPrintfType(dprintfType()); +} + +void SeerPrintpointCreateDialog::handleHelpToolButtonClicked () { + + SeerHelpPageDialog* help = new SeerHelpPageDialog(this); + help->loadFile(":/seer/resources/help/Printpoints.md"); + help->show(); + help->raise(); +} + diff --git a/src/SeerPrintpointCreateDialog.h b/src/SeerPrintpointCreateDialog.h index 06da32c6..f5f5cc46 100644 --- a/src/SeerPrintpointCreateDialog.h +++ b/src/SeerPrintpointCreateDialog.h @@ -52,9 +52,21 @@ class SeerPrintpointCreateDialog : public QDialog, protected Ui::SeerPrintpointC QString format () const; QString arguments () const; - QString printpointText () const; + QString dprintfType () const; + QString dprintfFunction () const; + QString dprintfChannel () const; + + void setDPrintfType (const QString& text); + void setDPrintfFunction (const QString& text); + void setDPrintfChannel (const QString& text); + + QString printpointParameters () const; public slots: + void handleDprintfTypeChanged (); + + private slots: + void handleHelpToolButtonClicked (); private: }; diff --git a/src/SeerPrintpointCreateDialog.ui b/src/SeerPrintpointCreateDialog.ui index 5153a5ef..92253459 100644 --- a/src/SeerPrintpointCreateDialog.ui +++ b/src/SeerPrintpointCreateDialog.ui @@ -6,8 +6,8 @@ 0 0 - 557 - 473 + 607 + 635 @@ -106,9 +106,9 @@ - + - Printpoint Type + Printpoint Conditions @@ -259,6 +259,122 @@ + + + + Printpoint Type + + + + + + Type + + + + + + + Printpoint output goes the Gdb Ouput tab. + + + gdb + + + typeButtonGroup + + + + + + + Printpoint output goes to the Seer Console. + + + call + + + typeButtonGroup + + + + + + + Printpoint output is handled by the gdbserver. + + + agent + + + typeButtonGroup + + + + + + + Qt::Horizontal + + + + 561 + 20 + + + + + + + + Help about Printpoints. + + + ... + + + + :/seer/resources/RelaxLightIcons/help-about.svg:/seer/resources/RelaxLightIcons/help-about.svg + + + + + + + Function + + + + + + + The name of a function in your program to use. + + + true + + + + + + + Channel + + + + + + + The channel variable, if required by the function. + + + true + + + + + + @@ -271,7 +387,32 @@ - + + filenameLineEdit + lineNumberLineEdit + functionLineEdit + labelLineEdit + temporaryCheckBox + conditionalCheckBox + conditionalLineEdit + pendingCheckBox + ignoreCountCheckBox + ignoreCountLineEdit + disabledCheckBox + threadIdCheckBox + threadIdLineEdit + formatLineEdit + argumentsLineEdit + typeGdbRadioButton + typeCallRadioButton + typeAgentRadioButton + typeHelpToolButton + dprintfFunctionLineEdit + dprintfChannelLineEdit + + + + buttonBox @@ -306,4 +447,7 @@ + + + diff --git a/src/SeerPrintpointsBrowserWidget.cpp b/src/SeerPrintpointsBrowserWidget.cpp index 4a0fa29f..c5714545 100644 --- a/src/SeerPrintpointsBrowserWidget.cpp +++ b/src/SeerPrintpointsBrowserWidget.cpp @@ -49,6 +49,7 @@ SeerPrintpointsBrowserWidget::SeerPrintpointsBrowserWidget (QWidget* parent) : Q QObject::connect(disablePrintpointsToolButton, &QToolButton::clicked, this, &SeerPrintpointsBrowserWidget::handleDisableToolButton); QObject::connect(conditionBreakpointToolButton, &QToolButton::clicked, this, &SeerPrintpointsBrowserWidget::handleConditionToolButton); QObject::connect(ignoreBreakpointToolButton, &QToolButton::clicked, this, &SeerPrintpointsBrowserWidget::handleIgnoreToolButton); + QObject::connect(commandBreakpointToolButton, &QToolButton::clicked, this, &SeerPrintpointsBrowserWidget::handleCommandToolButton); } SeerPrintpointsBrowserWidget::~SeerPrintpointsBrowserWidget () { @@ -127,7 +128,7 @@ void SeerPrintpointsBrowserWidget::handleText (const QString& text) { QString file_text = Seer::parseFirst(bkpt_text, "file=", '"', '"', false); QString fullname_text = Seer::parseFirst(bkpt_text, "fullname=", '"', '"', false); QString line_text = Seer::parseFirst(bkpt_text, "line=", '"', '"', false); - QString script_text = Seer::parseFirst(bkpt_text, "script=", '{', '}', false); + QString script_text = Seer::parseFirst(bkpt_text, "script=", '[', ']', false); QString thread_groups_text = Seer::parseFirst(bkpt_text, "thread-groups=", '[', ']', false); QString cond_text = Seer::parseFirst(bkpt_text, "cond=", '"', '"', false); QString times_text = Seer::parseFirst(bkpt_text, "times=", '"', '"', false); @@ -139,7 +140,9 @@ void SeerPrintpointsBrowserWidget::handleText (const QString& text) { continue; } - script_text = Seer::filterBookends(Seer::parseCommaList(script_text, '{', '}'), '"', '"').join('\n'); + // Remove '"' bookends and then remove one level of escapes. + script_text = Seer::filterBookends (script_text, '"', '"'); + script_text = Seer::filterEscapes(script_text); // Add the level to the tree. QTreeWidgetItem* topItem = new QTreeWidgetItem; @@ -228,15 +231,18 @@ void SeerPrintpointsBrowserWidget::handleAddToolButton () { } // Build a printpoint specification. - QString printpointParameters = dlg.printpointText(); + QString type = dlg.dprintfType(); + QString function = dlg.dprintfFunction(); + QString channel = dlg.dprintfChannel(); + QString parameters = dlg.printpointParameters(); // If nothing, just return. - if (printpointParameters == "") { + if (parameters == "" || type == "") { return; } // Otherwise send the command to create the printpoint. - emit insertPrintpoint(printpointParameters); + emit insertPrintpoint(type, function, channel, parameters); } void SeerPrintpointsBrowserWidget::handleDeleteToolButton () { @@ -376,6 +382,35 @@ void SeerPrintpointsBrowserWidget::handleIgnoreToolButton () { emit addBreakpointIgnore(printpoint, QString::number(count)); } +void SeerPrintpointsBrowserWidget::handleCommandToolButton () { + + // Get selected tree items. Only allow one. + QList items = printpointsTreeWidget->selectedItems(); + + if (items.count() == 0) { + return; + } + + if (items.count() > 1) { + QMessageBox::warning(this, "Seer", "Select only one printpoint when editing the command.", QMessageBox::Ok); + return; + } + + // Get the ignore text. + bool ok; + QString command = QInputDialog::getText(this, "Seer", "Enter the command to execute for this printpoint.", QLineEdit::Normal, items.front()->text(9), &ok); + + if (ok == false) { + return; + } + + // Get the selected breakpoint number. + QString breakpoint = items.front()->text(0); + + // Send the signal. + emit addBreakpointCommand(breakpoint, command); +} + void SeerPrintpointsBrowserWidget::showEvent (QShowEvent* event) { QWidget::showEvent(event); diff --git a/src/SeerPrintpointsBrowserWidget.h b/src/SeerPrintpointsBrowserWidget.h index 7821bded..97818bab 100644 --- a/src/SeerPrintpointsBrowserWidget.h +++ b/src/SeerPrintpointsBrowserWidget.h @@ -29,6 +29,7 @@ class SeerPrintpointsBrowserWidget : public QWidget, protected Ui::SeerPrintpoin void handleDisableToolButton (); void handleConditionToolButton (); void handleIgnoreToolButton (); + void handleCommandToolButton (); signals: void refreshPrintpointsList (); @@ -37,7 +38,8 @@ class SeerPrintpointsBrowserWidget : public QWidget, protected Ui::SeerPrintpoin void disablePrintpoints (QString printpoints); void addBreakpointCondition (QString printpoint, QString condition); void addBreakpointIgnore (QString printpoint, QString count); - void insertPrintpoint (QString printpoint); + void addBreakpointCommand (QString breakpoint, QString command); + void insertPrintpoint (QString type, QString function, QString channel, QString parameters); void selectedFile (QString file, QString fullname, int lineno); protected: diff --git a/src/SeerPrintpointsBrowserWidget.ui b/src/SeerPrintpointsBrowserWidget.ui index 99050110..12104423 100644 --- a/src/SeerPrintpointsBrowserWidget.ui +++ b/src/SeerPrintpointsBrowserWidget.ui @@ -13,8 +13,8 @@ Form - - + + @@ -72,7 +72,7 @@ - DPrintf + Command @@ -102,8 +102,8 @@ - - + + @@ -180,6 +180,20 @@ + + + + Edit command to selected breakpoint. + + + ... + + + + :/seer/resources/RelaxLightIcons/go-next.svg:/seer/resources/RelaxLightIcons/go-next.svg + + + diff --git a/src/resource.qrc b/src/resource.qrc index a767d273..61fd2afb 100644 --- a/src/resource.qrc +++ b/src/resource.qrc @@ -77,6 +77,7 @@ resources/help/ConnectDebugMode.md resources/help/RRDebugMode.md resources/help/CorefileDebugMode.md + resources/help/Printpoints.md diff --git a/src/resources/help/Printpoints.md b/src/resources/help/Printpoints.md new file mode 100644 index 00000000..bd535627 --- /dev/null +++ b/src/resources/help/Printpoints.md @@ -0,0 +1,133 @@ +## Printpoints + +### Introduction + +Printpoints are a type of gdb breakpoint that simply prints a custom message when the breakpoint +is reached. After the message is printed, the program is continued automatically. + +So, basically, a way to add print statements without adding them to your code. + +### Printpoint types + +There are 3 types of printpoints. + + +### 'gdb' printpoints + +The ```gdb``` printpoint is the most common. When used, it uses gdb's ```printf``` command, which +provides C style formatting. + +Consider this example of code: +``` + 12 + 13 std::cout << " C++ loop" << std::endl; + 14 for (n=1; n<=count; n++) { + 15 nfact = nfact * n; + 16 std::cout << std::setw(12) << n << std::setw(14) << nfact << std::endl; + 17 } + 18 +``` +A printpoint can be added to line 15 to print the value of ```n``` and ```count```. Create a +printpoint by RMB clicking on line 15 of source, or click 'Add a new printpoint' in the Printpoints +tab. Fill in the name of the source file and the line number. + +Now fill in the printpoint details: +``` +Format : "N=%d COUNT=%d\n" +Arguments : n count +Type : gdb +Function : +Channel : +``` + +When you run your program, the print statements will appear in Seer's Gdb tab. + +### 'call' printpoints + +The ```call``` printpoint type allows you to use an alternate ```print``` function instead of gdb's +```printf``` command. + +There are a couple restrictions for this ```print``` function. + +- Must have a signature that takes VA_ARGS. +- Needs to be part of your program. ie: linked in or part of some .so, like glibc. + +There are 2 ```call``` methods. One without a "channel" and one with a "channel". What is a "channel"? +It's like the first argument to ```fprintf()```, or ```dprintf()``` + +*** + +Here is an example of ```call``` without a "channel". It will use ```printf()``` from glibc. + +We'll use the same code example and will add the printpoint on the same line number. +``` +Format : "N=%d COUNT=%d\n" +Arguments : n count +Type : call +Function : printf +Channel : +``` + +When you run your program, the print statements will appear in Seer's Console tab. + +*** + +Here is an example of ```call``` ***with*** a "channel". It will use ```dprintf()``` from glibc, +which takes a file descriptor as its first argument. We'll be using FD of 1, which is stdout. + +We'll use the same code example and will add the printpoint on the same line number. +``` +Format : "N=%d COUNT=%d\n" +Arguments : n count +Type : call +Function : dprintf +Channel : 1 +``` + +When you run your program, the print statements will appear in Seer's Console tab. + + +### 'agent' printpoints + +If your program is started with ```gdbserver```, a printpoint type of ```agent``` will tell the +gdbserver to print the message. + +First, start the program using ```gdbserver```. +``` +$ gdbserver :1234 hellodprintf +``` +Then start Seer and connect to the ```gdbserver```. + +We'll use the same code example and will add the printpoint on the same line number. +``` +Format : "N=%d COUNT=%d\n" +Arguments : n count +Type : agent +Function : +Channel : +``` +The print statements will appear from the ```gdbserver``` process. + +### Warnings + +Printpoints, actually ```dprintf```, are not very error friendly. Errors in your parameters are +not checked until the breakpoint is reached. This can cause gdb to behave poorly or can, most +likely, confuse Seer. You'll end up restarting your debugging session. + +The ```call``` method seems to work only with C/C++ code. It doesn't work with Fortran. Not sure +about any other language. The error message is very vague and appears in the Gdb tab as "parsing error". +Seer ends up in a confused state. + +### References + +Printpoints use gdb's ```dprintf``` command. Not to be confused with the C language's ```dprintf()``` +function. + +https://sourceware.org/gdb/current/onlinedocs/gdb.html/Output.html +https://sourceware.org/gdb/current/onlinedocs/gdb.html/Dynamic-Printf.html + +Here's a good article from Andreas Heck where he creates a custom ```print``` function that writes +to a file, instead of stdout. This works with a ```call``` printpoint without a channel. + +https://abstractexpr.com/2024/03/03/dynamic-printf-debugging-with-gdb/ + diff --git a/tests/hellodprintf/.gitignore b/tests/hellodprintf/.gitignore new file mode 100644 index 00000000..ff5d7a47 --- /dev/null +++ b/tests/hellodprintf/.gitignore @@ -0,0 +1,5 @@ +hellodprintf +hellodprintf_fortran +hellodprintf_call_channel +hellodprintf_call_nochannel +*.o diff --git a/tests/hellodprintf/Makefile b/tests/hellodprintf/Makefile new file mode 100644 index 00000000..9823f4b4 --- /dev/null +++ b/tests/hellodprintf/Makefile @@ -0,0 +1,34 @@ +.PHONY: all +all: hellodprintf hellodprintf_call_channel hellodprintf_call_nochannel hellodprintf_fortran + +hellodprintf.o: hellodprintf.cpp + g++ -c -g hellodprintf.cpp + +hellodprintf_fortran.o: hellodprintf_fortran.cpp + g++ -c -g hellodprintf_fortran.cpp + +hellodprintf_call_channel.o: hellodprintf_call_channel.cpp + g++ -c -g hellodprintf_call_channel.cpp + +hellodprintf_call_nochannel.o: hellodprintf_call_nochannel.cpp + g++ -c -g hellodprintf_call_nochannel.cpp + +fortran_function.o: fortran_function.f + gfortran -c -g fortran_function.f + +hellodprintf: hellodprintf.o hellodprintf_fortran.o fortran_function.o + g++ -g -o hellodprintf hellodprintf.o fortran_function.o -lgfortran + +hellodprintf_call_channel: hellodprintf_call_channel.o + g++ -g -o hellodprintf_call_channel hellodprintf_call_channel.o + +hellodprintf_call_nochannel: hellodprintf_call_nochannel.o + g++ -g -o hellodprintf_call_nochannel hellodprintf_call_nochannel.o + +hellodprintf_fortran: hellodprintf_fortran.o fortran_function.o + g++ -g -o hellodprintf_fortran hellodprintf_fortran.o fortran_function.o -lgfortran + +.PHONY: clean +clean: + rm -f hellodprintf hellodprintf_call_channel hellodprintf_call_nochannel hellodprintf_fortran *.o + diff --git a/tests/hellodprintf/breakpoints_call_channel.seer b/tests/hellodprintf/breakpoints_call_channel.seer new file mode 100644 index 00000000..baeb974c --- /dev/null +++ b/tests/hellodprintf/breakpoints_call_channel.seer @@ -0,0 +1,3 @@ +break -source /nas/erniep/Development/seer/tests/hellodprintf/hellodprintf_call_channel.cpp -line 9 +break -source /nas/erniep/Development/seer/tests/hellodprintf/hellodprintf_call_channel.cpp -line 23 +dprintf -source /nas/erniep/Development/seer/tests/hellodprintf/hellodprintf_call_channel.cpp -line 18,"C: n=%d count=%d\n",n,count diff --git a/tests/hellodprintf/breakpoints_call_nochannel.seer b/tests/hellodprintf/breakpoints_call_nochannel.seer new file mode 100644 index 00000000..79c7d3d9 --- /dev/null +++ b/tests/hellodprintf/breakpoints_call_nochannel.seer @@ -0,0 +1,3 @@ +dprintf -source /nas/erniep/Development/seer/tests/hellodprintf/hellodprintf_call_nochannel.cpp -line 40,"C: n=%d count=%d\n",n,count +break -source /nas/erniep/Development/seer/tests/hellodprintf/hellodprintf_call_nochannel.cpp -line 27 +break -source /nas/erniep/Development/seer/tests/hellodprintf/hellodprintf_call_nochannel.cpp -line 47 diff --git a/tests/hellodprintf/breakpoints_fortran.seer b/tests/hellodprintf/breakpoints_fortran.seer new file mode 100644 index 00000000..3d217808 --- /dev/null +++ b/tests/hellodprintf/breakpoints_fortran.seer @@ -0,0 +1,3 @@ +break -source /nas/erniep/Development/seer/tests/hellodprintf/hellodprintf_fortran.cpp -line 13 +break -source /nas/erniep/Development/seer/tests/hellodprintf/hellodprintf_fortran.cpp -line 17 +dprintf -source /nas/erniep/Development/seer/tests/hellodprintf/fortran_function.f -line 11,"FORT: n=%d count=%d\n",n,count diff --git a/tests/hellodprintf/breakpoints_gdb.seer b/tests/hellodprintf/breakpoints_gdb.seer new file mode 100644 index 00000000..b4782a58 --- /dev/null +++ b/tests/hellodprintf/breakpoints_gdb.seer @@ -0,0 +1,3 @@ +break -source /nas/erniep/Development/seer/tests/hellodprintf/hellodprintf.cpp -line 9 +break -source /nas/erniep/Development/seer/tests/hellodprintf/hellodprintf.cpp -line 20 +dprintf -source /nas/erniep/Development/seer/tests/hellodprintf/hellodprintf.cpp -line 15,"C: n=%d count=%d\n",n,count diff --git a/tests/hellodprintf/fortran_function.f b/tests/hellodprintf/fortran_function.f new file mode 100644 index 00000000..b02f3d8b --- /dev/null +++ b/tests/hellodprintf/fortran_function.f @@ -0,0 +1,17 @@ + subroutine FORTRANFUNCTION(count) + + implicit none + integer :: count + integer :: nfact = 1 + integer :: n + + ! compute factorials + print*, "Fortran loop" + do n = 1, count + nfact = nfact * n + ! printing the value of n and its factorial + print*, n, " ", nfact + end do + + return + end diff --git a/tests/hellodprintf/hellodprintf.cpp b/tests/hellodprintf/hellodprintf.cpp new file mode 100644 index 00000000..2bac7440 --- /dev/null +++ b/tests/hellodprintf/hellodprintf.cpp @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include + +int main (int argc, char** argv) { + + int count = 10; + int nfact = 1; + int n; + + std::cout << " C++ loop" << std::endl; + for (n=1; n<=count; n++) { + nfact = nfact * n; + // printing the value of n and its factorial + std::cout << std::setw(12) << n << std::setw(14) << nfact << std::endl; + } + + return 0; +} + diff --git a/tests/hellodprintf/hellodprintf_call_channel.cpp b/tests/hellodprintf/hellodprintf_call_channel.cpp new file mode 100644 index 00000000..f0bfa2df --- /dev/null +++ b/tests/hellodprintf/hellodprintf_call_channel.cpp @@ -0,0 +1,25 @@ +#include +#include +#include +#include +#include + +int main (int argc, char** argv) { + + int count = 10; + int nfact = 1; + int n; + + // Add the 'dprintf' function to the program's symbol + // table. So we can use it for gdb's 'dprintf' breakpoints. + dprintf(1, " C++ loop\n"); + + for (n=1; n<=count; n++) { + nfact = nfact * n; + // printing the value of n and its factorial + std::cout << std::setw(12) << n << std::setw(14) << nfact << std::endl; + } + + return 0; +} + diff --git a/tests/hellodprintf/hellodprintf_call_nochannel.cpp b/tests/hellodprintf/hellodprintf_call_nochannel.cpp new file mode 100644 index 00000000..d6dfc59c --- /dev/null +++ b/tests/hellodprintf/hellodprintf_call_nochannel.cpp @@ -0,0 +1,49 @@ +#include +#include +#include +#include +#include + +FILE* logfile = NULL; + +extern "C" { + int log_msg (const char* format, ...) { + int n; + va_list args; + // init the variable length argument list + va_start(args, format); + + n = vfprintf(logfile, format, args); + + // cleanup the variable length argument list + va_end(args); + + return n; + } +} + +int main (int argc, char** argv) { + + const char* filename = "logfile.txt"; + logfile = fopen(filename, "w"); + if (logfile == NULL) { + fprintf(stderr, "Failed to open logfile: %s\n", filename); + return 1; + } + + int count = 10; + int nfact = 1; + int n; + + std::cout << " C++ loop" << std::endl; + for (n=1; n<=count; n++) { + nfact = nfact * n; + // printing the value of n and its factorial + std::cout << std::setw(12) << n << std::setw(14) << nfact << std::endl; + } + + fclose(logfile); + + return 0; +} + diff --git a/tests/hellodprintf/hellodprintf_fortran.cpp b/tests/hellodprintf/hellodprintf_fortran.cpp new file mode 100644 index 00000000..2784505c --- /dev/null +++ b/tests/hellodprintf/hellodprintf_fortran.cpp @@ -0,0 +1,19 @@ +#include +#include +#include +#include +#include + +extern "C" { + void fortranfunction_ (int* count); +} + +int main (int argc, char** argv) { + + int count = 10; + + fortranfunction_(&count); + + return 0; +} + diff --git a/tests/hellogdbserver/breakpoints.seer b/tests/hellogdbserver/breakpoints.seer new file mode 100644 index 00000000..2c8f180e --- /dev/null +++ b/tests/hellogdbserver/breakpoints.seer @@ -0,0 +1,4 @@ +break -source /nas/erniep/Development/seer/tests/hellogdbserver/hellogdbserver.c -line 127 +break -source /nas/erniep/Development/seer/tests/hellogdbserver/hellogdbserver.c -line 116 +catch rethrow +awatch x diff --git a/tests/hellostruct/breakpoints.seer b/tests/hellostruct/breakpoints.seer new file mode 100644 index 00000000..696632c1 --- /dev/null +++ b/tests/hellostruct/breakpoints.seer @@ -0,0 +1,8 @@ +watch argc +disable $bpnum +rwatch argc + ignore $bpnum 3 +awatch argc + commands + print argc + end diff --git a/tests/helloworld/tracepoints.seer b/tests/helloworld/tracepoints.seer new file mode 100644 index 00000000..f3fbe52b --- /dev/null +++ b/tests/helloworld/tracepoints.seer @@ -0,0 +1,5 @@ +tvariable $trace_timestamp +trace /nas/erniep/Development/seer/tests/helloworld/helloworld.cpp:19 + commands + collect i, argc, argv[i] + end