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