debug-info refactoring
[babeltrace.git] / plugins / lttng-utils / copy.c
1 /*
2 * copy.c
3 *
4 * Babeltrace Copy Trace Structure
5 *
6 * Copyright 2017 Julien Desfossez <jdesfossez@efficios.com>
7 *
8 * Author: Julien Desfossez <jdesfossez@efficios.com>
9 *
10 * Permission is hereby granted, free of charge, to any person obtaining a copy
11 * of this software and associated documentation files (the "Software"), to deal
12 * in the Software without restriction, including without limitation the rights
13 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 * copies of the Software, and to permit persons to whom the Software is
15 * furnished to do so, subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 */
28
29 #include <inttypes.h>
30 #include <babeltrace/ctf-ir/event.h>
31 #include <babeltrace/ctf-ir/packet.h>
32 #include <babeltrace/ctf-ir/event-class.h>
33 #include <babeltrace/ctf-ir/stream.h>
34 #include <babeltrace/ctf-ir/stream-class.h>
35 #include <babeltrace/ctf-ir/clock-class.h>
36 #include <babeltrace/ctf-ir/fields.h>
37 #include <babeltrace/ctf-writer/stream-class.h>
38 #include <babeltrace/ctf-writer/stream.h>
39
40 #include <ctfcopytrace.h>
41 #include "debug-info.h"
42
43 static
44 void unref_stream(struct bt_ctf_stream *stream)
45 {
46 bt_put(stream);
47 }
48
49 static
50 void unref_packet(struct bt_ctf_packet *packet)
51 {
52 bt_put(packet);
53 }
54
55 static
56 void unref_stream_class(struct bt_ctf_stream_class *stream_class)
57 {
58 bt_put(stream_class);
59 }
60
61 static
62 void unref_debug_info(struct debug_info *debug_info)
63 {
64 debug_info_destroy(debug_info);
65 }
66
67 static
68 struct bt_ctf_field *get_payload_field(FILE *err,
69 struct bt_ctf_event *event, const char *field_name)
70 {
71 struct bt_ctf_field *field = NULL, *sec = NULL;
72 struct bt_ctf_field_type *sec_type = NULL;
73
74 sec = bt_ctf_event_get_payload(event, NULL);
75 if (!sec) {
76 fprintf(err, "[error] %s in %s:%d\n", __func__,
77 __FILE__, __LINE__);
78 goto end;
79 }
80
81 sec_type = bt_ctf_field_get_type(sec);
82 if (!sec_type) {
83 fprintf(err, "[error] %s in %s:%d\n", __func__,
84 __FILE__, __LINE__);
85 goto end;
86 }
87
88 if (bt_ctf_field_type_get_type_id(sec_type) != BT_CTF_FIELD_TYPE_ID_STRUCT) {
89 fprintf(err, "[error] %s in %s:%d\n", __func__,
90 __FILE__, __LINE__);
91 goto end;
92 }
93
94 field = bt_ctf_field_structure_get_field(sec, field_name);
95
96 end:
97 bt_put(sec_type);
98 bt_put(sec);
99 return field;
100 }
101
102 static
103 struct bt_ctf_field *get_stream_event_context_field(FILE *err,
104 struct bt_ctf_event *event, const char *field_name)
105 {
106 struct bt_ctf_field *field = NULL, *sec = NULL;
107 struct bt_ctf_field_type *sec_type = NULL;
108
109 sec = bt_ctf_event_get_stream_event_context(event);
110 if (!sec) {
111 goto end;
112 }
113
114 sec_type = bt_ctf_field_get_type(sec);
115 if (!sec_type) {
116 fprintf(err, "[error] %s in %s:%d\n", __func__,
117 __FILE__, __LINE__);
118 goto end;
119 }
120
121 if (bt_ctf_field_type_get_type_id(sec_type) != BT_CTF_FIELD_TYPE_ID_STRUCT) {
122 fprintf(err, "[error] %s in %s:%d\n", __func__,
123 __FILE__, __LINE__);
124 goto end;
125 }
126
127 field = bt_ctf_field_structure_get_field(sec, field_name);
128
129 end:
130 bt_put(sec_type);
131 bt_put(sec);
132 return field;
133 }
134
135 BT_HIDDEN
136 int get_stream_event_context_unsigned_int_field_value(FILE *err,
137 struct bt_ctf_event *event, const char *field_name,
138 uint64_t *value)
139 {
140 int ret;
141 struct bt_ctf_field *field = NULL;
142 struct bt_ctf_field_type *field_type = NULL;
143
144 field = get_stream_event_context_field(err, event, field_name);
145 if (!field) {
146 goto error;
147 }
148
149 field_type = bt_ctf_field_get_type(field);
150 if (!field_type) {
151 fprintf(err, "[error] %s in %s:%d\n", __func__,
152 __FILE__, __LINE__);
153 goto error;
154 }
155
156 if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) {
157 fprintf(err, "[error] %s in %s:%d\n", __func__,
158 __FILE__, __LINE__);
159 goto error;
160 }
161
162 if (bt_ctf_field_type_integer_get_signed(field_type) != 0) {
163 fprintf(err, "[error] %s in %s:%d\n", __func__,
164 __FILE__, __LINE__);
165 goto error;
166 }
167
168 ret = bt_ctf_field_unsigned_integer_get_value(field, value);
169 goto end;
170
171 error:
172 ret = -1;
173 end:
174 bt_put(field_type);
175 bt_put(field);
176 return ret;
177 }
178
179 BT_HIDDEN
180 int get_stream_event_context_int_field_value(FILE *err, struct bt_ctf_event *event,
181 const char *field_name, int64_t *value)
182 {
183 struct bt_ctf_field *field = NULL;
184 struct bt_ctf_field_type *field_type = NULL;
185 int ret;
186
187 field = get_stream_event_context_field(err, event, field_name);
188 if (!field) {
189 goto error;
190 }
191
192 field_type = bt_ctf_field_get_type(field);
193 if (!field_type) {
194 fprintf(err, "[error] %s in %s:%d\n", __func__,
195 __FILE__, __LINE__);
196 goto error;
197 }
198
199 if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) {
200 fprintf(err, "[error] %s in %s:%d\n", __func__,
201 __FILE__, __LINE__);
202 goto error;
203 }
204
205 if (bt_ctf_field_type_integer_get_signed(field_type) != 1) {
206 fprintf(err, "[error] %s in %s:%d\n", __func__,
207 __FILE__, __LINE__);
208 goto error;
209 }
210
211 ret = bt_ctf_field_signed_integer_get_value(field, value);
212 goto end;
213
214 error:
215 ret = -1;
216 end:
217 bt_put(field_type);
218 bt_put(field);
219 return ret;
220 }
221
222 BT_HIDDEN
223 int get_payload_unsigned_int_field_value(FILE *err,
224 struct bt_ctf_event *event, const char *field_name,
225 uint64_t *value)
226 {
227 struct bt_ctf_field *field = NULL;
228 struct bt_ctf_field_type *field_type = NULL;
229 int ret;
230
231 field = get_payload_field(err, event, field_name);
232 if (!field) {
233 fprintf(err, "[error] %s in %s:%d\n", __func__,
234 __FILE__, __LINE__);
235 goto error;
236 }
237
238 field_type = bt_ctf_field_get_type(field);
239 if (!field_type) {
240 fprintf(err, "[error] %s in %s:%d\n", __func__,
241 __FILE__, __LINE__);
242 goto error;
243 }
244
245 if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) {
246 fprintf(err, "[error] %s in %s:%d\n", __func__,
247 __FILE__, __LINE__);
248 goto error;
249 }
250
251 if (bt_ctf_field_type_integer_get_signed(field_type) != 0) {
252 fprintf(err, "[error] %s in %s:%d\n", __func__,
253 __FILE__, __LINE__);
254 goto error;
255 }
256
257 ret = bt_ctf_field_unsigned_integer_get_value(field, value);
258 goto end;
259
260 error:
261 ret = -1;
262 end:
263 bt_put(field_type);
264 bt_put(field);
265 return ret;
266 }
267
268 BT_HIDDEN
269 int get_payload_int_field_value(FILE *err, struct bt_ctf_event *event,
270 const char *field_name, int64_t *value)
271 {
272 struct bt_ctf_field *field = NULL;
273 struct bt_ctf_field_type *field_type = NULL;
274 int ret;
275
276 field = get_payload_field(err, event, field_name);
277 if (!field) {
278 fprintf(err, "[error] %s in %s:%d\n", __func__,
279 __FILE__, __LINE__);
280 goto error;
281 }
282
283 field_type = bt_ctf_field_get_type(field);
284 if (!field_type) {
285 fprintf(err, "[error] %s in %s:%d\n", __func__,
286 __FILE__, __LINE__);
287 goto error;
288 }
289
290 if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_INTEGER) {
291 fprintf(err, "[error] %s in %s:%d\n", __func__,
292 __FILE__, __LINE__);
293 goto error;
294 }
295
296 if (bt_ctf_field_type_integer_get_signed(field_type) != 1) {
297 fprintf(err, "[error] %s in %s:%d\n", __func__,
298 __FILE__, __LINE__);
299 goto error;
300 }
301
302 ret = bt_ctf_field_signed_integer_get_value(field, value);
303 goto end;
304
305 error:
306 ret = -1;
307 end:
308 bt_put(field_type);
309 bt_put(field);
310 return ret;
311 }
312
313 BT_HIDDEN
314 int get_payload_string_field_value(FILE *err,
315 struct bt_ctf_event *event, const char *field_name,
316 const char **value)
317 {
318 struct bt_ctf_field *field = NULL;
319 struct bt_ctf_field_type *field_type = NULL;
320 int ret;
321
322 /*
323 * The field might not exist, no error here.
324 */
325 field = get_payload_field(err, event, field_name);
326 if (!field) {
327 goto error;
328 }
329
330 field_type = bt_ctf_field_get_type(field);
331 if (!field_type) {
332 fprintf(err, "[error] %s in %s:%d\n", __func__,
333 __FILE__, __LINE__);
334 goto error;
335 }
336
337 if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_STRING) {
338 fprintf(err, "[error] %s in %s:%d\n", __func__,
339 __FILE__, __LINE__);
340 goto error;
341 }
342
343 *value = bt_ctf_field_string_get_value(field);
344 if (!*value) {
345 fprintf(err, "[error] %s in %s:%d\n", __func__,
346 __FILE__, __LINE__);
347 goto error;
348 }
349
350 ret = 0;
351 goto end;
352
353 error:
354 ret = -1;
355 end:
356 bt_put(field_type);
357 bt_put(field);
358 return ret;
359 }
360
361 BT_HIDDEN
362 int get_payload_build_id_field_value(FILE *err,
363 struct bt_ctf_event *event, const char *field_name,
364 uint8_t **build_id, uint64_t *build_id_len)
365 {
366 struct bt_ctf_field *field = NULL, *seq_len = NULL;
367 struct bt_ctf_field_type *field_type = NULL;
368 struct bt_ctf_field *seq_field = NULL;
369 uint64_t i;
370 int ret;
371
372 *build_id = NULL;
373
374 field = get_payload_field(err, event, field_name);
375 if (!field) {
376 fprintf(err, "[error] %s in %s:%d\n", __func__,
377 __FILE__, __LINE__);
378 goto error;
379 }
380
381 field_type = bt_ctf_field_get_type(field);
382 if (!field_type) {
383 fprintf(err, "[error] %s in %s:%d\n", __func__,
384 __FILE__, __LINE__);
385 goto error;
386 }
387
388 if (bt_ctf_field_type_get_type_id(field_type) != BT_CTF_FIELD_TYPE_ID_SEQUENCE) {
389 fprintf(err, "[error] %s in %s:%d\n", __func__,
390 __FILE__, __LINE__);
391 goto error;
392 }
393 BT_PUT(field_type);
394
395 seq_len = bt_ctf_field_sequence_get_length(field);
396 if (!seq_len) {
397 fprintf(err, "[error] %s in %s:%d\n", __func__,
398 __FILE__, __LINE__);
399 goto error;
400 }
401
402 ret = bt_ctf_field_unsigned_integer_get_value(seq_len, build_id_len);
403 if (ret) {
404 fprintf(err, "[error] %s in %s:%d\n", __func__,
405 __FILE__, __LINE__);
406 goto error;
407 }
408 BT_PUT(seq_len);
409
410 *build_id = g_new0(uint8_t, *build_id_len);
411 if (!*build_id) {
412 fprintf(err, "[error] %s in %s:%d\n", __func__,
413 __FILE__, __LINE__);
414 goto error;
415 }
416
417 for (i = 0; i < *build_id_len; i++) {
418 uint64_t tmp;
419
420 seq_field = bt_ctf_field_sequence_get_field(field, i);
421 if (!seq_field) {
422 fprintf(err, "[error] %s in %s:%d\n", __func__,
423 __FILE__, __LINE__);
424 goto error;
425 }
426
427 ret = bt_ctf_field_unsigned_integer_get_value(seq_field, &tmp);
428 if (ret) {
429 fprintf(err, "[error] %s in %s:%d\n", __func__,
430 __FILE__, __LINE__);
431 goto error;
432 }
433 BT_PUT(seq_field);
434 (*build_id)[i] = (uint8_t) tmp;
435 }
436 ret = 0;
437 goto end;
438
439 error:
440 g_free(*build_id);
441 ret = -1;
442 end:
443 bt_put(field_type);
444 bt_put(field);
445 return ret;
446 }
447
448 static
449 struct debug_info *lookup_trace_debug_info(struct debug_info_iterator *debug_it,
450 struct bt_ctf_trace *writer_trace,
451 struct debug_info_trace *di_trace)
452 {
453 return (struct debug_info *) g_hash_table_lookup(
454 di_trace->trace_debug_map,
455 (gpointer) writer_trace);
456 }
457
458 static
459 struct debug_info *insert_new_debug_info(struct debug_info_iterator *debug_it,
460 struct bt_ctf_trace *writer_trace,
461 struct debug_info_trace *di_trace)
462 {
463 struct debug_info *debug_info = NULL;
464 struct bt_value *field = NULL;
465 const char *str_value;
466 enum bt_value_status ret;
467
468 field = bt_ctf_trace_get_environment_field_value_by_name(writer_trace,
469 "domain");
470 /* No domain field, no debug info */
471 if (!field) {
472 goto end;
473 }
474 ret = bt_value_string_get(field, &str_value);
475 if (ret != BT_VALUE_STATUS_OK) {
476 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
477 __FILE__, __LINE__);
478 goto end;
479 }
480 /* Domain not ust, no debug info */
481 if (strcmp(str_value, "ust") != 0) {
482 goto end;
483 }
484 BT_PUT(field);
485
486 /* No tracer_name, no debug info */
487 field = bt_ctf_trace_get_environment_field_value_by_name(writer_trace,
488 "tracer_name");
489 /* No tracer_name, no debug info */
490 if (!field) {
491 goto end;
492 }
493 ret = bt_value_string_get(field, &str_value);
494 if (ret != BT_VALUE_STATUS_OK) {
495 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
496 __FILE__, __LINE__);
497 goto end;
498 }
499 /* Tracer_name not lttng-ust, no debug info */
500 if (strcmp(str_value, "lttng-ust") != 0) {
501 goto end;
502 }
503 BT_PUT(field);
504
505 debug_info = debug_info_create(debug_it->debug_info_component);
506 if (!debug_info) {
507 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
508 __FILE__, __LINE__);
509 goto end;
510 }
511
512 g_hash_table_insert(di_trace->trace_debug_map, (gpointer) writer_trace,
513 debug_info);
514
515 end:
516 bt_put(field);
517 return debug_info;
518 }
519
520 static
521 struct debug_info *get_trace_debug_info(struct debug_info_iterator *debug_it,
522 struct bt_ctf_trace *writer_trace,
523 struct debug_info_trace *di_trace)
524 {
525 struct debug_info *debug_info;
526
527 debug_info = lookup_trace_debug_info(debug_it, writer_trace, di_trace);
528 if (debug_info) {
529 goto end;
530 }
531
532 debug_info = insert_new_debug_info(debug_it, writer_trace, di_trace);
533
534 end:
535 return debug_info;
536 }
537
538 static
539 struct debug_info_trace *lookup_trace(struct debug_info_iterator *debug_it,
540 struct bt_ctf_trace *trace)
541 {
542 return (struct debug_info_trace *) g_hash_table_lookup(
543 debug_it->trace_map,
544 (gpointer) trace);
545 }
546
547 static
548 struct debug_info_trace *insert_new_trace(struct debug_info_iterator *debug_it,
549 struct bt_ctf_stream *stream) {
550 struct bt_ctf_trace *writer_trace = NULL;
551 struct debug_info_trace *di_trace = NULL;
552 struct bt_ctf_trace *trace = NULL;
553 struct bt_ctf_stream_class *stream_class = NULL;
554 int ret;
555
556 writer_trace = bt_ctf_trace_create();
557 if (!writer_trace) {
558 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
559 __FILE__, __LINE__);
560 goto error;
561 }
562
563 stream_class = bt_ctf_stream_get_class(stream);
564 if (!stream_class) {
565 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
566 __FILE__, __LINE__);
567 goto error;
568 }
569
570 trace = bt_ctf_stream_class_get_trace(stream_class);
571 if (!trace) {
572 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
573 __FILE__, __LINE__);
574 goto error;
575 }
576
577 ret = ctf_copy_trace(debug_it->err, trace, writer_trace);
578 if (ret != BT_COMPONENT_STATUS_OK) {
579 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
580 __FILE__, __LINE__);
581 goto error;
582 }
583
584 di_trace = g_new0(struct debug_info_trace, 1);
585 if (!di_trace) {
586 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
587 __FILE__, __LINE__);
588 goto error;
589 }
590
591 di_trace->trace = trace;
592 di_trace->writer_trace = writer_trace;
593 di_trace->debug_info_component = debug_it->debug_info_component;
594 di_trace->stream_map = g_hash_table_new_full(g_direct_hash,
595 g_direct_equal, NULL, (GDestroyNotify) unref_stream);
596 di_trace->stream_class_map = g_hash_table_new_full(g_direct_hash,
597 g_direct_equal, NULL, (GDestroyNotify) unref_stream_class);
598 di_trace->packet_map = g_hash_table_new_full(g_direct_hash,
599 g_direct_equal, NULL, (GDestroyNotify) unref_packet);
600 di_trace->trace_debug_map = g_hash_table_new_full(g_direct_hash,
601 g_direct_equal, NULL, (GDestroyNotify) unref_debug_info);
602
603 g_hash_table_insert(debug_it->trace_map, (gpointer) trace, di_trace);
604
605 goto end;
606
607 error:
608 BT_PUT(writer_trace);
609 g_free(di_trace);
610 di_trace = NULL;
611 end:
612 bt_put(stream_class);
613 bt_put(trace);
614 return di_trace;
615 }
616
617 static
618 struct bt_ctf_packet *lookup_packet(struct debug_info_iterator *debug_it,
619 struct bt_ctf_packet *packet,
620 struct debug_info_trace *di_trace)
621 {
622 return (struct bt_ctf_packet *) g_hash_table_lookup(
623 di_trace->packet_map,
624 (gpointer) packet);
625 }
626
627 static
628 struct bt_ctf_packet *insert_new_packet(struct debug_info_iterator *debug_it,
629 struct bt_ctf_packet *packet,
630 struct bt_ctf_stream *writer_stream,
631 struct debug_info_trace *di_trace)
632 {
633 struct bt_ctf_packet *writer_packet;
634
635 writer_packet = bt_ctf_packet_create(writer_stream);
636 if (!writer_packet) {
637 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
638 __FILE__, __LINE__);
639 goto end;
640 }
641 g_hash_table_insert(di_trace->packet_map, (gpointer) packet, writer_packet);
642
643 end:
644 return writer_packet;
645 }
646
647 static
648 int add_debug_info_fields(FILE *err,
649 struct bt_ctf_field_type *writer_event_context_type,
650 struct debug_info_component *component)
651 {
652 struct bt_ctf_field_type *ip_field = NULL, *debug_field_type = NULL,
653 *bin_field_type = NULL, *func_field_type = NULL,
654 *src_field_type = NULL;
655 int ret = 0;
656
657 ip_field = bt_ctf_field_type_structure_get_field_type_by_name(
658 writer_event_context_type, "_ip");
659 /* No ip field, so no debug info. */
660 if (!ip_field) {
661 goto end;
662 }
663 BT_PUT(ip_field);
664
665 debug_field_type = bt_ctf_field_type_structure_get_field_type_by_name(
666 writer_event_context_type,
667 component->arg_debug_info_field_name);
668 /* Already existing debug_info field, no need to add it. */
669 if (debug_field_type) {
670 goto end;
671 }
672
673 debug_field_type = bt_ctf_field_type_structure_create();
674 if (!debug_field_type) {
675 fprintf(err, "[error] %s in %s:%d\n", __func__,
676 __FILE__, __LINE__);
677 goto error;
678 }
679
680 bin_field_type = bt_ctf_field_type_string_create();
681 if (!bin_field_type) {
682 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
683 __LINE__);
684 goto error;
685 }
686
687 func_field_type = bt_ctf_field_type_string_create();
688 if (!func_field_type) {
689 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
690 __LINE__);
691 goto error;
692 }
693
694 src_field_type = bt_ctf_field_type_string_create();
695 if (!src_field_type) {
696 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
697 __LINE__);
698 goto error;
699 }
700
701 ret = bt_ctf_field_type_structure_add_field(debug_field_type,
702 bin_field_type, "bin");
703 if (ret) {
704 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
705 __LINE__);
706 goto error;
707 }
708
709 ret = bt_ctf_field_type_structure_add_field(debug_field_type,
710 func_field_type, "func");
711 if (ret) {
712 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
713 __LINE__);
714 goto error;
715 }
716
717 ret = bt_ctf_field_type_structure_add_field(debug_field_type,
718 src_field_type, "src");
719 if (ret) {
720 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
721 __LINE__);
722 goto error;
723 }
724
725 ret = bt_ctf_field_type_structure_add_field(writer_event_context_type,
726 debug_field_type, component->arg_debug_info_field_name);
727 if (ret) {
728 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
729 __LINE__);
730 goto error;
731 }
732
733 ret = 0;
734 goto end;
735
736 error:
737 BT_PUT(debug_field_type);
738 ret = -1;
739 end:
740 bt_put(src_field_type);
741 bt_put(func_field_type);
742 bt_put(bin_field_type);
743 bt_put(debug_field_type);
744 return ret;
745 }
746
747 static
748 int create_debug_info_event_context_type(FILE *err,
749 struct bt_ctf_field_type *event_context_type,
750 struct bt_ctf_field_type *writer_event_context_type,
751 struct debug_info_component *component)
752 {
753 int ret, nr_fields, i;
754
755 nr_fields = bt_ctf_field_type_structure_get_field_count(event_context_type);
756 for (i = 0; i < nr_fields; i++) {
757 struct bt_ctf_field_type *field_type = NULL;
758 const char *field_name;
759
760 if (bt_ctf_field_type_structure_get_field(event_context_type,
761 &field_name, &field_type, i) < 0) {
762 fprintf(err, "[error] %s in %s:%d\n", __func__,
763 __FILE__, __LINE__);
764 goto error;
765 }
766
767 ret = bt_ctf_field_type_structure_add_field(writer_event_context_type,
768 field_type, field_name);
769 BT_PUT(field_type);
770 if (ret) {
771 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
772 __LINE__);
773 goto error;
774 }
775 }
776
777 ret = add_debug_info_fields(err, writer_event_context_type,
778 component);
779 goto end;
780
781 error:
782 ret = -1;
783 end:
784 return ret;
785 }
786
787 static
788 struct bt_ctf_stream_class *copy_stream_class_debug_info(FILE *err,
789 struct bt_ctf_stream_class *stream_class,
790 struct bt_ctf_trace *writer_trace,
791 struct debug_info_component *component)
792 {
793 struct bt_ctf_field_type *type = NULL;
794 struct bt_ctf_stream_class *writer_stream_class = NULL;
795 struct bt_ctf_field_type *writer_event_context_type = NULL;
796 int ret_int;
797 const char *name = bt_ctf_stream_class_get_name(stream_class);
798
799 if (strlen(name) == 0) {
800 name = NULL;
801 }
802
803 writer_stream_class = bt_ctf_stream_class_create(name);
804 if (!writer_stream_class) {
805 fprintf(err, "[error] %s in %s:%d\n",
806 __func__, __FILE__, __LINE__);
807 goto error;
808 }
809
810 type = bt_ctf_stream_class_get_packet_context_type(stream_class);
811 if (!type) {
812 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
813 __LINE__);
814 goto error;
815 }
816
817 ret_int = bt_ctf_stream_class_set_packet_context_type(
818 writer_stream_class, type);
819 if (ret_int < 0) {
820 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
821 __LINE__);
822 goto error;
823 }
824 BT_PUT(type);
825
826 type = bt_ctf_stream_class_get_event_header_type(stream_class);
827 if (!type) {
828 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
829 __LINE__);
830 goto error;
831 }
832
833 ret_int = bt_ctf_stream_class_set_event_header_type(
834 writer_stream_class, type);
835 if (ret_int < 0) {
836 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
837 __LINE__);
838 goto error;
839 }
840 BT_PUT(type);
841
842 type = bt_ctf_stream_class_get_event_context_type(stream_class);
843 if (type) {
844 writer_event_context_type = bt_ctf_field_type_structure_create();
845 if (!writer_event_context_type) {
846 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
847 __LINE__);
848 goto error;
849 }
850 ret_int = create_debug_info_event_context_type(err, type,
851 writer_event_context_type, component);
852 if (ret_int) {
853 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
854 __LINE__);
855 goto error;
856 }
857 BT_PUT(type);
858
859 ret_int = bt_ctf_stream_class_set_event_context_type(
860 writer_stream_class, writer_event_context_type);
861 if (ret_int < 0) {
862 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
863 __LINE__);
864 goto error;
865 }
866 BT_PUT(writer_event_context_type);
867 }
868
869 goto end;
870
871 error:
872 BT_PUT(writer_stream_class);
873 end:
874 bt_put(writer_event_context_type);
875 bt_put(type);
876 return writer_stream_class;
877 }
878
879 /*
880 * Add the original clock classes to the new trace, we do not need to copy
881 * them, and if we did, we would have to manually inspect the stream class
882 * to update the integers mapping to a clock.
883 */
884 static
885 int add_clock_classes(FILE *err, struct bt_ctf_trace *writer_trace,
886 struct bt_ctf_stream_class *writer_stream_class,
887 struct bt_ctf_trace *trace)
888 {
889 int ret, clock_class_count, i;
890
891 clock_class_count = bt_ctf_trace_get_clock_class_count(trace);
892
893 for (i = 0; i < clock_class_count; i++) {
894 struct bt_ctf_clock_class *clock_class =
895 bt_ctf_trace_get_clock_class_by_index(trace, i);
896
897 if (!clock_class) {
898 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
899 __LINE__);
900 goto error;
901 }
902
903 ret = bt_ctf_trace_add_clock_class(writer_trace, clock_class);
904 BT_PUT(clock_class);
905 if (ret != 0) {
906 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
907 __LINE__);
908 goto error;
909 }
910 }
911
912 ret = 0;
913 goto end;
914
915 error:
916 ret = -1;
917 end:
918 return ret;
919
920 }
921
922 static
923 struct bt_ctf_stream_class *insert_new_stream_class(
924 struct debug_info_iterator *debug_it,
925 struct bt_ctf_stream_class *stream_class)
926 {
927 struct bt_ctf_stream_class *writer_stream_class = NULL;
928 struct bt_ctf_trace *trace, *writer_trace = NULL;
929 struct debug_info_trace *di_trace;
930 enum bt_component_status ret;
931 int int_ret;
932
933 trace = bt_ctf_stream_class_get_trace(stream_class);
934 if (!trace) {
935 fprintf(debug_it->err,
936 "[error] %s in %s:%d\n", __func__, __FILE__,
937 __LINE__);
938 goto error;
939 }
940
941 di_trace = lookup_trace(debug_it, trace);
942 if (!di_trace) {
943 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
944 __FILE__, __LINE__);
945 ret = BT_COMPONENT_STATUS_ERROR;
946 goto error;
947 }
948 writer_trace = di_trace->writer_trace;
949 bt_get(writer_trace);
950
951 writer_stream_class = copy_stream_class_debug_info(debug_it->err, stream_class,
952 writer_trace, debug_it->debug_info_component);
953 if (!writer_stream_class) {
954 fprintf(debug_it->err, "[error] Failed to copy stream class\n");
955 fprintf(debug_it->err, "[error] %s in %s:%d\n",
956 __func__, __FILE__, __LINE__);
957 goto error;
958 }
959
960 int_ret = bt_ctf_trace_add_stream_class(writer_trace, writer_stream_class);
961 if (int_ret) {
962 fprintf(debug_it->err,
963 "[error] %s in %s:%d\n", __func__, __FILE__,
964 __LINE__);
965 goto error;
966 }
967
968 ret = add_clock_classes(debug_it->err, writer_trace,
969 writer_stream_class, trace);
970 if (ret != BT_COMPONENT_STATUS_OK) {
971 fprintf(debug_it->err,
972 "[error] %s in %s:%d\n", __func__, __FILE__,
973 __LINE__);
974 goto error;
975 }
976 BT_PUT(writer_trace);
977 BT_PUT(trace);
978
979 g_hash_table_insert(di_trace->stream_class_map,
980 (gpointer) stream_class, writer_stream_class);
981
982 goto end;
983
984 error:
985 BT_PUT(writer_stream_class);
986 end:
987 bt_put(trace);
988 bt_put(writer_trace);
989 return writer_stream_class;
990 }
991
992 static
993 struct bt_ctf_stream *insert_new_stream(
994 struct debug_info_iterator *debug_it,
995 struct bt_ctf_stream *stream,
996 struct debug_info_trace *di_trace)
997 {
998 struct bt_ctf_stream *writer_stream = NULL;
999 struct bt_ctf_stream_class *stream_class = NULL;
1000 struct bt_ctf_stream_class *writer_stream_class = NULL;
1001
1002 stream_class = bt_ctf_stream_get_class(stream);
1003 if (!stream_class) {
1004 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1005 __func__, __FILE__, __LINE__);
1006 goto error;
1007 }
1008
1009 writer_stream_class = g_hash_table_lookup(
1010 di_trace->stream_class_map,
1011 (gpointer) stream_class);
1012
1013 if (!writer_stream_class) {
1014 writer_stream_class = insert_new_stream_class(debug_it,
1015 stream_class);
1016 if (!writer_stream_class) {
1017 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1018 __func__, __FILE__, __LINE__);
1019 goto error;
1020 }
1021 }
1022 bt_get(writer_stream_class);
1023
1024 writer_stream = bt_ctf_stream_create(writer_stream_class,
1025 bt_ctf_stream_get_name(stream));
1026 if (!writer_stream) {
1027 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1028 __func__, __FILE__, __LINE__);
1029 goto error;
1030 }
1031
1032 g_hash_table_insert(di_trace->stream_map, (gpointer) stream,
1033 writer_stream);
1034
1035 goto end;
1036
1037 error:
1038 BT_PUT(writer_stream);
1039 end:
1040 bt_put(stream_class);
1041 bt_put(writer_stream_class);
1042 return writer_stream;
1043 }
1044
1045 static
1046 struct bt_ctf_stream *lookup_stream(struct debug_info_iterator *debug_it,
1047 struct bt_ctf_stream *stream,
1048 struct debug_info_trace *di_trace)
1049 {
1050 return (struct bt_ctf_stream *) g_hash_table_lookup(
1051 di_trace->stream_map, (gpointer) stream);
1052 }
1053
1054 static
1055 struct bt_ctf_event_class *get_event_class(struct debug_info_iterator *debug_it,
1056 struct bt_ctf_stream_class *writer_stream_class,
1057 struct bt_ctf_event_class *event_class)
1058 {
1059 return bt_ctf_stream_class_get_event_class_by_id(writer_stream_class,
1060 bt_ctf_event_class_get_id(event_class));
1061 }
1062
1063 static
1064 struct debug_info_trace *lookup_di_trace_from_stream(
1065 struct debug_info_iterator *debug_it,
1066 struct bt_ctf_stream *stream)
1067 {
1068 struct bt_ctf_stream_class *stream_class = NULL;
1069 struct bt_ctf_trace *trace = NULL;
1070 struct debug_info_trace *di_trace = NULL;
1071
1072 stream_class = bt_ctf_stream_get_class(stream);
1073 if (!stream_class) {
1074 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1075 __func__, __FILE__, __LINE__);
1076 goto end;
1077 }
1078
1079 trace = bt_ctf_stream_class_get_trace(stream_class);
1080 if (!trace) {
1081 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1082 __func__, __FILE__, __LINE__);
1083 goto end;
1084 }
1085
1086 di_trace = (struct debug_info_trace *) g_hash_table_lookup(
1087 debug_it->trace_map, (gpointer) trace);
1088
1089 end:
1090 BT_PUT(stream_class);
1091 BT_PUT(trace);
1092 return di_trace;
1093 }
1094
1095 static
1096 struct bt_ctf_stream *get_writer_stream(
1097 struct debug_info_iterator *debug_it,
1098 struct bt_ctf_packet *packet, struct bt_ctf_stream *stream)
1099 {
1100 struct bt_ctf_stream_class *stream_class = NULL;
1101 struct bt_ctf_stream *writer_stream = NULL;
1102 struct debug_info_trace *di_trace = NULL;
1103
1104 stream_class = bt_ctf_stream_get_class(stream);
1105 if (!stream_class) {
1106 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1107 __func__, __FILE__, __LINE__);
1108 goto error;
1109 }
1110
1111 di_trace = lookup_di_trace_from_stream(debug_it, stream);
1112 if (!di_trace) {
1113 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1114 __func__, __FILE__, __LINE__);
1115 goto error;
1116 }
1117
1118 writer_stream = lookup_stream(debug_it, stream, di_trace);
1119 if (!writer_stream) {
1120 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1121 __func__, __FILE__, __LINE__);
1122 goto error;
1123 }
1124 bt_get(writer_stream);
1125
1126 goto end;
1127
1128 error:
1129 BT_PUT(writer_stream);
1130 end:
1131 bt_put(stream_class);
1132 return writer_stream;
1133 }
1134
1135 BT_HIDDEN
1136 struct bt_ctf_packet *debug_info_new_packet(
1137 struct debug_info_iterator *debug_it,
1138 struct bt_ctf_packet *packet)
1139 {
1140 struct bt_ctf_stream *stream = NULL, *writer_stream = NULL;
1141 struct bt_ctf_field *writer_packet_context = NULL;
1142 struct bt_ctf_packet *writer_packet = NULL;
1143 struct debug_info_trace *di_trace;
1144 int int_ret;
1145
1146 stream = bt_ctf_packet_get_stream(packet);
1147 if (!stream) {
1148 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1149 __func__, __FILE__, __LINE__);
1150 goto error;
1151 }
1152
1153 writer_stream = get_writer_stream(debug_it, packet, stream);
1154 if (!writer_stream) {
1155 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1156 __func__, __FILE__, __LINE__);
1157 goto error;
1158 }
1159
1160 di_trace = lookup_di_trace_from_stream(debug_it, stream);
1161 if (!di_trace) {
1162 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1163 __FILE__, __LINE__);
1164 goto error;
1165 }
1166
1167 /*
1168 * If a packet was already opened, close it and remove it from
1169 * the HT.
1170 */
1171 writer_packet = lookup_packet(debug_it, packet, di_trace);
1172 if (writer_packet) {
1173 g_hash_table_remove(di_trace->packet_map, packet);
1174 BT_PUT(writer_packet);
1175 }
1176
1177 writer_packet = insert_new_packet(debug_it, packet, writer_stream,
1178 di_trace);
1179 if (!writer_packet) {
1180 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1181 __func__, __FILE__, __LINE__);
1182 goto error;
1183 }
1184
1185 writer_packet_context = ctf_copy_packet_context(debug_it->err, packet,
1186 writer_stream);
1187 if (!writer_packet_context) {
1188 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1189 __func__, __FILE__, __LINE__);
1190 goto error;
1191 }
1192
1193 int_ret = bt_ctf_packet_set_context(writer_packet, writer_packet_context);
1194 if (int_ret) {
1195 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1196 __func__, __FILE__, __LINE__);
1197 goto error;
1198 }
1199 goto end;
1200
1201 error:
1202
1203 end:
1204 bt_put(writer_packet_context);
1205 bt_put(writer_stream);
1206 bt_put(stream);
1207 return writer_packet;
1208 }
1209
1210 BT_HIDDEN
1211 struct bt_ctf_packet *debug_info_close_packet(
1212 struct debug_info_iterator *debug_it,
1213 struct bt_ctf_packet *packet)
1214 {
1215 struct bt_ctf_packet *writer_packet = NULL;
1216 struct bt_ctf_stream *stream = NULL;
1217 struct debug_info_trace *di_trace;
1218
1219 stream = bt_ctf_packet_get_stream(packet);
1220 if (!stream) {
1221 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1222 __FILE__, __LINE__);
1223 goto end;
1224 }
1225
1226 di_trace = lookup_di_trace_from_stream(debug_it, stream);
1227 if (!di_trace) {
1228 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1229 __FILE__, __LINE__);
1230 goto end;
1231 }
1232
1233 writer_packet = lookup_packet(debug_it, packet, di_trace);
1234 if (!writer_packet) {
1235 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1236 __func__, __FILE__, __LINE__);
1237 goto end;
1238 }
1239 g_hash_table_remove(di_trace->packet_map, packet);
1240
1241 end:
1242 bt_put(stream);
1243 return writer_packet;
1244 }
1245
1246 BT_HIDDEN
1247 struct bt_ctf_stream *debug_info_stream_begin(
1248 struct debug_info_iterator *debug_it,
1249 struct bt_ctf_stream *stream)
1250 {
1251 struct bt_ctf_stream *writer_stream;
1252 struct debug_info_trace *di_trace = NULL;
1253
1254 di_trace = lookup_di_trace_from_stream(debug_it, stream);
1255 if (!di_trace) {
1256 di_trace = insert_new_trace(debug_it, stream);
1257 if (!di_trace) {
1258 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1259 __func__, __FILE__, __LINE__);
1260 goto end;
1261 }
1262 }
1263
1264 writer_stream = lookup_stream(debug_it, stream, di_trace);
1265 if (writer_stream) {
1266 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1267 __func__, __FILE__, __LINE__);
1268 goto end;
1269 }
1270
1271 writer_stream = insert_new_stream(debug_it, stream, di_trace);
1272
1273 end:
1274 return writer_stream;
1275 }
1276
1277 BT_HIDDEN
1278 struct bt_ctf_stream *debug_info_stream_end(struct debug_info_iterator *debug_it,
1279 struct bt_ctf_stream *stream)
1280 {
1281 struct bt_ctf_stream *writer_stream;
1282 struct debug_info_trace *di_trace = NULL;
1283
1284 di_trace = lookup_di_trace_from_stream(debug_it, stream);
1285 if (!di_trace) {
1286 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1287 __func__, __FILE__, __LINE__);
1288 goto end;
1289 }
1290
1291 writer_stream = lookup_stream(debug_it, stream, di_trace);
1292 if (!writer_stream) {
1293 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1294 __func__, __FILE__, __LINE__);
1295 goto end;
1296 }
1297 bt_get(writer_stream);
1298 g_hash_table_remove(di_trace->stream_map, stream);
1299
1300 end:
1301 return writer_stream;
1302 }
1303
1304 static
1305 struct debug_info_source *lookup_debug_info(FILE *err,
1306 struct bt_ctf_event *event,
1307 struct debug_info *debug_info)
1308 {
1309 int64_t vpid;
1310 uint64_t ip;
1311 struct debug_info_source *dbg_info_src = NULL;
1312 int ret;
1313
1314 ret = get_stream_event_context_int_field_value(err, event,
1315 "_vpid", &vpid);
1316 if (ret) {
1317 goto end;
1318 }
1319
1320 ret = get_stream_event_context_unsigned_int_field_value(err, event,
1321 "_ip", &ip);
1322 if (ret) {
1323 goto end;
1324 }
1325
1326 /* Get debug info for this context. */
1327 dbg_info_src = debug_info_query(debug_info, vpid, ip);
1328
1329 end:
1330 return dbg_info_src;
1331 }
1332
1333 static
1334 int set_debug_info_field(FILE *err, struct bt_ctf_field *debug_field,
1335 struct debug_info_source *dbg_info_src,
1336 struct debug_info_component *component)
1337 {
1338 int i, nr_fields, ret = 0;
1339 struct bt_ctf_field_type *debug_field_type = NULL;
1340 struct bt_ctf_field *field = NULL;
1341 struct bt_ctf_field_type *field_type = NULL;
1342
1343 debug_field_type = bt_ctf_field_get_type(debug_field);
1344 if (!debug_field_type) {
1345 fprintf(err, "[error] %s in %s:%d\n", __func__,
1346 __FILE__, __LINE__);
1347 goto error;
1348 }
1349
1350 nr_fields = bt_ctf_field_type_structure_get_field_count(debug_field_type);
1351 for (i = 0; i < nr_fields; i++) {
1352 const char *field_name;
1353
1354 if (bt_ctf_field_type_structure_get_field(debug_field_type,
1355 &field_name, &field_type, i) < 0) {
1356 fprintf(err, "[error] %s in %s:%d\n", __func__,
1357 __FILE__, __LINE__);
1358 goto error;
1359 }
1360 BT_PUT(field_type);
1361
1362 field = bt_ctf_field_structure_get_field_by_index(debug_field, i);
1363 if (!strcmp(field_name, "bin")) {
1364 if (dbg_info_src && dbg_info_src->bin_path) {
1365 GString *tmp = g_string_new(NULL);
1366
1367 if (component->arg_full_path) {
1368 g_string_printf(tmp, "%s%s",
1369 dbg_info_src->bin_path,
1370 dbg_info_src->bin_loc);
1371 } else {
1372 g_string_printf(tmp, "%s%s",
1373 dbg_info_src->short_bin_path,
1374 dbg_info_src->bin_loc);
1375 }
1376 ret = bt_ctf_field_string_set_value(field, tmp->str);
1377 g_string_free(tmp, true);
1378 } else {
1379 ret = bt_ctf_field_string_set_value(field, "");
1380 }
1381 } else if (!strcmp(field_name, "func")) {
1382 if (dbg_info_src && dbg_info_src->func) {
1383 ret = bt_ctf_field_string_set_value(field,
1384 dbg_info_src->func);
1385 } else {
1386 ret = bt_ctf_field_string_set_value(field, "");
1387 }
1388 } else if (!strcmp(field_name, "src")) {
1389 if (dbg_info_src && dbg_info_src->src_path) {
1390 GString *tmp = g_string_new(NULL);
1391
1392 if (component->arg_full_path) {
1393 g_string_printf(tmp, "%s:%" PRId64,
1394 dbg_info_src->src_path,
1395 dbg_info_src->line_no);
1396 } else {
1397 g_string_printf(tmp, "%s:%" PRId64,
1398 dbg_info_src->short_src_path,
1399 dbg_info_src->line_no);
1400 }
1401 ret = bt_ctf_field_string_set_value(field, tmp->str);
1402 g_string_free(tmp, true);
1403 } else {
1404 ret = bt_ctf_field_string_set_value(field, "");
1405 }
1406 }
1407 BT_PUT(field);
1408 if (ret) {
1409 fprintf(err, "[error] %s in %s:%d\n", __func__,
1410 __FILE__, __LINE__);
1411 goto error;
1412 }
1413 }
1414 ret = 0;
1415 goto end;
1416
1417 error:
1418 ret = -1;
1419 end:
1420 bt_put(field_type);
1421 bt_put(field);
1422 bt_put(debug_field_type);
1423 return ret;
1424 }
1425
1426 static
1427 int copy_set_debug_info_stream_event_context(FILE *err,
1428 struct bt_ctf_field *event_context,
1429 struct bt_ctf_event *event,
1430 struct bt_ctf_event *writer_event,
1431 struct debug_info *debug_info,
1432 struct debug_info_component *component)
1433 {
1434 struct bt_ctf_field_type *writer_event_context_type = NULL,
1435 *event_context_type = NULL;
1436 struct bt_ctf_field *writer_event_context = NULL;
1437 struct bt_ctf_field *field = NULL, *copy_field = NULL, *debug_field = NULL;
1438 struct bt_ctf_field_type *field_type = NULL;
1439 struct debug_info_source *dbg_info_src;
1440 int ret, nr_fields, i;
1441
1442 writer_event_context = bt_ctf_event_get_stream_event_context(writer_event);
1443 if (!writer_event_context) {
1444 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__, __LINE__);
1445 goto error;
1446 }
1447
1448 writer_event_context_type = bt_ctf_field_get_type(writer_event_context);
1449 if (!writer_event_context_type) {
1450 fprintf(err, "[error] %s in %s:%d\n", __func__,
1451 __FILE__, __LINE__);
1452 goto error;
1453 }
1454
1455 event_context_type = bt_ctf_field_get_type(event_context);
1456 if (!event_context_type) {
1457 fprintf(err, "[error] %s in %s:%d\n", __func__,
1458 __FILE__, __LINE__);
1459 goto error;
1460 }
1461
1462 /*
1463 * If it is not a structure, we did not modify it to add the debug info
1464 * fields, so just assign it as is.
1465 */
1466 if (bt_ctf_field_type_get_type_id(writer_event_context_type) != BT_CTF_FIELD_TYPE_ID_STRUCT) {
1467 ret = bt_ctf_event_set_event_context(writer_event, event_context);
1468 goto end;
1469 }
1470
1471 dbg_info_src = lookup_debug_info(err, event, debug_info);
1472
1473 nr_fields = bt_ctf_field_type_structure_get_field_count(writer_event_context_type);
1474 for (i = 0; i < nr_fields; i++) {
1475 const char *field_name;
1476
1477 if (bt_ctf_field_type_structure_get_field(writer_event_context_type,
1478 &field_name, &field_type, i) < 0) {
1479 fprintf(err, "[error] %s in %s:%d\n", __func__,
1480 __FILE__, __LINE__);
1481 goto error;
1482 }
1483
1484 /*
1485 * Prevent illegal access in the event_context.
1486 */
1487 if (i < bt_ctf_field_type_structure_get_field_count(event_context_type)) {
1488 field = bt_ctf_field_structure_get_field_by_index(event_context, i);
1489 }
1490 /*
1491 * The debug_info field, only exists in the writer event or
1492 * if it was set by a earlier pass of the debug_info plugin.
1493 */
1494 if (!strcmp(field_name, component->arg_debug_info_field_name) &&
1495 !field) {
1496 debug_field = bt_ctf_field_structure_get_field_by_index(
1497 writer_event_context, i);
1498 if (!debug_field) {
1499 fprintf(err, "[error] %s in %s:%d\n", __func__,
1500 __FILE__, __LINE__);
1501 goto error;
1502 }
1503 ret = set_debug_info_field(err, debug_field,
1504 dbg_info_src, component);
1505 if (ret) {
1506 fprintf(err, "[error] %s in %s:%d\n", __func__,
1507 __FILE__, __LINE__);
1508 goto error;
1509 }
1510 BT_PUT(debug_field);
1511 } else {
1512 copy_field = bt_ctf_field_copy(field);
1513 if (!copy_field) {
1514 fprintf(err, "[error] %s in %s:%d\n", __func__,
1515 __FILE__, __LINE__);
1516 goto error;
1517 }
1518
1519 ret = bt_ctf_field_structure_set_field(writer_event_context,
1520 field_name, copy_field);
1521 if (ret) {
1522 fprintf(err, "[error] %s in %s:%d\n", __func__,
1523 __FILE__, __LINE__);
1524 goto error;
1525 }
1526 BT_PUT(copy_field);
1527 }
1528 BT_PUT(field_type);
1529 BT_PUT(field);
1530 }
1531
1532 ret = 0;
1533 goto end;
1534
1535 error:
1536 ret = -1;
1537 end:
1538 bt_put(event_context_type);
1539 bt_put(writer_event_context_type);
1540 bt_put(writer_event_context);
1541 bt_put(field);
1542 bt_put(copy_field);
1543 bt_put(debug_field);
1544 bt_put(field_type);
1545 return ret;
1546 }
1547
1548 static
1549 struct bt_ctf_clock_class *stream_class_get_clock_class(FILE *err,
1550 struct bt_ctf_stream_class *stream_class)
1551 {
1552 struct bt_ctf_trace *trace = NULL;
1553 struct bt_ctf_clock_class *clock_class = NULL;
1554
1555 trace = bt_ctf_stream_class_get_trace(stream_class);
1556 if (!trace) {
1557 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
1558 __LINE__);
1559 goto end;
1560 }
1561
1562 /* FIXME multi-clock? */
1563 clock_class = bt_ctf_trace_get_clock_class_by_index(trace, 0);
1564
1565 bt_put(trace);
1566
1567 end:
1568 return clock_class;
1569 }
1570
1571 static
1572 struct bt_ctf_clock_class *event_get_clock_class(FILE *err, struct bt_ctf_event *event)
1573 {
1574 struct bt_ctf_event_class *event_class = NULL;
1575 struct bt_ctf_stream_class *stream_class = NULL;
1576 struct bt_ctf_clock_class *clock_class = NULL;
1577
1578 event_class = bt_ctf_event_get_class(event);
1579 if (!event_class) {
1580 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
1581 __LINE__);
1582 goto error;
1583 }
1584
1585 stream_class = bt_ctf_event_class_get_stream_class(event_class);
1586 if (!stream_class) {
1587 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
1588 __LINE__);
1589 goto error;
1590 }
1591
1592 clock_class = stream_class_get_clock_class(err, stream_class);
1593 goto end;
1594
1595 error:
1596 BT_PUT(clock_class);
1597 end:
1598 bt_put(stream_class);
1599 bt_put(event_class);
1600 return clock_class;
1601 }
1602
1603 static
1604 int set_event_clock_value(FILE *err, struct bt_ctf_event *event,
1605 struct bt_ctf_event *writer_event)
1606 {
1607 struct bt_ctf_clock_class *clock_class = NULL;
1608 struct bt_ctf_clock_value *clock_value = NULL;
1609 int ret;
1610
1611 clock_class = event_get_clock_class(err, event);
1612 if (!clock_class) {
1613 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
1614 __LINE__);
1615 goto error;
1616 }
1617
1618 clock_value = bt_ctf_event_get_clock_value(event, clock_class);
1619 if (!clock_value) {
1620 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
1621 __LINE__);
1622 goto error;
1623 }
1624
1625 /*
1626 * We share the same clocks, so we can assign the clock value to the
1627 * writer event.
1628 */
1629 ret = bt_ctf_event_set_clock_value(writer_event, clock_value);
1630 if (ret) {
1631 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
1632 __LINE__);
1633 goto error;
1634 }
1635
1636 ret = 0;
1637 goto end;
1638
1639 error:
1640 ret = -1;
1641 end:
1642 bt_put(clock_class);
1643 bt_put(clock_value);
1644 return ret;
1645 }
1646
1647 static
1648 struct bt_ctf_event *debug_info_copy_event(FILE *err, struct bt_ctf_event *event,
1649 struct bt_ctf_event_class *writer_event_class,
1650 struct debug_info *debug_info,
1651 struct debug_info_component *component)
1652 {
1653 struct bt_ctf_event *writer_event = NULL;
1654 struct bt_ctf_field *field = NULL, *copy_field = NULL;
1655 int ret;
1656
1657 writer_event = bt_ctf_event_create(writer_event_class);
1658 if (!writer_event) {
1659 fprintf(err, "[error] %s in %s:%d\n", __func__, __FILE__,
1660 __LINE__);
1661 goto error;
1662 }
1663
1664 ret = set_event_clock_value(err, event, writer_event);
1665 if (ret) {
1666 fprintf(err, "[error] %s in %s:%d\n", __func__,
1667 __FILE__, __LINE__);
1668 goto error;
1669 }
1670
1671 /* Optional field, so it can fail silently. */
1672 field = bt_ctf_event_get_header(event);
1673 if (field) {
1674 ret = ctf_copy_event_header(err, event, writer_event_class,
1675 writer_event, field);
1676 if (ret) {
1677 fprintf(err, "[error] %s in %s:%d\n", __func__,
1678 __FILE__, __LINE__);
1679 goto error;
1680 }
1681 BT_PUT(field);
1682 }
1683
1684 /* Optional field, so it can fail silently. */
1685 field = bt_ctf_event_get_stream_event_context(event);
1686 if (field) {
1687 ret = copy_set_debug_info_stream_event_context(err,
1688 field, event, writer_event, debug_info,
1689 component);
1690 if (ret < 0) {
1691 fprintf(err, "[error] %s in %s:%d\n", __func__,
1692 __FILE__, __LINE__);
1693 goto error;
1694 }
1695 BT_PUT(field);
1696 }
1697
1698 /* Optional field, so it can fail silently. */
1699 field = bt_ctf_event_get_event_context(event);
1700 if (field) {
1701 copy_field = bt_ctf_field_copy(field);
1702 if (!copy_field) {
1703 fprintf(err, "[error] %s in %s:%d\n", __func__,
1704 __FILE__, __LINE__);
1705 goto error;
1706 }
1707 ret = bt_ctf_event_set_event_context(writer_event, copy_field);
1708 if (ret < 0) {
1709 fprintf(err, "[error] %s in %s:%d\n", __func__,
1710 __FILE__, __LINE__);
1711 goto error;
1712 }
1713 BT_PUT(copy_field);
1714 BT_PUT(field);
1715 }
1716
1717 field = bt_ctf_event_get_event_payload(event);
1718 if (!field) {
1719 fprintf(err, "[error] %s in %s:%d\n", __func__,
1720 __FILE__, __LINE__);
1721 goto error;
1722 }
1723 copy_field = bt_ctf_field_copy(field);
1724 if (copy_field) {
1725 ret = bt_ctf_event_set_event_payload(writer_event, copy_field);
1726 if (ret < 0) {
1727 fprintf(err, "[error] %s in %s:%d\n", __func__,
1728 __FILE__, __LINE__);
1729 goto error;
1730 }
1731 BT_PUT(copy_field);
1732 }
1733 BT_PUT(field);
1734
1735 goto end;
1736
1737 error:
1738 BT_PUT(writer_event);
1739 end:
1740 bt_put(copy_field);
1741 bt_put(field);
1742 return writer_event;
1743 }
1744
1745 BT_HIDDEN
1746 struct bt_ctf_event *debug_info_output_event(
1747 struct debug_info_iterator *debug_it,
1748 struct bt_ctf_event *event)
1749 {
1750 struct bt_ctf_event_class *event_class = NULL, *writer_event_class = NULL;
1751 struct bt_ctf_stream_class *stream_class = NULL, *writer_stream_class = NULL;
1752 struct bt_ctf_event *writer_event = NULL;
1753 struct bt_ctf_packet *packet = NULL, *writer_packet = NULL;
1754 struct bt_ctf_trace *writer_trace = NULL;
1755 struct bt_ctf_stream *stream = NULL;
1756 struct debug_info_trace *di_trace;
1757 struct debug_info *debug_info;
1758 const char *event_name;
1759 int int_ret;
1760
1761 event_class = bt_ctf_event_get_class(event);
1762 if (!event_class) {
1763 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1764 __FILE__, __LINE__);
1765 goto error;
1766 }
1767
1768 event_name = bt_ctf_event_class_get_name(event_class);
1769 if (!event_name) {
1770 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1771 __FILE__, __LINE__);
1772 goto error;
1773 }
1774
1775 stream_class = bt_ctf_event_class_get_stream_class(event_class);
1776 if (!stream_class) {
1777 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1778 __FILE__, __LINE__);
1779 goto error;
1780 }
1781 stream = bt_ctf_event_get_stream(event);
1782 if (!stream) {
1783 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1784 __FILE__, __LINE__);
1785 goto error;
1786 }
1787 di_trace = lookup_di_trace_from_stream(debug_it, stream);
1788 if (!di_trace) {
1789 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1790 __FILE__, __LINE__);
1791 goto error;
1792 }
1793
1794 writer_stream_class = g_hash_table_lookup(
1795 di_trace->stream_class_map,
1796 (gpointer) stream_class);
1797 if (!writer_stream_class) {
1798 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1799 __FILE__, __LINE__);
1800 goto error;
1801 }
1802 bt_get(writer_stream_class);
1803
1804 writer_event_class = get_event_class(debug_it,
1805 writer_stream_class, event_class);
1806 if (!writer_event_class) {
1807 writer_event_class = ctf_copy_event_class(debug_it->err,
1808 event_class);
1809 if (!writer_event_class) {
1810 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1811 __func__, __FILE__, __LINE__);
1812 goto error;
1813 }
1814 int_ret = bt_ctf_stream_class_add_event_class(
1815 writer_stream_class, writer_event_class);
1816 if (int_ret) {
1817 fprintf(debug_it->err, "[error] %s in %s:%d\n",
1818 __func__, __FILE__, __LINE__);
1819 goto error;
1820 }
1821 }
1822
1823 writer_trace = bt_ctf_stream_class_get_trace(writer_stream_class);
1824 if (!writer_trace) {
1825 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1826 __FILE__, __LINE__);
1827 goto error;
1828 }
1829
1830 debug_info = get_trace_debug_info(debug_it, writer_trace, di_trace);
1831 if (debug_info) {
1832 debug_info_handle_event(debug_it->err, event, debug_info);
1833 }
1834
1835 writer_event = debug_info_copy_event(debug_it->err, event,
1836 writer_event_class, debug_info,
1837 debug_it->debug_info_component);
1838 if (!writer_event) {
1839 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1840 __FILE__, __LINE__);
1841 fprintf(debug_it->err, "[error] Failed to copy event %s\n",
1842 bt_ctf_event_class_get_name(writer_event_class));
1843 goto error;
1844 }
1845
1846 packet = bt_ctf_event_get_packet(event);
1847 if (!packet) {
1848 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1849 __FILE__, __LINE__);
1850 goto error;
1851 }
1852
1853 writer_packet = lookup_packet(debug_it, packet, di_trace);
1854 if (!writer_packet) {
1855 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1856 __FILE__, __LINE__);
1857 goto error;
1858 }
1859 bt_get(writer_packet);
1860
1861 int_ret = bt_ctf_event_set_packet(writer_event, writer_packet);
1862 if (int_ret < 0) {
1863 fprintf(debug_it->err, "[error] %s in %s:%d\n", __func__,
1864 __FILE__, __LINE__);
1865 fprintf(debug_it->err, "[error] Failed to append event %s\n",
1866 bt_ctf_event_class_get_name(writer_event_class));
1867 goto error;
1868 }
1869
1870 /* Keep the reference on the writer event */
1871 goto end;
1872
1873 error:
1874 BT_PUT(writer_event);
1875
1876 end:
1877 bt_put(stream);
1878 bt_put(writer_trace);
1879 bt_put(writer_packet);
1880 bt_put(packet);
1881 bt_put(writer_event_class);
1882 bt_put(writer_stream_class);
1883 bt_put(stream_class);
1884 bt_put(event_class);
1885 return writer_event;
1886 }
This page took 0.117772 seconds and 4 git commands to generate.