@@ -666,83 +666,99 @@ static enum match_result match_chain_strings(const char *left,
666
666
return ret ;
667
667
}
668
668
669
- static enum match_result match_chain (struct callchain_cursor_node * node ,
670
- struct callchain_list * cnode )
669
+ /*
670
+ * We need to always use relative addresses because we're aggregating
671
+ * callchains from multiple threads, i.e. different address spaces, so
672
+ * comparing absolute addresses make no sense as a symbol in a DSO may end up
673
+ * in a different address when used in a different binary or even the same
674
+ * binary but with some sort of address randomization technique, thus we need
675
+ * to compare just relative addresses. -acme
676
+ */
677
+ static enum match_result match_chain_dso_addresses (struct map * left_map , u64 left_ip ,
678
+ struct map * right_map , u64 right_ip )
671
679
{
672
- struct symbol * sym = node -> sym ;
673
- u64 left , right ;
674
- struct dso * left_dso = NULL ;
675
- struct dso * right_dso = NULL ;
680
+ struct dso * left_dso = left_map ? left_map -> dso : NULL ;
681
+ struct dso * right_dso = right_map ? right_map -> dso : NULL ;
676
682
677
- if (callchain_param .key == CCKEY_SRCLINE ) {
678
- enum match_result match = match_chain_strings (cnode -> srcline ,
679
- node -> srcline );
683
+ if (left_dso != right_dso )
684
+ return left_dso < right_dso ? MATCH_LT : MATCH_GT ;
680
685
681
- /* if no srcline is available, fallback to symbol name */
682
- if (match == MATCH_ERROR && cnode -> ms .sym && node -> sym )
683
- match = match_chain_strings (cnode -> ms .sym -> name ,
684
- node -> sym -> name );
686
+ if (left_ip != right_ip )
687
+ return left_ip < right_ip ? MATCH_LT : MATCH_GT ;
685
688
686
- if ( match != MATCH_ERROR )
687
- return match ;
689
+ return MATCH_EQ ;
690
+ }
688
691
689
- /* otherwise fall-back to IP-based comparison below */
690
- }
692
+ static enum match_result match_chain (struct callchain_cursor_node * node ,
693
+ struct callchain_list * cnode )
694
+ {
695
+ enum match_result match = MATCH_ERROR ;
691
696
692
- if (cnode -> ms .sym && sym && callchain_param .key == CCKEY_FUNCTION ) {
693
- /*
694
- * Compare inlined frames based on their symbol name because
695
- * different inlined frames will have the same symbol start
696
- */
697
- if (cnode -> ms .sym -> inlined || node -> sym -> inlined )
698
- return match_chain_strings (cnode -> ms .sym -> name ,
699
- node -> sym -> name );
700
-
701
- left = cnode -> ms .sym -> start ;
702
- right = sym -> start ;
703
- left_dso = cnode -> ms .map -> dso ;
704
- right_dso = node -> map -> dso ;
705
- } else {
706
- left = cnode -> ip ;
707
- right = node -> ip ;
697
+ switch (callchain_param .key ) {
698
+ case CCKEY_SRCLINE :
699
+ match = match_chain_strings (cnode -> srcline , node -> srcline );
700
+ if (match != MATCH_ERROR )
701
+ break ;
702
+ /* otherwise fall-back to symbol-based comparison below */
703
+ __fallthrough ;
704
+ case CCKEY_FUNCTION :
705
+ if (node -> sym && cnode -> ms .sym ) {
706
+ /*
707
+ * Compare inlined frames based on their symbol name
708
+ * because different inlined frames will have the same
709
+ * symbol start. Otherwise do a faster comparison based
710
+ * on the symbol start address.
711
+ */
712
+ if (cnode -> ms .sym -> inlined || node -> sym -> inlined ) {
713
+ match = match_chain_strings (cnode -> ms .sym -> name ,
714
+ node -> sym -> name );
715
+ if (match != MATCH_ERROR )
716
+ break ;
717
+ } else {
718
+ match = match_chain_dso_addresses (cnode -> ms .map , cnode -> ms .sym -> start ,
719
+ node -> map , node -> sym -> start );
720
+ break ;
721
+ }
722
+ }
723
+ /* otherwise fall-back to IP-based comparison below */
724
+ __fallthrough ;
725
+ case CCKEY_ADDRESS :
726
+ default :
727
+ match = match_chain_dso_addresses (cnode -> ms .map , cnode -> ip , node -> map , node -> ip );
728
+ break ;
708
729
}
709
730
710
- if (left == right && left_dso == right_dso ) {
711
- if (node -> branch ) {
712
- cnode -> branch_count ++ ;
731
+ if (match == MATCH_EQ && node -> branch ) {
732
+ cnode -> branch_count ++ ;
713
733
714
- if (node -> branch_from ) {
715
- /*
716
- * It's "to" of a branch
717
- */
718
- cnode -> brtype_stat .branch_to = true;
734
+ if (node -> branch_from ) {
735
+ /*
736
+ * It's "to" of a branch
737
+ */
738
+ cnode -> brtype_stat .branch_to = true;
719
739
720
- if (node -> branch_flags .predicted )
721
- cnode -> predicted_count ++ ;
740
+ if (node -> branch_flags .predicted )
741
+ cnode -> predicted_count ++ ;
722
742
723
- if (node -> branch_flags .abort )
724
- cnode -> abort_count ++ ;
743
+ if (node -> branch_flags .abort )
744
+ cnode -> abort_count ++ ;
725
745
726
- branch_type_count (& cnode -> brtype_stat ,
727
- & node -> branch_flags ,
728
- node -> branch_from ,
729
- node -> ip );
730
- } else {
731
- /*
732
- * It's "from" of a branch
733
- */
734
- cnode -> brtype_stat .branch_to = false;
735
- cnode -> cycles_count +=
736
- node -> branch_flags .cycles ;
737
- cnode -> iter_count += node -> nr_loop_iter ;
738
- cnode -> iter_cycles += node -> iter_cycles ;
739
- }
746
+ branch_type_count (& cnode -> brtype_stat ,
747
+ & node -> branch_flags ,
748
+ node -> branch_from ,
749
+ node -> ip );
750
+ } else {
751
+ /*
752
+ * It's "from" of a branch
753
+ */
754
+ cnode -> brtype_stat .branch_to = false;
755
+ cnode -> cycles_count += node -> branch_flags .cycles ;
756
+ cnode -> iter_count += node -> nr_loop_iter ;
757
+ cnode -> iter_cycles += node -> iter_cycles ;
740
758
}
741
-
742
- return MATCH_EQ ;
743
759
}
744
760
745
- return left > right ? MATCH_GT : MATCH_LT ;
761
+ return match ;
746
762
}
747
763
748
764
/*
0 commit comments