1
0
Fork 0

CPU Time in threads view

This commit is contained in:
torusrxxx 2016-07-25 21:25:46 +08:00
parent 886511fdcd
commit bd8ac511d5
8 changed files with 84 additions and 19 deletions

View File

@ -690,6 +690,10 @@ typedef struct
THREADPRIORITY Priority;
THREADWAITREASON WaitReason;
DWORD LastError;
FILETIME UserTime;
FILETIME KernelTime;
FILETIME CreationTime;
ULONG64 Cycles; // Windows Vista or greater
} THREADALLINFO;
typedef struct

View File

@ -9,6 +9,15 @@
#include "threading.h"
static std::unordered_map<DWORD, THREADINFO> threadList;
// Function pointer for dynamic linking. Do not link statically for Windows XP compatibility.
// TODO: move this function definition out of thread.cpp
BOOL(WINAPI* QueryThreadCycleTime)(HANDLE ThreadHandle, PULONG64 CycleTime) = nullptr;
BOOL WINAPI QueryThreadCycleTimeUnsupported(HANDLE ThreadHandle, PULONG64 CycleTime)
{
*CycleTime = 0;
return TRUE;
}
void ThreadCreate(CREATE_THREAD_DEBUG_INFO* CreateThread)
{
@ -78,6 +87,13 @@ int ThreadGetCount()
void ThreadGetList(THREADLIST* List)
{
// Initialize function pointer
if(QueryThreadCycleTime == nullptr)
{
QueryThreadCycleTime = (BOOL(WINAPI*)(HANDLE, PULONG64))GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "QueryThreadCycleTime");
if(QueryThreadCycleTime == nullptr)
QueryThreadCycleTime = QueryThreadCycleTimeUnsupported;
}
ASSERT_NONNULL(List);
SHARED_ACQUIRE(LockThreads);
@ -97,6 +113,9 @@ void ThreadGetList(THREADLIST* List)
// Fill out the list data
int index = 0;
// Unused thread exit time
FILETIME threadExitTime;
for(auto & itr : threadList)
{
HANDLE threadHandle = itr.second.Handle;
@ -112,6 +131,8 @@ void ThreadGetList(THREADLIST* List)
List->list[index].Priority = ThreadGetPriority(threadHandle);
List->list[index].WaitReason = ThreadGetWaitReason(threadHandle);
List->list[index].LastError = ThreadGetLastErrorTEB(itr.second.ThreadLocalBase);
GetThreadTimes(threadHandle, &List->list[index].CreationTime, &threadExitTime, &List->list[index].KernelTime, &List->list[index].UserTime);
QueryThreadCycleTime(threadHandle, &List->list[index].Cycles);
index++;
}
}

View File

@ -164,7 +164,7 @@ void CPUDump::setupContextMenu()
mMenuBuilder->addAction(makeAction(DIcon("data-copy.png"), tr("Data co&py..."), SLOT(dataCopySlot())));
mMenuBuilder->addAction(makeShortcutAction(DIcon("sync.png"), tr("&Sync with expression"), SLOT(syncWithExpressionSlot()), "ActionSyncWithExpression"));
mMenuBuilder->addAction(makeAction(DIcon("animal-dog.png"), ArchValue(tr("Watch QWORD"), tr("Watch DWORD")), SLOT(watchSlot())));
mMenuBuilder->addAction(makeAction(DIcon("animal-dog.png"), ArchValue(tr("Watch DWORD"), tr("Watch QWORD")), SLOT(watchSlot())));
mMenuBuilder->addAction(makeShortcutAction(DIcon("entropy.png"), tr("Entrop&y..."), SLOT(entropySlot()), "ActionEntropy"));
MenuBuilder* wGotoMenu = new MenuBuilder(this);

View File

@ -202,7 +202,11 @@ ThreadView::ThreadView(StdTable* parent) : StdTable(parent)
addColumnAt(8 + charwidth * 12, tr("Priority"), false);
addColumnAt(8 + charwidth * 12, tr("Wait Reason"), false);
addColumnAt(8 + charwidth * 11, tr("Last Error"), false);
addColumnAt(0, tr("Name"), false);
addColumnAt(8 + charwidth * 12, tr("User Time"), false);
addColumnAt(8 + charwidth * 12, tr("Kernel Time"), false);
addColumnAt(8 + charwidth * 15, tr("Creation Time"), false);
addColumnAt(8 + charwidth * 10, tr("CPU Cycles"), false, "", SortBy::AsInt);
addColumnAt(8, tr("Name"), false);
loadColumnFromConfig("Thread");
//setCopyMenuOnly(true);
@ -223,7 +227,7 @@ void ThreadView::updateThreadList()
for(int i = 0; i < threadList.count; i++)
{
if(!threadList.list[i].BasicInfo.ThreadNumber)
setCellContent(i, 0, "Main");
setCellContent(i, 0, tr("Main"));
else
setCellContent(i, 0, ToDecString(threadList.list[i].BasicInfo.ThreadNumber));
setCellContent(i, 1, ToHexString(threadList.list[i].BasicInfo.ThreadId));
@ -380,7 +384,11 @@ void ThreadView::updateThreadList()
}
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, threadList.list[i].BasicInfo.threadName);
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);
}
mCurrentThreadId = "NONE";
if(threadList.count)

View File

