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