@@ -5,7 +5,7 @@ use anyhow::{Result, anyhow};
55use similar:: { Algorithm , capture_diff_slices, get_diff_ratio} ;
66
77use super :: {
8- DataDiff , DataDiffKind , DataRelocationDiff , ObjectDiff , SectionDiff , SymbolDiff ,
8+ DataDiff , DataDiffKind , DataDiffRow , DataRelocationDiff , ObjectDiff , SectionDiff , SymbolDiff ,
99 code:: { address_eq, section_name_eq} ,
1010} ;
1111use crate :: obj:: { Object , Relocation , ResolvedRelocation , Symbol , SymbolFlag , SymbolKind } ;
@@ -111,14 +111,12 @@ fn diff_data_range(left_data: &[u8], right_data: &[u8]) -> (f32, Vec<DataDiff>,
111111 left_data_diff. push ( DataDiff {
112112 data : left_data[ ..len. min ( left_data. len ( ) ) ] . to_vec ( ) ,
113113 kind,
114- len,
115- ..Default :: default ( )
114+ size : len,
116115 } ) ;
117116 right_data_diff. push ( DataDiff {
118117 data : right_data[ ..len. min ( right_data. len ( ) ) ] . to_vec ( ) ,
119118 kind,
120- len,
121- ..Default :: default ( )
119+ size : len,
122120 } ) ;
123121 if kind == DataDiffKind :: Replace {
124122 match left_len. cmp ( & right_len) {
@@ -127,29 +125,25 @@ fn diff_data_range(left_data: &[u8], right_data: &[u8]) -> (f32, Vec<DataDiff>,
127125 left_data_diff. push ( DataDiff {
128126 data : vec ! [ ] ,
129127 kind : DataDiffKind :: Insert ,
130- len,
131- ..Default :: default ( )
128+ size : len,
132129 } ) ;
133130 right_data_diff. push ( DataDiff {
134131 data : right_data[ left_len..right_len] . to_vec ( ) ,
135132 kind : DataDiffKind :: Insert ,
136- len,
137- ..Default :: default ( )
133+ size : len,
138134 } ) ;
139135 }
140136 Ordering :: Greater => {
141137 let len = left_len - right_len;
142138 left_data_diff. push ( DataDiff {
143139 data : left_data[ right_len..left_len] . to_vec ( ) ,
144140 kind : DataDiffKind :: Delete ,
145- len,
146- ..Default :: default ( )
141+ size : len,
147142 } ) ;
148143 right_data_diff. push ( DataDiff {
149144 data : vec ! [ ] ,
150145 kind : DataDiffKind :: Delete ,
151- len,
152- ..Default :: default ( )
146+ size : len,
153147 } ) ;
154148 }
155149 Ordering :: Equal => { }
@@ -219,16 +213,17 @@ fn diff_data_relocs_for_range<'left, 'right>(
219213
220214pub fn no_diff_data_section ( obj : & Object , section_idx : usize ) -> Result < SectionDiff > {
221215 let section = & obj. sections [ section_idx] ;
222- let len = section. data . len ( ) ;
223- let data = & section. data [ 0 ..len] ;
224216
225- let data_diff =
226- vec ! [ DataDiff { data: data. to_vec( ) , kind: DataDiffKind :: None , len, ..Default :: default ( ) } ] ;
217+ let data_diff = vec ! [ DataDiff {
218+ data: section. data. 0 . clone( ) ,
219+ kind: DataDiffKind :: None ,
220+ size: section. data. len( ) ,
221+ } ] ;
227222
228223 let mut reloc_diffs = Vec :: new ( ) ;
229224 for reloc in section. relocations . iter ( ) {
230225 let reloc_len = obj. arch . data_reloc_size ( reloc. flags ) ;
231- let range = reloc. address as usize ..reloc. address as usize + reloc_len;
226+ let range = reloc. address ..reloc. address + reloc_len as u64 ;
232227 reloc_diffs. push ( DataRelocationDiff {
233228 reloc : reloc. clone ( ) ,
234229 kind : DataDiffKind :: None ,
@@ -279,8 +274,7 @@ pub fn diff_data_section(
279274 ) {
280275 if let Some ( left_reloc) = left_reloc {
281276 let len = left_obj. arch . data_reloc_size ( left_reloc. relocation . flags ) ;
282- let range = left_reloc. relocation . address as usize
283- ..left_reloc. relocation . address as usize + len;
277+ let range = left_reloc. relocation . address ..left_reloc. relocation . address + len as u64 ;
284278 left_reloc_diffs. push ( DataRelocationDiff {
285279 reloc : left_reloc. relocation . clone ( ) ,
286280 kind : diff_kind,
@@ -289,8 +283,7 @@ pub fn diff_data_section(
289283 }
290284 if let Some ( right_reloc) = right_reloc {
291285 let len = right_obj. arch . data_reloc_size ( right_reloc. relocation . flags ) ;
292- let range = right_reloc. relocation . address as usize
293- ..right_reloc. relocation . address as usize + len;
286+ let range = right_reloc. relocation . address ..right_reloc. relocation . address + len as u64 ;
294287 right_reloc_diffs. push ( DataRelocationDiff {
295288 reloc : right_reloc. relocation . clone ( ) ,
296289 kind : diff_kind,
@@ -345,30 +338,32 @@ pub fn no_diff_data_symbol(obj: &Object, symbol_index: usize) -> Result<SymbolDi
345338 let range = start as usize ..end as usize ;
346339 let data = & section. data [ range. clone ( ) ] ;
347340
348- let len = symbol. size as usize ;
349- let data_diff =
350- vec ! [ DataDiff { data: data. to_vec( ) , kind: DataDiffKind :: None , len, ..Default :: default ( ) } ] ;
341+ let data_diff = vec ! [ DataDiff {
342+ data: data. to_vec( ) ,
343+ kind: DataDiffKind :: None ,
344+ size: symbol. size as usize ,
345+ } ] ;
351346
352347 let mut reloc_diffs = Vec :: new ( ) ;
353348 for reloc in section. relocations . iter ( ) {
354349 if !range. contains ( & ( reloc. address as usize ) ) {
355350 continue ;
356351 }
357352 let reloc_len = obj. arch . data_reloc_size ( reloc. flags ) ;
358- let range = reloc. address as usize ..reloc. address as usize + reloc_len;
353+ let range = reloc. address ..reloc. address + reloc_len as u64 ;
359354 reloc_diffs. push ( DataRelocationDiff {
360355 reloc : reloc. clone ( ) ,
361356 kind : DataDiffKind :: None ,
362357 range,
363358 } ) ;
364359 }
365360
361+ let data_rows = build_data_diff_rows ( & data_diff, & reloc_diffs, symbol. address ) ;
366362 Ok ( SymbolDiff {
367363 target_symbol : None ,
368364 match_percent : None ,
369365 diff_score : None ,
370- data_diff,
371- data_reloc_diff : reloc_diffs,
366+ data_rows,
372367 ..Default :: default ( )
373368 } )
374369}
@@ -454,8 +449,8 @@ pub fn diff_data_symbol(
454449
455450 if let Some ( left_reloc) = left_reloc {
456451 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;
452+ let range =
453+ left_reloc . relocation . address .. left_reloc. relocation . address + len as u64 ;
459454 left_reloc_diffs. push ( DataRelocationDiff {
460455 reloc : left_reloc. relocation . clone ( ) ,
461456 kind : diff_kind,
@@ -464,8 +459,8 @@ pub fn diff_data_symbol(
464459 }
465460 if let Some ( right_reloc) = right_reloc {
466461 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;
462+ let range =
463+ right_reloc . relocation . address .. right_reloc. relocation . address + len as u64 ;
469464 right_reloc_diffs. push ( DataRelocationDiff {
470465 reloc : right_reloc. relocation . clone ( ) ,
471466 kind : diff_kind,
@@ -486,23 +481,29 @@ pub fn diff_data_symbol(
486481 }
487482 }
488483
484+ left_reloc_diffs
485+ . sort_by ( |a, b| a. range . start . cmp ( & b. range . start ) . then ( a. range . end . cmp ( & b. range . end ) ) ) ;
486+ right_reloc_diffs
487+ . sort_by ( |a, b| a. range . start . cmp ( & b. range . start ) . then ( a. range . end . cmp ( & b. range . end ) ) ) ;
488+
489489 let match_percent = match_ratio * 100.0 ;
490+ let left_rows = build_data_diff_rows ( & left_data_diff, & left_reloc_diffs, left_symbol. address ) ;
491+ let right_rows =
492+ build_data_diff_rows ( & right_data_diff, & right_reloc_diffs, right_symbol. address ) ;
490493
491494 Ok ( (
492495 SymbolDiff {
493496 target_symbol : Some ( right_symbol_idx) ,
494497 match_percent : Some ( match_percent) ,
495498 diff_score : None ,
496- data_diff : left_data_diff,
497- data_reloc_diff : left_reloc_diffs,
499+ data_rows : left_rows,
498500 ..Default :: default ( )
499501 } ,
500502 SymbolDiff {
501503 target_symbol : Some ( left_symbol_idx) ,
502504 match_percent : Some ( match_percent) ,
503505 diff_score : None ,
504- data_diff : right_data_diff,
505- data_reloc_diff : right_reloc_diffs,
506+ data_rows : right_rows,
506507 ..Default :: default ( )
507508 } ,
508509 ) )
@@ -593,3 +594,68 @@ fn symbols_matching_section(
593594 && !s. flags . contains ( SymbolFlag :: Ignored )
594595 } )
595596}
597+
598+ pub const BYTES_PER_ROW : usize = 16 ;
599+
600+ fn build_data_diff_row (
601+ data_diffs : & [ DataDiff ] ,
602+ reloc_diffs : & [ DataRelocationDiff ] ,
603+ symbol_address : u64 ,
604+ row_index : usize ,
605+ ) -> DataDiffRow {
606+ let row_start = row_index * BYTES_PER_ROW ;
607+ let row_end = row_start + BYTES_PER_ROW ;
608+ let mut row_diff = DataDiffRow {
609+ address : symbol_address + row_start as u64 ,
610+ segments : Vec :: new ( ) ,
611+ relocations : Vec :: new ( ) ,
612+ } ;
613+
614+ // Collect all segments that overlap with this row
615+ let mut current_offset = 0 ;
616+ for diff in data_diffs {
617+ let diff_end = current_offset + diff. size ;
618+ if current_offset < row_end && diff_end > row_start {
619+ let start_in_diff = row_start. saturating_sub ( current_offset) ;
620+ let end_in_diff = row_end. min ( diff_end) - current_offset;
621+ if start_in_diff < end_in_diff {
622+ let data_slice = if diff. data . is_empty ( ) {
623+ Vec :: new ( )
624+ } else {
625+ diff. data [ start_in_diff..end_in_diff. min ( diff. data . len ( ) ) ] . to_vec ( )
626+ } ;
627+ row_diff. segments . push ( DataDiff {
628+ data : data_slice,
629+ kind : diff. kind ,
630+ size : end_in_diff - start_in_diff,
631+ } ) ;
632+ }
633+ }
634+ current_offset = diff_end;
635+ if current_offset >= row_start + BYTES_PER_ROW {
636+ break ;
637+ }
638+ }
639+
640+ // Collect all relocations that overlap with this row
641+ let row_end_absolute = row_diff. address + BYTES_PER_ROW as u64 ;
642+ row_diff. relocations = reloc_diffs
643+ . iter ( )
644+ . filter ( |rd| rd. range . start < row_end_absolute && rd. range . end > row_diff. address )
645+ . cloned ( )
646+ . collect ( ) ;
647+
648+ row_diff
649+ }
650+
651+ fn build_data_diff_rows (
652+ segments : & [ DataDiff ] ,
653+ relocations : & [ DataRelocationDiff ] ,
654+ symbol_address : u64 ,
655+ ) -> Vec < DataDiffRow > {
656+ let total_len = segments. iter ( ) . map ( |s| s. size as u64 ) . sum :: < u64 > ( ) ;
657+ let num_rows = total_len. div_ceil ( BYTES_PER_ROW as u64 ) as usize ;
658+ ( 0 ..num_rows)
659+ . map ( |row_index| build_data_diff_row ( segments, relocations, symbol_address, row_index) )
660+ . collect ( )
661+ }
0 commit comments