@@ -2,8 +2,8 @@ use core::fmt::Debug;
2
2
3
3
use libafl_bolts:: { Error , hash_64_fast} ;
4
4
use libipt:: {
5
- block:: BlockDecoder , enc_dec_builder:: EncoderDecoderBuilder , error:: PtErrorCode ,
6
- event:: EventType , image:: Image , status:: Status ,
5
+ block:: BlockDecoder , enc_dec_builder:: EncoderDecoderBuilder , error:: PtError ,
6
+ error :: PtErrorCode , event:: EventType , image:: Image , status:: Status ,
7
7
} ;
8
8
use num_traits:: SaturatingAdd ;
9
9
@@ -81,21 +81,46 @@ where
81
81
}
82
82
83
83
fn decode_and_resync_loop ( & mut self ) -> Result < ( ) , Error > {
84
+ const MAX_RESYNC_TRIALS : usize = 32 ;
85
+ let mut last_error_offset = 0 ;
86
+ let mut last_error_count = 0 ;
87
+
84
88
loop {
85
89
match self . decode_blocks_loop ( ) {
86
- Ok ( ( ) ) if self . status . eos ( ) => return Ok ( ( ) ) ,
87
- Ok ( ( ) ) | Err ( _) => ( ) ,
90
+ Ok ( ( ) ) => {
91
+ debug_assert ! (
92
+ self . status. eos( ) ,
93
+ "PT decoder decode_blocks_loop should return Ok only at the end of stream"
94
+ ) ;
95
+ return Ok ( ( ) ) ;
96
+ }
97
+ Err ( e) if e. code ( ) == PtErrorCode :: Eos => return Ok ( ( ) ) ,
98
+ Err ( _) => ( ) ,
99
+ }
100
+
101
+ let offset = self . decoder . offset ( ) . map_err ( error_from_pt_error) ?;
102
+ if offset == last_error_offset {
103
+ last_error_count += 1 ;
104
+ if last_error_count > MAX_RESYNC_TRIALS {
105
+ return Err ( Error :: illegal_state ( format ! (
106
+ "PT Decoder got stuck at trace offset {offset:x}.\
107
+ Make sure the decoder Image has the right content and offsets.\
108
+ Trying to continue decoding.",
109
+ ) ) ) ;
110
+ }
111
+ } else {
112
+ last_error_offset = offset;
88
113
}
89
114
90
115
match self . resync_loop ( ) {
91
116
Ok ( ( ) ) if self . status . eos ( ) => return Ok ( ( ) ) ,
92
117
Ok ( ( ) ) => ( ) ,
93
- Err ( e) => return Err ( e ) ,
118
+ Err ( e) => return Err ( error_from_pt_error ( e ) ) ,
94
119
}
95
120
}
96
121
}
97
122
98
- fn resync_loop ( & mut self ) -> Result < ( ) , Error >
123
+ fn resync_loop ( & mut self ) -> Result < ( ) , PtError >
99
124
where
100
125
T : SaturatingAdd + From < u8 > + Debug ,
101
126
{
@@ -108,41 +133,22 @@ where
108
133
Err ( e) => match e. code ( ) {
109
134
PtErrorCode :: Eos => return Ok ( ( ) ) ,
110
135
PtErrorCode :: EventIgnored => self . handle_event ( ) ?,
111
- _ => return Err ( Error :: illegal_state ( format ! ( "PT error in resync {e:?}" ) ) ) ,
136
+ _ => return Err ( e ) ,
112
137
} ,
113
138
}
114
139
}
115
140
}
116
141
117
- fn decode_blocks_loop ( & mut self ) -> Result < ( ) , Error >
142
+ fn decode_blocks_loop ( & mut self ) -> Result < ( ) , PtError >
118
143
where
119
144
T : SaturatingAdd + From < u8 > + Debug ,
120
145
{
121
- #[ cfg( debug_assertions) ]
122
- let mut trace_entry_iters: ( u64 , u64 ) = ( 0 , 0 ) ;
123
-
124
146
loop {
125
- #[ cfg( debug_assertions) ]
126
- {
127
- let offset = self . decoder . offset ( ) . map_err ( error_from_pt_error) ?;
128
- if trace_entry_iters. 0 == offset {
129
- trace_entry_iters. 1 += 1 ;
130
- if trace_entry_iters. 1 > 1000 {
131
- return Err ( Error :: illegal_state ( format ! (
132
- "PT Decoder got stuck at trace offset {offset:x}.\
133
- Make sure the decoder Image has the right content and offsets.",
134
- ) ) ) ;
135
- }
136
- } else {
137
- trace_entry_iters = ( offset, 0 ) ;
138
- }
139
- }
140
-
141
147
while self . status . event_pending ( ) {
142
148
self . handle_event ( ) ?;
143
149
}
144
150
145
- let offset = self . decoder . offset ( ) . map_err ( error_from_pt_error ) ?;
151
+ let offset = self . decoder . offset ( ) ?;
146
152
if self . should_ignore_vmx_root ( ) || offset <= self . trace_skip {
147
153
self . ignore_block ( ) ?;
148
154
} else {
@@ -155,7 +161,7 @@ where
155
161
}
156
162
}
157
163
158
- fn decode_block ( & mut self ) -> Result < ( ) , Error > {
164
+ fn decode_block ( & mut self ) -> Result < ( ) , PtError > {
159
165
match self . decoder . decode_next ( ) {
160
166
Ok ( ( b, s) ) => {
161
167
self . status = s;
@@ -172,37 +178,37 @@ where
172
178
}
173
179
Err ( e) => {
174
180
if e. code ( ) != PtErrorCode :: Eos {
175
- let offset = self . decoder . offset ( ) . map_err ( error_from_pt_error ) ?;
181
+ let offset = self . decoder . offset ( ) ?;
176
182
log:: info!(
177
183
"PT error in block next {e:?} trace offset {offset:x} last decoded block end {:x}" ,
178
184
self . previous_block_end_ip
179
185
) ;
180
186
}
181
- Err ( error_from_pt_error ( e ) )
187
+ Err ( e )
182
188
}
183
189
}
184
190
}
185
191
186
- fn ignore_block ( & mut self ) -> Result < ( ) , Error > {
192
+ fn ignore_block ( & mut self ) -> Result < ( ) , PtError > {
187
193
match self . decoder . decode_next ( ) {
188
194
Ok ( ( _, s) ) => {
189
195
self . status = s;
190
196
Ok ( ( ) )
191
197
}
192
198
Err ( e) => {
193
199
if e. code ( ) != PtErrorCode :: Eos {
194
- let offset = self . decoder . offset ( ) . map_err ( error_from_pt_error ) ?;
200
+ let offset = self . decoder . offset ( ) ?;
195
201
log:: trace!(
196
202
"PT error in ignore block {e:?} trace offset {offset:x} last decoded block end {:x}" ,
197
203
self . previous_block_end_ip
198
204
) ;
199
205
}
200
- Err ( error_from_pt_error ( e ) )
206
+ Err ( e )
201
207
}
202
208
}
203
209
}
204
210
205
- fn handle_event ( & mut self ) -> Result < ( ) , Error > {
211
+ fn handle_event ( & mut self ) -> Result < ( ) , PtError > {
206
212
match self . decoder . event ( ) {
207
213
Ok ( ( event, s) ) => {
208
214
self . status = s;
@@ -213,7 +219,7 @@ where
213
219
}
214
220
Ok ( ( ) )
215
221
}
216
- Err ( e) => Err ( Error :: illegal_state ( format ! ( "PT error in event {e:?}" ) ) ) ,
222
+ Err ( e) => Err ( e ) ,
217
223
}
218
224
}
219
225
0 commit comments