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