Skip to content

Commit 39bbff8

Browse files
authored
ApplyStartupHook diagnostic IPC command (#86813)
1 parent eb49594 commit 39bbff8

File tree

24 files changed

+551
-26
lines changed

24 files changed

+551
-26
lines changed

src/coreclr/System.Private.CoreLib/src/System/StartupHookProvider.CoreCLR.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,15 @@ namespace System
1212
{
1313
internal static partial class StartupHookProvider
1414
{
15-
private static void ManagedStartup()
15+
private static unsafe void ManagedStartup(char* pDiagnosticStartupHooks)
1616
{
1717
#if FEATURE_PERFTRACING
1818
if (EventSource.IsSupported)
1919
RuntimeEventSource.Initialize();
2020
#endif
2121

2222
if (IsSupported)
23-
ProcessStartupHooks();
23+
ProcessStartupHooks(new string(pDiagnosticStartupHooks));
2424
}
2525
}
2626
}

src/coreclr/nativeaot/Runtime/eventpipe/ds-rt-aot.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,13 @@ ds_rt_disable_perfmap (void)
285285
return DS_IPC_E_NOTSUPPORTED;
286286
}
287287

288+
static
289+
uint32_t
290+
ds_rt_apply_startup_hook (const ep_char16_t *startup_hook_path)
291+
{
292+
return DS_IPC_E_NOTSUPPORTED;
293+
}
294+
288295
/*
289296
* DiagnosticServer.
290297
*/

src/coreclr/vm/assembly.cpp

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
//#define STRICT_JITLOCK_ENTRY_LEAK_DETECTION
5353
//#define STRICT_CLSINITLOCK_ENTRY_LEAK_DETECTION
5454

55+
LPCWSTR s_wszDiagnosticStartupHookPaths = nullptr;
5556

5657
#ifndef DACCESS_COMPILE
5758

@@ -1122,7 +1123,47 @@ bool Assembly::IgnoresAccessChecksTo(Assembly *pAccessedAssembly)
11221123
return GetFriendAssemblyInfo()->IgnoresAccessChecksTo(pAccessedAssembly);
11231124
}
11241125

1126+
void Assembly::AddDiagnosticStartupHookPath(LPCWSTR wszPath)
1127+
{
1128+
LPCWSTR wszDiagnosticStartupHookPathsLocal = s_wszDiagnosticStartupHookPaths;
1129+
1130+
size_t cchPath = u16_strlen(wszPath);
1131+
size_t cchDiagnosticStartupHookPathsNew = cchPath;
1132+
size_t cchDiagnosticStartupHookPathsLocal = 0;
1133+
if (nullptr != wszDiagnosticStartupHookPathsLocal)
1134+
{
1135+
cchDiagnosticStartupHookPathsLocal = u16_strlen(wszDiagnosticStartupHookPathsLocal);
1136+
// Add 1 for the path separator
1137+
cchDiagnosticStartupHookPathsNew += cchDiagnosticStartupHookPathsLocal + 1;
1138+
}
11251139

1140+
size_t currentSize = cchDiagnosticStartupHookPathsNew + 1;
1141+
LPWSTR wszDiagnosticStartupHookPathsNew = new WCHAR[currentSize];
1142+
LPWSTR wszCurrent = wszDiagnosticStartupHookPathsNew;
1143+
1144+
u16_strcpy_s(wszCurrent, currentSize, wszPath);
1145+
wszCurrent += cchPath;
1146+
currentSize -= cchPath;
1147+
1148+
if (cchDiagnosticStartupHookPathsLocal > 0)
1149+
{
1150+
u16_strcpy_s(wszCurrent, currentSize, PATH_SEPARATOR_STR_W);
1151+
wszCurrent += 1;
1152+
currentSize -= 1;
1153+
1154+
u16_strcpy_s(wszCurrent, currentSize, wszDiagnosticStartupHookPathsLocal);
1155+
wszCurrent += cchDiagnosticStartupHookPathsLocal;
1156+
currentSize -= cchDiagnosticStartupHookPathsLocal;
1157+
}
1158+
1159+
// Expect null terminating character
1160+
_ASSERTE(currentSize == 1);
1161+
_ASSERTE(wszCurrent[0] == W('\0'));
1162+
1163+
s_wszDiagnosticStartupHookPaths = wszDiagnosticStartupHookPathsNew;
1164+
1165+
delete [] wszDiagnosticStartupHookPathsLocal;
1166+
}
11261167

