Integrate from internal VSTS to GitHub

This commit is contained in:
Mukul Sabharwal 2019-04-27 16:56:19 -07:00
Родитель 39ca5dcf4d
Коммит db5e96532f
24 изменённых файлов: 3915 добавлений и 1857 удалений

Просмотреть файл

@ -1,248 +0,0 @@
#include <thread>
#include <Windows.h>
#include <Evntprov.h>
#include <Evntcons.h>
#include <Evntrace.h>
#include <strsafe.h>
#define USAGE L"Usage: BPerfSymbolDataCollector LogsDirectory [ProcesNameFilters]\n"
#define EXAMPLE L"Example: BPerfSymbolDataCollector D:\\Data\\BPerfSymbols w3wp.exe\n"
#define EXAMPLE2 L"Example: BPerfSymbolDataCollector D:\\Data\\BPerfSymbols w3wp.exe;sql.exe\n"
#define CTRLCHANDLDED L"Ctrl+C handled, stopping session.\n"
#define LOGSESSION_NAME L"BPerfSymbols"
#define SYMBOLS_FILE_NAME L"Symbols.bin"
#define MAX_EVENT_SIZE 65536
#define UCHAR_SIZE 1
#define USHORT_SIZE 2
#define ULONG_SIZE 4
#define LARGE_INTEGER_SIZE 8
#define ULONGLONGSIZE 8
#define GUID_SIZE 16
#define CLRJITANDLOADERKEYWORD 0x00000018
constexpr GUID ClrRundownProviderGuid = {0xA669021C, 0xC450, 0x4609, {0xA0, 0x35, 0x5A, 0xF5, 0x9A, 0xF4, 0xDF, 0x18}}; // {A669021C-C450-4609-A035-5AF59AF4DF18}
constexpr GUID ClrProviderGuid = {0xE13C0D23, 0xCCBC, 0x4E12, {0x93, 0x1B, 0xD9, 0xCC, 0x2E, 0xEE, 0x27, 0xE4}}; // {E13C0D23-CCBC-4E12-931B-D9CC2EEE27E4}
constexpr GUID CoreClrProviderGuid = {0x319DC449, 0xADA5, 0x50F7, {0x42, 0x8E, 0x95, 0x7D, 0xB6, 0x79, 0x16, 0x68}}; // {319DC449-ADA5-50F7-428E-957DB6791668}
constexpr USHORT DCStopComplete = 146;
/* Begin Global Data */
TRACEHANDLE sessionHandle;
HANDLE outputFile;
BYTE writeBuffer[MAX_EVENT_SIZE];
bool ctrlCTriggered = false;
/* End Global Data */
BOOL WINAPI ConsoleControlHandler(DWORD ctrlType)
{
switch (ctrlType)
{
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
wprintf(CTRLCHANDLDED);
ctrlCTriggered = true;
EVENT_TRACE_PROPERTIES properties;
ZeroMemory(&properties, sizeof(EVENT_TRACE_PROPERTIES));
properties.Wnode.BufferSize = sizeof(EVENT_TRACE_PROPERTIES);
ControlTrace(0, LOGSESSION_NAME, &properties, EVENT_TRACE_CONTROL_STOP);
default:
break;
}
return FALSE;
}
ULONG WINAPI BufferCallback(_In_ PEVENT_TRACE_LOGFILEW callBack)
{
UNREFERENCED_PARAMETER(callBack);
return 1;
}
VOID WINAPI EventCallback(_In_ PEVENT_RECORD eventRecord)
{
CopyMemory(writeBuffer, &eventRecord->EventHeader.TimeStamp, LARGE_INTEGER_SIZE);
CopyMemory(writeBuffer + LARGE_INTEGER_SIZE, &eventRecord->EventHeader.ProcessId, ULONG_SIZE);
CopyMemory(writeBuffer + LARGE_INTEGER_SIZE + ULONG_SIZE, &eventRecord->EventHeader.ThreadId, ULONG_SIZE);
CopyMemory(writeBuffer + LARGE_INTEGER_SIZE + ULONG_SIZE + ULONG_SIZE, &eventRecord->EventHeader.ProviderId, GUID_SIZE);
CopyMemory(writeBuffer + LARGE_INTEGER_SIZE + ULONG_SIZE + ULONG_SIZE + GUID_SIZE, &eventRecord->EventHeader.EventDescriptor.Id, USHORT_SIZE);
CopyMemory(writeBuffer + LARGE_INTEGER_SIZE + ULONG_SIZE + ULONG_SIZE + GUID_SIZE + USHORT_SIZE, &eventRecord->EventHeader.EventDescriptor.Version, UCHAR_SIZE);
CopyMemory(writeBuffer + LARGE_INTEGER_SIZE + ULONG_SIZE + ULONG_SIZE + GUID_SIZE + USHORT_SIZE + UCHAR_SIZE, &eventRecord->EventHeader.EventDescriptor.Level, UCHAR_SIZE);
CopyMemory(writeBuffer + LARGE_INTEGER_SIZE + ULONG_SIZE + ULONG_SIZE + GUID_SIZE + USHORT_SIZE + UCHAR_SIZE + UCHAR_SIZE, &eventRecord->EventHeader.EventDescriptor.Channel, UCHAR_SIZE);
CopyMemory(writeBuffer + LARGE_INTEGER_SIZE + ULONG_SIZE + ULONG_SIZE + GUID_SIZE + USHORT_SIZE + UCHAR_SIZE + UCHAR_SIZE + UCHAR_SIZE, &eventRecord->EventHeader.EventDescriptor.Opcode, UCHAR_SIZE);
CopyMemory(writeBuffer + LARGE_INTEGER_SIZE + ULONG_SIZE + ULONG_SIZE + GUID_SIZE + USHORT_SIZE + UCHAR_SIZE + UCHAR_SIZE + UCHAR_SIZE + UCHAR_SIZE, &eventRecord->EventHeader.EventDescriptor.Task, USHORT_SIZE);
CopyMemory(writeBuffer + LARGE_INTEGER_SIZE + ULONG_SIZE + ULONG_SIZE + GUID_SIZE + USHORT_SIZE + UCHAR_SIZE + UCHAR_SIZE + UCHAR_SIZE + UCHAR_SIZE + USHORT_SIZE, &eventRecord->EventHeader.EventDescriptor.Keyword, ULONGLONGSIZE);
CopyMemory(writeBuffer + LARGE_INTEGER_SIZE + ULONG_SIZE + ULONG_SIZE + GUID_SIZE + USHORT_SIZE + UCHAR_SIZE + UCHAR_SIZE + UCHAR_SIZE + UCHAR_SIZE + USHORT_SIZE + ULONGLONGSIZE, &eventRecord->UserDataLength, USHORT_SIZE);
CopyMemory(writeBuffer + LARGE_INTEGER_SIZE + ULONG_SIZE + ULONG_SIZE + GUID_SIZE + USHORT_SIZE + UCHAR_SIZE + UCHAR_SIZE + UCHAR_SIZE + UCHAR_SIZE + USHORT_SIZE + ULONGLONGSIZE + USHORT_SIZE, eventRecord->UserData, eventRecord->UserDataLength);
DWORD numbBytesToWrite = LARGE_INTEGER_SIZE + ULONG_SIZE + ULONG_SIZE + GUID_SIZE + USHORT_SIZE + UCHAR_SIZE + UCHAR_SIZE + UCHAR_SIZE + UCHAR_SIZE + USHORT_SIZE + ULONGLONGSIZE + USHORT_SIZE + eventRecord->UserDataLength, offset = 0;
DWORD numberOfBytesWritten = 0;
while (WriteFile(outputFile, writeBuffer + offset, numbBytesToWrite, &numberOfBytesWritten, nullptr))
{
if (numberOfBytesWritten == 0)
{
break;
}
offset += numberOfBytesWritten;
numbBytesToWrite -= numberOfBytesWritten;
}
if (eventRecord->EventHeader.ProviderId == ClrRundownProviderGuid && eventRecord->EventHeader.EventDescriptor.Id == DCStopComplete)
{
EnableTraceEx2(sessionHandle, &ClrRundownProviderGuid, EVENT_CONTROL_CODE_DISABLE_PROVIDER, TRACE_LEVEL_VERBOSE, 0, 0, 0, nullptr);
}
}
HRESULT StartSymbolicDataSession(_In_ LPWSTR sessionName, _In_ LPCWSTR outputFileName, _In_opt_ LPCWSTR exeNamesFilter)
{
auto sessionNameSizeInBytes = (wcslen(sessionName) + 1) * sizeof(WCHAR);
auto bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + sessionNameSizeInBytes + sizeof(WCHAR); // for '\0'
auto sessionProperties = static_cast<PEVENT_TRACE_PROPERTIES>(malloc(bufferSize));
if (sessionProperties == nullptr)
{
return E_FAIL;
}
ZeroMemory(sessionProperties, bufferSize);
sessionProperties->Wnode.BufferSize = static_cast<ULONG>(bufferSize);
sessionProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
sessionProperties->Wnode.ClientContext = 1;
sessionProperties->MinimumBuffers = max(64, std::thread::hardware_concurrency() * 2);
sessionProperties->MaximumBuffers = sessionProperties->MinimumBuffers * 2;
sessionProperties->BufferSize = 1024; // 1MB
sessionProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE | EVENT_TRACE_INDEPENDENT_SESSION_MODE;
sessionProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
sessionProperties->LogFileNameOffset = 0; // real time session has no file name
sessionProperties->FlushTimer = 1; // 1 second
StringCbCopy(reinterpret_cast<LPWSTR>(reinterpret_cast<char *>(sessionProperties) + sessionProperties->LoggerNameOffset), sessionNameSizeInBytes, sessionName);
HRESULT hr;
auto retryCount = 1;
while (retryCount < 10)
{
hr = StartTrace(&sessionHandle, sessionName, sessionProperties);
if (hr != ERROR_SUCCESS)
{
if (hr == ERROR_ALREADY_EXISTS || hr == ERROR_INVALID_PARAMETER)
{
hr = ControlTrace(sessionHandle, sessionName, sessionProperties, EVENT_TRACE_CONTROL_STOP);
if (hr == ERROR_WMI_INSTANCE_NOT_FOUND || hr == ERROR_SUCCESS)
{
Sleep(100 * retryCount); // sleep for 100-milliseconds to let it propogate.
retryCount++;
continue;
}
}
return hr;
}
break;
}
outputFile = CreateFile(outputFileName, GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ, nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, nullptr);
if (outputFile == INVALID_HANDLE_VALUE)
{
return HRESULT_FROM_WIN32(::GetLastError());
}
EVENT_TRACE_LOGFILE logFile;
ZeroMemory(&logFile, sizeof(EVENT_TRACE_LOGFILE));
logFile.LogFileName = nullptr;
logFile.LoggerName = sessionName;
logFile.LogFileMode = PROCESS_TRACE_MODE_EVENT_RECORD | PROCESS_TRACE_MODE_REAL_TIME | PROCESS_TRACE_MODE_RAW_TIMESTAMP;
logFile.BufferCallback = BufferCallback;
logFile.EventRecordCallback = EventCallback;
TRACEHANDLE traceHandle = OpenTrace(&logFile);
if (traceHandle == reinterpret_cast<TRACEHANDLE>(INVALID_HANDLE_VALUE))
{
return HRESULT_FROM_WIN32(::GetLastError());
}
ENABLE_TRACE_PARAMETERS enableParameters;
ZeroMemory(&enableParameters, sizeof(ENABLE_TRACE_PARAMETERS));
enableParameters.FilterDescCount = 0;
enableParameters.Version = ENABLE_TRACE_PARAMETERS_VERSION_2;
EVENT_FILTER_DESCRIPTOR descriptor[1];
if (exeNamesFilter != nullptr)
{
descriptor[0].Ptr = ULONGLONG(exeNamesFilter);
descriptor[0].Size = static_cast<ULONG>((wcslen(exeNamesFilter) + 1) * sizeof(WCHAR));
descriptor[0].Type = EVENT_FILTER_TYPE_EXECUTABLE_NAME;
enableParameters.EnableFilterDesc = descriptor;
enableParameters.FilterDescCount = 1;
}
hr = EnableTraceEx2(sessionHandle, &ClrProviderGuid, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_VERBOSE, CLRJITANDLOADERKEYWORD, 0, 0, &enableParameters);
if (hr != ERROR_SUCCESS)
{
return hr;
}
hr = EnableTraceEx2(sessionHandle, &CoreClrProviderGuid, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_VERBOSE, CLRJITANDLOADERKEYWORD, 0, 0, &enableParameters);
if (hr != ERROR_SUCCESS)
{
return hr;
}
hr = EnableTraceEx2(sessionHandle, &ClrRundownProviderGuid, EVENT_CONTROL_CODE_ENABLE_PROVIDER, TRACE_LEVEL_VERBOSE, 0x00020118, 0, 0, &enableParameters);
if (hr != ERROR_SUCCESS)
{
return hr;
}
ProcessTrace(&traceHandle, 1, nullptr, nullptr);
CloseHandle(outputFile);
return ERROR_SUCCESS;
}
int wmain(_In_ int argc, _In_ PWSTR *argv)
{
if (argc < 2)
{
wprintf(USAGE);
wprintf(EXAMPLE);
wprintf(EXAMPLE2);
return ERROR_INVALID_PARAMETER;
}
auto flushThread = std::thread([] {
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
FlushFileBuffers(outputFile);
}
});
SetConsoleCtrlHandler(ConsoleControlHandler, true);
SetCurrentDirectory(argv[1]);
wprintf(L"\n BPerfSymbolDataCollector is running ...\n");
wprintf(L" ETW Session Name: ");
wprintf(LOGSESSION_NAME);
wprintf(L"\n Symbol File: ");
wprintf(argv[1]);
wprintf(L"\\");
wprintf(SYMBOLS_FILE_NAME);
wprintf(L"\n\n ** Provide this file location when starting up BPerfCPUSampleCollector **\n");
StartSymbolicDataSession(LOGSESSION_NAME, SYMBOLS_FILE_NAME, argc == 3 ? argv[2] : nullptr);
flushThread.detach(); // let process tear down take care of this
}

Просмотреть файл

@ -1,28 +0,0 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26020.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPerfSymbolDataCollector", "BPerfSymbolDataCollector.vcxproj", "{41DC00DB-09FE-4938-AE08-DE478CF5BC88}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{41DC00DB-09FE-4938-AE08-DE478CF5BC88}.Debug|x64.ActiveCfg = Debug|x64
{41DC00DB-09FE-4938-AE08-DE478CF5BC88}.Debug|x64.Build.0 = Debug|x64
{41DC00DB-09FE-4938-AE08-DE478CF5BC88}.Debug|x86.ActiveCfg = Debug|Win32
{41DC00DB-09FE-4938-AE08-DE478CF5BC88}.Debug|x86.Build.0 = Debug|Win32
{41DC00DB-09FE-4938-AE08-DE478CF5BC88}.Release|x64.ActiveCfg = Release|x64
{41DC00DB-09FE-4938-AE08-DE478CF5BC88}.Release|x64.Build.0 = Release|x64
{41DC00DB-09FE-4938-AE08-DE478CF5BC88}.Release|x86.ActiveCfg = Release|Win32
{41DC00DB-09FE-4938-AE08-DE478CF5BC88}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

