@@ -666,83 +666,99 @@ static enum match_result match_chain_strings(const char *left,
666666 return ret ;
667667}
668668
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 )
671679{
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 ;
676682
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 ;
680685
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 ;
685688
686- if ( match != MATCH_ERROR )
687- return match ;
689+ return MATCH_EQ ;
690+ }
688691
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 ;
691696
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 ;
708729 }
709730
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 ++ ;
713733
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;
719739
720- if (node -> branch_flags .predicted )
721- cnode -> predicted_count ++ ;
740+ if (node -> branch_flags .predicted )
741+ cnode -> predicted_count ++ ;
722742
723- if (node -> branch_flags .abort )
724- cnode -> abort_count ++ ;
743+ if (node -> branch_flags .abort )
744+ cnode -> abort_count ++ ;
725745
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 ;
740758 }
741-
742- return MATCH_EQ ;
743759 }
744760
745- return left > right ? MATCH_GT : MATCH_LT ;
761+ return match ;
746762}
747763
748764/*
0 commit comments