diff --git a/src/SeerPrintpointCreateDialog.cpp b/src/SeerPrintpointCreateDialog.cpp index 676a2a2..ee73cf2 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) { @@ -35,6 +36,7 @@ SeerPrintpointCreateDialog::SeerPrintpointCreateDialog (QWidget* parent) : QDial 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 () { @@ -308,3 +310,11 @@ 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 cf84dc3..f5f5cc4 100644 --- a/src/SeerPrintpointCreateDialog.h +++ b/src/SeerPrintpointCreateDialog.h @@ -65,6 +65,9 @@ class SeerPrintpointCreateDialog : public QDialog, protected Ui::SeerPrintpointC public slots: void handleDprintfTypeChanged (); + private slots: + void handleHelpToolButtonClicked (); + private: }; diff --git a/src/resource.qrc b/src/resource.qrc index a767d27..61fd2af 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 0000000..bd53562 --- /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/ +