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