@@ -24,13 +24,13 @@ pub fn diff_bss_symbol(
24
24
target_symbol : Some ( right_symbol_ref) ,
25
25
match_percent : Some ( percent) ,
26
26
diff_score : None ,
27
- instruction_rows : vec ! [ ] ,
27
+ .. Default :: default ( )
28
28
} ,
29
29
SymbolDiff {
30
30
target_symbol : Some ( left_symbol_ref) ,
31
31
match_percent : Some ( percent) ,
32
32
diff_score : None ,
33
- instruction_rows : vec ! [ ] ,
33
+ .. Default :: default ( )
34
34
} ,
35
35
) )
36
36
}
@@ -70,7 +70,83 @@ pub fn resolve_relocation<'obj>(
70
70
ResolvedRelocation { relocation : reloc, symbol }
71
71
}
72
72
73
- /// Compares relocations contained with a certain data range.
73
+ /// Compares the bytes within a certain data range.
74
+ fn diff_data_range ( left_data : & [ u8 ] , right_data : & [ u8 ] ) -> ( f32 , Vec < DataDiff > , Vec < DataDiff > ) {
75
+ let ops = capture_diff_slices ( Algorithm :: Patience , left_data, right_data) ;
76
+ let bytes_match_ratio = get_diff_ratio ( & ops, left_data. len ( ) , right_data. len ( ) ) ;
77
+
78
+ let mut left_data_diff = Vec :: < DataDiff > :: new ( ) ;
79
+ let mut right_data_diff = Vec :: < DataDiff > :: new ( ) ;
80
+ for op in ops {
81
+ let ( tag, left_range, right_range) = op. as_tag_tuple ( ) ;
82
+ let left_len = left_range. len ( ) ;
83
+ let right_len = right_range. len ( ) ;
84
+ let mut len = left_len. max ( right_len) ;
85
+ let kind = match tag {
86
+ similar:: DiffTag :: Equal => DataDiffKind :: None ,
87
+ similar:: DiffTag :: Delete => DataDiffKind :: Delete ,
88
+ similar:: DiffTag :: Insert => DataDiffKind :: Insert ,
89
+ similar:: DiffTag :: Replace => {
90
+ // Ensure replacements are equal length
91
+ len = left_len. min ( right_len) ;
92
+ DataDiffKind :: Replace
93
+ }
94
+ } ;
95
+ let left_data = & left_data[ left_range] ;
96
+ let right_data = & right_data[ right_range] ;
97
+ left_data_diff. push ( DataDiff {
98
+ data : left_data[ ..len. min ( left_data. len ( ) ) ] . to_vec ( ) ,
99
+ kind,
100
+ len,
101
+ ..Default :: default ( )
102
+ } ) ;
103
+ right_data_diff. push ( DataDiff {
104
+ data : right_data[ ..len. min ( right_data. len ( ) ) ] . to_vec ( ) ,
105
+ kind,
106
+ len,
107
+ ..Default :: default ( )
108
+ } ) ;
109
+ if kind == DataDiffKind :: Replace {
110
+ match left_len. cmp ( & right_len) {
111
+ Ordering :: Less => {
112
+ let len = right_len - left_len;
113
+ left_data_diff. push ( DataDiff {
114
+ data : vec ! [ ] ,
115
+ kind : DataDiffKind :: Insert ,
116
+ len,
117
+ ..Default :: default ( )
118
+ } ) ;
119
+ right_data_diff. push ( DataDiff {
120
+ data : right_data[ left_len..right_len] . to_vec ( ) ,
121
+ kind : DataDiffKind :: Insert ,
122
+ len,
123
+ ..Default :: default ( )
124
+ } ) ;
125
+ }
126
+ Ordering :: Greater => {
127
+ let len = left_len - right_len;
128
+ left_data_diff. push ( DataDiff {
129
+ data : left_data[ right_len..left_len] . to_vec ( ) ,
130
+ kind : DataDiffKind :: Delete ,
131
+ len,
132
+ ..Default :: default ( )
133
+ } ) ;
134
+ right_data_diff. push ( DataDiff {
135
+ data : vec ! [ ] ,
136
+ kind : DataDiffKind :: Delete ,
137
+ len,
138
+ ..Default :: default ( )
139
+ } ) ;
140
+ }
141
+ Ordering :: Equal => { }
142
+ }
143
+ }
144
+ }
145
+
146
+ ( bytes_match_ratio, left_data_diff, right_data_diff)
147
+ }
148
+
149
+ /// Compares relocations contained within a certain data range.
74
150
fn diff_data_relocs_for_range < ' left , ' right > (
75
151
left_obj : & ' left Object ,
76
152
right_obj : & ' right Object ,
@@ -172,76 +248,10 @@ pub fn diff_data_section(
172
248
. min ( right_section. size ) ;
173
249
let left_data = & left_section. data [ ..left_max as usize ] ;
174
250
let right_data = & right_section. data [ ..right_max as usize ] ;
175
- let ops = capture_diff_slices ( Algorithm :: Patience , left_data, right_data) ;
176
- let match_percent = get_diff_ratio ( & ops, left_data. len ( ) , right_data. len ( ) ) * 100.0 ;
177
251
178
- let mut left_data_diff = Vec :: < DataDiff > :: new ( ) ;
179
- let mut right_data_diff = Vec :: < DataDiff > :: new ( ) ;
180
- for op in ops {
181
- let ( tag, left_range, right_range) = op. as_tag_tuple ( ) ;
182
- let left_len = left_range. len ( ) ;
183
- let right_len = right_range. len ( ) ;
184
- let mut len = left_len. max ( right_len) ;
185
- let kind = match tag {
186
- similar:: DiffTag :: Equal => DataDiffKind :: None ,
187
- similar:: DiffTag :: Delete => DataDiffKind :: Delete ,
188
- similar:: DiffTag :: Insert => DataDiffKind :: Insert ,
189
- similar:: DiffTag :: Replace => {
190
- // Ensure replacements are equal length
191
- len = left_len. min ( right_len) ;
192
- DataDiffKind :: Replace
193
- }
194
- } ;
195
- let left_data = & left_section. data [ left_range] ;
196
- let right_data = & right_section. data [ right_range] ;
197
- left_data_diff. push ( DataDiff {
198
- data : left_data[ ..len. min ( left_data. len ( ) ) ] . to_vec ( ) ,
199
- kind,
200
- len,
201
- ..Default :: default ( )
202
- } ) ;
203
- right_data_diff. push ( DataDiff {
204
- data : right_data[ ..len. min ( right_data. len ( ) ) ] . to_vec ( ) ,
205
- kind,
206
- len,
207
- ..Default :: default ( )
208
- } ) ;
209
- if kind == DataDiffKind :: Replace {
210
- match left_len. cmp ( & right_len) {
211
- Ordering :: Less => {
212
- let len = right_len - left_len;
213
- left_data_diff. push ( DataDiff {
214
- data : vec ! [ ] ,
215
- kind : DataDiffKind :: Insert ,
216
- len,
217
- ..Default :: default ( )
218
- } ) ;
219
- right_data_diff. push ( DataDiff {
220
- data : right_data[ left_len..right_len] . to_vec ( ) ,
221
- kind : DataDiffKind :: Insert ,
222
- len,
223
- ..Default :: default ( )
224
- } ) ;
225
- }
226
- Ordering :: Greater => {
227
- let len = left_len - right_len;
228
- left_data_diff. push ( DataDiff {
229
- data : left_data[ right_len..left_len] . to_vec ( ) ,
230
- kind : DataDiffKind :: Delete ,
231
- len,
232
- ..Default :: default ( )
233
- } ) ;
234
- right_data_diff. push ( DataDiff {
235
- data : vec ! [ ] ,
236
- kind : DataDiffKind :: Delete ,
237
- len,
238
- ..Default :: default ( )
239
- } ) ;
240
- }
241
- Ordering :: Equal => { }
242
- }
243
- }
244
- }
252
+ let ( bytes_match_ratio, left_data_diff, right_data_diff) =
253
+ diff_data_range ( left_data, right_data) ;
254
+ let match_percent = bytes_match_ratio * 100.0 ;
245
255
246
256
let mut left_reloc_diffs = Vec :: new ( ) ;
247
257
let mut right_reloc_diffs = Vec :: new ( ) ;
@@ -300,6 +310,55 @@ pub fn diff_data_section(
300
310
Ok ( ( left_section_diff, right_section_diff) )
301
311
}
302
312
313
+ pub fn no_diff_data_symbol ( obj : & Object , symbol_index : usize ) -> Result < SymbolDiff > {
314
+ let symbol = & obj. symbols [ symbol_index] ;
315
+ let section_idx = symbol. section . ok_or_else ( || anyhow ! ( "Data symbol section not found" ) ) ?;
316
+ let section = & obj. sections [ section_idx] ;
317
+
318
+ let start = symbol
319
+ . address
320
+ . checked_sub ( section. address )
321
+ . ok_or_else ( || anyhow ! ( "Symbol address out of section bounds" ) ) ?;
322
+ let end = start + symbol. size ;
323
+ if end > section. size {
324
+ return Err ( anyhow ! (
325
+ "Symbol {} size out of section bounds ({} > {})" ,
326
+ symbol. name,
327
+ end,
328
+ section. size
329
+ ) ) ;
330
+ }
331
+ let range = start as usize ..end as usize ;
332
+ let data = & section. data [ range. clone ( ) ] ;
333
+
334
+ let len = symbol. size as usize ;
335
+ let data_diff =
336
+ vec ! [ DataDiff { data: data. to_vec( ) , kind: DataDiffKind :: None , len, ..Default :: default ( ) } ] ;
337
+
338
+ let mut reloc_diffs = Vec :: new ( ) ;
339
+ for reloc in section. relocations . iter ( ) {
340
+ if !range. contains ( & ( reloc. address as usize ) ) {
341
+ continue ;
342
+ }
343
+ let reloc_len = obj. arch . data_reloc_size ( reloc. flags ) ;
344
+ let range = reloc. address as usize ..reloc. address as usize + reloc_len;
345
+ reloc_diffs. push ( DataRelocationDiff {
346
+ reloc : reloc. clone ( ) ,
347
+ kind : DataDiffKind :: None ,
348
+ range,
349
+ } ) ;
350
+ }
351
+
352
+ Ok ( SymbolDiff {
353
+ target_symbol : None ,
354
+ match_percent : None ,
355
+ diff_score : None ,
356
+ data_diff,
357
+ data_reloc_diff : reloc_diffs,
358
+ ..Default :: default ( )
359
+ } )
360
+ }
361
+
303
362
pub fn diff_data_symbol (
304
363
left_obj : & Object ,
305
364
right_obj : & Object ,
@@ -348,6 +407,9 @@ pub fn diff_data_symbol(
348
407
let left_data = & left_section. data [ left_range. clone ( ) ] ;
349
408
let right_data = & right_section. data [ right_range. clone ( ) ] ;
350
409
410
+ let ( bytes_match_ratio, left_data_diff, right_data_diff) =
411
+ diff_data_range ( left_data, right_data) ;
412
+
351
413
let reloc_diffs = diff_data_relocs_for_range (
352
414
left_obj,
353
415
right_obj,
@@ -357,10 +419,9 @@ pub fn diff_data_symbol(
357
419
right_range,
358
420
) ;
359
421
360
- let ops = capture_diff_slices ( Algorithm :: Patience , left_data, right_data) ;
361
- let bytes_match_ratio = get_diff_ratio ( & ops, left_data. len ( ) , right_data. len ( ) ) ;
362
-
363
422
let mut match_ratio = bytes_match_ratio;
423
+ let mut left_reloc_diffs = Vec :: new ( ) ;
424
+ let mut right_reloc_diffs = Vec :: new ( ) ;
364
425
if !reloc_diffs. is_empty ( ) {
365
426
let mut total_reloc_bytes = 0 ;
366
427
let mut matching_reloc_bytes = 0 ;
@@ -376,6 +437,27 @@ pub fn diff_data_symbol(
376
437
if diff_kind == DataDiffKind :: None {
377
438
matching_reloc_bytes += reloc_diff_len;
378
439
}
440
+
441
+ if let Some ( left_reloc) = left_reloc {
442
+ let len = left_obj. arch . data_reloc_size ( left_reloc. relocation . flags ) ;
443
+ let range = left_reloc. relocation . address as usize
444
+ ..left_reloc. relocation . address as usize + len;
445
+ left_reloc_diffs. push ( DataRelocationDiff {
446
+ reloc : left_reloc. relocation . clone ( ) ,
447
+ kind : diff_kind,
448
+ range,
449
+ } ) ;
450
+ }
451
+ if let Some ( right_reloc) = right_reloc {
452
+ let len = right_obj. arch . data_reloc_size ( right_reloc. relocation . flags ) ;
453
+ let range = right_reloc. relocation . address as usize
454
+ ..right_reloc. relocation . address as usize + len;
455
+ right_reloc_diffs. push ( DataRelocationDiff {
456
+ reloc : right_reloc. relocation . clone ( ) ,
457
+ kind : diff_kind,
458
+ range,
459
+ } ) ;
460
+ }
379
461
}
380
462
if total_reloc_bytes > 0 {
381
463
let relocs_match_ratio = matching_reloc_bytes as f32 / total_reloc_bytes as f32 ;
@@ -397,13 +479,17 @@ pub fn diff_data_symbol(
397
479
target_symbol : Some ( right_symbol_idx) ,
398
480
match_percent : Some ( match_percent) ,
399
481
diff_score : None ,
400
- instruction_rows : vec ! [ ] ,
482
+ data_diff : left_data_diff,
483
+ data_reloc_diff : left_reloc_diffs,
484
+ ..Default :: default ( )
401
485
} ,
402
486
SymbolDiff {
403
487
target_symbol : Some ( left_symbol_idx) ,
404
488
match_percent : Some ( match_percent) ,
405
489
diff_score : None ,
406
- instruction_rows : vec ! [ ] ,
490
+ data_diff : right_data_diff,
491
+ data_reloc_diff : right_reloc_diffs,
492
+ ..Default :: default ( )
407
493
} ,
408
494
) )
409
495
}
0 commit comments