Просмотреть файл

@ -1,122 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{41DC00DB-09FE-4938-AE08-DE478CF5BC88}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>BPerfSymbolDataCollector</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="BPerfSymbolDataCollector.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

Просмотреть файл

@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="BPerfSymbolDataCollector.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

326
CPUSamplesCollector/.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,326 @@
syntax: glob
[Bb]inaries/
# Build tools related files
/[Tt]ools/
### VisualStudio ###
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
*.swp
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
build/
bld/
[Bb]in/
[Oo]bj/
msbuild.log
# add back architecture directories ignored in 'Build results'
!tests/x86
!src/mscorlib/src/System/Runtime/Intrinsics/X86
!tests/src/JIT/HardwareIntrinsics/X86
# Visual Studio 2015
.vs/
# Visual Studio 2015 Pre-CTP6
*.sln.ide
*.ide/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
#NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.html
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
*.nuget.g.props
*.nuget.g.targets
*.nuget.cache
**/packages/*
*.nuget.dgspec.json
project.lock.json
project.assets.json
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
*.metaproj
*.metaproj.tmp
.atom-build.json
tags
TAGS
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# C/C++ extension for Visual Studio Code
browse.VC.db
# Local settings folder for Visual Studio Code
.vscode/
### MonoDevelop ###
*.pidb
*.userprefs
### Windows ###
# Windows image file caches
Thumbs.db
ehthumbs.db
# Folder config file
Desktop.ini
# Recycle Bin used on file shares
$RECYCLE.BIN/
# Windows Installer files
*.cab
*.msi
*.msm
*.msp
# Windows shortcuts
*.lnk
# Common binary extensions on Windows
*.exe
*.exe.stackdump
*.dll
*.lib
### Linux ###
*~
\#*\#
# KDE directory preferences
.directory
### OSX ###
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear on external disk
.Spotlight-V100
.Trashes
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
# We have some checked in prebuilt generated files
!src/pal/prebuilt/idl/*_i.c
# Valid 'debug' folder, that contains CLR debugging code
!src/debug
# Ignore folders created by the test build
TestWrappers_x64_[d|D]ebug
TestWrappers_x64_[c|C]hecked
TestWrappers_x64_[r|R]elease
TestWrappers_x86_[d|D]ebug
TestWrappers_x86_[c|C]hecked
TestWrappers_x86_[r|R]elease
TestWrappers_arm_[d|D]ebug
TestWrappers_arm_[c|C]hecked
TestWrappers_arm_[r|R]elease
TestWrappers_arm64_[d|D]ebug
TestWrappers_arm64_[c|C]hecked
TestWrappers_arm64_[r|R]elease
tests/src/common/test_runtime/project.json
Vagrantfile
.vagrant
# CMake files
CMakeFiles/
cmake_install.cmake
CMakeCache.txt
Makefile
# Cross compilation
cross/rootfs/*
cross/android-rootfs/*
# add x86 as it is ignored in 'Build results'
!cross/x86
#python import files
*.pyc
# JIT32 files
src/jit32
# performance testing sandbox
sandbox
#IL linker for testing
linker
# Arcade files
/artifacts/toolset
/.packages
/.dotnet

Просмотреть файл

@ -0,0 +1,183 @@
[ETWSession]
Name=BPerfProfiles
FileNamePrefix=BPerfProfiles.
LogRotationIntervalInSeconds=900
DataDirectory=%DATADIR%\BPerfLogs\Profiles
BufferSizeInKB=1024
CPUSamplingRateInMS=1
; EVENT_TRACE_FLAG_PROCESS | EVENT_TRACE_FLAG_IMAGE_LOAD | EVENT_TRACE_FLAG_THREAD | EVENT_TRACE_FLAG_PROFILE;
KernelEnableFlags=16777223
EnableEmbeddingEventMetadata=1
EnableEmbeddingSymbolServerKeyInfo=1
EnableMetadataSideStream=1
OnDiskFormat=1
Providers=PerfInfo,Thread,Process,PageFault,ImageLoad,.NET Common Language Runtime,DotNet,System.Threading.Tasks.TplEventSource,Microsoft-Windows-ASPNET,Microsoft-Windows-TCPIP,Microsoft-Windows-Kernel-Process,Microsoft-Windows-Kernel-Processor-Power,HTTP Service Trace,Microsoft-Windows-DNS-Client,System.Diagnostics.Eventing.FrameworkEventSource,Microsoft-JScript,Microsoft-AspNetCore-Server-Kestrel,Microsoft-AspNetCore-Hosting,IIS: WWW Server,ASP.NET Events,BPerfStampingEventSource,BPerfInfoEventSource,PipelineInfoEventSource,MonitoredScopeEventSource,TcpHttpCorrelationEventSource,AutopilotLoggerEventSource,QuickInjectEventSource,MDMEventSource,SmartBuildEventSource,MiniStampEventSource,BufferManagerEventSource,FederationEventSource,ChunkDiagnosticsEventSource,ImageEmbeddingEventSource
ClassicEventIdsStack=PerfInfoStack,ImageLoadStack
[PerfInfoStack]
Guid={CE1DBFB4-137E-4DA6-87B0-3F59AA102CBC}
; SampledProfile
Type=46
[ImageLoadStack]
Guid={2CB15D1D-5FC1-11D2-ABE1-00A0C911F518}
Type=10
; Important Kernel Events
[PerfInfo] ; Timer (for CPU Profiling)
Guid={CE1DBFB4-137E-4DA6-87B0-3F59AA102CBC}
Level=4
[Thread] ; Thread Start/Stop
Guid={3D6FA8D1-FE05-11D0-9DDA-00C04FD7BA7C}
Level=4
[Process] ; Process Start/Stop
Guid={3D6FA8D0-FE05-11D0-9DDA-00C04FD7BA7C}
Level=4
[PageFault] ; PageFaults
Guid={3D6FA8D3-FE05-11D0-9DDA-00C04FD7BA7C}
Level=4
[ImageLoad] ; Image Load/Unloads
Guid={2CB15D1D-5FC1-11D2-ABE1-00A0C911F518}
Level=4
; Important OS Components
[.NET Common Language Runtime]
Guid={E13C0D23-CCBC-4E12-931B-D9CC2EEE27E4}
MatchAnyKeyword=2147581969
; Allocation Tick, GC Triggered, LoadVerbose, Exception Start, Catch, Finally
StackEventIdsFilter=10,35,80,143,250,252
Level=4
[DotNet]
Guid={319DC449-ADA5-50F7-428E-957DB6791668}
MatchAnyKeyword=2147581969
; Allocation Tick, GC Triggered, LoadVerbose, Exception Start, Catch, Finally
StackEventIdsFilter=10,35,80,143,250,252
Level=4
[System.Threading.Tasks.TplEventSource]
Guid={2E5DBA47-A3D2-4D16-8EE0-6671FFDCD7B5}
Level=5
MatchAnyKeyword=66
; System.Threading.Tasks.TplEventSource/TaskScheduled/Send, System.Threading.Tasks.TplEventSource/TaskWait/Send, System.Threading.Tasks.TplEventSource/AwaitTaskContinuationScheduled/Send
StackEventIdsFilter=7,10,12
[Microsoft-Windows-ASPNET]
Guid={EE799F41-CFA5-550B-BF2C-344747C1C668}
Level=4
[Microsoft-Windows-TCPIP]
Guid={2F07E2EE-15DB-40F1-90EF-9D7BA282188A}
Level=5
; TcpCreateEndpoint
StackEventIdsFilter=1013
; TcpTcbStopTimer, TcpipDeliveryIndicated, TcpipReceiveSlowPath, TcpipSendSlowPath, TcpTcbStartTimer, TcpDataTransferReceive, TcpReleaseIndication, Unknown, Unknown
ExcludeEventIdsFilter=1065,1157,1205,1206,1064,1074,1090,1319,1320
[Microsoft-Windows-Kernel-Process]
Guid={22FB2CD6-0E7B-422B-A0C7-2FAD1FD0E716}
Level=4
[Microsoft-Windows-Kernel-Processor-Power]
Guid={0F67E49F-FE51-4E9F-B490-6F2948CC6027}
Level=4
[HTTP Service Trace]
Guid={DD5EF90A-6398-47A4-AD34-4DCECDEF795F}
Level=4
[Microsoft-Windows-DNS-Client]
Guid={1C95126E-7EEA-49A9-A3FE-A378B03DDB4D}
Level=4
[System.Diagnostics.Eventing.FrameworkEventSource]
Guid={8E9F5090-2D75-4D03-8A81-E5AFBF85DAF1}
Level=4
[Microsoft-JScript]
Guid={57277741-3638-4A4B-BDBA-0AC6E45DA56C}
Level=4
[Microsoft-AspNetCore-Server-Kestrel]
Guid={BDEB4676-A36E-5442-DB99-4764E2326C7D}
Level=4
[Microsoft-AspNetCore-Hosting]
Guid={9E620D2A-55D4-5ADE-DEB7-C26046D245A8}
Level=4
[IIS: WWW Server]
Guid={3A2A4E84-4C21-4981-AE10-3FDA0D9B0F83}
Level=4
[ASP.NET Events]
Guid={AFF081FE-0247-4275-9C4E-021F3DC1DA35}
Level=4
; BPerf Critical
[BPerfStampingEventSource] ; Used for stamping request entry points / thread migrations
Guid={D46E5565-D624-4C4D-89CC-7A82887D3627}
Level=4
[BPerfInfoEventSource] ; Used for Stack Viewer
Guid={79430003-51BF-5F05-ED34-99CF32652C26}
Level=4
[PipelineInfoEventSource] ; Used for detecting end of request early termination
Guid={F929009C-E2CF-4408-873E-20D60DAE6B55}
Level=4
; Bing SNR Specific
[MonitoredScopeEventSource]
Guid={2E185D98-344D-5EF7-0630-AFE322F01B98}
Level=4
[TcpHttpCorrelationEventSource]
Guid={B51B554F-10F4-59D9-8C75-4273142D39C9}
Level=4
[AutopilotLoggerEventSource]
Guid={20DC2E75-5A26-5799-AFE1-11D887F18932}
Level=5
[QuickInjectEventSource]
Guid={5BF45913-60EB-5DD5-78FA-0C46DE21A2FB}
Level=4
[MDMEventSource]
Guid={EDC24920-E004-40F6-A8E1-0E6E48F39D84}
Level=4
; ULongMetricEvent, ExternallyAggregatedULongMetricEvent, ExternallyAggregatedDoubleMetricEvent, DoubleMetricEvent
StackEventIdsFilter=50,53,54,55
[SmartBuildEventSource]
Guid={1AB5F7B3-A330-50EE-3F97-9B55CD5CA518}
Level=4
[MiniStampEventSource]
Guid={E5F0384D-6D0C-5390-086C-7789F2311078}
Level=4
[BufferManagerEventSource]
Guid={B4397DF7-B17C-49BE-A199-262BE5A0F1A3}
Level=4
[FederationEventSource]
Guid={FDEC008F-293F-4B6F-9B38-13274105856D}
Level=4
[ChunkDiagnosticsEventSource]
Guid={7B4915F6-10B0-5AE4-3F3A-1065A44ADFE0}
Level=4
[ImageEmbeddingEventSource]
Guid={B9C54873-2E41-5D15-9637-50CAA653A1E9}
Level=4

Просмотреть файл

@ -1,22 +1,55 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26020.0
# Visual Studio Version 16
VisualStudioVersion = 16.0.28803.202
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BPerfCPUSamplesCollector", "BPerfCPUSamplesCollector.vcxproj", "{628BB6D0-1469-4652-9DF9-B7FEC89F0548}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dll", "dll\dll.vcxproj", "{7CEF2038-7FBC-4C06-880E-C2B64FF17D8D}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "exe", "exe\exe.vcxproj", "{8849F8A2-C5DC-4B8A-AE85-6BBD5C065171}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "lib", "lib\lib.vcxproj", "{4CC1C899-4372-4FF0-92B2-C841C332F17C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.BPerf.DataCollector", "mgd\Microsoft.BPerf.DataCollector.csproj", "{A1B3D838-12CF-43EB-829A-644A5E4E8C1A}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{628BB6D0-1469-4652-9DF9-B7FEC89F0548}.Debug|x64.ActiveCfg = Debug|x64
{628BB6D0-1469-4652-9DF9-B7FEC89F0548}.Debug|x64.Build.0 = Debug|x64
{628BB6D0-1469-4652-9DF9-B7FEC89F0548}.Release|x64.ActiveCfg = Release|x64
{628BB6D0-1469-4652-9DF9-B7FEC89F0548}.Release|x64.Build.0 = Release|x64
{7CEF2038-7FBC-4C06-880E-C2B64FF17D8D}.Debug|Any CPU.ActiveCfg = Debug|x64
{7CEF2038-7FBC-4C06-880E-C2B64FF17D8D}.Debug|x64.ActiveCfg = Debug|x64
{7CEF2038-7FBC-4C06-880E-C2B64FF17D8D}.Debug|x64.Build.0 = Debug|x64
{7CEF2038-7FBC-4C06-880E-C2B64FF17D8D}.Release|Any CPU.ActiveCfg = Release|x64
{7CEF2038-7FBC-4C06-880E-C2B64FF17D8D}.Release|x64.ActiveCfg = Release|x64
{7CEF2038-7FBC-4C06-880E-C2B64FF17D8D}.Release|x64.Build.0 = Release|x64
{8849F8A2-C5DC-4B8A-AE85-6BBD5C065171}.Debug|Any CPU.ActiveCfg = Debug|x64
{8849F8A2-C5DC-4B8A-AE85-6BBD5C065171}.Debug|x64.ActiveCfg = Debug|x64
{8849F8A2-C5DC-4B8A-AE85-6BBD5C065171}.Debug|x64.Build.0 = Debug|x64
{8849F8A2-C5DC-4B8A-AE85-6BBD5C065171}.Release|Any CPU.ActiveCfg = Release|x64
{8849F8A2-C5DC-4B8A-AE85-6BBD5C065171}.Release|x64.ActiveCfg = Release|x64
{8849F8A2-C5DC-4B8A-AE85-6BBD5C065171}.Release|x64.Build.0 = Release|x64
{4CC1C899-4372-4FF0-92B2-C841C332F17C}.Debug|Any CPU.ActiveCfg = Debug|x64
{4CC1C899-4372-4FF0-92B2-C841C332F17C}.Debug|x64.ActiveCfg = Debug|x64
{4CC1C899-4372-4FF0-92B2-C841C332F17C}.Debug|x64.Build.0 = Debug|x64
{4CC1C899-4372-4FF0-92B2-C841C332F17C}.Release|Any CPU.ActiveCfg = Release|x64
{4CC1C899-4372-4FF0-92B2-C841C332F17C}.Release|x64.ActiveCfg = Release|x64
{4CC1C899-4372-4FF0-92B2-C841C332F17C}.Release|x64.Build.0 = Release|x64
{A1B3D838-12CF-43EB-829A-644A5E4E8C1A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1B3D838-12CF-43EB-829A-644A5E4E8C1A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1B3D838-12CF-43EB-829A-644A5E4E8C1A}.Debug|x64.ActiveCfg = Debug|Any CPU
{A1B3D838-12CF-43EB-829A-644A5E4E8C1A}.Debug|x64.Build.0 = Debug|Any CPU
{A1B3D838-12CF-43EB-829A-644A5E4E8C1A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1B3D838-12CF-43EB-829A-644A5E4E8C1A}.Release|Any CPU.Build.0 = Release|Any CPU
{A1B3D838-12CF-43EB-829A-644A5E4E8C1A}.Release|x64.ActiveCfg = Release|Any CPU
{A1B3D838-12CF-43EB-829A-644A5E4E8C1A}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {8E75CC9E-19C0-4956-B5AA-9430652BA3D6}
EndGlobalSection
EndGlobal

Просмотреть файл

@ -1,36 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="JittedCodeResolutionSupportCode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="KernelTraceControlSupportCode.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Program.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TraceEventCallback.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="TraceEventCallback.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
</Project>

Просмотреть файл

@ -1,276 +0,0 @@
#include <relogger.h>
#define MAX_EVENT_SIZE 65536
#define ULONG_SIZE 4
#define LARGE_INTEGER_SIZE 8
#define ULONGLONGSIZE 8
#define USHORT_SIZE 2
#define GUID_SIZE 16
#define UCHAR_SIZE 1
BYTE userData[MAX_EVENT_SIZE];
bool Read(PBYTE buf, LARGE_INTEGER &retVal, DWORD &bytesAvailable)
{
if (bytesAvailable >= LARGE_INTEGER_SIZE)
{
buf -= bytesAvailable;
retVal.LowPart = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
retVal.HighPart = buf[7] << 24 | buf[6] << 16 | buf[5] << 8 | buf[4];
bytesAvailable -= LARGE_INTEGER_SIZE;
return true;
}
return false;
}
bool Read(PBYTE buf, ULONGLONG &retVal, DWORD &bytesAvailable)
{
if (bytesAvailable >= ULONGLONGSIZE)
{
buf -= bytesAvailable;
retVal = static_cast<ULONGLONG>(buf[0]) | static_cast<ULONGLONG>(buf[1]) << 8 | static_cast<ULONGLONG>(buf[2]) << 16 | static_cast<ULONGLONG>(buf[3]) << 24 | static_cast<ULONGLONG>(buf[4]) << 32 | static_cast<ULONGLONG>(buf[5]) << 40 | static_cast<ULONGLONG>(buf[6]) << 48 | static_cast<ULONGLONG>(buf[7]) << 56;
bytesAvailable -= ULONGLONGSIZE;
return true;
}
return false;
}
bool Read(PBYTE buf, ULONG &retVal, DWORD &bytesAvailable)
{
if (bytesAvailable >= ULONG_SIZE)
{
buf -= bytesAvailable;
retVal = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
bytesAvailable -= ULONG_SIZE;
return true;
}
return false;
}
bool Read(PBYTE buf, USHORT &retVal, DWORD &bytesAvailable)
{
if (bytesAvailable >= USHORT_SIZE)
{
buf -= bytesAvailable;
retVal = buf[1] << 8 | buf[0];
bytesAvailable -= USHORT_SIZE;
return true;
}
return false;
}
bool Read(PBYTE buf, UCHAR &retVal, DWORD &bytesAvailable)
{
if (bytesAvailable >= UCHAR_SIZE)
{
buf -= bytesAvailable;
retVal = buf[0];
bytesAvailable -= UCHAR_SIZE;
return true;
}
return false;
}
bool Read(PBYTE buf, GUID &retVal, DWORD &bytesAvailable)
{
if (bytesAvailable >= GUID_SIZE)
{
buf -= bytesAvailable;
retVal.Data1 = buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0];
retVal.Data2 = buf[5] << 8 | buf[4];
retVal.Data3 = buf[7] << 8 | buf[6];
retVal.Data4[0] = buf[8];
retVal.Data4[1] = buf[9];
retVal.Data4[2] = buf[10];
retVal.Data4[3] = buf[11];
retVal.Data4[4] = buf[12];
retVal.Data4[5] = buf[13];
retVal.Data4[6] = buf[14];
retVal.Data4[7] = buf[15];
bytesAvailable -= GUID_SIZE;
return true;
}
return false;
}
int i = 0;
bool ReadAndRelogEvent(ITraceRelogger *relogger, PBYTE buf, DWORD bytesAvailable, DWORD &bytesProcessed)
{
bytesProcessed = 0;
DWORD bytesAvailableABeginningOfFunction = bytesAvailable;
buf += bytesAvailableABeginningOfFunction;
LARGE_INTEGER timestamp;
ULONG processId;
ULONG threadId;
GUID providerId;
USHORT eventId;
UCHAR version;
UCHAR level;
UCHAR channel;
UCHAR opcode;
USHORT task;
ULONGLONG keyword;
USHORT userDataLength;
if (!Read(buf, timestamp, bytesAvailable))
{
return false;
}
if (!Read(buf, processId, bytesAvailable))
{
return false;
}
if (!Read(buf, threadId, bytesAvailable))
{
return false;
}
if (!Read(buf, providerId, bytesAvailable))
{
return false;
}
if (!Read(buf, eventId, bytesAvailable))
{
return false;
}
if (!Read(buf, version, bytesAvailable))
{
return false;
}
if (!Read(buf, level, bytesAvailable))
{
return false;
}
if (!Read(buf, channel, bytesAvailable))
{
return false;
}
if (!Read(buf, opcode, bytesAvailable))
{
return false;
}
if (!Read(buf, task, bytesAvailable))
{
return false;
}
if (!Read(buf, keyword, bytesAvailable))
{
return false;
}
if (!Read(buf, userDataLength, bytesAvailable))
{
return false;
}
if (bytesAvailable >= userDataLength)
{
buf -= bytesAvailable;
CopyMemory(userData, buf, userDataLength);
bytesAvailable -= userDataLength;
}
else
{
return false;
}
ITraceEvent *evt;
relogger->CreateEventInstance(0, 0, &evt);
EVENT_DESCRIPTOR eventDescriptor;
eventDescriptor.Id = eventId;
eventDescriptor.Version = version;
eventDescriptor.Level = level;
eventDescriptor.Channel = channel;
eventDescriptor.Opcode = opcode;
eventDescriptor.Task = task;
eventDescriptor.Keyword = keyword;
evt->SetProviderId(&providerId);
evt->SetTimeStamp(&timestamp);
evt->SetProcessId(processId);
evt->SetThreadId(threadId);
evt->SetEventDescriptor(&eventDescriptor);
evt->SetPayload(userData, userDataLength);
relogger->Inject(evt);
evt->Release();
bytesProcessed = bytesAvailableABeginningOfFunction - bytesAvailable;
return true;
}
void LogJittedCodeSymbolicData(HANDLE hFile, ITraceRelogger *relogger)
{
LARGE_INTEGER fileSize;
auto disk_buffer = static_cast<PBYTE>(malloc(MAX_EVENT_SIZE));
auto memory_buffer = static_cast<PBYTE>(malloc(MAX_EVENT_SIZE));
if (GetFileSizeEx(hFile, &fileSize) == FALSE)
{
return;
}
LONGLONG remainingFileSize = fileSize.QuadPart;
while (remainingFileSize > 0)
{
DWORD bytesToRead = static_cast<DWORD>(min(remainingFileSize, MAX_EVENT_SIZE));
bool shouldExitAfterRetry = bytesToRead < MAX_EVENT_SIZE;
{
DWORD bytesRead = 0, offset = 0;
while (ReadFile(hFile, disk_buffer, bytesToRead - offset, &bytesRead, nullptr))
{
if (bytesRead == 0)
{
break;
}
CopyMemory(memory_buffer + offset, disk_buffer, bytesRead);
offset += bytesRead;
}
}
remainingFileSize -= bytesToRead;
{
DWORD bytesAvailableToProcess = bytesToRead, bytesProcessed = 0, offsetIntoBuffer = 0;
while (ReadAndRelogEvent(relogger, memory_buffer + offsetIntoBuffer, bytesAvailableToProcess, bytesProcessed))
{
bytesAvailableToProcess -= bytesProcessed;
offsetIntoBuffer += bytesProcessed;
}
if (!shouldExitAfterRetry)
{
SetFilePointer(hFile, 0 - bytesAvailableToProcess, nullptr, FILE_CURRENT);
remainingFileSize += bytesAvailableToProcess;
}
}
}
free(disk_buffer);
free(memory_buffer);
}

Просмотреть файл

@ -1,367 +0,0 @@
#include <windows.h>
#include <evntcons.h>
#include <dbghelp.h>
#include "TraceEventCallback.h"
#define SystemRoot L"\\SystemRoot"
#define GlobalRoot L"\\\\?\\GLOBALROOT"
std::wstring InitWindowsDir()
{
auto dest = static_cast<PWCHAR>(malloc((MAX_PATH + 1) * 2));
GetWindowsDirectory(dest, MAX_PATH);
std::wstring windowsDirectory(dest);
free(dest);
return windowsDirectory;
}
static std::wstring &&windowsDirectory = InitWindowsDir();
auto ReadInt32(PBYTE &data)
{
uint32_t retVal;
char *p = reinterpret_cast<char *>(&retVal);
p[0] = data[0];
p[1] = data[1];
p[2] = data[2];
p[3] = data[3];
data += 4;
return retVal;
}
auto ReadInt64(PBYTE &data)
{
uint64_t retVal;
char *p = reinterpret_cast<char *>(&retVal);
p[0] = data[0];
p[1] = data[1];
p[2] = data[2];
p[3] = data[3];
p[4] = data[4];
p[5] = data[5];
p[6] = data[6];
p[7] = data[7];
data += 8;
return retVal;
}
template <class T>
T ReadPointer(PBYTE &data)
{
UNREFERENCED_PARAMETER(data);
throw std::logic_error("T must be uint64_t or uint32_t");
}
template <>
uint64_t ReadPointer<uint64_t>(PBYTE &data)
{
return ReadInt64(data);
}
template <>
uint32_t ReadPointer<uint32_t>(PBYTE &data)
{
return ReadInt32(data);
}
template <class PtrSizeType>
class ImageLoad
{
public:
PtrSizeType ImageBase;
PtrSizeType ImageSize;
uint32_t ProcessId;
uint32_t ImageChecksum;
uint32_t TimeDateStamp;
uint32_t Reserved0;
PtrSizeType DefaultBase;
uint32_t Reserved1;
uint32_t Reserved2;
uint32_t Reserved3;
uint32_t Reserved4;
std::wstring FileName;
ImageLoad(PBYTE data)
{
this->ImageBase = ReadPointer<PtrSizeType>(data);
this->ImageSize = ReadPointer<PtrSizeType>(data);
this->ProcessId = ReadInt32(data);
this->ImageChecksum = ReadInt32(data);
this->TimeDateStamp = ReadInt32(data);
this->Reserved0 = ReadInt32(data);
this->DefaultBase = ReadPointer<PtrSizeType>(data);
this->Reserved1 = ReadInt32(data);
this->Reserved2 = ReadInt32(data);
this->Reserved3 = ReadInt32(data);
this->Reserved4 = ReadInt32(data);
this->FileName = wstring(reinterpret_cast<const wchar_t *>(data));
}
};
typedef struct _CV_INFO_PDB70
{
DWORD CvSignature;
GUID Signature;
DWORD Age;
char PdbFileName[1];
} CV_INFO_PDB70, *PCV_INFO_PDB70;
constexpr GUID KernelTraceControlGuid = {0xB3E675D7, 0x2554, 0x4F18, {0x83, 0x0B, 0x27, 0x62, 0x73, 0x25, 0x60, 0xDE}};
template <typename T, size_t N>
constexpr size_t count_of(T (&)[N])
{
return N;
}
template <typename T, size_t N>
constexpr size_t size_of(T (&)[N])
{
return N * sizeof(T);
}
template <typename T, size_t N>
constexpr size_t length_of(T (&)[N])
{
return N - 1;
}
void InjectDbgIdEvent(ITraceRelogger *relogger, PEVENT_RECORD eventRecord, PCV_INFO_PDB70 data, int eventPointerSize, int flags, DWORD processId)
{
ITraceEvent *duplicateEvent;
relogger->CreateEventInstance(0, flags, &duplicateEvent);
EVENT_DESCRIPTOR eventDescriptor;
eventDescriptor.Id = -1;
eventDescriptor.Version = 2;
eventDescriptor.Channel = 0;
eventDescriptor.Level = 1;
eventDescriptor.Opcode = 36;
eventDescriptor.Task = 0;
eventDescriptor.Keyword = 0;
duplicateEvent->SetEventDescriptor(&eventDescriptor);
duplicateEvent->SetTimeStamp(&eventRecord->EventHeader.TimeStamp);
duplicateEvent->SetProcessorIndex(GetEventProcessorIndex(eventRecord));
duplicateEvent->SetProviderId(&KernelTraceControlGuid);
duplicateEvent->SetProcessId(processId);
duplicateEvent->SetThreadId(eventRecord->EventHeader.ThreadId);
auto pdbFileNameBufferLength = static_cast<int>(strlen(data->PdbFileName)) + 1;
auto payloadSize = eventPointerSize + pdbFileNameBufferLength + 2 * sizeof(int) + sizeof(GUID);
auto ptr = static_cast<PBYTE>(malloc(payloadSize));
auto payload = ptr;
CopyMemory(ptr, eventRecord->UserData, eventPointerSize);
ptr += eventPointerSize;
CopyMemory(ptr, &eventRecord->EventHeader.ProcessId, sizeof(int));
ptr += sizeof(int);
CopyMemory(ptr, &data->Signature, sizeof(GUID));
ptr += sizeof(GUID);
CopyMemory(ptr, &data->Age, sizeof(int));
ptr += sizeof(int);
CopyMemory(ptr, data->PdbFileName, pdbFileNameBufferLength);
duplicateEvent->SetPayload(payload, static_cast<ULONG>(payloadSize));
relogger->Inject(duplicateEvent);
duplicateEvent->Release();
free(payload);
}
void InjectImgIdEvent(ITraceRelogger *relogger, PEVENT_RECORD eventRecord, PCWCHAR originalFileName, DWORD imageSize, DWORD timestamp, int eventPointerSize, int flags, DWORD processId)
{
ITraceEvent *duplicateEvent;
relogger->CreateEventInstance(0, flags, &duplicateEvent);
EVENT_DESCRIPTOR eventDescriptor;
eventDescriptor.Id = -1;
eventDescriptor.Version = 2;
eventDescriptor.Channel = 0;
eventDescriptor.Level = 1;
eventDescriptor.Opcode = 0;
eventDescriptor.Task = 0;
eventDescriptor.Keyword = 0;
duplicateEvent->SetEventDescriptor(&eventDescriptor);
duplicateEvent->SetTimeStamp(&eventRecord->EventHeader.TimeStamp);
duplicateEvent->SetProcessorIndex(GetEventProcessorIndex(eventRecord));
duplicateEvent->SetProviderId(&KernelTraceControlGuid);
duplicateEvent->SetProcessId(processId);
duplicateEvent->SetThreadId(eventRecord->EventHeader.ThreadId);
auto originalFileNameBufferLength = (wcslen(originalFileName) + 1) * 2;
auto payloadSize = eventPointerSize + originalFileNameBufferLength + 4 * sizeof(int);
auto ptr = static_cast<PBYTE>(malloc(payloadSize));
auto payload = ptr;
DWORD *zeroAddr = nullptr;
CopyMemory(ptr, eventRecord->UserData, eventPointerSize);
ptr += eventPointerSize;
CopyMemory(ptr, &imageSize, sizeof(int));
ptr += sizeof(int);
CopyMemory(ptr, &zeroAddr, sizeof(int));
ptr += sizeof(int);
CopyMemory(ptr, &eventRecord->EventHeader.ProcessId, sizeof(int));
ptr += sizeof(int);
CopyMemory(ptr, &timestamp, sizeof(int));
ptr += sizeof(int);
CopyMemory(ptr, originalFileName, originalFileNameBufferLength);
duplicateEvent->SetPayload(payload, static_cast<ULONG>(payloadSize));
relogger->Inject(duplicateEvent);
duplicateEvent->Release();
free(payload);
}
HRESULT InjectKernelTraceControlEventsInner(PCWCHAR peFileName, PCWCHAR originalFileName, ITraceRelogger *relogger, PEVENT_RECORD eventRecord, DWORD processId)
{
auto file = CreateFile(peFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (file == INVALID_HANDLE_VALUE)
{
return ERROR_INVALID_HANDLE;
}
auto mapFile = CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr);
if (mapFile == nullptr)
{
CloseHandle(file);
return ERROR_INVALID_HANDLE;
}
auto imageBase = reinterpret_cast<PBYTE>(MapViewOfFile(mapFile, FILE_MAP_READ, 0, 0, 0));
auto dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(imageBase);
auto ntHeader = reinterpret_cast<PIMAGE_NT_HEADERS>(imageBase + dosHeader->e_lfanew);
auto header = &ntHeader->OptionalHeader;
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE || ntHeader->Signature != IMAGE_NT_SIGNATURE)
{
CloseHandle(mapFile);
CloseHandle(file);
return ERROR_BAD_ARGUMENTS;
}
auto flags = EVENT_HEADER_FLAG_CLASSIC_HEADER;
int eventPointerSize;
if ((eventRecord->EventHeader.Flags & EVENT_HEADER_FLAG_64_BIT_HEADER) != 0)
{
eventPointerSize = 8;
flags |= EVENT_HEADER_FLAG_64_BIT_HEADER;
}
else
{
eventPointerSize = 4;
flags |= EVENT_HEADER_FLAG_32_BIT_HEADER;
}
InjectImgIdEvent(relogger, eventRecord, originalFileName, header->SizeOfImage, ntHeader->FileHeader.TimeDateStamp, eventPointerSize, flags, processId);
ULONG numberOfDebugDirectories;
auto debugDirectories = static_cast<PIMAGE_DEBUG_DIRECTORY>(ImageDirectoryEntryToData(imageBase, FALSE, IMAGE_DIRECTORY_ENTRY_DEBUG, &numberOfDebugDirectories));
numberOfDebugDirectories /= sizeof(*debugDirectories);
PIMAGE_DEBUG_DIRECTORY current;
for (current = debugDirectories; numberOfDebugDirectories != 0; --numberOfDebugDirectories, ++current)
{
if (current->Type == IMAGE_DEBUG_TYPE_CODEVIEW)
{
auto data = reinterpret_cast<PCV_INFO_PDB70>(imageBase + current->PointerToRawData);
if (data->CvSignature == 0x53445352) // RSDS in ASCII
{
InjectDbgIdEvent(relogger, eventRecord, data, eventPointerSize, flags, processId);
}
break;
}
}
CloseHandle(mapFile);
CloseHandle(file);
return S_OK;
}
template <typename T>
wstring PEFileNameAndProcessIdFromEvent(PEVENT_RECORD eventRecord, DWORD *processId)
{
ImageLoad<T> imgLoadEvent(static_cast<PBYTE>(eventRecord->UserData));
*processId = imgLoadEvent.ProcessId;
wstring peFileName(imgLoadEvent.FileName.compare(0, length_of(SystemRoot), SystemRoot) == 0 ? windowsDirectory + imgLoadEvent.FileName.substr(length_of(SystemRoot)) : GlobalRoot + imgLoadEvent.FileName);
return peFileName;
}
__declspec(noinline) HRESULT InjectKernelTraceControlEvents(PEVENT_RECORD eventRecord, ITraceRelogger *relogger)
{
if (eventRecord->EventHeader.EventDescriptor.Opcode != DCStopOpCode)
{
return S_OK;
}
DWORD processId = 0;
wstring peFileName((eventRecord->EventHeader.Flags & EVENT_HEADER_FLAG_64_BIT_HEADER) != 0 ? PEFileNameAndProcessIdFromEvent<uint64_t>(eventRecord, &processId) : PEFileNameAndProcessIdFromEvent<uint32_t>(eventRecord, &processId));
auto peFileNamePtr = peFileName.c_str();
DWORD handle;
DWORD versionSize = GetFileVersionInfoSize(peFileNamePtr, &handle);
if (versionSize > 0)
{
auto buffer = malloc(versionSize);
if (GetFileVersionInfo(peFileNamePtr, handle, versionSize, buffer) != 0)
{
struct LANGANDCODEPAGE
{
WORD wLanguage;
WORD wCodePage;
} * lpTranslate;
UINT cbTranslate;
VerQueryValue(buffer, TEXT("\\VarFileInfo\\Translation"), reinterpret_cast<LPVOID *>(&lpTranslate), &cbTranslate);
for (unsigned i = 0; i < cbTranslate / sizeof(LANGANDCODEPAGE); ++i)
{
WCHAR dest[MAX_PATH + 1];
PWCHAR lpBuffer;
UINT dwBytes;
StringCchPrintf(dest, MAX_PATH, TEXT("\\StringFileInfo\\%04x%04x\\OriginalFilename"), lpTranslate[i].wLanguage, lpTranslate[i].wCodePage);
VerQueryValue(buffer, dest, reinterpret_cast<LPVOID *>(&lpBuffer), &dwBytes);
if (dwBytes == 0)
{
StringCchPrintf(dest, MAX_PATH, TEXT("\\StringFileInfo\\%04x%04x\\InternalName"), lpTranslate[i].wLanguage, lpTranslate[i].wCodePage);
VerQueryValue(buffer, dest, reinterpret_cast<LPVOID *>(&lpBuffer), &dwBytes);
if (dwBytes == 0)
{
lpBuffer = (PWCHAR)peFileNamePtr;
}
}
const LPWSTR lastDot = wcsrchr(lpBuffer, L'.');
if (lastDot && !_wcsicmp(lastDot, L".MUI"))
{
*lastDot = UNICODE_NULL;
}
InjectKernelTraceControlEventsInner(peFileNamePtr, lpBuffer, relogger, eventRecord, processId);
}
}
free(buffer);
}
else
{
InjectKernelTraceControlEventsInner(peFileNamePtr, peFileNamePtr, relogger, eventRecord, processId);
}
return S_OK;
}

Просмотреть файл

@ -1,436 +0,0 @@
#include <string>
#include <chrono>
#include <ctime>
#include <sstream>
#include <iomanip>
#include <relogger.h>
#include <windows.h>
#include <strsafe.h>
#include "TraceEventCallback.h"
#include <evntprov.h>
#define LOGFILE_PATH L""
#define LOGSESSION_NAME L"BPerfProfiles"
#define LOGFILE_NAME L"Relogger.etl"
typedef struct _STACK_TRACING_EVENT_ID
{
GUID EventGuid;
UCHAR Type;
UCHAR Reserved[7];
} STACK_TRACING_EVENT_ID, *PSTACK_TRACING_EVENT_ID;
enum EVENT_TRACE_INFORMATION_CLASS
{
EventTraceTimeProfileInformation = 3,
EventTraceStackCachingInformation = 16
};
enum SYSTEM_INFORMATION_CLASS
{
SystemPerformanceTraceInformation = 31
};
typedef struct _EVENT_TRACE_TIME_PROFILE_INFORMATION
{
EVENT_TRACE_INFORMATION_CLASS EventTraceInformationClass;
ULONG ProfileInterval;
} EVENT_TRACE_TIME_PROFILE_INFORMATION;
bool ctrlCTriggered = false;
typedef int(__stdcall *NtSetSystemInformation)(int SystemInformationClass, void *SystemInformation, int SystemInformationLength);
auto ntdll = LoadLibrary(L"ntdll.dll");
auto addr = NtSetSystemInformation(GetProcAddress(ntdll, "NtSetSystemInformation"));
ULONG EnableTraceEx2Shim(_In_ TRACEHANDLE traceHandle, _In_ LPCGUID guid, _In_ BYTE level, _In_ ULONG matchAnyKeyword, _In_ ULONG matchAllKeyword, _In_ ULONG timeout, _In_opt_ LPCWSTR exeNamesFilter, _In_opt_ const USHORT *stackEventIdsFilter, _In_ USHORT stackEventIdsCount)
{
int index = 0;
EVENT_FILTER_DESCRIPTOR descriptor[2];
ENABLE_TRACE_PARAMETERS enableParameters;
ZeroMemory(&enableParameters, sizeof(ENABLE_TRACE_PARAMETERS));
enableParameters.FilterDescCount = 0;
enableParameters.Version = ENABLE_TRACE_PARAMETERS_VERSION_2;
enableParameters.EnableFilterDesc = descriptor;
auto eventIdsBufferSize = ((stackEventIdsCount - 1) * 2) + sizeof(EVENT_FILTER_EVENT_ID);
PEVENT_FILTER_EVENT_ID eventIdsBuffer;
eventIdsBuffer = (PEVENT_FILTER_EVENT_ID)malloc(eventIdsBufferSize);
ZeroMemory(eventIdsBuffer, eventIdsBufferSize);
eventIdsBuffer->FilterIn = TRUE;
eventIdsBuffer->Reserved = 0;
eventIdsBuffer->Count = stackEventIdsCount;
auto eventIdsPtr = &eventIdsBuffer->Events[0];
for (int i = 0; i < stackEventIdsCount; ++i)
{
*eventIdsPtr++ = stackEventIdsFilter[i];
}
if (exeNamesFilter != nullptr)
{
descriptor[index].Ptr = (ULONGLONG)exeNamesFilter;
descriptor[index].Size = static_cast<ULONG>((wcslen(exeNamesFilter) + 1) * sizeof(WCHAR));
descriptor[index].Type = EVENT_FILTER_TYPE_EXECUTABLE_NAME;
index++;
}
if (stackEventIdsCount > 0)
{
descriptor[index].Ptr = (ULONGLONG)eventIdsBuffer;
descriptor[index].Size = static_cast<ULONG>(eventIdsBufferSize);
descriptor[index].Type = EVENT_FILTER_TYPE_STACKWALK;
index++;
enableParameters.EnableProperty = EVENT_ENABLE_PROPERTY_STACK_TRACE;
}
enableParameters.FilterDescCount = index; // set the right size
auto retVal = EnableTraceEx2(traceHandle, guid, EVENT_CONTROL_CODE_ENABLE_PROVIDER, level, matchAnyKeyword, matchAllKeyword, timeout, &enableParameters);
free(eventIdsBuffer);
return retVal;
}
void FillEventProperties(PEVENT_TRACE_PROPERTIES sessionProperties, ULONG bufferSize)
{
ZeroMemory(sessionProperties, bufferSize);
sessionProperties->Wnode.BufferSize = bufferSize;
sessionProperties->Wnode.Flags = WNODE_FLAG_TRACED_GUID;
sessionProperties->Wnode.ClientContext = 1;
sessionProperties->MinimumBuffers = max(64, std::thread::hardware_concurrency() * 2);
sessionProperties->MaximumBuffers = sessionProperties->MinimumBuffers * 2;
sessionProperties->BufferSize = 1024;
sessionProperties->LogFileMode = EVENT_TRACE_REAL_TIME_MODE | EVENT_TRACE_SYSTEM_LOGGER_MODE | EVENT_TRACE_INDEPENDENT_SESSION_MODE;
sessionProperties->LoggerNameOffset = sizeof(EVENT_TRACE_PROPERTIES);
sessionProperties->LogFileNameOffset = 0;
sessionProperties->FlushTimer = 1;
StringCbCopy(reinterpret_cast<LPWSTR>(reinterpret_cast<char *>(sessionProperties) + sessionProperties->LoggerNameOffset), (wcslen(LOGSESSION_NAME) + 1) * 2, LOGSESSION_NAME);
}
HRESULT StartSession(PTRACEHANDLE sessionHandle, PEVENT_TRACE_PROPERTIES sessionProperties)
{
HRESULT hr = ERROR_SUCCESS;
int retryCount = 1;
while (retryCount < 10)
{
hr = StartTrace(static_cast<PTRACEHANDLE>(sessionHandle), LOGSESSION_NAME, sessionProperties);
if (hr != ERROR_SUCCESS)
{
if (hr == ERROR_ALREADY_EXISTS)
{
hr = ControlTrace(*sessionHandle, LOGSESSION_NAME, sessionProperties, EVENT_TRACE_CONTROL_STOP);
if (hr == ERROR_WMI_INSTANCE_NOT_FOUND || hr == ERROR_SUCCESS)
{
Sleep(100 * retryCount); // sleep for 100-milliseconds to let it propogate.
retryCount++;
continue;
}
}
return hr;
}
break;
}
return hr;
}
bool AcquireProfilePrivileges()
{
bool privileged = false;
HANDLE tokenHandle;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &tokenHandle))
{
TOKEN_PRIVILEGES privileges;
privileges.PrivilegeCount = 1;
privileges.Privileges->Luid.LowPart = 11;
privileges.Privileges->Attributes = SE_PRIVILEGE_ENABLED;
if (AdjustTokenPrivileges(tokenHandle, false, &privileges, 0, nullptr, nullptr))
{
privileged = true;
}
CloseHandle(tokenHandle);
}
return privileged;
}
HRESULT RelogTraceFile(TRACEHANDLE sessionHandle, PWSTR outputFileName, int rollOverTimeMSec, PWSTR jittedCodeSymbolicDataFile)
{
HRESULT hr;
ITraceRelogger *relogger = nullptr;
TraceEventCallback *callback = nullptr;
hr = CoCreateInstance(CLSID_TraceRelogger, nullptr, CLSCTX_INPROC_SERVER, __uuidof(ITraceRelogger), reinterpret_cast<LPVOID *>(&relogger));
if (FAILED(hr))
{
wprintf(L"Failed to instantiate ITraceRelogger object: 0x%08x.\n", hr);
goto cleanup;
}
relogger->SetOutputFilename(outputFileName);
if (FAILED(hr))
{
wprintf(L"Failed to set output log file: 0x%08x.\n", hr);
goto cleanup;
}
TRACEHANDLE traceHandle;
hr = relogger->AddRealtimeTraceStream(LOGSESSION_NAME, nullptr, &traceHandle);
if (FAILED(hr))
{
wprintf(L"Failed to set log file input stream: 0x%08x.\n", hr);
goto cleanup;
}
callback = new TraceEventCallback(sessionHandle, relogger, rollOverTimeMSec, jittedCodeSymbolicDataFile);
if (callback == nullptr)
{
wprintf(L"Failed to allocate callback: 0x%08x.\n", hr);
goto cleanup;
}
hr = relogger->RegisterCallback(callback);
if (FAILED(hr))
{
wprintf(L"Failed to register callback: 0x%08x.\n", hr);
goto cleanup;
}
DoStartRundown(sessionHandle);
hr = relogger->ProcessTrace();
if (FAILED(hr))
{
wprintf(L"Failed to process trace: 0x%08x.\n", hr);
}
cleanup:
if (relogger != nullptr)
{
relogger->Release();
}
if (callback != nullptr)
{
callback->Release();
}
return hr;
}
wstring FormatProfileSting()
{
auto in_time_t = chrono::system_clock::to_time_t(chrono::system_clock::now());
tm nt;
localtime_s(&nt, &in_time_t);
wstringstream ss;
ss << put_time(&nt, L"%Y-%m-%d-%H-%M-%S");
return ss.str();
}
BOOL WINAPI ConsoleControlHandler(DWORD ctrlType)
{
switch (ctrlType)
{
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
wprintf(L"Ctrl+C handled, stopping session.\n");
ctrlCTriggered = true;
EVENT_TRACE_PROPERTIES properties;
ZeroMemory(&properties, sizeof(EVENT_TRACE_PROPERTIES));
properties.Wnode.BufferSize = sizeof(EVENT_TRACE_PROPERTIES);
ControlTrace(0, LOGSESSION_NAME, &properties, EVENT_TRACE_CONTROL_STOP);
default:
break;
}
return FALSE;
}
int wmain(const int argc, PWSTR *argv)
{
if (argc < 4)
{
printf("Usage: BPerfCPUSamplesCollector CpuTimerInMilliSeconds FileRolloverPeriodSec ProfileLogsDirectory [JittedCodeSymbolicDataFile] [ProcessNameFilters]\n");
printf("Example 1: BPerfCPUSamplesCollector 10 900 D:\\Data\\BPerfLogs D:\\Data\\BPerfSymbols\\Symbols.bin\n");
printf("Example 2: BPerfCPUSamplesCollector 10 900 D:\\Data\\BPerfLogs D:\\Data\\BPerfSymbols\\Symbols.bin w3wp.exe\n");
printf("Example 3: BPerfCPUSamplesCollector 10 900 D:\\Data\\BPerfLogs D:\\Data\\BPerfSymbols\\Symbols.bin w3wp.exe;sql.exe\n");
return ERROR_INVALID_PARAMETER;
}
SetConsoleCtrlHandler(ConsoleControlHandler, true);
HRESULT hr;
hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
if (FAILED(hr))
{
wprintf(L"Failed to initialize COM: 0x%08x\n", hr);
return HRESULT_CODE(hr);
}
/* set working dir */
SetCurrentDirectory(argv[3]);
auto cpuSampleMSec = _wtoi(argv[1]);
auto rolloverTimeMSec = _wtoi(argv[2]) * 1000;
if (!AcquireProfilePrivileges())
{
wprintf(L"Failed to acquire profiling privileges. Are you running as admin?\n");
return E_FAIL;
}
int bufferSize = sizeof(EVENT_TRACE_PROPERTIES) + sizeof(LOGFILE_PATH) + sizeof(LOGSESSION_NAME);
auto sessionProperties = static_cast<PEVENT_TRACE_PROPERTIES>(malloc(bufferSize));
if (sessionProperties == nullptr)
{
wprintf(L"Unable to allocate %d bytes for properties structure.\n", bufferSize);
return E_FAIL;
}
FillEventProperties(sessionProperties, bufferSize);
TRACEHANDLE sessionHandle;
hr = StartSession(&sessionHandle, sessionProperties);
if (FAILED(HRESULT(hr)))
{
wprintf(L"StartTrace() failed with %lu\n", hr);
goto cleanup;
}
ULONG data = EVENT_TRACE_FLAG_PROCESS | EVENT_TRACE_FLAG_IMAGE_LOAD | EVENT_TRACE_FLAG_THREAD | EVENT_TRACE_FLAG_PROFILE;
hr = TraceSetInformation(sessionHandle, TraceSystemTraceEnableFlagsInfo, &data, sizeof(ULONG));
if (hr != ERROR_SUCCESS)
{
wprintf(L"Failed to set trace information: 0x%08x.\n", hr);
goto cleanup;
}
auto exeNamesFilter = argc == 6 ? argv[5] : nullptr;
EnableTraceEx2Shim(sessionHandle, &AspNetEventSource, TRACE_LEVEL_INFORMATION, 0, 0, 0, exeNamesFilter, nullptr, 0);
EnableTraceEx2Shim(sessionHandle, &TplEventSource, TRACE_LEVEL_INFORMATION, 0x42, 0, 0, exeNamesFilter, nullptr, 0);
EnableTraceEx2Shim(sessionHandle, &BPerfStampingGuid, TRACE_LEVEL_INFORMATION, 0, 0, 0, exeNamesFilter, nullptr, 0);
EnableTraceEx2Shim(sessionHandle, &MonitoredScopeEventSource, TRACE_LEVEL_INFORMATION, 0, 0, 0, exeNamesFilter, nullptr, 0);
USHORT stacksForTcpIp[1] = {1013}; // Tcp Create Endpoint
EnableTraceEx2Shim(sessionHandle, &TcpIpProviderGuid, TRACE_LEVEL_INFORMATION, 0x1, 0, 0, exeNamesFilter, stacksForTcpIp, 1);
USHORT stacksForClr[3] = {80, 250, 252}; // Exception Start, Catch, Finally
EnableTraceEx2Shim(sessionHandle, &ClrGuid, TRACE_LEVEL_INFORMATION, 0x18011, 0, 0, exeNamesFilter, stacksForClr, 3);
EnableTraceEx2Shim(sessionHandle, &CoreClrGuid, TRACE_LEVEL_INFORMATION, 0x18011, 0, 0, exeNamesFilter, stacksForClr, 3);
if (hr != ERROR_SUCCESS)
{
wprintf(L"Failed to enable bperf stamping guid: 0x%08x.\n", hr);
goto cleanup;
}
STACK_TRACING_EVENT_ID stacks;
stacks.EventGuid = {0xce1dbfb4, 0x137e, 0x4da6, {0x87, 0xb0, 0x3f, 0x59, 0xaa, 0x10, 0x2c, 0xbc}};
stacks.Type = 0x2e;
hr = TraceSetInformation(sessionHandle, TraceStackTracingInfo, &stacks, sizeof(STACK_TRACING_EVENT_ID));
if (hr != ERROR_SUCCESS)
{
wprintf(L"Failed to set stack trace information: 0x%08x.\n", hr);
goto cleanup;
}
EVENT_TRACE_TIME_PROFILE_INFORMATION timeInfo;
timeInfo.EventTraceInformationClass = EventTraceTimeProfileInformation;
timeInfo.ProfileInterval = static_cast<int>(cpuSampleMSec * 10000.0 + .5);
hr = addr(SystemPerformanceTraceInformation, &timeInfo, sizeof(EVENT_TRACE_TIME_PROFILE_INFORMATION)); // set interval to 10ms
if (hr != ERROR_SUCCESS)
{
wprintf(L"Failed to set profile timer info\r\n");
}
wprintf(L"\n BPerfCPUSamplesCollector is running ...\n");
wprintf(L" Profiling Timer Speed : %dms\n", cpuSampleMSec);
wprintf(L" File Rotation Period : %ds\n", rolloverTimeMSec / 1000);
wprintf(L" ETW Session Name: %s\n", LOGSESSION_NAME);
wprintf(L" Profiles Directory Location: %s\n", argv[3]);
if (argc >= 5)
{
wprintf(L" Using Symbol Data File: %s\n", argv[4]);
}
if (argc == 6)
{
wprintf(L" Process Name Filters: %s\n", argv[5]);
}
wprintf(L"\n *** NOTE *** -> Profile file names start with ''BPerfProfiles'' followed by timestamp\n\n");
while (true)
{
if (ctrlCTriggered)
{
wprintf(L"BPerf exiting in response to Ctrl+C.");
break;
}
auto begin = FormatProfileSting();
hr = RelogTraceFile(sessionHandle, LOGFILE_NAME, rolloverTimeMSec, argc >= 5 ? argv[4] : nullptr);
if (FAILED(hr))
{
wprintf(L"Exiting because Relogging failed.");
break;
}
auto end = FormatProfileSting();
auto destWString = (L"BPerfProfiles." + begin + L"_" + end + L".etl");
auto dest = destWString.c_str();
wprintf(L" Writing '%s' ...", dest);
MoveFileW(LOGFILE_NAME, dest);
wprintf(L" Done\n");
}
timeInfo.ProfileInterval = static_cast<int>(10000.0 + .5); // set back to 1ms
addr(SystemPerformanceTraceInformation, &timeInfo, sizeof(EVENT_TRACE_TIME_PROFILE_INFORMATION));
EVENT_TRACE_PROPERTIES properties;
ZeroMemory(&properties, sizeof(EVENT_TRACE_PROPERTIES));
properties.Wnode.BufferSize = sizeof(EVENT_TRACE_PROPERTIES);
ControlTrace(0, LOGSESSION_NAME, &properties, EVENT_TRACE_CONTROL_STOP);
cleanup:
if (sessionProperties != nullptr)
{
free(sessionProperties);
}
CoUninitialize();
return HRESULT_CODE(hr);
}