11271168
enum CorEntryPointType
11281169
{
@@ -1376,7 +1417,7 @@ static void RunMainPost()
13761417
}
13771418
}
13781419

1379-
static void RunManagedStartup()
1420+
void RunManagedStartup()
13801421
{
13811422
CONTRACTL
13821423
{
@@ -1388,7 +1429,11 @@ static void RunManagedStartup()
13881429
CONTRACTL_END;
13891430

13901431
MethodDescCallSite managedStartup(METHOD__STARTUP_HOOK_PROVIDER__MANAGED_STARTUP);
1391-
managedStartup.Call(NULL);
1432+
1433+
ARG_SLOT args[1];
1434+
args[0] = PtrToArgSlot(s_wszDiagnosticStartupHookPaths);
1435+
1436+
managedStartup.Call(args);
13921437
}
13931438

13941439
INT32 Assembly::ExecuteMainMethod(PTRARRAYREF *stringArgs, BOOL waitForOtherThreads)

src/coreclr/vm/assembly.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -380,6 +380,8 @@ class Assembly
380380
}
381381
#endif
382382

383+
static void AddDiagnosticStartupHookPath(LPCWSTR wszPath);
384+
383385

384386
protected:
385387
#ifdef FEATURE_COMINTEROP

src/coreclr/vm/corelib.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -812,7 +812,7 @@ DEFINE_FIELD_U(rgiLastFrameFromForeignExceptionStackTrace, StackFrame
812812
DEFINE_FIELD_U(iFrameCount, StackFrameHelper, iFrameCount)
813813

814814
DEFINE_CLASS(STARTUP_HOOK_PROVIDER, System, StartupHookProvider)
815-
DEFINE_METHOD(STARTUP_HOOK_PROVIDER, MANAGED_STARTUP, ManagedStartup, SM_RetVoid)
815+
DEFINE_METHOD(STARTUP_HOOK_PROVIDER, MANAGED_STARTUP, ManagedStartup, SM_PtrChar_RetVoid)
816816

817817
DEFINE_CLASS(STREAM, IO, Stream)
818818
DEFINE_METHOD(STREAM, BEGIN_READ, BeginRead, IM_ArrByte_Int_Int_AsyncCallback_Object_RetIAsyncResult)

src/coreclr/vm/eventing/eventpipe/ds-rt-coreclr.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,28 @@ ds_rt_disable_perfmap (void)
329329
#endif // FEATURE_PERFMAP
330330
}
331331

332+
static ep_char16_t * _ds_rt_coreclr_diagnostic_startup_hook_paths = NULL;
333+
334+
static
335+
uint32_t
336+
ds_rt_apply_startup_hook (const ep_char16_t *startup_hook_path)
337+
{
338+
HRESULT hr = S_OK;
339+
// This is set to true when the EE has initialized, which occurs after
340+
// the diagnostic suspension point has completed.
341+
if (g_fEEStarted)
342+
{
343+
// TODO: Support loading and executing startup hook after EE has completely initialized.
344+
return DS_IPC_E_INVALIDARG;
345+
}
346+
else
347+
{
348+
Assembly::AddDiagnosticStartupHookPath(reinterpret_cast<LPCWSTR>(startup_hook_path));
349+
}
350+
351+
return DS_IPC_S_OK;
352+
}
353+
332354
/*
333355
* DiagnosticServer.
334356
*/

