1edbe9817SJiri Olsa /* 2edbe9817SJiri Olsa * CTF writing support via babeltrace. 3edbe9817SJiri Olsa * 4edbe9817SJiri Olsa * Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com> 5edbe9817SJiri Olsa * Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de> 6edbe9817SJiri Olsa * 7edbe9817SJiri Olsa * Released under the GPL v2. (and only v2, not any later version) 8edbe9817SJiri Olsa */ 9edbe9817SJiri Olsa 10edbe9817SJiri Olsa #include <linux/compiler.h> 11edbe9817SJiri Olsa #include <babeltrace/ctf-writer/writer.h> 12edbe9817SJiri Olsa #include <babeltrace/ctf-writer/clock.h> 13edbe9817SJiri Olsa #include <babeltrace/ctf-writer/stream.h> 14edbe9817SJiri Olsa #include <babeltrace/ctf-writer/event.h> 15edbe9817SJiri Olsa #include <babeltrace/ctf-writer/event-types.h> 16edbe9817SJiri Olsa #include <babeltrace/ctf-writer/event-fields.h> 17edbe9817SJiri Olsa #include <babeltrace/ctf/events.h> 18edbe9817SJiri Olsa #include <traceevent/event-parse.h> 19edbe9817SJiri Olsa #include "asm/bug.h" 20edbe9817SJiri Olsa #include "data-convert-bt.h" 21edbe9817SJiri Olsa #include "session.h" 22edbe9817SJiri Olsa #include "util.h" 23edbe9817SJiri Olsa #include "debug.h" 24edbe9817SJiri Olsa #include "tool.h" 25edbe9817SJiri Olsa #include "evlist.h" 26edbe9817SJiri Olsa #include "evsel.h" 27edbe9817SJiri Olsa #include "machine.h" 28edbe9817SJiri Olsa 29edbe9817SJiri Olsa #define pr_N(n, fmt, ...) \ 30edbe9817SJiri Olsa eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__) 31edbe9817SJiri Olsa 32edbe9817SJiri Olsa #define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__) 33edbe9817SJiri Olsa #define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__) 34edbe9817SJiri Olsa 35edbe9817SJiri Olsa #define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__) 36edbe9817SJiri Olsa 37edbe9817SJiri Olsa struct evsel_priv { 38edbe9817SJiri Olsa struct bt_ctf_event_class *event_class; 39edbe9817SJiri Olsa }; 40edbe9817SJiri Olsa 41edbe9817SJiri Olsa struct ctf_writer { 42edbe9817SJiri Olsa /* writer primitives */ 43edbe9817SJiri Olsa struct bt_ctf_writer *writer; 44edbe9817SJiri Olsa struct bt_ctf_stream *stream; 45edbe9817SJiri Olsa struct bt_ctf_stream_class *stream_class; 46edbe9817SJiri Olsa struct bt_ctf_clock *clock; 47edbe9817SJiri Olsa 48edbe9817SJiri Olsa /* data types */ 49edbe9817SJiri Olsa union { 50edbe9817SJiri Olsa struct { 51edbe9817SJiri Olsa struct bt_ctf_field_type *s64; 52edbe9817SJiri Olsa struct bt_ctf_field_type *u64; 53edbe9817SJiri Olsa struct bt_ctf_field_type *s32; 54edbe9817SJiri Olsa struct bt_ctf_field_type *u32; 55edbe9817SJiri Olsa struct bt_ctf_field_type *string; 56edbe9817SJiri Olsa struct bt_ctf_field_type *u64_hex; 57edbe9817SJiri Olsa }; 58edbe9817SJiri Olsa struct bt_ctf_field_type *array[6]; 59edbe9817SJiri Olsa } data; 60edbe9817SJiri Olsa }; 61edbe9817SJiri Olsa 62edbe9817SJiri Olsa struct convert { 63edbe9817SJiri Olsa struct perf_tool tool; 64edbe9817SJiri Olsa struct ctf_writer writer; 65edbe9817SJiri Olsa 66edbe9817SJiri Olsa u64 events_size; 67edbe9817SJiri Olsa u64 events_count; 68edbe9817SJiri Olsa }; 69edbe9817SJiri Olsa 70edbe9817SJiri Olsa static int value_set(struct bt_ctf_field_type *type, 71edbe9817SJiri Olsa struct bt_ctf_event *event, 72edbe9817SJiri Olsa const char *name, u64 val) 73edbe9817SJiri Olsa { 74edbe9817SJiri Olsa struct bt_ctf_field *field; 75edbe9817SJiri Olsa bool sign = bt_ctf_field_type_integer_get_signed(type); 76edbe9817SJiri Olsa int ret; 77edbe9817SJiri Olsa 78edbe9817SJiri Olsa field = bt_ctf_field_create(type); 79edbe9817SJiri Olsa if (!field) { 80edbe9817SJiri Olsa pr_err("failed to create a field %s\n", name); 81edbe9817SJiri Olsa return -1; 82edbe9817SJiri Olsa } 83edbe9817SJiri Olsa 84edbe9817SJiri Olsa if (sign) { 85edbe9817SJiri Olsa ret = bt_ctf_field_signed_integer_set_value(field, val); 86edbe9817SJiri Olsa if (ret) { 87edbe9817SJiri Olsa pr_err("failed to set field value %s\n", name); 88edbe9817SJiri Olsa goto err; 89edbe9817SJiri Olsa } 90edbe9817SJiri Olsa } else { 91edbe9817SJiri Olsa ret = bt_ctf_field_unsigned_integer_set_value(field, val); 92edbe9817SJiri Olsa if (ret) { 93edbe9817SJiri Olsa pr_err("failed to set field value %s\n", name); 94edbe9817SJiri Olsa goto err; 95edbe9817SJiri Olsa } 96edbe9817SJiri Olsa } 97edbe9817SJiri Olsa 98edbe9817SJiri Olsa ret = bt_ctf_event_set_payload(event, name, field); 99edbe9817SJiri Olsa if (ret) { 100edbe9817SJiri Olsa pr_err("failed to set payload %s\n", name); 101edbe9817SJiri Olsa goto err; 102edbe9817SJiri Olsa } 103edbe9817SJiri Olsa 104edbe9817SJiri Olsa pr2(" SET [%s = %" PRIu64 "]\n", name, val); 105edbe9817SJiri Olsa 106edbe9817SJiri Olsa err: 107edbe9817SJiri Olsa bt_ctf_field_put(field); 108edbe9817SJiri Olsa return ret; 109edbe9817SJiri Olsa } 110edbe9817SJiri Olsa 111edbe9817SJiri Olsa #define __FUNC_VALUE_SET(_name, _val_type) \ 112edbe9817SJiri Olsa static __maybe_unused int value_set_##_name(struct ctf_writer *cw, \ 113edbe9817SJiri Olsa struct bt_ctf_event *event, \ 114edbe9817SJiri Olsa const char *name, \ 115edbe9817SJiri Olsa _val_type val) \ 116edbe9817SJiri Olsa { \ 117edbe9817SJiri Olsa struct bt_ctf_field_type *type = cw->data._name; \ 118edbe9817SJiri Olsa return value_set(type, event, name, (u64) val); \ 119edbe9817SJiri Olsa } 120edbe9817SJiri Olsa 121edbe9817SJiri Olsa #define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name) 122edbe9817SJiri Olsa 123edbe9817SJiri Olsa FUNC_VALUE_SET(s32) 124edbe9817SJiri Olsa FUNC_VALUE_SET(u32) 125edbe9817SJiri Olsa FUNC_VALUE_SET(s64) 126edbe9817SJiri Olsa FUNC_VALUE_SET(u64) 127edbe9817SJiri Olsa __FUNC_VALUE_SET(u64_hex, u64) 128edbe9817SJiri Olsa 129edbe9817SJiri Olsa static int add_generic_values(struct ctf_writer *cw, 130edbe9817SJiri Olsa struct bt_ctf_event *event, 131edbe9817SJiri Olsa struct perf_evsel *evsel, 132edbe9817SJiri Olsa struct perf_sample *sample) 133edbe9817SJiri Olsa { 134edbe9817SJiri Olsa u64 type = evsel->attr.sample_type; 135edbe9817SJiri Olsa int ret; 136edbe9817SJiri Olsa 137edbe9817SJiri Olsa /* 138edbe9817SJiri Olsa * missing: 139edbe9817SJiri Olsa * PERF_SAMPLE_TIME - not needed as we have it in 140edbe9817SJiri Olsa * ctf event header 141edbe9817SJiri Olsa * PERF_SAMPLE_READ - TODO 142edbe9817SJiri Olsa * PERF_SAMPLE_CALLCHAIN - TODO 143edbe9817SJiri Olsa * PERF_SAMPLE_RAW - tracepoint fields are handled separately 144edbe9817SJiri Olsa * PERF_SAMPLE_BRANCH_STACK - TODO 145edbe9817SJiri Olsa * PERF_SAMPLE_REGS_USER - TODO 146edbe9817SJiri Olsa * PERF_SAMPLE_STACK_USER - TODO 147edbe9817SJiri Olsa */ 148edbe9817SJiri Olsa 149edbe9817SJiri Olsa if (type & PERF_SAMPLE_IP) { 150edbe9817SJiri Olsa ret = value_set_u64_hex(cw, event, "ip", sample->ip); 151edbe9817SJiri Olsa if (ret) 152edbe9817SJiri Olsa return -1; 153edbe9817SJiri Olsa } 154edbe9817SJiri Olsa 155edbe9817SJiri Olsa if (type & PERF_SAMPLE_TID) { 156edbe9817SJiri Olsa ret = value_set_s32(cw, event, "tid", sample->tid); 157edbe9817SJiri Olsa if (ret) 158edbe9817SJiri Olsa return -1; 159edbe9817SJiri Olsa 160edbe9817SJiri Olsa ret = value_set_s32(cw, event, "pid", sample->pid); 161edbe9817SJiri Olsa if (ret) 162edbe9817SJiri Olsa return -1; 163edbe9817SJiri Olsa } 164edbe9817SJiri Olsa 165edbe9817SJiri Olsa if ((type & PERF_SAMPLE_ID) || 166edbe9817SJiri Olsa (type & PERF_SAMPLE_IDENTIFIER)) { 167edbe9817SJiri Olsa ret = value_set_u64(cw, event, "id", sample->id); 168edbe9817SJiri Olsa if (ret) 169edbe9817SJiri Olsa return -1; 170edbe9817SJiri Olsa } 171edbe9817SJiri Olsa 172edbe9817SJiri Olsa if (type & PERF_SAMPLE_STREAM_ID) { 173edbe9817SJiri Olsa ret = value_set_u64(cw, event, "stream_id", sample->stream_id); 174edbe9817SJiri Olsa if (ret) 175edbe9817SJiri Olsa return -1; 176edbe9817SJiri Olsa } 177edbe9817SJiri Olsa 178edbe9817SJiri Olsa if (type & PERF_SAMPLE_CPU) { 179edbe9817SJiri Olsa ret = value_set_u32(cw, event, "cpu", sample->cpu); 180edbe9817SJiri Olsa if (ret) 181edbe9817SJiri Olsa return -1; 182edbe9817SJiri Olsa } 183edbe9817SJiri Olsa 184edbe9817SJiri Olsa if (type & PERF_SAMPLE_PERIOD) { 185edbe9817SJiri Olsa ret = value_set_u64(cw, event, "period", sample->period); 186edbe9817SJiri Olsa if (ret) 187edbe9817SJiri Olsa return -1; 188edbe9817SJiri Olsa } 189edbe9817SJiri Olsa 190edbe9817SJiri Olsa if (type & PERF_SAMPLE_WEIGHT) { 191edbe9817SJiri Olsa ret = value_set_u64(cw, event, "weight", sample->weight); 192edbe9817SJiri Olsa if (ret) 193edbe9817SJiri Olsa return -1; 194edbe9817SJiri Olsa } 195edbe9817SJiri Olsa 196edbe9817SJiri Olsa if (type & PERF_SAMPLE_DATA_SRC) { 197edbe9817SJiri Olsa ret = value_set_u64(cw, event, "data_src", sample->data_src); 198edbe9817SJiri Olsa if (ret) 199edbe9817SJiri Olsa return -1; 200edbe9817SJiri Olsa } 201edbe9817SJiri Olsa 202edbe9817SJiri Olsa if (type & PERF_SAMPLE_TRANSACTION) { 203edbe9817SJiri Olsa ret = value_set_u64(cw, event, "transaction", sample->transaction); 204edbe9817SJiri Olsa if (ret) 205edbe9817SJiri Olsa return -1; 206edbe9817SJiri Olsa } 207edbe9817SJiri Olsa 208edbe9817SJiri Olsa return 0; 209edbe9817SJiri Olsa } 210edbe9817SJiri Olsa 211edbe9817SJiri Olsa static int process_sample_event(struct perf_tool *tool, 212edbe9817SJiri Olsa union perf_event *_event __maybe_unused, 213edbe9817SJiri Olsa struct perf_sample *sample, 214edbe9817SJiri Olsa struct perf_evsel *evsel, 215edbe9817SJiri Olsa struct machine *machine __maybe_unused) 216edbe9817SJiri Olsa { 217edbe9817SJiri Olsa struct convert *c = container_of(tool, struct convert, tool); 218edbe9817SJiri Olsa struct evsel_priv *priv = evsel->priv; 219edbe9817SJiri Olsa struct ctf_writer *cw = &c->writer; 220edbe9817SJiri Olsa struct bt_ctf_event_class *event_class; 221edbe9817SJiri Olsa struct bt_ctf_event *event; 222edbe9817SJiri Olsa int ret; 223edbe9817SJiri Olsa 224edbe9817SJiri Olsa if (WARN_ONCE(!priv, "Failed to setup all events.\n")) 225edbe9817SJiri Olsa return 0; 226edbe9817SJiri Olsa 227edbe9817SJiri Olsa event_class = priv->event_class; 228edbe9817SJiri Olsa 229edbe9817SJiri Olsa /* update stats */ 230edbe9817SJiri Olsa c->events_count++; 231edbe9817SJiri Olsa c->events_size += _event->header.size; 232edbe9817SJiri Olsa 233edbe9817SJiri Olsa pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count); 234edbe9817SJiri Olsa 235edbe9817SJiri Olsa event = bt_ctf_event_create(event_class); 236edbe9817SJiri Olsa if (!event) { 237edbe9817SJiri Olsa pr_err("Failed to create an CTF event\n"); 238edbe9817SJiri Olsa return -1; 239edbe9817SJiri Olsa } 240edbe9817SJiri Olsa 241edbe9817SJiri Olsa bt_ctf_clock_set_time(cw->clock, sample->time); 242edbe9817SJiri Olsa 243edbe9817SJiri Olsa ret = add_generic_values(cw, event, evsel, sample); 244edbe9817SJiri Olsa if (ret) 245edbe9817SJiri Olsa return -1; 246edbe9817SJiri Olsa 247edbe9817SJiri Olsa bt_ctf_stream_append_event(cw->stream, event); 248edbe9817SJiri Olsa bt_ctf_event_put(event); 249edbe9817SJiri Olsa return 0; 250edbe9817SJiri Olsa } 251edbe9817SJiri Olsa 252edbe9817SJiri Olsa static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel, 253edbe9817SJiri Olsa struct bt_ctf_event_class *event_class) 254edbe9817SJiri Olsa { 255edbe9817SJiri Olsa u64 type = evsel->attr.sample_type; 256edbe9817SJiri Olsa 257edbe9817SJiri Olsa /* 258edbe9817SJiri Olsa * missing: 259edbe9817SJiri Olsa * PERF_SAMPLE_TIME - not needed as we have it in 260edbe9817SJiri Olsa * ctf event header 261edbe9817SJiri Olsa * PERF_SAMPLE_READ - TODO 262edbe9817SJiri Olsa * PERF_SAMPLE_CALLCHAIN - TODO 263edbe9817SJiri Olsa * PERF_SAMPLE_RAW - tracepoint fields are handled separately 264edbe9817SJiri Olsa * PERF_SAMPLE_BRANCH_STACK - TODO 265edbe9817SJiri Olsa * PERF_SAMPLE_REGS_USER - TODO 266edbe9817SJiri Olsa * PERF_SAMPLE_STACK_USER - TODO 267edbe9817SJiri Olsa */ 268edbe9817SJiri Olsa 269edbe9817SJiri Olsa #define ADD_FIELD(cl, t, n) \ 270edbe9817SJiri Olsa do { \ 271edbe9817SJiri Olsa pr2(" field '%s'\n", n); \ 272edbe9817SJiri Olsa if (bt_ctf_event_class_add_field(cl, t, n)) { \ 273edbe9817SJiri Olsa pr_err("Failed to add field '%s;\n", n); \ 274edbe9817SJiri Olsa return -1; \ 275edbe9817SJiri Olsa } \ 276edbe9817SJiri Olsa } while (0) 277edbe9817SJiri Olsa 278edbe9817SJiri Olsa if (type & PERF_SAMPLE_IP) 279edbe9817SJiri Olsa ADD_FIELD(event_class, cw->data.u64_hex, "ip"); 280edbe9817SJiri Olsa 281edbe9817SJiri Olsa if (type & PERF_SAMPLE_TID) { 282edbe9817SJiri Olsa ADD_FIELD(event_class, cw->data.s32, "tid"); 283edbe9817SJiri Olsa ADD_FIELD(event_class, cw->data.s32, "pid"); 284edbe9817SJiri Olsa } 285edbe9817SJiri Olsa 286edbe9817SJiri Olsa if ((type & PERF_SAMPLE_ID) || 287edbe9817SJiri Olsa (type & PERF_SAMPLE_IDENTIFIER)) 288edbe9817SJiri Olsa ADD_FIELD(event_class, cw->data.u64, "id"); 289edbe9817SJiri Olsa 290edbe9817SJiri Olsa if (type & PERF_SAMPLE_STREAM_ID) 291edbe9817SJiri Olsa ADD_FIELD(event_class, cw->data.u64, "stream_id"); 292edbe9817SJiri Olsa 293edbe9817SJiri Olsa if (type & PERF_SAMPLE_CPU) 294edbe9817SJiri Olsa ADD_FIELD(event_class, cw->data.u32, "cpu"); 295edbe9817SJiri Olsa 296edbe9817SJiri Olsa if (type & PERF_SAMPLE_PERIOD) 297edbe9817SJiri Olsa ADD_FIELD(event_class, cw->data.u64, "period"); 298edbe9817SJiri Olsa 299edbe9817SJiri Olsa if (type & PERF_SAMPLE_WEIGHT) 300edbe9817SJiri Olsa ADD_FIELD(event_class, cw->data.u64, "weight"); 301edbe9817SJiri Olsa 302edbe9817SJiri Olsa if (type & PERF_SAMPLE_DATA_SRC) 303edbe9817SJiri Olsa ADD_FIELD(event_class, cw->data.u64, "data_src"); 304edbe9817SJiri Olsa 305edbe9817SJiri Olsa if (type & PERF_SAMPLE_TRANSACTION) 306edbe9817SJiri Olsa ADD_FIELD(event_class, cw->data.u64, "transaction"); 307edbe9817SJiri Olsa 308edbe9817SJiri Olsa #undef ADD_FIELD 309edbe9817SJiri Olsa return 0; 310edbe9817SJiri Olsa } 311edbe9817SJiri Olsa 312edbe9817SJiri Olsa static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel) 313edbe9817SJiri Olsa { 314edbe9817SJiri Olsa struct bt_ctf_event_class *event_class; 315edbe9817SJiri Olsa struct evsel_priv *priv; 316edbe9817SJiri Olsa const char *name = perf_evsel__name(evsel); 317edbe9817SJiri Olsa int ret; 318edbe9817SJiri Olsa 319edbe9817SJiri Olsa pr("Adding event '%s' (type %d)\n", name, evsel->attr.type); 320edbe9817SJiri Olsa 321edbe9817SJiri Olsa event_class = bt_ctf_event_class_create(name); 322edbe9817SJiri Olsa if (!event_class) 323edbe9817SJiri Olsa return -1; 324edbe9817SJiri Olsa 325edbe9817SJiri Olsa ret = add_generic_types(cw, evsel, event_class); 326edbe9817SJiri Olsa if (ret) 327edbe9817SJiri Olsa goto err; 328edbe9817SJiri Olsa 329edbe9817SJiri Olsa ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class); 330edbe9817SJiri Olsa if (ret) { 331edbe9817SJiri Olsa pr("Failed to add event class into stream.\n"); 332edbe9817SJiri Olsa goto err; 333edbe9817SJiri Olsa } 334edbe9817SJiri Olsa 335edbe9817SJiri Olsa priv = malloc(sizeof(*priv)); 336edbe9817SJiri Olsa if (!priv) 337edbe9817SJiri Olsa goto err; 338edbe9817SJiri Olsa 339edbe9817SJiri Olsa priv->event_class = event_class; 340edbe9817SJiri Olsa evsel->priv = priv; 341edbe9817SJiri Olsa return 0; 342edbe9817SJiri Olsa 343edbe9817SJiri Olsa err: 344edbe9817SJiri Olsa bt_ctf_event_class_put(event_class); 345edbe9817SJiri Olsa pr_err("Failed to add event '%s'.\n", name); 346edbe9817SJiri Olsa return -1; 347edbe9817SJiri Olsa } 348edbe9817SJiri Olsa 349edbe9817SJiri Olsa static int setup_events(struct ctf_writer *cw, struct perf_session *session) 350edbe9817SJiri Olsa { 351edbe9817SJiri Olsa struct perf_evlist *evlist = session->evlist; 352edbe9817SJiri Olsa struct perf_evsel *evsel; 353edbe9817SJiri Olsa int ret; 354edbe9817SJiri Olsa 355edbe9817SJiri Olsa evlist__for_each(evlist, evsel) { 356edbe9817SJiri Olsa ret = add_event(cw, evsel); 357edbe9817SJiri Olsa if (ret) 358edbe9817SJiri Olsa return ret; 359edbe9817SJiri Olsa } 360edbe9817SJiri Olsa return 0; 361edbe9817SJiri Olsa } 362edbe9817SJiri Olsa 363edbe9817SJiri Olsa static int ctf_writer__setup_env(struct ctf_writer *cw, 364edbe9817SJiri Olsa struct perf_session *session) 365edbe9817SJiri Olsa { 366edbe9817SJiri Olsa struct perf_header *header = &session->header; 367edbe9817SJiri Olsa struct bt_ctf_writer *writer = cw->writer; 368edbe9817SJiri Olsa 369edbe9817SJiri Olsa #define ADD(__n, __v) \ 370edbe9817SJiri Olsa do { \ 371edbe9817SJiri Olsa if (bt_ctf_writer_add_environment_field(writer, __n, __v)) \ 372edbe9817SJiri Olsa return -1; \ 373edbe9817SJiri Olsa } while (0) 374edbe9817SJiri Olsa 375edbe9817SJiri Olsa ADD("host", header->env.hostname); 376edbe9817SJiri Olsa ADD("sysname", "Linux"); 377edbe9817SJiri Olsa ADD("release", header->env.os_release); 378edbe9817SJiri Olsa ADD("version", header->env.version); 379edbe9817SJiri Olsa ADD("machine", header->env.arch); 380edbe9817SJiri Olsa ADD("domain", "kernel"); 381edbe9817SJiri Olsa ADD("tracer_name", "perf"); 382edbe9817SJiri Olsa 383edbe9817SJiri Olsa #undef ADD 384edbe9817SJiri Olsa return 0; 385edbe9817SJiri Olsa } 386edbe9817SJiri Olsa 387edbe9817SJiri Olsa static int ctf_writer__setup_clock(struct ctf_writer *cw) 388edbe9817SJiri Olsa { 389edbe9817SJiri Olsa struct bt_ctf_clock *clock = cw->clock; 390edbe9817SJiri Olsa 391edbe9817SJiri Olsa bt_ctf_clock_set_description(clock, "perf clock"); 392edbe9817SJiri Olsa 393edbe9817SJiri Olsa #define SET(__n, __v) \ 394edbe9817SJiri Olsa do { \ 395edbe9817SJiri Olsa if (bt_ctf_clock_set_##__n(clock, __v)) \ 396edbe9817SJiri Olsa return -1; \ 397edbe9817SJiri Olsa } while (0) 398edbe9817SJiri Olsa 399edbe9817SJiri Olsa SET(frequency, 1000000000); 400edbe9817SJiri Olsa SET(offset_s, 0); 401edbe9817SJiri Olsa SET(offset, 0); 402edbe9817SJiri Olsa SET(precision, 10); 403edbe9817SJiri Olsa SET(is_absolute, 0); 404edbe9817SJiri Olsa 405edbe9817SJiri Olsa #undef SET 406edbe9817SJiri Olsa return 0; 407edbe9817SJiri Olsa } 408edbe9817SJiri Olsa 409edbe9817SJiri Olsa static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex) 410edbe9817SJiri Olsa { 411edbe9817SJiri Olsa struct bt_ctf_field_type *type; 412edbe9817SJiri Olsa 413edbe9817SJiri Olsa type = bt_ctf_field_type_integer_create(size); 414edbe9817SJiri Olsa if (!type) 415edbe9817SJiri Olsa return NULL; 416edbe9817SJiri Olsa 417edbe9817SJiri Olsa if (sign && 418edbe9817SJiri Olsa bt_ctf_field_type_integer_set_signed(type, 1)) 419edbe9817SJiri Olsa goto err; 420edbe9817SJiri Olsa 421edbe9817SJiri Olsa if (hex && 422edbe9817SJiri Olsa bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL)) 423edbe9817SJiri Olsa goto err; 424edbe9817SJiri Olsa 425edbe9817SJiri Olsa pr2("Created type: INTEGER %d-bit %ssigned %s\n", 426edbe9817SJiri Olsa size, sign ? "un" : "", hex ? "hex" : ""); 427edbe9817SJiri Olsa return type; 428edbe9817SJiri Olsa 429edbe9817SJiri Olsa err: 430edbe9817SJiri Olsa bt_ctf_field_type_put(type); 431edbe9817SJiri Olsa return NULL; 432edbe9817SJiri Olsa } 433edbe9817SJiri Olsa 434edbe9817SJiri Olsa static void ctf_writer__cleanup_data(struct ctf_writer *cw) 435edbe9817SJiri Olsa { 436edbe9817SJiri Olsa unsigned int i; 437edbe9817SJiri Olsa 438edbe9817SJiri Olsa for (i = 0; i < ARRAY_SIZE(cw->data.array); i++) 439edbe9817SJiri Olsa bt_ctf_field_type_put(cw->data.array[i]); 440edbe9817SJiri Olsa } 441edbe9817SJiri Olsa 442edbe9817SJiri Olsa static int ctf_writer__init_data(struct ctf_writer *cw) 443edbe9817SJiri Olsa { 444edbe9817SJiri Olsa #define CREATE_INT_TYPE(type, size, sign, hex) \ 445edbe9817SJiri Olsa do { \ 446edbe9817SJiri Olsa (type) = create_int_type(size, sign, hex); \ 447edbe9817SJiri Olsa if (!(type)) \ 448edbe9817SJiri Olsa goto err; \ 449edbe9817SJiri Olsa } while (0) 450edbe9817SJiri Olsa 451edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.s64, 64, true, false); 452edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.u64, 64, false, false); 453edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.s32, 32, true, false); 454edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.u32, 32, false, false); 455edbe9817SJiri Olsa CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true); 456edbe9817SJiri Olsa 457edbe9817SJiri Olsa cw->data.string = bt_ctf_field_type_string_create(); 458edbe9817SJiri Olsa if (cw->data.string) 459edbe9817SJiri Olsa return 0; 460edbe9817SJiri Olsa 461edbe9817SJiri Olsa err: 462edbe9817SJiri Olsa ctf_writer__cleanup_data(cw); 463edbe9817SJiri Olsa pr_err("Failed to create data types.\n"); 464edbe9817SJiri Olsa return -1; 465edbe9817SJiri Olsa } 466edbe9817SJiri Olsa 467edbe9817SJiri Olsa static void ctf_writer__cleanup(struct ctf_writer *cw) 468edbe9817SJiri Olsa { 469edbe9817SJiri Olsa ctf_writer__cleanup_data(cw); 470edbe9817SJiri Olsa 471edbe9817SJiri Olsa bt_ctf_clock_put(cw->clock); 472edbe9817SJiri Olsa bt_ctf_stream_put(cw->stream); 473edbe9817SJiri Olsa bt_ctf_stream_class_put(cw->stream_class); 474edbe9817SJiri Olsa bt_ctf_writer_put(cw->writer); 475edbe9817SJiri Olsa 476edbe9817SJiri Olsa /* and NULL all the pointers */ 477edbe9817SJiri Olsa memset(cw, 0, sizeof(*cw)); 478edbe9817SJiri Olsa } 479edbe9817SJiri Olsa 480edbe9817SJiri Olsa static int ctf_writer__init(struct ctf_writer *cw, const char *path) 481edbe9817SJiri Olsa { 482edbe9817SJiri Olsa struct bt_ctf_writer *writer; 483edbe9817SJiri Olsa struct bt_ctf_stream_class *stream_class; 484edbe9817SJiri Olsa struct bt_ctf_stream *stream; 485edbe9817SJiri Olsa struct bt_ctf_clock *clock; 486edbe9817SJiri Olsa 487edbe9817SJiri Olsa /* CTF writer */ 488edbe9817SJiri Olsa writer = bt_ctf_writer_create(path); 489edbe9817SJiri Olsa if (!writer) 490edbe9817SJiri Olsa goto err; 491edbe9817SJiri Olsa 492edbe9817SJiri Olsa cw->writer = writer; 493edbe9817SJiri Olsa 494edbe9817SJiri Olsa /* CTF clock */ 495edbe9817SJiri Olsa clock = bt_ctf_clock_create("perf_clock"); 496edbe9817SJiri Olsa if (!clock) { 497edbe9817SJiri Olsa pr("Failed to create CTF clock.\n"); 498edbe9817SJiri Olsa goto err_cleanup; 499edbe9817SJiri Olsa } 500edbe9817SJiri Olsa 501edbe9817SJiri Olsa cw->clock = clock; 502edbe9817SJiri Olsa 503edbe9817SJiri Olsa if (ctf_writer__setup_clock(cw)) { 504edbe9817SJiri Olsa pr("Failed to setup CTF clock.\n"); 505edbe9817SJiri Olsa goto err_cleanup; 506edbe9817SJiri Olsa } 507edbe9817SJiri Olsa 508edbe9817SJiri Olsa /* CTF stream class */ 509edbe9817SJiri Olsa stream_class = bt_ctf_stream_class_create("perf_stream"); 510edbe9817SJiri Olsa if (!stream_class) { 511edbe9817SJiri Olsa pr("Failed to create CTF stream class.\n"); 512edbe9817SJiri Olsa goto err_cleanup; 513edbe9817SJiri Olsa } 514edbe9817SJiri Olsa 515edbe9817SJiri Olsa cw->stream_class = stream_class; 516edbe9817SJiri Olsa 517edbe9817SJiri Olsa /* CTF clock stream setup */ 518edbe9817SJiri Olsa if (bt_ctf_stream_class_set_clock(stream_class, clock)) { 519edbe9817SJiri Olsa pr("Failed to assign CTF clock to stream class.\n"); 520edbe9817SJiri Olsa goto err_cleanup; 521edbe9817SJiri Olsa } 522edbe9817SJiri Olsa 523edbe9817SJiri Olsa if (ctf_writer__init_data(cw)) 524edbe9817SJiri Olsa goto err_cleanup; 525edbe9817SJiri Olsa 526edbe9817SJiri Olsa /* CTF stream instance */ 527edbe9817SJiri Olsa stream = bt_ctf_writer_create_stream(writer, stream_class); 528edbe9817SJiri Olsa if (!stream) { 529edbe9817SJiri Olsa pr("Failed to create CTF stream.\n"); 530edbe9817SJiri Olsa goto err_cleanup; 531edbe9817SJiri Olsa } 532edbe9817SJiri Olsa 533edbe9817SJiri Olsa cw->stream = stream; 534edbe9817SJiri Olsa 535edbe9817SJiri Olsa /* CTF clock writer setup */ 536edbe9817SJiri Olsa if (bt_ctf_writer_add_clock(writer, clock)) { 537edbe9817SJiri Olsa pr("Failed to assign CTF clock to writer.\n"); 538edbe9817SJiri Olsa goto err_cleanup; 539edbe9817SJiri Olsa } 540edbe9817SJiri Olsa 541edbe9817SJiri Olsa return 0; 542edbe9817SJiri Olsa 543edbe9817SJiri Olsa err_cleanup: 544edbe9817SJiri Olsa ctf_writer__cleanup(cw); 545edbe9817SJiri Olsa err: 546edbe9817SJiri Olsa pr_err("Failed to setup CTF writer.\n"); 547edbe9817SJiri Olsa return -1; 548edbe9817SJiri Olsa } 549edbe9817SJiri Olsa 550edbe9817SJiri Olsa int bt_convert__perf2ctf(const char *input, const char *path) 551edbe9817SJiri Olsa { 552edbe9817SJiri Olsa struct perf_session *session; 553edbe9817SJiri Olsa struct perf_data_file file = { 554edbe9817SJiri Olsa .path = input, 555edbe9817SJiri Olsa .mode = PERF_DATA_MODE_READ, 556edbe9817SJiri Olsa }; 557edbe9817SJiri Olsa struct convert c = { 558edbe9817SJiri Olsa .tool = { 559edbe9817SJiri Olsa .sample = process_sample_event, 560edbe9817SJiri Olsa .mmap = perf_event__process_mmap, 561edbe9817SJiri Olsa .mmap2 = perf_event__process_mmap2, 562edbe9817SJiri Olsa .comm = perf_event__process_comm, 563edbe9817SJiri Olsa .exit = perf_event__process_exit, 564edbe9817SJiri Olsa .fork = perf_event__process_fork, 565edbe9817SJiri Olsa .lost = perf_event__process_lost, 566edbe9817SJiri Olsa .tracing_data = perf_event__process_tracing_data, 567edbe9817SJiri Olsa .build_id = perf_event__process_build_id, 568edbe9817SJiri Olsa .ordered_events = true, 569edbe9817SJiri Olsa .ordering_requires_timestamps = true, 570edbe9817SJiri Olsa }, 571edbe9817SJiri Olsa }; 572edbe9817SJiri Olsa struct ctf_writer *cw = &c.writer; 573edbe9817SJiri Olsa int err = -1; 574edbe9817SJiri Olsa 575edbe9817SJiri Olsa /* CTF writer */ 576edbe9817SJiri Olsa if (ctf_writer__init(cw, path)) 577edbe9817SJiri Olsa return -1; 578edbe9817SJiri Olsa 579edbe9817SJiri Olsa /* perf.data session */ 580edbe9817SJiri Olsa session = perf_session__new(&file, 0, NULL); 581edbe9817SJiri Olsa if (!session) 582edbe9817SJiri Olsa goto free_writer; 583edbe9817SJiri Olsa 584edbe9817SJiri Olsa /* CTF writer env/clock setup */ 585edbe9817SJiri Olsa if (ctf_writer__setup_env(cw, session)) 586edbe9817SJiri Olsa goto free_session; 587edbe9817SJiri Olsa 588edbe9817SJiri Olsa /* CTF events setup */ 589edbe9817SJiri Olsa if (setup_events(cw, session)) 590edbe9817SJiri Olsa goto free_session; 591edbe9817SJiri Olsa 592edbe9817SJiri Olsa err = perf_session__process_events(session, &c.tool); 593edbe9817SJiri Olsa if (!err) 594edbe9817SJiri Olsa err = bt_ctf_stream_flush(cw->stream); 595edbe9817SJiri Olsa 596edbe9817SJiri Olsa fprintf(stderr, 597edbe9817SJiri Olsa "[ perf data convert: Converted '%s' into CTF data '%s' ]\n", 598edbe9817SJiri Olsa file.path, path); 599edbe9817SJiri Olsa 600edbe9817SJiri Olsa fprintf(stderr, 601edbe9817SJiri Olsa "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n", 602edbe9817SJiri Olsa (double) c.events_size / 1024.0 / 1024.0, 603edbe9817SJiri Olsa c.events_count); 604edbe9817SJiri Olsa 605edbe9817SJiri Olsa /* its all good */ 606edbe9817SJiri Olsa free_session: 607edbe9817SJiri Olsa perf_session__delete(session); 608edbe9817SJiri Olsa 609edbe9817SJiri Olsa free_writer: 610edbe9817SJiri Olsa ctf_writer__cleanup(cw); 611edbe9817SJiri Olsa return err; 612edbe9817SJiri Olsa } 613