@@ -4,9 +4,9 @@ use alloc::{
44 vec,
55 vec:: Vec ,
66} ;
7- use core:: { num:: NonZeroU32 , ops:: Range } ;
7+ use core:: { cmp :: Ordering , num:: NonZeroU32 , ops:: Range } ;
88
9- use anyhow:: Result ;
9+ use anyhow:: { Result , anyhow } ;
1010
1111use crate :: {
1212 diff:: {
@@ -17,7 +17,7 @@ use crate::{
1717 symbol_name_matches,
1818 } ,
1919 } ,
20- obj:: { InstructionRef , Object , Relocation , SectionKind , Symbol , SymbolFlag } ,
20+ obj:: { InstructionRef , Object , Relocation , SectionKind , Symbol , SymbolFlag , SymbolKind } ,
2121} ;
2222
2323pub mod code;
@@ -47,6 +47,7 @@ pub struct SymbolDiff {
4747 pub diff_score : Option < ( u64 , u64 ) > ,
4848 pub instruction_rows : Vec < InstructionDiffRow > ,
4949 pub data_rows : Vec < DataDiffRow > ,
50+ pub order : Option < Ordering > ,
5051}
5152
5253#[ derive( Debug , Clone , Default ) ]
@@ -207,8 +208,8 @@ pub fn diff_objs(
207208 let mut right = right. map ( |p| ( p, ObjectDiff :: new_from_obj ( p) ) ) ;
208209 let mut prev = prev. map ( |p| ( p, ObjectDiff :: new_from_obj ( p) ) ) ;
209210
210- for symbol_match in symbol_matches {
211- match symbol_match {
211+ for symbol_match in & symbol_matches {
212+ match * symbol_match {
212213 SymbolMatch {
213214 left : Some ( left_symbol_ref) ,
214215 right : Some ( right_symbol_ref) ,
@@ -412,13 +413,110 @@ pub fn diff_objs(
412413 }
413414 }
414415
416+ if let Some ( ( left_obj, left_out) ) = left. as_mut ( )
417+ && let Some ( ( right_obj, right_out) ) = right. as_mut ( )
418+ {
419+ let mut done_section_names = BTreeSet :: new ( ) ;
420+ for left_section in left_obj. sections . iter ( ) {
421+ if done_section_names. contains ( & left_section. name ) {
422+ continue ;
423+ }
424+ done_section_names. insert ( & left_section. name ) ;
425+ diff_order_for_section_name (
426+ left_obj,
427+ right_obj,
428+ left_out,
429+ right_out,
430+ & left_section. name ,
431+ & symbol_matches,
432+ ) ?;
433+ }
434+ }
435+
415436 Ok ( DiffObjsResult {
416437 left : left. map ( |( _, o) | o) ,
417438 right : right. map ( |( _, o) | o) ,
418439 prev : prev. map ( |( _, o) | o) ,
419440 } )
420441}
421442
443+ fn symbols_matching_section_name < ' obj > (
444+ obj : & ' obj Object ,
445+ section_name : & str ,
446+ ) -> impl Iterator < Item = ( usize , & ' obj Symbol ) > {
447+ obj. symbols . iter ( ) . enumerate ( ) . filter ( move |( _, s) | {
448+ let curr_section_name = symbol_section ( obj, s) . map ( |( n, _) | n) ;
449+ curr_section_name == Some ( section_name)
450+ && s. kind != SymbolKind :: Section
451+ && s. size > 0
452+ && !s. flags . contains ( SymbolFlag :: Hidden )
453+ && !s. flags . contains ( SymbolFlag :: Ignored )
454+ } )
455+ }
456+
457+ fn diff_order_for_section_name (
458+ left_obj : & Object ,
459+ right_obj : & Object ,
460+ left_diff : & mut ObjectDiff ,
461+ right_diff : & mut ObjectDiff ,
462+ section_name : & str ,
463+ symbol_matches : & Vec < SymbolMatch > ,
464+ ) -> Result < ( ) > {
465+ let mut left_paired_symbol_idxs = BTreeSet :: new ( ) ;
466+ let mut right_paired_symbol_idxs = BTreeSet :: new ( ) ;
467+ let mut left_sym_idx_to_right_sym_idx = BTreeMap :: new ( ) ;
468+ for symbol_match in symbol_matches {
469+ let Some ( left_symbol_idx) = symbol_match. left else {
470+ continue ;
471+ } ;
472+ let Some ( right_symbol_idx) = symbol_match. right else {
473+ continue ;
474+ } ;
475+ left_paired_symbol_idxs. insert ( left_symbol_idx) ;
476+ right_paired_symbol_idxs. insert ( right_symbol_idx) ;
477+ left_sym_idx_to_right_sym_idx. insert ( left_symbol_idx, right_symbol_idx) ;
478+ }
479+
480+ let left_paired_symbols: Vec < _ > = symbols_matching_section_name ( left_obj, section_name)
481+ . filter ( |( sym_idx, _) | left_paired_symbol_idxs. contains ( sym_idx) )
482+ . collect ( ) ;
483+ let right_paired_symbols: Vec < _ > = symbols_matching_section_name ( right_obj, section_name)
484+ . filter ( |( sym_idx, _) | right_paired_symbol_idxs. contains ( sym_idx) )
485+ . collect ( ) ;
486+
487+ let mut expected_right_order_idx = 0 ;
488+ for ( left_order_idx, ( left_symbol_idx, _left_symbol) ) in left_paired_symbols. iter ( ) . enumerate ( )
489+ {
490+ let right_symbol_idx = left_sym_idx_to_right_sym_idx. get ( left_symbol_idx) . unwrap ( ) ;
491+ let right_order_idx = right_paired_symbols
492+ . iter ( )
493+ . position ( |( sym_idx, _) | sym_idx == right_symbol_idx)
494+ . ok_or_else ( || {
495+ anyhow ! ( "Failed to find right side symbol for paired left side symbol" )
496+ } ) ?;
497+ if right_order_idx == left_order_idx {
498+ // In the correct spot.
499+ left_diff. symbols [ * left_symbol_idx] . order = Some ( Ordering :: Equal ) ;
500+ right_diff. symbols [ * right_symbol_idx] . order = Some ( Ordering :: Equal ) ;
501+ expected_right_order_idx = left_order_idx + 1
502+ } else if right_order_idx == expected_right_order_idx {
503+ // In the wrong spot, but correct relative to the symbol before it.
504+ // Don't show this as a diff to reduce noise.
505+ left_diff. symbols [ * left_symbol_idx] . order = Some ( Ordering :: Equal ) ;
506+ right_diff. symbols [ * right_symbol_idx] . order = Some ( Ordering :: Equal ) ;
507+ } else {
508+ // In the wrong spot.
509+ left_diff. symbols [ * left_symbol_idx] . order =
510+ Some ( expected_right_order_idx. cmp ( & right_order_idx) ) ;
511+ right_diff. symbols [ * right_symbol_idx] . order =
512+ Some ( right_order_idx. cmp ( & expected_right_order_idx) ) ;
513+ expected_right_order_idx = right_order_idx;
514+ }
515+ expected_right_order_idx += 1 ;
516+ }
517+ Ok ( ( ) )
518+ }
519+
422520/// Score entry for a candidate symbol when searching for similar functions.
423521#[ derive( Debug , Clone ) ]
424522pub struct SimilarSymbol {
0 commit comments