data-convert-bt.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183
  1. /*
  2. * CTF writing support via babeltrace.
  3. *
  4. * Copyright (C) 2014, Jiri Olsa <jolsa@redhat.com>
  5. * Copyright (C) 2014, Sebastian Andrzej Siewior <bigeasy@linutronix.de>
  6. *
  7. * Released under the GPL v2. (and only v2, not any later version)
  8. */
  9. #include <linux/compiler.h>
  10. #include <babeltrace/ctf-writer/writer.h>
  11. #include <babeltrace/ctf-writer/clock.h>
  12. #include <babeltrace/ctf-writer/stream.h>
  13. #include <babeltrace/ctf-writer/event.h>
  14. #include <babeltrace/ctf-writer/event-types.h>
  15. #include <babeltrace/ctf-writer/event-fields.h>
  16. #include <babeltrace/ctf-ir/utils.h>
  17. #include <babeltrace/ctf/events.h>
  18. #include <traceevent/event-parse.h>
  19. #include "asm/bug.h"
  20. #include "data-convert-bt.h"
  21. #include "session.h"
  22. #include "util.h"
  23. #include "debug.h"
  24. #include "tool.h"
  25. #include "evlist.h"
  26. #include "evsel.h"
  27. #include "machine.h"
  28. #define pr_N(n, fmt, ...) \
  29. eprintf(n, debug_data_convert, fmt, ##__VA_ARGS__)
  30. #define pr(fmt, ...) pr_N(1, pr_fmt(fmt), ##__VA_ARGS__)
  31. #define pr2(fmt, ...) pr_N(2, pr_fmt(fmt), ##__VA_ARGS__)
  32. #define pr_time2(t, fmt, ...) pr_time_N(2, debug_data_convert, t, pr_fmt(fmt), ##__VA_ARGS__)
  33. struct evsel_priv {
  34. struct bt_ctf_event_class *event_class;
  35. };
  36. #define MAX_CPUS 4096
  37. struct ctf_stream {
  38. struct bt_ctf_stream *stream;
  39. int cpu;
  40. u32 count;
  41. };
  42. struct ctf_writer {
  43. /* writer primitives */
  44. struct bt_ctf_writer *writer;
  45. struct ctf_stream **stream;
  46. int stream_cnt;
  47. struct bt_ctf_stream_class *stream_class;
  48. struct bt_ctf_clock *clock;
  49. /* data types */
  50. union {
  51. struct {
  52. struct bt_ctf_field_type *s64;
  53. struct bt_ctf_field_type *u64;
  54. struct bt_ctf_field_type *s32;
  55. struct bt_ctf_field_type *u32;
  56. struct bt_ctf_field_type *string;
  57. struct bt_ctf_field_type *u64_hex;
  58. };
  59. struct bt_ctf_field_type *array[6];
  60. } data;
  61. };
  62. struct convert {
  63. struct perf_tool tool;
  64. struct ctf_writer writer;
  65. u64 events_size;
  66. u64 events_count;
  67. /* Ordered events configured queue size. */
  68. u64 queue_size;
  69. };
  70. static int value_set(struct bt_ctf_field_type *type,
  71. struct bt_ctf_event *event,
  72. const char *name, u64 val)
  73. {
  74. struct bt_ctf_field *field;
  75. bool sign = bt_ctf_field_type_integer_get_signed(type);
  76. int ret;
  77. field = bt_ctf_field_create(type);
  78. if (!field) {
  79. pr_err("failed to create a field %s\n", name);
  80. return -1;
  81. }
  82. if (sign) {
  83. ret = bt_ctf_field_signed_integer_set_value(field, val);
  84. if (ret) {
  85. pr_err("failed to set field value %s\n", name);
  86. goto err;
  87. }
  88. } else {
  89. ret = bt_ctf_field_unsigned_integer_set_value(field, val);
  90. if (ret) {
  91. pr_err("failed to set field value %s\n", name);
  92. goto err;
  93. }
  94. }
  95. ret = bt_ctf_event_set_payload(event, name, field);
  96. if (ret) {
  97. pr_err("failed to set payload %s\n", name);
  98. goto err;
  99. }
  100. pr2(" SET [%s = %" PRIu64 "]\n", name, val);
  101. err:
  102. bt_ctf_field_put(field);
  103. return ret;
  104. }
  105. #define __FUNC_VALUE_SET(_name, _val_type) \
  106. static __maybe_unused int value_set_##_name(struct ctf_writer *cw, \
  107. struct bt_ctf_event *event, \
  108. const char *name, \
  109. _val_type val) \
  110. { \
  111. struct bt_ctf_field_type *type = cw->data._name; \
  112. return value_set(type, event, name, (u64) val); \
  113. }
  114. #define FUNC_VALUE_SET(_name) __FUNC_VALUE_SET(_name, _name)
  115. FUNC_VALUE_SET(s32)
  116. FUNC_VALUE_SET(u32)
  117. FUNC_VALUE_SET(s64)
  118. FUNC_VALUE_SET(u64)
  119. __FUNC_VALUE_SET(u64_hex, u64)
  120. static struct bt_ctf_field_type*
  121. get_tracepoint_field_type(struct ctf_writer *cw, struct format_field *field)
  122. {
  123. unsigned long flags = field->flags;
  124. if (flags & FIELD_IS_STRING)
  125. return cw->data.string;
  126. if (!(flags & FIELD_IS_SIGNED)) {
  127. /* unsigned long are mostly pointers */
  128. if (flags & FIELD_IS_LONG || flags & FIELD_IS_POINTER)
  129. return cw->data.u64_hex;
  130. }
  131. if (flags & FIELD_IS_SIGNED) {
  132. if (field->size == 8)
  133. return cw->data.s64;
  134. else
  135. return cw->data.s32;
  136. }
  137. if (field->size == 8)
  138. return cw->data.u64;
  139. else
  140. return cw->data.u32;
  141. }
  142. static unsigned long long adjust_signedness(unsigned long long value_int, int size)
  143. {
  144. unsigned long long value_mask;
  145. /*
  146. * value_mask = (1 << (size * 8 - 1)) - 1.
  147. * Directly set value_mask for code readers.
  148. */
  149. switch (size) {
  150. case 1:
  151. value_mask = 0x7fULL;
  152. break;
  153. case 2:
  154. value_mask = 0x7fffULL;
  155. break;
  156. case 4:
  157. value_mask = 0x7fffffffULL;
  158. break;
  159. case 8:
  160. /*
  161. * For 64 bit value, return it self. There is no need
  162. * to fill high bit.
  163. */
  164. /* Fall through */
  165. default:
  166. /* BUG! */
  167. return value_int;
  168. }
  169. /* If it is a positive value, don't adjust. */
  170. if ((value_int & (~0ULL - value_mask)) == 0)
  171. return value_int;
  172. /* Fill upper part of value_int with 1 to make it a negative long long. */
  173. return (value_int & value_mask) | ~value_mask;
  174. }
  175. static int add_tracepoint_field_value(struct ctf_writer *cw,
  176. struct bt_ctf_event_class *event_class,
  177. struct bt_ctf_event *event,
  178. struct perf_sample *sample,
  179. struct format_field *fmtf)
  180. {
  181. struct bt_ctf_field_type *type;
  182. struct bt_ctf_field *array_field;
  183. struct bt_ctf_field *field;
  184. const char *name = fmtf->name;
  185. void *data = sample->raw_data;
  186. unsigned long flags = fmtf->flags;
  187. unsigned int n_items;
  188. unsigned int i;
  189. unsigned int offset;
  190. unsigned int len;
  191. int ret;
  192. name = fmtf->alias;
  193. offset = fmtf->offset;
  194. len = fmtf->size;
  195. if (flags & FIELD_IS_STRING)
  196. flags &= ~FIELD_IS_ARRAY;
  197. if (flags & FIELD_IS_DYNAMIC) {
  198. unsigned long long tmp_val;
  199. tmp_val = pevent_read_number(fmtf->event->pevent,
  200. data + offset, len);
  201. offset = tmp_val;
  202. len = offset >> 16;
  203. offset &= 0xffff;
  204. }
  205. if (flags & FIELD_IS_ARRAY) {
  206. type = bt_ctf_event_class_get_field_by_name(
  207. event_class, name);
  208. array_field = bt_ctf_field_create(type);
  209. bt_ctf_field_type_put(type);
  210. if (!array_field) {
  211. pr_err("Failed to create array type %s\n", name);
  212. return -1;
  213. }
  214. len = fmtf->size / fmtf->arraylen;
  215. n_items = fmtf->arraylen;
  216. } else {
  217. n_items = 1;
  218. array_field = NULL;
  219. }
  220. type = get_tracepoint_field_type(cw, fmtf);
  221. for (i = 0; i < n_items; i++) {
  222. if (flags & FIELD_IS_ARRAY)
  223. field = bt_ctf_field_array_get_field(array_field, i);
  224. else
  225. field = bt_ctf_field_create(type);
  226. if (!field) {
  227. pr_err("failed to create a field %s\n", name);
  228. return -1;
  229. }
  230. if (flags & FIELD_IS_STRING)
  231. ret = bt_ctf_field_string_set_value(field,
  232. data + offset + i * len);
  233. else {
  234. unsigned long long value_int;
  235. value_int = pevent_read_number(
  236. fmtf->event->pevent,
  237. data + offset + i * len, len);
  238. if (!(flags & FIELD_IS_SIGNED))
  239. ret = bt_ctf_field_unsigned_integer_set_value(
  240. field, value_int);
  241. else
  242. ret = bt_ctf_field_signed_integer_set_value(
  243. field, adjust_signedness(value_int, len));
  244. }
  245. if (ret) {
  246. pr_err("failed to set file value %s\n", name);
  247. goto err_put_field;
  248. }
  249. if (!(flags & FIELD_IS_ARRAY)) {
  250. ret = bt_ctf_event_set_payload(event, name, field);
  251. if (ret) {
  252. pr_err("failed to set payload %s\n", name);
  253. goto err_put_field;
  254. }
  255. }
  256. bt_ctf_field_put(field);
  257. }
  258. if (flags & FIELD_IS_ARRAY) {
  259. ret = bt_ctf_event_set_payload(event, name, array_field);
  260. if (ret) {
  261. pr_err("Failed add payload array %s\n", name);
  262. return -1;
  263. }
  264. bt_ctf_field_put(array_field);
  265. }
  266. return 0;
  267. err_put_field:
  268. bt_ctf_field_put(field);
  269. return -1;
  270. }
  271. static int add_tracepoint_fields_values(struct ctf_writer *cw,
  272. struct bt_ctf_event_class *event_class,
  273. struct bt_ctf_event *event,
  274. struct format_field *fields,
  275. struct perf_sample *sample)
  276. {
  277. struct format_field *field;
  278. int ret;
  279. for (field = fields; field; field = field->next) {
  280. ret = add_tracepoint_field_value(cw, event_class, event, sample,
  281. field);
  282. if (ret)
  283. return -1;
  284. }
  285. return 0;
  286. }
  287. static int add_tracepoint_values(struct ctf_writer *cw,
  288. struct bt_ctf_event_class *event_class,
  289. struct bt_ctf_event *event,
  290. struct perf_evsel *evsel,
  291. struct perf_sample *sample)
  292. {
  293. struct format_field *common_fields = evsel->tp_format->format.common_fields;
  294. struct format_field *fields = evsel->tp_format->format.fields;
  295. int ret;
  296. ret = add_tracepoint_fields_values(cw, event_class, event,
  297. common_fields, sample);
  298. if (!ret)
  299. ret = add_tracepoint_fields_values(cw, event_class, event,
  300. fields, sample);
  301. return ret;
  302. }
  303. static int add_generic_values(struct ctf_writer *cw,
  304. struct bt_ctf_event *event,
  305. struct perf_evsel *evsel,
  306. struct perf_sample *sample)
  307. {
  308. u64 type = evsel->attr.sample_type;
  309. int ret;
  310. /*
  311. * missing:
  312. * PERF_SAMPLE_TIME - not needed as we have it in
  313. * ctf event header
  314. * PERF_SAMPLE_READ - TODO
  315. * PERF_SAMPLE_CALLCHAIN - TODO
  316. * PERF_SAMPLE_RAW - tracepoint fields are handled separately
  317. * PERF_SAMPLE_BRANCH_STACK - TODO
  318. * PERF_SAMPLE_REGS_USER - TODO
  319. * PERF_SAMPLE_STACK_USER - TODO
  320. */
  321. if (type & PERF_SAMPLE_IP) {
  322. ret = value_set_u64_hex(cw, event, "perf_ip", sample->ip);
  323. if (ret)
  324. return -1;
  325. }
  326. if (type & PERF_SAMPLE_TID) {
  327. ret = value_set_s32(cw, event, "perf_tid", sample->tid);
  328. if (ret)
  329. return -1;
  330. ret = value_set_s32(cw, event, "perf_pid", sample->pid);
  331. if (ret)
  332. return -1;
  333. }
  334. if ((type & PERF_SAMPLE_ID) ||
  335. (type & PERF_SAMPLE_IDENTIFIER)) {
  336. ret = value_set_u64(cw, event, "perf_id", sample->id);
  337. if (ret)
  338. return -1;
  339. }
  340. if (type & PERF_SAMPLE_STREAM_ID) {
  341. ret = value_set_u64(cw, event, "perf_stream_id", sample->stream_id);
  342. if (ret)
  343. return -1;
  344. }
  345. if (type & PERF_SAMPLE_PERIOD) {
  346. ret = value_set_u64(cw, event, "perf_period", sample->period);
  347. if (ret)
  348. return -1;
  349. }
  350. if (type & PERF_SAMPLE_WEIGHT) {
  351. ret = value_set_u64(cw, event, "perf_weight", sample->weight);
  352. if (ret)
  353. return -1;
  354. }
  355. if (type & PERF_SAMPLE_DATA_SRC) {
  356. ret = value_set_u64(cw, event, "perf_data_src",
  357. sample->data_src);
  358. if (ret)
  359. return -1;
  360. }
  361. if (type & PERF_SAMPLE_TRANSACTION) {
  362. ret = value_set_u64(cw, event, "perf_transaction",
  363. sample->transaction);
  364. if (ret)
  365. return -1;
  366. }
  367. return 0;
  368. }
  369. static int ctf_stream__flush(struct ctf_stream *cs)
  370. {
  371. int err = 0;
  372. if (cs) {
  373. err = bt_ctf_stream_flush(cs->stream);
  374. if (err)
  375. pr_err("CTF stream %d flush failed\n", cs->cpu);
  376. pr("Flush stream for cpu %d (%u samples)\n",
  377. cs->cpu, cs->count);
  378. cs->count = 0;
  379. }
  380. return err;
  381. }
  382. static struct ctf_stream *ctf_stream__create(struct ctf_writer *cw, int cpu)
  383. {
  384. struct ctf_stream *cs;
  385. struct bt_ctf_field *pkt_ctx = NULL;
  386. struct bt_ctf_field *cpu_field = NULL;
  387. struct bt_ctf_stream *stream = NULL;
  388. int ret;
  389. cs = zalloc(sizeof(*cs));
  390. if (!cs) {
  391. pr_err("Failed to allocate ctf stream\n");
  392. return NULL;
  393. }
  394. stream = bt_ctf_writer_create_stream(cw->writer, cw->stream_class);
  395. if (!stream) {
  396. pr_err("Failed to create CTF stream\n");
  397. goto out;
  398. }
  399. pkt_ctx = bt_ctf_stream_get_packet_context(stream);
  400. if (!pkt_ctx) {
  401. pr_err("Failed to obtain packet context\n");
  402. goto out;
  403. }
  404. cpu_field = bt_ctf_field_structure_get_field(pkt_ctx, "cpu_id");
  405. bt_ctf_field_put(pkt_ctx);
  406. if (!cpu_field) {
  407. pr_err("Failed to obtain cpu field\n");
  408. goto out;
  409. }
  410. ret = bt_ctf_field_unsigned_integer_set_value(cpu_field, (u32) cpu);
  411. if (ret) {
  412. pr_err("Failed to update CPU number\n");
  413. goto out;
  414. }
  415. bt_ctf_field_put(cpu_field);
  416. cs->cpu = cpu;
  417. cs->stream = stream;
  418. return cs;
  419. out:
  420. if (cpu_field)
  421. bt_ctf_field_put(cpu_field);
  422. if (stream)
  423. bt_ctf_stream_put(stream);
  424. free(cs);
  425. return NULL;
  426. }
  427. static void ctf_stream__delete(struct ctf_stream *cs)
  428. {
  429. if (cs) {
  430. bt_ctf_stream_put(cs->stream);
  431. free(cs);
  432. }
  433. }
  434. static struct ctf_stream *ctf_stream(struct ctf_writer *cw, int cpu)
  435. {
  436. struct ctf_stream *cs = cw->stream[cpu];
  437. if (!cs) {
  438. cs = ctf_stream__create(cw, cpu);
  439. cw->stream[cpu] = cs;
  440. }
  441. return cs;
  442. }
  443. static int get_sample_cpu(struct ctf_writer *cw, struct perf_sample *sample,
  444. struct perf_evsel *evsel)
  445. {
  446. int cpu = 0;
  447. if (evsel->attr.sample_type & PERF_SAMPLE_CPU)
  448. cpu = sample->cpu;
  449. if (cpu > cw->stream_cnt) {
  450. pr_err("Event was recorded for CPU %d, limit is at %d.\n",
  451. cpu, cw->stream_cnt);
  452. cpu = 0;
  453. }
  454. return cpu;
  455. }
  456. #define STREAM_FLUSH_COUNT 100000
  457. /*
  458. * Currently we have no other way to determine the
  459. * time for the stream flush other than keep track
  460. * of the number of events and check it against
  461. * threshold.
  462. */
  463. static bool is_flush_needed(struct ctf_stream *cs)
  464. {
  465. return cs->count >= STREAM_FLUSH_COUNT;
  466. }
  467. static int process_sample_event(struct perf_tool *tool,
  468. union perf_event *_event __maybe_unused,
  469. struct perf_sample *sample,
  470. struct perf_evsel *evsel,
  471. struct machine *machine __maybe_unused)
  472. {
  473. struct convert *c = container_of(tool, struct convert, tool);
  474. struct evsel_priv *priv = evsel->priv;
  475. struct ctf_writer *cw = &c->writer;
  476. struct ctf_stream *cs;
  477. struct bt_ctf_event_class *event_class;
  478. struct bt_ctf_event *event;
  479. int ret;
  480. if (WARN_ONCE(!priv, "Failed to setup all events.\n"))
  481. return 0;
  482. event_class = priv->event_class;
  483. /* update stats */
  484. c->events_count++;
  485. c->events_size += _event->header.size;
  486. pr_time2(sample->time, "sample %" PRIu64 "\n", c->events_count);
  487. event = bt_ctf_event_create(event_class);
  488. if (!event) {
  489. pr_err("Failed to create an CTF event\n");
  490. return -1;
  491. }
  492. bt_ctf_clock_set_time(cw->clock, sample->time);
  493. ret = add_generic_values(cw, event, evsel, sample);
  494. if (ret)
  495. return -1;
  496. if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
  497. ret = add_tracepoint_values(cw, event_class, event,
  498. evsel, sample);
  499. if (ret)
  500. return -1;
  501. }
  502. cs = ctf_stream(cw, get_sample_cpu(cw, sample, evsel));
  503. if (cs) {
  504. if (is_flush_needed(cs))
  505. ctf_stream__flush(cs);
  506. cs->count++;
  507. bt_ctf_stream_append_event(cs->stream, event);
  508. }
  509. bt_ctf_event_put(event);
  510. return cs ? 0 : -1;
  511. }
  512. /* If dup < 0, add a prefix. Else, add _dupl_X suffix. */
  513. static char *change_name(char *name, char *orig_name, int dup)
  514. {
  515. char *new_name = NULL;
  516. size_t len;
  517. if (!name)
  518. name = orig_name;
  519. if (dup >= 10)
  520. goto out;
  521. /*
  522. * Add '_' prefix to potential keywork. According to
  523. * Mathieu Desnoyers (https://lkml.org/lkml/2015/1/23/652),
  524. * futher CTF spec updating may require us to use '$'.
  525. */
  526. if (dup < 0)
  527. len = strlen(name) + sizeof("_");
  528. else
  529. len = strlen(orig_name) + sizeof("_dupl_X");
  530. new_name = malloc(len);
  531. if (!new_name)
  532. goto out;
  533. if (dup < 0)
  534. snprintf(new_name, len, "_%s", name);
  535. else
  536. snprintf(new_name, len, "%s_dupl_%d", orig_name, dup);
  537. out:
  538. if (name != orig_name)
  539. free(name);
  540. return new_name;
  541. }
  542. static int event_class_add_field(struct bt_ctf_event_class *event_class,
  543. struct bt_ctf_field_type *type,
  544. struct format_field *field)
  545. {
  546. struct bt_ctf_field_type *t = NULL;
  547. char *name;
  548. int dup = 1;
  549. int ret;
  550. /* alias was already assigned */
  551. if (field->alias != field->name)
  552. return bt_ctf_event_class_add_field(event_class, type,
  553. (char *)field->alias);
  554. name = field->name;
  555. /* If 'name' is a keywork, add prefix. */
  556. if (bt_ctf_validate_identifier(name))
  557. name = change_name(name, field->name, -1);
  558. if (!name) {
  559. pr_err("Failed to fix invalid identifier.");
  560. return -1;
  561. }
  562. while ((t = bt_ctf_event_class_get_field_by_name(event_class, name))) {
  563. bt_ctf_field_type_put(t);
  564. name = change_name(name, field->name, dup++);
  565. if (!name) {
  566. pr_err("Failed to create dup name for '%s'\n", field->name);
  567. return -1;
  568. }
  569. }
  570. ret = bt_ctf_event_class_add_field(event_class, type, name);
  571. if (!ret)
  572. field->alias = name;
  573. return ret;
  574. }
  575. static int add_tracepoint_fields_types(struct ctf_writer *cw,
  576. struct format_field *fields,
  577. struct bt_ctf_event_class *event_class)
  578. {
  579. struct format_field *field;
  580. int ret;
  581. for (field = fields; field; field = field->next) {
  582. struct bt_ctf_field_type *type;
  583. unsigned long flags = field->flags;
  584. pr2(" field '%s'\n", field->name);
  585. type = get_tracepoint_field_type(cw, field);
  586. if (!type)
  587. return -1;
  588. /*
  589. * A string is an array of chars. For this we use the string
  590. * type and don't care that it is an array. What we don't
  591. * support is an array of strings.
  592. */
  593. if (flags & FIELD_IS_STRING)
  594. flags &= ~FIELD_IS_ARRAY;
  595. if (flags & FIELD_IS_ARRAY)
  596. type = bt_ctf_field_type_array_create(type, field->arraylen);
  597. ret = event_class_add_field(event_class, type, field);
  598. if (flags & FIELD_IS_ARRAY)
  599. bt_ctf_field_type_put(type);
  600. if (ret) {
  601. pr_err("Failed to add field '%s': %d\n",
  602. field->name, ret);
  603. return -1;
  604. }
  605. }
  606. return 0;
  607. }
  608. static int add_tracepoint_types(struct ctf_writer *cw,
  609. struct perf_evsel *evsel,
  610. struct bt_ctf_event_class *class)
  611. {
  612. struct format_field *common_fields = evsel->tp_format->format.common_fields;
  613. struct format_field *fields = evsel->tp_format->format.fields;
  614. int ret;
  615. ret = add_tracepoint_fields_types(cw, common_fields, class);
  616. if (!ret)
  617. ret = add_tracepoint_fields_types(cw, fields, class);
  618. return ret;
  619. }
  620. static int add_generic_types(struct ctf_writer *cw, struct perf_evsel *evsel,
  621. struct bt_ctf_event_class *event_class)
  622. {
  623. u64 type = evsel->attr.sample_type;
  624. /*
  625. * missing:
  626. * PERF_SAMPLE_TIME - not needed as we have it in
  627. * ctf event header
  628. * PERF_SAMPLE_READ - TODO
  629. * PERF_SAMPLE_CALLCHAIN - TODO
  630. * PERF_SAMPLE_RAW - tracepoint fields are handled separately
  631. * PERF_SAMPLE_BRANCH_STACK - TODO
  632. * PERF_SAMPLE_REGS_USER - TODO
  633. * PERF_SAMPLE_STACK_USER - TODO
  634. */
  635. #define ADD_FIELD(cl, t, n) \
  636. do { \
  637. pr2(" field '%s'\n", n); \
  638. if (bt_ctf_event_class_add_field(cl, t, n)) { \
  639. pr_err("Failed to add field '%s';\n", n); \
  640. return -1; \
  641. } \
  642. } while (0)
  643. if (type & PERF_SAMPLE_IP)
  644. ADD_FIELD(event_class, cw->data.u64_hex, "perf_ip");
  645. if (type & PERF_SAMPLE_TID) {
  646. ADD_FIELD(event_class, cw->data.s32, "perf_tid");
  647. ADD_FIELD(event_class, cw->data.s32, "perf_pid");
  648. }
  649. if ((type & PERF_SAMPLE_ID) ||
  650. (type & PERF_SAMPLE_IDENTIFIER))
  651. ADD_FIELD(event_class, cw->data.u64, "perf_id");
  652. if (type & PERF_SAMPLE_STREAM_ID)
  653. ADD_FIELD(event_class, cw->data.u64, "perf_stream_id");
  654. if (type & PERF_SAMPLE_PERIOD)
  655. ADD_FIELD(event_class, cw->data.u64, "perf_period");
  656. if (type & PERF_SAMPLE_WEIGHT)
  657. ADD_FIELD(event_class, cw->data.u64, "perf_weight");
  658. if (type & PERF_SAMPLE_DATA_SRC)
  659. ADD_FIELD(event_class, cw->data.u64, "perf_data_src");
  660. if (type & PERF_SAMPLE_TRANSACTION)
  661. ADD_FIELD(event_class, cw->data.u64, "perf_transaction");
  662. #undef ADD_FIELD
  663. return 0;
  664. }
  665. static int add_event(struct ctf_writer *cw, struct perf_evsel *evsel)
  666. {
  667. struct bt_ctf_event_class *event_class;
  668. struct evsel_priv *priv;
  669. const char *name = perf_evsel__name(evsel);
  670. int ret;
  671. pr("Adding event '%s' (type %d)\n", name, evsel->attr.type);
  672. event_class = bt_ctf_event_class_create(name);
  673. if (!event_class)
  674. return -1;
  675. ret = add_generic_types(cw, evsel, event_class);
  676. if (ret)
  677. goto err;
  678. if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
  679. ret = add_tracepoint_types(cw, evsel, event_class);
  680. if (ret)
  681. goto err;
  682. }
  683. ret = bt_ctf_stream_class_add_event_class(cw->stream_class, event_class);
  684. if (ret) {
  685. pr("Failed to add event class into stream.\n");
  686. goto err;
  687. }
  688. priv = malloc(sizeof(*priv));
  689. if (!priv)
  690. goto err;
  691. priv->event_class = event_class;
  692. evsel->priv = priv;
  693. return 0;
  694. err:
  695. bt_ctf_event_class_put(event_class);
  696. pr_err("Failed to add event '%s'.\n", name);
  697. return -1;
  698. }
  699. static int setup_events(struct ctf_writer *cw, struct perf_session *session)
  700. {
  701. struct perf_evlist *evlist = session->evlist;
  702. struct perf_evsel *evsel;
  703. int ret;
  704. evlist__for_each(evlist, evsel) {
  705. ret = add_event(cw, evsel);
  706. if (ret)
  707. return ret;
  708. }
  709. return 0;
  710. }
  711. static int setup_streams(struct ctf_writer *cw, struct perf_session *session)
  712. {
  713. struct ctf_stream **stream;
  714. struct perf_header *ph = &session->header;
  715. int ncpus;
  716. /*
  717. * Try to get the number of cpus used in the data file,
  718. * if not present fallback to the MAX_CPUS.
  719. */
  720. ncpus = ph->env.nr_cpus_avail ?: MAX_CPUS;
  721. stream = zalloc(sizeof(*stream) * ncpus);
  722. if (!stream) {
  723. pr_err("Failed to allocate streams.\n");
  724. return -ENOMEM;
  725. }
  726. cw->stream = stream;
  727. cw->stream_cnt = ncpus;
  728. return 0;
  729. }
  730. static void free_streams(struct ctf_writer *cw)
  731. {
  732. int cpu;
  733. for (cpu = 0; cpu < cw->stream_cnt; cpu++)
  734. ctf_stream__delete(cw->stream[cpu]);
  735. free(cw->stream);
  736. }
  737. static int ctf_writer__setup_env(struct ctf_writer *cw,
  738. struct perf_session *session)
  739. {
  740. struct perf_header *header = &session->header;
  741. struct bt_ctf_writer *writer = cw->writer;
  742. #define ADD(__n, __v) \
  743. do { \
  744. if (bt_ctf_writer_add_environment_field(writer, __n, __v)) \
  745. return -1; \
  746. } while (0)
  747. ADD("host", header->env.hostname);
  748. ADD("sysname", "Linux");
  749. ADD("release", header->env.os_release);
  750. ADD("version", header->env.version);
  751. ADD("machine", header->env.arch);
  752. ADD("domain", "kernel");
  753. ADD("tracer_name", "perf");
  754. #undef ADD
  755. return 0;
  756. }
  757. static int ctf_writer__setup_clock(struct ctf_writer *cw)
  758. {
  759. struct bt_ctf_clock *clock = cw->clock;
  760. bt_ctf_clock_set_description(clock, "perf clock");
  761. #define SET(__n, __v) \
  762. do { \
  763. if (bt_ctf_clock_set_##__n(clock, __v)) \
  764. return -1; \
  765. } while (0)
  766. SET(frequency, 1000000000);
  767. SET(offset_s, 0);
  768. SET(offset, 0);
  769. SET(precision, 10);
  770. SET(is_absolute, 0);
  771. #undef SET
  772. return 0;
  773. }
  774. static struct bt_ctf_field_type *create_int_type(int size, bool sign, bool hex)
  775. {
  776. struct bt_ctf_field_type *type;
  777. type = bt_ctf_field_type_integer_create(size);
  778. if (!type)
  779. return NULL;
  780. if (sign &&
  781. bt_ctf_field_type_integer_set_signed(type, 1))
  782. goto err;
  783. if (hex &&
  784. bt_ctf_field_type_integer_set_base(type, BT_CTF_INTEGER_BASE_HEXADECIMAL))
  785. goto err;
  786. pr2("Created type: INTEGER %d-bit %ssigned %s\n",
  787. size, sign ? "un" : "", hex ? "hex" : "");
  788. return type;
  789. err:
  790. bt_ctf_field_type_put(type);
  791. return NULL;
  792. }
  793. static void ctf_writer__cleanup_data(struct ctf_writer *cw)
  794. {
  795. unsigned int i;
  796. for (i = 0; i < ARRAY_SIZE(cw->data.array); i++)
  797. bt_ctf_field_type_put(cw->data.array[i]);
  798. }
  799. static int ctf_writer__init_data(struct ctf_writer *cw)
  800. {
  801. #define CREATE_INT_TYPE(type, size, sign, hex) \
  802. do { \
  803. (type) = create_int_type(size, sign, hex); \
  804. if (!(type)) \
  805. goto err; \
  806. } while (0)
  807. CREATE_INT_TYPE(cw->data.s64, 64, true, false);
  808. CREATE_INT_TYPE(cw->data.u64, 64, false, false);
  809. CREATE_INT_TYPE(cw->data.s32, 32, true, false);
  810. CREATE_INT_TYPE(cw->data.u32, 32, false, false);
  811. CREATE_INT_TYPE(cw->data.u64_hex, 64, false, true);
  812. cw->data.string = bt_ctf_field_type_string_create();
  813. if (cw->data.string)
  814. return 0;
  815. err:
  816. ctf_writer__cleanup_data(cw);
  817. pr_err("Failed to create data types.\n");
  818. return -1;
  819. }
  820. static void ctf_writer__cleanup(struct ctf_writer *cw)
  821. {
  822. ctf_writer__cleanup_data(cw);
  823. bt_ctf_clock_put(cw->clock);
  824. free_streams(cw);
  825. bt_ctf_stream_class_put(cw->stream_class);
  826. bt_ctf_writer_put(cw->writer);
  827. /* and NULL all the pointers */
  828. memset(cw, 0, sizeof(*cw));
  829. }
  830. static int ctf_writer__init(struct ctf_writer *cw, const char *path)
  831. {
  832. struct bt_ctf_writer *writer;
  833. struct bt_ctf_stream_class *stream_class;
  834. struct bt_ctf_clock *clock;
  835. struct bt_ctf_field_type *pkt_ctx_type;
  836. int ret;
  837. /* CTF writer */
  838. writer = bt_ctf_writer_create(path);
  839. if (!writer)
  840. goto err;
  841. cw->writer = writer;
  842. /* CTF clock */
  843. clock = bt_ctf_clock_create("perf_clock");
  844. if (!clock) {
  845. pr("Failed to create CTF clock.\n");
  846. goto err_cleanup;
  847. }
  848. cw->clock = clock;
  849. if (ctf_writer__setup_clock(cw)) {
  850. pr("Failed to setup CTF clock.\n");
  851. goto err_cleanup;
  852. }
  853. /* CTF stream class */
  854. stream_class = bt_ctf_stream_class_create("perf_stream");
  855. if (!stream_class) {
  856. pr("Failed to create CTF stream class.\n");
  857. goto err_cleanup;
  858. }
  859. cw->stream_class = stream_class;
  860. /* CTF clock stream setup */
  861. if (bt_ctf_stream_class_set_clock(stream_class, clock)) {
  862. pr("Failed to assign CTF clock to stream class.\n");
  863. goto err_cleanup;
  864. }
  865. if (ctf_writer__init_data(cw))
  866. goto err_cleanup;
  867. /* Add cpu_id for packet context */
  868. pkt_ctx_type = bt_ctf_stream_class_get_packet_context_type(stream_class);
  869. if (!pkt_ctx_type)
  870. goto err_cleanup;
  871. ret = bt_ctf_field_type_structure_add_field(pkt_ctx_type, cw->data.u32, "cpu_id");
  872. bt_ctf_field_type_put(pkt_ctx_type);
  873. if (ret)
  874. goto err_cleanup;
  875. /* CTF clock writer setup */
  876. if (bt_ctf_writer_add_clock(writer, clock)) {
  877. pr("Failed to assign CTF clock to writer.\n");
  878. goto err_cleanup;
  879. }
  880. return 0;
  881. err_cleanup:
  882. ctf_writer__cleanup(cw);
  883. err:
  884. pr_err("Failed to setup CTF writer.\n");
  885. return -1;
  886. }
  887. static int ctf_writer__flush_streams(struct ctf_writer *cw)
  888. {
  889. int cpu, ret = 0;
  890. for (cpu = 0; cpu < cw->stream_cnt && !ret; cpu++)
  891. ret = ctf_stream__flush(cw->stream[cpu]);
  892. return ret;
  893. }
  894. static int convert__config(const char *var, const char *value, void *cb)
  895. {
  896. struct convert *c = cb;
  897. if (!strcmp(var, "convert.queue-size")) {
  898. c->queue_size = perf_config_u64(var, value);
  899. return 0;
  900. }
  901. return perf_default_config(var, value, cb);
  902. }
  903. int bt_convert__perf2ctf(const char *input, const char *path, bool force)
  904. {
  905. struct perf_session *session;
  906. struct perf_data_file file = {
  907. .path = input,
  908. .mode = PERF_DATA_MODE_READ,
  909. .force = force,
  910. };
  911. struct convert c = {
  912. .tool = {
  913. .sample = process_sample_event,
  914. .mmap = perf_event__process_mmap,
  915. .mmap2 = perf_event__process_mmap2,
  916. .comm = perf_event__process_comm,
  917. .exit = perf_event__process_exit,
  918. .fork = perf_event__process_fork,
  919. .lost = perf_event__process_lost,
  920. .tracing_data = perf_event__process_tracing_data,
  921. .build_id = perf_event__process_build_id,
  922. .ordered_events = true,
  923. .ordering_requires_timestamps = true,
  924. },
  925. };
  926. struct ctf_writer *cw = &c.writer;
  927. int err = -1;
  928. perf_config(convert__config, &c);
  929. /* CTF writer */
  930. if (ctf_writer__init(cw, path))
  931. return -1;
  932. /* perf.data session */
  933. session = perf_session__new(&file, 0, &c.tool);
  934. if (!session)
  935. goto free_writer;
  936. if (c.queue_size) {
  937. ordered_events__set_alloc_size(&session->ordered_events,
  938. c.queue_size);
  939. }
  940. /* CTF writer env/clock setup */
  941. if (ctf_writer__setup_env(cw, session))
  942. goto free_session;
  943. /* CTF events setup */
  944. if (setup_events(cw, session))
  945. goto free_session;
  946. if (setup_streams(cw, session))
  947. goto free_session;
  948. err = perf_session__process_events(session);
  949. if (!err)
  950. err = ctf_writer__flush_streams(cw);
  951. else
  952. pr_err("Error during conversion.\n");
  953. fprintf(stderr,
  954. "[ perf data convert: Converted '%s' into CTF data '%s' ]\n",
  955. file.path, path);
  956. fprintf(stderr,
  957. "[ perf data convert: Converted and wrote %.3f MB (%" PRIu64 " samples) ]\n",
  958. (double) c.events_size / 1024.0 / 1024.0,
  959. c.events_count);
  960. perf_session__delete(session);
  961. ctf_writer__cleanup(cw);
  962. return err;
  963. free_session:
  964. perf_session__delete(session);
  965. free_writer:
  966. ctf_writer__cleanup(cw);
  967. pr_err("Error during conversion setup.\n");
  968. return err;
  969. }