Просмотреть файл

@ -1,135 +0,0 @@
#include "TraceEventCallback.h"
#include <unordered_set>
unordered_set<ULONG> threadingTrackingTable;
unordered_set<ULONG> taskTrackingTable;
__declspec(noinline) void HandleRundowCompletion(PEVENT_RECORD eventRecord, ITraceRelogger *relogger, bool isCancelled)
{
if (eventRecord->EventHeader.EventDescriptor.Opcode == RundownComplete && isCancelled)
{
relogger->Cancel();
}
}
__declspec(noinline) void HandleBPerfStampingEvents(PEVENT_RECORD eventRecord)
{
switch (eventRecord->EventHeader.EventDescriptor.Id)
{
case 1:
threadingTrackingTable.insert(eventRecord->EventHeader.ThreadId);
break;
case 2:
threadingTrackingTable.erase(eventRecord->EventHeader.ThreadId);
break;
}
}
__declspec(noinline) void HandleTplEvents(PEVENT_RECORD eventRecord)
{
switch (eventRecord->EventHeader.EventDescriptor.Id)
{
case TaskScheduled:
{
if (threadingTrackingTable.find(eventRecord->EventHeader.ThreadId) != threadingTrackingTable.end())
{
auto taskId = *reinterpret_cast<ULONG *>(static_cast<PBYTE>(eventRecord->UserData) + 8);
taskTrackingTable.insert(taskId);
}
}
break;
case TaskStart:
{
auto taskId = *reinterpret_cast<ULONG *>(static_cast<PBYTE>(eventRecord->UserData) + 8);
if (taskTrackingTable.find(taskId) != taskTrackingTable.end())
{
// if yes, then we should track this thread also
threadingTrackingTable.insert(eventRecord->EventHeader.ThreadId);
}
}
break;
case TaskStop:
{
auto taskId = *reinterpret_cast<ULONG *>(static_cast<PBYTE>(eventRecord->UserData) + 8);
taskTrackingTable.erase(taskId);
threadingTrackingTable.erase(eventRecord->EventHeader.ThreadId);
}
break;
}
}
__declspec(noinline) void ResetThreadState(PEVENT_RECORD eventRecord)
{
if (eventRecord->EventHeader.ProviderId == ThreadGuid ||
eventRecord->EventHeader.ProviderId == ClrGuid &&
(eventRecord->EventHeader.EventDescriptor.Id == ThreadPoolWorkerThreadStartOpCode ||
eventRecord->EventHeader.EventDescriptor.Id == ThreadPoolWorkerThreadStopOpCode))
{
threadingTrackingTable.erase(eventRecord->EventHeader.ThreadId);
}
}
HRESULT STDMETHODCALLTYPE TraceEventCallback::OnEvent(ITraceEvent *traceEvent, ITraceRelogger *relogger)
{
PEVENT_RECORD eventRecord;
traceEvent->GetEventRecord(&eventRecord);
if (eventRecord->EventHeader.ProviderId == ThreadGuid && eventRecord->EventHeader.EventDescriptor.Opcode == CSwitchOpCode)
{
auto oldThreadId = *reinterpret_cast<ULONG *>(static_cast<PBYTE>(eventRecord->UserData) + 4);
if (threadingTrackingTable.find(oldThreadId) != threadingTrackingTable.end())
{
relogger->Inject(traceEvent);
}
return S_OK;
}
if (eventRecord->EventHeader.ProviderId == TplEventSource)
{
HandleTplEvents(eventRecord);
}
if (eventRecord->EventHeader.ProviderId == BPerfStampingGuid)
{
HandleBPerfStampingEvents(eventRecord);
}
if (eventRecord->EventHeader.ProviderId == ThreadGuid || eventRecord->EventHeader.ProviderId == ClrGuid)
{
ResetThreadState(eventRecord);
}
if (eventRecord->EventHeader.ProviderId == ImageLoadGuid)
{
InjectKernelTraceControlEvents(eventRecord, relogger);
}
if (eventRecord->EventHeader.ProviderId == RundownGuid)
{
HandleRundowCompletion(eventRecord, relogger, this->isCancelled);
}
return relogger->Inject(traceEvent);
}
HRESULT STDMETHODCALLTYPE TraceEventCallback::OnBeginProcessTrace(ITraceEvent *header, ITraceRelogger *relogger)
{
UNREFERENCED_PARAMETER(relogger);
UNREFERENCED_PARAMETER(header);
return S_OK;
}
HRESULT STDMETHODCALLTYPE TraceEventCallback::OnFinalizeProcessTrace(ITraceRelogger *relogger)
{
if (this->jittedCodeSymbolicDataFile != nullptr)
{
HANDLE hFile = CreateFileW(this->jittedCodeSymbolicDataFile, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (hFile != INVALID_HANDLE_VALUE)
{
LogJittedCodeSymbolicData(hFile, relogger);
}
}
return S_OK;
}

Просмотреть файл

@ -1,164 +0,0 @@
#pragma once
#include <thread>
#include <objbase.h>
#include <relogger.h>
#include <atomic>
#include <agents.h>
#include <ppltasks.h>
#include <evntrace.h>
#include <strsafe.h>
#include <unordered_map>
#include <evntcons.h>
constexpr GUID PerfInfoGuid = {0xce1dbfb4, 0x137e, 0x4da6, {0x87, 0xb0, 0x3f, 0x59, 0xaa, 0x10, 0x2c, 0xbc}};
constexpr GUID BPerfStampingGuid = {0xD46E5565, 0xD624, 0x4C4D, {0x89, 0xCC, 0x7A, 0x82, 0x88, 0x7D, 0x36, 0x27}};
constexpr GUID ThreadGuid = {0x3d6fa8d1, 0xfe05, 0x11d0, {0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c}};
constexpr GUID ProcessGuid = {0x3d6fa8d0, 0xfe05, 0x11d0, {0x9d, 0xda, 0x00, 0xc0, 0x4f, 0xd7, 0xba, 0x7c}};
constexpr GUID RundownGuid = {0x68fdd900, 0x4a3e, 0x11d1, {0x84, 0xf4, 0x00, 0x00, 0xf8, 0x04, 0x64, 0xe3}};
constexpr GUID ImageLoadGuid = {0x2cb15d1d, 0x5fc1, 0x11d2, {0xab, 0xe1, 0x00, 0xa0, 0xc9, 0x11, 0xf5, 0x18}};
constexpr GUID ClrGuid = {0xE13C0D23, 0xCCBC, 0x4E12, {0x93, 0x1B, 0xD9, 0xCC, 0x2E, 0xEE, 0x27, 0xE4}};
constexpr GUID CoreClrGuid = {0x319DC449, 0xADA5, 0x50F7, {0x42, 0x8E, 0x95, 0x7D, 0xB6, 0x79, 0x16, 0x68}};
constexpr GUID TplEventSource = {0x2e5dba47, 0xa3d2, 0x4d16, {0x8e, 0xe0, 0x66, 0x71, 0xff, 0xdc, 0xd7, 0xb5}};
constexpr GUID AspNetEventSource = {0xee799f41, 0xcfa5, 0x550b, {0xbf, 0x2c, 0x34, 0x47, 0x47, 0xc1, 0xc6, 0x68}};
constexpr GUID TcpIpProviderGuid = {0x2f07e2ee, 0x15db, 0x40f1, {0x90, 0xef, 0x9d, 0x7b, 0xa2, 0x82, 0x18, 0x8a}};
constexpr GUID KernelProcessGuid = {0x22fb2cd6, 0x0e7b, 0x422b, {0xa0, 0xc7, 0x2f, 0xad, 0x1f, 0xd0, 0xe7, 0x16}};
constexpr GUID MonitoredScopeEventSource = {0x2e185d98, 0x344d, 0x5ef7, {0x06, 0x30, 0xaf, 0xe3, 0x22, 0xf0, 0x1b, 0x98}};
constexpr UCHAR CSwitchOpCode = 36;
constexpr UCHAR StackWalkOpCode = 32;
constexpr UCHAR DCStopOpCode = 4;
constexpr UCHAR ThreadPoolWorkerThreadStartOpCode = 50;
constexpr UCHAR ThreadPoolWorkerThreadStopOpCode = 51;
constexpr USHORT TaskScheduled = 7;
constexpr USHORT TaskStart = 8;
constexpr USHORT TaskStop = 9;
constexpr USHORT RundownComplete = 8;
__declspec(noinline) HRESULT InjectKernelTraceControlEvents(PEVENT_RECORD eventRecord, ITraceRelogger *relogger);
void LogJittedCodeSymbolicData(HANDLE hFile, ITraceRelogger *relogger);
using namespace concurrency;
using namespace std;
inline void DoRundown(TRACEHANDLE tracehandle, ULONG type)
{
EVENT_FILTER_DESCRIPTOR descriptor[1];
descriptor[0].Type = EVENT_FILTER_TYPE_TRACEHANDLE;
descriptor[0].Ptr = reinterpret_cast<ULONGLONG>(&tracehandle);
descriptor[0].Size = sizeof(TRACEHANDLE);
ENABLE_TRACE_PARAMETERS enableParameters;
ZeroMemory(&enableParameters, sizeof(ENABLE_TRACE_PARAMETERS));
enableParameters.Version = ENABLE_TRACE_PARAMETERS_VERSION_2;
enableParameters.EnableFilterDesc = descriptor;
enableParameters.FilterDescCount = 1;
EnableTraceEx2(tracehandle, &AspNetEventSource, EVENT_CONTROL_CODE_CAPTURE_STATE, 0, 0, 0, 0, &enableParameters);
EnableTraceEx2(tracehandle, &TplEventSource, EVENT_CONTROL_CODE_CAPTURE_STATE, 0, 0, 0, 0, &enableParameters);
EnableTraceEx2(tracehandle, &MonitoredScopeEventSource, EVENT_CONTROL_CODE_CAPTURE_STATE, 0, 0, 0, 0, &enableParameters);
GUID systemGuid = {0x9e814aad, 0x3204, 0x11d2, {0x9a, 0x82, 0x00, 0x60, 0x08, 0xa8, 0x69, 0x39}};
EnableTraceEx2(tracehandle, &systemGuid, EVENT_CONTROL_CODE_CAPTURE_STATE, 0, type, 0, INFINITE, &enableParameters);
}
inline void DoStartRundown(TRACEHANDLE tracehandle)
{
DoRundown(tracehandle, 1);
}
inline void DoStopRundown(TRACEHANDLE tracehandle)
{
DoRundown(tracehandle, 2);
}
// Creates a task that completes after the specified delay.
inline task<void> complete_after(unsigned int timeout)
{
// A task completion event that is set when a timer fires.
task_completion_event<void> tce;
// Create a non-repeating timer.
auto fire_once = new timer<int>(timeout, 0, nullptr, false);
// Create a call object that sets the completion event after the timer fires.
auto callback = new call<int>([tce](int) {
tce.set();
});
// Connect the timer to the callback and start the timer.
fire_once->link_target(callback);
fire_once->start();
// Create a task that completes after the completion event is set.
task<void> event_set(tce);
// Create a continuation task that cleans up resources and
// and return that continuation task.
return event_set.then([callback, fire_once]() {
delete callback;
delete fire_once;
});
}
class TraceEventCallback : public ITraceEventCallback
{
public:
HRESULT STDMETHODCALLTYPE OnEvent(ITraceEvent *traceEvent, ITraceRelogger *relogger) override;
HRESULT STDMETHODCALLTYPE OnBeginProcessTrace(ITraceEvent *header, ITraceRelogger *relogger) override;
HRESULT STDMETHODCALLTYPE OnFinalizeProcessTrace(ITraceRelogger *relogger) override;
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *ppObj) override
{
if (riid == __uuidof(IUnknown) || riid == __uuidof(ITraceEventCallback))
{
*ppObj = this;
}
else
{
*ppObj = nullptr;
return E_NOINTERFACE;
}
this->AddRef();
return ERROR_SUCCESS;
}
ULONG STDMETHODCALLTYPE AddRef() override
{
return atomic_fetch_add(&this->refCount, 1) + 1;
}
ULONG STDMETHODCALLTYPE Release() override
{
int count = atomic_fetch_sub(&this->refCount, 1) - 1;
if (count == 0)
{
delete this;
}
return count;
}
TraceEventCallback(TRACEHANDLE tracehandle, ITraceRelogger *relogger, int rollOverTimeMSec, PWSTR jittedCodeSymbolicDataFile)
{
this->isCancelled = false;
this->refCount = 0;
this->jittedCodeSymbolicDataFile = jittedCodeSymbolicDataFile;
this->reloggerCancellationTask = complete_after(rollOverTimeMSec).then([this, relogger, tracehandle] {
this->isCancelled = true;
DoStopRundown(tracehandle);
});
}
virtual ~TraceEventCallback()
{
}
private:
bool isCancelled;
atomic<int> refCount;
task<void> reloggerCancellationTask;
PWSTR jittedCodeSymbolicDataFile;
};