@ -209,7 +209,7 @@ Configuration::Configuration() : QObject(), noMoreMsgbox(false)
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "CallStack", 4);
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "SEH", 4);
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Script", 3);
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Thread", 10);
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Thread", 14);
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Handle", 5);
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "TcpConnection", 3);
AbstractTableView::setupColumnConfigDefaultValue(guiUint, "Privilege", 2);

View File

@ -1,4 +1,5 @@
#include <stdint.h>
#include "main.h"
#include "StringUtil.h"
#include "float128.h"
#include "MiscUtil.h"
@ -208,6 +209,7 @@ QString GetDataTypeString(void* buffer, duint size, ENCODETYPE type)
QString ToDateString(const QDate & date)
{
/*
static const char* months[] =
{
"Jan",
@ -224,4 +226,23 @@ QString ToDateString(const QDate & date)
"Dec"
};
return QString().sprintf("%s %d %d", months[date.month() - 1], date.day(), date.year());
*/
return QLocale(QString(currentLocale)).toString(date);
}
QString FILETIMEToDate(const FILETIME & date)
{
FILETIME localdate;
FileTimeToLocalFileTime(&date, &localdate);
SYSTEMTIME systime;
FileTimeToSystemTime(&localdate, &systime);
QDate qdate = QDate(systime.wYear, systime.wMonth, systime.wDay);
quint64 time100ns = (quint64)localdate.dwHighDateTime << 32 | (quint64)localdate.dwLowDateTime;
time100ns %= (1000ull * 60ull * 60ull * 24ull * 10000ull);
localdate.dwHighDateTime = time100ns >> 32;
localdate.dwLowDateTime = time100ns & 0xFFFFFFFF;
if(qdate != QDate::currentDate())
return ToDateString(qdate) + FILETIMEToTime(localdate);
else // today
return FILETIMEToTime(localdate);
}

View File

@ -17,11 +17,12 @@ static QString ToPtrString(duint Address)
// QString::arg():
// ((int32)0xFFFF0000) == 0xFFFFFFFFFFFF0000 with sign extension
//
char temp[32];
#ifdef _WIN64
char temp[33];
sprintf_s(temp, "%016llX", Address);
#else
char temp[17];
sprintf_s(temp, "%08X", Address);
#endif // _WIN64
@ -30,7 +31,7 @@ static QString ToPtrString(duint Address)
static QString ToLongLongHexString(unsigned long long Value)
{
char temp[32];
char temp[33];
sprintf_s(temp, "%llX", Value);
@ -39,7 +40,7 @@ static QString ToLongLongHexString(unsigned long long Value)
static QString ToHexString(duint Value)
{
char temp[32];
char temp[33];
#ifdef _WIN64
sprintf_s(temp, "%llX", Value);
@ -112,6 +113,22 @@ static T & ArchValue(T & x32value, T & x64value)
#endif //_WIN64
}
// Format : d:hh:mm:ss.1234567
static QString FILETIMEToTime(const FILETIME & time)
{
// FILETIME is in 100ns
quint64 time100ns = (quint64)time.dwHighDateTime << 32 | (quint64)time.dwLowDateTime;
quint64 milliseconds = time100ns / 10000;
quint64 days = milliseconds / (1000 * 60 * 60 * 24);
QTime qtime = QTime::fromMSecsSinceStartOfDay(milliseconds % (1000 * 60 * 60 * 24));
if(days == 0)
return QString().sprintf("%02d:%02d:%02d.%07lld", qtime.hour(), qtime.minute(), qtime.second(), time100ns % 10000000);
else
return QString().sprintf("%lld:%02d:%02d:%02d.%07lld", days, qtime.hour(), qtime.minute(), qtime.second(), time100ns % 10000000);
}
QString FILETIMEToDate(const FILETIME & date);
static bool GetCommentFormat(duint addr, QString & comment, bool* autoComment = nullptr)
{
comment.clear();

View File

@ -17,18 +17,16 @@ UpdateChecker::UpdateChecker(QWidget* parent)
void UpdateChecker::checkForUpdates()
{
get(QNetworkRequest(QUrl("http://jenkins.x64dbg.com/job/vs13/lastSuccessfulBuild/api/json")));
//get(QNetworkRequest(QUrl("http://jenkins.x64dbg.com/job/vs13/lastSuccessfulBuild/api/json")));
//jenkins is disabled.
SimpleErrorBox(mParent, "Error", "Cannot check for updates because the update server is down.");
}
void UpdateChecker::finishedSlot(QNetworkReply* reply)
{
if(reply->error() != QNetworkReply::NoError) //error
{
QMessageBox msg(QMessageBox::Critical, tr("Network Error!"), reply->errorString());
msg.setParent(mParent, Qt::Dialog);
msg.setWindowIcon(DIcon("compile-error.png"));
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
msg.exec();
SimpleErrorBox(mParent, tr("Network Error!"), reply->errorString());
return;
}
bool ok = false;
@ -40,11 +38,7 @@ void UpdateChecker::finishedSlot(QNetworkReply* reply)
reply->close();
if(!ok)
{
QMessageBox msg(QMessageBox::Critical, tr("Error!"), tr("File on server could not be parsed..."));
msg.setParent(mParent, Qt::Dialog);
msg.setWindowIcon(DIcon("compile-error.png"));
msg.setWindowFlags(msg.windowFlags() & (~Qt::WindowContextHelpButtonHint));
msg.exec();
SimpleErrorBox(mParent, tr("Error!"), tr("File on server could not be parsed..."));
return;
}
auto server = QDateTime::fromTime_t(timestamp).date();