[PATCH 5/8] perf data: Add tracepoint events fields CTF conversion support
From: Sebastian Andrzej Siewior 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 } ... Cc: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Frederic Weisbecker Cc: Jeremie Galarneau Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Sebastian Andrzej Siewior Cc: Tom Zanussi Signed-off-by: Jiri Olsa Signed-off-by: Sebastian Andrzej Siewior --- tools/perf/util/data-convert-bt.c | 242 ++ 1 file changed, 242 insertions(+) diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index e372e03ff480..6fa5c3ef336b 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) FUNC_VALUE_SET(u64) __FUNC_VALUE_SET(u64_hex, u64) +static struct bt_ctf_field_type* +get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) +{ + unsigned long flags = field->flags; + + if (flags & FIELD_IS_STRING) + return cw->data.string; + + if (!(flags & FIELD_IS_SIGNED)) { + /* unsigned long are mostly pointers */ + if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER) + return cw->data.u64_hex; + } + + if (flags & FIELD_IS_SIGNED) { + if (field->size == 8) + return cw->data.s64; + else + return cw->data.s32; + } + + if (field->size == 8) + return cw->data.u64; + else + return cw->data.u32; +} + +static int add_tracepoint_field_value(struct ctf_writer *cw, + struct bt_ctf_event_class *event_class, + struct bt_ctf_event *event, + struct perf_sample *sample, + struct format_field *fmtf) +{ + struct bt_ctf_field_type *type; + struct bt_ctf_field *array_field; + struct bt_ctf_field *field; + const char *name = fmtf->name; + void *data = sample->raw_data; + unsigned long long value_int; + unsigned long flags = fmtf->flags; + unsigned int n_items; + unsigned int i; + unsigned int offset; + unsigned int len; + int ret; + + offset = fmtf->offset; + len = fmtf->size; + if (flags & FIELD_IS_STRING) + flags &= ~FIELD_IS_ARRAY; + + if (flags & FIELD_IS_DYNAMIC) { + unsigned long long tmp_val; + + tmp_val = pevent_read_number(fmtf->event->pevent, + data + offset, len); + offset = tmp_val; + len = offset >> 16; + offset &= 0x; + } + + if (flags & FIELD_IS_ARRAY) { + + type = bt_ctf_event_class_get_field_by_name( + event_class, name); + array_field = bt_ctf_field_create(type); + bt_ctf_field_type_put(type); + if (!array_field) { + pr_err("Failed to create array type %s\n", name); + return -1; + } + + len = fmtf->size / fmtf->arraylen; + n_items = fmtf->arraylen; + } else { + n_items = 1; + array_field = NULL; + } + + type = get_tracepoint_field_type(cw, fmtf); + + for (i = 0; i < n_items; i++) { + if (!(flags & FIELD_IS_STRING)) + value_int = pevent_read_number( + fmtf->event->pevent, + data + offset + i * len, len); + + if (flags & FIELD_IS_ARRAY) + field = bt_ctf_field_array_get_field(array_field, i); + else + field = bt_ctf_field_create(type); + + if (!field) { + pr_err("failed to create a field %s\n", name); + return -1; + } + + if (flags & FIELD_IS_STRING) + ret = bt_ctf_field_string_set_value(field, + data + offset + i * len); + else if (!(flags & FIELD_IS_SIGNED)) + ret = bt_ctf_field_unsigned_integer_set_value( + field, value_int); + else + ret =
[PATCH 5/8] perf data: Add tracepoint events fields CTF conversion support
From: Sebastian Andrzej Siewior bige...@linutronix.de 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 } ... Cc: Arnaldo Carvalho de Melo a...@redhat.com Cc: David Ahern dsah...@gmail.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Jeremie Galarneau jga...@efficios.com Cc: Jiri Olsa jo...@kernel.org Cc: Namhyung Kim namhy...@gmail.com Cc: Paul Mackerras pau...@samba.org Cc: Peter Zijlstra pet...@infradead.org Cc: Sebastian Andrzej Siewior bige...@linutronix.de Cc: Tom Zanussi tzanu...@gmail.com Signed-off-by: Jiri Olsa jo...@kernel.org Signed-off-by: Sebastian Andrzej Siewior bige...@linutronix.de --- tools/perf/util/data-convert-bt.c | 242 ++ 1 file changed, 242 insertions(+) diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index e372e03ff480..6fa5c3ef336b 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) FUNC_VALUE_SET(u64) __FUNC_VALUE_SET(u64_hex, u64) +static struct bt_ctf_field_type* +get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) +{ + unsigned long flags = field-flags; + + if (flags FIELD_IS_STRING) + return cw-data.string; + + if (!(flags FIELD_IS_SIGNED)) { + /* unsigned long are mostly pointers */ + if (flags FIELD_IS_LONG || flags FIELD_IS_POINTER) + return cw-data.u64_hex; + } + + if (flags FIELD_IS_SIGNED) { + if (field-size == 8) + return cw-data.s64; + else + return cw-data.s32; + } + + if (field-size == 8) + return cw-data.u64; + else + return cw-data.u32; +} + +static int add_tracepoint_field_value(struct ctf_writer *cw, + struct bt_ctf_event_class *event_class, + struct bt_ctf_event *event, + struct perf_sample *sample, + struct format_field *fmtf) +{ + struct bt_ctf_field_type *type; + struct bt_ctf_field *array_field; + struct bt_ctf_field *field; + const char *name = fmtf-name; + void *data = sample-raw_data; + unsigned long long value_int; + unsigned long flags = fmtf-flags; + unsigned int n_items; + unsigned int i; + unsigned int offset; + unsigned int len; + int ret; + + offset = fmtf-offset; + len = fmtf-size; + if (flags FIELD_IS_STRING) + flags = ~FIELD_IS_ARRAY; + + if (flags FIELD_IS_DYNAMIC) { + unsigned long long tmp_val; + + tmp_val = pevent_read_number(fmtf-event-pevent, + data + offset, len); + offset = tmp_val; + len = offset 16; + offset = 0x; + } + + if (flags FIELD_IS_ARRAY) { + + type = bt_ctf_event_class_get_field_by_name( + event_class, name); + array_field = bt_ctf_field_create(type); + bt_ctf_field_type_put(type); + if (!array_field) { + pr_err(Failed to create array type %s\n, name); + return -1; + } + + len = fmtf-size / fmtf-arraylen; + n_items = fmtf-arraylen; + } else { + n_items = 1; + array_field = NULL; + } + + type = get_tracepoint_field_type(cw, fmtf); + + for (i = 0; i n_items; i++) { + if (!(flags FIELD_IS_STRING)) + value_int = pevent_read_number( + fmtf-event-pevent, + data + offset + i * len, len); + + if (flags FIELD_IS_ARRAY) + field = bt_ctf_field_array_get_field(array_field, i); + else + field = bt_ctf_field_create(type); + + if (!field) { + pr_err(failed to create a field %s\n, name); + return -1; + } + + if (flags FIELD_IS_STRING) + ret = bt_ctf_field_string_set_value(field, + data + offset + i * len); + else if (!(flags FIELD_IS_SIGNED)) +
[PATCH 5/8] perf data: Add tracepoint events fields CTF conversion support
From: Sebastian Andrzej Siewior 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 } ... Cc: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Frederic Weisbecker Cc: Jeremie Galarneau Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Sebastian Andrzej Siewior Cc: Tom Zanussi Signed-off-by: Jiri Olsa Signed-off-by: Sebastian Andrzej Siewior --- tools/perf/util/data-convert-bt.c | 242 ++ 1 file changed, 242 insertions(+) diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index e372e03ff480..6fa5c3ef336b 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) FUNC_VALUE_SET(u64) __FUNC_VALUE_SET(u64_hex, u64) +static struct bt_ctf_field_type* +get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) +{ + unsigned long flags = field->flags; + + if (flags & FIELD_IS_STRING) + return cw->data.string; + + if (!(flags & FIELD_IS_SIGNED)) { + /* unsigned long are mostly pointers */ + if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER) + return cw->data.u64_hex; + } + + if (flags & FIELD_IS_SIGNED) { + if (field->size == 8) + return cw->data.s64; + else + return cw->data.s32; + } + + if (field->size == 8) + return cw->data.u64; + else + return cw->data.u32; +} + +static int add_tracepoint_field_value(struct ctf_writer *cw, + struct bt_ctf_event_class *event_class, + struct bt_ctf_event *event, + struct perf_sample *sample, + struct format_field *fmtf) +{ + struct bt_ctf_field_type *type; + struct bt_ctf_field *array_field; + struct bt_ctf_field *field; + const char *name = fmtf->name; + void *data = sample->raw_data; + unsigned long long value_int; + unsigned long flags = fmtf->flags; + unsigned int n_items; + unsigned int i; + unsigned int offset; + unsigned int len; + int ret; + + offset = fmtf->offset; + len = fmtf->size; + if (flags & FIELD_IS_STRING) + flags &= ~FIELD_IS_ARRAY; + + if (flags & FIELD_IS_DYNAMIC) { + unsigned long long tmp_val; + + tmp_val = pevent_read_number(fmtf->event->pevent, + data + offset, len); + offset = tmp_val; + len = offset >> 16; + offset &= 0x; + } + + if (flags & FIELD_IS_ARRAY) { + + type = bt_ctf_event_class_get_field_by_name( + event_class, name); + array_field = bt_ctf_field_create(type); + bt_ctf_field_type_put(type); + if (!array_field) { + pr_err("Failed to create array type %s\n", name); + return -1; + } + + len = fmtf->size / fmtf->arraylen; + n_items = fmtf->arraylen; + } else { + n_items = 1; + array_field = NULL; + } + + type = get_tracepoint_field_type(cw, fmtf); + + for (i = 0; i < n_items; i++) { + if (!(flags & FIELD_IS_STRING)) + value_int = pevent_read_number( + fmtf->event->pevent, + data + offset + i * len, len); + + if (flags & FIELD_IS_ARRAY) + field = bt_ctf_field_array_get_field(array_field, i); + else + field = bt_ctf_field_create(type); + + if (!field) { + pr_err("failed to create a field %s\n", name); + return -1; + } + + if (flags & FIELD_IS_STRING) + ret = bt_ctf_field_string_set_value(field, + data + offset + i * len); + else if (!(flags & FIELD_IS_SIGNED)) + ret = bt_ctf_field_unsigned_integer_set_value( + field, value_int); + else + ret =
[PATCH 5/8] perf data: Add tracepoint events fields CTF conversion support
From: Sebastian Andrzej Siewior bige...@linutronix.de 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 } ... Cc: Arnaldo Carvalho de Melo a...@redhat.com Cc: David Ahern dsah...@gmail.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Jeremie Galarneau jga...@efficios.com Cc: Jiri Olsa jo...@kernel.org Cc: Namhyung Kim namhy...@gmail.com Cc: Paul Mackerras pau...@samba.org Cc: Peter Zijlstra pet...@infradead.org Cc: Sebastian Andrzej Siewior bige...@linutronix.de Cc: Tom Zanussi tzanu...@gmail.com Signed-off-by: Jiri Olsa jo...@kernel.org Signed-off-by: Sebastian Andrzej Siewior bige...@linutronix.de --- tools/perf/util/data-convert-bt.c | 242 ++ 1 file changed, 242 insertions(+) diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index e372e03ff480..6fa5c3ef336b 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) FUNC_VALUE_SET(u64) __FUNC_VALUE_SET(u64_hex, u64) +static struct bt_ctf_field_type* +get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) +{ + unsigned long flags = field-flags; + + if (flags FIELD_IS_STRING) + return cw-data.string; + + if (!(flags FIELD_IS_SIGNED)) { + /* unsigned long are mostly pointers */ + if (flags FIELD_IS_LONG || flags FIELD_IS_POINTER) + return cw-data.u64_hex; + } + + if (flags FIELD_IS_SIGNED) { + if (field-size == 8) + return cw-data.s64; + else + return cw-data.s32; + } + + if (field-size == 8) + return cw-data.u64; + else + return cw-data.u32; +} + +static int add_tracepoint_field_value(struct ctf_writer *cw, + struct bt_ctf_event_class *event_class, + struct bt_ctf_event *event, + struct perf_sample *sample, + struct format_field *fmtf) +{ + struct bt_ctf_field_type *type; + struct bt_ctf_field *array_field; + struct bt_ctf_field *field; + const char *name = fmtf-name; + void *data = sample-raw_data; + unsigned long long value_int; + unsigned long flags = fmtf-flags; + unsigned int n_items; + unsigned int i; + unsigned int offset; + unsigned int len; + int ret; + + offset = fmtf-offset; + len = fmtf-size; + if (flags FIELD_IS_STRING) + flags = ~FIELD_IS_ARRAY; + + if (flags FIELD_IS_DYNAMIC) { + unsigned long long tmp_val; + + tmp_val = pevent_read_number(fmtf-event-pevent, + data + offset, len); + offset = tmp_val; + len = offset 16; + offset = 0x; + } + + if (flags FIELD_IS_ARRAY) { + + type = bt_ctf_event_class_get_field_by_name( + event_class, name); + array_field = bt_ctf_field_create(type); + bt_ctf_field_type_put(type); + if (!array_field) { + pr_err(Failed to create array type %s\n, name); + return -1; + } + + len = fmtf-size / fmtf-arraylen; + n_items = fmtf-arraylen; + } else { + n_items = 1; + array_field = NULL; + } + + type = get_tracepoint_field_type(cw, fmtf); + + for (i = 0; i n_items; i++) { + if (!(flags FIELD_IS_STRING)) + value_int = pevent_read_number( + fmtf-event-pevent, + data + offset + i * len, len); + + if (flags FIELD_IS_ARRAY) + field = bt_ctf_field_array_get_field(array_field, i); + else + field = bt_ctf_field_create(type); + + if (!field) { + pr_err(failed to create a field %s\n, name); + return -1; + } + + if (flags FIELD_IS_STRING) + ret = bt_ctf_field_string_set_value(field, + data + offset + i * len); + else if (!(flags FIELD_IS_SIGNED)) +
[PATCH 5/8] perf data: Add tracepoint events fields CTF conversion support
From: Sebastian Andrzej Siewior 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 } ... Cc: Arnaldo Carvalho de Melo Cc: David Ahern Cc: Frederic Weisbecker Cc: Jeremie Galarneau Cc: Jiri Olsa Cc: Namhyung Kim Cc: Paul Mackerras Cc: Peter Zijlstra Cc: Sebastian Andrzej Siewior Cc: Tom Zanussi Signed-off-by: Jiri Olsa Signed-off-by: Sebastian Andrzej Siewior --- tools/perf/util/data-convert-bt.c | 242 ++ 1 file changed, 242 insertions(+) diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 3c39fae9c07e..cf1b16c89120 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) FUNC_VALUE_SET(u64) __FUNC_VALUE_SET(u64_hex, u64) +static struct bt_ctf_field_type* +get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) +{ + unsigned long flags = field->flags; + + if (flags & FIELD_IS_STRING) + return cw->data.string; + + if (!(flags & FIELD_IS_SIGNED)) { + /* unsigned long are mostly pointers */ + if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER) + return cw->data.u64_hex; + } + + if (flags & FIELD_IS_SIGNED) { + if (field->size == 8) + return cw->data.s64; + else + return cw->data.s32; + } + + if (field->size == 8) + return cw->data.u64; + else + return cw->data.u32; +} + +static int add_tracepoint_field_value(struct ctf_writer *cw, + struct bt_ctf_event_class *event_class, + struct bt_ctf_event *event, + struct perf_sample *sample, + struct format_field *fmtf) +{ + struct bt_ctf_field_type *type; + struct bt_ctf_field *array_field; + struct bt_ctf_field *field; + const char *name = fmtf->name; + void *data = sample->raw_data; + unsigned long long value_int; + unsigned long flags = fmtf->flags; + unsigned int n_items; + unsigned int i; + unsigned int offset; + unsigned int len; + int ret; + + offset = fmtf->offset; + len = fmtf->size; + if (flags & FIELD_IS_STRING) + flags &= ~FIELD_IS_ARRAY; + + if (flags & FIELD_IS_DYNAMIC) { + unsigned long long tmp_val; + + tmp_val = pevent_read_number(fmtf->event->pevent, + data + offset, len); + offset = tmp_val; + len = offset >> 16; + offset &= 0x; + } + + if (flags & FIELD_IS_ARRAY) { + + type = bt_ctf_event_class_get_field_by_name( + event_class, name); + array_field = bt_ctf_field_create(type); + bt_ctf_field_type_put(type); + if (!array_field) { + pr_err("Failed to create array type %s\n", name); + return -1; + } + + len = fmtf->size / fmtf->arraylen; + n_items = fmtf->arraylen; + } else { + n_items = 1; + array_field = NULL; + } + + type = get_tracepoint_field_type(cw, fmtf); + + for (i = 0; i < n_items; i++) { + if (!(flags & FIELD_IS_STRING)) + value_int = pevent_read_number( + fmtf->event->pevent, + data + offset + i * len, len); + + if (flags & FIELD_IS_ARRAY) + field = bt_ctf_field_array_get_field(array_field, i); + else + field = bt_ctf_field_create(type); + + if (!field) { + pr_err("failed to create a field %s\n", name); + return -1; + } + + if (flags & FIELD_IS_STRING) + ret = bt_ctf_field_string_set_value(field, + data + offset + i * len); + else if (!(flags & FIELD_IS_SIGNED)) + ret = bt_ctf_field_unsigned_integer_set_value( + field, value_int); + else + ret =
[PATCH 5/8] perf data: Add tracepoint events fields CTF conversion support
From: Sebastian Andrzej Siewior bige...@linutronix.de 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 } ... Cc: Arnaldo Carvalho de Melo a...@redhat.com Cc: David Ahern dsah...@gmail.com Cc: Frederic Weisbecker fweis...@gmail.com Cc: Jeremie Galarneau jga...@efficios.com Cc: Jiri Olsa jo...@kernel.org Cc: Namhyung Kim namhy...@gmail.com Cc: Paul Mackerras pau...@samba.org Cc: Peter Zijlstra pet...@infradead.org Cc: Sebastian Andrzej Siewior bige...@linutronix.de Cc: Tom Zanussi tzanu...@gmail.com Signed-off-by: Jiri Olsa jo...@kernel.org Signed-off-by: Sebastian Andrzej Siewior bige...@linutronix.de --- tools/perf/util/data-convert-bt.c | 242 ++ 1 file changed, 242 insertions(+) diff --git a/tools/perf/util/data-convert-bt.c b/tools/perf/util/data-convert-bt.c index 3c39fae9c07e..cf1b16c89120 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) FUNC_VALUE_SET(u64) __FUNC_VALUE_SET(u64_hex, u64) +static struct bt_ctf_field_type* +get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field) +{ + unsigned long flags = field-flags; + + if (flags FIELD_IS_STRING) + return cw-data.string; + + if (!(flags FIELD_IS_SIGNED)) { + /* unsigned long are mostly pointers */ + if (flags FIELD_IS_LONG || flags FIELD_IS_POINTER) + return cw-data.u64_hex; + } + + if (flags FIELD_IS_SIGNED) { + if (field-size == 8) + return cw-data.s64; + else + return cw-data.s32; + } + + if (field-size == 8) + return cw-data.u64; + else + return cw-data.u32; +} + +static int add_tracepoint_field_value(struct ctf_writer *cw, + struct bt_ctf_event_class *event_class, + struct bt_ctf_event *event, + struct perf_sample *sample, + struct format_field *fmtf) +{ + struct bt_ctf_field_type *type; + struct bt_ctf_field *array_field; + struct bt_ctf_field *field; + const char *name = fmtf-name; + void *data = sample-raw_data; + unsigned long long value_int; + unsigned long flags = fmtf-flags; + unsigned int n_items; + unsigned int i; + unsigned int offset; + unsigned int len; + int ret; + + offset = fmtf-offset; + len = fmtf-size; + if (flags FIELD_IS_STRING) + flags = ~FIELD_IS_ARRAY; + + if (flags FIELD_IS_DYNAMIC) { + unsigned long long tmp_val; + + tmp_val = pevent_read_number(fmtf-event-pevent, + data + offset, len); + offset = tmp_val; + len = offset 16; + offset = 0x; + } + + if (flags FIELD_IS_ARRAY) { + + type = bt_ctf_event_class_get_field_by_name( + event_class, name); + array_field = bt_ctf_field_create(type); + bt_ctf_field_type_put(type); + if (!array_field) { + pr_err(Failed to create array type %s\n, name); + return -1; + } + + len = fmtf-size / fmtf-arraylen; + n_items = fmtf-arraylen; + } else { + n_items = 1; + array_field = NULL; + } + + type = get_tracepoint_field_type(cw, fmtf); + + for (i = 0; i n_items; i++) { + if (!(flags FIELD_IS_STRING)) + value_int = pevent_read_number( + fmtf-event-pevent, + data + offset + i * len, len); + + if (flags FIELD_IS_ARRAY) + field = bt_ctf_field_array_get_field(array_field, i); + else + field = bt_ctf_field_create(type); + + if (!field) { + pr_err(failed to create a field %s\n, name); + return -1; + } + + if (flags FIELD_IS_STRING) + ret = bt_ctf_field_string_set_value(field, + data + offset + i * len); + else if (!(flags FIELD_IS_SIGNED)) +