1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun #include <inttypes.h>
3*4882a593Smuzhiyun #include <stdio.h>
4*4882a593Smuzhiyun #include <stdbool.h>
5*4882a593Smuzhiyun #include <traceevent/event-parse.h>
6*4882a593Smuzhiyun #include "evsel.h"
7*4882a593Smuzhiyun #include "util/evsel_fprintf.h"
8*4882a593Smuzhiyun #include "util/event.h"
9*4882a593Smuzhiyun #include "callchain.h"
10*4882a593Smuzhiyun #include "map.h"
11*4882a593Smuzhiyun #include "strlist.h"
12*4882a593Smuzhiyun #include "symbol.h"
13*4882a593Smuzhiyun #include "srcline.h"
14*4882a593Smuzhiyun
comma_fprintf(FILE * fp,bool * first,const char * fmt,...)15*4882a593Smuzhiyun static int comma_fprintf(FILE *fp, bool *first, const char *fmt, ...)
16*4882a593Smuzhiyun {
17*4882a593Smuzhiyun va_list args;
18*4882a593Smuzhiyun int ret = 0;
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun if (!*first) {
21*4882a593Smuzhiyun ret += fprintf(fp, ",");
22*4882a593Smuzhiyun } else {
23*4882a593Smuzhiyun ret += fprintf(fp, ":");
24*4882a593Smuzhiyun *first = false;
25*4882a593Smuzhiyun }
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun va_start(args, fmt);
28*4882a593Smuzhiyun ret += vfprintf(fp, fmt, args);
29*4882a593Smuzhiyun va_end(args);
30*4882a593Smuzhiyun return ret;
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun
__print_attr__fprintf(FILE * fp,const char * name,const char * val,void * priv)33*4882a593Smuzhiyun static int __print_attr__fprintf(FILE *fp, const char *name, const char *val, void *priv)
34*4882a593Smuzhiyun {
35*4882a593Smuzhiyun return comma_fprintf(fp, (bool *)priv, " %s: %s", name, val);
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun
evsel__fprintf(struct evsel * evsel,struct perf_attr_details * details,FILE * fp)38*4882a593Smuzhiyun int evsel__fprintf(struct evsel *evsel, struct perf_attr_details *details, FILE *fp)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun bool first = true;
41*4882a593Smuzhiyun int printed = 0;
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun if (details->event_group) {
44*4882a593Smuzhiyun struct evsel *pos;
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun if (!evsel__is_group_leader(evsel))
47*4882a593Smuzhiyun return 0;
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun if (evsel->core.nr_members > 1)
50*4882a593Smuzhiyun printed += fprintf(fp, "%s{", evsel->group_name ?: "");
51*4882a593Smuzhiyun
52*4882a593Smuzhiyun printed += fprintf(fp, "%s", evsel__name(evsel));
53*4882a593Smuzhiyun for_each_group_member(pos, evsel)
54*4882a593Smuzhiyun printed += fprintf(fp, ",%s", evsel__name(pos));
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun if (evsel->core.nr_members > 1)
57*4882a593Smuzhiyun printed += fprintf(fp, "}");
58*4882a593Smuzhiyun goto out;
59*4882a593Smuzhiyun }
60*4882a593Smuzhiyun
61*4882a593Smuzhiyun printed += fprintf(fp, "%s", evsel__name(evsel));
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun if (details->verbose) {
64*4882a593Smuzhiyun printed += perf_event_attr__fprintf(fp, &evsel->core.attr,
65*4882a593Smuzhiyun __print_attr__fprintf, &first);
66*4882a593Smuzhiyun } else if (details->freq) {
67*4882a593Smuzhiyun const char *term = "sample_freq";
68*4882a593Smuzhiyun
69*4882a593Smuzhiyun if (!evsel->core.attr.freq)
70*4882a593Smuzhiyun term = "sample_period";
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun printed += comma_fprintf(fp, &first, " %s=%" PRIu64,
73*4882a593Smuzhiyun term, (u64)evsel->core.attr.sample_freq);
74*4882a593Smuzhiyun }
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun if (details->trace_fields) {
77*4882a593Smuzhiyun struct tep_format_field *field;
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun if (evsel->core.attr.type != PERF_TYPE_TRACEPOINT) {
80*4882a593Smuzhiyun printed += comma_fprintf(fp, &first, " (not a tracepoint)");
81*4882a593Smuzhiyun goto out;
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun field = evsel->tp_format->format.fields;
85*4882a593Smuzhiyun if (field == NULL) {
86*4882a593Smuzhiyun printed += comma_fprintf(fp, &first, " (no trace field)");
87*4882a593Smuzhiyun goto out;
88*4882a593Smuzhiyun }
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun printed += comma_fprintf(fp, &first, " trace_fields: %s", field->name);
91*4882a593Smuzhiyun
92*4882a593Smuzhiyun field = field->next;
93*4882a593Smuzhiyun while (field) {
94*4882a593Smuzhiyun printed += comma_fprintf(fp, &first, "%s", field->name);
95*4882a593Smuzhiyun field = field->next;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun out:
99*4882a593Smuzhiyun fputc('\n', fp);
100*4882a593Smuzhiyun return ++printed;
101*4882a593Smuzhiyun }
102*4882a593Smuzhiyun
sample__fprintf_callchain(struct perf_sample * sample,int left_alignment,unsigned int print_opts,struct callchain_cursor * cursor,struct strlist * bt_stop_list,FILE * fp)103*4882a593Smuzhiyun int sample__fprintf_callchain(struct perf_sample *sample, int left_alignment,
104*4882a593Smuzhiyun unsigned int print_opts, struct callchain_cursor *cursor,
105*4882a593Smuzhiyun struct strlist *bt_stop_list, FILE *fp)
106*4882a593Smuzhiyun {
107*4882a593Smuzhiyun int printed = 0;
108*4882a593Smuzhiyun struct callchain_cursor_node *node;
109*4882a593Smuzhiyun int print_ip = print_opts & EVSEL__PRINT_IP;
110*4882a593Smuzhiyun int print_sym = print_opts & EVSEL__PRINT_SYM;
111*4882a593Smuzhiyun int print_dso = print_opts & EVSEL__PRINT_DSO;
112*4882a593Smuzhiyun int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;
113*4882a593Smuzhiyun int print_oneline = print_opts & EVSEL__PRINT_ONELINE;
114*4882a593Smuzhiyun int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
115*4882a593Smuzhiyun int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
116*4882a593Smuzhiyun int print_arrow = print_opts & EVSEL__PRINT_CALLCHAIN_ARROW;
117*4882a593Smuzhiyun int print_skip_ignored = print_opts & EVSEL__PRINT_SKIP_IGNORED;
118*4882a593Smuzhiyun char s = print_oneline ? ' ' : '\t';
119*4882a593Smuzhiyun bool first = true;
120*4882a593Smuzhiyun
121*4882a593Smuzhiyun if (sample->callchain) {
122*4882a593Smuzhiyun struct addr_location node_al;
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun callchain_cursor_commit(cursor);
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun while (1) {
127*4882a593Smuzhiyun struct symbol *sym;
128*4882a593Smuzhiyun struct map *map;
129*4882a593Smuzhiyun u64 addr = 0;
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun node = callchain_cursor_current(cursor);
132*4882a593Smuzhiyun if (!node)
133*4882a593Smuzhiyun break;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun sym = node->ms.sym;
136*4882a593Smuzhiyun map = node->ms.map;
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun if (sym && sym->ignore && print_skip_ignored)
139*4882a593Smuzhiyun goto next;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun if (print_arrow && !first)
144*4882a593Smuzhiyun printed += fprintf(fp, " <-");
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun if (print_ip)
147*4882a593Smuzhiyun printed += fprintf(fp, "%c%16" PRIx64, s, node->ip);
148*4882a593Smuzhiyun
149*4882a593Smuzhiyun if (map)
150*4882a593Smuzhiyun addr = map->map_ip(map, node->ip);
151*4882a593Smuzhiyun
152*4882a593Smuzhiyun if (print_sym) {
153*4882a593Smuzhiyun printed += fprintf(fp, " ");
154*4882a593Smuzhiyun node_al.addr = addr;
155*4882a593Smuzhiyun node_al.map = map;
156*4882a593Smuzhiyun
157*4882a593Smuzhiyun if (print_symoffset) {
158*4882a593Smuzhiyun printed += __symbol__fprintf_symname_offs(sym, &node_al,
159*4882a593Smuzhiyun print_unknown_as_addr,
160*4882a593Smuzhiyun true, fp);
161*4882a593Smuzhiyun } else {
162*4882a593Smuzhiyun printed += __symbol__fprintf_symname(sym, &node_al,
163*4882a593Smuzhiyun print_unknown_as_addr, fp);
164*4882a593Smuzhiyun }
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun if (print_dso && (!sym || !sym->inlined)) {
168*4882a593Smuzhiyun printed += fprintf(fp, " (");
169*4882a593Smuzhiyun printed += map__fprintf_dsoname(map, fp);
170*4882a593Smuzhiyun printed += fprintf(fp, ")");
171*4882a593Smuzhiyun }
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun if (print_srcline)
174*4882a593Smuzhiyun printed += map__fprintf_srcline(map, addr, "\n ", fp);
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun if (sym && sym->inlined)
177*4882a593Smuzhiyun printed += fprintf(fp, " (inlined)");
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun if (!print_oneline)
180*4882a593Smuzhiyun printed += fprintf(fp, "\n");
181*4882a593Smuzhiyun
182*4882a593Smuzhiyun /* Add srccode here too? */
183*4882a593Smuzhiyun if (bt_stop_list && sym &&
184*4882a593Smuzhiyun strlist__has_entry(bt_stop_list, sym->name)) {
185*4882a593Smuzhiyun break;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun first = false;
189*4882a593Smuzhiyun next:
190*4882a593Smuzhiyun callchain_cursor_advance(cursor);
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun }
193*4882a593Smuzhiyun
194*4882a593Smuzhiyun return printed;
195*4882a593Smuzhiyun }
196*4882a593Smuzhiyun
sample__fprintf_sym(struct perf_sample * sample,struct addr_location * al,int left_alignment,unsigned int print_opts,struct callchain_cursor * cursor,struct strlist * bt_stop_list,FILE * fp)197*4882a593Smuzhiyun int sample__fprintf_sym(struct perf_sample *sample, struct addr_location *al,
198*4882a593Smuzhiyun int left_alignment, unsigned int print_opts,
199*4882a593Smuzhiyun struct callchain_cursor *cursor, struct strlist *bt_stop_list, FILE *fp)
200*4882a593Smuzhiyun {
201*4882a593Smuzhiyun int printed = 0;
202*4882a593Smuzhiyun int print_ip = print_opts & EVSEL__PRINT_IP;
203*4882a593Smuzhiyun int print_sym = print_opts & EVSEL__PRINT_SYM;
204*4882a593Smuzhiyun int print_dso = print_opts & EVSEL__PRINT_DSO;
205*4882a593Smuzhiyun int print_symoffset = print_opts & EVSEL__PRINT_SYMOFFSET;
206*4882a593Smuzhiyun int print_srcline = print_opts & EVSEL__PRINT_SRCLINE;
207*4882a593Smuzhiyun int print_unknown_as_addr = print_opts & EVSEL__PRINT_UNKNOWN_AS_ADDR;
208*4882a593Smuzhiyun
209*4882a593Smuzhiyun if (cursor != NULL) {
210*4882a593Smuzhiyun printed += sample__fprintf_callchain(sample, left_alignment, print_opts,
211*4882a593Smuzhiyun cursor, bt_stop_list, fp);
212*4882a593Smuzhiyun } else {
213*4882a593Smuzhiyun printed += fprintf(fp, "%-*.*s", left_alignment, left_alignment, " ");
214*4882a593Smuzhiyun
215*4882a593Smuzhiyun if (print_ip)
216*4882a593Smuzhiyun printed += fprintf(fp, "%16" PRIx64, sample->ip);
217*4882a593Smuzhiyun
218*4882a593Smuzhiyun if (print_sym) {
219*4882a593Smuzhiyun printed += fprintf(fp, " ");
220*4882a593Smuzhiyun if (print_symoffset) {
221*4882a593Smuzhiyun printed += __symbol__fprintf_symname_offs(al->sym, al,
222*4882a593Smuzhiyun print_unknown_as_addr,
223*4882a593Smuzhiyun true, fp);
224*4882a593Smuzhiyun } else {
225*4882a593Smuzhiyun printed += __symbol__fprintf_symname(al->sym, al,
226*4882a593Smuzhiyun print_unknown_as_addr, fp);
227*4882a593Smuzhiyun }
228*4882a593Smuzhiyun }
229*4882a593Smuzhiyun
230*4882a593Smuzhiyun if (print_dso) {
231*4882a593Smuzhiyun printed += fprintf(fp, " (");
232*4882a593Smuzhiyun printed += map__fprintf_dsoname(al->map, fp);
233*4882a593Smuzhiyun printed += fprintf(fp, ")");
234*4882a593Smuzhiyun }
235*4882a593Smuzhiyun
236*4882a593Smuzhiyun if (print_srcline)
237*4882a593Smuzhiyun printed += map__fprintf_srcline(al->map, al->addr, "\n ", fp);
238*4882a593Smuzhiyun }
239*4882a593Smuzhiyun
240*4882a593Smuzhiyun return printed;
241*4882a593Smuzhiyun }
242