@@ -23,7 +23,7 @@ mod test {
2323
2424 #[ test]
2525 fn test_config_empty ( ) {
26- let c = Config :: < ( ) > :: new ( & mut [ 0 ; 0 ] ) ;
26+ let c = ConfigBuilder :: new ( & mut [ 0 ; 0 ] ) . finish ( ) ;
2727 assert_eq ! ( c. 0 . begin, c. 0 . end) ;
2828 assert_eq ! ( c. 0 . size, mem:: size_of:: <pt_config>( ) ) ;
2929 }
@@ -32,26 +32,26 @@ mod test {
3232 fn test_config_buf ( ) {
3333 let mut data = [ 0 ; 16 ] ;
3434 let len = data. len ( ) ;
35- let c = Config :: < ( ) > :: new ( & mut data) ;
35+ let c = ConfigBuilder :: new ( & mut data) . finish ( ) ;
3636 assert_eq ! ( c. 0 . end as usize - c. 0 . begin as usize , len) ;
3737 }
3838
3939 #[ test]
4040 fn test_config_all ( ) {
4141 let mut data = [ 18 ; 3 ] ;
42- let mut c = Config :: new ( & mut data ) ;
43- c . set_cpu ( Cpu :: intel ( 1 , 2 , 3 ) ) ;
44- c . set_freq ( Frequency :: new ( 1 , 2 , 3 , 4 ) ) ;
45- c . set_flags ( BlockFlags :: END_ON_CALL | BlockFlags :: END_ON_JUMP ) ;
46- let mut f = AddrFilter :: new ( ) ;
47- f . set_addr0 ( AddrRange :: new ( 1 , 2 , AddrConfig :: STOP ) ) ;
48- f . set_addr1 ( AddrRange :: new ( 3 , 4 , AddrConfig :: FILTER ) ) ;
49- f . set_addr2 ( AddrRange :: new ( 5 , 6 , AddrConfig :: DISABLED ) ) ;
50- f . set_addr3 ( AddrRange :: new ( 7 , 8 , AddrConfig :: STOP ) ) ;
51- c . set_filter ( f ) ;
52- c . set_callback ( |c , p| {
53- ( Unknown :: new ( c . 0 . cpu . model + p [ 0 ] ) , 1 )
54- } ) ;
42+ let c = ConfigBuilder :: with_callback (
43+ & mut data , |c , p| {
44+ ( Unknown :: new ( c . 0 . cpu . model + p [ 0 ] ) , 1 ) } )
45+ . filter ( AddrFilterBuilder :: new ( )
46+ . addr0 ( AddrRange :: new ( 1 , 2 , AddrConfig :: STOP ) )
47+ . addr1 ( AddrRange :: new ( 3 , 4 , AddrConfig :: FILTER ) )
48+ . addr2 ( AddrRange :: new ( 5 , 6 , AddrConfig :: DISABLED ) )
49+ . addr3 ( AddrRange :: new ( 7 , 8 , AddrConfig :: STOP ) )
50+ . finish ( ) )
51+ . cpu ( Cpu :: intel ( 1 , 2 , 3 ) )
52+ . freq ( Frequency :: new ( 1 , 2 , 3 , 4 ) )
53+ . flags ( BlockFlags :: END_ON_CALL | BlockFlags :: END_ON_JUMP )
54+ . finish ( ) ;
5555
5656 assert_eq ! ( c. 0 . cpu. family, 1 ) ;
5757 assert_eq ! ( c. 0 . cpu. model, 2 ) ;
@@ -117,39 +117,46 @@ mod test {
117117 #[ test]
118118 fn test_config_callback_safety ( ) {
119119 let mut kektop = [ 10 ; 9 ] ;
120- let mut cfg = Config :: new ( & mut kektop) ;
121- cfg. set_cpu ( Cpu :: intel ( 1 , 2 , 3 ) ) ;
122- cfg. set_callback ( |c, p, | {
123- ( Unknown :: new( c. 0 . cpu. stepping + p[ 8 ] ) , 17 )
124- } ) ;
120+ let mut cfg = ConfigBuilder :: with_callback (
121+ & mut kektop,
122+ |c, p, | { ( Unknown :: new( c. 0 . cpu. stepping + p[ 8 ] ) , 17 ) } )
123+ . cpu( Cpu :: intel( 1 , 2 , 3 ) ) . finish( ) ;
125124
126125 for _ in 0 ..10 { assert ! ( check_callback( & mut cfg, 13 , 17 ) ) }
127- cfg. set_callback ( |c, p| {
128- ( Unknown :: new ( c. 0 . cpu . model + p[ 0 ] ) , 1 )
129- } ) ;
130- for _ in 0 ..10 { assert ! ( check_callback( & mut cfg, 12 , 1 ) ) }
131126 }
132127
133128 #[ test]
134129 #[ should_panic]
135130 fn test_config_callback_out_of_bounds ( ) {
136131 let mut kektop = [ 10 ; 9 ] ;
137- let mut cfg = Config :: new ( & mut kektop) ;
138- let raw: * const pt_config = cfg. 0 . as_ref ( ) ;
139- cfg. set_cpu ( Cpu :: intel ( 1 , 2 , 3 ) ) ;
140- cfg. set_callback ( |c, p, | {
132+ let cfg = ConfigBuilder :: with_callback ( & mut kektop, |c, p, | {
141133 // make sure no move or copy is done
142134 if let Cow :: Owned ( _) = c. 0 { panic ! ( "BUG!" ) }
143- assert_eq ! ( c. 0 . as_ref( ) as * const _, raw) ;
135+ // assert_eq!(c.0.as_ref() as *const _, raw);
144136 ( Unknown :: new( p[ 100 ] ) , 17 )
145- } ) ;
137+ } ) . cpu( Cpu :: intel( 1 , 2 , 3 ) ) . finish( ) ;
138+
146139 unsafe {
147140 let mut ukn : pt_packet_unknown = std:: mem:: zeroed ( ) ;
148141 cfg . 0 . decode. callback. unwrap( ) ( & mut ukn,
149142 cfg. 0 . as_ref ( ) , cfg. 0 . begin ,
150143 cfg. 0 . decode . context ) ;
151144 }
152145 }
146+
147+ #[ test]
148+ fn test_builder_buf_lifetimes( ) {
149+ let mut x = [ 10 ; 10 ] ;
150+ let a : Config < ( ) > ;
151+ {
152+ let mut c = ConfigBuilder :: new ( & mut x) ;
153+ a = c. finish ( ) ;
154+ c. cpu ( Cpu :: intel ( 1 , 2 , 3 ) ) ;
155+ let b = c. finish ( ) ;
156+ unsafe { assert_eq ! ( b. buffer( ) , [ 10 ; 10 ] ) } ;
157+ }
158+ unsafe { assert_eq ! ( a. buffer( ) , [ 10 ; 10 ] ) } ;
159+ }
153160}
154161
155162unsafe extern "C" fn decode_callback < ' a , F , C > ( ukn : * mut pt_packet_unknown ,
@@ -175,68 +182,84 @@ unsafe extern "C" fn decode_callback<'a, F, C>(ukn: *mut pt_packet_unknown,
175182 bytes as i32
176183}
177184
178- /// A libipt configuration
179- pub struct Config < ' a , C > ( pub ( crate ) Cow < ' a , pt_config > , PhantomData < C > ) ;
180- impl < ' a , C > Config < ' a , C > {
181- /// Initializes a Config instance with only a buffer.
182- ///
183- /// Chain this functions with the setter methods to provide the arguments you need
184- pub fn new ( buf : & ' a mut [ u8 ] ) -> Self {
185+ /// A helper type to create the libipt Configuration instance
186+ pub struct ConfigBuilder < ' a , T > ( pt_config , PhantomData < & ' a mut T > ) ;
187+ impl < ' a , T > ConfigBuilder < ' a , T > {
188+ /// Initializes a Config instance with a buffer and decoder callback
189+ pub fn with_callback < F > ( buf : & ' a mut [ u8 ] , mut cb : F ) -> Self
190+ where F : FnMut ( & Config < T > , & [ u8 ] ) -> ( Unknown < T > , u32 ) ,
191+ F : ' a {
185192 let mut cfg: pt_config = unsafe { mem:: zeroed ( ) } ;
186193 cfg. size = mem:: size_of :: < pt_config > ( ) ;
187194 cfg. begin = buf. as_mut_ptr ( ) ;
188195 cfg. end = unsafe { buf. as_mut_ptr ( ) . offset ( buf. len ( ) as isize ) } ;
189- Config :: < C > ( Cow :: Owned ( cfg) , PhantomData )
190- }
191-
192- #[ inline]
193- fn ensure_owned ( & mut self ) -> & mut pt_config {
194- match & mut self . 0 {
195- Cow :: Borrowed ( _) => unreachable ! ( ) ,
196- Cow :: Owned ( c) => c
197- }
196+ cfg. decode . callback = Some ( decode_callback :: < F , T > ) ;
197+ cfg. decode . context = & mut cb as * mut _ as * mut c_void ;
198+ ConfigBuilder :: < T > ( cfg, PhantomData )
198199 }
199200
200201 /// The cpu used for capturing the data.
201202 /// It's highly recommended to provide this information.
202203 /// Processor specific workarounds will be identified this way.
203- # [ inline ]
204- pub fn set_cpu ( & mut self , cpu : Cpu ) {
205- let c = self . ensure_owned ( ) ;
206- c . cpu = cpu . 0 ;
207- c . errata = cpu . determine_errata ( ) ;
204+ pub fn cpu ( & mut self , cpu : Cpu ) -> & mut Self {
205+ self . 0 . cpu = cpu . 0 ;
206+ self . 0 . errata = cpu . determine_errata ( ) ;
207+
208+ self
208209 }
209210
210211 /// Frequency values used for timing packets (mtc)
211- # [ inline ]
212- pub fn set_freq ( & mut self , freq : Frequency ) {
213- let c = self . ensure_owned ( ) ;
214- c . mtc_freq = freq. mtc ;
215- c . nom_freq = freq. nom ;
216- c . cpuid_0x15_eax = freq . tsc ;
217- c . cpuid_0x15_ebx = freq . ctc ;
212+ pub fn freq ( & mut self , freq : Frequency ) -> & mut Self {
213+ self . 0 . mtc_freq = freq . mtc ;
214+ self . 0 . nom_freq = freq . nom ;
215+ self . 0 . cpuid_0x15_eax = freq. tsc ;
216+ self . 0 . cpuid_0x15_ebx = freq. ctc ;
217+
218+ self
218219 }
219220
220221 /// Decoder specific flags
221- # [ inline ]
222- pub fn set_flags ( & mut self , flags : impl Into < pt_conf_flags > ) {
223- self . ensure_owned ( ) . flags = flags . into ( )
222+ pub fn flags ( & mut self , flags : impl Into < pt_conf_flags > ) -> & mut Self {
223+ self . 0 . flags = flags . into ( ) ;
224+ self
224225 }
225226
226227 /// Address filter configuration
227- # [ inline ]
228- pub fn set_filter ( & mut self , filter : AddrFilter ) {
229- self . ensure_owned ( ) . addr_filter = filter . 0
228+ pub fn filter ( & mut self , filter : AddrFilter ) -> & mut Self {
229+ self . 0 . addr_filter = filter . 0 ;
230+ self
230231 }
231232
232- /// A callback for decoding unknown packets
233- #[ inline]
234- pub fn set_callback < ' b , F > ( & mut self , mut cb : F )
235- where F : FnMut ( & Config < C > , & [ u8 ] ) -> ( Unknown < C > , u32 ) ,
236- F : ' a {
237- let c = self . ensure_owned ( ) ;
238- c. decode . callback = Some ( decode_callback :: < F , C > ) ;
239- c. decode . context = & mut cb as * mut _ as * mut c_void ;
233+ /// turn itself into a new `Config`
234+ pub fn finish ( & self ) -> Config < ' a , T > {
235+ Config ( Cow :: Owned ( self . 0 ) , self . 1 )
236+ }
237+ }
238+
239+ impl < ' a > ConfigBuilder < ' a , ( ) > {
240+ /// Initializes a Config instance with only a buffer.
241+ /// If you want to use a decoder callback,
242+ /// use the `with_callback` function
243+ pub fn new ( buf : & ' a mut [ u8 ] ) -> ConfigBuilder < ( ) > {
244+ let mut cfg: pt_config = unsafe { mem:: zeroed ( ) } ;
245+ cfg. size = mem:: size_of :: < pt_config > ( ) ;
246+ cfg. begin = buf. as_mut_ptr ( ) ;
247+ cfg. end = unsafe { buf. as_mut_ptr ( ) . offset ( buf. len ( ) as isize ) } ;
248+ ConfigBuilder :: < ( ) > ( cfg, PhantomData )
249+ }
250+ }
251+
252+ /// A libipt configuration
253+ pub struct Config < ' a , C > ( pub ( crate ) Cow < ' a , pt_config > , PhantomData < & ' a mut C > ) ;
254+ impl < ' a , C > Config < ' a , C > {
255+ /// Gets this configs buffer.
256+ /// This operation is unsafe because an encoder might write into the buffer
257+ /// at any time
258+ pub unsafe fn buffer ( & self ) -> & ' a [ u8 ] {
259+ std:: slice:: from_raw_parts (
260+ self . 0 . begin ,
261+ self . 0 . end as usize - self . 0 . begin as usize
262+ )
240263 }
241264}
242265
0 commit comments