diff --git a/notes/README.thread-groups b/notes/README.thread-groups index 6fef6af..2cf068f 100644 --- a/notes/README.thread-groups +++ b/notes/README.thread-groups @@ -1,6 +1,22 @@ -list-thread-groups + ^done,groups=[ + { + id="i1", + type="process", + pid="5424", + executable="/home/erniep/Development/Peak/src/seer/tests/helloinferior/helloinferior", + cores=["0"] + }, + { id="i2", + type="process", + pid="5432", + executable="/home/erniep/Development/Peak/src/seer/tests/helloinferior/helloinferior", + cores=["5"] + } + ] + ^done,groups=[ { id=\"i1\", @@ -11,8 +27,73 @@ } ] + ^done,groups=[ + { + id="i1", + type="process", + pid="3665", + executable="/home/erniep/Development/Peak/src/Apps/Explorer/explorer", + cores=["0","2","4","5","6","7"] + } + ] + + -list-thread-groups --recurse 1 + ^done,groups=[ + { + id="i1", + type="process", + pid="5424", + executable="/home/erniep/Development/Peak/src/seer/tests/helloinferior/helloinferior", + cores=["0"], + threads=[ + { + id="1", + target-id="process 5424", + name="helloinferior", + frame={ + level="0", + addr="0x0000000000400702", + func="main", + args=[], + file="helloinferior.c", + fullname="/home/erniep/Development/Peak/src/seer/tests/helloinferior/helloinferior.c", + line="11", + arch="i386:x86-64" + }, + state="stopped", + core="0" + } + ] + }, + + { + id="i2", + type="process", + pid="5432", + executable="/home/erniep/Development/Peak/src/seer/tests/helloinferior/helloinferior", + cores=["5"], + threads=[ + { + id="2", + target-id="process 5432", + name="helloinferior", + frame={ + level="0", + addr="0x00007ffff7147a68", + func="fork", + args=[], + from="/lib64/libc.so.6", + arch="i386:x86-64"}, + state="stopped", + core="5" + } + ] + } + ] + + ^done,groups=[ { id=\"i1\", diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6884f8b..241d077 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -72,6 +72,7 @@ set(HEADER_FILES SeerStackManagerWidget.h SeerThreadFramesBrowserWidget.h SeerThreadIdsBrowserWidget.h + SeerThreadGroupsBrowserWidget.h SeerThreadManagerWidget.h SeerGdbLogWidget.h SeerTildeLogWidget.h @@ -154,6 +155,7 @@ set(SOURCE_FILES SeerStackManagerWidget.cpp SeerThreadFramesBrowserWidget.cpp SeerThreadIdsBrowserWidget.cpp + SeerThreadGroupsBrowserWidget.cpp SeerThreadManagerWidget.cpp SeerGdbLogWidget.cpp SeerTildeLogWidget.cpp diff --git a/src/SeerGdbWidget.cpp b/src/SeerGdbWidget.cpp index 22cfe09..5910475 100644 --- a/src/SeerGdbWidget.cpp +++ b/src/SeerGdbWidget.cpp @@ -124,8 +124,6 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) { QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, stackManagerWidget->stackLocalsBrowserWidget(), &SeerStackLocalsBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, stackManagerWidget->stackArgumentsBrowserWidget(), &SeerStackArgumentsBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, stackManagerWidget, &SeerStackManagerWidget::handleText); - QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, threadManagerWidget->threadIdsBrowserWidget(), &SeerThreadIdsBrowserWidget::handleText); - QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, _breakpointsBrowserWidget, &SeerBreakpointsBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, _watchpointsBrowserWidget, &SeerWatchpointsBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, _catchpointsBrowserWidget, &SeerCatchpointsBrowserWidget::handleText); @@ -137,8 +135,12 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) { QObject::connect(_gdbMonitor, &GdbMonitor::astrixTextOutput, this, &SeerGdbWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::equalTextOutput, this, &SeerGdbWidget::handleText); + QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::equalTextOutput, threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::handleText); QObject::connect(_gdbMonitor, &GdbMonitor::astrixTextOutput, threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::handleText); + QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, threadManagerWidget->threadIdsBrowserWidget(), &SeerThreadIdsBrowserWidget::handleText); + QObject::connect(_gdbMonitor, &GdbMonitor::caretTextOutput, threadManagerWidget->threadGroupsBrowserWidget(), &SeerThreadGroupsBrowserWidget::handleText); + QObject::connect(_gdbMonitor, &GdbMonitor::equalTextOutput, threadManagerWidget->threadGroupsBrowserWidget(), &SeerThreadGroupsBrowserWidget::handleText); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::refreshBreakpointsList, this, &SeerGdbWidget::handleGdbGenericpointList); QObject::connect(editorManagerWidget, &SeerEditorManagerWidget::refreshStackFrames, this, &SeerGdbWidget::handleGdbStackListFrames); @@ -205,6 +207,7 @@ SeerGdbWidget::SeerGdbWidget (QWidget* parent) : QWidget(parent) { QObject::connect(threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::refreshThreadFrames, this, &SeerGdbWidget::handleGdbThreadListFrames); QObject::connect(threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::selectedFile, editorManagerWidget, &SeerEditorManagerWidget::handleOpenFile); QObject::connect(threadManagerWidget->threadFramesBrowserWidget(), &SeerThreadFramesBrowserWidget::selectedThread, this, &SeerGdbWidget::handleGdbThreadSelectId); + QObject::connect(threadManagerWidget->threadGroupsBrowserWidget(), &SeerThreadGroupsBrowserWidget::refreshThreadGroups, this, &SeerGdbWidget::handleGdbThreadListGroups); QObject::connect(threadManagerWidget, &SeerThreadManagerWidget::schedulerLockingModeChanged, this, &SeerGdbWidget::handleGdbSchedulerLockingMode); QObject::connect(threadManagerWidget, &SeerThreadManagerWidget::scheduleMultipleModeChanged, this, &SeerGdbWidget::handleGdbScheduleMultipleMode); QObject::connect(threadManagerWidget, &SeerThreadManagerWidget::forkFollowsModeChanged, this, &SeerGdbWidget::handleGdbForkFollowMode); @@ -1452,6 +1455,15 @@ void SeerGdbWidget::handleGdbPrintpointInsert (QString printpoint) { } +void SeerGdbWidget::handleGdbThreadListFrames () { + + if (executableLaunchMode() == "") { + return; + } + + handleGdbCommand("-thread-info"); +} + void SeerGdbWidget::handleGdbThreadListIds () { if (executableLaunchMode() == "") { @@ -1461,13 +1473,13 @@ void SeerGdbWidget::handleGdbThreadListIds () { handleGdbCommand("-thread-list-ids"); } -void SeerGdbWidget::handleGdbThreadListFrames () { +void SeerGdbWidget::handleGdbThreadListGroups () { if (executableLaunchMode() == "") { return; } - handleGdbCommand("-thread-info"); + handleGdbCommand("-list-thread-groups"); } void SeerGdbWidget::handleGdbThreadSelectId (int threadid) { diff --git a/src/SeerGdbWidget.h b/src/SeerGdbWidget.h index 015d226..4a60d50 100644 --- a/src/SeerGdbWidget.h +++ b/src/SeerGdbWidget.h @@ -211,8 +211,9 @@ class SeerGdbWidget : public QWidget, protected Ui::SeerGdbWidgetForm { void handleGdbPrintpointEnable (QString breakpoints); void handleGdbPrintpointDisable (QString breakpoints); void handleGdbPrintpointInsert (QString printpoint); - void handleGdbThreadListIds (); void handleGdbThreadListFrames (); + void handleGdbThreadListIds (); + void handleGdbThreadListGroups (); void handleGdbThreadSelectId (int threadid); void handleGdbRegisterListNames (); void handleGdbRegisterListValues (QString fmt); diff --git a/src/SeerMainWindow.cpp b/src/SeerMainWindow.cpp index f00670b..0078f73 100644 --- a/src/SeerMainWindow.cpp +++ b/src/SeerMainWindow.cpp @@ -643,6 +643,9 @@ void SeerMainWindow::handleText (const QString& text) { }else if (text.startsWith("^done,threads=[")) { return; + }else if (text.startsWith("^done,groups=[")) { + return; + }else if (text.startsWith("^done,register-names=[") && text.endsWith("]")) { return; diff --git a/src/SeerThreadGroupsBrowserWidget.cpp b/src/SeerThreadGroupsBrowserWidget.cpp new file mode 100644 index 0000000..9d2126b --- /dev/null +++ b/src/SeerThreadGroupsBrowserWidget.cpp @@ -0,0 +1,142 @@ +#include "SeerThreadGroupsBrowserWidget.h" +#include "SeerUtl.h" +#include +#include +#include +#include +#include + +SeerThreadGroupsBrowserWidget::SeerThreadGroupsBrowserWidget (QWidget* parent) : QWidget(parent) { + + // Construct the UI. + setupUi(this); + + // Setup the widgets + groupTreeWidget->setMouseTracking(true); + groupTreeWidget->setSortingEnabled(false); + groupTreeWidget->resizeColumnToContents(0); // id + groupTreeWidget->resizeColumnToContents(1); // type + groupTreeWidget->resizeColumnToContents(2); // pid + groupTreeWidget->resizeColumnToContents(3); // executable + groupTreeWidget->resizeColumnToContents(4); // cores + + groupTreeWidget->clear(); + + // Connect things. + QObject::connect(groupTreeWidget, &QTreeWidget::itemEntered, this, &SeerThreadGroupsBrowserWidget::handleItemEntered); +} + +SeerThreadGroupsBrowserWidget::~SeerThreadGroupsBrowserWidget () { +} + +void SeerThreadGroupsBrowserWidget::handleText (const QString& text) { + + // Don't do any work if the widget is hidden. + if (isHidden()) { + return; + } + + QApplication::setOverrideCursor(Qt::BusyCursor); + + if (text.startsWith("^done,groups=[")) { + + // ^done,groups=[ + // { + // id="i1", + // type="process", + // pid="5424", + // executable="/home/erniep/Development/Peak/src/seer/tests/helloinferior/helloinferior", + // cores=["0"] + // }, + // { id="i2", + // type="process", + // pid="5432", + // executable="/home/erniep/Development/Peak/src/seer/tests/helloinferior/helloinferior", + // cores=["5"] + // } + // ] + + //qDebug() << text; + + groupTreeWidget->clear(); + + QString groups_text = Seer::parseFirst(text, "groups=", '[', ']', false); + + //qDebug() << groups_text; + + if (groups_text != "") { + + QStringList groups_list = Seer::parse(groups_text, "", '{', '}', false); + + for ( const auto& group_text : groups_list ) { + + QString id_text = Seer::parseFirst(group_text, "id=", '"', '"', false); + QString type_text = Seer::parseFirst(group_text, "type=", '"', '"', false); + QString pid_text = Seer::parseFirst(group_text, "pid=", '"', '"', false); + QString exe_text = Seer::parseFirst(group_text, "executable=", '"', '"', false); + QString cores_text = Seer::parseFirst(group_text, "cores=", '[', ']', false); + + // Create the item. + QTreeWidgetItem* item = new QTreeWidgetItem; + item->setText(0, id_text); + item->setText(1, type_text); + item->setText(2, pid_text); + item->setText(3, exe_text); + item->setText(4, cores_text); + + // Add the frame to the tree. + groupTreeWidget->addTopLevelItem(item); + } + } + + }else if (text.startsWith("=thread-created,id=")) { + + // =thread-created,id="2",group-id="i2" + refresh(); + + }else if (text.startsWith("=thread-exited,id=")) { + + // =thread-exited,id="2",group-id="i2" + refresh(); + + }else if (text.startsWith("^error,msg=\"No registers.\"")) { + groupTreeWidget->clear(); + + }else{ + // Ignore others. + } + + groupTreeWidget->resizeColumnToContents(0); + groupTreeWidget->resizeColumnToContents(1); + groupTreeWidget->resizeColumnToContents(2); + //groupTreeWidget->resizeColumnToContents(3); // Don't resize. + groupTreeWidget->resizeColumnToContents(4); + + QApplication::restoreOverrideCursor(); +} + +void SeerThreadGroupsBrowserWidget::refresh () { + emit refreshThreadIds(); + emit refreshThreadGroups(); +} + +void SeerThreadGroupsBrowserWidget::handleItemEntered (QTreeWidgetItem* item, int column) { + + Q_UNUSED(column); + + //qDebug() << item->text(0) << column; + + item->setToolTip(0, item->text(0) + " : " + item->text(1) + " : " + item->text(2) + " : " + item->text(3) + " : " + item->text(4)); + + for (int i=1; icolumnCount(); i++) { // Copy tooltip to other columns. + item->setToolTip(i, item->toolTip(0)); + } +} + +void SeerThreadGroupsBrowserWidget::showEvent (QShowEvent* event) { + + QWidget::showEvent(event); + + refresh(); +} + diff --git a/src/SeerThreadGroupsBrowserWidget.h b/src/SeerThreadGroupsBrowserWidget.h new file mode 100644 index 0000000..e923bdd --- /dev/null +++ b/src/SeerThreadGroupsBrowserWidget.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include +#include "ui_SeerThreadGroupsBrowserWidget.h" + +class SeerThreadGroupsBrowserWidget : public QWidget, protected Ui::SeerThreadGroupsBrowserWidgetForm { + + Q_OBJECT + + public: + explicit SeerThreadGroupsBrowserWidget (QWidget* parent = 0); + ~SeerThreadGroupsBrowserWidget (); + + public slots: + void handleText (const QString& text); + void refresh (); + + protected slots: + void handleItemEntered (QTreeWidgetItem* item, int column); + + signals: + void refreshThreadGroups (); + void refreshThreadIds (); + + protected: + void showEvent (QShowEvent* event); + + private: +}; + diff --git a/src/SeerThreadGroupsBrowserWidget.ui b/src/SeerThreadGroupsBrowserWidget.ui new file mode 100644 index 0000000..691b048 --- /dev/null +++ b/src/SeerThreadGroupsBrowserWidget.ui @@ -0,0 +1,53 @@ + + + SeerThreadGroupsBrowserWidgetForm + + + + 0 + 0 + 794 + 528 + + + + Form + + + + + + 5 + + + + Thread Id + + + + + Type + + + + + Pid + + + + + Executable + + + + + Cores + + + + + + + + + diff --git a/src/SeerThreadIdsBrowserWidget.ui b/src/SeerThreadIdsBrowserWidget.ui index feba56f..5f90126 100644 --- a/src/SeerThreadIdsBrowserWidget.ui +++ b/src/SeerThreadIdsBrowserWidget.ui @@ -21,7 +21,7 @@ - Id + Thread Id diff --git a/src/SeerThreadManagerWidget.cpp b/src/SeerThreadManagerWidget.cpp index 8f7d562..7eed4bf 100644 --- a/src/SeerThreadManagerWidget.cpp +++ b/src/SeerThreadManagerWidget.cpp @@ -16,9 +16,11 @@ SeerThreadManagerWidget::SeerThreadManagerWidget (QWidget* parent) : QWidget(par _threadFramesBrowserWidget = new SeerThreadFramesBrowserWidget(this); _threadIdsBrowserWidget = new SeerThreadIdsBrowserWidget(this); + _threadGroupsBrowserWidget = new SeerThreadGroupsBrowserWidget(this); tabWidget->addTab(_threadFramesBrowserWidget, "Frames"); tabWidget->addTab(_threadIdsBrowserWidget, "Ids"); + tabWidget->addTab(_threadGroupsBrowserWidget, "Groups"); QToolButton* refreshToolButton = new QToolButton(tabWidget); refreshToolButton->setIcon(QIcon(":/seer/resources/RelaxLightIcons/view-refresh.svg")); @@ -35,12 +37,16 @@ SeerThreadManagerWidget::SeerThreadManagerWidget (QWidget* parent) : QWidget(par SeerThreadManagerWidget::~SeerThreadManagerWidget () { } +SeerThreadFramesBrowserWidget* SeerThreadManagerWidget::threadFramesBrowserWidget () { + return _threadFramesBrowserWidget; +} + SeerThreadIdsBrowserWidget* SeerThreadManagerWidget::threadIdsBrowserWidget () { return _threadIdsBrowserWidget; } -SeerThreadFramesBrowserWidget* SeerThreadManagerWidget::threadFramesBrowserWidget () { - return _threadFramesBrowserWidget; +SeerThreadGroupsBrowserWidget* SeerThreadManagerWidget::threadGroupsBrowserWidget () { + return _threadGroupsBrowserWidget; } void SeerThreadManagerWidget::setSchedulerLockingMode (const QString& mode) { @@ -77,6 +83,7 @@ void SeerThreadManagerWidget::handleRefreshToolButtonClicked () { threadFramesBrowserWidget()->refresh(); threadIdsBrowserWidget()->refresh(); + threadGroupsBrowserWidget()->refresh(); } void SeerThreadManagerWidget::handleSchedulerLockingComboBox (int index) { diff --git a/src/SeerThreadManagerWidget.h b/src/SeerThreadManagerWidget.h index df37a31..7c9cb8d 100644 --- a/src/SeerThreadManagerWidget.h +++ b/src/SeerThreadManagerWidget.h @@ -1,7 +1,8 @@ #pragma once -#include "SeerThreadIdsBrowserWidget.h" #include "SeerThreadFramesBrowserWidget.h" +#include "SeerThreadIdsBrowserWidget.h" +#include "SeerThreadGroupsBrowserWidget.h" #include @@ -15,15 +16,15 @@ class SeerThreadManagerWidget : public QWidget, protected Ui::SeerThreadManagerW explicit SeerThreadManagerWidget (QWidget* parent = 0); ~SeerThreadManagerWidget (); - SeerThreadIdsBrowserWidget* threadIdsBrowserWidget (); SeerThreadFramesBrowserWidget* threadFramesBrowserWidget (); + SeerThreadIdsBrowserWidget* threadIdsBrowserWidget (); + SeerThreadGroupsBrowserWidget* threadGroupsBrowserWidget (); signals: void schedulerLockingModeChanged (const QString& mode); void scheduleMultipleModeChanged (const QString& mode); void forkFollowsModeChanged (const QString& mode); - public slots: void setSchedulerLockingMode (const QString& mode); QString schedulerLockingMode () const; @@ -41,7 +42,8 @@ class SeerThreadManagerWidget : public QWidget, protected Ui::SeerThreadManagerW void handleForkFollowComboBox (int index); private: - SeerThreadIdsBrowserWidget* _threadIdsBrowserWidget; SeerThreadFramesBrowserWidget* _threadFramesBrowserWidget; + SeerThreadIdsBrowserWidget* _threadIdsBrowserWidget; + SeerThreadGroupsBrowserWidget* _threadGroupsBrowserWidget; };