@@ -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
}
@@ -84,7 +84,83 @@ pub fn resolve_relocation<'obj>(
84
84
ResolvedRelocation { relocation : reloc, symbol }
85
85
}
86
86
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.
88
164
fn diff_data_relocs_for_range < ' left , ' right > (
89
165
left_obj : & ' left Object ,
90
166
right_obj : & ' right Object ,
@@ -186,76 +262,10 @@ pub fn diff_data_section(
186
262
. min ( right_section. size ) ;
187
263
let left_data = & left_section. data [ ..left_max as usize ] ;
188
264
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 ;
191
265
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 ;
259
269
260
270
let mut left_reloc_diffs = Vec :: new ( ) ;
261
271
let mut right_reloc_diffs = Vec :: new ( ) ;
@@ -314,6 +324,55 @@ pub fn diff_data_section(
314
324
Ok ( ( left_section_diff, right_section_diff) )
315
325
}
316
326
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
+
317
376
pub fn diff_data_symbol (
318
377
left_obj : & Object ,
319
378
right_obj : & Object ,
@@ -362,6 +421,9 @@ pub fn diff_data_symbol(
362
421
let left_data = & left_section. data [ left_range. clone ( ) ] ;
363
422
let right_data = & right_section. data [ right_range. clone ( ) ] ;
364
423
424
+ let ( bytes_match_ratio, left_data_diff, right_data_diff) =
425
+ diff_data_range ( left_data, right_data) ;
426
+
365
427
let reloc_diffs = diff_data_relocs_for_range (
366
428
left_obj,
367
429
right_obj,
@@ -371,10 +433,9 @@ pub fn diff_data_symbol(
371
433
right_range,
372
434
) ;
373
435
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
-
377
436
let mut match_ratio = bytes_match_ratio;
437
+ let mut left_reloc_diffs = Vec :: new ( ) ;
438
+ let mut right_reloc_diffs = Vec :: new ( ) ;
378
439
if !reloc_diffs. is_empty ( ) {
379
440
let mut total_reloc_bytes = 0 ;
380
441
let mut matching_reloc_bytes = 0 ;
@@ -390,6 +451,27 @@ pub fn diff_data_symbol(
390
451
if diff_kind == DataDiffKind :: None {
391
452
matching_reloc_bytes += reloc_diff_len;
392
453
}
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
+ }
393
475
}
394
476
if total_reloc_bytes > 0 {
395
477
let relocs_match_ratio = matching_reloc_bytes as f32 / total_reloc_bytes as f32 ;
@@ -411,13 +493,17 @@ pub fn diff_data_symbol(
411
493
target_symbol : Some ( right_symbol_idx) ,
412
494
match_percent : Some ( match_percent) ,
413
495
diff_score : None ,
414
- instruction_rows : vec ! [ ] ,
496
+ data_diff : left_data_diff,
497
+ data_reloc_diff : left_reloc_diffs,
498
+ ..Default :: default ( )
415
499
} ,
416
500
SymbolDiff {
417
501
target_symbol : Some ( left_symbol_idx) ,
418
502
match_percent : Some ( match_percent) ,
419
503
diff_score : None ,
420
- instruction_rows : vec ! [ ] ,
504
+ data_diff : right_data_diff,
505
+ data_reloc_diff : right_reloc_diffs,
506
+ ..Default :: default ( )
421
507
} ,
422
508
) )
423
509
}
0 commit comments