33use std:: {
44 ffi:: CStr ,
55 mem:: transmute,
6- os:: raw:: { c_char, c_void} ,
6+ os:: raw:: { c_char, c_void, c_int } ,
77 path:: Path ,
88 ptr,
99 collections:: HashMap ,
1010} ;
1111
1212use rb_sys:: {
13- rb_add_event_hook2 , rb_remove_event_hook_with_data , rb_define_class,
13+ rb_define_class,
1414 rb_define_alloc_func, rb_define_method, rb_funcall, rb_intern,
15- rb_event_hook_flag_t:: RUBY_EVENT_HOOK_FLAG_RAW_ARG ,
16- rb_event_flag_t, rb_trace_arg_t,
17- rb_tracearg_event_flag, rb_tracearg_lineno, rb_tracearg_path, rb_tracearg_self,
18- rb_tracearg_binding, rb_tracearg_callee_id, rb_tracearg_return_value,
19- rb_tracearg_raised_exception,
15+ rb_event_flag_t,
2016 rb_cObject, VALUE , ID , RUBY_EVENT_LINE , RUBY_EVENT_CALL , RUBY_EVENT_RETURN ,
2117 RUBY_EVENT_RAISE ,
2218 rb_raise, rb_eIOError,
2319 rb_sym2id, rb_id2name, rb_id2sym, rb_obj_classname, rb_num2long
2420} ;
2521use rb_sys:: { RARRAY_LEN , RARRAY_CONST_PTR , RSTRING_LEN , RSTRING_PTR , RB_INTEGER_TYPE_P , RB_TYPE_P , RB_SYMBOL_P , RB_FLOAT_TYPE_P , NIL_P , rb_protect} ;
2622use rb_sys:: { Qtrue , Qfalse , Qnil } ;
27- use std:: os:: raw:: c_int;
2823use runtime_tracing:: {
29- Tracer , Line , ValueRecord , TypeKind , TypeSpecificInfo , TypeRecord , FieldTypeRecord , TypeId ,
24+ Tracer , Line , ValueRecord , TypeKind , TypeSpecificInfo , TypeRecord , FieldTypeRecord ,
3025 EventLogKind , TraceLowLevelEvent , CallRecord , FullValueRecord , ReturnRecord , RecordEvent ,
3126} ;
3227
28+ // Event hook function type from Ruby debug.h
29+ type rb_event_hook_func_t = Option < unsafe extern "C" fn ( rb_event_flag_t , VALUE , VALUE , ID , VALUE ) > ;
30+
31+ // Event hook flags enum from Ruby debug.h
32+ #[ repr( C ) ]
33+ #[ derive( Clone , Copy ) ]
34+ enum rb_event_hook_flag_t {
35+ RUBY_EVENT_HOOK_FLAG_SAFE = 0x01 ,
36+ RUBY_EVENT_HOOK_FLAG_DELETED = 0x02 ,
37+ RUBY_EVENT_HOOK_FLAG_RAW_ARG = 0x04 ,
38+ }
39+
3340#[ repr( C ) ]
3441struct RTypedData {
3542 _basic : [ VALUE ; 2 ] ,
@@ -73,6 +80,31 @@ extern "C" {
7380 static rb_cStruct: VALUE ;
7481 static rb_cRange: VALUE ;
7582 fn rb_method_boundp ( klass : VALUE , mid : ID , ex : c_int ) -> VALUE ;
83+
84+ // TracePoint API functions that aren't in rb_sys
85+ fn rb_add_event_hook2 (
86+ func : rb_event_hook_func_t ,
87+ events : rb_event_flag_t ,
88+ data : VALUE ,
89+ hook_flag : rb_event_hook_flag_t ,
90+ ) ;
91+ fn rb_remove_event_hook_with_data (
92+ func : rb_event_hook_func_t ,
93+ data : VALUE ,
94+ ) -> c_int ;
95+ fn rb_tracearg_event_flag ( trace_arg : * mut rb_trace_arg_t ) -> rb_event_flag_t ;
96+ fn rb_tracearg_lineno ( trace_arg : * mut rb_trace_arg_t ) -> VALUE ;
97+ fn rb_tracearg_path ( trace_arg : * mut rb_trace_arg_t ) -> VALUE ;
98+ fn rb_tracearg_self ( trace_arg : * mut rb_trace_arg_t ) -> VALUE ;
99+ fn rb_tracearg_binding ( trace_arg : * mut rb_trace_arg_t ) -> VALUE ;
100+ fn rb_tracearg_callee_id ( trace_arg : * mut rb_trace_arg_t ) -> VALUE ;
101+ fn rb_tracearg_return_value ( trace_arg : * mut rb_trace_arg_t ) -> VALUE ;
102+ fn rb_tracearg_raised_exception ( trace_arg : * mut rb_trace_arg_t ) -> VALUE ;
103+ }
104+
105+ #[ repr( C ) ]
106+ struct rb_trace_arg_t {
107+ // Opaque struct representing rb_trace_arg_struct from Ruby
76108}
77109
78110struct Recorder {
@@ -168,7 +200,11 @@ static mut RECORDER_TYPE: rb_data_type_t = rb_data_type_t {
168200
169201unsafe fn get_recorder ( obj : VALUE ) -> * mut Recorder {
170202 let ty = std:: ptr:: addr_of!( RECORDER_TYPE ) as * const rb_data_type_t ;
171- rb_check_typeddata ( obj, ty) as * mut Recorder
203+ let ptr = rb_check_typeddata ( obj, ty) ;
204+ if ptr. is_null ( ) {
205+ rb_raise ( rb_eIOError, b"Invalid recorder object\0 " . as_ptr ( ) as * const c_char ) ;
206+ }
207+ ptr as * mut Recorder
172208}
173209
174210unsafe extern "C" fn ruby_recorder_alloc ( klass : VALUE ) -> VALUE {
@@ -207,27 +243,27 @@ unsafe extern "C" fn enable_tracing(self_val: VALUE) -> VALUE {
207243 let recorder = & mut * get_recorder ( self_val) ;
208244 if !recorder. active {
209245 let raw_cb: unsafe extern "C" fn ( VALUE , * mut rb_trace_arg_t ) = event_hook_raw;
210- let cb : unsafe extern "C" fn ( rb_event_flag_t , VALUE , VALUE , ID , VALUE ) = transmute ( raw_cb) ;
246+ let func : rb_event_hook_func_t = Some ( transmute ( raw_cb) ) ;
211247 rb_add_event_hook2 (
212- Some ( cb ) ,
248+ func ,
213249 RUBY_EVENT_LINE | RUBY_EVENT_CALL | RUBY_EVENT_RETURN | RUBY_EVENT_RAISE ,
214250 self_val,
215- RUBY_EVENT_HOOK_FLAG_RAW_ARG ,
251+ rb_event_hook_flag_t :: RUBY_EVENT_HOOK_FLAG_RAW_ARG ,
216252 ) ;
217253 recorder. active = true ;
218254 }
219- rb_sys :: Qnil . into ( )
255+ Qnil . into ( )
220256}
221257
222258unsafe extern "C" fn disable_tracing ( self_val : VALUE ) -> VALUE {
223259 let recorder = & mut * get_recorder ( self_val) ;
224260 if recorder. active {
225261 let raw_cb: unsafe extern "C" fn ( VALUE , * mut rb_trace_arg_t ) = event_hook_raw;
226- let cb : unsafe extern "C" fn ( rb_event_flag_t , VALUE , VALUE , ID , VALUE ) = transmute ( raw_cb) ;
227- rb_remove_event_hook_with_data ( Some ( cb ) , self_val) ;
262+ let func : rb_event_hook_func_t = Some ( transmute ( raw_cb) ) ;
263+ rb_remove_event_hook_with_data ( func , self_val) ;
228264 recorder. active = false ;
229265 }
230- rb_sys :: Qnil . into ( )
266+ Qnil . into ( )
231267}
232268
233269fn flush_to_dir ( tracer : & Tracer , dir : & Path ) -> Result < ( ) , Box < dyn std:: error:: Error > > {
@@ -531,7 +567,7 @@ unsafe extern "C" fn flush_trace(self_val: VALUE, out_dir: VALUE) -> VALUE {
531567 Err ( e) => rb_raise ( rb_eIOError, b"Invalid UTF-8 in path: %s\0 " . as_ptr ( ) as * const c_char , e. to_string ( ) . as_ptr ( ) as * const c_char ) ,
532568 }
533569
534- rb_sys :: Qnil . into ( )
570+ Qnil . into ( )
535571}
536572
537573unsafe extern "C" fn record_event_api ( self_val : VALUE , path : VALUE , line : VALUE , content : VALUE ) -> VALUE {
@@ -546,7 +582,7 @@ unsafe extern "C" fn record_event_api(self_val: VALUE, path: VALUE, line: VALUE,
546582 let line_num = rb_num2long ( line) as i64 ;
547583 let content_str = value_to_string ( content, recorder. to_s_id ) . unwrap_or_default ( ) ;
548584 record_event ( & mut recorder. tracer , & path_str, line_num, & content_str) ;
549- rb_sys :: Qnil . into ( )
585+ Qnil . into ( )
550586}
551587
552588/// Raw-argument callback (Ruby will call it when we set
@@ -654,13 +690,30 @@ pub extern "C" fn Init_codetracer_ruby_recorder() {
654690 unsafe {
655691 let class = rb_define_class ( b"RubyRecorder\0 " . as_ptr ( ) as * const c_char , rb_cObject) ;
656692 rb_define_alloc_func ( class, Some ( ruby_recorder_alloc) ) ;
657- let enable_cb: unsafe extern "C" fn ( VALUE ) -> VALUE = enable_tracing;
658- let disable_cb: unsafe extern "C" fn ( VALUE ) -> VALUE = disable_tracing;
659- let flush_cb: unsafe extern "C" fn ( VALUE , VALUE ) -> VALUE = flush_trace;
660- let event_cb: unsafe extern "C" fn ( VALUE , VALUE , VALUE , VALUE ) -> VALUE = record_event_api;
661- rb_define_method ( class, b"enable_tracing\0 " . as_ptr ( ) as * const c_char , Some ( transmute ( enable_cb) ) , 0 ) ;
662- rb_define_method ( class, b"disable_tracing\0 " . as_ptr ( ) as * const c_char , Some ( transmute ( disable_cb) ) , 0 ) ;
663- rb_define_method ( class, b"flush_trace\0 " . as_ptr ( ) as * const c_char , Some ( transmute ( flush_cb) ) , 1 ) ;
664- rb_define_method ( class, b"record_event\0 " . as_ptr ( ) as * const c_char , Some ( transmute ( event_cb) ) , 3 ) ;
693+
694+ rb_define_method (
695+ class,
696+ b"enable_tracing\0 " . as_ptr ( ) as * const c_char ,
697+ Some ( std:: mem:: transmute ( enable_tracing as * const ( ) ) ) ,
698+ 0
699+ ) ;
700+ rb_define_method (
701+ class,
702+ b"disable_tracing\0 " . as_ptr ( ) as * const c_char ,
703+ Some ( std:: mem:: transmute ( disable_tracing as * const ( ) ) ) ,
704+ 0
705+ ) ;
706+ rb_define_method (
707+ class,
708+ b"flush_trace\0 " . as_ptr ( ) as * const c_char ,
709+ Some ( std:: mem:: transmute ( flush_trace as * const ( ) ) ) ,
710+ 1
711+ ) ;
712+ rb_define_method (
713+ class,
714+ b"record_event\0 " . as_ptr ( ) as * const c_char ,
715+ Some ( std:: mem:: transmute ( record_event_api as * const ( ) ) ) ,
716+ 3
717+ ) ;
665718 }
666719}
0 commit comments