@@ -5,7 +5,7 @@ use anyhow::{Result, anyhow};
5
5
use similar:: { Algorithm , capture_diff_slices, get_diff_ratio} ;
6
6
7
7
use super :: {
8
- DataDiff , DataDiffKind , DataRelocationDiff , ObjectDiff , SectionDiff , SymbolDiff ,
8
+ DataDiff , DataDiffKind , DataDiffRow , DataRelocationDiff , ObjectDiff , SectionDiff , SymbolDiff ,
9
9
code:: { address_eq, section_name_eq} ,
10
10
} ;
11
11
use 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>,
111
111
left_data_diff. push ( DataDiff {
112
112
data : left_data[ ..len. min ( left_data. len ( ) ) ] . to_vec ( ) ,
113
113
kind,
114
- len,
115
- ..Default :: default ( )
114
+ size : len,
116
115
} ) ;
117
116
right_data_diff. push ( DataDiff {
118
117
data : right_data[ ..len. min ( right_data. len ( ) ) ] . to_vec ( ) ,
119
118
kind,
120
- len,
121
- ..Default :: default ( )
119
+ size : len,
122
120
} ) ;
123
121
if kind == DataDiffKind :: Replace {
124
122
match left_len. cmp ( & right_len) {
@@ -127,29 +125,25 @@ fn diff_data_range(left_data: &[u8], right_data: &[u8]) -> (f32, Vec<DataDiff>,
127
125
left_data_diff. push ( DataDiff {
128
126
data : vec ! [ ] ,
129
127
kind : DataDiffKind :: Insert ,
130
- len,
131
- ..Default :: default ( )
128
+ size : len,
132
129
} ) ;
133
130
right_data_diff. push ( DataDiff {
134
131
data : right_data[ left_len..right_len] . to_vec ( ) ,
135
132
kind : DataDiffKind :: Insert ,
136
- len,
137
- ..Default :: default ( )
133
+ size : len,
138
134
} ) ;
139
135
}
140
136
Ordering :: Greater => {
141
137
let len = left_len - right_len;
142
138
left_data_diff. push ( DataDiff {
143
139
data : left_data[ right_len..left_len] . to_vec ( ) ,
144
140
kind : DataDiffKind :: Delete ,
145
- len,
146
- ..Default :: default ( )
141
+ size : len,
147
142
} ) ;
148
143
right_data_diff. push ( DataDiff {
149
144
data : vec ! [ ] ,
150
145
kind : DataDiffKind :: Delete ,
151
- len,
152
- ..Default :: default ( )
146
+ size : len,
153
147
} ) ;
154
148
}
155
149
Ordering :: Equal => { }
@@ -219,16 +213,17 @@ fn diff_data_relocs_for_range<'left, 'right>(
219
213
220
214
pub fn no_diff_data_section ( obj : & Object , section_idx : usize ) -> Result < SectionDiff > {
221
215
let section = & obj. sections [ section_idx] ;
222
- let len = section. data . len ( ) ;
223
- let data = & section. data [ 0 ..len] ;
224
216
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
+ } ] ;
227
222
228
223
let mut reloc_diffs = Vec :: new ( ) ;
229
224
for reloc in section. relocations . iter ( ) {
230
225
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 ;
232
227
reloc_diffs. push ( DataRelocationDiff {
233
228
reloc : reloc. clone ( ) ,
234
229
kind : DataDiffKind :: None ,
@@ -279,8 +274,7 @@ pub fn diff_data_section(
279
274
) {
280
275
if let Some ( left_reloc) = left_reloc {
281
276
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 ;
284
278
left_reloc_diffs. push ( DataRelocationDiff {
285
279
reloc : left_reloc. relocation . clone ( ) ,
286
280
kind : diff_kind,
@@ -289,8 +283,7 @@ pub fn diff_data_section(
289
283
}
290
284
if let Some ( right_reloc) = right_reloc {
291
285
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 ;
294
287
right_reloc_diffs. push ( DataRelocationDiff {
295
288
reloc : right_reloc. relocation . clone ( ) ,
296
289
kind : diff_kind,
@@ -345,30 +338,32 @@ pub fn no_diff_data_symbol(obj: &Object, symbol_index: usize) -> Result<SymbolDi
345
338
let range = start as usize ..end as usize ;
346
339
let data = & section. data [ range. clone ( ) ] ;
347
340
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
+ } ] ;
351
346
352
347
let mut reloc_diffs = Vec :: new ( ) ;
353
348
for reloc in section. relocations . iter ( ) {
354
349
if !range. contains ( & ( reloc. address as usize ) ) {
355
350
continue ;
356
351
}
357
352
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 ;
359
354
reloc_diffs. push ( DataRelocationDiff {
360
355
reloc : reloc. clone ( ) ,
361
356
kind : DataDiffKind :: None ,
362
357
range,
363
358
} ) ;
364
359
}
365
360
361
+ let data_rows = build_data_diff_rows ( & data_diff, & reloc_diffs, symbol. address ) ;
366
362
Ok ( SymbolDiff {
367
363
target_symbol : None ,
368
364
match_percent : None ,
369
365
diff_score : None ,
370
- data_diff,
371
- data_reloc_diff : reloc_diffs,
366
+ data_rows,
372
367
..Default :: default ( )
373
368
} )
374
369
}
@@ -454,8 +449,8 @@ pub fn diff_data_symbol(
454
449
455
450
if let Some ( left_reloc) = left_reloc {
456
451
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 ;
459
454
left_reloc_diffs. push ( DataRelocationDiff {
460
455
reloc : left_reloc. relocation . clone ( ) ,
461
456
kind : diff_kind,
@@ -464,8 +459,8 @@ pub fn diff_data_symbol(
464
459
}
465
460
if let Some ( right_reloc) = right_reloc {
466
461
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 ;
469
464
right_reloc_diffs. push ( DataRelocationDiff {
470
465
reloc : right_reloc. relocation . clone ( ) ,
471
466
kind : diff_kind,
@@ -486,23 +481,29 @@ pub fn diff_data_symbol(
486
481
}
487
482
}
488
483
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
+
489
489
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 ) ;
490
493
491
494
Ok ( (
492
495
SymbolDiff {
493
496
target_symbol : Some ( right_symbol_idx) ,
494
497
match_percent : Some ( match_percent) ,
495
498
diff_score : None ,
496
- data_diff : left_data_diff,
497
- data_reloc_diff : left_reloc_diffs,
499
+ data_rows : left_rows,
498
500
..Default :: default ( )
499
501
} ,
500
502
SymbolDiff {
501
503
target_symbol : Some ( left_symbol_idx) ,
502
504
match_percent : Some ( match_percent) ,
503
505
diff_score : None ,
504
- data_diff : right_data_diff,
505
- data_reloc_diff : right_reloc_diffs,
506
+ data_rows : right_rows,
506
507
..Default :: default ( )
507
508
} ,
508
509
) )
@@ -593,3 +594,68 @@ fn symbols_matching_section(
593
594
&& !s. flags . contains ( SymbolFlag :: Ignored )
594
595
} )
595
596
}
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