-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Emit ICorProfiler ModuleLoadFinished for dynamic modules (#77068)
- Loading branch information
Showing
7 changed files
with
217 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
#include "moduleload.h" | ||
|
||
GUID ModuleLoad::GetClsid() | ||
{ | ||
// {1774B2E5-028B-4FA8-9DE5-26218CBCBBAC } | ||
GUID clsid = {0x1774b2e5, 0x028b, 0x4fa8, {0x9d, 0xe5, 0x26, 0x21, 0x8c, 0xbc, 0xbb, 0xac}}; | ||
return clsid; | ||
} | ||
|
||
HRESULT ModuleLoad::InitializeCommon(IUnknown* pICorProfilerInfoUnk) | ||
{ | ||
Profiler::Initialize(pICorProfilerInfoUnk); | ||
|
||
HRESULT hr = S_OK; | ||
printf("Setting exception mask\n"); | ||
if (FAILED(hr = pCorProfilerInfo->SetEventMask2(COR_PRF_MONITOR_MODULE_LOADS | COR_PRF_MONITOR_ASSEMBLY_LOADS, 0))) | ||
{ | ||
_failures++; | ||
printf("FAIL: ICorProfilerInfo::SetEventMask2() failed hr=0x%x", hr); | ||
return hr; | ||
} | ||
|
||
return S_OK; | ||
} | ||
|
||
HRESULT ModuleLoad::Initialize(IUnknown* pICorProfilerInfoUnk) | ||
{ | ||
return InitializeCommon(pICorProfilerInfoUnk); | ||
} | ||
|
||
HRESULT ModuleLoad::InitializeForAttach(IUnknown* pICorProfilerInfoUnk, void* pvClientData, UINT cbClientData) | ||
{ | ||
return InitializeCommon(pICorProfilerInfoUnk); | ||
} | ||
|
||
HRESULT ModuleLoad::LoadAsNotificationOnly(BOOL *pbNotificationOnly) | ||
{ | ||
*pbNotificationOnly = TRUE; | ||
return S_OK; | ||
} | ||
|
||
HRESULT ModuleLoad::AssemblyLoadStarted(AssemblyID assemblyId) | ||
{ | ||
_assemblyLoadStartedCount++; | ||
return S_OK; | ||
} | ||
|
||
HRESULT ModuleLoad::AssemblyLoadFinished(AssemblyID assemblyId, HRESULT hrStatus) | ||
{ | ||
_assemblyLoadFinishedCount++; | ||
return S_OK; | ||
} | ||
|
||
HRESULT ModuleLoad::ModuleLoadStarted(ModuleID moduleId) | ||
{ | ||
_moduleLoadStartedCount++; | ||
return S_OK; | ||
} | ||
|
||
HRESULT ModuleLoad::ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus) | ||
{ | ||
_moduleLoadFinishedCount++; | ||
return S_OK; | ||
} | ||
|
||
|
||
HRESULT ModuleLoad::Shutdown() | ||
{ | ||
Profiler::Shutdown(); | ||
|
||
if(_failures == 0 | ||
&& (_moduleLoadStartedCount != 0) | ||
&& (_assemblyLoadStartedCount != 0) | ||
&& (_moduleLoadStartedCount == _moduleLoadFinishedCount) | ||
&& (_assemblyLoadStartedCount == _assemblyLoadFinishedCount)) | ||
{ | ||
printf("PROFILER TEST PASSES\n"); | ||
} | ||
else | ||
{ | ||
printf("PROFILER TEST FAILED, failures=%d moduleLoadStarted=%d moduleLoadFinished=%d assemblyLoadStarted=%d assemblyLoadFinished=%d\n", | ||
_failures.load(), | ||
_moduleLoadStartedCount.load(), | ||
_moduleLoadFinishedCount.load(), | ||
_assemblyLoadStartedCount.load(), | ||
_assemblyLoadFinishedCount.load()); | ||
} | ||
|
||
fflush(stdout); | ||
|
||
return S_OK; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
#pragma once | ||
|
||
#include "../profiler.h" | ||
|
||
class ModuleLoad : public Profiler | ||
{ | ||
public: | ||
|
||
ModuleLoad() : | ||
Profiler(), | ||
_assemblyLoadStartedCount(0), | ||
_assemblyLoadFinishedCount(0), | ||
_moduleLoadStartedCount(0), | ||
_moduleLoadFinishedCount(0), | ||
_failures(0) | ||
{ | ||
|
||
} | ||
|
||
static GUID GetClsid(); | ||
virtual HRESULT STDMETHODCALLTYPE Initialize(IUnknown* pICorProfilerInfoUnk); | ||
virtual HRESULT STDMETHODCALLTYPE InitializeForAttach(IUnknown* pICorProfilerInfoUnk, void* pvClientData, UINT cbClientData); | ||
virtual HRESULT STDMETHODCALLTYPE Shutdown(); | ||
virtual HRESULT STDMETHODCALLTYPE LoadAsNotificationOnly(BOOL *pbNotificationOnly); | ||
|
||
virtual HRESULT STDMETHODCALLTYPE AssemblyLoadStarted(AssemblyID assemblyId); | ||
virtual HRESULT STDMETHODCALLTYPE AssemblyLoadFinished(AssemblyID assemblyId, HRESULT hrStatus); | ||
virtual HRESULT STDMETHODCALLTYPE ModuleLoadStarted(ModuleID moduleId); | ||
virtual HRESULT STDMETHODCALLTYPE ModuleLoadFinished(ModuleID moduleId, HRESULT hrStatus); | ||
|
||
private: | ||
std::atomic<int> _assemblyLoadStartedCount; | ||
std::atomic<int> _assemblyLoadFinishedCount; | ||
std::atomic<int> _moduleLoadStartedCount; | ||
std::atomic<int> _moduleLoadFinishedCount; | ||
std::atomic<int> _failures; | ||
|
||
HRESULT InitializeCommon(IUnknown* pCorProfilerInfoUnk); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System; | ||
using System.IO; | ||
using System.Runtime.CompilerServices; | ||
using System.Runtime.InteropServices; | ||
using System.Threading; | ||
using System.Reflection; | ||
using System.Reflection.Emit; | ||
|
||
namespace Profiler.Tests | ||
{ | ||
class ModuleLoadTest | ||
{ | ||
private static readonly Guid ModuleLoadGuid = new Guid("1774B2E5-028B-4FA8-9DE5-26218CBCBBAC"); | ||
|
||
public static int RunTest(string[] args) | ||
{ | ||
var type = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("TestAssembly"), AssemblyBuilderAccess.Run) | ||
.DefineDynamicModule("TestModule") | ||
.DefineType("TestClass", TypeAttributes.Public) | ||
.CreateType(); | ||
|
||
var obj = Activator.CreateInstance(type); | ||
if (obj == null) | ||
{ | ||
throw new NullReferenceException(); | ||
} | ||
|
||
return 100; | ||
} | ||
|
||
public static int Main(string[] args) | ||
{ | ||
if (args.Length > 0 && args[0].Equals("RunTest", StringComparison.OrdinalIgnoreCase)) | ||
{ | ||
return RunTest(args); | ||
} | ||
|
||
return ProfilerTestRunner.Run(profileePath: System.Reflection.Assembly.GetExecutingAssembly().Location, | ||
testName: "UnitTestModuleLoad", | ||
profilerClsid: ModuleLoadGuid); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
<Project Sdk="Microsoft.NET.Sdk"> | ||
<PropertyGroup> | ||
<TargetFrameworkIdentifier>.NETCoreApp</TargetFrameworkIdentifier> | ||
<OutputType>exe</OutputType> | ||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> | ||
<!-- This test provides no interesting scenarios for GCStress --> | ||
<GCStressIncompatible>true</GCStressIncompatible> | ||
<!-- The test launches a secondary process and process launch creates | ||
an infinite event loop in the SocketAsyncEngine on Linux. Since | ||
runincontext loads even framework assemblies into the unloadable | ||
context, locals in this loop prevent unloading --> | ||
<UnloadabilityIncompatible>true</UnloadabilityIncompatible> | ||
</PropertyGroup> | ||
<ItemGroup> | ||
<Compile Include="$(MSBuildProjectName).cs" /> | ||
<ProjectReference Include="$(TestSourceDir)Common/CoreCLRTestLibrary/CoreCLRTestLibrary.csproj" /> | ||
<ProjectReference Include="../common/profiler_common.csproj" /> | ||
<CMakeProjectReference Include="$(MSBuildThisFileDirectory)/../native/CMakeLists.txt" /> | ||
</ItemGroup> | ||
</Project> |