@@ -1105,14 +1105,42 @@ static int perf_sample__fprintf_addr(struct perf_sample *sample,
1105
1105
return printed ;
1106
1106
}
1107
1107
1108
+ static const char * resolve_branch_sym (struct perf_sample * sample ,
1109
+ struct perf_evsel * evsel ,
1110
+ struct thread * thread ,
1111
+ struct addr_location * al ,
1112
+ u64 * ip )
1113
+ {
1114
+ struct addr_location addr_al ;
1115
+ struct perf_event_attr * attr = & evsel -> attr ;
1116
+ const char * name = NULL ;
1117
+
1118
+ if (sample -> flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN )) {
1119
+ if (sample_addr_correlates_sym (attr )) {
1120
+ thread__resolve (thread , & addr_al , sample );
1121
+ if (addr_al .sym )
1122
+ name = addr_al .sym -> name ;
1123
+ else
1124
+ * ip = sample -> addr ;
1125
+ } else {
1126
+ * ip = sample -> addr ;
1127
+ }
1128
+ } else if (sample -> flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END )) {
1129
+ if (al -> sym )
1130
+ name = al -> sym -> name ;
1131
+ else
1132
+ * ip = sample -> ip ;
1133
+ }
1134
+ return name ;
1135
+ }
1136
+
1108
1137
static int perf_sample__fprintf_callindent (struct perf_sample * sample ,
1109
1138
struct perf_evsel * evsel ,
1110
1139
struct thread * thread ,
1111
1140
struct addr_location * al , FILE * fp )
1112
1141
{
1113
1142
struct perf_event_attr * attr = & evsel -> attr ;
1114
1143
size_t depth = thread_stack__depth (thread );
1115
- struct addr_location addr_al ;
1116
1144
const char * name = NULL ;
1117
1145
static int spacing ;
1118
1146
int len = 0 ;
@@ -1126,22 +1154,7 @@ static int perf_sample__fprintf_callindent(struct perf_sample *sample,
1126
1154
if (thread -> ts && sample -> flags & PERF_IP_FLAG_RETURN )
1127
1155
depth += 1 ;
1128
1156
1129
- if (sample -> flags & (PERF_IP_FLAG_CALL | PERF_IP_FLAG_TRACE_BEGIN )) {
1130
- if (sample_addr_correlates_sym (attr )) {
1131
- thread__resolve (thread , & addr_al , sample );
1132
- if (addr_al .sym )
1133
- name = addr_al .sym -> name ;
1134
- else
1135
- ip = sample -> addr ;
1136
- } else {
1137
- ip = sample -> addr ;
1138
- }
1139
- } else if (sample -> flags & (PERF_IP_FLAG_RETURN | PERF_IP_FLAG_TRACE_END )) {
1140
- if (al -> sym )
1141
- name = al -> sym -> name ;
1142
- else
1143
- ip = sample -> ip ;
1144
- }
1157
+ name = resolve_branch_sym (sample , evsel , thread , al , & ip );
1145
1158
1146
1159
if (PRINT_FIELD (DSO ) && !(PRINT_FIELD (IP ) || PRINT_FIELD (ADDR ))) {
1147
1160
dlen += fprintf (fp , "(" );
@@ -1647,6 +1660,47 @@ static void perf_sample__fprint_metric(struct perf_script *script,
1647
1660
}
1648
1661
}
1649
1662
1663
+ static bool show_event (struct perf_sample * sample ,
1664
+ struct perf_evsel * evsel ,
1665
+ struct thread * thread ,
1666
+ struct addr_location * al )
1667
+ {
1668
+ int depth = thread_stack__depth (thread );
1669
+
1670
+ if (!symbol_conf .graph_function )
1671
+ return true;
1672
+
1673
+ if (thread -> filter ) {
1674
+ if (depth <= thread -> filter_entry_depth ) {
1675
+ thread -> filter = false;
1676
+ return false;
1677
+ }
1678
+ return true;
1679
+ } else {
1680
+ const char * s = symbol_conf .graph_function ;
1681
+ u64 ip ;
1682
+ const char * name = resolve_branch_sym (sample , evsel , thread , al ,
1683
+ & ip );
1684
+ unsigned nlen ;
1685
+
1686
+ if (!name )
1687
+ return false;
1688
+ nlen = strlen (name );
1689
+ while (* s ) {
1690
+ unsigned len = strcspn (s , "," );
1691
+ if (nlen == len && !strncmp (name , s , len )) {
1692
+ thread -> filter = true;
1693
+ thread -> filter_entry_depth = depth ;
1694
+ return true;
1695
+ }
1696
+ s += len ;
1697
+ if (* s == ',' )
1698
+ s ++ ;
1699
+ }
1700
+ return false;
1701
+ }
1702
+ }
1703
+
1650
1704
static void process_event (struct perf_script * script ,
1651
1705
struct perf_sample * sample , struct perf_evsel * evsel ,
1652
1706
struct addr_location * al ,
@@ -1661,6 +1715,9 @@ static void process_event(struct perf_script *script,
1661
1715
if (output [type ].fields == 0 )
1662
1716
return ;
1663
1717
1718
+ if (!show_event (sample , evsel , thread , al ))
1719
+ return ;
1720
+
1664
1721
++ es -> samples ;
1665
1722
1666
1723
perf_sample__fprintf_start (sample , thread , evsel ,
@@ -3237,6 +3294,8 @@ int cmd_script(int argc, const char **argv)
3237
3294
"Decode calls from from itrace" , parse_call_trace ),
3238
3295
OPT_CALLBACK_OPTARG (0 , "call-ret-trace" , & itrace_synth_opts , NULL , NULL ,
3239
3296
"Decode calls and returns from itrace" , parse_callret_trace ),
3297
+ OPT_STRING (0 , "graph-function" , & symbol_conf .graph_function , "symbol[,symbol...]" ,
3298
+ "Only print symbols and callees with --call-trace/--call-ret-trace" ),
3240
3299
OPT_STRING (0 , "stop-bt" , & symbol_conf .bt_stop_list_str , "symbol[,symbol...]" ,
3241
3300
"Stop display of callgraph at these symbols" ),
3242
3301
OPT_STRING ('C' , "cpu" , & cpu_list , "cpu" , "list of cpus to profile" ),
@@ -3494,7 +3553,8 @@ int cmd_script(int argc, const char **argv)
3494
3553
script .session = session ;
3495
3554
script__setup_sample_type (& script );
3496
3555
3497
- if (output [PERF_TYPE_HARDWARE ].fields & PERF_OUTPUT_CALLINDENT )
3556
+ if ((output [PERF_TYPE_HARDWARE ].fields & PERF_OUTPUT_CALLINDENT ) ||
3557
+ symbol_conf .graph_function )
3498
3558
itrace_synth_opts .thread_stack = true;
3499
3559
3500
3560
session -> itrace_synth_opts = & itrace_synth_opts ;
0 commit comments