aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2015-02-20 17:17:02 -0500
committerArnaldo Carvalho de Melo <acme@redhat.com>2015-03-13 06:47:49 -0400
commit69364727be2f3dc71a046771965c3c9d5ccce699 (patch)
tree08b8a8c0a8af78e75ea4b6aed7d13c4efbf23ffa /tools
parent65f46e0214c64198a0266c37181a7776e16b7e53 (diff)
perf data: Add tracepoint events fields CTF conversion support
Adding support to convert tracepoint event fields into CTF event fields. We parse each tracepoint event for CTF conversion and add tracepoint fields as regular CTF event fields, so they appear in babeltrace output like: $ babeltrace ./ctf-data/ ... [09:02:00.950703057] (+?.?????????) sched:sched_stat_runtime: { }, { perf_ip = ... SNIP ... common_type = 298, common_flags = 1, \ common_preempt_count = 0, common_pid = 31813, comm = "perf", pid = 31813, runtime = 458800, vruntime = 52059858071 } ... Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Cc: David Ahern <dsahern@gmail.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Jeremie Galarneau <jgalar@efficios.com> Cc: Namhyung Kim <namhyung@gmail.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Tom Zanussi <tzanussi@gmail.com> Cc: Wang Nan <wangnan0@huawei.com> Link: http://lkml.kernel.org/r/1424470628-5969-6-git-send-email-jolsa@kernel.org Signed-off-by: Jiri Olsa <jolsa@kernel.org> Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/util/data-convert-bt.c242
1 files changed, 242 insertions, 0 deletions
diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c
index 1afd381b2346..c6d62268cc2a 100644
--- a/tools/perf/util/data-convert-bt.c
+++ b/tools/perf/util/data-convert-bt.c
@@ -126,6 +126,177 @@ FUNC_VALUE_SET(s64)
126FUNC_VALUE_SET(u64) 126FUNC_VALUE_SET(u64)
127__FUNC_VALUE_SET(u64_hex, u64) 127__FUNC_VALUE_SET(u64_hex, u64)
128 128
129static struct bt_ctf_field_type*
130get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
131{
132 unsigned long flags = field->flags;
133
134 if (flags & FIELD_IS_STRING)
135 return cw->data.string;
136
137 if (!(flags & FIELD_IS_SIGNED)) {
138 /* unsigned long are mostly pointers */
139 if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
140 return cw->data.u64_hex;
141 }
142
143 if (flags & FIELD_IS_SIGNED) {
144 if (field->size == 8)
145 return cw->data.s64;
146 else
147 return cw->data.s32;
148 }
149
150 if (field->size == 8)
151 return cw->data.u64;
152 else
153 return cw->data.u32;
154}
155
156static int add_tracepoint_field_value(struct ctf_writer *cw,
157 struct bt_ctf_event_class *event_class,
158 struct bt_ctf_event *event,
159 struct perf_sample *sample,
160 struct format_field *fmtf)
161{
162 struct bt_ctf_field_type *type;
163 struct bt_ctf_field *array_field;
164 struct bt_ctf_field *field;
165 const char *name = fmtf->name;
166 void *data = sample->raw_data;
167 unsigned long long value_int;
168 unsigned long flags = fmtf->flags;
169 unsigned int n_items;
170 unsigned int i;
171 unsigned int offset;
172 unsigned int len;
173 int ret;
174
175 offset = fmtf->offset;
176 len = fmtf->size;
177 if (flags & FIELD_IS_STRING)
178 flags &= ~FIELD_IS_ARRAY;
179
180 if (flags & FIELD_IS_DYNAMIC) {
181 unsigned long long tmp_val;
182
183 tmp_val = pevent_read_number(fmtf->event->pevent,
184 data + offset, len);
185 offset = tmp_val;
186 len = offset >> 16;
187 offset &= 0xffff;
188 }
189
190 if (flags & FIELD_IS_ARRAY) {
191
192 type = bt_ctf_event_class_get_field_by_name(
193 event_class, name);
194 array_field = bt_ctf_field_create(type);
195 bt_ctf_field_type_put(type);
196 if (!array_field) {
197 pr_err("Failed to create array type %s\n", name);
198 return -1;
199 }
200
201 len = fmtf->size / fmtf->arraylen;
202 n_items = fmtf->arraylen;
203 } else {
204 n_items = 1;
205 array_field = NULL;
206 }
207
208 type = get_tracepoint_field_type(cw, fmtf);
209
210 for (i = 0; i < n_items; i++) {
211 if (!(flags & FIELD_IS_STRING))
212 value_int = pevent_read_number(
213 fmtf->event->pevent,
214 data + offset + i * len, len);
215
216 if (flags & FIELD_IS_ARRAY)
217 field = bt_ctf_field_array_get_field(array_field, i);
218 else
219 field = bt_ctf_field_create(type);
220
221 if (!field) {
222 pr_err("failed to create a field %s\n", name);
223 return -1;
224 }
225
226 if (flags & FIELD_IS_STRING)
227 ret = bt_ctf_field_string_set_value(field,
228 data + offset + i * len);
229 else if (!(flags & FIELD_IS_SIGNED))
230 ret = bt_ctf_field_unsigned_integer_set_value(
231 field, value_int);
232 else
233 ret = bt_ctf_field_signed_integer_set_value(
234 field, value_int);
235 if (ret) {
236 pr_err("failed to set file value %s\n", name);
237 goto err_put_field;
238 }
239 if (!(flags & FIELD_IS_ARRAY)) {
240 ret = bt_ctf_event_set_payload(event, name, field);
241 if (ret) {
242 pr_err("failed to set payload %s\n", name);
243 goto err_put_field;
244 }
245 }
246 bt_ctf_field_put(field);
247 }
248 if (flags & FIELD_IS_ARRAY) {
249 ret = bt_ctf_event_set_payload(event, name, array_field);
250 if (ret) {
251 pr_err("Failed add payload array %s\n", name);
252 return -1;
253 }
254 bt_ctf_field_put(array_field);
255 }
256 return 0;
257
258err_put_field:
259 bt_ctf_field_put(field);
260 return -1;
261}
262
263static int add_tracepoint_fields_values(struct ctf_writer *cw,
264 struct bt_ctf_event_class *event_class,
265 struct bt_ctf_event *event,
266 struct format_field *fields,
267 struct perf_sample *sample)
268{
269 struct format_field *field;
270 int ret;
271
272 for (field = fields; field; field = field->next) {
273 ret = add_tracepoint_field_value(cw, event_class, event, sample,
274 field);
275 if (ret)
276 return -1;
277 }
278 return 0;
279}
280
281static int add_tracepoint_values(struct ctf_writer *cw,
282 struct bt_ctf_event_class *event_class,
283 struct bt_ctf_event *event,
284 struct perf_evsel *evsel,
285 struct perf_sample *sample)
286{
287 struct format_field *common_fields = evsel->tp_format->format.common_fields;
288 struct format_field *fields = evsel->tp_format->format.fields;
289 int ret;
290
291 ret = add_tracepoint_fields_values(cw, event_class, event,
292 common_fields, sample);
293 if (!ret)
294 ret = add_tracepoint_fields_values(cw, event_class, event,
295 fields, sample);
296
297 return ret;
298}
299
129static int add_generic_values(struct ctf_writer *cw, 300static int add_generic_values(struct ctf_writer *cw,
130 struct bt_ctf_event *event, 301 struct bt_ctf_event *event,
131 struct perf_evsel *evsel, 302 struct perf_evsel *evsel,
@@ -246,11 +417,76 @@ static int process_sample_event(struct perf_tool *tool,
246 if (ret) 417 if (ret)
247 return -1; 418 return -1;
248 419
420 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
421 ret = add_tracepoint_values(cw, event_class, event,
422 evsel, sample);
423 if (ret)
424 return -1;
425 }
426
249 bt_ctf_stream_append_event(cw->stream, event); 427 bt_ctf_stream_append_event(cw->stream, event);
250 bt_ctf_event_put(event); 428 bt_ctf_event_put(event);
251 return 0; 429 return 0;
252} 430}
253 431
432static int add_tracepoint_fields_types(struct ctf_writer *cw,
433 struct format_field *fields,
434 struct bt_ctf_event_class *event_class)
435{
436 struct format_field *field;
437 int ret;
438
439 for (field = fields; field; field = field->next) {
440 struct bt_ctf_field_type *type;
441 unsigned long flags = field->flags;
442
443 pr2(" field '%s'\n", field->name);
444
445 type = get_tracepoint_field_type(cw, field);
446 if (!type)
447 return -1;
448
449 /*
450 * A string is an array of chars. For this we use the string
451 * type and don't care that it is an array. What we don't
452 * support is an array of strings.
453 */
454 if (flags & FIELD_IS_STRING)
455 flags &= ~FIELD_IS_ARRAY;
456
457 if (flags & FIELD_IS_ARRAY)
458 type = bt_ctf_field_type_array_create(type, field->arraylen);
459
460 ret = bt_ctf_event_class_add_field(event_class, type,
461 field->name);
462
463 if (flags & FIELD_IS_ARRAY)
464 bt_ctf_field_type_put(type);
465
466 if (ret) {
467 pr_err("Failed to add field '%s\n", field->name);
468 return -1;
469 }
470 }
471
472 return 0;
473}
474
475static int add_tracepoint_types(struct ctf_writer *cw,
476 struct perf_evsel *evsel,
477 struct bt_ctf_event_class *class)
478{
479 struct format_field *common_fields = evsel->tp_format->format.common_fields;
480 struct format_field *fields = evsel->tp_format->format.fields;
481 int ret;
482
483 ret = add_tracepoint_fields_types(cw, common_fields, class);
484 if (!ret)
485 ret = add_tracepoint_fields_types(cw, fields, class);
486
487 return ret;
488}
489
254static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel, 490static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
255 struct bt_ctf_event_class *event_class) 491 struct bt_ctf_event_class *event_class)
256{ 492{
@@ -328,6 +564,12 @@ static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
328 if (ret) 564 if (ret)
329 goto err; 565 goto err;
330 566
567 if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
568 ret = add_tracepoint_types(cw, evsel, event_class);
569 if (ret)
570 goto err;
571 }
572
331 ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class); 573 ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
332 if (ret) { 574 if (ret) {
333 pr("Failed to add event class into stream.\n"); 575 pr("Failed to add event class into stream.\n");