diff --git a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
index 506d9bd5320f54..5d22c457f23f8a 100644
--- a/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
+++ b/src/installer/pkg/sfx/Microsoft.NETCore.App/Directory.Build.props
@@ -169,6 +169,7 @@
+
@@ -176,6 +177,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/mono/CMakeLists.txt b/src/mono/CMakeLists.txt
index 1437fc59feb482..fcb13923813afe 100644
--- a/src/mono/CMakeLists.txt
+++ b/src/mono/CMakeLists.txt
@@ -11,6 +11,14 @@ set(CMAKE_CXX_FLAGS_CHECKED "")
set(CMAKE_EXE_LINKER_FLAGS_CHECKED "")
set(CMAKE_SHARED_LINKER_FLAGS_CHECKED "")
+if(NOT MONO_LIB_NAME)
+ set(MONO_LIB_NAME "monosgen-2.0")
+endif()
+
+if(NOT MONO_SHARED_LIB_NAME)
+ set(MONO_SHARED_LIB_NAME "$(MONO_LIB_NAME)")
+endif()
+
include(GNUInstallDirs)
include(CheckIncludeFile)
include(CheckFunctionExists)
@@ -106,7 +114,6 @@ if(DISABLE_INTERPRETER)
endif()
add_definitions(-DHAVE_CONFIG_H)
-add_definitions(-DMONO_DLL_EXPORT)
if(GCC)
add_definitions(-g) # TODO: should this really be on by default?
@@ -652,6 +659,18 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug")
endif()
### End of debug build checks
+######################################
+# COMPONENT BUILD CHECKS
+######################################
+if(DISABLE_COMPONENTS AND NOT STATIC_COMPONENTS)
+ set(STATIC_COMPONENTS 1)
+endif()
+
+if(DISABLE_LINK_STATIC_COMPONENTS AND NOT STATIC_COMPONENTS)
+ set(STATIC_COMPONENTS 1)
+endif()
+### End of component build checks
+
######################################
# OTHER CHECKS
######################################
diff --git a/src/mono/cmake/config.h.in b/src/mono/cmake/config.h.in
index 259fff72457acd..b466563394a041 100644
--- a/src/mono/cmake/config.h.in
+++ b/src/mono/cmake/config.h.in
@@ -1052,9 +1052,11 @@
/* Enable runtime support for metadata updates */
#cmakedefine ENABLE_METADATA_UPDATE 1
+/* Enable static linking of mono runtime components */
+#cmakedefine STATIC_COMPONENTS
+
#if defined(ENABLE_LLVM) && defined(HOST_WIN32) && defined(TARGET_WIN32) && (!defined(TARGET_AMD64) || !defined(_MSC_VER))
#error LLVM for host=Windows and target=Windows is only supported on x64 MSVC build.
#endif
#endif
-
diff --git a/src/mono/cmake/options.cmake b/src/mono/cmake/options.cmake
index 56da20953393db..b18f3aa4b1aaf4 100644
--- a/src/mono/cmake/options.cmake
+++ b/src/mono/cmake/options.cmake
@@ -53,6 +53,7 @@ option (ENABLE_CHECKED_BUILD_THREAD "Enable runtime history of per-thread coop s
option (ENABLE_CHECKED_BUILD_METADATA "Enable runtime checks of mempool references between metadata images (must set env var MONO_CHECK_MODE=metadata)")
option (ENABLE_METADATA_UPDATE "Enable runtime support for metadata updates")
option (ENABLE_MSCORDBI "Generate mscordbi to support icordbg interface")
+option (STATIC_COMPONENTS "Compile mono runtime components as static (not dynamic) libraries")
set (GC_SUSPEND "default" CACHE STRING "GC suspend method (default, preemptive, coop, hybrid)")
set (CHECKED_BUILD "" CACHE STRING "Set ENABLE_CHECKED_BUILD_ options at once. Comma-separated list of lowercase ENABLE_CHECKED_BUILD_ options ie. 'gc,threads,private_types' etc.")
@@ -60,3 +61,4 @@ set (ENABLE_MINIMAL "" CACHE STRING "Set many DISABLE_ options at once. Comma-se
set (AOT_TARGET_TRIPLE "" CACHE STRING "Target triple for AOT cross compiler")
set (AOT_OFFSETS_FILE "" CACHE STRING "Offsets file for AOT cross compiler")
set (LLVM_PREFIX "" CACHE STRING "Enable LLVM support with LLVM installed at .")
+
diff --git a/src/mono/mono.proj b/src/mono/mono.proj
index c41d29595c8c62..c9b3f7e36ad228 100644
--- a/src/mono/mono.proj
+++ b/src/mono/mono.proj
@@ -19,24 +19,24 @@
.cmd
.sh
.exe
- .dll
- .dylib
- .dylib
- .so
- lib
- lib
+ lib
+ .dylib
+ .dll
+ .so
+ .lib
+ .a
\"
python3
python
- coreclr.dll
- libcoreclr.dylib
- libcoreclr.dylib
- libcoreclr.so
- libmonosgen-2.0.dylib
- libmonosgen-2.0.so
- libmonosgen-2.0.a
- $(CoreClrFileName)
- libmonosgen-2.0.a
+ coreclr
+ $(LibPrefix)$(CoreClrLibName)$(SharedLibExt)
+ monosgen-2.0
+ $(MonoLibName)
+ $(CoreClrLibName)
+ $(LibPrefix)$(MonoSharedLibName)$(SharedLibExt)
+ $(LibPrefix)$(MonoLibName)$(StaticLibExt)
+ $(MonoStaticLibFileName)
+ $(MonoSharedLibFileName)
$(Configuration)
$(Configuration)
$([MSBuild]::NormalizeDirectory('$(ArtifactsDir)', 'tests', 'coreclr', '$(TargetOS).$(Platform).$(CoreClrTestConfig)', 'Tests', 'Core_Root'))
@@ -74,6 +74,16 @@
hybrid
+
+
+ true
+ true
+ true
+
+
+ true
+
+
@@ -190,6 +200,8 @@
<_MonoCMakeArgs Condition="'$(CMakeArgs)' != ''" Include="$(CMakeArgs)"/>
<_MonoCMakeArgs Condition="'$(MonoEnableLLVM)' == 'true'" Include="-DLLVM_PREFIX=$(MonoLLVMDir.TrimEnd('\/'))" />
<_MonoCMakeArgs Include="-DGC_SUSPEND=$(MonoThreadSuspend)" />
+ <_MonoCMakeArgs Include="-DMONO_LIB_NAME=$(MonoLibName)" />
+ <_MonoCMakeArgs Include="-DMONO_SHARED_LIB_NAME=$(MonoSharedLibName)" />
@@ -272,10 +284,11 @@
<_MonoMinimal Condition="'$(Configuration)' == 'Release' and '$(MonoEnableAssertMessages)' != 'true'">$(_MonoMinimal),assert_messages
- <_MonoCMakeArgs Include="-DENABLE_MINIMAL=jit,portability,sgen_major_marksweep_conc,sgen_split_nursery,sgen_gc_bridge,sgen_toggleref,sgen_debug_helpers,sgen_binary_protocol,logging,shared_perfcounters,interpreter,threads,eventpipe,qcalls$(_MonoMinimal)"/>
+ <_MonoCMakeArgs Include="-DENABLE_MINIMAL=jit,portability,sgen_major_marksweep_conc,sgen_split_nursery,sgen_gc_bridge,sgen_toggleref,sgen_debug_helpers,sgen_binary_protocol,logging,shared_perfcounters,interpreter,threads,qcalls$(_MonoMinimal)"/>
<_MonoCMakeArgs Include="-DENABLE_INTERP_LIB=1"/>
<_MonoCMakeArgs Include="-DDISABLE_ICALL_TABLES=1"/>
<_MonoCMakeArgs Include="-DDISABLE_CRASH_REPORTING=1"/>
+ <_MonoCMakeArgs Include="-DDISABLE_COMPONENTS=1"/>
<_MonoCMakeArgs Include="-DENABLE_ICALL_EXPORT=1"/>
<_MonoCMakeArgs Include="-DENABLE_LAZY_GC_THREAD_CREATION=1"/>
<_MonoCMakeArgs Include="-DENABLE_LLVM_RUNTIME=1"/>
@@ -349,7 +362,6 @@
<_MonoCMakeArgs Include="-DENABLE_MINIMAL=ssa,portability,logging" />
<_MonoCMakeArgs Include="-DENABLE_SIGALTSTACK=1"/>
<_MonoCMakeArgs Include="-DDISABLE_CRASH_REPORTING=1"/>
- <_MonoCMakeArgs Include="-DENABLE_PERFTRACING=0"/>
<_MonoCFLAGS Condition="'$(Platform)' == 'arm'" Include="-march=armv7-a" />
<_MonoCFLAGS Condition="'$(Platform)' == 'arm'" Include="-mtune=cortex-a8" />
@@ -396,6 +408,17 @@
<_MonoCMakeArgs Include="-DENABLE_MSCORDBI=1" />
+
+ <_MonoCMakeArgs Include="-DFEATURE_PERFTRACING_PAL_TCP=1"/>
+ <_MonoCMakeArgs Include="-DFEATURE_PERFTRACING_DISABLE_LISTEN_PORTS=1"/>
+ <_MonoCMakeArgs Include="-DDISABLE_LINK_STATIC_COMPONENTS=1" />
+
+
+
+
+ <_MonoCMakeArgs Include="-DSTATIC_COMPONENTS=1" />
+
+
<_MonoCFLAGSOption>-DCMAKE_C_FLAGS="@(_MonoCPPFLAGS, ' ') @(_MonoCFLAGS, ' ')"
<_MonoCXXFLAGSOption>-DCMAKE_CXX_FLAGS="@(_MonoCPPFLAGS, ' ') @(_MonoCXXFLAGS, ' ')"
@@ -546,6 +569,7 @@
+
@@ -607,14 +631,9 @@
- <_MonoRuntimeFilePath Condition="'$(TargetsWindows)' == 'true'">$(MonoObjDir)out\bin\monosgen-2.0.dll
- <_MonoRuntimeFilePath Condition="'$(TargetsOSX)' == 'true'">$(MonoObjDir)out\lib\libmonosgen-2.0.dylib
- <_MonoRuntimeFilePath Condition="'$(TargetsMacCatalyst)' == 'true'">$(MonoObjDir)out\lib\libmonosgen-2.0.dylib
- <_MonoRuntimeFilePath Condition="'$(TargetsiOS)' == 'true'">$(MonoObjDir)out\lib\libmonosgen-2.0.dylib
- <_MonoRuntimeFilePath Condition="'$(TargetstvOS)' == 'true'">$(MonoObjDir)out\lib\libmonosgen-2.0.dylib
- <_MonoRuntimeFilePath Condition="'$(TargetsBrowser)' == 'true'">$(MonoObjDir)out\lib\libmonosgen-2.0.a
- <_MonoRuntimeFilePath Condition="'$(_MonoRuntimeFilePath)' == ''">$(MonoObjDir)out\lib\libmonosgen-2.0.so
- <_MonoRuntimeStaticFilePath Condition="'$(TargetsMacCatalyst)' == 'true' or '$(TargetsiOS)' == 'true' or '$(TargetstvOS)' == 'true' or '$(TargetsAndroid)' == 'true'">$(MonoObjDir)out\lib\libmonosgen-2.0.a
+ <_MonoRuntimeFilePath Condition="'$(TargetsWindows)' == 'true'">$(MonoObjDir)out\bin\$(MonoFileName)
+ <_MonoRuntimeFilePath Condition="'$(_MonoRuntimeFilePath)' == ''">$(MonoObjDir)out\lib\$(MonoFileName)
+ <_MonoRuntimeStaticFilePath Condition="'$(TargetsMacCatalyst)' == 'true' or '$(TargetsiOS)' == 'true' or '$(TargetstvOS)' == 'true' or '$(TargetsAndroid)' == 'true'">$(MonoObjDir)out\lib\$(MonoStaticLibFileName)
<_MonoIncludeInterpStaticFiles Condition="'$(TargetsBrowser)' == 'true'">true
<_MonoIncludeIcuFiles Condition="'$(TargetsiOS)' == 'true' or '$(TargetstvOS)' == 'true'">true
@@ -624,11 +643,20 @@
- <_MonoRuntimeArtifacts Include="$(_MonoRuntimeFilePath)">
+ <_MonoRuntimeComponentsStaticFilePath Include="$([System.IO.Directory]::GetParent($(_MonoRuntimeFilePath)))\libmono-component-*$(StaticLibExt)" Condition="Exists($(_MonoRuntimeFilePath))" />
+ <_MonoRuntimeComponentsSharedFilePath Include="$([System.IO.Directory]::GetParent($(_MonoRuntimeFilePath)))\libmono-component-*$(SharedLibExt)" Condition="Exists($(_MonoRuntimeFilePath))" />
+ <_MonoRuntimeArtifacts Include="$(_MonoRuntimeFilePath)" Condition="Exists($(_MonoRuntimeFilePath))">
$(RuntimeBinDir)$(MonoFileName)
- <_MonoRuntimeArtifacts Include="$(_MonoRuntimeStaticFilePath)">
- $(RuntimeBinDir)$(MonoStaticFileName)
+ <_MonoRuntimeArtifacts Include="$(_MonoRuntimeStaticFilePath)" Condition="Exists($(_MonoRuntimeStaticFilePath)) and '$(_MonoRuntimeStaticFilePath)' != '$(_MonoRuntimeFilePath)'">
+ $(RuntimeBinDir)$(MonoStaticLibFileName)
+
+
+ <_MonoRuntimeArtifacts Include="@(_MonoRuntimeComponentsStaticFilePath)">
+ $(RuntimeBinDir)%(_MonoRuntimeComponentsStaticFilePath.Filename)%(_MonoRuntimeComponentsStaticFilePath.Extension)
+
+ <_MonoRuntimeArtifacts Include="@(_MonoRuntimeComponentsSharedFilePath)">
+ $(RuntimeBinDir)%(_MonoRuntimeComponentsSharedFilePath.Filename)%(_MonoRuntimeComponentsSharedFilePath.Extension)
<_MonoRuntimeArtifacts Include="$(_MonoAotCrossFilePath)">
$(RuntimeBinDir)cross\$(PackageRID)\mono-aot-cross$(ExeExt)
@@ -658,11 +686,11 @@
<_MonoRuntimeArtifacts Condition="'$(TargetsBrowser)' == 'true' and '$(BuildMonoAOTCrossCompilerOnly)' != 'true'" Include="$(MonoObjDir)out\lib\libmono-profiler-aot.a">
$(RuntimeBinDir)libmono-profiler-aot.a
- <_MonoICorDebugArtifacts Condition="'$(MonoMsCorDbi)' == 'true'" Include="$(MonoObjDir)out\lib\$(LibPrefix)dbgshim$(LibExt)">
- $(RuntimeBinDir)$(LibPrefix)dbgshim$(LibExt)
+ <_MonoICorDebugArtifacts Condition="'$(MonoMsCorDbi)' == 'true'" Include="$(MonoObjDir)out\lib\$(LibPrefix)dbgshim$(SharedLibExt)">
+ $(RuntimeBinDir)$(LibPrefix)dbgshim$(SharedLibExt)
- <_MonoICorDebugArtifacts Condition="'$(MonoMsCorDbi)' == 'true'" Include="$(MonoObjDir)out\lib\$(LibPrefix)mscordbi$(LibExt)">
- $(RuntimeBinDir)$(LibPrefix)mscordbi$(LibExt)
+ <_MonoICorDebugArtifacts Condition="'$(MonoMsCorDbi)' == 'true'" Include="$(MonoObjDir)out\lib\$(LibPrefix)mscordbi$(SharedLibExt)">
+ $(RuntimeBinDir)$(LibPrefix)mscordbi$(SharedLibExt)
<_IcuArtifacts Condition="'$(_MonoIncludeIcuFiles)' == 'true'"
diff --git a/src/mono/mono/CMakeLists.txt b/src/mono/mono/CMakeLists.txt
index 817a804b68752c..897a1886ac74b8 100644
--- a/src/mono/mono/CMakeLists.txt
+++ b/src/mono/mono/CMakeLists.txt
@@ -2,12 +2,6 @@ project(mono)
set(subdirs mini profiler)
-if(ENABLE_PERFTRACING)
- list(APPEND subdirs
- eventpipe/test
- )
-endif(ENABLE_PERFTRACING)
-
foreach(dir ${subdirs})
add_subdirectory(${dir})
endforeach()
diff --git a/src/mono/mono/component/CMakeLists.txt b/src/mono/mono/component/CMakeLists.txt
new file mode 100644
index 00000000000000..276be1a596dce0
--- /dev/null
+++ b/src/mono/mono/component/CMakeLists.txt
@@ -0,0 +1,131 @@
+# a list of every component.
+set(components "")
+
+# the sources for each individiable component define a new
+# component_name-sources_base list for each component, and a
+# component_name-stub-sources_base list for the component stub.
+
+# hot_reload
+list(APPEND components
+ hot_reload
+)
+set(hot_reload-sources_base
+ hot_reload.c
+ hot_reload.h
+ )
+set(hot_reload-stub-sources_base
+ hot_reload-stub.c
+ )
+
+# diagnostics_tracing (event_pipe/diagnostics_server)
+list(APPEND components
+ diagnostics_tracing
+)
+
+set(SHARED_EVENTPIPE_INCLUDE_PATH "../../../native/")
+set(SHARED_EVENTPIPE_SOURCE_PATH "../../../native/eventpipe/")
+set(MONO_EVENTPIPE_SHIM_SOURCE_PATH "../eventpipe/")
+
+include(${MONO_EVENTPIPE_SHIM_SOURCE_PATH}/CMakeLists.txt)
+
+include_directories(
+ ${SHARED_EVENTPIPE_INCLUDE_PATH}
+ ${MONO_EVENTPIPE_SHIM_SOURCE_PATH}
+)
+
+set(diagnostics_tracing-sources_base
+ ${eventpipe_sources}
+ ${diagnostic_server_sources}
+ event_pipe.c
+ event_pipe.h
+ diagnostics_server.c
+ diagnostics_server.h
+ )
+set(diagnostics_tracing-stub-sources_base
+ event_pipe-stub.c
+ diagnostics_server-stub.c
+ )
+
+# from here down, all the components are treated in the same way
+
+# a generic component interface that all components implement
+add_library(component_base INTERFACE)
+target_sources(component_base INTERFACE
+ ../component/component.h
+)
+
+if(DISABLE_COMPONENTS OR (NOT STATIC_COMPONENTS AND HOST_WIN32))
+ set(DISABLE_COMPONENT_OBJECTS 1)
+endif()
+
+# define a component_name-objects and component_name-stub-objects object
+# targets with the relative source file names
+foreach(component IN LISTS components)
+ addprefix("${component}-sources" ../component "${${component}-sources_base}")
+ if(NOT DISABLE_COMPONENT_OBJECTS)
+ add_library("${component}-objects" OBJECT "${${component}-sources}")
+ target_link_libraries("${component}-objects" component_base)
+ endif()
+ addprefix("${component}-stub-sources" ../component "${${component}-stub-sources_base}")
+ add_library("${component}-stub-objects" OBJECT "${${component}-stub-sources}")
+ target_link_libraries("${component}-stub-objects" component_base)
+endforeach()
+
+if(NOT DISABLE_COMPONENTS AND NOT STATIC_COMPONENTS)
+ # define a shared library for each component
+ foreach(component IN LISTS components)
+ if(HOST_WIN32)
+ add_library("mono-component-${component}" SHARED "${${component}-sources}")
+ target_compile_definitions("mono-component-${component}" PRIVATE -DCOMPILING_COMPONENT_DYNAMIC;-DMONO_DLL_IMPORT)
+ else()
+ add_library("mono-component-${component}" SHARED $)
+ endif()
+ # each shared library component gets its own copy for eglib
+ #
+ # FIXME: this is bad for things like the g_log_set_default_handler/g_logv
+ # which use global state - we should move those functions into
+ # monosgen-shared and get them via dynamic linking.
+ target_sources("mono-component-${component}" PRIVATE $)
+ if(NOT DISABLE_SHARED_LIBS)
+ # If we disable shared libs, but build dynamic components we would need
+ # to enable allowing undefined symbols here (presumably to be resolved
+ # from the mono-sgen executable. But that's not a configuration we
+ # should need in dotnet/runtime.
+ target_link_libraries("mono-component-${component}" PRIVATE monosgen-shared)
+ endif()
+ target_link_libraries("mono-component-${component}" PRIVATE ${OS_LIBS})
+ install(TARGETS "mono-component-${component}" LIBRARY)
+ endforeach()
+
+elseif(NOT DISABLE_COMPONENTS AND STATIC_COMPONENTS)
+
+ #define a static library for each component and component stub
+ foreach(component IN LISTS components)
+ add_library("mono-component-${component}-static" STATIC $)
+ install(TARGETS "mono-component-${component}-static" LIBRARY)
+ endforeach()
+ foreach(component IN LISTS components)
+ add_library("mono-component-${component}-stub-static" STATIC $)
+ install(TARGETS "mono-component-${component}-stub-static" LIBRARY)
+ endforeach()
+
+ # define a list of mono-components objects for mini if building a shared libmono with static-linked components
+ set(mono-components-objects "")
+ foreach(component IN LISTS components)
+ list(APPEND mono-components-objects $)
+ endforeach()
+
+endif()
+
+# define a list of mono-components-stubs objects that will be linked into
+# the runtime to be used as fallbacks if the dynamic components are not
+# available or when only static component stubs are requested.
+set(mono-components-stub-objects "")
+foreach(component IN LISTS components)
+ list(APPEND mono-components-stub-objects $)
+endforeach()
+
+
+# component tests
+set(MONO_EVENTPIPE_TEST_SOURCE_PATH "${MONO_EVENTPIPE_SHIM_SOURCE_PATH}/test")
+include(${MONO_EVENTPIPE_TEST_SOURCE_PATH}/CMakeLists.txt)
diff --git a/src/mono/mono/component/component.h b/src/mono/mono/component/component.h
new file mode 100644
index 00000000000000..afc15a118739a0
--- /dev/null
+++ b/src/mono/mono/component/component.h
@@ -0,0 +1,24 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#ifndef _MONO_COMPONENT_COMPONENT_H
+#define _MONO_COMPONENT_COMPONENT_H
+
+#include
+#ifndef __cplusplus
+#include
+#endif // __cplusplus
+
+#define MONO_COMPONENT_ITF_VERSION 1
+
+typedef struct _MonoComponent MonoComponent;
+
+typedef bool (*MonoComponent_AvailableFn) (void);
+
+struct _MonoComponent {
+ intptr_t itf_version;
+ MonoComponent_AvailableFn available;
+};
+
+#endif/*_MONO_COMPONENT_COMPONENT_H*/
diff --git a/src/mono/mono/component/diagnostics_server-stub.c b/src/mono/mono/component/diagnostics_server-stub.c
new file mode 100644
index 00000000000000..0a8f6649cda25a
--- /dev/null
+++ b/src/mono/mono/component/diagnostics_server-stub.c
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#include
+#include "mono/component/diagnostics_server.h"
+#include "mono/metadata/components.h"
+
+/*
+ * Forward declares of all static functions.
+ */
+
+static bool
+diagnostics_server_stub_available (void);
+
+static bool
+diagnostics_server_stub_init (void);
+
+static bool
+diagnostics_server_stub_shutdown (void);
+
+static void
+diagnostics_server_stub_pause_for_diagnostics_monitor (void);
+
+static void
+diagnostics_server_stub_disable (void);
+
+static MonoComponentDiagnosticsServer fn_table = {
+ { MONO_COMPONENT_ITF_VERSION, &diagnostics_server_stub_available },
+ &diagnostics_server_stub_init,
+ &diagnostics_server_stub_shutdown,
+ &diagnostics_server_stub_pause_for_diagnostics_monitor,
+ &diagnostics_server_stub_disable
+};
+
+static bool
+diagnostics_server_stub_available (void)
+{
+ return false;
+}
+
+static bool
+diagnostics_server_stub_init (void)
+{
+ return true;
+}
+
+static bool
+diagnostics_server_stub_shutdown (void)
+{
+ return true;
+}
+
+static void
+diagnostics_server_stub_pause_for_diagnostics_monitor (void)
+{
+}
+
+static void
+diagnostics_server_stub_disable (void)
+{
+}
+
+#ifdef STATIC_COMPONENTS
+MONO_COMPONENT_EXPORT_ENTRYPOINT
+MonoComponentDiagnosticsServer *
+mono_component_diagnostics_server_init (void)
+{
+ return mono_component_diagnostics_server_stub_init ();
+}
+#endif
+
+MonoComponentDiagnosticsServer *
+mono_component_diagnostics_server_stub_init (void)
+{
+ return &fn_table;
+}
diff --git a/src/mono/mono/component/diagnostics_server.c b/src/mono/mono/component/diagnostics_server.c
new file mode 100644
index 00000000000000..c03b1296038d9d
--- /dev/null
+++ b/src/mono/mono/component/diagnostics_server.c
@@ -0,0 +1,38 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#include
+#include
+#include
+#include
+#include
+
+#ifndef STATIC_COMPONENTS
+MONO_COMPONENT_EXPORT_ENTRYPOINT
+MonoComponentDiagnosticsServer *
+mono_component_diagnostics_server_init (void);
+#endif
+
+static bool
+diagnostics_server_available (void);
+
+static MonoComponentDiagnosticsServer fn_table = {
+ { MONO_COMPONENT_ITF_VERSION, &diagnostics_server_available },
+ &ds_server_init,
+ &ds_server_shutdown,
+ &ds_server_pause_for_diagnostics_monitor,
+ &ds_server_disable
+};
+
+static bool
+diagnostics_server_available (void)
+{
+ return true;
+}
+
+MonoComponentDiagnosticsServer *
+mono_component_diagnostics_server_init (void)
+{
+ return &fn_table;
+}
diff --git a/src/mono/mono/component/diagnostics_server.h b/src/mono/mono/component/diagnostics_server.h
new file mode 100644
index 00000000000000..cbc32eb9192d1a
--- /dev/null
+++ b/src/mono/mono/component/diagnostics_server.h
@@ -0,0 +1,32 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#ifndef _MONO_COMPONENT_DIAGNOSTICS_SERVER_H
+#define _MONO_COMPONENT_DIAGNOSTICS_SERVER_H
+
+#include "mono/component/component.h"
+#include "mono/utils/mono-compiler.h"
+
+#ifndef ENABLE_PERFTRACING
+#define ENABLE_PERFTRACING
+#endif
+
+#include
+#include
+
+typedef struct _MonoComponentDiagnosticsServer {
+ MonoComponent component;
+ bool (*init) (void);
+ bool (*shutdown) (void);
+ void (*pause_for_diagnostics_monitor) (void);
+ void (*disable) (void);
+} MonoComponentDiagnosticsServer;
+
+#ifdef STATIC_COMPONENTS
+MONO_COMPONENT_EXPORT_ENTRYPOINT
+MonoComponentDiagnosticsServer *
+mono_component_diagnostics_server_init (void);
+#endif
+
+#endif /*_MONO_COMPONENT_DIAGNOSTICS_SERVER_H*/
diff --git a/src/mono/mono/component/event_pipe-stub.c b/src/mono/mono/component/event_pipe-stub.c
new file mode 100644
index 00000000000000..ce008d05b4f297
--- /dev/null
+++ b/src/mono/mono/component/event_pipe-stub.c
@@ -0,0 +1,263 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#include
+#include "mono/component/event_pipe.h"
+#include "mono/metadata/components.h"
+
+static EventPipeSessionID _dummy_session_id;
+
+static uint8_t _max_event_pipe_type_size [256];
+
+/*
+ * Forward declares of all static functions.
+ */
+
+static bool
+event_pipe_stub_available (void);
+
+static void
+event_pipe_stub_init (void);
+
+static void
+event_pipe_stub_finish_init (void);
+
+static void
+event_pipe_stub_shutdown (void);
+
+static EventPipeSessionID
+event_pipe_stub_enable (
+ const ep_char8_t *output_path,
+ uint32_t circular_buffer_size_in_mb,
+ const EventPipeProviderConfigurationNative *providers,
+ uint32_t providers_len,
+ EventPipeSessionType session_type,
+ EventPipeSerializationFormat format,
+ bool rundown_requested,
+ IpcStream *stream,
+ EventPipeSessionSynchronousCallback sync_callback);
+
+static void
+event_pipe_stub_disable (EventPipeSessionID id);
+
+static bool
+event_pipe_stub_get_next_event (
+ EventPipeSessionID session_id,
+ EventPipeEventInstanceData *instance);
+
+static EventPipeWaitHandle
+event_pipe_stub_get_wait_handle (EventPipeSessionID session_id);
+
+static void
+event_pipe_stub_start_streaming (EventPipeSessionID session_id);
+
+static void
+event_pipe_stub_write_event_2 (
+ EventPipeEvent *ep_event,
+ EventData *event_data,
+ uint32_t event_data_len,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id);
+
+static EventPipeProvider *
+event_pipe_stub_create_provider (
+ const ep_char8_t *provider_name,
+ EventPipeCallback callback_func,
+ EventPipeCallbackDataFree callback_data_free_func,
+ void *callback_data);
+
+static void
+event_pipe_stub_delete_provider (EventPipeProvider *provider);
+
+static EventPipeProvider *
+event_pipe_stub_get_provider (const ep_char8_t *provider_name);
+
+static EventPipeEvent *
+event_pipe_stub_provider_add_event (
+ EventPipeProvider *provider,
+ uint32_t event_id,
+ uint64_t keywords,
+ uint32_t event_version,
+ EventPipeEventLevel level,
+ bool need_stack,
+ const uint8_t *metadata,
+ uint32_t metadata_len);
+
+static bool
+event_pipe_stub_get_session_info (
+ EventPipeSessionID session_id,
+ EventPipeSessionInfo *instance);
+
+static bool
+event_pipe_stub_thread_ctrl_activity_id (
+ EventPipeActivityControlCode activity_control_code,
+ uint8_t *activity_id,
+ uint32_t activity_id_len);
+
+static bool
+event_pipe_stub_write_event_ee_startup_start (void);
+
+
+static MonoComponentEventPipe fn_table = {
+ { MONO_COMPONENT_ITF_VERSION, &event_pipe_stub_available },
+ &event_pipe_stub_init,
+ &event_pipe_stub_finish_init,
+ &event_pipe_stub_shutdown,
+ &event_pipe_stub_enable,
+ &event_pipe_stub_disable,
+ &event_pipe_stub_get_next_event,
+ &event_pipe_stub_get_wait_handle,
+ &event_pipe_stub_start_streaming,
+ &event_pipe_stub_write_event_2,
+ &event_pipe_stub_create_provider,
+ &event_pipe_stub_delete_provider,
+ &event_pipe_stub_get_provider,
+ &event_pipe_stub_provider_add_event,
+ &event_pipe_stub_get_session_info,
+ &event_pipe_stub_thread_ctrl_activity_id,
+ &event_pipe_stub_write_event_ee_startup_start
+};
+
+static bool
+event_pipe_stub_available (void)
+{
+ return false;
+}
+
+static void
+event_pipe_stub_init (void)
+{
+}
+
+static void
+event_pipe_stub_finish_init (void)
+{
+}
+
+static void
+event_pipe_stub_shutdown (void)
+{
+}
+
+static EventPipeSessionID
+event_pipe_stub_enable (
+ const ep_char8_t *output_path,
+ uint32_t circular_buffer_size_in_mb,
+ const EventPipeProviderConfigurationNative *providers,
+ uint32_t providers_len,
+ EventPipeSessionType session_type,
+ EventPipeSerializationFormat format,
+ bool rundown_requested,
+ IpcStream *stream,
+ EventPipeSessionSynchronousCallback sync_callback)
+{
+ return (EventPipeSessionID)&_dummy_session_id;
+}
+
+static void
+event_pipe_stub_disable (EventPipeSessionID id)
+{
+}
+
+static bool
+event_pipe_stub_get_next_event (
+ EventPipeSessionID session_id,
+ EventPipeEventInstanceData *instance)
+{
+ return false;
+}
+
+static EventPipeWaitHandle
+event_pipe_stub_get_wait_handle (EventPipeSessionID session_id)
+{
+ return (EventPipeWaitHandle)NULL;
+}
+
+static void
+event_pipe_stub_start_streaming (EventPipeSessionID session_id)
+{
+}
+
+static void
+event_pipe_stub_write_event_2 (
+ EventPipeEvent *ep_event,
+ EventData *event_data,
+ uint32_t event_data_len,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id)
+{
+}
+
+static EventPipeProvider *
+event_pipe_stub_create_provider (
+ const ep_char8_t *provider_name,
+ EventPipeCallback callback_func,
+ EventPipeCallbackDataFree callback_data_free_func,
+ void *callback_data)
+{
+ return (EventPipeProvider *)_max_event_pipe_type_size;
+}
+
+static void
+event_pipe_stub_delete_provider (EventPipeProvider *provider)
+{
+}
+
+static EventPipeProvider *
+event_pipe_stub_get_provider (const ep_char8_t *provider_name)
+{
+ return NULL;
+}
+
+static EventPipeEvent *
+event_pipe_stub_provider_add_event (
+ EventPipeProvider *provider,
+ uint32_t event_id,
+ uint64_t keywords,
+ uint32_t event_version,
+ EventPipeEventLevel level,
+ bool need_stack,
+ const uint8_t *metadata,
+ uint32_t metadata_len)
+{
+ return (EventPipeEvent *)_max_event_pipe_type_size;
+}
+
+static bool
+event_pipe_stub_get_session_info (
+ EventPipeSessionID session_id,
+ EventPipeSessionInfo *instance)
+{
+ return false;
+}
+
+static bool
+event_pipe_stub_thread_ctrl_activity_id (
+ EventPipeActivityControlCode activity_control_code,
+ uint8_t *activity_id,
+ uint32_t activity_id_len)
+{
+ return false;
+}
+
+static bool
+event_pipe_stub_write_event_ee_startup_start (void)
+{
+ return true;
+}
+
+#ifdef STATIC_COMPONENTS
+MONO_COMPONENT_EXPORT_ENTRYPOINT
+MonoComponentEventPipe *
+mono_component_event_pipe_init (void)
+{
+ return mono_component_event_pipe_stub_init ();
+}
+#endif
+
+MonoComponentEventPipe *
+mono_component_event_pipe_stub_init (void)
+{
+ return &fn_table;
+}
diff --git a/src/mono/mono/component/event_pipe.c b/src/mono/mono/component/event_pipe.c
new file mode 100644
index 00000000000000..74588de587e84b
--- /dev/null
+++ b/src/mono/mono/component/event_pipe.c
@@ -0,0 +1,245 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+struct _EventPipeProviderConfigurationNative {
+ gunichar2 *provider_name;
+ uint64_t keywords;
+ uint32_t logging_level;
+ gunichar2 *filter_data;
+};
+
+struct _EventPipeSessionInfo {
+ int64_t starttime_as_utc_filetime;
+ int64_t start_timestamp;
+ int64_t timestamp_frequency;
+};
+
+struct _EventPipeEventInstanceData {
+ intptr_t provider_id;
+ uint32_t event_id;
+ uint32_t thread_id;
+ int64_t timestamp;
+ uint8_t activity_id [EP_ACTIVITY_ID_SIZE];
+ uint8_t related_activity_id [EP_ACTIVITY_ID_SIZE];
+ const uint8_t *payload;
+ uint32_t payload_len;
+};
+
+/*
+ * Forward declares of all static functions.
+ */
+
+static bool
+event_pipe_available (void);
+
+static EventPipeSessionID
+event_pipe_enable (
+ const ep_char8_t *output_path,
+ uint32_t circular_buffer_size_in_mb,
+ const EventPipeProviderConfigurationNative *providers,
+ uint32_t providers_len,
+ EventPipeSessionType session_type,
+ EventPipeSerializationFormat format,
+ bool rundown_requested,
+ IpcStream *stream,
+ EventPipeSessionSynchronousCallback sync_callback);
+
+static bool
+event_pipe_get_next_event (
+ EventPipeSessionID session_id,
+ EventPipeEventInstanceData *instance);
+
+static bool
+event_pipe_get_session_info (
+ EventPipeSessionID session_id,
+ EventPipeSessionInfo *instance);
+
+static bool
+event_pipe_thread_ctrl_activity_id(
+ EventPipeActivityControlCode activity_control_code,
+ uint8_t *activity_id,
+ uint32_t activity_id_len);
+
+static MonoComponentEventPipe fn_table = {
+ { MONO_COMPONENT_ITF_VERSION, &event_pipe_available },
+ &ep_init,
+ &ep_finish_init,
+ &ep_shutdown,
+ &event_pipe_enable,
+ &ep_disable,
+ &event_pipe_get_next_event,
+ &ep_get_wait_handle,
+ &ep_start_streaming,
+ &ep_write_event_2,
+ &ep_create_provider,
+ &ep_delete_provider,
+ &ep_get_provider,
+ &ep_provider_add_event,
+ &event_pipe_get_session_info,
+ &event_pipe_thread_ctrl_activity_id,
+ &ep_rt_mono_write_event_ee_startup_start
+};
+
+static bool
+event_pipe_available (void)
+{
+ return true;
+}
+
+static EventPipeSessionID
+event_pipe_enable (
+ const ep_char8_t *output_path,
+ uint32_t circular_buffer_size_in_mb,
+ const EventPipeProviderConfigurationNative *providers,
+ uint32_t providers_len,
+ EventPipeSessionType session_type,
+ EventPipeSerializationFormat format,
+ bool rundown_requested,
+ IpcStream *stream,
+ EventPipeSessionSynchronousCallback sync_callback)
+{
+ ERROR_DECL (error);
+ EventPipeSessionID session_id = 0;
+
+ EventPipeProviderConfiguration *config_providers = g_new0 (EventPipeProviderConfiguration, providers_len);
+
+ if (config_providers) {
+ for (int i = 0; i < providers_len; ++i) {
+ ep_provider_config_init (
+ &config_providers[i],
+ providers[i].provider_name ? mono_utf16_to_utf8 (providers[i].provider_name, g_utf16_len (providers[i].provider_name), error) : NULL,
+ providers [i].keywords,
+ (EventPipeEventLevel)providers [i].logging_level,
+ providers[i].filter_data ? mono_utf16_to_utf8 (providers[i].filter_data, g_utf16_len (providers[i].filter_data), error) : NULL);
+ }
+ }
+
+ session_id = ep_enable (
+ output_path,
+ circular_buffer_size_in_mb,
+ config_providers,
+ providers_len,
+ session_type,
+ format,
+ rundown_requested,
+ stream,
+ sync_callback);
+
+ if (config_providers) {
+ for (int i = 0; i < providers_len; ++i) {
+ ep_provider_config_fini (&config_providers[i]);
+ g_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config_providers[i]));
+ g_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config_providers[i]));
+ }
+ }
+
+ return session_id;
+}
+
+static bool
+event_pipe_get_next_event (
+ EventPipeSessionID session_id,
+ EventPipeEventInstanceData *instance)
+{
+ EP_ASSERT (instance != NULL);
+
+ EventPipeEventInstance *const next_instance = ep_get_next_event (session_id);
+ EventPipeEventInstanceData *const data = (EventPipeEventInstanceData *)instance;
+ if (next_instance && data) {
+ const EventPipeEvent *const ep_event = ep_event_instance_get_ep_event (next_instance);
+ if (ep_event) {
+ data->provider_id = (intptr_t)ep_event_get_provider (ep_event);
+ data->event_id = ep_event_get_event_id (ep_event);
+ }
+ data->thread_id = ep_event_instance_get_thread_id (next_instance);
+ data->timestamp = ep_event_instance_get_timestamp (next_instance);
+ memcpy (&data->activity_id, ep_event_instance_get_activity_id_cref (next_instance), EP_ACTIVITY_ID_SIZE);
+ memcpy (&data->related_activity_id, ep_event_instance_get_related_activity_id_cref (next_instance), EP_ACTIVITY_ID_SIZE);
+ data->payload = ep_event_instance_get_data (next_instance);
+ data->payload_len = ep_event_instance_get_data_len (next_instance);
+ }
+
+ return next_instance != NULL;
+}
+
+static bool
+event_pipe_get_session_info (
+ EventPipeSessionID session_id,
+ EventPipeSessionInfo *instance)
+{
+ bool result = false;
+ if (instance) {
+ EventPipeSession *session = ep_get_session ((EventPipeSessionID)session_id);
+ if (session) {
+ instance->starttime_as_utc_filetime = ep_session_get_session_start_time (session);
+ instance->start_timestamp = ep_session_get_session_start_timestamp (session);
+ instance->timestamp_frequency = ep_perf_frequency_query ();
+ result = true;
+ }
+ }
+
+ return result;
+}
+
+static bool
+event_pipe_thread_ctrl_activity_id (
+ EventPipeActivityControlCode activity_control_code,
+ uint8_t *activity_id,
+ uint32_t activity_id_len)
+{
+ bool result = true;
+ ep_rt_thread_activity_id_handle_t activity_id_handle = ep_thread_get_activity_id_handle ();
+
+ if (activity_id_handle == NULL)
+ return false;
+
+ uint8_t current_activity_id [EP_ACTIVITY_ID_SIZE];
+ switch (activity_control_code) {
+ case EP_ACTIVITY_CONTROL_GET_ID:
+ ep_thread_get_activity_id (activity_id_handle, activity_id, EP_ACTIVITY_ID_SIZE);
+ break;
+ case EP_ACTIVITY_CONTROL_SET_ID:
+ ep_thread_set_activity_id (activity_id_handle, activity_id, EP_ACTIVITY_ID_SIZE);
+ break;
+ case EP_ACTIVITY_CONTROL_CREATE_ID:
+ ep_thread_create_activity_id (activity_id, EP_ACTIVITY_ID_SIZE);
+ break;
+ case EP_ACTIVITY_CONTROL_GET_SET_ID:
+ ep_thread_get_activity_id (activity_id_handle, current_activity_id, EP_ACTIVITY_ID_SIZE);
+ ep_thread_set_activity_id (activity_id_handle, activity_id, EP_ACTIVITY_ID_SIZE);
+ memcpy (activity_id, current_activity_id, EP_ACTIVITY_ID_SIZE);
+ break;
+ case EP_ACTIVITY_CONTROL_CREATE_SET_ID:
+ ep_thread_get_activity_id (activity_id_handle, activity_id, EP_ACTIVITY_ID_SIZE);
+ ep_thread_create_activity_id (current_activity_id, EP_ACTIVITY_ID_SIZE);
+ ep_thread_set_activity_id (activity_id_handle, current_activity_id, EP_ACTIVITY_ID_SIZE);
+ break;
+ default:
+ result = false;
+ break;
+ }
+
+ return result;
+}
+
+#ifndef STATIC_COMPONENTS
+MONO_COMPONENT_EXPORT_ENTRYPOINT
+MonoComponentEventPipe *
+mono_component_event_pipe_init (void);
+#endif
+
+MonoComponentEventPipe *
+mono_component_event_pipe_init (void)
+{
+ return &fn_table;
+}
diff --git a/src/mono/mono/component/event_pipe.h b/src/mono/mono/component/event_pipe.h
new file mode 100644
index 00000000000000..76ac80d9f484f1
--- /dev/null
+++ b/src/mono/mono/component/event_pipe.h
@@ -0,0 +1,161 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#ifndef _MONO_COMPONENT_EVENT_PIPE_H
+#define _MONO_COMPONENT_EVENT_PIPE_H
+
+#include
+#include "mono/utils/mono-compiler.h"
+
+#ifndef ENABLE_PERFTRACING
+#define ENABLE_PERFTRACING
+#endif
+
+#include
+#include
+
+typedef enum _EventPipeActivityControlCode {
+ EP_ACTIVITY_CONTROL_GET_ID = 1,
+ EP_ACTIVITY_CONTROL_SET_ID = 2,
+ EP_ACTIVITY_CONTROL_CREATE_ID = 3,
+ EP_ACTIVITY_CONTROL_GET_SET_ID = 4,
+ EP_ACTIVITY_CONTROL_CREATE_SET_ID = 5
+} EventPipeActivityControlCode;
+
+typedef struct _EventPipeProviderConfigurationNative EventPipeProviderConfigurationNative;
+typedef struct _EventPipeEventInstanceData EventPipeEventInstanceData;
+typedef struct _EventPipeSessionInfo EventPipeSessionInfo;
+
+/*
+ * EventPipe.
+ */
+
+typedef void
+(*event_pipe_component_init_func) (void);
+
+typedef void
+(*event_pipe_component_finish_init_func) (void);
+
+typedef void
+(*event_pipe_component_shutdown_func) (void);
+
+typedef EventPipeSessionID
+(*event_pipe_component_enable_func) (
+ const ep_char8_t *output_path,
+ uint32_t circular_buffer_size_in_mb,
+ const EventPipeProviderConfigurationNative *providers,
+ uint32_t providers_len,
+ EventPipeSessionType session_type,
+ EventPipeSerializationFormat format,
+ bool rundown_requested,
+ IpcStream *stream,
+ EventPipeSessionSynchronousCallback sync_callback);
+
+typedef void
+(*event_pipe_component_disable_func) (EventPipeSessionID id);
+
+typedef bool
+(*event_pipe_component_get_next_event_func) (
+ EventPipeSessionID session_id,
+ EventPipeEventInstanceData *instance);
+
+typedef EventPipeWaitHandle
+(*event_pipe_component_get_wait_handle_func) (EventPipeSessionID session_id);
+
+typedef void
+(*event_pipe_component_start_streaming_func) (EventPipeSessionID session_id);
+
+typedef void
+(*event_pipe_component_write_event_2_func) (
+ EventPipeEvent *ep_event,
+ EventData *event_data,
+ uint32_t event_data_len,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id);
+
+/*
+ * EventPipeProvider.
+ */
+
+typedef EventPipeProvider *
+(*event_pipe_component_create_provider_func) (
+ const ep_char8_t *provider_name,
+ EventPipeCallback callback_func,
+ EventPipeCallbackDataFree callback_data_free_func,
+ void *callback_data);
+
+typedef void
+(*event_pipe_component_delete_provider_func) (EventPipeProvider *provider);
+
+typedef EventPipeProvider *
+(*event_pipe_component_get_provider_func) (const ep_char8_t *provider_name);
+
+typedef EventPipeEvent *
+(*event_pipe_component_provider_add_event_func) (
+ EventPipeProvider *provider,
+ uint32_t event_id,
+ uint64_t keywords,
+ uint32_t event_version,
+ EventPipeEventLevel level,
+ bool need_stack,
+ const uint8_t *metadata,
+ uint32_t metadata_len);
+
+/*
+ * EventPipeSession.
+ */
+
+typedef bool
+(*event_pipe_component_get_session_info_func) (
+ EventPipeSessionID session_id,
+ EventPipeSessionInfo *instance);
+
+/*
+ * EventPipeThread.
+ */
+
+typedef bool
+(*event_pipe_component_thread_ctrl_activity_id_func)(
+ EventPipeActivityControlCode activity_control_code,
+ uint8_t *activity_id,
+ uint32_t activity_id_len);
+
+/*
+ * EventPipe Native Events.
+ */
+
+typedef bool
+(*event_pipe_component_write_event_ee_startup_start_func)(void);
+
+/*
+ * MonoComponentEventPipe function table.
+ */
+
+typedef struct _MonoComponentEventPipe {
+ MonoComponent component;
+ event_pipe_component_init_func init;
+ event_pipe_component_finish_init_func finish_init;
+ event_pipe_component_shutdown_func shutdown;
+ event_pipe_component_enable_func enable;
+ event_pipe_component_disable_func disable;
+ event_pipe_component_get_next_event_func get_next_event;
+ event_pipe_component_get_wait_handle_func get_wait_handle;
+ event_pipe_component_start_streaming_func start_streaming;
+ event_pipe_component_write_event_2_func write_event_2;
+ event_pipe_component_create_provider_func create_provider;
+ event_pipe_component_delete_provider_func delete_provider;
+ event_pipe_component_get_provider_func get_provider;
+ event_pipe_component_provider_add_event_func provider_add_event;
+ event_pipe_component_get_session_info_func get_session_info;
+ event_pipe_component_thread_ctrl_activity_id_func thread_ctrl_activity_id;
+ event_pipe_component_write_event_ee_startup_start_func write_event_ee_startup_start;
+} MonoComponentEventPipe;
+
+#ifdef STATIC_COMPONENTS
+MONO_COMPONENT_EXPORT_ENTRYPOINT
+MonoComponentEventPipe *
+mono_component_event_pipe_init (void);
+#endif
+
+#endif /*_MONO_COMPONENT_EVENT_PIPE_H*/
diff --git a/src/mono/mono/component/hot_reload-stub.c b/src/mono/mono/component/hot_reload-stub.c
new file mode 100644
index 00000000000000..7f1fdd20f03c20
--- /dev/null
+++ b/src/mono/mono/component/hot_reload-stub.c
@@ -0,0 +1,50 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#include
+#include
+#include "mono/component/component.h"
+#include "mono/component/hot_reload.h"
+#include "mono/metadata/components.h"
+#include "mono/utils/mono-compiler.h"
+#include "mono/utils/mono-error-internals.h"
+
+static bool
+hot_reload_stub_available (void);
+
+static void
+hot_reload_stub_apply_changes (MonoImage *base_image, gconstpointer dmeta, uint32_t dmeta_len, gconstpointer dil, uint32_t dil_len, MonoError *error);
+
+static MonoComponentHotReload fn_table = {
+ { MONO_COMPONENT_ITF_VERSION, &hot_reload_stub_available },
+ &hot_reload_stub_apply_changes,
+};
+
+#ifdef STATIC_COMPONENTS
+MONO_COMPONENT_EXPORT_ENTRYPOINT
+MonoComponentHotReload *
+mono_component_hot_reload_init (void)
+{
+ return mono_component_hot_reload_stub_init ();
+}
+#endif
+
+MonoComponentHotReload *
+mono_component_hot_reload_stub_init (void)
+{
+ return &fn_table;
+}
+
+bool
+hot_reload_stub_available (void)
+{
+ return false;
+}
+
+void
+hot_reload_stub_apply_changes (MonoImage *base_image, gconstpointer dmeta, uint32_t dmeta_len, gconstpointer dil, uint32_t dil_len, MonoError *error)
+{
+ mono_error_set_not_supported (error, "Hot reload not supported in this runtime.");
+}
+
diff --git a/src/mono/mono/component/hot_reload.c b/src/mono/mono/component/hot_reload.c
new file mode 100644
index 00000000000000..2963eb6648914e
--- /dev/null
+++ b/src/mono/mono/component/hot_reload.c
@@ -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.
+//
+
+#include
+#include
+
+#include
+
+#include
+
+#ifndef STATIC_COMPONENTS
+MONO_COMPONENT_EXPORT_ENTRYPOINT
+MonoComponentHotReload *
+mono_component_hot_reload_init (void);
+#endif
+
+static bool
+hot_reload_available (void);
+
+static void
+hot_reload_apply_changes (MonoImage *base_image, gconstpointer dmeta, uint32_t dmeta_len, gconstpointer dil, uint32_t dil_len, MonoError *error);
+
+static MonoComponentHotReload fn_table = {
+ { MONO_COMPONENT_ITF_VERSION, &hot_reload_available },
+ &hot_reload_apply_changes,
+};
+
+MonoComponentHotReload *
+mono_component_hot_reload_init (void)
+{
+ /* TODO: implement me */
+ return &fn_table;
+}
+
+static bool
+hot_reload_available (void)
+{
+ return true;
+}
+
+static void
+hot_reload_apply_changes (MonoImage *base_image, gconstpointer dmeta, uint32_t dmeta_len, gconstpointer dil, uint32_t dil_len, MonoError *error)
+{
+ /* TODO: implement me */
+}
diff --git a/src/mono/mono/component/hot_reload.h b/src/mono/mono/component/hot_reload.h
new file mode 100644
index 00000000000000..eb56b51006d12a
--- /dev/null
+++ b/src/mono/mono/component/hot_reload.h
@@ -0,0 +1,25 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#ifndef _MONO_COMPONENT_HOT_RELOAD_H
+#define _MONO_COMPONENT_HOT_RELOAD_H
+
+#include
+#include "mono/metadata/object-forward.h"
+#include "mono/utils/mono-error.h"
+#include "mono/utils/mono-compiler.h"
+#include "mono/component/component.h"
+
+typedef struct _MonoComponentHotReload {
+ MonoComponent component;
+ void (*apply_changes) (MonoImage *base_image, gconstpointer dmeta, uint32_t dmeta_len, gconstpointer dil, uint32_t dil_len, MonoError *error);
+} MonoComponentHotReload;
+
+#ifdef STATIC_COMPONENTS
+MONO_COMPONENT_EXPORT_ENTRYPOINT
+MonoComponentHotReload *
+mono_component_hot_reload_init (void);
+#endif
+
+#endif/*_MONO_COMPONENT_HOT_RELOAD_H*/
diff --git a/src/mono/mono/eglib/CMakeLists.txt b/src/mono/mono/eglib/CMakeLists.txt
index 520359c38e1ea8..d8b7d01a1e4bf7 100644
--- a/src/mono/mono/eglib/CMakeLists.txt
+++ b/src/mono/mono/eglib/CMakeLists.txt
@@ -45,3 +45,5 @@ set(eglib_common_sources
unicode-data.h)
addprefix(eglib_sources ../eglib/ "${eglib_platform_sources};${eglib_common_sources}")
+
+add_library(eglib_objects OBJECT "${eglib_sources}")
diff --git a/src/mono/mono/eventpipe/CMakeLists.txt b/src/mono/mono/eventpipe/CMakeLists.txt
index 7dad16975afdc6..f7ee1e3c0bdde2 100644
--- a/src/mono/mono/eventpipe/CMakeLists.txt
+++ b/src/mono/mono/eventpipe/CMakeLists.txt
@@ -1,33 +1,56 @@
if(ENABLE_PERFTRACING)
if (FEATURE_PERFTRACING_PAL_TCP)
- add_definitions(-DFEATURE_PERFTRACING_PAL_TCP)
+ add_definitions(-DENABLE_PERFTRACING_PAL_TCP)
endif (FEATURE_PERFTRACING_PAL_TCP)
+ if (FEATURE_PERFTRACING_DISABLE_LISTEN_PORTS)
+ add_definitions(-DENABLE_PERFTRACING_DISABLE_LISTEN_PORTS)
+ endif (FEATURE_PERFTRACING_DISABLE_LISTEN_PORTS)
+
+ if (FEATURE_PERFTRACING_DISABLE_CONNECT_PORTS)
+ add_definitions(-DENABLE_PERFTRACING_DISABLE_CONNECT_PORTS)
+ endif (FEATURE_PERFTRACING_DISABLE_CONNECT_PORTS)
+
include (${SHARED_EVENTPIPE_SOURCE_PATH}CMakeLists.txt)
set(MONO_EVENTPIPE_SHIM_SOURCES "")
set(MONO_EVENTPIPE_SHIM_HEADERS "")
+ set(MONO_DIAGNOSTIC_SERVER_SHIM_SOURCES "")
+ set(MONO_DIAGNOSTIC_SERVER_SHIM_HEADERS "")
+
list(APPEND MONO_EVENTPIPE_SHIM_SOURCES
- ds-rt-mono.c
ep-rt-mono.c
)
+ list(APPEND MONO_DIAGNOSTIC_SERVER_SHIM_SOURCES
+ ds-rt-mono.c
+ )
+
list(APPEND MONO_EVENTPIPE_SHIM_HEADERS
- ds-rt-mono.h
- ds-rt-types-mono.h
ep-rt-config-mono.h
ep-rt-mono.h
ep-rt-types-mono.h
)
+ list(APPEND MONO_DIAGNOSTIC_SERVER_SHIM_HEADERS
+ ds-rt-mono.h
+ ds-rt-types-mono.h
+ )
+
set(shared_eventpipe_sources_base "")
set(mono_eventpipe_shim_sources_base "")
+ set(shared_diagnostic_server_sources_base "")
+ set(mono_diagnostic_server_shim_sources_base "")
+
list(APPEND shared_eventpipe_sources_base
${SHARED_EVENTPIPE_SOURCES}
${SHARED_EVENTPIPE_HEADERS}
+ )
+
+ list(APPEND shared_diagnostic_server_sources_base
${SHARED_DIAGNOSTIC_SERVER_SOURCES}
${SHARED_DIAGNOSTIC_SERVER_HEADERS}
${SHARED_DIAGNOSTIC_SERVER_PAL_SOURCES}
@@ -39,10 +62,19 @@ if(ENABLE_PERFTRACING)
${MONO_EVENTPIPE_SHIM_HEADERS}
)
+ list(APPEND mono_diagnostic_server_shim_sources_base
+ ${MONO_DIAGNOSTIC_SERVER_SHIM_SOURCES}
+ ${MONO_DIAGNOSTIC_SERVER_SHIM_HEADERS}
+ )
+
addprefix(shared_eventpipe_sources_base ${SHARED_EVENTPIPE_SOURCE_PATH} "${shared_eventpipe_sources_base}")
addprefix(mono_eventpipe_shim_sources_base ${MONO_EVENTPIPE_SHIM_SOURCE_PATH} "${mono_eventpipe_shim_sources_base}")
+ addprefix(shared_diagnostic_server_sources_base ${SHARED_EVENTPIPE_SOURCE_PATH} "${shared_diagnostic_server_sources_base}")
+ addprefix(mono_diagnostic_server_shim_sources_base ${MONO_EVENTPIPE_SHIM_SOURCE_PATH} "${mono_diagnostic_server_shim_sources_base}")
+
set(eventpipe_sources ${shared_eventpipe_sources_base} ${mono_eventpipe_shim_sources_base})
+ set(diagnostic_server_sources ${shared_diagnostic_server_sources_base} ${mono_diagnostic_server_shim_sources_base})
set_source_files_properties(${SHARED_EVENTPIPE_SOURCE_PATH}/ep-sources.c PROPERTIES COMPILE_DEFINITIONS EP_FORCE_INCLUDE_SOURCE_FILES)
set_source_files_properties(${SHARED_EVENTPIPE_SOURCE_PATH}/ds-sources.c PROPERTIES COMPILE_DEFINITIONS DS_FORCE_INCLUDE_SOURCE_FILES)
diff --git a/src/mono/mono/eventpipe/ep-rt-config-mono.h b/src/mono/mono/eventpipe/ep-rt-config-mono.h
index ec3ceb9f4aba01..7b08ff795f3909 100644
--- a/src/mono/mono/eventpipe/ep-rt-config-mono.h
+++ b/src/mono/mono/eventpipe/ep-rt-config-mono.h
@@ -1,7 +1,6 @@
#ifndef __EVENTPIPE_RT_CONFIG_MONO_H__
#define __EVENTPIPE_RT_CONFIG_MONO_H__
-#define EP_RT_MONO_USE_STATIC_RUNTIME
#define EP_THREAD_INCLUDE_ACTIVITY_ID
#endif /* __EVENTPIPE_RT_CONFIG_MONO_H__ */
diff --git a/src/mono/mono/eventpipe/ep-rt-mono.c b/src/mono/mono/eventpipe/ep-rt-mono.c
index 3cc88969dda0f1..7c677639b085a4 100644
--- a/src/mono/mono/eventpipe/ep-rt-mono.c
+++ b/src/mono/mono/eventpipe/ep-rt-mono.c
@@ -6,326 +6,671 @@
#include
#include
#include
-#include
+
#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
+// EventPipe rt init state.
+gboolean _ep_rt_mono_initialized;
+
+// EventPipe TLS key.
+MonoNativeTlsKey _ep_rt_mono_thread_holder_tls_id;
+
+// Random byte provider.
+gpointer _ep_rt_mono_rand_provider;
+
+// EventPipe global config lock.
ep_rt_spin_lock_handle_t _ep_rt_mono_config_lock = {0};
-EventPipeMonoFuncTable _ep_rt_mono_func_table = {0};
+// OS cmd line.
mono_lazy_init_t _ep_rt_mono_os_cmd_line_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
char *_ep_rt_mono_os_cmd_line = NULL;
+// Managed cmd line.
mono_lazy_init_t _ep_rt_mono_managed_cmd_line_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
char *_ep_rt_mono_managed_cmd_line = NULL;
-#ifdef HOST_WIN32
-int64_t
-ep_rt_mono_perf_counter_query (void)
-{
- LARGE_INTEGER value;
- if (QueryPerformanceCounter (&value))
- return (int64_t)value.QuadPart;
- else
- return 0;
-}
+// Sample profiler.
+static GArray * _ep_rt_mono_sampled_thread_callstacks = NULL;
+static uint32_t _ep_rt_mono_max_sampled_thread_count = 32;
-int64_t
-ep_rt_mono_perf_frequency_query (void)
-{
- LARGE_INTEGER value;
- if (QueryPerformanceFrequency (&value))
- return (int64_t)value.QuadPart;
- else
- return 0;
-}
+// Rundown events.
+EventPipeProvider *EventPipeProviderDotNETRuntimeRundown = NULL;
+EventPipeEvent *EventPipeEventMethodDCEndVerbose_V1 = NULL;
+EventPipeEvent *EventPipeEventDCEndInit_V1 = NULL;
+EventPipeEvent *EventPipeEventDCEndComplete_V1 = NULL;
+EventPipeEvent *EventPipeEventMethodDCEndILToNativeMap = NULL;
+EventPipeEvent *EventPipeEventDomainModuleDCEnd_V1 = NULL;
+EventPipeEvent *EventPipeEventModuleDCEnd_V2 = NULL;
+EventPipeEvent *EventPipeEventAssemblyDCEnd_V1 = NULL;
+EventPipeEvent *EventPipeEventAppDomainDCEnd_V1 = NULL;
+EventPipeEvent *EventPipeEventRuntimeInformationDCStart = NULL;
-void
-ep_rt_mono_system_time_get (EventPipeSystemTime *system_time)
-{
- SYSTEMTIME value;
- GetSystemTime (&value);
+// Runtime private events.
+EventPipeProvider *EventPipeProviderDotNETRuntimePrivate = NULL;
+EventPipeEvent *EventPipeEventEEStartupStart_V1 = NULL;
- EP_ASSERT (system_time != NULL);
- ep_system_time_set (
- system_time,
- value.wYear,
- value.wMonth,
- value.wDayOfWeek,
- value.wDay,
- value.wHour,
- value.wMinute,
- value.wSecond,
- value.wMilliseconds);
-}
+// Rundown types.
+typedef
+bool
+(*ep_rt_mono_fire_method_rundown_events_func)(
+ const uint64_t method_id,
+ const uint64_t module_id,
+ const uint64_t method_start_address,
+ const uint32_t method_size,
+ const uint32_t method_token,
+ const uint32_t method_flags,
+ const ep_char8_t *method_namespace,
+ const ep_char8_t *method_name,
+ const ep_char8_t *method_signature,
+ const uint16_t count_of_map_entries,
+ const uint32_t *il_offsets,
+ const uint32_t *native_offsets,
+ void *user_data);
-int64_t
-ep_rt_mono_system_timestamp_get (void)
-{
- FILETIME value;
- GetSystemTimeAsFileTime (&value);
- return (int64_t)((((uint64_t)value.dwHighDateTime) << 32) | (uint64_t)value.dwLowDateTime);
-}
-#else
-#include
-#include
-#include
-#include
+typedef
+bool
+(*ep_rt_mono_fire_assembly_rundown_events_func)(
+ const uint64_t domain_id,
+ const uint64_t assembly_id,
+ const uint32_t assembly_flags,
+ const uint32_t binding_id,
+ const ep_char8_t *assembly_name,
+ const uint64_t module_id,
+ const uint32_t module_flags,
+ const uint32_t reserved_flags,
+ const ep_char8_t *module_il_path,
+ const ep_char8_t *module_native_path,
+ const uint8_t *managed_pdb_signature,
+ const uint32_t managed_pdb_age,
+ const ep_char8_t *managed_pdb_build_path,
+ const uint8_t *native_pdb_signature,
+ const uint32_t native_pdb_age,
+ const ep_char8_t *native_pdb_build_path,
+ void *user_data);
-#if HAVE_SYS_TIME_H
-#include
-#endif // HAVE_SYS_TIME_H
+typedef
+bool
+(*ep_rt_mono_fire_domain_rundown_events_func)(
+ const uint64_t domain_id,
+ const uint32_t domain_flags,
+ const ep_char8_t *domain_name,
+ const uint32_t domain_index,
+ void *user_data);
-#if HAVE_MACH_ABSOLUTE_TIME
-#include
-static mono_lazy_init_t _ep_rt_mono_time_base_info_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
-static mach_timebase_info_data_t _ep_rt_mono_time_base_info = {0};
-#endif
+typedef struct _EventPipeFireMethodEventsData{
+ MonoDomain *domain;
+ uint8_t *buffer;
+ size_t buffer_size;
+ ep_rt_mono_fire_method_rundown_events_func method_events_func;
+} EventPipeFireMethodEventsData;
-#ifdef HAVE_LOCALTIME_R
-#define HAVE_GMTIME_R 1
-#endif
+typedef struct _EventPipeSampleProfileData {
+ EventPipeStackContents stack_contents;
+ uint64_t thread_id;
+ uintptr_t thread_ip;
+ uint32_t payload_data;
+} EventPipeSampleProfileData;
-static const int64_t SECS_BETWEEN_1601_AND_1970_EPOCHS = 11644473600LL;
-static const int64_t SECS_TO_100NS = 10000000;
-static const int64_t SECS_TO_NS = 1000000000;
-static const int64_t MSECS_TO_MIS = 1000;
+// Rundown flags.
+#define RUNTIME_SKU_CORECLR 0x2
+#define METHOD_FLAGS_DYNAMIC_METHOD 0x1
+#define METHOD_FLAGS_GENERIC_METHOD 0x2
+#define METHOD_FLAGS_SHARED_GENERIC_METHOD 0x4
+#define METHOD_FLAGS_JITTED_METHOD 0x8
+#define METHOD_FLAGS_JITTED_HELPER_METHOD 0x10
-/* clock_gettime () is found by configure on Apple builds, but its only present from ios 10, macos 10.12, tvos 10 and watchos 3 */
-#if defined (HAVE_CLOCK_MONOTONIC) && (defined(TARGET_IOS) || defined(TARGET_OSX) || defined(TARGET_WATCHOS) || defined(TARGET_TVOS))
-#undef HAVE_CLOCK_MONOTONIC
-#endif
+#define MODULE_FLAGS_NATIVE_MODULE 0x2
+#define MODULE_FLAGS_DYNAMIC_MODULE 0x4
+#define MODULE_FLAGS_MANIFEST_MODULE 0x8
-#ifndef HAVE_CLOCK_MONOTONIC
-static const int64_t MISECS_TO_NS = 1000;
-#endif
+#define ASSEMBLY_FLAGS_DYNAMIC_ASSEMBLY 0x2
+#define ASSEMBLY_FLAGS_NATIVE_ASSEMBLY 0x4
+#define ASSEMBLY_FLAGS_COLLECTIBLE_ASSEMBLY 0x8
+
+#define DOMAIN_FLAGS_DEFAULT_DOMAIN 0x1
+#define DOMAIN_FLAGS_EXECUTABLE_DOMAIN 0x2
+
+/*
+ * Forward declares of all static functions.
+ */
static
-void
-time_base_info_lazy_init (void);
+bool
+resize_buffer (
+ uint8_t **buffer,
+ size_t *size,
+ size_t current_size,
+ size_t new_size,
+ bool *fixed_buffer);
static
-int64_t
-system_time_to_int64 (
- time_t sec,
- long nsec);
+bool
+write_buffer (
+ const uint8_t *value,
+ size_t value_size,
+ uint8_t **buffer,
+ size_t *offset,
+ size_t *size,
+ bool *fixed_buffer);
-#if HAVE_MACH_ABSOLUTE_TIME
static
-void
-time_base_info_lazy_init (void)
-{
- kern_return_t result = mach_timebase_info (&_ep_rt_mono_time_base_info);
- if (result != KERN_SUCCESS)
- memset (&_ep_rt_mono_time_base_info, 0, sizeof (_ep_rt_mono_time_base_info));
-}
-#endif
+bool
+write_buffer_string_utf8_t (
+ const ep_char8_t *value,
+ uint8_t **buffer,
+ size_t *offset,
+ size_t *size,
+ bool *fixed_buffer);
-int64_t
-ep_rt_mono_perf_counter_query (void)
-{
-#if HAVE_MACH_ABSOLUTE_TIME
- return (int64_t)mach_absolute_time ();
-#elif HAVE_CLOCK_MONOTONIC
- struct timespec ts;
- int result = clock_gettime (CLOCK_MONOTONIC, &ts);
- if (result == 0)
- return ((int64_t)(ts.tv_sec) * (int64_t)(SECS_TO_NS)) + (int64_t)(ts.tv_nsec);
-#else
- #error "ep_rt_mono_perf_counter_get requires either mach_absolute_time () or clock_gettime (CLOCK_MONOTONIC) to be supported."
-#endif
- return 0;
-}
+static
+bool
+write_runtime_info_dc_start (
+ const uint16_t clr_instance_id,
+ const uint16_t sku_id,
+ const uint16_t bcl_major_version,
+ const uint16_t bcl_minor_version,
+ const uint16_t bcl_build_number,
+ const uint16_t bcl_qfe_number,
+ const uint16_t vm_major_version,
+ const uint16_t vm_minor_version,
+ const uint16_t vm_build_number,
+ const uint16_t vm_qfe_number,
+ const uint32_t startup_flags,
+ const uint8_t startup_mode,
+ const ep_char8_t *cmd_line,
+ const uint8_t * object_guid,
+ const ep_char8_t *runtime_dll_path,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id);
-int64_t
-ep_rt_mono_perf_frequency_query (void)
-{
-#if HAVE_MACH_ABSOLUTE_TIME
- // (numer / denom) gives you the nanoseconds per tick, so the below code
- // computes the number of ticks per second. We explicitly do the multiplication
- // first in order to help minimize the error that is produced by integer division.
- mono_lazy_initialize (&_ep_rt_mono_time_base_info_init, time_base_info_lazy_init);
- if (_ep_rt_mono_time_base_info.denom == 0 || _ep_rt_mono_time_base_info.numer == 0)
- return 0;
- return ((int64_t)(SECS_TO_NS) * (int64_t)(_ep_rt_mono_time_base_info.denom)) / (int64_t)(_ep_rt_mono_time_base_info.numer);
-#elif HAVE_CLOCK_MONOTONIC
- // clock_gettime () returns a result in terms of nanoseconds rather than a count. This
- // means that we need to either always scale the result by the actual resolution (to
- // get a count) or we need to say the resolution is in terms of nanoseconds. We prefer
- // the latter since it allows the highest throughput and should minimize error propagated
- // to the user.
- return (int64_t)(SECS_TO_NS);
-#else
- #error "ep_rt_mono_perf_frequency_query requires either mach_absolute_time () or clock_gettime (CLOCK_MONOTONIC) to be supported."
-#endif
- return 0;
-}
+static
+bool
+write_runtime_info_dc_start (
+ const uint16_t clr_instance_id,
+ const uint16_t sku_id,
+ const uint16_t bcl_major_version,
+ const uint16_t bcl_minor_version,
+ const uint16_t bcl_build_number,
+ const uint16_t bcl_qfe_number,
+ const uint16_t vm_major_version,
+ const uint16_t vm_minor_version,
+ const uint16_t vm_build_number,
+ const uint16_t vm_qfe_number,
+ const uint32_t startup_flags,
+ const uint8_t startup_mode,
+ const ep_char8_t *cmd_line,
+ const uint8_t * object_guid,
+ const ep_char8_t *runtime_dll_path,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id);
-void
-ep_rt_mono_system_time_get (EventPipeSystemTime *system_time)
-{
- time_t tt;
-#if HAVE_GMTIME_R
- struct tm ut;
-#endif /* HAVE_GMTIME_R */
- struct tm *ut_ptr;
- struct timeval time_val;
- int timeofday_retval;
+static
+bool
+write_event_dc_end_complete_v1 (
+ const uint16_t clr_instance_id,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id);
- EP_ASSERT (system_time != NULL);
+static
+bool
+write_event_method_dc_end_il_to_native_map (
+ const uint64_t method_id,
+ const uint64_t rejit_id,
+ const uint8_t method_extent,
+ const uint16_t count_of_map_entries,
+ const uint32_t *il_offsets,
+ const uint32_t *native_offsets,
+ const uint16_t clr_instance_id,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id);
- tt = time (NULL);
+static
+bool
+write_event_method_dc_end_verbose_v1 (
+ const uint64_t method_id,
+ const uint64_t module_id,
+ const uint64_t method_start_address,
+ const uint32_t method_size,
+ const uint32_t method_token,
+ const uint32_t method_flags,
+ const ep_char8_t *method_namespace,
+ const ep_char8_t *method_name,
+ const ep_char8_t *method_signature,
+ const uint16_t clr_instance_id,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id);
- /* We can't get millisecond resolution from time (), so we get it from gettimeofday () */
- timeofday_retval = gettimeofday (&time_val, NULL);
+static
+bool
+write_event_module_dc_end_v2 (
+ const uint64_t module_id,
+ const uint64_t assembly_id,
+ const uint32_t module_flags,
+ const uint32_t reserved_1,
+ const ep_char8_t *module_il_path,
+ const ep_char8_t *module_native_path,
+ const uint16_t clr_instance_id,
+ const uint8_t *managed_pdb_signature,
+ const uint32_t managed_pdb_age,
+ const ep_char8_t *managed_pdb_build_path,
+ const uint8_t *native_pdb_signature,
+ const uint32_t native_pdb_age,
+ const ep_char8_t *native_pdb_build_path,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id);
-#if HAVE_GMTIME_R
- ut_ptr = &ut;
- if (gmtime_r (&tt, ut_ptr) == NULL)
-#else /* HAVE_GMTIME_R */
- if ((ut_ptr = gmtime (&tt)) == NULL)
-#endif /* HAVE_GMTIME_R */
- g_assert_not_reached ();
+static
+bool
+write_event_module_dc_end_v2 (
+ const uint64_t module_id,
+ const uint64_t assembly_id,
+ const uint32_t module_flags,
+ const uint32_t reserved_1,
+ const ep_char8_t *module_il_path,
+ const ep_char8_t *module_native_path,
+ const uint16_t clr_instance_id,
+ const uint8_t *managed_pdb_signature,
+ const uint32_t managed_pdb_age,
+ const ep_char8_t *managed_pdb_build_path,
+ const uint8_t *native_pdb_signature,
+ const uint32_t native_pdb_age,
+ const ep_char8_t *native_pdb_build_path,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id);
- uint16_t milliseconds = 0;
- if (timeofday_retval != -1) {
- int old_seconds;
- int new_seconds;
+static
+bool
+write_event_assembly_dc_end_v1 (
+ const uint64_t assembly_id,
+ const uint64_t domain_id,
+ const uint64_t binding_id,
+ const uint32_t assembly_flags,
+ const ep_char8_t *fully_qualified_name,
+ const uint16_t clr_instance_id,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id);
- milliseconds = time_val.tv_usec / MSECS_TO_MIS;
+static
+bool
+write_event_domain_dc_end_v1 (
+ const uint64_t domain_id,
+ const uint32_t domain_flags,
+ const ep_char8_t *domain_name,
+ const uint32_t domain_index,
+ const uint16_t clr_instance_id,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id);
- old_seconds = ut_ptr->tm_sec;
- new_seconds = time_val.tv_sec % 60;
+static
+bool
+fire_method_rundown_events_func (
+ const uint64_t method_id,
+ const uint64_t module_id,
+ const uint64_t method_start_address,
+ const uint32_t method_size,
+ const uint32_t method_token,
+ const uint32_t method_flags,
+ const ep_char8_t *method_namespace,
+ const ep_char8_t *method_name,
+ const ep_char8_t *method_signature,
+ const uint16_t count_of_map_entries,
+ const uint32_t *il_offsets,
+ const uint32_t *native_offsets,
+ void *user_data);
- /* just in case we reached the next second in the interval between time () and gettimeofday () */
- if (old_seconds != new_seconds)
- milliseconds = 999;
- }
+static
+bool
+fire_assembly_rundown_events_func (
+ const uint64_t domain_id,
+ const uint64_t assembly_id,
+ const uint32_t assembly_flags,
+ const uint32_t binding_id,
+ const ep_char8_t *assembly_name,
+ const uint64_t module_id,
+ const uint32_t module_flags,
+ const uint32_t reserved_flags,
+ const ep_char8_t *module_il_path,
+ const ep_char8_t *module_native_path,
+ const uint8_t *managed_pdb_signature,
+ const uint32_t managed_pdb_age,
+ const ep_char8_t *managed_pdb_build_path,
+ const uint8_t *native_pdb_signature,
+ const uint32_t native_pdb_age,
+ const ep_char8_t *native_pdb_build_path,
+ void *user_data);
- ep_system_time_set (
- system_time,
- 1900 + ut_ptr->tm_year,
- ut_ptr->tm_mon + 1,
- ut_ptr->tm_wday,
- ut_ptr->tm_mday,
- ut_ptr->tm_hour,
- ut_ptr->tm_min,
- ut_ptr->tm_sec,
- milliseconds);
-}
+static
+bool
+fire_domain_rundown_events_func (
+ const uint64_t domain_id,
+ const uint32_t domain_flags,
+ const ep_char8_t *domain_name,
+ const uint32_t domain_index,
+ void *user_data);
static
-inline
+void
+init_dotnet_runtime_rundown (void);
+
+static
+bool
+write_event_ee_startup_start_v1 (
+ const uint16_t clr_instance_id,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id);
+
+static
+void
+init_dotnet_runtime_private (void);
+
+static
+void
+eventpipe_fire_method_events (
+ MonoJitInfo *ji,
+ MonoMethod *method,
+ EventPipeFireMethodEventsData *events_data);
+
+static
+void
+eventpipe_fire_method_events_func (
+ MonoJitInfo *ji,
+ void *user_data);
+
+static
+void
+eventpipe_fire_assembly_events (
+ MonoDomain *domain,
+ MonoAssembly *assembly,
+ ep_rt_mono_fire_assembly_rundown_events_func assembly_events_func);
+
+static
+gboolean
+eventpipe_execute_rundown (
+ ep_rt_mono_fire_domain_rundown_events_func domain_events_func,
+ ep_rt_mono_fire_assembly_rundown_events_func assembly_events_func,
+ ep_rt_mono_fire_method_rundown_events_func methods_events_func);
+
+static
+gboolean
+eventpipe_walk_managed_stack_for_thread_func (
+ MonoStackFrameInfo *frame,
+ MonoContext *ctx,
+ void *data);
+
+static
+gboolean
+eventpipe_sample_profiler_walk_managed_stack_for_thread_func (
+ MonoStackFrameInfo *frame,
+ MonoContext *ctx,
+ void *data);
+
+static
+void
+profiler_eventpipe_thread_exited (
+ MonoProfiler *prof,
+ uintptr_t tid);
+
+/*
+ * Forward declares of all private functions (accessed using extern in ep-rt-mono.h).
+ */
+
+void
+ep_rt_mono_init (void);
+
+void
+ep_rt_mono_fini (void);
+
+bool
+ep_rt_mono_rand_try_get_bytes (
+ uint8_t *buffer,
+ size_t buffer_size);
+
+EventPipeThread *
+ep_rt_mono_thread_get_or_create (void);
+
+void *
+ep_rt_mono_thread_attach (bool background_thread);
+
+void
+ep_rt_mono_thread_detach (void);
+
+void
+ep_rt_mono_thread_exited (void);
+
int64_t
-system_time_to_int64 (
- time_t sec,
- long nsec)
+ep_rt_mono_perf_counter_query (void);
+
+int64_t
+ep_rt_mono_perf_frequency_query (void);
+
+void
+ep_rt_mono_system_time_get (EventPipeSystemTime *system_time);
+
+int64_t
+ep_rt_mono_system_timestamp_get (void);
+
+void
+ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array);
+
+void
+ep_rt_mono_init_providers_and_events (void);
+
+void
+ep_rt_mono_fini_providers_and_events (void);
+
+bool
+ep_rt_mono_sample_profiler_write_sampling_event_for_threads (
+ ep_rt_thread_handle_t sampling_thread,
+ EventPipeEvent *sampling_event);
+
+bool
+ep_rt_mono_walk_managed_stack_for_thread (
+ ep_rt_thread_handle_t thread,
+ EventPipeStackContents *stack_contents);
+
+bool
+ep_rt_mono_method_get_simple_assembly_name (
+ ep_rt_method_desc_t *method,
+ ep_char8_t *name,
+ size_t name_len);
+
+bool
+ep_rt_mono_method_get_full_name (
+ ep_rt_method_desc_t *method,
+ ep_char8_t *name,
+ size_t name_len);
+
+void
+ep_rt_mono_execute_rundown (void);
+
+static
+inline
+uint16_t
+clr_instance_get_id (void)
{
- return ((int64_t)sec + SECS_BETWEEN_1601_AND_1970_EPOCHS) * SECS_TO_100NS + (nsec / 100);
+ // Mono runtime id.
+ return 9;
}
-int64_t
-ep_rt_mono_system_timestamp_get (void)
+static
+bool
+resize_buffer (
+ uint8_t **buffer,
+ size_t *size,
+ size_t current_size,
+ size_t new_size,
+ bool *fixed_buffer)
{
-#if HAVE_CLOCK_MONOTONIC
- struct timespec time;
- if (clock_gettime (CLOCK_REALTIME, &time) == 0)
- return system_time_to_int64 (time.tv_sec, time.tv_nsec);
-#else
- struct timeval time;
- if (gettimeofday (&time, NULL) == 0)
- return system_time_to_int64 (time.tv_sec, time.tv_usec * MISECS_TO_NS);
-#endif
- else
- return system_time_to_int64 (0, 0);
+ EP_ASSERT (buffer != NULL);
+ EP_ASSERT (size != NULL);
+ EP_ASSERT (fixed_buffer != NULL);
+
+ new_size = (size_t)(new_size * 1.5);
+ if (new_size < *size) {
+ EP_ASSERT (!"Overflow");
+ return false;
+ }
+
+ if (new_size < 32)
+ new_size = 32;
+
+ uint8_t *new_buffer;
+ new_buffer = ep_rt_byte_array_alloc (new_size);
+ ep_raise_error_if_nok (new_buffer != NULL);
+
+ memcpy (new_buffer, *buffer, current_size);
+
+ if (!*fixed_buffer)
+ ep_rt_byte_array_free (*buffer);
+
+ *buffer = new_buffer;
+ *size = new_size;
+ *fixed_buffer = false;
+
+ return true;
+
+ep_on_error:
+ return false;
}
-#endif
-#ifndef HOST_WIN32
-#if defined(__APPLE__)
-#if defined (TARGET_OSX)
-G_BEGIN_DECLS
-gchar ***_NSGetEnviron(void);
-G_END_DECLS
-#define environ (*_NSGetEnviron())
-#else
-static char *_ep_rt_mono_environ[1] = { NULL };
-#define environ _ep_rt_mono_environ
-#endif /* defined (TARGET_OSX) */
-#else
-G_BEGIN_DECLS
-extern char **environ;
-G_END_DECLS
-#endif /* defined (__APPLE__) */
-#endif /* !defined (HOST_WIN32) */
+static
+bool
+write_buffer (
+ const uint8_t *value,
+ size_t value_size,
+ uint8_t **buffer,
+ size_t *offset,
+ size_t *size,
+ bool *fixed_buffer)
+{
+ EP_ASSERT (value != NULL);
+ EP_ASSERT (buffer != NULL);
+ EP_ASSERT (offset != NULL);
+ EP_ASSERT (size != NULL);
+ EP_ASSERT (fixed_buffer != NULL);
-void
-ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array)
+ if ((value_size + *offset) > *size)
+ ep_raise_error_if_nok (resize_buffer (buffer, size, *offset, *size + value_size, fixed_buffer));
+
+ memcpy (*buffer + *offset, value, value_size);
+ *offset += value_size;
+
+ return true;
+
+ep_on_error:
+ return false;
+}
+
+static
+bool
+write_buffer_string_utf8_t (
+ const ep_char8_t *value,
+ uint8_t **buffer,
+ size_t *offset,
+ size_t *size,
+ bool *fixed_buffer)
{
- EP_ASSERT (env_array != NULL);
-#ifdef HOST_WIN32
- LPWSTR envs = GetEnvironmentStringsW ();
- if (envs) {
- LPWSTR next = envs;
- while (*next) {
- ep_rt_env_array_utf16_append (env_array, ep_rt_utf16_string_dup (next));
- next += ep_rt_utf16_string_len (next) + 1;
- }
- FreeEnvironmentStringsW (envs);
+ if (!value)
+ return true;
+
+ GFixedBufferCustomAllocatorData custom_alloc_data;
+ custom_alloc_data.buffer = *buffer + *offset;
+ custom_alloc_data.buffer_size = *size - *offset;
+ custom_alloc_data.req_buffer_size = 0;
+
+ if (!g_utf8_to_utf16_custom_alloc (value, -1, NULL, NULL, g_fixed_buffer_custom_allocator, &custom_alloc_data, NULL)) {
+ ep_raise_error_if_nok (resize_buffer (buffer, size, *offset, *size + custom_alloc_data.req_buffer_size, fixed_buffer));
+ custom_alloc_data.buffer = *buffer + *offset;
+ custom_alloc_data.buffer_size = *size - *offset;
+ custom_alloc_data.req_buffer_size = 0;
+ ep_raise_error_if_nok (g_utf8_to_utf16_custom_alloc (value, -1, NULL, NULL, g_fixed_buffer_custom_allocator, &custom_alloc_data, NULL) != NULL);
}
-#else
- gchar **next = NULL;
- for (next = environ; *next != NULL; ++next)
- ep_rt_env_array_utf16_append (env_array, ep_rt_utf8_to_utf16_string (*next, -1));
-#endif
-}
-// Rundown flags.
-#define RUNTIME_SKU_CORECLR 0x2
+ *offset += custom_alloc_data.req_buffer_size;
+ return true;
-// Rundown events.
-EventPipeProvider *EventPipeProviderDotNETRuntimeRundown = NULL;
-EventPipeEvent *EventPipeEventMethodDCEndVerbose_V1 = NULL;
-EventPipeEvent *EventPipeEventDCEndInit_V1 = NULL;
-EventPipeEvent *EventPipeEventDCEndComplete_V1 = NULL;
-EventPipeEvent *EventPipeEventMethodDCEndILToNativeMap = NULL;
-EventPipeEvent *EventPipeEventDomainModuleDCEnd_V1 = NULL;
-EventPipeEvent *EventPipeEventModuleDCEnd_V2 = NULL;
-EventPipeEvent *EventPipeEventAssemblyDCEnd_V1 = NULL;
-EventPipeEvent *EventPipeEventAppDomainDCEnd_V1 = NULL;
-EventPipeEvent *EventPipeEventRuntimeInformationDCStart = NULL;
+ep_on_error:
+ return false;
+}
+
+static
+inline
+bool
+write_buffer_guid_t (
+ const uint8_t *value,
+ uint8_t **buffer,
+ size_t *offset,
+ size_t *size,
+ bool *fixed_buffer)
+{
+ return write_buffer (value, EP_GUID_SIZE, buffer, offset, size, fixed_buffer);
+}
-/*
- * Forward declares of all static rundown functions.
- */
+static
+inline
+bool
+write_buffer_uint8_t (
+ const uint8_t *value,
+ uint8_t **buffer,
+ size_t *offset,
+ size_t *size,
+ bool *fixed_buffer)
+{
+ return write_buffer (value, sizeof (uint8_t), buffer, offset, size, fixed_buffer);
+}
static
+inline
bool
-resize_buffer (
+write_buffer_uint16_t (
+ const uint16_t *value,
uint8_t **buffer,
+ size_t *offset,
size_t *size,
- size_t current_size,
- size_t new_size,
- bool *fixed_buffer);
+ bool *fixed_buffer)
+{
+ return write_buffer ((const uint8_t *)value, sizeof (uint16_t), buffer, offset, size, fixed_buffer);
+}
static
+inline
bool
-write_buffer (
- const uint8_t *value,
- size_t value_size,
+write_buffer_uint32_t (
+ const uint32_t *value,
uint8_t **buffer,
size_t *offset,
size_t *size,
- bool *fixed_buffer);
+ bool *fixed_buffer)
+{
+ return write_buffer ((const uint8_t *)value, sizeof (uint32_t), buffer, offset, size, fixed_buffer);
+}
static
+inline
bool
-write_buffer_string_utf8_t (
- const ep_char8_t *value,
+write_buffer_uint64_t (
+ const uint64_t *value,
uint8_t **buffer,
size_t *offset,
size_t *size,
- bool *fixed_buffer);
+ bool *fixed_buffer)
+{
+ return write_buffer ((const uint8_t *)value, sizeof (uint64_t), buffer, offset, size, fixed_buffer);
+}
static
bool
@@ -346,35 +691,119 @@ write_runtime_info_dc_start (
const uint8_t * object_guid,
const ep_char8_t *runtime_dll_path,
const uint8_t *activity_id,
- const uint8_t *related_activity_id);
+ const uint8_t *related_activity_id)
+{
+ EP_ASSERT (EventPipeEventRuntimeInformationDCStart != NULL);
+
+ if (!ep_event_is_enabled (EventPipeEventRuntimeInformationDCStart))
+ return true;
+
+ uint8_t stack_buffer [153];
+ uint8_t *buffer = stack_buffer;
+ size_t offset = 0;
+ size_t size = sizeof (stack_buffer);
+ bool fixed_buffer = true;
+ bool success = true;
+
+ success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&sku_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&bcl_major_version, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&bcl_minor_version, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&bcl_build_number, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&bcl_qfe_number, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&vm_major_version, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&vm_minor_version, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&vm_build_number, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&vm_qfe_number, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint32_t (&startup_flags, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint8_t (&startup_mode, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_string_utf8_t (cmd_line, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_guid_t (object_guid, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_string_utf8_t (runtime_dll_path, &buffer, &offset, &size, &fixed_buffer);
+
+ ep_raise_error_if_nok (success);
+
+ ep_write_event (EventPipeEventRuntimeInformationDCStart, buffer, (uint32_t)offset, activity_id, related_activity_id);
+
+ep_on_exit:
+ if (!fixed_buffer)
+ ep_rt_byte_array_free (buffer);
+ return success;
+
+ep_on_error:
+ EP_ASSERT (!success);
+ ep_exit_error_handler ();
+}
static
bool
-write_runtime_info_dc_start (
+write_event_dc_end_init_v1 (
const uint16_t clr_instance_id,
- const uint16_t sku_id,
- const uint16_t bcl_major_version,
- const uint16_t bcl_minor_version,
- const uint16_t bcl_build_number,
- const uint16_t bcl_qfe_number,
- const uint16_t vm_major_version,
- const uint16_t vm_minor_version,
- const uint16_t vm_build_number,
- const uint16_t vm_qfe_number,
- const uint32_t startup_flags,
- const uint8_t startup_mode,
- const ep_char8_t *cmd_line,
- const uint8_t * object_guid,
- const ep_char8_t *runtime_dll_path,
const uint8_t *activity_id,
- const uint8_t *related_activity_id);
+ const uint8_t *related_activity_id)
+{
+ EP_ASSERT (EventPipeEventDCEndInit_V1 != NULL);
+
+ if (!ep_event_is_enabled (EventPipeEventDCEndInit_V1))
+ return true;
+
+ uint8_t stack_buffer [32];
+ uint8_t *buffer = stack_buffer;
+ size_t offset = 0;
+ size_t size = sizeof (stack_buffer);
+ bool fixed_buffer = true;
+ bool success = true;
+
+ success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
+
+ ep_raise_error_if_nok (success);
+
+ ep_write_event (EventPipeEventDCEndInit_V1, buffer, (uint32_t)offset, activity_id, related_activity_id);
+
+ep_on_exit:
+ if (!fixed_buffer)
+ ep_rt_byte_array_free (buffer);
+ return success;
+
+ep_on_error:
+ EP_ASSERT (!success);
+ ep_exit_error_handler ();
+}
static
bool
write_event_dc_end_complete_v1 (
const uint16_t clr_instance_id,
const uint8_t *activity_id,
- const uint8_t *related_activity_id);
+ const uint8_t *related_activity_id)
+{
+ EP_ASSERT (EventPipeEventDCEndComplete_V1 != NULL);
+
+ if (!ep_event_is_enabled (EventPipeEventDCEndComplete_V1))
+ return true;
+
+ uint8_t stack_buffer [32];
+ uint8_t *buffer = stack_buffer;
+ size_t offset = 0;
+ size_t size = sizeof (stack_buffer);
+ bool fixed_buffer = true;
+ bool success = true;
+
+ success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
+
+ ep_raise_error_if_nok (success);
+
+ ep_write_event (EventPipeEventDCEndComplete_V1, buffer, (uint32_t)offset, activity_id, related_activity_id);
+
+ep_on_exit:
+ if (!fixed_buffer)
+ ep_rt_byte_array_free (buffer);
+ return success;
+
+ep_on_error:
+ EP_ASSERT (!success);
+ ep_exit_error_handler ();
+}
static
bool
@@ -387,88 +816,45 @@ write_event_method_dc_end_il_to_native_map (
const uint32_t *native_offsets,
const uint16_t clr_instance_id,
const uint8_t *activity_id,
- const uint8_t *related_activity_id);
+ const uint8_t *related_activity_id)
+{
+ EP_ASSERT (EventPipeEventMethodDCEndILToNativeMap != NULL);
-static
-bool
-write_event_method_dc_end_verbose_v1 (
- const uint64_t method_id,
- const uint64_t module_id,
- const uint64_t method_start_address,
- const uint32_t method_size,
- const uint32_t method_token,
- const uint32_t method_flags,
- const ep_char8_t *method_namespace,
- const ep_char8_t *method_name,
- const ep_char8_t *method_signature,
- const uint16_t clr_instance_id,
- const uint8_t *activity_id,
- const uint8_t *related_activity_id);
+ if (!ep_event_is_enabled (EventPipeEventMethodDCEndILToNativeMap))
+ return true;
-static
-bool
-write_event_module_dc_end_v2 (
- const uint64_t module_id,
- const uint64_t assembly_id,
- const uint32_t module_flags,
- const uint32_t reserved_1,
- const ep_char8_t *module_il_path,
- const ep_char8_t *module_native_path,
- const uint16_t clr_instance_id,
- const uint8_t *managed_pdb_signature,
- const uint32_t managed_pdb_age,
- const ep_char8_t *managed_pdb_build_path,
- const uint8_t *native_pdb_signature,
- const uint32_t native_pdb_age,
- const ep_char8_t *native_pdb_build_path,
- const uint8_t *activity_id,
- const uint8_t *related_activity_id);
+ uint8_t stack_buffer [32];
+ uint8_t *buffer = stack_buffer;
+ size_t offset = 0;
+ size_t size = sizeof (stack_buffer);
+ bool fixed_buffer = true;
+ bool success = true;
-static
-bool
-write_event_module_dc_end_v2 (
- const uint64_t module_id,
- const uint64_t assembly_id,
- const uint32_t module_flags,
- const uint32_t reserved_1,
- const ep_char8_t *module_il_path,
- const ep_char8_t *module_native_path,
- const uint16_t clr_instance_id,
- const uint8_t *managed_pdb_signature,
- const uint32_t managed_pdb_age,
- const ep_char8_t *managed_pdb_build_path,
- const uint8_t *native_pdb_signature,
- const uint32_t native_pdb_age,
- const ep_char8_t *native_pdb_build_path,
- const uint8_t *activity_id,
- const uint8_t *related_activity_id);
+ success &= write_buffer_uint64_t (&method_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint64_t (&rejit_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint8_t (&method_extent, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&count_of_map_entries, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer ((const uint8_t *)il_offsets, sizeof (const uint32_t) * (int32_t)count_of_map_entries, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer ((const uint8_t *)native_offsets, sizeof (const uint32_t) * (int32_t)count_of_map_entries, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
-static
-bool
-write_event_assembly_dc_end_v1 (
- const uint64_t assembly_id,
- const uint64_t domain_id,
- const uint64_t binding_id,
- const uint32_t assembly_flags,
- const ep_char8_t *fully_qualified_name,
- const uint16_t clr_instance_id,
- const uint8_t *activity_id,
- const uint8_t *related_activity_id);
+ ep_raise_error_if_nok (success);
-static
-bool
-write_event_domain_dc_end_v1 (
- const uint64_t domain_id,
- const uint32_t domain_flags,
- const ep_char8_t *domain_name,
- const uint32_t domain_index,
- const uint16_t clr_instance_id,
- const uint8_t *activity_id,
- const uint8_t *related_activity_id);
+ ep_write_event (EventPipeEventMethodDCEndILToNativeMap, buffer, (uint32_t)offset, activity_id, related_activity_id);
+
+ep_on_exit:
+ if (!fixed_buffer)
+ ep_rt_byte_array_free (buffer);
+ return success;
+
+ep_on_error:
+ EP_ASSERT (!success);
+ ep_exit_error_handler ();
+}
static
bool
-fire_method_rundown_events_func (
+write_event_method_dc_end_verbose_v1 (
const uint64_t method_id,
const uint64_t module_id,
const uint64_t method_start_address,
@@ -478,272 +864,232 @@ fire_method_rundown_events_func (
const ep_char8_t *method_namespace,
const ep_char8_t *method_name,
const ep_char8_t *method_signature,
- const uint16_t count_of_map_entries,
- const uint32_t *il_offsets,
- const uint32_t *native_offsets,
- void *user_data);
+ const uint16_t clr_instance_id,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id)
+{
+ EP_ASSERT (EventPipeEventMethodDCEndVerbose_V1 != NULL);
+
+ if (!ep_event_is_enabled (EventPipeEventMethodDCEndVerbose_V1))
+ return true;
+
+ uint8_t stack_buffer [230];
+ uint8_t *buffer = stack_buffer;
+ size_t offset = 0;
+ size_t size = sizeof (stack_buffer);
+ bool fixed_buffer = true;
+ bool success = true;
+
+ success &= write_buffer_uint64_t (&method_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint64_t (&module_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint64_t (&method_start_address, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint32_t (&method_size, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint32_t (&method_token, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint32_t (&method_flags, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_string_utf8_t (method_namespace, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_string_utf8_t (method_name, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_string_utf8_t (method_signature, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
+
+ ep_raise_error_if_nok (success);
+
+ ep_write_event (EventPipeEventMethodDCEndVerbose_V1, buffer, (uint32_t)offset, activity_id, related_activity_id);
+
+ep_on_exit:
+ if (!fixed_buffer)
+ ep_rt_byte_array_free (buffer);
+ return success;
+
+ep_on_error:
+ EP_ASSERT (!success);
+ ep_exit_error_handler ();
+}
static
bool
-fire_assembly_rundown_events_func (
- const uint64_t domain_id,
- const uint64_t assembly_id,
- const uint32_t assembly_flags,
- const uint32_t binding_id,
- const ep_char8_t *assembly_name,
+write_event_module_dc_end_v2 (
const uint64_t module_id,
+ const uint64_t assembly_id,
const uint32_t module_flags,
- const uint32_t reserved_flags,
+ const uint32_t reserved_1,
const ep_char8_t *module_il_path,
const ep_char8_t *module_native_path,
+ const uint16_t clr_instance_id,
const uint8_t *managed_pdb_signature,
const uint32_t managed_pdb_age,
const ep_char8_t *managed_pdb_build_path,
const uint8_t *native_pdb_signature,
const uint32_t native_pdb_age,
const ep_char8_t *native_pdb_build_path,
- void *user_data);
-
-static
-bool
-fire_domain_rundown_events_func (
- const uint64_t domain_id,
- const uint32_t domain_flags,
- const ep_char8_t *domain_name,
- const uint32_t domain_index,
- void *user_data);
-
-static
-void
-init_dotnet_runtime_rundown (void);
-
-static
-inline
-uint16_t
-clr_instance_get_id (void)
-{
- // Mono runtime id.
- return 9;
-}
-
-static
-bool
-resize_buffer (
- uint8_t **buffer,
- size_t *size,
- size_t current_size,
- size_t new_size,
- bool *fixed_buffer)
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id)
{
- EP_ASSERT (buffer != NULL);
- EP_ASSERT (size != NULL);
- EP_ASSERT (fixed_buffer != NULL);
-
- new_size = (size_t)(new_size * 1.5);
- if (new_size < *size) {
- EP_ASSERT (!"Overflow");
- return false;
- }
+ EP_ASSERT (EventPipeEventModuleDCEnd_V2 != NULL);
- if (new_size < 32)
- new_size = 32;
+ if (!ep_event_is_enabled (EventPipeEventModuleDCEnd_V2))
+ return true;
- uint8_t *new_buffer;
- new_buffer = ep_rt_byte_array_alloc (new_size);
- ep_raise_error_if_nok (new_buffer != NULL);
+ uint8_t stack_buffer [290];
+ uint8_t *buffer = stack_buffer;
+ size_t offset = 0;
+ size_t size = sizeof (stack_buffer);
+ bool fixed_buffer = true;
+ bool success = true;
- memcpy (new_buffer, *buffer, current_size);
+ success &= write_buffer_uint64_t (&module_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint64_t (&assembly_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint32_t (&module_flags, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint32_t (&reserved_1, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_string_utf8_t (module_il_path, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_string_utf8_t (module_native_path, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_guid_t (managed_pdb_signature, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint32_t (&managed_pdb_age, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_string_utf8_t (managed_pdb_build_path, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_guid_t (native_pdb_signature, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint32_t (&native_pdb_age, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_string_utf8_t (native_pdb_build_path, &buffer, &offset, &size, &fixed_buffer);
- if (!*fixed_buffer)
- ep_rt_byte_array_free (*buffer);
+ ep_raise_error_if_nok (success);
- *buffer = new_buffer;
- *size = new_size;
- *fixed_buffer = false;
+ ep_write_event (EventPipeEventModuleDCEnd_V2, buffer, (uint32_t)offset, activity_id, related_activity_id);
- return true;
+ep_on_exit:
+ if (!fixed_buffer)
+ ep_rt_byte_array_free (buffer);
+ return success;
ep_on_error:
- return false;
+ EP_ASSERT (!success);
+ ep_exit_error_handler ();
}
static
bool
-write_buffer (
- const uint8_t *value,
- size_t value_size,
- uint8_t **buffer,
- size_t *offset,
- size_t *size,
- bool *fixed_buffer)
+write_event_domain_module_dc_end_v1 (
+ const uint64_t module_id,
+ const uint64_t assembly_id,
+ const uint64_t domain_id,
+ const uint32_t module_flags,
+ const uint32_t reserved_1,
+ const ep_char8_t *module_il_path,
+ const ep_char8_t *module_native_path,
+ const uint16_t clr_instance_id,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id)
{
- EP_ASSERT (value != NULL);
- EP_ASSERT (buffer != NULL);
- EP_ASSERT (offset != NULL);
- EP_ASSERT (size != NULL);
- EP_ASSERT (fixed_buffer != NULL);
-
- if ((value_size + *offset) > *size)
- ep_raise_error_if_nok (resize_buffer (buffer, size, *offset, *size + value_size, fixed_buffer));
-
- memcpy (*buffer + *offset, value, value_size);
- *offset += value_size;
-
- return true;
-
-ep_on_error:
- return false;
-}
+ EP_ASSERT (EventPipeEventDomainModuleDCEnd_V1 != NULL);
-static
-bool
-write_buffer_string_utf8_t (
- const ep_char8_t *value,
- uint8_t **buffer,
- size_t *offset,
- size_t *size,
- bool *fixed_buffer)
-{
- if (!value)
+ if (!ep_event_is_enabled (EventPipeEventDomainModuleDCEnd_V1))
return true;
- GFixedBufferCustomAllocatorData custom_alloc_data;
- custom_alloc_data.buffer = *buffer + *offset;
- custom_alloc_data.buffer_size = *size - *offset;
- custom_alloc_data.req_buffer_size = 0;
-
- if (!g_utf8_to_utf16_custom_alloc (value, -1, NULL, NULL, g_fixed_buffer_custom_allocator, &custom_alloc_data, NULL)) {
- ep_raise_error_if_nok (resize_buffer (buffer, size, *offset, *size + custom_alloc_data.req_buffer_size, fixed_buffer));
- custom_alloc_data.buffer = *buffer + *offset;
- custom_alloc_data.buffer_size = *size - *offset;
- custom_alloc_data.req_buffer_size = 0;
- ep_raise_error_if_nok (g_utf8_to_utf16_custom_alloc (value, -1, NULL, NULL, g_fixed_buffer_custom_allocator, &custom_alloc_data, NULL) != NULL);
- }
+ uint8_t stack_buffer [162];
+ uint8_t *buffer = stack_buffer;
+ size_t offset = 0;
+ size_t size = sizeof (stack_buffer);
+ bool fixed_buffer = true;
+ bool success = true;
- *offset += custom_alloc_data.req_buffer_size;
- return true;
+ success &= write_buffer_uint64_t (&module_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint64_t (&assembly_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint64_t (&domain_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint32_t (&module_flags, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint32_t (&reserved_1, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_string_utf8_t (module_il_path, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_string_utf8_t (module_native_path, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
-ep_on_error:
- return false;
-}
+ ep_raise_error_if_nok (success);
-static
-inline
-bool
-write_buffer_guid_t (
- const uint8_t *value,
- uint8_t **buffer,
- size_t *offset,
- size_t *size,
- bool *fixed_buffer)
-{
- return write_buffer (value, EP_GUID_SIZE, buffer, offset, size, fixed_buffer);
-}
+ ep_write_event (EventPipeEventDomainModuleDCEnd_V1, buffer, (uint32_t)offset, activity_id, related_activity_id);
-static
-inline
-bool
-write_buffer_uint8_t (
- const uint8_t *value,
- uint8_t **buffer,
- size_t *offset,
- size_t *size,
- bool *fixed_buffer)
-{
- return write_buffer (value, sizeof (uint8_t), buffer, offset, size, fixed_buffer);
-}
+ep_on_exit:
+ if (!fixed_buffer)
+ ep_rt_byte_array_free (buffer);
+ return success;
-static
-inline
-bool
-write_buffer_uint16_t (
- const uint16_t *value,
- uint8_t **buffer,
- size_t *offset,
- size_t *size,
- bool *fixed_buffer)
-{
- return write_buffer ((const uint8_t *)value, sizeof (uint16_t), buffer, offset, size, fixed_buffer);
+ep_on_error:
+ EP_ASSERT (!success);
+ ep_exit_error_handler ();
}
static
-inline
bool
-write_buffer_uint32_t (
- const uint32_t *value,
- uint8_t **buffer,
- size_t *offset,
- size_t *size,
- bool *fixed_buffer)
+write_event_assembly_dc_end_v1 (
+ const uint64_t assembly_id,
+ const uint64_t domain_id,
+ const uint64_t binding_id,
+ const uint32_t assembly_flags,
+ const ep_char8_t *fully_qualified_name,
+ const uint16_t clr_instance_id,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id)
{
- return write_buffer ((const uint8_t *)value, sizeof (uint32_t), buffer, offset, size, fixed_buffer);
-}
+ EP_ASSERT (EventPipeEventAssemblyDCEnd_V1 != NULL);
-static
-inline
-bool
-write_buffer_uint64_t (
- const uint64_t *value,
- uint8_t **buffer,
- size_t *offset,
- size_t *size,
- bool *fixed_buffer)
-{
- return write_buffer ((const uint8_t *)value, sizeof (uint64_t), buffer, offset, size, fixed_buffer);
+ if (!ep_event_is_enabled (EventPipeEventAssemblyDCEnd_V1))
+ return true;
+
+ uint8_t stack_buffer [94];
+ uint8_t *buffer = stack_buffer;
+ size_t offset = 0;
+ size_t size = sizeof (stack_buffer);
+ bool fixed_buffer = true;
+ bool success = true;
+
+ success &= write_buffer_uint64_t (&assembly_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint64_t (&domain_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint64_t (&binding_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint32_t (&assembly_flags, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_string_utf8_t (fully_qualified_name, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
+
+ ep_raise_error_if_nok (success);
+
+ ep_write_event (EventPipeEventAssemblyDCEnd_V1, buffer, (uint32_t)offset, activity_id, related_activity_id);
+
+ep_on_exit:
+ if (!fixed_buffer)
+ ep_rt_byte_array_free (buffer);
+ return success;
+
+ep_on_error:
+ EP_ASSERT (!success);
+ ep_exit_error_handler ();
}
static
bool
-write_runtime_info_dc_start (
+write_event_domain_dc_end_v1 (
+ const uint64_t domain_id,
+ const uint32_t domain_flags,
+ const ep_char8_t *domain_name,
+ const uint32_t domain_index,
const uint16_t clr_instance_id,
- const uint16_t sku_id,
- const uint16_t bcl_major_version,
- const uint16_t bcl_minor_version,
- const uint16_t bcl_build_number,
- const uint16_t bcl_qfe_number,
- const uint16_t vm_major_version,
- const uint16_t vm_minor_version,
- const uint16_t vm_build_number,
- const uint16_t vm_qfe_number,
- const uint32_t startup_flags,
- const uint8_t startup_mode,
- const ep_char8_t *cmd_line,
- const uint8_t * object_guid,
- const ep_char8_t *runtime_dll_path,
const uint8_t *activity_id,
const uint8_t *related_activity_id)
{
- EP_ASSERT (EventPipeEventRuntimeInformationDCStart != NULL);
+ EP_ASSERT (EventPipeEventAppDomainDCEnd_V1 != NULL);
- if (!ep_event_is_enabled (EventPipeEventRuntimeInformationDCStart))
+ if (!ep_event_is_enabled (EventPipeEventAppDomainDCEnd_V1))
return true;
- uint8_t stack_buffer [153];
+ uint8_t stack_buffer [82];
uint8_t *buffer = stack_buffer;
size_t offset = 0;
size_t size = sizeof (stack_buffer);
bool fixed_buffer = true;
bool success = true;
+ success &= write_buffer_uint64_t (&domain_id, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint32_t (&domain_flags, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_string_utf8_t (domain_name, &buffer, &offset, &size, &fixed_buffer);
+ success &= write_buffer_uint32_t (&domain_index, &buffer, &offset, &size, &fixed_buffer);
success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&sku_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&bcl_major_version, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&bcl_minor_version, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&bcl_build_number, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&bcl_qfe_number, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&vm_major_version, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&vm_minor_version, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&vm_build_number, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&vm_qfe_number, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint32_t (&startup_flags, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint8_t (&startup_mode, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_string_utf8_t (cmd_line, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_guid_t (object_guid, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_string_utf8_t (runtime_dll_path, &buffer, &offset, &size, &fixed_buffer);
ep_raise_error_if_nok (success);
- ep_write_event (EventPipeEventRuntimeInformationDCStart, buffer, (uint32_t)offset, activity_id, related_activity_id);
+ ep_write_event (EventPipeEventAppDomainDCEnd_V1, buffer, (uint32_t)offset, activity_id, related_activity_id);
ep_on_exit:
if (!fixed_buffer)
@@ -757,14 +1103,14 @@ write_runtime_info_dc_start (
static
bool
-write_event_dc_end_init_v1 (
+write_event_ee_startup_start_v1 (
const uint16_t clr_instance_id,
const uint8_t *activity_id,
const uint8_t *related_activity_id)
{
- EP_ASSERT (EventPipeEventDCEndInit_V1 != NULL);
+ EP_ASSERT (EventPipeEventEEStartupStart_V1 != NULL);
- if (!ep_event_is_enabled (EventPipeEventDCEndInit_V1))
+ if (!ep_event_is_enabled (EventPipeEventEEStartupStart_V1))
return true;
uint8_t stack_buffer [32];
@@ -778,7 +1124,7 @@ write_event_dc_end_init_v1 (
ep_raise_error_if_nok (success);
- ep_write_event (EventPipeEventDCEndInit_V1, buffer, (uint32_t)offset, activity_id, related_activity_id);
+ ep_write_event (EventPipeEventEEStartupStart_V1, buffer, (uint32_t)offset, activity_id, related_activity_id);
ep_on_exit:
if (!fixed_buffer)
@@ -790,503 +1136,848 @@ write_event_dc_end_init_v1 (
ep_exit_error_handler ();
}
+// Mapping FireEtw* CoreClr functions.
+#define FireEtwRuntimeInformationDCStart(...) write_runtime_info_dc_start(__VA_ARGS__,NULL,NULL)
+#define FireEtwDCEndInit_V1(...) write_event_dc_end_init_v1(__VA_ARGS__,NULL,NULL)
+#define FireEtwMethodDCEndILToNativeMap(...) write_event_method_dc_end_il_to_native_map(__VA_ARGS__,NULL,NULL)
+#define FireEtwMethodDCEndVerbose_V1(...) write_event_method_dc_end_verbose_v1(__VA_ARGS__,NULL,NULL)
+#define FireEtwModuleDCEnd_V2(...) write_event_module_dc_end_v2(__VA_ARGS__,NULL,NULL)
+#define FireEtwDomainModuleDCEnd_V1(...) write_event_domain_module_dc_end_v1(__VA_ARGS__,NULL,NULL)
+#define FireEtwAssemblyDCEnd_V1(...) write_event_assembly_dc_end_v1(__VA_ARGS__,NULL,NULL)
+#define FireEtwAppDomainDCEnd_V1(...) write_event_domain_dc_end_v1(__VA_ARGS__,NULL,NULL)
+#define FireEtwDCEndComplete_V1(...) write_event_dc_end_complete_v1(__VA_ARGS__,NULL,NULL)
+#define FireEtwEEStartupStart_V1(...) write_event_ee_startup_start_v1(__VA_ARGS__,NULL,NULL)
+
+static
+bool
+fire_method_rundown_events_func (
+ const uint64_t method_id,
+ const uint64_t module_id,
+ const uint64_t method_start_address,
+ const uint32_t method_size,
+ const uint32_t method_token,
+ const uint32_t method_flags,
+ const ep_char8_t *method_namespace,
+ const ep_char8_t *method_name,
+ const ep_char8_t *method_signature,
+ const uint16_t count_of_map_entries,
+ const uint32_t *il_offsets,
+ const uint32_t *native_offsets,
+ void *user_data)
+{
+ FireEtwMethodDCEndILToNativeMap (
+ method_id,
+ 0,
+ 0,
+ count_of_map_entries,
+ il_offsets,
+ native_offsets,
+ clr_instance_get_id ());
+
+ FireEtwMethodDCEndVerbose_V1 (
+ method_id,
+ module_id,
+ method_start_address,
+ method_size,
+ method_token,
+ method_flags,
+ method_namespace,
+ method_name,
+ method_signature,
+ clr_instance_get_id ());
+
+ return true;
+}
+
+static
+bool
+fire_assembly_rundown_events_func (
+ const uint64_t domain_id,
+ const uint64_t assembly_id,
+ const uint32_t assembly_flags,
+ const uint32_t binding_id,
+ const ep_char8_t *assembly_name,
+ const uint64_t module_id,
+ const uint32_t module_flags,
+ const uint32_t reserved_flags,
+ const ep_char8_t *module_il_path,
+ const ep_char8_t *module_native_path,
+ const uint8_t *managed_pdb_signature,
+ const uint32_t managed_pdb_age,
+ const ep_char8_t *managed_pdb_build_path,
+ const uint8_t *native_pdb_signature,
+ const uint32_t native_pdb_age,
+ const ep_char8_t *native_pdb_build_path,
+ void *user_data)
+{
+ FireEtwModuleDCEnd_V2 (
+ module_id,
+ assembly_id,
+ module_flags,
+ reserved_flags,
+ module_il_path,
+ module_native_path,
+ clr_instance_get_id (),
+ managed_pdb_signature,
+ managed_pdb_age,
+ managed_pdb_build_path,
+ native_pdb_signature,
+ native_pdb_age,
+ native_pdb_build_path);
+
+ FireEtwDomainModuleDCEnd_V1 (
+ module_id,
+ assembly_id,
+ domain_id,
+ module_flags,
+ reserved_flags,
+ module_il_path,
+ module_native_path,
+ clr_instance_get_id ());
+
+ FireEtwAssemblyDCEnd_V1 (
+ assembly_id,
+ domain_id,
+ binding_id,
+ assembly_flags,
+ assembly_name,
+ clr_instance_get_id ());
+
+ return true;
+}
+
+static
+bool
+fire_domain_rundown_events_func (
+ const uint64_t domain_id,
+ const uint32_t domain_flags,
+ const ep_char8_t *domain_name,
+ const uint32_t domain_index,
+ void *user_data)
+{
+ return FireEtwAppDomainDCEnd_V1 (
+ domain_id,
+ domain_flags,
+ domain_name,
+ domain_index,
+ clr_instance_get_id ());
+}
+
static
-bool
-write_event_dc_end_complete_v1 (
- const uint16_t clr_instance_id,
- const uint8_t *activity_id,
- const uint8_t *related_activity_id)
+void
+init_dotnet_runtime_rundown (void)
{
- EP_ASSERT (EventPipeEventDCEndComplete_V1 != NULL);
+ //TODO: Add callback method to enable/disable more native events getting into EventPipe (when enabled).
+ EP_ASSERT (EventPipeProviderDotNETRuntimeRundown == NULL);
+ EventPipeProviderDotNETRuntimeRundown = ep_create_provider (ep_config_get_rundown_provider_name_utf8 (), NULL, NULL, NULL);
- if (!ep_event_is_enabled (EventPipeEventDCEndComplete_V1))
- return true;
+ EP_ASSERT (EventPipeEventMethodDCEndVerbose_V1 == NULL);
+ EventPipeEventMethodDCEndVerbose_V1 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 144, 48, 1, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
- uint8_t stack_buffer [32];
- uint8_t *buffer = stack_buffer;
- size_t offset = 0;
- size_t size = sizeof (stack_buffer);
- bool fixed_buffer = true;
- bool success = true;
+ EP_ASSERT (EventPipeEventDCEndComplete_V1 == NULL);
+ EventPipeEventDCEndComplete_V1 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 146, 131128, 1, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
- success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
+ EP_ASSERT (EventPipeEventDCEndInit_V1 == NULL);
+ EventPipeEventDCEndInit_V1 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 148, 131128, 1, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
- ep_raise_error_if_nok (success);
+ EP_ASSERT (EventPipeEventMethodDCEndILToNativeMap == NULL);
+ EventPipeEventMethodDCEndILToNativeMap = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 150, 131072, 0, EP_EVENT_LEVEL_VERBOSE, true, NULL, 0);
- ep_write_event (EventPipeEventDCEndComplete_V1, buffer, (uint32_t)offset, activity_id, related_activity_id);
+ EP_ASSERT (EventPipeEventDomainModuleDCEnd_V1 == NULL);
+ EventPipeEventDomainModuleDCEnd_V1 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 152, 8, 1, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
-ep_on_exit:
- if (!fixed_buffer)
- ep_rt_byte_array_free (buffer);
- return success;
+ EP_ASSERT (EventPipeEventModuleDCEnd_V2 == NULL);
+ EventPipeEventModuleDCEnd_V2 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 154, 536870920, 2, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
-ep_on_error:
- EP_ASSERT (!success);
- ep_exit_error_handler ();
+ EP_ASSERT (EventPipeEventAssemblyDCEnd_V1 == NULL);
+ EventPipeEventAssemblyDCEnd_V1 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 156, 8, 1, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
+
+ EP_ASSERT (EventPipeEventAppDomainDCEnd_V1 == NULL);
+ EventPipeEventAppDomainDCEnd_V1 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 158, 8, 1, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
+
+ EP_ASSERT (EventPipeEventRuntimeInformationDCStart == NULL);
+ EventPipeEventRuntimeInformationDCStart = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 187, 0, 0, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
}
static
-bool
-write_event_method_dc_end_il_to_native_map (
- const uint64_t method_id,
- const uint64_t rejit_id,
- const uint8_t method_extent,
- const uint16_t count_of_map_entries,
- const uint32_t *il_offsets,
- const uint32_t *native_offsets,
- const uint16_t clr_instance_id,
- const uint8_t *activity_id,
- const uint8_t *related_activity_id)
+void
+init_dotnet_runtime_private (void)
{
- EP_ASSERT (EventPipeEventMethodDCEndILToNativeMap != NULL);
-
- if (!ep_event_is_enabled (EventPipeEventMethodDCEndILToNativeMap))
- return true;
-
- uint8_t stack_buffer [32];
- uint8_t *buffer = stack_buffer;
- size_t offset = 0;
- size_t size = sizeof (stack_buffer);
- bool fixed_buffer = true;
- bool success = true;
-
- success &= write_buffer_uint64_t (&method_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint64_t (&rejit_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint8_t (&method_extent, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&count_of_map_entries, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer ((const uint8_t *)il_offsets, sizeof (const uint32_t) * (int32_t)count_of_map_entries, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer ((const uint8_t *)native_offsets, sizeof (const uint32_t) * (int32_t)count_of_map_entries, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
-
- ep_raise_error_if_nok (success);
-
- ep_write_event (EventPipeEventMethodDCEndILToNativeMap, buffer, (uint32_t)offset, activity_id, related_activity_id);
-
-ep_on_exit:
- if (!fixed_buffer)
- ep_rt_byte_array_free (buffer);
- return success;
+ //TODO: Add callback method to enable/disable more native events getting into EventPipe (when enabled).
+ EP_ASSERT (EventPipeProviderDotNETRuntimePrivate == NULL);
+ EventPipeProviderDotNETRuntimePrivate = ep_create_provider (ep_config_get_private_provider_name_utf8 (), NULL, NULL, NULL);
-ep_on_error:
- EP_ASSERT (!success);
- ep_exit_error_handler ();
+ EP_ASSERT (EventPipeEventEEStartupStart_V1 == NULL);
+ EventPipeEventEEStartupStart_V1 = ep_provider_add_event (EventPipeProviderDotNETRuntimePrivate, 80, 2147483648, 1, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
}
static
-bool
-write_event_method_dc_end_verbose_v1 (
- const uint64_t method_id,
- const uint64_t module_id,
- const uint64_t method_start_address,
- const uint32_t method_size,
- const uint32_t method_token,
- const uint32_t method_flags,
- const ep_char8_t *method_namespace,
- const ep_char8_t *method_name,
- const ep_char8_t *method_signature,
- const uint16_t clr_instance_id,
- const uint8_t *activity_id,
- const uint8_t *related_activity_id)
+void
+eventpipe_fire_method_events (
+ MonoJitInfo *ji,
+ MonoMethod *method,
+ EventPipeFireMethodEventsData *events_data)
{
- EP_ASSERT (EventPipeEventMethodDCEndVerbose_V1 != NULL);
+ EP_ASSERT (ji != NULL);
+ EP_ASSERT (events_data->domain != NULL);
+ EP_ASSERT (events_data->method_events_func != NULL);
+
+ uint64_t method_id = 0;
+ uint64_t module_id = 0;
+ uint64_t method_code_start = (uint64_t)ji->code_start;
+ uint32_t method_code_size = (uint32_t)ji->code_size;
+ uint32_t method_token = 0;
+ uint32_t method_flags = 0;
+ uint8_t kind = MONO_CLASS_DEF;
+ char *method_namespace = NULL;
+ const char *method_name = NULL;
+ char *method_signature = NULL;
+
+ //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc.
+
+ if (method) {
+ method_id = (uint64_t)method;
+ method_token = method->token;
+
+ if (mono_jit_info_get_generic_sharing_context (ji))
+ method_flags |= METHOD_FLAGS_SHARED_GENERIC_METHOD;
+
+ if (method->dynamic)
+ method_flags |= METHOD_FLAGS_DYNAMIC_METHOD;
+
+ if (!ji->from_aot && !ji->from_llvm) {
+ method_flags |= METHOD_FLAGS_JITTED_METHOD;
+ if (method->wrapper_type != MONO_WRAPPER_NONE)
+ method_flags |= METHOD_FLAGS_JITTED_HELPER_METHOD;
+ }
- if (!ep_event_is_enabled (EventPipeEventMethodDCEndVerbose_V1))
- return true;
+ if (method->is_generic || method->is_inflated)
+ method_flags |= METHOD_FLAGS_GENERIC_METHOD;
- uint8_t stack_buffer [230];
- uint8_t *buffer = stack_buffer;
- size_t offset = 0;
- size_t size = sizeof (stack_buffer);
- bool fixed_buffer = true;
- bool success = true;
+ method_name = method->name;
+ method_signature = mono_signature_full_name (method->signature);
- success &= write_buffer_uint64_t (&method_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint64_t (&module_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint64_t (&method_start_address, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint32_t (&method_size, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint32_t (&method_token, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint32_t (&method_flags, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_string_utf8_t (method_namespace, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_string_utf8_t (method_name, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_string_utf8_t (method_signature, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
+ if (method->klass) {
+ module_id = (uint64_t)m_class_get_image (method->klass);
+ kind = m_class_get_class_kind (method->klass);
+ if (kind == MONO_CLASS_GTD || kind == MONO_CLASS_GINST)
+ method_flags |= METHOD_FLAGS_GENERIC_METHOD;
+ method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL);
+ }
+ }
- ep_raise_error_if_nok (success);
+ uint16_t offset_entries = 0;
+ uint32_t *il_offsets = NULL;
+ uint32_t *native_offsets = NULL;
+
+ MonoDebugMethodJitInfo *debug_info = method ? mono_debug_find_method (method, events_data->domain) : NULL;
+ if (debug_info) {
+ offset_entries = debug_info->num_line_numbers;
+ size_t needed_size = (offset_entries * sizeof (uint32_t) * 2);
+ if (!events_data->buffer || needed_size > events_data->buffer_size) {
+ g_free (events_data->buffer);
+ events_data->buffer_size = (size_t)(needed_size * 1.5);
+ events_data->buffer = g_new (uint8_t, events_data->buffer_size);
+ }
- ep_write_event (EventPipeEventMethodDCEndVerbose_V1, buffer, (uint32_t)offset, activity_id, related_activity_id);
+ if (events_data->buffer) {
+ il_offsets = (uint32_t*)events_data->buffer;
+ native_offsets = il_offsets + offset_entries;
-ep_on_exit:
- if (!fixed_buffer)
- ep_rt_byte_array_free (buffer);
- return success;
+ for (int offset_count = 0; offset_count < offset_entries; ++offset_count) {
+ il_offsets [offset_count] = debug_info->line_numbers [offset_count].il_offset;
+ native_offsets [offset_count] = debug_info->line_numbers [offset_count].native_offset;
+ }
+ }
-ep_on_error:
- EP_ASSERT (!success);
- ep_exit_error_handler ();
+ mono_debug_free_method_jit_info (debug_info);
+ }
+
+ if (events_data->buffer && !il_offsets && !native_offsets) {
+ // No IL offset -> Native offset mapping available. Put all code on IL offset 0.
+ EP_ASSERT (events_data->buffer_size >= sizeof (uint32_t) * 2);
+ offset_entries = 1;
+ il_offsets = (uint32_t*)events_data->buffer;
+ native_offsets = il_offsets + offset_entries;
+ il_offsets [0] = 0;
+ native_offsets [0] = (uint32_t)ji->code_size;
+ }
+
+ events_data->method_events_func (
+ method_id,
+ module_id,
+ method_code_start,
+ method_code_size,
+ method_token,
+ method_flags,
+ (ep_char8_t *)method_namespace,
+ (ep_char8_t *)method_name,
+ (ep_char8_t *)method_signature,
+ offset_entries,
+ il_offsets,
+ native_offsets,
+ NULL);
+
+ g_free (method_namespace);
+ g_free (method_signature);
}
static
-bool
-write_event_module_dc_end_v2 (
- const uint64_t module_id,
- const uint64_t assembly_id,
- const uint32_t module_flags,
- const uint32_t reserved_1,
- const ep_char8_t *module_il_path,
- const ep_char8_t *module_native_path,
- const uint16_t clr_instance_id,
- const uint8_t *managed_pdb_signature,
- const uint32_t managed_pdb_age,
- const ep_char8_t *managed_pdb_build_path,
- const uint8_t *native_pdb_signature,
- const uint32_t native_pdb_age,
- const ep_char8_t *native_pdb_build_path,
- const uint8_t *activity_id,
- const uint8_t *related_activity_id)
+void
+eventpipe_fire_method_events_func (
+ MonoJitInfo *ji,
+ void *user_data)
{
- EP_ASSERT (EventPipeEventModuleDCEnd_V2 != NULL);
+ EventPipeFireMethodEventsData *events_data = (EventPipeFireMethodEventsData *)user_data;
+ EP_ASSERT (events_data != NULL);
- if (!ep_event_is_enabled (EventPipeEventModuleDCEnd_V2))
- return true;
-
- uint8_t stack_buffer [290];
- uint8_t *buffer = stack_buffer;
- size_t offset = 0;
- size_t size = sizeof (stack_buffer);
- bool fixed_buffer = true;
- bool success = true;
+ if (ji && !ji->is_trampoline && !ji->async) {
+ MonoMethod *method = jinfo_get_method (ji);
+ if (method && !m_method_is_wrapper (method))
+ eventpipe_fire_method_events (ji, method, events_data);
+ }
+}
- success &= write_buffer_uint64_t (&module_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint64_t (&assembly_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint32_t (&module_flags, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint32_t (&reserved_1, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_string_utf8_t (module_il_path, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_string_utf8_t (module_native_path, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_guid_t (managed_pdb_signature, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint32_t (&managed_pdb_age, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_string_utf8_t (managed_pdb_build_path, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_guid_t (native_pdb_signature, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint32_t (&native_pdb_age, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_string_utf8_t (native_pdb_build_path, &buffer, &offset, &size, &fixed_buffer);
+static
+void
+eventpipe_fire_assembly_events (
+ MonoDomain *domain,
+ MonoAssembly *assembly,
+ ep_rt_mono_fire_assembly_rundown_events_func assembly_events_func)
+{
+ EP_ASSERT (domain != NULL);
+ EP_ASSERT (assembly != NULL);
+ EP_ASSERT (assembly_events_func != NULL);
+
+ uint64_t domain_id = (uint64_t)domain;
+ uint64_t module_id = (uint64_t)assembly->image;
+ uint64_t assembly_id = (uint64_t)assembly;
+
+ // TODO: Extract all module IL/Native paths and pdb metadata when available.
+ const char *module_il_path = "";
+ const char *module_il_pdb_path = "";
+ const char *module_native_path = "";
+ const char *module_native_pdb_path = "";
+ uint8_t signature [EP_GUID_SIZE] = { 0 };
+ uint32_t module_il_pdb_age = 0;
+ uint32_t module_native_pdb_age = 0;
+
+ uint32_t reserved_flags = 0;
+ uint64_t binding_id = 0;
+
+ // Native methods are part of JIT table and already emitted.
+ // TODO: FireEtwMethodDCEndVerbose_V1_or_V2 for all native methods in module as well?
+
+ // Netcore has a 1:1 between assemblies and modules, so its always a manifest module.
+ uint32_t module_flags = MODULE_FLAGS_MANIFEST_MODULE;
+ if (assembly->image) {
+ if (assembly->image->dynamic)
+ module_flags |= MODULE_FLAGS_DYNAMIC_MODULE;
+ if (assembly->image->aot_module)
+ module_flags |= MODULE_FLAGS_NATIVE_MODULE;
+
+ module_il_path = assembly->image->filename ? assembly->image->filename : "";
+ }
- ep_raise_error_if_nok (success);
+ uint32_t assembly_flags = 0;
+ if (assembly->dynamic)
+ assembly_flags |= ASSEMBLY_FLAGS_DYNAMIC_ASSEMBLY;
- ep_write_event (EventPipeEventModuleDCEnd_V2, buffer, (uint32_t)offset, activity_id, related_activity_id);
+ if (assembly->image && assembly->image->aot_module) {
+ assembly_flags |= ASSEMBLY_FLAGS_NATIVE_ASSEMBLY;
+ }
-ep_on_exit:
- if (!fixed_buffer)
- ep_rt_byte_array_free (buffer);
- return success;
+ char *assembly_name = mono_stringify_assembly_name (&assembly->aname);
-ep_on_error:
- EP_ASSERT (!success);
- ep_exit_error_handler ();
+ assembly_events_func (
+ domain_id,
+ assembly_id,
+ assembly_flags,
+ binding_id,
+ (const ep_char8_t*)assembly_name,
+ module_id,
+ module_flags,
+ reserved_flags,
+ (const ep_char8_t *)module_il_path,
+ (const ep_char8_t *)module_native_path,
+ signature,
+ module_il_pdb_age,
+ (const ep_char8_t *)module_il_pdb_path,
+ signature,
+ module_native_pdb_age,
+ (const ep_char8_t *)module_native_pdb_path,
+ NULL);
+
+ g_free (assembly_name);
}
static
-bool
-write_event_domain_module_dc_end_v1 (
- const uint64_t module_id,
- const uint64_t assembly_id,
- const uint64_t domain_id,
- const uint32_t module_flags,
- const uint32_t reserved_1,
- const ep_char8_t *module_il_path,
- const ep_char8_t *module_native_path,
- const uint16_t clr_instance_id,
- const uint8_t *activity_id,
- const uint8_t *related_activity_id)
+gboolean
+eventpipe_execute_rundown (
+ ep_rt_mono_fire_domain_rundown_events_func domain_events_func,
+ ep_rt_mono_fire_assembly_rundown_events_func assembly_events_func,
+ ep_rt_mono_fire_method_rundown_events_func method_events_func)
{
- EP_ASSERT (EventPipeEventDomainModuleDCEnd_V1 != NULL);
+ EP_ASSERT (domain_events_func != NULL);
+ EP_ASSERT (assembly_events_func != NULL);
+ EP_ASSERT (method_events_func != NULL);
+
+ // Under netcore we only have root domain.
+ MonoDomain *root_domain = mono_get_root_domain ();
+ if (root_domain) {
+ uint64_t domain_id = (uint64_t)root_domain;
+
+ // Iterate all functions in use (both JIT and AOT).
+ EventPipeFireMethodEventsData events_data;
+ events_data.domain = root_domain;
+ events_data.buffer_size = 1024 * sizeof(uint32_t);
+ events_data.buffer = g_new (uint8_t, events_data.buffer_size);
+ events_data.method_events_func = method_events_func;
+ mono_jit_info_table_foreach_internal (eventpipe_fire_method_events_func, &events_data);
+ g_free (events_data.buffer);
+
+ // Iterate all assemblies in domain.
+ GPtrArray *assemblies = mono_alc_get_all_loaded_assemblies ();
+ if (assemblies) {
+ for (int i = 0; i < assemblies->len; ++i) {
+ MonoAssembly *assembly = (MonoAssembly *)g_ptr_array_index (assemblies, i);
+ if (assembly)
+ eventpipe_fire_assembly_events (root_domain, assembly, assembly_events_func);
+ }
+ g_ptr_array_free (assemblies, TRUE);
+ }
- if (!ep_event_is_enabled (EventPipeEventDomainModuleDCEnd_V1))
- return true;
+ uint32_t domain_flags = DOMAIN_FLAGS_DEFAULT_DOMAIN | DOMAIN_FLAGS_EXECUTABLE_DOMAIN;
+ const char *domain_name = root_domain->friendly_name ? root_domain->friendly_name : "";
+ uint32_t domain_index = 1;
- uint8_t stack_buffer [162];
- uint8_t *buffer = stack_buffer;
- size_t offset = 0;
- size_t size = sizeof (stack_buffer);
- bool fixed_buffer = true;
- bool success = true;
+ domain_events_func (
+ domain_id,
+ domain_flags,
+ (const ep_char8_t *)domain_name,
+ domain_index,
+ NULL);
+ }
- success &= write_buffer_uint64_t (&module_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint64_t (&assembly_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint64_t (&domain_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint32_t (&module_flags, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint32_t (&reserved_1, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_string_utf8_t (module_il_path, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_string_utf8_t (module_native_path, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
+ return TRUE;
+}
- ep_raise_error_if_nok (success);
+static
+gboolean
+eventpipe_walk_managed_stack_for_thread_func (
+ MonoStackFrameInfo *frame,
+ MonoContext *ctx,
+ void *data)
+{
+ EP_ASSERT (frame != NULL);
+ EP_ASSERT (data != NULL);
+
+ switch (frame->type) {
+ case FRAME_TYPE_DEBUGGER_INVOKE:
+ case FRAME_TYPE_MANAGED_TO_NATIVE:
+ case FRAME_TYPE_TRAMPOLINE:
+ case FRAME_TYPE_INTERP_TO_MANAGED:
+ case FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX:
+ return FALSE;
+ case FRAME_TYPE_MANAGED:
+ case FRAME_TYPE_INTERP:
+ if (!frame->ji)
+ return FALSE;
+ MonoMethod *method = frame->ji->async ? NULL : frame->actual_method;
+ if (method && !m_method_is_wrapper (method))
+ ep_stack_contents_append ((EventPipeStackContents *)data, (uintptr_t)((uint8_t*)frame->ji->code_start + frame->native_offset), method);
+ return ep_stack_contents_get_length ((EventPipeStackContents *)data) >= EP_MAX_STACK_DEPTH;
+ default:
+ EP_UNREACHABLE ("eventpipe_walk_managed_stack_for_thread_func");
+ return FALSE;
+ }
+}
- ep_write_event (EventPipeEventDomainModuleDCEnd_V1, buffer, (uint32_t)offset, activity_id, related_activity_id);
+static
+gboolean
+eventpipe_sample_profiler_walk_managed_stack_for_thread_func (
+ MonoStackFrameInfo *frame,
+ MonoContext *ctx,
+ void *data)
+{
+ EP_ASSERT (frame != NULL);
+ EP_ASSERT (data != NULL);
-ep_on_exit:
- if (!fixed_buffer)
- ep_rt_byte_array_free (buffer);
- return success;
+ EventPipeSampleProfileData *sample_data = (EventPipeSampleProfileData *)data;
-ep_on_error:
- EP_ASSERT (!success);
- ep_exit_error_handler ();
+ if (sample_data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR) {
+ if (frame->type == FRAME_TYPE_MANAGED_TO_NATIVE)
+ sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
+ else
+ sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
+ }
+
+ return eventpipe_walk_managed_stack_for_thread_func (frame, ctx, &sample_data->stack_contents);
}
static
-bool
-write_event_assembly_dc_end_v1 (
- const uint64_t assembly_id,
- const uint64_t domain_id,
- const uint64_t binding_id,
- const uint32_t assembly_flags,
- const ep_char8_t *fully_qualified_name,
- const uint16_t clr_instance_id,
- const uint8_t *activity_id,
- const uint8_t *related_activity_id)
+void
+profiler_eventpipe_thread_exited (
+ MonoProfiler *prof,
+ uintptr_t tid)
{
- EP_ASSERT (EventPipeEventAssemblyDCEnd_V1 != NULL);
+ void ep_rt_mono_thread_exited (void);
+ ep_rt_mono_thread_exited ();
+}
- if (!ep_event_is_enabled (EventPipeEventAssemblyDCEnd_V1))
- return true;
+void
+ep_rt_mono_init (void)
+{
+ mono_native_tls_alloc (&_ep_rt_mono_thread_holder_tls_id, NULL);
- uint8_t stack_buffer [94];
- uint8_t *buffer = stack_buffer;
- size_t offset = 0;
- size_t size = sizeof (stack_buffer);
- bool fixed_buffer = true;
- bool success = true;
+ mono_100ns_ticks ();
+ mono_rand_open ();
+ _ep_rt_mono_rand_provider = mono_rand_init (NULL, 0);
- success &= write_buffer_uint64_t (&assembly_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint64_t (&domain_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint64_t (&binding_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint32_t (&assembly_flags, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_string_utf8_t (fully_qualified_name, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
+ _ep_rt_mono_initialized = TRUE;
- ep_raise_error_if_nok (success);
+ MonoProfilerHandle profiler = mono_profiler_create (NULL);
+ mono_profiler_set_thread_stopped_callback (profiler, profiler_eventpipe_thread_exited);
+}
- ep_write_event (EventPipeEventAssemblyDCEnd_V1, buffer, (uint32_t)offset, activity_id, related_activity_id);
+void
+ep_rt_mono_fini (void)
+{
+ if (_ep_rt_mono_sampled_thread_callstacks)
+ g_array_free (_ep_rt_mono_sampled_thread_callstacks, TRUE);
-ep_on_exit:
- if (!fixed_buffer)
- ep_rt_byte_array_free (buffer);
- return success;
+ if (_ep_rt_mono_initialized)
+ mono_rand_close (_ep_rt_mono_rand_provider);
-ep_on_error:
- EP_ASSERT (!success);
- ep_exit_error_handler ();
+ _ep_rt_mono_sampled_thread_callstacks = NULL;
+ _ep_rt_mono_rand_provider = NULL;
+ _ep_rt_mono_initialized = FALSE;
}
-static
bool
-write_event_domain_dc_end_v1 (
- const uint64_t domain_id,
- const uint32_t domain_flags,
- const ep_char8_t *domain_name,
- const uint32_t domain_index,
- const uint16_t clr_instance_id,
- const uint8_t *activity_id,
- const uint8_t *related_activity_id)
+ep_rt_mono_rand_try_get_bytes (
+ uint8_t *buffer,
+ size_t buffer_size)
{
- EP_ASSERT (EventPipeEventAppDomainDCEnd_V1 != NULL);
-
- if (!ep_event_is_enabled (EventPipeEventAppDomainDCEnd_V1))
- return true;
+ EP_ASSERT (_ep_rt_mono_rand_provider != NULL);
- uint8_t stack_buffer [82];
- uint8_t *buffer = stack_buffer;
- size_t offset = 0;
- size_t size = sizeof (stack_buffer);
- bool fixed_buffer = true;
- bool success = true;
+ ERROR_DECL (error);
+ return mono_rand_try_get_bytes (&_ep_rt_mono_rand_provider, (guchar *)buffer, (gssize)buffer_size, error);
+}
- success &= write_buffer_uint64_t (&domain_id, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint32_t (&domain_flags, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_string_utf8_t (domain_name, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint32_t (&domain_index, &buffer, &offset, &size, &fixed_buffer);
- success &= write_buffer_uint16_t (&clr_instance_id, &buffer, &offset, &size, &fixed_buffer);
+EventPipeThread *
+ep_rt_mono_thread_get_or_create (void)
+{
+ EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (_ep_rt_mono_thread_holder_tls_id);
+ if (!thread_holder) {
+ thread_holder = thread_holder_alloc_func ();
+ mono_native_tls_set_value (_ep_rt_mono_thread_holder_tls_id, thread_holder);
+ }
+ return ep_thread_holder_get_thread (thread_holder);
+}
- ep_raise_error_if_nok (success);
+void *
+ep_rt_mono_thread_attach (bool background_thread)
+{
+ MonoThread *thread = NULL;
+
+ // NOTE, under netcore, only root domain exists.
+ if (!mono_thread_current ()) {
+ thread = mono_thread_internal_attach (mono_get_root_domain ());
+ if (background_thread && thread) {
+ mono_thread_set_state (thread, ThreadState_Background);
+ mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NO_SAMPLE);
+ }
+ }
- ep_write_event (EventPipeEventAppDomainDCEnd_V1, buffer, (uint32_t)offset, activity_id, related_activity_id);
+ return thread;
+}
-ep_on_exit:
- if (!fixed_buffer)
- ep_rt_byte_array_free (buffer);
- return success;
+void
+ep_rt_mono_thread_detach (void)
+{
+ MonoThread *current_thread = mono_thread_current ();
+ if (current_thread)
+ mono_thread_internal_detach (current_thread);
+}
-ep_on_error:
- EP_ASSERT (!success);
- ep_exit_error_handler ();
+void
+ep_rt_mono_thread_exited (void)
+{
+ if (_ep_rt_mono_initialized) {
+ EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (_ep_rt_mono_thread_holder_tls_id);
+ if (thread_holder)
+ thread_holder_free_func (thread_holder);
+ mono_native_tls_set_value (_ep_rt_mono_thread_holder_tls_id, NULL);
+ }
}
-// Mapping FireEtw* CoreClr functions.
-#define FireEtwRuntimeInformationDCStart(...) write_runtime_info_dc_start(__VA_ARGS__,NULL,NULL)
-#define FireEtwDCEndInit_V1(...) write_event_dc_end_init_v1(__VA_ARGS__,NULL,NULL)
-#define FireEtwMethodDCEndILToNativeMap(...) write_event_method_dc_end_il_to_native_map(__VA_ARGS__,NULL,NULL)
-#define FireEtwMethodDCEndVerbose_V1(...) write_event_method_dc_end_verbose_v1(__VA_ARGS__,NULL,NULL)
-#define FireEtwModuleDCEnd_V2(...) write_event_module_dc_end_v2(__VA_ARGS__,NULL,NULL)
-#define FireEtwDomainModuleDCEnd_V1(...) write_event_domain_module_dc_end_v1(__VA_ARGS__,NULL,NULL)
-#define FireEtwAssemblyDCEnd_V1(...) write_event_assembly_dc_end_v1(__VA_ARGS__,NULL,NULL)
-#define FireEtwAppDomainDCEnd_V1(...) write_event_domain_dc_end_v1(__VA_ARGS__,NULL,NULL)
-#define FireEtwDCEndComplete_V1(...) write_event_dc_end_complete_v1(__VA_ARGS__,NULL,NULL)
+#ifdef HOST_WIN32
+int64_t
+ep_rt_mono_perf_counter_query (void)
+{
+ LARGE_INTEGER value;
+ if (QueryPerformanceCounter (&value))
+ return (int64_t)value.QuadPart;
+ else
+ return 0;
+}
-static
-bool
-fire_method_rundown_events_func (
- const uint64_t method_id,
- const uint64_t module_id,
- const uint64_t method_start_address,
- const uint32_t method_size,
- const uint32_t method_token,
- const uint32_t method_flags,
- const ep_char8_t *method_namespace,
- const ep_char8_t *method_name,
- const ep_char8_t *method_signature,
- const uint16_t count_of_map_entries,
- const uint32_t *il_offsets,
- const uint32_t *native_offsets,
- void *user_data)
+int64_t
+ep_rt_mono_perf_frequency_query (void)
{
- FireEtwMethodDCEndILToNativeMap (
- method_id,
- 0,
- 0,
- count_of_map_entries,
- il_offsets,
- native_offsets,
- clr_instance_get_id ());
+ LARGE_INTEGER value;
+ if (QueryPerformanceFrequency (&value))
+ return (int64_t)value.QuadPart;
+ else
+ return 0;
+}
- FireEtwMethodDCEndVerbose_V1 (
- method_id,
- module_id,
- method_start_address,
- method_size,
- method_token,
- method_flags,
- method_namespace,
- method_name,
- method_signature,
- clr_instance_get_id ());
+void
+ep_rt_mono_system_time_get (EventPipeSystemTime *system_time)
+{
+ SYSTEMTIME value;
+ GetSystemTime (&value);
- return true;
+ EP_ASSERT (system_time != NULL);
+ ep_system_time_set (
+ system_time,
+ value.wYear,
+ value.wMonth,
+ value.wDayOfWeek,
+ value.wDay,
+ value.wHour,
+ value.wMinute,
+ value.wSecond,
+ value.wMilliseconds);
}
-static
-bool
-fire_assembly_rundown_events_func (
- const uint64_t domain_id,
- const uint64_t assembly_id,
- const uint32_t assembly_flags,
- const uint32_t binding_id,
- const ep_char8_t *assembly_name,
- const uint64_t module_id,
- const uint32_t module_flags,
- const uint32_t reserved_flags,
- const ep_char8_t *module_il_path,
- const ep_char8_t *module_native_path,
- const uint8_t *managed_pdb_signature,
- const uint32_t managed_pdb_age,
- const ep_char8_t *managed_pdb_build_path,
- const uint8_t *native_pdb_signature,
- const uint32_t native_pdb_age,
- const ep_char8_t *native_pdb_build_path,
- void *user_data)
+int64_t
+ep_rt_mono_system_timestamp_get (void)
{
- FireEtwModuleDCEnd_V2 (
- module_id,
- assembly_id,
- module_flags,
- reserved_flags,
- module_il_path,
- module_native_path,
- clr_instance_get_id (),
- managed_pdb_signature,
- managed_pdb_age,
- managed_pdb_build_path,
- native_pdb_signature,
- native_pdb_age,
- native_pdb_build_path);
+ FILETIME value;
+ GetSystemTimeAsFileTime (&value);
+ return (int64_t)((((uint64_t)value.dwHighDateTime) << 32) | (uint64_t)value.dwLowDateTime);
+}
+#else
+#include
+#include
+#include
+#include
+
+#if HAVE_SYS_TIME_H
+#include
+#endif // HAVE_SYS_TIME_H
+
+#if HAVE_MACH_ABSOLUTE_TIME
+#include
+static mono_lazy_init_t _ep_rt_mono_time_base_info_init = MONO_LAZY_INIT_STATUS_NOT_INITIALIZED;
+static mach_timebase_info_data_t _ep_rt_mono_time_base_info = {0};
+#endif
+
+#ifdef HAVE_LOCALTIME_R
+#define HAVE_GMTIME_R 1
+#endif
+
+static const int64_t SECS_BETWEEN_1601_AND_1970_EPOCHS = 11644473600LL;
+static const int64_t SECS_TO_100NS = 10000000;
+static const int64_t SECS_TO_NS = 1000000000;
+static const int64_t MSECS_TO_MIS = 1000;
+
+/* clock_gettime () is found by configure on Apple builds, but its only present from ios 10, macos 10.12, tvos 10 and watchos 3 */
+#if defined (HAVE_CLOCK_MONOTONIC) && (defined(TARGET_IOS) || defined(TARGET_OSX) || defined(TARGET_WATCHOS) || defined(TARGET_TVOS))
+#undef HAVE_CLOCK_MONOTONIC
+#endif
+
+#ifndef HAVE_CLOCK_MONOTONIC
+static const int64_t MISECS_TO_NS = 1000;
+#endif
- FireEtwDomainModuleDCEnd_V1 (
- module_id,
- assembly_id,
- domain_id,
- module_flags,
- reserved_flags,
- module_il_path,
- module_native_path,
- clr_instance_get_id ());
+static
+void
+time_base_info_lazy_init (void);
- FireEtwAssemblyDCEnd_V1 (
- assembly_id,
- domain_id,
- binding_id,
- assembly_flags,
- assembly_name,
- clr_instance_get_id ());
+static
+int64_t
+system_time_to_int64 (
+ time_t sec,
+ long nsec);
- return true;
+#if HAVE_MACH_ABSOLUTE_TIME
+static
+void
+time_base_info_lazy_init (void)
+{
+ kern_return_t result = mach_timebase_info (&_ep_rt_mono_time_base_info);
+ if (result != KERN_SUCCESS)
+ memset (&_ep_rt_mono_time_base_info, 0, sizeof (_ep_rt_mono_time_base_info));
}
+#endif
-static
-bool
-fire_domain_rundown_events_func (
- const uint64_t domain_id,
- const uint32_t domain_flags,
- const ep_char8_t *domain_name,
- const uint32_t domain_index,
- void *user_data)
+int64_t
+ep_rt_mono_perf_counter_query (void)
{
- return FireEtwAppDomainDCEnd_V1 (
- domain_id,
- domain_flags,
- domain_name,
- domain_index,
- clr_instance_get_id ());
+#if HAVE_MACH_ABSOLUTE_TIME
+ return (int64_t)mach_absolute_time ();
+#elif HAVE_CLOCK_MONOTONIC
+ struct timespec ts;
+ int result = clock_gettime (CLOCK_MONOTONIC, &ts);
+ if (result == 0)
+ return ((int64_t)(ts.tv_sec) * (int64_t)(SECS_TO_NS)) + (int64_t)(ts.tv_nsec);
+#else
+ #error "ep_rt_mono_perf_counter_get requires either mach_absolute_time () or clock_gettime (CLOCK_MONOTONIC) to be supported."
+#endif
+ return 0;
+}
+
+int64_t
+ep_rt_mono_perf_frequency_query (void)
+{
+#if HAVE_MACH_ABSOLUTE_TIME
+ // (numer / denom) gives you the nanoseconds per tick, so the below code
+ // computes the number of ticks per second. We explicitly do the multiplication
+ // first in order to help minimize the error that is produced by integer division.
+ mono_lazy_initialize (&_ep_rt_mono_time_base_info_init, time_base_info_lazy_init);
+ if (_ep_rt_mono_time_base_info.denom == 0 || _ep_rt_mono_time_base_info.numer == 0)
+ return 0;
+ return ((int64_t)(SECS_TO_NS) * (int64_t)(_ep_rt_mono_time_base_info.denom)) / (int64_t)(_ep_rt_mono_time_base_info.numer);
+#elif HAVE_CLOCK_MONOTONIC
+ // clock_gettime () returns a result in terms of nanoseconds rather than a count. This
+ // means that we need to either always scale the result by the actual resolution (to
+ // get a count) or we need to say the resolution is in terms of nanoseconds. We prefer
+ // the latter since it allows the highest throughput and should minimize error propagated
+ // to the user.
+ return (int64_t)(SECS_TO_NS);
+#else
+ #error "ep_rt_mono_perf_frequency_query requires either mach_absolute_time () or clock_gettime (CLOCK_MONOTONIC) to be supported."
+#endif
+ return 0;
}
-static
void
-init_dotnet_runtime_rundown (void)
+ep_rt_mono_system_time_get (EventPipeSystemTime *system_time)
{
- //TODO: Add callback method to enable/disable more native events getting into EventPipe (when enabled).
- EP_ASSERT (EventPipeProviderDotNETRuntimeRundown == NULL);
- EventPipeProviderDotNETRuntimeRundown = ep_create_provider (ep_config_get_rundown_provider_name_utf8 (), NULL, NULL, NULL);
+ time_t tt;
+#if HAVE_GMTIME_R
+ struct tm ut;
+#endif /* HAVE_GMTIME_R */
+ struct tm *ut_ptr;
+ struct timeval time_val;
+ int timeofday_retval;
- EP_ASSERT (EventPipeEventMethodDCEndVerbose_V1 == NULL);
- EventPipeEventMethodDCEndVerbose_V1 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 144, 48, 1, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
+ EP_ASSERT (system_time != NULL);
- EP_ASSERT (EventPipeEventDCEndComplete_V1 == NULL);
- EventPipeEventDCEndComplete_V1 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 146, 131128, 1, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
+ tt = time (NULL);
- EP_ASSERT (EventPipeEventDCEndInit_V1 == NULL);
- EventPipeEventDCEndInit_V1 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 148, 131128, 1, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
+ /* We can't get millisecond resolution from time (), so we get it from gettimeofday () */
+ timeofday_retval = gettimeofday (&time_val, NULL);
- EP_ASSERT (EventPipeEventMethodDCEndILToNativeMap == NULL);
- EventPipeEventMethodDCEndILToNativeMap = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 150, 131072, 0, EP_EVENT_LEVEL_VERBOSE, true, NULL, 0);
+#if HAVE_GMTIME_R
+ ut_ptr = &ut;
+ if (gmtime_r (&tt, ut_ptr) == NULL)
+#else /* HAVE_GMTIME_R */
+ if ((ut_ptr = gmtime (&tt)) == NULL)
+#endif /* HAVE_GMTIME_R */
+ EP_UNREACHABLE ();
- EP_ASSERT (EventPipeEventDomainModuleDCEnd_V1 == NULL);
- EventPipeEventDomainModuleDCEnd_V1 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 152, 8, 1, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
+ uint16_t milliseconds = 0;
+ if (timeofday_retval != -1) {
+ int old_seconds;
+ int new_seconds;
- EP_ASSERT (EventPipeEventModuleDCEnd_V2 == NULL);
- EventPipeEventModuleDCEnd_V2 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 154, 536870920, 2, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
+ milliseconds = time_val.tv_usec / MSECS_TO_MIS;
- EP_ASSERT (EventPipeEventAssemblyDCEnd_V1 == NULL);
- EventPipeEventAssemblyDCEnd_V1 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 156, 8, 1, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
+ old_seconds = ut_ptr->tm_sec;
+ new_seconds = time_val.tv_sec % 60;
- EP_ASSERT (EventPipeEventAppDomainDCEnd_V1 == NULL);
- EventPipeEventAppDomainDCEnd_V1 = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 158, 8, 1, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
+ /* just in case we reached the next second in the interval between time () and gettimeofday () */
+ if (old_seconds != new_seconds)
+ milliseconds = 999;
+ }
- EP_ASSERT (EventPipeEventRuntimeInformationDCStart == NULL);
- EventPipeEventRuntimeInformationDCStart = ep_provider_add_event (EventPipeProviderDotNETRuntimeRundown, 187, 0, 0, EP_EVENT_LEVEL_INFORMATIONAL, true, NULL, 0);
+ ep_system_time_set (
+ system_time,
+ 1900 + ut_ptr->tm_year,
+ ut_ptr->tm_mon + 1,
+ ut_ptr->tm_wday,
+ ut_ptr->tm_mday,
+ ut_ptr->tm_hour,
+ ut_ptr->tm_min,
+ ut_ptr->tm_sec,
+ milliseconds);
+}
+
+static
+inline
+int64_t
+system_time_to_int64 (
+ time_t sec,
+ long nsec)
+{
+ return ((int64_t)sec + SECS_BETWEEN_1601_AND_1970_EPOCHS) * SECS_TO_100NS + (nsec / 100);
+}
+
+int64_t
+ep_rt_mono_system_timestamp_get (void)
+{
+#if HAVE_CLOCK_MONOTONIC
+ struct timespec time;
+ if (clock_gettime (CLOCK_REALTIME, &time) == 0)
+ return system_time_to_int64 (time.tv_sec, time.tv_nsec);
+#else
+ struct timeval time;
+ if (gettimeofday (&time, NULL) == 0)
+ return system_time_to_int64 (time.tv_sec, time.tv_usec * MISECS_TO_NS);
+#endif
+ else
+ return system_time_to_int64 (0, 0);
+}
+#endif
+
+#ifndef HOST_WIN32
+#if defined(__APPLE__)
+#if defined (TARGET_OSX)
+G_BEGIN_DECLS
+gchar ***_NSGetEnviron(void);
+G_END_DECLS
+#define environ (*_NSGetEnviron())
+#else
+static char *_ep_rt_mono_environ[1] = { NULL };
+#define environ _ep_rt_mono_environ
+#endif /* defined (TARGET_OSX) */
+#else
+G_BEGIN_DECLS
+extern char **environ;
+G_END_DECLS
+#endif /* defined (__APPLE__) */
+#endif /* !defined (HOST_WIN32) */
+
+void
+ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array)
+{
+ EP_ASSERT (env_array != NULL);
+#ifdef HOST_WIN32
+ LPWSTR envs = GetEnvironmentStringsW ();
+ if (envs) {
+ LPWSTR next = envs;
+ while (*next) {
+ ep_rt_env_array_utf16_append (env_array, ep_rt_utf16_string_dup (next));
+ next += ep_rt_utf16_string_len (next) + 1;
+ }
+ FreeEnvironmentStringsW (envs);
+ }
+#else
+ gchar **next = NULL;
+ for (next = environ; *next != NULL; ++next)
+ ep_rt_env_array_utf16_append (env_array, ep_rt_utf8_to_utf16_string (*next, -1));
+#endif
}
void
ep_rt_mono_init_providers_and_events (void)
{
init_dotnet_runtime_rundown ();
+ init_dotnet_runtime_private ();
}
void
@@ -1296,9 +1987,125 @@ ep_rt_mono_fini_providers_and_events (void)
// Deallocating providers/events here might cause AV if a WriteEvent
// was to occur. Thus, we are not doing this cleanup.
+ // ep_delete_provider (EventPipeProviderDotNETRuntimePrivate);
// ep_delete_provider (EventPipeProviderDotNETRuntimeRundown);
}
+bool
+ep_rt_mono_walk_managed_stack_for_thread (
+ ep_rt_thread_handle_t thread,
+ EventPipeStackContents *stack_contents)
+{
+ EP_ASSERT (thread != NULL && stack_contents != NULL);
+
+ if (thread == ep_rt_thread_get_handle ())
+ mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (eventpipe_walk_managed_stack_for_thread_func, NULL, MONO_UNWIND_SIGNAL_SAFE, stack_contents);
+ else
+ mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_walk_managed_stack_for_thread_func, mono_thread_info_get_suspend_state (thread), MONO_UNWIND_SIGNAL_SAFE, stack_contents);
+
+ return true;
+}
+
+bool
+ep_rt_mono_method_get_simple_assembly_name (
+ ep_rt_method_desc_t *method,
+ ep_char8_t *name,
+ size_t name_len)
+{
+ EP_ASSERT (method != NULL);
+ EP_ASSERT (name != NULL);
+
+ MonoClass *method_class = mono_method_get_class (method);
+ MonoImage *method_image = method_class ? mono_class_get_image (method_class) : NULL;
+ const ep_char8_t *assembly_name = method_image ? mono_image_get_name (method_image) : NULL;
+
+ if (!assembly_name)
+ return false;
+
+ g_strlcpy (name, assembly_name, name_len);
+ return true;
+}
+
+bool
+ep_rt_mono_method_get_full_name (
+ ep_rt_method_desc_t *method,
+ ep_char8_t *name,
+ size_t name_len)
+{
+ EP_ASSERT (method != NULL);
+ EP_ASSERT (name != NULL);
+
+ char *full_method_name = mono_method_get_name_full (method, TRUE, TRUE, MONO_TYPE_NAME_FORMAT_IL);
+ if (!full_method_name)
+ return false;
+
+ g_strlcpy (name, full_method_name, name_len);
+
+ g_free (full_method_name);
+ return true;
+}
+
+bool
+ep_rt_mono_sample_profiler_write_sampling_event_for_threads (
+ ep_rt_thread_handle_t sampling_thread,
+ EventPipeEvent *sampling_event)
+{
+ // Follows CoreClr implementation of sample profiler. Generic invasive/expensive way to do CPU sample profiling relying on STW and stackwalks.
+ // TODO: Investigate alternatives on platforms supporting Signals/SuspendThread (see Mono profiler) or CPU PMU's (see ETW/perf_event_open).
+
+ // Sample profiler only runs on one thread, no need to synchorinize.
+ if (!_ep_rt_mono_sampled_thread_callstacks)
+ _ep_rt_mono_sampled_thread_callstacks = g_array_sized_new (FALSE, FALSE, sizeof (EventPipeSampleProfileData), _ep_rt_mono_max_sampled_thread_count);
+
+ // Make sure there is room based on previous max number of sampled threads.
+ // NOTE, there is a chance there are more threads than max, if that's the case we will
+ // miss those threads in this sample, but will be included in next when max has been adjusted.
+ g_array_set_size (_ep_rt_mono_sampled_thread_callstacks, _ep_rt_mono_max_sampled_thread_count);
+
+ uint32_t filtered_thread_count = 0;
+ uint32_t sampled_thread_count = 0;
+
+ mono_stop_world (MONO_THREAD_INFO_FLAGS_NO_GC | MONO_THREAD_INFO_FLAGS_NO_SAMPLE);
+
+ // Record all info needed in sample events while runtime is suspended, must be async safe.
+ FOREACH_THREAD_SAFE_EXCLUDE (thread_info, MONO_THREAD_INFO_FLAGS_NO_GC | MONO_THREAD_INFO_FLAGS_NO_SAMPLE) {
+ if (!mono_thread_info_is_running (thread_info)) {
+ MonoThreadUnwindState *thread_state = mono_thread_info_get_suspend_state (thread_info);
+ if (thread_state->valid) {
+ if (sampled_thread_count < _ep_rt_mono_max_sampled_thread_count) {
+ EventPipeSampleProfileData *data = &g_array_index (_ep_rt_mono_sampled_thread_callstacks, EventPipeSampleProfileData, sampled_thread_count);
+ data->thread_id = ep_rt_thread_id_t_to_uint64_t (mono_thread_info_get_tid (thread_info));
+ data->thread_ip = (uintptr_t)MONO_CONTEXT_GET_IP (&thread_state->ctx);
+ data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR;
+ ep_stack_contents_reset (&data->stack_contents);
+ mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_sample_profiler_walk_managed_stack_for_thread_func, thread_state, MONO_UNWIND_SIGNAL_SAFE, data);
+ sampled_thread_count++;
+ }
+ }
+ }
+ filtered_thread_count++;
+ } FOREACH_THREAD_SAFE_END
+
+ mono_restart_world (MONO_THREAD_INFO_FLAGS_NO_GC | MONO_THREAD_INFO_FLAGS_NO_SAMPLE);
+
+ // Fire sample event for threads. Must be done after runtime is resumed since it's not async safe.
+ // Since we can't keep thread info around after runtime as been suspended, use an empty
+ // adapter instance and only set recorded tid as parameter inside adapter.
+ THREAD_INFO_TYPE adapter = { { 0 } };
+ for (uint32_t i = 0; i < sampled_thread_count; ++i) {
+ EventPipeSampleProfileData *data = &g_array_index (_ep_rt_mono_sampled_thread_callstacks, EventPipeSampleProfileData, i);
+ if (data->payload_data != EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR && ep_stack_contents_get_length(&data->stack_contents) > 0) {
+ mono_thread_info_set_tid (&adapter, ep_rt_uint64_t_to_thread_id_t (data->thread_id));
+ ep_write_sample_profile_event (sampling_thread, sampling_event, &adapter, &data->stack_contents, (uint8_t *)&data->payload_data, sizeof (data->payload_data));
+ }
+ }
+
+ // Current thread count will be our next maximum sampled threads.
+ _ep_rt_mono_max_sampled_thread_count = filtered_thread_count;
+
+ return true;
+}
+
void
ep_rt_mono_execute_rundown (void)
{
@@ -1331,8 +2138,7 @@ ep_rt_mono_execute_rundown (void)
FireEtwDCEndInit_V1 (clr_instance_get_id ());
- EP_ASSERT (_ep_rt_mono_func_table.ep_rt_mono_execute_rundown != NULL);
- _ep_rt_mono_func_table.ep_rt_mono_execute_rundown (
+ eventpipe_execute_rundown (
fire_domain_rundown_events_func,
fire_assembly_rundown_events_func,
fire_method_rundown_events_func);
@@ -1340,6 +2146,12 @@ ep_rt_mono_execute_rundown (void)
FireEtwDCEndComplete_V1 (clr_instance_get_id ());
}
+bool
+ep_rt_mono_write_event_ee_startup_start (void)
+{
+ return FireEtwEEStartupStart_V1 (clr_instance_get_id ());
+}
+
#endif /* ENABLE_PERFTRACING */
MONO_EMPTY_SOURCE_FILE(eventpipe_rt_mono);
diff --git a/src/mono/mono/eventpipe/ep-rt-mono.h b/src/mono/mono/eventpipe/ep-rt-mono.h
index e8590d9bbdafbb..fd8c94cd766cb7 100644
--- a/src/mono/mono/eventpipe/ep-rt-mono.h
+++ b/src/mono/mono/eventpipe/ep-rt-mono.h
@@ -10,6 +10,7 @@
#include
#include
#include
+
#include
#include
#include
@@ -17,11 +18,11 @@
#include
#include
#include
+#include
+#include
#include
#include
#include
-#include
-#include
#undef EP_ARRAY_SIZE
#define EP_ARRAY_SIZE(expr) G_N_ELEMENTS(expr)
@@ -347,166 +348,12 @@ prefix_name ## _rt_ ## type_name ## _ ## func_name
#define EP_RT_DEFINE_HASH_MAP_ITERATOR(hash_map_name, hash_map_type, iterator_type, key_type, value_type) \
EP_RT_DEFINE_HASH_MAP_ITERATOR_PREFIX(ep, hash_map_name, hash_map_type, iterator_type, key_type, value_type)
-// Rundown callbacks.
-typedef
-bool
-(*ep_rt_mono_fire_method_rundown_events_func)(
- const uint64_t method_id,
- const uint64_t module_id,
- const uint64_t method_start_address,
- const uint32_t method_size,
- const uint32_t method_token,
- const uint32_t method_flags,
- const ep_char8_t *method_namespace,
- const ep_char8_t *method_name,
- const ep_char8_t *method_signature,
- const uint16_t count_of_map_entries,
- const uint32_t *il_offsets,
- const uint32_t *native_offsets,
- void *user_data);
-
-typedef
-bool
-(*ep_rt_mono_fire_assembly_rundown_events_func)(
- const uint64_t domain_id,
- const uint64_t assembly_id,
- const uint32_t assembly_flags,
- const uint32_t binding_id,
- const ep_char8_t *assembly_name,
- const uint64_t module_id,
- const uint32_t module_flags,
- const uint32_t reserved_flags,
- const ep_char8_t *module_il_path,
- const ep_char8_t *module_native_path,
- const uint8_t *managed_pdb_signature,
- const uint32_t managed_pdb_age,
- const ep_char8_t *managed_pdb_build_path,
- const uint8_t *native_pdb_signature,
- const uint32_t native_pdb_age,
- const ep_char8_t *native_pdb_build_path,
- void *user_data);
-
-typedef
-bool
-(*ep_rt_mono_fire_domain_rundown_events_func)(
- const uint64_t domain_id,
- const uint32_t domain_flags,
- const ep_char8_t *domain_name,
- const uint32_t domain_index,
- void *user_data);
-
-typedef EventPipeThreadHolder * (*ep_rt_thread_holder_alloc_func)(void);
-typedef void (*ep_rt_thread_holder_free_func)(EventPipeThreadHolder *thread_holder);
-
-typedef int (*ep_rt_mono_cpu_count_func)(void);
-typedef int (*ep_rt_mono_process_current_pid_func)(void);
-typedef MonoNativeThreadId (*ep_rt_mono_native_thread_id_get_func)(void);
-typedef gboolean (*ep_rt_mono_native_thread_id_equals_func)(MonoNativeThreadId, MonoNativeThreadId);
-typedef gboolean (*ep_rt_mono_runtime_is_shutting_down_func)(void);
-typedef gboolean (*ep_rt_mono_rand_try_get_bytes_func)(guchar *buffer, gssize buffer_size, MonoError *error);
-typedef EventPipeThread * (*ep_rt_mono_thread_get_func)(void);
-typedef EventPipeThread * (*ep_rt_mono_thread_get_or_create_func)(void);
-typedef void (*ep_rt_mono_thread_exited_func)(void);
-typedef gint (*ep_rt_mono_thread_info_sleep_func)(guint32 ms, gboolean *alerted);
-typedef gboolean (*ep_rt_mono_thread_info_yield_func)(void);
-typedef gpointer (*ep_rt_mono_w32file_create_func)(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs);
-typedef gboolean (*ep_rt_mono_w32file_write_func)(gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten, gint32 *win32error);
-typedef gboolean (*ep_rt_mono_w32file_close_func)(gpointer handle);
-typedef gpointer (*ep_rt_mono_w32event_create_func)(gboolean manual, gboolean initial);
-typedef gboolean (*ep_rt_mono_w32event_close_func)(gpointer handle);
-typedef void (*ep_rt_mono_w32event_set_func)(gpointer handle);
-typedef MonoW32HandleWaitRet (*ep_rt_mono_w32handle_wait_one_func)(gpointer handle, guint32 timeout, gboolean alertable);
-typedef void* (*ep_rt_mono_valloc_func)(void *addr, size_t length, int flags, MonoMemAccountType type);
-typedef int (*ep_rt_mono_vfree_func)(void *addr, size_t length, MonoMemAccountType type);
-typedef int (*ep_rt_mono_valloc_granule_func)(void);
-typedef gboolean (*ep_rt_mono_thread_platform_create_thread_func)(ep_rt_thread_start_func thread_func, gpointer thread_data, gsize * const stack_size, ep_rt_thread_id_t *thread_id);
-typedef gpointer (*ep_rt_mono_thread_attach_func)(gboolean);
-typedef void (*ep_rt_mono_thread_detach_func)(void);
-typedef char* (*ep_rt_mono_get_os_cmd_line_func)(void);
-typedef char* (*ep_rt_mono_get_managed_cmd_line_func)(void);
-typedef gboolean (*ep_rt_mono_execute_rundown_func)(ep_rt_mono_fire_domain_rundown_events_func domain_events_func, ep_rt_mono_fire_assembly_rundown_events_func assembly_events_func, ep_rt_mono_fire_method_rundown_events_func methods_events_func);
-typedef gboolean (*ep_rt_mono_walk_managed_stack_for_thread_func)(ep_rt_thread_handle_t thread, EventPipeStackContents *stack_contents);
-typedef gboolean (*ep_rt_mono_sample_profiler_write_sampling_event_for_threads_func)(ep_rt_thread_handle_t sampling_thread, EventPipeEvent *sampling_event);
-typedef gboolean (*ep_rt_mono_method_get_simple_assembly_name_func)(ep_rt_method_desc_t *method, ep_char8_t *name, size_t name_len);
-typedef gboolean (*ep_rt_mono_method_get_full_name_func)(ep_rt_method_desc_t *method, ep_char8_t *name, size_t name_len);
-
-typedef struct _EventPipeMonoFuncTable {
- ep_rt_mono_process_current_pid_func ep_rt_mono_process_current_pid;
- ep_rt_mono_cpu_count_func ep_rt_mono_cpu_count;
- ep_rt_mono_native_thread_id_get_func ep_rt_mono_native_thread_id_get;
- ep_rt_mono_native_thread_id_equals_func ep_rt_mono_native_thread_id_equals;
- ep_rt_mono_runtime_is_shutting_down_func ep_rt_mono_runtime_is_shutting_down;
- ep_rt_mono_rand_try_get_bytes_func ep_rt_mono_rand_try_get_bytes;
- ep_rt_mono_thread_get_func ep_rt_mono_thread_get;
- ep_rt_mono_thread_get_or_create_func ep_rt_mono_thread_get_or_create;
- ep_rt_mono_thread_exited_func ep_rt_mono_thread_exited;
- ep_rt_mono_thread_info_sleep_func ep_rt_mono_thread_info_sleep;
- ep_rt_mono_thread_info_yield_func ep_rt_mono_thread_info_yield;
- ep_rt_mono_w32file_create_func ep_rt_mono_w32file_create;
- ep_rt_mono_w32file_write_func ep_rt_mono_w32file_write;
- ep_rt_mono_w32file_close_func ep_rt_mono_w32file_close;
- ep_rt_mono_w32event_create_func ep_rt_mono_w32event_create;
- ep_rt_mono_w32event_close_func ep_rt_mono_w32event_close;
- ep_rt_mono_w32event_set_func ep_rt_mono_w32event_set;
- ep_rt_mono_w32handle_wait_one_func ep_rt_mono_w32hadle_wait_one;
- ep_rt_mono_valloc_func ep_rt_mono_valloc;
- ep_rt_mono_vfree_func ep_rt_mono_vfree;
- ep_rt_mono_valloc_granule_func ep_rt_mono_valloc_granule;
- ep_rt_mono_thread_platform_create_thread_func ep_rt_mono_thread_platform_create_thread;
- ep_rt_mono_thread_attach_func ep_rt_mono_thread_attach;
- ep_rt_mono_thread_detach_func ep_rt_mono_thread_detach;
- ep_rt_mono_get_os_cmd_line_func ep_rt_mono_get_os_cmd_line;
- ep_rt_mono_get_managed_cmd_line_func ep_rt_mono_get_managed_cmd_line;
- ep_rt_mono_execute_rundown_func ep_rt_mono_execute_rundown;
- ep_rt_mono_walk_managed_stack_for_thread_func ep_rt_mono_walk_managed_stack_for_thread;
- ep_rt_mono_sample_profiler_write_sampling_event_for_threads_func ep_rt_mono_sample_profiler_write_sampling_event_for_threads;
- ep_rt_mono_method_get_simple_assembly_name_func ep_rt_mono_method_get_simple_assembly_name;
- ep_rt_mono_method_get_full_name_func ep_rt_mono_method_get_full_name;
-} EventPipeMonoFuncTable;
-
-int64_t
-ep_rt_mono_perf_counter_query (void);
-
-int64_t
-ep_rt_mono_perf_frequency_query (void);
-
-void
-ep_rt_mono_system_time_get (EventPipeSystemTime *system_time);
-
-int64_t
-ep_rt_mono_system_timestamp_get (void);
-
-void
-ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array);
-
-void
-ep_rt_mono_init_providers_and_events (void);
-
-void
-ep_rt_mono_fini_providers_and_events (void);
-
-void
-ep_rt_mono_execute_rundown (void);
-
-static
-inline
-EventPipeMonoFuncTable *
-ep_rt_mono_func_table_get (void)
-{
- extern EventPipeMonoFuncTable _ep_rt_mono_func_table;
- return &_ep_rt_mono_func_table;
-}
-
static
inline
char *
os_command_line_get (void)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
return mono_get_os_cmd_line ();
-#else
- return ep_rt_mono_func_table_get ()->ep_rt_mono_get_os_cmd_line ();
-#endif
}
static
@@ -550,11 +397,7 @@ inline
char *
managed_command_line_get (void)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
return mono_runtime_get_managed_cmd_line ();
-#else
- return ep_rt_mono_func_table_get ()->ep_rt_mono_get_managed_cmd_line ();
-#endif
}
static
@@ -602,17 +445,6 @@ ep_rt_mono_config_lock_get (void)
return &_ep_rt_mono_config_lock;
}
-MONO_PROFILER_API
-void
-mono_eventpipe_init (
- EventPipeMonoFuncTable *table,
- ep_rt_thread_holder_alloc_func thread_holder_alloc_func,
- ep_rt_thread_holder_free_func thread_holder_free_func);
-
-MONO_PROFILER_API
-void
-mono_eventpipe_fini (void);
-
/*
* Helpers
*/
@@ -644,11 +476,7 @@ inline
MonoNativeThreadId
ep_rt_mono_native_thread_id_get (void)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
return mono_native_thread_id_get ();
-#else
- return ep_rt_mono_func_table_get ()->ep_rt_mono_native_thread_id_get ();
-#endif
}
static
@@ -656,27 +484,7 @@ inline
gboolean
ep_rt_mono_native_thread_id_equals (MonoNativeThreadId id1, MonoNativeThreadId id2)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
return mono_native_thread_id_equals (id1, id2);
-#else
- return ep_rt_mono_func_table_get ()->ep_rt_mono_native_thread_id_equals (id1, id2);
-#endif
-}
-
-static
-inline
-gboolean
-ep_rt_mono_rand_try_get_bytes (guchar *buffer, gssize buffer_size, MonoError *error)
-{
- return ep_rt_mono_func_table_get ()->ep_rt_mono_rand_try_get_bytes (buffer, buffer_size, error);
-}
-
-static
-inline
-void
-ep_rt_mono_thread_exited (void)
-{
- ep_rt_mono_func_table_get ()->ep_rt_mono_thread_exited ();
}
static
@@ -684,11 +492,8 @@ inline
gpointer
ep_rt_mono_w32file_create (const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
+ //TODO, replace with low level PAL implementation.
return mono_w32file_create (name, fileaccess, sharemode, createmode, attrs);
-#else
- return ep_rt_mono_func_table_get ()->ep_rt_mono_w32file_create (name, fileaccess, sharemode, createmode, attrs);
-#endif
}
static
@@ -696,11 +501,8 @@ inline
gboolean
ep_rt_mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten, gint32 *win32error)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
+ //TODO, replace with low level PAL implementation.
return mono_w32file_write (handle, buffer, numbytes, byteswritten, win32error);
-#else
- return ep_rt_mono_func_table_get ()->ep_rt_mono_w32file_write (handle, buffer, numbytes, byteswritten, win32error);
-#endif
}
static
@@ -708,11 +510,8 @@ inline
gboolean
ep_rt_mono_w32file_close (gpointer handle)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
+ //TODO, replace with low level PAL implementation.
return mono_w32file_close (handle);
-#else
- return ep_rt_mono_func_table_get ()->ep_rt_mono_w32file_close (handle);
-#endif
}
static
@@ -720,7 +519,8 @@ inline
void
ep_rt_mono_thread_setup (bool background_thread)
{
- ep_rt_mono_func_table_get ()->ep_rt_mono_thread_attach (background_thread);
+ extern void * ep_rt_mono_thread_attach (bool background_thread);
+ ep_rt_mono_thread_attach (background_thread);
}
static
@@ -728,7 +528,8 @@ inline
void
ep_rt_mono_thread_teardown (void)
{
- ep_rt_mono_func_table_get ()->ep_rt_mono_thread_detach ();
+ extern void ep_rt_mono_thread_detach (void);
+ ep_rt_mono_thread_detach ();
}
/*
@@ -803,7 +604,9 @@ inline
void
ep_rt_init (void)
{
- mono_eventpipe_init (ep_rt_mono_func_table_get (), thread_holder_alloc_func, thread_holder_free_func);
+ extern void ep_rt_mono_init (void);
+ ep_rt_mono_init ();
+
ep_rt_spin_lock_alloc (ep_rt_mono_config_lock_get ());
}
@@ -816,7 +619,9 @@ ep_rt_shutdown (void)
mono_lazy_cleanup (os_command_line_get_init (), os_command_line_lazy_clean);
ep_rt_spin_lock_free (ep_rt_mono_config_lock_get ());
- mono_eventpipe_fini ();
+
+ extern void ep_rt_mono_fini (void);
+ ep_rt_mono_fini ();
}
static
@@ -860,7 +665,8 @@ ep_rt_walk_managed_stack_for_thread (
ep_rt_thread_handle_t thread,
EventPipeStackContents *stack_contents)
{
- return (ep_rt_mono_func_table_get ()->ep_rt_mono_walk_managed_stack_for_thread (thread, stack_contents) == TRUE) ? true : false;
+ extern bool ep_rt_mono_walk_managed_stack_for_thread (ep_rt_thread_handle_t thread, EventPipeStackContents *stack_contents);
+ return ep_rt_mono_walk_managed_stack_for_thread (thread, stack_contents);
}
static
@@ -871,7 +677,8 @@ ep_rt_method_get_simple_assembly_name (
ep_char8_t *name,
size_t name_len)
{
- return (ep_rt_mono_func_table_get ()->ep_rt_mono_method_get_simple_assembly_name (method, name, name_len) == TRUE) ? true : false;
+ extern bool ep_rt_mono_method_get_simple_assembly_name (ep_rt_method_desc_t *method, ep_char8_t *name, size_t name_len);
+ return ep_rt_mono_method_get_simple_assembly_name (method, name, name_len);
}
static
@@ -882,7 +689,8 @@ ep_rt_method_get_full_name (
ep_char8_t *name,
size_t name_len)
{
- return (ep_rt_mono_func_table_get ()->ep_rt_mono_method_get_full_name (method, name, name_len) == TRUE) ? true : false;
+ extern bool ep_rt_mono_method_get_full_name (ep_rt_method_desc_t *method, ep_char8_t *name, size_t name_len);
+ return ep_rt_mono_method_get_full_name (method, name, name_len);
}
static
@@ -898,6 +706,7 @@ inline
void
ep_rt_init_providers_and_events (void)
{
+ extern void ep_rt_mono_init_providers_and_events (void);
ep_rt_mono_init_providers_and_events ();
}
@@ -1089,7 +898,8 @@ static
void
ep_rt_sample_profiler_write_sampling_event_for_threads (ep_rt_thread_handle_t sampling_thread, EventPipeEvent *sampling_event)
{
- ep_rt_mono_func_table_get ()->ep_rt_mono_sample_profiler_write_sampling_event_for_threads (sampling_thread, sampling_event);
+ extern bool ep_rt_mono_sample_profiler_write_sampling_event_for_threads (ep_rt_thread_handle_t sampling_thread, EventPipeEvent *sampling_event);
+ ep_rt_mono_sample_profiler_write_sampling_event_for_threads (sampling_thread, sampling_event);
}
static
@@ -1196,12 +1006,9 @@ ep_rt_wait_event_alloc (
bool manual,
bool initial)
{
+ //TODO, replace with low level PAL implementation.
EP_ASSERT (wait_event != NULL);
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
wait_event->event = mono_w32event_create (manual, initial);
-#else
- wait_event->event = ep_rt_mono_func_table_get ()->ep_rt_mono_w32event_create (manual, initial);
-#endif
}
static
@@ -1209,12 +1016,9 @@ inline
void
ep_rt_wait_event_free (ep_rt_wait_event_handle_t *wait_event)
{
+ //TODO, replace with low level PAL implementation.
if (wait_event != NULL && wait_event->event != NULL) {
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
mono_w32event_close (wait_event->event);
-#else
- ep_rt_mono_func_table_get ()->ep_rt_mono_w32event_close (wait_event->event);
-#endif
wait_event->event = NULL;
}
}
@@ -1224,12 +1028,9 @@ inline
bool
ep_rt_wait_event_set (ep_rt_wait_event_handle_t *wait_event)
{
+ //TODO, replace with low level PAL implementation.
EP_ASSERT (wait_event != NULL && wait_event->event != NULL);
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
mono_w32event_set (wait_event->event);
-#else
- ep_rt_mono_func_table_get ()->ep_rt_mono_w32event_set (wait_event->event);
-#endif
return true;
}
@@ -1241,12 +1042,9 @@ ep_rt_wait_event_wait (
uint32_t timeout,
bool alertable)
{
+ //TODO, replace with low level PAL implementation.
EP_ASSERT (wait_event != NULL && wait_event->event != NULL);
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
return (int32_t)mono_w32handle_wait_one (wait_event->event, timeout, alertable);
-#else
- return (int32_t)ep_rt_mono_func_table_get ()->ep_rt_mono_w32hadle_wait_one (wait_event->event, timeout, alertable);
-#endif
}
static
@@ -1290,11 +1088,7 @@ inline
bool
ep_rt_process_detach (void)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
return (mono_runtime_is_shutting_down () == TRUE) ? true : false;
-#else
- return (ep_rt_mono_func_table_get ()->ep_rt_mono_runtime_is_shutting_down () == TRUE) ? true : false;
-#endif
}
static
@@ -1315,8 +1109,8 @@ ep_rt_create_activity_id (
EP_ASSERT (activity_id != NULL);
EP_ASSERT (activity_id_len == EP_ACTIVITY_ID_SIZE);
- ERROR_DECL (error);
- ep_rt_mono_rand_try_get_bytes ((guchar *)activity_id, EP_ACTIVITY_ID_SIZE, error);
+ extern bool ep_rt_mono_rand_try_get_bytes (uint8_t *buffer,size_t buffer_size);
+ ep_rt_mono_rand_try_get_bytes ((guchar *)activity_id, EP_ACTIVITY_ID_SIZE);
const uint16_t version_mask = 0xF000;
const uint16_t random_guid_version = 0x4000;
@@ -1347,7 +1141,7 @@ inline
bool
ep_rt_is_running (void)
{
- return ep_rt_process_detach ();
+ return !ep_rt_process_detach ();
}
static
@@ -1357,8 +1151,10 @@ ep_rt_execute_rundown (void)
{
if (ep_rt_config_value_get_rundown () > 0) {
// Ask the runtime to emit rundown events.
- if (/*is_running &&*/ !ep_rt_process_shutdown ())
+ if (/*is_running &&*/ !ep_rt_process_shutdown ()) {
+ extern void ep_rt_mono_execute_rundown (void);
ep_rt_mono_execute_rundown ();
+ }
}
}
@@ -1431,11 +1227,7 @@ ep_rt_thread_create (
thread_params->thread_params.thread_func = thread_func;
thread_params->thread_params.thread_params = params;
thread_params->background_thread = true;
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
return (mono_thread_platform_create_thread (ep_rt_thread_mono_start_func, thread_params, NULL, (ep_rt_thread_id_t *)id) == TRUE) ? true : false;
-#else
- return (ep_rt_mono_func_table_get ()->ep_rt_mono_thread_platform_create_thread (ep_rt_thread_mono_start_func, thread_params, NULL, (ep_rt_thread_id_t *)id) == TRUE) ? true : false;
-#endif
}
return false;
@@ -1454,11 +1246,7 @@ inline
uint32_t
ep_rt_current_process_get_id (void)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
return (uint32_t)mono_process_current_pid ();
-#else
- return (uint32_t)ep_rt_mono_func_table_get ()->ep_rt_mono_process_current_pid ();
-#endif
}
static
@@ -1474,11 +1262,7 @@ inline
uint32_t
ep_rt_processors_get_count (void)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
return (uint32_t)mono_cpu_count ();
-#else
- return (uint32_t)ep_rt_mono_func_table_get ()->ep_rt_mono_cpu_count ();
-#endif
}
static
@@ -1486,11 +1270,7 @@ inline
ep_rt_thread_id_t
ep_rt_current_thread_get_id (void)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
return mono_native_thread_id_get ();
-#else
- return ep_rt_mono_func_table_get ()->ep_rt_mono_native_thread_id_get ();
-#endif
}
static
@@ -1498,6 +1278,7 @@ inline
int64_t
ep_rt_perf_counter_query (void)
{
+ extern int64_t ep_rt_mono_perf_counter_query (void);
return ep_rt_mono_perf_counter_query ();
}
@@ -1506,6 +1287,7 @@ inline
int64_t
ep_rt_perf_frequency_query (void)
{
+ extern int64_t ep_rt_mono_perf_frequency_query (void);
return ep_rt_mono_perf_frequency_query ();
}
@@ -1514,6 +1296,7 @@ inline
void
ep_rt_system_time_get (EventPipeSystemTime *system_time)
{
+ extern void ep_rt_mono_system_time_get (EventPipeSystemTime *system_time);
ep_rt_mono_system_time_get (system_time);
}
@@ -1522,6 +1305,7 @@ inline
int64_t
ep_rt_system_timestamp_get (void)
{
+ extern int64_t ep_rt_mono_system_timestamp_get (void);
return ep_rt_mono_system_timestamp_get ();
}
@@ -1530,11 +1314,7 @@ inline
int32_t
ep_rt_system_get_alloc_granularity (void)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
return (int32_t)mono_valloc_granule ();
-#else
- return (int32_t)ep_rt_mono_func_table_get ()->ep_rt_mono_valloc_granule ();
-#endif
}
static
@@ -1602,11 +1382,8 @@ inline
uint8_t *
ep_rt_valloc0 (size_t buffer_size)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
uint8_t *buffer = (uint8_t *)mono_valloc (NULL, buffer_size, MONO_MMAP_READ | MONO_MMAP_WRITE, MONO_MEM_ACCOUNT_PROFILER);
-#else
- uint8_t *buffer = (uint8_t *)ep_rt_mono_func_table_get ()->ep_rt_mono_valloc (NULL, buffer_size, MONO_MMAP_READ | MONO_MMAP_WRITE, MONO_MEM_ACCOUNT_PROFILER);
-#endif
+
if (buffer)
memset (buffer, 0, buffer_size);
return buffer;
@@ -1620,11 +1397,7 @@ ep_rt_vfree (
size_t buffer_size)
{
if (buffer)
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
mono_vfree (buffer, buffer_size, MONO_MEM_ACCOUNT_PROFILER);
-#else
- ep_rt_mono_func_table_get ()->ep_rt_mono_vfree (buffer, buffer_size, MONO_MEM_ACCOUNT_PROFILER);
-#endif
}
static
@@ -1663,6 +1436,7 @@ inline
void
ep_rt_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array)
{
+ extern void ep_rt_mono_os_environment_get_utf16 (ep_rt_env_array_utf16_t *env_array);
ep_rt_mono_os_environment_get_utf16 (env_array);
}
@@ -1706,13 +1480,43 @@ ep_rt_lock_requires_lock_not_held (const ep_rt_lock_handle_t *lock)
* SpinLock.
*/
+#ifdef EP_CHECKED_BUILD
+static
+inline
+void
+ep_rt_spin_lock_set_owning_thread_id (
+ ep_rt_spin_lock_handle_t *spin_lock,
+ MonoNativeThreadId thread_id)
+{
+ if (sizeof (spin_lock->owning_thread_id) == sizeof (uint32_t))
+ ep_rt_volatile_store_uint32_t ((uint32_t *)&spin_lock->owning_thread_id, MONO_NATIVE_THREAD_ID_TO_UINT (thread_id));
+ else if (sizeof (spin_lock->owning_thread_id) == sizeof (uint64_t))
+ ep_rt_volatile_store_uint64_t ((uint64_t *)&spin_lock->owning_thread_id, MONO_NATIVE_THREAD_ID_TO_UINT (thread_id));
+ else
+ spin_lock->owning_thread_id = thread_id;
+}
+
+static
+inline
+MonoNativeThreadId
+ep_rt_spin_lock_get_owning_thread_id (const ep_rt_spin_lock_handle_t *spin_lock)
+{
+ if (sizeof (spin_lock->owning_thread_id) == sizeof (uint32_t))
+ return MONO_UINT_TO_NATIVE_THREAD_ID (ep_rt_volatile_load_uint32_t ((const uint32_t *)&spin_lock->owning_thread_id));
+ else if (sizeof (spin_lock->owning_thread_id) == sizeof (uint64_t))
+ return MONO_UINT_TO_NATIVE_THREAD_ID (ep_rt_volatile_load_uint64_t ((const uint64_t *)&spin_lock->owning_thread_id));
+ else
+ return spin_lock->owning_thread_id;
+}
+#endif
+
static
inline
void
ep_rt_spin_lock_alloc (ep_rt_spin_lock_handle_t *spin_lock)
{
#ifdef EP_CHECKED_BUILD
- spin_lock->lock_is_held = false;
+ ep_rt_spin_lock_set_owning_thread_id (spin_lock, MONO_UINT_TO_NATIVE_THREAD_ID (0));
#endif
spin_lock->lock = g_new0 (MonoCoopMutex, 1);
if (spin_lock->lock)
@@ -1739,8 +1543,7 @@ ep_rt_spin_lock_aquire (ep_rt_spin_lock_handle_t *spin_lock)
if (spin_lock && spin_lock->lock) {
mono_coop_mutex_lock (spin_lock->lock);
#ifdef EP_CHECKED_BUILD
- spin_lock->owning_thread_id = ep_rt_mono_native_thread_id_get ();
- spin_lock->lock_is_held = true;
+ ep_rt_spin_lock_set_owning_thread_id (spin_lock, ep_rt_mono_native_thread_id_get ());
#endif
}
return true;
@@ -1753,8 +1556,7 @@ ep_rt_spin_lock_release (ep_rt_spin_lock_handle_t *spin_lock)
{
if (spin_lock && spin_lock->lock) {
#ifdef EP_CHECKED_BUILD
- spin_lock->lock_is_held = false;
- spin_lock->owning_thread_id = MONO_UINT_TO_NATIVE_THREAD_ID (0);
+ ep_rt_spin_lock_set_owning_thread_id (spin_lock, MONO_UINT_TO_NATIVE_THREAD_ID (0));
#endif
mono_coop_mutex_unlock (spin_lock->lock);
}
@@ -1767,7 +1569,7 @@ inline
void
ep_rt_spin_lock_requires_lock_held (const ep_rt_spin_lock_handle_t *spin_lock)
{
- g_assert (spin_lock->lock_is_held && ep_rt_mono_native_thread_id_equals (spin_lock->owning_thread_id, ep_rt_mono_native_thread_id_get ()));
+ g_assert (ep_rt_mono_native_thread_id_equals (ep_rt_spin_lock_get_owning_thread_id (spin_lock), ep_rt_mono_native_thread_id_get ()));
}
static
@@ -1775,7 +1577,7 @@ inline
void
ep_rt_spin_lock_requires_lock_not_held (const ep_rt_spin_lock_handle_t *spin_lock)
{
- g_assert (!spin_lock->lock_is_held || (spin_lock->lock_is_held && !ep_rt_mono_native_thread_id_equals (spin_lock->owning_thread_id, ep_rt_mono_native_thread_id_get ())));
+ g_assert (!ep_rt_mono_native_thread_id_equals (ep_rt_spin_lock_get_owning_thread_id (spin_lock), ep_rt_mono_native_thread_id_get ()));
}
#endif
@@ -2001,13 +1803,9 @@ inline
EventPipeThread *
ep_rt_thread_get (void)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
- extern MonoNativeTlsKey ep_rt_mono_thread_holder_tls_id;
- EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (ep_rt_mono_thread_holder_tls_id);
+ extern MonoNativeTlsKey _ep_rt_mono_thread_holder_tls_id;
+ EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (_ep_rt_mono_thread_holder_tls_id);
return thread_holder ? ep_thread_holder_get_thread (thread_holder) : NULL;
-#else
- return ep_rt_mono_func_table_get ()->ep_rt_mono_thread_get ();
-#endif
}
static
@@ -2016,8 +1814,10 @@ EventPipeThread *
ep_rt_thread_get_or_create (void)
{
EventPipeThread *thread = ep_rt_thread_get ();
- if (!thread)
- thread = ep_rt_mono_func_table_get ()->ep_rt_mono_thread_get_or_create ();
+ if (!thread) {
+ extern EventPipeThread * ep_rt_mono_thread_get_or_create (void);
+ thread = ep_rt_mono_thread_get_or_create ();
+ }
return thread;
}
@@ -2114,17 +1914,10 @@ int32_t
ep_rt_mono_thread_sleep (uint32_t ms, bool alertable)
{
gboolean alerted = false;
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
if (alertable)
return (int32_t)mono_thread_info_sleep (ms, &alerted);
else
return (int32_t)mono_thread_info_sleep (ms, NULL);
-#else
- if (alertable)
- return (int32_t)ep_rt_mono_func_table_get ()->ep_rt_mono_thread_info_sleep (ms, &alerted);
- else
- return (int32_t)ep_rt_mono_func_table_get ()->ep_rt_mono_thread_info_sleep (ms, NULL);
-#endif
}
static
@@ -2132,11 +1925,7 @@ inline
bool
ep_rt_mono_thread_yield (void)
{
-#ifdef EP_RT_MONO_USE_STATIC_RUNTIME
return (mono_thread_info_yield () == TRUE) ? true : false;
-#else
- return (ep_rt_mono_func_table_get ()->ep_rt_mono_thread_info_yield () == TRUE) ? true : false;
-#endif
}
// See src/coreclr/vm/spinlock.h for details.
@@ -2317,5 +2106,12 @@ ep_rt_volatile_store_ptr_without_barrier (
*ptr = value;
}
+/*
+ * EventPipe Native Events.
+ */
+
+bool
+ep_rt_mono_write_event_ee_startup_start (void);
+
#endif /* ENABLE_PERFTRACING */
#endif /* __EVENTPIPE_RT_MONO_H__ */
diff --git a/src/mono/mono/eventpipe/ep-rt-types-mono.h b/src/mono/mono/eventpipe/ep-rt-types-mono.h
index 484ee34d8c3a02..ef248e56af8b1e 100644
--- a/src/mono/mono/eventpipe/ep-rt-types-mono.h
+++ b/src/mono/mono/eventpipe/ep-rt-types-mono.h
@@ -68,8 +68,7 @@ struct _rt_mono_event_internal_t {
struct _rt_mono_lock_internal_t {
MonoCoopMutex *lock;
#ifdef EP_CHECKED_BUILD
- MonoNativeThreadId owning_thread_id;
- bool lock_is_held;
+ volatile MonoNativeThreadId owning_thread_id;
#endif
};
diff --git a/src/mono/mono/eventpipe/test/CMakeLists.txt b/src/mono/mono/eventpipe/test/CMakeLists.txt
index f0f5612ecd07c5..65784b823c4960 100644
--- a/src/mono/mono/eventpipe/test/CMakeLists.txt
+++ b/src/mono/mono/eventpipe/test/CMakeLists.txt
@@ -1,6 +1,7 @@
if(ENABLE_PERFTRACING)
- if(ENABLE_EVENTPIPE_TEST AND (NOT DISABLE_LIBS) AND (NOT DISABLE_EXECUTABLES))
+ # TODO: Add support for dynamic components once package/deploy have been resolved.
+ if(ENABLE_EVENTPIPE_TEST AND STATIC_COMPONENTS AND (NOT DISABLE_COMPONENTS) AND (NOT DISABLE_LIBS) AND (NOT DISABLE_EXECUTABLES))
set(EVENTPIPE_TEST_SOURCES "")
set(EVENTPIPE_TEST_HEADERS "")
@@ -26,42 +27,19 @@ if(ENABLE_PERFTRACING)
ep-tests-debug.h
)
- include_directories(
- ${PROJECT_SOURCE_DIR}/../../native/
- ${PROJECT_SOURCE_DIR}/..
- ${PROJECT_SOURCE_DIR}
- ${PROJECT_SOURCE_DIR}/eglib
- ${PROJECT_BINARY_DIR}/..
- ${PROJECT_BINARY_DIR}/eglib
- )
-
- if(HAVE_SYS_ICU)
- if(ICU_LIBDIR)
- set(ICU_LDFLAGS "-L${ICU_LIBDIR}")
- endif()
- endif()
-
- if(HOST_DARWIN)
- set(OS_LIBS "-framework CoreFoundation" "-framework Foundation")
- elseif(HOST_IOS)
- set(OS_LIBS "-framework CoreFoundation" "-lobjc" "-lc++")
- elseif(HOST_ANDROID)
- set(OS_LIBS m dl log)
- elseif(HOST_LINUX)
- set(OS_LIBS pthread m dl)
- elseif(HOST_WIN32)
- set(OS_LIBS bcrypt.lib ws2_32.lib version.lib winmm.lib)
- endif()
+ addprefix(EVENTPIPE_TEST_SOURCES ${MONO_EVENTPIPE_TEST_SOURCE_PATH} "${EVENTPIPE_TEST_SOURCES}")
+ addprefix(EVENTPIPE_TEST_HEADERS ${MONO_EVENTPIPE_TEST_SOURCE_PATH} "${EVENTPIPE_TEST_HEADERS}")
set(CMAKE_SKIP_RPATH 1)
add_executable(ep-test ${EVENTPIPE_TEST_SOURCES} ${EVENTPIPE_TEST_HEADERS})
+ target_sources(ep-test PRIVATE "${mono-components-objects}")
target_link_libraries(ep-test monosgen-static ${OS_LIBS} ${ICONV_LIB} ${LLVM_LIBS} ${ICU_LIBS})
if(ICU_LDFLAGS)
set_target_properties(ep-test PROPERTIES LINK_FLAGS ${ICU_LDFLAGS})
endif()
install(TARGETS ep-test RUNTIME)
- else(ENABLE_EVENTPIPE_TEST AND (NOT DISABLE_LIBS) AND (NOT DISABLE_EXECUTABLES))
+ else(ENABLE_EVENTPIPE_TEST AND STATIC_COMPONENTS AND (NOT DISABLE_COMPONENTS) AND (NOT DISABLE_LIBS) AND (NOT DISABLE_EXECUTABLES))
message(VERBOSE "Skip building native EventPipe library test runner.")
- endif(ENABLE_EVENTPIPE_TEST AND (NOT DISABLE_LIBS) AND (NOT DISABLE_EXECUTABLES))
+ endif(ENABLE_EVENTPIPE_TEST AND STATIC_COMPONENTS AND (NOT DISABLE_COMPONENTS) AND (NOT DISABLE_LIBS) AND (NOT DISABLE_EXECUTABLES))
endif(ENABLE_PERFTRACING)
diff --git a/src/mono/mono/eventpipe/test/ep-buffer-manager-tests.c b/src/mono/mono/eventpipe/test/ep-buffer-manager-tests.c
index 35f38084b0ba68..3a13b05911e8de 100644
--- a/src/mono/mono/eventpipe/test/ep-buffer-manager-tests.c
+++ b/src/mono/mono/eventpipe/test/ep-buffer-manager-tests.c
@@ -333,7 +333,7 @@ test_buffer_manager_read_event (void)
test_location = 5;
- ep_raise_error_if_nok (ep_event_instance_get_thread_id (ep_event_instance) == ep_rt_current_thread_get_id ());
+ ep_raise_error_if_nok (ep_event_instance_get_thread_id (ep_event_instance) == ep_rt_thread_id_t_to_uint64_t (ep_rt_current_thread_get_id ()));
ep_on_exit:
buffer_manager_fini (buffer_manager,thread, session, provider, ep_event);
@@ -581,11 +581,12 @@ test_buffer_manager_perf (void)
static RESULT
test_buffer_manager_teardown (void)
{
+#ifdef _CRTDBG_MAP_ALLOC
// Need to emulate a thread exit to make sure TLS gets cleaned up for current thread
// or we will get memory leaks reported.
+ extern void ep_rt_mono_thread_exited (void);
ep_rt_mono_thread_exited ();
-#ifdef _CRTDBG_MAP_ALLOC
_CrtMemCheckpoint (&eventpipe_memory_end_snapshot);
if ( _CrtMemDifference( &eventpipe_memory_diff_snapshot, &eventpipe_memory_start_snapshot, &eventpipe_memory_end_snapshot) ) {
_CrtMemDumpStatistics( &eventpipe_memory_diff_snapshot );
diff --git a/src/mono/mono/eventpipe/test/ep-setup-tests.c b/src/mono/mono/eventpipe/test/ep-setup-tests.c
index 30743664ac6c7f..6bb24553e7f356 100644
--- a/src/mono/mono/eventpipe/test/ep-setup-tests.c
+++ b/src/mono/mono/eventpipe/test/ep-setup-tests.c
@@ -12,6 +12,8 @@ test_setup (void)
if (core_root) {
mono_set_assemblies_path (core_root);
g_free (core_root);
+ } else {
+ mono_set_assemblies_path (".");
}
eventpipe_test_domain = mono_jit_init_version_for_test_only ("eventpipe-tests", "v4.0.30319");
diff --git a/src/mono/mono/eventpipe/test/ep-tests.c b/src/mono/mono/eventpipe/test/ep-tests.c
index 34179b61642b8b..b0e7803924551d 100644
--- a/src/mono/mono/eventpipe/test/ep-tests.c
+++ b/src/mono/mono/eventpipe/test/ep-tests.c
@@ -1256,6 +1256,7 @@ test_eventpipe_mem_checkpoint (void)
#ifdef _CRTDBG_MAP_ALLOC
// Need to emulate a thread exit to make sure TLS gets cleaned up for current thread
// or we will get memory leaks reported.
+ extern void ep_rt_mono_thread_exited (void);
ep_rt_mono_thread_exited ();
_CrtMemCheckpoint (&eventpipe_memory_end_snapshot);
diff --git a/src/mono/mono/eventpipe/test/ep-thread-tests.c b/src/mono/mono/eventpipe/test/ep-thread-tests.c
index 1ffe239b47c3dd..2eb85ff976c2da 100644
--- a/src/mono/mono/eventpipe/test/ep-thread-tests.c
+++ b/src/mono/mono/eventpipe/test/ep-thread-tests.c
@@ -128,6 +128,7 @@ test_get_or_create_thread (void)
// Need to emulate a thread exit to make sure TLS gets cleaned up for current thread
// or we will get memory leaks reported.
+ extern void ep_rt_mono_thread_exited (void);
ep_rt_mono_thread_exited ();
thread = ep_thread_get ();
@@ -199,6 +200,7 @@ test_thread_activity_id (void)
// Need to emulate a thread exit to make sure TLS gets cleaned up for current thread
// or we will get memory leaks reported.
+ extern void ep_rt_mono_thread_exited (void);
ep_rt_mono_thread_exited ();
thread = ep_thread_get ();
diff --git a/src/mono/mono/metadata/CMakeLists.txt b/src/mono/mono/metadata/CMakeLists.txt
index 4b56d07c440560..1b7ba75f6b0e44 100644
--- a/src/mono/mono/metadata/CMakeLists.txt
+++ b/src/mono/mono/metadata/CMakeLists.txt
@@ -71,6 +71,8 @@ set(metadata_common_sources
class-setup-vtable.c
cominterop.c
cominterop.h
+ components.h
+ components.c
coree.c
coree.h
coree-internals.h
diff --git a/src/mono/mono/metadata/appdomain.c b/src/mono/mono/metadata/appdomain.c
index 6426bc8729a168..9626f3a91e57c3 100644
--- a/src/mono/mono/metadata/appdomain.c
+++ b/src/mono/mono/metadata/appdomain.c
@@ -69,10 +69,7 @@
#include
#include
#include
-
-#ifdef ENABLE_PERFTRACING
-#include
-#endif
+#include
#ifdef HOST_WIN32
#include
@@ -281,10 +278,10 @@ mono_runtime_init_checked (MonoDomain *domain, MonoThreadStartCB start_cb, MonoT
mono_thread_internal_attach (domain);
-#if defined(ENABLE_PERFTRACING) && !defined(DISABLE_EVENTPIPE)
- ds_server_init ();
- ds_server_pause_for_diagnostics_monitor ();
-#endif
+ mono_component_diagnostics_server ()->init ();
+ mono_component_diagnostics_server ()->pause_for_diagnostics_monitor ();
+
+ mono_component_event_pipe ()->write_event_ee_startup_start ();
mono_type_initialization_init ();
diff --git a/src/mono/mono/metadata/class-internals.h b/src/mono/mono/metadata/class-internals.h
index 233e4ecc9b655e..2889d03722304e 100644
--- a/src/mono/mono/metadata/class-internals.h
+++ b/src/mono/mono/metadata/class-internals.h
@@ -16,6 +16,7 @@
#include "mono/sgen/gc-internal-agnostic.h"
#include "mono/utils/mono-error-internals.h"
#include "mono/utils/mono-memory-model.h"
+#include "mono/utils/mono-compiler.h"
#define MONO_CLASS_IS_ARRAY(c) (m_class_get_rank (c))
@@ -1126,6 +1127,7 @@ mono_identifier_escape_type_name_chars (const char* identifier);
char*
mono_type_get_full_name (MonoClass *klass);
+MONO_COMPONENT_API
char *
mono_method_get_name_full (MonoMethod *method, gboolean signature, gboolean ret, MonoTypeNameFormat format);
diff --git a/src/mono/mono/metadata/components.c b/src/mono/mono/metadata/components.c
new file mode 100644
index 00000000000000..6301566d6c45bb
--- /dev/null
+++ b/src/mono/mono/metadata/components.c
@@ -0,0 +1,194 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#include
+#include
+#include
+#include "mono/component/component.h"
+#include "mono/component/hot_reload.h"
+#include "mono/component/event_pipe.h"
+#include "mono/component/diagnostics_server.h"
+#include "mono/metadata/class-internals.h"
+#include "mono/metadata/components.h"
+#include "mono/utils/mono-dl.h"
+#include "mono/utils/mono-logger-internals.h"
+#include "mono/utils/mono-path.h"
+
+typedef MonoComponent * (*MonoComponentInitFn) (void);
+
+typedef struct _MonoComponentEntry {
+ const char *lib_name;
+ const char *name;
+ MonoComponentInitFn init;
+ MonoComponent **component;
+ MonoDl *lib;
+} MonoComponentEntry;
+
+#ifdef STATIC_COMPONENTS
+#define COMPONENT_INIT_FUNC(name) (MonoComponentInitFn) mono_component_ ## name ## _init
+#else
+#define COMPONENT_INIT_FUNC(name) (MonoComponentInitFn) mono_component_ ## name ## _stub_init
+#endif
+
+#define HOT_RELOAD_LIBRARY_NAME "hot_reload"
+#define HOT_RELOAD_COMPONENT_NAME HOT_RELOAD_LIBRARY_NAME
+MonoComponentHotReload *hot_reload = NULL;
+
+MonoComponentEventPipe *event_pipe = NULL;
+MonoComponentDiagnosticsServer *diagnostics_server = NULL;
+
+// DiagnosticsServer/EventPipe components currently hosted by diagnostics_tracing library.
+#define DIAGNOSTICS_TRACING_LIBRARY_NAME "diagnostics_tracing"
+#define EVENT_PIPE_COMPONENT_NAME "event_pipe"
+#define DIAGNOSTICS_SERVER_COMPONENT_NAME "diagnostics_server"
+
+/* One per component */
+MonoComponentEntry components[] = {
+ { HOT_RELOAD_LIBRARY_NAME, HOT_RELOAD_COMPONENT_NAME, COMPONENT_INIT_FUNC (hot_reload), (MonoComponent**)&hot_reload, NULL },
+ { DIAGNOSTICS_TRACING_LIBRARY_NAME, EVENT_PIPE_COMPONENT_NAME, COMPONENT_INIT_FUNC (event_pipe), (MonoComponent**)&event_pipe, NULL },
+ { DIAGNOSTICS_TRACING_LIBRARY_NAME, DIAGNOSTICS_SERVER_COMPONENT_NAME, COMPONENT_INIT_FUNC (diagnostics_server), (MonoComponent**)&diagnostics_server, NULL },
+};
+
+#ifndef STATIC_COMPONENTS
+static MonoComponent*
+get_component (const MonoComponentEntry *component, MonoDl **component_lib);
+#endif
+
+void
+mono_components_init (void)
+{
+#ifdef STATIC_COMPONENTS
+ /* directly call each components init function */
+ /* TODO: support disabled components.
+ *
+ * The issue here is that we need to do static linking, so if we don't
+ * directly reference mono_component__init anywhere (ie
+ * if we dlsym from RTLD_DEFAULT) the static linking of the final
+ * binary won't actually include that symbol (unless we play
+ * platform-specific linker tricks).
+ *
+ * So maybe we will need some API hook so that embedders need to call
+ * to pass us the address of each component that isn't disabled.
+ *
+ */
+ for (int i = 0; i < G_N_ELEMENTS (components); ++i)
+ *components [i].component = components [i].init ();
+#else
+ /* call get_component for each component and init it or its stubs and add it to loaded_components */
+ MonoDl *lib = NULL;
+
+ for (int i = 0; i < G_N_ELEMENTS (components); ++i) {
+ *components [i].component = get_component (&components [i], &lib);
+ components [i].lib = lib;
+ if (!*components [i].component)
+ *components [i].component = components [i].init ();
+ }
+#endif
+ /* validate components interface version */
+ for (int i = 0; i < G_N_ELEMENTS (components); ++i) {
+ guint64 version = (guint64)(*components [i].component)->itf_version;
+ g_assertf (version == MONO_COMPONENT_ITF_VERSION, "%s component returned unexpected interface version (expected %" PRIu64 " got %" PRIu64 ")", components [i].name, (guint64)MONO_COMPONENT_ITF_VERSION, version);
+ }
+}
+
+static char*
+component_init_name (const MonoComponentEntry *component)
+{
+ return g_strdup_printf ("mono_component_%s_init", component->name);
+}
+
+static gpointer
+load_component_entrypoint (MonoDl *lib, const MonoComponentEntry *component)
+{
+ char *component_init = component_init_name (component);
+ gpointer sym = NULL;
+ char *error_msg = mono_dl_symbol (lib, component_init, &sym);
+ if (error_msg) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Component %s library does not have symbol %s: %s", component->name, component_init, error_msg);
+ g_free (error_msg);
+ g_free (component_init);
+ return NULL;
+ }
+ g_free (component_init);
+ return sym;
+}
+
+#ifndef STATIC_COMPONENTS
+static char*
+component_library_base_name (const MonoComponentEntry *component)
+{
+ return g_strdup_printf ("mono-component-%s", component->lib_name);
+}
+
+static char *
+components_dir (void)
+{
+ static char *dir = NULL;
+ if (!dir) {
+ char buf[4096];
+ if (g_module_address ((void *)components_dir, buf, sizeof (buf), NULL, NULL, 0, NULL)) {
+ char *resolvedname = mono_path_resolve_symlinks (buf);
+ dir = g_path_get_dirname (resolvedname);
+ g_free (resolvedname);
+ }
+ }
+ return dir;
+}
+
+static MonoDl*
+try_load (const char* dir, const MonoComponentEntry *component, const char* component_base_lib)
+{
+ MonoDl *lib = NULL;
+ void *iter = NULL;
+ char *path = NULL;
+ while ((path = mono_dl_build_path (dir, component_base_lib, &iter)) && !lib) {
+ char *error_msg = NULL;
+ lib = mono_dl_open (path, MONO_DL_EAGER, &error_msg);
+ if (!lib) {
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Component %s not found: %s", component->name, error_msg);
+ g_free (error_msg);
+ continue;
+ }
+ }
+ if (lib)
+ mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_DLLIMPORT, "Component %s found at %s", component->name, path);
+ g_free (path);
+ return lib;
+}
+
+static MonoComponentInitFn
+load_component (const MonoComponentEntry *component, MonoDl **lib_out)
+{
+ char *component_base_lib = component_library_base_name (component);
+ MonoComponentInitFn result = NULL;
+
+ /* FIXME: just copy what mono_profiler_load does, assuming it works */
+
+ /* FIXME: do I need to provide a path? */
+ MonoDl *lib = NULL;
+ lib = try_load (components_dir (), component, component_base_lib);
+ if (!lib)
+ lib = try_load (NULL, component, component_base_lib);
+
+ g_free (component_base_lib);
+ if (!lib)
+ goto done;
+
+ gpointer sym = load_component_entrypoint (lib, component);
+
+ result = (MonoComponentInitFn)sym;
+ *lib_out = lib;
+done:
+ return result;
+}
+
+MonoComponent*
+get_component (const MonoComponentEntry *component, MonoDl **lib_out)
+{
+ MonoComponentInitFn initfn = load_component (component, lib_out);
+ if (!initfn)
+ return NULL;
+ return initfn();
+}
+#endif
diff --git a/src/mono/mono/metadata/components.h b/src/mono/mono/metadata/components.h
new file mode 100644
index 00000000000000..2fd82eaf97e398
--- /dev/null
+++ b/src/mono/mono/metadata/components.h
@@ -0,0 +1,51 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+#ifndef _MONO_METADATA_COMPONENTS_H
+#define _MONO_METADATA_COMPONENTS_H
+
+#include
+#include
+#include
+#include
+
+void
+mono_components_init (void);
+
+/* Declare each component's getter function here */
+static inline
+MonoComponentHotReload *
+mono_component_hot_reload (void)
+{
+ extern MonoComponentHotReload *hot_reload;
+ return hot_reload;
+}
+
+static inline
+MonoComponentEventPipe *
+mono_component_event_pipe (void)
+{
+ extern MonoComponentEventPipe *event_pipe;
+ return event_pipe;
+}
+
+static inline
+MonoComponentDiagnosticsServer *
+mono_component_diagnostics_server (void)
+{
+ extern MonoComponentDiagnosticsServer *diagnostics_server;
+ return diagnostics_server;
+}
+
+/* Declare each copomnents stub init function here */
+MonoComponentHotReload *
+mono_component_hot_reload_stub_init (void);
+
+MonoComponentEventPipe *
+mono_component_event_pipe_stub_init (void);
+
+MonoComponentDiagnosticsServer *
+mono_component_diagnostics_server_stub_init (void);
+
+#endif/*_MONO_METADATA_COMPONENTS_H*/
diff --git a/src/mono/mono/metadata/environment-internals.h b/src/mono/mono/metadata/environment-internals.h
index cfd13afc4d53b6..510f4222c90ede 100644
--- a/src/mono/mono/metadata/environment-internals.h
+++ b/src/mono/mono/metadata/environment-internals.h
@@ -7,10 +7,12 @@
#ifndef _MONO_METADATA_ENVIRONMENT_INTERNALS_H_
#define _MONO_METADATA_ENVIRONMENT_INTERNALS_H_
+#include
+
void
mono_set_os_args (int argc, char **argv);
-char *
+MONO_COMPONENT_API char *
mono_get_os_cmd_line (void);
#endif /* _MONO_METADATA_ENVIRONMENT_INTERNALS_H_ */
diff --git a/src/mono/mono/metadata/gc-internals.h b/src/mono/mono/metadata/gc-internals.h
index f52deb7dbda4d8..34203f25357957 100644
--- a/src/mono/mono/metadata/gc-internals.h
+++ b/src/mono/mono/metadata/gc-internals.h
@@ -18,6 +18,7 @@
#include
#include
#include
+#include
/* Register a memory area as a conservatively scanned GC root */
#define MONO_GC_REGISTER_ROOT_PINNING(x,src,key,msg) mono_gc_register_root ((char*)&(x), sizeof(x), MONO_GC_DESCRIPTOR_NULL, (src), (key), (msg))
@@ -426,7 +427,7 @@ extern gchar **mono_do_not_finalize_class_names;
* Unified runtime stop/restart world, SGEN Only.
* Will take and release the LOCK_GC.
*/
-void mono_stop_world (MonoThreadInfoFlags flags);
-void mono_restart_world (MonoThreadInfoFlags flags);
+MONO_COMPONENT_API void mono_stop_world (MonoThreadInfoFlags flags);
+MONO_COMPONENT_API void mono_restart_world (MonoThreadInfoFlags flags);
#endif /* __MONO_METADATA_GC_INTERNAL_H__ */
diff --git a/src/mono/mono/metadata/icall-eventpipe.c b/src/mono/mono/metadata/icall-eventpipe.c
index c8ab05a558af30..53755c6b2f0277 100644
--- a/src/mono/mono/metadata/icall-eventpipe.c
+++ b/src/mono/mono/metadata/icall-eventpipe.c
@@ -1,206 +1,15 @@
#include
#include
#include
-
#include
#if defined(ENABLE_PERFTRACING) && !defined(DISABLE_EVENTPIPE)
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-// Rundown flags.
-#define METHOD_FLAGS_DYNAMIC_METHOD 0x1
-#define METHOD_FLAGS_GENERIC_METHOD 0x2
-#define METHOD_FLAGS_SHARED_GENERIC_METHOD 0x4
-#define METHOD_FLAGS_JITTED_METHOD 0x8
-#define METHOD_FLAGS_JITTED_HELPER_METHOD 0x10
-
-#define MODULE_FLAGS_NATIVE_MODULE 0x2
-#define MODULE_FLAGS_DYNAMIC_MODULE 0x4
-#define MODULE_FLAGS_MANIFEST_MODULE 0x8
-
-#define ASSEMBLY_FLAGS_DYNAMIC_ASSEMBLY 0x2
-#define ASSEMBLY_FLAGS_NATIVE_ASSEMBLY 0x4
-#define ASSEMBLY_FLAGS_COLLECTIBLE_ASSEMBLY 0x8
-
-#define DOMAIN_FLAGS_DEFAULT_DOMAIN 0x1
-#define DOMAIN_FLAGS_EXECUTABLE_DOMAIN 0x2
-
-typedef enum _EventPipeActivityControlCode {
- EP_ACTIVITY_CONTROL_GET_ID = 1,
- EP_ACTIVITY_CONTROL_SET_ID = 2,
- EP_ACTIVITY_CONTROL_CREATE_ID = 3,
- EP_ACTIVITY_CONTROL_GET_SET_ID = 4,
- EP_ACTIVITY_CONTROL_CREATE_SET_ID = 5
-} EventPipeActivityControlCode;
-
-typedef struct _EventPipeProviderConfigurationNative {
- gunichar2 *provider_name;
- uint64_t keywords;
- uint32_t logging_level;
- gunichar2 *filter_data;
-} EventPipeProviderConfigurationNative;
-
-typedef struct _EventPipeSessionInfo {
- int64_t starttime_as_utc_filetime;
- int64_t start_timestamp;
- int64_t timestamp_frequency;
-} EventPipeSessionInfo;
-
-typedef struct _EventPipeEventInstanceData {
- intptr_t provider_id;
- uint32_t event_id;
- uint32_t thread_id;
- int64_t timestamp;
- uint8_t activity_id [EP_ACTIVITY_ID_SIZE];
- uint8_t related_activity_id [EP_ACTIVITY_ID_SIZE];
- const uint8_t *payload;
- uint32_t payload_len;
-} EventPipeEventInstanceData;
-
-typedef struct _EventPipeFireMethodEventsData{
- MonoDomain *domain;
- uint8_t *buffer;
- size_t buffer_size;
- ep_rt_mono_fire_method_rundown_events_func method_events_func;
-} EventPipeFireMethodEventsData;
-
-typedef struct _EventPipeSampleProfileData {
- EventPipeStackContents stack_contents;
- uint64_t thread_id;
- uintptr_t thread_ip;
- uint32_t payload_data;
-} EventPipeSampleProfileData;
-
-gboolean ep_rt_mono_initialized;
-MonoNativeTlsKey ep_rt_mono_thread_holder_tls_id;
-gpointer ep_rt_mono_rand_provider;
-
-static ep_rt_thread_holder_alloc_func thread_holder_alloc_callback_func;
-static ep_rt_thread_holder_free_func thread_holder_free_callback_func;
-
-static GArray * _ep_rt_mono_sampled_thread_callstacks = NULL;
-static uint32_t _ep_rt_mono_max_sampled_thread_count = 32;
+#include
/*
* Forward declares of all static functions.
*/
-static
-gboolean
-rand_try_get_bytes_func (
- guchar *buffer,
- gssize buffer_size,
- MonoError *error);
-
-static
-EventPipeThread *
-eventpipe_thread_get (void);
-
-static
-EventPipeThread *
-eventpipe_thread_get_or_create (void);
-
-static
-void
-eventpipe_thread_exited (void);
-
-static
-void
-profiler_eventpipe_thread_exited (
- MonoProfiler *prof,
- uintptr_t tid);
-
-static
-gpointer
-eventpipe_thread_attach (gboolean background_thread);
-
-static
-void
-eventpipe_thread_detach (void);
-
-static
-void
-eventpipe_fire_method_events (
- MonoJitInfo *ji,
- MonoMethod *method,
- EventPipeFireMethodEventsData *events_data);
-
-static
-void
-eventpipe_fire_method_events_func (
- MonoJitInfo *ji,
- gpointer user_data);
-
-static
-void
-eventpipe_fire_assembly_events (
- MonoDomain *domain,
- MonoAssembly *assembly,
- ep_rt_mono_fire_assembly_rundown_events_func assembly_events_func);
-
-static
-gboolean
-eventpipe_execute_rundown (
- ep_rt_mono_fire_domain_rundown_events_func domain_events_func,
- ep_rt_mono_fire_assembly_rundown_events_func assembly_events_func,
- ep_rt_mono_fire_method_rundown_events_func methods_events_func);
-
-static
-gboolean
-eventpipe_walk_managed_stack_for_thread_func (
- MonoStackFrameInfo *frame,
- MonoContext *ctx,
- gpointer data);
-
-static
-gboolean
-eventpipe_walk_managed_stack_for_thread (
- ep_rt_thread_handle_t thread,
- EventPipeStackContents *stack_contents);
-
-static
-gboolean
-eventpipe_sample_profiler_walk_managed_stack_for_thread_func (
- MonoStackFrameInfo *frame,
- MonoContext *ctx,
- gpointer data);
-
-static
-gboolean
-eventpipe_sample_profiler_write_sampling_event_for_threads (
- ep_rt_thread_handle_t sampling_thread,
- EventPipeEvent *sampling_event);
-
-static
-gboolean
-eventpipe_method_get_simple_assembly_name (
- ep_rt_method_desc_t *method,
- ep_char8_t *name,
- size_t name_len);
-
-static
-gboolean
-evetpipe_method_get_full_name (
- ep_rt_method_desc_t *method,
- ep_char8_t *name,
- size_t name_len);
-
static
void
delegate_callback_data_free_func (
@@ -218,578 +27,6 @@ delegate_callback_func (
EventFilterDescriptor *filter_data,
void *callback_context);
-static
-gboolean
-rand_try_get_bytes_func (
- guchar *buffer,
- gssize buffer_size,
- MonoError *error)
-{
- g_assert (ep_rt_mono_rand_provider != NULL);
- return mono_rand_try_get_bytes (&ep_rt_mono_rand_provider, buffer, buffer_size, error);
-}
-
-static
-EventPipeThread *
-eventpipe_thread_get (void)
-{
- EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (ep_rt_mono_thread_holder_tls_id);
- return thread_holder ? ep_thread_holder_get_thread (thread_holder) : NULL;
-}
-
-static
-EventPipeThread *
-eventpipe_thread_get_or_create (void)
-{
- EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (ep_rt_mono_thread_holder_tls_id);
- if (!thread_holder && thread_holder_alloc_callback_func) {
- thread_holder = thread_holder_alloc_callback_func ();
- mono_native_tls_set_value (ep_rt_mono_thread_holder_tls_id, thread_holder);
- }
- return ep_thread_holder_get_thread (thread_holder);
-}
-
-static
-void
-eventpipe_thread_exited (void)
-{
- if (ep_rt_mono_initialized) {
- EventPipeThreadHolder *thread_holder = (EventPipeThreadHolder *)mono_native_tls_get_value (ep_rt_mono_thread_holder_tls_id);
- if (thread_holder && thread_holder_free_callback_func)
- thread_holder_free_callback_func (thread_holder);
- mono_native_tls_set_value (ep_rt_mono_thread_holder_tls_id, NULL);
- }
-}
-
-static
-void
-profiler_eventpipe_thread_exited (
- MonoProfiler *prof,
- uintptr_t tid)
-{
- eventpipe_thread_exited ();
-}
-
-static
-gpointer
-eventpipe_thread_attach (gboolean background_thread)
-{
- MonoThread *thread = NULL;
-
- // NOTE, under netcore, only root domain exists.
- if (!mono_thread_current ()) {
- thread = mono_thread_internal_attach (mono_get_root_domain ());
- if (background_thread && thread) {
- mono_thread_set_state (thread, ThreadState_Background);
- mono_thread_info_set_flags (MONO_THREAD_INFO_FLAGS_NO_SAMPLE);
- }
- }
-
- return thread;
-}
-
-static
-void
-eventpipe_thread_detach (void)
-{
- MonoThread *current_thread = mono_thread_current ();
- if (current_thread)
- mono_thread_internal_detach (current_thread);
-}
-
-static
-void
-eventpipe_fire_method_events (
- MonoJitInfo *ji,
- MonoMethod *method,
- EventPipeFireMethodEventsData *events_data)
-{
- g_assert_checked (ji != NULL);
- g_assert_checked (events_data->domain != NULL);
- g_assert_checked (events_data->method_events_func != NULL);
-
- uint64_t method_id = 0;
- uint64_t module_id = 0;
- uint64_t method_code_start = (uint64_t)ji->code_start;
- uint32_t method_code_size = (uint32_t)ji->code_size;
- uint32_t method_token = 0;
- uint32_t method_flags = 0;
- uint8_t kind = MONO_CLASS_DEF;
- char *method_namespace = NULL;
- const char *method_name = NULL;
- char *method_signature = NULL;
-
- //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc.
-
- if (method) {
- method_id = (uint64_t)method;
- method_token = method->token;
-
- if (mono_jit_info_get_generic_sharing_context (ji))
- method_flags |= METHOD_FLAGS_SHARED_GENERIC_METHOD;
-
- if (method->dynamic)
- method_flags |= METHOD_FLAGS_DYNAMIC_METHOD;
-
- if (!ji->from_aot && !ji->from_llvm) {
- method_flags |= METHOD_FLAGS_JITTED_METHOD;
- if (method->wrapper_type != MONO_WRAPPER_NONE)
- method_flags |= METHOD_FLAGS_JITTED_HELPER_METHOD;
- }
-
- if (method->is_generic || method->is_inflated)
- method_flags |= METHOD_FLAGS_GENERIC_METHOD;
-
- method_name = method->name;
- method_signature = mono_signature_full_name (method->signature);
-
- if (method->klass) {
- module_id = (uint64_t)m_class_get_image (method->klass);
- kind = m_class_get_class_kind (method->klass);
- if (kind == MONO_CLASS_GTD || kind == MONO_CLASS_GINST)
- method_flags |= METHOD_FLAGS_GENERIC_METHOD;
- method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL);
- }
- }
-
- uint16_t offset_entries = 0;
- uint32_t *il_offsets = NULL;
- uint32_t *native_offsets = NULL;
-
- MonoDebugMethodJitInfo *debug_info = method ? mono_debug_find_method (method, events_data->domain) : NULL;
- if (debug_info) {
- offset_entries = debug_info->num_line_numbers;
- size_t needed_size = (offset_entries * sizeof (uint32_t) * 2);
- if (!events_data->buffer || needed_size > events_data->buffer_size) {
- g_free (events_data->buffer);
- events_data->buffer_size = (size_t)(needed_size * 1.5);
- events_data->buffer = g_new (uint8_t, events_data->buffer_size);
- }
-
- if (events_data->buffer) {
- il_offsets = (uint32_t*)events_data->buffer;
- native_offsets = il_offsets + offset_entries;
-
- for (int offset_count = 0; offset_count < offset_entries; ++offset_count) {
- il_offsets [offset_count] = debug_info->line_numbers [offset_count].il_offset;
- native_offsets [offset_count] = debug_info->line_numbers [offset_count].native_offset;
- }
- }
-
- mono_debug_free_method_jit_info (debug_info);
- }
-
- if (events_data->buffer && !il_offsets && !native_offsets) {
- // No IL offset -> Native offset mapping available. Put all code on IL offset 0.
- g_assert_checked (events_data->buffer_size >= sizeof (uint32_t) * 2);
- offset_entries = 1;
- il_offsets = (uint32_t*)events_data->buffer;
- native_offsets = il_offsets + offset_entries;
- il_offsets [0] = 0;
- native_offsets [0] = (uint32_t)ji->code_size;
- }
-
- events_data->method_events_func (
- method_id,
- module_id,
- method_code_start,
- method_code_size,
- method_token,
- method_flags,
- (ep_char8_t *)method_namespace,
- (ep_char8_t *)method_name,
- (ep_char8_t *)method_signature,
- offset_entries,
- il_offsets,
- native_offsets,
- NULL);
-
- g_free (method_namespace);
- g_free (method_signature);
-}
-
-static
-void
-eventpipe_fire_method_events_func (
- MonoJitInfo *ji,
- gpointer user_data)
-{
- EventPipeFireMethodEventsData *events_data = (EventPipeFireMethodEventsData *)user_data;
- g_assert_checked (events_data != NULL);
-
- if (ji && !ji->is_trampoline && !ji->async) {
- MonoMethod *method = jinfo_get_method (ji);
- if (method && !m_method_is_wrapper (method))
- eventpipe_fire_method_events (ji, method, events_data);
- }
-}
-
-static
-void
-eventpipe_fire_assembly_events (
- MonoDomain *domain,
- MonoAssembly *assembly,
- ep_rt_mono_fire_assembly_rundown_events_func assembly_events_func)
-{
- g_assert_checked (domain != NULL);
- g_assert_checked (assembly != NULL);
- g_assert_checked (assembly_events_func != NULL);
-
- uint64_t domain_id = (uint64_t)domain;
- uint64_t module_id = (uint64_t)assembly->image;
- uint64_t assembly_id = (uint64_t)assembly;
-
- // TODO: Extract all module IL/Native paths and pdb metadata when available.
- const char *module_il_path = "";
- const char *module_il_pdb_path = "";
- const char *module_native_path = "";
- const char *module_native_pdb_path = "";
- uint8_t signature [EP_GUID_SIZE] = { 0 };
- uint32_t module_il_pdb_age = 0;
- uint32_t module_native_pdb_age = 0;
-
- uint32_t reserved_flags = 0;
- uint64_t binding_id = 0;
-
- // Native methods are part of JIT table and already emitted.
- // TODO: FireEtwMethodDCEndVerbose_V1_or_V2 for all native methods in module as well?
-
- // Netcore has a 1:1 between assemblies and modules, so its always a manifest module.
- uint32_t module_flags = MODULE_FLAGS_MANIFEST_MODULE;
- if (assembly->image) {
- if (assembly->image->dynamic)
- module_flags |= MODULE_FLAGS_DYNAMIC_MODULE;
- if (assembly->image->aot_module)
- module_flags |= MODULE_FLAGS_NATIVE_MODULE;
-
- module_il_path = assembly->image->filename ? assembly->image->filename : "";
- }
-
- uint32_t assembly_flags = 0;
- if (assembly->dynamic)
- assembly_flags |= ASSEMBLY_FLAGS_DYNAMIC_ASSEMBLY;
-
- if (assembly->image && assembly->image->aot_module) {
- assembly_flags |= ASSEMBLY_FLAGS_NATIVE_ASSEMBLY;
- }
-
- char *assembly_name = mono_stringify_assembly_name (&assembly->aname);
-
- assembly_events_func (
- domain_id,
- assembly_id,
- assembly_flags,
- binding_id,
- (const ep_char8_t*)assembly_name,
- module_id,
- module_flags,
- reserved_flags,
- (const ep_char8_t *)module_il_path,
- (const ep_char8_t *)module_native_path,
- signature,
- module_il_pdb_age,
- (const ep_char8_t *)module_il_pdb_path,
- signature,
- module_native_pdb_age,
- (const ep_char8_t *)module_native_pdb_path,
- NULL);
-
- g_free (assembly_name);
-}
-
-static
-gboolean
-eventpipe_execute_rundown (
- ep_rt_mono_fire_domain_rundown_events_func domain_events_func,
- ep_rt_mono_fire_assembly_rundown_events_func assembly_events_func,
- ep_rt_mono_fire_method_rundown_events_func method_events_func)
-{
- g_assert_checked (domain_events_func != NULL);
- g_assert_checked (assembly_events_func != NULL);
- g_assert_checked (method_events_func != NULL);
-
- // Under netcore we only have root domain.
- MonoDomain *root_domain = mono_get_root_domain ();
- if (root_domain) {
- uint64_t domain_id = (uint64_t)root_domain;
-
- // Iterate all functions in use (both JIT and AOT).
- EventPipeFireMethodEventsData events_data;
- events_data.domain = root_domain;
- events_data.buffer_size = 1024 * sizeof(uint32_t);
- events_data.buffer = g_new (uint8_t, events_data.buffer_size);
- events_data.method_events_func = method_events_func;
- mono_jit_info_table_foreach_internal (eventpipe_fire_method_events_func, &events_data);
- g_free (events_data.buffer);
-
- // Iterate all assemblies in domain.
- GPtrArray *assemblies = mono_alc_get_all_loaded_assemblies ();
- if (assemblies) {
- for (int i = 0; i < assemblies->len; ++i) {
- MonoAssembly *assembly = (MonoAssembly *)g_ptr_array_index (assemblies, i);
- if (assembly)
- eventpipe_fire_assembly_events (root_domain, assembly, assembly_events_func);
- }
- g_ptr_array_free (assemblies, TRUE);
- }
-
- uint32_t domain_flags = DOMAIN_FLAGS_DEFAULT_DOMAIN | DOMAIN_FLAGS_EXECUTABLE_DOMAIN;
- const char *domain_name = root_domain->friendly_name ? root_domain->friendly_name : "";
- uint32_t domain_index = 1;
-
- domain_events_func (
- domain_id,
- domain_flags,
- (const ep_char8_t *)domain_name,
- domain_index,
- NULL);
- }
-
- return TRUE;
-}
-
-static
-gboolean
-eventpipe_walk_managed_stack_for_thread_func (
- MonoStackFrameInfo *frame,
- MonoContext *ctx,
- gpointer data)
-{
- g_assert_checked (frame != NULL);
- g_assert_checked (data != NULL);
-
- switch (frame->type) {
- case FRAME_TYPE_DEBUGGER_INVOKE:
- case FRAME_TYPE_MANAGED_TO_NATIVE:
- case FRAME_TYPE_TRAMPOLINE:
- case FRAME_TYPE_INTERP_TO_MANAGED:
- case FRAME_TYPE_INTERP_TO_MANAGED_WITH_CTX:
- return FALSE;
- case FRAME_TYPE_MANAGED:
- case FRAME_TYPE_INTERP:
- if (!frame->ji)
- return FALSE;
- MonoMethod *method = frame->ji->async ? NULL : frame->actual_method;
- if (method && !m_method_is_wrapper (method))
- ep_stack_contents_append ((EventPipeStackContents *)data, (uintptr_t)((uint8_t*)frame->ji->code_start + frame->native_offset), method);
- return ep_stack_contents_get_length ((EventPipeStackContents *)data) >= EP_MAX_STACK_DEPTH;
- default:
- g_assert_not_reached ();
- return FALSE;
- }
-}
-
-static
-gboolean
-eventpipe_walk_managed_stack_for_thread (
- ep_rt_thread_handle_t thread,
- EventPipeStackContents *stack_contents)
-{
- g_assert (thread != NULL && stack_contents != NULL);
-
- if (thread == ep_rt_thread_get_handle ())
- mono_get_eh_callbacks ()->mono_walk_stack_with_ctx (eventpipe_walk_managed_stack_for_thread_func, NULL, MONO_UNWIND_SIGNAL_SAFE, stack_contents);
- else
- mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_walk_managed_stack_for_thread_func, mono_thread_info_get_suspend_state (thread), MONO_UNWIND_SIGNAL_SAFE, stack_contents);
-
- return TRUE;
-}
-
-static
-gboolean
-eventpipe_sample_profiler_walk_managed_stack_for_thread_func (
- MonoStackFrameInfo *frame,
- MonoContext *ctx,
- gpointer data)
-{
- g_assert_checked (frame != NULL);
- g_assert_checked (data != NULL);
-
- EventPipeSampleProfileData *sample_data = (EventPipeSampleProfileData *)data;
-
- if (sample_data->payload_data == EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR) {
- if (frame->type == FRAME_TYPE_MANAGED_TO_NATIVE)
- sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL;
- else
- sample_data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED;
- }
-
- return eventpipe_walk_managed_stack_for_thread_func (frame, ctx, &sample_data->stack_contents);
-}
-
-static
-gboolean
-eventpipe_sample_profiler_write_sampling_event_for_threads (
- ep_rt_thread_handle_t sampling_thread,
- EventPipeEvent *sampling_event)
-{
- // Follows CoreClr implementation of sample profiler. Generic invasive/expensive way to do CPU sample profiling relying on STW and stackwalks.
- // TODO: Investigate alternatives on platforms supporting Signals/SuspendThread (see Mono profiler) or CPU PMU's (see ETW/perf_event_open).
-
- // Sample profiler only runs on one thread, no need to synchorinize.
- if (!_ep_rt_mono_sampled_thread_callstacks)
- _ep_rt_mono_sampled_thread_callstacks = g_array_sized_new (FALSE, FALSE, sizeof (EventPipeSampleProfileData), _ep_rt_mono_max_sampled_thread_count);
-
- // Make sure there is room based on previous max number of sampled threads.
- // NOTE, there is a chance there are more threads than max, if that's the case we will
- // miss those threads in this sample, but will be included in next when max has been adjusted.
- g_array_set_size (_ep_rt_mono_sampled_thread_callstacks, _ep_rt_mono_max_sampled_thread_count);
-
- uint32_t filtered_thread_count = 0;
- uint32_t sampled_thread_count = 0;
-
- mono_stop_world (MONO_THREAD_INFO_FLAGS_NO_GC | MONO_THREAD_INFO_FLAGS_NO_SAMPLE);
-
- // Record all info needed in sample events while runtime is suspended, must be async safe.
- FOREACH_THREAD_SAFE_EXCLUDE (thread_info, MONO_THREAD_INFO_FLAGS_NO_GC | MONO_THREAD_INFO_FLAGS_NO_SAMPLE) {
- if (!mono_thread_info_is_running (thread_info)) {
- MonoThreadUnwindState *thread_state = mono_thread_info_get_suspend_state (thread_info);
- if (thread_state->valid) {
- if (sampled_thread_count < _ep_rt_mono_max_sampled_thread_count) {
- EventPipeSampleProfileData *data = &g_array_index (_ep_rt_mono_sampled_thread_callstacks, EventPipeSampleProfileData, sampled_thread_count);
- data->thread_id = ep_rt_thread_id_t_to_uint64_t (mono_thread_info_get_tid (thread_info));
- data->thread_ip = (uintptr_t)MONO_CONTEXT_GET_IP (&thread_state->ctx);
- data->payload_data = EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR;
- ep_stack_contents_reset (&data->stack_contents);
- mono_get_eh_callbacks ()->mono_walk_stack_with_state (eventpipe_sample_profiler_walk_managed_stack_for_thread_func, thread_state, MONO_UNWIND_SIGNAL_SAFE, data);
- sampled_thread_count++;
- }
- }
- }
- filtered_thread_count++;
- } FOREACH_THREAD_SAFE_END
-
- mono_restart_world (MONO_THREAD_INFO_FLAGS_NO_GC | MONO_THREAD_INFO_FLAGS_NO_SAMPLE);
-
- // Fire sample event for threads. Must be done after runtime is resumed since it's not async safe.
- // Since we can't keep thread info around after runtime as been suspended, use an empty
- // adapter instance and only set recorded tid as parameter inside adapter.
- THREAD_INFO_TYPE adapter = { 0 };
- for (uint32_t i = 0; i < sampled_thread_count; ++i) {
- EventPipeSampleProfileData *data = &g_array_index (_ep_rt_mono_sampled_thread_callstacks, EventPipeSampleProfileData, i);
- if (data->payload_data != EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR && ep_stack_contents_get_length(&data->stack_contents) > 0) {
- mono_thread_info_set_tid (&adapter, ep_rt_uint64_t_to_thread_id_t (data->thread_id));
- ep_write_sample_profile_event (sampling_thread, sampling_event, &adapter, &data->stack_contents, (uint8_t *)&data->payload_data, sizeof (data->payload_data));
- }
- }
-
- // Current thread count will be our next maximum sampled threads.
- _ep_rt_mono_max_sampled_thread_count = filtered_thread_count;
-
- return TRUE;
-}
-
-static
-gboolean
-eventpipe_method_get_simple_assembly_name (
- ep_rt_method_desc_t *method,
- ep_char8_t *name,
- size_t name_len)
-{
- g_assert_checked (method != NULL);
- g_assert_checked (name != NULL);
-
- MonoClass *method_class = mono_method_get_class (method);
- MonoImage *method_image = method_class ? mono_class_get_image (method_class) : NULL;
- const ep_char8_t *assembly_name = method_image ? mono_image_get_name (method_image) : NULL;
-
- if (!assembly_name)
- return FALSE;
-
- g_strlcpy (name, assembly_name, name_len);
- return TRUE;
-}
-
-static
-gboolean
-evetpipe_method_get_full_name (
- ep_rt_method_desc_t *method,
- ep_char8_t *name,
- size_t name_len)
-{
- g_assert_checked (method != NULL);
- g_assert_checked (name != NULL);
-
- char *full_method_name = mono_method_get_name_full (method, TRUE, TRUE, MONO_TYPE_NAME_FORMAT_IL);
- if (!full_method_name)
- return FALSE;
-
- g_strlcpy (name, full_method_name, name_len);
-
- g_free (full_method_name);
- return TRUE;
-}
-
-void
-mono_eventpipe_init (
- EventPipeMonoFuncTable *table,
- ep_rt_thread_holder_alloc_func thread_holder_alloc_func,
- ep_rt_thread_holder_free_func thread_holder_free_func)
-{
- if (table != NULL) {
- table->ep_rt_mono_cpu_count = mono_cpu_count;
- table->ep_rt_mono_process_current_pid = mono_process_current_pid;
- table->ep_rt_mono_native_thread_id_get = mono_native_thread_id_get;
- table->ep_rt_mono_native_thread_id_equals = mono_native_thread_id_equals;
- table->ep_rt_mono_runtime_is_shutting_down = mono_runtime_is_shutting_down;
- table->ep_rt_mono_rand_try_get_bytes = rand_try_get_bytes_func;
- table->ep_rt_mono_thread_get = eventpipe_thread_get;
- table->ep_rt_mono_thread_get_or_create = eventpipe_thread_get_or_create;
- table->ep_rt_mono_thread_exited = eventpipe_thread_exited;
- table->ep_rt_mono_thread_info_sleep = mono_thread_info_sleep;
- table->ep_rt_mono_thread_info_yield = mono_thread_info_yield;
- table->ep_rt_mono_w32file_close = mono_w32file_close;
- table->ep_rt_mono_w32file_create = mono_w32file_create;
- table->ep_rt_mono_w32file_write = mono_w32file_write;
- table->ep_rt_mono_w32event_create = mono_w32event_create;
- table->ep_rt_mono_w32event_close = mono_w32event_close;
- table->ep_rt_mono_w32event_set = mono_w32event_set;
- table->ep_rt_mono_w32hadle_wait_one = mono_w32handle_wait_one;
- table->ep_rt_mono_valloc = mono_valloc;
- table->ep_rt_mono_vfree = mono_vfree;
- table->ep_rt_mono_valloc_granule = mono_valloc_granule;
- table->ep_rt_mono_thread_platform_create_thread = mono_thread_platform_create_thread;
- table->ep_rt_mono_thread_attach = eventpipe_thread_attach;
- table->ep_rt_mono_thread_detach = eventpipe_thread_detach;
- table->ep_rt_mono_get_os_cmd_line = mono_get_os_cmd_line;
- table->ep_rt_mono_get_managed_cmd_line = mono_runtime_get_managed_cmd_line;
- table->ep_rt_mono_execute_rundown = eventpipe_execute_rundown;
- table->ep_rt_mono_walk_managed_stack_for_thread = eventpipe_walk_managed_stack_for_thread;
- table->ep_rt_mono_sample_profiler_write_sampling_event_for_threads = eventpipe_sample_profiler_write_sampling_event_for_threads;
- table->ep_rt_mono_method_get_simple_assembly_name = eventpipe_method_get_simple_assembly_name;
- table->ep_rt_mono_method_get_full_name = evetpipe_method_get_full_name;
- }
-
- thread_holder_alloc_callback_func = thread_holder_alloc_func;
- thread_holder_free_callback_func = thread_holder_free_func;
- mono_native_tls_alloc (&ep_rt_mono_thread_holder_tls_id, NULL);
-
- mono_100ns_ticks ();
- mono_rand_open ();
- ep_rt_mono_rand_provider = mono_rand_init (NULL, 0);
-
- ep_rt_mono_initialized = TRUE;
-
- MonoProfilerHandle profiler = mono_profiler_create (NULL);
- mono_profiler_set_thread_stopped_callback (profiler, profiler_eventpipe_thread_exited);
-}
-
-void
-mono_eventpipe_fini (void)
-{
- if (_ep_rt_mono_sampled_thread_callstacks)
- g_array_free (_ep_rt_mono_sampled_thread_callstacks, TRUE);
-
- if (ep_rt_mono_initialized)
- mono_rand_close (ep_rt_mono_rand_provider);
-
- _ep_rt_mono_sampled_thread_callstacks = NULL;
- ep_rt_mono_rand_provider = NULL;
- thread_holder_alloc_callback_func = NULL;
- thread_holder_free_callback_func = NULL;
- ep_rt_mono_initialized = FALSE;
-}
-
static
void
delegate_callback_data_free_func (
@@ -857,11 +94,11 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_CreateProvider (
char *provider_name_utf8 = mono_string_handle_to_utf8 (provider_name, error);
if (is_ok (error) && provider_name_utf8) {
- provider = ep_create_provider (provider_name_utf8, delegate_callback_func, delegate_callback_data_free_func, callback_data);
+ provider = mono_component_event_pipe ()->create_provider (provider_name_utf8, delegate_callback_func, delegate_callback_data_free_func, callback_data);
}
g_free (provider_name_utf8);
- return provider;
+ return (gconstpointer)provider;
}
intptr_t
@@ -877,7 +114,7 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_DefineEvent (
g_assert (provider_handle != 0);
EventPipeProvider *provider = (EventPipeProvider *)provider_handle;
- EventPipeEvent *ep_event = ep_provider_add_event (provider, event_id, (uint64_t)keywords, event_version, (EventPipeEventLevel)level, /* needStack = */ true, metadata, metadata_len);
+ EventPipeEvent *ep_event = mono_component_event_pipe ()->provider_add_event (provider, event_id, (uint64_t)keywords, event_version, (EventPipeEventLevel)level, /* needStack = */ true, metadata, metadata_len);
g_assert (ep_event != NULL);
return (intptr_t)ep_event;
@@ -886,15 +123,14 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_DefineEvent (
void
ves_icall_System_Diagnostics_Tracing_EventPipeInternal_DeleteProvider (intptr_t provider_handle)
{
- if (provider_handle) {
- ep_delete_provider ((EventPipeProvider *)provider_handle);
- }
+ if (provider_handle)
+ mono_component_event_pipe ()->delete_provider ((EventPipeProvider *)provider_handle);
}
void
ves_icall_System_Diagnostics_Tracing_EventPipeInternal_Disable (uint64_t session_id)
{
- ep_disable (session_id);
+ mono_component_event_pipe ()->disable (session_id);
}
uint64_t
@@ -915,42 +151,21 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_Enable (
if (output_file)
output_file_utf8 = mono_utf16_to_utf8 (output_file, g_utf16_len (output_file), error);
- EventPipeProviderConfigurationNative *native_config_providers = (EventPipeProviderConfigurationNative *)providers;
- EventPipeProviderConfiguration *config_providers = g_new0 (EventPipeProviderConfiguration, providers_len);
-
- if (config_providers) {
- for (int i = 0; i < providers_len; ++i) {
- ep_provider_config_init (
- &config_providers[i],
- native_config_providers[i].provider_name ? mono_utf16_to_utf8 (native_config_providers[i].provider_name, g_utf16_len (native_config_providers[i].provider_name), error) : NULL,
- native_config_providers [i].keywords,
- (EventPipeEventLevel)native_config_providers [i].logging_level,
- native_config_providers[i].filter_data ? mono_utf16_to_utf8 (native_config_providers[i].filter_data, g_utf16_len (native_config_providers[i].filter_data), error) : NULL);
- }
- }
-
- session_id = ep_enable (
+ session_id = mono_component_event_pipe ()->enable (
output_file_utf8,
circular_buffer_size_mb,
- config_providers,
+ (EventPipeProviderConfigurationNative *)providers,
providers_len,
output_file != NULL ? EP_SESSION_TYPE_FILE : EP_SESSION_TYPE_LISTENER,
(EventPipeSerializationFormat)format,
true,
NULL,
NULL);
- ep_start_streaming (session_id);
- if (config_providers) {
- for (int i = 0; i < providers_len; ++i) {
- ep_provider_config_fini (&config_providers[i]);
- g_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config_providers[i]));
- g_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config_providers[i]));
- }
- }
+ mono_component_event_pipe ()->start_streaming (session_id);
g_free (output_file_utf8);
- return session_id;
+ return (uint64_t)session_id;
}
int32_t
@@ -958,40 +173,7 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_EventActivityIdControl (
uint32_t control_code,
/* GUID * */uint8_t *activity_id)
{
- int32_t result = 0;
- ep_rt_thread_activity_id_handle_t activity_id_handle = ep_thread_get_activity_id_handle ();
-
- if (activity_id_handle == NULL)
- return 1;
-
- uint8_t current_activity_id [EP_ACTIVITY_ID_SIZE];
- EventPipeActivityControlCode activity_control_code = (EventPipeActivityControlCode)control_code;
- switch (activity_control_code) {
- case EP_ACTIVITY_CONTROL_GET_ID:
- ep_thread_get_activity_id (activity_id_handle, activity_id, EP_ACTIVITY_ID_SIZE);
- break;
- case EP_ACTIVITY_CONTROL_SET_ID:
- ep_thread_set_activity_id (activity_id_handle, activity_id, EP_ACTIVITY_ID_SIZE);
- break;
- case EP_ACTIVITY_CONTROL_CREATE_ID:
- ep_thread_create_activity_id (activity_id, EP_ACTIVITY_ID_SIZE);
- break;
- case EP_ACTIVITY_CONTROL_GET_SET_ID:
- ep_thread_get_activity_id (activity_id_handle, current_activity_id, EP_ACTIVITY_ID_SIZE);
- ep_thread_set_activity_id (activity_id_handle, activity_id, EP_ACTIVITY_ID_SIZE);
- memcpy (activity_id, current_activity_id, EP_ACTIVITY_ID_SIZE);
- break;
- case EP_ACTIVITY_CONTROL_CREATE_SET_ID:
- ep_thread_get_activity_id (activity_id_handle, activity_id, EP_ACTIVITY_ID_SIZE);
- ep_thread_create_activity_id (current_activity_id, EP_ACTIVITY_ID_SIZE);
- ep_thread_set_activity_id (activity_id_handle, current_activity_id, EP_ACTIVITY_ID_SIZE);
- break;
- default:
- result = 1;
- break;
- }
-
- return result;
+ return mono_component_event_pipe ()->thread_ctrl_activity_id ((EventPipeActivityControlCode)control_code, activity_id, EP_ACTIVITY_ID_SIZE) ? 0 : 1;
}
MonoBoolean
@@ -999,25 +181,7 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetNextEvent (
uint64_t session_id,
/* EventPipeEventInstanceData * */void *instance)
{
- g_assert (instance != NULL);
-
- EventPipeEventInstance *const next_instance = ep_get_next_event (session_id);
- EventPipeEventInstanceData *const data = (EventPipeEventInstanceData *)instance;
- if (next_instance && data) {
- const EventPipeEvent *const ep_event = ep_event_instance_get_ep_event (next_instance);
- if (ep_event) {
- data->provider_id = (intptr_t)ep_event_get_provider (ep_event);
- data->event_id = ep_event_get_event_id (ep_event);
- }
- data->thread_id = ep_event_instance_get_thread_id (next_instance);
- data->timestamp = ep_event_instance_get_timestamp (next_instance);
- memcpy (&data->activity_id, ep_event_instance_get_activity_id_cref (next_instance), EP_ACTIVITY_ID_SIZE);
- memcpy (&data->related_activity_id, ep_event_instance_get_related_activity_id_cref (next_instance), EP_ACTIVITY_ID_SIZE);
- data->payload = ep_event_instance_get_data (next_instance);
- data->payload_len = ep_event_instance_get_data_len (next_instance);
- }
-
- return next_instance != NULL;
+ return mono_component_event_pipe ()->get_next_event ((EventPipeSessionID)session_id, (EventPipeEventInstanceData *)instance) ? TRUE : FALSE;
}
intptr_t
@@ -1029,7 +193,7 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetProvider (const gunich
if (provider_name) {
provider_name_utf8 = mono_utf16_to_utf8 (provider_name, g_utf16_len (provider_name), error);
- provider = ep_get_provider (provider_name_utf8);
+ provider = mono_component_event_pipe()->get_provider (provider_name_utf8);
}
g_free (provider_name_utf8);
@@ -1041,25 +205,13 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetSessionInfo (
uint64_t session_id,
/* EventPipeSessionInfo * */void *session_info)
{
- bool result = false;
- if (session_info) {
- EventPipeSession *session = ep_get_session ((EventPipeSessionID)session_id);
- if (session) {
- EventPipeSessionInfo *instance = (EventPipeSessionInfo *)session_info;
- instance->starttime_as_utc_filetime = ep_session_get_session_start_time (session);
- instance->start_timestamp = ep_session_get_session_start_timestamp (session);
- instance->timestamp_frequency = ep_perf_frequency_query ();
- result = true;
- }
- }
-
- return result;
+ return mono_component_event_pipe()->get_session_info (session_id, (EventPipeSessionInfo *)session_info) ? TRUE : FALSE;
}
intptr_t
ves_icall_System_Diagnostics_Tracing_EventPipeInternal_GetWaitHandle (uint64_t session_id)
{
- return (intptr_t)ep_get_wait_handle (session_id);
+ return (intptr_t) mono_component_event_pipe()->get_wait_handle ((EventPipeSessionID)session_id);
}
void
@@ -1072,7 +224,7 @@ ves_icall_System_Diagnostics_Tracing_EventPipeInternal_WriteEventData (
{
g_assert (event_handle);
EventPipeEvent *ep_event = (EventPipeEvent *)event_handle;
- ep_write_event_2 (ep_event, (EventData *)event_data, event_data_len, activity_id, related_activity_id);
+ mono_component_event_pipe()->write_event_2 (ep_event, (EventData *)event_data, event_data_len, activity_id, related_activity_id);
}
#else /* ENABLE_PERFTRACING */
diff --git a/src/mono/mono/metadata/jit-info.h b/src/mono/mono/metadata/jit-info.h
index dabb36af8bf3e1..ec41b61c0b3417 100644
--- a/src/mono/mono/metadata/jit-info.h
+++ b/src/mono/mono/metadata/jit-info.h
@@ -260,7 +260,7 @@ mono_jit_info_add_aot_module (MonoImage *image, gpointer start, gpointer end);
MonoGenericJitInfo*
mono_jit_info_get_generic_jit_info (MonoJitInfo *ji);
-MonoGenericSharingContext*
+MONO_COMPONENT_API MonoGenericSharingContext*
mono_jit_info_get_generic_sharing_context (MonoJitInfo *ji);
void
@@ -289,7 +289,7 @@ MonoJitInfo* mono_jit_info_table_find_internal (gpointer addr, gboolean try_aot,
typedef void (*MonoJitInfoFunc) (MonoJitInfo *ji, gpointer user_data);
-void
+MONO_COMPONENT_API void
mono_jit_info_table_foreach_internal (MonoJitInfoFunc func, gpointer user_data);
void
diff --git a/src/mono/mono/metadata/loader-internals.h b/src/mono/mono/metadata/loader-internals.h
index ec6eb8f80cdf3b..af4ff2e4865685 100644
--- a/src/mono/mono/metadata/loader-internals.h
+++ b/src/mono/mono/metadata/loader-internals.h
@@ -278,7 +278,7 @@ mono_alc_add_assembly (MonoAssemblyLoadContext *alc, MonoAssembly *ass);
MonoAssembly*
mono_alc_find_assembly (MonoAssemblyLoadContext *alc, MonoAssemblyName *aname);
-GPtrArray*
+MONO_COMPONENT_API GPtrArray*
mono_alc_get_all_loaded_assemblies (void);
MONO_API void
diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c
index e18a6f4ec8b8cc..0d9c7dcfe048bb 100644
--- a/src/mono/mono/metadata/metadata.c
+++ b/src/mono/mono/metadata/metadata.c
@@ -30,6 +30,7 @@
#include "debug-helpers.h"
#include "abi-details.h"
#include "cominterop.h"
+#include "components.h"
#include
#include
#include
@@ -2029,6 +2030,8 @@ mono_metadata_init (void)
for (i = 0; i < NBUILTIN_TYPES (); ++i)
g_hash_table_insert (type_cache, (gpointer) &builtin_types [i], (gpointer) &builtin_types [i]);
+ mono_components_init ();
+
#ifdef ENABLE_METADATA_UPDATE
mono_metadata_update_init ();
#endif
diff --git a/src/mono/mono/metadata/native-library.c b/src/mono/mono/metadata/native-library.c
index 13c0cf562d5ca5..e70f24f7cc480d 100644
--- a/src/mono/mono/metadata/native-library.c
+++ b/src/mono/mono/metadata/native-library.c
@@ -1224,7 +1224,7 @@ ves_icall_System_Runtime_InteropServices_NativeLibrary_FreeLib (gpointer lib, Mo
g_hash_table_add (native_library_module_blocklist, module);
mono_dl_close (module);
} else {
- MonoDl raw_module = { 0 };
+ MonoDl raw_module = { { 0 } };
raw_module.handle = lib;
mono_dl_close (&raw_module);
}
@@ -1255,7 +1255,7 @@ ves_icall_System_Runtime_InteropServices_NativeLibrary_GetSymbol (gpointer lib,
if (!symbol)
mono_error_set_generic_error (error, "System", "EntryPointNotFoundException", "%s: %s", module->full_name, symbol_name);
} else {
- MonoDl raw_module = { 0 };
+ MonoDl raw_module = { { 0 } };
raw_module.handle = lib;
mono_dl_symbol (&raw_module, symbol_name, &symbol);
if (!symbol)
diff --git a/src/mono/mono/metadata/object-internals.h b/src/mono/mono/metadata/object-internals.h
index c92ea7bcf43d62..49af8f525f91e7 100644
--- a/src/mono/mono/metadata/object-internals.h
+++ b/src/mono/mono/metadata/object-internals.h
@@ -691,6 +691,7 @@ mono_get_runtime_callbacks (void);
void
mono_install_eh_callbacks (MonoRuntimeExceptionHandlingCallbacks *cbs);
+MONO_COMPONENT_API
MonoRuntimeExceptionHandlingCallbacks *
mono_get_eh_callbacks (void);
@@ -1795,6 +1796,7 @@ mono_string_from_utf32_checked (const mono_unichar4 *data, MonoError *error);
char*
mono_ldstr_utf8 (MonoImage *image, guint32 idx, MonoError *error);
+MONO_COMPONENT_API
char*
mono_utf16_to_utf8 (const mono_unichar2 *s, gsize slength, MonoError *error);
@@ -2070,7 +2072,7 @@ mono_gc_wbarrier_value_copy_internal (void* dest, const void* src, int count, Mo
void
mono_gc_wbarrier_object_copy_internal (MonoObject* obj, MonoObject *src);
-char *
+MONO_COMPONENT_API char *
mono_runtime_get_managed_cmd_line (void);
char *
diff --git a/src/mono/mono/metadata/threads-types.h b/src/mono/mono/metadata/threads-types.h
index b9c963721d58e2..e3869ca5b5fdd5 100644
--- a/src/mono/mono/metadata/threads-types.h
+++ b/src/mono/mono/metadata/threads-types.h
@@ -207,7 +207,7 @@ void mono_thread_internal_unhandled_exception (MonoObject* exc);
void mono_alloc_special_static_data_free (GHashTable *special_static_fields);
-void mono_thread_set_state (MonoInternalThread *thread, MonoThreadState state);
+MONO_COMPONENT_API void mono_thread_set_state (MonoInternalThread *thread, MonoThreadState state);
void mono_thread_clr_state (MonoInternalThread *thread, MonoThreadState state);
gboolean mono_thread_test_state (MonoInternalThread *thread, MonoThreadState test);
gboolean mono_thread_test_and_set_state (MonoInternalThread *thread, MonoThreadState test, MonoThreadState set);
diff --git a/src/mono/mono/metadata/w32event.h b/src/mono/mono/metadata/w32event.h
index 74a045cc4dd0db..8f88ce09450239 100644
--- a/src/mono/mono/metadata/w32event.h
+++ b/src/mono/mono/metadata/w32event.h
@@ -12,16 +12,20 @@
#include "object-internals.h"
#include "w32handle.h"
#include
+#include
void
mono_w32event_init (void);
+MONO_COMPONENT_API
gpointer
mono_w32event_create (gboolean manual, gboolean initial);
+MONO_COMPONENT_API
gboolean
mono_w32event_close (gpointer handle);
+MONO_COMPONENT_API
void
mono_w32event_set (gpointer handle);
diff --git a/src/mono/mono/metadata/w32file.h b/src/mono/mono/metadata/w32file.h
index 2700933c98bc38..86e1c05f397e1a 100644
--- a/src/mono/mono/metadata/w32file.h
+++ b/src/mono/mono/metadata/w32file.h
@@ -142,12 +142,15 @@ typedef struct {
void
mono_w32file_init (void);
+MONO_COMPONENT_API
gpointer
mono_w32file_create(const gunichar2 *name, guint32 fileaccess, guint32 sharemode, guint32 createmode, guint32 attrs);
+MONO_COMPONENT_API
gboolean
mono_w32file_close (gpointer handle);
+MONO_COMPONENT_API
gboolean
mono_w32file_write (gpointer handle, gconstpointer buffer, guint32 numbytes, guint32 *byteswritten, gint32 *win32error);
diff --git a/src/mono/mono/metadata/w32handle.h b/src/mono/mono/metadata/w32handle.h
index c985e793232fb6..6ec82b812e0772 100644
--- a/src/mono/mono/metadata/w32handle.h
+++ b/src/mono/mono/metadata/w32handle.h
@@ -16,6 +16,7 @@
#include "mono/utils/mono-coop-mutex.h"
#include "mono/utils/mono-error.h"
+#include
#define MONO_W32HANDLE_MAXIMUM_WAIT_OBJECTS 64
#define MONO_INFINITE_WAIT ((guint32) 0xFFFFFFFF)
@@ -136,6 +137,7 @@ mono_w32handle_lock (MonoW32Handle *handle_data);
void
mono_w32handle_unlock (MonoW32Handle *handle_data);
+MONO_COMPONENT_API
MonoW32HandleWaitRet
mono_w32handle_wait_one (gpointer handle, guint32 timeout, gboolean alertable);
diff --git a/src/mono/mono/mini/CMakeLists.txt b/src/mono/mono/mini/CMakeLists.txt
index 6e5c37ba16b352..8fbc1af6141fa1 100644
--- a/src/mono/mono/mini/CMakeLists.txt
+++ b/src/mono/mono/mini/CMakeLists.txt
@@ -19,6 +19,18 @@ include_directories(
${PROJECT_SOURCE_DIR}/../eglib
${PROJECT_SOURCE_DIR}/../sgen)
+if(HOST_DARWIN)
+set(OS_LIBS "-framework CoreFoundation" "-framework Foundation")
+elseif(HOST_IOS)
+set(OS_LIBS "-framework CoreFoundation" "-lobjc" "-lc++")
+elseif(HOST_ANDROID)
+set(OS_LIBS m dl log)
+elseif(HOST_LINUX)
+set(OS_LIBS pthread m dl)
+elseif(HOST_WIN32)
+set(OS_LIBS bcrypt.lib Mswsock.lib ws2_32.lib psapi.lib version.lib advapi32.lib winmm.lib kernel32.lib)
+endif()
+
#
# SUBDIRS
#
@@ -29,21 +41,7 @@ include(../sgen/CMakeLists.txt)
if(INTERNAL_ZLIB) # TODO: hook up HAVE_SYS_ZLIB instead
include(../zlib/CMakeLists.txt)
endif()
-
-if(ENABLE_PERFTRACING)
-
- set (SHARED_EVENTPIPE_INCLUDE_PATH "../../../native/")
- set (SHARED_EVENTPIPE_SOURCE_PATH "../../../native/eventpipe/")
- set (MONO_EVENTPIPE_SHIM_SOURCE_PATH "../eventpipe/")
-
- include(${MONO_EVENTPIPE_SHIM_SOURCE_PATH}/CMakeLists.txt)
-
- include_directories(
- ${SHARED_EVENTPIPE_INCLUDE_PATH}
- ${MONO_EVENTPIPE_SHIM_SOURCE_PATH}
- )
-
-endif(ENABLE_PERFTRACING)
+include(../component/CMakeLists.txt)
if(HOST_WIN32)
# /OPT:ICF merges idential functions breaking mono_lookup_icall_symbol ()
@@ -242,8 +240,6 @@ set(windows_sources
mini-windows.c
mini-windows-tls-callback.c
mini-windows.h
- mini-windows-dllmain.c
- # mini-windows-dlldac.c
)
set(posix_sources
@@ -310,23 +306,21 @@ if(LLVM_LIBDIR)
link_directories(${LLVM_LIBDIR})
endif()
-if(HOST_DARWIN)
-set(OS_LIBS "-framework CoreFoundation" "-framework Foundation")
-elseif(HOST_IOS)
-set(OS_LIBS "-framework CoreFoundation" "-lobjc" "-lc++")
-elseif(HOST_ANDROID)
-set(OS_LIBS m dl log)
-elseif(HOST_LINUX)
-set(OS_LIBS pthread m dl)
-elseif(HOST_WIN32)
-set(OS_LIBS bcrypt.lib Mswsock.lib ws2_32.lib psapi.lib version.lib advapi32.lib winmm.lib kernel32.lib)
+if(HOST_WIN32)
set(mini_sources "${mini_sources};${PROJECT_BINARY_DIR}/../../NativeVersion.rc") # this is generated by GenerateMonoVersionFile in mono.proj
endif()
+set(monosgen-sources "${metadata_sources};${utils_sources};${sgen_sources};${icu_shim_sources};${mini_sources};${zlib_sources}")
+
+add_library(monosgen-objects OBJECT "${monosgen-sources}")
+add_library(monosgen-static STATIC $;$)
+set_target_properties(monosgen-static PROPERTIES OUTPUT_NAME ${MONO_LIB_NAME})
+
+if(DISABLE_COMPONENTS)
+ # add component fallback stubs into static mono library when components have been disabled.
+ target_sources(monosgen-static PRIVATE "${mono-components-stub-objects}")
+endif()
-add_library(monosgen-objects OBJECT "${eglib_sources};${metadata_sources};${utils_sources};${sgen_sources};${icu_shim_sources};${eventpipe_sources};${mini_sources};${zlib_sources}")
-add_library(monosgen-static STATIC $)
-set_target_properties(monosgen-static PROPERTIES OUTPUT_NAME monosgen-2.0)
if(NOT DISABLE_LIBS)
install(TARGETS monosgen-static LIBRARY)
install(FILES ${metadata_public_headers}
@@ -337,14 +331,21 @@ if(NOT DISABLE_LIBS)
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/mono-2.0/mono/jit)
endif()
if(NOT DISABLE_SHARED_LIBS)
- add_library(monosgen-shared SHARED $ )
- set_target_properties(monosgen-shared PROPERTIES OUTPUT_NAME monosgen-2.0)
+ if(HOST_WIN32)
+ add_library(monosgen-shared SHARED "mini-windows-dllmain.c;${monosgen-sources}")
+ target_compile_definitions(monosgen-shared PRIVATE -DMONO_DLL_EXPORT)
+ else()
+ add_library(monosgen-shared SHARED $)
+ target_compile_definitions(monosgen-objects PRIVATE -DMONO_DLL_EXPORT)
+ endif()
+ target_sources(monosgen-shared PRIVATE $)
+ set_target_properties(monosgen-shared PROPERTIES OUTPUT_NAME ${MONO_SHARED_LIB_NAME})
if(TARGET_WIN32)
- # on Windows the import library for the shared monosgen-2.0 library will have the same name as the static library (monosgen-2.0.lib),
+ # on Windows the import library for the shared mono library will have the same name as the static library,
# to avoid a conflict we rename the import library with the .import.lib suffix
set_target_properties(monosgen-shared PROPERTIES IMPORT_SUFFIX ".import.lib")
endif()
- target_link_libraries(monosgen-shared ${OS_LIBS} ${ICONV_LIB} ${LLVM_LIBS} ${ICU_LIBS})
+ target_link_libraries(monosgen-shared PRIVATE ${OS_LIBS} ${ICONV_LIB} ${LLVM_LIBS} ${ICU_LIBS})
if(ICU_LDFLAGS)
set_property(TARGET monosgen-shared APPEND_STRING PROPERTY LINK_FLAGS " ${ICU_LDFLAGS}")
endif()
@@ -354,7 +355,26 @@ if(NOT DISABLE_SHARED_LIBS)
if(TARGET_DARWIN)
set_property(TARGET monosgen-shared APPEND_STRING PROPERTY LINK_FLAGS " -Wl,-compatibility_version -Wl,2.0 -Wl,-current_version -Wl,2.0")
endif()
+ if(NOT DISABLE_COMPONENTS AND STATIC_COMPONENTS AND NOT DISABLE_LINK_STATIC_COMPONENTS)
+ # if components are built statically, but we're building a shared lib mono,
+ # link them into the library
+ target_sources(monosgen-shared PRIVATE "${mono-components-objects}")
+ elseif(NOT DISABLE_COMPONENTS AND STATIC_COMPONENTS AND DISABLE_LINK_STATIC_COMPONENTS)
+ # if components are built statically, we're building a shared lib mono, but we shouldn't link components
+ # link the fallback stubs into the runtime
+ target_sources(monosgen-shared PRIVATE "${mono-components-stub-objects}")
+ elseif(NOT DISABLE_COMPONENTS AND NOT STATIC_COMPONENTS)
+ # if components are built dynamically, link the fallback stubs into the runtime
+ target_sources(monosgen-shared PRIVATE "${mono-components-stub-objects}")
+ elseif(DISABLE_COMPONENTS)
+ # if components are disabled, link the fallback stubs into the runtime
+ target_sources(monosgen-shared PRIVATE "${mono-components-stub-objects}")
+ endif()
install(TARGETS monosgen-shared LIBRARY)
+ if(HOST_WIN32 AND TARGET_AMD64)
+ add_library(monosgen-shared-dac SHARED "mini-windows-dlldac.c")
+ set_target_properties(monosgen-shared-dac PROPERTIES OUTPUT_NAME ${MONO_SHARED_LIB_NAME}-dac)
+ endif()
endif()
find_package(Python3 COMPONENTS Interpreter)
@@ -398,7 +418,21 @@ if(NOT DISABLE_EXECUTABLES)
set(sgen_sources "${sgen_sources};${PROJECT_BINARY_DIR}/../../NativeVersion.rc")
endif()
add_executable(mono-sgen "${sgen_sources}")
- target_link_libraries(mono-sgen monosgen-static ${OS_LIBS} ${ICONV_LIB} ${LLVM_LIBS} ${ICU_LIBS})
+ target_link_libraries(mono-sgen PRIVATE monosgen-static ${OS_LIBS} ${ICONV_LIB} ${LLVM_LIBS} ${ICU_LIBS})
+ if(NOT DISABLE_COMPONENTS AND STATIC_COMPONENTS AND NOT DISABLE_LINK_STATIC_COMPONENTS)
+ # if components are built statically, link them into runtime.
+ target_sources(mono-sgen PRIVATE "${mono-components-objects}")
+ elseif(NOT DISABLE_COMPONENTS AND STATIC_COMPONENTS AND DISABLE_LINK_STATIC_COMPONENTS)
+ # if components are built statically, but we shouldn't link components
+ # link the fallback stubs into the runtime
+ target_sources(mono-sgen PRIVATE "${mono-components-stub-objects}")
+ elseif(NOT DISABLE_COMPONENTS AND NOT STATIC_COMPONENTS)
+ # if components are built dynamically, link the fallback stubs into the runtime
+ target_sources(mono-sgen PRIVATE "${mono-components-stub-objects}")
+ elseif(DISABLE_COMPONENTS)
+ # if components are disabled, link the fallback stubs into the runtime
+ # fallback stubs already provided in monosgen-static when components are disabled
+ endif()
if(ICU_LDFLAGS)
set_property(TARGET mono-sgen APPEND_STRING PROPERTY LINK_FLAGS " ${ICU_LDFLAGS}")
endif()
diff --git a/src/mono/mono/mini/mini-runtime.c b/src/mono/mono/mini/mini-runtime.c
index f1c43bcabaea95..0dc726c4b530e5 100644
--- a/src/mono/mono/mini/mini-runtime.c
+++ b/src/mono/mono/mini/mini-runtime.c
@@ -71,11 +71,7 @@
#include
#include
#include
-
-#ifdef ENABLE_PERFTRACING
-#include
-#include
-#endif
+#include
#include "mini.h"
#include "seq-points.h"
@@ -4428,12 +4424,10 @@ mini_init (const char *filename, const char *runtime_version)
else
domain = mono_init_from_assembly (filename, filename);
-#if defined(ENABLE_PERFTRACING) && !defined(DISABLE_EVENTPIPE)
if (mono_compile_aot)
- ds_server_disable ();
+ mono_component_diagnostics_server ()->disable ();
- ep_init ();
-#endif
+ mono_component_event_pipe ()->init ();
if (mono_aot_only) {
/* This helps catch code allocation requests */
@@ -4500,9 +4494,7 @@ mini_init (const char *filename, const char *runtime_version)
#endif
mono_threads_set_runtime_startup_finished ();
-#if defined(ENABLE_PERFTRACING) && !defined(DISABLE_EVENTPIPE)
- ep_finish_init ();
-#endif
+ mono_component_event_pipe ()->finish_init ();
#ifdef ENABLE_EXPERIMENT_TIERED
if (!mono_compile_aot) {
@@ -4883,10 +4875,8 @@ mini_cleanup (MonoDomain *domain)
jit_stats_cleanup ();
mono_jit_dump_cleanup ();
mini_get_interp_callbacks ()->cleanup ();
-#if defined(ENABLE_PERFTRACING) && !defined(DISABLE_EVENTPIPE)
- ep_shutdown ();
- ds_server_shutdown ();
-#endif
+ mono_component_event_pipe ()->shutdown ();
+ mono_component_diagnostics_server ()->shutdown ();
}
void
diff --git a/src/mono/mono/utils/atomic.h b/src/mono/mono/utils/atomic.h
index 4b46122c518656..5ba7bd2c2a0861 100755
--- a/src/mono/mono/utils/atomic.h
+++ b/src/mono/mono/utils/atomic.h
@@ -373,7 +373,7 @@ static inline gint64 mono_atomic_load_i64(volatile gint64 *src)
#else
/* Implement 64-bit cas by hand or emulate it. */
-extern gint64 mono_atomic_cas_i64(volatile gint64 *dest, gint64 exch, gint64 comp);
+MONO_COMPONENT_API gint64 mono_atomic_cas_i64(volatile gint64 *dest, gint64 exch, gint64 comp);
/* Implement all other 64-bit atomics in terms of a specialized CAS
* in this case, since chances are that the other 64-bit atomic
diff --git a/src/mono/mono/utils/mono-compiler.h b/src/mono/mono/utils/mono-compiler.h
index 4f6043e3349d22..f5f8b860ca0cd9 100644
--- a/src/mono/mono/utils/mono-compiler.h
+++ b/src/mono/mono/utils/mono-compiler.h
@@ -14,6 +14,8 @@
#include
#endif
+#include
+
#ifdef __GNUC__
#define MONO_ATTR_USED __attribute__ ((__used__))
#else
@@ -81,6 +83,18 @@ typedef ptrdiff_t ssize_t;
/* Used to mark internal functions used by the CoreFX PAL library */
#define MONO_PAL_API MONO_API
+/* Mono components */
+
+/* Used to mark internal functions used by dynamically linked runtime components */
+#define MONO_COMPONENT_API MONO_API
+
+#ifdef COMPILING_COMPONENT_DYNAMIC
+#define MONO_COMPONENT_EXPORT_ENTRYPOINT MONO_EXTERN_C MONO_API_EXPORT
+#else
+#define MONO_COMPONENT_EXPORT_ENTRYPOINT /* empty */
+#endif
+
+
#ifdef __GNUC__
#define MONO_ALWAYS_INLINE __attribute__ ((__always_inline__))
#elif defined(_MSC_VER)
diff --git a/src/mono/mono/utils/mono-proclib.h b/src/mono/mono/utils/mono-proclib.h
index 01c93526c124b5..6b653bd7ff27e9 100644
--- a/src/mono/mono/utils/mono-proclib.h
+++ b/src/mono/mono/utils/mono-proclib.h
@@ -70,7 +70,7 @@ char* mono_process_get_name (gpointer pid, char *buf, int len);
gint64 mono_process_get_data (gpointer pid, MonoProcessData data);
gint64 mono_process_get_data_with_error (gpointer pid, MonoProcessData data, MonoProcessError *error);
-int mono_process_current_pid (void);
+MONO_COMPONENT_API int mono_process_current_pid (void);
MONO_API int mono_cpu_count (void);
gint64 mono_cpu_get_data (int cpu_id, MonoCpuData data, MonoProcessError *error);
diff --git a/src/mono/mono/utils/mono-rand.h b/src/mono/mono/utils/mono-rand.h
index 2f3b6aaa36cff3..4ce397aa8e4f75 100644
--- a/src/mono/mono/utils/mono-rand.h
+++ b/src/mono/mono/utils/mono-rand.h
@@ -10,18 +10,22 @@
#include "mono-compiler.h"
#include "mono-error.h"
+MONO_COMPONENT_API
gboolean
mono_rand_open (void);
+MONO_COMPONENT_API
gpointer
mono_rand_init (const guchar *seed, gssize seed_size);
+MONO_COMPONENT_API
gboolean
mono_rand_try_get_bytes (gpointer *handle, guchar *buffer, gssize buffer_size, MonoError *error);
gboolean
mono_rand_try_get_uint32 (gpointer *handle, guint32 *val, guint32 min, guint32 max, MonoError *error);
+MONO_COMPONENT_API
void
mono_rand_close (gpointer handle);
diff --git a/src/mono/mono/utils/mono-threads.h b/src/mono/mono/utils/mono-threads.h
index 8d08f10fe5baf0..c0cd48216528b3 100644
--- a/src/mono/mono/utils/mono-threads.h
+++ b/src/mono/mono/utils/mono-threads.h
@@ -23,6 +23,7 @@
#include
#include
#include
+#include
#include
#include
@@ -451,9 +452,7 @@ mono_thread_info_unset_internal_thread_gchandle (THREAD_INFO_TYPE *info);
gboolean
mono_thread_info_is_exiting (void);
-#ifdef HOST_WIN32
-G_EXTERN_C // due to THREAD_INFO_TYPE varying
-#endif
+MONO_COMPONENT_API
THREAD_INFO_TYPE *
mono_thread_info_current (void);
@@ -470,6 +469,7 @@ mono_thread_info_current_unchecked (void);
MONO_API int
mono_thread_info_get_small_id (void);
+MONO_COMPONENT_API
MonoLinkedListSet*
mono_thread_info_list_head (void);
@@ -506,7 +506,7 @@ mono_thread_info_get_stack_bounds (guint8 **staddr, size_t *stsize);
MONO_API gboolean
mono_thread_info_yield (void);
-gint
+MONO_COMPONENT_API gint
mono_thread_info_sleep (guint32 ms, gboolean *alerted);
gint
@@ -624,7 +624,7 @@ gint mono_threads_suspend_get_suspend_signal (void);
gint mono_threads_suspend_get_restart_signal (void);
gint mono_threads_suspend_get_abort_signal (void);
-gboolean
+MONO_COMPONENT_API gboolean
mono_thread_platform_create_thread (MonoThreadStart thread_fn, gpointer thread_data,
gsize* const stack_size, MonoNativeThreadId *tid);
@@ -763,7 +763,7 @@ gboolean mono_threads_transition_peek_blocking_suspend_requested (THREAD_INFO_TY
void mono_threads_transition_begin_no_safepoints (THREAD_INFO_TYPE* info, const char *func);
void mono_threads_transition_end_no_safepoints (THREAD_INFO_TYPE* info, const char *func);
-G_EXTERN_C // due to THREAD_INFO_TYPE varying
+MONO_COMPONENT_API
MonoThreadUnwindState* mono_thread_info_get_suspend_state (THREAD_INFO_TYPE *info);
gpointer
@@ -772,8 +772,7 @@ mono_threads_enter_gc_unsafe_region_cookie (void);
void mono_thread_info_wait_for_resume (THREAD_INFO_TYPE *info);
/* Advanced suspend API, used for suspending multiple threads as once. */
-G_EXTERN_C // due to THREAD_INFO_TYPE varying
-gboolean mono_thread_info_is_running (THREAD_INFO_TYPE *info);
+MONO_COMPONENT_API gboolean mono_thread_info_is_running (THREAD_INFO_TYPE *info);
gboolean mono_thread_info_is_live (THREAD_INFO_TYPE *info);
G_EXTERN_C // due to THREAD_INFO_TYPE varying
int mono_thread_info_suspend_count (THREAD_INFO_TYPE *info);
diff --git a/src/mono/mono/utils/mono-time.h b/src/mono/mono/utils/mono-time.h
index 921efbbc61a95c..874a4677c693ac 100644
--- a/src/mono/mono/utils/mono-time.h
+++ b/src/mono/mono/utils/mono-time.h
@@ -20,7 +20,7 @@ gint64 mono_msec_boottime (void);
gint64 mono_msec_ticks (void);
/* Returns the number of 100ns ticks from unspecified time: this should be monotonic */
-gint64 mono_100ns_ticks (void);
+MONO_COMPONENT_API gint64 mono_100ns_ticks (void);
/* Returns the number of 100ns ticks since 1/1/1601, UTC timezone */
gint64 mono_100ns_datetime (void);
diff --git a/src/native/eventpipe/CMakeLists.txt b/src/native/eventpipe/CMakeLists.txt
index 07acdcf6800029..c320b615fc410e 100644
--- a/src/native/eventpipe/CMakeLists.txt
+++ b/src/native/eventpipe/CMakeLists.txt
@@ -41,6 +41,7 @@ if(ENABLE_PERFTRACING OR FEATURE_PERFTRACING)
ep-file.h
ep-getter-setter.h
ep-ipc-pal-types.h
+ ep-ipc-pal-types-forward.h
ep-ipc-stream.h
ep-json-file.h
ep-metadata-generator.h
@@ -56,6 +57,7 @@ if(ENABLE_PERFTRACING OR FEATURE_PERFTRACING)
ep-stream.h
ep-thread.h
ep-types.h
+ ep-types-forward.h
)
list(APPEND SHARED_DIAGNOSTIC_SERVER_SOURCES
diff --git a/src/native/eventpipe/ds-ipc.c b/src/native/eventpipe/ds-ipc.c
index 8493eeab058246..a8b12b1e980f16 100644
--- a/src/native/eventpipe/ds-ipc.c
+++ b/src/native/eventpipe/ds-ipc.c
@@ -7,6 +7,7 @@
#define DS_IMPL_IPC_PAL_GETTER_SETTER
#include "ds-ipc.h"
#include "ds-protocol.h"
+#include "ep.h"
#include "ds-rt.h"
/*
@@ -164,7 +165,7 @@ ipc_stream_factory_build_and_add_port (
bool result = false;
DiagnosticsIpc *ipc = NULL;
-#ifndef DS_IPC_PAL_TCP
+#ifndef DS_IPC_DISABLE_LISTEN_PORTS
if (!default_port && builder->type == DS_PORT_TYPE_LISTEN) {
// Ignore listen type (see conversation in https://github.com/dotnet/runtime/pull/40499 for details)
DS_LOG_INFO_0 ("ipc_stream_factory_build_and_add_port - Ignoring LISTEN port configuration");
@@ -238,6 +239,8 @@ ipc_log_poll_handles (ds_rt_ipc_poll_handle_array_t *ipc_poll_handles)
bool
ds_ipc_stream_factory_init (void)
{
+ ep_ipc_stream_factory_callback_set (ds_ipc_stream_factory_any_suspended_ports);
+
ds_rt_port_array_alloc (&_ds_port_array);
return ds_rt_port_array_is_valid (&_ds_port_array);
}
@@ -255,6 +258,8 @@ ds_ipc_stream_factory_fini (void)
}
ds_rt_port_array_free (&_ds_port_array);*/
+
+ ep_ipc_stream_factory_callback_set (NULL);
}
bool
diff --git a/src/native/eventpipe/ds-rt-config.h b/src/native/eventpipe/ds-rt-config.h
index 678ee18de2bde9..cb84d7d31afd1b 100644
--- a/src/native/eventpipe/ds-rt-config.h
+++ b/src/native/eventpipe/ds-rt-config.h
@@ -11,7 +11,7 @@
#define DS_INCLUDE_SOURCE_FILES
#endif
-#ifdef FEATURE_PERFTRACING_PAL_TCP
+#ifdef ENABLE_PERFTRACING_PAL_TCP
#define DS_IPC_PAL_TCP
#else
#ifndef HOST_WIN32
@@ -21,11 +21,11 @@
#endif
#endif
-#ifdef FEATURE_PERFTRACING_DISABLE_CONNECT_PORTS
+#ifdef ENABLE_PERFTRACING_DISABLE_CONNECT_PORTS
#define DS_IPC_DISABLE_CONNECT_PORTS
#endif
-#ifdef FEATURE_PERFTRACING_DISABLE_LISTEN_PORTS
+#ifdef ENABLE_PERFTRACING_DISABLE_LISTEN_PORTS
#define DS_IPC_DISABLE_LISTEN_PORTS
#endif
diff --git a/src/native/eventpipe/ds-server.c b/src/native/eventpipe/ds-server.c
index 7f9c6866e0341c..dfce6d6860464e 100644
--- a/src/native/eventpipe/ds-server.c
+++ b/src/native/eventpipe/ds-server.c
@@ -116,7 +116,7 @@ EP_RT_DEFINE_THREAD_FUNC (server_thread)
EP_ASSERT (server_volatile_load_shutting_down_state () || ds_ipc_stream_factory_has_active_ports ());
if (!ds_ipc_stream_factory_has_active_ports ()) {
-#ifndef DS_IPC_PAL_TCP
+#ifndef DS_IPC_DISABLE_LISTEN_PORTS
DS_LOG_ERROR_0 ("Diagnostics IPC listener was undefined");
#endif
return 1;
diff --git a/src/native/eventpipe/ep-buffer-manager.c b/src/native/eventpipe/ep-buffer-manager.c
index bcab43e1d34480..5b7c0592caf1b3 100644
--- a/src/native/eventpipe/ep-buffer-manager.c
+++ b/src/native/eventpipe/ep-buffer-manager.c
@@ -1371,6 +1371,7 @@ ep_buffer_manager_write_all_buffers_to_file_v4 (
}
ep_on_exit:
+ ep_rt_thread_session_state_array_fini(&session_states_to_delete);
return;
ep_on_error:
ep_exit_error_handler ();
diff --git a/src/native/eventpipe/ep-ipc-pal-types-forward.h b/src/native/eventpipe/ep-ipc-pal-types-forward.h
new file mode 100644
index 00000000000000..2c890cce81a772
--- /dev/null
+++ b/src/native/eventpipe/ep-ipc-pal-types-forward.h
@@ -0,0 +1,22 @@
+#ifndef __EVENTPIPE_IPC_PAL_TYPES_FORWARD_H__
+#define __EVENTPIPE_IPC_PAL_TYPES_FORWARD_H__
+
+#ifdef ENABLE_PERFTRACING
+
+#include
+#include
+#ifndef __cplusplus
+#include
+#endif // __cplusplus
+
+typedef char ep_char8_t;
+
+/*
+ * IPC Stream Structs.
+ */
+
+typedef struct _IpcStream IpcStream;
+typedef struct _IpcStreamVtable IpcStreamVtable;
+
+#endif /* ENABLE_PERFTRACING */
+#endif /* __EVENTPIPE_IPC_PAL_TYPES_FORWARD_H__ */
diff --git a/src/native/eventpipe/ep-ipc-pal-types.h b/src/native/eventpipe/ep-ipc-pal-types.h
index ac2f3d0c5bd678..a353b8a3c104c8 100644
--- a/src/native/eventpipe/ep-ipc-pal-types.h
+++ b/src/native/eventpipe/ep-ipc-pal-types.h
@@ -9,20 +9,7 @@
#endif
#include "ep-getter-setter.h"
-#include
-#include
-#ifndef __cplusplus
-#include
-#endif // __cplusplus
-
-typedef char ep_char8_t;
-
-/*
- * IPC Stream Structs.
- */
-
-typedef struct _IpcStream IpcStream;
-typedef struct _IpcStreamVtable IpcStreamVtable;
+#include "ep-ipc-pal-types-forward.h"
#endif /* ENABLE_PERFTRACING */
#endif /* __EVENTPIPE_IPC_PAL_TYPES_H__ */
diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h
new file mode 100644
index 00000000000000..c6954d632961cd
--- /dev/null
+++ b/src/native/eventpipe/ep-types-forward.h
@@ -0,0 +1,207 @@
+#ifndef __EVENTPIPE_TYPES_FORWARD_H__
+#define __EVENTPIPE_TYPES_FORWARD_H__
+
+#ifdef ENABLE_PERFTRACING
+
+/*
+ * EventPipe Structs.
+ */
+
+typedef struct _EventData EventData;
+typedef struct _EventFilterDescriptor EventFilterDescriptor;
+typedef struct _EventPipeBuffer EventPipeBuffer;
+typedef struct _EventPipeBufferList EventPipeBufferList;
+typedef struct _EventPipeBufferManager EventPipeBufferManager;
+typedef struct _EventPipeBlock EventPipeBlock;
+typedef struct _EventPipeBlockVtable EventPipeBlockVtable;
+typedef struct _EventPipeConfiguration EventPipeConfiguration;
+typedef struct _EventPipeEvent EventPipeEvent;
+typedef struct _EventPipeEventBlockBase EventPipeEventBlockBase;
+typedef struct _EventPipeEventBlock EventPipeEventBlock;
+typedef struct _EventPipeEventHeader EventPipeEventHeader;
+typedef struct _EventPipeEventInstance EventPipeEventInstance;
+typedef struct _EventPipeEventMetadataEvent EventPipeEventMetadataEvent;
+typedef struct _EventPipeEventPayload EventPipeEventPayload;
+typedef struct _EventPipeEventSource EventPipeEventSource;
+typedef struct _EventPipeFile EventPipeFile;
+typedef struct _EventPipeJsonFile EventPipeJsonFile;
+typedef struct _EventPipeMetadataBlock EventPipeMetadataBlock;
+typedef struct _EventPipeParameterDesc EventPipeParameterDesc;
+typedef struct _EventPipeProvider EventPipeProvider;
+typedef struct _EventPipeProviderCallbackData EventPipeProviderCallbackData;
+typedef struct _EventPipeProviderCallbackDataQueue EventPipeProviderCallbackDataQueue;
+typedef struct _EventPipeProviderConfiguration EventPipeProviderConfiguration;
+typedef struct _EventPipeSession EventPipeSession;
+typedef struct _EventPipeSessionProvider EventPipeSessionProvider;
+typedef struct _EventPipeSessionProviderList EventPipeSessionProviderList;
+typedef struct _EventPipeSequencePoint EventPipeSequencePoint;
+typedef struct _EventPipeSequencePointBlock EventPipeSequencePointBlock;
+typedef struct _EventPipeStackBlock EventPipeStackBlock;
+typedef struct _EventPipeStackContents EventPipeStackContents;
+typedef struct _EventPipeSystemTime EventPipeSystemTime;
+typedef struct _EventPipeThread EventPipeThread;
+typedef struct _EventPipeThreadHolder EventPipeThreadHolder;
+typedef struct _EventPipeThreadSessionState EventPipeThreadSessionState;
+typedef struct _FastSerializableObject FastSerializableObject;
+typedef struct _FastSerializableObjectVtable FastSerializableObjectVtable;
+typedef struct _FastSerializer FastSerializer;
+typedef struct _FileStream FileStream;
+typedef struct _FileStreamWriter FileStreamWriter;
+typedef struct _IpcStreamWriter IpcStreamWriter;
+typedef struct _StackHashEntry StackHashEntry;
+typedef struct _StackHashKey StackHashKey;
+typedef struct _StreamWriter StreamWriter;
+typedef struct _StreamWriterVtable StreamWriterVtable;
+
+#define EP_MAX_NUMBER_OF_SESSIONS 64
+
+#define EP_GUID_SIZE 16
+
+#define EP_ACTIVITY_ID_SIZE EP_GUID_SIZE
+
+#define EP_MAX_STACK_DEPTH 100
+
+/*
+ * EventPipe Enums.
+ */
+
+typedef enum {
+ EP_BUFFER_STATE_WRITABLE = 0,
+ EP_BUFFER_STATE_READ_ONLY = 1
+} EventPipeBufferState;
+
+typedef enum {
+ EP_EVENT_LEVEL_LOGALWAYS,
+ EP_EVENT_LEVEL_CRITICAL,
+ EP_EVENT_LEVEL_ERROR,
+ EP_EVENT_LEVEL_WARNING,
+ EP_EVENT_LEVEL_INFORMATIONAL,
+ EP_EVENT_LEVEL_VERBOSE
+} EventPipeEventLevel;
+
+typedef enum {
+ EP_FILE_FLUSH_FLAGS_EVENT_BLOCK = 1,
+ EP_FILE_FLUSH_FLAGS_METADATA_BLOCK = 2,
+ EP_FILE_FLUSH_FLAGS_STACK_BLOCK = 4,
+ EP_FILE_FLUSH_FLAGS_ALL_BLOCKS = EP_FILE_FLUSH_FLAGS_EVENT_BLOCK | EP_FILE_FLUSH_FLAGS_METADATA_BLOCK | EP_FILE_FLUSH_FLAGS_STACK_BLOCK
+} EventPipeFileFlushFlags;
+
+// Represents the type of an event parameter.
+// This enum is derived from the managed TypeCode type, though
+// not all of these values are available in TypeCode.
+// For example, Guid does not exist in TypeCode.
+// Keep this in sync with COR_PRF_EVENTPIPE_PARAM_TYPE defined in
+// corprof.idl
+typedef enum {
+ EP_PARAMETER_TYPE_EMPTY = 0, // Null reference
+ EP_PARAMETER_TYPE_OBJECT = 1, // Instance that isn't a value
+ EP_PARAMETER_TYPE_DB_NULL = 2, // Database null value
+ EP_PARAMETER_TYPE_BOOLEAN = 3, // Boolean
+ EP_PARAMETER_TYPE_CHAR = 4, // Unicode character
+ EP_PARAMETER_TYPE_SBYTE = 5, // Signed 8-bit integer
+ EP_PARAMETER_TYPE_BYTE = 6, // Unsigned 8-bit integer
+ EP_PARAMETER_TYPE_INT16 = 7, // Signed 16-bit integer
+ EP_PARAMETER_TYPE_UINT16 = 8, // Unsigned 16-bit integer
+ EP_PARAMETER_TYPE_INT32 = 9, // Signed 32-bit integer
+ EP_PARAMETER_TYPE_UINT32 = 10, // Unsigned 32-bit integer
+ EP_PARAMETER_TYPE_INT64 = 11, // Signed 64-bit integer
+ EP_PARAMETER_TYPE_UINT64 = 12, // Unsigned 64-bit integer
+ EP_PARAMETER_TYPE_SINGLE = 13, // IEEE 32-bit float
+ EP_PARAMETER_TYPE_DOUBLE = 14, // IEEE 64-bit double
+ EP_PARAMETER_TYPE_DECIMAL = 15, // Decimal
+ EP_PARAMETER_TYPE_DATE_TIME = 16, // DateTime
+ EP_PARAMETER_TYPE_GUID = 17, // Guid
+ EP_PARAMETER_TYPE_STRING = 18, // Unicode character string
+ EP_PARAMETER_TYPE_ARRAY = 19 // Indicates the type is an arbitrary sized array
+} EventPipeParameterType;
+
+typedef enum {
+ EP_METADATA_TAG_OPCODE = 1,
+ EP_METADATA_TAG_PARAMETER_PAYLOAD = 2
+} EventPipeMetadataTag;
+
+typedef enum {
+ EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR = 0,
+ EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL = 1,
+ EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED = 2
+} EventPipeSampleProfilerSampleType;
+
+typedef enum {
+ // Default format used in .Net Core 2.0-3.0 Preview 6
+ // TBD - it may remain the default format .Net Core 3.0 when
+ // used with private EventPipe managed API via reflection.
+ // This format had limited official exposure in documented
+ // end-user RTM scenarios, but it is supported by PerfView,
+ // TraceEvent, and was used by AI profiler.
+ EP_SERIALIZATION_FORMAT_NETPERF_V3,
+ // Default format we plan to use in .Net Core 3 Preview7+
+ // for most if not all scenarios.
+ EP_SERIALIZATION_FORMAT_NETTRACE_V4,
+ EP_SERIALIZATION_FORMAT_COUNT
+} EventPipeSerializationFormat;
+
+typedef enum {
+ EP_SESSION_TYPE_FILE,
+ EP_SESSION_TYPE_LISTENER,
+ EP_SESSION_TYPE_IPCSTREAM,
+ EP_SESSION_TYPE_SYNCHRONOUS
+} EventPipeSessionType ;
+
+typedef enum {
+ EP_STATE_NOT_INITIALIZED,
+ EP_STATE_INITIALIZED,
+ EP_STATE_SHUTTING_DOWN
+} EventPipeState;
+
+typedef enum {
+ EP_THREAD_TYPE_SERVER,
+ EP_THREAD_TYPE_SESSION,
+ EP_THREAD_TYPE_SAMPLING
+} EventPipeThreadType;
+
+/*
+ * EventPipe Basic Types.
+ */
+
+typedef intptr_t EventPipeWaitHandle;
+typedef uint64_t EventPipeSessionID;
+typedef unsigned short ep_char16_t;
+typedef int64_t ep_timestamp_t;
+typedef int64_t ep_system_timestamp_t;
+
+/*
+ * EventPipe Callbacks.
+ */
+
+// Define the event pipe callback to match the ETW callback signature.
+typedef void (*EventPipeCallback)(
+ const uint8_t *source_id,
+ unsigned long is_enabled,
+ uint8_t level,
+ uint64_t match_any_keywords,
+ uint64_t match_all_keywords,
+ EventFilterDescriptor *filter_data,
+ void *callback_data);
+
+typedef void (*EventPipeCallbackDataFree)(
+ EventPipeCallback callback,
+ void *callback_data);
+
+typedef void (*EventPipeSessionSynchronousCallback)(
+ EventPipeProvider *provider,
+ uint32_t event_id,
+ uint32_t event_version,
+ uint32_t metadata_blob_len,
+ const uint8_t *metadata_blob,
+ uint32_t event_data_len,
+ const uint8_t *event_data,
+ const uint8_t *activity_id,
+ const uint8_t *related_activity_id,
+ /*ep_rt_thread_handle_t*/ void *event_thread,
+ uint32_t stack_frames_len,
+ uintptr_t *stack_frames);
+
+typedef bool (*EventPipeIpcStreamFactorySuspendedPortsCallback)(void);
+
+#endif /* ENABLE_PERFTRACING */
+#endif /* __EVENTPIPE_TYPES_FORWARD_H__ */
diff --git a/src/native/eventpipe/ep-types.h b/src/native/eventpipe/ep-types.h
index 0c91757fcfbe95..22ad3a749bf865 100644
--- a/src/native/eventpipe/ep-types.h
+++ b/src/native/eventpipe/ep-types.h
@@ -10,206 +10,10 @@
#endif
#include "ep-getter-setter.h"
-/*
- * EventPipe Structs.
- */
-
-typedef struct _EventData EventData;
-typedef struct _EventFilterDescriptor EventFilterDescriptor;
-typedef struct _EventPipeBuffer EventPipeBuffer;
-typedef struct _EventPipeBufferList EventPipeBufferList;
-typedef struct _EventPipeBufferManager EventPipeBufferManager;
-typedef struct _EventPipeBlock EventPipeBlock;
-typedef struct _EventPipeBlockVtable EventPipeBlockVtable;
-typedef struct _EventPipeConfiguration EventPipeConfiguration;
-typedef struct _EventPipeEvent EventPipeEvent;
-typedef struct _EventPipeEventBlockBase EventPipeEventBlockBase;
-typedef struct _EventPipeEventBlock EventPipeEventBlock;
-typedef struct _EventPipeEventHeader EventPipeEventHeader;
-typedef struct _EventPipeEventInstance EventPipeEventInstance;
-typedef struct _EventPipeEventMetadataEvent EventPipeEventMetadataEvent;
-typedef struct _EventPipeEventPayload EventPipeEventPayload;
-typedef struct _EventPipeEventSource EventPipeEventSource;
-typedef struct _EventPipeFile EventPipeFile;
-typedef struct _EventPipeJsonFile EventPipeJsonFile;
-typedef struct _EventPipeMetadataBlock EventPipeMetadataBlock;
-typedef struct _EventPipeParameterDesc EventPipeParameterDesc;
-typedef struct _EventPipeProvider EventPipeProvider;
-typedef struct _EventPipeProviderCallbackData EventPipeProviderCallbackData;
-typedef struct _EventPipeProviderCallbackDataQueue EventPipeProviderCallbackDataQueue;
-typedef struct _EventPipeProviderConfiguration EventPipeProviderConfiguration;
-typedef struct _EventPipeSession EventPipeSession;
-typedef struct _EventPipeSessionProvider EventPipeSessionProvider;
-typedef struct _EventPipeSessionProviderList EventPipeSessionProviderList;
-typedef struct _EventPipeSequencePoint EventPipeSequencePoint;
-typedef struct _EventPipeSequencePointBlock EventPipeSequencePointBlock;
-typedef struct _EventPipeStackBlock EventPipeStackBlock;
-typedef struct _EventPipeStackContents EventPipeStackContents;
-typedef struct _EventPipeSystemTime EventPipeSystemTime;
-typedef struct _EventPipeThread EventPipeThread;
-typedef struct _EventPipeThreadHolder EventPipeThreadHolder;
-typedef struct _EventPipeThreadSessionState EventPipeThreadSessionState;
-typedef struct _FastSerializableObject FastSerializableObject;
-typedef struct _FastSerializableObjectVtable FastSerializableObjectVtable;
-typedef struct _FastSerializer FastSerializer;
-typedef struct _FileStream FileStream;
-typedef struct _FileStreamWriter FileStreamWriter;
-typedef struct _IpcStreamWriter IpcStreamWriter;
-typedef struct _StackHashEntry StackHashEntry;
-typedef struct _StackHashKey StackHashKey;
-typedef struct _StreamWriter StreamWriter;
-typedef struct _StreamWriterVtable StreamWriterVtable;
-
-#define EP_MAX_NUMBER_OF_SESSIONS 64
-
-#define EP_GUID_SIZE 16
-
-#define EP_ACTIVITY_ID_SIZE EP_GUID_SIZE
-
-#define EP_MAX_STACK_DEPTH 100
-
-/*
- * EventPipe Enums.
- */
-
-typedef enum {
- EP_BUFFER_STATE_WRITABLE = 0,
- EP_BUFFER_STATE_READ_ONLY = 1
-} EventPipeBufferState;
-
-typedef enum {
- EP_EVENT_LEVEL_LOGALWAYS,
- EP_EVENT_LEVEL_CRITICAL,
- EP_EVENT_LEVEL_ERROR,
- EP_EVENT_LEVEL_WARNING,
- EP_EVENT_LEVEL_INFORMATIONAL,
- EP_EVENT_LEVEL_VERBOSE
-} EventPipeEventLevel;
-
-typedef enum {
- EP_FILE_FLUSH_FLAGS_EVENT_BLOCK = 1,
- EP_FILE_FLUSH_FLAGS_METADATA_BLOCK = 2,
- EP_FILE_FLUSH_FLAGS_STACK_BLOCK = 4,
- EP_FILE_FLUSH_FLAGS_ALL_BLOCKS = EP_FILE_FLUSH_FLAGS_EVENT_BLOCK | EP_FILE_FLUSH_FLAGS_METADATA_BLOCK | EP_FILE_FLUSH_FLAGS_STACK_BLOCK
-} EventPipeFileFlushFlags;
-
-// Represents the type of an event parameter.
-// This enum is derived from the managed TypeCode type, though
-// not all of these values are available in TypeCode.
-// For example, Guid does not exist in TypeCode.
-// Keep this in sync with COR_PRF_EVENTPIPE_PARAM_TYPE defined in
-// corprof.idl
-typedef enum {
- EP_PARAMETER_TYPE_EMPTY = 0, // Null reference
- EP_PARAMETER_TYPE_OBJECT = 1, // Instance that isn't a value
- EP_PARAMETER_TYPE_DB_NULL = 2, // Database null value
- EP_PARAMETER_TYPE_BOOLEAN = 3, // Boolean
- EP_PARAMETER_TYPE_CHAR = 4, // Unicode character
- EP_PARAMETER_TYPE_SBYTE = 5, // Signed 8-bit integer
- EP_PARAMETER_TYPE_BYTE = 6, // Unsigned 8-bit integer
- EP_PARAMETER_TYPE_INT16 = 7, // Signed 16-bit integer
- EP_PARAMETER_TYPE_UINT16 = 8, // Unsigned 16-bit integer
- EP_PARAMETER_TYPE_INT32 = 9, // Signed 32-bit integer
- EP_PARAMETER_TYPE_UINT32 = 10, // Unsigned 32-bit integer
- EP_PARAMETER_TYPE_INT64 = 11, // Signed 64-bit integer
- EP_PARAMETER_TYPE_UINT64 = 12, // Unsigned 64-bit integer
- EP_PARAMETER_TYPE_SINGLE = 13, // IEEE 32-bit float
- EP_PARAMETER_TYPE_DOUBLE = 14, // IEEE 64-bit double
- EP_PARAMETER_TYPE_DECIMAL = 15, // Decimal
- EP_PARAMETER_TYPE_DATE_TIME = 16, // DateTime
- EP_PARAMETER_TYPE_GUID = 17, // Guid
- EP_PARAMETER_TYPE_STRING = 18, // Unicode character string
- EP_PARAMETER_TYPE_ARRAY = 19 // Indicates the type is an arbitrary sized array
-} EventPipeParameterType;
-
-typedef enum {
- EP_METADATA_TAG_OPCODE = 1,
- EP_METADATA_TAG_PARAMETER_PAYLOAD = 2
-} EventPipeMetadataTag;
-
-typedef enum {
- EP_SAMPLE_PROFILER_SAMPLE_TYPE_ERROR = 0,
- EP_SAMPLE_PROFILER_SAMPLE_TYPE_EXTERNAL = 1,
- EP_SAMPLE_PROFILER_SAMPLE_TYPE_MANAGED = 2
-} EventPipeSampleProfilerSampleType;
-
-typedef enum {
- // Default format used in .Net Core 2.0-3.0 Preview 6
- // TBD - it may remain the default format .Net Core 3.0 when
- // used with private EventPipe managed API via reflection.
- // This format had limited official exposure in documented
- // end-user RTM scenarios, but it is supported by PerfView,
- // TraceEvent, and was used by AI profiler.
- EP_SERIALIZATION_FORMAT_NETPERF_V3,
- // Default format we plan to use in .Net Core 3 Preview7+
- // for most if not all scenarios.
- EP_SERIALIZATION_FORMAT_NETTRACE_V4,
- EP_SERIALIZATION_FORMAT_COUNT
-} EventPipeSerializationFormat;
-
-typedef enum {
- EP_SESSION_TYPE_FILE,
- EP_SESSION_TYPE_LISTENER,
- EP_SESSION_TYPE_IPCSTREAM,
- EP_SESSION_TYPE_SYNCHRONOUS
-} EventPipeSessionType ;
-
-typedef enum {
- EP_STATE_NOT_INITIALIZED,
- EP_STATE_INITIALIZED,
- EP_STATE_SHUTTING_DOWN
-} EventPipeState;
-
-typedef enum {
- EP_THREAD_TYPE_SERVER,
- EP_THREAD_TYPE_SESSION,
- EP_THREAD_TYPE_SAMPLING
-} EventPipeThreadType;
-
-/*
- * EventPipe Basic Types.
- */
-
-typedef intptr_t EventPipeWaitHandle;
-typedef uint64_t EventPipeSessionID;
-typedef unsigned short ep_char16_t;
-typedef int64_t ep_timestamp_t;
-typedef int64_t ep_system_timestamp_t;
+#include "ep-types-forward.h"
#include "ep-rt-types.h"
-/*
- * EventPipe Callbacks.
- */
-
-// Define the event pipe callback to match the ETW callback signature.
-typedef void (*EventPipeCallback)(
- const uint8_t *source_id,
- unsigned long is_enabled,
- uint8_t level,
- uint64_t match_any_keywords,
- uint64_t match_all_keywords,
- EventFilterDescriptor *filter_data,
- void *callback_data);
-
-typedef void (*EventPipeCallbackDataFree)(
- EventPipeCallback callback,
- void *callback_data);
-
-typedef void (*EventPipeSessionSynchronousCallback)(
- EventPipeProvider *provider,
- uint32_t event_id,
- uint32_t event_version,
- uint32_t metadata_blob_len,
- const uint8_t *metadata_blob,
- uint32_t event_data_len,
- const uint8_t *event_data,
- const uint8_t *activity_id,
- const uint8_t *related_activity_id,
- ep_rt_thread_handle_t event_thread,
- uint32_t stack_frames_len,
- uintptr_t *stack_frames);
-
/*
* EventFilterDescriptor.
*/
diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c
index 5517c7d98fcc75..9552dd59eb11a3 100644
--- a/src/native/eventpipe/ep.c
+++ b/src/native/eventpipe/ep.c
@@ -20,6 +20,8 @@ static bool _ep_can_start_threads = false;
static ep_rt_session_id_array_t _ep_deferred_enable_session_ids = { 0 };
static ep_rt_session_id_array_t _ep_deferred_disable_session_ids = { 0 };
+static EventPipeIpcStreamFactorySuspendedPortsCallback _ep_ipc_stream_factory_suspended_ports_callback = NULL;
+
/*
* Forward declares of all static functions.
*/
@@ -842,8 +844,7 @@ static
bool
ipc_stream_factory_any_suspended_ports (void)
{
- extern bool ds_ipc_stream_factory_any_suspended_ports (void);
- return ds_ipc_stream_factory_any_suspended_ports ();
+ return _ep_ipc_stream_factory_suspended_ports_callback ? _ep_ipc_stream_factory_suspended_ports_callback () : false;
}
#ifdef EP_CHECKED_BUILD
@@ -1523,6 +1524,12 @@ ep_system_time_set (
system_time->milliseconds = milliseconds;
}
+void
+ep_ipc_stream_factory_callback_set (EventPipeIpcStreamFactorySuspendedPortsCallback suspended_ports_callback)
+{
+ _ep_ipc_stream_factory_suspended_ports_callback = suspended_ports_callback;
+}
+
#endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */
#endif /* ENABLE_PERFTRACING */
diff --git a/src/native/eventpipe/ep.h b/src/native/eventpipe/ep.h
index cfb99aa9d65a92..fb2dafd246924c 100644
--- a/src/native/eventpipe/ep.h
+++ b/src/native/eventpipe/ep.h
@@ -337,6 +337,13 @@ ep_system_time_get (EventPipeSystemTime *system_time)
ep_rt_system_time_get (system_time);
}
+/*
+ * EventPipeIpcStreamFactoryCallback.
+ */
+
+void
+ep_ipc_stream_factory_callback_set (EventPipeIpcStreamFactorySuspendedPortsCallback suspended_ports_callback);
+
#else /* ENABLE_PERFTRACING */
static
diff --git a/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs b/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs
index af036e41e27375..7667f0ae6fe8e4 100644
--- a/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs
+++ b/src/tasks/AndroidAppBuilder/AndroidAppBuilder.cs
@@ -33,6 +33,11 @@ public class AndroidAppBuilderTask : Task
///
public bool ForceAOT { get; set; }
+ ///
+ /// List of components to static link, if available
+ ///
+ public string? StaticLinkedComponentNames { get; set; } = ""!;
+
[Required]
public string RuntimeIdentifier { get; set; } = ""!;
@@ -90,6 +95,7 @@ public override bool Execute()
apkBuilder.KeyStorePath = KeyStorePath;
apkBuilder.ForceInterpreter = ForceInterpreter;
apkBuilder.ForceAOT = ForceAOT;
+ apkBuilder.StaticLinkedComponentNames = StaticLinkedComponentNames;
apkBuilder.Assemblies = Assemblies;
(ApkBundlePath, ApkPackageId) = apkBuilder.BuildApk(abi, MainLibraryFileName, MonoRuntimeHeaders);
diff --git a/src/tasks/AndroidAppBuilder/ApkBuilder.cs b/src/tasks/AndroidAppBuilder/ApkBuilder.cs
index 0ce54fd15c1d6d..67e5cd7c6a5c2c 100644
--- a/src/tasks/AndroidAppBuilder/ApkBuilder.cs
+++ b/src/tasks/AndroidAppBuilder/ApkBuilder.cs
@@ -24,6 +24,7 @@ public class ApkBuilder
public string? KeyStorePath { get; set; }
public bool ForceInterpreter { get; set; }
public bool ForceAOT { get; set; }
+ public string? StaticLinkedComponentNames { get; set; }
public ITaskItem[] Assemblies { get; set; } = Array.Empty();
public (string apk, string packageId) BuildApk(
@@ -171,6 +172,7 @@ public class ApkBuilder
// 1. Build libmonodroid.so` via cmake
+ string nativeLibraries = "";
string monoRuntimeLib = Path.Combine(AppDir, "libmonosgen-2.0.a");
if (!File.Exists(monoRuntimeLib))
{
@@ -178,9 +180,56 @@ public class ApkBuilder
}
else
{
- monoRuntimeLib = $" {monoRuntimeLib}{Environment.NewLine}";
+ nativeLibraries += $"{monoRuntimeLib}{Environment.NewLine}";
}
+ string[] staticComponentStubLibs = Directory.GetFiles(AppDir, "libmono-component-*-stub-static.a");
+ bool staticLinkAllComponents = false;
+ string[] componentNames = Array.Empty();
+
+ if (!string.IsNullOrEmpty(StaticLinkedComponentNames) && StaticLinkedComponentNames.Equals("*", StringComparison.OrdinalIgnoreCase))
+ staticLinkAllComponents = true;
+ else if (!string.IsNullOrEmpty(StaticLinkedComponentNames))
+ componentNames = StaticLinkedComponentNames.Split(";");
+
+ // by default, component stubs will be linked and depending on how mono runtime has been build,
+ // stubs can disable or dynamic load components.
+ foreach (string staticComponentStubLib in staticComponentStubLibs)
+ {
+ string componentLibToLink = staticComponentStubLib;
+ if (staticLinkAllComponents)
+ {
+ // static link component.
+ componentLibToLink = componentLibToLink.Replace("-stub-static.a", "-static.a", StringComparison.OrdinalIgnoreCase);
+ }
+ else
+ {
+ foreach (string componentName in componentNames)
+ {
+ if (componentLibToLink.Contains(componentName, StringComparison.OrdinalIgnoreCase))
+ {
+ // static link component.
+ componentLibToLink = componentLibToLink.Replace("-stub-static.a", "-static.a", StringComparison.OrdinalIgnoreCase);
+ break;
+ }
+ }
+ }
+
+ // if lib doesn't exist (primarly due to runtime build without static lib support), fallback linking stub lib.
+ if (!File.Exists(componentLibToLink))
+ {
+ Utils.LogInfo($"\nCouldn't find static component library: {componentLibToLink}, linking static component stub library: {staticComponentStubLib}.\n");
+ componentLibToLink = staticComponentStubLib;
+ }
+
+ nativeLibraries += $" {componentLibToLink}{Environment.NewLine}";
+ }
+
+ // There's a circular dependecy between static mono runtime lib and static component libraries.
+ // Adding mono runtime lib before and after component libs will resolve issues with undefined symbols
+ // due to circular dependecy.
+ nativeLibraries += $" {monoRuntimeLib}{Environment.NewLine}";
+
string aotSources = "";
foreach (string asm in assemblerFiles)
{
@@ -190,7 +239,7 @@ public class ApkBuilder
string cmakeLists = Utils.GetEmbeddedResource("CMakeLists-android.txt")
.Replace("%MonoInclude%", monoRuntimeHeaders)
- .Replace("%NativeLibrariesToLink%", monoRuntimeLib)
+ .Replace("%NativeLibrariesToLink%", nativeLibraries)
.Replace("%AotSources%", aotSources)
.Replace("%AotModulesSource%", string.IsNullOrEmpty(aotSources) ? "" : "modules.c");
diff --git a/src/tasks/AppleAppBuilder/AppleAppBuilder.cs b/src/tasks/AppleAppBuilder/AppleAppBuilder.cs
index 6affce39e30f5b..85efde52b045fa 100644
--- a/src/tasks/AppleAppBuilder/AppleAppBuilder.cs
+++ b/src/tasks/AppleAppBuilder/AppleAppBuilder.cs
@@ -126,6 +126,11 @@ public string TargetOS
///
public bool ForceAOT { get; set; }
+ ///
+ /// List of components to static link, if available
+ ///
+ public string? StaticLinkedComponentNames { get; set; } = ""!;
+
///
/// Forces the runtime to use the invariant mode
///
@@ -199,7 +204,7 @@ public override bool Execute()
generator.EnableRuntimeLogging = EnableRuntimeLogging;
XcodeProjectPath = generator.GenerateXCode(ProjectName, MainLibraryFileName, assemblerFiles,
- AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, NativeMainSource);
+ AppDir, binDir, MonoRuntimeHeaders, !isDevice, UseConsoleUITemplate, ForceAOT, ForceInterpreter, InvariantGlobalization, Optimized, StaticLinkedComponentNames, NativeMainSource);
if (BuildAppBundle)
{
diff --git a/src/tasks/AppleAppBuilder/Xcode.cs b/src/tasks/AppleAppBuilder/Xcode.cs
index 442eb539af38b2..90bf0ff56ab2aa 100644
--- a/src/tasks/AppleAppBuilder/Xcode.cs
+++ b/src/tasks/AppleAppBuilder/Xcode.cs
@@ -53,6 +53,7 @@ public string GenerateXCode(
bool forceInterpreter,
bool invariantGlobalization,
bool stripDebugSymbols,
+ string? staticLinkedComponentNames=null,
string? nativeMainSource = null)
{
// bundle everything as resources excluding native files
@@ -102,11 +103,58 @@ public string GenerateXCode(
.Replace("%MonoInclude%", monoInclude)
.Replace("%HardenedRuntime%", hardenedRuntime ? "TRUE" : "FALSE");
+ string toLink = "";
+
+ string[] allComponentLibs = Directory.GetFiles(workspace, "libmono-component-*-static.a");
+ string[] staticComponentStubLibs = Directory.GetFiles(workspace, "libmono-component-*-stub-static.a");
+ bool staticLinkAllComponents = false;
+ string[] componentNames = Array.Empty();
+
+ if (!string.IsNullOrEmpty(staticLinkedComponentNames) && staticLinkedComponentNames.Equals("*", StringComparison.OrdinalIgnoreCase))
+ staticLinkAllComponents = true;
+ else if (!string.IsNullOrEmpty(staticLinkedComponentNames))
+ componentNames = staticLinkedComponentNames.Split(";");
+
+ // by default, component stubs will be linked and depending on how mono runtime has been build,
+ // stubs can disable or dynamic load components.
+ foreach (string staticComponentStubLib in staticComponentStubLibs)
+ {
+ string componentLibToLink = staticComponentStubLib;
+ if (staticLinkAllComponents)
+ {
+ // static link component.
+ componentLibToLink = componentLibToLink.Replace("-stub-static.a", "-static.a", StringComparison.OrdinalIgnoreCase);
+ }
+ else
+ {
+ foreach (string componentName in componentNames)
+ {
+ if (componentLibToLink.Contains(componentName, StringComparison.OrdinalIgnoreCase))
+ {
+ // static link component.
+ componentLibToLink = componentLibToLink.Replace("-stub-static.a", "-static.a", StringComparison.OrdinalIgnoreCase);
+ break;
+ }
+ }
+ }
+
+ // if lib doesn't exist (primarly due to runtime build without static lib support), fallback linking stub lib.
+ if (!File.Exists(componentLibToLink))
+ {
+ Utils.LogInfo($"\nCouldn't find static component library: {componentLibToLink}, linking static component stub library: {staticComponentStubLib}.\n");
+ componentLibToLink = staticComponentStubLib;
+ }
+
+ toLink += $" \"-force_load {componentLibToLink}\"{Environment.NewLine}";
+ }
string[] dylibs = Directory.GetFiles(workspace, "*.dylib");
- string toLink = "";
foreach (string lib in Directory.GetFiles(workspace, "*.a"))
{
+ // all component libs already added to linker.
+ if (allComponentLibs.Any(lib.Contains))
+ continue;
+
string libName = Path.GetFileNameWithoutExtension(lib);
// libmono must always be statically linked, for other librarires we can use dylibs
bool dylibExists = libName != "libmonosgen-2.0" && dylibs.Any(dylib => Path.GetFileName(dylib) == libName + ".dylib");