@@ -166,13 +166,31 @@ event_reg(uint32_t fd, const char *command, uint32_t *write, uint32_t *enabled)
166166 reg .enable_size = sizeof (* enabled ); // uint8_t
167167 // reg.flags //uint16_t
168168 reg .enable_addr = (uint64_t )enabled ; // uint64_t
169- reg .name_args = (uint64_t )command ; // uint64_t
170169
171- if (ioctl (fd , DIAG_IOCSREG , & reg ) == -1 )
170+ // Hard-coded format as per the documentation
171+ const char * format = "u8 version; u16 event_id; __rel_loc u8[] extension; __rel_loc u8[] payload; __rel_loc u8[] meta" ;
172+
173+ // Dynamically allocate space for name_args
174+ size_t name_args_size = strlen (command ) + strlen (format ) + 2 ; // +2 for space and null terminator
175+ char * name_args = (char * )malloc (name_args_size );
176+ if (!name_args )
177+ return -1 ; // Memory allocation failed
178+
179+ if (snprintf (name_args , name_args_size , "%s %s" , command , format ) >= name_args_size ) {
180+ free (name_args );
181+ return -1 ; // Name and format combination is too long
182+ }
183+
184+ reg .name_args = (uint64_t )name_args ; // uint64_t
185+
186+ if (ioctl (fd , DIAG_IOCSREG , & reg ) == -1 ) {
187+ free (name_args );
172188 return -1 ;
189+ }
173190
174191 * write = reg .write_index ; // uint32_t
175192
193+ free (name_args );
176194 return 0 ;
177195#else // HAVE_LINUX_USER_EVENTS_H
178196 // Not Supported
@@ -624,6 +642,158 @@ ep_session_write_all_buffers_to_file (EventPipeSession *session, bool *events_wr
624642 return !ep_file_has_errors (session -> file );
625643}
626644
645+ bool
646+ ep_tracepoint_write (
647+ EventPipeSession * session ,
648+ ep_rt_thread_handle_t thread ,
649+ EventPipeEvent * ep_event ,
650+ EventPipeEventPayload * ep_event_payload ,
651+ const uint8_t * activity_id ,
652+ const uint8_t * related_activity_id ,
653+ ep_rt_thread_handle_t event_thread ,
654+ EventPipeStackContents * stack )
655+ {
656+ #ifdef HAVE_SYS_UIO_H
657+ EventPipeProvider * provider = ep_event_get_provider (ep_event );
658+
659+ EventPipeSessionProviderList * session_provider_list = ep_session_get_providers (session );
660+ 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 ));
661+
662+ uint32_t event_id = ep_event_get_event_id (ep_event );
663+
664+ dn_umap_t * event_id_to_tracepoint_map = ep_session_provider_get_event_id_to_tracepoint_map (session_provider );
665+ dn_umap_it_t found1 = dn_umap_find (event_id_to_tracepoint_map , & event_id );
666+ EventPipeTracepoint * tracepoint = NULL ;
667+ if (dn_umap_it_end (found1 )) {
668+ // If we don't have a tracepoint for this event_id, use the default tracepoint
669+ tracepoint = session_provider -> default_tracepoint ;
670+ } else {
671+ // We have a tracepoint for this event_id
672+ tracepoint = dn_umap_it_value_t (found1 , EventPipeTracepoint * );
673+ }
674+ if (tracepoint == NULL ) {
675+ // No tracepoint for this event_id and no default tracepoint, so we can't write the event.
676+ return false;
677+ }
678+
679+ if (tracepoint -> enabled == 0 ) {
680+ // No listeners
681+ return false;
682+ }
683+
684+ struct iovec io [9 ];
685+
686+ io [0 ].iov_base = & tracepoint -> write_index ; // __u32 from event_reg
687+ io [0 ].iov_len = sizeof (tracepoint -> write_index );
688+
689+ uint8_t version = 0x01 ; // hardcoded for the first tracepoint format version
690+ io [1 ].iov_base = & version ;
691+ io [1 ].iov_len = sizeof (version );
692+
693+ uint16_t truncated_event_id = event_id & 0xFFFF ;
694+ io [2 ].iov_base = & truncated_event_id ;
695+ io [2 ].iov_len = sizeof (truncated_event_id );
696+
697+ // The data transmitted in version 1 is
698+ // extension - a NetTrace V6 LabelList
699+ // payload - the EventPipe Event Payload
700+ // meta - the EventPipe Event metadata
701+
702+ bool activity_id_is_empty = true;
703+ if (activity_id != NULL ) {
704+ // If the activity_id is not empty, then we don't consider it empty.
705+ for (int i = 0 ; i < EP_ACTIVITY_ID_SIZE ; ++ i ) {
706+ if (activity_id [i ] != 0 ) {
707+ activity_id_is_empty = false;
708+ break ;
709+ }
710+ }
711+ }
712+ bool related_activity_id_is_empty = true;
713+ if (related_activity_id != NULL ) {
714+ // If the related_activity_id is not empty, then we don't consider it empty.
715+ for (int i = 0 ; i < EP_ACTIVITY_ID_SIZE ; ++ i ) {
716+ if (related_activity_id [i ] != 0 ) {
717+ related_activity_id_is_empty = false;
718+ break ;
719+ }
720+ }
721+ }
722+ // extension generation helper
723+ uint16_t extension_len = 0 ;
724+ if (activity_id != NULL && !activity_id_is_empty )
725+ extension_len += 1 + EP_ACTIVITY_ID_SIZE ; // ActivityId kind + value
726+ if (related_activity_id != NULL && !related_activity_id_is_empty )
727+ extension_len += 1 + EP_ACTIVITY_ID_SIZE ; // RelatedActivityId kind + value
728+
729+ uint8_t * extension = NULL ;
730+ if (extension_len > 0 ) {
731+ extension = (uint8_t * )malloc (extension_len );
732+ EP_ASSERT (extension != NULL );
733+ uint16_t offset = 0 ;
734+ if (activity_id != NULL && !activity_id_is_empty ) {
735+ // If there is a related_activity_id, use 0x81 (more follows), else 0x01 (no more follows)
736+ extension [offset ] = (related_activity_id != NULL && !related_activity_id_is_empty ) ? 0x81 : 0x01 ;
737+ memcpy (extension + offset + 1 , activity_id , EP_ACTIVITY_ID_SIZE );
738+ offset += 1 + EP_ACTIVITY_ID_SIZE ;
739+ }
740+ if (related_activity_id != NULL && !related_activity_id_is_empty ) {
741+ // RelatedActivityId: 0x02 (no more follows)
742+ extension [offset ] = 0x02 ;
743+ memcpy (extension + offset + 1 , related_activity_id , EP_ACTIVITY_ID_SIZE );
744+ offset += 1 + EP_ACTIVITY_ID_SIZE ;
745+ }
746+ }
747+
748+ uint32_t payload_len = ep_event_payload_get_size (ep_event_payload );
749+ if ((payload_len & 0xFFFF0000 ) != 0 ) {
750+ // Payload is too large, we can't write it.
751+ return false;
752+ }
753+ uint8_t * payload = (uint8_t * )malloc (payload_len );
754+ EP_ASSERT (payload != NULL );
755+ ep_event_payload_copy_data (ep_event_payload , payload );
756+
757+ // meta
758+ const uint8_t * metadata = ep_event_get_metadata (ep_event );
759+ uint32_t metadata_len = ep_event_get_metadata_len (ep_event );
760+
761+ // calculated __rel_loc values
762+ uint32_t meta_rel_loc = metadata_len << 16 | ((extension_len + payload_len ) & 0xFFFF );
763+ uint32_t payload_rel_loc = payload_len << 16 | ((sizeof (meta_rel_loc ) + extension_len ) & 0xFFFF );
764+ uint32_t extension_rel_loc = extension_len << 16 | ((sizeof (payload_rel_loc ) + sizeof (meta_rel_loc )) & 0xFFFF );
765+ io [3 ].iov_base = & extension_rel_loc ;
766+ io [3 ].iov_len = sizeof (extension_rel_loc );
767+
768+ io [4 ].iov_base = & payload_rel_loc ;
769+ io [4 ].iov_len = sizeof (payload_rel_loc );
770+
771+ io [5 ].iov_base = & meta_rel_loc ;
772+ io [5 ].iov_len = sizeof (meta_rel_loc );
773+
774+ // Actual data buffers
775+ io [6 ].iov_base = extension ;
776+ io [6 ].iov_len = extension_len ;
777+
778+ io [7 ].iov_base = payload ;
779+ io [7 ].iov_len = payload_len ;
780+
781+ io [8 ].iov_base = (void * )metadata ;
782+ io [8 ].iov_len = metadata_len ;
783+ int32_t result = writev (session -> user_events_data_fd , (const struct iovec * )io , 9 );
784+ if (result == -1 ) {
785+ // Failed to write the event, return false.
786+ // return false;
787+ return false;
788+ }
789+
790+ return true;
791+ #else // HAVE_SYS_UIO_H
792+ // Not Supported
793+ return false;
794+ #endif // HAVE_SYS_UIO_H
795+ }
796+
627797bool
628798ep_session_write_event (
629799 EventPipeSession * session ,
@@ -661,6 +831,17 @@ ep_session_write_event (
661831 stack == NULL ? NULL : (uintptr_t * )ep_stack_contents_get_pointer (stack ),
662832 session -> callback_additional_data );
663833 result = true;
834+ } else if (session -> session_type == EP_SESSION_TYPE_USEREVENTS ) {
835+ EP_ASSERT (session -> user_events_data_fd != 0 );
836+ result = ep_tracepoint_write (
837+ session ,
838+ thread ,
839+ ep_event ,
840+ payload ,
841+ activity_id ,
842+ related_activity_id ,
843+ event_thread ,
844+ stack );
664845 } else {
665846 EP_ASSERT (session -> buffer_manager != NULL );
666847 result = ep_buffer_manager_write_event (
0 commit comments