mirror of
https://github.com/DynamoRIO/dynamorio.git
synced 2026-10-12 02:02:04 +00:00
Updates our Github Actions runners to install clang-format-21. Updates runsuite.cmake to prefer that version. Reformats our files with this version. Fixes #8008
254 lines
7.9 KiB
C
254 lines
7.9 KiB
C
/* **********************************************************
|
|
* Copyright (c) 2003 VMware, Inc. All rights reserved.
|
|
* **********************************************************/
|
|
|
|
/*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* * Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* * Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* * Neither the name of VMware, Inc. nor the names of its contributors may be
|
|
* used to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
* DAMAGE.
|
|
*/
|
|
|
|
#define _WIN32_WINNT 0x0400
|
|
|
|
#include <Windows.h>
|
|
#include <stdio.h>
|
|
#include <Tlhelp32.h>
|
|
#include <tchar.h>
|
|
#include <pdh.h>
|
|
|
|
// a.s.
|
|
#include <stdlib.h>
|
|
|
|
#define MAXPATH 80
|
|
#define NCOUNTERS 27
|
|
#define MCOUNTERS 3
|
|
|
|
TCHAR *counters[NCOUNTERS] = {
|
|
_T("Thread Count"),
|
|
_T("Working Set"),
|
|
_T("Page Faults/sec"),
|
|
_T("Page File Bytes"),
|
|
_T("% User Time"),
|
|
_T("% Privileged Time"),
|
|
_T("% Processor Time"),
|
|
_T("Creating Process ID"),
|
|
_T("Elapsed Time"),
|
|
_T("Handle Count"),
|
|
_T("ID Process"),
|
|
_T("IO Data Bytes/sec"),
|
|
_T("IO Data Operations/sec"),
|
|
_T("IO Other Bytes/sec"),
|
|
_T("IO Other Operations/sec"),
|
|
_T("IO Read Bytes/sec"),
|
|
_T("IO Read Operations/sec"),
|
|
_T("IO Write Bytes/sec"),
|
|
_T("IO Write Operations/sec"),
|
|
_T("Page File Bytes Peak"),
|
|
_T("Pool Nonpaged Bytes"),
|
|
_T("Pool Paged Bytes"),
|
|
_T("Priority Base"),
|
|
_T("Private Bytes"),
|
|
_T("Virtual Bytes"),
|
|
_T("Virtual Bytes Peak"),
|
|
_T("Working Set Peak"),
|
|
};
|
|
|
|
TCHAR *shortnames[NCOUNTERS] = {
|
|
_T("tc"), _T("wss"), _T("pgflts"), _T("pgfileK"), _T("utimes"),
|
|
_T("ktimes"), _T("ttimes"), _T("ppid"), _T("realtim"), _T("handles"),
|
|
_T("pid"), _T("IOdataK"), _T("IOdataO"), _T("IOothrK"), _T("IOothrO"),
|
|
_T("IOreadK"), _T("IOreadO"), _T("IOwritK"), _T("IOwritO"), _T("pgfpeak"),
|
|
_T("poolnpK"), _T("poolpK"), _T("priorty"), _T("privK"), _T("vmK"),
|
|
_T("vmpeak"), _T("wsspeak"),
|
|
};
|
|
|
|
TCHAR *formatstrings[NCOUNTERS] = {
|
|
_T("%.0f\t"), _T("%.0f\t"), _T("%.0f\t"), _T("%.0f\t"), _T("%.2f\t"), _T("%.2f\t"),
|
|
_T("%.2f\t"), _T("%.0f\t"), _T("%.2f\t"), _T("%.0f\t"), _T("%.0f\t"), _T("%.0f\t"),
|
|
_T("%.0f\t"), _T("%.0f\t"), _T("%.0f\t"), _T("%.0f\t"), _T("%.0f\t"), _T("%.0f\t"),
|
|
_T("%.0f\t"), _T("%.0f\t"), _T("%.0f\t"), _T("%.0f\t"), _T("%.0f\t"), _T("%.0f\t"),
|
|
_T("%.0f\t"), _T("%.0f\t"), _T("%.0f\t"),
|
|
};
|
|
|
|
BOOL use_kb[NCOUNTERS] = {
|
|
0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
|
|
};
|
|
|
|
int
|
|
waitforprocess(TCHAR *name)
|
|
{
|
|
HANDLE processes;
|
|
PROCESSENTRY32 pe = { sizeof(pe) };
|
|
BOOL fOK;
|
|
while (1) {
|
|
processes = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
fOK = Process32First(processes, &pe);
|
|
for (; fOK; fOK = Process32Next(processes, &pe)) {
|
|
if (!_tcsicmp(pe.szExeFile, name))
|
|
return pe.th32ProcessID;
|
|
}
|
|
CloseHandle(processes);
|
|
Sleep(181);
|
|
}
|
|
}
|
|
|
|
// a.s.
|
|
void
|
|
GetProcNameFromId(int pid, TCHAR *pName)
|
|
{
|
|
HANDLE processes;
|
|
PROCESSENTRY32 pe = { sizeof(pe) };
|
|
BOOL fOK;
|
|
while (1) {
|
|
processes = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
fOK = Process32First(processes, &pe);
|
|
for (; fOK; fOK = Process32Next(processes, &pe)) {
|
|
if ((int)pe.th32ProcessID == pid) {
|
|
_tcscpy(pName, pe.szExeFile);
|
|
return;
|
|
}
|
|
}
|
|
CloseHandle(processes);
|
|
Sleep(181);
|
|
}
|
|
}
|
|
// eof a.s.
|
|
|
|
int __cdecl
|
|
_tmain(int argc, TCHAR **argv)
|
|
{
|
|
HQUERY hQuery;
|
|
HCOUNTER *pCounterHandle;
|
|
PDH_STATUS pdhStatus;
|
|
PDH_FMT_COUNTERVALUE fmtValue;
|
|
DWORD ctrType;
|
|
TCHAR szPathBuffer[MAXPATH];
|
|
int i, samples = 0;
|
|
int NUM_SAMPLES = 1000, INTERVAL_MS = 1000;
|
|
int pid;
|
|
FILE *fp = stdout;
|
|
char fn[MAXPATH];
|
|
TCHAR basename[MAXPATH];
|
|
HANDLE htimer;
|
|
LARGE_INTEGER duetime;
|
|
|
|
if (argc < 2) {
|
|
_ftprintf(stderr,
|
|
_T("Usage: %s [<exeName> | <pid> | all] [num_samples] [interval] ")
|
|
_T("[outputfile]\n"),
|
|
argv[0]);
|
|
return -1;
|
|
}
|
|
|
|
if (_tcscmp(argv[1], _T("all"))) {
|
|
if (isalpha(*argv[1])) {
|
|
printf("waiting...\n");
|
|
pid = waitforprocess(argv[1]);
|
|
// remove .exe
|
|
_tcscpy(basename, argv[1]);
|
|
basename[_tcslen(argv[1]) - 4] = _T('\0');
|
|
} else {
|
|
pid = _ttoi(argv[1]);
|
|
GetProcNameFromId(pid, basename);
|
|
basename[_tcslen(basename) - 4] = _T('\0');
|
|
}
|
|
// eof a.s.
|
|
} else {
|
|
pid = 0;
|
|
_tcscpy(basename, _T("_Total"));
|
|
}
|
|
|
|
if (argc > 2) {
|
|
NUM_SAMPLES = _ttoi(argv[2]);
|
|
if (argc > 3)
|
|
INTERVAL_MS = _ttoi(argv[3]);
|
|
if (argc > 4) {
|
|
sprintf(fn, "%S", argv[4]);
|
|
fp = fopen(fn, "w");
|
|
if (fp == NULL) {
|
|
_ftprintf(stderr, _T("error opening output file %s\n"), argv[4]);
|
|
return -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
_ftprintf(stderr, _T("Monitoring %s, pid=%d. Using %d samples at %dms interval\n"),
|
|
basename, pid, NUM_SAMPLES, INTERVAL_MS);
|
|
|
|
pdhStatus = PdhOpenQuery(0, 0, &hQuery);
|
|
pCounterHandle = (HCOUNTER *)malloc(NCOUNTERS * sizeof(HCOUNTER));
|
|
|
|
for (i = 0; i < NCOUNTERS; ++i) {
|
|
_stprintf(szPathBuffer, _T("\\Process(%s)\\%s"), basename, counters[i]);
|
|
pdhStatus = PdhAddCounter(hQuery, szPathBuffer, 0, &pCounterHandle[i]);
|
|
}
|
|
|
|
// "Prime" counters that need two values to display a formatted value.
|
|
pdhStatus = PdhCollectQueryData(hQuery);
|
|
|
|
// disp titles
|
|
for (i = 0; i < NCOUNTERS; ++i)
|
|
_ftprintf(fp, _T("%s\t"), shortnames[i]);
|
|
_ftprintf(fp, _T("\n"));
|
|
|
|
htimer = CreateWaitableTimer(NULL, FALSE, NULL);
|
|
duetime.LowPart = 0;
|
|
duetime.HighPart = 0;
|
|
SetWaitableTimer(htimer, &duetime, INTERVAL_MS, NULL, NULL, FALSE);
|
|
|
|
while (samples++ < NUM_SAMPLES) {
|
|
|
|
// first wait is instantaneous
|
|
WaitForSingleObject(htimer, INTERVAL_MS * 2);
|
|
|
|
pdhStatus = PdhCollectQueryData(hQuery);
|
|
|
|
for (i = 0; i < NCOUNTERS; ++i) {
|
|
// Get the current value of this counter.
|
|
pdhStatus = PdhGetFormattedCounterValue(pCounterHandle[i], PDH_FMT_DOUBLE,
|
|
&ctrType, &fmtValue);
|
|
|
|
if (pdhStatus == ERROR_SUCCESS) {
|
|
_ftprintf(fp, formatstrings[i],
|
|
use_kb[i] ? fmtValue.doubleValue / 1024 : fmtValue.doubleValue);
|
|
} else {
|
|
goto processgone;
|
|
}
|
|
}
|
|
_ftprintf(fp, _T("\n"));
|
|
}
|
|
|
|
processgone:
|
|
|
|
pdhStatus = PdhCloseQuery(hQuery);
|
|
|
|
if (fp != stdout)
|
|
fclose(fp);
|
|
|
|
free(pCounterHandle);
|
|
|
|
return 0;
|
|
}
|