src/coreclr/vm/metasig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,7 @@ DEFINE_METASIG(SM(IntPtr_Bool_RetVoid, I F, v))
338338
DEFINE_METASIG(SM(IntPtr_UInt_IntPtr_RetVoid, I K I, v))
339339
DEFINE_METASIG(SM(IntPtr_RetUInt, I, K))
340340
DEFINE_METASIG(SM(PtrChar_RetInt, P(u), i))
341+
DEFINE_METASIG(SM(PtrChar_RetVoid, P(u), v))
341342
DEFINE_METASIG(SM(IntPtr_IntPtr_RetIntPtr, I I, I))
342343
DEFINE_METASIG(SM(IntPtr_IntPtr_Int_RetIntPtr, I I i, I))
343344
DEFINE_METASIG(SM(PtrVoid_PtrVoid_RetVoid, P(v) P(v), v))

src/libraries/System.Private.CoreLib/src/ILLink/ILLink.Suppressions.LibraryBuild.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
<argument>ILLink</argument>
2020
<argument>IL2026</argument>
2121
<property name="Scope">member</property>
22-
<property name="Target">M:System.StartupHookProvider.ProcessStartupHooks()</property>
22+
<property name="Target">M:System.StartupHookProvider.ProcessStartupHooks(System.String)</property>
2323
<property name="Justification">This warning is left in the product so developers get an ILLink warning when trimming an app with System.StartupHookProvider.IsSupported=true.</property>
2424
</attribute>
2525
</assembly>

src/libraries/System.Private.CoreLib/src/System/StartupHookProvider.cs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33

44
using System;
5+
using System.Collections.Generic;
56
using System.Diagnostics;
67
using System.Diagnostics.Tracing;
78
using System.Diagnostics.CodeAnalysis;
@@ -27,15 +28,25 @@ private struct StartupHookNameOrPath
2728

2829
// Parse a string specifying a list of assemblies and types
2930
// containing a startup hook, and call each hook in turn.
30-
private static void ProcessStartupHooks()
31+
private static void ProcessStartupHooks(string diagnosticStartupHooks)
3132
{
3233
if (!IsSupported)
3334
return;
3435

3536
string? startupHooksVariable = AppContext.GetData("STARTUP_HOOKS") as string;
36-
if (startupHooksVariable == null)
37-
{
37+
if (null == startupHooksVariable && string.IsNullOrEmpty(diagnosticStartupHooks))
3838
return;
39+
40+
List<string> startupHookParts = new();
41+
42+
if (!string.IsNullOrEmpty(diagnosticStartupHooks))
43+
{
44+
startupHookParts.AddRange(diagnosticStartupHooks.Split(Path.PathSeparator));
45+
}
46+
47+
if (null != startupHooksVariable)
48+
{
49+
startupHookParts.AddRange(startupHooksVariable.Split(Path.PathSeparator));
3950
}
4051

4152
ReadOnlySpan<char> disallowedSimpleAssemblyNameChars = stackalloc char[4]
@@ -47,9 +58,8 @@ private static void ProcessStartupHooks()
4758
};
4859

4960
// Parse startup hooks variable
50-
string[] startupHookParts = startupHooksVariable.Split(Path.PathSeparator);
51-
StartupHookNameOrPath[] startupHooks = new StartupHookNameOrPath[startupHookParts.Length];
52-
for (int i = 0; i < startupHookParts.Length; i++)
61+
StartupHookNameOrPath[] startupHooks = new StartupHookNameOrPath[startupHookParts.Count];
62+
for (int i = 0; i < startupHookParts.Count; i++)
5363
{
5464
string startupHookPart = startupHookParts[i];
5565
if (string.IsNullOrEmpty(startupHookPart))

src/mono/mono/eventpipe/ds-rt-mono.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,14 @@ ds_rt_disable_perfmap (void)
239239
return DS_IPC_E_NOTSUPPORTED;
240240
}
241241

242+
static
243+
uint32_t
244+
ds_rt_apply_startup_hook (const ep_char16_t *startup_hook_path)
245+
{
246+
// TODO: Implement.
247+
return DS_IPC_E_NOTSUPPORTED;
248+
}
249+
242250
/*
243251
* DiagnosticServer.
244252
*/

0 commit comments

Comments
 (0)