From ff7cbad36722143f2ee986d159279ef008997583 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Thu, 3 Apr 2025 19:09:29 +0000 Subject: [PATCH 01/32] [DiagnosticServer] Refactor and Cleanup Visual reorder of Diagnostics enum structs Fix a couple naming typos Spaces to tabs consistency --- src/native/eventpipe/ds-eventpipe-protocol.c | 2 +- src/native/eventpipe/ds-ipc-pal-socket.c | 4 +- src/native/eventpipe/ds-ipc.c | 2 +- src/native/eventpipe/ds-protocol.c | 26 ++++----- src/native/eventpipe/ds-protocol.h | 8 +-- src/native/eventpipe/ds-server.c | 10 ++-- src/native/eventpipe/ds-types.h | 56 ++++++++++---------- src/native/eventpipe/ep.c | 6 +-- 8 files changed, 56 insertions(+), 58 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index b359102ee0d35a..02511aab095d63 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -547,7 +547,7 @@ eventpipe_protocol_helper_collect_tracing ( EventPipeSessionID session_id = 0; bool result = false; - session_id = ep_enable_3(&options); + session_id = ep_enable_3 (&options); if (session_id == 0) { ds_ipc_message_send_error (stream, DS_IPC_E_FAIL); diff --git a/src/native/eventpipe/ds-ipc-pal-socket.c b/src/native/eventpipe/ds-ipc-pal-socket.c index c9764e6a3ffd6a..0826dbb55d5adb 100644 --- a/src/native/eventpipe/ds-ipc-pal-socket.c +++ b/src/native/eventpipe/ds-ipc-pal-socket.c @@ -552,9 +552,9 @@ ipc_socket_accept ( DS_ENTER_BLOCKING_PAL_SECTION; do { #if HAVE_ACCEPT4 && defined(SOCK_CLOEXEC) - client_socket = accept4 (s, address, address_len, SOCK_CLOEXEC); + client_socket = accept4 (s, address, address_len, SOCK_CLOEXEC); #else - client_socket = accept (s, address, address_len); + client_socket = accept (s, address, address_len); #endif } while (ipc_retry_syscall (client_socket)); diff --git a/src/native/eventpipe/ds-ipc.c b/src/native/eventpipe/ds-ipc.c index f8cd6a5ad52ee3..6527d5bbce706d 100644 --- a/src/native/eventpipe/ds-ipc.c +++ b/src/native/eventpipe/ds-ipc.c @@ -709,7 +709,7 @@ connect_port_get_ipc_poll_handle_func ( buffer [0] = '\0'; DS_LOG_DEBUG_1 ("connect_port_get_ipc_poll_handle - returned connection %s", buffer); - if (!ds_icp_advertise_v1_send (connection)) { + if (!ds_ipc_advertise_v1_send (connection)) { if (callback) callback("Failed to send advertise message", -1); ep_raise_error (); diff --git a/src/native/eventpipe/ds-protocol.c b/src/native/eventpipe/ds-protocol.c index d1cbee0ac35782..0f615fb2b3e22e 100644 --- a/src/native/eventpipe/ds-protocol.c +++ b/src/native/eventpipe/ds-protocol.c @@ -26,7 +26,7 @@ const DiagnosticsIpcHeader _ds_ipc_generic_error_header = { (uint16_t)0x0000 }; -static uint8_t _ds_ipc_advertise_cooike_v1 [EP_GUID_SIZE] = { 0 }; +static uint8_t _ds_ipc_advertise_cookie_v1 [EP_GUID_SIZE] = { 0 }; /* * Forward declares of all static functions. @@ -74,13 +74,13 @@ ipc_message_try_parse_string_utf16_t_byte_array ( uint8_t * ds_ipc_advertise_cookie_v1_get (void) { - return _ds_ipc_advertise_cooike_v1; + return _ds_ipc_advertise_cookie_v1; } void ds_ipc_advertise_cookie_v1_init (void) { - ep_thread_create_activity_id ((uint8_t *)&_ds_ipc_advertise_cooike_v1, EP_GUID_SIZE); + ep_thread_create_activity_id ((uint8_t *)&_ds_ipc_advertise_cookie_v1, EP_GUID_SIZE); } /** @@ -98,7 +98,7 @@ ds_ipc_advertise_cookie_v1_init (void) * 2 bytes - unused 2 byte field for futureproofing */ bool -ds_icp_advertise_v1_send (DiagnosticsIpcStream *stream) +ds_ipc_advertise_v1_send (DiagnosticsIpcStream *stream) { uint8_t advertise_buffer [DOTNET_IPC_V1_ADVERTISE_SIZE]; uint8_t *cookie = ds_ipc_advertise_cookie_v1_get (); @@ -426,15 +426,15 @@ ds_ipc_message_try_parse_bool ( uint32_t *buffer_len, bool *value) { - EP_ASSERT (buffer != NULL); - EP_ASSERT (buffer_len != NULL); - EP_ASSERT (value != NULL); - - uint8_t temp_value; - bool result = ds_ipc_message_try_parse_value (buffer, buffer_len, (uint8_t *)&temp_value, 1); - if (result) - *value = temp_value == 0 ? false : true; - return result; + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (value != NULL); + + uint8_t temp_value; + bool result = ds_ipc_message_try_parse_value (buffer, buffer_len, (uint8_t *)&temp_value, 1); + if (result) + *value = temp_value == 0 ? false : true; + return result; } bool diff --git a/src/native/eventpipe/ds-protocol.h b/src/native/eventpipe/ds-protocol.h index bb3a10120341d6..826f293d48ce5c 100644 --- a/src/native/eventpipe/ds-protocol.h +++ b/src/native/eventpipe/ds-protocol.h @@ -27,7 +27,7 @@ void ds_ipc_advertise_cookie_v1_init (void); bool -ds_icp_advertise_v1_send (DiagnosticsIpcStream *stream); +ds_ipc_advertise_v1_send (DiagnosticsIpcStream *stream); /* * DiagnosticsIpcHeader @@ -59,8 +59,8 @@ struct _DiagnosticsIpcHeader { #endif DS_DEFINE_GETTER_ARRAY_REF(DiagnosticsIpcHeader *, ipc_header, uint8_t *, const uint8_t *, magic, magic[0]) -DS_DEFINE_GETTER(DiagnosticsIpcHeader *, ipc_header, uint8_t, commandset) -DS_DEFINE_GETTER(DiagnosticsIpcHeader *, ipc_header, uint8_t, commandid) +DS_DEFINE_GETTER(DiagnosticsIpcHeader *, ipc_header, uint8_t, commandset) // ds_ipc_header_get_commandset +DS_DEFINE_GETTER(DiagnosticsIpcHeader *, ipc_header, uint8_t, commandid) // ds_ipc_header_get_commandid /* * DiagnosticsIpcMessage @@ -87,7 +87,7 @@ struct _DiagnosticsIpcMessage { }; #endif -DS_DEFINE_GETTER_REF(DiagnosticsIpcMessage *, ipc_message, DiagnosticsIpcHeader *, header) +DS_DEFINE_GETTER_REF(DiagnosticsIpcMessage *, ipc_message, DiagnosticsIpcHeader *, header) // ds_ipc_message_get_header_ref DiagnosticsIpcMessage * ds_ipc_message_init (DiagnosticsIpcMessage *message); diff --git a/src/native/eventpipe/ds-server.c b/src/native/eventpipe/ds-server.c index 52d5da9cd5da2c..a89f757970167c 100644 --- a/src/native/eventpipe/ds-server.c +++ b/src/native/eventpipe/ds-server.c @@ -145,18 +145,18 @@ static size_t server_loop_tick (void* data) { DS_LOG_INFO_2 ("DiagnosticServer - received IPC message with command set (%d) and command id (%d)", ds_ipc_header_get_commandset (ds_ipc_message_get_header_ref (&message)), ds_ipc_header_get_commandid (ds_ipc_message_get_header_ref (&message))); switch ((DiagnosticsServerCommandSet)ds_ipc_header_get_commandset (ds_ipc_message_get_header_ref (&message))) { - case DS_SERVER_COMMANDSET_EVENTPIPE: - ds_eventpipe_protocol_helper_handle_ipc_message (&message, stream); - break; case DS_SERVER_COMMANDSET_DUMP: ds_dump_protocol_helper_handle_ipc_message (&message, stream); break; - case DS_SERVER_COMMANDSET_PROCESS: - ds_process_protocol_helper_handle_ipc_message (&message, stream); + case DS_SERVER_COMMANDSET_EVENTPIPE: + ds_eventpipe_protocol_helper_handle_ipc_message (&message, stream); break; case DS_SERVER_COMMANDSET_PROFILER: ds_profiler_protocol_helper_handle_ipc_message (&message, stream); break; + case DS_SERVER_COMMANDSET_PROCESS: + ds_process_protocol_helper_handle_ipc_message (&message, stream); + break; default: server_protocol_helper_unknown_command (&message, stream); break; diff --git a/src/native/eventpipe/ds-types.h b/src/native/eventpipe/ds-types.h index a7596da6052a33..f8ef4b216dec6d 100644 --- a/src/native/eventpipe/ds-types.h +++ b/src/native/eventpipe/ds-types.h @@ -43,15 +43,6 @@ typedef struct _EventPipeStopTracingCommandPayload EventPipeStopTracingCommandPa * Diagnostics Enums. */ -// The Diagnostic command set is 0x01 -typedef enum { - DS_DUMP_COMMANDID_RESERVED = 0x00, - DS_DUMP_COMMANDID_GENERATE_CORE_DUMP = 0x01, - DS_DUMP_COMMANDID_GENERATE_CORE_DUMP2 = 0x02, - DS_DUMP_COMMANDID_GENERATE_CORE_DUMP3 = 0x03, - // future -} DiagnosticsDumpCommandId; - typedef enum { DS_IPC_MAGIC_VERSION_DOTNET_IPC_V1 = 0x01, // FUTURE @@ -66,8 +57,34 @@ typedef enum { DS_SERVER_COMMANDSET_SERVER = 0xFF } DiagnosticsServerCommandSet; +// The dump command set is 0x01 +typedef enum { + DS_DUMP_COMMANDID_RESERVED = 0x00, + DS_DUMP_COMMANDID_GENERATE_CORE_DUMP = 0x01, + DS_DUMP_COMMANDID_GENERATE_CORE_DUMP2 = 0x02, + DS_DUMP_COMMANDID_GENERATE_CORE_DUMP3 = 0x03, + // future +} DiagnosticsDumpCommandId; + // The event pipe command set is 0x02 -// see ds-ipc.h and ds-server.h for more details +typedef enum { + EP_COMMANDID_STOP_TRACING = 0x01, + EP_COMMANDID_COLLECT_TRACING = 0x02, + EP_COMMANDID_COLLECT_TRACING_2 = 0x03, + EP_COMMANDID_COLLECT_TRACING_3 = 0x04, + EP_COMMANDID_COLLECT_TRACING_4 = 0x05, + // future +} EventPipeCommandId; + +// The profiler command set is 0x03 +typedef enum { + DS_PROFILER_COMMANDID_RESERVED = 0x00, + DS_PROFILER_COMMANDID_ATTACH_PROFILER = 0x01, + DS_PROFILER_COMMANDID_STARTUP_PROFILER = 0x02, + // future +} DiagnosticsProfilerCommandId; + +// The process command set is 0x04 typedef enum { DS_PROCESS_COMMANDID_GET_PROCESS_INFO = 0x00, DS_PROCESS_COMMANDID_RESUME_RUNTIME = 0x01, @@ -81,14 +98,6 @@ typedef enum { // future } DiagnosticsProcessCommandId; -// The Diagnostic command set is 0x01 -typedef enum { - DS_PROFILER_COMMANDID_RESERVED = 0x00, - DS_PROFILER_COMMANDID_ATTACH_PROFILER = 0x01, - DS_PROFILER_COMMANDID_STARTUP_PROFILER = 0x02, - // future -} DiagnosticsProfilerCommandId; - // Overlaps with DiagnosticsServerCommandId // DON'T create overlapping values typedef enum { @@ -97,17 +106,6 @@ typedef enum { DS_SERVER_RESPONSEID_ERROR = 0xFF, } DiagnosticsServerResponseId; -// The event pipe command set is 0x02 -// see ds-ipc.h and ds-server.h for more details -typedef enum { - EP_COMMANDID_STOP_TRACING = 0x01, - EP_COMMANDID_COLLECT_TRACING = 0x02, - EP_COMMANDID_COLLECT_TRACING_2 = 0x03, - EP_COMMANDID_COLLECT_TRACING_3 = 0x04, - EP_COMMANDID_COLLECT_TRACING_4 = 0x05, - // future -} EventPipeCommandId; - typedef enum { DS_PORT_TYPE_LISTEN = 0, DS_PORT_TYPE_CONNECT = 1 diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index 45e853febed841..eafd641d930a7a 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -984,7 +984,7 @@ ep_enable ( EventPipeSessionID sessionId = 0; EventPipeSessionOptions options; - ep_session_options_init( + ep_session_options_init ( &options, output_path, circular_buffer_size_in_mb, @@ -998,9 +998,9 @@ ep_enable ( sync_callback, callback_additional_data); - sessionId = ep_enable_3(&options); + sessionId = ep_enable_3 (&options); - ep_session_options_fini(&options); + ep_session_options_fini (&options); return sessionId; } From d9a59c17ca7b117c3ecae30e0b18ad0e7defcc64 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Sun, 1 Jun 2025 23:10:05 -0400 Subject: [PATCH 02/32] [EventPipe] Add User_events structs --- src/native/eventpipe/ep-types-forward.h | 3 ++ src/native/eventpipe/ep-types.h | 59 +++++++++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index 4e3b218291506d..99c5cb19b0755a 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -31,6 +31,8 @@ typedef struct _EventPipeProvider EventPipeProvider; typedef struct _EventPipeProviderCallbackData EventPipeProviderCallbackData; typedef struct _EventPipeProviderCallbackDataQueue EventPipeProviderCallbackDataQueue; typedef struct _EventPipeProviderConfiguration EventPipeProviderConfiguration; +typedef struct _EventPipeProviderEventFilter EventPipeProviderEventFilter; +typedef struct _EventPipeProviderTracepointConfiguration EventPipeProviderTracepointConfiguration; typedef struct _EventPipeExecutionCheckpoint EventPipeExecutionCheckpoint; typedef struct _EventPipeSession EventPipeSession; typedef struct _EventPipeSessionProvider EventPipeSessionProvider; @@ -44,6 +46,7 @@ typedef struct _EventPipeSystemTime EventPipeSystemTime; typedef struct _EventPipeThread EventPipeThread; typedef struct _EventPipeThreadHolder EventPipeThreadHolder; typedef struct _EventPipeThreadSessionState EventPipeThreadSessionState; +typedef struct _EventPipeTracepoint EventPipeTracepoint; typedef struct _FastSerializableObject FastSerializableObject; typedef struct _FastSerializableObjectVtable FastSerializableObjectVtable; typedef struct _FastSerializer FastSerializer; diff --git a/src/native/eventpipe/ep-types.h b/src/native/eventpipe/ep-types.h index 7a16bc77a3466f..f9e673895e95bb 100644 --- a/src/native/eventpipe/ep-types.h +++ b/src/native/eventpipe/ep-types.h @@ -175,6 +175,65 @@ ep_provider_callback_data_queue_try_dequeue ( EventPipeProviderCallbackDataQueue *provider_callback_data_queue, EventPipeProviderCallbackData *provider_callback_data); +/* + * EventPipeTracepoint. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_EP_GETTER_SETTER) +struct _EventPipeTracepoint { +#else +struct _EventPipeTracepoint_Internal { +#endif + ep_char8_t tracepoint_format[256]; + uint32_t write_index; + uint32_t enabled; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_EP_GETTER_SETTER) +struct _EventPipeTracepoint { + uint8_t _internal [sizeof (struct _EventPipeTracepoint_Internal)]; +}; +#endif + +/* + * EventPipeProviderEventFilter. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_EP_GETTER_SETTER) +struct _EventPipeProviderEventFilter { +#else +struct _EventPipeProviderEventFilter_Internal { +#endif + bool enable; + dn_umap_t *event_ids; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_EP_GETTER_SETTER) +struct _EventPipeProviderEventFilter { + uint8_t _internal [sizeof (struct _EventPipeProviderEventFilter_Internal)]; +}; +#endif + +/* + * EventPipeProviderTracepointConfiguration. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_EP_GETTER_SETTER) +struct _EventPipeProviderTracepointConfiguration { +#else +struct _EventPipeProviderTracepointConfiguration_Internal { +#endif + EventPipeTracepoint default_tracepoint; + dn_vector_t *tracepoints; + dn_umap_t *event_id_to_tracepoint_map; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_EP_GETTER_SETTER) +struct _EventPipeProviderTracepointConfiguration { + uint8_t _internal [sizeof (struct _EventPipeProviderTracepointConfiguration_Internal)]; +}; +#endif + /* * EventPipeProviderConfiguration. */ From 1eecfdc155346715a81eec831968e91a1695ffa2 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Mon, 2 Jun 2025 05:10:56 +0000 Subject: [PATCH 03/32] [EventPipe] Add User_events eventpipe session --- src/native/eventpipe/ds-eventpipe-protocol.c | 3 +- src/native/eventpipe/ep-session-provider.c | 26 ++++++++++- src/native/eventpipe/ep-session-provider.h | 13 ++++++ src/native/eventpipe/ep-session.c | 44 ++++++++++++++++-- src/native/eventpipe/ep-session.h | 8 +++- src/native/eventpipe/ep-types-forward.h | 3 +- src/native/eventpipe/ep-types.h | 12 +++++ src/native/eventpipe/ep.c | 49 +++++++++++++++++--- src/native/eventpipe/ep.h | 4 +- 9 files changed, 148 insertions(+), 14 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 02511aab095d63..77706cf5343f9b 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -543,7 +543,8 @@ eventpipe_protocol_helper_collect_tracing ( payload->stackwalk_requested, ds_ipc_stream_get_stream_ref (stream), NULL, - NULL); + NULL, + 0); EventPipeSessionID session_id = 0; bool result = false; diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index c4bbdf5b958c3b..ac0712d24e0955 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -51,6 +51,24 @@ ep_session_provider_alloc ( uint64_t keywords, EventPipeEventLevel logging_level, const ep_char8_t *filter_data) +{ + return ep_session_provider_alloc ( + provider_name, + keywords, + logging_level, + filter_data, + NULL, + NULL); +} + +EventPipeSessionProvider * +ep_session_provider_alloc ( + const ep_char8_t *provider_name, + uint64_t keywords, + EventPipeEventLevel logging_level, + const ep_char8_t *filter_data, + EventPipeProviderEventFilter *event_filter, + EventPipeProviderTracepointConfiguration *tracepoint_config) { EventPipeSessionProvider *instance = ep_rt_object_alloc (EventPipeSessionProvider); ep_raise_error_if_nok (instance != NULL); @@ -67,6 +85,8 @@ ep_session_provider_alloc ( instance->keywords = keywords; instance->logging_level = logging_level; + instance->event_filter = event_filter; + instance->tracepoint_config = tracepoint_config; ep_on_exit: return instance; @@ -82,6 +102,8 @@ ep_session_provider_free (EventPipeSessionProvider * session_provider) { ep_return_void_if_nok (session_provider != NULL); + ep_tracepoint_config_free (session_provider->tracepoint_config); + ep_event_filter_free (session_provider->event_filter); ep_rt_utf8_string_free (session_provider->filter_data); ep_rt_utf8_string_free (session_provider->provider_name); ep_rt_object_free (session_provider); @@ -122,7 +144,9 @@ ep_session_provider_list_alloc ( ep_provider_config_get_provider_name (config), ep_provider_config_get_keywords (config), ep_provider_config_get_logging_level (config), - ep_provider_config_get_filter_data (config)); + ep_provider_config_get_filter_data (config), + ep_provider_config_get_event_filter (config), + ep_provider_config_get_tracepoint_config (config)); ep_raise_error_if_nok (dn_list_push_back (instance->providers, session_provider)); } } diff --git a/src/native/eventpipe/ep-session-provider.h b/src/native/eventpipe/ep-session-provider.h index 31852c7ba8184d..0247254e27f068 100644 --- a/src/native/eventpipe/ep-session-provider.h +++ b/src/native/eventpipe/ep-session-provider.h @@ -24,6 +24,8 @@ struct _EventPipeSessionProvider_Internal { uint64_t keywords; EventPipeEventLevel logging_level; ep_char8_t *filter_data; + EventPipeProviderEventFilter *event_filter; + EventPipeProviderTracepointConfiguration *tracepoint_config; }; #if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_SESSION_PROVIDER_GETTER_SETTER) @@ -36,6 +38,8 @@ EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, const ep_char8_t EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, uint64_t, keywords) EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, EventPipeEventLevel, logging_level) EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, const ep_char8_t *, filter_data) +EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, EventPipeProviderEventFilter *, event_filter) +EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, EventPipeProviderTracepointConfiguration *, tracepoint_config) EventPipeSessionProvider * ep_session_provider_alloc ( @@ -44,6 +48,15 @@ ep_session_provider_alloc ( EventPipeEventLevel logging_level, const ep_char8_t *filter_data); +EventPipeSessionProvider * +ep_session_provider_alloc ( + const ep_char8_t *provider_name, + uint64_t keywords, + EventPipeEventLevel logging_level, + const ep_char8_t *filter_data, + EventPipeProviderEventFilter *event_filter, + EventPipeProviderTracepointConfiguration *tracepoint_config); + void ep_session_provider_free (EventPipeSessionProvider * session_provider); diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index a8b23f8402e759..a98b47806a1123 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -30,6 +30,10 @@ static void ep_session_remove_dangling_session_states (EventPipeSession *session); +static +void +ep_session_disable_user_events (EventPipeSession *session); + /* * EventPipeSession. */ @@ -169,11 +173,12 @@ ep_session_alloc ( const EventPipeProviderConfiguration *providers, uint32_t providers_len, EventPipeSessionSynchronousCallback sync_callback, - void *callback_additional_data) + void *callback_additional_data, + uint32_t user_events_data_fd) { EP_ASSERT (index < EP_MAX_NUMBER_OF_SESSIONS); EP_ASSERT (format < EP_SERIALIZATION_FORMAT_COUNT); - EP_ASSERT (session_type == EP_SESSION_TYPE_SYNCHRONOUS || circular_buffer_size_in_mb > 0); + EP_ASSERT (!ep_session_type_uses_buffer_manager (session_type) || circular_buffer_size_in_mb > 0); EP_ASSERT (providers_len > 0); EP_ASSERT (providers != NULL); EP_ASSERT ((sync_callback != NULL) == (session_type == EP_SESSION_TYPE_SYNCHRONOUS)); @@ -205,7 +210,7 @@ ep_session_alloc ( sequence_point_alloc_budget = 10 * 1024 * 1024; } - if (session_type != EP_SESSION_TYPE_SYNCHRONOUS) { + if (ep_session_type_uses_buffer_manager (session_type)) { instance->buffer_manager = ep_buffer_manager_alloc (instance, ((size_t)circular_buffer_size_in_mb) << 20, sequence_point_alloc_budget); ep_raise_error_if_nok (instance->buffer_manager != NULL); } @@ -233,6 +238,14 @@ ep_session_alloc ( ipc_stream_writer = NULL; break; + case EP_SESSION_TYPE_USEREVENTS: + ep_raise_error_if_nok (user_events_data_fd != 0); + // Transfer ownership of the user_events_data file descriptor to the EventPipe Session. + instance->user_events_data_fd = user_events_data_fd; + // With the user_events_data file, register tracepoints for each provider's tracepoint configurations + // ep_session_user_events_tracepoints_init (instance); + break; + default: break; } @@ -504,6 +517,7 @@ ep_session_disable (EventPipeSession *session) bool ignored; ep_session_write_all_buffers_to_file (session, &ignored); + ep_session_disable_user_events (session); ep_session_provider_list_clear (session->providers); } @@ -523,6 +537,21 @@ ep_session_write_all_buffers_to_file (EventPipeSession *session, bool *events_wr return !ep_file_has_errors (session->file); } +static +void +ep_session_disable_user_events (EventPipeSession *session) +{ + EP_ASSERT (session != NULL); + ep_return_void_if_nok (session->session_type == EP_SESSION_TYPE_USEREVENTS); + + ep_requires_lock_held (); + + if (session->user_events_data_fd != 0) { + close (session->user_events_data_fd); + session->user_events_data_fd = 0; + } +} + bool ep_session_write_event ( EventPipeSession *session, @@ -665,6 +694,15 @@ ep_session_has_started (EventPipeSession *session) return ep_rt_volatile_load_uint32_t (&session->started) == 1 ? true : false; } +bool +ep_session_type_uses_buffer_manager (EventPipeSessionType session_type) +{ + if (session_type == EP_SESSION_TYPE_SYNCHRONOUS || session_type == EP_SESSION_TYPE_USEREVENTS) + return false; + + return true; +} + #endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ #endif /* ENABLE_PERFTRACING */ diff --git a/src/native/eventpipe/ep-session.h b/src/native/eventpipe/ep-session.h index 90b733751301d5..ad6187c7c71f6f 100644 --- a/src/native/eventpipe/ep-session.h +++ b/src/native/eventpipe/ep-session.h @@ -69,6 +69,8 @@ struct _EventPipeSession_Internal { volatile uint32_t started; // Reference count for the session. This is used to track the number of references to the session. volatile uint32_t ref_count; + // The user_events_data file descriptor to register Tracepoints and write user_events to. + uint32_t user_events_data_fd; }; #if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_SESSION_GETTER_SETTER) @@ -100,7 +102,8 @@ ep_session_alloc ( const EventPipeProviderConfiguration *providers, uint32_t providers_len, EventPipeSessionSynchronousCallback sync_callback, - void *callback_additional_data); + void *callback_additional_data, + uint32_t user_events_data_fd); void ep_session_inc_ref (EventPipeSession *session); @@ -214,5 +217,8 @@ ep_session_resume (EventPipeSession *session); bool ep_session_has_started (EventPipeSession *session); +bool +ep_session_type_uses_buffer_manager (EventPipeSessionType session_type); + #endif /* ENABLE_PERFTRACING */ #endif /* __EVENTPIPE_SESSION_H__ */ diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index 99c5cb19b0755a..3dddfae6aba5c7 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -150,7 +150,8 @@ typedef enum { EP_SESSION_TYPE_LISTENER, EP_SESSION_TYPE_IPCSTREAM, EP_SESSION_TYPE_SYNCHRONOUS, - EP_SESSION_TYPE_FILESTREAM + EP_SESSION_TYPE_FILESTREAM, + EP_SESSION_TYPE_USEREVENTS } EventPipeSessionType ; typedef enum { diff --git a/src/native/eventpipe/ep-types.h b/src/native/eventpipe/ep-types.h index f9e673895e95bb..8404f938a31e5c 100644 --- a/src/native/eventpipe/ep-types.h +++ b/src/native/eventpipe/ep-types.h @@ -214,6 +214,12 @@ struct _EventPipeProviderEventFilter { }; #endif +void +ep_event_filter_fini (EventPipeProviderEventFilter *event_filter); + +void +ep_event_filter_free (EventPipeProviderEventFilter *event_filter); + /* * EventPipeProviderTracepointConfiguration. */ @@ -234,6 +240,12 @@ struct _EventPipeProviderTracepointConfiguration { }; #endif +void +ep_tracepoint_config_fini (EventPipeProviderTracepointConfiguration *tracepoint_config); + +void +ep_tracepoint_config_free (EventPipeProviderTracepointConfiguration *tracepoint_config); + /* * EventPipeProviderConfiguration. */ diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index eafd641d930a7a..d8cd4422e09a29 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -469,7 +469,7 @@ static bool check_options_valid (const EventPipeSessionOptions *options) { if (options->format >= EP_SERIALIZATION_FORMAT_COUNT) return false; - if (options->circular_buffer_size_in_mb <= 0 && options->session_type != EP_SESSION_TYPE_SYNCHRONOUS) + if (options->circular_buffer_size_in_mb <= 0 && ep_session_type_uses_buffer_manager (options->session_type)) return false; if (options->providers == NULL || options->providers_len <= 0) return false; @@ -477,6 +477,9 @@ static bool check_options_valid (const EventPipeSessionOptions *options) return false; if (options->session_type == EP_SESSION_TYPE_IPCSTREAM && options->stream == NULL) return false; + // More UserEvents specific checks can be added here. + if (options->session_type == EP_SESSION_TYPE_USEREVENTS && options->user_events_data_fd == 0) + return false; return true; } @@ -491,7 +494,7 @@ enable ( EP_ASSERT (options != NULL); EP_ASSERT (options->format < EP_SERIALIZATION_FORMAT_COUNT); - EP_ASSERT (options->session_type == EP_SESSION_TYPE_SYNCHRONOUS || options->circular_buffer_size_in_mb > 0); + EP_ASSERT (!ep_session_type_uses_buffer_manager (options->session_type) || options->circular_buffer_size_in_mb > 0); EP_ASSERT (options->providers_len > 0 && options->providers != NULL); EventPipeSession *session = NULL; @@ -515,7 +518,8 @@ enable ( options->providers, options->providers_len, options->sync_callback, - options->callback_additional_data); + options->callback_additional_data, + options->user_events_data_fd); ep_raise_error_if_nok (session != NULL && ep_session_is_valid (session)); @@ -601,7 +605,7 @@ disable_holding_lock ( // Disable session tracing. config_enable_disable (ep_config_get (), session, provider_callback_data_queue, false); - ep_session_disable (session); // WriteAllBuffersToFile, and remove providers. + ep_session_disable (session); // WriteAllBuffersToFile, disable user_events, and remove providers. // Do rundown before fully stopping the session unless rundown wasn't requested if ((ep_session_get_rundown_keyword (session) != 0) && _ep_can_start_threads) { @@ -996,7 +1000,8 @@ ep_enable ( true, // stackwalk_requested stream, sync_callback, - callback_additional_data); + callback_additional_data, + 0); sessionId = ep_enable_3 (&options); @@ -1126,7 +1131,8 @@ ep_session_options_init ( bool stackwalk_requested, IpcStream* stream, EventPipeSessionSynchronousCallback sync_callback, - void* callback_additional_data) + void* callback_additional_data, + uint32_t user_events_data_fd) { EP_ASSERT (options != NULL); @@ -1141,6 +1147,7 @@ ep_session_options_init ( options->stream = stream; options->sync_callback = sync_callback; options->callback_additional_data = callback_additional_data; + options->user_events_data_fd = user_events_data_fd; } void @@ -1744,6 +1751,36 @@ ep_ipc_stream_factory_callback_set (EventPipeIpcStreamFactorySuspendedPortsCallb _ep_ipc_stream_factory_suspended_ports_callback = suspended_ports_callback; } +void +ep_event_filter_fini (EventPipeProviderEventFilter *event_filter) +{ + ep_return_void_if_nok (event_filter != NULL); +} + +void +ep_event_filter_free (EventPipeProviderEventFilter *event_filter) +{ + ep_return_void_if_nok (event_filter != NULL); + + ep_event_filter_fini (event_filter); + ep_rt_object_free (event_filter); +} + +void +ep_tracepoint_config_fini (EventPipeProviderTracepointConfiguration *tracepoint_config) +{ + ep_return_void_if_nok (tracepoint_config != NULL); +} + +void +ep_tracepoint_config_free (EventPipeProviderTracepointConfiguration *tracepoint_config) +{ + ep_return_void_if_nok (tracepoint_config != NULL); + + ep_tracepoint_config_fini (tracepoint_config); + ep_rt_object_free (tracepoint_config); +} + #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 fd8c019121c1e3..b5d88b9170fd27 100644 --- a/src/native/eventpipe/ep.h +++ b/src/native/eventpipe/ep.h @@ -127,6 +127,7 @@ typedef struct EventPipeSessionOptions { EventPipeSerializationFormat format; uint64_t rundown_keyword; bool stackwalk_requested; + uint32_t user_events_data_fd; } EventPipeSessionOptions; void @@ -142,7 +143,8 @@ ep_session_options_init ( bool stackwalk_requested, IpcStream *stream, EventPipeSessionSynchronousCallback sync_callback, - void *callback_additional_data); + void *callback_additional_data, + uint32_t user_events_data_fd); void ep_session_options_fini (EventPipeSessionOptions* options); From 52bd1a13831568bf92445c075b3c5fb7205a86c3 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Mon, 2 Jun 2025 05:20:35 +0000 Subject: [PATCH 04/32] [DiagnosticServer] Revamp Provider Config deserialization To support the new user_events-based eventpipe session, add a more modular and flexible EventPipeProviderConfiguration deserializer. --- src/native/eventpipe/ds-eventpipe-protocol.c | 407 +++++++++++++++++++ src/native/eventpipe/ep-types-forward.h | 13 + src/native/eventpipe/ep-types.h | 4 + src/native/eventpipe/ep.c | 19 + 4 files changed, 443 insertions(+) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 77706cf5343f9b..da3609498b155c 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -60,6 +60,28 @@ eventpipe_collect_tracing_command_try_parse_stackwalk_requested ( uint32_t *buffer_len, bool *stackwalk_requested); +static +bool +eventpipe_collect_tracing_command_try_parse_event_filter ( + uint8_t **buffer, + uint32_t *buffer_len, + EventPipeProviderEventFilter *event_filter); + +static +bool +eventpipe_collect_tracing_command_try_parse_tracepoint_config ( + uint8_t **buffer, + uint32_t *buffer_len, + EventPipeProviderTracepointConfiguration *tracepoint_config); + +static +bool +eventpipe_collect_tracing_command_try_parse_provider_config ( + uint8_t **buffer, + uint32_t *buffer_len, + EventPipeProviderOptionalFieldFlags optional_field_flags, + EventPipeProviderConfiguration *provider_config); + static bool eventpipe_collect_tracing_command_try_parse_config ( @@ -67,6 +89,14 @@ eventpipe_collect_tracing_command_try_parse_config ( uint32_t *buffer_len, dn_vector_t **result); +static +bool +eventpipe_collect_tracing_command_try_parse_config ( + uint8_t **buffer, + uint32_t *buffer_len, + dn_vector_t **result, + EventPipeProviderOptionalFieldFlags optional_field_flags); + static uint8_t * eventpipe_collect_tracing_command_try_parse_payload ( @@ -193,6 +223,301 @@ eventpipe_collect_tracing_command_try_parse_stackwalk_requested ( return ds_ipc_message_try_parse_bool (buffer, buffer_len, stackwalk_requested); } +static +void +DN_CALLBACK_CALLTYPE +event_id_hashset_key_dispose_func (void *data) +{ + ep_rt_object_free ((uint32_t *)data); +} + +/* + * eventpipe_collect_tracing_command_try_parse_event_filter + * + * Introduced in CollectTracing5, the event filter provides EventPipe Sessions + * additional control over which events are enabled/disabled for a particular provider. + * + * event_filter format: + * - bool enable: 0 to disable events, 1 to enable events + * - array event_ids: If specified, a list of Event IDs to disable or enable + * + * Dynamically allocates memory for the event_ids hashset and passes ownership to the caller. + */ +static +bool +eventpipe_collect_tracing_command_try_parse_event_filter ( + uint8_t **buffer, + uint32_t *buffer_len, + EventPipeProviderEventFilter *event_filter) +{ + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (event_filter != NULL); + + bool result = false; + uint32_t event_id_array_len = 0; + uint32_t *event_id = NULL; + + ep_raise_error_if_nok (ds_ipc_message_try_parse_bool (buffer, buffer_len, &event_filter->enable)); + + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &event_id_array_len)); + if (event_id_array_len > 0) { + dn_umap_custom_alloc_params_t event_id_hashset_params = {0, }; + event_id_hashset_params.hash_func = dn_int_hash; + event_id_hashset_params.equal_func = dn_int_equal; + event_id_hashset_params.key_dispose_func = event_id_hashset_key_dispose_func; + event_filter->event_ids = dn_umap_custom_alloc (&event_id_hashset_params); + ep_raise_error_if_nok (event_filter->event_ids != NULL); + + for (uint32_t i = 0; i < event_id_array_len; ++i) { + event_id = ep_rt_object_alloc (uint32_t); + ep_raise_error_if_nok (event_id != NULL); + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, event_id)); + dn_umap_result_t result = dn_umap_insert (event_filter->event_ids, event_id, NULL); + event_id = NULL; // Ownership transferred to the hashset. + ep_raise_error_if_nok (result.result); + } + } else { + event_filter->event_ids = NULL; + } + + result = true; + +ep_on_exit: + return result; + +ep_on_error: + if (event_id != NULL) { + ep_rt_object_free (event_id); + event_id = NULL; + } + + ep_event_filter_fini (event_filter); + + ep_exit_error_handler (); +} + +/* + * eventpipe_collect_tracing_command_try_parse_tracepoint_config + * + * Introduced in CollectTracing5, user_events-based EventPipe Sessions are required to + * specify a tracepoint configuration per-provider that details which events should be + * written to which tracepoints. Atleast one of default_tracepoint_name or tracepoints + * must be specified. + * + * tracepoint_config format: + * - string default_tracepoint_name: If specified, the default tracepoint to write unmapped enabled events to. + * - array tracepoints: If specified, maps enabled events to tracepoints. + * + * tracepoint_set format: + * - string tracepoint_name: the tracepoint to write the following enabled events_ids to. + * - array event_ids: The Event IDs to be written to tracepoint_name. + */ +static +bool +eventpipe_collect_tracing_command_try_parse_tracepoint_config ( + uint8_t **buffer, + uint32_t *buffer_len, + EventPipeProviderTracepointConfiguration *tracepoint_config) +{ + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (tracepoint_config != NULL); + + bool result = false; + + EventPipeTracepoint *tracepoint = NULL; + const ep_char8_t *tracepoint_name = NULL; + size_t default_tracepoint_format_len = 0; + uint8_t *tracepoint_name_byte_array = NULL; + uint32_t tracepoint_name_byte_array_len = 0; + + uint32_t tracepoint_set_array_len = 0; + uint32_t *event_id = NULL; + + tracepoint_config->default_tracepoint.tracepoint_format[0] = '\0'; // Initialize to empty string. + tracepoint_config->tracepoints = NULL; + tracepoint_config->event_id_to_tracepoint_map = NULL; + + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &tracepoint_name_byte_array, &tracepoint_name_byte_array_len)); + + if (tracepoint_name_byte_array) { + // Make Helper + tracepoint_name = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)tracepoint_name_byte_array); + ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (tracepoint_name)); + ep_rt_byte_array_free (tracepoint_name_byte_array); + tracepoint_name_byte_array = NULL; + + default_tracepoint_format_len = strlen(tracepoint_name) + strlen(EP_TRACEPOINT_FORMAT_V1) + 2; // +2 for space and null terminator + int32_t res = snprintf(tracepoint_config->default_tracepoint.tracepoint_format, default_tracepoint_format_len, "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); + ep_raise_error_if_nok (res >= 0 && (size_t)res < default_tracepoint_format_len); + ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); + tracepoint_name = NULL; + } + + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &tracepoint_set_array_len)); + + if (tracepoint_set_array_len > 0) { + dn_vector_custom_alloc_params_t tracepoint_set_array_params = {0, }; + tracepoint_set_array_params.capacity = tracepoint_set_array_len; + // free func to free the EventPipeTracepoint? + tracepoint_config->tracepoints = dn_vector_custom_alloc_t (&tracepoint_set_array_params, EventPipeTracepoint); + ep_raise_error_if_nok (tracepoint_config->tracepoints != NULL); + + dn_umap_custom_alloc_params_t params = {0, }; + params.hash_func = dn_int_hash; + params.equal_func = dn_int_equal; + params.key_dispose_func = event_id_hashset_key_dispose_func; + tracepoint_config->event_id_to_tracepoint_map = dn_umap_custom_alloc (¶ms); + ep_raise_error_if_nok (tracepoint_config->event_id_to_tracepoint_map != NULL); + + for (uint32_t i = 0; i < tracepoint_set_array_len; ++i) { + tracepoint = ep_rt_object_alloc (EventPipeTracepoint); // Onwership will be transferred to the tracepoint_config's tracepoint vector. + ep_raise_error_if_nok (tracepoint != NULL); + + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &tracepoint_name_byte_array, &tracepoint_name_byte_array_len)); + + // Make Helper + tracepoint_name = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)tracepoint_name_byte_array); + ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (tracepoint_name)); + ep_rt_byte_array_free (tracepoint_name_byte_array); + tracepoint_name_byte_array = NULL; + + default_tracepoint_format_len = strlen(tracepoint_name) + strlen(EP_TRACEPOINT_FORMAT_V1) + 2; // +2 for space and null terminator + int32_t res = snprintf(tracepoint->tracepoint_format, default_tracepoint_format_len, "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); + ep_raise_error_if_nok (res >= 0 && (size_t)res < default_tracepoint_format_len); + ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); + tracepoint_name = NULL; + + uint32_t event_id_array_len = 0; + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &event_id_array_len)); + ep_raise_error_if_nok (event_id_array_len > 0); + + for (uint32_t j = 0; j < event_id_array_len; ++j) { + event_id = ep_rt_object_alloc (uint32_t); // Ownership will be transferred to the tracepoint_config's event_id_to_tracepoint_map. + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, event_id)); + dn_umap_insert (tracepoint_config->event_id_to_tracepoint_map, event_id, tracepoint); + // Ownership of event_id is transferred to the map. + } + + ep_raise_error_if_nok (dn_vector_push_back (tracepoint_config->tracepoints, tracepoint)); + // Ownership of tracepoint is transferred to the tracepoint_config's tracepoint vector. + } + } + + ep_raise_error_if_nok (tracepoint_config->default_tracepoint.tracepoint_format != NULL || tracepoint_config->tracepoints != NULL); + + result = true; + +ep_on_exit: + return result; + +ep_on_error: + ep_rt_object_free (event_id); + event_id = NULL; + + ep_rt_object_free (tracepoint); + tracepoint = NULL; + + ep_tracepoint_config_fini (tracepoint_config); + + ep_rt_byte_array_free (tracepoint_name_byte_array); + tracepoint_name_byte_array = NULL; + + ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); + tracepoint_name = NULL; + + ep_exit_error_handler (); +} + +/* + * eventpipe_collect_tracing_command_try_parse_provider_config + * + * Deserializes a single EventPipeProviderConfiguration from the IPC Stream + * + * Dynamically allocates memory for the EventPipeProviderConfiguration fields and passes ownership to the caller. + */ +static +bool +eventpipe_collect_tracing_command_try_parse_provider_config ( + uint8_t **buffer, + uint32_t *buffer_len, + EventPipeProviderOptionalFieldFlags optional_field_flags, + EventPipeProviderConfiguration *provider_config) +{ + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (provider_config != NULL); + + bool result = false; + + uint32_t log_level = 0; + + uint8_t *provider_name_byte_array = NULL; + uint32_t provider_name_byte_array_len = 0; + + uint8_t *filter_data_byte_array = NULL; + uint32_t filter_data_byte_array_len = 0; + + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint64_t (buffer, buffer_len, &provider_config->keywords)); + + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &log_level)); + provider_config->logging_level = (EventPipeEventLevel)log_level; + ep_raise_error_if_nok (provider_config->logging_level <= EP_EVENT_LEVEL_VERBOSE); + + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &provider_name_byte_array, &provider_name_byte_array_len)); + provider_config->provider_name = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)provider_name_byte_array); + ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (provider_config->provider_name)); + ep_rt_byte_array_free (provider_name_byte_array); + provider_name_byte_array = NULL; + + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &filter_data_byte_array, &filter_data_byte_array_len)); + if (filter_data_byte_array) { + provider_config->filter_data = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)filter_data_byte_array); + ep_raise_error_if_nok (provider_config->filter_data != NULL); + ep_rt_byte_array_free (filter_data_byte_array); + filter_data_byte_array = NULL; + } + + if ((optional_field_flags & EP_PROVIDER_OPTFIELD_EVENT_FILTER) != 0) { + provider_config->event_filter = ep_rt_object_alloc (EventPipeProviderEventFilter); + ep_raise_error_if_nok (provider_config->event_filter != NULL); + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_filter (buffer, buffer_len, provider_config->event_filter)); + } + + if ((optional_field_flags & EP_PROVIDER_OPTFIELD_TRACEPOINT_CONFIG) != 0) { + provider_config->tracepoint_config = ep_rt_object_alloc (EventPipeProviderTracepointConfiguration); + ep_raise_error_if_nok (provider_config->tracepoint_config != NULL); + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_tracepoint_config (buffer, buffer_len, provider_config->tracepoint_config)); + } + + result = true; + +ep_on_exit: + return result; + +ep_on_error: + ep_tracepoint_config_free (provider_config->tracepoint_config); + provider_config->tracepoint_config = NULL; + + ep_event_filter_free (provider_config->event_filter); + provider_config->event_filter = NULL; + + ep_rt_utf8_string_free ((ep_char8_t *)provider_config->filter_data); + provider_config->filter_data = NULL; + + ep_rt_byte_array_free (filter_data_byte_array); + filter_data_byte_array = NULL; + + ep_rt_utf8_string_free ((ep_char8_t *)provider_config->provider_name); + provider_config->provider_name = NULL; + + ep_rt_byte_array_free (provider_name_byte_array); + provider_name_byte_array = NULL; + + ep_exit_error_handler (); +} + static bool eventpipe_collect_tracing_command_try_parse_config ( @@ -281,6 +606,87 @@ eventpipe_collect_tracing_command_try_parse_config ( ep_exit_error_handler (); } +/* + * eventpipe_collect_tracing_command_try_parse_config + * + * With the introduction of CollectTracing5, there is more flexiblity in provider configuration encoding. + * This function deserializes all provider configurations from the IPC Stream, providing callers the flexibility + * to specify which optional fields are present for the particular CollectTracingN command. + * + * Ownership of all EventPipeProviderConfigurations data is transferred to the caller. + */ +static +bool +eventpipe_collect_tracing_command_try_parse_config ( + uint8_t **buffer, + uint32_t *buffer_len, + dn_vector_t **result, + EventPipeProviderOptionalFieldFlags optional_field_flags) +{ + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (result != NULL); + + // Picking an arbitrary upper bound, + // This should be larger than any reasonable client request. + const uint32_t max_count_configs = 1000; + uint32_t count_configs = 0; + dn_vector_custom_alloc_params_t params = {0, }; + + EventPipeProviderConfiguration *provider_config = NULL; + + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &count_configs)); + ep_raise_error_if_nok (count_configs <= max_count_configs); + params.capacity = count_configs; + // Free func for the EventPipeProviderConfiguration? + *result = dn_vector_custom_alloc_t (¶ms, EventPipeProviderConfiguration); + ep_raise_error_if_nok (*result); + + for (uint32_t i = 0; i < count_configs; ++i) { + provider_config = ep_rt_object_alloc (EventPipeProviderConfiguration); + ep_raise_error_if_nok (provider_config != NULL); + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_provider_config ( + buffer, + buffer_len, + optional_field_flags, + provider_config)); + + ep_raise_error_if_nok (dn_vector_push_back (*result, *provider_config)); + provider_config = NULL; // Ownership transferred. + } + +ep_on_exit: + return (count_configs > 0); + +ep_on_error: + count_configs = 0; + + // Until ep_provider_config_fini/free is implemented, we need to manually free the provider_config. + if (provider_config != NULL) { + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (provider_config)); + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (provider_config)); + ep_event_filter_free (ep_provider_config_get_event_filter (provider_config)); + ep_tracepoint_config_free (ep_provider_config_get_tracepoint_config (provider_config)); + ep_rt_object_free (provider_config); + provider_config = NULL; + } + + // Until ep_provider_config_fini/free is implemented, we need to manually free the provider_config. + if (*result != NULL) { + DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, *result) { + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); + ep_event_filter_free (ep_provider_config_get_event_filter (&config)); + ep_tracepoint_config_free (ep_provider_config_get_tracepoint_config (&config)); + ep_rt_object_free (&config); + } DN_VECTOR_FOREACH_END; + } + + dn_vector_free (*result); + *result = NULL; + ep_exit_error_handler (); +} + EventPipeCollectTracingCommandPayload * ds_eventpipe_collect_tracing_command_payload_alloc (void) { @@ -296,6 +702,7 @@ ds_eventpipe_collect_tracing_command_payload_free (EventPipeCollectTracingComman DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) { ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); + // What about the EventPipeProviderConfiguration allocated in eventpipe_collect_tracing_command_try_parse_config } DN_VECTOR_FOREACH_END; ep_rt_object_free (payload); diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index 3dddfae6aba5c7..bbad7e4bb61d01 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -166,6 +166,19 @@ typedef enum { EP_THREAD_TYPE_SAMPLING } EventPipeThreadType; +/* + * CollectTracing5 introduces additional provider configuration fields. + * For backwards compatibility, these fields are optional and + * these flags indicate which of the optional fields should be + * deserialized from the IPC Stream. + */ +typedef enum +{ + EP_PROVIDER_OPTFIELD_NONE = 0, + EP_PROVIDER_OPTFIELD_EVENT_FILTER = 1, + EP_PROVIDER_OPTFIELD_TRACEPOINT_CONFIG = 2 +} EventPipeProviderOptionalFieldFlags; + /* * EventPipe Basic Types. */ diff --git a/src/native/eventpipe/ep-types.h b/src/native/eventpipe/ep-types.h index 8404f938a31e5c..e3e04a226a986f 100644 --- a/src/native/eventpipe/ep-types.h +++ b/src/native/eventpipe/ep-types.h @@ -259,6 +259,8 @@ struct _EventPipeProviderConfiguration_Internal { const ep_char8_t *filter_data; uint64_t keywords; EventPipeEventLevel logging_level; + EventPipeProviderEventFilter *event_filter; + EventPipeProviderTracepointConfiguration *tracepoint_config; }; @@ -272,6 +274,8 @@ EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, const ep_cha EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, const ep_char8_t *, filter_data) EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, uint64_t, keywords) EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, EventPipeEventLevel, logging_level) +EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, EventPipeProviderEventFilter *, event_filter) +EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, EventPipeProviderTracepointConfiguration *, tracepoint_config) EventPipeProviderConfiguration * ep_provider_config_init ( diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index d8cd4422e09a29..a1d70b9ad8e967 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -378,6 +378,10 @@ ep_provider_config_init ( provider_config->logging_level = logging_level; provider_config->filter_data = filter_data; + // Currently only supported through IPC Command + provider_config->event_filter = NULL; + provider_config->tracepoint_config = NULL; + // Runtime specific rundown provider configuration. ep_rt_provider_config_init (provider_config); @@ -1755,6 +1759,11 @@ void ep_event_filter_fini (EventPipeProviderEventFilter *event_filter) { ep_return_void_if_nok (event_filter != NULL); + + if (event_filter->event_ids) { + dn_umap_free (event_filter->event_ids); + event_filter->event_ids = NULL; + } } void @@ -1770,6 +1779,16 @@ void ep_tracepoint_config_fini (EventPipeProviderTracepointConfiguration *tracepoint_config) { ep_return_void_if_nok (tracepoint_config != NULL); + + if (tracepoint_config->event_id_to_tracepoint_map) { + dn_umap_free (tracepoint_config->event_id_to_tracepoint_map); + tracepoint_config->event_id_to_tracepoint_map = NULL; + } + + if (tracepoint_config->tracepoints) { + dn_vector_free (tracepoint_config->tracepoints); + tracepoint_config->tracepoints = NULL; + } } void From 26284e2adb34eee5e4a1acfedb487eeac35c2f1a Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Sat, 31 May 2025 19:24:16 +0000 Subject: [PATCH 05/32] [DiagnosticServer] Deprecate old deserializer --- src/native/eventpipe/ds-eventpipe-protocol.c | 103 +------------------ 1 file changed, 4 insertions(+), 99 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index da3609498b155c..54560bd3671830 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -82,13 +82,6 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( EventPipeProviderOptionalFieldFlags optional_field_flags, EventPipeProviderConfiguration *provider_config); -static -bool -eventpipe_collect_tracing_command_try_parse_config ( - uint8_t **buffer, - uint32_t *buffer_len, - dn_vector_t **result); - static bool eventpipe_collect_tracing_command_try_parse_config ( @@ -518,94 +511,6 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( ep_exit_error_handler (); } -static -bool -eventpipe_collect_tracing_command_try_parse_config ( - uint8_t **buffer, - uint32_t *buffer_len, - dn_vector_t **result) -{ - EP_ASSERT (buffer != NULL); - EP_ASSERT (buffer_len != NULL); - EP_ASSERT (result != NULL); - - // Picking an arbitrary upper bound, - // This should be larger than any reasonable client request. - // TODO: This might be too large. - const uint32_t max_count_configs = 1000; - uint32_t count_configs = 0; - - uint8_t *provider_name_byte_array = NULL; - uint8_t *filter_data_byte_array = NULL; - - ep_char8_t *provider_name_utf8 = NULL; - ep_char8_t *filter_data_utf8 = NULL; - - dn_vector_custom_alloc_params_t params = {0, }; - - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &count_configs)); - ep_raise_error_if_nok (count_configs <= max_count_configs); - - params.capacity = count_configs; - - *result = dn_vector_custom_alloc_t (¶ms, EventPipeProviderConfiguration); - ep_raise_error_if_nok (*result); - - for (uint32_t i = 0; i < count_configs; ++i) { - uint64_t keywords = 0; - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint64_t (buffer, buffer_len, &keywords)); - - uint32_t log_level = 0; - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &log_level)); - ep_raise_error_if_nok (log_level <= EP_EVENT_LEVEL_VERBOSE); - - uint32_t provider_name_byte_array_len = 0; - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &provider_name_byte_array, &provider_name_byte_array_len)); - - provider_name_utf8 = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)provider_name_byte_array); - ep_raise_error_if_nok (provider_name_utf8 != NULL); - - ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (provider_name_utf8)); - - ep_rt_byte_array_free (provider_name_byte_array); - provider_name_byte_array = NULL; - - uint32_t filter_data_byte_array_len = 0; - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &filter_data_byte_array, &filter_data_byte_array_len)); - - // This parameter is optional. - if (filter_data_byte_array) { - filter_data_utf8 = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)filter_data_byte_array); - ep_raise_error_if_nok (filter_data_utf8 != NULL); - - ep_rt_byte_array_free (filter_data_byte_array); - filter_data_byte_array = NULL; - } - - EventPipeProviderConfiguration provider_config; - if (ep_provider_config_init (&provider_config, provider_name_utf8, keywords, (EventPipeEventLevel)log_level, filter_data_utf8)) { - if (dn_vector_push_back (*result, provider_config)) { - // Ownership transferred. - provider_name_utf8 = NULL; - filter_data_utf8 = NULL; - } - ep_provider_config_fini (&provider_config); - } - ep_raise_error_if_nok (provider_name_utf8 == NULL && filter_data_utf8 == NULL); - } - -ep_on_exit: - return (count_configs > 0); - -ep_on_error: - count_configs = 0; - ep_rt_byte_array_free (provider_name_byte_array); - ep_rt_utf8_string_free (provider_name_utf8); - ep_rt_byte_array_free (filter_data_byte_array); - ep_rt_utf8_string_free (filter_data_utf8); - ep_exit_error_handler (); -} - /* * eventpipe_collect_tracing_command_try_parse_config * @@ -730,7 +635,7 @@ eventpipe_collect_tracing_command_try_parse_payload ( if (!eventpipe_collect_tracing_command_try_parse_circular_buffer_size (&buffer_cursor, &buffer_cursor_len, &instance->circular_buffer_size_in_mb ) || !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || - !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs)) + !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs, EP_PROVIDER_OPTFIELD_NONE)) ep_raise_error (); instance->rundown_requested = true; instance->stackwalk_requested = true; @@ -764,7 +669,7 @@ eventpipe_collect_tracing2_command_try_parse_payload ( if (!eventpipe_collect_tracing_command_try_parse_circular_buffer_size (&buffer_cursor, &buffer_cursor_len, &instance->circular_buffer_size_in_mb ) || !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || !eventpipe_collect_tracing_command_try_parse_rundown_requested (&buffer_cursor, &buffer_cursor_len, &instance->rundown_requested) || - !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs)) + !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs, EP_PROVIDER_OPTFIELD_NONE)) ep_raise_error (); instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; @@ -800,7 +705,7 @@ eventpipe_collect_tracing3_command_try_parse_payload ( !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || !eventpipe_collect_tracing_command_try_parse_rundown_requested (&buffer_cursor, &buffer_cursor_len, &instance->rundown_requested) || !eventpipe_collect_tracing_command_try_parse_stackwalk_requested (&buffer_cursor, &buffer_cursor_len, &instance->stackwalk_requested) || - !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs)) + !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs, EP_PROVIDER_OPTFIELD_NONE)) ep_raise_error (); instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; @@ -834,7 +739,7 @@ eventpipe_collect_tracing4_command_try_parse_payload ( !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || !eventpipe_collect_tracing_command_try_parse_rundown_keyword (&buffer_cursor, &buffer_cursor_len, &instance->rundown_keyword) || !eventpipe_collect_tracing_command_try_parse_stackwalk_requested (&buffer_cursor, &buffer_cursor_len, &instance->stackwalk_requested) || - !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs)) + !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs, EP_PROVIDER_OPTFIELD_NONE)) ep_raise_error (); instance->rundown_requested = instance->rundown_keyword != 0; From 3ea4e8292d174fd55237a2e93e3b2c820fb3350c Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Wed, 16 Apr 2025 21:46:14 +0000 Subject: [PATCH 06/32] [DiagnosticServer] Add CollectTracing5 command parser --- src/native/eventpipe/ds-eventpipe-protocol.c | 99 +++++++++++++++++++- src/native/eventpipe/ds-eventpipe-protocol.h | 2 + src/native/eventpipe/ds-types.h | 1 + src/native/eventpipe/ep-types-forward.h | 9 ++ 4 files changed, 108 insertions(+), 3 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 54560bd3671830..56584e021f0dd9 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -114,6 +114,12 @@ eventpipe_collect_tracing4_command_try_parse_payload ( uint8_t *buffer, uint16_t buffer_len); +static +uint8_t * +eventpipe_collect_tracing5_command_try_parse_payload ( + uint8_t *buffer, + uint16_t buffer_len); + static bool eventpipe_protocol_helper_stop_tracing ( @@ -640,6 +646,7 @@ eventpipe_collect_tracing_command_try_parse_payload ( instance->rundown_requested = true; instance->stackwalk_requested = true; instance->rundown_keyword = ep_default_rundown_keyword; + instance->session_type = EP_IPC_SESSION_TYPE_STREAMING; ep_on_exit: return (uint8_t *)instance; @@ -675,6 +682,7 @@ eventpipe_collect_tracing2_command_try_parse_payload ( instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; instance->stackwalk_requested = true; + instance->session_type = EP_IPC_SESSION_TYPE_STREAMING; ep_on_exit: return (uint8_t *)instance; @@ -709,6 +717,7 @@ eventpipe_collect_tracing3_command_try_parse_payload ( ep_raise_error (); instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; + instance->session_type = EP_IPC_SESSION_TYPE_STREAMING; ep_on_exit: return (uint8_t *)instance; @@ -743,6 +752,67 @@ eventpipe_collect_tracing4_command_try_parse_payload ( ep_raise_error (); instance->rundown_requested = instance->rundown_keyword != 0; + instance->session_type = EP_IPC_SESSION_TYPE_STREAMING; + +ep_on_exit: + return (uint8_t *)instance; + +ep_on_error: + ds_eventpipe_collect_tracing_command_payload_free (instance); + instance = NULL; + ep_exit_error_handler (); +} + +/* + * eventpipe_collect_tracing5_command_try_parse_payload + * + * Implements the CollectTracing5 IPC Protocol deserialization. + * + * Ownership of the EventPipeCollectTracingCommandPayload is transferred to the caller. + */ +static +uint8_t * +eventpipe_collect_tracing5_command_try_parse_payload ( + uint8_t *buffer, + uint16_t buffer_len) +{ + EP_ASSERT (buffer != NULL); + + uint8_t * buffer_cursor = buffer; + uint32_t buffer_cursor_len = buffer_len; + + EventPipeProviderOptionalFieldFlags optional_field_flags = EP_PROVIDER_OPTFIELD_EVENT_FILTER; + + EventPipeCollectTracingCommandPayload *instance = ds_eventpipe_collect_tracing_command_payload_alloc (); + ep_raise_error_if_nok (instance != NULL); + + instance->incoming_buffer = buffer; + + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (&buffer_cursor, &buffer_cursor_len, &instance->session_type)); + ep_raise_error_if_nok (instance->session_type < EP_IPC_SESSION_TYPE_COUNT); + + if (instance->session_type == EP_IPC_SESSION_TYPE_STREAMING) { + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_circular_buffer_size (&buffer_cursor, &buffer_cursor_len, &instance->circular_buffer_size_in_mb)); + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format)); + } else if (instance->session_type == EP_IPC_SESSION_TYPE_USEREVENTS) { + instance->circular_buffer_size_in_mb = 0; + instance->serialization_format = EP_SERIALIZATION_FORMAT_NETTRACE_V4; // Serialization format isn't used for user_events sessions, default for check_options_valid. + } + + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint64_t (&buffer_cursor, &buffer_cursor_len, &instance->rundown_keyword)); + + if (instance->session_type == EP_IPC_SESSION_TYPE_STREAMING) { + ep_raise_error_if_nok (ds_ipc_message_try_parse_bool (&buffer_cursor, &buffer_cursor_len, &instance->stackwalk_requested)); + } else if (instance->session_type == EP_IPC_SESSION_TYPE_USEREVENTS) { + instance->stackwalk_requested = false; + } + + if (instance->session_type == EP_IPC_SESSION_TYPE_USEREVENTS) + optional_field_flags = (EventPipeProviderOptionalFieldFlags)(optional_field_flags | EP_PROVIDER_OPTFIELD_TRACEPOINT_CONFIG); + + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs, optional_field_flags)); + + instance->rundown_requested = instance->rundown_keyword != 0; ep_on_exit: return (uint8_t *)instance; @@ -842,6 +912,11 @@ eventpipe_protocol_helper_collect_tracing ( return false; } + uint32_t user_events_data_fd = -1; + if (payload->session_type == EP_IPC_SESSION_TYPE_USEREVENTS) { + // Extract file descriptor from IpcStream + } + EventPipeSessionOptions options; ep_session_options_init( &options, @@ -849,14 +924,14 @@ eventpipe_protocol_helper_collect_tracing ( payload->circular_buffer_size_in_mb, dn_vector_data_t (payload->provider_configs, EventPipeProviderConfiguration), dn_vector_size (payload->provider_configs), - EP_SESSION_TYPE_IPCSTREAM, + payload->session_type == EP_IPC_SESSION_TYPE_USEREVENTS ? EP_SESSION_TYPE_USEREVENTS : EP_SESSION_TYPE_IPCSTREAM, payload->serialization_format, payload->rundown_keyword, payload->stackwalk_requested, - ds_ipc_stream_get_stream_ref (stream), + payload->session_type == EP_IPC_SESSION_TYPE_STREAMING ? ds_ipc_stream_get_stream_ref (stream) : NULL, NULL, NULL, - 0); + user_events_data_fd); EventPipeSessionID session_id = 0; bool result = false; @@ -929,6 +1004,24 @@ ds_eventpipe_protocol_helper_handle_ipc_message ( payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing4_command_try_parse_payload); result = eventpipe_protocol_helper_collect_tracing (payload, stream); break; + case EP_COMMANDID_COLLECT_TRACING_5: + payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing5_command_try_parse_payload); + result = eventpipe_protocol_helper_collect_tracing (payload, stream); + // If there was a problem transferring ownership of the payload to the session's providers, + // we need to free the dynamically allocated event_filter and tracepoint_config here. + if (!result) { + if (payload->provider_configs != NULL) { + // Until ep_provider_config_fini is implemented, we need to manually free the provider_config manually. + DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) { + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); + ep_event_filter_free (ep_provider_config_get_event_filter (&config)); + ep_tracepoint_config_free (ep_provider_config_get_tracepoint_config (&config)); + ep_rt_object_free (&config); + } DN_VECTOR_FOREACH_END; + } + } + break; case EP_COMMANDID_STOP_TRACING: result = eventpipe_protocol_helper_stop_tracing (message, stream); break; diff --git a/src/native/eventpipe/ds-eventpipe-protocol.h b/src/native/eventpipe/ds-eventpipe-protocol.h index 14496068a109b9..5101ddf1b0938f 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.h +++ b/src/native/eventpipe/ds-eventpipe-protocol.h @@ -21,6 +21,7 @@ // Command = 0x0203 // Command = 0x0204 // Command = 0x0205 +// Command = 0x0206 #if defined(DS_INLINE_GETTER_SETTER) || defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER) struct _EventPipeCollectTracingCommandPayload { #else @@ -42,6 +43,7 @@ struct _EventPipeCollectTracingCommandPayload_Internal { bool rundown_requested; bool stackwalk_requested; uint64_t rundown_keyword; + uint32_t session_type; }; #if !defined(DS_INLINE_GETTER_SETTER) && !defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER) diff --git a/src/native/eventpipe/ds-types.h b/src/native/eventpipe/ds-types.h index f8ef4b216dec6d..5337497e180f21 100644 --- a/src/native/eventpipe/ds-types.h +++ b/src/native/eventpipe/ds-types.h @@ -73,6 +73,7 @@ typedef enum { EP_COMMANDID_COLLECT_TRACING_2 = 0x03, EP_COMMANDID_COLLECT_TRACING_3 = 0x04, EP_COMMANDID_COLLECT_TRACING_4 = 0x05, + EP_COMMANDID_COLLECT_TRACING_5 = 0x06, // future } EventPipeCommandId; diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index bbad7e4bb61d01..525a08ae04e226 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -179,6 +179,15 @@ typedef enum EP_PROVIDER_OPTFIELD_TRACEPOINT_CONFIG = 2 } EventPipeProviderOptionalFieldFlags; +/* + * EventPipe session types that can be started via IPC commands. + */ +typedef enum { + EP_IPC_SESSION_TYPE_STREAMING, + EP_IPC_SESSION_TYPE_USEREVENTS, + EP_IPC_SESSION_TYPE_COUNT +} EventPipeIPCSessionType; + /* * EventPipe Basic Types. */ From 97b12d1befbc1b1dd69f7869066f8937f4598aed Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Fri, 2 May 2025 22:49:49 +0000 Subject: [PATCH 07/32] [DiagnosticServer] Deserialize file_descriptor from IPC Stream The user_events_data file is required to register user_events tracepoints. Require profilers to pass over the corresponding file descriptor with SCM_RIGHTS in order to initialize the user_events EventPipe session. --- src/native/eventpipe/ds-eventpipe-protocol.c | 5 +- src/native/eventpipe/ds-ipc-pal-namedpipe.c | 9 ++++ src/native/eventpipe/ds-ipc-pal-socket.c | 53 ++++++++++++++++++++ src/native/eventpipe/ds-ipc-pal-websocket.c | 9 ++++ src/native/eventpipe/ds-ipc-pal.h | 5 ++ 5 files changed, 80 insertions(+), 1 deletion(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 56584e021f0dd9..d5413d442ef469 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -914,7 +914,10 @@ eventpipe_protocol_helper_collect_tracing ( uint32_t user_events_data_fd = -1; if (payload->session_type == EP_IPC_SESSION_TYPE_USEREVENTS) { - // Extract file descriptor from IpcStream + if (!ds_ipc_stream_read_fd (stream, &user_events_data_fd)) { + ds_ipc_message_send_error (stream, DS_IPC_E_BAD_ENCODING); + return false; + } } EventPipeSessionOptions options; diff --git a/src/native/eventpipe/ds-ipc-pal-namedpipe.c b/src/native/eventpipe/ds-ipc-pal-namedpipe.c index b7cfd0528fa4e0..90a8ab144ff4a5 100644 --- a/src/native/eventpipe/ds-ipc-pal-namedpipe.c +++ b/src/native/eventpipe/ds-ipc-pal-namedpipe.c @@ -906,6 +906,15 @@ ds_ipc_stream_read ( timeout_ms); } +bool +ds_ipc_stream_read_fd ( + DiagnosticsIpcStream *ipc_stream, + uint32_t *data_fd) +{ + // Not Supported + return false; +} + bool ds_ipc_stream_write ( DiagnosticsIpcStream *ipc_stream, diff --git a/src/native/eventpipe/ds-ipc-pal-socket.c b/src/native/eventpipe/ds-ipc-pal-socket.c index 0826dbb55d5adb..80c48687dd21d4 100644 --- a/src/native/eventpipe/ds-ipc-pal-socket.c +++ b/src/native/eventpipe/ds-ipc-pal-socket.c @@ -1556,6 +1556,59 @@ ds_ipc_stream_read ( timeout_ms); } +bool +ds_ipc_stream_read_fd ( + DiagnosticsIpcStream *ipc_stream, + uint32_t *data_fd) +{ +#if HAVE_SYS_SOCKET_H + EP_ASSERT (ipc_stream != NULL); + EP_ASSERT (data_fd != NULL); + + struct msghdr msg = {0}; + + msg.msg_name = NULL; + msg.msg_namelen = 0; + + struct iovec io_vec[1]; + uint8_t buffer[1]; + io_vec[0].iov_base = buffer; + io_vec[0].iov_len = 1; + + msg.msg_iov = io_vec; + msg.msg_iovlen = 1; + + union { + struct cmsghdr cmsg; + char control[CMSG_SPACE(sizeof(*data_fd))]; + } control_un; + msg.msg_control = control_un.control; + msg.msg_controllen = sizeof(control_un.control); + + ssize_t n = recvmsg(ipc_stream->client_socket, &msg, 0); + if (n < 0) { + return false; + } + + struct cmsghdr *cmptr; + if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL || + cmptr->cmsg_level != SOL_SOCKET || + cmptr->cmsg_type != SCM_RIGHTS) { + return false; + } + + memcpy(data_fd, CMSG_DATA(cmptr), sizeof(*data_fd)); // This is a file descriptor, data_fd should have enough space + if (*data_fd < 0) { + return false; + } + + return true; +#else // HAVE_SYS_SOCKET_H + // Not supported + return false; +#endif // HAVE_SYS_SOCKET_H +} + bool ds_ipc_stream_write ( DiagnosticsIpcStream *ipc_stream, diff --git a/src/native/eventpipe/ds-ipc-pal-websocket.c b/src/native/eventpipe/ds-ipc-pal-websocket.c index 21f617325d9a12..3f63e35506f30c 100644 --- a/src/native/eventpipe/ds-ipc-pal-websocket.c +++ b/src/native/eventpipe/ds-ipc-pal-websocket.c @@ -490,6 +490,15 @@ ds_ipc_stream_read ( timeout_ms); } +bool +ds_ipc_stream_read_fd ( + DiagnosticsIpcStream *ipc_stream, + uint32_t *data_fd) +{ + // Not Supported + return false; +} + bool ds_ipc_stream_write ( DiagnosticsIpcStream *ipc_stream, diff --git a/src/native/eventpipe/ds-ipc-pal.h b/src/native/eventpipe/ds-ipc-pal.h index 8e246ed671955c..4f649fcf44891a 100644 --- a/src/native/eventpipe/ds-ipc-pal.h +++ b/src/native/eventpipe/ds-ipc-pal.h @@ -113,6 +113,11 @@ ds_ipc_stream_read ( uint32_t *bytes_read, uint32_t timeout_ms); +bool +ds_ipc_stream_read_fd ( + DiagnosticsIpcStream *ipc_stream, + uint32_t *data_fd); + bool ds_ipc_stream_write ( DiagnosticsIpcStream *ipc_stream, From d20e58406bcc3a2c0b5672849e9d169f10b01f5a Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Fri, 2 May 2025 18:05:47 +0000 Subject: [PATCH 08/32] [EventPipe] Use Event_filter to set EventPipeEvent enabled mask --- src/native/eventpipe/ep-provider.c | 40 ++++++++-------------- src/native/eventpipe/ep-session-provider.c | 38 ++++++++++++++++++++ src/native/eventpipe/ep-session-provider.h | 5 +++ 3 files changed, 58 insertions(+), 25 deletions(-) diff --git a/src/native/eventpipe/ep-provider.c b/src/native/eventpipe/ep-provider.c index 7670f23453ac46..7a2fd1cb533834 100644 --- a/src/native/eventpipe/ep-provider.c +++ b/src/native/eventpipe/ep-provider.c @@ -50,8 +50,7 @@ int64_t provider_compute_event_enable_mask ( const EventPipeConfiguration *config, const EventPipeProvider *provider, - int64_t keywords, - EventPipeEventLevel event_level); + const EventPipeEvent *ep_event); /* * EventPipeProvider. @@ -127,7 +126,7 @@ provider_refresh_event_state (EventPipeEvent *ep_event) EventPipeConfiguration *config = provider->config; EP_ASSERT (config != NULL); - int64_t enable_mask = provider_compute_event_enable_mask (config, provider, ep_event_get_keywords (ep_event), ep_event_get_level (ep_event)); + int64_t enable_mask = provider_compute_event_enable_mask (config, provider, ep_event); ep_event_set_enabled_mask (ep_event, enable_mask); ep_requires_lock_held (); @@ -139,8 +138,7 @@ int64_t provider_compute_event_enable_mask ( const EventPipeConfiguration *config, const EventPipeProvider *provider, - int64_t keywords, - EventPipeEventLevel event_level) + const EventPipeEvent *ep_event) { EP_ASSERT (provider != NULL); @@ -148,29 +146,21 @@ provider_compute_event_enable_mask ( int64_t result = 0; bool provider_enabled = ep_provider_get_enabled (provider); + if (!provider_enabled) + return result; + for (int i = 0; i < EP_MAX_NUMBER_OF_SESSIONS; i++) { // Entering EventPipe lock gave us a barrier, we don't need more of them. EventPipeSession *session = ep_volatile_load_session_without_barrier (i); - if (session) { - EventPipeSessionProvider *session_provider = config_get_session_provider (config, session, provider); - if (session_provider) { - int64_t session_keyword = ep_session_provider_get_keywords (session_provider); - EventPipeEventLevel session_level = ep_session_provider_get_logging_level (session_provider); - // The event is enabled if: - // - The provider is enabled. - // - The event keywords are unspecified in the manifest (== 0) or when masked with the enabled config are != 0. - // - The event level is LogAlways - // or the provider's verbosity level is LogAlways - // or the provider's verbosity level is set to greater than the event's verbosity level in the manifest. - bool keyword_enabled = (keywords == 0) || ((session_keyword & keywords) != 0); - bool level_enabled = (event_level == EP_EVENT_LEVEL_LOGALWAYS) || - (session_level == EP_EVENT_LEVEL_LOGALWAYS) || - (session_level >= event_level); - - if (provider_enabled && keyword_enabled && level_enabled) - result = result | ep_session_get_mask (session); - } - } + if (session == NULL) + continue; + + EventPipeSessionProvider *session_provider = config_get_session_provider (config, session, provider); + if (session_provider == NULL) + continue; + + if (ep_session_provider_allows_event (session_provider, ep_event)) + result = result | ep_session_get_mask (session); } ep_requires_lock_held (); diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index ac0712d24e0955..5d51bf6355a272 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -109,6 +109,44 @@ ep_session_provider_free (EventPipeSessionProvider * session_provider) ep_rt_object_free (session_provider); } +bool +ep_event_filter_allows_event_id ( + const EventPipeProviderEventFilter *event_filter, + uint32_t event_id) +{ + if (event_filter == NULL) + return true; + + if (event_filter->event_ids == NULL) + return !event_filter->enable; + + return event_filter->enable == dn_umap_contains (event_filter->event_ids, &event_id); +} + +bool +ep_session_provider_allows_event ( + const EventPipeSessionProvider *session_provider, + const EventPipeEvent *ep_event) +{ + EP_ASSERT(session_provider != NULL); + + uint64_t keywords = ep_event_get_keywords (ep_event); + uint64_t session_keywords = ep_session_provider_get_keywords(session_provider); + if ((keywords != 0) && ((session_keywords & keywords) == 0)) + return false; + + EventPipeEventLevel event_level = ep_event_get_level (ep_event); + EventPipeEventLevel session_level = ep_session_provider_get_logging_level(session_provider); + if ((event_level != EP_EVENT_LEVEL_LOGALWAYS) && + (session_level != EP_EVENT_LEVEL_LOGALWAYS) && + (session_level < event_level)) + return false; + + uint32_t event_id = ep_event_get_event_id (ep_event); + EventPipeProviderEventFilter *event_filter = ep_session_provider_get_event_filter (session_provider); + return ep_event_filter_allows_event_id (event_filter, event_id); +} + /* * EventPipeSessionProviderList. */ diff --git a/src/native/eventpipe/ep-session-provider.h b/src/native/eventpipe/ep-session-provider.h index 0247254e27f068..46fda0e6b547a7 100644 --- a/src/native/eventpipe/ep-session-provider.h +++ b/src/native/eventpipe/ep-session-provider.h @@ -60,6 +60,11 @@ ep_session_provider_alloc ( void ep_session_provider_free (EventPipeSessionProvider * session_provider); +bool +ep_session_provider_allows_event ( + const EventPipeSessionProvider *session_provider, + const EventPipeEvent *ep_event); + /* * EventPipeSessionProviderList. */ From e81e10c4d0418e093dd6fe5ab534ff82619e6f48 Mon Sep 17 00:00:00 2001 From: mdh1418 Date: Sun, 1 Jun 2025 23:18:19 -0400 Subject: [PATCH 09/32] [UserEvents] Register and unregister tracepoints --- src/native/eventpipe/configure.cmake | 5 + src/native/eventpipe/ep-session.c | 145 ++++++++++++++++++++- src/native/eventpipe/ep-session.h | 6 + src/native/eventpipe/ep-shared-config.h.in | 1 + src/native/eventpipe/ep-types-forward.h | 8 ++ 5 files changed, 164 insertions(+), 1 deletion(-) diff --git a/src/native/eventpipe/configure.cmake b/src/native/eventpipe/configure.cmake index b0af4301d6a914..48b0ac40ab598a 100644 --- a/src/native/eventpipe/configure.cmake +++ b/src/native/eventpipe/configure.cmake @@ -17,6 +17,11 @@ if (CLR_CMAKE_HOST_IOS OR CLR_CMAKE_HOST_TVOS OR CLR_CMAKE_HOST_ANDROID) set(FEATURE_PERFTRACING_DISABLE_DEFAULT_LISTEN_PORT 1) endif() +check_include_files( + "linux/user_events.h;sys/ioctl.h;unistd.h" + HAVE_LINUX_USER_EVENTS_H +) + if (NOT DEFINED EP_GENERATED_HEADER_PATH) message(FATAL_ERROR "Required configuration EP_GENERATED_HEADER_PATH not set.") endif (NOT DEFINED EP_GENERATED_HEADER_PATH) diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index a98b47806a1123..962c7ad83feb8e 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -30,6 +30,23 @@ static void ep_session_remove_dangling_session_states (EventPipeSession *session); +static +bool +ep_tracepoint_reg( + uint32_t fd, + EventPipeTracepoint *tracepoint); + +static +bool +ep_tracepoint_unreg ( + uint32_t fd, + EventPipeTracepoint *tracepoint); + +static +void +ep_session_user_events_tracepoints_init ( + EventPipeSession *session); + static void ep_session_disable_user_events (EventPipeSession *session); @@ -160,6 +177,107 @@ session_disable_streaming_thread (EventPipeSession *session) ep_rt_wait_event_free (rt_thread_shutdown_event); } +static +bool +ep_tracepoint_reg ( + uint32_t fd, + EventPipeTracepoint *tracepoint) +{ +#if HAVE_LINUX_USER_EVENTS_H + struct user_reg reg = {0}; + + reg.size = sizeof(reg); + reg.enable_bit = EP_TRACEPOINT_ENABLE_BIT; + reg.enable_size = sizeof(tracepoint->enabled); + reg.enable_addr = (uint64_t)&tracepoint->enabled; + + reg.name_args = (uint64_t)tracepoint->tracepoint_format; + + if (ioctl(fd, DIAG_IOCSREG, ®) == -1) + return false; + + tracepoint->write_index = reg.write_index; + + return true; +#else // HAVE_LINUX_USER_EVENTS_H + // Not Supported + return false; +#endif // HAVE_LINUX_USER_EVENTS_H +} + +static +bool +ep_tracepoint_unreg ( + uint32_t fd, + EventPipeTracepoint *tracepoint) +{ +#if HAVE_LINUX_USER_EVENTS_H + struct user_unreg unreg = {0}; + + unreg.size = sizeof(unreg); + unreg.disable_bit = EP_TRACEPOINT_ENABLE_BIT; + unreg.disable_addr = (uint64_t)&tracepoint->enabled; + + if (ioctl(fd, DIAG_IOCSUNREG, &unreg) == -1) + return false; + + return true; +#else // HAVE_LINUX_USER_EVENTS_H + // Not Supported + return false; +#endif // HAVE_LINUX_USER_EVENTS_H +} + +/* + * + * + * + * + */ +static +void +ep_session_user_events_tracepoints_init ( + EventPipeSession *session) +{ + EP_ASSERT (session != NULL); + EP_ASSERT (session->session_type == EP_SESSION_TYPE_USEREVENTS); + EP_ASSERT (session->user_events_data_fd != 0); + + EventPipeSessionProviderList *providers = ep_session_get_providers (session); + EP_ASSERT (providers != NULL); + + for (dn_list_it_t it = dn_list_begin (ep_session_provider_list_get_providers (providers)); !dn_list_it_end (it); it = dn_list_it_next (it)) { + EventPipeSessionProvider *session_provider = *dn_list_it_data_t (it, EventPipeSessionProvider *); + EP_ASSERT (session_provider != NULL); + + EventPipeProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); + EP_ASSERT (tracepoint_config != NULL); + EP_ASSERT (tracepoint_config->default_tracepoint.tracepoint_format != NULL || tracepoint_config->tracepoints != NULL); + + if (tracepoint_config->default_tracepoint.tracepoint_format != NULL) { + ep_raise_error_if_nok (ep_tracepoint_reg (session->user_events_data_fd, + &tracepoint_config->default_tracepoint)); + } + + dn_vector_t *tracepoints = tracepoint_config->tracepoints; + if (tracepoints != NULL) { + for (uint32_t i = 0; i < tracepoints->size; ++i) { + EventPipeTracepoint *tracepoint = *dn_vector_index_t (tracepoints, EventPipeTracepoint *, i); + ep_raise_error_if_nok (tracepoint != NULL); + + ep_raise_error_if_nok (ep_tracepoint_reg (session->user_events_data_fd, + tracepoint)); + } + } + } + +ep_on_exit: + return; + +ep_on_error: + ep_exit_error_handler (); +} + EventPipeSession * ep_session_alloc ( uint32_t index, @@ -243,7 +361,7 @@ ep_session_alloc ( // Transfer ownership of the user_events_data file descriptor to the EventPipe Session. instance->user_events_data_fd = user_events_data_fd; // With the user_events_data file, register tracepoints for each provider's tracepoint configurations - // ep_session_user_events_tracepoints_init (instance); + ep_session_user_events_tracepoints_init (instance); break; default: @@ -541,15 +659,40 @@ static void ep_session_disable_user_events (EventPipeSession *session) { +#if HAVE_LINUX_USER_EVENTS_H EP_ASSERT (session != NULL); ep_return_void_if_nok (session->session_type == EP_SESSION_TYPE_USEREVENTS); ep_requires_lock_held (); + // Remove all tracepoints. + EventPipeSessionProviderList *providers = ep_session_get_providers (session); + EP_ASSERT (providers != NULL); + for (dn_list_it_t it = dn_list_begin (ep_session_provider_list_get_providers (providers)); !dn_list_it_end (it); it = dn_list_it_next (it)) { + EventPipeSessionProvider *session_provider = *dn_list_it_data_t (it, EventPipeSessionProvider *); + EventPipeProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); + if (tracepoint_config->default_tracepoint.tracepoint_format != NULL) + ep_tracepoint_unreg (session->user_events_data_fd, &tracepoint_config->default_tracepoint); + + if (tracepoint_config->tracepoints != NULL) { + for (uint32_t i = 0; i < tracepoint_config->tracepoints->size; ++i) { + EventPipeTracepoint *tracepoint = *dn_vector_index_t (tracepoint_config->tracepoints, EventPipeTracepoint *, i); + EP_ASSERT (tracepoint != NULL); + + ep_tracepoint_unreg (session->user_events_data_fd, tracepoint); + } + dn_vector_clear (tracepoint_config->tracepoints); + } + } + if (session->user_events_data_fd != 0) { close (session->user_events_data_fd); session->user_events_data_fd = 0; } +#else + // Not Supported + return; +#endif // HAVE_LINUX_USER_EVENTS_H } bool diff --git a/src/native/eventpipe/ep-session.h b/src/native/eventpipe/ep-session.h index ad6187c7c71f6f..a21a906101bef8 100644 --- a/src/native/eventpipe/ep-session.h +++ b/src/native/eventpipe/ep-session.h @@ -13,6 +13,12 @@ #endif #include "ep-getter-setter.h" +#if HAVE_LINUX_USER_EVENTS_H +#include // DIAG_IOCSREG +#include // ep_tracepoint_reg +#include // close +#endif // HAVE_LINUX_USER_EVENTS_H + /* * EventPipeSession. */ diff --git a/src/native/eventpipe/ep-shared-config.h.in b/src/native/eventpipe/ep-shared-config.h.in index 526b45cbb7d99c..3d7c10c8f53ccc 100644 --- a/src/native/eventpipe/ep-shared-config.h.in +++ b/src/native/eventpipe/ep-shared-config.h.in @@ -2,6 +2,7 @@ #define EP_SHARED_CONFIG_H_INCLUDED #cmakedefine01 HAVE_SYS_SOCKET_H +#cmakedefine01 HAVE_LINUX_USER_EVENTS_H /* This platforms supports setting flags atomically when accepting connections. */ #cmakedefine01 HAVE_ACCEPT4 diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index 525a08ae04e226..e630f4a2b298a4 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -66,6 +66,14 @@ typedef struct _StreamWriterVtable StreamWriterVtable; #define EP_MAX_STACK_DEPTH 100 +/* + * User_Events constants + */ + +#define EP_TRACEPOINT_ENABLE_BIT 31 + +#define EP_TRACEPOINT_FORMAT_V1 "u8 version; u16 event_id; __rel_loc u8[] extension; __rel_loc u8[] payload; __rel_loc u8[] meta" + /* * EventPipe Enums. */ From d6648a2dbe824ce6f0569ac979a2d20383a39848 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Sat, 3 May 2025 02:36:40 +0000 Subject: [PATCH 10/32] [UserEvents] Write events to tracepoints --- src/native/eventpipe/configure.cmake | 5 + src/native/eventpipe/ep-session.c | 225 +++++++++++++++++++++ src/native/eventpipe/ep-session.h | 4 + src/native/eventpipe/ep-shared-config.h.in | 1 + src/native/eventpipe/ep-types-forward.h | 10 + 5 files changed, 245 insertions(+) diff --git a/src/native/eventpipe/configure.cmake b/src/native/eventpipe/configure.cmake index 48b0ac40ab598a..5409fe0f4928f7 100644 --- a/src/native/eventpipe/configure.cmake +++ b/src/native/eventpipe/configure.cmake @@ -22,6 +22,11 @@ check_include_files( HAVE_LINUX_USER_EVENTS_H ) +check_include_file( + "sys/uio.h" + HAVE_SYS_UIO_H +) + if (NOT DEFINED EP_GENERATED_HEADER_PATH) message(FATAL_ERROR "Required configuration EP_GENERATED_HEADER_PATH not set.") endif (NOT DEFINED EP_GENERATED_HEADER_PATH) diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 962c7ad83feb8e..1e6302d1bc49e9 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -51,6 +51,24 @@ static void ep_session_disable_user_events (EventPipeSession *session); +static +EventPipeTracepoint * +ep_session_get_tracepoint_for_event ( + EventPipeSession *session, + EventPipeEvent* ep_event); + +static +bool +ep_is_guid_empty(const uint8_t *guid); + +static +uint16_t +ep_tracepoint_construct_extension_buffer( + uint8_t *extension, + const uint8_t *activity_id, + const uint8_t *related_activity_id); + + /* * EventPipeSession. */ @@ -695,6 +713,202 @@ ep_session_disable_user_events (EventPipeSession *session) #endif // HAVE_LINUX_USER_EVENTS_H } +static +EventPipeTracepoint * +ep_session_get_tracepoint_for_event ( + EventPipeSession *session, + EventPipeEvent* ep_event) +{ + EP_ASSERT (session != NULL); + EP_ASSERT (ep_event != NULL); + EP_ASSERT (session->session_type == EP_SESSION_TYPE_USEREVENTS); + + EventPipeTracepoint *tracepoint = NULL; + + EventPipeProvider *provider = ep_event_get_provider (ep_event); + EventPipeSessionProviderList *session_provider_list = ep_session_get_providers (session); + EventPipeSessionProvider *session_provider = ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (session_provider_list), ep_provider_get_provider_name (provider)); + EventPipeProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); + + if (tracepoint_config->default_tracepoint.tracepoint_format != NULL) + tracepoint = &tracepoint_config->default_tracepoint; + + dn_umap_t *event_id_to_tracepoint_map = tracepoint_config->event_id_to_tracepoint_map; + if (event_id_to_tracepoint_map == NULL) + return tracepoint; + + uint32_t event_id = ep_event_get_event_id (ep_event); + dn_umap_it_t tracepoint_found = dn_umap_find (event_id_to_tracepoint_map, &event_id); + if (!dn_umap_it_end (tracepoint_found)) + tracepoint = dn_umap_it_value_t (tracepoint_found, EventPipeTracepoint *); + + return tracepoint; +} + +static +bool +ep_is_guid_empty(const uint8_t *guid) +{ + if (guid == NULL) + return true; + + for (size_t i = 0; i < EP_ACTIVITY_ID_SIZE; ++i) { + if (guid[i] != 0) + return false; + } + + return true; +} + +/* + * ep_tracepoint_construct_extension_buffer + * + * EventPipe Tracepoints include an extension buffer + * that encodes other optional information in the + * the NetTrace V6 LabelList format. + */ +static +uint16_t +ep_tracepoint_construct_extension_buffer( + uint8_t *extension, + const uint8_t *activity_id, + const uint8_t *related_activity_id) +{ + uint16_t offset = 0; + + bool activity_id_is_empty = ep_is_guid_empty (activity_id); + bool related_activity_id_is_empty = ep_is_guid_empty (related_activity_id); + + if (!activity_id_is_empty) { + extension[offset] = !related_activity_id_is_empty ? 0x81 : 0x01; + memcpy(extension + offset + 1, activity_id, EP_ACTIVITY_ID_SIZE); + offset += 1 + EP_ACTIVITY_ID_SIZE; + } + + if (!related_activity_id_is_empty) { + extension[offset] = 0x02; + memcpy(extension + offset + 1, related_activity_id, EP_ACTIVITY_ID_SIZE); + offset += 1 + EP_ACTIVITY_ID_SIZE; + } + + return offset; +} + +bool +ep_tracepoint_write ( + EventPipeSession *session, + ep_rt_thread_handle_t thread, + EventPipeEvent *ep_event, + EventPipeEventPayload *ep_event_payload, + const uint8_t *activity_id, + const uint8_t *related_activity_id, + ep_rt_thread_handle_t event_thread, + EventPipeStackContents *stack) +{ +#if HAVE_SYS_UIO_H + EP_ASSERT (session != NULL); + EP_ASSERT (ep_event != NULL); + + EventPipeTracepoint *tracepoint = ep_session_get_tracepoint_for_event (session, ep_event); + if (tracepoint == NULL) + return false; + + if (tracepoint->enabled == 0) + return false; + + uint8_t version = 0x01; // hardcoded for the first tracepoint format version + + uint32_t event_id = ep_event_get_event_id (ep_event); + uint16_t truncated_event_id = event_id & 0xFFFF; // For parity with EventSource, there shouldn't be any that need more than 16 bits. + + uint8_t extension[EP_MAX_EXTENSION_SIZE]; + memset(extension, 0, EP_MAX_EXTENSION_SIZE); + uint16_t extension_len = ep_tracepoint_construct_extension_buffer (extension, activity_id, related_activity_id); + EP_ASSERT(extension_len <= EP_MAX_EXTENSION_SIZE); + + uint32_t payload_len = ep_event_payload_get_size (ep_event_payload); + if ((payload_len & 0xFFFF0000) != 0) + return false; + + uint32_t metadata_len = ep_event_get_metadata_len (ep_event); + if ((metadata_len & 0xFFFF0000) != 0) + return false; + + uint32_t meta_rel_loc = metadata_len << 16 | ((extension_len + payload_len) & 0xFFFF); + if (((extension_len + payload_len) & 0xFFFF0000) != 0) + return false; + + uint32_t payload_rel_loc = payload_len << 16 | ((sizeof(meta_rel_loc) + extension_len) & 0xFFFF); + if (((sizeof(meta_rel_loc) + extension_len) & 0xFFFF0000) != 0) + return false; + + uint32_t extension_rel_loc = extension_len << 16 | ((sizeof(payload_rel_loc) + sizeof(meta_rel_loc)) & 0xFFFF); + if (((sizeof(payload_rel_loc) + sizeof(meta_rel_loc)) & 0xFFFF0000) != 0) + return false; + + struct iovec static_io[EP_DEFAULT_IOVEC_SIZE]; + struct iovec *io = static_io; + EventData *event_data = NULL; + uint32_t index = EP_TRACEPOINT_V1_PAYLOAD_INDEX; + // Since ep_event_payload can use multiple buffers, try to fit that in first + if (ep_event_payload_get_data (ep_event_payload) != NULL) { + io[index].iov_base = ep_event_payload_get_data (ep_event_payload); + io[index].iov_len = payload_len; + index++; + } else { + event_data = ep_event_payload->event_data; + + // In the unlikely event that an event_payload uses more EventData structs than can fit in the static iovec, + // dynamically allocate to fit all event_data buffers + if (ep_event_payload->event_data_len >= EP_DEFAULT_IOVEC_SIZE - EP_TRACEPOINT_V1_PAYLOAD_INDEX) { + io = (struct iovec *)malloc (sizeof (struct iovec) * (EP_TRACEPOINT_V1_PAYLOAD_INDEX + ep_event_payload->event_data_len)); + if (io == NULL) + return false; + } + + for (uint32_t i = 0; i < ep_event_payload->event_data_len; ++i) { + io[index + i].iov_base = (void *)ep_event_data_get_ptr (&event_data[i]); + io[index + i].iov_len = ep_event_data_get_size (&event_data[i]); + } + index += ep_event_payload->event_data_len; + } + + io[0].iov_base = &tracepoint->write_index; + io[0].iov_len = sizeof(tracepoint->write_index); + + io[1].iov_base = &version; + io[1].iov_len = sizeof(version); + + io[2].iov_base = &truncated_event_id; + io[2].iov_len = sizeof(truncated_event_id); + + io[3].iov_base = &extension_rel_loc; + io[3].iov_len = sizeof(extension_rel_loc); + + io[4].iov_base = &payload_rel_loc; + io[4].iov_len = sizeof(payload_rel_loc); + + io[5].iov_base = &meta_rel_loc; + io[5].iov_len = sizeof(meta_rel_loc); + + io[6].iov_base = extension; + io[6].iov_len = extension_len; + + io[index].iov_base = (void *)ep_event_get_metadata (ep_event); + io[index].iov_len = metadata_len; + + size_t bytes_written = writev(session->user_events_data_fd, (const struct iovec *)io, index + 1); + + if (io != static_io) + free (io); + + return bytes_written != -1; +#else // HAVE_SYS_UIO_H + // Not Supported + return false; +#endif // HAVE_SYS_UIO_H +} + bool ep_session_write_event ( EventPipeSession *session, @@ -732,6 +946,17 @@ ep_session_write_event ( stack == NULL ? NULL : (uintptr_t *)ep_stack_contents_get_pointer (stack), session->callback_additional_data); result = true; + } else if (session->session_type == EP_SESSION_TYPE_USEREVENTS) { + EP_ASSERT (session->user_events_data_fd != 0); + result = ep_tracepoint_write ( + session, + thread, + ep_event, + payload, + activity_id, + related_activity_id, + event_thread, + stack); } else { EP_ASSERT (session->buffer_manager != NULL); result = ep_buffer_manager_write_event ( diff --git a/src/native/eventpipe/ep-session.h b/src/native/eventpipe/ep-session.h index a21a906101bef8..0b85673ffe27c0 100644 --- a/src/native/eventpipe/ep-session.h +++ b/src/native/eventpipe/ep-session.h @@ -19,6 +19,10 @@ #include // close #endif // HAVE_LINUX_USER_EVENTS_H + +#if HAVE_SYS_UIO_H +#include // iovec +#endif // HAVE_SYS_UIO_H /* * EventPipeSession. */ diff --git a/src/native/eventpipe/ep-shared-config.h.in b/src/native/eventpipe/ep-shared-config.h.in index 3d7c10c8f53ccc..b894ba6b5e1a18 100644 --- a/src/native/eventpipe/ep-shared-config.h.in +++ b/src/native/eventpipe/ep-shared-config.h.in @@ -3,6 +3,7 @@ #cmakedefine01 HAVE_SYS_SOCKET_H #cmakedefine01 HAVE_LINUX_USER_EVENTS_H +#cmakedefine01 HAVE_SYS_UIO_H /* This platforms supports setting flags atomically when accepting connections. */ #cmakedefine01 HAVE_ACCEPT4 diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index e630f4a2b298a4..0fb55fe7ed02a7 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -74,6 +74,16 @@ typedef struct _StreamWriterVtable StreamWriterVtable; #define EP_TRACEPOINT_FORMAT_V1 "u8 version; u16 event_id; __rel_loc u8[] extension; __rel_loc u8[] payload; __rel_loc u8[] meta" +#define EP_MAX_EXTENSION_SIZE (2 * (EP_ACTIVITY_ID_SIZE + 1)) + +// Number of static iovec buffers for writing user_events +// EventPipeEventPayloads may contain a variable number of EventData structures, +// so statically allocate a reasonable number of iovecs to avoid dynamic allocations +#define EP_DEFAULT_IOVEC_SIZE 30 + +// Tracepoint V1 - write_index, version, truncated_event_id, extension_rel_loc, payload_rel_loc, meta_rel_loc, extension, payload, metadata +#define EP_TRACEPOINT_V1_PAYLOAD_INDEX 7 + /* * EventPipe Enums. */ From e20b17650b3a38b44d99c06becd54ea1f2bde03c Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Mon, 2 Jun 2025 16:27:02 +0000 Subject: [PATCH 11/32] Fixup CI build failures --- src/coreclr/vm/eventpipeadapter.h | 4 +- .../mono/eventpipe/test/ep-session-tests.c | 2 +- src/native/eventpipe/configure.cmake | 1 + src/native/eventpipe/ds-eventpipe-protocol.c | 14 +++-- src/native/eventpipe/ds-ipc-pal-socket.c | 2 +- src/native/eventpipe/ep-event-source.c | 2 +- src/native/eventpipe/ep-session-provider.c | 25 +++------ src/native/eventpipe/ep-session-provider.h | 7 --- src/native/eventpipe/ep-session.c | 56 ++++++++++++------- 9 files changed, 60 insertions(+), 53 deletions(-) diff --git a/src/coreclr/vm/eventpipeadapter.h b/src/coreclr/vm/eventpipeadapter.h index f344d206629c12..2b261d9162d561 100644 --- a/src/coreclr/vm/eventpipeadapter.h +++ b/src/coreclr/vm/eventpipeadapter.h @@ -385,7 +385,9 @@ class EventPipeAdapter final ep_provider_config_get_provider_name (&config[0]), ep_provider_config_get_keywords (&config[0]), (EventPipeEventLevel)ep_provider_config_get_logging_level (&config[0]), - ep_provider_config_get_filter_data (&config[0])); + ep_provider_config_get_filter_data (&config[0]), + NULL, + NULL); } static HRESULT GetProviderName(const EventPipeProvider *provider, ULONG numNameChars, ULONG *numNameCharsOut, LPWSTR name) diff --git a/src/mono/mono/eventpipe/test/ep-session-tests.c b/src/mono/mono/eventpipe/test/ep-session-tests.c index 0c2506eab62e0e..6ce5bf1815b939 100644 --- a/src/mono/mono/eventpipe/test/ep-session-tests.c +++ b/src/mono/mono/eventpipe/test/ep-session-tests.c @@ -111,7 +111,7 @@ test_add_session_providers (void) test_location = 3; - test_session_provider = ep_session_provider_alloc (TEST_PROVIDER_NAME, 1, EP_EVENT_LEVEL_LOGALWAYS, ""); + test_session_provider = ep_session_provider_alloc (TEST_PROVIDER_NAME, 1, EP_EVENT_LEVEL_LOGALWAYS, "", NULL, NULL); ep_raise_error_if_nok (test_session_provider != NULL); test_location = 4; diff --git a/src/native/eventpipe/configure.cmake b/src/native/eventpipe/configure.cmake index 5409fe0f4928f7..8e5336d32ed8aa 100644 --- a/src/native/eventpipe/configure.cmake +++ b/src/native/eventpipe/configure.cmake @@ -1,5 +1,6 @@ include(CheckSymbolExists) include(CheckIncludeFile) +include(CheckIncludeFiles) check_include_file( sys/socket.h diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index d5413d442ef469..6cb953db27005e 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -230,6 +230,14 @@ event_id_hashset_key_dispose_func (void *data) ep_rt_object_free ((uint32_t *)data); } +static +void +DN_CALLBACK_CALLTYPE +ep_provider_config_free_func (void *provider_config) +{ + ep_rt_object_free ((EventPipeProviderConfiguration *)provider_config); +} + /* * eventpipe_collect_tracing_command_try_parse_event_filter * @@ -549,7 +557,6 @@ eventpipe_collect_tracing_command_try_parse_config ( ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &count_configs)); ep_raise_error_if_nok (count_configs <= max_count_configs); params.capacity = count_configs; - // Free func for the EventPipeProviderConfiguration? *result = dn_vector_custom_alloc_t (¶ms, EventPipeProviderConfiguration); ep_raise_error_if_nok (*result); @@ -589,11 +596,10 @@ eventpipe_collect_tracing_command_try_parse_config ( ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); ep_event_filter_free (ep_provider_config_get_event_filter (&config)); ep_tracepoint_config_free (ep_provider_config_get_tracepoint_config (&config)); - ep_rt_object_free (&config); } DN_VECTOR_FOREACH_END; } - dn_vector_free (*result); + dn_vector_custom_free (*result, ep_provider_config_free_func); *result = NULL; ep_exit_error_handler (); } @@ -1020,8 +1026,8 @@ ds_eventpipe_protocol_helper_handle_ipc_message ( ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); ep_event_filter_free (ep_provider_config_get_event_filter (&config)); ep_tracepoint_config_free (ep_provider_config_get_tracepoint_config (&config)); - ep_rt_object_free (&config); } DN_VECTOR_FOREACH_END; + dn_vector_custom_free (payload->provider_configs, ep_provider_config_free_func); } } break; diff --git a/src/native/eventpipe/ds-ipc-pal-socket.c b/src/native/eventpipe/ds-ipc-pal-socket.c index 80c48687dd21d4..90ab23bf6b0ffd 100644 --- a/src/native/eventpipe/ds-ipc-pal-socket.c +++ b/src/native/eventpipe/ds-ipc-pal-socket.c @@ -1561,7 +1561,7 @@ ds_ipc_stream_read_fd ( DiagnosticsIpcStream *ipc_stream, uint32_t *data_fd) { -#if HAVE_SYS_SOCKET_H +#if HAVE_SYS_SOCKET_H && defined(SOL_SOCKET) && defined(SCM_RIGHTS) && defined(CMSG_SPACE) && defined(CMSG_FIRSTHDR) && defined(CMSG_DATA) EP_ASSERT (ipc_stream != NULL); EP_ASSERT (data_fd != NULL); diff --git a/src/native/eventpipe/ep-event-source.c b/src/native/eventpipe/ep-event-source.c index 982f75a3c531b8..7d1f8f57e4ff50 100644 --- a/src/native/eventpipe/ep-event-source.c +++ b/src/native/eventpipe/ep-event-source.c @@ -202,7 +202,7 @@ ep_event_source_enable ( ep_requires_lock_held (); bool result = true; - EventPipeSessionProvider *session_provider = ep_session_provider_alloc (event_source->provider_name, (uint64_t)-1, EP_EVENT_LEVEL_LOGALWAYS, NULL); + EventPipeSessionProvider *session_provider = ep_session_provider_alloc (event_source->provider_name, (uint64_t)-1, EP_EVENT_LEVEL_LOGALWAYS, NULL, NULL, NULL); if (session_provider != NULL) result = ep_session_add_session_provider (session, session_provider); return result; diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index 5d51bf6355a272..05ebc0c65a699f 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -23,6 +23,12 @@ session_provider_compare_name_func ( const void *a, const void *b); +static +bool +ep_event_filter_allows_event_id ( + const EventPipeProviderEventFilter *event_filter, + uint32_t event_id); + /* * EventPipeSessionProvider. */ @@ -45,22 +51,6 @@ session_provider_compare_name_func ( return (a) ? !ep_rt_utf8_string_compare (ep_session_provider_get_provider_name ((EventPipeSessionProvider *)a), (const ep_char8_t *)b) : false; } -EventPipeSessionProvider * -ep_session_provider_alloc ( - const ep_char8_t *provider_name, - uint64_t keywords, - EventPipeEventLevel logging_level, - const ep_char8_t *filter_data) -{ - return ep_session_provider_alloc ( - provider_name, - keywords, - logging_level, - filter_data, - NULL, - NULL); -} - EventPipeSessionProvider * ep_session_provider_alloc ( const ep_char8_t *provider_name, @@ -109,6 +99,7 @@ ep_session_provider_free (EventPipeSessionProvider * session_provider) ep_rt_object_free (session_provider); } +static bool ep_event_filter_allows_event_id ( const EventPipeProviderEventFilter *event_filter, @@ -174,7 +165,7 @@ ep_session_provider_list_alloc ( if ((ep_rt_utf8_string_compare(ep_provider_get_wildcard_name_utf8 (), ep_provider_config_get_provider_name (config)) == 0) && (ep_provider_config_get_keywords (config) == 0xFFFFFFFFFFFFFFFF) && ((ep_provider_config_get_logging_level (config) == EP_EVENT_LEVEL_VERBOSE) && (instance->catch_all_provider == NULL))) { - instance->catch_all_provider = ep_session_provider_alloc (NULL, 0xFFFFFFFFFFFFFFFF, EP_EVENT_LEVEL_VERBOSE, NULL ); + instance->catch_all_provider = ep_session_provider_alloc (NULL, 0xFFFFFFFFFFFFFFFF, EP_EVENT_LEVEL_VERBOSE, NULL, NULL, NULL); ep_raise_error_if_nok (instance->catch_all_provider != NULL); } else { diff --git a/src/native/eventpipe/ep-session-provider.h b/src/native/eventpipe/ep-session-provider.h index 46fda0e6b547a7..44b6af81759c7f 100644 --- a/src/native/eventpipe/ep-session-provider.h +++ b/src/native/eventpipe/ep-session-provider.h @@ -41,13 +41,6 @@ EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, const ep_char8_t EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, EventPipeProviderEventFilter *, event_filter) EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, EventPipeProviderTracepointConfiguration *, tracepoint_config) -EventPipeSessionProvider * -ep_session_provider_alloc ( - const ep_char8_t *provider_name, - uint64_t keywords, - EventPipeEventLevel logging_level, - const ep_char8_t *filter_data); - EventPipeSessionProvider * ep_session_provider_alloc ( const ep_char8_t *provider_name, diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 1e6302d1bc49e9..19716a935dae5a 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -64,10 +64,21 @@ ep_is_guid_empty(const uint8_t *guid); static uint16_t ep_tracepoint_construct_extension_buffer( - uint8_t *extension, - const uint8_t *activity_id, - const uint8_t *related_activity_id); + uint8_t *extension, + const uint8_t *activity_id, + const uint8_t *related_activity_id); +static +bool +ep_tracepoint_write ( + EventPipeSession *session, + ep_rt_thread_handle_t thread, + EventPipeEvent *ep_event, + EventPipeEventPayload *ep_event_payload, + const uint8_t *activity_id, + const uint8_t *related_activity_id, + ep_rt_thread_handle_t event_thread, + EventPipeStackContents *stack); /* * EventPipeSession. @@ -516,7 +527,9 @@ ep_session_enable_rundown (EventPipeSession *session) ep_provider_config_get_provider_name (&rundown_provider), ep_provider_config_get_keywords (&rundown_provider), ep_provider_config_get_logging_level (&rundown_provider), - ep_provider_config_get_filter_data (&rundown_provider)); + ep_provider_config_get_filter_data (&rundown_provider), + NULL, + NULL); ep_raise_error_if_nok (ep_session_add_session_provider (session, session_provider)); @@ -749,15 +762,15 @@ static bool ep_is_guid_empty(const uint8_t *guid) { - if (guid == NULL) + if (guid == NULL) return true; for (size_t i = 0; i < EP_ACTIVITY_ID_SIZE; ++i) { - if (guid[i] != 0) + if (guid[i] != 0) return false; - } + } - return true; + return true; } /* @@ -770,30 +783,31 @@ ep_is_guid_empty(const uint8_t *guid) static uint16_t ep_tracepoint_construct_extension_buffer( - uint8_t *extension, - const uint8_t *activity_id, - const uint8_t *related_activity_id) + uint8_t *extension, + const uint8_t *activity_id, + const uint8_t *related_activity_id) { - uint16_t offset = 0; + uint16_t offset = 0; bool activity_id_is_empty = ep_is_guid_empty (activity_id); bool related_activity_id_is_empty = ep_is_guid_empty (related_activity_id); if (!activity_id_is_empty) { - extension[offset] = !related_activity_id_is_empty ? 0x81 : 0x01; - memcpy(extension + offset + 1, activity_id, EP_ACTIVITY_ID_SIZE); - offset += 1 + EP_ACTIVITY_ID_SIZE; - } + extension[offset] = !related_activity_id_is_empty ? 0x81 : 0x01; + memcpy(extension + offset + 1, activity_id, EP_ACTIVITY_ID_SIZE); + offset += 1 + EP_ACTIVITY_ID_SIZE; + } - if (!related_activity_id_is_empty) { - extension[offset] = 0x02; - memcpy(extension + offset + 1, related_activity_id, EP_ACTIVITY_ID_SIZE); - offset += 1 + EP_ACTIVITY_ID_SIZE; - } + if (!related_activity_id_is_empty) { + extension[offset] = 0x02; + memcpy(extension + offset + 1, related_activity_id, EP_ACTIVITY_ID_SIZE); + offset += 1 + EP_ACTIVITY_ID_SIZE; + } return offset; } +static bool ep_tracepoint_write ( EventPipeSession *session, From 64632d3514a56cfd3e4153cca6f4b7ba8717725e Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Thu, 5 Jun 2025 15:09:28 +0000 Subject: [PATCH 12/32] Cleanup missed CI build failures --- src/native/eventpipe/ds-eventpipe-protocol.c | 6 +++--- src/native/eventpipe/ep-session.c | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 6cb953db27005e..02d3e314588357 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -280,9 +280,9 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( event_id = ep_rt_object_alloc (uint32_t); ep_raise_error_if_nok (event_id != NULL); ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, event_id)); - dn_umap_result_t result = dn_umap_insert (event_filter->event_ids, event_id, NULL); + dn_umap_result_t insert_result = dn_umap_insert (event_filter->event_ids, event_id, NULL); event_id = NULL; // Ownership transferred to the hashset. - ep_raise_error_if_nok (result.result); + ep_raise_error_if_nok (insert_result.result); } } else { event_filter->event_ids = NULL; @@ -412,7 +412,7 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( } } - ep_raise_error_if_nok (tracepoint_config->default_tracepoint.tracepoint_format != NULL || tracepoint_config->tracepoints != NULL); + ep_raise_error_if_nok (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0' || tracepoint_config->tracepoints != NULL); result = true; diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 19716a935dae5a..dc48f8675181bf 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -281,9 +281,9 @@ ep_session_user_events_tracepoints_init ( EventPipeProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); EP_ASSERT (tracepoint_config != NULL); - EP_ASSERT (tracepoint_config->default_tracepoint.tracepoint_format != NULL || tracepoint_config->tracepoints != NULL); + EP_ASSERT (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0' || tracepoint_config->tracepoints != NULL); - if (tracepoint_config->default_tracepoint.tracepoint_format != NULL) { + if (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0') { ep_raise_error_if_nok (ep_tracepoint_reg (session->user_events_data_fd, &tracepoint_config->default_tracepoint)); } @@ -702,7 +702,7 @@ ep_session_disable_user_events (EventPipeSession *session) for (dn_list_it_t it = dn_list_begin (ep_session_provider_list_get_providers (providers)); !dn_list_it_end (it); it = dn_list_it_next (it)) { EventPipeSessionProvider *session_provider = *dn_list_it_data_t (it, EventPipeSessionProvider *); EventPipeProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); - if (tracepoint_config->default_tracepoint.tracepoint_format != NULL) + if (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0') ep_tracepoint_unreg (session->user_events_data_fd, &tracepoint_config->default_tracepoint); if (tracepoint_config->tracepoints != NULL) { @@ -743,7 +743,7 @@ ep_session_get_tracepoint_for_event ( EventPipeSessionProvider *session_provider = ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (session_provider_list), ep_provider_get_provider_name (provider)); EventPipeProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); - if (tracepoint_config->default_tracepoint.tracepoint_format != NULL) + if (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0') tracepoint = &tracepoint_config->default_tracepoint; dn_umap_t *event_id_to_tracepoint_map = tracepoint_config->event_id_to_tracepoint_map; From 2d9b4d9eb3007184b276a5690fe49292325c1efb Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Thu, 5 Jun 2025 15:11:12 +0000 Subject: [PATCH 13/32] Address feedback Fix parameter order Use umap_ptr_uint32 macros for EventFilter Remove tracepoint_name const qualifier Prevent buffer overflow in tracepoint_format copying Skip duplicate tracepoint config fini Null out tracepoint after transferring ownership Use dn_vector_ptr_t for provider configurations Wrap entire functions under macro checks Use int for file descriptor Fix formatting Add checks for ep_session_disable session specific logic Use dn_vector_ptr for the tracepoints sets Use switch case for event writing Scope tracepoint registration to sessions Remove ep prefix from static functions Move includes to source Define max tracepoint format length --- .../eventpipe/test/ep-buffer-manager-tests.c | 3 +- .../mono/eventpipe/test/ep-buffer-tests.c | 3 +- .../mono/eventpipe/test/ep-session-tests.c | 9 +- .../mono/eventpipe/test/ep-thread-tests.c | 3 +- src/native/eventpipe/configure.cmake | 19 +- src/native/eventpipe/ds-eventpipe-protocol.c | 135 ++++------- src/native/eventpipe/ds-eventpipe-protocol.h | 2 +- src/native/eventpipe/ds-ipc-pal-namedpipe.c | 2 +- src/native/eventpipe/ds-ipc-pal-socket.c | 41 ++-- src/native/eventpipe/ds-ipc-pal-websocket.c | 2 +- src/native/eventpipe/ds-ipc-pal.h | 2 +- src/native/eventpipe/ep-session-provider.c | 8 +- src/native/eventpipe/ep-session.c | 211 +++++++++++------- src/native/eventpipe/ep-session.h | 14 +- src/native/eventpipe/ep-shared-config.h.in | 5 +- src/native/eventpipe/ep-types-forward.h | 2 + src/native/eventpipe/ep-types.h | 4 +- src/native/eventpipe/ep.c | 12 +- src/native/eventpipe/ep.h | 4 +- 19 files changed, 248 insertions(+), 233 deletions(-) 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 dcad1f2f88353c..ad2c671100cb7e 100644 --- a/src/mono/mono/eventpipe/test/ep-buffer-manager-tests.c +++ b/src/mono/mono/eventpipe/test/ep-buffer-manager-tests.c @@ -103,7 +103,8 @@ buffer_manager_init ( current_provider_config, 1, NULL, - NULL); + NULL, + 0); EP_LOCK_EXIT (section1) ep_raise_error_if_nok (*session != NULL); diff --git a/src/mono/mono/eventpipe/test/ep-buffer-tests.c b/src/mono/mono/eventpipe/test/ep-buffer-tests.c index d1eb3eb56f5d37..87aca21c2b8468 100644 --- a/src/mono/mono/eventpipe/test/ep-buffer-tests.c +++ b/src/mono/mono/eventpipe/test/ep-buffer-tests.c @@ -91,7 +91,8 @@ load_buffer_with_events_init ( current_provider_config, 1, NULL, - NULL); + NULL, + 0); EP_LOCK_EXIT (section1) ep_raise_error_if_nok (*session != NULL); diff --git a/src/mono/mono/eventpipe/test/ep-session-tests.c b/src/mono/mono/eventpipe/test/ep-session-tests.c index 6ce5bf1815b939..a5f49a37fa0546 100644 --- a/src/mono/mono/eventpipe/test/ep-session-tests.c +++ b/src/mono/mono/eventpipe/test/ep-session-tests.c @@ -51,7 +51,8 @@ test_create_delete_session (void) current_provider_config, 1, NULL, - NULL); + NULL, + 0); EP_LOCK_EXIT (section1) ep_raise_error_if_nok (test_session != NULL); @@ -93,7 +94,8 @@ test_add_session_providers (void) current_provider_config, 1, NULL, - NULL); + NULL, + 0); ep_raise_error_if_nok_holding_lock (test_session != NULL, section1); @@ -176,7 +178,8 @@ test_session_special_get_set (void) current_provider_config, 1, NULL, - NULL); + NULL, + 0); EP_LOCK_EXIT (section1) ep_raise_error_if_nok (test_session != NULL); diff --git a/src/mono/mono/eventpipe/test/ep-thread-tests.c b/src/mono/mono/eventpipe/test/ep-thread-tests.c index 77342b7633f250..c5acc665a1c5ac 100644 --- a/src/mono/mono/eventpipe/test/ep-thread-tests.c +++ b/src/mono/mono/eventpipe/test/ep-thread-tests.c @@ -399,7 +399,8 @@ test_thread_session_state (void) provider_config, 1, NULL, - NULL); + NULL, + 0); EP_LOCK_EXIT (section1) if (!session) { diff --git a/src/native/eventpipe/configure.cmake b/src/native/eventpipe/configure.cmake index 8e5336d32ed8aa..8bb378efd3f20d 100644 --- a/src/native/eventpipe/configure.cmake +++ b/src/native/eventpipe/configure.cmake @@ -18,16 +18,31 @@ if (CLR_CMAKE_HOST_IOS OR CLR_CMAKE_HOST_TVOS OR CLR_CMAKE_HOST_ANDROID) set(FEATURE_PERFTRACING_DISABLE_DEFAULT_LISTEN_PORT 1) endif() -check_include_files( - "linux/user_events.h;sys/ioctl.h;unistd.h" +check_include_file( + linux/user_events.h HAVE_LINUX_USER_EVENTS_H ) +check_include_file( + sys/ioctl.h + HAVE_SYS_IOCTL_H +) + +check_include_file( + unistd.h + HAVE_UNISTD_H +) + check_include_file( "sys/uio.h" HAVE_SYS_UIO_H ) +check_include_file( + errno.h + HAVE_ERRNO_H +) + if (NOT DEFINED EP_GENERATED_HEADER_PATH) message(FATAL_ERROR "Required configuration EP_GENERATED_HEADER_PATH not set.") endif (NOT DEFINED EP_GENERATED_HEADER_PATH) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 02d3e314588357..dcfa0946adffc5 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -87,8 +87,8 @@ bool eventpipe_collect_tracing_command_try_parse_config ( uint8_t **buffer, uint32_t *buffer_len, - dn_vector_t **result, - EventPipeProviderOptionalFieldFlags optional_field_flags); + EventPipeProviderOptionalFieldFlags optional_field_flags, + dn_vector_ptr_t **result); static uint8_t * @@ -222,22 +222,6 @@ eventpipe_collect_tracing_command_try_parse_stackwalk_requested ( return ds_ipc_message_try_parse_bool (buffer, buffer_len, stackwalk_requested); } -static -void -DN_CALLBACK_CALLTYPE -event_id_hashset_key_dispose_func (void *data) -{ - ep_rt_object_free ((uint32_t *)data); -} - -static -void -DN_CALLBACK_CALLTYPE -ep_provider_config_free_func (void *provider_config) -{ - ep_rt_object_free ((EventPipeProviderConfiguration *)provider_config); -} - /* * eventpipe_collect_tracing_command_try_parse_event_filter * @@ -263,25 +247,18 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( bool result = false; uint32_t event_id_array_len = 0; - uint32_t *event_id = NULL; ep_raise_error_if_nok (ds_ipc_message_try_parse_bool (buffer, buffer_len, &event_filter->enable)); ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &event_id_array_len)); if (event_id_array_len > 0) { - dn_umap_custom_alloc_params_t event_id_hashset_params = {0, }; - event_id_hashset_params.hash_func = dn_int_hash; - event_id_hashset_params.equal_func = dn_int_equal; - event_id_hashset_params.key_dispose_func = event_id_hashset_key_dispose_func; - event_filter->event_ids = dn_umap_custom_alloc (&event_id_hashset_params); + event_filter->event_ids = dn_umap_alloc (); ep_raise_error_if_nok (event_filter->event_ids != NULL); for (uint32_t i = 0; i < event_id_array_len; ++i) { - event_id = ep_rt_object_alloc (uint32_t); - ep_raise_error_if_nok (event_id != NULL); - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, event_id)); - dn_umap_result_t insert_result = dn_umap_insert (event_filter->event_ids, event_id, NULL); - event_id = NULL; // Ownership transferred to the hashset. + uint32_t event_id; + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &event_id)); + dn_umap_result_t insert_result = dn_umap_ptr_uint32_insert (event_filter->event_ids, (void *)(uintptr_t)event_id, 0); ep_raise_error_if_nok (insert_result.result); } } else { @@ -294,11 +271,6 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( return result; ep_on_error: - if (event_id != NULL) { - ep_rt_object_free (event_id); - event_id = NULL; - } - ep_event_filter_fini (event_filter); ep_exit_error_handler (); @@ -334,13 +306,12 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( bool result = false; EventPipeTracepoint *tracepoint = NULL; - const ep_char8_t *tracepoint_name = NULL; + ep_char8_t *tracepoint_name = NULL; size_t default_tracepoint_format_len = 0; uint8_t *tracepoint_name_byte_array = NULL; uint32_t tracepoint_name_byte_array_len = 0; uint32_t tracepoint_set_array_len = 0; - uint32_t *event_id = NULL; tracepoint_config->default_tracepoint.tracepoint_format[0] = '\0'; // Initialize to empty string. tracepoint_config->tracepoints = NULL; @@ -354,9 +325,9 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (tracepoint_name)); ep_rt_byte_array_free (tracepoint_name_byte_array); tracepoint_name_byte_array = NULL; - + default_tracepoint_format_len = strlen(tracepoint_name) + strlen(EP_TRACEPOINT_FORMAT_V1) + 2; // +2 for space and null terminator - int32_t res = snprintf(tracepoint_config->default_tracepoint.tracepoint_format, default_tracepoint_format_len, "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); + int32_t res = snprintf(tracepoint_config->default_tracepoint.tracepoint_format, sizeof(tracepoint_config->default_tracepoint.tracepoint_format), "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); ep_raise_error_if_nok (res >= 0 && (size_t)res < default_tracepoint_format_len); ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); tracepoint_name = NULL; @@ -365,21 +336,16 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &tracepoint_set_array_len)); if (tracepoint_set_array_len > 0) { - dn_vector_custom_alloc_params_t tracepoint_set_array_params = {0, }; + dn_vector_ptr_custom_alloc_params_t tracepoint_set_array_params = {0, }; tracepoint_set_array_params.capacity = tracepoint_set_array_len; - // free func to free the EventPipeTracepoint? - tracepoint_config->tracepoints = dn_vector_custom_alloc_t (&tracepoint_set_array_params, EventPipeTracepoint); + tracepoint_config->tracepoints = dn_vector_ptr_custom_alloc (&tracepoint_set_array_params); ep_raise_error_if_nok (tracepoint_config->tracepoints != NULL); - dn_umap_custom_alloc_params_t params = {0, }; - params.hash_func = dn_int_hash; - params.equal_func = dn_int_equal; - params.key_dispose_func = event_id_hashset_key_dispose_func; - tracepoint_config->event_id_to_tracepoint_map = dn_umap_custom_alloc (¶ms); + tracepoint_config->event_id_to_tracepoint_map = dn_umap_alloc (); ep_raise_error_if_nok (tracepoint_config->event_id_to_tracepoint_map != NULL); for (uint32_t i = 0; i < tracepoint_set_array_len; ++i) { - tracepoint = ep_rt_object_alloc (EventPipeTracepoint); // Onwership will be transferred to the tracepoint_config's tracepoint vector. + tracepoint = ep_rt_object_alloc (EventPipeTracepoint); // Ownership will be transferred to the tracepoint_config's tracepoint vector. ep_raise_error_if_nok (tracepoint != NULL); ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &tracepoint_name_byte_array, &tracepoint_name_byte_array_len)); @@ -391,7 +357,7 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( tracepoint_name_byte_array = NULL; default_tracepoint_format_len = strlen(tracepoint_name) + strlen(EP_TRACEPOINT_FORMAT_V1) + 2; // +2 for space and null terminator - int32_t res = snprintf(tracepoint->tracepoint_format, default_tracepoint_format_len, "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); + int32_t res = snprintf(tracepoint->tracepoint_format, sizeof(tracepoint->tracepoint_format), "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); ep_raise_error_if_nok (res >= 0 && (size_t)res < default_tracepoint_format_len); ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); tracepoint_name = NULL; @@ -401,13 +367,14 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( ep_raise_error_if_nok (event_id_array_len > 0); for (uint32_t j = 0; j < event_id_array_len; ++j) { - event_id = ep_rt_object_alloc (uint32_t); // Ownership will be transferred to the tracepoint_config's event_id_to_tracepoint_map. - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, event_id)); - dn_umap_insert (tracepoint_config->event_id_to_tracepoint_map, event_id, tracepoint); - // Ownership of event_id is transferred to the map. + uint32_t event_id; + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &event_id)); + dn_umap_result_t insert_result = dn_umap_insert (tracepoint_config->event_id_to_tracepoint_map, (void *)(uintptr_t)event_id, tracepoint); + ep_raise_error_if_nok (insert_result.result); } - ep_raise_error_if_nok (dn_vector_push_back (tracepoint_config->tracepoints, tracepoint)); + ep_raise_error_if_nok (dn_vector_ptr_push_back (tracepoint_config->tracepoints, tracepoint)); + tracepoint = NULL; // Ownership of tracepoint is transferred to the tracepoint_config's tracepoint vector. } } @@ -420,14 +387,9 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( return result; ep_on_error: - ep_rt_object_free (event_id); - event_id = NULL; - ep_rt_object_free (tracepoint); tracepoint = NULL; - ep_tracepoint_config_fini (tracepoint_config); - ep_rt_byte_array_free (tracepoint_name_byte_array); tracepoint_name_byte_array = NULL; @@ -539,8 +501,8 @@ bool eventpipe_collect_tracing_command_try_parse_config ( uint8_t **buffer, uint32_t *buffer_len, - dn_vector_t **result, - EventPipeProviderOptionalFieldFlags optional_field_flags) + EventPipeProviderOptionalFieldFlags optional_field_flags, + dn_vector_ptr_t **result) { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); @@ -550,14 +512,14 @@ eventpipe_collect_tracing_command_try_parse_config ( // This should be larger than any reasonable client request. const uint32_t max_count_configs = 1000; uint32_t count_configs = 0; - dn_vector_custom_alloc_params_t params = {0, }; + dn_vector_ptr_custom_alloc_params_t params = {0, }; EventPipeProviderConfiguration *provider_config = NULL; ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &count_configs)); ep_raise_error_if_nok (count_configs <= max_count_configs); params.capacity = count_configs; - *result = dn_vector_custom_alloc_t (¶ms, EventPipeProviderConfiguration); + *result = dn_vector_ptr_custom_alloc (¶ms); ep_raise_error_if_nok (*result); for (uint32_t i = 0; i < count_configs; ++i) { @@ -569,7 +531,7 @@ eventpipe_collect_tracing_command_try_parse_config ( optional_field_flags, provider_config)); - ep_raise_error_if_nok (dn_vector_push_back (*result, *provider_config)); + ep_raise_error_if_nok (dn_vector_ptr_push_back (*result, provider_config)); provider_config = NULL; // Ownership transferred. } @@ -579,7 +541,6 @@ eventpipe_collect_tracing_command_try_parse_config ( ep_on_error: count_configs = 0; - // Until ep_provider_config_fini/free is implemented, we need to manually free the provider_config. if (provider_config != NULL) { ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (provider_config)); ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (provider_config)); @@ -591,16 +552,12 @@ eventpipe_collect_tracing_command_try_parse_config ( // Until ep_provider_config_fini/free is implemented, we need to manually free the provider_config. if (*result != NULL) { - DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, *result) { - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); - ep_event_filter_free (ep_provider_config_get_event_filter (&config)); - ep_tracepoint_config_free (ep_provider_config_get_tracepoint_config (&config)); + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeProviderConfiguration *, config, *result) { + ep_event_filter_free (ep_provider_config_get_event_filter (config)); + ep_tracepoint_config_free (ep_provider_config_get_tracepoint_config (config)); } DN_VECTOR_FOREACH_END; } - dn_vector_custom_free (*result, ep_provider_config_free_func); - *result = NULL; ep_exit_error_handler (); } @@ -616,9 +573,9 @@ ds_eventpipe_collect_tracing_command_payload_free (EventPipeCollectTracingComman ep_return_void_if_nok (payload != NULL); ep_rt_byte_array_free (payload->incoming_buffer); - DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) { - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeProviderConfiguration *, config, payload->provider_configs) { + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (config)); + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (config)); // What about the EventPipeProviderConfiguration allocated in eventpipe_collect_tracing_command_try_parse_config } DN_VECTOR_FOREACH_END; @@ -647,7 +604,7 @@ eventpipe_collect_tracing_command_try_parse_payload ( if (!eventpipe_collect_tracing_command_try_parse_circular_buffer_size (&buffer_cursor, &buffer_cursor_len, &instance->circular_buffer_size_in_mb ) || !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || - !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs, EP_PROVIDER_OPTFIELD_NONE)) + !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, EP_PROVIDER_OPTFIELD_NONE, &instance->provider_configs)) ep_raise_error (); instance->rundown_requested = true; instance->stackwalk_requested = true; @@ -682,7 +639,7 @@ eventpipe_collect_tracing2_command_try_parse_payload ( if (!eventpipe_collect_tracing_command_try_parse_circular_buffer_size (&buffer_cursor, &buffer_cursor_len, &instance->circular_buffer_size_in_mb ) || !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || !eventpipe_collect_tracing_command_try_parse_rundown_requested (&buffer_cursor, &buffer_cursor_len, &instance->rundown_requested) || - !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs, EP_PROVIDER_OPTFIELD_NONE)) + !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, EP_PROVIDER_OPTFIELD_NONE, &instance->provider_configs)) ep_raise_error (); instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; @@ -719,7 +676,7 @@ eventpipe_collect_tracing3_command_try_parse_payload ( !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || !eventpipe_collect_tracing_command_try_parse_rundown_requested (&buffer_cursor, &buffer_cursor_len, &instance->rundown_requested) || !eventpipe_collect_tracing_command_try_parse_stackwalk_requested (&buffer_cursor, &buffer_cursor_len, &instance->stackwalk_requested) || - !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs, EP_PROVIDER_OPTFIELD_NONE)) + !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, EP_PROVIDER_OPTFIELD_NONE, &instance->provider_configs)) ep_raise_error (); instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; @@ -754,7 +711,7 @@ eventpipe_collect_tracing4_command_try_parse_payload ( !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || !eventpipe_collect_tracing_command_try_parse_rundown_keyword (&buffer_cursor, &buffer_cursor_len, &instance->rundown_keyword) || !eventpipe_collect_tracing_command_try_parse_stackwalk_requested (&buffer_cursor, &buffer_cursor_len, &instance->stackwalk_requested) || - !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs, EP_PROVIDER_OPTFIELD_NONE)) + !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, EP_PROVIDER_OPTFIELD_NONE, &instance->provider_configs)) ep_raise_error (); instance->rundown_requested = instance->rundown_keyword != 0; @@ -816,7 +773,7 @@ eventpipe_collect_tracing5_command_try_parse_payload ( if (instance->session_type == EP_IPC_SESSION_TYPE_USEREVENTS) optional_field_flags = (EventPipeProviderOptionalFieldFlags)(optional_field_flags | EP_PROVIDER_OPTFIELD_TRACEPOINT_CONFIG); - ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, &instance->provider_configs, optional_field_flags)); + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, optional_field_flags, &instance->provider_configs)); instance->rundown_requested = instance->rundown_keyword != 0; @@ -918,7 +875,7 @@ eventpipe_protocol_helper_collect_tracing ( return false; } - uint32_t user_events_data_fd = -1; + int user_events_data_fd = 0; if (payload->session_type == EP_IPC_SESSION_TYPE_USEREVENTS) { if (!ds_ipc_stream_read_fd (stream, &user_events_data_fd)) { ds_ipc_message_send_error (stream, DS_IPC_E_BAD_ENCODING); @@ -931,8 +888,8 @@ eventpipe_protocol_helper_collect_tracing ( &options, NULL, payload->circular_buffer_size_in_mb, - dn_vector_data_t (payload->provider_configs, EventPipeProviderConfiguration), - dn_vector_size (payload->provider_configs), + *(EventPipeProviderConfiguration **)dn_vector_ptr_data (payload->provider_configs), + dn_vector_ptr_size (payload->provider_configs), payload->session_type == EP_IPC_SESSION_TYPE_USEREVENTS ? EP_SESSION_TYPE_USEREVENTS : EP_SESSION_TYPE_IPCSTREAM, payload->serialization_format, payload->rundown_keyword, @@ -1016,20 +973,6 @@ ds_eventpipe_protocol_helper_handle_ipc_message ( case EP_COMMANDID_COLLECT_TRACING_5: payload = (EventPipeCollectTracingCommandPayload *)ds_ipc_message_try_parse_payload (message, eventpipe_collect_tracing5_command_try_parse_payload); result = eventpipe_protocol_helper_collect_tracing (payload, stream); - // If there was a problem transferring ownership of the payload to the session's providers, - // we need to free the dynamically allocated event_filter and tracepoint_config here. - if (!result) { - if (payload->provider_configs != NULL) { - // Until ep_provider_config_fini is implemented, we need to manually free the provider_config manually. - DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) { - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); - ep_event_filter_free (ep_provider_config_get_event_filter (&config)); - ep_tracepoint_config_free (ep_provider_config_get_tracepoint_config (&config)); - } DN_VECTOR_FOREACH_END; - dn_vector_custom_free (payload->provider_configs, ep_provider_config_free_func); - } - } break; case EP_COMMANDID_STOP_TRACING: result = eventpipe_protocol_helper_stop_tracing (message, stream); diff --git a/src/native/eventpipe/ds-eventpipe-protocol.h b/src/native/eventpipe/ds-eventpipe-protocol.h index 5101ddf1b0938f..b53b97e74868d5 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.h +++ b/src/native/eventpipe/ds-eventpipe-protocol.h @@ -37,7 +37,7 @@ struct _EventPipeCollectTracingCommandPayload_Internal { // provider_config = ulong keywords, uint logLevel, string provider_name, string filter_data uint8_t *incoming_buffer; - dn_vector_t *provider_configs; + dn_vector_ptr_t *provider_configs; uint32_t circular_buffer_size_in_mb; EventPipeSerializationFormat serialization_format; bool rundown_requested; diff --git a/src/native/eventpipe/ds-ipc-pal-namedpipe.c b/src/native/eventpipe/ds-ipc-pal-namedpipe.c index 90a8ab144ff4a5..2444cb763c6496 100644 --- a/src/native/eventpipe/ds-ipc-pal-namedpipe.c +++ b/src/native/eventpipe/ds-ipc-pal-namedpipe.c @@ -909,7 +909,7 @@ ds_ipc_stream_read ( bool ds_ipc_stream_read_fd ( DiagnosticsIpcStream *ipc_stream, - uint32_t *data_fd) + int *data_fd) { // Not Supported return false; diff --git a/src/native/eventpipe/ds-ipc-pal-socket.c b/src/native/eventpipe/ds-ipc-pal-socket.c index 90ab23bf6b0ffd..4a16fb5f81f253 100644 --- a/src/native/eventpipe/ds-ipc-pal-socket.c +++ b/src/native/eventpipe/ds-ipc-pal-socket.c @@ -1556,12 +1556,12 @@ ds_ipc_stream_read ( timeout_ms); } +#if HAVE_SYS_SOCKET_H && defined(SOL_SOCKET) && defined(SCM_RIGHTS) && defined(CMSG_SPACE) && defined(CMSG_FIRSTHDR) && defined(CMSG_DATA) bool ds_ipc_stream_read_fd ( DiagnosticsIpcStream *ipc_stream, - uint32_t *data_fd) + int *data_fd) { -#if HAVE_SYS_SOCKET_H && defined(SOL_SOCKET) && defined(SCM_RIGHTS) && defined(CMSG_SPACE) && defined(CMSG_FIRSTHDR) && defined(CMSG_DATA) EP_ASSERT (ipc_stream != NULL); EP_ASSERT (data_fd != NULL); @@ -1571,43 +1571,44 @@ ds_ipc_stream_read_fd ( msg.msg_namelen = 0; struct iovec io_vec[1]; - uint8_t buffer[1]; + char buffer[1]; io_vec[0].iov_base = buffer; io_vec[0].iov_len = 1; msg.msg_iov = io_vec; msg.msg_iovlen = 1; - union { - struct cmsghdr cmsg; - char control[CMSG_SPACE(sizeof(*data_fd))]; - } control_un; - msg.msg_control = control_un.control; - msg.msg_controllen = sizeof(control_un.control); + char control[CMSG_SPACE(sizeof(int))]; + msg.msg_control = control; + msg.msg_controllen = sizeof(control); - ssize_t n = recvmsg(ipc_stream->client_socket, &msg, 0); - if (n < 0) { - return false; - } + ssize_t res; + while ((res = recvmsg(ipc_stream->client_socket, &msg, 0)) < 0 && errno == EINTR); + if (res < 0) + return false; struct cmsghdr *cmptr; if ((cmptr = CMSG_FIRSTHDR(&msg)) == NULL || cmptr->cmsg_level != SOL_SOCKET || - cmptr->cmsg_type != SCM_RIGHTS) { + cmptr->cmsg_type != SCM_RIGHTS) return false; - } - memcpy(data_fd, CMSG_DATA(cmptr), sizeof(*data_fd)); // This is a file descriptor, data_fd should have enough space - if (*data_fd < 0) { + memcpy(data_fd, CMSG_DATA(cmptr), sizeof(int)); + if (*data_fd < 0) return false; - } return true; -#else // HAVE_SYS_SOCKET_H +} +#else // HAVE_SYS_SOCKET_H && defined(SOL_SOCKET) && defined(SCM_RIGHTS) && defined(CMSG_SPACE) && defined(CMSG_FIRSTHDR) && defined(CMSG_DATA) +bool +ds_ipc_stream_read_fd ( + DiagnosticsIpcStream *ipc_stream, + int *data_fd) +{ // Not supported return false; -#endif // HAVE_SYS_SOCKET_H } +#endif // HAVE_SYS_SOCKET_H && defined(SOL_SOCKET) && defined(SCM_RIGHTS) && defined(CMSG_SPACE) && defined(CMSG_FIRSTHDR) && defined(CMSG_DATA) bool ds_ipc_stream_write ( diff --git a/src/native/eventpipe/ds-ipc-pal-websocket.c b/src/native/eventpipe/ds-ipc-pal-websocket.c index 3f63e35506f30c..97eb89025a468a 100644 --- a/src/native/eventpipe/ds-ipc-pal-websocket.c +++ b/src/native/eventpipe/ds-ipc-pal-websocket.c @@ -493,7 +493,7 @@ ds_ipc_stream_read ( bool ds_ipc_stream_read_fd ( DiagnosticsIpcStream *ipc_stream, - uint32_t *data_fd) + int *data_fd) { // Not Supported return false; diff --git a/src/native/eventpipe/ds-ipc-pal.h b/src/native/eventpipe/ds-ipc-pal.h index 4f649fcf44891a..362ea3925f92ba 100644 --- a/src/native/eventpipe/ds-ipc-pal.h +++ b/src/native/eventpipe/ds-ipc-pal.h @@ -116,7 +116,7 @@ ds_ipc_stream_read ( bool ds_ipc_stream_read_fd ( DiagnosticsIpcStream *ipc_stream, - uint32_t *data_fd); + int *data_fd); bool ds_ipc_stream_write ( diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index 05ebc0c65a699f..c4d4c5b4b1abfd 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -25,7 +25,7 @@ session_provider_compare_name_func ( static bool -ep_event_filter_allows_event_id ( +event_filter_allows_event_id ( const EventPipeProviderEventFilter *event_filter, uint32_t event_id); @@ -101,7 +101,7 @@ ep_session_provider_free (EventPipeSessionProvider * session_provider) static bool -ep_event_filter_allows_event_id ( +event_filter_allows_event_id ( const EventPipeProviderEventFilter *event_filter, uint32_t event_id) { @@ -111,7 +111,7 @@ ep_event_filter_allows_event_id ( if (event_filter->event_ids == NULL) return !event_filter->enable; - return event_filter->enable == dn_umap_contains (event_filter->event_ids, &event_id); + return event_filter->enable == dn_umap_contains (event_filter->event_ids, (void*)(uintptr_t)event_id); } bool @@ -135,7 +135,7 @@ ep_session_provider_allows_event ( uint32_t event_id = ep_event_get_event_id (ep_event); EventPipeProviderEventFilter *event_filter = ep_session_provider_get_event_filter (session_provider); - return ep_event_filter_allows_event_id (event_filter, event_id); + return event_filter_allows_event_id (event_filter, event_id); } /* diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index dc48f8675181bf..cc0587c85f3bf2 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -13,6 +13,26 @@ #include "ep-event-payload.h" #include "ep-rt.h" +#if HAVE_LINUX_USER_EVENTS_H +#include // DIAG_IOCSREG +#endif // HAVE_LINUX_USER_EVENTS_H + +#if HAVE_SYS_IOCTL_H +#include // session_register_tracepoint +#endif // HAVE_SYS_IOCTL_H + +#if HAVE_UNISTD_H +#include // close +#endif // HAVE_UNISTD_H + +#if HAVE_SYS_UIO_H +#include // iovec +#endif // HAVE_SYS_UIO_H + +#if HAVE_ERRNO_H +#include // errno +#endif // HAVE_ERRNO_H + /* * Forward declares of all static functions. */ @@ -32,45 +52,46 @@ ep_session_remove_dangling_session_states (EventPipeSession *session); static bool -ep_tracepoint_reg( - uint32_t fd, +session_register_tracepoint ( + EventPipeSession *session, EventPipeTracepoint *tracepoint); static bool -ep_tracepoint_unreg ( - uint32_t fd, +session_unregister_tracepoint ( + EventPipeSession *session, EventPipeTracepoint *tracepoint); static void -ep_session_user_events_tracepoints_init ( - EventPipeSession *session); +session_user_events_tracepoints_init ( + EventPipeSession *session, + int user_events_data_fd); static void -ep_session_disable_user_events (EventPipeSession *session); +session_disable_user_events (EventPipeSession *session); static EventPipeTracepoint * -ep_session_get_tracepoint_for_event ( +session_get_tracepoint_for_event ( EventPipeSession *session, EventPipeEvent* ep_event); static bool -ep_is_guid_empty(const uint8_t *guid); +is_guid_empty(const uint8_t *guid); static uint16_t -ep_tracepoint_construct_extension_buffer( +tracepoint_construct_extension_buffer ( uint8_t *extension, const uint8_t *activity_id, const uint8_t *related_activity_id); static bool -ep_tracepoint_write ( +session_tracepoint_write_event ( EventPipeSession *session, ep_rt_thread_handle_t thread, EventPipeEvent *ep_event, @@ -206,13 +227,13 @@ session_disable_streaming_thread (EventPipeSession *session) ep_rt_wait_event_free (rt_thread_shutdown_event); } +#if HAVE_LINUX_USER_EVENTS_H && HAVE_SYS_IOCTL_H static bool -ep_tracepoint_reg ( - uint32_t fd, +session_register_tracepoint ( + EventPipeSession *session, EventPipeTracepoint *tracepoint) { -#if HAVE_LINUX_USER_EVENTS_H struct user_reg reg = {0}; reg.size = sizeof(reg); @@ -222,55 +243,69 @@ ep_tracepoint_reg ( reg.name_args = (uint64_t)tracepoint->tracepoint_format; - if (ioctl(fd, DIAG_IOCSREG, ®) == -1) + if (ioctl(session->user_events_data_fd, DIAG_IOCSREG, ®) == -1) return false; tracepoint->write_index = reg.write_index; return true; -#else // HAVE_LINUX_USER_EVENTS_H - // Not Supported - return false; -#endif // HAVE_LINUX_USER_EVENTS_H } static bool -ep_tracepoint_unreg ( - uint32_t fd, +session_unregister_tracepoint ( + EventPipeSession *session, EventPipeTracepoint *tracepoint) { -#if HAVE_LINUX_USER_EVENTS_H struct user_unreg unreg = {0}; unreg.size = sizeof(unreg); unreg.disable_bit = EP_TRACEPOINT_ENABLE_BIT; unreg.disable_addr = (uint64_t)&tracepoint->enabled; - if (ioctl(fd, DIAG_IOCSUNREG, &unreg) == -1) + if (ioctl(session->user_events_data_fd, DIAG_IOCSUNREG, &unreg) == -1) return false; return true; -#else // HAVE_LINUX_USER_EVENTS_H +} +#else // HAVE_LINUX_USER_EVENTS_H && HAVE_SYS_IOCTL_H +static +bool +session_register_tracepoint ( + EventPipeSession *session, + EventPipeTracepoint *tracepoint) +{ + // Not Supported + return false; +} + +static +bool +session_unregister_tracepoint ( + EventPipeSession *session, + EventPipeTracepoint *tracepoint) +{ // Not Supported return false; -#endif // HAVE_LINUX_USER_EVENTS_H } +#endif // HAVE_LINUX_USER_EVENTS_H && HAVE_SYS_IOCTL_H /* + * session_user_events_tracepoints_init * - * - * - * + * Registers all configured tracepoints for the user_events eventpipe session. */ static void -ep_session_user_events_tracepoints_init ( - EventPipeSession *session) +session_user_events_tracepoints_init ( + EventPipeSession *session, + int user_events_data_fd) { EP_ASSERT (session != NULL); EP_ASSERT (session->session_type == EP_SESSION_TYPE_USEREVENTS); - EP_ASSERT (session->user_events_data_fd != 0); + EP_ASSERT (user_events_data_fd != 0); + + session->user_events_data_fd = user_events_data_fd; EventPipeSessionProviderList *providers = ep_session_get_providers (session); EP_ASSERT (providers != NULL); @@ -284,19 +319,14 @@ ep_session_user_events_tracepoints_init ( EP_ASSERT (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0' || tracepoint_config->tracepoints != NULL); if (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0') { - ep_raise_error_if_nok (ep_tracepoint_reg (session->user_events_data_fd, - &tracepoint_config->default_tracepoint)); + ep_raise_error_if_nok (session_register_tracepoint (session, &tracepoint_config->default_tracepoint)); } - dn_vector_t *tracepoints = tracepoint_config->tracepoints; - if (tracepoints != NULL) { - for (uint32_t i = 0; i < tracepoints->size; ++i) { - EventPipeTracepoint *tracepoint = *dn_vector_index_t (tracepoints, EventPipeTracepoint *, i); - ep_raise_error_if_nok (tracepoint != NULL); - - ep_raise_error_if_nok (ep_tracepoint_reg (session->user_events_data_fd, - tracepoint)); - } + if (tracepoint_config->tracepoints != NULL) { + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeTracepoint *, tracepoint, tracepoint_config->tracepoints) { + EP_ASSERT (tracepoint != NULL); + ep_raise_error_if_nok (session_register_tracepoint (session, tracepoint)); + } DN_VECTOR_PTR_FOREACH_END; } } @@ -321,7 +351,7 @@ ep_session_alloc ( uint32_t providers_len, EventPipeSessionSynchronousCallback sync_callback, void *callback_additional_data, - uint32_t user_events_data_fd) + int user_events_data_fd) { EP_ASSERT (index < EP_MAX_NUMBER_OF_SESSIONS); EP_ASSERT (format < EP_SERIALIZATION_FORMAT_COUNT); @@ -387,10 +417,8 @@ ep_session_alloc ( case EP_SESSION_TYPE_USEREVENTS: ep_raise_error_if_nok (user_events_data_fd != 0); - // Transfer ownership of the user_events_data file descriptor to the EventPipe Session. - instance->user_events_data_fd = user_events_data_fd; // With the user_events_data file, register tracepoints for each provider's tracepoint configurations - ep_session_user_events_tracepoints_init (instance); + session_user_events_tracepoints_init (instance, user_events_data_fd); break; default: @@ -664,9 +692,14 @@ ep_session_disable (EventPipeSession *session) if ((session->session_type == EP_SESSION_TYPE_IPCSTREAM || session->session_type == EP_SESSION_TYPE_FILESTREAM) && ep_session_get_streaming_enabled (session)) session_disable_streaming_thread (session); - bool ignored; - ep_session_write_all_buffers_to_file (session, &ignored); - ep_session_disable_user_events (session); + if (session->session_type == EP_SESSION_TYPE_USEREVENTS) + session_disable_user_events (session); + + if (session->file != NULL && ep_session_type_uses_buffer_manager (session->session_type)) { + bool ignored; + ep_session_write_all_buffers_to_file (session, &ignored); + } + ep_session_provider_list_clear (session->providers); } @@ -688,47 +721,41 @@ ep_session_write_all_buffers_to_file (EventPipeSession *session, bool *events_wr static void -ep_session_disable_user_events (EventPipeSession *session) +session_disable_user_events (EventPipeSession *session) { -#if HAVE_LINUX_USER_EVENTS_H EP_ASSERT (session != NULL); ep_return_void_if_nok (session->session_type == EP_SESSION_TYPE_USEREVENTS); ep_requires_lock_held (); - // Remove all tracepoints. + // Unregister all tracepoints. EventPipeSessionProviderList *providers = ep_session_get_providers (session); EP_ASSERT (providers != NULL); for (dn_list_it_t it = dn_list_begin (ep_session_provider_list_get_providers (providers)); !dn_list_it_end (it); it = dn_list_it_next (it)) { EventPipeSessionProvider *session_provider = *dn_list_it_data_t (it, EventPipeSessionProvider *); EventPipeProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); if (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0') - ep_tracepoint_unreg (session->user_events_data_fd, &tracepoint_config->default_tracepoint); + session_unregister_tracepoint (session, &tracepoint_config->default_tracepoint); if (tracepoint_config->tracepoints != NULL) { - for (uint32_t i = 0; i < tracepoint_config->tracepoints->size; ++i) { - EventPipeTracepoint *tracepoint = *dn_vector_index_t (tracepoint_config->tracepoints, EventPipeTracepoint *, i); + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeTracepoint *, tracepoint, tracepoint_config->tracepoints) { EP_ASSERT (tracepoint != NULL); - - ep_tracepoint_unreg (session->user_events_data_fd, tracepoint); - } - dn_vector_clear (tracepoint_config->tracepoints); + session_unregister_tracepoint (session, tracepoint); + } DN_VECTOR_PTR_FOREACH_END; } } if (session->user_events_data_fd != 0) { +#if HAVE_UNISTD_H close (session->user_events_data_fd); +#endif // HAVE_UNISTD_H session->user_events_data_fd = 0; } -#else - // Not Supported - return; -#endif // HAVE_LINUX_USER_EVENTS_H } static EventPipeTracepoint * -ep_session_get_tracepoint_for_event ( +session_get_tracepoint_for_event ( EventPipeSession *session, EventPipeEvent* ep_event) { @@ -751,7 +778,7 @@ ep_session_get_tracepoint_for_event ( return tracepoint; uint32_t event_id = ep_event_get_event_id (ep_event); - dn_umap_it_t tracepoint_found = dn_umap_find (event_id_to_tracepoint_map, &event_id); + dn_umap_it_t tracepoint_found = dn_umap_find (event_id_to_tracepoint_map, (void *)(uintptr_t)event_id); if (!dn_umap_it_end (tracepoint_found)) tracepoint = dn_umap_it_value_t (tracepoint_found, EventPipeTracepoint *); @@ -760,7 +787,7 @@ ep_session_get_tracepoint_for_event ( static bool -ep_is_guid_empty(const uint8_t *guid) +is_guid_empty(const uint8_t *guid) { if (guid == NULL) return true; @@ -774,7 +801,7 @@ ep_is_guid_empty(const uint8_t *guid) } /* - * ep_tracepoint_construct_extension_buffer + * tracepoint_construct_extension_buffer * * EventPipe Tracepoints include an extension buffer * that encodes other optional information in the @@ -782,15 +809,17 @@ ep_is_guid_empty(const uint8_t *guid) */ static uint16_t -ep_tracepoint_construct_extension_buffer( +tracepoint_construct_extension_buffer ( uint8_t *extension, const uint8_t *activity_id, const uint8_t *related_activity_id) { uint16_t offset = 0; - bool activity_id_is_empty = ep_is_guid_empty (activity_id); - bool related_activity_id_is_empty = ep_is_guid_empty (related_activity_id); + memset(extension, 0, EP_MAX_EXTENSION_SIZE); + + bool activity_id_is_empty = is_guid_empty (activity_id); + bool related_activity_id_is_empty = is_guid_empty (related_activity_id); if (!activity_id_is_empty) { extension[offset] = !related_activity_id_is_empty ? 0x81 : 0x01; @@ -807,9 +836,10 @@ ep_tracepoint_construct_extension_buffer( return offset; } +#if HAVE_SYS_UIO_H && HAVE_ERRNO_H static bool -ep_tracepoint_write ( +session_tracepoint_write_event ( EventPipeSession *session, ep_rt_thread_handle_t thread, EventPipeEvent *ep_event, @@ -819,11 +849,10 @@ ep_tracepoint_write ( ep_rt_thread_handle_t event_thread, EventPipeStackContents *stack) { -#if HAVE_SYS_UIO_H EP_ASSERT (session != NULL); EP_ASSERT (ep_event != NULL); - EventPipeTracepoint *tracepoint = ep_session_get_tracepoint_for_event (session, ep_event); + EventPipeTracepoint *tracepoint = session_get_tracepoint_for_event (session, ep_event); if (tracepoint == NULL) return false; @@ -836,8 +865,7 @@ ep_tracepoint_write ( uint16_t truncated_event_id = event_id & 0xFFFF; // For parity with EventSource, there shouldn't be any that need more than 16 bits. uint8_t extension[EP_MAX_EXTENSION_SIZE]; - memset(extension, 0, EP_MAX_EXTENSION_SIZE); - uint16_t extension_len = ep_tracepoint_construct_extension_buffer (extension, activity_id, related_activity_id); + uint16_t extension_len = tracepoint_construct_extension_buffer (extension, activity_id, related_activity_id); EP_ASSERT(extension_len <= EP_MAX_EXTENSION_SIZE); uint32_t payload_len = ep_event_payload_get_size (ep_event_payload); @@ -911,17 +939,31 @@ ep_tracepoint_write ( io[index].iov_base = (void *)ep_event_get_metadata (ep_event); io[index].iov_len = metadata_len; - size_t bytes_written = writev(session->user_events_data_fd, (const struct iovec *)io, index + 1); + size_t bytes_written; + while ((bytes_written = writev(session->user_events_data_fd, (const struct iovec *)io, index + 1) < 0) && errno == EINTR); if (io != static_io) free (io); return bytes_written != -1; -#else // HAVE_SYS_UIO_H +} +#else // HAVE_SYS_UIO_H && HAVE_ERRNO_H +static +bool +session_tracepoint_write_event ( + EventPipeSession *session, + ep_rt_thread_handle_t thread, + EventPipeEvent *ep_event, + EventPipeEventPayload *ep_event_payload, + const uint8_t *activity_id, + const uint8_t *related_activity_id, + ep_rt_thread_handle_t event_thread, + EventPipeStackContents *stack) +{ // Not Supported return false; -#endif // HAVE_SYS_UIO_H } +#endif // HAVE_SYS_UIO_H && HAVE_ERRNO_H bool ep_session_write_event ( @@ -944,7 +986,9 @@ ep_session_write_event ( // Filter events specific to "this" session based on precomputed flag on provider/events. if (ep_event_is_enabled_by_mask (ep_event, ep_session_get_mask (session))) { - if (session->synchronous_callback) { + switch (session->session_type) { + case EP_SESSION_TYPE_SYNCHRONOUS: + EP_ASSERT (session->synchronous_callback != NULL); session->synchronous_callback ( ep_event_get_provider (ep_event), ep_event_get_event_id (ep_event), @@ -960,9 +1004,10 @@ ep_session_write_event ( stack == NULL ? NULL : (uintptr_t *)ep_stack_contents_get_pointer (stack), session->callback_additional_data); result = true; - } else if (session->session_type == EP_SESSION_TYPE_USEREVENTS) { + break; + case EP_SESSION_TYPE_USEREVENTS: EP_ASSERT (session->user_events_data_fd != 0); - result = ep_tracepoint_write ( + result = session_tracepoint_write_event ( session, thread, ep_event, @@ -971,7 +1016,8 @@ ep_session_write_event ( related_activity_id, event_thread, stack); - } else { + break; + default: EP_ASSERT (session->buffer_manager != NULL); result = ep_buffer_manager_write_event ( session->buffer_manager, @@ -983,6 +1029,7 @@ ep_session_write_event ( related_activity_id, event_thread, stack); + break; } } diff --git a/src/native/eventpipe/ep-session.h b/src/native/eventpipe/ep-session.h index 0b85673ffe27c0..56af80bf3438ed 100644 --- a/src/native/eventpipe/ep-session.h +++ b/src/native/eventpipe/ep-session.h @@ -13,16 +13,6 @@ #endif #include "ep-getter-setter.h" -#if HAVE_LINUX_USER_EVENTS_H -#include // DIAG_IOCSREG -#include // ep_tracepoint_reg -#include // close -#endif // HAVE_LINUX_USER_EVENTS_H - - -#if HAVE_SYS_UIO_H -#include // iovec -#endif // HAVE_SYS_UIO_H /* * EventPipeSession. */ @@ -80,7 +70,7 @@ struct _EventPipeSession_Internal { // Reference count for the session. This is used to track the number of references to the session. volatile uint32_t ref_count; // The user_events_data file descriptor to register Tracepoints and write user_events to. - uint32_t user_events_data_fd; + int user_events_data_fd; }; #if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_SESSION_GETTER_SETTER) @@ -113,7 +103,7 @@ ep_session_alloc ( uint32_t providers_len, EventPipeSessionSynchronousCallback sync_callback, void *callback_additional_data, - uint32_t user_events_data_fd); + int user_events_data_fd); void ep_session_inc_ref (EventPipeSession *session); diff --git a/src/native/eventpipe/ep-shared-config.h.in b/src/native/eventpipe/ep-shared-config.h.in index b894ba6b5e1a18..512599fef5d02a 100644 --- a/src/native/eventpipe/ep-shared-config.h.in +++ b/src/native/eventpipe/ep-shared-config.h.in @@ -1,9 +1,12 @@ #ifndef EP_SHARED_CONFIG_H_INCLUDED #define EP_SHARED_CONFIG_H_INCLUDED -#cmakedefine01 HAVE_SYS_SOCKET_H +#cmakedefine01 HAVE_ERRNO_H #cmakedefine01 HAVE_LINUX_USER_EVENTS_H +#cmakedefine01 HAVE_SYS_IOCTL_H +#cmakedefine01 HAVE_SYS_SOCKET_H #cmakedefine01 HAVE_SYS_UIO_H +#cmakedefine01 HAVE_UNISTD_H /* This platforms supports setting flags atomically when accepting connections. */ #cmakedefine01 HAVE_ACCEPT4 diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index 0fb55fe7ed02a7..d220f61478ab75 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -72,6 +72,8 @@ typedef struct _StreamWriterVtable StreamWriterVtable; #define EP_TRACEPOINT_ENABLE_BIT 31 +#define EP_TRACEPOINT_FORMAT_MAX_SIZE 512 + #define EP_TRACEPOINT_FORMAT_V1 "u8 version; u16 event_id; __rel_loc u8[] extension; __rel_loc u8[] payload; __rel_loc u8[] meta" #define EP_MAX_EXTENSION_SIZE (2 * (EP_ACTIVITY_ID_SIZE + 1)) diff --git a/src/native/eventpipe/ep-types.h b/src/native/eventpipe/ep-types.h index e3e04a226a986f..4c98a58d27ba6a 100644 --- a/src/native/eventpipe/ep-types.h +++ b/src/native/eventpipe/ep-types.h @@ -184,7 +184,7 @@ struct _EventPipeTracepoint { #else struct _EventPipeTracepoint_Internal { #endif - ep_char8_t tracepoint_format[256]; + ep_char8_t tracepoint_format[EP_TRACEPOINT_FORMAT_MAX_SIZE]; uint32_t write_index; uint32_t enabled; }; @@ -230,7 +230,7 @@ struct _EventPipeProviderTracepointConfiguration { struct _EventPipeProviderTracepointConfiguration_Internal { #endif EventPipeTracepoint default_tracepoint; - dn_vector_t *tracepoints; + dn_vector_ptr_t *tracepoints; dn_umap_t *event_id_to_tracepoint_map; }; diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index a1d70b9ad8e967..0f493eb9f9f9da 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -1136,7 +1136,7 @@ ep_session_options_init ( IpcStream* stream, EventPipeSessionSynchronousCallback sync_callback, void* callback_additional_data, - uint32_t user_events_data_fd) + int user_events_data_fd) { EP_ASSERT (options != NULL); @@ -1775,6 +1775,14 @@ ep_event_filter_free (EventPipeProviderEventFilter *event_filter) ep_rt_object_free (event_filter); } +static +void +DN_CALLBACK_CALLTYPE +tracepoint_free_func (void *tracepoint) +{ + ep_rt_object_free (*(EventPipeTracepoint **)tracepoint); +} + void ep_tracepoint_config_fini (EventPipeProviderTracepointConfiguration *tracepoint_config) { @@ -1786,7 +1794,7 @@ ep_tracepoint_config_fini (EventPipeProviderTracepointConfiguration *tracepoint_ } if (tracepoint_config->tracepoints) { - dn_vector_free (tracepoint_config->tracepoints); + dn_vector_ptr_custom_free (tracepoint_config->tracepoints, tracepoint_free_func); tracepoint_config->tracepoints = NULL; } } diff --git a/src/native/eventpipe/ep.h b/src/native/eventpipe/ep.h index b5d88b9170fd27..e82b247e4186ba 100644 --- a/src/native/eventpipe/ep.h +++ b/src/native/eventpipe/ep.h @@ -127,7 +127,7 @@ typedef struct EventPipeSessionOptions { EventPipeSerializationFormat format; uint64_t rundown_keyword; bool stackwalk_requested; - uint32_t user_events_data_fd; + int user_events_data_fd; } EventPipeSessionOptions; void @@ -144,7 +144,7 @@ ep_session_options_init ( IpcStream *stream, EventPipeSessionSynchronousCallback sync_callback, void *callback_additional_data, - uint32_t user_events_data_fd); + int user_events_data_fd); void ep_session_options_fini (EventPipeSessionOptions* options); From a16e1981852872a709fe417d23c715750328eb43 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Fri, 6 Jun 2025 22:32:04 +0000 Subject: [PATCH 14/32] Address Feedback const EventPipeProviderConfiguration Adhere to the standard where EventPipeProviderConfiguration is read-only. Create event filter and tracepoint config duplication helpers to give the SessionProvider its own copy. --- src/native/eventpipe/ds-eventpipe-protocol.c | 52 ++++++------- src/native/eventpipe/ep-session-provider.c | 18 ++++- src/native/eventpipe/ep-session-provider.h | 4 +- src/native/eventpipe/ep-types.h | 14 +++- src/native/eventpipe/ep.c | 81 ++++++++++++++++++++ 5 files changed, 132 insertions(+), 37 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index dcfa0946adffc5..893bd7c814652b 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -428,6 +428,9 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( uint8_t *filter_data_byte_array = NULL; uint32_t filter_data_byte_array_len = 0; + EventPipeProviderEventFilter *event_filter = NULL; + EventPipeProviderTracepointConfiguration *tracepoint_config = NULL; + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint64_t (buffer, buffer_len, &provider_config->keywords)); ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &log_level)); @@ -449,15 +452,19 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( } if ((optional_field_flags & EP_PROVIDER_OPTFIELD_EVENT_FILTER) != 0) { - provider_config->event_filter = ep_rt_object_alloc (EventPipeProviderEventFilter); - ep_raise_error_if_nok (provider_config->event_filter != NULL); - ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_filter (buffer, buffer_len, provider_config->event_filter)); + event_filter = ep_rt_object_alloc(EventPipeProviderEventFilter); + ep_raise_error_if_nok (event_filter != NULL); + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_filter (buffer, buffer_len, event_filter)); + provider_config->event_filter = event_filter; + event_filter = NULL; // Ownership transferred to provider_config. } if ((optional_field_flags & EP_PROVIDER_OPTFIELD_TRACEPOINT_CONFIG) != 0) { - provider_config->tracepoint_config = ep_rt_object_alloc (EventPipeProviderTracepointConfiguration); - ep_raise_error_if_nok (provider_config->tracepoint_config != NULL); - ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_tracepoint_config (buffer, buffer_len, provider_config->tracepoint_config)); + tracepoint_config = ep_rt_object_alloc (EventPipeProviderTracepointConfiguration); + ep_raise_error_if_nok (tracepoint_config != NULL); + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_tracepoint_config (buffer, buffer_len, tracepoint_config)); + provider_config->tracepoint_config = tracepoint_config; + tracepoint_config = NULL; // Ownership transferred to provider_config. } result = true; @@ -466,21 +473,19 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( return result; ep_on_error: - ep_tracepoint_config_free (provider_config->tracepoint_config); - provider_config->tracepoint_config = NULL; - - ep_event_filter_free (provider_config->event_filter); - provider_config->event_filter = NULL; + if (tracepoint_config != NULL) { + ep_tracepoint_config_free (tracepoint_config); + tracepoint_config = NULL; + } - ep_rt_utf8_string_free ((ep_char8_t *)provider_config->filter_data); - provider_config->filter_data = NULL; + if (event_filter != NULL) { + ep_event_filter_free (event_filter); + event_filter = NULL; + } ep_rt_byte_array_free (filter_data_byte_array); filter_data_byte_array = NULL; - ep_rt_utf8_string_free ((ep_char8_t *)provider_config->provider_name); - provider_config->provider_name = NULL; - ep_rt_byte_array_free (provider_name_byte_array); provider_name_byte_array = NULL; @@ -544,20 +549,12 @@ eventpipe_collect_tracing_command_try_parse_config ( if (provider_config != NULL) { ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (provider_config)); ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (provider_config)); - ep_event_filter_free (ep_provider_config_get_event_filter (provider_config)); - ep_tracepoint_config_free (ep_provider_config_get_tracepoint_config (provider_config)); + ep_event_filter_free ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (provider_config)); + ep_tracepoint_config_free ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (provider_config)); ep_rt_object_free (provider_config); provider_config = NULL; } - // Until ep_provider_config_fini/free is implemented, we need to manually free the provider_config. - if (*result != NULL) { - DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeProviderConfiguration *, config, *result) { - ep_event_filter_free (ep_provider_config_get_event_filter (config)); - ep_tracepoint_config_free (ep_provider_config_get_tracepoint_config (config)); - } DN_VECTOR_FOREACH_END; - } - ep_exit_error_handler (); } @@ -576,7 +573,8 @@ ds_eventpipe_collect_tracing_command_payload_free (EventPipeCollectTracingComman DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeProviderConfiguration *, config, payload->provider_configs) { ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (config)); ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (config)); - // What about the EventPipeProviderConfiguration allocated in eventpipe_collect_tracing_command_try_parse_config + ep_event_filter_free ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (config)); + ep_tracepoint_config_free ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (config)); } DN_VECTOR_FOREACH_END; ep_rt_object_free (payload); diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index c4d4c5b4b1abfd..1bc8fec075d04a 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -57,8 +57,8 @@ ep_session_provider_alloc ( uint64_t keywords, EventPipeEventLevel logging_level, const ep_char8_t *filter_data, - EventPipeProviderEventFilter *event_filter, - EventPipeProviderTracepointConfiguration *tracepoint_config) + const EventPipeProviderEventFilter *event_filter, + const EventPipeProviderTracepointConfiguration *tracepoint_config) { EventPipeSessionProvider *instance = ep_rt_object_alloc (EventPipeSessionProvider); ep_raise_error_if_nok (instance != NULL); @@ -75,8 +75,18 @@ ep_session_provider_alloc ( instance->keywords = keywords; instance->logging_level = logging_level; - instance->event_filter = event_filter; - instance->tracepoint_config = tracepoint_config; + instance->event_filter = NULL; + instance->tracepoint_config = NULL; + + if (event_filter) { + instance->event_filter = ep_provider_event_filter_dup (event_filter); + ep_raise_error_if_nok (instance->event_filter != NULL); + } + + if (tracepoint_config) { + instance->tracepoint_config = ep_provider_tracepoint_config_dup (tracepoint_config); + ep_raise_error_if_nok (instance->tracepoint_config != NULL); + } ep_on_exit: return instance; diff --git a/src/native/eventpipe/ep-session-provider.h b/src/native/eventpipe/ep-session-provider.h index 44b6af81759c7f..fe17e134726582 100644 --- a/src/native/eventpipe/ep-session-provider.h +++ b/src/native/eventpipe/ep-session-provider.h @@ -47,8 +47,8 @@ ep_session_provider_alloc ( uint64_t keywords, EventPipeEventLevel logging_level, const ep_char8_t *filter_data, - EventPipeProviderEventFilter *event_filter, - EventPipeProviderTracepointConfiguration *tracepoint_config); + const EventPipeProviderEventFilter *event_filter, + const EventPipeProviderTracepointConfiguration *tracepoint_config); void ep_session_provider_free (EventPipeSessionProvider * session_provider); diff --git a/src/native/eventpipe/ep-types.h b/src/native/eventpipe/ep-types.h index 4c98a58d27ba6a..1fb5bd6aab94fc 100644 --- a/src/native/eventpipe/ep-types.h +++ b/src/native/eventpipe/ep-types.h @@ -214,6 +214,9 @@ struct _EventPipeProviderEventFilter { }; #endif +EventPipeProviderEventFilter * +ep_provider_event_filter_dup (const EventPipeProviderEventFilter *event_filter_src); + void ep_event_filter_fini (EventPipeProviderEventFilter *event_filter); @@ -240,6 +243,9 @@ struct _EventPipeProviderTracepointConfiguration { }; #endif +EventPipeProviderTracepointConfiguration * +ep_provider_tracepoint_config_dup (const EventPipeProviderTracepointConfiguration *tracepoint_config); + void ep_tracepoint_config_fini (EventPipeProviderTracepointConfiguration *tracepoint_config); @@ -259,8 +265,8 @@ struct _EventPipeProviderConfiguration_Internal { const ep_char8_t *filter_data; uint64_t keywords; EventPipeEventLevel logging_level; - EventPipeProviderEventFilter *event_filter; - EventPipeProviderTracepointConfiguration *tracepoint_config; + const EventPipeProviderEventFilter *event_filter; + const EventPipeProviderTracepointConfiguration *tracepoint_config; }; @@ -274,8 +280,8 @@ EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, const ep_cha EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, const ep_char8_t *, filter_data) EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, uint64_t, keywords) EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, EventPipeEventLevel, logging_level) -EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, EventPipeProviderEventFilter *, event_filter) -EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, EventPipeProviderTracepointConfiguration *, tracepoint_config) +EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, const EventPipeProviderEventFilter *, event_filter) +EP_DEFINE_GETTER(EventPipeProviderConfiguration *, provider_config, const EventPipeProviderTracepointConfiguration *, tracepoint_config) EventPipeProviderConfiguration * ep_provider_config_init ( diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index 0f493eb9f9f9da..08a52e91ebd2fe 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -1755,6 +1755,32 @@ ep_ipc_stream_factory_callback_set (EventPipeIpcStreamFactorySuspendedPortsCallb _ep_ipc_stream_factory_suspended_ports_callback = suspended_ports_callback; } +EventPipeProviderEventFilter * +ep_provider_event_filter_dup (const EventPipeProviderEventFilter *event_filter_src) +{ + ep_return_null_if_nok (event_filter_src != NULL); + + EventPipeProviderEventFilter *event_filter = ep_rt_object_alloc (EventPipeProviderEventFilter); + ep_return_null_if_nok (event_filter != NULL); + + event_filter->enable = event_filter_src->enable; + event_filter->event_ids = dn_umap_alloc (); + ep_return_null_if_nok (event_filter->event_ids != NULL); + + DN_UMAP_FOREACH_KEY_BEGIN (uint32_t *, event_id, event_filter_src->event_ids) { + dn_umap_result_t insert_result = dn_umap_ptr_uint32_insert (event_filter->event_ids, event_id, 0); + ep_raise_error_if_nok (insert_result.result); + } DN_UMAP_FOREACH_END; + +ep_on_exit: + return event_filter; + +ep_on_error: + ep_event_filter_free (event_filter); + event_filter = NULL; + ep_exit_error_handler (); +} + void ep_event_filter_fini (EventPipeProviderEventFilter *event_filter) { @@ -1775,6 +1801,61 @@ ep_event_filter_free (EventPipeProviderEventFilter *event_filter) ep_rt_object_free (event_filter); } +EventPipeProviderTracepointConfiguration * +ep_provider_tracepoint_config_dup (const EventPipeProviderTracepointConfiguration *tracepoint_config_src) +{ + ep_return_null_if_nok (tracepoint_config_src != NULL); + + EventPipeProviderTracepointConfiguration *tracepoint_config = ep_rt_object_alloc (EventPipeProviderTracepointConfiguration); + ep_return_null_if_nok (tracepoint_config != NULL); + + EventPipeTracepoint *tracepoint_copy = NULL; + dn_umap_t *tracepoints_seen = NULL; + tracepoint_config->default_tracepoint.tracepoint_format[0] = '\0'; + if (tracepoint_config_src->default_tracepoint.tracepoint_format[0] != '\0') + memcpy(&tracepoint_config->default_tracepoint, &tracepoint_config_src->default_tracepoint, sizeof(EventPipeTracepoint)); + + tracepoint_config->tracepoints = NULL; + if (tracepoint_config_src->tracepoints) { + dn_vector_ptr_custom_alloc_params_t tracepoint_set_array_params = {0, }; + tracepoint_set_array_params.capacity = tracepoint_config_src->tracepoints->size; + tracepoint_config->tracepoints = dn_vector_ptr_custom_alloc (&tracepoint_set_array_params); + ep_raise_error_if_nok (tracepoint_config->tracepoints != NULL); + + tracepoint_config->event_id_to_tracepoint_map = dn_umap_alloc (); + ep_raise_error_if_nok (tracepoint_config->event_id_to_tracepoint_map != NULL); + + tracepoints_seen = dn_umap_alloc (); + ep_raise_error_if_nok (tracepoints_seen != NULL); + + DN_UMAP_FOREACH_BEGIN (uint32_t *, event_id, EventPipeTracepoint *, tracepoint, tracepoint_config_src->event_id_to_tracepoint_map) { + if (!dn_umap_extract_key (tracepoints_seen, tracepoint, NULL, (void **)&tracepoint_copy)) { + tracepoint_copy = ep_rt_object_alloc (EventPipeTracepoint); + ep_return_null_if_nok (tracepoint_copy != NULL); + memcpy(tracepoint_copy, tracepoint, sizeof(EventPipeTracepoint)); + dn_umap_result_t insert_result = dn_umap_insert (tracepoints_seen, tracepoint, tracepoint_copy); + ep_raise_error_if_nok (insert_result.result); + ep_raise_error_if_nok (dn_vector_ptr_push_back (tracepoint_config->tracepoints, tracepoint_copy)); + } + dn_umap_result_t insert_result = dn_umap_insert (tracepoint_config->event_id_to_tracepoint_map, event_id, tracepoint_copy); + ep_raise_error_if_nok (insert_result.result); + } DN_UMAP_FOREACH_END; + } + +ep_on_exit: + dn_umap_free (tracepoints_seen); + return tracepoint_config; + +ep_on_error: + if (tracepoint_copy != NULL) { + ep_rt_object_free (tracepoint_copy); + tracepoint_copy = NULL; + } + ep_tracepoint_config_free (tracepoint_config); + tracepoint_config = NULL; + ep_exit_error_handler (); +} + static void DN_CALLBACK_CALLTYPE From 7baa695225e8a0315bd3b786119cd4d52a821bd3 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Sat, 7 Jun 2025 04:07:50 +0000 Subject: [PATCH 15/32] Address feedback Add string deserializer helper --- src/native/eventpipe/ds-eventpipe-protocol.c | 108 ++++++++----------- src/native/eventpipe/ds-protocol.c | 37 +++++++ src/native/eventpipe/ds-protocol.h | 6 ++ 3 files changed, 87 insertions(+), 64 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 893bd7c814652b..94a6ea9f11d853 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -67,6 +67,12 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( uint32_t *buffer_len, EventPipeProviderEventFilter *event_filter); +static +bool +tracepoint_format_init ( + EventPipeTracepoint *tracepoint, + const ep_char8_t *tracepoint_name); + static bool eventpipe_collect_tracing_command_try_parse_tracepoint_config ( @@ -276,6 +282,24 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( ep_exit_error_handler (); } +static +bool +tracepoint_format_init ( + EventPipeTracepoint *tracepoint, + const ep_char8_t *tracepoint_name) +{ + EP_ASSERT (tracepoint != NULL); + + tracepoint->tracepoint_format[0] = '\0'; + if (tracepoint_name == NULL || tracepoint_name[0] == '\0') + return true; + + size_t default_tracepoint_format_len = strlen(tracepoint_name) + strlen(EP_TRACEPOINT_FORMAT_V1) + 2; // +2 for space and null terminator + int32_t res = snprintf(tracepoint->tracepoint_format, sizeof(tracepoint->tracepoint_format), "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); + + return (res >= 0 && (size_t)res < sizeof(tracepoint->tracepoint_format)); +} + /* * eventpipe_collect_tracing_command_try_parse_tracepoint_config * @@ -307,31 +331,17 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( EventPipeTracepoint *tracepoint = NULL; ep_char8_t *tracepoint_name = NULL; - size_t default_tracepoint_format_len = 0; - uint8_t *tracepoint_name_byte_array = NULL; - uint32_t tracepoint_name_byte_array_len = 0; uint32_t tracepoint_set_array_len = 0; - tracepoint_config->default_tracepoint.tracepoint_format[0] = '\0'; // Initialize to empty string. tracepoint_config->tracepoints = NULL; tracepoint_config->event_id_to_tracepoint_map = NULL; - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &tracepoint_name_byte_array, &tracepoint_name_byte_array_len)); - - if (tracepoint_name_byte_array) { - // Make Helper - tracepoint_name = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)tracepoint_name_byte_array); - ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (tracepoint_name)); - ep_rt_byte_array_free (tracepoint_name_byte_array); - tracepoint_name_byte_array = NULL; + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &tracepoint_name)); - default_tracepoint_format_len = strlen(tracepoint_name) + strlen(EP_TRACEPOINT_FORMAT_V1) + 2; // +2 for space and null terminator - int32_t res = snprintf(tracepoint_config->default_tracepoint.tracepoint_format, sizeof(tracepoint_config->default_tracepoint.tracepoint_format), "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); - ep_raise_error_if_nok (res >= 0 && (size_t)res < default_tracepoint_format_len); - ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); - tracepoint_name = NULL; - } + ep_raise_error_if_nok (tracepoint_format_init (&tracepoint_config->default_tracepoint, tracepoint_name)); + ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); + tracepoint_name = NULL; ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &tracepoint_set_array_len)); @@ -348,17 +358,10 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( tracepoint = ep_rt_object_alloc (EventPipeTracepoint); // Ownership will be transferred to the tracepoint_config's tracepoint vector. ep_raise_error_if_nok (tracepoint != NULL); - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &tracepoint_name_byte_array, &tracepoint_name_byte_array_len)); - - // Make Helper - tracepoint_name = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)tracepoint_name_byte_array); + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &tracepoint_name)); ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (tracepoint_name)); - ep_rt_byte_array_free (tracepoint_name_byte_array); - tracepoint_name_byte_array = NULL; - default_tracepoint_format_len = strlen(tracepoint_name) + strlen(EP_TRACEPOINT_FORMAT_V1) + 2; // +2 for space and null terminator - int32_t res = snprintf(tracepoint->tracepoint_format, sizeof(tracepoint->tracepoint_format), "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); - ep_raise_error_if_nok (res >= 0 && (size_t)res < default_tracepoint_format_len); + ep_raise_error_if_nok (tracepoint_format_init (tracepoint, tracepoint_name)); ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); tracepoint_name = NULL; @@ -390,9 +393,6 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( ep_rt_object_free (tracepoint); tracepoint = NULL; - ep_rt_byte_array_free (tracepoint_name_byte_array); - tracepoint_name_byte_array = NULL; - ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); tracepoint_name = NULL; @@ -422,12 +422,8 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( uint32_t log_level = 0; - uint8_t *provider_name_byte_array = NULL; - uint32_t provider_name_byte_array_len = 0; - - uint8_t *filter_data_byte_array = NULL; - uint32_t filter_data_byte_array_len = 0; - + ep_char8_t *provider_name = NULL; + ep_char8_t *filter_data = NULL; EventPipeProviderEventFilter *event_filter = NULL; EventPipeProviderTracepointConfiguration *tracepoint_config = NULL; @@ -437,19 +433,14 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( provider_config->logging_level = (EventPipeEventLevel)log_level; ep_raise_error_if_nok (provider_config->logging_level <= EP_EVENT_LEVEL_VERBOSE); - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &provider_name_byte_array, &provider_name_byte_array_len)); - provider_config->provider_name = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)provider_name_byte_array); - ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (provider_config->provider_name)); - ep_rt_byte_array_free (provider_name_byte_array); - provider_name_byte_array = NULL; - - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &filter_data_byte_array, &filter_data_byte_array_len)); - if (filter_data_byte_array) { - provider_config->filter_data = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)filter_data_byte_array); - ep_raise_error_if_nok (provider_config->filter_data != NULL); - ep_rt_byte_array_free (filter_data_byte_array); - filter_data_byte_array = NULL; - } + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &provider_name)); + ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (provider_name)); + provider_config->provider_name = provider_name; + provider_name = NULL; // Ownership transferred to provider_config. + + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &filter_data)); + provider_config->filter_data = filter_data; + filter_data = NULL; // Ownership transferred to provider_config. if ((optional_field_flags & EP_PROVIDER_OPTFIELD_EVENT_FILTER) != 0) { event_filter = ep_rt_object_alloc(EventPipeProviderEventFilter); @@ -473,21 +464,10 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( return result; ep_on_error: - if (tracepoint_config != NULL) { - ep_tracepoint_config_free (tracepoint_config); - tracepoint_config = NULL; - } - - if (event_filter != NULL) { - ep_event_filter_free (event_filter); - event_filter = NULL; - } - - ep_rt_byte_array_free (filter_data_byte_array); - filter_data_byte_array = NULL; - - ep_rt_byte_array_free (provider_name_byte_array); - provider_name_byte_array = NULL; + ep_tracepoint_config_free (tracepoint_config); + ep_event_filter_free (event_filter); + ep_rt_utf8_string_free (filter_data); + ep_rt_utf8_string_free (provider_name); ep_exit_error_handler (); } diff --git a/src/native/eventpipe/ds-protocol.c b/src/native/eventpipe/ds-protocol.c index 0f615fb2b3e22e..24dc4f4c5cf8bd 100644 --- a/src/native/eventpipe/ds-protocol.c +++ b/src/native/eventpipe/ds-protocol.c @@ -453,6 +453,43 @@ ds_ipc_message_try_parse_uint32_t ( return result; } +bool +ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc( + uint8_t **buffer, + uint32_t *buffer_len, + ep_char8_t **string_utf8) +{ + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (string_utf8 != NULL); + + bool result = false; + + uint8_t *byte_array = NULL; + uint32_t byte_array_len = 0; + + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &byte_array, &byte_array_len)); + + *string_utf8 = NULL; + if (byte_array) { + *string_utf8 = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)byte_array); + ep_raise_error_if_nok (*string_utf8 != NULL); + + ep_rt_byte_array_free (byte_array); + byte_array = NULL; + } + + result = true; + +ep_on_exit: + return result; + +ep_on_error: + ep_rt_byte_array_free (byte_array); + ep_rt_utf8_string_free (*string_utf8); + ep_exit_error_handler (); +} + bool ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc ( uint8_t **buffer, diff --git a/src/native/eventpipe/ds-protocol.h b/src/native/eventpipe/ds-protocol.h index 826f293d48ce5c..91af929616d2df 100644 --- a/src/native/eventpipe/ds-protocol.h +++ b/src/native/eventpipe/ds-protocol.h @@ -129,6 +129,12 @@ ds_ipc_message_try_parse_uint32_t ( uint32_t *buffer_len, uint32_t *value); +bool +ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc( + uint8_t **buffer, + uint32_t *buffer_len, + ep_char8_t **string_utf8); + bool ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc ( uint8_t **buffer, From 20ecd2e96aae3c434e4ab96930de00bde4c90d0b Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Sat, 7 Jun 2025 17:47:59 +0000 Subject: [PATCH 16/32] Revert provider_configs to vector of structs --- src/native/eventpipe/ds-eventpipe-protocol.c | 51 ++++++++++---------- src/native/eventpipe/ds-eventpipe-protocol.h | 2 +- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 94a6ea9f11d853..9096afb916cdec 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -94,7 +94,7 @@ eventpipe_collect_tracing_command_try_parse_config ( uint8_t **buffer, uint32_t *buffer_len, EventPipeProviderOptionalFieldFlags optional_field_flags, - dn_vector_ptr_t **result); + dn_vector_t **result); static uint8_t * @@ -427,6 +427,13 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( EventPipeProviderEventFilter *event_filter = NULL; EventPipeProviderTracepointConfiguration *tracepoint_config = NULL; + provider_config->keywords = 0; + provider_config->logging_level = (EventPipeEventLevel)0; + provider_config->provider_name = NULL; + provider_config->filter_data = NULL; + provider_config->event_filter = NULL; + provider_config->tracepoint_config = NULL; + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint64_t (buffer, buffer_len, &provider_config->keywords)); ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &log_level)); @@ -487,7 +494,7 @@ eventpipe_collect_tracing_command_try_parse_config ( uint8_t **buffer, uint32_t *buffer_len, EventPipeProviderOptionalFieldFlags optional_field_flags, - dn_vector_ptr_t **result) + dn_vector_t **result) { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); @@ -497,27 +504,25 @@ eventpipe_collect_tracing_command_try_parse_config ( // This should be larger than any reasonable client request. const uint32_t max_count_configs = 1000; uint32_t count_configs = 0; - dn_vector_ptr_custom_alloc_params_t params = {0, }; + dn_vector_custom_alloc_params_t params = {0, }; - EventPipeProviderConfiguration *provider_config = NULL; + EventPipeProviderConfiguration provider_config; ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &count_configs)); ep_raise_error_if_nok (count_configs <= max_count_configs); params.capacity = count_configs; - *result = dn_vector_ptr_custom_alloc (¶ms); + *result = dn_vector_custom_alloc_t (¶ms, EventPipeProviderConfiguration); ep_raise_error_if_nok (*result); for (uint32_t i = 0; i < count_configs; ++i) { - provider_config = ep_rt_object_alloc (EventPipeProviderConfiguration); - ep_raise_error_if_nok (provider_config != NULL); ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_provider_config ( buffer, buffer_len, optional_field_flags, - provider_config)); + &provider_config)); - ep_raise_error_if_nok (dn_vector_ptr_push_back (*result, provider_config)); - provider_config = NULL; // Ownership transferred. + ep_raise_error_if_nok (dn_vector_push_back (*result, provider_config)); + ep_provider_config_fini (&provider_config); } ep_on_exit: @@ -526,14 +531,10 @@ eventpipe_collect_tracing_command_try_parse_config ( ep_on_error: count_configs = 0; - if (provider_config != NULL) { - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (provider_config)); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (provider_config)); - ep_event_filter_free ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (provider_config)); - ep_tracepoint_config_free ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (provider_config)); - ep_rt_object_free (provider_config); - provider_config = NULL; - } + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&provider_config)); + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&provider_config)); + ep_event_filter_free ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (&provider_config)); + ep_tracepoint_config_free ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (&provider_config)); ep_exit_error_handler (); } @@ -550,11 +551,11 @@ ds_eventpipe_collect_tracing_command_payload_free (EventPipeCollectTracingComman ep_return_void_if_nok (payload != NULL); ep_rt_byte_array_free (payload->incoming_buffer); - DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeProviderConfiguration *, config, payload->provider_configs) { - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (config)); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (config)); - ep_event_filter_free ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (config)); - ep_tracepoint_config_free ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (config)); + DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) { + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); + ep_event_filter_free ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (&config)); + ep_tracepoint_config_free ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (&config)); } DN_VECTOR_FOREACH_END; ep_rt_object_free (payload); @@ -866,8 +867,8 @@ eventpipe_protocol_helper_collect_tracing ( &options, NULL, payload->circular_buffer_size_in_mb, - *(EventPipeProviderConfiguration **)dn_vector_ptr_data (payload->provider_configs), - dn_vector_ptr_size (payload->provider_configs), + dn_vector_data_t (payload->provider_configs, EventPipeProviderConfiguration), + dn_vector_size (payload->provider_configs), payload->session_type == EP_IPC_SESSION_TYPE_USEREVENTS ? EP_SESSION_TYPE_USEREVENTS : EP_SESSION_TYPE_IPCSTREAM, payload->serialization_format, payload->rundown_keyword, diff --git a/src/native/eventpipe/ds-eventpipe-protocol.h b/src/native/eventpipe/ds-eventpipe-protocol.h index b53b97e74868d5..5101ddf1b0938f 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.h +++ b/src/native/eventpipe/ds-eventpipe-protocol.h @@ -37,7 +37,7 @@ struct _EventPipeCollectTracingCommandPayload_Internal { // provider_config = ulong keywords, uint logLevel, string provider_name, string filter_data uint8_t *incoming_buffer; - dn_vector_ptr_t *provider_configs; + dn_vector_t *provider_configs; uint32_t circular_buffer_size_in_mb; EventPipeSerializationFormat serialization_format; bool rundown_requested; From c12c002d5c824c25bd8cba713c5451e0468d9d5b Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Sat, 7 Jun 2025 18:16:03 +0000 Subject: [PATCH 17/32] Dynamically allocate tracepoint format --- src/native/eventpipe/ds-eventpipe-protocol.c | 28 +------------- src/native/eventpipe/ep-session.c | 2 +- src/native/eventpipe/ep-types.h | 7 +++- src/native/eventpipe/ep.c | 39 ++++++++++++++++++-- 4 files changed, 44 insertions(+), 32 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 9096afb916cdec..75b6b221120281 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -67,12 +67,6 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( uint32_t *buffer_len, EventPipeProviderEventFilter *event_filter); -static -bool -tracepoint_format_init ( - EventPipeTracepoint *tracepoint, - const ep_char8_t *tracepoint_name); - static bool eventpipe_collect_tracing_command_try_parse_tracepoint_config ( @@ -282,24 +276,6 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( ep_exit_error_handler (); } -static -bool -tracepoint_format_init ( - EventPipeTracepoint *tracepoint, - const ep_char8_t *tracepoint_name) -{ - EP_ASSERT (tracepoint != NULL); - - tracepoint->tracepoint_format[0] = '\0'; - if (tracepoint_name == NULL || tracepoint_name[0] == '\0') - return true; - - size_t default_tracepoint_format_len = strlen(tracepoint_name) + strlen(EP_TRACEPOINT_FORMAT_V1) + 2; // +2 for space and null terminator - int32_t res = snprintf(tracepoint->tracepoint_format, sizeof(tracepoint->tracepoint_format), "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); - - return (res >= 0 && (size_t)res < sizeof(tracepoint->tracepoint_format)); -} - /* * eventpipe_collect_tracing_command_try_parse_tracepoint_config * @@ -339,7 +315,7 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &tracepoint_name)); - ep_raise_error_if_nok (tracepoint_format_init (&tracepoint_config->default_tracepoint, tracepoint_name)); + ep_raise_error_if_nok (ep_tracepoint_format_init (&tracepoint_config->default_tracepoint, tracepoint_name)); ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); tracepoint_name = NULL; @@ -361,7 +337,7 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &tracepoint_name)); ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (tracepoint_name)); - ep_raise_error_if_nok (tracepoint_format_init (tracepoint, tracepoint_name)); + ep_raise_error_if_nok (ep_tracepoint_format_init (tracepoint, tracepoint_name)); ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); tracepoint_name = NULL; diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index cc0587c85f3bf2..00db20540bc280 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -939,7 +939,7 @@ session_tracepoint_write_event ( io[index].iov_base = (void *)ep_event_get_metadata (ep_event); io[index].iov_len = metadata_len; - size_t bytes_written; + ssize_t bytes_written; while ((bytes_written = writev(session->user_events_data_fd, (const struct iovec *)io, index + 1) < 0) && errno == EINTR); if (io != static_io) diff --git a/src/native/eventpipe/ep-types.h b/src/native/eventpipe/ep-types.h index 1fb5bd6aab94fc..b693971bf19f11 100644 --- a/src/native/eventpipe/ep-types.h +++ b/src/native/eventpipe/ep-types.h @@ -184,7 +184,7 @@ struct _EventPipeTracepoint { #else struct _EventPipeTracepoint_Internal { #endif - ep_char8_t tracepoint_format[EP_TRACEPOINT_FORMAT_MAX_SIZE]; + const ep_char8_t *tracepoint_format; uint32_t write_index; uint32_t enabled; }; @@ -195,6 +195,11 @@ struct _EventPipeTracepoint { }; #endif +bool +ep_tracepoint_format_init ( + EventPipeTracepoint *tracepoint, + const ep_char8_t *tracepoint_name); + /* * EventPipeProviderEventFilter. */ diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index 08a52e91ebd2fe..cd3383ef842081 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -1755,6 +1755,38 @@ ep_ipc_stream_factory_callback_set (EventPipeIpcStreamFactorySuspendedPortsCallb _ep_ipc_stream_factory_suspended_ports_callback = suspended_ports_callback; } +bool +ep_tracepoint_format_init ( + EventPipeTracepoint *tracepoint, + const ep_char8_t *tracepoint_name) +{ + EP_ASSERT (tracepoint != NULL); + + bool result = false; + int32_t res = 0; + + tracepoint->tracepoint_format = NULL; + if (tracepoint_name == NULL || tracepoint_name[0] == '\0') + return true; + + size_t tracepoint_format_len = strlen(tracepoint_name) + strlen(EP_TRACEPOINT_FORMAT_V1) + 2; // +2 for space and null terminator + ep_char8_t *tracepoint_format = ep_rt_utf8_string_alloc (tracepoint_format_len); + ep_raise_error_if_nok (tracepoint_format != NULL); + res = snprintf(tracepoint_format, sizeof(tracepoint_format), "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); + ep_raise_error_if_nok (res >= 0 && (size_t)res < sizeof(tracepoint_format)); + tracepoint->tracepoint_format = tracepoint_format; + tracepoint_format = NULL; + + result = true; + +ep_on_exit: + return result; + +ep_on_error: + ep_rt_utf8_string_free (tracepoint_format); + ep_exit_error_handler (); +} + EventPipeProviderEventFilter * ep_provider_event_filter_dup (const EventPipeProviderEventFilter *event_filter_src) { @@ -1811,9 +1843,7 @@ ep_provider_tracepoint_config_dup (const EventPipeProviderTracepointConfiguratio EventPipeTracepoint *tracepoint_copy = NULL; dn_umap_t *tracepoints_seen = NULL; - tracepoint_config->default_tracepoint.tracepoint_format[0] = '\0'; - if (tracepoint_config_src->default_tracepoint.tracepoint_format[0] != '\0') - memcpy(&tracepoint_config->default_tracepoint, &tracepoint_config_src->default_tracepoint, sizeof(EventPipeTracepoint)); + ep_raise_error_if_nok (ep_tracepoint_format_init (&tracepoint_config->default_tracepoint, tracepoint_config_src->default_tracepoint.tracepoint_format)); tracepoint_config->tracepoints = NULL; if (tracepoint_config_src->tracepoints) { @@ -1832,7 +1862,8 @@ ep_provider_tracepoint_config_dup (const EventPipeProviderTracepointConfiguratio if (!dn_umap_extract_key (tracepoints_seen, tracepoint, NULL, (void **)&tracepoint_copy)) { tracepoint_copy = ep_rt_object_alloc (EventPipeTracepoint); ep_return_null_if_nok (tracepoint_copy != NULL); - memcpy(tracepoint_copy, tracepoint, sizeof(EventPipeTracepoint)); + ep_raise_error_if_nok (ep_tracepoint_format_init (tracepoint_copy, tracepoint->tracepoint_format)); + dn_umap_result_t insert_result = dn_umap_insert (tracepoints_seen, tracepoint, tracepoint_copy); ep_raise_error_if_nok (insert_result.result); ep_raise_error_if_nok (dn_vector_ptr_push_back (tracepoint_config->tracepoints, tracepoint_copy)); From 6e8ea9567296d976574242091d61652982c9bdfa Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Sun, 8 Jun 2025 15:22:27 +0000 Subject: [PATCH 18/32] Fix CI Build failures --- src/native/eventpipe/ep-shared-config.h.in | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/native/eventpipe/ep-shared-config.h.in b/src/native/eventpipe/ep-shared-config.h.in index 512599fef5d02a..0eeb73e1dcb4f2 100644 --- a/src/native/eventpipe/ep-shared-config.h.in +++ b/src/native/eventpipe/ep-shared-config.h.in @@ -6,7 +6,8 @@ #cmakedefine01 HAVE_SYS_IOCTL_H #cmakedefine01 HAVE_SYS_SOCKET_H #cmakedefine01 HAVE_SYS_UIO_H -#cmakedefine01 HAVE_UNISTD_H +/* mono files use ifdef HAVE_UNISTD_H, so for compatibility */ +#cmakedefine HAVE_UNISTD_H 1 /* This platforms supports setting flags atomically when accepting connections. */ #cmakedefine01 HAVE_ACCEPT4 From a06f09196515e9c8653196a6f9b506849f980d08 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Mon, 9 Jun 2025 02:23:54 +0000 Subject: [PATCH 19/32] Split ProviderConfiguration structs --- src/native/eventpipe/ds-eventpipe-protocol.c | 202 ++++++++++++------- src/native/eventpipe/ep-session-provider.c | 194 +++++++++++++++++- src/native/eventpipe/ep-session-provider.h | 71 ++++++- src/native/eventpipe/ep-session.c | 6 +- src/native/eventpipe/ep-types-forward.h | 3 + src/native/eventpipe/ep-types.h | 69 +++---- src/native/eventpipe/ep.c | 165 --------------- 7 files changed, 419 insertions(+), 291 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 75b6b221120281..a39ea13d8ab553 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -60,6 +60,18 @@ eventpipe_collect_tracing_command_try_parse_stackwalk_requested ( uint32_t *buffer_len, bool *stackwalk_requested); +static +bool +eventpipe_collect_tracing_command_try_parse_event_ids ( + uint8_t **buffer, + uint32_t *buffer_len, + const uint32_t length, + uint32_t **event_ids); + +static +void +eventpipe_collect_tracing_command_free_event_filter (EventPipeProviderEventFilter *event_filter); + static bool eventpipe_collect_tracing_command_try_parse_event_filter ( @@ -67,6 +79,14 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( uint32_t *buffer_len, EventPipeProviderEventFilter *event_filter); +static +void +eventpipe_collect_tracing_command_free_tracepoint_set (EventPipeProviderTracepointSet *tracepoint_set); + +static +void +eventpipe_collect_tracing_command_free_tracepoint_config (EventPipeProviderTracepointConfiguration *tracepoint_config); + static bool eventpipe_collect_tracing_command_try_parse_tracepoint_config ( @@ -222,6 +242,52 @@ eventpipe_collect_tracing_command_try_parse_stackwalk_requested ( return ds_ipc_message_try_parse_bool (buffer, buffer_len, stackwalk_requested); } +static +bool +eventpipe_collect_tracing_command_try_parse_event_ids ( + uint8_t **buffer, + uint32_t *buffer_len, + const uint32_t length, + uint32_t **event_ids) +{ + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (event_ids != NULL); + + bool result = false; + + *event_ids = NULL; + if (length == 0) + return true; + + *event_ids = ep_rt_object_array_alloc (uint32_t, length); + ep_raise_error_if_nok (*event_ids != NULL); + for (uint32_t i = 0; i < length; ++i) + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &(*event_ids)[i])); + + result = true; + +ep_on_exit: + return result; + +ep_on_error: + ep_rt_object_array_free (*event_ids); + *event_ids = NULL; + + ep_exit_error_handler (); +} + +static +void +eventpipe_collect_tracing_command_free_event_filter (EventPipeProviderEventFilter *event_filter) +{ + ep_return_void_if_nok (event_filter != NULL); + + ep_rt_object_array_free ((uint32_t *)event_filter->event_ids); + + ep_rt_object_free (event_filter); +} + /* * eventpipe_collect_tracing_command_try_parse_event_filter * @@ -246,24 +312,15 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( EP_ASSERT (event_filter != NULL); bool result = false; - uint32_t event_id_array_len = 0; + uint32_t *event_ids = NULL; ep_raise_error_if_nok (ds_ipc_message_try_parse_bool (buffer, buffer_len, &event_filter->enable)); - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &event_id_array_len)); - if (event_id_array_len > 0) { - event_filter->event_ids = dn_umap_alloc (); - ep_raise_error_if_nok (event_filter->event_ids != NULL); + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &event_filter->length)); - for (uint32_t i = 0; i < event_id_array_len; ++i) { - uint32_t event_id; - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &event_id)); - dn_umap_result_t insert_result = dn_umap_ptr_uint32_insert (event_filter->event_ids, (void *)(uintptr_t)event_id, 0); - ep_raise_error_if_nok (insert_result.result); - } - } else { - event_filter->event_ids = NULL; - } + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_ids (buffer, buffer_len, event_filter->length, &event_ids)); + event_filter->event_ids = event_ids; + event_ids = NULL; // Ownership transferred to event_filter. result = true; @@ -271,11 +328,36 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( return result; ep_on_error: - ep_event_filter_fini (event_filter); - ep_exit_error_handler (); } +static +void +eventpipe_collect_tracing_command_free_tracepoint_sets (EventPipeProviderTracepointSet *tracepoint_set, uint32_t length) +{ + ep_return_void_if_nok (tracepoint_set != NULL); + + for (uint32_t i = 0; i < length; ++i) { + ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_set->tracepoint_name); + ep_rt_object_array_free ((uint32_t *)tracepoint_set->event_ids); + } + + ep_rt_object_array_free (tracepoint_set); +} + +static +void +eventpipe_collect_tracing_command_free_tracepoint_config (EventPipeProviderTracepointConfiguration *tracepoint_config) +{ + ep_return_void_if_nok (tracepoint_config != NULL); + + ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_config->default_tracepoint_name); + + eventpipe_collect_tracing_command_free_tracepoint_sets ((EventPipeProviderTracepointSet *)tracepoint_config->non_default_tracepoints, tracepoint_config->non_default_tracepoints_length); + + ep_rt_object_free (tracepoint_config); +} + /* * eventpipe_collect_tracing_command_try_parse_tracepoint_config * @@ -305,60 +387,38 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( bool result = false; - EventPipeTracepoint *tracepoint = NULL; ep_char8_t *tracepoint_name = NULL; - - uint32_t tracepoint_set_array_len = 0; - - tracepoint_config->tracepoints = NULL; - tracepoint_config->event_id_to_tracepoint_map = NULL; + EventPipeProviderTracepointSet *non_default_tracepoints = NULL; + uint32_t *event_ids = NULL; ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &tracepoint_name)); + tracepoint_config->default_tracepoint_name = tracepoint_name; + tracepoint_name = NULL; // Ownership transferred to tracepoint_config. - ep_raise_error_if_nok (ep_tracepoint_format_init (&tracepoint_config->default_tracepoint, tracepoint_name)); - ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); - tracepoint_name = NULL; + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &tracepoint_config->non_default_tracepoints_length)); - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &tracepoint_set_array_len)); - - if (tracepoint_set_array_len > 0) { - dn_vector_ptr_custom_alloc_params_t tracepoint_set_array_params = {0, }; - tracepoint_set_array_params.capacity = tracepoint_set_array_len; - tracepoint_config->tracepoints = dn_vector_ptr_custom_alloc (&tracepoint_set_array_params); - ep_raise_error_if_nok (tracepoint_config->tracepoints != NULL); - - tracepoint_config->event_id_to_tracepoint_map = dn_umap_alloc (); - ep_raise_error_if_nok (tracepoint_config->event_id_to_tracepoint_map != NULL); - - for (uint32_t i = 0; i < tracepoint_set_array_len; ++i) { - tracepoint = ep_rt_object_alloc (EventPipeTracepoint); // Ownership will be transferred to the tracepoint_config's tracepoint vector. - ep_raise_error_if_nok (tracepoint != NULL); - - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &tracepoint_name)); - ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (tracepoint_name)); - - ep_raise_error_if_nok (ep_tracepoint_format_init (tracepoint, tracepoint_name)); - ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); - tracepoint_name = NULL; + if (tracepoint_config->non_default_tracepoints_length > 0) { + non_default_tracepoints = ep_rt_object_array_alloc (EventPipeProviderTracepointSet, tracepoint_config->non_default_tracepoints_length); + ep_raise_error_if_nok (non_default_tracepoints != NULL); + } - uint32_t event_id_array_len = 0; - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &event_id_array_len)); - ep_raise_error_if_nok (event_id_array_len > 0); + for (uint32_t i = 0; i < tracepoint_config->non_default_tracepoints_length; ++i) { + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &tracepoint_name)); + ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (tracepoint_name)); + non_default_tracepoints[i].tracepoint_name = tracepoint_name; + tracepoint_name = NULL; // Ownership transferred to tracepoint_set. - for (uint32_t j = 0; j < event_id_array_len; ++j) { - uint32_t event_id; - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &event_id)); - dn_umap_result_t insert_result = dn_umap_insert (tracepoint_config->event_id_to_tracepoint_map, (void *)(uintptr_t)event_id, tracepoint); - ep_raise_error_if_nok (insert_result.result); - } + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &non_default_tracepoints[i].event_ids_length)); - ep_raise_error_if_nok (dn_vector_ptr_push_back (tracepoint_config->tracepoints, tracepoint)); - tracepoint = NULL; - // Ownership of tracepoint is transferred to the tracepoint_config's tracepoint vector. - } + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_ids (buffer, buffer_len, non_default_tracepoints[i].event_ids_length, &event_ids)); + non_default_tracepoints[i].event_ids = event_ids; + event_ids = NULL; // Ownership transferred to tracepoint_set. } - ep_raise_error_if_nok (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0' || tracepoint_config->tracepoints != NULL); + tracepoint_config->non_default_tracepoints = non_default_tracepoints; + non_default_tracepoints = NULL; // Ownership transferred to tracepoint_config. + + ep_raise_error_if_nok (tracepoint_config->default_tracepoint_name != NULL || tracepoint_config->non_default_tracepoints_length > 0); result = true; @@ -366,11 +426,9 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( return result; ep_on_error: - ep_rt_object_free (tracepoint); - tracepoint = NULL; - - ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_name); - tracepoint_name = NULL; + ep_rt_object_array_free (event_ids); + eventpipe_collect_tracing_command_free_tracepoint_sets ((EventPipeProviderTracepointSet *)non_default_tracepoints, tracepoint_config->non_default_tracepoints_length); + ep_rt_utf8_string_free (tracepoint_name); ep_exit_error_handler (); } @@ -426,7 +484,7 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( filter_data = NULL; // Ownership transferred to provider_config. if ((optional_field_flags & EP_PROVIDER_OPTFIELD_EVENT_FILTER) != 0) { - event_filter = ep_rt_object_alloc(EventPipeProviderEventFilter); + event_filter = ep_rt_object_alloc (EventPipeProviderEventFilter); ep_raise_error_if_nok (event_filter != NULL); ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_filter (buffer, buffer_len, event_filter)); provider_config->event_filter = event_filter; @@ -447,8 +505,8 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( return result; ep_on_error: - ep_tracepoint_config_free (tracepoint_config); - ep_event_filter_free (event_filter); + eventpipe_collect_tracing_command_free_tracepoint_config (tracepoint_config); + eventpipe_collect_tracing_command_free_event_filter (event_filter); ep_rt_utf8_string_free (filter_data); ep_rt_utf8_string_free (provider_name); @@ -509,8 +567,8 @@ eventpipe_collect_tracing_command_try_parse_config ( ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&provider_config)); ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&provider_config)); - ep_event_filter_free ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (&provider_config)); - ep_tracepoint_config_free ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (&provider_config)); + eventpipe_collect_tracing_command_free_event_filter ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (&provider_config)); + eventpipe_collect_tracing_command_free_tracepoint_config ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (&provider_config)); ep_exit_error_handler (); } @@ -530,8 +588,8 @@ ds_eventpipe_collect_tracing_command_payload_free (EventPipeCollectTracingComman DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) { ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); - ep_event_filter_free ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (&config)); - ep_tracepoint_config_free ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (&config)); + eventpipe_collect_tracing_command_free_event_filter ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (&config)); + eventpipe_collect_tracing_command_free_tracepoint_config ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (&config)); } DN_VECTOR_FOREACH_END; ep_rt_object_free (payload); diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index 1bc8fec075d04a..1c58e20aa07fd2 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -23,6 +23,31 @@ session_provider_compare_name_func ( const void *a, const void *b); +static +void +session_provider_event_filter_free (EventPipeSessionProviderEventFilter *event_filter); + +static +EventPipeSessionProviderEventFilter * +session_provider_event_filter_alloc (const EventPipeProviderEventFilter *event_filter); + +static +void +DN_CALLBACK_CALLTYPE +tracepoint_free_func (void *tracepoint); + +static +void +session_provider_tracepoint_config_free (EventPipeSessionProviderTracepointConfiguration *tracepoint_config); + +static +ep_char8_t * +tracepoint_format_alloc (const ep_char8_t *tracepoint_name); + +static +EventPipeSessionProviderTracepointConfiguration * +session_provider_tracepoint_config_alloc (const EventPipeProviderTracepointConfiguration *tracepoint_config); + static bool event_filter_allows_event_id ( @@ -51,6 +76,163 @@ session_provider_compare_name_func ( return (a) ? !ep_rt_utf8_string_compare (ep_session_provider_get_provider_name ((EventPipeSessionProvider *)a), (const ep_char8_t *)b) : false; } +static +void +session_provider_event_filter_free (EventPipeSessionProviderEventFilter *event_filter) +{ + ep_return_void_if_nok (event_filter != NULL); + + if (event_filter->event_ids != NULL) { + dn_umap_free (event_filter->event_ids); + event_filter->event_ids = NULL; + } + + ep_rt_object_free (event_filter); +} + +static +EventPipeSessionProviderEventFilter * +session_provider_event_filter_alloc (const EventPipeProviderEventFilter *event_filter) +{ + EP_ASSERT (event_filter != NULL); + + EventPipeSessionProviderEventFilter *instance = ep_rt_object_alloc (EventPipeSessionProviderEventFilter); + ep_raise_error_if_nok (instance != NULL); + + instance->enable = event_filter->enable; + + instance->event_ids = NULL; + if (event_filter->length > 0) { + instance->event_ids = dn_umap_alloc (); + ep_raise_error_if_nok (instance->event_ids != NULL); + + for (uint32_t i = 0; i < event_filter->length; ++i) { + dn_umap_result_t insert_result = dn_umap_ptr_uint32_insert (instance->event_ids, (void *)(uintptr_t)event_filter->event_ids[i], 0); + ep_raise_error_if_nok (insert_result.result); + } + } + +ep_on_exit: + return instance; + +ep_on_error: + session_provider_event_filter_free (instance); + instance = NULL; + ep_exit_error_handler (); +} + +static +void +DN_CALLBACK_CALLTYPE +tracepoint_free_func (void *tracepoint) +{ + EventPipeTracepoint *tp = *(EventPipeTracepoint **)tracepoint; + ep_rt_utf8_string_free ((ep_char8_t *)tp->tracepoint_format); + ep_rt_object_free (tp); +} + +static +void +session_provider_tracepoint_config_free (EventPipeSessionProviderTracepointConfiguration *tracepoint_config) +{ + ep_return_void_if_nok (tracepoint_config != NULL); + + if (tracepoint_config->event_id_to_tracepoint_map) { + dn_umap_free (tracepoint_config->event_id_to_tracepoint_map); + tracepoint_config->event_id_to_tracepoint_map = NULL; + } + + if (tracepoint_config->tracepoints) { + dn_vector_ptr_custom_free (tracepoint_config->tracepoints, tracepoint_free_func); + tracepoint_config->tracepoints = NULL; + } + + ep_rt_object_free (tracepoint_config); +} + +static +ep_char8_t * +tracepoint_format_alloc (const ep_char8_t *tracepoint_name) +{ + ep_return_null_if_nok (tracepoint_name != NULL && tracepoint_name[0] != '\0'); + + int32_t res = 0; + size_t tracepoint_format_len = strlen(tracepoint_name) + strlen(EP_TRACEPOINT_FORMAT_V1) + 2; // +2 for space and null terminator + ep_char8_t *tracepoint_format = ep_rt_utf8_string_alloc (tracepoint_format_len); + ep_raise_error_if_nok (tracepoint_format != NULL); + + res = snprintf(tracepoint_format, tracepoint_format_len, "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); + ep_raise_error_if_nok (res >= 0 && (size_t)res < tracepoint_format_len); + +ep_on_exit: + return tracepoint_format; + +ep_on_error: + ep_rt_utf8_string_free (tracepoint_format); + tracepoint_format = NULL; + ep_exit_error_handler (); +} + +static +EventPipeSessionProviderTracepointConfiguration * +session_provider_tracepoint_config_alloc (const EventPipeProviderTracepointConfiguration *tracepoint_config) +{ + EP_ASSERT (tracepoint_config != NULL); + + EventPipeSessionProviderTracepointConfiguration *instance = ep_rt_object_alloc (EventPipeSessionProviderTracepointConfiguration); + EventPipeTracepoint *tracepoint = NULL; + ep_raise_error_if_nok (instance != NULL); + + instance->default_tracepoint.tracepoint_format = tracepoint_format_alloc (tracepoint_config->default_tracepoint_name); + + instance->tracepoints = NULL; + instance->event_id_to_tracepoint_map = NULL; + + if (tracepoint_config->non_default_tracepoints_length > 0) { + dn_vector_ptr_custom_alloc_params_t tracepoints_array_params = {0, }; + tracepoints_array_params.capacity = tracepoint_config->non_default_tracepoints_length; + instance->tracepoints = dn_vector_ptr_custom_alloc (&tracepoints_array_params); + ep_raise_error_if_nok (instance->tracepoints != NULL); + + instance->event_id_to_tracepoint_map = dn_umap_alloc (); + ep_raise_error_if_nok (instance->event_id_to_tracepoint_map != NULL); + + for (uint32_t i = 0; i < tracepoint_config->non_default_tracepoints_length; ++i) { + const EventPipeProviderTracepointSet *tracepoint_set = &tracepoint_config->non_default_tracepoints[i]; + + tracepoint = ep_rt_object_alloc (EventPipeTracepoint); + ep_raise_error_if_nok (tracepoint != NULL); + + tracepoint->tracepoint_format = tracepoint_format_alloc (tracepoint_set->tracepoint_name); + ep_raise_error_if_nok (tracepoint->tracepoint_format != NULL); + + for (uint32_t j = 0; j < tracepoint_set->event_ids_length; ++j) { + uint32_t event_id = tracepoint_set->event_ids[j]; + + dn_umap_result_t insert_result = dn_umap_insert (instance->event_id_to_tracepoint_map, (void *)(uintptr_t)event_id, tracepoint); + ep_raise_error_if_nok (insert_result.result); + } + + ep_raise_error_if_nok (dn_vector_ptr_push_back (instance->tracepoints, tracepoint)); + tracepoint = NULL; // Ownership transferred to the session provider tracepoint configuration. + } + } + + ep_raise_error_if_nok (instance->default_tracepoint.tracepoint_format != NULL || instance->tracepoints != NULL); + +ep_on_exit: + return instance; + +ep_on_error: + if (tracepoint != NULL) { + ep_rt_utf8_string_free ((ep_char8_t *)tracepoint->tracepoint_format); + ep_rt_object_free (tracepoint); + } + session_provider_tracepoint_config_free (instance); + instance = NULL; + ep_exit_error_handler (); +} + EventPipeSessionProvider * ep_session_provider_alloc ( const ep_char8_t *provider_name, @@ -79,12 +261,12 @@ ep_session_provider_alloc ( instance->tracepoint_config = NULL; if (event_filter) { - instance->event_filter = ep_provider_event_filter_dup (event_filter); + instance->event_filter = session_provider_event_filter_alloc (event_filter); ep_raise_error_if_nok (instance->event_filter != NULL); } if (tracepoint_config) { - instance->tracepoint_config = ep_provider_tracepoint_config_dup (tracepoint_config); + instance->tracepoint_config = session_provider_tracepoint_config_alloc (tracepoint_config); ep_raise_error_if_nok (instance->tracepoint_config != NULL); } @@ -102,8 +284,8 @@ ep_session_provider_free (EventPipeSessionProvider * session_provider) { ep_return_void_if_nok (session_provider != NULL); - ep_tracepoint_config_free (session_provider->tracepoint_config); - ep_event_filter_free (session_provider->event_filter); + session_provider_tracepoint_config_free (session_provider->tracepoint_config); + session_provider_event_filter_free ((EventPipeSessionProviderEventFilter *)session_provider->event_filter); ep_rt_utf8_string_free (session_provider->filter_data); ep_rt_utf8_string_free (session_provider->provider_name); ep_rt_object_free (session_provider); @@ -112,7 +294,7 @@ ep_session_provider_free (EventPipeSessionProvider * session_provider) static bool event_filter_allows_event_id ( - const EventPipeProviderEventFilter *event_filter, + const EventPipeSessionProviderEventFilter *event_filter, uint32_t event_id) { if (event_filter == NULL) @@ -144,7 +326,7 @@ ep_session_provider_allows_event ( return false; uint32_t event_id = ep_event_get_event_id (ep_event); - EventPipeProviderEventFilter *event_filter = ep_session_provider_get_event_filter (session_provider); + const EventPipeSessionProviderEventFilter *event_filter = ep_session_provider_get_event_filter (session_provider); return event_filter_allows_event_id (event_filter, event_id); } diff --git a/src/native/eventpipe/ep-session-provider.h b/src/native/eventpipe/ep-session-provider.h index fe17e134726582..2f4db2d8030e45 100644 --- a/src/native/eventpipe/ep-session-provider.h +++ b/src/native/eventpipe/ep-session-provider.h @@ -11,6 +11,69 @@ #endif #include "ep-getter-setter.h" +/* + * EventPipeTracepoint. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_EP_GETTER_SETTER) +struct _EventPipeTracepoint { +#else +struct _EventPipeTracepoint_Internal { +#endif + const ep_char8_t *tracepoint_format; + uint32_t write_index; + uint32_t enabled; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_EP_GETTER_SETTER) +struct _EventPipeTracepoint { + uint8_t _internal [sizeof (struct _EventPipeTracepoint_Internal)]; +}; +#endif + + +/* + * EventPipeSessionProviderEventFilter. + * + * Used in conjunction with keywords and logging level to determine + * whether an event should be enabled for the session. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_EP_GETTER_SETTER) +struct _EventPipeSessionProviderEventFilter { +#else +struct _EventPipeSessionProviderEventFilter_Internal { +#endif + bool enable; + dn_umap_t *event_ids; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_EP_GETTER_SETTER) +struct _EventPipeSessionProviderEventFilter { + uint8_t _internal [sizeof (struct _EventPipeSessionProviderEventFilter_Internal)]; +}; +#endif + +/* + * EventPipeSessionProviderTracepointConfiguration. + */ + +#if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_EP_GETTER_SETTER) +struct _EventPipeSessionProviderTracepointConfiguration { +#else +struct _EventPipeSessionProviderTracepointConfiguration_Internal { +#endif + EventPipeTracepoint default_tracepoint; + dn_vector_ptr_t *tracepoints; + dn_umap_t *event_id_to_tracepoint_map; +}; + +#if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_EP_GETTER_SETTER) +struct _EventPipeSessionProviderTracepointConfiguration { + uint8_t _internal [sizeof (struct _EventPipeSessionProviderTracepointConfiguration_Internal)]; +}; +#endif + /* * EventPipeSessionProvider. */ @@ -24,8 +87,8 @@ struct _EventPipeSessionProvider_Internal { uint64_t keywords; EventPipeEventLevel logging_level; ep_char8_t *filter_data; - EventPipeProviderEventFilter *event_filter; - EventPipeProviderTracepointConfiguration *tracepoint_config; + const EventPipeSessionProviderEventFilter *event_filter; + EventPipeSessionProviderTracepointConfiguration *tracepoint_config; }; #if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_SESSION_PROVIDER_GETTER_SETTER) @@ -38,8 +101,8 @@ EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, const ep_char8_t EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, uint64_t, keywords) EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, EventPipeEventLevel, logging_level) EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, const ep_char8_t *, filter_data) -EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, EventPipeProviderEventFilter *, event_filter) -EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, EventPipeProviderTracepointConfiguration *, tracepoint_config) +EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, const EventPipeSessionProviderEventFilter *, event_filter) +EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, EventPipeSessionProviderTracepointConfiguration *, tracepoint_config) EventPipeSessionProvider * ep_session_provider_alloc ( diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 00db20540bc280..44bb475141f43b 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -314,7 +314,7 @@ session_user_events_tracepoints_init ( EventPipeSessionProvider *session_provider = *dn_list_it_data_t (it, EventPipeSessionProvider *); EP_ASSERT (session_provider != NULL); - EventPipeProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); + EventPipeSessionProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); EP_ASSERT (tracepoint_config != NULL); EP_ASSERT (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0' || tracepoint_config->tracepoints != NULL); @@ -733,7 +733,7 @@ session_disable_user_events (EventPipeSession *session) EP_ASSERT (providers != NULL); for (dn_list_it_t it = dn_list_begin (ep_session_provider_list_get_providers (providers)); !dn_list_it_end (it); it = dn_list_it_next (it)) { EventPipeSessionProvider *session_provider = *dn_list_it_data_t (it, EventPipeSessionProvider *); - EventPipeProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); + EventPipeSessionProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); if (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0') session_unregister_tracepoint (session, &tracepoint_config->default_tracepoint); @@ -768,7 +768,7 @@ session_get_tracepoint_for_event ( EventPipeProvider *provider = ep_event_get_provider (ep_event); EventPipeSessionProviderList *session_provider_list = ep_session_get_providers (session); EventPipeSessionProvider *session_provider = ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (session_provider_list), ep_provider_get_provider_name (provider)); - EventPipeProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); + EventPipeSessionProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); if (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0') tracepoint = &tracepoint_config->default_tracepoint; diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index d220f61478ab75..41b88efcd4b216 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -33,10 +33,13 @@ typedef struct _EventPipeProviderCallbackDataQueue EventPipeProviderCallbackData typedef struct _EventPipeProviderConfiguration EventPipeProviderConfiguration; typedef struct _EventPipeProviderEventFilter EventPipeProviderEventFilter; typedef struct _EventPipeProviderTracepointConfiguration EventPipeProviderTracepointConfiguration; +typedef struct _EventPipeProviderTracepointSet EventPipeProviderTracepointSet; typedef struct _EventPipeExecutionCheckpoint EventPipeExecutionCheckpoint; typedef struct _EventPipeSession EventPipeSession; typedef struct _EventPipeSessionProvider EventPipeSessionProvider; +typedef struct _EventPipeSessionProviderEventFilter EventPipeSessionProviderEventFilter; typedef struct _EventPipeSessionProviderList EventPipeSessionProviderList; +typedef struct _EventPipeSessionProviderTracepointConfiguration EventPipeSessionProviderTracepointConfiguration; typedef struct _EventPipeSequencePoint EventPipeSequencePoint; typedef struct _EventPipeSequencePointBlock EventPipeSequencePointBlock; typedef struct _EventPipeStackBlock EventPipeStackBlock; diff --git a/src/native/eventpipe/ep-types.h b/src/native/eventpipe/ep-types.h index b693971bf19f11..e431a7ebfa2c2c 100644 --- a/src/native/eventpipe/ep-types.h +++ b/src/native/eventpipe/ep-types.h @@ -176,60 +176,56 @@ ep_provider_callback_data_queue_try_dequeue ( EventPipeProviderCallbackData *provider_callback_data); /* - * EventPipeTracepoint. + * EventPipeProviderEventFilter. + * + * Used as read-only data to configure a SessionProvider's set EventFilter, + * matching the DiagnosticServer IPC Protocol encoding specification. */ #if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_EP_GETTER_SETTER) -struct _EventPipeTracepoint { +struct _EventPipeProviderEventFilter { #else -struct _EventPipeTracepoint_Internal { +struct _EventPipeProviderEventFilter_Internal { #endif - const ep_char8_t *tracepoint_format; - uint32_t write_index; - uint32_t enabled; + bool enable; + uint32_t length; + const uint32_t *event_ids; }; #if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_EP_GETTER_SETTER) -struct _EventPipeTracepoint { - uint8_t _internal [sizeof (struct _EventPipeTracepoint_Internal)]; +struct _EventPipeProviderEventFilter { + uint8_t _internal [sizeof (struct _EventPipeProviderEventFilter_Internal)]; }; #endif -bool -ep_tracepoint_format_init ( - EventPipeTracepoint *tracepoint, - const ep_char8_t *tracepoint_name); - /* - * EventPipeProviderEventFilter. + * EventPipeProviderTracepointSet. + * + * Used as read-only data to configure a Tracepoint Configuration's set of non-default + * tracepoints, matching the DiagnosticServer IPC Protocol encoding specification. */ #if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_EP_GETTER_SETTER) -struct _EventPipeProviderEventFilter { +struct _EventPipeProviderTracepointSet { #else -struct _EventPipeProviderEventFilter_Internal { +struct _EventPipeProviderTracepointSet_Internal { #endif - bool enable; - dn_umap_t *event_ids; + const ep_char8_t *tracepoint_name; + const uint32_t *event_ids; + uint32_t event_ids_length; }; #if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_EP_GETTER_SETTER) -struct _EventPipeProviderEventFilter { - uint8_t _internal [sizeof (struct _EventPipeProviderEventFilter_Internal)]; +struct _EventPipeProviderTracepointSet { + uint8_t _internal [sizeof (struct _EventPipeProviderTracepointSet_Internal)]; }; #endif -EventPipeProviderEventFilter * -ep_provider_event_filter_dup (const EventPipeProviderEventFilter *event_filter_src); - -void -ep_event_filter_fini (EventPipeProviderEventFilter *event_filter); - -void -ep_event_filter_free (EventPipeProviderEventFilter *event_filter); - /* * EventPipeProviderTracepointConfiguration. + * + * Used as read-only data to configure the SessionProvider's Tracepoint + * configuration, matching the DiagnosticServer IPC Protocol encoding specification. */ #if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_EP_GETTER_SETTER) @@ -237,9 +233,9 @@ struct _EventPipeProviderTracepointConfiguration { #else struct _EventPipeProviderTracepointConfiguration_Internal { #endif - EventPipeTracepoint default_tracepoint; - dn_vector_ptr_t *tracepoints; - dn_umap_t *event_id_to_tracepoint_map; + const ep_char8_t *default_tracepoint_name; + const EventPipeProviderTracepointSet *non_default_tracepoints; + uint32_t non_default_tracepoints_length; }; #if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_EP_GETTER_SETTER) @@ -248,15 +244,6 @@ struct _EventPipeProviderTracepointConfiguration { }; #endif -EventPipeProviderTracepointConfiguration * -ep_provider_tracepoint_config_dup (const EventPipeProviderTracepointConfiguration *tracepoint_config); - -void -ep_tracepoint_config_fini (EventPipeProviderTracepointConfiguration *tracepoint_config); - -void -ep_tracepoint_config_free (EventPipeProviderTracepointConfiguration *tracepoint_config); - /* * EventPipeProviderConfiguration. */ diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index cd3383ef842081..a6b7b35f49c365 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -1755,171 +1755,6 @@ ep_ipc_stream_factory_callback_set (EventPipeIpcStreamFactorySuspendedPortsCallb _ep_ipc_stream_factory_suspended_ports_callback = suspended_ports_callback; } -bool -ep_tracepoint_format_init ( - EventPipeTracepoint *tracepoint, - const ep_char8_t *tracepoint_name) -{ - EP_ASSERT (tracepoint != NULL); - - bool result = false; - int32_t res = 0; - - tracepoint->tracepoint_format = NULL; - if (tracepoint_name == NULL || tracepoint_name[0] == '\0') - return true; - - size_t tracepoint_format_len = strlen(tracepoint_name) + strlen(EP_TRACEPOINT_FORMAT_V1) + 2; // +2 for space and null terminator - ep_char8_t *tracepoint_format = ep_rt_utf8_string_alloc (tracepoint_format_len); - ep_raise_error_if_nok (tracepoint_format != NULL); - res = snprintf(tracepoint_format, sizeof(tracepoint_format), "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); - ep_raise_error_if_nok (res >= 0 && (size_t)res < sizeof(tracepoint_format)); - tracepoint->tracepoint_format = tracepoint_format; - tracepoint_format = NULL; - - result = true; - -ep_on_exit: - return result; - -ep_on_error: - ep_rt_utf8_string_free (tracepoint_format); - ep_exit_error_handler (); -} - -EventPipeProviderEventFilter * -ep_provider_event_filter_dup (const EventPipeProviderEventFilter *event_filter_src) -{ - ep_return_null_if_nok (event_filter_src != NULL); - - EventPipeProviderEventFilter *event_filter = ep_rt_object_alloc (EventPipeProviderEventFilter); - ep_return_null_if_nok (event_filter != NULL); - - event_filter->enable = event_filter_src->enable; - event_filter->event_ids = dn_umap_alloc (); - ep_return_null_if_nok (event_filter->event_ids != NULL); - - DN_UMAP_FOREACH_KEY_BEGIN (uint32_t *, event_id, event_filter_src->event_ids) { - dn_umap_result_t insert_result = dn_umap_ptr_uint32_insert (event_filter->event_ids, event_id, 0); - ep_raise_error_if_nok (insert_result.result); - } DN_UMAP_FOREACH_END; - -ep_on_exit: - return event_filter; - -ep_on_error: - ep_event_filter_free (event_filter); - event_filter = NULL; - ep_exit_error_handler (); -} - -void -ep_event_filter_fini (EventPipeProviderEventFilter *event_filter) -{ - ep_return_void_if_nok (event_filter != NULL); - - if (event_filter->event_ids) { - dn_umap_free (event_filter->event_ids); - event_filter->event_ids = NULL; - } -} - -void -ep_event_filter_free (EventPipeProviderEventFilter *event_filter) -{ - ep_return_void_if_nok (event_filter != NULL); - - ep_event_filter_fini (event_filter); - ep_rt_object_free (event_filter); -} - -EventPipeProviderTracepointConfiguration * -ep_provider_tracepoint_config_dup (const EventPipeProviderTracepointConfiguration *tracepoint_config_src) -{ - ep_return_null_if_nok (tracepoint_config_src != NULL); - - EventPipeProviderTracepointConfiguration *tracepoint_config = ep_rt_object_alloc (EventPipeProviderTracepointConfiguration); - ep_return_null_if_nok (tracepoint_config != NULL); - - EventPipeTracepoint *tracepoint_copy = NULL; - dn_umap_t *tracepoints_seen = NULL; - ep_raise_error_if_nok (ep_tracepoint_format_init (&tracepoint_config->default_tracepoint, tracepoint_config_src->default_tracepoint.tracepoint_format)); - - tracepoint_config->tracepoints = NULL; - if (tracepoint_config_src->tracepoints) { - dn_vector_ptr_custom_alloc_params_t tracepoint_set_array_params = {0, }; - tracepoint_set_array_params.capacity = tracepoint_config_src->tracepoints->size; - tracepoint_config->tracepoints = dn_vector_ptr_custom_alloc (&tracepoint_set_array_params); - ep_raise_error_if_nok (tracepoint_config->tracepoints != NULL); - - tracepoint_config->event_id_to_tracepoint_map = dn_umap_alloc (); - ep_raise_error_if_nok (tracepoint_config->event_id_to_tracepoint_map != NULL); - - tracepoints_seen = dn_umap_alloc (); - ep_raise_error_if_nok (tracepoints_seen != NULL); - - DN_UMAP_FOREACH_BEGIN (uint32_t *, event_id, EventPipeTracepoint *, tracepoint, tracepoint_config_src->event_id_to_tracepoint_map) { - if (!dn_umap_extract_key (tracepoints_seen, tracepoint, NULL, (void **)&tracepoint_copy)) { - tracepoint_copy = ep_rt_object_alloc (EventPipeTracepoint); - ep_return_null_if_nok (tracepoint_copy != NULL); - ep_raise_error_if_nok (ep_tracepoint_format_init (tracepoint_copy, tracepoint->tracepoint_format)); - - dn_umap_result_t insert_result = dn_umap_insert (tracepoints_seen, tracepoint, tracepoint_copy); - ep_raise_error_if_nok (insert_result.result); - ep_raise_error_if_nok (dn_vector_ptr_push_back (tracepoint_config->tracepoints, tracepoint_copy)); - } - dn_umap_result_t insert_result = dn_umap_insert (tracepoint_config->event_id_to_tracepoint_map, event_id, tracepoint_copy); - ep_raise_error_if_nok (insert_result.result); - } DN_UMAP_FOREACH_END; - } - -ep_on_exit: - dn_umap_free (tracepoints_seen); - return tracepoint_config; - -ep_on_error: - if (tracepoint_copy != NULL) { - ep_rt_object_free (tracepoint_copy); - tracepoint_copy = NULL; - } - ep_tracepoint_config_free (tracepoint_config); - tracepoint_config = NULL; - ep_exit_error_handler (); -} - -static -void -DN_CALLBACK_CALLTYPE -tracepoint_free_func (void *tracepoint) -{ - ep_rt_object_free (*(EventPipeTracepoint **)tracepoint); -} - -void -ep_tracepoint_config_fini (EventPipeProviderTracepointConfiguration *tracepoint_config) -{ - ep_return_void_if_nok (tracepoint_config != NULL); - - if (tracepoint_config->event_id_to_tracepoint_map) { - dn_umap_free (tracepoint_config->event_id_to_tracepoint_map); - tracepoint_config->event_id_to_tracepoint_map = NULL; - } - - if (tracepoint_config->tracepoints) { - dn_vector_ptr_custom_free (tracepoint_config->tracepoints, tracepoint_free_func); - tracepoint_config->tracepoints = NULL; - } -} - -void -ep_tracepoint_config_free (EventPipeProviderTracepointConfiguration *tracepoint_config) -{ - ep_return_void_if_nok (tracepoint_config != NULL); - - ep_tracepoint_config_fini (tracepoint_config); - ep_rt_object_free (tracepoint_config); -} - #endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ #endif /* ENABLE_PERFTRACING */ From 677b7d98a61da279edfa28ef5dd93b1f1a9afa3e Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Tue, 10 Jun 2025 15:18:12 +0000 Subject: [PATCH 20/32] Reuse EventPipeSessionTypes --- src/native/eventpipe/ds-eventpipe-protocol.c | 38 ++++++++++++-------- src/native/eventpipe/ep-types-forward.h | 9 ----- 2 files changed, 24 insertions(+), 23 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index a39ea13d8ab553..c7a549dea6ba85 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -622,7 +622,7 @@ eventpipe_collect_tracing_command_try_parse_payload ( instance->rundown_requested = true; instance->stackwalk_requested = true; instance->rundown_keyword = ep_default_rundown_keyword; - instance->session_type = EP_IPC_SESSION_TYPE_STREAMING; + instance->session_type = EP_SESSION_TYPE_IPCSTREAM; ep_on_exit: return (uint8_t *)instance; @@ -658,7 +658,7 @@ eventpipe_collect_tracing2_command_try_parse_payload ( instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; instance->stackwalk_requested = true; - instance->session_type = EP_IPC_SESSION_TYPE_STREAMING; + instance->session_type = EP_SESSION_TYPE_IPCSTREAM; ep_on_exit: return (uint8_t *)instance; @@ -693,7 +693,7 @@ eventpipe_collect_tracing3_command_try_parse_payload ( ep_raise_error (); instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; - instance->session_type = EP_IPC_SESSION_TYPE_STREAMING; + instance->session_type = EP_SESSION_TYPE_IPCSTREAM; ep_on_exit: return (uint8_t *)instance; @@ -728,7 +728,7 @@ eventpipe_collect_tracing4_command_try_parse_payload ( ep_raise_error (); instance->rundown_requested = instance->rundown_keyword != 0; - instance->session_type = EP_IPC_SESSION_TYPE_STREAMING; + instance->session_type = EP_SESSION_TYPE_IPCSTREAM; ep_on_exit: return (uint8_t *)instance; @@ -757,6 +757,7 @@ eventpipe_collect_tracing5_command_try_parse_payload ( uint8_t * buffer_cursor = buffer; uint32_t buffer_cursor_len = buffer_len; + uint32_t session_type = 0; EventPipeProviderOptionalFieldFlags optional_field_flags = EP_PROVIDER_OPTFIELD_EVENT_FILTER; EventPipeCollectTracingCommandPayload *instance = ds_eventpipe_collect_tracing_command_payload_alloc (); @@ -764,26 +765,35 @@ eventpipe_collect_tracing5_command_try_parse_payload ( instance->incoming_buffer = buffer; - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (&buffer_cursor, &buffer_cursor_len, &instance->session_type)); - ep_raise_error_if_nok (instance->session_type < EP_IPC_SESSION_TYPE_COUNT); + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (&buffer_cursor, &buffer_cursor_len, &session_type)); + switch (session_type) { + case 0: + instance->session_type = EP_SESSION_TYPE_IPCSTREAM; + break; + case 1: + instance->session_type = EP_SESSION_TYPE_USEREVENTS; + break; + default: + ep_raise_error (); + } - if (instance->session_type == EP_IPC_SESSION_TYPE_STREAMING) { + if (instance->session_type == EP_SESSION_TYPE_IPCSTREAM) { ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_circular_buffer_size (&buffer_cursor, &buffer_cursor_len, &instance->circular_buffer_size_in_mb)); ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format)); - } else if (instance->session_type == EP_IPC_SESSION_TYPE_USEREVENTS) { + } else if (instance->session_type == EP_SESSION_TYPE_USEREVENTS) { instance->circular_buffer_size_in_mb = 0; instance->serialization_format = EP_SERIALIZATION_FORMAT_NETTRACE_V4; // Serialization format isn't used for user_events sessions, default for check_options_valid. } ep_raise_error_if_nok (ds_ipc_message_try_parse_uint64_t (&buffer_cursor, &buffer_cursor_len, &instance->rundown_keyword)); - if (instance->session_type == EP_IPC_SESSION_TYPE_STREAMING) { + if (instance->session_type == EP_SESSION_TYPE_IPCSTREAM) { ep_raise_error_if_nok (ds_ipc_message_try_parse_bool (&buffer_cursor, &buffer_cursor_len, &instance->stackwalk_requested)); - } else if (instance->session_type == EP_IPC_SESSION_TYPE_USEREVENTS) { + } else if (instance->session_type == EP_SESSION_TYPE_USEREVENTS) { instance->stackwalk_requested = false; } - if (instance->session_type == EP_IPC_SESSION_TYPE_USEREVENTS) + if (instance->session_type == EP_SESSION_TYPE_USEREVENTS) optional_field_flags = (EventPipeProviderOptionalFieldFlags)(optional_field_flags | EP_PROVIDER_OPTFIELD_TRACEPOINT_CONFIG); ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, optional_field_flags, &instance->provider_configs)); @@ -889,7 +899,7 @@ eventpipe_protocol_helper_collect_tracing ( } int user_events_data_fd = 0; - if (payload->session_type == EP_IPC_SESSION_TYPE_USEREVENTS) { + if (payload->session_type == EP_SESSION_TYPE_USEREVENTS) { if (!ds_ipc_stream_read_fd (stream, &user_events_data_fd)) { ds_ipc_message_send_error (stream, DS_IPC_E_BAD_ENCODING); return false; @@ -903,11 +913,11 @@ eventpipe_protocol_helper_collect_tracing ( payload->circular_buffer_size_in_mb, dn_vector_data_t (payload->provider_configs, EventPipeProviderConfiguration), dn_vector_size (payload->provider_configs), - payload->session_type == EP_IPC_SESSION_TYPE_USEREVENTS ? EP_SESSION_TYPE_USEREVENTS : EP_SESSION_TYPE_IPCSTREAM, + payload->session_type == EP_SESSION_TYPE_USEREVENTS ? EP_SESSION_TYPE_USEREVENTS : EP_SESSION_TYPE_IPCSTREAM, payload->serialization_format, payload->rundown_keyword, payload->stackwalk_requested, - payload->session_type == EP_IPC_SESSION_TYPE_STREAMING ? ds_ipc_stream_get_stream_ref (stream) : NULL, + payload->session_type == EP_SESSION_TYPE_IPCSTREAM ? ds_ipc_stream_get_stream_ref (stream) : NULL, NULL, NULL, user_events_data_fd); diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index 41b88efcd4b216..93ba6b7e5c7fc5 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -202,15 +202,6 @@ typedef enum EP_PROVIDER_OPTFIELD_TRACEPOINT_CONFIG = 2 } EventPipeProviderOptionalFieldFlags; -/* - * EventPipe session types that can be started via IPC commands. - */ -typedef enum { - EP_IPC_SESSION_TYPE_STREAMING, - EP_IPC_SESSION_TYPE_USEREVENTS, - EP_IPC_SESSION_TYPE_COUNT -} EventPipeIPCSessionType; - /* * EventPipe Basic Types. */ From db7a3f5d83c5390084d6f6f9d12462b185203bde Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Tue, 10 Jun 2025 17:44:37 +0000 Subject: [PATCH 21/32] Constrain tracepoint_config modification to session provider --- src/native/eventpipe/ep-session-provider.c | 203 ++++++++++++++++++++- src/native/eventpipe/ep-session-provider.h | 20 +- src/native/eventpipe/ep-session.c | 174 ++---------------- src/native/eventpipe/ep-types-forward.h | 2 +- 4 files changed, 230 insertions(+), 169 deletions(-) diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index 1c58e20aa07fd2..3b9dd737f485c3 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -7,6 +7,14 @@ #include "ep-session-provider.h" #include "ep-rt.h" +#if HAVE_LINUX_USER_EVENTS_H +#include // DIAG_IOCSREG +#endif // HAVE_LINUX_USER_EVENTS_H + +#if HAVE_SYS_IOCTL_H +#include // session_register_tracepoint +#endif // HAVE_SYS_IOCTL_H + /* * Forward declares of all static functions. */ @@ -31,6 +39,18 @@ static EventPipeSessionProviderEventFilter * session_provider_event_filter_alloc (const EventPipeProviderEventFilter *event_filter); +static +bool +session_provider_tracepoint_register ( + EventPipeSessionProviderTracepoint *tracepoint, + int user_events_data_fd); + +static +bool +session_provider_tracepoint_unregister ( + EventPipeSessionProviderTracepoint *tracepoint, + int user_events_data_fd); + static void DN_CALLBACK_CALLTYPE @@ -121,12 +141,186 @@ session_provider_event_filter_alloc (const EventPipeProviderEventFilter *event_f ep_exit_error_handler (); } +/* + * EventPipeSessionProviderTracepoint. + */ + +#if HAVE_LINUX_USER_EVENTS_H && HAVE_SYS_IOCTL_H +static +bool +session_provider_tracepoint_register ( + EventPipeSessionProviderTracepoint *tracepoint, + int user_events_data_fd) +{ + EP_ASSERT (tracepoint != NULL); + EP_ASSERT (user_events_data_fd != 0); + struct user_reg reg = {0}; + + reg.size = sizeof(reg); + reg.enable_bit = EP_TRACEPOINT_ENABLE_BIT; + reg.enable_size = sizeof(tracepoint->enabled); + reg.enable_addr = (uint64_t)&tracepoint->enabled; + + reg.name_args = (uint64_t)tracepoint->tracepoint_format; + + if (ioctl(user_events_data_fd, DIAG_IOCSREG, ®) == -1) + return false; + + tracepoint->write_index = reg.write_index; + + return true; +} + +static +bool +session_provider_tracepoint_unregister ( + EventPipeSessionProviderTracepoint *tracepoint, + int user_events_data_fd) +{ + EP_ASSERT (tracepoint != NULL); + EP_ASSERT (user_events_data_fd != 0); + struct user_unreg unreg = {0}; + + unreg.size = sizeof(unreg); + unreg.disable_bit = EP_TRACEPOINT_ENABLE_BIT; + unreg.disable_addr = (uint64_t)&tracepoint->enabled; + + if (ioctl(user_events_data_fd, DIAG_IOCSUNREG, &unreg) == -1) + return false; + + return true; +} +#else // HAVE_LINUX_USER_EVENTS_H && HAVE_SYS_IOCTL_H +static +bool +session_provider_tracepoint_register ( + EventPipeSessionProviderTracepoint *tracepoint, + int user_events_data_fd) +{ + // Not Supported + return false; +} + +static +bool +session_provider_tracepoint_unregister ( + EventPipeSessionProviderTracepoint *tracepoint, + int user_events_data_fd) +{ + // Not Supported + return false; +} +#endif // HAVE_LINUX_USER_EVENTS_H && HAVE_SYS_IOCTL_H + +/* + * ep_session_provider_register_tracepoints + * + * Registers the tracepoints configured for the session provider with the user events data file descriptor. + * + * Returns true if the session_provider has tracepoints and all were successfully registered. + */ +bool +ep_session_provider_register_tracepoints ( + EventPipeSessionProvider *session_provider, + int user_events_data_fd) +{ + EP_ASSERT (session_provider != NULL); + EP_ASSERT (user_events_data_fd > 0); + + if (user_events_data_fd <= 0) + return false; + + EventPipeSessionProviderTracepointConfiguration *tracepoint_config = session_provider->tracepoint_config; + if (tracepoint_config == NULL) + return false; + + if (tracepoint_config->default_tracepoint.tracepoint_format == NULL && tracepoint_config->tracepoints == NULL) + return false; + + if (tracepoint_config->default_tracepoint.tracepoint_format != NULL && + !session_provider_tracepoint_register (&tracepoint_config->default_tracepoint, user_events_data_fd)) + return false; + + if (tracepoint_config->tracepoints != NULL) { + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeSessionProviderTracepoint *, tracepoint, tracepoint_config->tracepoints) { + EP_ASSERT (tracepoint != NULL); + if (!session_provider_tracepoint_register (tracepoint, user_events_data_fd)) + return false; + } DN_VECTOR_PTR_FOREACH_END; + } + + return true; +} + +/* + * ep_session_provider_unregister_tracepoints + * + * Attempts to unregister all tracepoints configured for the session provider with the user events data file descriptor. + */ +void +ep_session_provider_unregister_tracepoints ( + EventPipeSessionProvider *session_provider, + int user_events_data_fd) +{ + EP_ASSERT (session_provider != NULL); + EP_ASSERT (user_events_data_fd > 0); + + if (user_events_data_fd <= 0) + return; + + if (session_provider->tracepoint_config == NULL) + return; + + EventPipeSessionProviderTracepointConfiguration *tracepoint_config = session_provider->tracepoint_config; + if (tracepoint_config->default_tracepoint.tracepoint_format != NULL) + session_provider_tracepoint_unregister (&tracepoint_config->default_tracepoint, user_events_data_fd); + + if (tracepoint_config->tracepoints != NULL) { + DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeSessionProviderTracepoint *, tracepoint, tracepoint_config->tracepoints) { + EP_ASSERT (tracepoint != NULL); + session_provider_tracepoint_unregister (tracepoint, user_events_data_fd); + } DN_VECTOR_PTR_FOREACH_END; + } +} + +/* + * ep_session_provider_get_tracepoint_for_event + * + * Returns the session provider's tracepoint associated with the EventPipeEvent. + */ +const EventPipeSessionProviderTracepoint * +ep_session_provider_get_tracepoint_for_event ( + const EventPipeSessionProvider *session_provider, + const EventPipeEvent *ep_event) +{ + EP_ASSERT (session_provider != NULL); + EP_ASSERT (ep_event != NULL); + + const EventPipeSessionProviderTracepoint *tracepoint = NULL; + const EventPipeSessionProviderTracepointConfiguration *tracepoint_config = session_provider->tracepoint_config; + if (tracepoint_config == NULL) + return tracepoint; + + if (tracepoint_config->default_tracepoint.tracepoint_format != NULL) + tracepoint = &tracepoint_config->default_tracepoint; + + if (tracepoint_config->event_id_to_tracepoint_map == NULL) + return tracepoint; + + uint32_t event_id = ep_event_get_event_id (ep_event); + dn_umap_it_t tracepoint_found = dn_umap_find (tracepoint_config->event_id_to_tracepoint_map, (void *)(uintptr_t)event_id); + if (!dn_umap_it_end (tracepoint_found)) + tracepoint = dn_umap_it_value_t (tracepoint_found, EventPipeSessionProviderTracepoint *); + + return tracepoint; +} + static void DN_CALLBACK_CALLTYPE tracepoint_free_func (void *tracepoint) { - EventPipeTracepoint *tp = *(EventPipeTracepoint **)tracepoint; + EventPipeSessionProviderTracepoint *tp = *(EventPipeSessionProviderTracepoint **)tracepoint; ep_rt_utf8_string_free ((ep_char8_t *)tp->tracepoint_format); ep_rt_object_free (tp); } @@ -180,7 +374,7 @@ session_provider_tracepoint_config_alloc (const EventPipeProviderTracepointConfi EP_ASSERT (tracepoint_config != NULL); EventPipeSessionProviderTracepointConfiguration *instance = ep_rt_object_alloc (EventPipeSessionProviderTracepointConfiguration); - EventPipeTracepoint *tracepoint = NULL; + EventPipeSessionProviderTracepoint *tracepoint = NULL; ep_raise_error_if_nok (instance != NULL); instance->default_tracepoint.tracepoint_format = tracepoint_format_alloc (tracepoint_config->default_tracepoint_name); @@ -200,7 +394,7 @@ session_provider_tracepoint_config_alloc (const EventPipeProviderTracepointConfi for (uint32_t i = 0; i < tracepoint_config->non_default_tracepoints_length; ++i) { const EventPipeProviderTracepointSet *tracepoint_set = &tracepoint_config->non_default_tracepoints[i]; - tracepoint = ep_rt_object_alloc (EventPipeTracepoint); + tracepoint = ep_rt_object_alloc (EventPipeSessionProviderTracepoint); ep_raise_error_if_nok (tracepoint != NULL); tracepoint->tracepoint_format = tracepoint_format_alloc (tracepoint_set->tracepoint_name); @@ -326,8 +520,7 @@ ep_session_provider_allows_event ( return false; uint32_t event_id = ep_event_get_event_id (ep_event); - const EventPipeSessionProviderEventFilter *event_filter = ep_session_provider_get_event_filter (session_provider); - return event_filter_allows_event_id (event_filter, event_id); + return event_filter_allows_event_id (session_provider->event_filter, event_id); } /* diff --git a/src/native/eventpipe/ep-session-provider.h b/src/native/eventpipe/ep-session-provider.h index 2f4db2d8030e45..09459928d6b4d5 100644 --- a/src/native/eventpipe/ep-session-provider.h +++ b/src/native/eventpipe/ep-session-provider.h @@ -12,7 +12,7 @@ #include "ep-getter-setter.h" /* - * EventPipeTracepoint. + * EventPipeSessionProviderTracepoint. */ #if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_EP_GETTER_SETTER) @@ -31,6 +31,20 @@ struct _EventPipeTracepoint { }; #endif +bool +ep_session_provider_register_tracepoints ( + EventPipeSessionProvider *session_provider, + int user_events_data_fd); + +void +ep_session_provider_unregister_tracepoints ( + EventPipeSessionProvider *session_provider, + int user_events_data_fd); + +const EventPipeSessionProviderTracepoint * +ep_session_provider_get_tracepoint_for_event ( + const EventPipeSessionProvider *session_provider, + const EventPipeEvent *ep_event); /* * EventPipeSessionProviderEventFilter. @@ -63,7 +77,7 @@ struct _EventPipeSessionProviderTracepointConfiguration { #else struct _EventPipeSessionProviderTracepointConfiguration_Internal { #endif - EventPipeTracepoint default_tracepoint; + EventPipeSessionProviderTracepoint default_tracepoint; dn_vector_ptr_t *tracepoints; dn_umap_t *event_id_to_tracepoint_map; }; @@ -101,8 +115,6 @@ EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, const ep_char8_t EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, uint64_t, keywords) EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, EventPipeEventLevel, logging_level) EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, const ep_char8_t *, filter_data) -EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, const EventPipeSessionProviderEventFilter *, event_filter) -EP_DEFINE_GETTER(EventPipeSessionProvider *, session_provider, EventPipeSessionProviderTracepointConfiguration *, tracepoint_config) EventPipeSessionProvider * ep_session_provider_alloc ( diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 44bb475141f43b..19e7d4005e3c8f 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -13,14 +13,6 @@ #include "ep-event-payload.h" #include "ep-rt.h" -#if HAVE_LINUX_USER_EVENTS_H -#include // DIAG_IOCSREG -#endif // HAVE_LINUX_USER_EVENTS_H - -#if HAVE_SYS_IOCTL_H -#include // session_register_tracepoint -#endif // HAVE_SYS_IOCTL_H - #if HAVE_UNISTD_H #include // close #endif // HAVE_UNISTD_H @@ -52,18 +44,6 @@ ep_session_remove_dangling_session_states (EventPipeSession *session); static bool -session_register_tracepoint ( - EventPipeSession *session, - EventPipeTracepoint *tracepoint); - -static -bool -session_unregister_tracepoint ( - EventPipeSession *session, - EventPipeTracepoint *tracepoint); - -static -void session_user_events_tracepoints_init ( EventPipeSession *session, int user_events_data_fd); @@ -72,12 +52,6 @@ static void session_disable_user_events (EventPipeSession *session); -static -EventPipeTracepoint * -session_get_tracepoint_for_event ( - EventPipeSession *session, - EventPipeEvent* ep_event); - static bool is_guid_empty(const uint8_t *guid); @@ -227,83 +201,22 @@ session_disable_streaming_thread (EventPipeSession *session) ep_rt_wait_event_free (rt_thread_shutdown_event); } -#if HAVE_LINUX_USER_EVENTS_H && HAVE_SYS_IOCTL_H -static -bool -session_register_tracepoint ( - EventPipeSession *session, - EventPipeTracepoint *tracepoint) -{ - struct user_reg reg = {0}; - - reg.size = sizeof(reg); - reg.enable_bit = EP_TRACEPOINT_ENABLE_BIT; - reg.enable_size = sizeof(tracepoint->enabled); - reg.enable_addr = (uint64_t)&tracepoint->enabled; - - reg.name_args = (uint64_t)tracepoint->tracepoint_format; - - if (ioctl(session->user_events_data_fd, DIAG_IOCSREG, ®) == -1) - return false; - - tracepoint->write_index = reg.write_index; - - return true; -} - -static -bool -session_unregister_tracepoint ( - EventPipeSession *session, - EventPipeTracepoint *tracepoint) -{ - struct user_unreg unreg = {0}; - - unreg.size = sizeof(unreg); - unreg.disable_bit = EP_TRACEPOINT_ENABLE_BIT; - unreg.disable_addr = (uint64_t)&tracepoint->enabled; - - if (ioctl(session->user_events_data_fd, DIAG_IOCSUNREG, &unreg) == -1) - return false; - - return true; -} -#else // HAVE_LINUX_USER_EVENTS_H && HAVE_SYS_IOCTL_H -static -bool -session_register_tracepoint ( - EventPipeSession *session, - EventPipeTracepoint *tracepoint) -{ - // Not Supported - return false; -} - -static -bool -session_unregister_tracepoint ( - EventPipeSession *session, - EventPipeTracepoint *tracepoint) -{ - // Not Supported - return false; -} -#endif // HAVE_LINUX_USER_EVENTS_H && HAVE_SYS_IOCTL_H - /* * session_user_events_tracepoints_init * * Registers all configured tracepoints for the user_events eventpipe session. */ static -void +bool session_user_events_tracepoints_init ( EventPipeSession *session, int user_events_data_fd) { EP_ASSERT (session != NULL); EP_ASSERT (session->session_type == EP_SESSION_TYPE_USEREVENTS); - EP_ASSERT (user_events_data_fd != 0); + + if (user_events_data_fd <= 0) + return false; session->user_events_data_fd = user_events_data_fd; @@ -314,27 +227,11 @@ session_user_events_tracepoints_init ( EventPipeSessionProvider *session_provider = *dn_list_it_data_t (it, EventPipeSessionProvider *); EP_ASSERT (session_provider != NULL); - EventPipeSessionProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); - EP_ASSERT (tracepoint_config != NULL); - EP_ASSERT (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0' || tracepoint_config->tracepoints != NULL); - - if (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0') { - ep_raise_error_if_nok (session_register_tracepoint (session, &tracepoint_config->default_tracepoint)); - } - - if (tracepoint_config->tracepoints != NULL) { - DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeTracepoint *, tracepoint, tracepoint_config->tracepoints) { - EP_ASSERT (tracepoint != NULL); - ep_raise_error_if_nok (session_register_tracepoint (session, tracepoint)); - } DN_VECTOR_PTR_FOREACH_END; - } + if (!ep_session_provider_register_tracepoints (session_provider, session->user_events_data_fd)) + return false; } - -ep_on_exit: - return; - -ep_on_error: - ep_exit_error_handler (); + + return true; } EventPipeSession * @@ -416,9 +313,8 @@ ep_session_alloc ( break; case EP_SESSION_TYPE_USEREVENTS: - ep_raise_error_if_nok (user_events_data_fd != 0); // With the user_events_data file, register tracepoints for each provider's tracepoint configurations - session_user_events_tracepoints_init (instance, user_events_data_fd); + ep_raise_error_if_nok (session_user_events_tracepoints_init (instance, user_events_data_fd)); break; default: @@ -728,21 +624,11 @@ session_disable_user_events (EventPipeSession *session) ep_requires_lock_held (); - // Unregister all tracepoints. EventPipeSessionProviderList *providers = ep_session_get_providers (session); EP_ASSERT (providers != NULL); for (dn_list_it_t it = dn_list_begin (ep_session_provider_list_get_providers (providers)); !dn_list_it_end (it); it = dn_list_it_next (it)) { EventPipeSessionProvider *session_provider = *dn_list_it_data_t (it, EventPipeSessionProvider *); - EventPipeSessionProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); - if (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0') - session_unregister_tracepoint (session, &tracepoint_config->default_tracepoint); - - if (tracepoint_config->tracepoints != NULL) { - DN_VECTOR_PTR_FOREACH_BEGIN (EventPipeTracepoint *, tracepoint, tracepoint_config->tracepoints) { - EP_ASSERT (tracepoint != NULL); - session_unregister_tracepoint (session, tracepoint); - } DN_VECTOR_PTR_FOREACH_END; - } + ep_session_provider_unregister_tracepoints (session_provider, session->user_events_data_fd); } if (session->user_events_data_fd != 0) { @@ -753,38 +639,6 @@ session_disable_user_events (EventPipeSession *session) } } -static -EventPipeTracepoint * -session_get_tracepoint_for_event ( - EventPipeSession *session, - EventPipeEvent* ep_event) -{ - EP_ASSERT (session != NULL); - EP_ASSERT (ep_event != NULL); - EP_ASSERT (session->session_type == EP_SESSION_TYPE_USEREVENTS); - - EventPipeTracepoint *tracepoint = NULL; - - EventPipeProvider *provider = ep_event_get_provider (ep_event); - EventPipeSessionProviderList *session_provider_list = ep_session_get_providers (session); - EventPipeSessionProvider *session_provider = ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (session_provider_list), ep_provider_get_provider_name (provider)); - EventPipeSessionProviderTracepointConfiguration *tracepoint_config = ep_session_provider_get_tracepoint_config (session_provider); - - if (tracepoint_config->default_tracepoint.tracepoint_format[0] != '\0') - tracepoint = &tracepoint_config->default_tracepoint; - - dn_umap_t *event_id_to_tracepoint_map = tracepoint_config->event_id_to_tracepoint_map; - if (event_id_to_tracepoint_map == NULL) - return tracepoint; - - uint32_t event_id = ep_event_get_event_id (ep_event); - dn_umap_it_t tracepoint_found = dn_umap_find (event_id_to_tracepoint_map, (void *)(uintptr_t)event_id); - if (!dn_umap_it_end (tracepoint_found)) - tracepoint = dn_umap_it_value_t (tracepoint_found, EventPipeTracepoint *); - - return tracepoint; -} - static bool is_guid_empty(const uint8_t *guid) @@ -852,7 +706,10 @@ session_tracepoint_write_event ( EP_ASSERT (session != NULL); EP_ASSERT (ep_event != NULL); - EventPipeTracepoint *tracepoint = session_get_tracepoint_for_event (session, ep_event); + EventPipeProvider *provider = ep_event_get_provider (ep_event); + EventPipeSessionProviderList *session_provider_list = ep_session_get_providers (session); + EventPipeSessionProvider *session_provider = ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (session_provider_list), ep_provider_get_provider_name (provider)); + const EventPipeSessionProviderTracepoint *tracepoint = ep_session_provider_get_tracepoint_for_event (session_provider, ep_event); if (tracepoint == NULL) return false; @@ -907,7 +764,6 @@ session_tracepoint_write_event ( if (io == NULL) return false; } - for (uint32_t i = 0; i < ep_event_payload->event_data_len; ++i) { io[index + i].iov_base = (void *)ep_event_data_get_ptr (&event_data[i]); io[index + i].iov_len = ep_event_data_get_size (&event_data[i]); @@ -915,7 +771,7 @@ session_tracepoint_write_event ( index += ep_event_payload->event_data_len; } - io[0].iov_base = &tracepoint->write_index; + io[0].iov_base = (void *)&tracepoint->write_index; io[0].iov_len = sizeof(tracepoint->write_index); io[1].iov_base = &version; diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index 93ba6b7e5c7fc5..d1a80c83a06d1a 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -49,7 +49,7 @@ typedef struct _EventPipeSystemTime EventPipeSystemTime; typedef struct _EventPipeThread EventPipeThread; typedef struct _EventPipeThreadHolder EventPipeThreadHolder; typedef struct _EventPipeThreadSessionState EventPipeThreadSessionState; -typedef struct _EventPipeTracepoint EventPipeTracepoint; +typedef struct _EventPipeTracepoint EventPipeSessionProviderTracepoint; typedef struct _FastSerializableObject FastSerializableObject; typedef struct _FastSerializableObjectVtable FastSerializableObjectVtable; typedef struct _FastSerializer FastSerializer; From bcbc8677e76696ea778270db36b1f37317ae4810 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Tue, 10 Jun 2025 22:07:07 +0000 Subject: [PATCH 22/32] Fixup compilation error --- src/native/eventpipe/ep-session-provider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index 3b9dd737f485c3..9224945459edfa 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -71,7 +71,7 @@ session_provider_tracepoint_config_alloc (const EventPipeProviderTracepointConfi static bool event_filter_allows_event_id ( - const EventPipeProviderEventFilter *event_filter, + const EventPipeSessionProviderEventFilter *event_filter, uint32_t event_id); /* From e607a07d0e91fbecab1e1faa74b128ae46c54b76 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Tue, 10 Jun 2025 22:07:50 +0000 Subject: [PATCH 23/32] Move metadata into extensions portion --- src/native/eventpipe/ep-session.c | 62 ++++++++++++------------- src/native/eventpipe/ep-types-forward.h | 9 ++-- 2 files changed, 36 insertions(+), 35 deletions(-) diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 19e7d4005e3c8f..48e6cf1da4231a 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -58,7 +58,7 @@ is_guid_empty(const uint8_t *guid); static uint16_t -tracepoint_construct_extension_buffer ( +construct_extension_buffer ( uint8_t *extension, const uint8_t *activity_id, const uint8_t *related_activity_id); @@ -655,15 +655,14 @@ is_guid_empty(const uint8_t *guid) } /* - * tracepoint_construct_extension_buffer + * construct_extension_buffer * * EventPipe Tracepoints include an extension buffer - * that encodes other optional information in the - * the NetTrace V6 LabelList format. + * that encodes other optional information. */ static uint16_t -tracepoint_construct_extension_buffer ( +construct_extension_buffer ( uint8_t *extension, const uint8_t *activity_id, const uint8_t *related_activity_id) @@ -676,13 +675,13 @@ tracepoint_construct_extension_buffer ( bool related_activity_id_is_empty = is_guid_empty (related_activity_id); if (!activity_id_is_empty) { - extension[offset] = !related_activity_id_is_empty ? 0x81 : 0x01; + extension[offset] = 0x02; memcpy(extension + offset + 1, activity_id, EP_ACTIVITY_ID_SIZE); offset += 1 + EP_ACTIVITY_ID_SIZE; } if (!related_activity_id_is_empty) { - extension[offset] = 0x02; + extension[offset] = 0x03; memcpy(extension + offset + 1, related_activity_id, EP_ACTIVITY_ID_SIZE); offset += 1 + EP_ACTIVITY_ID_SIZE; } @@ -721,28 +720,29 @@ session_tracepoint_write_event ( uint32_t event_id = ep_event_get_event_id (ep_event); uint16_t truncated_event_id = event_id & 0xFFFF; // For parity with EventSource, there shouldn't be any that need more than 16 bits. - uint8_t extension[EP_MAX_EXTENSION_SIZE]; - uint16_t extension_len = tracepoint_construct_extension_buffer (extension, activity_id, related_activity_id); - EP_ASSERT(extension_len <= EP_MAX_EXTENSION_SIZE); + uint8_t extension_metadata[5]; + extension_metadata[0] = 0x01; // label + uint32_t metadata_len = ep_event_get_metadata_len (ep_event); + memcpy (extension_metadata + 1, &metadata_len, sizeof (metadata_len)); - uint32_t payload_len = ep_event_payload_get_size (ep_event_payload); - if ((payload_len & 0xFFFF0000) != 0) - return false; + uint8_t extension_activity_ids[EP_MAX_EXTENSION_SIZE]; + uint16_t extension_activity_ids_len = construct_extension_buffer (extension_activity_ids, activity_id, related_activity_id); + EP_ASSERT(extension_activity_ids_len <= EP_MAX_EXTENSION_SIZE); - uint32_t metadata_len = ep_event_get_metadata_len (ep_event); - if ((metadata_len & 0xFFFF0000) != 0) + uint32_t extension_len = 5 + metadata_len + extension_activity_ids_len; + if (extension_len & 0xFFFF0000) return false; - uint32_t meta_rel_loc = metadata_len << 16 | ((extension_len + payload_len) & 0xFFFF); - if (((extension_len + payload_len) & 0xFFFF0000) != 0) + uint32_t payload_len = ep_event_payload_get_size (ep_event_payload); + if ((payload_len & 0xFFFF0000) != 0) return false; - uint32_t payload_rel_loc = payload_len << 16 | ((sizeof(meta_rel_loc) + extension_len) & 0xFFFF); - if (((sizeof(meta_rel_loc) + extension_len) & 0xFFFF0000) != 0) + uint32_t payload_rel_loc = payload_len << 16 | (extension_len & 0xFFFF); + if ((extension_len & 0xFFFF0000) != 0) return false; - uint32_t extension_rel_loc = extension_len << 16 | ((sizeof(payload_rel_loc) + sizeof(meta_rel_loc)) & 0xFFFF); - if (((sizeof(payload_rel_loc) + sizeof(meta_rel_loc)) & 0xFFFF0000) != 0) + uint32_t extension_rel_loc = extension_len << 16 | (sizeof(payload_rel_loc) & 0xFFFF); + if (sizeof(payload_rel_loc) & 0xFFFF0000) return false; struct iovec static_io[EP_DEFAULT_IOVEC_SIZE]; @@ -765,10 +765,10 @@ session_tracepoint_write_event ( return false; } for (uint32_t i = 0; i < ep_event_payload->event_data_len; ++i) { - io[index + i].iov_base = (void *)ep_event_data_get_ptr (&event_data[i]); - io[index + i].iov_len = ep_event_data_get_size (&event_data[i]); + io[index].iov_base = (void *)ep_event_data_get_ptr (&event_data[i]); + io[index].iov_len = ep_event_data_get_size (&event_data[i]); + ++index; } - index += ep_event_payload->event_data_len; } io[0].iov_base = (void *)&tracepoint->write_index; @@ -786,17 +786,17 @@ session_tracepoint_write_event ( io[4].iov_base = &payload_rel_loc; io[4].iov_len = sizeof(payload_rel_loc); - io[5].iov_base = &meta_rel_loc; - io[5].iov_len = sizeof(meta_rel_loc); + io[5].iov_base = extension_metadata; + io[5].iov_len = sizeof(extension_metadata); - io[6].iov_base = extension; - io[6].iov_len = extension_len; + io[6].iov_base = (void *)ep_event_get_metadata (ep_event); + io[6].iov_len = metadata_len; - io[index].iov_base = (void *)ep_event_get_metadata (ep_event); - io[index].iov_len = metadata_len; + io[7].iov_base = extension_activity_ids; + io[7].iov_len = extension_activity_ids_len; ssize_t bytes_written; - while ((bytes_written = writev(session->user_events_data_fd, (const struct iovec *)io, index + 1) < 0) && errno == EINTR); + while ((bytes_written = writev(session->user_events_data_fd, (const struct iovec *)io, index) < 0) && errno == EINTR); if (io != static_io) free (io); diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index d1a80c83a06d1a..66ef10e715acee 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -77,7 +77,11 @@ typedef struct _StreamWriterVtable StreamWriterVtable; #define EP_TRACEPOINT_FORMAT_MAX_SIZE 512 -#define EP_TRACEPOINT_FORMAT_V1 "u8 version; u16 event_id; __rel_loc u8[] extension; __rel_loc u8[] payload; __rel_loc u8[] meta" +#define EP_TRACEPOINT_FORMAT_V1 "u8 version; u16 event_id; __rel_loc u8[] extension; __rel_loc u8[] payload" + +// Tracepoint V1 - write_index, version, truncated_event_id, extension_rel_loc, payload_rel_loc, meta_rel_loc, extension, payload, metadata +// To avoid dynamic allocations, using multiple iovec buffers to write the extension +#define EP_TRACEPOINT_V1_PAYLOAD_INDEX 8 #define EP_MAX_EXTENSION_SIZE (2 * (EP_ACTIVITY_ID_SIZE + 1)) @@ -86,9 +90,6 @@ typedef struct _StreamWriterVtable StreamWriterVtable; // so statically allocate a reasonable number of iovecs to avoid dynamic allocations #define EP_DEFAULT_IOVEC_SIZE 30 -// Tracepoint V1 - write_index, version, truncated_event_id, extension_rel_loc, payload_rel_loc, meta_rel_loc, extension, payload, metadata -#define EP_TRACEPOINT_V1_PAYLOAD_INDEX 7 - /* * EventPipe Enums. */ From 53cde483a1333b00f9e891fc091043f30b7a6770 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Wed, 11 Jun 2025 03:04:05 +0000 Subject: [PATCH 24/32] Free default tracepoint format --- src/native/eventpipe/ep-session-provider.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index 9224945459edfa..a6519928dd5f7d 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -341,6 +341,8 @@ session_provider_tracepoint_config_free (EventPipeSessionProviderTracepointConfi tracepoint_config->tracepoints = NULL; } + ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_config->default_tracepoint.tracepoint_format); + ep_rt_object_free (tracepoint_config); } From faff9ea1ea1a4660a033e701d64dc7f847869367 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Wed, 11 Jun 2025 18:33:17 +0000 Subject: [PATCH 25/32] Address feedback Use ep_provider_config_fini helper Add session_type deserializing helper Fix tabbing Add dn_umap_uint32_ptr macro Handle tracepoint registration failure Change ep_session_write_event order Use dn_list foreach Add size check to extension activity ids construction Add ep_rt_utf8_string_printf_alloc helper --- src/native/containers/dn-umap-t.h | 1 + src/native/eventpipe/ds-eventpipe-protocol.c | 135 +++++++++---------- src/native/eventpipe/ds-eventpipe-protocol.h | 2 +- src/native/eventpipe/ds-protocol.c | 28 ++-- src/native/eventpipe/ep-session-provider.c | 45 +++---- src/native/eventpipe/ep-session-provider.h | 2 +- src/native/eventpipe/ep-session.c | 108 +++++++++------ src/native/eventpipe/ep-string.c | 31 +++++ src/native/eventpipe/ep-string.h | 4 + src/native/eventpipe/ep-types-forward.h | 11 +- src/native/eventpipe/ep-types.h | 9 ++ src/native/eventpipe/ep.c | 42 +++++- 12 files changed, 257 insertions(+), 161 deletions(-) diff --git a/src/native/containers/dn-umap-t.h b/src/native/containers/dn-umap-t.h index 9c22938db219bd..50583e947a4ac8 100644 --- a/src/native/containers/dn-umap-t.h +++ b/src/native/containers/dn-umap-t.h @@ -72,5 +72,6 @@ DN_UMAP_T (ptr, void *, int16, int16_t) DN_UMAP_T (ptr, void *, uint16, uint16_t) DN_UMAP_T (ptr, void *, int32, int32_t) DN_UMAP_T (ptr, void *, uint32, uint32_t) +DN_UMAP_T (uint32, uint32_t, ptr, void *) #endif /* __DN_UMAP_T_H__ */ diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index c7a549dea6ba85..fb0e385e9ea0a4 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -25,6 +25,14 @@ eventpipe_protocol_helper_send_start_tracing_success ( DiagnosticsIpcStream *stream, EventPipeSessionID session_id); +static +inline +bool +eventpipe_collect_tracing_command_try_parse_session_type ( + uint8_t **buffer, + uint32_t *buffer_len, + EventPipeSessionType *session_type); + static bool eventpipe_collect_tracing_command_try_parse_serialization_format ( @@ -68,10 +76,6 @@ eventpipe_collect_tracing_command_try_parse_event_ids ( const uint32_t length, uint32_t **event_ids); -static -void -eventpipe_collect_tracing_command_free_event_filter (EventPipeProviderEventFilter *event_filter); - static bool eventpipe_collect_tracing_command_try_parse_event_filter ( @@ -79,14 +83,6 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( uint32_t *buffer_len, EventPipeProviderEventFilter *event_filter); -static -void -eventpipe_collect_tracing_command_free_tracepoint_set (EventPipeProviderTracepointSet *tracepoint_set); - -static -void -eventpipe_collect_tracing_command_free_tracepoint_config (EventPipeProviderTracepointConfiguration *tracepoint_config); - static bool eventpipe_collect_tracing_command_try_parse_tracepoint_config ( @@ -110,6 +106,11 @@ eventpipe_collect_tracing_command_try_parse_config ( EventPipeProviderOptionalFieldFlags optional_field_flags, dn_vector_t **result); +static +void +DN_CALLBACK_CALLTYPE +eventpipe_provider_configs_free_func (void *data); + static uint8_t * eventpipe_collect_tracing_command_try_parse_payload ( @@ -162,6 +163,38 @@ eventpipe_protocol_helper_unknown_command ( * EventPipeCollectTracingCommandPayload */ +static +inline +bool +eventpipe_collect_tracing_command_try_parse_session_type ( + uint8_t **buffer, + uint32_t *buffer_len, + EventPipeSessionType *type) +{ + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (type != NULL); + + uint32_t session_type; + bool can_parse = ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &session_type); + + bool ipc_valid_session_type = false; + switch (session_type) { + case 0: + *type = EP_SESSION_TYPE_IPCSTREAM; + ipc_valid_session_type = true; + break; + case 1: + *type = EP_SESSION_TYPE_USEREVENTS; + ipc_valid_session_type = true; + break; + default: + break; + } + + return can_parse && ipc_valid_session_type; +} + static inline bool @@ -277,17 +310,6 @@ eventpipe_collect_tracing_command_try_parse_event_ids ( ep_exit_error_handler (); } -static -void -eventpipe_collect_tracing_command_free_event_filter (EventPipeProviderEventFilter *event_filter) -{ - ep_return_void_if_nok (event_filter != NULL); - - ep_rt_object_array_free ((uint32_t *)event_filter->event_ids); - - ep_rt_object_free (event_filter); -} - /* * eventpipe_collect_tracing_command_try_parse_event_filter * @@ -331,33 +353,6 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( ep_exit_error_handler (); } -static -void -eventpipe_collect_tracing_command_free_tracepoint_sets (EventPipeProviderTracepointSet *tracepoint_set, uint32_t length) -{ - ep_return_void_if_nok (tracepoint_set != NULL); - - for (uint32_t i = 0; i < length; ++i) { - ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_set->tracepoint_name); - ep_rt_object_array_free ((uint32_t *)tracepoint_set->event_ids); - } - - ep_rt_object_array_free (tracepoint_set); -} - -static -void -eventpipe_collect_tracing_command_free_tracepoint_config (EventPipeProviderTracepointConfiguration *tracepoint_config) -{ - ep_return_void_if_nok (tracepoint_config != NULL); - - ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_config->default_tracepoint_name); - - eventpipe_collect_tracing_command_free_tracepoint_sets ((EventPipeProviderTracepointSet *)tracepoint_config->non_default_tracepoints, tracepoint_config->non_default_tracepoints_length); - - ep_rt_object_free (tracepoint_config); -} - /* * eventpipe_collect_tracing_command_try_parse_tracepoint_config * @@ -556,7 +551,10 @@ eventpipe_collect_tracing_command_try_parse_config ( &provider_config)); ep_raise_error_if_nok (dn_vector_push_back (*result, provider_config)); - ep_provider_config_fini (&provider_config); + provider_config.provider_name = NULL; + provider_config.filter_data = NULL; + provider_config.event_filter = NULL; + provider_config.tracepoint_config = NULL; } ep_on_exit: @@ -565,10 +563,7 @@ eventpipe_collect_tracing_command_try_parse_config ( ep_on_error: count_configs = 0; - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&provider_config)); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&provider_config)); - eventpipe_collect_tracing_command_free_event_filter ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (&provider_config)); - eventpipe_collect_tracing_command_free_tracepoint_config ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (&provider_config)); + ep_provider_config_fini (&provider_config); ep_exit_error_handler (); } @@ -579,18 +574,21 @@ ds_eventpipe_collect_tracing_command_payload_alloc (void) return ep_rt_object_alloc (EventPipeCollectTracingCommandPayload); } +static +void +DN_CALLBACK_CALLTYPE +eventpipe_provider_configs_free_func (void *data) +{ + ep_provider_config_fini ((EventPipeProviderConfiguration *)data); +} + void ds_eventpipe_collect_tracing_command_payload_free (EventPipeCollectTracingCommandPayload *payload) { ep_return_void_if_nok (payload != NULL); ep_rt_byte_array_free (payload->incoming_buffer); - DN_VECTOR_FOREACH_BEGIN (EventPipeProviderConfiguration, config, payload->provider_configs) { - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&config)); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&config)); - eventpipe_collect_tracing_command_free_event_filter ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (&config)); - eventpipe_collect_tracing_command_free_tracepoint_config ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (&config)); - } DN_VECTOR_FOREACH_END; + dn_vector_custom_free (payload->provider_configs, eventpipe_provider_configs_free_func); ep_rt_object_free (payload); } @@ -757,7 +755,6 @@ eventpipe_collect_tracing5_command_try_parse_payload ( uint8_t * buffer_cursor = buffer; uint32_t buffer_cursor_len = buffer_len; - uint32_t session_type = 0; EventPipeProviderOptionalFieldFlags optional_field_flags = EP_PROVIDER_OPTFIELD_EVENT_FILTER; EventPipeCollectTracingCommandPayload *instance = ds_eventpipe_collect_tracing_command_payload_alloc (); @@ -765,17 +762,7 @@ eventpipe_collect_tracing5_command_try_parse_payload ( instance->incoming_buffer = buffer; - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (&buffer_cursor, &buffer_cursor_len, &session_type)); - switch (session_type) { - case 0: - instance->session_type = EP_SESSION_TYPE_IPCSTREAM; - break; - case 1: - instance->session_type = EP_SESSION_TYPE_USEREVENTS; - break; - default: - ep_raise_error (); - } + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_session_type (&buffer_cursor, &buffer_cursor_len, &instance->session_type)); if (instance->session_type == EP_SESSION_TYPE_IPCSTREAM) { ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_circular_buffer_size (&buffer_cursor, &buffer_cursor_len, &instance->circular_buffer_size_in_mb)); @@ -913,7 +900,7 @@ eventpipe_protocol_helper_collect_tracing ( payload->circular_buffer_size_in_mb, dn_vector_data_t (payload->provider_configs, EventPipeProviderConfiguration), dn_vector_size (payload->provider_configs), - payload->session_type == EP_SESSION_TYPE_USEREVENTS ? EP_SESSION_TYPE_USEREVENTS : EP_SESSION_TYPE_IPCSTREAM, + payload->session_type, payload->serialization_format, payload->rundown_keyword, payload->stackwalk_requested, diff --git a/src/native/eventpipe/ds-eventpipe-protocol.h b/src/native/eventpipe/ds-eventpipe-protocol.h index 5101ddf1b0938f..0615f473ebc043 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.h +++ b/src/native/eventpipe/ds-eventpipe-protocol.h @@ -43,7 +43,7 @@ struct _EventPipeCollectTracingCommandPayload_Internal { bool rundown_requested; bool stackwalk_requested; uint64_t rundown_keyword; - uint32_t session_type; + EventPipeSessionType session_type; }; #if !defined(DS_INLINE_GETTER_SETTER) && !defined(DS_IMPL_EVENTPIPE_PROTOCOL_GETTER_SETTER) diff --git a/src/native/eventpipe/ds-protocol.c b/src/native/eventpipe/ds-protocol.c index 24dc4f4c5cf8bd..9015f128bab51a 100644 --- a/src/native/eventpipe/ds-protocol.c +++ b/src/native/eventpipe/ds-protocol.c @@ -455,39 +455,39 @@ ds_ipc_message_try_parse_uint32_t ( bool ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc( - uint8_t **buffer, - uint32_t *buffer_len, - ep_char8_t **string_utf8) + uint8_t **buffer, + uint32_t *buffer_len, + ep_char8_t **string_utf8) { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); EP_ASSERT (string_utf8 != NULL); - bool result = false; + bool result = false; - uint8_t *byte_array = NULL; - uint32_t byte_array_len = 0; + uint8_t *byte_array = NULL; + uint32_t byte_array_len = 0; - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &byte_array, &byte_array_len)); + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &byte_array, &byte_array_len)); - *string_utf8 = NULL; + *string_utf8 = NULL; if (byte_array) { - *string_utf8 = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)byte_array); + *string_utf8 = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)byte_array); ep_raise_error_if_nok (*string_utf8 != NULL); - ep_rt_byte_array_free (byte_array); + ep_rt_byte_array_free (byte_array); byte_array = NULL; - } + } - result = true; + result = true; ep_on_exit: - return result; + return result; ep_on_error: ep_rt_byte_array_free (byte_array); ep_rt_utf8_string_free (*string_utf8); - ep_exit_error_handler (); + ep_exit_error_handler (); } bool diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index a6519928dd5f7d..6cd971a45f7f6c 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -61,7 +61,7 @@ void session_provider_tracepoint_config_free (EventPipeSessionProviderTracepointConfiguration *tracepoint_config); static -ep_char8_t * +const ep_char8_t * tracepoint_format_alloc (const ep_char8_t *tracepoint_name); static @@ -70,7 +70,7 @@ session_provider_tracepoint_config_alloc (const EventPipeProviderTracepointConfi static bool -event_filter_allows_event_id ( +event_filter_enables_event_id ( const EventPipeSessionProviderEventFilter *event_filter, uint32_t event_id); @@ -127,7 +127,7 @@ session_provider_event_filter_alloc (const EventPipeProviderEventFilter *event_f ep_raise_error_if_nok (instance->event_ids != NULL); for (uint32_t i = 0; i < event_filter->length; ++i) { - dn_umap_result_t insert_result = dn_umap_ptr_uint32_insert (instance->event_ids, (void *)(uintptr_t)event_filter->event_ids[i], 0); + dn_umap_result_t insert_result = dn_umap_uint32_ptr_insert (instance->event_ids, event_filter->event_ids[i], NULL); ep_raise_error_if_nok (insert_result.result); } } @@ -308,7 +308,7 @@ ep_session_provider_get_tracepoint_for_event ( return tracepoint; uint32_t event_id = ep_event_get_event_id (ep_event); - dn_umap_it_t tracepoint_found = dn_umap_find (tracepoint_config->event_id_to_tracepoint_map, (void *)(uintptr_t)event_id); + dn_umap_it_t tracepoint_found = dn_umap_uint32_ptr_find (tracepoint_config->event_id_to_tracepoint_map, event_id); if (!dn_umap_it_end (tracepoint_found)) tracepoint = dn_umap_it_value_t (tracepoint_found, EventPipeSessionProviderTracepoint *); @@ -320,6 +320,7 @@ void DN_CALLBACK_CALLTYPE tracepoint_free_func (void *tracepoint) { + EP_ASSERT (tracepoint != NULL); EventPipeSessionProviderTracepoint *tp = *(EventPipeSessionProviderTracepoint **)tracepoint; ep_rt_utf8_string_free ((ep_char8_t *)tp->tracepoint_format); ep_rt_object_free (tp); @@ -347,26 +348,15 @@ session_provider_tracepoint_config_free (EventPipeSessionProviderTracepointConfi } static -ep_char8_t * +const ep_char8_t * tracepoint_format_alloc (const ep_char8_t *tracepoint_name) { - ep_return_null_if_nok (tracepoint_name != NULL && tracepoint_name[0] != '\0'); - - int32_t res = 0; - size_t tracepoint_format_len = strlen(tracepoint_name) + strlen(EP_TRACEPOINT_FORMAT_V1) + 2; // +2 for space and null terminator - ep_char8_t *tracepoint_format = ep_rt_utf8_string_alloc (tracepoint_format_len); - ep_raise_error_if_nok (tracepoint_format != NULL); - - res = snprintf(tracepoint_format, tracepoint_format_len, "%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); - ep_raise_error_if_nok (res >= 0 && (size_t)res < tracepoint_format_len); - -ep_on_exit: - return tracepoint_format; + ep_return_null_if_nok (tracepoint_name != NULL); + + if (strlen(tracepoint_name) > EP_TRACEPOINT_NAME_MAX_SIZE) + return NULL; -ep_on_error: - ep_rt_utf8_string_free (tracepoint_format); - tracepoint_format = NULL; - ep_exit_error_handler (); + return ep_rt_utf8_string_printf_alloc ("%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); } static @@ -405,7 +395,7 @@ session_provider_tracepoint_config_alloc (const EventPipeProviderTracepointConfi for (uint32_t j = 0; j < tracepoint_set->event_ids_length; ++j) { uint32_t event_id = tracepoint_set->event_ids[j]; - dn_umap_result_t insert_result = dn_umap_insert (instance->event_id_to_tracepoint_map, (void *)(uintptr_t)event_id, tracepoint); + dn_umap_result_t insert_result = dn_umap_uint32_ptr_insert (instance->event_id_to_tracepoint_map, event_id, tracepoint); ep_raise_error_if_nok (insert_result.result); } @@ -481,7 +471,7 @@ ep_session_provider_free (EventPipeSessionProvider * session_provider) ep_return_void_if_nok (session_provider != NULL); session_provider_tracepoint_config_free (session_provider->tracepoint_config); - session_provider_event_filter_free ((EventPipeSessionProviderEventFilter *)session_provider->event_filter); + session_provider_event_filter_free (session_provider->event_filter); ep_rt_utf8_string_free (session_provider->filter_data); ep_rt_utf8_string_free (session_provider->provider_name); ep_rt_object_free (session_provider); @@ -489,7 +479,7 @@ ep_session_provider_free (EventPipeSessionProvider * session_provider) static bool -event_filter_allows_event_id ( +event_filter_enables_event_id ( const EventPipeSessionProviderEventFilter *event_filter, uint32_t event_id) { @@ -499,7 +489,10 @@ event_filter_allows_event_id ( if (event_filter->event_ids == NULL) return !event_filter->enable; - return event_filter->enable == dn_umap_contains (event_filter->event_ids, (void*)(uintptr_t)event_id); + dn_umap_it_t it = dn_umap_uint32_ptr_find (event_filter->event_ids, event_id); + bool contains_event_id = !dn_umap_it_end (it); + + return event_filter->enable == contains_event_id; } bool @@ -522,7 +515,7 @@ ep_session_provider_allows_event ( return false; uint32_t event_id = ep_event_get_event_id (ep_event); - return event_filter_allows_event_id (session_provider->event_filter, event_id); + return event_filter_enables_event_id (session_provider->event_filter, event_id); } /* diff --git a/src/native/eventpipe/ep-session-provider.h b/src/native/eventpipe/ep-session-provider.h index 09459928d6b4d5..9b740c3e2fec7f 100644 --- a/src/native/eventpipe/ep-session-provider.h +++ b/src/native/eventpipe/ep-session-provider.h @@ -101,7 +101,7 @@ struct _EventPipeSessionProvider_Internal { uint64_t keywords; EventPipeEventLevel logging_level; ep_char8_t *filter_data; - const EventPipeSessionProviderEventFilter *event_filter; + EventPipeSessionProviderEventFilter *event_filter; EventPipeSessionProviderTracepointConfiguration *tracepoint_config; }; diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 48e6cf1da4231a..6f8daa54221553 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -58,8 +58,9 @@ is_guid_empty(const uint8_t *guid); static uint16_t -construct_extension_buffer ( +construct_extension_activity_ids_buffer ( uint8_t *extension, + size_t extension_size, const uint8_t *activity_id, const uint8_t *related_activity_id); @@ -215,23 +216,29 @@ session_user_events_tracepoints_init ( EP_ASSERT (session != NULL); EP_ASSERT (session->session_type == EP_SESSION_TYPE_USEREVENTS); - if (user_events_data_fd <= 0) - return false; - - session->user_events_data_fd = user_events_data_fd; + bool result = false; - EventPipeSessionProviderList *providers = ep_session_get_providers (session); + EventPipeSessionProviderList *providers = ep_session_get_providers (session);; EP_ASSERT (providers != NULL); - for (dn_list_it_t it = dn_list_begin (ep_session_provider_list_get_providers (providers)); !dn_list_it_end (it); it = dn_list_it_next (it)) { - EventPipeSessionProvider *session_provider = *dn_list_it_data_t (it, EventPipeSessionProvider *); + ep_raise_error_if_nok (user_events_data_fd > 0); + session->user_events_data_fd = user_events_data_fd; + + DN_LIST_FOREACH_BEGIN (EventPipeSessionProvider *, session_provider, ep_session_provider_list_get_providers (providers)) { EP_ASSERT (session_provider != NULL); - if (!ep_session_provider_register_tracepoints (session_provider, session->user_events_data_fd)) - return false; - } + ep_raise_error_if_nok (ep_session_provider_register_tracepoints (session_provider, session->user_events_data_fd)); + } DN_LIST_FOREACH_END; - return true; + result = true; + +ep_on_exit: + return result; + +ep_on_error: + session_disable_user_events (session); + session->user_events_data_fd = 0; + ep_exit_error_handler (); } EventPipeSession * @@ -591,7 +598,7 @@ ep_session_disable (EventPipeSession *session) if (session->session_type == EP_SESSION_TYPE_USEREVENTS) session_disable_user_events (session); - if (session->file != NULL && ep_session_type_uses_buffer_manager (session->session_type)) { + if (session->file != NULL) { bool ignored; ep_session_write_all_buffers_to_file (session, &ignored); } @@ -620,16 +627,15 @@ void session_disable_user_events (EventPipeSession *session) { EP_ASSERT (session != NULL); - ep_return_void_if_nok (session->session_type == EP_SESSION_TYPE_USEREVENTS); + ep_return_void_if_nok (session->session_type == EP_SESSION_TYPE_USEREVENTS && session->user_events_data_fd > 0); ep_requires_lock_held (); EventPipeSessionProviderList *providers = ep_session_get_providers (session); EP_ASSERT (providers != NULL); - for (dn_list_it_t it = dn_list_begin (ep_session_provider_list_get_providers (providers)); !dn_list_it_end (it); it = dn_list_it_next (it)) { - EventPipeSessionProvider *session_provider = *dn_list_it_data_t (it, EventPipeSessionProvider *); + DN_LIST_FOREACH_BEGIN (EventPipeSessionProvider *, session_provider, ep_session_provider_list_get_providers (providers)) { ep_session_provider_unregister_tracepoints (session_provider, session->user_events_data_fd); - } + } DN_LIST_FOREACH_END; if (session->user_events_data_fd != 0) { #if HAVE_UNISTD_H @@ -655,41 +661,51 @@ is_guid_empty(const uint8_t *guid) } /* - * construct_extension_buffer + * construct_extension_activity_ids_buffer * - * EventPipe Tracepoints include an extension buffer - * that encodes other optional information. + * Encodes non-empty activity ID and related activity ID. */ static uint16_t -construct_extension_buffer ( +construct_extension_activity_ids_buffer ( uint8_t *extension, + size_t extension_size, const uint8_t *activity_id, const uint8_t *related_activity_id) { uint16_t offset = 0; - memset(extension, 0, EP_MAX_EXTENSION_SIZE); + memset (extension, 0, extension_size); bool activity_id_is_empty = is_guid_empty (activity_id); bool related_activity_id_is_empty = is_guid_empty (related_activity_id); + EP_ASSERT ((size_t)(offset + 1 + EP_ACTIVITY_ID_SIZE) <= extension_size); if (!activity_id_is_empty) { extension[offset] = 0x02; - memcpy(extension + offset + 1, activity_id, EP_ACTIVITY_ID_SIZE); - offset += 1 + EP_ACTIVITY_ID_SIZE; + ++offset; + memcpy (extension + offset, activity_id, EP_ACTIVITY_ID_SIZE); + offset += EP_ACTIVITY_ID_SIZE; } - + + EP_ASSERT ((size_t)(offset + 1 + EP_ACTIVITY_ID_SIZE) <= extension_size); if (!related_activity_id_is_empty) { extension[offset] = 0x03; - memcpy(extension + offset + 1, related_activity_id, EP_ACTIVITY_ID_SIZE); - offset += 1 + EP_ACTIVITY_ID_SIZE; + ++offset; + memcpy (extension + offset, related_activity_id, EP_ACTIVITY_ID_SIZE); + offset += EP_ACTIVITY_ID_SIZE; } return offset; } #if HAVE_SYS_UIO_H && HAVE_ERRNO_H +/* + * session_tracepoint_write_event + * + * Writes the event data to the corresponding tracepoint, as configured by the session provider. + * For minimum performance overhead, this function prefers static buffers over dynamic allocations. + */ static bool session_tracepoint_write_event ( @@ -720,16 +736,16 @@ session_tracepoint_write_event ( uint32_t event_id = ep_event_get_event_id (ep_event); uint16_t truncated_event_id = event_id & 0xFFFF; // For parity with EventSource, there shouldn't be any that need more than 16 bits. - uint8_t extension_metadata[5]; + uint8_t extension_metadata[EP_EXTENSION_METADATA_PREFIX_SIZE]; extension_metadata[0] = 0x01; // label uint32_t metadata_len = ep_event_get_metadata_len (ep_event); memcpy (extension_metadata + 1, &metadata_len, sizeof (metadata_len)); - uint8_t extension_activity_ids[EP_MAX_EXTENSION_SIZE]; - uint16_t extension_activity_ids_len = construct_extension_buffer (extension_activity_ids, activity_id, related_activity_id); - EP_ASSERT(extension_activity_ids_len <= EP_MAX_EXTENSION_SIZE); + uint8_t extension_activity_ids[EP_EXTENSION_ACTIVITIES_SIZE]; + uint16_t extension_activity_ids_len = construct_extension_activity_ids_buffer (extension_activity_ids, EP_EXTENSION_ACTIVITIES_SIZE, activity_id, related_activity_id); + EP_ASSERT(extension_activity_ids_len <= EP_EXTENSION_ACTIVITIES_SIZE); - uint32_t extension_len = 5 + metadata_len + extension_activity_ids_len; + uint32_t extension_len = EP_EXTENSION_METADATA_PREFIX_SIZE + metadata_len + extension_activity_ids_len; if (extension_len & 0xFFFF0000) return false; @@ -843,6 +859,22 @@ ep_session_write_event ( // Filter events specific to "this" session based on precomputed flag on provider/events. if (ep_event_is_enabled_by_mask (ep_event, ep_session_get_mask (session))) { switch (session->session_type) { + case EP_SESSION_TYPE_FILE: + case EP_SESSION_TYPE_LISTENER: + case EP_SESSION_TYPE_IPCSTREAM: + case EP_SESSION_TYPE_FILESTREAM: + EP_ASSERT (session->buffer_manager != NULL); + result = ep_buffer_manager_write_event ( + session->buffer_manager, + thread, + session, + ep_event, + payload, + activity_id, + related_activity_id, + event_thread, + stack); + break; case EP_SESSION_TYPE_SYNCHRONOUS: EP_ASSERT (session->synchronous_callback != NULL); session->synchronous_callback ( @@ -874,17 +906,7 @@ ep_session_write_event ( stack); break; default: - EP_ASSERT (session->buffer_manager != NULL); - result = ep_buffer_manager_write_event ( - session->buffer_manager, - thread, - session, - ep_event, - payload, - activity_id, - related_activity_id, - event_thread, - stack); + EP_UNREACHABLE ("Unknown session type."); break; } } diff --git a/src/native/eventpipe/ep-string.c b/src/native/eventpipe/ep-string.c index a41b50104de455..b0a4e0fcbdb8d1 100644 --- a/src/native/eventpipe/ep-string.c +++ b/src/native/eventpipe/ep-string.c @@ -8,6 +8,7 @@ #include "ep-rt.h" #include +#include // va_list, va_start, va_end static ep_char16_t * @@ -133,6 +134,36 @@ ep_rt_utf16le_to_utf8_string_n ( return ep_utf16_to_utf8_string_impl(str, len, /*treat_as_le*/ true); } +ep_char8_t * +ep_rt_utf8_string_printf_alloc (const ep_char8_t *format, ...) +{ + if (!format) + return NULL; + + va_list args; + va_start (args, format); + int len = vsnprintf (NULL, 0, format, args); + va_end (args); + if (len < 0) + return NULL; + + size_t size = (size_t)len + 1; + ep_char8_t *buffer = ep_rt_utf8_string_alloc (size); + if (!buffer) + return NULL; + + va_start (args, format); + int written = vsnprintf (buffer, size, format, args); + va_end (args); + + if (written < 0 || (size_t)written >= size) { + ep_rt_utf8_string_free (buffer); + return NULL; + } + + return buffer; +} + #endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ #endif /* ENABLE_PERFTRACING */ diff --git a/src/native/eventpipe/ep-string.h b/src/native/eventpipe/ep-string.h index 6adb8e99d160f9..fc14844a4ff235 100644 --- a/src/native/eventpipe/ep-string.h +++ b/src/native/eventpipe/ep-string.h @@ -60,5 +60,9 @@ ep_rt_utf16le_to_utf8_string_n ( const ep_char16_t *str, size_t len); +// Allocates a new UTF-8 string and formats it according to the specified format and arguments. +ep_char8_t * +ep_rt_utf8_string_printf_alloc (const ep_char8_t *format, ...); + #endif /* ENABLE_PERFTRACING */ #endif /* EVENTPIPE_STRING_H */ diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index 66ef10e715acee..8acd27396b7c90 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -79,11 +79,20 @@ typedef struct _StreamWriterVtable StreamWriterVtable; #define EP_TRACEPOINT_FORMAT_V1 "u8 version; u16 event_id; __rel_loc u8[] extension; __rel_loc u8[] payload" +// [Tracepoint Name] + " " + [Tracepoint Format V1] + "\0" <= EP_TRACEPOINT_FORMAT_MAX_SIZE +#define EP_TRACEPOINT_NAME_MAX_SIZE (EP_TRACEPOINT_FORMAT_MAX_SIZE - (sizeof(EP_TRACEPOINT_FORMAT_V1) - 1) - 2) + // Tracepoint V1 - write_index, version, truncated_event_id, extension_rel_loc, payload_rel_loc, meta_rel_loc, extension, payload, metadata // To avoid dynamic allocations, using multiple iovec buffers to write the extension #define EP_TRACEPOINT_V1_PAYLOAD_INDEX 8 -#define EP_MAX_EXTENSION_SIZE (2 * (EP_ACTIVITY_ID_SIZE + 1)) +// Used to serialize optional activity Ids in the extensions blob +// 1 byte for label, EP_ACTIVITY_ID_SIZE for the activity ID +#define EP_EXTENSION_ACTIVITIES_SIZE (2 * (1 + EP_ACTIVITY_ID_SIZE)) + +// Serialized before Event metadata in the extensions blob +// 1 byte for label, 4 bytes for metadata size +#define EP_EXTENSION_METADATA_PREFIX_SIZE 5 // Number of static iovec buffers for writing user_events // EventPipeEventPayloads may contain a variable number of EventData structures, diff --git a/src/native/eventpipe/ep-types.h b/src/native/eventpipe/ep-types.h index e431a7ebfa2c2c..70c2f3b812ff45 100644 --- a/src/native/eventpipe/ep-types.h +++ b/src/native/eventpipe/ep-types.h @@ -198,6 +198,9 @@ struct _EventPipeProviderEventFilter { }; #endif +void +eventpipe_collect_tracing_command_free_event_filter (EventPipeProviderEventFilter *event_filter); + /* * EventPipeProviderTracepointSet. * @@ -221,6 +224,9 @@ struct _EventPipeProviderTracepointSet { }; #endif +void +eventpipe_collect_tracing_command_free_tracepoint_sets (EventPipeProviderTracepointSet *tracepoint_set, uint32_t length); + /* * EventPipeProviderTracepointConfiguration. * @@ -244,6 +250,9 @@ struct _EventPipeProviderTracepointConfiguration { }; #endif +void +eventpipe_collect_tracing_command_free_tracepoint_config (EventPipeProviderTracepointConfiguration *tracepoint_config); + /* * EventPipeProviderConfiguration. */ diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index a6b7b35f49c365..036c37187d207a 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -358,6 +358,41 @@ ep_provider_callback_data_free (EventPipeProviderCallbackData *provider_callback ep_rt_object_free (provider_callback_data); } +void +eventpipe_collect_tracing_command_free_event_filter (EventPipeProviderEventFilter *event_filter) +{ + ep_return_void_if_nok (event_filter != NULL); + + ep_rt_object_array_free ((uint32_t *)event_filter->event_ids); + + ep_rt_object_free (event_filter); +} + +void +eventpipe_collect_tracing_command_free_tracepoint_sets (EventPipeProviderTracepointSet *tracepoint_set, uint32_t length) +{ + ep_return_void_if_nok (tracepoint_set != NULL); + + for (uint32_t i = 0; i < length; ++i) { + ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_set->tracepoint_name); + ep_rt_object_array_free ((uint32_t *)tracepoint_set->event_ids); + } + + ep_rt_object_array_free (tracepoint_set); +} + +void +eventpipe_collect_tracing_command_free_tracepoint_config (EventPipeProviderTracepointConfiguration *tracepoint_config) +{ + ep_return_void_if_nok (tracepoint_config != NULL); + + ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_config->default_tracepoint_name); + + eventpipe_collect_tracing_command_free_tracepoint_sets ((EventPipeProviderTracepointSet *)tracepoint_config->non_default_tracepoints, tracepoint_config->non_default_tracepoints_length); + + ep_rt_object_free (tracepoint_config); +} + /* * EventPipeProviderConfiguration. */ @@ -391,7 +426,12 @@ ep_provider_config_init ( void ep_provider_config_fini (EventPipeProviderConfiguration *provider_config) { - ; + ep_return_void_if_nok (provider_config != NULL); + + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (provider_config)); + ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (provider_config)); + eventpipe_collect_tracing_command_free_event_filter ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (provider_config)); + eventpipe_collect_tracing_command_free_tracepoint_config ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (provider_config)); } /* From a7a8f839e0edc009235217ee8df789aba7064776 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Thu, 12 Jun 2025 18:38:51 +0000 Subject: [PATCH 26/32] Address feedback Refactor tracepoint writing logic Use local constants Rename provider config parser --- src/native/eventpipe/ds-eventpipe-protocol.c | 16 +- src/native/eventpipe/ds-eventpipe-protocol.h | 24 ++- src/native/eventpipe/ep-session-provider.c | 13 +- src/native/eventpipe/ep-session-provider.h | 10 +- src/native/eventpipe/ep-session.c | 167 ++++++++++--------- src/native/eventpipe/ep-types-forward.h | 45 +---- 6 files changed, 129 insertions(+), 146 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index fb0e385e9ea0a4..cd3969a9c09a87 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -100,7 +100,7 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( static bool -eventpipe_collect_tracing_command_try_parse_config ( +eventpipe_collect_tracing_command_try_parse_provider_configs ( uint8_t **buffer, uint32_t *buffer_len, EventPipeProviderOptionalFieldFlags optional_field_flags, @@ -509,7 +509,7 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( } /* - * eventpipe_collect_tracing_command_try_parse_config + * eventpipe_collect_tracing_command_try_parse_provider_configs * * With the introduction of CollectTracing5, there is more flexiblity in provider configuration encoding. * This function deserializes all provider configurations from the IPC Stream, providing callers the flexibility @@ -519,7 +519,7 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( */ static bool -eventpipe_collect_tracing_command_try_parse_config ( +eventpipe_collect_tracing_command_try_parse_provider_configs ( uint8_t **buffer, uint32_t *buffer_len, EventPipeProviderOptionalFieldFlags optional_field_flags, @@ -615,7 +615,7 @@ eventpipe_collect_tracing_command_try_parse_payload ( if (!eventpipe_collect_tracing_command_try_parse_circular_buffer_size (&buffer_cursor, &buffer_cursor_len, &instance->circular_buffer_size_in_mb ) || !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || - !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, EP_PROVIDER_OPTFIELD_NONE, &instance->provider_configs)) + !eventpipe_collect_tracing_command_try_parse_provider_configs (&buffer_cursor, &buffer_cursor_len, EP_PROVIDER_OPTFIELD_NONE, &instance->provider_configs)) ep_raise_error (); instance->rundown_requested = true; instance->stackwalk_requested = true; @@ -650,7 +650,7 @@ eventpipe_collect_tracing2_command_try_parse_payload ( if (!eventpipe_collect_tracing_command_try_parse_circular_buffer_size (&buffer_cursor, &buffer_cursor_len, &instance->circular_buffer_size_in_mb ) || !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || !eventpipe_collect_tracing_command_try_parse_rundown_requested (&buffer_cursor, &buffer_cursor_len, &instance->rundown_requested) || - !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, EP_PROVIDER_OPTFIELD_NONE, &instance->provider_configs)) + !eventpipe_collect_tracing_command_try_parse_provider_configs (&buffer_cursor, &buffer_cursor_len, EP_PROVIDER_OPTFIELD_NONE, &instance->provider_configs)) ep_raise_error (); instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; @@ -687,7 +687,7 @@ eventpipe_collect_tracing3_command_try_parse_payload ( !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || !eventpipe_collect_tracing_command_try_parse_rundown_requested (&buffer_cursor, &buffer_cursor_len, &instance->rundown_requested) || !eventpipe_collect_tracing_command_try_parse_stackwalk_requested (&buffer_cursor, &buffer_cursor_len, &instance->stackwalk_requested) || - !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, EP_PROVIDER_OPTFIELD_NONE, &instance->provider_configs)) + !eventpipe_collect_tracing_command_try_parse_provider_configs (&buffer_cursor, &buffer_cursor_len, EP_PROVIDER_OPTFIELD_NONE, &instance->provider_configs)) ep_raise_error (); instance->rundown_keyword = instance->rundown_requested ? ep_default_rundown_keyword : 0; @@ -722,7 +722,7 @@ eventpipe_collect_tracing4_command_try_parse_payload ( !eventpipe_collect_tracing_command_try_parse_serialization_format (&buffer_cursor, &buffer_cursor_len, &instance->serialization_format) || !eventpipe_collect_tracing_command_try_parse_rundown_keyword (&buffer_cursor, &buffer_cursor_len, &instance->rundown_keyword) || !eventpipe_collect_tracing_command_try_parse_stackwalk_requested (&buffer_cursor, &buffer_cursor_len, &instance->stackwalk_requested) || - !eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, EP_PROVIDER_OPTFIELD_NONE, &instance->provider_configs)) + !eventpipe_collect_tracing_command_try_parse_provider_configs (&buffer_cursor, &buffer_cursor_len, EP_PROVIDER_OPTFIELD_NONE, &instance->provider_configs)) ep_raise_error (); instance->rundown_requested = instance->rundown_keyword != 0; @@ -783,7 +783,7 @@ eventpipe_collect_tracing5_command_try_parse_payload ( if (instance->session_type == EP_SESSION_TYPE_USEREVENTS) optional_field_flags = (EventPipeProviderOptionalFieldFlags)(optional_field_flags | EP_PROVIDER_OPTFIELD_TRACEPOINT_CONFIG); - ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_config (&buffer_cursor, &buffer_cursor_len, optional_field_flags, &instance->provider_configs)); + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_provider_configs (&buffer_cursor, &buffer_cursor_len, optional_field_flags, &instance->provider_configs)); instance->rundown_requested = instance->rundown_keyword != 0; diff --git a/src/native/eventpipe/ds-eventpipe-protocol.h b/src/native/eventpipe/ds-eventpipe-protocol.h index 0615f473ebc043..749a44e1a9edc6 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.h +++ b/src/native/eventpipe/ds-eventpipe-protocol.h @@ -13,8 +13,23 @@ #endif #include "ds-getter-setter.h" +/* + * CollectTracing5 introduces additional provider configuration fields. + * For backwards compatibility, these fields are optional and + * these flags indicate which of the optional fields should be + * deserialized from the IPC Stream. + */ +typedef enum +{ + EP_PROVIDER_OPTFIELD_NONE = 0, + EP_PROVIDER_OPTFIELD_EVENT_FILTER = 1, + EP_PROVIDER_OPTFIELD_TRACEPOINT_CONFIG = 2 +} EventPipeProviderOptionalFieldFlags; + /* * EventPipeCollectTracingCommandPayload +* +* https://github.com/dotnet/diagnostics/blob/main/documentation/design-docs/ipc-protocol.md */ // Command = 0x0202 @@ -27,15 +42,6 @@ struct _EventPipeCollectTracingCommandPayload { #else struct _EventPipeCollectTracingCommandPayload_Internal { #endif - // The protocol buffer is defined as: - // X, Y, Z means encode bytes for X followed by bytes for Y followed by bytes for Z - // message = uint circularBufferMB, uint format, array providers - // uint = 4 little endian bytes - // wchar = 2 little endian bytes, UTF16 encoding - // array = uint length, length # of Ts - // string = (array where the last char must = 0) or (length = 0) - // provider_config = ulong keywords, uint logLevel, string provider_name, string filter_data - uint8_t *incoming_buffer; dn_vector_t *provider_configs; uint32_t circular_buffer_size_in_mb; diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index 6cd971a45f7f6c..e84e749875f63b 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -157,7 +157,7 @@ session_provider_tracepoint_register ( struct user_reg reg = {0}; reg.size = sizeof(reg); - reg.enable_bit = EP_TRACEPOINT_ENABLE_BIT; + reg.enable_bit = EP_SESSION_PROVIDER_TRACEPOINT_ENABLE_BIT; reg.enable_size = sizeof(tracepoint->enabled); reg.enable_addr = (uint64_t)&tracepoint->enabled; @@ -182,7 +182,7 @@ session_provider_tracepoint_unregister ( struct user_unreg unreg = {0}; unreg.size = sizeof(unreg); - unreg.disable_bit = EP_TRACEPOINT_ENABLE_BIT; + unreg.disable_bit = EP_SESSION_PROVIDER_TRACEPOINT_ENABLE_BIT; unreg.disable_addr = (uint64_t)&tracepoint->enabled; if (ioctl(user_events_data_fd, DIAG_IOCSUNREG, &unreg) == -1) @@ -351,12 +351,15 @@ static const ep_char8_t * tracepoint_format_alloc (const ep_char8_t *tracepoint_name) { + const int format_max_size = 512; + const ep_char8_t *args = "u8 version; u16 event_id; __rel_loc u8[] extension; __rel_loc u8[] payload"; + ep_return_null_if_nok (tracepoint_name != NULL); - - if (strlen(tracepoint_name) > EP_TRACEPOINT_NAME_MAX_SIZE) + + if ((strlen(tracepoint_name) + strlen(args) + 2) > format_max_size) // +2 for the space and null terminator return NULL; - return ep_rt_utf8_string_printf_alloc ("%s %s", tracepoint_name, EP_TRACEPOINT_FORMAT_V1); + return ep_rt_utf8_string_printf_alloc ("%s %s", tracepoint_name, args); } static diff --git a/src/native/eventpipe/ep-session-provider.h b/src/native/eventpipe/ep-session-provider.h index 9b740c3e2fec7f..5a9fb8b10b561a 100644 --- a/src/native/eventpipe/ep-session-provider.h +++ b/src/native/eventpipe/ep-session-provider.h @@ -16,9 +16,9 @@ */ #if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_EP_GETTER_SETTER) -struct _EventPipeTracepoint { +struct _EventPipeSessionProviderTracepoint { #else -struct _EventPipeTracepoint_Internal { +struct _EventPipeSessionProviderTracepoint_Internal { #endif const ep_char8_t *tracepoint_format; uint32_t write_index; @@ -26,11 +26,13 @@ struct _EventPipeTracepoint_Internal { }; #if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_EP_GETTER_SETTER) -struct _EventPipeTracepoint { - uint8_t _internal [sizeof (struct _EventPipeTracepoint_Internal)]; +struct _EventPipeSessionProviderTracepoint { + uint8_t _internal [sizeof (struct _EventPipeSessionProviderTracepoint_Internal)]; }; #endif +#define EP_SESSION_PROVIDER_TRACEPOINT_ENABLE_BIT 31 + bool ep_session_provider_register_tracepoints ( EventPipeSessionProvider *session_provider, diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 6f8daa54221553..c60313403f7587 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -731,88 +731,106 @@ session_tracepoint_write_event ( if (tracepoint->enabled == 0) return false; - uint8_t version = 0x01; // hardcoded for the first tracepoint format version - - uint32_t event_id = ep_event_get_event_id (ep_event); - uint16_t truncated_event_id = event_id & 0xFFFF; // For parity with EventSource, there shouldn't be any that need more than 16 bits. - - uint8_t extension_metadata[EP_EXTENSION_METADATA_PREFIX_SIZE]; - extension_metadata[0] = 0x01; // label - uint32_t metadata_len = ep_event_get_metadata_len (ep_event); - memcpy (extension_metadata + 1, &metadata_len, sizeof (metadata_len)); - - uint8_t extension_activity_ids[EP_EXTENSION_ACTIVITIES_SIZE]; - uint16_t extension_activity_ids_len = construct_extension_activity_ids_buffer (extension_activity_ids, EP_EXTENSION_ACTIVITIES_SIZE, activity_id, related_activity_id); - EP_ASSERT(extension_activity_ids_len <= EP_EXTENSION_ACTIVITIES_SIZE); - - uint32_t extension_len = EP_EXTENSION_METADATA_PREFIX_SIZE + metadata_len + extension_activity_ids_len; - if (extension_len & 0xFFFF0000) - return false; - - uint32_t payload_len = ep_event_payload_get_size (ep_event_payload); - if ((payload_len & 0xFFFF0000) != 0) - return false; + // Setup iovec array + const int max_non_parameter_iov = 8; + const int max_static_io_capacity = 30; // Should account for most events that use EventData structs + struct iovec static_io[max_static_io_capacity]; + struct iovec *io = static_io; - uint32_t payload_rel_loc = payload_len << 16 | (extension_len & 0xFFFF); - if ((extension_len & 0xFFFF0000) != 0) - return false; + uint8_t *ep_event_data = ep_event_payload_get_data (ep_event_payload); - uint32_t extension_rel_loc = extension_len << 16 | (sizeof(payload_rel_loc) & 0xFFFF); - if (sizeof(payload_rel_loc) & 0xFFFF0000) - return false; + int param_iov = ep_event_data != NULL ? 1 : ep_event_payload->event_data_len; + int io_elem_capacity = param_iov + max_non_parameter_iov; + if (io_elem_capacity > max_static_io_capacity) { + io = (struct iovec *)malloc (sizeof (struct iovec) * io_elem_capacity); + if (io == NULL) + return false; + } - struct iovec static_io[EP_DEFAULT_IOVEC_SIZE]; - struct iovec *io = static_io; - EventData *event_data = NULL; - uint32_t index = EP_TRACEPOINT_V1_PAYLOAD_INDEX; - // Since ep_event_payload can use multiple buffers, try to fit that in first - if (ep_event_payload_get_data (ep_event_payload) != NULL) { - io[index].iov_base = ep_event_payload_get_data (ep_event_payload); - io[index].iov_len = payload_len; - index++; + int io_index = 0; + + // Write Index + io[io_index].iov_base = (void *)&tracepoint->write_index; + io[io_index].iov_len = sizeof(tracepoint->write_index); + io_index++; + + // Version + uint8_t version = 0x01; // Format V1 + io[io_index].iov_base = &version; + io[io_index].iov_len = sizeof(version); + io_index++; + + // Truncated event id + // For parity with EventSource, there shouldn't be any that need more than 16 bits. + uint16_t truncated_event_id = ep_event_get_event_id (ep_event) & 0xFFFF; + io[io_index].iov_base = &truncated_event_id; + io[io_index].iov_len = sizeof(truncated_event_id); + io_index++; + + // Extension and payload relative locations (to be fixed up later) + uint32_t extension_rel_loc = 0; + io[io_index].iov_base = &extension_rel_loc; + io[io_index].iov_len = sizeof(extension_rel_loc); + io_index++; + + uint32_t payload_rel_loc = 0; + io[io_index].iov_base = &payload_rel_loc; + io[io_index].iov_len = sizeof(payload_rel_loc); + io_index++; + + // Extension + int extension_len = 0; + + // Extension Event Metadata + int metadata_len = ep_event_get_metadata_len (ep_event); + uint8_t extension_metadata[1 + sizeof(uint32_t)]; + extension_metadata[0] = 0x01; // label + *(uint32_t*)&extension_metadata[1] = metadata_len; + io[io_index].iov_base = extension_metadata; + io[io_index].iov_len = sizeof(extension_metadata); + io_index++; + extension_len += sizeof(extension_metadata); + + io[io_index].iov_base = (void *)ep_event_get_metadata (ep_event); + io[io_index].iov_len = metadata_len; + io_index++; + extension_len += metadata_len; + + // Extension Activity IDs + const int extension_activity_ids_max_len = 2 * (1 + EP_ACTIVITY_ID_SIZE); + uint8_t extension_activity_ids[extension_activity_ids_max_len]; + uint16_t extension_activity_ids_len = construct_extension_activity_ids_buffer (extension_activity_ids, extension_activity_ids_max_len, activity_id, related_activity_id); + EP_ASSERT (extension_activity_ids_len <= extension_activity_ids_max_len); + io[io_index].iov_base = extension_activity_ids; + io[io_index].iov_len = extension_activity_ids_len; + io_index++; + extension_len += extension_activity_ids_len; + + EP_ASSERT (io_index <= max_non_parameter_iov); + + int ep_event_payload_len = 0; + // EventPipeEventPayload + if (ep_event_data != NULL) { + io[io_index].iov_base = ep_event_data; + io[io_index].iov_len = ep_event_payload_get_size (ep_event_payload); + io_index++; + ep_event_payload_len += ep_event_payload_get_size (ep_event_payload); } else { - event_data = ep_event_payload->event_data; - - // In the unlikely event that an event_payload uses more EventData structs than can fit in the static iovec, - // dynamically allocate to fit all event_data buffers - if (ep_event_payload->event_data_len >= EP_DEFAULT_IOVEC_SIZE - EP_TRACEPOINT_V1_PAYLOAD_INDEX) { - io = (struct iovec *)malloc (sizeof (struct iovec) * (EP_TRACEPOINT_V1_PAYLOAD_INDEX + ep_event_payload->event_data_len)); - if (io == NULL) - return false; - } + EventData *event_data = ep_event_payload->event_data; for (uint32_t i = 0; i < ep_event_payload->event_data_len; ++i) { - io[index].iov_base = (void *)ep_event_data_get_ptr (&event_data[i]); - io[index].iov_len = ep_event_data_get_size (&event_data[i]); - ++index; + io[io_index].iov_base = (void *)ep_event_data_get_ptr (&event_data[i]); + io[io_index].iov_len = ep_event_data_get_size (&event_data[i]); + io_index++; + ep_event_payload_len += ep_event_data_get_size (&event_data[i]); } } - io[0].iov_base = (void *)&tracepoint->write_index; - io[0].iov_len = sizeof(tracepoint->write_index); - - io[1].iov_base = &version; - io[1].iov_len = sizeof(version); - - io[2].iov_base = &truncated_event_id; - io[2].iov_len = sizeof(truncated_event_id); - - io[3].iov_base = &extension_rel_loc; - io[3].iov_len = sizeof(extension_rel_loc); - - io[4].iov_base = &payload_rel_loc; - io[4].iov_len = sizeof(payload_rel_loc); - - io[5].iov_base = extension_metadata; - io[5].iov_len = sizeof(extension_metadata); - - io[6].iov_base = (void *)ep_event_get_metadata (ep_event); - io[6].iov_len = metadata_len; - - io[7].iov_base = extension_activity_ids; - io[7].iov_len = extension_activity_ids_len; + // Calculate the relative locations for extension and payload. + extension_rel_loc = extension_len << 16 | (sizeof(payload_rel_loc) & 0xFFFF); + payload_rel_loc = ep_event_payload_len << 16 | (extension_len & 0xFFFF); ssize_t bytes_written; - while ((bytes_written = writev(session->user_events_data_fd, (const struct iovec *)io, index) < 0) && errno == EINTR); + while ((bytes_written = writev(session->user_events_data_fd, (const struct iovec *)io, io_index) < 0) && errno == EINTR); if (io != static_io) free (io); @@ -1004,10 +1022,7 @@ ep_session_has_started (EventPipeSession *session) bool ep_session_type_uses_buffer_manager (EventPipeSessionType session_type) { - if (session_type == EP_SESSION_TYPE_SYNCHRONOUS || session_type == EP_SESSION_TYPE_USEREVENTS) - return false; - - return true; + return (session_type != EP_SESSION_TYPE_SYNCHRONOUS && session_type != EP_SESSION_TYPE_USEREVENTS); } #endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ diff --git a/src/native/eventpipe/ep-types-forward.h b/src/native/eventpipe/ep-types-forward.h index 8acd27396b7c90..0aa597b155fdb7 100644 --- a/src/native/eventpipe/ep-types-forward.h +++ b/src/native/eventpipe/ep-types-forward.h @@ -49,7 +49,7 @@ typedef struct _EventPipeSystemTime EventPipeSystemTime; typedef struct _EventPipeThread EventPipeThread; typedef struct _EventPipeThreadHolder EventPipeThreadHolder; typedef struct _EventPipeThreadSessionState EventPipeThreadSessionState; -typedef struct _EventPipeTracepoint EventPipeSessionProviderTracepoint; +typedef struct _EventPipeSessionProviderTracepoint EventPipeSessionProviderTracepoint; typedef struct _FastSerializableObject FastSerializableObject; typedef struct _FastSerializableObjectVtable FastSerializableObjectVtable; typedef struct _FastSerializer FastSerializer; @@ -69,36 +69,6 @@ typedef struct _StreamWriterVtable StreamWriterVtable; #define EP_MAX_STACK_DEPTH 100 -/* - * User_Events constants - */ - -#define EP_TRACEPOINT_ENABLE_BIT 31 - -#define EP_TRACEPOINT_FORMAT_MAX_SIZE 512 - -#define EP_TRACEPOINT_FORMAT_V1 "u8 version; u16 event_id; __rel_loc u8[] extension; __rel_loc u8[] payload" - -// [Tracepoint Name] + " " + [Tracepoint Format V1] + "\0" <= EP_TRACEPOINT_FORMAT_MAX_SIZE -#define EP_TRACEPOINT_NAME_MAX_SIZE (EP_TRACEPOINT_FORMAT_MAX_SIZE - (sizeof(EP_TRACEPOINT_FORMAT_V1) - 1) - 2) - -// Tracepoint V1 - write_index, version, truncated_event_id, extension_rel_loc, payload_rel_loc, meta_rel_loc, extension, payload, metadata -// To avoid dynamic allocations, using multiple iovec buffers to write the extension -#define EP_TRACEPOINT_V1_PAYLOAD_INDEX 8 - -// Used to serialize optional activity Ids in the extensions blob -// 1 byte for label, EP_ACTIVITY_ID_SIZE for the activity ID -#define EP_EXTENSION_ACTIVITIES_SIZE (2 * (1 + EP_ACTIVITY_ID_SIZE)) - -// Serialized before Event metadata in the extensions blob -// 1 byte for label, 4 bytes for metadata size -#define EP_EXTENSION_METADATA_PREFIX_SIZE 5 - -// Number of static iovec buffers for writing user_events -// EventPipeEventPayloads may contain a variable number of EventData structures, -// so statically allocate a reasonable number of iovecs to avoid dynamic allocations -#define EP_DEFAULT_IOVEC_SIZE 30 - /* * EventPipe Enums. */ @@ -199,19 +169,6 @@ typedef enum { EP_THREAD_TYPE_SAMPLING } EventPipeThreadType; -/* - * CollectTracing5 introduces additional provider configuration fields. - * For backwards compatibility, these fields are optional and - * these flags indicate which of the optional fields should be - * deserialized from the IPC Stream. - */ -typedef enum -{ - EP_PROVIDER_OPTFIELD_NONE = 0, - EP_PROVIDER_OPTFIELD_EVENT_FILTER = 1, - EP_PROVIDER_OPTFIELD_TRACEPOINT_CONFIG = 2 -} EventPipeProviderOptionalFieldFlags; - /* * EventPipe Basic Types. */ From 08e5f2e9dc64a357e21c064193baf80fbbed8bee Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Fri, 13 Jun 2025 18:44:06 +0000 Subject: [PATCH 27/32] Consistently use addresses of struct fields --- src/native/eventpipe/ds-eventpipe-protocol.c | 246 +++++++++++-------- src/native/eventpipe/ds-protocol.c | 6 +- src/native/eventpipe/ds-protocol.h | 4 +- src/native/eventpipe/ep-session-provider.h | 9 +- 4 files changed, 150 insertions(+), 115 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index cd3969a9c09a87..44727ddfb3a1cc 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -68,27 +68,42 @@ eventpipe_collect_tracing_command_try_parse_stackwalk_requested ( uint32_t *buffer_len, bool *stackwalk_requested); +static +bool +eventpipe_collect_tracing_command_try_parse_logging_level ( + uint8_t **buffer, + uint32_t *buffer_len, + EventPipeEventLevel *logging_level); + static bool eventpipe_collect_tracing_command_try_parse_event_ids ( uint8_t **buffer, uint32_t *buffer_len, const uint32_t length, - uint32_t **event_ids); + const uint32_t **event_ids); static bool eventpipe_collect_tracing_command_try_parse_event_filter ( uint8_t **buffer, uint32_t *buffer_len, - EventPipeProviderEventFilter *event_filter); + const EventPipeProviderEventFilter **event_filter); + +static +bool +eventpipe_collect_tracing_command_try_parse_tracepoint_sets ( + uint8_t **buffer, + uint32_t *buffer_len, + const uint32_t length, + const EventPipeProviderTracepointSet **tracepoint_sets); static bool eventpipe_collect_tracing_command_try_parse_tracepoint_config ( uint8_t **buffer, uint32_t *buffer_len, - EventPipeProviderTracepointConfiguration *tracepoint_config); + const EventPipeProviderTracepointConfiguration **tracepoint_config); static bool @@ -275,28 +290,55 @@ eventpipe_collect_tracing_command_try_parse_stackwalk_requested ( return ds_ipc_message_try_parse_bool (buffer, buffer_len, stackwalk_requested); } +static +bool +eventpipe_collect_tracing_command_try_parse_logging_level ( + uint8_t **buffer, + uint32_t *buffer_len, + EventPipeEventLevel *logging_level) +{ + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (logging_level != NULL); + + uint32_t log_level = 0; + bool can_parse = ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &log_level); + + *logging_level = (EventPipeEventLevel)log_level; + return can_parse && (0 <= (int32_t)log_level) && ((int32_t)log_level <= (int32_t)EP_EVENT_LEVEL_VERBOSE); +} + +/* + * eventpipe_collect_tracing_command_try_parse_event_ids + * + * Parses an array of event IDs from the IPC buffer. Allocates memory for the array + * and transfers ownership to the caller. + */ static bool eventpipe_collect_tracing_command_try_parse_event_ids ( uint8_t **buffer, uint32_t *buffer_len, const uint32_t length, - uint32_t **event_ids) + const uint32_t **event_ids) { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); EP_ASSERT (event_ids != NULL); bool result = false; - *event_ids = NULL; + if (length == 0) return true; - *event_ids = ep_rt_object_array_alloc (uint32_t, length); - ep_raise_error_if_nok (*event_ids != NULL); + uint32_t *ids = ep_rt_object_array_alloc (uint32_t, length); + ep_raise_error_if_nok (ids != NULL); for (uint32_t i = 0; i < length; ++i) - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &(*event_ids)[i])); + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &ids[i])); + + *event_ids = ids; + ids = NULL; result = true; @@ -304,45 +346,41 @@ eventpipe_collect_tracing_command_try_parse_event_ids ( return result; ep_on_error: - ep_rt_object_array_free (*event_ids); - *event_ids = NULL; - + ep_rt_object_array_free (ids); ep_exit_error_handler (); } /* * eventpipe_collect_tracing_command_try_parse_event_filter * - * Introduced in CollectTracing5, the event filter provides EventPipe Sessions - * additional control over which events are enabled/disabled for a particular provider. - * - * event_filter format: - * - bool enable: 0 to disable events, 1 to enable events - * - array event_ids: If specified, a list of Event IDs to disable or enable - * - * Dynamically allocates memory for the event_ids hashset and passes ownership to the caller. + * Parses an EventPipeProviderEventFilter from the IPC Stream. Allocates memory for the EventPipeProviderEventFilter + * and transfers ownership to the caller. */ static bool eventpipe_collect_tracing_command_try_parse_event_filter ( uint8_t **buffer, uint32_t *buffer_len, - EventPipeProviderEventFilter *event_filter) + const EventPipeProviderEventFilter **event_filter) { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); EP_ASSERT (event_filter != NULL); bool result = false; - uint32_t *event_ids = NULL; + *event_filter = NULL; + + EventPipeProviderEventFilter *filter = ep_rt_object_alloc (EventPipeProviderEventFilter); + ep_raise_error_if_nok (filter != NULL); - ep_raise_error_if_nok (ds_ipc_message_try_parse_bool (buffer, buffer_len, &event_filter->enable)); + ep_raise_error_if_nok (ds_ipc_message_try_parse_bool (buffer, buffer_len, &filter->enable)); - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &event_filter->length)); + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &filter->length)); - ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_ids (buffer, buffer_len, event_filter->length, &event_ids)); - event_filter->event_ids = event_ids; - event_ids = NULL; // Ownership transferred to event_filter. + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_ids (buffer, buffer_len, filter->length, &filter->event_ids)); + + *event_filter = filter; + filter = NULL; result = true; @@ -350,70 +388,93 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( return result; ep_on_error: + eventpipe_collect_tracing_command_free_event_filter (filter); ep_exit_error_handler (); } /* - * eventpipe_collect_tracing_command_try_parse_tracepoint_config + * eventpipe_collect_tracing_command_try_parse_tracepoint_sets * - * Introduced in CollectTracing5, user_events-based EventPipe Sessions are required to - * specify a tracepoint configuration per-provider that details which events should be - * written to which tracepoints. Atleast one of default_tracepoint_name or tracepoints - * must be specified. - * - * tracepoint_config format: - * - string default_tracepoint_name: If specified, the default tracepoint to write unmapped enabled events to. - * - array tracepoints: If specified, maps enabled events to tracepoints. - * - * tracepoint_set format: - * - string tracepoint_name: the tracepoint to write the following enabled events_ids to. - * - array event_ids: The Event IDs to be written to tracepoint_name. + * Parses an array of EventPipeProviderTracepointSets from the IPC buffer. + * Allocates memory for the array and its contents, passing ownership to the caller. */ static bool -eventpipe_collect_tracing_command_try_parse_tracepoint_config ( +eventpipe_collect_tracing_command_try_parse_tracepoint_sets ( uint8_t **buffer, uint32_t *buffer_len, - EventPipeProviderTracepointConfiguration *tracepoint_config) + const uint32_t length, + const EventPipeProviderTracepointSet **tracepoint_sets) { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); - EP_ASSERT (tracepoint_config != NULL); + EP_ASSERT (tracepoint_set != NULL); bool result = false; + *tracepoint_sets = NULL; - ep_char8_t *tracepoint_name = NULL; - EventPipeProviderTracepointSet *non_default_tracepoints = NULL; - uint32_t *event_ids = NULL; + if (length == 0) + return false; + + EventPipeProviderTracepointSet *sets = ep_rt_object_array_alloc (EventPipeProviderTracepointSet, length); + ep_raise_error_if_nok (sets != NULL); - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &tracepoint_name)); - tracepoint_config->default_tracepoint_name = tracepoint_name; - tracepoint_name = NULL; // Ownership transferred to tracepoint_config. + for (uint32_t i = 0; i < length; ++i) { + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &sets[i].tracepoint_name)); + ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (sets[i].tracepoint_name)); - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &tracepoint_config->non_default_tracepoints_length)); + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &sets[i].event_ids_length)); - if (tracepoint_config->non_default_tracepoints_length > 0) { - non_default_tracepoints = ep_rt_object_array_alloc (EventPipeProviderTracepointSet, tracepoint_config->non_default_tracepoints_length); - ep_raise_error_if_nok (non_default_tracepoints != NULL); + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_ids (buffer, buffer_len, sets[i].event_ids_length, &sets[i].event_ids)); } - for (uint32_t i = 0; i < tracepoint_config->non_default_tracepoints_length; ++i) { - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &tracepoint_name)); - ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (tracepoint_name)); - non_default_tracepoints[i].tracepoint_name = tracepoint_name; - tracepoint_name = NULL; // Ownership transferred to tracepoint_set. + *tracepoint_sets = sets; + sets = NULL; - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &non_default_tracepoints[i].event_ids_length)); + result = true; - ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_ids (buffer, buffer_len, non_default_tracepoints[i].event_ids_length, &event_ids)); - non_default_tracepoints[i].event_ids = event_ids; - event_ids = NULL; // Ownership transferred to tracepoint_set. - } +ep_on_exit: + return result; - tracepoint_config->non_default_tracepoints = non_default_tracepoints; - non_default_tracepoints = NULL; // Ownership transferred to tracepoint_config. +ep_on_error: + eventpipe_collect_tracing_command_free_tracepoint_sets (sets, length); + ep_exit_error_handler (); +} - ep_raise_error_if_nok (tracepoint_config->default_tracepoint_name != NULL || tracepoint_config->non_default_tracepoints_length > 0); +/* + * eventpipe_collect_tracing_command_try_parse_tracepoint_config + * + * Parses an EventPipeProviderTracepointConfiguration from the IPC Stream. + * Allocates memory for the EventPipeProviderTracepointConfiguration and its fields, + * passing ownership to the caller. + */ +static +bool +eventpipe_collect_tracing_command_try_parse_tracepoint_config ( + uint8_t **buffer, + uint32_t *buffer_len, + const EventPipeProviderTracepointConfiguration **tracepoint_config) +{ + EP_ASSERT (buffer != NULL); + EP_ASSERT (buffer_len != NULL); + EP_ASSERT (tracepoint_config != NULL); + + bool result = false; + *tracepoint_config = NULL; + + EventPipeProviderTracepointConfiguration *config = ep_rt_object_alloc (EventPipeProviderTracepointConfiguration); + ep_raise_error_if_nok (config != NULL); + + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &config->default_tracepoint_name)); + + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &config->non_default_tracepoints_length)); + + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_tracepoint_sets (buffer, buffer_len, config->non_default_tracepoints_length, &config->non_default_tracepoints)); + + ep_raise_error_if_nok (config->default_tracepoint_name != NULL || config->non_default_tracepoints_length > 0); + + *tracepoint_config = config; + config = NULL; result = true; @@ -421,10 +482,7 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( return result; ep_on_error: - ep_rt_object_array_free (event_ids); - eventpipe_collect_tracing_command_free_tracepoint_sets ((EventPipeProviderTracepointSet *)non_default_tracepoints, tracepoint_config->non_default_tracepoints_length); - ep_rt_utf8_string_free (tracepoint_name); - + eventpipe_collect_tracing_command_free_tracepoint_config (config); ep_exit_error_handler (); } @@ -449,13 +507,6 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( bool result = false; - uint32_t log_level = 0; - - ep_char8_t *provider_name = NULL; - ep_char8_t *filter_data = NULL; - EventPipeProviderEventFilter *event_filter = NULL; - EventPipeProviderTracepointConfiguration *tracepoint_config = NULL; - provider_config->keywords = 0; provider_config->logging_level = (EventPipeEventLevel)0; provider_config->provider_name = NULL; @@ -465,34 +516,18 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( ep_raise_error_if_nok (ds_ipc_message_try_parse_uint64_t (buffer, buffer_len, &provider_config->keywords)); - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &log_level)); - provider_config->logging_level = (EventPipeEventLevel)log_level; - ep_raise_error_if_nok (provider_config->logging_level <= EP_EVENT_LEVEL_VERBOSE); - - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &provider_name)); - ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (provider_name)); - provider_config->provider_name = provider_name; - provider_name = NULL; // Ownership transferred to provider_config. - - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &filter_data)); - provider_config->filter_data = filter_data; - filter_data = NULL; // Ownership transferred to provider_config. - - if ((optional_field_flags & EP_PROVIDER_OPTFIELD_EVENT_FILTER) != 0) { - event_filter = ep_rt_object_alloc (EventPipeProviderEventFilter); - ep_raise_error_if_nok (event_filter != NULL); - ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_filter (buffer, buffer_len, event_filter)); - provider_config->event_filter = event_filter; - event_filter = NULL; // Ownership transferred to provider_config. - } + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_logging_level (buffer, buffer_len, &provider_config->logging_level)); - if ((optional_field_flags & EP_PROVIDER_OPTFIELD_TRACEPOINT_CONFIG) != 0) { - tracepoint_config = ep_rt_object_alloc (EventPipeProviderTracepointConfiguration); - ep_raise_error_if_nok (tracepoint_config != NULL); - ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_tracepoint_config (buffer, buffer_len, tracepoint_config)); - provider_config->tracepoint_config = tracepoint_config; - tracepoint_config = NULL; // Ownership transferred to provider_config. - } + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &provider_config->provider_name)); + ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (provider_config->provider_name)); + + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &provider_config->filter_data)); + + if ((optional_field_flags & EP_PROVIDER_OPTFIELD_EVENT_FILTER) != 0) + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_filter (buffer, buffer_len, &provider_config->event_filter)); + + if ((optional_field_flags & EP_PROVIDER_OPTFIELD_TRACEPOINT_CONFIG) != 0) + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_tracepoint_config (buffer, buffer_len, &provider_config->tracepoint_config)); result = true; @@ -500,11 +535,6 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( return result; ep_on_error: - eventpipe_collect_tracing_command_free_tracepoint_config (tracepoint_config); - eventpipe_collect_tracing_command_free_event_filter (event_filter); - ep_rt_utf8_string_free (filter_data); - ep_rt_utf8_string_free (provider_name); - ep_exit_error_handler (); } diff --git a/src/native/eventpipe/ds-protocol.c b/src/native/eventpipe/ds-protocol.c index 9015f128bab51a..021be0a7b49e0e 100644 --- a/src/native/eventpipe/ds-protocol.c +++ b/src/native/eventpipe/ds-protocol.c @@ -454,10 +454,10 @@ ds_ipc_message_try_parse_uint32_t ( } bool -ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc( +ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc ( uint8_t **buffer, uint32_t *buffer_len, - ep_char8_t **string_utf8) + const ep_char8_t **string_utf8) { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); @@ -486,7 +486,7 @@ ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc( ep_on_error: ep_rt_byte_array_free (byte_array); - ep_rt_utf8_string_free (*string_utf8); + ep_rt_utf8_string_free ((ep_char8_t *)*string_utf8); ep_exit_error_handler (); } diff --git a/src/native/eventpipe/ds-protocol.h b/src/native/eventpipe/ds-protocol.h index 91af929616d2df..60925726e26f1c 100644 --- a/src/native/eventpipe/ds-protocol.h +++ b/src/native/eventpipe/ds-protocol.h @@ -130,10 +130,10 @@ ds_ipc_message_try_parse_uint32_t ( uint32_t *value); bool -ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc( +ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc ( uint8_t **buffer, uint32_t *buffer_len, - ep_char8_t **string_utf8); + const ep_char8_t **string_utf8); bool ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc ( diff --git a/src/native/eventpipe/ep-session-provider.h b/src/native/eventpipe/ep-session-provider.h index 5a9fb8b10b561a..91de2d20b9b40b 100644 --- a/src/native/eventpipe/ep-session-provider.h +++ b/src/native/eventpipe/ep-session-provider.h @@ -51,8 +51,8 @@ ep_session_provider_get_tracepoint_for_event ( /* * EventPipeSessionProviderEventFilter. * - * Used in conjunction with keywords and logging level to determine - * whether an event should be enabled for the session. + * Introduced in CollectTracing5, the event filter provides EventPipe Sessions + * additional control over which events are enabled/disabled for a particular provider. */ #if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_EP_GETTER_SETTER) @@ -72,6 +72,11 @@ struct _EventPipeSessionProviderEventFilter { /* * EventPipeSessionProviderTracepointConfiguration. + * + * Introduced in CollectTracing5, user_events-based EventPipe Sessions are required to + * specify a tracepoint configuration per-provider that details which events should be + * written to which tracepoints. Atleast one of default_tracepoint_name or tracepoints + * must be specified. */ #if defined(EP_INLINE_GETTER_SETTER) || defined(EP_IMPL_EP_GETTER_SETTER) From 1f22763857af47ce88adc53d6aea9368eb2f52bd Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Fri, 13 Jun 2025 23:50:16 +0000 Subject: [PATCH 28/32] Fix typo --- src/native/eventpipe/ds-eventpipe-protocol.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 44727ddfb3a1cc..4fc2dfaaf2964d 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -408,7 +408,7 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_sets ( { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); - EP_ASSERT (tracepoint_set != NULL); + EP_ASSERT (tracepoint_sets != NULL); bool result = false; *tracepoint_sets = NULL; From 6e01b62713b34b16c4fc54356be2d2d85d1719b7 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Tue, 17 Jun 2025 04:25:46 +0000 Subject: [PATCH 29/32] Address feedback Make struct data ownership consistent by removing const Make external source files use getters and internal source files directly access data. Add session_provider_tracepoint_free Disallow null tracepoint_name in tracepoint_format_alloc Remove redundant checks Cleanup ep_rt_utf8_string_printf_alloc Cleanup writing to tracepoint --- src/native/eventpipe/ds-eventpipe-protocol.c | 90 +++++++++----------- src/native/eventpipe/ds-protocol.c | 4 +- src/native/eventpipe/ds-protocol.h | 2 +- src/native/eventpipe/ep-event-payload.h | 2 + src/native/eventpipe/ep-session-provider.c | 66 ++++++++------ src/native/eventpipe/ep-session-provider.h | 12 ++- src/native/eventpipe/ep-session.c | 53 ++++++------ src/native/eventpipe/ep-string.c | 52 +++++------ src/native/eventpipe/ep-types.h | 18 ++-- src/native/eventpipe/ep.c | 28 +++--- 10 files changed, 171 insertions(+), 156 deletions(-) diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index 4fc2dfaaf2964d..d7de374543a456 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -80,30 +80,30 @@ bool eventpipe_collect_tracing_command_try_parse_event_ids ( uint8_t **buffer, uint32_t *buffer_len, - const uint32_t length, - const uint32_t **event_ids); + uint32_t length, + uint32_t **event_ids); static bool eventpipe_collect_tracing_command_try_parse_event_filter ( uint8_t **buffer, uint32_t *buffer_len, - const EventPipeProviderEventFilter **event_filter); + EventPipeProviderEventFilter **event_filter); static bool eventpipe_collect_tracing_command_try_parse_tracepoint_sets ( uint8_t **buffer, uint32_t *buffer_len, - const uint32_t length, - const EventPipeProviderTracepointSet **tracepoint_sets); + uint32_t length, + EventPipeProviderTracepointSet **tracepoint_sets); static bool eventpipe_collect_tracing_command_try_parse_tracepoint_config ( uint8_t **buffer, uint32_t *buffer_len, - const EventPipeProviderTracepointConfiguration **tracepoint_config); + EventPipeProviderTracepointConfiguration **tracepoint_config); static bool @@ -319,8 +319,8 @@ bool eventpipe_collect_tracing_command_try_parse_event_ids ( uint8_t **buffer, uint32_t *buffer_len, - const uint32_t length, - const uint32_t **event_ids) + uint32_t length, + uint32_t **event_ids) { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); @@ -332,13 +332,10 @@ eventpipe_collect_tracing_command_try_parse_event_ids ( if (length == 0) return true; - uint32_t *ids = ep_rt_object_array_alloc (uint32_t, length); - ep_raise_error_if_nok (ids != NULL); + *event_ids = ep_rt_object_array_alloc (uint32_t, length); + ep_raise_error_if_nok (*event_ids != NULL); for (uint32_t i = 0; i < length; ++i) - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &ids[i])); - - *event_ids = ids; - ids = NULL; + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &(*event_ids)[i])); result = true; @@ -346,7 +343,8 @@ eventpipe_collect_tracing_command_try_parse_event_ids ( return result; ep_on_error: - ep_rt_object_array_free (ids); + ep_rt_object_array_free (*event_ids); + *event_ids = NULL; ep_exit_error_handler (); } @@ -361,26 +359,22 @@ bool eventpipe_collect_tracing_command_try_parse_event_filter ( uint8_t **buffer, uint32_t *buffer_len, - const EventPipeProviderEventFilter **event_filter) + EventPipeProviderEventFilter **event_filter) { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); EP_ASSERT (event_filter != NULL); bool result = false; - *event_filter = NULL; - EventPipeProviderEventFilter *filter = ep_rt_object_alloc (EventPipeProviderEventFilter); - ep_raise_error_if_nok (filter != NULL); + *event_filter = ep_rt_object_alloc (EventPipeProviderEventFilter); + ep_raise_error_if_nok (*event_filter != NULL); - ep_raise_error_if_nok (ds_ipc_message_try_parse_bool (buffer, buffer_len, &filter->enable)); + ep_raise_error_if_nok (ds_ipc_message_try_parse_bool (buffer, buffer_len, &(*event_filter)->enable)); - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &filter->length)); + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &(*event_filter)->length)); - ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_ids (buffer, buffer_len, filter->length, &filter->event_ids)); - - *event_filter = filter; - filter = NULL; + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_ids (buffer, buffer_len, (*event_filter)->length, &(*event_filter)->event_ids)); result = true; @@ -388,7 +382,8 @@ eventpipe_collect_tracing_command_try_parse_event_filter ( return result; ep_on_error: - eventpipe_collect_tracing_command_free_event_filter (filter); + eventpipe_collect_tracing_command_free_event_filter (*event_filter); + *event_filter = NULL; ep_exit_error_handler (); } @@ -403,8 +398,8 @@ bool eventpipe_collect_tracing_command_try_parse_tracepoint_sets ( uint8_t **buffer, uint32_t *buffer_len, - const uint32_t length, - const EventPipeProviderTracepointSet **tracepoint_sets) + uint32_t length, + EventPipeProviderTracepointSet **tracepoint_sets) { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); @@ -416,28 +411,26 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_sets ( if (length == 0) return false; - EventPipeProviderTracepointSet *sets = ep_rt_object_array_alloc (EventPipeProviderTracepointSet, length); - ep_raise_error_if_nok (sets != NULL); + *tracepoint_sets = ep_rt_object_array_alloc (EventPipeProviderTracepointSet, length); + ep_raise_error_if_nok (*tracepoint_sets != NULL); for (uint32_t i = 0; i < length; ++i) { - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &sets[i].tracepoint_name)); - ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty (sets[i].tracepoint_name)); + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &(*tracepoint_sets)[i].tracepoint_name)); + ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty ((*tracepoint_sets)[i].tracepoint_name)); - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &sets[i].event_ids_length)); + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &(*tracepoint_sets)[i].event_ids_length)); - ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_ids (buffer, buffer_len, sets[i].event_ids_length, &sets[i].event_ids)); + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_event_ids (buffer, buffer_len, (*tracepoint_sets)[i].event_ids_length, &(*tracepoint_sets)[i].event_ids)); } - *tracepoint_sets = sets; - sets = NULL; - result = true; ep_on_exit: return result; ep_on_error: - eventpipe_collect_tracing_command_free_tracepoint_sets (sets, length); + eventpipe_collect_tracing_command_free_tracepoint_sets (*tracepoint_sets, length); + *tracepoint_sets = NULL; ep_exit_error_handler (); } @@ -453,28 +446,24 @@ bool eventpipe_collect_tracing_command_try_parse_tracepoint_config ( uint8_t **buffer, uint32_t *buffer_len, - const EventPipeProviderTracepointConfiguration **tracepoint_config) + EventPipeProviderTracepointConfiguration **tracepoint_config) { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); EP_ASSERT (tracepoint_config != NULL); bool result = false; - *tracepoint_config = NULL; - EventPipeProviderTracepointConfiguration *config = ep_rt_object_alloc (EventPipeProviderTracepointConfiguration); - ep_raise_error_if_nok (config != NULL); + *tracepoint_config = ep_rt_object_alloc (EventPipeProviderTracepointConfiguration); + ep_raise_error_if_nok (*tracepoint_config != NULL); - ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &config->default_tracepoint_name)); + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &(*tracepoint_config)->default_tracepoint_name)); - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &config->non_default_tracepoints_length)); + ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &(*tracepoint_config)->non_default_tracepoints_length)); - ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_tracepoint_sets (buffer, buffer_len, config->non_default_tracepoints_length, &config->non_default_tracepoints)); + ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_tracepoint_sets (buffer, buffer_len, (*tracepoint_config)->non_default_tracepoints_length, &(*tracepoint_config)->non_default_tracepoints)); - ep_raise_error_if_nok (config->default_tracepoint_name != NULL || config->non_default_tracepoints_length > 0); - - *tracepoint_config = config; - config = NULL; + ep_raise_error_if_nok ((*tracepoint_config)->default_tracepoint_name != NULL || (*tracepoint_config)->non_default_tracepoints_length > 0); result = true; @@ -482,7 +471,8 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_config ( return result; ep_on_error: - eventpipe_collect_tracing_command_free_tracepoint_config (config); + eventpipe_collect_tracing_command_free_tracepoint_config (*tracepoint_config); + *tracepoint_config = NULL; ep_exit_error_handler (); } diff --git a/src/native/eventpipe/ds-protocol.c b/src/native/eventpipe/ds-protocol.c index 021be0a7b49e0e..a4fc181bb33dd6 100644 --- a/src/native/eventpipe/ds-protocol.c +++ b/src/native/eventpipe/ds-protocol.c @@ -457,7 +457,7 @@ bool ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc ( uint8_t **buffer, uint32_t *buffer_len, - const ep_char8_t **string_utf8) + ep_char8_t **string_utf8) { EP_ASSERT (buffer != NULL); EP_ASSERT (buffer_len != NULL); @@ -486,7 +486,7 @@ ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc ( ep_on_error: ep_rt_byte_array_free (byte_array); - ep_rt_utf8_string_free ((ep_char8_t *)*string_utf8); + ep_rt_utf8_string_free (*string_utf8); ep_exit_error_handler (); } diff --git a/src/native/eventpipe/ds-protocol.h b/src/native/eventpipe/ds-protocol.h index 60925726e26f1c..8205602206df86 100644 --- a/src/native/eventpipe/ds-protocol.h +++ b/src/native/eventpipe/ds-protocol.h @@ -133,7 +133,7 @@ bool ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc ( uint8_t **buffer, uint32_t *buffer_len, - const ep_char8_t **string_utf8); + ep_char8_t **string_utf8); bool ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc ( diff --git a/src/native/eventpipe/ep-event-payload.h b/src/native/eventpipe/ep-event-payload.h index ae96c5cdebf97e..89d85df89be946 100644 --- a/src/native/eventpipe/ep-event-payload.h +++ b/src/native/eventpipe/ep-event-payload.h @@ -78,6 +78,8 @@ struct _EventPipeEventPayload { #endif EP_DEFINE_GETTER(EventPipeEventPayload *, event_payload, uint8_t *, data) +EP_DEFINE_GETTER(EventPipeEventPayload *, event_payload, const EventData *, event_data) +EP_DEFINE_GETTER(EventPipeEventPayload *, event_payload, uint32_t, event_data_len) EP_DEFINE_GETTER(EventPipeEventPayload *, event_payload, uint32_t, size) static diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index e84e749875f63b..8e2fd52412f7ef 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -51,6 +51,10 @@ session_provider_tracepoint_unregister ( EventPipeSessionProviderTracepoint *tracepoint, int user_events_data_fd); +static +void +session_provider_tracepoint_free (EventPipeSessionProviderTracepoint *tracepoint); + static void DN_CALLBACK_CALLTYPE @@ -61,8 +65,8 @@ void session_provider_tracepoint_config_free (EventPipeSessionProviderTracepointConfiguration *tracepoint_config); static -const ep_char8_t * -tracepoint_format_alloc (const ep_char8_t *tracepoint_name); +ep_char8_t * +tracepoint_format_alloc (ep_char8_t *tracepoint_name); static EventPipeSessionProviderTracepointConfiguration * @@ -71,7 +75,7 @@ session_provider_tracepoint_config_alloc (const EventPipeProviderTracepointConfi static bool event_filter_enables_event_id ( - const EventPipeSessionProviderEventFilter *event_filter, + EventPipeSessionProviderEventFilter *event_filter, uint32_t event_id); /* @@ -290,14 +294,14 @@ ep_session_provider_unregister_tracepoints ( */ const EventPipeSessionProviderTracepoint * ep_session_provider_get_tracepoint_for_event ( - const EventPipeSessionProvider *session_provider, - const EventPipeEvent *ep_event) + EventPipeSessionProvider *session_provider, + EventPipeEvent *ep_event) { EP_ASSERT (session_provider != NULL); EP_ASSERT (ep_event != NULL); - const EventPipeSessionProviderTracepoint *tracepoint = NULL; - const EventPipeSessionProviderTracepointConfiguration *tracepoint_config = session_provider->tracepoint_config; + EventPipeSessionProviderTracepoint *tracepoint = NULL; + EventPipeSessionProviderTracepointConfiguration *tracepoint_config = session_provider->tracepoint_config; if (tracepoint_config == NULL) return tracepoint; @@ -307,23 +311,29 @@ ep_session_provider_get_tracepoint_for_event ( if (tracepoint_config->event_id_to_tracepoint_map == NULL) return tracepoint; - uint32_t event_id = ep_event_get_event_id (ep_event); - dn_umap_it_t tracepoint_found = dn_umap_uint32_ptr_find (tracepoint_config->event_id_to_tracepoint_map, event_id); + dn_umap_it_t tracepoint_found = dn_umap_uint32_ptr_find (tracepoint_config->event_id_to_tracepoint_map, ep_event_get_event_id (ep_event)); if (!dn_umap_it_end (tracepoint_found)) tracepoint = dn_umap_it_value_t (tracepoint_found, EventPipeSessionProviderTracepoint *); return tracepoint; } +static +void +session_provider_tracepoint_free (EventPipeSessionProviderTracepoint *tracepoint) +{ + ep_return_void_if_nok (tracepoint != NULL); + + ep_rt_utf8_string_free (tracepoint->tracepoint_format); + ep_rt_object_free (tracepoint); +} + static void DN_CALLBACK_CALLTYPE tracepoint_free_func (void *tracepoint) { - EP_ASSERT (tracepoint != NULL); - EventPipeSessionProviderTracepoint *tp = *(EventPipeSessionProviderTracepoint **)tracepoint; - ep_rt_utf8_string_free ((ep_char8_t *)tp->tracepoint_format); - ep_rt_object_free (tp); + session_provider_tracepoint_free (*(EventPipeSessionProviderTracepoint **)tracepoint); } static @@ -342,20 +352,20 @@ session_provider_tracepoint_config_free (EventPipeSessionProviderTracepointConfi tracepoint_config->tracepoints = NULL; } - ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_config->default_tracepoint.tracepoint_format); + ep_rt_utf8_string_free (tracepoint_config->default_tracepoint.tracepoint_format); ep_rt_object_free (tracepoint_config); } static -const ep_char8_t * -tracepoint_format_alloc (const ep_char8_t *tracepoint_name) +ep_char8_t * +tracepoint_format_alloc (ep_char8_t *tracepoint_name) { + EP_ASSERT (tracepoint_name != NULL); + const int format_max_size = 512; const ep_char8_t *args = "u8 version; u16 event_id; __rel_loc u8[] extension; __rel_loc u8[] payload"; - ep_return_null_if_nok (tracepoint_name != NULL); - if ((strlen(tracepoint_name) + strlen(args) + 2) > format_max_size) // +2 for the space and null terminator return NULL; @@ -372,7 +382,11 @@ session_provider_tracepoint_config_alloc (const EventPipeProviderTracepointConfi EventPipeSessionProviderTracepoint *tracepoint = NULL; ep_raise_error_if_nok (instance != NULL); - instance->default_tracepoint.tracepoint_format = tracepoint_format_alloc (tracepoint_config->default_tracepoint_name); + instance->default_tracepoint.tracepoint_format = NULL; + if (tracepoint_config->default_tracepoint_name != NULL) { + instance->default_tracepoint.tracepoint_format = tracepoint_format_alloc (tracepoint_config->default_tracepoint_name); + ep_raise_error_if_nok (instance->default_tracepoint.tracepoint_format != NULL); + } instance->tracepoints = NULL; instance->event_id_to_tracepoint_map = NULL; @@ -413,10 +427,7 @@ session_provider_tracepoint_config_alloc (const EventPipeProviderTracepointConfi return instance; ep_on_error: - if (tracepoint != NULL) { - ep_rt_utf8_string_free ((ep_char8_t *)tracepoint->tracepoint_format); - ep_rt_object_free (tracepoint); - } + session_provider_tracepoint_free (tracepoint); session_provider_tracepoint_config_free (instance); instance = NULL; ep_exit_error_handler (); @@ -483,7 +494,7 @@ ep_session_provider_free (EventPipeSessionProvider * session_provider) static bool event_filter_enables_event_id ( - const EventPipeSessionProviderEventFilter *event_filter, + EventPipeSessionProviderEventFilter *event_filter, uint32_t event_id) { if (event_filter == NULL) @@ -500,18 +511,17 @@ event_filter_enables_event_id ( bool ep_session_provider_allows_event ( - const EventPipeSessionProvider *session_provider, + EventPipeSessionProvider *session_provider, const EventPipeEvent *ep_event) { EP_ASSERT(session_provider != NULL); uint64_t keywords = ep_event_get_keywords (ep_event); - uint64_t session_keywords = ep_session_provider_get_keywords(session_provider); - if ((keywords != 0) && ((session_keywords & keywords) == 0)) + if ((keywords != 0) && ((session_provider->keywords & keywords) == 0)) return false; EventPipeEventLevel event_level = ep_event_get_level (ep_event); - EventPipeEventLevel session_level = ep_session_provider_get_logging_level(session_provider); + EventPipeEventLevel session_level = session_provider->logging_level; if ((event_level != EP_EVENT_LEVEL_LOGALWAYS) && (session_level != EP_EVENT_LEVEL_LOGALWAYS) && (session_level < event_level)) diff --git a/src/native/eventpipe/ep-session-provider.h b/src/native/eventpipe/ep-session-provider.h index 91de2d20b9b40b..b8c682cdb4bdf5 100644 --- a/src/native/eventpipe/ep-session-provider.h +++ b/src/native/eventpipe/ep-session-provider.h @@ -20,7 +20,7 @@ struct _EventPipeSessionProviderTracepoint { #else struct _EventPipeSessionProviderTracepoint_Internal { #endif - const ep_char8_t *tracepoint_format; + ep_char8_t *tracepoint_format; uint32_t write_index; uint32_t enabled; }; @@ -33,6 +33,10 @@ struct _EventPipeSessionProviderTracepoint { #define EP_SESSION_PROVIDER_TRACEPOINT_ENABLE_BIT 31 +EP_DEFINE_GETTER(EventPipeSessionProviderTracepoint *, session_provider_tracepoint, const ep_char8_t *, tracepoint_format) +EP_DEFINE_GETTER(EventPipeSessionProviderTracepoint *, session_provider_tracepoint, uint32_t, write_index) +EP_DEFINE_GETTER(EventPipeSessionProviderTracepoint *, session_provider_tracepoint, uint32_t, enabled) + bool ep_session_provider_register_tracepoints ( EventPipeSessionProvider *session_provider, @@ -45,8 +49,8 @@ ep_session_provider_unregister_tracepoints ( const EventPipeSessionProviderTracepoint * ep_session_provider_get_tracepoint_for_event ( - const EventPipeSessionProvider *session_provider, - const EventPipeEvent *ep_event); + EventPipeSessionProvider *session_provider, + EventPipeEvent *ep_event); /* * EventPipeSessionProviderEventFilter. @@ -137,7 +141,7 @@ ep_session_provider_free (EventPipeSessionProvider * session_provider); bool ep_session_provider_allows_event ( - const EventPipeSessionProvider *session_provider, + EventPipeSessionProvider *session_provider, const EventPipeEvent *ep_event); /* diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index c60313403f7587..f5d3d432b727f9 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -218,7 +218,7 @@ session_user_events_tracepoints_init ( bool result = false; - EventPipeSessionProviderList *providers = ep_session_get_providers (session);; + EventPipeSessionProviderList *providers = session->providers; EP_ASSERT (providers != NULL); ep_raise_error_if_nok (user_events_data_fd > 0); @@ -226,7 +226,6 @@ session_user_events_tracepoints_init ( DN_LIST_FOREACH_BEGIN (EventPipeSessionProvider *, session_provider, ep_session_provider_list_get_providers (providers)) { EP_ASSERT (session_provider != NULL); - ep_raise_error_if_nok (ep_session_provider_register_tracepoints (session_provider, session->user_events_data_fd)); } DN_LIST_FOREACH_END; @@ -237,7 +236,6 @@ session_user_events_tracepoints_init ( ep_on_error: session_disable_user_events (session); - session->user_events_data_fd = 0; ep_exit_error_handler (); } @@ -631,18 +629,16 @@ session_disable_user_events (EventPipeSession *session) ep_requires_lock_held (); - EventPipeSessionProviderList *providers = ep_session_get_providers (session); + EventPipeSessionProviderList *providers = session->providers; EP_ASSERT (providers != NULL); DN_LIST_FOREACH_BEGIN (EventPipeSessionProvider *, session_provider, ep_session_provider_list_get_providers (providers)) { ep_session_provider_unregister_tracepoints (session_provider, session->user_events_data_fd); } DN_LIST_FOREACH_END; - if (session->user_events_data_fd != 0) { #if HAVE_UNISTD_H - close (session->user_events_data_fd); + close (session->user_events_data_fd); #endif // HAVE_UNISTD_H - session->user_events_data_fd = 0; - } + session->user_events_data_fd = 0; } static @@ -722,13 +718,13 @@ session_tracepoint_write_event ( EP_ASSERT (ep_event != NULL); EventPipeProvider *provider = ep_event_get_provider (ep_event); - EventPipeSessionProviderList *session_provider_list = ep_session_get_providers (session); + EventPipeSessionProviderList *session_provider_list = session->providers; EventPipeSessionProvider *session_provider = ep_session_provider_list_find_by_name (ep_session_provider_list_get_providers (session_provider_list), ep_provider_get_provider_name (provider)); const EventPipeSessionProviderTracepoint *tracepoint = ep_session_provider_get_tracepoint_for_event (session_provider, ep_event); if (tracepoint == NULL) return false; - if (tracepoint->enabled == 0) + if (ep_session_provider_tracepoint_get_enabled (tracepoint) == 0) return false; // Setup iovec array @@ -738,8 +734,8 @@ session_tracepoint_write_event ( struct iovec *io = static_io; uint8_t *ep_event_data = ep_event_payload_get_data (ep_event_payload); - - int param_iov = ep_event_data != NULL ? 1 : ep_event_payload->event_data_len; + uint32_t ep_event_data_len = ep_event_payload_get_event_data_len (ep_event_payload); + int param_iov = ep_event_data != NULL ? 1 : ep_event_data_len; int io_elem_capacity = param_iov + max_non_parameter_iov; if (io_elem_capacity > max_static_io_capacity) { io = (struct iovec *)malloc (sizeof (struct iovec) * io_elem_capacity); @@ -750,8 +746,9 @@ session_tracepoint_write_event ( int io_index = 0; // Write Index - io[io_index].iov_base = (void *)&tracepoint->write_index; - io[io_index].iov_len = sizeof(tracepoint->write_index); + uint32_t write_index = ep_session_provider_tracepoint_get_write_index (tracepoint); + io[io_index].iov_base = (void *)&write_index; + io[io_index].iov_len = sizeof(write_index); io_index++; // Version @@ -779,10 +776,10 @@ session_tracepoint_write_event ( io_index++; // Extension - int extension_len = 0; + uint32_t extension_len = 0; // Extension Event Metadata - int metadata_len = ep_event_get_metadata_len (ep_event); + uint32_t metadata_len = ep_event_get_metadata_len (ep_event); uint8_t extension_metadata[1 + sizeof(uint32_t)]; extension_metadata[0] = 0x01; // label *(uint32_t*)&extension_metadata[1] = metadata_len; @@ -808,26 +805,34 @@ session_tracepoint_write_event ( EP_ASSERT (io_index <= max_non_parameter_iov); - int ep_event_payload_len = 0; + uint32_t ep_event_payload_total_size = 0; // EventPipeEventPayload if (ep_event_data != NULL) { + uint32_t ep_event_payload_size = ep_event_payload_get_size (ep_event_payload); io[io_index].iov_base = ep_event_data; - io[io_index].iov_len = ep_event_payload_get_size (ep_event_payload); + io[io_index].iov_len = ep_event_payload_size; io_index++; - ep_event_payload_len += ep_event_payload_get_size (ep_event_payload); + ep_event_payload_total_size += ep_event_payload_size; } else { - EventData *event_data = ep_event_payload->event_data; - for (uint32_t i = 0; i < ep_event_payload->event_data_len; ++i) { + const EventData *event_data = ep_event_payload_get_event_data (ep_event_payload); + for (uint32_t i = 0; i < ep_event_data_len; ++i) { + uint32_t ep_event_data_size = ep_event_data_get_size (&event_data[i]); io[io_index].iov_base = (void *)ep_event_data_get_ptr (&event_data[i]); - io[io_index].iov_len = ep_event_data_get_size (&event_data[i]); + io[io_index].iov_len = ep_event_data_size; io_index++; - ep_event_payload_len += ep_event_data_get_size (&event_data[i]); + ep_event_payload_total_size += ep_event_data_size; } } + if ((extension_len & 0xFFFF0000) != 0) + return false; + + if ((ep_event_payload_total_size & 0xFFFF0000) != 0) + return false; + // Calculate the relative locations for extension and payload. extension_rel_loc = extension_len << 16 | (sizeof(payload_rel_loc) & 0xFFFF); - payload_rel_loc = ep_event_payload_len << 16 | (extension_len & 0xFFFF); + payload_rel_loc = ep_event_payload_total_size << 16 | (extension_len & 0xFFFF); ssize_t bytes_written; while ((bytes_written = writev(session->user_events_data_fd, (const struct iovec *)io, io_index) < 0) && errno == EINTR); diff --git a/src/native/eventpipe/ep-string.c b/src/native/eventpipe/ep-string.c index b0a4e0fcbdb8d1..1b9971d00a7d29 100644 --- a/src/native/eventpipe/ep-string.c +++ b/src/native/eventpipe/ep-string.c @@ -137,31 +137,33 @@ ep_rt_utf16le_to_utf8_string_n ( ep_char8_t * ep_rt_utf8_string_printf_alloc (const ep_char8_t *format, ...) { - if (!format) - return NULL; - - va_list args; - va_start (args, format); - int len = vsnprintf (NULL, 0, format, args); - va_end (args); - if (len < 0) - return NULL; - - size_t size = (size_t)len + 1; - ep_char8_t *buffer = ep_rt_utf8_string_alloc (size); - if (!buffer) - return NULL; - - va_start (args, format); - int written = vsnprintf (buffer, size, format, args); - va_end (args); - - if (written < 0 || (size_t)written >= size) { - ep_rt_utf8_string_free (buffer); - return NULL; - } - - return buffer; + if (!format) + return NULL; + + va_list args; + va_start (args, format); + + va_list args_copy; + va_copy (args_copy, args); + int len = vsnprintf (NULL, 0, format, args_copy); + va_end (args_copy); + if (len < 0) + return NULL; + + size_t size = (size_t)len + 1; + ep_char8_t *buffer = ep_rt_utf8_string_alloc (size); + if (!buffer) + return NULL; + + int written = vsnprintf (buffer, size, format, args); + va_end (args); + + if (written < 0 || (size_t)written >= size) { + ep_rt_utf8_string_free (buffer); + return NULL; + } + + return buffer; } #endif /* !defined(EP_INCLUDE_SOURCE_FILES) || defined(EP_FORCE_INCLUDE_SOURCE_FILES) */ diff --git a/src/native/eventpipe/ep-types.h b/src/native/eventpipe/ep-types.h index 70c2f3b812ff45..01537e50e27350 100644 --- a/src/native/eventpipe/ep-types.h +++ b/src/native/eventpipe/ep-types.h @@ -189,7 +189,7 @@ struct _EventPipeProviderEventFilter_Internal { #endif bool enable; uint32_t length; - const uint32_t *event_ids; + uint32_t *event_ids; }; #if !defined(EP_INLINE_GETTER_SETTER) && !defined(EP_IMPL_EP_GETTER_SETTER) @@ -213,8 +213,8 @@ struct _EventPipeProviderTracepointSet { #else struct _EventPipeProviderTracepointSet_Internal { #endif - const ep_char8_t *tracepoint_name; - const uint32_t *event_ids; + ep_char8_t *tracepoint_name; + uint32_t *event_ids; uint32_t event_ids_length; }; @@ -239,8 +239,8 @@ struct _EventPipeProviderTracepointConfiguration { #else struct _EventPipeProviderTracepointConfiguration_Internal { #endif - const ep_char8_t *default_tracepoint_name; - const EventPipeProviderTracepointSet *non_default_tracepoints; + ep_char8_t *default_tracepoint_name; + EventPipeProviderTracepointSet *non_default_tracepoints; uint32_t non_default_tracepoints_length; }; @@ -262,12 +262,12 @@ struct _EventPipeProviderConfiguration { #else struct _EventPipeProviderConfiguration_Internal { #endif - const ep_char8_t *provider_name; - const ep_char8_t *filter_data; + ep_char8_t *provider_name; + ep_char8_t *filter_data; uint64_t keywords; EventPipeEventLevel logging_level; - const EventPipeProviderEventFilter *event_filter; - const EventPipeProviderTracepointConfiguration *tracepoint_config; + EventPipeProviderEventFilter *event_filter; + EventPipeProviderTracepointConfiguration *tracepoint_config; }; diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index 036c37187d207a..a8fbe30b0f8e09 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -363,7 +363,7 @@ eventpipe_collect_tracing_command_free_event_filter (EventPipeProviderEventFilte { ep_return_void_if_nok (event_filter != NULL); - ep_rt_object_array_free ((uint32_t *)event_filter->event_ids); + ep_rt_object_array_free (event_filter->event_ids); ep_rt_object_free (event_filter); } @@ -374,8 +374,8 @@ eventpipe_collect_tracing_command_free_tracepoint_sets (EventPipeProviderTracepo ep_return_void_if_nok (tracepoint_set != NULL); for (uint32_t i = 0; i < length; ++i) { - ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_set->tracepoint_name); - ep_rt_object_array_free ((uint32_t *)tracepoint_set->event_ids); + ep_rt_utf8_string_free (tracepoint_set->tracepoint_name); + ep_rt_object_array_free (tracepoint_set->event_ids); } ep_rt_object_array_free (tracepoint_set); @@ -386,9 +386,9 @@ eventpipe_collect_tracing_command_free_tracepoint_config (EventPipeProviderTrace { ep_return_void_if_nok (tracepoint_config != NULL); - ep_rt_utf8_string_free ((ep_char8_t *)tracepoint_config->default_tracepoint_name); + ep_rt_utf8_string_free (tracepoint_config->default_tracepoint_name); - eventpipe_collect_tracing_command_free_tracepoint_sets ((EventPipeProviderTracepointSet *)tracepoint_config->non_default_tracepoints, tracepoint_config->non_default_tracepoints_length); + eventpipe_collect_tracing_command_free_tracepoint_sets (tracepoint_config->non_default_tracepoints, tracepoint_config->non_default_tracepoints_length); ep_rt_object_free (tracepoint_config); } @@ -408,10 +408,12 @@ ep_provider_config_init ( EP_ASSERT (provider_config != NULL); EP_ASSERT (provider_name != NULL); - provider_config->provider_name = provider_name; + provider_config->provider_name = ep_rt_utf8_string_dup (provider_name); provider_config->keywords = keywords; provider_config->logging_level = logging_level; - provider_config->filter_data = filter_data; + provider_config->filter_data = NULL; + if (filter_data != NULL) + provider_config->filter_data = ep_rt_utf8_string_dup (filter_data); // Currently only supported through IPC Command provider_config->event_filter = NULL; @@ -428,10 +430,10 @@ ep_provider_config_fini (EventPipeProviderConfiguration *provider_config) { ep_return_void_if_nok (provider_config != NULL); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (provider_config)); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (provider_config)); - eventpipe_collect_tracing_command_free_event_filter ((EventPipeProviderEventFilter *)ep_provider_config_get_event_filter (provider_config)); - eventpipe_collect_tracing_command_free_tracepoint_config ((EventPipeProviderTracepointConfiguration *)ep_provider_config_get_tracepoint_config (provider_config)); + ep_rt_utf8_string_free (provider_config->provider_name); + ep_rt_utf8_string_free (provider_config->filter_data); + eventpipe_collect_tracing_command_free_event_filter (provider_config->event_filter); + eventpipe_collect_tracing_command_free_tracepoint_config (provider_config->tracepoint_config); } /* @@ -1149,8 +1151,8 @@ ep_enable_2 ( if (providers) { for (int32_t i = 0; i < providers_len; ++i) { ep_provider_config_fini (&providers [i]); - ep_rt_utf8_string_free ((ep_char8_t *)providers [i].provider_name); - ep_rt_utf8_string_free ((ep_char8_t *)providers [i].filter_data); + ep_rt_utf8_string_free (providers [i].provider_name); + ep_rt_utf8_string_free (providers [i].filter_data); } ep_rt_object_array_free (providers); } From 54ec5182708efc37401fe209ec01bc79a4095815 Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Tue, 17 Jun 2025 16:45:29 +0000 Subject: [PATCH 30/32] Address feedback Update ep_provider_config_init/fini callsites Make resource cleanup logic consistent Account for early exit memory leaks Various cleanup --- .../nativeaot/Runtime/eventpipeinternal.cpp | 14 ++++++++------ src/coreclr/vm/eventpipeadapter.h | 14 ++++++++------ src/mono/mono/component/event_pipe.c | 13 +++++++------ src/native/containers/dn-vector.c | 3 +++ src/native/eventpipe/ds-eventpipe-protocol.c | 16 ++++++---------- src/native/eventpipe/ds-protocol.c | 4 +++- src/native/eventpipe/ep-session.c | 12 +++++++----- src/native/eventpipe/ep-string.c | 8 ++++++-- src/native/eventpipe/ep.c | 13 ++++++------- 9 files changed, 54 insertions(+), 43 deletions(-) diff --git a/src/coreclr/nativeaot/Runtime/eventpipeinternal.cpp b/src/coreclr/nativeaot/Runtime/eventpipeinternal.cpp index 0fc3881c53476e..ca79248b1ecaa4 100644 --- a/src/coreclr/nativeaot/Runtime/eventpipeinternal.cpp +++ b/src/coreclr/nativeaot/Runtime/eventpipeinternal.cpp @@ -67,12 +67,16 @@ EXTERN_C uint64_t QCALLTYPE EventPipeInternal_Enable( if (configProviders) { for (uint32_t i = 0; i < numProviders; ++i) { + ep_char8_t *providerName = ep_rt_utf16_to_utf8_string (reinterpret_cast(nativeProviders[i].pProviderName)); + ep_char8_t *filterData = ep_rt_utf16_to_utf8_string (reinterpret_cast(nativeProviders[i].pFilterData)); ep_provider_config_init ( &configProviders[i], - ep_rt_utf16_to_utf8_string (reinterpret_cast(nativeProviders[i].pProviderName)), + providerName, nativeProviders[i].keywords, static_cast(nativeProviders[i].loggingLevel), - ep_rt_utf16_to_utf8_string (reinterpret_cast(nativeProviders[i].pFilterData))); + filterData); + ep_rt_utf8_string_free (providerName); + ep_rt_utf8_string_free (filterData); } } @@ -95,10 +99,8 @@ EXTERN_C uint64_t QCALLTYPE EventPipeInternal_Enable( ep_start_streaming(result); if (configProviders) { - for (uint32_t i = 0; i < numProviders; ++i) { - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&configProviders[i])); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&configProviders[i])); - } + for (uint32_t i = 0; i < numProviders; ++i) + ep_provider_config_fini (&configProviders[i]); free(configProviders); } diff --git a/src/coreclr/vm/eventpipeadapter.h b/src/coreclr/vm/eventpipeadapter.h index 2b261d9162d561..6673a3abccd89a 100644 --- a/src/coreclr/vm/eventpipeadapter.h +++ b/src/coreclr/vm/eventpipeadapter.h @@ -40,12 +40,16 @@ class EventPipeProviderConfigurationAdapter final m_providerConfigsLen = providerConfigsLen; if (m_providerConfigs) { for (uint32_t i = 0; i < providerConfigsLen; ++i) { + ep_char8_t *providerName = ep_rt_utf16_to_utf8_string (reinterpret_cast(providerConfigs[i].providerName)); + ep_char8_t *filterData = ep_rt_utf16_to_utf8_string (reinterpret_cast(providerConfigs[i].filterData)); ep_provider_config_init ( &m_providerConfigs[i], - ep_rt_utf16_to_utf8_string (reinterpret_cast(providerConfigs[i].providerName)), + providerName, providerConfigs[i].keywords, static_cast(providerConfigs[i].loggingLevel), - ep_rt_utf16_to_utf8_string (reinterpret_cast(providerConfigs[i].filterData))); + filterData); + ep_rt_utf8_string_free (providerName); + ep_rt_utf8_string_free (filterData); } } } @@ -54,10 +58,8 @@ class EventPipeProviderConfigurationAdapter final { STATIC_CONTRACT_NOTHROW; if (m_providerConfigs) { - for (uint32_t i = 0; i < m_providerConfigsLen; ++i) { - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_provider_name (&m_providerConfigs[i])); - ep_rt_utf8_string_free ((ep_char8_t *)ep_provider_config_get_filter_data (&m_providerConfigs[i])); - } + for (uint32_t i = 0; i < m_providerConfigsLen; ++i) + ep_provider_config_fini(&m_providerConfigs[i]); delete [] m_providerConfigs; } } diff --git a/src/mono/mono/component/event_pipe.c b/src/mono/mono/component/event_pipe.c index ac591492eb2f0d..ad4e4d7516ba1e 100644 --- a/src/mono/mono/component/event_pipe.c +++ b/src/mono/mono/component/event_pipe.c @@ -158,12 +158,16 @@ event_pipe_enable ( if (config_providers) { for (guint32 i = 0; i < providers_len; ++i) { + char *provider_name = providers[i].provider_name ? mono_utf16_to_utf8 (providers[i].provider_name, g_utf16_len (providers[i].provider_name), error) : NULL; + char *filter_data = providers[i].filter_data ? mono_utf16_to_utf8 (providers[i].filter_data, g_utf16_len (providers[i].filter_data), error) : NULL; 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, + provider_name, 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); + filter_data); + g_free (provider_name); + g_free (filter_data); } } @@ -180,11 +184,8 @@ event_pipe_enable ( NULL); if (config_providers) { - for (guint32 i = 0; i < providers_len; ++i) { + for (guint32 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; diff --git a/src/native/containers/dn-vector.c b/src/native/containers/dn-vector.c index a70eda7bdb901b..5e2cd46c1e822c 100644 --- a/src/native/containers/dn-vector.c +++ b/src/native/containers/dn-vector.c @@ -268,6 +268,9 @@ dn_vector_custom_free ( dn_vector_t *vector, dn_vector_dispose_func_t dispose_func) { + if (DN_UNLIKELY(!vector)) + return; + dn_vector_custom_dispose (vector, dispose_func); dn_allocator_free (vector->_internal._allocator, vector); } diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index d7de374543a456..ef95db8a653540 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -525,6 +525,7 @@ eventpipe_collect_tracing_command_try_parse_provider_config ( return result; ep_on_error: + ep_provider_config_fini (provider_config); ep_exit_error_handler (); } @@ -555,8 +556,6 @@ eventpipe_collect_tracing_command_try_parse_provider_configs ( uint32_t count_configs = 0; dn_vector_custom_alloc_params_t params = {0, }; - EventPipeProviderConfiguration provider_config; - ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &count_configs)); ep_raise_error_if_nok (count_configs <= max_count_configs); params.capacity = count_configs; @@ -564,17 +563,15 @@ eventpipe_collect_tracing_command_try_parse_provider_configs ( ep_raise_error_if_nok (*result); for (uint32_t i = 0; i < count_configs; ++i) { + EventPipeProviderConfiguration provider_config; ep_raise_error_if_nok (eventpipe_collect_tracing_command_try_parse_provider_config ( buffer, buffer_len, optional_field_flags, &provider_config)); - ep_raise_error_if_nok (dn_vector_push_back (*result, provider_config)); - provider_config.provider_name = NULL; - provider_config.filter_data = NULL; - provider_config.event_filter = NULL; - provider_config.tracepoint_config = NULL; + if (!dn_vector_push_back (*result, provider_config)) + ep_provider_config_fini (&provider_config); } ep_on_exit: @@ -582,9 +579,8 @@ eventpipe_collect_tracing_command_try_parse_provider_configs ( ep_on_error: count_configs = 0; - - ep_provider_config_fini (&provider_config); - + dn_vector_custom_free (*result, eventpipe_provider_configs_free_func); + *result = NULL; ep_exit_error_handler (); } diff --git a/src/native/eventpipe/ds-protocol.c b/src/native/eventpipe/ds-protocol.c index a4fc181bb33dd6..8338c8103a9550 100644 --- a/src/native/eventpipe/ds-protocol.c +++ b/src/native/eventpipe/ds-protocol.c @@ -468,9 +468,10 @@ ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc ( uint8_t *byte_array = NULL; uint32_t byte_array_len = 0; + *string_utf8 = NULL; + ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_byte_array_alloc (buffer, buffer_len, &byte_array, &byte_array_len)); - *string_utf8 = NULL; if (byte_array) { *string_utf8 = ep_rt_utf16le_to_utf8_string ((const ep_char16_t *)byte_array); ep_raise_error_if_nok (*string_utf8 != NULL); @@ -487,6 +488,7 @@ ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc ( ep_on_error: ep_rt_byte_array_free (byte_array); ep_rt_utf8_string_free (*string_utf8); + *string_utf8 = NULL; ep_exit_error_handler (); } diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index f5d3d432b727f9..367915e53a17a5 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -638,7 +638,7 @@ session_disable_user_events (EventPipeSession *session) #if HAVE_UNISTD_H close (session->user_events_data_fd); #endif // HAVE_UNISTD_H - session->user_events_data_fd = 0; + session->user_events_data_fd = -1; } static @@ -669,6 +669,8 @@ construct_extension_activity_ids_buffer ( const uint8_t *activity_id, const uint8_t *related_activity_id) { + EP_ASSERT (extension != NULL); + EP_ASSERT (extension_size >= 2 * (1 + EP_ACTIVITY_ID_SIZE)); uint16_t offset = 0; memset (extension, 0, extension_size); @@ -824,11 +826,11 @@ session_tracepoint_write_event ( } } - if ((extension_len & 0xFFFF0000) != 0) - return false; - - if ((ep_event_payload_total_size & 0xFFFF0000) != 0) + if (((extension_len & 0xFFFF0000) != 0) || ((ep_event_payload_total_size & 0xFFFF0000) != 0)) { + if (io != static_io) + free (io); return false; + } // Calculate the relative locations for extension and payload. extension_rel_loc = extension_len << 16 | (sizeof(payload_rel_loc) & 0xFFFF); diff --git a/src/native/eventpipe/ep-string.c b/src/native/eventpipe/ep-string.c index 1b9971d00a7d29..04afaa0e484597 100644 --- a/src/native/eventpipe/ep-string.c +++ b/src/native/eventpipe/ep-string.c @@ -147,13 +147,17 @@ ep_rt_utf8_string_printf_alloc (const ep_char8_t *format, ...) va_copy (args_copy, args); int len = vsnprintf (NULL, 0, format, args_copy); va_end (args_copy); - if (len < 0) + if (len < 0) { + va_end (args); return NULL; + } size_t size = (size_t)len + 1; ep_char8_t *buffer = ep_rt_utf8_string_alloc (size); - if (!buffer) + if (!buffer) { + va_end (args); return NULL; + } int written = vsnprintf (buffer, size, format, args); va_end (args); diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index a8fbe30b0f8e09..9a68ec9287dda3 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -1082,9 +1082,9 @@ ep_enable_2 ( providers = ep_rt_object_array_alloc (EventPipeProviderConfiguration, providers_len); ep_raise_error_if_nok (providers != NULL); - ep_provider_config_init (&providers [0], ep_rt_utf8_string_dup (ep_config_get_public_provider_name_utf8 ()), 0x4c14fccbd, EP_EVENT_LEVEL_VERBOSE, NULL); - ep_provider_config_init (&providers [1], ep_rt_utf8_string_dup (ep_config_get_private_provider_name_utf8 ()), 0x4002000b, EP_EVENT_LEVEL_VERBOSE, NULL); - ep_provider_config_init (&providers [2], ep_rt_utf8_string_dup (ep_config_get_sample_profiler_provider_name_utf8 ()), 0x0, EP_EVENT_LEVEL_VERBOSE, NULL); + ep_provider_config_init (&providers [0], ep_config_get_public_provider_name_utf8 (), 0x4c14fccbd, EP_EVENT_LEVEL_VERBOSE, NULL); + ep_provider_config_init (&providers [1], ep_config_get_private_provider_name_utf8 (), 0x4002000b, EP_EVENT_LEVEL_VERBOSE, NULL); + ep_provider_config_init (&providers [2], ep_config_get_sample_profiler_provider_name_utf8 (), 0x0, EP_EVENT_LEVEL_VERBOSE, NULL); } else { // Count number of providers to parse. while (*providers_config_to_parse != '\0') { @@ -1122,6 +1122,8 @@ ep_enable_2 ( args = get_next_config_value_as_utf8_string (&providers_config_to_parse); ep_provider_config_init (&providers [current_provider++], provider_name, keyword_mask, level, args); + ep_rt_utf8_string_free (provider_name); + ep_rt_utf8_string_free (args); if (!providers_config_to_parse) break; @@ -1149,11 +1151,8 @@ ep_enable_2 ( ep_on_exit: if (providers) { - for (int32_t i = 0; i < providers_len; ++i) { + for (int32_t i = 0; i < providers_len; ++i) ep_provider_config_fini (&providers [i]); - ep_rt_utf8_string_free (providers [i].provider_name); - ep_rt_utf8_string_free (providers [i].filter_data); - } ep_rt_object_array_free (providers); } From 93f7f0abd91557a4d04d0620fcf519566520847c Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Tue, 17 Jun 2025 20:45:55 +0000 Subject: [PATCH 31/32] Address Feedback Fix eventpipe_collect_tracing_command_free_tracepoint_sets logic Clarify len variable names Consistently use -1 as invalid file descriptor Update event_pipe to use ep_rt_utf16_to_utf8_string/free --- src/mono/mono/component/event_pipe.c | 9 ++++---- src/native/eventpipe/ds-eventpipe-protocol.c | 24 ++++++++++---------- src/native/eventpipe/ep-session-provider.c | 12 +++++----- src/native/eventpipe/ep-session.c | 6 ++--- src/native/eventpipe/ep-types.h | 2 +- src/native/eventpipe/ep.c | 14 ++++++------ 6 files changed, 33 insertions(+), 34 deletions(-) diff --git a/src/mono/mono/component/event_pipe.c b/src/mono/mono/component/event_pipe.c index ad4e4d7516ba1e..0c020405a97b15 100644 --- a/src/mono/mono/component/event_pipe.c +++ b/src/mono/mono/component/event_pipe.c @@ -151,23 +151,22 @@ event_pipe_enable ( IpcStream *stream, EventPipeSessionSynchronousCallback sync_callback) { - ERROR_DECL (error); EventPipeSessionID session_id = 0; EventPipeProviderConfiguration *config_providers = g_new0 (EventPipeProviderConfiguration, providers_len); if (config_providers) { for (guint32 i = 0; i < providers_len; ++i) { - char *provider_name = providers[i].provider_name ? mono_utf16_to_utf8 (providers[i].provider_name, g_utf16_len (providers[i].provider_name), error) : NULL; - char *filter_data = providers[i].filter_data ? mono_utf16_to_utf8 (providers[i].filter_data, g_utf16_len (providers[i].filter_data), error) : NULL; + ep_char8_t *provider_name = ep_rt_utf16_to_utf8_string ((const ep_char16_t *)(providers[i].provider_name)); + ep_char8_t *filter_data = ep_rt_utf16_to_utf8_string ((const ep_char16_t *)(providers[i].filter_data)); ep_provider_config_init ( &config_providers[i], provider_name, providers [i].keywords, (EventPipeEventLevel)providers [i].logging_level, filter_data); - g_free (provider_name); - g_free (filter_data); + ep_rt_utf8_string_free (provider_name); + ep_rt_utf8_string_free (filter_data); } } diff --git a/src/native/eventpipe/ds-eventpipe-protocol.c b/src/native/eventpipe/ds-eventpipe-protocol.c index ef95db8a653540..4f5e6daf299d5a 100644 --- a/src/native/eventpipe/ds-eventpipe-protocol.c +++ b/src/native/eventpipe/ds-eventpipe-protocol.c @@ -80,7 +80,7 @@ bool eventpipe_collect_tracing_command_try_parse_event_ids ( uint8_t **buffer, uint32_t *buffer_len, - uint32_t length, + uint32_t event_ids_len, uint32_t **event_ids); static @@ -95,7 +95,7 @@ bool eventpipe_collect_tracing_command_try_parse_tracepoint_sets ( uint8_t **buffer, uint32_t *buffer_len, - uint32_t length, + uint32_t tracepoint_sets_len, EventPipeProviderTracepointSet **tracepoint_sets); static @@ -319,7 +319,7 @@ bool eventpipe_collect_tracing_command_try_parse_event_ids ( uint8_t **buffer, uint32_t *buffer_len, - uint32_t length, + uint32_t event_ids_len, uint32_t **event_ids) { EP_ASSERT (buffer != NULL); @@ -329,12 +329,12 @@ eventpipe_collect_tracing_command_try_parse_event_ids ( bool result = false; *event_ids = NULL; - if (length == 0) + if (event_ids_len == 0) return true; - *event_ids = ep_rt_object_array_alloc (uint32_t, length); + *event_ids = ep_rt_object_array_alloc (uint32_t, event_ids_len); ep_raise_error_if_nok (*event_ids != NULL); - for (uint32_t i = 0; i < length; ++i) + for (uint32_t i = 0; i < event_ids_len; ++i) ep_raise_error_if_nok (ds_ipc_message_try_parse_uint32_t (buffer, buffer_len, &(*event_ids)[i])); result = true; @@ -398,7 +398,7 @@ bool eventpipe_collect_tracing_command_try_parse_tracepoint_sets ( uint8_t **buffer, uint32_t *buffer_len, - uint32_t length, + uint32_t tracepoint_sets_len, EventPipeProviderTracepointSet **tracepoint_sets) { EP_ASSERT (buffer != NULL); @@ -408,13 +408,13 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_sets ( bool result = false; *tracepoint_sets = NULL; - if (length == 0) + if (tracepoint_sets_len == 0) return false; - *tracepoint_sets = ep_rt_object_array_alloc (EventPipeProviderTracepointSet, length); + *tracepoint_sets = ep_rt_object_array_alloc (EventPipeProviderTracepointSet, tracepoint_sets_len); ep_raise_error_if_nok (*tracepoint_sets != NULL); - for (uint32_t i = 0; i < length; ++i) { + for (uint32_t i = 0; i < tracepoint_sets_len; ++i) { ep_raise_error_if_nok (ds_ipc_message_try_parse_string_utf16_t_string_utf8_t_alloc (buffer, buffer_len, &(*tracepoint_sets)[i].tracepoint_name)); ep_raise_error_if_nok (!ep_rt_utf8_string_is_null_or_empty ((*tracepoint_sets)[i].tracepoint_name)); @@ -429,7 +429,7 @@ eventpipe_collect_tracing_command_try_parse_tracepoint_sets ( return result; ep_on_error: - eventpipe_collect_tracing_command_free_tracepoint_sets (*tracepoint_sets, length); + eventpipe_collect_tracing_command_free_tracepoint_sets (*tracepoint_sets, tracepoint_sets_len); *tracepoint_sets = NULL; ep_exit_error_handler (); } @@ -901,7 +901,7 @@ eventpipe_protocol_helper_collect_tracing ( return false; } - int user_events_data_fd = 0; + int user_events_data_fd = -1; if (payload->session_type == EP_SESSION_TYPE_USEREVENTS) { if (!ds_ipc_stream_read_fd (stream, &user_events_data_fd)) { ds_ipc_message_send_error (stream, DS_IPC_E_BAD_ENCODING); diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index 8e2fd52412f7ef..d8b165f563845e 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -157,7 +157,7 @@ session_provider_tracepoint_register ( int user_events_data_fd) { EP_ASSERT (tracepoint != NULL); - EP_ASSERT (user_events_data_fd != 0); + EP_ASSERT (user_events_data_fd != -1); struct user_reg reg = {0}; reg.size = sizeof(reg); @@ -182,7 +182,7 @@ session_provider_tracepoint_unregister ( int user_events_data_fd) { EP_ASSERT (tracepoint != NULL); - EP_ASSERT (user_events_data_fd != 0); + EP_ASSERT (user_events_data_fd != -1); struct user_unreg unreg = {0}; unreg.size = sizeof(unreg); @@ -229,9 +229,9 @@ ep_session_provider_register_tracepoints ( int user_events_data_fd) { EP_ASSERT (session_provider != NULL); - EP_ASSERT (user_events_data_fd > 0); + EP_ASSERT (user_events_data_fd != -1); - if (user_events_data_fd <= 0) + if (user_events_data_fd < 0) return false; EventPipeSessionProviderTracepointConfiguration *tracepoint_config = session_provider->tracepoint_config; @@ -267,9 +267,9 @@ ep_session_provider_unregister_tracepoints ( int user_events_data_fd) { EP_ASSERT (session_provider != NULL); - EP_ASSERT (user_events_data_fd > 0); + EP_ASSERT (user_events_data_fd != -1); - if (user_events_data_fd <= 0) + if (user_events_data_fd < 0) return; if (session_provider->tracepoint_config == NULL) diff --git a/src/native/eventpipe/ep-session.c b/src/native/eventpipe/ep-session.c index 367915e53a17a5..ac9cf1d7e36320 100644 --- a/src/native/eventpipe/ep-session.c +++ b/src/native/eventpipe/ep-session.c @@ -221,7 +221,7 @@ session_user_events_tracepoints_init ( EventPipeSessionProviderList *providers = session->providers; EP_ASSERT (providers != NULL); - ep_raise_error_if_nok (user_events_data_fd > 0); + ep_raise_error_if_nok (user_events_data_fd != -1); session->user_events_data_fd = user_events_data_fd; DN_LIST_FOREACH_BEGIN (EventPipeSessionProvider *, session_provider, ep_session_provider_list_get_providers (providers)) { @@ -625,7 +625,7 @@ void session_disable_user_events (EventPipeSession *session) { EP_ASSERT (session != NULL); - ep_return_void_if_nok (session->session_type == EP_SESSION_TYPE_USEREVENTS && session->user_events_data_fd > 0); + ep_return_void_if_nok (session->session_type == EP_SESSION_TYPE_USEREVENTS && session->user_events_data_fd != -1); ep_requires_lock_held (); @@ -919,7 +919,7 @@ ep_session_write_event ( result = true; break; case EP_SESSION_TYPE_USEREVENTS: - EP_ASSERT (session->user_events_data_fd != 0); + EP_ASSERT (session->user_events_data_fd != -1); result = session_tracepoint_write_event ( session, thread, diff --git a/src/native/eventpipe/ep-types.h b/src/native/eventpipe/ep-types.h index 01537e50e27350..bb2b6223a504f5 100644 --- a/src/native/eventpipe/ep-types.h +++ b/src/native/eventpipe/ep-types.h @@ -225,7 +225,7 @@ struct _EventPipeProviderTracepointSet { #endif void -eventpipe_collect_tracing_command_free_tracepoint_sets (EventPipeProviderTracepointSet *tracepoint_set, uint32_t length); +eventpipe_collect_tracing_command_free_tracepoint_sets (EventPipeProviderTracepointSet *tracepoint_sets, uint32_t tracepoint_sets_len); /* * EventPipeProviderTracepointConfiguration. diff --git a/src/native/eventpipe/ep.c b/src/native/eventpipe/ep.c index 9a68ec9287dda3..b67c825b982a64 100644 --- a/src/native/eventpipe/ep.c +++ b/src/native/eventpipe/ep.c @@ -369,16 +369,16 @@ eventpipe_collect_tracing_command_free_event_filter (EventPipeProviderEventFilte } void -eventpipe_collect_tracing_command_free_tracepoint_sets (EventPipeProviderTracepointSet *tracepoint_set, uint32_t length) +eventpipe_collect_tracing_command_free_tracepoint_sets (EventPipeProviderTracepointSet *tracepoint_sets, uint32_t tracepoint_sets_len) { - ep_return_void_if_nok (tracepoint_set != NULL); + ep_return_void_if_nok (tracepoint_sets != NULL); - for (uint32_t i = 0; i < length; ++i) { - ep_rt_utf8_string_free (tracepoint_set->tracepoint_name); - ep_rt_object_array_free (tracepoint_set->event_ids); + for (uint32_t i = 0; i < tracepoint_sets_len; ++i) { + ep_rt_utf8_string_free (tracepoint_sets[i].tracepoint_name); + ep_rt_object_array_free (tracepoint_sets[i].event_ids); } - ep_rt_object_array_free (tracepoint_set); + ep_rt_object_array_free (tracepoint_sets); } void @@ -524,7 +524,7 @@ static bool check_options_valid (const EventPipeSessionOptions *options) if (options->session_type == EP_SESSION_TYPE_IPCSTREAM && options->stream == NULL) return false; // More UserEvents specific checks can be added here. - if (options->session_type == EP_SESSION_TYPE_USEREVENTS && options->user_events_data_fd == 0) + if (options->session_type == EP_SESSION_TYPE_USEREVENTS && options->user_events_data_fd == -1) return false; return true; From e25e9f0c91ed675c2671e54c22df356b400bc62d Mon Sep 17 00:00:00 2001 From: Mitchell Hwang Date: Wed, 18 Jun 2025 14:40:45 +0000 Subject: [PATCH 32/32] Fix Sign mismatch build error --- src/native/eventpipe/ep-session-provider.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/eventpipe/ep-session-provider.c b/src/native/eventpipe/ep-session-provider.c index d8b165f563845e..30ec490627cabf 100644 --- a/src/native/eventpipe/ep-session-provider.c +++ b/src/native/eventpipe/ep-session-provider.c @@ -366,7 +366,7 @@ tracepoint_format_alloc (ep_char8_t *tracepoint_name) const int format_max_size = 512; const ep_char8_t *args = "u8 version; u16 event_id; __rel_loc u8[] extension; __rel_loc u8[] payload"; - if ((strlen(tracepoint_name) + strlen(args) + 2) > format_max_size) // +2 for the space and null terminator + if ((strlen(tracepoint_name) + strlen(args) + 2) > (size_t)format_max_size) // +2 for the space and null terminator return NULL; return ep_rt_utf8_string_printf_alloc ("%s %s", tracepoint_name, args);