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