diff --git a/src/dbg/commands/cmd-gui.cpp b/src/dbg/commands/cmd-gui.cpp index 16201c28..60aa7cca 100644 --- a/src/dbg/commands/cmd-gui.cpp +++ b/src/dbg/commands/cmd-gui.cpp @@ -10,54 +10,21 @@ bool cbShowThreadId(int argc, char* argv[]) { - duint threadID = 0; + if(argc > 1) + { + duint threadId = 0; + if(!valfromstring(argv[1], &threadId, false)) + return false; - if(argc > 2) - { - dprintf(QT_TRANSLATE_NOOP("DBG", "Too many arguments specified. Only 1 argument can be passed, or none.\n")); - return false; - } - else if(argc == 2) - { - if(!valfromstring(argv[1], &threadID)) + SELECTIONDATA newSelection = { threadId, threadId }; + if(!GuiSelectionSet(GUI_THREADS, &newSelection)) { - dprintf(QT_TRANSLATE_NOOP("DBG", "Failed to parse an expression: %s.\n"), argv[1]); + dprintf(QT_TRANSLATE_NOOP("DBG", "Invalid thread %s\n"), formatpidtid((DWORD)threadId).c_str()); return false; } } - else if(argc == 1) - { - GuiShowThreads(); - return true; - } - - THREADLIST threads_head{}; - DbgGetThreadList(&threads_head); - GuiUpdateThreadView(); // To be sure that we have the freshest stuff - - bool threadFound = false; - int row; - for(row = 0; row < threads_head.count; row++) - { - THREADALLINFO currThread = threads_head.list[row]; - if(currThread.BasicInfo.ThreadId == threadID) - { - threadFound = true; - break; - } - } - - BridgeFree(threads_head.list); - if(!threadFound) - { - dprintf(QT_TRANSLATE_NOOP("DBG", "Could not find provided thread ID: %llu\n"), threadID); - return false; - } - - SELECTIONDATA foundThreadGUIRow{row, row}; GuiShowThreads(); - GuiSelectionSet(GUI_THREADS, &foundThreadGUIRow); return true; } diff --git a/src/gui/Src/Bridge/Bridge.cpp b/src/gui/Src/Bridge/Bridge.cpp index 2f8d0a8a..f28d1946 100644 --- a/src/gui/Src/Bridge/Bridge.cpp +++ b/src/gui/Src/Bridge/Bridge.cpp @@ -688,6 +688,9 @@ void* Bridge::processMessage(GUIMSG type, void* param1, void* param2) case GUI_SYMMOD: emit selectionSymmodGet(selection); break; + case GUI_THREADS: + emit selectionThreadsGet(selection); + break; default: return (void*)false; } diff --git a/src/gui/Src/Bridge/Bridge.h b/src/gui/Src/Bridge/Bridge.h index 2225efe3..c301cd33 100644 --- a/src/gui/Src/Bridge/Bridge.h +++ b/src/gui/Src/Bridge/Bridge.h @@ -130,6 +130,7 @@ signals: void selectionMemmapGet(SELECTIONDATA* selection); void selectionMemmapSet(const SELECTIONDATA* selection); void selectionSymmodGet(SELECTIONDATA* selection); + void selectionThreadsGet(SELECTIONDATA* selection); void selectionThreadsSet(const SELECTIONDATA* selection); void getStrWindow(const QString title, QString* text); void autoCompleteAddCmd(const QString cmd); diff --git a/src/gui/Src/Gui/CallStackView.cpp b/src/gui/Src/Gui/CallStackView.cpp index a3083474..59d2917f 100644 --- a/src/gui/Src/Gui/CallStackView.cpp +++ b/src/gui/Src/Gui/CallStackView.cpp @@ -162,7 +162,6 @@ void CallStackView::updateCallStackSlot() DbgFunctions()->GetCallStackByThread(threadList.list[currentIndexToDraw].BasicInfo.Handle, &callstack); setRowCount(currentRow + callstack.total + 1); auto threadId = threadList.list[currentIndexToDraw].BasicInfo.ThreadId; - setCellContent(currentRow, ColThread, ToDecString(threadId)); QString threadName = threadList.list[currentIndexToDraw].BasicInfo.threadName; QString colThreadString = ToDecString(threadList.list[currentIndexToDraw].BasicInfo.ThreadId); @@ -265,6 +264,7 @@ void CallStackView::renameThreadSlot() DbgCmdExec(QString("setthreadname %1, \"%2\"").arg(ToHexString(threadId)).arg(DbgCmdEscape(threadName))); } + void CallStackView::followInThreadsSlot() { QStringList threadIDName = getCellContent(getInitialSelection(), ColThread).split(" - "); diff --git a/src/gui/Src/Gui/HandlesView.cpp b/src/gui/Src/Gui/HandlesView.cpp index 75d4207d..e4c6f2f9 100644 --- a/src/gui/Src/Gui/HandlesView.cpp +++ b/src/gui/Src/Gui/HandlesView.cpp @@ -118,7 +118,7 @@ HandlesView::HandlesView(QWidget* parent) : QWidget(parent) mActionFollowProc = new QAction(DIcon(ArchValue("processor32", "processor64")), tr("Follow Proc in Disassembler"), this); connect(mActionFollowProc, SIGNAL(triggered()), this, SLOT(followInDisasmSlot())); mActionFollowProc->setShortcut(Qt::Key_Return); - mActionFollowThread = new QAction(DIcon("arrow-threads"), tr("Follow in Threads window"), this); + mActionFollowThread = new QAction(DIcon("arrow-threads"), tr("Follow in Threads"), this); connect(mActionFollowThread, SIGNAL(triggered()), this, SLOT(followInThreads())); mWindowsTable->addAction(mActionFollowProc); mActionToggleProcBP = new QAction(DIcon("breakpoint_toggle"), tr("Toggle Breakpoint in Proc"), this); diff --git a/src/gui/Src/Gui/ThreadView.cpp b/src/gui/Src/Gui/ThreadView.cpp index c34def7f..df0a289e 100644 --- a/src/gui/Src/Gui/ThreadView.cpp +++ b/src/gui/Src/Gui/ThreadView.cpp @@ -17,7 +17,7 @@ void ThreadView::contextMenuSlot(const QPoint & pos) void ThreadView::gotoThreadEntrySlot() { - QString addrText = getCellContent(getInitialSelection(), 2); + QString addrText = getCellContent(getInitialSelection(), ColEntry); DbgCmdExecDirect(QString("disasm " + addrText)); } @@ -167,6 +167,7 @@ ThreadView::ThreadView(StdTable* parent) : StdTable(parent) //setCopyMenuOnly(true); connect(Bridge::getBridge(), SIGNAL(selectionThreadsSet(const SELECTIONDATA*)), this, SLOT(selectionThreadsSet(const SELECTIONDATA*))); + connect(Bridge::getBridge(), SIGNAL(selectionThreadsGet(SELECTIONDATA*)), this, SLOT(selectionThreadsGet(SELECTIONDATA*))); connect(Bridge::getBridge(), SIGNAL(updateThreads()), this, SLOT(updateThreadListSlot())); connect(this, SIGNAL(doubleClickedSignal()), this, SLOT(doubleClickedSlot())); connect(this, SIGNAL(contextMenuSignal(QPoint)), this, SLOT(contextMenuSlot(QPoint))); @@ -178,19 +179,27 @@ ThreadView::ThreadView(StdTable* parent) : StdTable(parent) void ThreadView::selectionThreadsSet(const SELECTIONDATA* selection) { - if(selection->start >= getRowCount() || - selection->end >= getRowCount() || - selection->start > selection->end) + auto selectedThreadId = selection->start; + auto rowCount = getRowCount(); + for(duint row = 0; row < rowCount; row++) { - Bridge::getBridge()->setResult(BridgeResult::SelectionSet, 0); - return; + auto threadId = getCellUserdata(row, ColThreadId); + if(threadId == selectedThreadId) + { + setSingleSelection(row); + Bridge::getBridge()->setResult(BridgeResult::SelectionSet, 1); + return; + } } - mSelection.firstSelectedIndex = selection->start; - mSelection.fromIndex = selection->start; - mSelection.toIndex = selection->end; - Bridge::getBridge()->setResult(BridgeResult::SelectionSet, 1); - emit selectionChanged(mSelection.firstSelectedIndex); + Bridge::getBridge()->setResult(BridgeResult::SelectionSet, 0); +} + +void ThreadView::selectionThreadsGet(SELECTIONDATA* selection) +{ + auto threadId = getCellUserdata(getInitialSelection(), ColThreadId); + selection->start = selection->end = threadId; + Bridge::getBridge()->setResult(BridgeResult::SelectionGet, 1); } void ThreadView::updateThreadListSlot() @@ -203,15 +212,15 @@ void ThreadView::updateThreadListSlot() for(int i = 0; i < threadList.count; i++) { if(!threadList.list[i].BasicInfo.ThreadNumber) - setCellContent(i, 0, tr("Main")); + setCellContent(i, ColNumber, tr("Main")); else - setCellContent(i, 0, ToDecString(threadList.list[i].BasicInfo.ThreadNumber)); - setCellContent(i, 1, QString().sprintf(tidFormat, threadList.list[i].BasicInfo.ThreadId)); - setCellUserdata(i, 1, threadList.list[i].BasicInfo.ThreadId); - setCellContent(i, 2, ToPtrString(threadList.list[i].BasicInfo.ThreadStartAddress)); - setCellContent(i, 3, ToPtrString(threadList.list[i].BasicInfo.ThreadLocalBase)); - setCellContent(i, 4, ToPtrString(threadList.list[i].ThreadCip)); - setCellContent(i, 5, ToDecString(threadList.list[i].SuspendCount)); + setCellContent(i, ColNumber, ToDecString(threadList.list[i].BasicInfo.ThreadNumber)); + setCellContent(i, ColThreadId, QString().sprintf(tidFormat, threadList.list[i].BasicInfo.ThreadId)); + setCellUserdata(i, ColThreadId, threadList.list[i].BasicInfo.ThreadId); + setCellContent(i, ColEntry, ToPtrString(threadList.list[i].BasicInfo.ThreadStartAddress)); + setCellContent(i, ColTeb, ToPtrString(threadList.list[i].BasicInfo.ThreadLocalBase)); + setCellContent(i, ColCip, ToPtrString(threadList.list[i].ThreadCip)); + setCellContent(i, ColSuspendCount, ToDecString(threadList.list[i].SuspendCount)); QString priorityString; switch(threadList.list[i].Priority) { @@ -240,7 +249,7 @@ void ThreadView::updateThreadListSlot() priorityString = tr("Unknown"); break; } - setCellContent(i, 6, priorityString); + setCellContent(i, ColPriority, priorityString); QString waitReasonString; switch(threadList.list[i].WaitReason) { @@ -359,13 +368,13 @@ void ThreadView::updateThreadListSlot() waitReasonString = "Unknown"; break; } - setCellContent(i, 7, waitReasonString); - setCellContent(i, 8, QString("%1").arg(threadList.list[i].LastError, sizeof(unsigned int) * 2, 16, QChar('0')).toUpper()); - setCellContent(i, 9, FILETIMEToTime(threadList.list[i].UserTime)); - setCellContent(i, 10, FILETIMEToTime(threadList.list[i].KernelTime)); - setCellContent(i, 11, FILETIMEToDate(threadList.list[i].CreationTime)); - setCellContent(i, 12, ToLongLongHexString(threadList.list[i].Cycles)); - setCellContent(i, 13, threadList.list[i].BasicInfo.threadName); + setCellContent(i, ColWaitReason, waitReasonString); + setCellContent(i, ColLastError, QString("%1").arg(threadList.list[i].LastError, sizeof(unsigned int) * 2, 16, QChar('0')).toUpper()); + setCellContent(i, ColUserTime, FILETIMEToTime(threadList.list[i].UserTime)); + setCellContent(i, ColKernelTime, FILETIMEToTime(threadList.list[i].KernelTime)); + setCellContent(i, ColCreationTime, FILETIMEToDate(threadList.list[i].CreationTime)); + setCellContent(i, ColCpuCycles, ToLongLongHexString(threadList.list[i].Cycles)); + setCellContent(i, ColThreadName, threadList.list[i].BasicInfo.threadName); } mCurrentThreadId = -1; if(threadList.count) @@ -381,7 +390,7 @@ void ThreadView::updateThreadListSlot() QString ThreadView::paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h) { QString ret = StdTable::paintContent(painter, row, col, x, y, w, h); - duint threadId = getCellUserdata(row, 1); + duint threadId = getCellUserdata(row, ColThreadId); if(threadId == mCurrentThreadId && !col) { painter->fillRect(QRect(x, y, w, h), QBrush(ConfigColor("ThreadCurrentBackgroundColor"))); @@ -394,17 +403,17 @@ QString ThreadView::paintContent(QPainter* painter, duint row, duint col, int x, void ThreadView::doubleClickedSlot() { - duint threadId = getCellUserdata(getInitialSelection(), 1); + duint threadId = getCellUserdata(getInitialSelection(), ColThreadId); DbgCmdExecDirect("switchthread " + ToHexString(threadId)); - QString addrText = getCellContent(getInitialSelection(), 4); + QString addrText = getCellContent(getInitialSelection(), ColCip); DbgCmdExec("disasm " + addrText); } void ThreadView::setNameSlot() { - duint threadId = getCellUserdata(getInitialSelection(), 1); - QString threadName = getCellContent(getInitialSelection(), 13); + duint threadId = getCellUserdata(getInitialSelection(), ColThreadId); + QString threadName = getCellContent(getInitialSelection(), ColThreadName); if(!SimpleInputBox(this, tr("Thread name - %1").arg(threadId), threadName, threadName, QString())) return; diff --git a/src/gui/Src/Gui/ThreadView.h b/src/gui/Src/Gui/ThreadView.h index 0ef17566..8cdc15cd 100644 --- a/src/gui/Src/Gui/ThreadView.h +++ b/src/gui/Src/Gui/ThreadView.h @@ -10,11 +10,13 @@ public: explicit ThreadView(StdTable* parent = nullptr); QString paintContent(QPainter* painter, duint row, duint col, int x, int y, int w, int h) override; void setupContextMenu(); + signals: void displayThreadsView(); public slots: void selectionThreadsSet(const SELECTIONDATA* selection); + void selectionThreadsGet(SELECTIONDATA* selection); void updateThreadListSlot(); void doubleClickedSlot(); void execCommandSlot(); @@ -26,4 +28,22 @@ private: QAction* makeCommandAction(QAction* action, const QString & command); duint mCurrentThreadId; MenuBuilder* mMenuBuilder; + + enum + { + ColNumber = 0, + ColThreadId, + ColEntry, + ColTeb, + ColCip, + ColSuspendCount, + ColPriority, + ColWaitReason, + ColLastError, + ColUserTime, + ColKernelTime, + ColCreationTime, + ColCpuCycles, + ColThreadName, + }; };