4545#include "pmus.h"
4646#include "string2.h"
4747#include "util/util.h"
48+ #include "util/symbol.h"
49+ #include "util/annotate.h"
4850
4951struct c2c_hists {
5052 struct hists hists ;
@@ -62,6 +64,7 @@ struct compute_stats {
6264
6365struct c2c_hist_entry {
6466 struct c2c_hists * hists ;
67+ struct evsel * evsel ;
6568 struct c2c_stats stats ;
6669 unsigned long * cpuset ;
6770 unsigned long * nodeset ;
@@ -225,6 +228,12 @@ he__get_c2c_hists(struct hist_entry *he,
225228 return hists ;
226229}
227230
231+ static void c2c_he__set_evsel (struct c2c_hist_entry * c2c_he ,
232+ struct evsel * evsel )
233+ {
234+ c2c_he -> evsel = evsel ;
235+ }
236+
228237static void c2c_he__set_cpu (struct c2c_hist_entry * c2c_he ,
229238 struct perf_sample * sample )
230239{
@@ -275,6 +284,33 @@ static void compute_stats(struct c2c_hist_entry *c2c_he,
275284 update_stats (& cstats -> load , weight );
276285}
277286
287+ /*
288+ * Return true if annotation is possible. When list is NULL,
289+ * it means that we are called at the c2c_browser level,
290+ * in that case we allow annotation to be initialized. When list
291+ * is non-NULL, it means that we are called at the cacheline_browser
292+ * level, in that case we allow annotation only if use_browser
293+ * is set and symbol information is available.
294+ */
295+ static bool perf_c2c__has_annotation (struct perf_hpp_list * list )
296+ {
297+ if (use_browser != 1 )
298+ return false;
299+ return !list || list -> sym ;
300+ }
301+
302+ static void perf_c2c__evsel_hists_inc_stats (struct evsel * evsel ,
303+ struct hist_entry * he ,
304+ struct perf_sample * sample )
305+ {
306+ struct hists * evsel_hists = evsel__hists (evsel );
307+
308+ hists__inc_nr_samples (evsel_hists , he -> filtered );
309+ evsel_hists -> stats .total_period += sample -> period ;
310+ if (!he -> filtered )
311+ evsel_hists -> stats .total_non_filtered_period += sample -> period ;
312+ }
313+
278314static int process_sample_event (const struct perf_tool * tool __maybe_unused ,
279315 union perf_event * event ,
280316 struct perf_sample * sample ,
@@ -334,8 +370,15 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused,
334370
335371 c2c_he__set_cpu (c2c_he , sample );
336372 c2c_he__set_node (c2c_he , sample );
373+ c2c_he__set_evsel (c2c_he , evsel );
337374
338375 hists__inc_nr_samples (& c2c_hists -> hists , he -> filtered );
376+
377+ if (perf_c2c__has_annotation (NULL )) {
378+ perf_c2c__evsel_hists_inc_stats (evsel , he , sample );
379+ addr_map_symbol__inc_samples (mem_info__iaddr (mi ), sample , evsel );
380+ }
381+
339382 ret = hist_entry__append_callchain (he , sample );
340383
341384 if (!ret ) {
@@ -371,6 +414,7 @@ static int process_sample_event(const struct perf_tool *tool __maybe_unused,
371414
372415 c2c_he__set_cpu (c2c_he , sample );
373416 c2c_he__set_node (c2c_he , sample );
417+ c2c_he__set_evsel (c2c_he , evsel );
374418
375419 hists__inc_nr_samples (& c2c_hists -> hists , he -> filtered );
376420 ret = hist_entry__append_callchain (he , sample );
@@ -1997,6 +2041,9 @@ static int c2c_hists__init_sort(struct perf_hpp_list *hpp_list, char *name, stru
19972041 if (dim == & dim_dso )
19982042 hpp_list -> dso = 1 ;
19992043
2044+ if (dim == & dim_symbol || dim == & dim_iaddr )
2045+ hpp_list -> sym = 1 ;
2046+
20002047 perf_hpp_list__register_sort_field (hpp_list , & c2c_fmt -> fmt );
20012048 return 0 ;
20022049}
@@ -2550,6 +2597,40 @@ static void perf_c2c__hists_fprintf(FILE *out, struct perf_session *session)
25502597}
25512598
25522599#ifdef HAVE_SLANG_SUPPORT
2600+
2601+ static int perf_c2c__toggle_annotation (struct hist_browser * browser )
2602+ {
2603+ struct hist_entry * he = browser -> he_selection ;
2604+ struct symbol * sym = NULL ;
2605+ struct annotated_source * src = NULL ;
2606+ struct c2c_hist_entry * c2c_he = NULL ;
2607+
2608+ if (!perf_c2c__has_annotation (he -> hists -> hpp_list )) {
2609+ ui_browser__help_window (& browser -> b , "No annotation support" );
2610+ return 0 ;
2611+ }
2612+
2613+ if (he == NULL ) {
2614+ ui_browser__help_window (& browser -> b , "No entry selected for annotation" );
2615+ return 0 ;
2616+ }
2617+
2618+ sym = he -> ms .sym ;
2619+ if (sym == NULL ) {
2620+ ui_browser__help_window (& browser -> b , "Can not annotate, no symbol found" );
2621+ return 0 ;
2622+ }
2623+
2624+ src = symbol__hists (sym , 0 );
2625+ if (src == NULL ) {
2626+ ui_browser__help_window (& browser -> b , "Failed to initialize annotation source" );
2627+ return 0 ;
2628+ }
2629+
2630+ c2c_he = container_of (he , struct c2c_hist_entry , he );
2631+ return hist_entry__tui_annotate (he , c2c_he -> evsel , NULL );
2632+ }
2633+
25532634static void c2c_browser__update_nr_entries (struct hist_browser * hb )
25542635{
25552636 u64 nr_entries = 0 ;
@@ -2617,6 +2698,7 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he)
26172698 " ENTER Toggle callchains (if present) \n"
26182699 " n Toggle Node details info \n"
26192700 " s Toggle full length of symbol and source line columns \n"
2701+ " a Toggle annotation view \n"
26202702 " q Return back to cacheline list \n" ;
26212703
26222704 if (!he )
@@ -2651,6 +2733,9 @@ static int perf_c2c__browse_cacheline(struct hist_entry *he)
26512733 c2c .node_info = (c2c .node_info + 1 ) % 3 ;
26522734 setup_nodes_header ();
26532735 break ;
2736+ case 'a' :
2737+ perf_c2c__toggle_annotation (browser );
2738+ break ;
26542739 case 'q' :
26552740 goto out ;
26562741 case '?' :
@@ -3006,6 +3091,7 @@ static int perf_c2c__report(int argc, const char **argv)
30063091 const char * display = NULL ;
30073092 const char * coalesce = NULL ;
30083093 bool no_source = false;
3094+ const char * disassembler_style = NULL , * objdump_path = NULL ;
30093095 const struct option options [] = {
30103096 OPT_STRING ('k' , "vmlinux" , & symbol_conf .vmlinux_name ,
30113097 "file" , "vmlinux pathname" ),
@@ -3033,13 +3119,23 @@ static int perf_c2c__report(int argc, const char **argv)
30333119 OPT_BOOLEAN (0 , "stitch-lbr" , & c2c .stitch_lbr ,
30343120 "Enable LBR callgraph stitching approach" ),
30353121 OPT_BOOLEAN (0 , "double-cl" , & chk_double_cl , "Detect adjacent cacheline false sharing" ),
3122+ OPT_STRING ('M' , "disassembler-style" , & disassembler_style , "disassembler style" ,
3123+ "Specify disassembler style (e.g. -M intel for intel syntax)" ),
3124+ OPT_STRING (0 , "objdump" , & objdump_path , "path" ,
3125+ "objdump binary to use for disassembly and annotations" ),
30363126 OPT_PARENT (c2c_options ),
30373127 OPT_END ()
30383128 };
30393129 int err = 0 ;
30403130 const char * output_str , * sort_str = NULL ;
30413131 struct perf_env * env ;
30423132
3133+ annotation_options__init ();
3134+
3135+ err = hists__init ();
3136+ if (err < 0 )
3137+ goto out ;
3138+
30433139 argc = parse_options (argc , argv , options , report_c2c_usage ,
30443140 PARSE_OPT_STOP_AT_NON_OPTION );
30453141 if (argc )
@@ -3052,6 +3148,27 @@ static int perf_c2c__report(int argc, const char **argv)
30523148 if (c2c .stats_only )
30533149 c2c .use_stdio = true;
30543150
3151+ /**
3152+ * Annotation related options disassembler_style, objdump_path are set
3153+ * in the c2c_options, so we can use them here.
3154+ */
3155+ if (disassembler_style ) {
3156+ annotate_opts .disassembler_style = strdup (disassembler_style );
3157+ if (!annotate_opts .disassembler_style ) {
3158+ err = - ENOMEM ;
3159+ pr_err ("Failed to allocate memory for annotation options\n" );
3160+ goto out ;
3161+ }
3162+ }
3163+ if (objdump_path ) {
3164+ annotate_opts .objdump_path = strdup (objdump_path );
3165+ if (!annotate_opts .objdump_path ) {
3166+ err = - ENOMEM ;
3167+ pr_err ("Failed to allocate memory for annotation options\n" );
3168+ goto out ;
3169+ }
3170+ }
3171+
30553172 err = symbol__validate_sym_arguments ();
30563173 if (err )
30573174 goto out ;
@@ -3126,6 +3243,38 @@ static int perf_c2c__report(int argc, const char **argv)
31263243 if (err )
31273244 goto out_mem2node ;
31283245
3246+ if (c2c .use_stdio )
3247+ use_browser = 0 ;
3248+ else
3249+ use_browser = 1 ;
3250+
3251+ /*
3252+ * Only in the TUI browser we are doing integrated annotation,
3253+ * so don't allocate extra space that won't be used in the stdio
3254+ * implementation.
3255+ */
3256+ if (perf_c2c__has_annotation (NULL )) {
3257+ int ret = symbol__annotation_init ();
3258+
3259+ if (ret < 0 )
3260+ goto out_mem2node ;
3261+ /*
3262+ * For searching by name on the "Browse map details".
3263+ * providing it only in verbose mode not to bloat too
3264+ * much struct symbol.
3265+ */
3266+ if (verbose > 0 ) {
3267+ /*
3268+ * XXX: Need to provide a less kludgy way to ask for
3269+ * more space per symbol, the u32 is for the index on
3270+ * the ui browser.
3271+ * See symbol__browser_index.
3272+ */
3273+ symbol_conf .priv_size += sizeof (u32 );
3274+ }
3275+ annotation_config__init ();
3276+ }
3277+
31293278 if (symbol__init (env ) < 0 )
31303279 goto out_mem2node ;
31313280
@@ -3135,11 +3284,6 @@ static int perf_c2c__report(int argc, const char **argv)
31353284 goto out_mem2node ;
31363285 }
31373286
3138- if (c2c .use_stdio )
3139- use_browser = 0 ;
3140- else
3141- use_browser = 1 ;
3142-
31433287 setup_browser (false);
31443288
31453289 err = perf_session__process_events (session );
@@ -3210,6 +3354,7 @@ static int perf_c2c__report(int argc, const char **argv)
32103354out_session :
32113355 perf_session__delete (session );
32123356out :
3357+ annotation_options__exit ();
32133358 return err ;
32143359}
32153360
0 commit comments