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