@@ -168,13 +168,31 @@ event_reg(uint32_t fd, const char *command, uint32_t *write, uint32_t *enabled)
168
168
reg .enable_size = sizeof (* enabled ); // uint8_t
169
169
// reg.flags //uint16_t
170
170
reg .enable_addr = (uint64_t )enabled ; // uint64_t
171
- reg .name_args = (uint64_t )command ; // uint64_t
172
171
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 );
174
190
return -1 ;
191
+ }
175
192
176
193
* write = reg .write_index ; // uint32_t
177
194
195
+ free (name_args );
178
196
return 0 ;
179
197
#else // HAVE_LINUX_USER_EVENTS_H
180
198
// Not Supported
@@ -636,6 +654,158 @@ ep_session_write_all_buffers_to_file (EventPipeSession *session, bool *events_wr
636
654
return !ep_file_has_errors (session -> file );
637
655
}
638
656
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
+
639
809
bool
640
810
ep_session_write_event (
641
811
EventPipeSession * session ,
@@ -673,6 +843,17 @@ ep_session_write_event (
673
843
stack == NULL ? NULL : (uintptr_t * )ep_stack_contents_get_pointer (stack ),
674
844
session -> callback_additional_data );
675
845
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 );
676
857
} else {
677
858
EP_ASSERT (session -> buffer_manager != NULL );
678
859
result = ep_buffer_manager_write_event (
0 commit comments