Fixed a bunch of things.

This commit is contained in:
Ernie Pasveer
2025-03-30 14:29:20 -05:00
parent b12e9d25b1
commit 81a09d3bb4
13 changed files with 451 additions and 29 deletions
+2
View File
@@ -99,6 +99,7 @@ set(HEADER_FILES
SeerTypeBrowserWidget.h
SeerStaticBrowserWidget.h
SeerSkipBrowserWidget.h
SeerSkipCreateDialog.h
SeerSourceSymbolLibraryManagerWidget.h
SeerStackArgumentsBrowserWidget.h
SeerStackFramesBrowserWidget.h
@@ -199,6 +200,7 @@ set(SOURCE_FILES
SeerTypeBrowserWidget.cpp
SeerStaticBrowserWidget.cpp
SeerSkipBrowserWidget.cpp
SeerSkipCreateDialog.cpp
SeerSourceSymbolLibraryManagerWidget.cpp
SeerStackArgumentsBrowserWidget.cpp
SeerStackFramesBrowserWidget.cpp
+22
View File
@@ -231,6 +231,7 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) {
QObject::connect(sourceLibraryManagerWidget->adaExceptionsBrowserWidget(), &SeerAdaExceptionsBrowserWidget::refreshAdaExceptions, this, &SeerGdbWidget::handleGdbAdaListExceptions);
QObject::connect(sourceLibraryManagerWidget->adaExceptionsBrowserWidget(), &SeerAdaExceptionsBrowserWidget::insertCatchpoint, this, &SeerGdbWidget::handleGdbCatchpointInsert);
QObject::connect(sourceLibraryManagerWidget->skipBrowserWidget(), &SeerSkipBrowserWidget::refreshSkipList, this, &SeerGdbWidget::handleGdbListSkips);
QObject::connect(sourceLibraryManagerWidget->skipBrowserWidget(), &SeerSkipBrowserWidget::addSkip, this, &SeerGdbWidget::handleGdbAddSkip);
QObject::connect(sourceLibraryManagerWidget->skipBrowserWidget(), &SeerSkipBrowserWidget::deleteSkips, this, &SeerGdbWidget::handleGdbDeleteSkips);
QObject::connect(sourceLibraryManagerWidget->skipBrowserWidget(), &SeerSkipBrowserWidget::enableSkips, this, &SeerGdbWidget::handleGdbEnableSkips);
QObject::connect(sourceLibraryManagerWidget->skipBrowserWidget(), &SeerSkipBrowserWidget::disableSkips, this, &SeerGdbWidget::handleGdbDisableSkips);
@@ -2310,6 +2311,27 @@ void SeerGdbWidget::handleGdbListSkips () {
handleGdbCommand("-skip-list");
}
void SeerGdbWidget::handleGdbAddSkip (QString skipmode, QString skipparameters) {
if (executableLaunchMode() == "") {
return;
}
if (skipmode == "file") {
handleGdbCommand("-skip-create-file " + skipparameters);
}else if (skipmode == "gfile") {
handleGdbCommand("-skip-create-gfile " + skipparameters);
}else if (skipmode == "function") {
handleGdbCommand("-skip-create-function " + skipparameters);
}else if (skipmode == "rfunction") {
handleGdbCommand("-skip-create-rfunction " + skipparameters);
}else{
return;
}
handleGdbListSkips();
}
void SeerGdbWidget::handleGdbDeleteSkips (QString skipids) {
if (executableLaunchMode() == "") {
+1
View File
@@ -300,6 +300,7 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm {
void handleGdbAdaListTasks ();
void handleGdbAdaListExceptions ();
void handleGdbListSkips ();
void handleGdbAddSkip (QString skipmode, QString skipparameters);
void handleGdbDeleteSkips (QString skipids);
void handleGdbEnableSkips (QString skipids);
void handleGdbDisableSkips (QString skipids);
+2 -3
View File
@@ -408,13 +408,12 @@ void SeerMemoryVisualizerWidget::handlePrintButton () {
QPrinter printer;
QPrintDialog* dlg = new QPrintDialog(&printer, this);
QPrintDialog dialog(&printer, this);
if (dlg->exec() != QDialog::Accepted) {
if (dialog.exec() != QDialog::Accepted) {
return;
}
// Make a copy so we can temporarily add a header.
QTextDocument* clone = 0;
+24 -5
View File
@@ -1,12 +1,8 @@
#include "SeerSkipBrowserWidget.h"
#include "SeerSkipCreateDialog.h"
#include "SeerUtl.h"
#include <QtWidgets/QTreeWidget>
#include <QtWidgets/QTreeWidgetItemIterator>
#include <QtWidgets/QLabel>
#include <QtWidgets/QApplication>
#include <QtCore/QFileInfo>
#include <QtCore/Qt>
#include <QtCore/QMap>
#include <QtCore/QDebug>
SeerSkipBrowserWidget::SeerSkipBrowserWidget (QWidget* parent) : QWidget(parent) {
@@ -26,6 +22,7 @@ SeerSkipBrowserWidget::SeerSkipBrowserWidget (QWidget* parent) : QWidget(parent)
skipTreeWidget->setSortingEnabled(false);
// Connect things.
QObject::connect(skipAddToolButton, &QToolButton::clicked, this, &SeerSkipBrowserWidget::handleAddToolButton);
QObject::connect(skipDeleteToolButton, &QToolButton::clicked, this, &SeerSkipBrowserWidget::handleDeleteToolButton);
QObject::connect(skipEnableToolButton, &QToolButton::clicked, this, &SeerSkipBrowserWidget::handleEnableToolButton);
QObject::connect(skipDisableToolButton, &QToolButton::clicked, this, &SeerSkipBrowserWidget::handleDisableToolButton);
@@ -89,6 +86,28 @@ void SeerSkipBrowserWidget::handleText (const QString& text) {
QApplication::restoreOverrideCursor();
}
void SeerSkipBrowserWidget::handleAddToolButton () {
// Create the dialog.
SeerSkipCreateDialog dialog(this);
// Execute it.
if (dialog.exec() != QDialog::Accepted) {
return;
}
// Get result.
QString mode = dialog.skipMode();
QString parameters = dialog.skipParameters();
if (mode == "" || parameters == "") {
return;
}
// Send the 'add skip' command.
emit addSkip(mode, parameters);
}
void SeerSkipBrowserWidget::handleDeleteToolButton () {
// Get selected tree items.
+2
View File
@@ -17,12 +17,14 @@ class SeerSkipBrowserWidget : public QWidget, protected Ui::SeerSkipBrowserWidge
void refresh ();
protected slots:
void handleAddToolButton ();
void handleDeleteToolButton ();
void handleEnableToolButton ();
void handleDisableToolButton ();
signals:
void refreshSkipList ();
void addSkip (const QString& skipMode, const QString& skipParameters);
void deleteSkips (const QString& skips);
void enableSkips (const QString& skips);
void disableSkips (const QString& skips);
-17
View File
@@ -91,23 +91,6 @@
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="skipHelpToolButton">
<property name="enabled">
<bool>true</bool>
</property>
<property name="toolTip">
<string>Help on skips.</string>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/seer/resources/RelaxLightIcons/help-about.svg</normaloff>:/seer/resources/RelaxLightIcons/help-about.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item row="1" column="0">
+92
View File
@@ -0,0 +1,92 @@
#include "SeerSkipCreateDialog.h"
#include "SeerHelpPageDialog.h"
#include <QtCore/QDebug>
SeerSkipCreateDialog::SeerSkipCreateDialog (QWidget* parent) : QDialog(parent) {
// Set up the UI.
setupUi(this);
// Setup the widgets
fileRadioButton->setChecked(true);
fileRadioButton->setFocus();
// Connect things.
QObject::connect(modeButtonGroup, QOverload<int>::of(&QButtonGroup::idClicked), this, &SeerSkipCreateDialog::handleModeButtonGroup);
QObject::connect(helpToolButton, &QToolButton::clicked, this, &SeerSkipCreateDialog::handleHelpToolButton);
handleModeButtonGroup();
}
SeerSkipCreateDialog::~SeerSkipCreateDialog () {
}
void SeerSkipCreateDialog::handleModeButtonGroup () {
// Disable all text fields. We'll enable one later.
fileLineEdit->setEnabled(false);
fileGlobLineEdit->setEnabled(false);
functionLineEdit->setEnabled(false);
functionRegexLineEdit->setEnabled(false);
// Enable the one that is selected.
QAbstractButton* button = modeButtonGroup->checkedButton();
if (button == dynamic_cast<QAbstractButton*>(fileRadioButton)) {
fileLineEdit->setEnabled(true);
} else if (button == dynamic_cast<QAbstractButton*>(fileGlobRadioButton)) {
fileGlobLineEdit->setEnabled(true);
} else if (button == dynamic_cast<QAbstractButton*>(functionRadioButton)) {
functionLineEdit->setEnabled(true);
} else if (button == dynamic_cast<QAbstractButton*>(functionRegexRadioButton)) {
functionRegexLineEdit->setEnabled(true);
}
}
void SeerSkipCreateDialog::handleHelpToolButton () {
SeerHelpPageDialog* help = new SeerHelpPageDialog(this);
help->loadFile(":/seer/resources/help/Skips.md");
help->show();
help->raise();
}
QString SeerSkipCreateDialog::skipMode () const {
// Build a catchpoint specification.
QString skipMode;
if (fileRadioButton->isChecked()) {
skipMode = "file";
}else if (fileGlobRadioButton->isChecked()) {
skipMode = "gfile";
}else if (functionRadioButton->isChecked()) {
skipMode = "function";
}else if (functionRegexRadioButton->isChecked()) {
skipMode = "rfunction";
}
qDebug() << skipMode;
return skipMode;
}
QString SeerSkipCreateDialog::skipParameters () const {
// Build a catchpoint specification.
QString skipParameters;
if (fileRadioButton->isChecked()) {
skipParameters = fileLineEdit->text();
}else if (fileGlobRadioButton->isChecked()) {
skipParameters = fileGlobLineEdit->text();
}else if (functionRadioButton->isChecked()) {
skipParameters = functionLineEdit->text();
}else if (functionRegexRadioButton->isChecked()) {
skipParameters = functionRegexLineEdit->text();
}
qDebug() << skipParameters;
return skipParameters;
}
+26
View File
@@ -0,0 +1,26 @@
#pragma once
#include <QtWidgets/QDialog>
#include <QtCore/QString>
#include "ui_SeerSkipCreateDialog.h"
class SeerSkipCreateDialog : public QDialog, protected Ui::SeerSkipCreateDialogForm {
Q_OBJECT
public:
explicit SeerSkipCreateDialog (QWidget* parent = 0);
~SeerSkipCreateDialog ();
QString skipMode () const;
QString skipParameters () const;
public slots:
private slots:
void handleModeButtonGroup ();
void handleHelpToolButton ();
private:
};
+200
View File
@@ -0,0 +1,200 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>SeerSkipCreateDialogForm</class>
<widget class="QDialog" name="SeerSkipCreateDialogForm">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>471</width>
<height>253</height>
</rect>
</property>
<property name="windowTitle">
<string>Create a Skip</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="label">
<property name="text">
<string>Specify Skip details.</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>348</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QToolButton" name="helpToolButton">
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/seer/resources/RelaxLightIcons/help-about.svg</normaloff>:/seer/resources/RelaxLightIcons/help-about.svg</iconset>
</property>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="QRadioButton" name="fileRadioButton">
<property name="text">
<string>Filename</string>
</property>
<attribute name="buttonGroup">
<string notr="true">modeButtonGroup</string>
</attribute>
</widget>
</item>
<item row="0" column="1">
<widget class="QLineEdit" name="fileLineEdit">
<property name="placeholderText">
<string>file</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QRadioButton" name="fileGlobRadioButton">
<property name="text">
<string>Filename (glob)</string>
</property>
<attribute name="buttonGroup">
<string notr="true">modeButtonGroup</string>
</attribute>
</widget>
</item>
<item row="1" column="1">
<widget class="QLineEdit" name="fileGlobLineEdit">
<property name="placeholderText">
<string>file-glob-pattern</string>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QRadioButton" name="functionRadioButton">
<property name="text">
<string>Function </string>
</property>
<attribute name="buttonGroup">
<string notr="true">modeButtonGroup</string>
</attribute>
</widget>
</item>
<item row="2" column="1">
<widget class="QLineEdit" name="functionLineEdit">
<property name="placeholderText">
<string>linespec</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QRadioButton" name="functionRegexRadioButton">
<property name="text">
<string>Function (regex)</string>
</property>
<attribute name="buttonGroup">
<string notr="true">modeButtonGroup</string>
</attribute>
</widget>
</item>
<item row="3" column="1">
<widget class="QLineEdit" name="functionRegexLineEdit">
<property name="placeholderText">
<string>regex</string>
</property>
</widget>
</item>
<item row="4" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>17</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>fileRadioButton</tabstop>
<tabstop>fileGlobRadioButton</tabstop>
<tabstop>functionRadioButton</tabstop>
<tabstop>functionRegexRadioButton</tabstop>
<tabstop>fileLineEdit</tabstop>
<tabstop>fileGlobLineEdit</tabstop>
<tabstop>functionLineEdit</tabstop>
<tabstop>functionRegexLineEdit</tabstop>
<tabstop>helpToolButton</tabstop>
</tabstops>
<resources>
<include location="resource.qrc"/>
</resources>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>SeerSkipCreateDialogForm</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>SeerSkipCreateDialogForm</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
<buttongroups>
<buttongroup name="modeButtonGroup"/>
</buttongroups>
</ui>
+1
View File
@@ -78,6 +78,7 @@
<file>resources/help/RRDebugMode.md</file>
<file>resources/help/CorefileDebugMode.md</file>
<file>resources/help/Printpoints.md</file>
<file>resources/help/Skips.md</file>
</qresource>
</RCC>
+68
View File
@@ -0,0 +1,68 @@
## Skips
### Introduction
Skips are gdb's way of ignoring non-important arguments that are functions when stepping into a function to debug.
For example, consider this code:
```
101 int func()
102 {
103 foo(boring());
104 bar(boring());
105 }
```
` `
Suppose you wish to step into the functions ```foo``` and ```bar```, but you are not interested in stepping through ```boring```.
If you run ```step``` at line 103, youll enter ```boring()```, but if you run ```next```, youll step over both ```foo``` and ```boring```!
One solution is to ```step``` into ```boring``` and use the ```finish``` command to immediately exit it. But this can become tedious if ```boring``` is called from many places.
A more flexible solution is to tell gdb to execute ```boring``` with out stepping into it. The ```skip``` command does this.
### Skip types
There are 4 types of skips.
#### 'file' skips
This skip takes a single source file. All functions descriped in the file will be skipped when stepping.
#### 'file glob-pattern' skips
Functions in files matching file-glob-pattern will be skipped over when stepping.
#### 'function' skips
This skip takes a single function specification (see the Location-Specifications link below).
This function will be skipped when stepping.
#### 'function regex' skips
Functions whose name matches regexp will be skipped over when stepping.
This form is useful for complex function names. For example, there is generally no need to step into C++ std::string constructors or destructors.
Plus with C++ templates it can be hard to write out the full name of the function, and often it doesnt matter what the template arguments are.
Specifying the function to be skipped as a regular expression makes this easier.
```
^std::(allocator|basic_string)<.*>::~?\1 *\(
```
` `
If you want to skip every templated C++ constructor and destructor in the std namespace you can do:
```
^std::([a-zA-z0-9_]+)<.*>::~?\1 *\(
```
` `
### References
Here is gdb's reference for the ```skip``` command.
https://sourceware.org/gdb/current/onlinedocs/gdb.html/Skipping-Over-Functions-and-Files.html
https://sourceware.org/gdb/current/onlinedocs/gdb.html/Location-Specifications.html#Location-Specifications
Here's a good article from "MaskRay" where he describes skips in an easy to understand way.
https://maskray.me/blog/2024-12-30-skipping-boring-functions-in-debuggers
` `
+11 -4
View File
@@ -8,6 +8,7 @@ class MISkip(gdb.MICommand):
-skip-delete Delete a list of skip id's.
-skip-enable Enable a list of skip id's.
-skip-disable Disable a list of skip id's.
-skip-create Functions described in manual syntax will be skipped over when stepping.
-skip-create-file Functions in file will be skipped over when stepping.
-skip-create-gfile Functions in files matching file-glob-pattern will be skipped over when stepping.
-skip-create-function Functions named by linespec or the function containing the line named by linespec will be skipped over when stepping.
@@ -36,6 +37,8 @@ class MISkip(gdb.MICommand):
if columns:
if (columns.group(1) == "Num"):
continue
if (columns.group(1) == "Not"):
continue
skipmeta = {}
skipmeta["number"] = columns.group(1)
skipmeta["enable"] = columns.group(2)
@@ -57,17 +60,20 @@ class MISkip(gdb.MICommand):
elif self._mode == "disable":
gdb.execute ("skip disable " + " ".join(argv), to_string=True)
return None
elif self._mode == "create":
gdb.execute ("skip \"" + " ".join(argv) + "\"", to_string=True)
return None
elif self._mode == "createfile":
gdb.execute ("skip -file " + " ".join(argv), to_string=True)
gdb.execute ("skip -file \"" + " ".join(argv) + "\"", to_string=True)
return None
elif self._mode == "creategfile":
gdb.execute ("skip -gfile " + " ".join(argv), to_string=True)
gdb.execute ("skip -gfile \"" + " ".join(argv) + "\"", to_string=True)
return None
elif self._mode == "createfunction":
gdb.execute ("skip -function " + " ".join(argv), to_string=True)
gdb.execute ("skip -function \"" + " ".join(argv) + "\"", to_string=True)
return None
elif self._mode == "createrfunction":
gdb.execute ("skip -ffunction " + " ".join(argv), to_string=True)
gdb.execute ("skip -ffunction \"" + " ".join(argv) + "\"", to_string=True)
return None
else:
raise gdb.GdbError("skips: Invalid parameter: %s" % self._mode)
@@ -76,6 +82,7 @@ MISkip("-skip-list", "list")
MISkip("-skip-delete", "delete")
MISkip("-skip-enable", "enable")
MISkip("-skip-disable", "disable")
MISkip("-skip-create", "create")
MISkip("-skip-create-file", "createfile")
MISkip("-skip-create-gfile", "creategfile")
MISkip("-skip-create-function", "createfunction")