From 5525d0bbb57d5550d71a0a15158f992b0e694000 Mon Sep 17 00:00:00 2001 From: Johan Lorensson Date: Tue, 25 May 2021 10:32:44 +0200 Subject: [PATCH] Emit JITStarting, MethodLoad, ModuleLoad and AssemblyLoad EventPipe events on Mono. (#53020) * Add native JIT event into EventPipe. * Emit module/assembly load native events into EventPipe. * Emit MethodDCEnd_V1 and MethodILToNativeMap EventPipe events. --- src/coreclr/scripts/genEventPipe.py | 6 +- src/coreclr/scripts/genEventing.py | 11 +- src/mono/mono/eventpipe/ep-rt-mono.c | 645 ++++++++++++++++++++- src/mono/mono/eventpipe/ep-rt-mono.h | 70 ++- src/mono/mono/eventpipe/gen-eventing-event-inc.lst | 19 +- src/mono/mono/eventpipe/test/ep-teardown-tests.c | 2 + src/mono/mono/eventpipe/test/ep-tests.c | 82 +++ 7 files changed, 802 insertions(+), 33 deletions(-) diff --git a/src/coreclr/scripts/genEventPipe.py b/src/coreclr/scripts/genEventPipe.py index 8ec9e21..380710d 100644 --- a/src/coreclr/scripts/genEventPipe.py +++ b/src/coreclr/scripts/genEventPipe.py @@ -166,13 +166,11 @@ def generateClrEventPipeWriteEventsImpl( WriteEventImpl.append("\n return ERROR_SUCCESS;\n}\n\n") # EventPipeProvider and EventPipeEvent initialization - callbackName = "" + callbackName = 'EventPipeEtwCallback' + providerPrettyName createProviderFunc = "" if runtimeFlavor.coreclr: - callbackName = 'EventPipeEtwCallback' + providerPrettyName createProviderFunc = "EventPipeAdapter::CreateProvider" elif runtimeFlavor.mono: - callbackName = "NULL" createProviderFunc = "create_provider" eventPipeCallbackCastExpr = "" @@ -181,6 +179,8 @@ def generateClrEventPipeWriteEventsImpl( else: eventPipeCallbackCastExpr = "(EventPipeCallback)" + if runtimeFlavor.mono: + WriteEventImpl.append("void " + callbackName + "(const uint8_t *, unsigned long, uint8_t, uint64_t, uint64_t, EventFilterDescriptor *, void *);\n\n") if extern: WriteEventImpl.append('extern "C" ') WriteEventImpl.append( diff --git a/src/coreclr/scripts/genEventing.py b/src/coreclr/scripts/genEventing.py index 43fd56b..f1e341a 100644 --- a/src/coreclr/scripts/genEventing.py +++ b/src/coreclr/scripts/genEventing.py @@ -714,6 +714,10 @@ typedef struct _DOTNET_TRACE_CONTEXT else: Clrallevents.write("\n") + if not is_windows and not write_xplatheader: + Clrallevents.write(eventpipe_trace_context_typedef) # define EVENTPIPE_TRACE_CONTEXT + Clrallevents.write("\n") + for providerNode in tree.getElementsByTagName('provider'): templateNodes = providerNode.getElementsByTagName('template') allTemplates = parseTemplateNodes(templateNodes) @@ -725,9 +729,12 @@ typedef struct _DOTNET_TRACE_CONTEXT providerName = providerNode.getAttribute('name') providerSymbol = providerNode.getAttribute('symbol') + eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context" if is_windows: - eventpipeProviderCtxName = providerSymbol + "_EVENTPIPE_Context" - Clrallevents.write(('constexpr ' if target_cpp else 'const ') + 'EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') + Clrallevents.write(('constexpr ' if target_cpp else '') + 'EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') + + if not is_windows and not write_xplatheader: + Clrallevents.write('__attribute__((weak)) EVENTPIPE_TRACE_CONTEXT ' + eventpipeProviderCtxName + ' = { W("' + providerName + '"), 0, false, 0 };\n') if write_xplatheader: clrproviders = os.path.join(incDir, "clrproviders.h") diff --git a/src/mono/mono/eventpipe/ep-rt-mono.c b/src/mono/mono/eventpipe/ep-rt-mono.c index 9cbf980..1fe1119 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono.c +++ b/src/mono/mono/eventpipe/ep-rt-mono.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include #include @@ -48,6 +47,9 @@ char *_ep_rt_mono_managed_cmd_line = NULL; static GArray * _ep_rt_mono_sampled_thread_callstacks = NULL; static uint32_t _ep_rt_mono_max_sampled_thread_count = 32; +// Mono profiler. +static MonoProfilerHandle _ep_rt_mono_profiler = NULL; + // Rundown types. typedef bool @@ -64,6 +66,8 @@ bool const uint16_t count_of_map_entries, const uint32_t *il_offsets, const uint32_t *native_offsets, + bool aot_method, + bool verbose, void *user_data); typedef @@ -118,6 +122,8 @@ typedef struct _EventPipeSampleProfileData { #define METHOD_FLAGS_SHARED_GENERIC_METHOD 0x4 #define METHOD_FLAGS_JITTED_METHOD 0x8 #define METHOD_FLAGS_JITTED_HELPER_METHOD 0x10 +#define METHOD_FLAGS_EXTENT_HOT_SECTION 0x00000000 +#define METHOD_FLAGS_EXTENT_COLD_SECTION 0x10000000 #define MODULE_FLAGS_NATIVE_MODULE 0x2 #define MODULE_FLAGS_DYNAMIC_MODULE 0x4 @@ -149,6 +155,8 @@ fire_method_rundown_events_func ( const uint16_t count_of_map_entries, const uint32_t *il_offsets, const uint32_t *native_offsets, + bool aot_method, + bool verbose, void *user_data); static @@ -228,6 +236,37 @@ profiler_eventpipe_thread_exited ( MonoProfiler *prof, uintptr_t tid); +static +void +profiler_jit_begin ( + MonoProfiler *prof, + MonoMethod *method); + +static +void +profiler_jit_failed ( + MonoProfiler *prof, + MonoMethod *method); + +static +void +profiler_jit_done ( + MonoProfiler *prof, + MonoMethod *method, + MonoJitInfo *ji); + +static +void +profiler_image_loaded ( + MonoProfiler *prof, + MonoImage *image); + +static +void +profiler_assembly_loaded ( + MonoProfiler *prof, + MonoAssembly *assembly); + /* * Forward declares of all private functions (accessed using extern in ep-rt-mono.h). */ @@ -277,6 +316,12 @@ void ep_rt_mono_init_providers_and_events (void); void +ep_rt_mono_provider_config_init (EventPipeProviderConfiguration *provider_config); + +bool +ep_rt_mono_providers_validate_all_disabled (void); + +void ep_rt_mono_fini_providers_and_events (void); bool @@ -328,6 +373,8 @@ fire_method_rundown_events_func ( const uint16_t count_of_map_entries, const uint32_t *il_offsets, const uint32_t *native_offsets, + bool aot_method, + bool verbose, void *user_data) { FireEtwMethodDCEndILToNativeMap ( @@ -341,19 +388,59 @@ fire_method_rundown_events_func ( NULL, NULL); - 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 (), - NULL, - NULL); + if (verbose) { + FireEtwMethodDCEndVerbose_V1 ( + method_id, + module_id, + method_start_address, + method_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION, + method_namespace, + method_name, + method_signature, + clr_instance_get_id (), + NULL, + NULL); + + if (aot_method) + FireEtwMethodDCEndVerbose_V1 ( + method_id, + module_id, + method_start_address, + method_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION, + method_namespace, + method_name, + method_signature, + clr_instance_get_id (), + NULL, + NULL); + } else { + FireEtwMethodDCEnd_V1 ( + method_id, + module_id, + method_start_address, + method_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION, + clr_instance_get_id (), + NULL, + NULL); + + if (aot_method) + FireEtwMethodDCEnd_V1 ( + method_id, + module_id, + method_start_address, + method_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION, + clr_instance_get_id (), + NULL, + NULL); + } return true; } @@ -461,6 +548,7 @@ eventpipe_fire_method_events ( char *method_namespace = NULL; const char *method_name = NULL; char *method_signature = NULL; + bool verbose = (MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.Level >= (uint8_t)EP_EVENT_LEVEL_VERBOSE); //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc. @@ -483,16 +571,20 @@ eventpipe_fire_method_events ( 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); } + + if (verbose) { + method_name = method->name; + method_signature = mono_signature_full_name (method->signature); + if (method->klass) + method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL); + } + } uint16_t offset_entries = 0; @@ -545,6 +637,8 @@ eventpipe_fire_method_events ( offset_entries, il_offsets, native_offsets, + (ji->from_aot || ji->from_llvm), + verbose, NULL); g_free (method_namespace); @@ -793,8 +887,8 @@ ep_rt_mono_init (void) _ep_rt_mono_initialized = TRUE; - MonoProfilerHandle profiler = mono_profiler_create (NULL); - mono_profiler_set_thread_stopped_callback (profiler, profiler_eventpipe_thread_exited); + _ep_rt_mono_profiler = mono_profiler_create (NULL); + mono_profiler_set_thread_stopped_callback (_ep_rt_mono_profiler, profiler_eventpipe_thread_exited); } void @@ -1158,6 +1252,24 @@ ep_rt_mono_init_providers_and_events (void) } void +ep_rt_mono_provider_config_init (EventPipeProviderConfiguration *provider_config) +{ + if (!ep_rt_utf8_string_compare (ep_config_get_rundown_provider_name_utf8 (), ep_provider_config_get_provider_name (provider_config))) { + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.Level = ep_provider_config_get_logging_level (provider_config); + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = ep_provider_config_get_keywords (provider_config); + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.IsEnabled = true; + } +} + +bool +ep_rt_mono_providers_validate_all_disabled (void) +{ + return (!MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled && + !MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.IsEnabled && + !MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.IsEnabled); +} + +void ep_rt_mono_fini_providers_and_events (void) { // dotnet/runtime: issue 12775: EventPipe shutdown race conditions @@ -1349,6 +1461,499 @@ ep_rt_mono_write_event_ee_startup_start (void) NULL); } +bool +ep_rt_mono_write_event_jit_start (MonoMethod *method) +{ + if (!EventEnabledMethodJittingStarted_V1 ()) + return true; + + //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc. + if (method) { + uint64_t method_id = 0; + uint64_t module_id = 0; + uint32_t code_size = 0; + uint32_t method_token = 0; + char *method_namespace = NULL; + const char *method_name = NULL; + char *method_signature = NULL; + + //TODO: SendMethodDetailsEvent + + method_id = (uint64_t)method; + + if (!method->dynamic) + method_token = method->token; + + if (!mono_method_has_no_body (method)) { + ERROR_DECL (error); + MonoMethodHeader *header = mono_method_get_header_internal (method, error); + if (header) + code_size = header->code_size; + } + + 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); + method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL); + } + + FireEtwMethodJittingStarted_V1 ( + method_id, + module_id, + method_token, + code_size, + method_namespace, + method_name, + method_signature, + clr_instance_get_id (), + NULL, + NULL); + + g_free (method_namespace); + g_free (method_signature); + } + + return true; +} + +bool +ep_rt_mono_write_event_method_il_to_native_map ( + MonoMethod *method, + MonoJitInfo *ji) +{ + if (!EventEnabledMethodILToNativeMap ()) + return true; + + if (method) { + // Under netcore we only have root domain. + MonoDomain *root_domain = mono_get_root_domain (); + + uint64_t method_id = (uint64_t)method; + uint32_t fixed_buffer [64]; + uint8_t *buffer = NULL; + + uint16_t offset_entries = 0; + uint32_t *il_offsets = NULL; + uint32_t *native_offsets = NULL; + + MonoDebugMethodJitInfo *debug_info = method ? mono_debug_find_method (method, root_domain) : NULL; + if (debug_info) { + offset_entries = debug_info->num_line_numbers; + size_t needed_size = (offset_entries * sizeof (uint32_t) * 2); + if (needed_size > sizeof (fixed_buffer)) { + buffer = g_new (uint8_t, needed_size); + il_offsets = (uint32_t*)buffer; + } else { + il_offsets = fixed_buffer; + } + if (il_offsets) { + 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 (!il_offsets && !native_offsets) { + // No IL offset -> Native offset mapping available. Put all code on IL offset 0. + EP_ASSERT (sizeof (fixed_buffer) >= sizeof (uint32_t) * 2); + offset_entries = 1; + il_offsets = fixed_buffer; + native_offsets = il_offsets + offset_entries; + il_offsets [0] = 0; + native_offsets [0] = ji ? (uint32_t)ji->code_size : 0; + } + + FireEtwMethodILToNativeMap ( + method_id, + 0, + 0, + offset_entries, + il_offsets, + native_offsets, + clr_instance_get_id (), + NULL, + NULL); + + g_free (buffer); + } + + return true; +} + +bool +ep_rt_mono_write_event_method_load ( + MonoMethod *method, + MonoJitInfo *ji) +{ + if (!EventEnabledMethodLoad_V1 () && !EventEnabledMethodLoadVerbose_V1()) + return true; + + //TODO: Optimize string formatting into functions accepting GString to reduce heap alloc. + if (method) { + uint64_t method_id = 0; + uint64_t module_id = 0; + uint64_t method_code_start = ji ? (uint64_t)ji->code_start : 0; + uint32_t method_code_size = ji ? (uint32_t)ji->code_size : 0; + 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; + bool verbose = (MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.Level >= (uint8_t)EP_EVENT_LEVEL_VERBOSE); + + method_id = (uint64_t)method; + + if (!method->dynamic) + method_token = method->token; + + if (ji && mono_jit_info_get_generic_sharing_context (ji)) { + method_flags |= METHOD_FLAGS_SHARED_GENERIC_METHOD; + verbose = true; + } + + if (method->dynamic) { + method_flags |= METHOD_FLAGS_DYNAMIC_METHOD; + verbose = true; + } + + if (ji && !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; + verbose = true; + } + + 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; + } + + //TODO: SendMethodDetailsEvent + + if (verbose) { + method_name = method->name; + method_signature = mono_signature_full_name (method->signature); + + if (method->klass) + method_namespace = mono_type_get_name_full (m_class_get_byval_arg (method->klass), MONO_TYPE_NAME_FORMAT_IL); + + FireEtwMethodLoadVerbose_V1 ( + method_id, + module_id, + method_code_start, + method_code_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION, + method_namespace, + method_name, + method_signature, + clr_instance_get_id (), + NULL, + NULL); + + if (ji && (ji->from_aot || ji->from_llvm)) + FireEtwMethodLoadVerbose_V1 ( + method_id, + module_id, + method_code_start, + method_code_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION, + method_namespace, + method_name, + method_signature, + clr_instance_get_id (), + NULL, + NULL); + } else { + FireEtwMethodLoad_V1 ( + method_id, + module_id, + method_code_start, + method_code_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_HOT_SECTION, + clr_instance_get_id (), + NULL, + NULL); + + if (ji && (ji->from_aot || ji->from_llvm)) + FireEtwMethodLoad_V1 ( + method_id, + module_id, + method_code_start, + method_code_size, + method_token, + method_flags | METHOD_FLAGS_EXTENT_COLD_SECTION, + clr_instance_get_id (), + NULL, + NULL); + } + + g_free (method_namespace); + g_free (method_signature); + } + + return true; +} + +bool +ep_rt_mono_write_event_module_load (MonoImage *image) +{ + if (!EventEnabledModuleLoad_V2 () && !EventEnabledDomainModuleLoad_V1()) + return true; + + if (image) { + // Under netcore we only have root domain. + MonoDomain *root_domain = mono_get_root_domain (); + + uint64_t domain_id = (uint64_t)root_domain; + uint64_t module_id = (uint64_t)image; + uint64_t assembly_id = (uint64_t)image->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; + + // Netcore has a 1:1 between assemblies and modules, so its always a manifest module. + uint32_t module_flags = MODULE_FLAGS_MANIFEST_MODULE; + if (image->dynamic) + module_flags |= MODULE_FLAGS_DYNAMIC_MODULE; + if (image->aot_module) + module_flags |= MODULE_FLAGS_NATIVE_MODULE; + + module_il_path = image->filename ? image->filename : ""; + + FireEtwModuleLoad_V2 ( + module_id, + assembly_id, + module_flags, + reserved_flags, + module_il_path, + module_native_path, + clr_instance_get_id (), + signature, + module_il_pdb_age, + module_il_pdb_path, + signature, + module_native_pdb_age, + module_native_pdb_path, + NULL, + NULL); + + FireEtwDomainModuleLoad_V1 ( + module_id, + assembly_id, + domain_id, + module_flags, + reserved_flags, + module_il_path, + module_native_path, + clr_instance_get_id (), + NULL, + NULL); + } + + return true; +} + +bool +ep_rt_mono_write_event_assembly_load (MonoAssembly *assembly) +{ + if (!EventEnabledAssemblyLoad_V1 ()) + return true; + + if (assembly) { + // Under netcore we only have root domain. + MonoDomain *root_domain = mono_get_root_domain (); + + uint64_t domain_id = (uint64_t)root_domain; + uint64_t assembly_id = (uint64_t)assembly; + uint64_t binding_id = 0; + + 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); + + FireEtwAssemblyLoad_V1 ( + assembly_id, + domain_id, + binding_id, + assembly_flags, + assembly_name, + clr_instance_get_id (), + NULL, + NULL); + + g_free (assembly_name); + } + + return true; +} + +static +void +profiler_jit_begin ( + MonoProfiler *prof, + MonoMethod *method) +{ + ep_rt_mono_write_event_jit_start (method); +} + +static +void +profiler_jit_failed ( + MonoProfiler *prof, + MonoMethod *method) +{ + //TODO: CoreCLR doesn't have this case, so no failure event currently exists. +} + +static +void +profiler_jit_done ( + MonoProfiler *prof, + MonoMethod *method, + MonoJitInfo *ji) +{ + ep_rt_mono_write_event_method_load (method, ji); + ep_rt_mono_write_event_method_il_to_native_map (method, ji); +} + +static +void +profiler_image_loaded ( + MonoProfiler *prof, + MonoImage *image) +{ + if (image && image->heap_pdb.size == 0) + ep_rt_mono_write_event_module_load (image); +} + +static +void +profiler_assembly_loaded ( + MonoProfiler *prof, + MonoAssembly *assembly) +{ + ep_rt_mono_write_event_assembly_load (assembly); +} + +void +EventPipeEtwCallbackDotNETRuntime ( + 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) +{ + ep_rt_config_requires_lock_not_held (); + + EP_ASSERT(is_enabled == 0 || is_enabled == 1) ; + EP_ASSERT (_ep_rt_mono_profiler != NULL); + + EP_LOCK_ENTER (section1) + if (is_enabled == 1 && !MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled) { + // Add profiler callbacks for DotNETRuntime provider events. + mono_profiler_set_jit_begin_callback (_ep_rt_mono_profiler, profiler_jit_begin); + mono_profiler_set_jit_failed_callback (_ep_rt_mono_profiler, profiler_jit_failed); + mono_profiler_set_jit_done_callback (_ep_rt_mono_profiler, profiler_jit_done); + mono_profiler_set_image_loaded_callback (_ep_rt_mono_profiler, profiler_image_loaded); + mono_profiler_set_assembly_loaded_callback (_ep_rt_mono_profiler, profiler_assembly_loaded); + } else if (is_enabled == 0 && MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled) { + // Remove profiler callbacks for DotNETRuntime provider events. + mono_profiler_set_assembly_loaded_callback (_ep_rt_mono_profiler, NULL); + mono_profiler_set_image_loaded_callback (_ep_rt_mono_profiler, NULL); + mono_profiler_set_jit_done_callback (_ep_rt_mono_profiler, NULL); + mono_profiler_set_jit_failed_callback (_ep_rt_mono_profiler, NULL); + mono_profiler_set_jit_begin_callback (_ep_rt_mono_profiler, NULL); + } + EP_LOCK_EXIT (section1) + + MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.Level = level; + MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords; + MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false); + +ep_on_exit: + ep_rt_config_requires_lock_not_held (); + return; + +ep_on_error: + ep_exit_error_handler (); +} + +void +EventPipeEtwCallbackDotNETRuntimeRundown ( + 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) +{ + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.Level = level; + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords; + MICROSOFT_WINDOWS_DOTNETRUNTIME_RUNDOWN_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false); +} + +void +EventPipeEtwCallbackDotNETRuntimePrivate ( + 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) +{ + MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.Level = level; + MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords; + MICROSOFT_WINDOWS_DOTNETRUNTIME_PRIVATE_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false); +} + +void +EventPipeEtwCallbackDotNETRuntimeStress ( + 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) +{ + MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context.Level = level; + MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context.EnabledKeywordsBitmask = match_any_keywords; + MICROSOFT_WINDOWS_DOTNETRUNTIME_STRESS_PROVIDER_EVENTPIPE_Context.IsEnabled = (is_enabled == 1 ? true : false); +} + #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 920f5b6..985e7d8 100644 --- a/src/mono/mono/eventpipe/ep-rt-mono.h +++ b/src/mono/mono/eventpipe/ep-rt-mono.h @@ -707,7 +707,8 @@ inline void ep_rt_provider_config_init (EventPipeProviderConfiguration *provider_config) { - ; + extern void ep_rt_mono_provider_config_init (EventPipeProviderConfiguration *provider_config); + ep_rt_mono_provider_config_init (provider_config); } static @@ -724,7 +725,8 @@ inline bool ep_rt_providers_validate_all_disabled (void) { - return true; + extern bool ep_rt_mono_providers_validate_all_disabled (void); + return ep_rt_mono_providers_validate_all_disabled (); } static @@ -2144,5 +2146,69 @@ ep_rt_volatile_store_ptr_without_barrier ( bool ep_rt_mono_write_event_ee_startup_start (void); +bool +ep_rt_mono_write_event_jit_start (MonoMethod *method); + +bool +ep_rt_mono_write_event_method_il_to_native_map ( + MonoMethod *method, + MonoJitInfo *ji); + +bool +ep_rt_mono_write_event_method_load ( + MonoMethod *method, + MonoJitInfo *ji); + +bool +ep_rt_mono_write_event_module_load (MonoImage *image); + +bool +ep_rt_mono_write_event_assembly_load (MonoAssembly *assembly); + +/* +* EventPipe provider callbacks. +*/ + +void +EventPipeEtwCallbackDotNETRuntime ( + 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); + +void +EventPipeEtwCallbackDotNETRuntimeRundown ( + 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); + +void +EventPipeEtwCallbackDotNETRuntimePrivate ( + 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); + +void +EventPipeEtwCallbackDotNETRuntimeStress ( + 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); + + #endif /* ENABLE_PERFTRACING */ #endif /* __EVENTPIPE_RT_MONO_H__ */ diff --git a/src/mono/mono/eventpipe/gen-eventing-event-inc.lst b/src/mono/mono/eventpipe/gen-eventing-event-inc.lst index b9945b1..b80a674 100644 --- a/src/mono/mono/eventpipe/gen-eventing-event-inc.lst +++ b/src/mono/mono/eventpipe/gen-eventing-event-inc.lst @@ -1,13 +1,20 @@ # Native runtime events supported by Mono runtime. -RuntimeInformationDCStart -RuntimeInformationDCStart AppDomainDCEnd_V1 -DCEndInit_V1 +AssemblyDCEnd_V1 +AssemblyLoad_V1 DCEndComplete_V1 +DCEndInit_V1 +DomainModuleDCEnd_V1 +DomainModuleLoad_V1 EEStartupStart_V1 MethodDCEndILToNativeMap +MethodDCEnd_V1 MethodDCEndVerbose_V1 -DomainModuleDCEnd_V1 -AssemblyDCEnd_V1 -ModuleDCEnd_V2 \ No newline at end of file +MethodILToNativeMap +MethodJittingStarted_V1 +MethodLoad_V1 +MethodLoadVerbose_V1 +ModuleDCEnd_V2 +ModuleLoad_V2 +RuntimeInformationDCStart diff --git a/src/mono/mono/eventpipe/test/ep-teardown-tests.c b/src/mono/mono/eventpipe/test/ep-teardown-tests.c index 8a07420..2d663a5 100644 --- a/src/mono/mono/eventpipe/test/ep-teardown-tests.c +++ b/src/mono/mono/eventpipe/test/ep-teardown-tests.c @@ -3,6 +3,7 @@ #include #define TEST_FILE "./ep_test_create_file.txt" +#define TEST_FILE_2 "./ep_test_create_file_2.txt" extern MonoDomain *eventpipe_test_domain; @@ -12,6 +13,7 @@ test_teardown (void) if (eventpipe_test_domain) mono_jit_cleanup (eventpipe_test_domain); + unlink (TEST_FILE_2); unlink (TEST_FILE); return NULL; diff --git a/src/mono/mono/eventpipe/test/ep-tests.c b/src/mono/mono/eventpipe/test/ep-tests.c index b0e7803..ce8ae48 100644 --- a/src/mono/mono/eventpipe/test/ep-tests.c +++ b/src/mono/mono/eventpipe/test/ep-tests.c @@ -13,6 +13,7 @@ #define TEST_PROVIDER_NAME "MyTestProvider" #define TEST_FILE "./ep_test_create_file.txt" +#define TEST_FILE_2 "./ep_test_create_file_2.txt" //#define TEST_PERF @@ -380,6 +381,86 @@ ep_on_error: } static RESULT +test_enable_disable_multiple_default_provider_config (void) +{ + RESULT result = NULL; + uint32_t test_location = 0; + + EventPipeSessionID session_id_1 = 0; + EventPipeSessionID session_id_2 = 0; + + session_id_1 = ep_enable_2 ( + TEST_FILE, + 1, + NULL, + EP_SESSION_TYPE_FILE, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + false, + NULL, + NULL); + + if (!session_id_1) { + result = FAILED ("Failed to enable session"); + ep_raise_error (); + } + + test_location = 2; + + result = validate_default_provider_config ((EventPipeSession *)session_id_1); + ep_raise_error_if_nok (result == NULL); + + test_location = 3; + + ep_start_streaming (session_id_1); + + if (!ep_enabled ()) { + result = FAILED ("event pipe disabled"); + ep_raise_error (); + } + + test_location = 4; + + session_id_2 = ep_enable_2 ( + TEST_FILE_2, + 1, + NULL, + EP_SESSION_TYPE_FILE, + EP_SERIALIZATION_FORMAT_NETTRACE_V4, + false, + NULL, + NULL); + + if (!session_id_2) { + result = FAILED ("Failed to enable session"); + ep_raise_error (); + } + + test_location = 5; + + result = validate_default_provider_config ((EventPipeSession *)session_id_2); + ep_raise_error_if_nok (result == NULL); + + test_location = 6; + + ep_start_streaming (session_id_2); + + if (!ep_enabled ()) { + result = FAILED ("event pipe disabled"); + ep_raise_error (); + } + +ep_on_exit: + ep_disable (session_id_1); + ep_disable (session_id_2); + return result; + +ep_on_error: + if (!result) + result = FAILED ("Failed at test location=%i", test_location); + ep_exit_error_handler (); +} + +static RESULT test_enable_disable_provider_config (void) { RESULT result = NULL; @@ -1327,6 +1408,7 @@ static Test ep_tests [] = { #endif {"test_eventpipe_mem_checkpoint", test_eventpipe_mem_checkpoint}, {"test_enable_disable_default_provider_config", test_enable_disable_default_provider_config}, + {"test_enable_disable_multiple_default_provider_config", test_enable_disable_multiple_default_provider_config}, {"test_enable_disable_provider_parse_default_config", test_enable_disable_provider_parse_default_config}, {"test_eventpipe_reset_mem_checkpoint", test_eventpipe_reset_mem_checkpoint}, {"test_eventpipe_teardown", test_eventpipe_teardown}, -- 2.7.4