@@ -24,13 +24,13 @@ pub fn diff_bss_symbol(
2424 target_symbol : Some ( right_symbol_ref) ,
2525 match_percent : Some ( percent) ,
2626 diff_score : None ,
27- instruction_rows : vec ! [ ] ,
27+ .. Default :: default ( )
2828 } ,
2929 SymbolDiff {
3030 target_symbol : Some ( left_symbol_ref) ,
3131 match_percent : Some ( percent) ,
3232 diff_score : None ,
33- instruction_rows : vec ! [ ] ,
33+ .. Default :: default ( )
3434 } ,
3535 ) )
3636}
@@ -84,7 +84,83 @@ pub fn resolve_relocation<'obj>(
8484 ResolvedRelocation { relocation : reloc, symbol }
8585}
8686
87- /// Compares relocations contained with a certain data range.
87+ /// Compares the bytes within a certain data range.
88+ fn diff_data_range ( left_data : & [ u8 ] , right_data : & [ u8 ] ) -> ( f32 , Vec < DataDiff > , Vec < DataDiff > ) {
89+ let ops = capture_diff_slices ( Algorithm :: Patience , left_data, right_data) ;
90+ let bytes_match_ratio = get_diff_ratio ( & ops, left_data. len ( ) , right_data. len ( ) ) ;
91+
92+ let mut left_data_diff = Vec :: < DataDiff > :: new ( ) ;
93+ let mut right_data_diff = Vec :: < DataDiff > :: new ( ) ;
94+ for op in ops {
95+ let ( tag, left_range, right_range) = op. as_tag_tuple ( ) ;
96+ let left_len = left_range. len ( ) ;
97+ let right_len = right_range. len ( ) ;
98+ let mut len = left_len. max ( right_len) ;
99+ let kind = match tag {
100+ similar:: DiffTag :: Equal => DataDiffKind :: None ,
101+ similar:: DiffTag :: Delete => DataDiffKind :: Delete ,
102+ similar:: DiffTag :: Insert => DataDiffKind :: Insert ,
103+ similar:: DiffTag :: Replace => {
104+ // Ensure replacements are equal length
105+ len = left_len. min ( right_len) ;
106+ DataDiffKind :: Replace
107+ }
108+ } ;
109+ let left_data = & left_data[ left_range] ;
110+ let right_data = & right_data[ right_range] ;
111+ left_data_diff. push ( DataDiff {
112+ data : left_data[ ..len. min ( left_data. len ( ) ) ] . to_vec ( ) ,
113+ kind,
114+ len,
115+ ..Default :: default ( )
116+ } ) ;
117+ right_data_diff. push ( DataDiff {
118+ data : right_data[ ..len. min ( right_data. len ( ) ) ] . to_vec ( ) ,
119+ kind,
120+ len,
121+ ..Default :: default ( )
122+ } ) ;
123+ if kind == DataDiffKind :: Replace {
124+ match left_len. cmp ( & right_len) {
125+ Ordering :: Less => {
126+ let len = right_len - left_len;
127+ left_data_diff. push ( DataDiff {
128+ data : vec ! [ ] ,
129+ kind : DataDiffKind :: Insert ,
130+ len,
131+ ..Default :: default ( )
132+ } ) ;
133+ right_data_diff. push ( DataDiff {
134+ data : right_data[ left_len..right_len] . to_vec ( ) ,
135+ kind : DataDiffKind :: Insert ,
136+ len,
137+ ..Default :: default ( )
138+ } ) ;
139+ }
140+ Ordering :: Greater => {
141+ let len = left_len - right_len;
142+ left_data_diff. push ( DataDiff {
143+ data : left_data[ right_len..left_len] . to_vec ( ) ,
144+ kind : DataDiffKind :: Delete ,
145+ len,
146+ ..Default :: default ( )
147+ } ) ;
148+ right_data_diff. push ( DataDiff {
149+ data : vec ! [ ] ,
150+ kind : DataDiffKind :: Delete ,
151+ len,
152+ ..Default :: default ( )
153+ } ) ;
154+ }
155+ Ordering :: Equal => { }
156+ }
157+ }
158+ }
159+
160+ ( bytes_match_ratio, left_data_diff, right_data_diff)
161+ }
162+
163+ /// Compares relocations contained within a certain data range.
88164fn diff_data_relocs_for_range < ' left , ' right > (
89165 left_obj : & ' left Object ,
90166 right_obj : & ' right Object ,
@@ -186,76 +262,10 @@ pub fn diff_data_section(
186262 . min ( right_section. size ) ;
187263 let left_data = & left_section. data [ ..left_max as usize ] ;
188264 let right_data = & right_section. data [ ..right_max as usize ] ;
189- let ops = capture_diff_slices ( Algorithm :: Patience , left_data, right_data) ;
190- let match_percent = get_diff_ratio ( & ops, left_data. len ( ) , right_data. len ( ) ) * 100.0 ;
191265
192- let mut left_data_diff = Vec :: < DataDiff > :: new ( ) ;
193- let mut right_data_diff = Vec :: < DataDiff > :: new ( ) ;
194- for op in ops {
195- let ( tag, left_range, right_range) = op. as_tag_tuple ( ) ;
196- let left_len = left_range. len ( ) ;
197- let right_len = right_range. len ( ) ;
198- let mut len = left_len. max ( right_len) ;
199- let kind = match tag {
200- similar:: DiffTag :: Equal => DataDiffKind :: None ,
201- similar:: DiffTag :: Delete => DataDiffKind :: Delete ,
202- similar:: DiffTag :: Insert => DataDiffKind :: Insert ,
203- similar:: DiffTag :: Replace => {
204- // Ensure replacements are equal length
205- len = left_len. min ( right_len) ;
206- DataDiffKind :: Replace
207- }
208- } ;
209- let left_data = & left_section. data [ left_range] ;
210- let right_data = & right_section. data [ right_range] ;
211- left_data_diff. push ( DataDiff {
212- data : left_data[ ..len. min ( left_data. len ( ) ) ] . to_vec ( ) ,
213- kind,
214- len,
215- ..Default :: default ( )
216- } ) ;
217- right_data_diff. push ( DataDiff {
218- data : right_data[ ..len. min ( right_data. len ( ) ) ] . to_vec ( ) ,
219- kind,
220- len,
221- ..Default :: default ( )
222- } ) ;
223- if kind == DataDiffKind :: Replace {
224- match left_len. cmp ( & right_len) {
225- Ordering :: Less => {
226- let len = right_len - left_len;
227- left_data_diff. push ( DataDiff {
228- data : vec ! [ ] ,
229- kind : DataDiffKind :: Insert ,
230- len,
231- ..Default :: default ( )
232- } ) ;
233- right_data_diff. push ( DataDiff {
234- data : right_data[ left_len..right_len] . to_vec ( ) ,
235- kind : DataDiffKind :: Insert ,
236- len,
237- ..Default :: default ( )
238- } ) ;
239- }
240- Ordering :: Greater => {
241- let len = left_len - right_len;
242- left_data_diff. push ( DataDiff {
243- data : left_data[ right_len..left_len] . to_vec ( ) ,
244- kind : DataDiffKind :: Delete ,
245- len,
246- ..Default :: default ( )
247- } ) ;
248- right_data_diff. push ( DataDiff {
249- data : vec ! [ ] ,
250- kind : DataDiffKind :: Delete ,
251- len,
252- ..Default :: default ( )
253- } ) ;
254- }
255- Ordering :: Equal => { }
256- }
257- }
258- }
266+ let ( bytes_match_ratio, left_data_diff, right_data_diff) =
267+ diff_data_range ( left_data, right_data) ;
268+ let match_percent = bytes_match_ratio * 100.0 ;
259269
260270 let mut left_reloc_diffs = Vec :: new ( ) ;
261271 let mut right_reloc_diffs = Vec :: new ( ) ;
@@ -314,6 +324,55 @@ pub fn diff_data_section(
314324 Ok ( ( left_section_diff, right_section_diff) )
315325}
316326
327+ pub fn no_diff_data_symbol ( obj : & Object , symbol_index : usize ) -> Result < SymbolDiff > {
328+ let symbol = & obj. symbols [ symbol_index] ;
329+ let section_idx = symbol. section . ok_or_else ( || anyhow ! ( "Data symbol section not found" ) ) ?;
330+ let section = & obj. sections [ section_idx] ;
331+
332+ let start = symbol
333+ . address
334+ . checked_sub ( section. address )
335+ . ok_or_else ( || anyhow ! ( "Symbol address out of section bounds" ) ) ?;
336+ let end = start + symbol. size ;
337+ if end > section. size {
338+ return Err ( anyhow ! (
339+ "Symbol {} size out of section bounds ({} > {})" ,
340+ symbol. name,
341+ end,
342+ section. size
343+ ) ) ;
344+ }
345+ let range = start as usize ..end as usize ;
346+ let data = & section. data [ range. clone ( ) ] ;
347+
348+ let len = symbol. size as usize ;
349+ let data_diff =
350+ vec ! [ DataDiff { data: data. to_vec( ) , kind: DataDiffKind :: None , len, ..Default :: default ( ) } ] ;
351+
352+ let mut reloc_diffs = Vec :: new ( ) ;
353+ for reloc in section. relocations . iter ( ) {
354+ if !range. contains ( & ( reloc. address as usize ) ) {
355+ continue ;
356+ }
357+ let reloc_len = obj. arch . data_reloc_size ( reloc. flags ) ;
358+ let range = reloc. address as usize ..reloc. address as usize + reloc_len;
359+ reloc_diffs. push ( DataRelocationDiff {
360+ reloc : reloc. clone ( ) ,
361+ kind : DataDiffKind :: None ,
362+ range,
363+ } ) ;
364+ }
365+
366+ Ok ( SymbolDiff {
367+ target_symbol : None ,
368+ match_percent : None ,
369+ diff_score : None ,
370+ data_diff,
371+ data_reloc_diff : reloc_diffs,
372+ ..Default :: default ( )
373+ } )
374+ }
375+
317376pub fn diff_data_symbol (
318377 left_obj : & Object ,
319378 right_obj : & Object ,
@@ -362,6 +421,9 @@ pub fn diff_data_symbol(
362421 let left_data = & left_section. data [ left_range. clone ( ) ] ;
363422 let right_data = & right_section. data [ right_range. clone ( ) ] ;
364423
424+ let ( bytes_match_ratio, left_data_diff, right_data_diff) =
425+ diff_data_range ( left_data, right_data) ;
426+
365427 let reloc_diffs = diff_data_relocs_for_range (
366428 left_obj,
367429 right_obj,
@@ -371,10 +433,9 @@ pub fn diff_data_symbol(
371433 right_range,
372434 ) ;
373435
374- let ops = capture_diff_slices ( Algorithm :: Patience , left_data, right_data) ;
375- let bytes_match_ratio = get_diff_ratio ( & ops, left_data. len ( ) , right_data. len ( ) ) ;
376-
377436 let mut match_ratio = bytes_match_ratio;
437+ let mut left_reloc_diffs = Vec :: new ( ) ;
438+ let mut right_reloc_diffs = Vec :: new ( ) ;
378439 if !reloc_diffs. is_empty ( ) {
379440 let mut total_reloc_bytes = 0 ;
380441 let mut matching_reloc_bytes = 0 ;
@@ -390,6 +451,27 @@ pub fn diff_data_symbol(
390451 if diff_kind == DataDiffKind :: None {
391452 matching_reloc_bytes += reloc_diff_len;
392453 }
454+
455+ if let Some ( left_reloc) = left_reloc {
456+ let len = left_obj. arch . data_reloc_size ( left_reloc. relocation . flags ) ;
457+ let range = left_reloc. relocation . address as usize
458+ ..left_reloc. relocation . address as usize + len;
459+ left_reloc_diffs. push ( DataRelocationDiff {
460+ reloc : left_reloc. relocation . clone ( ) ,
461+ kind : diff_kind,
462+ range,
463+ } ) ;
464+ }
465+ if let Some ( right_reloc) = right_reloc {
466+ let len = right_obj. arch . data_reloc_size ( right_reloc. relocation . flags ) ;
467+ let range = right_reloc. relocation . address as usize
468+ ..right_reloc. relocation . address as usize + len;
469+ right_reloc_diffs. push ( DataRelocationDiff {
470+ reloc : right_reloc. relocation . clone ( ) ,
471+ kind : diff_kind,
472+ range,
473+ } ) ;
474+ }
393475 }
394476 if total_reloc_bytes > 0 {
395477 let relocs_match_ratio = matching_reloc_bytes as f32 / total_reloc_bytes as f32 ;
@@ -411,13 +493,17 @@ pub fn diff_data_symbol(
411493 target_symbol : Some ( right_symbol_idx) ,
412494 match_percent : Some ( match_percent) ,
413495 diff_score : None ,
414- instruction_rows : vec ! [ ] ,
496+ data_diff : left_data_diff,
497+ data_reloc_diff : left_reloc_diffs,
498+ ..Default :: default ( )
415499 } ,
416500 SymbolDiff {
417501 target_symbol : Some ( left_symbol_idx) ,
418502 match_percent : Some ( match_percent) ,
419503 diff_score : None ,
420- instruction_rows : vec ! [ ] ,
504+ data_diff : right_data_diff,
505+ data_reloc_diff : right_reloc_diffs,
506+ ..Default :: default ( )
421507 } ,
422508 ) )
423509}
0 commit comments