mirror of
https://github.com/epasveer/seer.git
synced 2026-08-29 08:34:42 +08:00
Finished skip command, for now.
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
* Optionally add a timestamp to the Seer and Gdb log widgets.
|
||||
* Add 'gdbserver debug' checkbox to Connect launch tab. For showing
|
||||
gdb and gdbserver communication debug information in gdb tab.
|
||||
* Manage gdb skip commands via a new Skip Browser.
|
||||
|
||||
## [2.5] - 2024-12-24
|
||||
* Console now supports a subset of ANSI color codes.
|
||||
|
||||
@@ -1011,6 +1011,7 @@ void SeerGdbWidget::handleGdbRunExecutable (const QString& breakMode) {
|
||||
handleGdbCommand("-gdb-set non-stop off");
|
||||
}
|
||||
|
||||
handleGdbLoadMICommands();
|
||||
handleGdbSourceScripts();
|
||||
}
|
||||
|
||||
@@ -1145,6 +1146,7 @@ void SeerGdbWidget::handleGdbAttachExecutable () {
|
||||
handleGdbCommand("-gdb-set mi-async on"); // Turn on async mode so the 'interrupt' can happen.
|
||||
}
|
||||
|
||||
handleGdbLoadMICommands();
|
||||
handleGdbSourceScripts();
|
||||
}
|
||||
|
||||
@@ -1219,6 +1221,7 @@ void SeerGdbWidget::handleGdbConnectExecutable () {
|
||||
break;
|
||||
}
|
||||
|
||||
handleGdbLoadMICommands();
|
||||
handleGdbSourceScripts();
|
||||
}
|
||||
|
||||
@@ -1434,6 +1437,7 @@ void SeerGdbWidget::handleGdbCoreFileExecutable () {
|
||||
handleGdbCommand("-gdb-set mi-async on"); // Turn on async mode so the 'interrupt' can happen.
|
||||
}
|
||||
|
||||
handleGdbLoadMICommands();
|
||||
handleGdbSourceScripts();
|
||||
}
|
||||
|
||||
@@ -3663,6 +3667,58 @@ void SeerGdbWidget::handleGdbForkFollowMode (QString mode) {
|
||||
}
|
||||
}
|
||||
|
||||
void SeerGdbWidget::handleGdbLoadMICommands () {
|
||||
|
||||
// Don't do anything, if isn't running.
|
||||
if (isGdbRuning() == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Path the MI files in the resources.
|
||||
QString miPath = ":/seer/resources/mi-python/"; // Resource file path
|
||||
|
||||
QDir miDirectory(miPath);
|
||||
|
||||
if (!miDirectory.exists()) {
|
||||
qDebug() << "Directory does not exist:" << miPath;
|
||||
return;
|
||||
}
|
||||
|
||||
// Get list of MI files.
|
||||
QFileInfoList miList = miDirectory.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries);
|
||||
|
||||
// Print the list.
|
||||
qDebug() << "Sourcing scripts from:" << miPath;
|
||||
foreach (QFileInfo miInfo, miList) {
|
||||
|
||||
// Open the source file from resources.
|
||||
QFile miFile(miInfo.absoluteFilePath());
|
||||
if (!miFile.exists()) {
|
||||
qDebug() << "Resource file" << miInfo << "does not exist!";
|
||||
continue;
|
||||
}
|
||||
|
||||
// Destination file path in /tmp.
|
||||
QString destinationPath = "/tmp/" + miInfo.fileName();
|
||||
|
||||
// Copy to temp. Don't check return status. I don't think it works
|
||||
// if the source is in Resources.
|
||||
miFile.copy(destinationPath);
|
||||
|
||||
// Source it.
|
||||
if (QFile::exists(destinationPath) == false) {
|
||||
continue;
|
||||
}
|
||||
|
||||
qDebug() << "source " + miInfo.absoluteFilePath();
|
||||
|
||||
QString command = "source " + destinationPath;
|
||||
|
||||
handleGdbCommand(command);
|
||||
}
|
||||
qDebug() << "Done.";
|
||||
}
|
||||
|
||||
void SeerGdbWidget::handleGdbSourceScripts () {
|
||||
|
||||
// Don't do anything, if isn't running.
|
||||
|
||||
@@ -345,6 +345,7 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm {
|
||||
void handleGdbSchedulerLockingMode (QString mode);
|
||||
void handleGdbScheduleMultipleMode (QString mode);
|
||||
void handleGdbForkFollowMode (QString mode);
|
||||
void handleGdbLoadMICommands ();
|
||||
void handleGdbSourceScripts ();
|
||||
|
||||
void handleGdbProcessFinished (int exitCode, QProcess::ExitStatus exitStatus);
|
||||
|
||||
@@ -1004,6 +1004,9 @@ void SeerMainWindow::handleText (const QString& text) {
|
||||
}else if (text.startsWith("^done,ada-exceptions={") && text.endsWith("}")) {
|
||||
return;
|
||||
|
||||
}else if (text.startsWith("^done,skips=[") && text.endsWith("]")) {
|
||||
return;
|
||||
|
||||
}else if (text.contains(QRegularExpression("^([0-9]+)\\^done"))) {
|
||||
return;
|
||||
|
||||
|
||||
@@ -79,6 +79,8 @@
|
||||
<file>resources/help/CorefileDebugMode.md</file>
|
||||
<file>resources/help/Printpoints.md</file>
|
||||
<file>resources/help/Skips.md</file>
|
||||
<file>resources/mi-python/MIEcho.py</file>
|
||||
<file>resources/mi-python/MISkip.py</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ Seer presents this information in three tabs:
|
||||
* Statics
|
||||
* Libraries
|
||||
* Ada exceptions
|
||||
* Skips
|
||||
|
||||
### Source
|
||||
|
||||
@@ -108,10 +109,30 @@ This information is shown for each exception:
|
||||
There is a button to quickly create a catchpoint for a selected exception. Once created, Seer will
|
||||
stop the program when the exception is raised.
|
||||
|
||||
### Skip commands
|
||||
|
||||
This browser manages the gdb skip commands you might have set up. A skip will bypass entering a function
|
||||
when the 'step' command is used. Skips can be described in various ways - filename, function name, and with
|
||||
glob wildcarding or regex. See the 'gdb skip' reference below.
|
||||
|
||||
This information is shown for each exception:
|
||||
```
|
||||
Column Description
|
||||
---------- -------------------------------------------------
|
||||
Number The skip's interal number.
|
||||
Enable Is the skip enabled?
|
||||
Glob Is the skip a file glob wildcard?
|
||||
File The name of the file. Can be <none> if the skip is a function.
|
||||
RE Is the skip a function regex?
|
||||
Function The name of the function. Can be <none> if the skip is a file.
|
||||
```
|
||||
Skips can be: added, deleted, enabled, or disabled. As well, they can be saved to Seer's settings or loaded.
|
||||
|
||||
### References
|
||||
|
||||
Consult these references
|
||||
|
||||
1. [Link](https://en.wikipedia.org/wiki/Regular_expression) Regular expressions.
|
||||
2. [Link](https://en.wikipedia.org/wiki/Glob_(programming)) Unix wildcards.
|
||||
3. [Link](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Skipping-Over-Functions-and-Files.html) GDB Skip command.
|
||||
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
#
|
||||
# Gdb's own custon Python MI command.
|
||||
#
|
||||
# https://sourceware.org/gdb/current/onlinedocs/gdb.html/GDB_002fMI-Commands-In-Python.html#GDB_002fMI-Commands-In-Python
|
||||
# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Basic-Python.html#Basic-Python
|
||||
#
|
||||
|
||||
class MIEcho(gdb.MICommand):
|
||||
"""Echo arguments passed to the command."""
|
||||
|
||||
def __init__(self, name, mode):
|
||||
self._mode = mode
|
||||
super(MIEcho, self).__init__(name)
|
||||
|
||||
def invoke(self, argv):
|
||||
if self._mode == 'dict':
|
||||
return { 'dict': { 'argv' : argv } }
|
||||
elif self._mode == 'list':
|
||||
return { 'list': argv }
|
||||
else:
|
||||
return { 'string': ", ".join(argv) }
|
||||
|
||||
|
||||
MIEcho("-echo-dict", "dict")
|
||||
MIEcho("-echo-list", "list")
|
||||
MIEcho("-echo-string", "string")
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
import re
|
||||
|
||||
#
|
||||
# Python MI command to manage gdb's "skip" command..
|
||||
#
|
||||
# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Skipping-Over-Functions-and-Files.html
|
||||
#
|
||||
|
||||
class MISkip(gdb.MICommand):
|
||||
"""
|
||||
Run the 'skip' command.
|
||||
|
||||
-skip-list List all skips, including the id for each skip.
|
||||
-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.
|
||||
-skip-create-rfunction Functions whose name matches regexp will be skipped over when stepping.
|
||||
|
||||
See: https://sourceware.org/gdb/current/onlinedocs/gdb.html/Skipping-Over-Functions-and-Files.html
|
||||
"""
|
||||
|
||||
def __init__(self, name, mode):
|
||||
self._mode = mode
|
||||
super(MISkip, self).__init__(name)
|
||||
|
||||
def invoke(self, argv):
|
||||
if self._mode == "list":
|
||||
|
||||
skipentries = []
|
||||
|
||||
result = gdb.execute ("info skip " + " ".join(argv), to_string=True)
|
||||
|
||||
lines = result.split("\n")
|
||||
for line in lines:
|
||||
if (line == ""):
|
||||
continue
|
||||
|
||||
columns = re.search(r"^(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(\S+)\s+(.*)$", line)
|
||||
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)
|
||||
skipmeta["glob"] = columns.group(3)
|
||||
skipmeta["file"] = columns.group(4)
|
||||
skipmeta["re"] = columns.group(5)
|
||||
skipmeta["function"] = columns.group(6)
|
||||
|
||||
skipentries.append(skipmeta)
|
||||
|
||||
return { "skips": skipentries}
|
||||
|
||||
elif self._mode == "delete":
|
||||
gdb.execute ("skip delete " + " ".join(argv), to_string=True)
|
||||
return None
|
||||
elif self._mode == "enable":
|
||||
gdb.execute ("skip enable " + " ".join(argv), to_string=True)
|
||||
return None
|
||||
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)
|
||||
return None
|
||||
elif self._mode == "creategfile":
|
||||
gdb.execute ("skip -gfile \"" + " ".join(argv) + "\"", to_string=True)
|
||||
return None
|
||||
elif self._mode == "createfunction":
|
||||
gdb.execute ("skip -function \"" + " ".join(argv) + "\"", to_string=True)
|
||||
return None
|
||||
elif self._mode == "createrfunction":
|
||||
gdb.execute ("skip -rfunction \"" + " ".join(argv) + "\"", to_string=True)
|
||||
return None
|
||||
else:
|
||||
raise gdb.GdbError("skips: Invalid parameter: %s" % self._mode)
|
||||
|
||||
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")
|
||||
MISkip("-skip-create-rfunction", "createrfunction")
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
#
|
||||
# Gdb's own custon Python MI command.
|
||||
#
|
||||
# https://sourceware.org/gdb/current/onlinedocs/gdb.html/GDB_002fMI-Commands-In-Python.html#GDB_002fMI-Commands-In-Python
|
||||
# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Basic-Python.html#Basic-Python
|
||||
#
|
||||
|
||||
class MIEcho(gdb.MICommand):
|
||||
"""Echo arguments passed to the command."""
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import re
|
||||
|
||||
#
|
||||
# Python MI command to manage gdb's "skip" command..
|
||||
#
|
||||
# https://sourceware.org/gdb/current/onlinedocs/gdb.html/Skipping-Over-Functions-and-Files.html
|
||||
#
|
||||
|
||||
class MISkip(gdb.MICommand):
|
||||
"""
|
||||
Run the 'skip' command.
|
||||
|
||||
Reference in New Issue
Block a user