Просмотреть файл

@ -0,0 +1,21 @@
#define BPERFDLLIMPORT
#include "../lib/Program.h"
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
UNREFERENCED_PARAMETER(hModule);
UNREFERENCED_PARAMETER(ul_reason_for_call);
UNREFERENCED_PARAMETER(lpReserved);
return TRUE;
}
extern "C" __declspec(dllexport) int StartBPerf(int argc, PWSTR* argv, bool setCtrlCHandler, void(*fileMovedCallback)(const int length, const wchar_t *))
{
return InvokeBPerfStart(argc, argv, setCtrlCHandler, fileMovedCallback);
}
extern "C" __declspec(dllexport) void StopBPerf()
{
InvokeBPerfStop();
}

Просмотреть файл

@ -0,0 +1,85 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<TargetName>BPerfCPUSamplesCollectorLibrary</TargetName>
<ProjectGuid>{7CEF2038-7FBC-4C06-880E-C2B64FF17D8D}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>BPerfCPUSamplesCollectorLibrary</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>tdh.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BufferSecurityCheck>false</BufferSecurityCheck>
<ExceptionHandling>false</ExceptionHandling>
<ControlFlowGuard>false</ControlFlowGuard>
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>tdh.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="dll.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\lib\lib.vcxproj">
<Project>{4cc1c899-4372-4ff0-92b2-c841c332f17c}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,6 @@
#include "../lib/Program.h"
int wmain(int argc, PWSTR *argv)
{
return InvokeBPerfStart(argc, argv, true, nullptr);
}

