GUI: thread list view (completed 100%)
BRIDGE: added thread list API DBG: almost completed thread list (needs LastError + WaitReason)
This commit is contained in:
parent
87491800c4
commit
e71d10203a
|
@ -565,6 +565,11 @@ BRIDGE_IMPEXP bool DbgStackCommentGet(duint addr, STACK_COMMENT* comment)
|
|||
return (bool)(duint)_dbg_sendmessage(DBG_STACK_COMMENT_GET, (void*)addr, comment);
|
||||
}
|
||||
|
||||
BRIDGE_IMPEXP void DbgGetThreadList(THREADLIST* list)
|
||||
{
|
||||
_dbg_sendmessage(DBG_GET_THREAD_LIST, list, 0);
|
||||
}
|
||||
|
||||
//GUI
|
||||
BRIDGE_IMPEXP void GuiDisasmAt(duint addr, duint cip)
|
||||
{
|
||||
|
@ -748,6 +753,11 @@ BRIDGE_IMPEXP void GuiUpdateDumpView()
|
|||
_gui_sendmessage(GUI_UPDATE_DUMP_VIEW, 0, 0);
|
||||
}
|
||||
|
||||
BRIDGE_IMPEXP void GuiUpdateThreadView()
|
||||
{
|
||||
_gui_sendmessage(GUI_UPDATE_THREAD_VIEW, 0, 0);
|
||||
}
|
||||
|
||||
//Main
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
|
|
|
@ -114,8 +114,9 @@ enum DBGMSG
|
|||
DBG_SYMBOL_ENUM, // param1=SYMBOLCBINFO* cbInfo, param2=unused
|
||||
DBG_ASSEMBLE_AT, // param1=duint addr, param2=const char* instruction
|
||||
DBG_MODBASE_FROM_NAME, // param1=const char* modname, param2=unused
|
||||
DBG_DISASM_AT, // param1=duint addr, param2=DISASM_INSTR* instr
|
||||
DBG_STACK_COMMENT_GET // param1=duint addr, param2=STACK_COMMENT* comment
|
||||
DBG_DISASM_AT, // param1=duint addr, param2=DISASM_INSTR* instr
|
||||
DBG_STACK_COMMENT_GET, // param1=duint addr, param2=STACK_COMMENT* comment
|
||||
DBG_GET_THREAD_LIST // param1=THREADALLINFO* list, param2=unused
|
||||
};
|
||||
|
||||
enum SCRIPTLINETYPE
|
||||
|
@ -147,6 +148,59 @@ enum STRING_TYPE
|
|||
str_unicode
|
||||
};
|
||||
|
||||
enum THREADPRIORITY
|
||||
{
|
||||
PriorityIdle = -15,
|
||||
PriorityAboveNormal = 1,
|
||||
PriorityBelowNormal = -1,
|
||||
PriorityHighest = 2,
|
||||
PriorityLowest = -2,
|
||||
PriorityNormal = 0,
|
||||
PriorityTimeCritical = 15,
|
||||
PriorityUnknown = 0x7FFFFFFF
|
||||
};
|
||||
|
||||
enum THREADWAITREASON
|
||||
{
|
||||
Executive = 0,
|
||||
FreePage = 1,
|
||||
PageIn = 2,
|
||||
PoolAllocation = 3,
|
||||
DelayExecution = 4,
|
||||
Suspended = 5,
|
||||
UserRequest = 6,
|
||||
WrExecutive = 7,
|
||||
WrFreePage = 8,
|
||||
WrPageIn = 9,
|
||||
WrPoolAllocation = 10,
|
||||
WrDelayExecution = 11,
|
||||
WrSuspended = 12,
|
||||
WrUserRequest = 13,
|
||||
WrEventPair = 14,
|
||||
WrQueue = 15,
|
||||
WrLpcReceive = 16,
|
||||
WrLpcReply = 17,
|
||||
WrVirtualMemory = 18,
|
||||
WrPageOut = 19,
|
||||
WrRendezvous = 20,
|
||||
Spare2 = 21,
|
||||
Spare3 = 22,
|
||||
Spare4 = 23,
|
||||
Spare5 = 24,
|
||||
WrCalloutStack = 25,
|
||||
WrKernel = 26,
|
||||
WrResource = 27,
|
||||
WrPushLock = 28,
|
||||
WrMutex = 29,
|
||||
WrQuantumEnd = 30,
|
||||
WrDispatchInt = 31,
|
||||
WrPreempted = 32,
|
||||
WrYieldExecution = 33,
|
||||
WrFastMutex = 34,
|
||||
WrGuardedMutex = 35,
|
||||
WrRundown = 36,
|
||||
};
|
||||
|
||||
//Debugger typedefs
|
||||
struct SYMBOLINFO;
|
||||
|
||||
|
@ -295,6 +349,32 @@ struct STACK_COMMENT
|
|||
char comment[MAX_COMMENT_SIZE];
|
||||
};
|
||||
|
||||
struct THREADINFO
|
||||
{
|
||||
int ThreadNumber;
|
||||
HANDLE hThread;
|
||||
DWORD dwThreadId;
|
||||
duint ThreadStartAddress;
|
||||
duint ThreadLocalBase;
|
||||
};
|
||||
|
||||
struct THREADALLINFO
|
||||
{
|
||||
THREADINFO BasicInfo;
|
||||
duint ThreadCip;
|
||||
DWORD SuspendCount;
|
||||
THREADPRIORITY Priority;
|
||||
THREADWAITREASON WaitReason;
|
||||
DWORD LastError;
|
||||
};
|
||||
|
||||
struct THREADLIST
|
||||
{
|
||||
int count;
|
||||
THREADALLINFO* list;
|
||||
int CurrentThread;
|
||||
};
|
||||
|
||||
//Debugger functions
|
||||
BRIDGE_IMPEXP const char* DbgInit();
|
||||
BRIDGE_IMPEXP bool DbgMemRead(duint va, unsigned char* dest, duint size);
|
||||
|
@ -340,6 +420,7 @@ BRIDGE_IMPEXP bool DbgAssembleAt(duint addr, const char* instruction);
|
|||
BRIDGE_IMPEXP duint DbgModBaseFromName(const char* name);
|
||||
BRIDGE_IMPEXP void DbgDisasmAt(duint addr, DISASM_INSTR* instr);
|
||||
BRIDGE_IMPEXP bool DbgStackCommentGet(duint addr, STACK_COMMENT* comment);
|
||||
BRIDGE_IMPEXP void DbgGetThreadList(THREADLIST* list);
|
||||
|
||||
//Gui enums
|
||||
enum GUIMSG
|
||||
|
@ -378,7 +459,8 @@ enum GUIMSG
|
|||
GUI_REF_SETSINGLESELECTION, // param1=int index, param2=bool scroll
|
||||
GUI_REF_SETPROGRESS, // param1=int progress, param2=unused
|
||||
GUI_STACK_DUMP_AT, // param1=duint addr, param2=duint csp
|
||||
GUI_UPDATE_DUMP_VIEW // param1=unused, param2=unused
|
||||
GUI_UPDATE_DUMP_VIEW, // param1=unused, param2=unused
|
||||
GUI_UPDATE_THREAD_VIEW // param1=unused, param2=unused
|
||||
};
|
||||
|
||||
//GUI structures
|
||||
|
@ -425,6 +507,7 @@ BRIDGE_IMPEXP void GuiReferenceSetSingleSelection(int index, bool scroll);
|
|||
BRIDGE_IMPEXP void GuiReferenceSetProgress(int progress);
|
||||
BRIDGE_IMPEXP void GuiStackDumpAt(duint addr, duint csp);
|
||||
BRIDGE_IMPEXP void GuiUpdateDumpView();
|
||||
BRIDGE_IMPEXP void GuiUpdateThreadView();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "symbolinfo.h"
|
||||
#include "assemble.h"
|
||||
#include "stackinfo.h"
|
||||
#include "thread.h"
|
||||
|
||||
extern "C" DLL_EXPORT duint _dbg_memfindbaseaddr(duint addr, duint* size)
|
||||
{
|
||||
|
@ -619,6 +620,12 @@ extern "C" DLL_EXPORT uint _dbg_sendmessage(DBGMSG type, void* param1, void* par
|
|||
return stackcommentget((uint)param1, (STACK_COMMENT*)param2);
|
||||
}
|
||||
break;
|
||||
|
||||
case DBG_GET_THREAD_LIST:
|
||||
{
|
||||
threadgetlist((THREADLIST*)param1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -57,6 +57,7 @@ struct PLUG_CB_CREATETHREAD
|
|||
struct PLUG_CB_EXITTHREAD
|
||||
{
|
||||
EXIT_THREAD_DEBUG_INFO* ExitThread;
|
||||
DWORD dwThreadId;
|
||||
};
|
||||
|
||||
struct PLUG_CB_SYSTEMBREAKPOINT
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "x64_dbg.h"
|
||||
#include "disasm_helper.h"
|
||||
#include "symbolinfo.h"
|
||||
#include "thread.h"
|
||||
|
||||
#include "BeaEngine\BeaEngine.h"
|
||||
|
||||
|
@ -492,6 +493,13 @@ static void cbCreateProcess(CREATE_PROCESS_DEBUG_INFO* CreateProcessInfo)
|
|||
callbackInfo.DebugFileName=DebugFileName;
|
||||
callbackInfo.fdProcessInfo=fdProcessInfo;
|
||||
plugincbcall(CB_CREATEPROCESS, &callbackInfo);
|
||||
|
||||
//update thread list
|
||||
CREATE_THREAD_DEBUG_INFO threadInfo;
|
||||
threadInfo.hThread=CreateProcessInfo->hThread;
|
||||
threadInfo.lpStartAddress=CreateProcessInfo->lpStartAddress;
|
||||
threadInfo.lpThreadLocalBase=CreateProcessInfo->lpThreadLocalBase;
|
||||
threadcreate(&threadInfo);
|
||||
}
|
||||
|
||||
static void cbExitProcess(EXIT_PROCESS_DEBUG_INFO* ExitProcess)
|
||||
|
@ -505,6 +513,7 @@ static void cbExitProcess(EXIT_PROCESS_DEBUG_INFO* ExitProcess)
|
|||
|
||||
static void cbCreateThread(CREATE_THREAD_DEBUG_INFO* CreateThread)
|
||||
{
|
||||
threadcreate(CreateThread); //update thread list
|
||||
PLUG_CB_CREATETHREAD callbackInfo;
|
||||
callbackInfo.CreateThread=CreateThread;
|
||||
plugincbcall(CB_CREATETHREAD, &callbackInfo);
|
||||
|
@ -512,9 +521,12 @@ static void cbCreateThread(CREATE_THREAD_DEBUG_INFO* CreateThread)
|
|||
|
||||
static void cbExitThread(EXIT_THREAD_DEBUG_INFO* ExitThread)
|
||||
{
|
||||
DWORD dwThreadId=((DEBUG_EVENT*)GetDebugData())->dwThreadId;
|
||||
PLUG_CB_EXITTHREAD callbackInfo;
|
||||
callbackInfo.ExitThread=ExitThread;
|
||||
callbackInfo.dwThreadId=dwThreadId;
|
||||
plugincbcall(CB_EXITTHREAD, &callbackInfo);
|
||||
threadexit(dwThreadId);
|
||||
}
|
||||
|
||||
static void cbSystemBreakpoint(void* ExceptionData)
|
||||
|
@ -529,6 +541,7 @@ static void cbSystemBreakpoint(void* ExceptionData)
|
|||
//update GUI
|
||||
DebugUpdateGui(GetContextData(UE_CIP), true);
|
||||
GuiSetDebugState(paused);
|
||||
GuiUpdateThreadView();
|
||||
//lock
|
||||
lock(WAITID_RUN);
|
||||
bSkipExceptions=false;
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
#include "thread.h"
|
||||
#include "console.h"
|
||||
|
||||
static std::vector<THREADINFO> threadList;
|
||||
static int threadNum;
|
||||
static int currentThread;
|
||||
|
||||
void threadcreate(CREATE_THREAD_DEBUG_INFO* CreateThread)
|
||||
{
|
||||
THREADINFO curInfo;
|
||||
curInfo.ThreadNumber=threadNum;
|
||||
curInfo.hThread=CreateThread->hThread;
|
||||
curInfo.dwThreadId=((DEBUG_EVENT*)GetDebugData())->dwThreadId;
|
||||
curInfo.ThreadStartAddress=(uint)CreateThread->lpStartAddress;
|
||||
curInfo.ThreadLocalBase=(uint)CreateThread->lpThreadLocalBase;
|
||||
threadList.push_back(curInfo);
|
||||
threadNum++;
|
||||
GuiUpdateThreadView();
|
||||
}
|
||||
|
||||
void threadexit(DWORD dwThreadId)
|
||||
{
|
||||
for(int i=0; i<threadList.size(); i++)
|
||||
if(threadList.at(i).dwThreadId==dwThreadId)
|
||||
{
|
||||
threadList.erase(threadList.begin()+i);
|
||||
break;
|
||||
}
|
||||
GuiUpdateThreadView();
|
||||
}
|
||||
|
||||
void threadclear()
|
||||
{
|
||||
threadNum=0;
|
||||
std::vector<THREADINFO>().swap(threadList);
|
||||
GuiUpdateThreadView();
|
||||
}
|
||||
|
||||
static THREADWAITREASON GetThreadWaitReason(DWORD dwThreadId)
|
||||
{
|
||||
return Executive;
|
||||
}
|
||||
|
||||
void threadgetlist(THREADLIST* list)
|
||||
{
|
||||
int count=threadList.size();
|
||||
list->count=count;
|
||||
if(!count)
|
||||
return;
|
||||
list->list=(THREADALLINFO*)BridgeAlloc(count*sizeof(THREADALLINFO));
|
||||
for(int i=0; i<count; i++)
|
||||
{
|
||||
if(((DEBUG_EVENT*)GetDebugData())->dwThreadId==threadList.at(i).dwThreadId)
|
||||
currentThread=i;
|
||||
memset(&list->list[i], 0, sizeof(THREADALLINFO));
|
||||
memcpy(&list->list[i].BasicInfo, &threadList.at(i), sizeof(THREADINFO));
|
||||
HANDLE hThread=list->list[i].BasicInfo.hThread;
|
||||
list->list[i].ThreadCip=GetContextDataEx(hThread, UE_CIP);
|
||||
list->list[i].SuspendCount=SuspendThread(hThread);
|
||||
ResumeThread(hThread);
|
||||
list->list[i].Priority=(THREADPRIORITY)GetThreadPriority(list->list[i].BasicInfo.hThread);
|
||||
list->list[i].WaitReason=GetThreadWaitReason(list->list[i].BasicInfo.dwThreadId);
|
||||
}
|
||||
list->CurrentThread=currentThread;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef _THREAD_H
|
||||
#define _THREAD_H
|
||||
|
||||
#include "_global.h"
|
||||
#include "debugger.h"
|
||||
|
||||
//functions
|
||||
void threadcreate(CREATE_THREAD_DEBUG_INFO* CreateThread);
|
||||
void threadexit(DWORD dwThreadId);
|
||||
void threadclear();
|
||||
void threadgetlist(THREADLIST* list);
|
||||
|
||||
#endif //_THREAD_H
|
|
@ -117,6 +117,8 @@
|
|||
<Unit filename="stackinfo.h" />
|
||||
<Unit filename="symbolinfo.cpp" />
|
||||
<Unit filename="symbolinfo.h" />
|
||||
<Unit filename="thread.cpp" />
|
||||
<Unit filename="thread.h" />
|
||||
<Unit filename="threading.cpp" />
|
||||
<Unit filename="threading.h" />
|
||||
<Unit filename="value.cpp" />
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
<ClCompile Include="sqlhelper.cpp" />
|
||||
<ClCompile Include="stackinfo.cpp" />
|
||||
<ClCompile Include="symbolinfo.cpp" />
|
||||
<ClCompile Include="thread.cpp" />
|
||||
<ClCompile Include="threading.cpp" />
|
||||
<ClCompile Include="value.cpp" />
|
||||
<ClCompile Include="variable.cpp" />
|
||||
|
@ -57,6 +58,7 @@
|
|||
<ClInclude Include="sqlhelper.h" />
|
||||
<ClInclude Include="stackinfo.h" />
|
||||
<ClInclude Include="symbolinfo.h" />
|
||||
<ClInclude Include="thread.h" />
|
||||
<ClInclude Include="threading.h" />
|
||||
<ClInclude Include="value.h" />
|
||||
<ClInclude Include="variable.h" />
|
||||
|
|
|
@ -90,6 +90,9 @@
|
|||
<ClCompile Include="stackinfo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="thread.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="_exports.h">
|
||||
|
@ -173,5 +176,8 @@
|
|||
<ClInclude Include="stackinfo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="thread.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -56,7 +56,8 @@ SOURCES += \
|
|||
Src/BasicView/SymbolView.cpp \
|
||||
Src/BasicView/RegistersView.cpp \
|
||||
Src/BasicView/SearchListView.cpp \
|
||||
Src/BasicView/ReferenceView.cpp
|
||||
Src/BasicView/ReferenceView.cpp \
|
||||
Src/BasicView/ThreadView.cpp
|
||||
|
||||
|
||||
HEADERS += \
|
||||
|
@ -93,7 +94,8 @@ HEADERS += \
|
|||
Src/Gui/CPUStack.h \
|
||||
Src/BasicView/SymbolView.h \
|
||||
Src/BasicView/SearchListView.h \
|
||||
Src/BasicView/ReferenceView.h
|
||||
Src/BasicView/ReferenceView.h \
|
||||
Src/BasicView/ThreadView.h
|
||||
|
||||
INCLUDEPATH += \
|
||||
Src \
|
||||
|
|
|
@ -45,7 +45,7 @@ QString ScriptView::paintContent(QPainter* painter, int_t rowBase, int rowOffset
|
|||
if(DbgScriptBpGet(line)) //breakpoint
|
||||
painter->setPen(QPen(QColor("#FF0000"))); //red address
|
||||
else
|
||||
painter->setPen(QPen(QColor("#FFFFFF"))); //black address
|
||||
painter->setPen(QPen(QColor("#FFFFFF"))); //white address
|
||||
}
|
||||
else if(DbgScriptBpGet(line)) //breakpoint
|
||||
{
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
#include "ThreadView.h"
|
||||
|
||||
ThreadView::ThreadView(StdTable *parent) : StdTable(parent)
|
||||
{
|
||||
int charwidth=QFontMetrics(this->font()).width(QChar(' '));
|
||||
addColumnAt(8+charwidth*sizeof(unsigned int)*2, "Number", false);
|
||||
addColumnAt(8+charwidth*sizeof(unsigned int)*2, "ID", false);
|
||||
addColumnAt(8+charwidth*sizeof(uint_t)*2, "Entry", false);
|
||||
addColumnAt(8+charwidth*sizeof(uint_t)*2, "TEB", false);
|
||||
#ifdef _WIN64
|
||||
addColumnAt(8+charwidth*sizeof(uint_t)*2, "RIP", false);
|
||||
#else
|
||||
addColumnAt(8+charwidth*sizeof(uint_t)*2, "EIP", false);
|
||||
#endif //_WIN64
|
||||
addColumnAt(8+charwidth*14, "Suspend Count", false);
|
||||
addColumnAt(8+charwidth*20, "Priority", false);
|
||||
addColumnAt(8+charwidth*16, "WaitReason", false);
|
||||
addColumnAt(8+charwidth*10, "LastError", false);
|
||||
addColumnAt(0, "", false);
|
||||
|
||||
connect(Bridge::getBridge(), SIGNAL(updateThreads()), this, SLOT(updateThreadList()));
|
||||
}
|
||||
|
||||
void ThreadView::updateThreadList()
|
||||
{
|
||||
THREADLIST threadList;
|
||||
memset(&threadList, 0, sizeof(THREADLIST));
|
||||
DbgGetThreadList(&threadList);
|
||||
setRowCount(threadList.count);
|
||||
for(int i=0; i<threadList.count; i++)
|
||||
{
|
||||
if(!threadList.list[i].BasicInfo.ThreadNumber)
|
||||
setCellContent(i, 0, "Main");
|
||||
else
|
||||
setCellContent(i, 0, QString("%1").arg(threadList.list[i].BasicInfo.ThreadNumber, 0, 10));
|
||||
setCellContent(i, 1, QString("%1").arg(threadList.list[i].BasicInfo.dwThreadId, 0, 16).toUpper());
|
||||
setCellContent(i, 2, QString("%1").arg(threadList.list[i].BasicInfo.ThreadStartAddress, sizeof(int_t) * 2, 16, QChar('0')).toUpper());
|
||||
setCellContent(i, 3, QString("%1").arg(threadList.list[i].BasicInfo.ThreadLocalBase, sizeof(int_t) * 2, 16, QChar('0')).toUpper());
|
||||
setCellContent(i, 4, QString("%1").arg(threadList.list[i].ThreadCip, sizeof(int_t) * 2, 16, QChar('0')).toUpper());
|
||||
setCellContent(i, 5, QString("%1").arg(threadList.list[i].SuspendCount, 0, 10));
|
||||
QString priorityString;
|
||||
switch(threadList.list[i].Priority)
|
||||
{
|
||||
case PriorityIdle:
|
||||
priorityString="Idle";
|
||||
break;
|
||||
case PriorityAboveNormal:
|
||||
priorityString="AboveNormal";
|
||||
break;
|
||||
case PriorityBelowNormal:
|
||||
priorityString="BelowNormal";
|
||||
break;
|
||||
case PriorityHighest:
|
||||
priorityString="Highest";
|
||||
break;
|
||||
case PriorityLowest:
|
||||
priorityString="Lowest";
|
||||
break;
|
||||
case PriorityNormal:
|
||||
priorityString="Normal";
|
||||
break;
|
||||
case PriorityTimeCritical:
|
||||
priorityString="TimeCritical";
|
||||
break;
|
||||
default:
|
||||
priorityString="Unknown";
|
||||
break;
|
||||
}
|
||||
setCellContent(i, 6, priorityString);
|
||||
QString waitReasonString;
|
||||
switch(threadList.list[i].WaitReason)
|
||||
{
|
||||
case Executive:
|
||||
waitReasonString="Executive";
|
||||
break;
|
||||
case FreePage:
|
||||
waitReasonString="FreePage";
|
||||
break;
|
||||
case PageIn:
|
||||
waitReasonString="PageIn";
|
||||
break;
|
||||
case PoolAllocation:
|
||||
waitReasonString="PoolAllocation";
|
||||
break;
|
||||
case DelayExecution:
|
||||
waitReasonString="DelayExecution";
|
||||
break;
|
||||
case Suspended:
|
||||
waitReasonString="Suspended";
|
||||
break;
|
||||
case UserRequest:
|
||||
waitReasonString="UserRequest";
|
||||
break;
|
||||
case WrExecutive:
|
||||
waitReasonString="WrExecutive";
|
||||
break;
|
||||
case WrFreePage:
|
||||
waitReasonString="WrFreePage";
|
||||
break;
|
||||
case WrPageIn:
|
||||
waitReasonString="WrPageIn";
|
||||
break;
|
||||
case WrPoolAllocation:
|
||||
waitReasonString="WrPoolAllocation";
|
||||
break;
|
||||
case WrDelayExecution:
|
||||
waitReasonString="WrDelayExecution";
|
||||
break;
|
||||
case WrSuspended:
|
||||
waitReasonString="WrSuspended";
|
||||
break;
|
||||
case WrUserRequest:
|
||||
waitReasonString="WrUserRequest";
|
||||
break;
|
||||
case WrEventPair:
|
||||
waitReasonString="WrEventPair";
|
||||
break;
|
||||
case WrQueue:
|
||||
waitReasonString="WrQueue";
|
||||
break;
|
||||
case WrLpcReceive:
|
||||
waitReasonString="WrLpcReceive";
|
||||
break;
|
||||
case WrLpcReply:
|
||||
waitReasonString="WrLpcReply";
|
||||
break;
|
||||
case WrVirtualMemory:
|
||||
waitReasonString="WrVirtualMemory";
|
||||
break;
|
||||
case WrPageOut:
|
||||
waitReasonString="WrPageOut";
|
||||
break;
|
||||
case WrRendezvous:
|
||||
waitReasonString="WrRendezvous";
|
||||
break;
|
||||
case Spare2:
|
||||
waitReasonString="Spare2";
|
||||
break;
|
||||
case Spare3:
|
||||
waitReasonString="Spare3";
|
||||
break;
|
||||
case Spare4:
|
||||
waitReasonString="Spare4";
|
||||
break;
|
||||
case Spare5:
|
||||
waitReasonString="Spare5";
|
||||
break;
|
||||
case WrCalloutStack:
|
||||
waitReasonString="WrCalloutStack";
|
||||
break;
|
||||
case WrKernel:
|
||||
waitReasonString="WrKernel";
|
||||
break;
|
||||
case WrResource:
|
||||
waitReasonString="WrResource";
|
||||
break;
|
||||
case WrPushLock:
|
||||
waitReasonString="WrPushLock";
|
||||
break;
|
||||
case WrMutex:
|
||||
waitReasonString="WrMutex";
|
||||
break;
|
||||
case WrQuantumEnd:
|
||||
waitReasonString="WrQuantumEnd";
|
||||
break;
|
||||
case WrDispatchInt:
|
||||
waitReasonString="WrDispatchInt";
|
||||
break;
|
||||
case WrPreempted:
|
||||
waitReasonString="WrPreempted";
|
||||
break;
|
||||
case WrYieldExecution:
|
||||
waitReasonString="WrYieldExecution";
|
||||
break;
|
||||
case WrFastMutex:
|
||||
waitReasonString="WrFastMutex";
|
||||
break;
|
||||
case WrGuardedMutex:
|
||||
waitReasonString="WrGuardedMutex";
|
||||
break;
|
||||
case WrRundown:
|
||||
waitReasonString="WrRundown";
|
||||
break;
|
||||
default:
|
||||
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());
|
||||
}
|
||||
if(threadList.count)
|
||||
BridgeFree(threadList.list);
|
||||
mCurrentThread=threadList.CurrentThread;
|
||||
reloadData();
|
||||
}
|
||||
|
||||
QString ThreadView::paintContent(QPainter* painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h)
|
||||
{
|
||||
QString ret=StdTable::paintContent(painter, rowBase, rowOffset, col, x, y, w, h);
|
||||
if(rowBase+rowOffset==mCurrentThread && !col)
|
||||
{
|
||||
painter->save();
|
||||
painter->fillRect(QRect(x, y, w, h), QBrush(QColor("#000000")));
|
||||
painter->setPen(QPen(QColor("#ffffff"))); //white text
|
||||
painter->drawText(QRect(x + 4, y , w - 4 , h), Qt::AlignVCenter | Qt::AlignLeft, ret);
|
||||
painter->restore();
|
||||
ret="";
|
||||
}
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
#ifndef THREADVIEW_H
|
||||
#define THREADVIEW_H
|
||||
|
||||
#include "StdTable.h"
|
||||
#include "Bridge.h"
|
||||
|
||||
class ThreadView : public StdTable
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ThreadView(StdTable* parent = 0);
|
||||
QString paintContent(QPainter* painter, int_t rowBase, int rowOffset, int col, int x, int y, int w, int h);
|
||||
|
||||
public slots:
|
||||
void updateThreadList();
|
||||
|
||||
private:
|
||||
int mCurrentThread;
|
||||
};
|
||||
|
||||
#endif // THREADVIEW_H
|
|
@ -215,6 +215,11 @@ void Bridge::emitUpdateDump()
|
|||
emit updateDump();
|
||||
}
|
||||
|
||||
void Bridge::emitUpdateThreads()
|
||||
{
|
||||
emit updateThreads();
|
||||
}
|
||||
|
||||
/************************************************************************************
|
||||
Static Functions
|
||||
************************************************************************************/
|
||||
|
@ -451,6 +456,12 @@ __declspec(dllexport) void* _gui_sendmessage(GUIMSG type, void* param1, void* pa
|
|||
}
|
||||
break;
|
||||
|
||||
case GUI_UPDATE_THREAD_VIEW:
|
||||
{
|
||||
Bridge::getBridge()->emitUpdateThreads();
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
{
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ public:
|
|||
void emitReferenceSetProgress(int progress);
|
||||
void emitStackDumpAt(uint_t va, uint_t csp);
|
||||
void emitUpdateDump();
|
||||
void emitUpdateThreads();
|
||||
|
||||
//Public variables
|
||||
void* winId;
|
||||
|
@ -99,6 +100,7 @@ signals:
|
|||
void referenceSetProgress(int progress);
|
||||
void stackDumpAt(uint_t va, uint_t csp);
|
||||
void updateDump();
|
||||
void updateThreads();
|
||||
|
||||
private:
|
||||
QMutex mBridgeMutex;
|
||||
|
|
|
@ -67,6 +67,10 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||
mReferenceView->setWindowTitle("References");
|
||||
mReferenceView->setWindowIcon(QIcon(":/icons/images/search.png"));
|
||||
|
||||
mThreadView = new ThreadView();
|
||||
mThreadView->setWindowTitle("Threads");
|
||||
mThreadView->setWindowIcon(QIcon(":/icons/images/arrow-threads.png"));
|
||||
|
||||
//Create the tab widget
|
||||
mTabWidget = new QTabWidget();
|
||||
|
||||
|
@ -78,6 +82,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||
mTabWidget->addTab(mScriptView, mScriptView->windowIcon(), mScriptView->windowTitle());
|
||||
mTabWidget->addTab(mSymbolView, mSymbolView->windowIcon(), mSymbolView->windowTitle());
|
||||
mTabWidget->addTab(mReferenceView, mReferenceView->windowIcon(),mReferenceView->windowTitle());
|
||||
mTabWidget->addTab(mThreadView, mThreadView->windowIcon(), mThreadView->windowTitle());
|
||||
|
||||
setCentralWidget(mTabWidget);
|
||||
|
||||
|
@ -119,6 +124,7 @@ MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWi
|
|||
connect(ui->actionSymbolInfo,SIGNAL(triggered()),this,SLOT(displaySymbolWidget()));
|
||||
connect(mSymbolView,SIGNAL(showCpu()),this,SLOT(displayCpuWidget()));
|
||||
connect(ui->actionReferences,SIGNAL(triggered()),this,SLOT(displayReferencesWidget()));
|
||||
connect(ui->actionThreads,SIGNAL(triggered()),this,SLOT(displayThreadsWidget()));
|
||||
|
||||
connect(Bridge::getBridge(), SIGNAL(updateWindowTitle(QString)), this, SLOT(updateWindowTitleSlot(QString)));
|
||||
connect(Bridge::getBridge(), SIGNAL(updateCPUTitle(QString)), this, SLOT(updateCPUTitleSlot(QString)));
|
||||
|
@ -491,3 +497,10 @@ void MainWindow::displayReferencesWidget()
|
|||
mReferenceView->setFocus();
|
||||
setTab(mReferenceView);
|
||||
}
|
||||
|
||||
void MainWindow::displayThreadsWidget()
|
||||
{
|
||||
mThreadView->show();
|
||||
mThreadView->setFocus();
|
||||
setTab(mThreadView);
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include "ScriptView.h"
|
||||
#include "SymbolView.h"
|
||||
#include "ReferenceView.h"
|
||||
#include "ThreadView.h"
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
|
@ -55,6 +56,7 @@ public slots:
|
|||
void displayCpuWidget();
|
||||
void displaySymbolWidget();
|
||||
void displayReferencesWidget();
|
||||
void displayThreadsWidget();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
|
@ -68,6 +70,7 @@ private:
|
|||
BreakpointsView* mBreakpointsView;
|
||||
ScriptView* mScriptView;
|
||||
ReferenceView* mReferenceView;
|
||||
ThreadView* mThreadView;
|
||||
|
||||
StatusLabel* mStatusLabel;
|
||||
StatusLabel* mLastLogLabel;
|
||||
|
|
|
@ -52,6 +52,7 @@
|
|||
<addaction name="actionScript"/>
|
||||
<addaction name="actionSymbolInfo"/>
|
||||
<addaction name="actionReferences"/>
|
||||
<addaction name="actionThreads"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuDebug">
|
||||
<property name="title">
|
||||
|
@ -126,6 +127,7 @@
|
|||
<addaction name="actionScript"/>
|
||||
<addaction name="actionSymbolInfo"/>
|
||||
<addaction name="actionReferences"/>
|
||||
<addaction name="actionThreads"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="actionScylla"/>
|
||||
</widget>
|
||||
|
@ -447,6 +449,21 @@
|
|||
<string>Alt+R</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionThreads">
|
||||
<property name="icon">
|
||||
<iconset resource="../../resource.qrc">
|
||||
<normaloff>:/icons/images/arrow-threads.png</normaloff>:/icons/images/arrow-threads.png</iconset>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Threads</string>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Threads</string>
|
||||
</property>
|
||||
<property name="shortcut">
|
||||
<string>Alt+T</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources>
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 710 B |
|
@ -27,5 +27,6 @@
|
|||
<file>images/breakpoint.png</file>
|
||||
<file>images/pdb.png</file>
|
||||
<file>images/search.png</file>
|
||||
<file>images/arrow-threads.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
|
Loading…
Reference in New Issue