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