Просмотреть файл

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
@ -11,21 +11,24 @@
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{628BB6D0-1469-4652-9DF9-B7FEC89F0548}</ProjectGuid>
<VCProjectVersion>16.0</VCProjectVersion>
<TargetName>BPerfCPUSamplesCollector</TargetName>
<ProjectGuid>{8849F8A2-C5DC-4B8A-AE85-6BBD5C065171}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>BPerfCPUSamplesCollector</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
@ -38,40 +41,47 @@
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<ConformanceMode>true</ConformanceMode>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<AdditionalDependencies>version.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>tdh.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<ConformanceMode>true</ConformanceMode>
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
<ExceptionHandling>false</ExceptionHandling>
<ControlFlowGuard>false</ControlFlowGuard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<AdditionalDependencies>version.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>tdh.lib;version.lib;%(AdditionalDependencies)</AdditionalDependencies>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="JittedCodeResolutionSupportCode.cpp" />
<ClCompile Include="KernelTraceControlSupportCode.cpp" />
<ClCompile Include="Program.cpp" />
<ClCompile Include="TraceEventCallback.cpp" />
<ClCompile Include="exe.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="TraceEventCallback.h" />
<ProjectReference Include="..\lib\lib.vcxproj">
<Project>{4cc1c899-4372-4ff0-92b2-c841c332f17c}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,509 @@
#include <windows.h>
#include <evntcons.h>
#include <string>
#include <relogger.h>
#include <evntrace.h>
#include <strsafe.h>
#include <tdh.h>
static DWORD RVAToFileOffset(PIMAGE_NT_HEADERS32 ntHeader, DWORD rva)
{
PIMAGE_SECTION_HEADER sections = IMAGE_FIRST_SECTION(ntHeader);
DWORD numberOfSections = ntHeader->FileHeader.NumberOfSections;
for (DWORD i = 0; i < numberOfSections; ++i)
{
if (sections[i].VirtualAddress <= rva && rva < sections[i].VirtualAddress + sections[i].Misc.VirtualSize)
{
return sections[i].PointerToRawData + (rva - sections[i].VirtualAddress);
}
}
return 0;
}
constexpr UCHAR DCStartOpCode = 3;
constexpr UCHAR DCStopOpCode = 4;
#define SystemRoot L"\\SystemRoot"
#define GlobalRoot L"\\\\?\\GLOBALROOT"
#define MAX_EVENT_SIZE 65536
#define HALF_EVENT_SIZE 32768
#define addr(x) &x[0]
template <typename T, size_t N>
constexpr size_t countOf(T const (&)[N]) noexcept
{
return N;
}
auto ReadInt32(PBYTE &data)
{
uint32_t retVal;
char *p = reinterpret_cast<char *>(&retVal);
p[0] = data[0];
p[1] = data[1];
p[2] = data[2];
p[3] = data[3];
data += 4;
return retVal;
}
auto ReadInt64(PBYTE &data)
{
uint64_t retVal;
char *p = reinterpret_cast<char *>(&retVal);
p[0] = data[0];
p[1] = data[1];
p[2] = data[2];
p[3] = data[3];
p[4] = data[4];
p[5] = data[5];
p[6] = data[6];
p[7] = data[7];
data += 8;
return retVal;
}
template <class T>
T ReadPointer(PBYTE &data)
{
UNREFERENCED_PARAMETER(data);
throw std::logic_error("T must be uint64_t or uint32_t");
}
template <>
uint64_t ReadPointer<uint64_t>(PBYTE &data)
{
return ReadInt64(data);
}
template <>
uint32_t ReadPointer<uint32_t>(PBYTE &data)
{
return ReadInt32(data);
}
template <class PtrSizeType>
class ImageLoad
{
public:
PtrSizeType ImageBase;
PtrSizeType ImageSize;
uint32_t ProcessId;
uint32_t ImageChecksum;
uint32_t TimeDateStamp;
uint32_t Reserved0;
PtrSizeType DefaultBase;
uint32_t Reserved1;
uint32_t Reserved2;
uint32_t Reserved3;
uint32_t Reserved4;
wchar_t* FileName;
ImageLoad(PBYTE data)
{
this->ImageBase = ReadPointer<PtrSizeType>(data);
this->ImageSize = ReadPointer<PtrSizeType>(data);
this->ProcessId = ReadInt32(data);
this->ImageChecksum = ReadInt32(data);
this->TimeDateStamp = ReadInt32(data);
this->Reserved0 = ReadInt32(data);
this->DefaultBase = ReadPointer<PtrSizeType>(data);
this->Reserved1 = ReadInt32(data);
this->Reserved2 = ReadInt32(data);
this->Reserved3 = ReadInt32(data);
this->Reserved4 = ReadInt32(data);
this->FileName = reinterpret_cast<wchar_t *>(data);
}
};
typedef struct _CV_INFO_PDB70
{
DWORD CvSignature;
GUID Signature;
DWORD Age;
char PdbFileName[1];
} CV_INFO_PDB70, *PCV_INFO_PDB70;
constexpr GUID KernelTraceControlGuid = {0xB3E675D7, 0x2554, 0x4F18, {0x83, 0x0B, 0x27, 0x62, 0x73, 0x25, 0x60, 0xDE}};
constexpr GUID EventMetadataGuid = {0xbbccf6c1, 0x6cd1, 0x48c4, {0x80, 0xff, 0x83, 0x94, 0x82, 0xe3, 0x76, 0x71}};
template <typename T, size_t N>
constexpr size_t count_of(T (&)[N])
{
return N;
}
template <typename T, size_t N>
constexpr size_t size_of(T (&)[N])
{
return N * sizeof(T);
}
template <typename T, size_t N>
constexpr size_t length_of(T (&)[N])
{
return N - 1;
}
void InjectDbgIdEvent(ITraceRelogger *relogger, PEVENT_RECORD eventRecord, PCV_INFO_PDB70 data, int eventPointerSize, int flags, DWORD processId)
{
BYTE payload[MAX_EVENT_SIZE];
ITraceEvent *duplicateEvent;
relogger->CreateEventInstance(0, flags, &duplicateEvent);
EVENT_DESCRIPTOR eventDescriptor;
eventDescriptor.Id = 0xFFFF;
eventDescriptor.Version = 2;
eventDescriptor.Channel = 0;
eventDescriptor.Level = 1;
eventDescriptor.Opcode = 36;
eventDescriptor.Task = 0;
eventDescriptor.Keyword = 0;
duplicateEvent->SetEventDescriptor(&eventDescriptor);
duplicateEvent->SetTimeStamp(&eventRecord->EventHeader.TimeStamp);
duplicateEvent->SetProcessorIndex(GetEventProcessorIndex(eventRecord));
duplicateEvent->SetProviderId(&KernelTraceControlGuid);
duplicateEvent->SetProcessId(processId);
duplicateEvent->SetThreadId(eventRecord->EventHeader.ThreadId);
auto pdbFileNameBufferLength = static_cast<int>(strlen(data->PdbFileName)) + 1;
const auto payloadSize = eventPointerSize + pdbFileNameBufferLength + 2 * sizeof(int) + sizeof(GUID);
auto ptr = addr(payload);
CopyMemory(ptr, eventRecord->UserData, eventPointerSize);
ptr += eventPointerSize;
CopyMemory(ptr, &processId, sizeof(int));
ptr += sizeof(int);
CopyMemory(ptr, &data->Signature, sizeof(GUID));
ptr += sizeof(GUID);
CopyMemory(ptr, &data->Age, sizeof(int));
ptr += sizeof(int);
CopyMemory(ptr, data->PdbFileName, pdbFileNameBufferLength);
duplicateEvent->SetPayload(addr(payload), static_cast<ULONG>(payloadSize));
relogger->Inject(duplicateEvent);
duplicateEvent->Release();
}
void InjectImgIdEvent(ITraceRelogger *relogger, PEVENT_RECORD eventRecord, PCWCHAR originalFileName, DWORD imageSize, DWORD timestamp, int eventPointerSize, int flags, DWORD processId)
{
BYTE payload[MAX_EVENT_SIZE];
ITraceEvent *duplicateEvent;
relogger->CreateEventInstance(0, flags, &duplicateEvent);
EVENT_DESCRIPTOR eventDescriptor;
eventDescriptor.Id = 0xFFFF;
eventDescriptor.Version = 2;
eventDescriptor.Channel = 0;
eventDescriptor.Level = 1;
eventDescriptor.Opcode = 0;
eventDescriptor.Task = 0;
eventDescriptor.Keyword = 0;
duplicateEvent->SetEventDescriptor(&eventDescriptor);
duplicateEvent->SetTimeStamp(&eventRecord->EventHeader.TimeStamp);
duplicateEvent->SetProcessorIndex(GetEventProcessorIndex(eventRecord));
duplicateEvent->SetProviderId(&KernelTraceControlGuid);
duplicateEvent->SetProcessId(processId);
duplicateEvent->SetThreadId(eventRecord->EventHeader.ThreadId);
auto originalFileNameBufferLength = (wcslen(originalFileName) + 1) * 2;
const auto payloadSize = eventPointerSize + originalFileNameBufferLength + 4 * sizeof(int);
auto ptr = addr(payload);
DWORD *zeroAddr = nullptr;
CopyMemory(ptr, eventRecord->UserData, eventPointerSize);
ptr += eventPointerSize;
CopyMemory(ptr, &imageSize, sizeof(int));
ptr += sizeof(int);
CopyMemory(ptr, &zeroAddr, sizeof(int));
ptr += sizeof(int);
CopyMemory(ptr, &processId, sizeof(int));
ptr += sizeof(int);
CopyMemory(ptr, &timestamp, sizeof(int));
ptr += sizeof(int);
CopyMemory(ptr, originalFileName, originalFileNameBufferLength);
duplicateEvent->SetPayload(addr(payload), static_cast<ULONG>(payloadSize));
relogger->Inject(duplicateEvent);
duplicateEvent->Release();
}
HRESULT InjectKernelTraceControlEventsInner(PCWCHAR peFileName, PCWCHAR originalFileName, ITraceRelogger *relogger, PEVENT_RECORD eventRecord, DWORD processId)
{
const auto file = CreateFile(peFileName, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (file == INVALID_HANDLE_VALUE)
{
return ERROR_INVALID_HANDLE;
}
const auto mapFile = CreateFileMapping(file, nullptr, PAGE_READONLY, 0, 0, nullptr);
if (mapFile == nullptr)
{
CloseHandle(file);
return ERROR_INVALID_HANDLE;
}
const auto imageBase = reinterpret_cast<PBYTE>(MapViewOfFile(mapFile, FILE_MAP_READ, 0, 0, 0));
const auto dosHeader = reinterpret_cast<PIMAGE_DOS_HEADER>(imageBase);
auto ntHeader = reinterpret_cast<PIMAGE_NT_HEADERS32>(imageBase + dosHeader->e_lfanew);
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE || ntHeader->Signature != IMAGE_NT_SIGNATURE)
{
UnmapViewOfFile(imageBase);
CloseHandle(mapFile);
CloseHandle(file);
return ERROR_BAD_ARGUMENTS;
}
auto flags = EVENT_HEADER_FLAG_CLASSIC_HEADER;
int eventPointerSize;
DWORD sizeOfImage;
IMAGE_DATA_DIRECTORY debugDescriptorDirectory;
if ((eventRecord->EventHeader.Flags & EVENT_HEADER_FLAG_64_BIT_HEADER) != 0)
{
auto ntHeader64 = reinterpret_cast<PIMAGE_NT_HEADERS64>(imageBase + dosHeader->e_lfanew);
sizeOfImage = ntHeader64->OptionalHeader.SizeOfImage;
debugDescriptorDirectory = ntHeader64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
eventPointerSize = 8;
flags |= EVENT_HEADER_FLAG_64_BIT_HEADER;
}
else
{
sizeOfImage = ntHeader->OptionalHeader.SizeOfImage;
debugDescriptorDirectory = ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG];
eventPointerSize = 4;
flags |= EVENT_HEADER_FLAG_32_BIT_HEADER;
}
InjectImgIdEvent(relogger, eventRecord, originalFileName, sizeOfImage, ntHeader->FileHeader.TimeDateStamp, eventPointerSize, flags, processId);
if (debugDescriptorDirectory.VirtualAddress != 0)
{
auto debugDirectories = (PIMAGE_DEBUG_DIRECTORY)(imageBase + RVAToFileOffset(ntHeader, debugDescriptorDirectory.VirtualAddress));
ULONG numberOfDebugDirectories = debugDescriptorDirectory.Size / sizeof(IMAGE_DEBUG_DIRECTORY);
for (PIMAGE_DEBUG_DIRECTORY current = debugDirectories; numberOfDebugDirectories != 0; --numberOfDebugDirectories, ++current)
{
if (current->Type == IMAGE_DEBUG_TYPE_CODEVIEW)
{
const auto data = reinterpret_cast<PCV_INFO_PDB70>(imageBase + current->PointerToRawData);
if (data->CvSignature == 0x53445352) // RSDS in ASCII
{
InjectDbgIdEvent(relogger, eventRecord, data, eventPointerSize, flags, processId);
}
break;
}
}
}
UnmapViewOfFile(imageBase);
CloseHandle(mapFile);
CloseHandle(file);
return S_OK;
}
template <typename T>
void PEFileNameAndProcessIdFromEvent(PEVENT_RECORD eventRecord, DWORD *processId, wchar_t* ptr, size_t size)
{
ImageLoad<T> imgLoadEvent(static_cast<PBYTE>(eventRecord->UserData));
*processId = imgLoadEvent.ProcessId;
if (_wcsnicmp(imgLoadEvent.FileName, SystemRoot, length_of(SystemRoot)) == 0)
{
WCHAR windowsDirectory[(MAX_PATH + 1) * 2];
GetWindowsDirectory(addr(windowsDirectory), MAX_PATH);
StringCbPrintfW(ptr, size, L"%s%s", addr(windowsDirectory), imgLoadEvent.FileName + length_of(SystemRoot));
}
else
{
StringCbPrintfW(ptr, size, L"%s%s", GlobalRoot, imgLoadEvent.FileName);
}
}
__declspec(noinline) HRESULT InjectKernelTraceControlEvents(PEVENT_RECORD eventRecord, ITraceRelogger *relogger)
{
{
WCHAR peFileNamePtr[HALF_EVENT_SIZE];
BYTE buffer[HALF_EVENT_SIZE];
DWORD processId = 0;
if ((eventRecord->EventHeader.Flags & EVENT_HEADER_FLAG_64_BIT_HEADER) != 0)
{
PEFileNameAndProcessIdFromEvent<uint64_t>(eventRecord, &processId, addr(peFileNamePtr), size_of(peFileNamePtr));
}
else
{
PEFileNameAndProcessIdFromEvent<uint32_t>(eventRecord, &processId, addr(peFileNamePtr), size_of(peFileNamePtr));
}
DWORD handle;
const DWORD versionSize = GetFileVersionInfoSize(peFileNamePtr, &handle);
if (versionSize > 0)
{
if (GetFileVersionInfo(peFileNamePtr, handle, versionSize, addr(buffer)) != 0)
{
struct LANGANDCODEPAGE
{
WORD wLanguage;
WORD wCodePage;
} * lpTranslate;
UINT cbTranslate;
VerQueryValue(addr(buffer), TEXT("\\VarFileInfo\\Translation"), reinterpret_cast<LPVOID *>(&lpTranslate), &cbTranslate);
for (unsigned i = 0; i < cbTranslate / sizeof(LANGANDCODEPAGE); ++i)
{
WCHAR dest[MAX_PATH + 1];
PWCHAR lpBuffer;
UINT dwBytes;
StringCchPrintf(dest, MAX_PATH, TEXT("\\StringFileInfo\\%04x%04x\\OriginalFilename"), lpTranslate[i].wLanguage, lpTranslate[i].wCodePage);
VerQueryValue(addr(buffer), dest, reinterpret_cast<LPVOID *>(&lpBuffer), &dwBytes);
if (dwBytes == 0)
{
StringCchPrintf(dest, MAX_PATH, TEXT("\\StringFileInfo\\%04x%04x\\InternalName"), lpTranslate[i].wLanguage, lpTranslate[i].wCodePage);
VerQueryValue(addr(buffer), dest, reinterpret_cast<LPVOID *>(&lpBuffer), &dwBytes);
if (dwBytes == 0)
{
lpBuffer = const_cast<PWCHAR>(peFileNamePtr);
}
}
const LPWSTR lastDot = wcsrchr(lpBuffer, L'.');
if (lastDot == nullptr)
{
auto lpBuffer2 = lpBuffer + wcslen(lpBuffer);
lpBuffer2[0] = L'.';
lpBuffer2[1] = L'd';
lpBuffer2[2] = L'l';
lpBuffer2[3] = L'l';
lpBuffer2[4] = L'\0';
}
else
{
if (lastDot && !_wcsicmp(lastDot, L".MUI"))
{
*lastDot = UNICODE_NULL;
}
}
auto strippedPeFile = wcsrchr(lpBuffer, '\\');
if (strippedPeFile == nullptr)
{
strippedPeFile = lpBuffer;
}
else
{
strippedPeFile += 1;
}
InjectKernelTraceControlEventsInner(peFileNamePtr, strippedPeFile, relogger, eventRecord, processId);
}
}
}
else
{
auto strippedPeFile = wcsrchr(peFileNamePtr, '\\');
if (strippedPeFile == nullptr)
{
strippedPeFile = peFileNamePtr;
}
else
{
strippedPeFile += 1;
}
InjectKernelTraceControlEventsInner(peFileNamePtr, strippedPeFile, relogger, eventRecord, processId);
}
}
return S_OK;
}
__declspec(noinline) HRESULT InjectTraceEventInfoEvent(PEVENT_RECORD eventRecord, ITraceRelogger *relogger)
{
ULONG bufferSize = 0;
TDHSTATUS status;
BYTE buffer[MAX_EVENT_SIZE];
if ((eventRecord->EventHeader.Flags & EVENT_HEADER_FLAG_CLASSIC_HEADER) != 0)
{
status = TdhGetEventInformation(eventRecord, 0, nullptr, nullptr, &bufferSize);
if (status == ERROR_INSUFFICIENT_BUFFER && bufferSize > 0)
{
status = TdhGetEventInformation(eventRecord, 0, nullptr, (PTRACE_EVENT_INFO)addr(buffer), &bufferSize);
}
}
else
{
status = TdhGetManifestEventInformation(&eventRecord->EventHeader.ProviderId, &eventRecord->EventHeader.EventDescriptor, nullptr, &bufferSize);
if (status == ERROR_INSUFFICIENT_BUFFER && bufferSize > 0)
{
status = TdhGetManifestEventInformation(&eventRecord->EventHeader.ProviderId, &eventRecord->EventHeader.EventDescriptor, (PTRACE_EVENT_INFO)addr(buffer), &bufferSize);
}
}
if (status == ERROR_SUCCESS)
{
auto flags = EVENT_HEADER_FLAG_CLASSIC_HEADER;
if ((eventRecord->EventHeader.Flags & EVENT_HEADER_FLAG_64_BIT_HEADER) != 0)
{
flags |= EVENT_HEADER_FLAG_64_BIT_HEADER;
}
else
{
flags |= EVENT_HEADER_FLAG_32_BIT_HEADER;
}
ITraceEvent *duplicateEvent;
relogger->CreateEventInstance(0, flags, &duplicateEvent);
EVENT_DESCRIPTOR eventDescriptor;
eventDescriptor.Id = 0xFFFF;
eventDescriptor.Version = 0;
eventDescriptor.Channel = 0;
eventDescriptor.Level = 0;
eventDescriptor.Opcode = 32;
eventDescriptor.Task = 0;
eventDescriptor.Keyword = 0;
duplicateEvent->SetEventDescriptor(&eventDescriptor);
duplicateEvent->SetProcessorIndex(GetEventProcessorIndex(eventRecord));
duplicateEvent->SetProviderId(&EventMetadataGuid);
duplicateEvent->SetTimeStamp(&eventRecord->EventHeader.TimeStamp);
duplicateEvent->SetProcessId(eventRecord->EventHeader.ProcessId);
duplicateEvent->SetThreadId(eventRecord->EventHeader.ThreadId);
duplicateEvent->SetPayload(addr(buffer), static_cast<ULONG>(bufferSize));
relogger->Inject(duplicateEvent);
duplicateEvent->Release();
}
return S_OK;
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,56 @@
#pragma once
#include <Windows.h>
constexpr GUID ImageLoadGuid = { 0x2cb15d1d, 0x5fc1, 0x11d2, {0xab, 0xe1, 0x00, 0xa0, 0xc9, 0x11, 0xf5, 0x18} };
constexpr GUID ClrProviderGuid = { 0xE13C0D23, 0xCCBC, 0x4E12, {0x93, 0x1B, 0xD9, 0xCC, 0x2E, 0xEE, 0x27, 0xE4} };
constexpr GUID KernelProcessGuid = { 0x22fb2cd6, 0x0e7b, 0x422b, { 0xa0, 0xc7, 0x2f, 0xad, 0x1f, 0xd0, 0xe7, 0x16 } };
constexpr USHORT MethodLoadEvent = 143;
constexpr USHORT MethodUnloadEvent = 144;
constexpr USHORT ModuleLoadEvent = 152;
constexpr USHORT ModuleUnloadEvent = 153;
constexpr USHORT ILToNativeMapEvent = 190;
struct SafeFileHandle
{
SafeFileHandle(HANDLE handle)
{
this->h = handle;
}
SafeFileHandle(SafeFileHandle &&movedFrom) noexcept
{
this->h = movedFrom.h;
movedFrom.h = INVALID_HANDLE_VALUE;
}
SafeFileHandle(const SafeFileHandle& that)
{
this->h = that.h;
}
SafeFileHandle& operator=(const SafeFileHandle& that)
{
this->h = that.h;
return *this;
}
~SafeFileHandle()
{
if (this->h != INVALID_HANDLE_VALUE)
{
CloseHandle(this->h);
}
}
const HANDLE Get() const
{
return this->h;
}
private:
HANDLE h;
};
int InvokeBPerfStart(const int argc, PWSTR *argv, bool setCtrlCHandler, void (*fileMovedCallback)(const int length, const wchar_t *));
void InvokeBPerfStop();

Просмотреть файл

@ -0,0 +1,389 @@
#pragma once
#include <objbase.h>
#include <relogger.h>
#include <evntrace.h>
#include <strsafe.h>
#include <evntcons.h>
#include <unordered_set>
struct EventKey
{
GUID ProviderGuid;
USHORT EventId;
UCHAR Version;
EventKey(const GUID &providerId, USHORT eventId, UCHAR version) : ProviderGuid(providerId), EventId(eventId), Version(version)
{
}
bool operator==(const EventKey &other) const noexcept
{
return InlineIsEqualGUID(this->ProviderGuid, other.ProviderGuid) && this->EventId == other.EventId && this->Version == other.Version;
}
};
struct EventKeyHasher
{
size_t operator()(const EventKey &k) const noexcept
{
using std::size_t;
using std::string;
const uint64_t *p = reinterpret_cast<const uint64_t *>(&k.ProviderGuid);
const std::hash<uint64_t> hash;
return hash(p[0]) ^ hash(p[1]) ^ k.EventId ^ k.Version;
}
};
struct ContextInfo
{
ContextInfo(PBYTE buffer, PBYTE compressionBuffer, PBYTE workspace, HANDLE dataFile, HANDLE indexFile, HANDLE metadataFile, ITraceRelogger *relogger, BOOL enableMetadata, BOOL enableSymbolServerInfo, const std::unordered_map<std::wstring, std::wstring> * volumeMap)
{
this->Buffer = buffer;
this->CompressionBuffer = compressionBuffer;
this->Workspace = workspace;
this->DataFile = dataFile;
this->IndexFile = indexFile;
this->MetadataFile = metadataFile;
this->Offset = 0;
this->LastEventIndexedTimeStamp = 0;
this->PerfFreq = 0;
this->Relogger = relogger;
this->EnableMetadata = enableMetadata;
this->EnableSymbolServerInfo = enableSymbolServerInfo;
this->VolumeMap = volumeMap;
#ifdef DEBUG
this->TotalEvents = 0;
#endif
}
std::unordered_set<EventKey, EventKeyHasher> EventMetadataWrittenMap;
PBYTE Buffer;
DWORD Offset;
LONGLONG LastEventIndexedTimeStamp;
LONGLONG PerfFreq;
HANDLE DataFile;
HANDLE IndexFile;
HANDLE MetadataFile;
PBYTE CompressionBuffer;
PBYTE Workspace;
ITraceRelogger *Relogger;
BOOL EnableMetadata;
BOOL EnableSymbolServerInfo;
const std::unordered_map<std::wstring, std::wstring> * VolumeMap;
#ifdef DEBUG
ULONG TotalEvents;
#endif
};
struct ContextInfo2
{
ContextInfo2(FILETIME startTime, LARGE_INTEGER startQPC, const wchar_t * dataDirectory, const std::unordered_set<std::wstring> * clrProcessNamesSet, const std::unordered_map<std::wstring, std::wstring> * volumeMap)
{
this->StartTime = startTime;
this->StartQPC = startQPC;
this->DataDirectory = dataDirectory;
this->CLRProcessNamesSet = clrProcessNamesSet;
this->VolumeMap = volumeMap;
}
const std::unordered_set<std::wstring> * CLRProcessNamesSet;
FILETIME StartTime;
LARGE_INTEGER StartQPC;
const wchar_t * DataDirectory;
const std::unordered_map<std::wstring, std::wstring> * VolumeMap;
std::unordered_map<ULONG, SafeFileHandle> ManagedMethodMapFile;
std::unordered_map<ULONG, SafeFileHandle> ManagedILToNativeMapFile;
std::unordered_map<ULONG, SafeFileHandle> ManagedModuleMapFile;
std::unordered_map<ULONG, SafeFileHandle> NativeModuleMapFile;
std::unordered_map<ULONG, SafeFileHandle> DataFile;
std::unordered_map<ULONG, LONG> OffsetIntoDataFile;
};
__declspec(noinline) HRESULT InjectKernelTraceControlEvents(PEVENT_RECORD eventRecord, ITraceRelogger *relogger);
__declspec(noinline) HRESULT InjectTraceEventInfoEvent(PEVENT_RECORD eventRecord, ITraceRelogger *relogger);
class TraceEventCallback : public ITraceEventCallback
{
public:
HRESULT STDMETHODCALLTYPE OnEvent(ITraceEvent *traceEvent, ITraceRelogger *relogger) override;
HRESULT STDMETHODCALLTYPE OnBeginProcessTrace(ITraceEvent *header, ITraceRelogger *relogger) override;
HRESULT STDMETHODCALLTYPE OnFinalizeProcessTrace(ITraceRelogger *relogger) override;
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *ppObj) override
{
UNREFERENCED_PARAMETER(riid);
UNREFERENCED_PARAMETER(ppObj);
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE AddRef() override
{
return 0;
}
ULONG STDMETHODCALLTYPE Release() override
{
return 0;
}
TraceEventCallback(BOOL enableMetadata, BOOL enableSymbolServerInfo, const std::unordered_map<std::wstring, std::wstring>* volumeMap)
{
this->enableMetadata = enableMetadata;
this->enableSymbolServerInfo = enableSymbolServerInfo;
this->volumeMap = volumeMap;
this->qpc = { 0 };
}
virtual ~TraceEventCallback()
{
}
private:
BOOL enableMetadata;
BOOL enableSymbolServerInfo;
std::unordered_set<EventKey, EventKeyHasher> eventMetadataLogged;
LARGE_INTEGER qpc;
const std::unordered_map<std::wstring, std::wstring>* volumeMap;
};
class FakeTraceEvent : public ITraceEvent
{
HRESULT STDMETHODCALLTYPE Clone(ITraceEvent **NewEvent) override
{
UNREFERENCED_PARAMETER(NewEvent);
return S_OK;
}
HRESULT STDMETHODCALLTYPE GetUserContext(void **UserContext) override
{
*UserContext = &this->eventRecord.UserContext;
return S_OK;
}
HRESULT STDMETHODCALLTYPE GetEventRecord(PEVENT_RECORD *EventRecord) override
{
*EventRecord = &this->eventRecord;
return S_OK;
}
HRESULT STDMETHODCALLTYPE SetPayload(BYTE *Payload, ULONG PayloadSize) override
{
this->eventRecord.UserData = Payload;
this->eventRecord.UserDataLength = (USHORT)PayloadSize;
return S_OK;
}
HRESULT STDMETHODCALLTYPE SetEventDescriptor(PCEVENT_DESCRIPTOR EventDescriptor) override
{
this->eventRecord.EventHeader.EventDescriptor = *EventDescriptor;
return S_OK;
}
HRESULT STDMETHODCALLTYPE SetProcessId(ULONG ProcessId) override
{
this->eventRecord.EventHeader.ProcessId = ProcessId;
return S_OK;
}
HRESULT STDMETHODCALLTYPE SetProcessorIndex(ULONG ProcessorIndex) override
{
this->eventRecord.BufferContext.ProcessorIndex = (USHORT)ProcessorIndex;
return S_OK;
}
HRESULT STDMETHODCALLTYPE SetThreadId(ULONG ThreadId) override
{
this->eventRecord.EventHeader.ThreadId = ThreadId;
return S_OK;
}
HRESULT STDMETHODCALLTYPE SetThreadTimes(ULONG KernelTime, ULONG UserTime) override
{
this->eventRecord.EventHeader.KernelTime = KernelTime;
this->eventRecord.EventHeader.UserTime = UserTime;
return S_OK;
}
HRESULT STDMETHODCALLTYPE SetActivityId(LPCGUID ActivityId) override
{
this->eventRecord.EventHeader.ActivityId = *ActivityId;
return S_OK;
}
HRESULT STDMETHODCALLTYPE SetTimeStamp(LARGE_INTEGER *TimeStamp) override
{
this->eventRecord.EventHeader.TimeStamp = *TimeStamp;
return S_OK;
}
HRESULT STDMETHODCALLTYPE SetProviderId(LPCGUID ProviderId) override
{
this->eventRecord.EventHeader.ProviderId = *ProviderId;
return S_OK;
}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *ppObj) override
{
UNREFERENCED_PARAMETER(riid);
UNREFERENCED_PARAMETER(ppObj);
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE AddRef() override
{
return 0;
}
ULONG STDMETHODCALLTYPE Release() override
{
return 0;
}
private:
EVENT_RECORD eventRecord;
public:
FakeTraceEvent()
{
}
void Initialize(USHORT flags)
{
this->eventRecord = { 0 };
this->eventRecord.EventHeader.Flags = flags;
if ((flags & EVENT_HEADER_FLAG_CLASSIC_HEADER) != 0)
{
this->eventRecord.EventHeader.EventProperty = EVENT_HEADER_PROPERTY_LEGACY_EVENTLOG;
this->eventRecord.EventHeader.HeaderType = 0;
this->eventRecord.EventHeader.Size = (USHORT)sizeof(EVENT_HEADER);
}
else
{
this->eventRecord.EventHeader.EventProperty = EVENT_HEADER_PROPERTY_XML;
this->eventRecord.EventHeader.HeaderType = 1;
this->eventRecord.EventHeader.Size = (USHORT)sizeof(EVENT_HEADER);
}
}
};
class FakeTraceRelogger : public ITraceRelogger
{
public:
HRESULT SetUserContext(ContextInfo *context)
{
this->userContext = context;
return S_OK;
}
HRESULT STDMETHODCALLTYPE AddLogfileTraceStream(BSTR LogfileName, void *UserContext, TRACEHANDLE *TraceHandle) override
{
UNREFERENCED_PARAMETER(LogfileName);
UNREFERENCED_PARAMETER(UserContext);
UNREFERENCED_PARAMETER(TraceHandle);
return S_OK;
}
HRESULT STDMETHODCALLTYPE AddRealtimeTraceStream(BSTR LoggerName, void *UserContext, TRACEHANDLE *TraceHandle) override
{
UNREFERENCED_PARAMETER(LoggerName);
UNREFERENCED_PARAMETER(UserContext);
UNREFERENCED_PARAMETER(TraceHandle);
return S_OK;
}
HRESULT STDMETHODCALLTYPE RegisterCallback(ITraceEventCallback *Callback) override
{
UNREFERENCED_PARAMETER(Callback);
return S_OK;
}
HRESULT STDMETHODCALLTYPE Inject(ITraceEvent *Event) override
{
PEVENT_RECORD eventRecord;
Event->GetEventRecord(&eventRecord);
eventRecord->UserContext = this->userContext;
BOOL enableMetadata = this->userContext->EnableMetadata;
BOOL enableSymbolServerInfo = this->userContext->EnableSymbolServerInfo;
this->userContext->EnableMetadata = FALSE;
this->userContext->EnableSymbolServerInfo = FALSE;
this->callback(eventRecord);
this->userContext->EnableMetadata = enableMetadata;
this->userContext->EnableSymbolServerInfo = enableSymbolServerInfo;
return S_OK;
}
HRESULT STDMETHODCALLTYPE CreateEventInstance(TRACEHANDLE TraceHandle, ULONG Flags, ITraceEvent **Event) override
{
UNREFERENCED_PARAMETER(TraceHandle);
this->fakeTraceEvent.Initialize((USHORT)Flags);
*Event = &this->fakeTraceEvent; // NOTE: This is valid because all calls to CreateEventInstance are within the lifetime of this Relogger, and there is no recursion.
return S_OK;
}
HRESULT STDMETHODCALLTYPE ProcessTrace(void) override
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE SetOutputFilename(BSTR LogfileName) override
{
UNREFERENCED_PARAMETER(LogfileName);
return S_OK;
}
HRESULT STDMETHODCALLTYPE SetCompressionMode(BOOLEAN CompressionMode) override
{
UNREFERENCED_PARAMETER(CompressionMode);
return S_OK;
}
HRESULT STDMETHODCALLTYPE Cancel(void) override
{
return S_OK;
}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, PVOID *ppObj) override
{
UNREFERENCED_PARAMETER(riid);
UNREFERENCED_PARAMETER(ppObj);
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE AddRef() override
{
return 0;
}
ULONG STDMETHODCALLTYPE Release() override
{
return 0;
}
private:
PEVENT_RECORD_CALLBACK callback;
ContextInfo *userContext;
FakeTraceEvent fakeTraceEvent;
public:
FakeTraceRelogger(PEVENT_RECORD_CALLBACK callback)
{
this->callback = callback;
}
};

Просмотреть файл

@ -0,0 +1,88 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<TargetName>BPerfCPUSamplesCollector</TargetName>
<ProjectGuid>{4CC1C899-4372-4FF0-92B2-C841C332F17C}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>BPerfCPUSamplesCollector</RootNamespace>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v142</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>tdh.lib;version.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<EnableEnhancedInstructionSet>AdvancedVectorExtensions2</EnableEnhancedInstructionSet>
<ExceptionHandling>false</ExceptionHandling>
<ControlFlowGuard>false</ControlFlowGuard>
<OmitFramePointers>true</OmitFramePointers>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<SDLCheck>true</SDLCheck>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>tdh.lib;version.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="KernelTraceControlSupportCode.cpp" />
<ClCompile Include="Program.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Program.h" />
<ClInclude Include="TraceEventCallback.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
</Project>

Просмотреть файл

@ -0,0 +1,59 @@
namespace Microsoft.BPerf
{
using System;
using System.Runtime.InteropServices;
public delegate void FileMoveNotifyCallback(string fileName);
internal delegate void FileMoveCallbackInternal(int length, IntPtr fileName);
public static class DataCollector
{
private static FileMoveNotifyCallback fileMoveNotifyCallback;
public static void Start(string fullDirectoryPath, int rollOverTimeSeconds, FileMoveNotifyCallback callback)
{
if (string.IsNullOrEmpty(fullDirectoryPath))
{
throw new ArgumentNullException(nameof(fullDirectoryPath));
}
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
string[] argvs = { "unused", "1", rollOverTimeSeconds.ToString(), fullDirectoryPath };
IntPtr[] arr = new IntPtr[argvs.Length];
for (var i = 0; i < argvs.Length; ++i)
{
arr[i] = Marshal.StringToHGlobalUni(argvs[i]);
}
FileMoveCallbackInternal c = FileMoveInternal;
fileMoveNotifyCallback = callback;
StartBPerf(argvs.Length, arr, false, Marshal.GetFunctionPointerForDelegate(c));
GC.KeepAlive(c);
}
public static void Stop()
{
StopBPerf();
}
private static void FileMoveInternal(int length, IntPtr fileNamePtr)
{
string fileName = Marshal.PtrToStringUni(fileNamePtr, length);
fileMoveNotifyCallback(fileName);
}
[DllImport(@"BPerfCPUSamplesCollectorLibrary.dll")]
private static extern int StartBPerf(int argc, IntPtr[] argv, bool setCtrlCHandler, IntPtr fileMoveCallback);
[DllImport(@"BPerfCPUSamplesCollectorLibrary.dll")]
private static extern void StopBPerf();
}
}

Просмотреть файл

@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
</Project>