Skip to content

Commit

Permalink
CsWin32 bindings, heavy overhaul, CMake native hooks, debug generator…
Browse files Browse the repository at this point in the history
… guard
  • Loading branch information
mvenditto committed Jan 10, 2024
1 parent 439b718 commit d6b06b8
Show file tree
Hide file tree
Showing 304 changed files with 3,083 additions and 25,499 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

*.zip
include/
build/
*.exp
*.lib
*.dll
Expand Down
6 changes: 6 additions & 0 deletions ClrProfiling.Backend.Common/Abstractions/IStackCrawler.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace ClrProfiling.Backend.Abstractions;

public interface IStackCrawler
{

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using uint64_t = ulong;

namespace CorProf.Profiling.Abstractions;
namespace ClrProfiling.Backend.Abstractions;

public interface IThreadInfo
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace CorProf.Profiling.Abstractions;
namespace ClrProfiling.Backend.Abstractions;

public interface IThreadManager
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,16 @@
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>disable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<Platforms>AnyCPU;x64</Platforms>
<Platforms>x64;x86</Platforms>
</PropertyGroup>

<ItemGroup>
<Compile Include="..\CorProf.Helpers\GlobalUsings.cs" Link="GlobalUsings.cs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="8.0.0" />
<PackageReference Include="Serilog" Version="3.1.1" />
<PackageReference Include="Serilog.Sinks.Console" Version="5.0.0" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CorProf.Core\CorProf.Core.csproj" />
<ProjectReference Include="..\CorProf.Helpers\CorProf.Helpers.csproj" />
<ProjectReference Include="..\ClrProfiling.Core\ClrProfiling.Core.csproj" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
using CorProf.Profiling.Threading;
using ClrProfiling.Backend.Threading;
using System.Runtime.CompilerServices;

namespace CorProf.Profiling.Extensions;
namespace ClrProfiling.Backend.Extensions;

public static class ManagedThreadRegistryExtensions
{
Expand Down
2 changes: 2 additions & 0 deletions ClrProfiling.Backend.Common/GlobalUsings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
global using ThreadID = nuint;
global using HANDLE = nint;
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using CorProf.Profiling.Abstractions;
using ClrProfiling.Backend.Abstractions;

namespace CorProf.Profiling.Threading;
namespace ClrProfiling.Backend.Threading;

public sealed class ManagedThreadInfo : IThreadInfo
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using Microsoft.Extensions.Logging;
using System.Collections.Concurrent;
using System.Runtime.CompilerServices;

namespace CorProf.Profiling.Threading;
namespace ClrProfiling.Backend.Threading;

public unsafe sealed class ManagedThreadRegistry
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\CorProf.Profiling\CorProf.Profiling.csproj" />
<ProjectReference Include="..\ClrProfiling.Backend.Common\ClrProfiling.Backend.Common.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ internal static class FILETIMEExtensions
{
public static ulong ToMilliseconds2(this FILETIME filetime)
{
if (PInvoke.FileTimeToSystemTime(filetime, out var systemTime))
if (PInvoke_Windows.FileTimeToSystemTime(filetime, out var systemTime))
{
return systemTime.ToMilliseconds();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
global using COR_PRF_FRAME_INFO = ulong;
global using WCHAR = ushort;
global using DWORD = uint;

#region winnt.h
global using HANDLE = nint;
#endregion
global using WORD = ushort;
global using DWORD64 = ulong;
global using BYTE = byte;

#region corprof.h
global using ProcessID = nuint;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"$schema": "https://aka.ms/CsWin32.schema.json",
"allowMarshaling": false,
"useSafeHandles": false
"useSafeHandles": false,
"className": "PInvoke_Windows"
}
File renamed without changes.
3 changes: 3 additions & 0 deletions ClrProfiling.Backend.Windows/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("ClrProfiling.Backend.Windows.Tests")]
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
using System.Runtime.InteropServices;
using WORD = ushort;
using DWORD = uint;
using DWORD64 = ulong;
using BYTE = byte;

namespace CorProf.Profiling.Windows64.Stack;

namespace ClrProfiling.Backend.Windows.Stack;

internal static unsafe partial class NtDllNativeMethods
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
using CorProf.Bindings;
using CorProf.Profiling.Abstractions;
using CorProf.Profiling.Threading;
using ClrProfiling.Backend.Abstractions;
using ClrProfiling.Backend.Threading;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Text;
using Windows.Win32;
using Windows.Win32.Foundation;
using Windows.Win32.System.Diagnostics.Debug;
using Windows.Win32.System.Diagnostics.ClrProfiling;


namespace CorProf.Profiling.Windows64.Stack;
namespace ClrProfiling.Backend.Windows.Stack;

public unsafe partial class Windows64StackWalker : IStackCrawler, IDisposable
{
Expand Down Expand Up @@ -79,7 +78,7 @@ private int IsFramePointerInsideStackBounds(ulong stackPointer, ulong stackBase,

public int Unwind()
{
if(!PInvoke.GetThreadContext(_osThreadHandle, _threadContext)) // TODO
if(!PInvoke_Windows.GetThreadContext(_osThreadHandle, _threadContext)) // TODO
{
return 1;
}
Expand Down Expand Up @@ -115,7 +114,7 @@ public int Unwind()
// Lookup the function table entry using the point at which control left the procedure
// TODO: RtlLookupFunctionEntry may try to acquire locks, we need to handle that case to avoid
// deadlocks.
IMAGE_RUNTIME_FUNCTION_ENTRY* functionEntry = PInvoke.RtlLookupFunctionEntry(
IMAGE_RUNTIME_FUNCTION_ENTRY* functionEntry = PInvoke_Windows.RtlLookupFunctionEntry(
_threadContext->Rip,
&imageBaseAddress,
_unwindHistoryTable);
Expand All @@ -136,7 +135,7 @@ public int Unwind()
// frame pointer of the establisher and check if there is an exception
// handler for the frame.
// TODO: RtlVirtualUnwind may try to acquire locks, we need to handle that case to avoid
_ = PInvoke.RtlVirtualUnwind(
_ = PInvoke_Windows.RtlVirtualUnwind(
RTL_VIRTUAL_UNWIND_HANDLER_TYPE.UNW_FLAG_NHANDLER, // The function has no handler
imageBaseAddress,
_threadContext->Rip,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
using Microsoft.Extensions.Logging;
using CorProf.Profiling.Abstractions;
using ClrProfiling.Backend.Abstractions;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.InteropServices;
using Microsoft.Extensions.Logging.Abstractions;
using CorProf.Profiling.Threading;
using static CorProf.Profiling.Windows64.Stack.NtDllNativeMethods;
using ClrProfiling.Backend.Threading;
using Microsoft.Diagnostics.Runtime.Utilities;
using Serilog;
using System.Diagnostics;
using CorProf.Bindings;
using Windows.Win32;
using Windows.Win32.System.Diagnostics.Debug;
using Windows.Win32.Foundation;
using Windows.Wdk.System.Threading;
using KAFFINITY = ulong;
using KPRIORITY = int;
using CorProf.Helpers;
using System.Reflection.Metadata.Ecma335; // LONG
using Windows.Win32.System.Diagnostics.ClrProfiling;
using System.ComponentModel;

namespace CorProf.Profiling.Windows64;
namespace ClrProfiling.Backend.Windows;

public class Windows64ThreadManager : IThreadManager, IDisposable
{
Expand All @@ -45,21 +43,21 @@ public unsafe Windows64ThreadManager(ILogger<Windows64ThreadManager> logger, ICo

private static unsafe void InitQueryInformationThreadDelegate()
{
var ntdll = PInvoke.GetModuleHandle("ntdll.dll");
var ntdll = PInvoke_Windows.GetModuleHandle("ntdll.dll");

if (ntdll == IntPtr.Zero)
{
ntdll = PInvoke.LoadLibrary("ntdll.dll");
ntdll = PInvoke_Windows.LoadLibrary("ntdll.dll");
}

QueryInformationThreadDelegate = (delegate* unmanaged[Stdcall]<HANDLE, THREADINFOCLASS, void*, uint, uint*, NTSTATUS>)PInvoke.GetProcAddress(ntdll, "NtQueryInformationThread").Value;
QueryInformationThreadDelegate = (delegate* unmanaged[Stdcall]<HANDLE, THREADINFOCLASS, void*, uint, uint*, NTSTATUS>)PInvoke_Windows.GetProcAddress(ntdll, "NtQueryInformationThread").Value;
}

public unsafe nint GetThreadHandle(ulong managedThreadId)
public unsafe nint GetThreadHandle(nuint managedThreadId)
{
var osThreadHandle = IntPtr.Zero;
var osThreadHandle = HANDLE.Null;

var hr = _profilerInfo->GetHandleFromThread(managedThreadId, (void**)&osThreadHandle);
var hr = _profilerInfo->GetHandleFromThread(managedThreadId, &osThreadHandle);

if (hr != HResult.S_OK)
{
Expand All @@ -71,27 +69,27 @@ public unsafe nint GetThreadHandle(ulong managedThreadId)

var currProcess = Process.GetCurrentProcess();
var processHandle = new HANDLE(currProcess.Handle);
var threadHandle = new HANDLE(osThreadHandle);

const uint THREAD_ALL_ACCESS = 0x1FFFFF;
const DUPLICATE_HANDLE_OPTIONS DefaultDuplicateHandleOpts = 0;

var realThreadHandle = HANDLE.Null;

// acquire a real handle instead of a pseudo-handle.
hr = PInvoke.DuplicateHandle(
var result = PInvoke_Windows.DuplicateHandle(
processHandle,
threadHandle,
osThreadHandle,
processHandle,
&realThreadHandle,
THREAD_ALL_ACCESS,
false,
new BOOL(false),
DefaultDuplicateHandleOpts
);

if (hr <= HResult.S_OK)
if (result.Value == 0)
{
Log.Logger.Warning("FAIL Kernel32::DuplicateHandle() with hr=0x{hr:x8}", hr);
var err = Marshal.GetLastWin32Error();
Log.Logger.Warning("FAIL Kernel32::DuplicateHandle() with err=0x{hr:x8}: {Message}", err, new Win32Exception(err).Message);
return hr;
}

Expand All @@ -102,7 +100,7 @@ public ulong GetThreadCpuTime(IThreadInfo threadInfo)
{
var threadHandle = new HANDLE(threadInfo.OSThreadHandle);

var success = PInvoke.GetThreadTimes(
var success = PInvoke_Windows.GetThreadTimes(
threadHandle, out var _, out var _, out var kernelTime, out var userTime);

if (success)
Expand Down Expand Up @@ -130,7 +128,7 @@ internal unsafe bool EnsureThreadIsSuspended(HANDLE osThreadHandle)

for (var i = 0; i < 10; i++)
{
var result = PInvoke.GetThreadContext(osThreadHandle, context);
var result = PInvoke_Windows.GetThreadContext(osThreadHandle, context);
_logger.LogDebug("GetThreadContext(): {Result}", result);

if (result)
Expand Down Expand Up @@ -163,7 +161,7 @@ public unsafe bool TrySuspendThread(ManagedThreadInfo clrThreadInfo)
var context = (CONTEXT*)NativeMemory.AlignedAlloc((nuint)sizeof(CONTEXT), 16);
context->ContextFlags = CONTEXT_FLAGS.CONTEXT_INTEGER_AMD64; // CONTEXT_INTEGER

var suspendCount = PInvoke.SuspendThread(osThreadHandle);
var suspendCount = PInvoke_Windows.SuspendThread(osThreadHandle);

if (suspendCount == SuspendThreadFailed)
{
Expand All @@ -184,12 +182,12 @@ public unsafe bool TrySuspendThread(ManagedThreadInfo clrThreadInfo)
// ensure the thread is actually suspended.
// SuspendThread() is asynchronous and the scheduler may not immediately suspend the thread.
// see: https://devblogs.microsoft.com/oldnewthing/20150205-00/?p=44743
if (PInvoke.GetThreadContext(osThreadHandle, context).Value != 0)
if (PInvoke_Windows.GetThreadContext(osThreadHandle, context).Value != 0)
{
// do not allocate after the thread is suspend or it may deadlock!
return true;
}
PInvoke.ResumeThread(osThreadHandle);
PInvoke_Windows.ResumeThread(osThreadHandle);

_logger.LogWarning("Unable to suspend thread 0x{OsThreadHandle:x8}", osThreadHandle);

Expand All @@ -200,7 +198,7 @@ public bool TryResumeThread(ManagedThreadInfo clrThreadInfo)
{
var osThreadHandle = new HANDLE(clrThreadInfo.OSThreadHandle);

var suspendCount = PInvoke.ResumeThread(osThreadHandle);
var suspendCount = PInvoke_Windows.ResumeThread(osThreadHandle);

if (suspendCount == ResumeThreadFailed)
{
Expand Down
Loading

0 comments on commit d6b06b8

Please sign in to comment.