flt.lttng-utils.debug-info: honor component's initial log level
[babeltrace.git] / src / plugins / lttng-utils / debug-info / debug-info.c
1 /*
2 * Babeltrace - Debug Information State Tracker
3 *
4 * Copyright (c) 2015 EfficiOS Inc. and Linux Foundation
5 * Copyright (c) 2015 Philippe Proulx <pproulx@efficios.com>
6 * Copyright (c) 2015 Antoine Busque <abusque@efficios.com>
7 * Copyright (c) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
8 * Copyright (c) 2019 Francis Deslauriers <francis.deslauriers@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_OUTPUT_LEVEL log_level
30 #define BT_LOG_TAG "PLUGIN/FLT.LTTNG-UTILS.DEBUG-INFO"
31 #include "logging/log.h"
32
33 #include <glib.h>
34
35 #include "common/assert.h"
36 #include "common/common.h"
37 #include "fd-cache/fd-cache.h"
38
39 #include "bin-info.h"
40 #include "debug-info.h"
41 #include "trace-ir-data-copy.h"
42 #include "trace-ir-mapping.h"
43 #include "trace-ir-metadata-copy.h"
44 #include "utils.h"
45
46 #define DEFAULT_DEBUG_INFO_FIELD_NAME "debug_info"
47 #define LTTNG_UST_STATEDUMP_PREFIX "lttng_ust"
48 #define VPID_FIELD_NAME "vpid"
49 #define IP_FIELD_NAME "ip"
50 #define BADDR_FIELD_NAME "baddr"
51 #define CRC32_FIELD_NAME "crc"
52 #define BUILD_ID_FIELD_NAME "build_id"
53 #define FILENAME_FIELD_NAME "filename"
54 #define IS_PIC_FIELD_NAME "is_pic"
55 #define MEMSZ_FIELD_NAME "memsz"
56 #define PATH_FIELD_NAME "path"
57
58 struct debug_info_component {
59 bt_logging_level log_level;
60 gchar *arg_debug_dir;
61 gchar *arg_debug_info_field_name;
62 gchar *arg_target_prefix;
63 bt_bool arg_full_path;
64 };
65
66 struct debug_info_msg_iter {
67 bt_logging_level log_level;
68 struct debug_info_component *debug_info_component;
69 bt_self_message_iterator *input_iterator;
70 bt_self_component *self_comp;
71 bt_self_component_port_input_message_iterator *msg_iter;
72
73 struct trace_ir_maps *ir_maps;
74 /* in_trace -> debug_info_mapping. */
75 GHashTable *debug_info_map;
76
77 struct bt_fd_cache fd_cache;
78 };
79
80 struct debug_info_source {
81 /* Strings are owned by debug_info_source. */
82 gchar *func;
83 /*
84 * Store the line number as a string so that the allocation and
85 * conversion to string is only done once.
86 */
87 gchar *line_no;
88 gchar *src_path;
89 /* short_src_path points inside src_path, no need to free. */
90 const gchar *short_src_path;
91 gchar *bin_path;
92 /* short_bin_path points inside bin_path, no need to free. */
93 const gchar *short_bin_path;
94 /*
95 * Location within the binary. Either absolute (@0x1234) or
96 * relative (+0x4321).
97 */
98 gchar *bin_loc;
99 };
100
101 struct proc_debug_info_sources {
102 /*
103 * Hash table: base address (pointer to uint64_t) to bin info; owned by
104 * proc_debug_info_sources.
105 */
106 GHashTable *baddr_to_bin_info;
107
108 /*
109 * Hash table: IP (pointer to uint64_t) to (struct debug_info_source *);
110 * owned by proc_debug_info_sources.
111 */
112 GHashTable *ip_to_debug_info_src;
113 };
114
115 struct debug_info {
116 bt_logging_level log_level;
117 struct debug_info_component *comp;
118 const bt_trace *input_trace;
119 uint64_t destruction_listener_id;
120
121 /*
122 * Hash table of VPIDs (pointer to int64_t) to
123 * (struct proc_debug_info_sources*); owned by debug_info.
124 */
125 GHashTable *vpid_to_proc_dbg_info_src;
126 GQuark q_statedump_bin_info;
127 GQuark q_statedump_debug_link;
128 GQuark q_statedump_build_id;
129 GQuark q_statedump_start;
130 GQuark q_dl_open;
131 GQuark q_lib_load;
132 GQuark q_lib_unload;
133 struct bt_fd_cache *fd_cache; /* Weak ref. Owned by the iterator. */
134 };
135
136 static
137 int debug_info_init(struct debug_info *info)
138 {
139 info->q_statedump_bin_info = g_quark_from_string(
140 "lttng_ust_statedump:bin_info");
141 info->q_statedump_debug_link = g_quark_from_string(
142 "lttng_ust_statedump:debug_link");
143 info->q_statedump_build_id = g_quark_from_string(
144 "lttng_ust_statedump:build_id");
145 info->q_statedump_start = g_quark_from_string(
146 "lttng_ust_statedump:start");
147 info->q_dl_open = g_quark_from_string("lttng_ust_dl:dlopen");
148 info->q_lib_load = g_quark_from_string("lttng_ust_lib:load");
149 info->q_lib_unload = g_quark_from_string("lttng_ust_lib:unload");
150
151 return bin_info_init(info->log_level);
152 }
153
154 static
155 void debug_info_source_destroy(struct debug_info_source *debug_info_src)
156 {
157 if (!debug_info_src) {
158 return;
159 }
160
161 g_free(debug_info_src->func);
162 g_free(debug_info_src->line_no);
163 g_free(debug_info_src->src_path);
164 g_free(debug_info_src->bin_path);
165 g_free(debug_info_src->bin_loc);
166 g_free(debug_info_src);
167 }
168
169 static
170 struct debug_info_source *debug_info_source_create_from_bin(
171 struct bin_info *bin, uint64_t ip)
172 {
173 int ret;
174 struct debug_info_source *debug_info_src = NULL;
175 struct source_location *src_loc = NULL;
176 bt_logging_level log_level = bin->log_level;
177
178 debug_info_src = g_new0(struct debug_info_source, 1);
179
180 if (!debug_info_src) {
181 goto end;
182 }
183
184 /* Lookup function name */
185 ret = bin_info_lookup_function_name(bin, ip, &debug_info_src->func);
186 if (ret) {
187 goto error;
188 }
189
190 /* Can't retrieve src_loc from ELF, or could not find binary, skip. */
191 if (!bin->is_elf_only || !debug_info_src->func) {
192 /* Lookup source location */
193 ret = bin_info_lookup_source_location(bin, ip, &src_loc);
194 if (ret) {
195 BT_LOGI("Failed to lookup source location: ret=%d", ret);
196 }
197 }
198
199 if (src_loc) {
200 debug_info_src->line_no =
201 g_strdup_printf("%"PRId64, src_loc->line_no);
202 if (!debug_info_src->line_no) {
203 BT_LOGE("Error occured when setting line_no field.");
204 goto error;
205 }
206
207 if (src_loc->filename) {
208 debug_info_src->src_path = g_strdup(src_loc->filename);
209 if (!debug_info_src->src_path) {
210 goto error;
211 }
212
213 debug_info_src->short_src_path = get_filename_from_path(
214 debug_info_src->src_path);
215 }
216 source_location_destroy(src_loc);
217 }
218
219 if (bin->elf_path) {
220 debug_info_src->bin_path = g_strdup(bin->elf_path);
221 if (!debug_info_src->bin_path) {
222 goto error;
223 }
224
225 debug_info_src->short_bin_path = get_filename_from_path(
226 debug_info_src->bin_path);
227
228 ret = bin_info_get_bin_loc(bin, ip, &(debug_info_src->bin_loc));
229 if (ret) {
230 goto error;
231 }
232 }
233
234 end:
235 return debug_info_src;
236
237 error:
238 debug_info_source_destroy(debug_info_src);
239 return NULL;
240 }
241
242 static
243 void proc_debug_info_sources_destroy(
244 struct proc_debug_info_sources *proc_dbg_info_src)
245 {
246 if (!proc_dbg_info_src) {
247 return;
248 }
249
250 if (proc_dbg_info_src->baddr_to_bin_info) {
251 g_hash_table_destroy(proc_dbg_info_src->baddr_to_bin_info);
252 }
253
254 if (proc_dbg_info_src->ip_to_debug_info_src) {
255 g_hash_table_destroy(proc_dbg_info_src->ip_to_debug_info_src);
256 }
257
258 g_free(proc_dbg_info_src);
259 }
260
261 static
262 struct proc_debug_info_sources *proc_debug_info_sources_create(void)
263 {
264 struct proc_debug_info_sources *proc_dbg_info_src = NULL;
265
266 proc_dbg_info_src = g_new0(struct proc_debug_info_sources, 1);
267 if (!proc_dbg_info_src) {
268 goto end;
269 }
270
271 proc_dbg_info_src->baddr_to_bin_info = g_hash_table_new_full(
272 g_int64_hash, g_int64_equal, (GDestroyNotify) g_free,
273 (GDestroyNotify) bin_info_destroy);
274 if (!proc_dbg_info_src->baddr_to_bin_info) {
275 goto error;
276 }
277
278 proc_dbg_info_src->ip_to_debug_info_src = g_hash_table_new_full(
279 g_int64_hash, g_int64_equal, (GDestroyNotify) g_free,
280 (GDestroyNotify) debug_info_source_destroy);
281 if (!proc_dbg_info_src->ip_to_debug_info_src) {
282 goto error;
283 }
284
285 end:
286 return proc_dbg_info_src;
287
288 error:
289 proc_debug_info_sources_destroy(proc_dbg_info_src);
290 return NULL;
291 }
292
293 static
294 struct proc_debug_info_sources *proc_debug_info_sources_ht_get_entry(
295 GHashTable *ht, int64_t vpid)
296 {
297 gpointer key = g_new0(int64_t, 1);
298 struct proc_debug_info_sources *proc_dbg_info_src = NULL;
299
300 if (!key) {
301 goto end;
302 }
303
304 *((int64_t *) key) = vpid;
305
306 /* Exists? Return it */
307 proc_dbg_info_src = g_hash_table_lookup(ht, key);
308 if (proc_dbg_info_src) {
309 goto end;
310 }
311
312 /* Otherwise, create and return it */
313 proc_dbg_info_src = proc_debug_info_sources_create();
314 if (!proc_dbg_info_src) {
315 goto end;
316 }
317
318 g_hash_table_insert(ht, key, proc_dbg_info_src);
319 /* Ownership passed to ht */
320 key = NULL;
321 end:
322 g_free(key);
323 return proc_dbg_info_src;
324 }
325
326 static inline
327 const bt_field *event_borrow_payload_field(const bt_event *event,
328 const char *field_name)
329 {
330 const bt_field *event_payload, *field;
331
332 event_payload = bt_event_borrow_payload_field_const(event);
333 BT_ASSERT(event_payload);
334
335 field = bt_field_structure_borrow_member_field_by_name_const(
336 event_payload, field_name);
337 return field;
338 }
339
340 static inline
341 const bt_field *event_borrow_common_context_field(const bt_event *event,
342 const char *field_name)
343 {
344 const bt_field *event_common_ctx, *field = NULL;
345
346 event_common_ctx = bt_event_borrow_common_context_field_const(event);
347 if (!event_common_ctx) {
348 goto end;
349 }
350
351 field = bt_field_structure_borrow_member_field_by_name_const(
352 event_common_ctx, field_name);
353
354 end:
355 return field;
356 }
357
358 static inline
359 void event_get_common_context_signed_integer_field_value(
360 const bt_event *event, const char *field_name, int64_t *value)
361 {
362 *value = bt_field_signed_integer_get_value(
363 event_borrow_common_context_field(event, field_name));
364 }
365
366 static inline
367 int event_get_payload_build_id_length(const bt_event *event,
368 const char *field_name, uint64_t *build_id_len)
369 {
370 const bt_field *build_id_field;
371 const bt_field_class *build_id_field_class;
372
373 build_id_field = event_borrow_payload_field(event, field_name);
374 build_id_field_class = bt_field_borrow_class_const(build_id_field);
375
376 BT_ASSERT(bt_field_class_get_type(build_id_field_class) ==
377 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY);
378 BT_ASSERT(bt_field_class_get_type(
379 bt_field_class_array_borrow_element_field_class_const(
380 build_id_field_class)) ==
381 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER);
382
383 *build_id_len = bt_field_array_get_length(build_id_field);
384
385 return 0;
386 }
387
388 static inline
389 int event_get_payload_build_id_value(const bt_event *event,
390 const char *field_name, uint8_t *build_id)
391 {
392 const bt_field *curr_field, *build_id_field;
393 const bt_field_class *build_id_field_class;
394 uint64_t i, build_id_len;
395 int ret;
396
397 ret = 0;
398
399 build_id_field = event_borrow_payload_field(event, field_name);
400 build_id_field_class = bt_field_borrow_class_const(build_id_field);
401
402 BT_ASSERT(bt_field_class_get_type(build_id_field_class) ==
403 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY);
404 BT_ASSERT(bt_field_class_get_type(
405 bt_field_class_array_borrow_element_field_class_const(
406 build_id_field_class)) ==
407 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER);
408
409 build_id_len = bt_field_array_get_length(build_id_field);
410
411 for (i = 0; i < build_id_len; i++) {
412 curr_field =
413 bt_field_array_borrow_element_field_by_index_const(
414 build_id_field, i);
415
416 build_id[i] = bt_field_unsigned_integer_get_value(curr_field);
417 }
418
419 return ret;
420 }
421
422 static
423 void event_get_payload_unsigned_integer_field_value(const bt_event *event,
424 const char *field_name, uint64_t *value)
425 {
426 *value = bt_field_unsigned_integer_get_value(
427 event_borrow_payload_field(event, field_name));
428 }
429
430 static
431 void event_get_payload_string_field_value(const bt_event *event,
432 const char *field_name, const char **value)
433 {
434 *value = bt_field_string_get_value(
435 event_borrow_payload_field(event, field_name));
436 }
437
438 static inline
439 bool event_has_payload_field(const bt_event *event,
440 const char *field_name)
441 {
442 return event_borrow_payload_field(event, field_name) != NULL;
443 }
444
445 static
446 struct debug_info_source *proc_debug_info_sources_get_entry(
447 struct debug_info *debug_info,
448 struct proc_debug_info_sources *proc_dbg_info_src, uint64_t ip)
449 {
450 struct debug_info_source *debug_info_src = NULL;
451 gpointer key = g_new0(uint64_t, 1);
452 GHashTableIter iter;
453 gpointer baddr, value;
454
455 if (!key) {
456 goto end;
457 }
458
459 *((uint64_t *) key) = ip;
460
461 /* Look in IP to debug infos hash table first. */
462 debug_info_src = g_hash_table_lookup(
463 proc_dbg_info_src->ip_to_debug_info_src,
464 key);
465 if (debug_info_src) {
466 goto end;
467 }
468
469 /* Check in all bin_infos. */
470 g_hash_table_iter_init(&iter, proc_dbg_info_src->baddr_to_bin_info);
471
472 while (g_hash_table_iter_next(&iter, &baddr, &value))
473 {
474 struct bin_info *bin = value;
475
476 if (!bin_info_has_address(value, ip)) {
477 continue;
478 }
479
480 /*
481 * Found; add it to cache.
482 *
483 * FIXME: this should be bounded in size (and implement
484 * a caching policy), and entries should be prunned when
485 * libraries are unmapped.
486 */
487 debug_info_src = debug_info_source_create_from_bin(bin, ip);
488 if (debug_info_src) {
489 g_hash_table_insert(
490 proc_dbg_info_src->ip_to_debug_info_src,
491 key, debug_info_src);
492 /* Ownership passed to ht. */
493 key = NULL;
494 }
495 break;
496 }
497
498 end:
499 free(key);
500 return debug_info_src;
501 }
502
503 static
504 struct debug_info_source *debug_info_query(struct debug_info *debug_info,
505 int64_t vpid, uint64_t ip)
506 {
507 struct debug_info_source *dbg_info_src = NULL;
508 struct proc_debug_info_sources *proc_dbg_info_src;
509
510 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
511 debug_info->vpid_to_proc_dbg_info_src, vpid);
512 if (!proc_dbg_info_src) {
513 goto end;
514 }
515
516 dbg_info_src = proc_debug_info_sources_get_entry(debug_info,
517 proc_dbg_info_src, ip);
518
519 end:
520 return dbg_info_src;
521 }
522
523 static
524 struct debug_info *debug_info_create(struct debug_info_component *comp,
525 const bt_trace *trace, struct bt_fd_cache *fdc)
526 {
527 int ret;
528 struct debug_info *debug_info;
529
530 BT_ASSERT(comp);
531 BT_ASSERT(trace);
532 BT_ASSERT(fdc);
533
534 debug_info = g_new0(struct debug_info, 1);
535 if (!debug_info) {
536 goto end;
537 }
538
539 debug_info->log_level = comp->log_level;
540 debug_info->vpid_to_proc_dbg_info_src = g_hash_table_new_full(
541 g_int64_hash, g_int64_equal, (GDestroyNotify) g_free,
542 (GDestroyNotify) proc_debug_info_sources_destroy);
543 if (!debug_info->vpid_to_proc_dbg_info_src) {
544 goto error;
545 }
546
547 debug_info->comp = comp;
548 ret = debug_info_init(debug_info);
549 if (ret) {
550 goto error;
551 }
552
553 debug_info->input_trace = trace;
554 debug_info->fd_cache = fdc;
555
556 end:
557 return debug_info;
558 error:
559 g_free(debug_info);
560 return NULL;
561 }
562
563 static
564 void debug_info_destroy(struct debug_info *debug_info)
565 {
566 bt_logging_level log_level;
567 bt_trace_status status;
568 if (!debug_info) {
569 goto end;
570 }
571
572 log_level = debug_info->log_level;
573
574 if (debug_info->vpid_to_proc_dbg_info_src) {
575 g_hash_table_destroy(debug_info->vpid_to_proc_dbg_info_src);
576 }
577
578 status = bt_trace_remove_destruction_listener(debug_info->input_trace,
579 debug_info->destruction_listener_id);
580 if (status != BT_TRACE_STATUS_OK) {
581 BT_LOGE("Trace destruction listener removal failed.");
582 }
583
584 g_free(debug_info);
585 end:
586 return;
587 }
588
589 static
590 void handle_event_statedump_build_id(struct debug_info *debug_info,
591 const bt_event *event)
592 {
593 struct proc_debug_info_sources *proc_dbg_info_src;
594 uint64_t build_id_len, baddr;
595 uint8_t *build_id = NULL;
596 struct bin_info *bin;
597 int64_t vpid;
598 int ret = 0;
599
600 event_get_common_context_signed_integer_field_value(event,
601 VPID_FIELD_NAME, &vpid);
602 event_get_payload_unsigned_integer_field_value(event,
603 BADDR_FIELD_NAME, &baddr);
604
605 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
606 debug_info->vpid_to_proc_dbg_info_src, vpid);
607 if (!proc_dbg_info_src) {
608 goto end;
609 }
610
611 bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info,
612 (gpointer) &baddr);
613 if (!bin) {
614 /*
615 * The build_id event comes after the bin has been
616 * created. If it isn't found, just ignore this event.
617 */
618 goto end;
619 }
620 ret = event_get_payload_build_id_length(event, BUILD_ID_FIELD_NAME,
621 &build_id_len);
622
623 build_id = g_new0(uint8_t, build_id_len);
624 if (!build_id) {
625 goto end;
626 }
627
628 ret = event_get_payload_build_id_value(event, BUILD_ID_FIELD_NAME,
629 build_id);
630 if (ret) {
631 goto end;
632 }
633
634 ret = bin_info_set_build_id(bin, build_id, build_id_len);
635 if (ret) {
636 goto end;
637 }
638
639 /*
640 * Reset the is_elf_only flag in case it had been set
641 * previously, because we might find separate debug info using
642 * the new build id information.
643 */
644 bin->is_elf_only = false;
645
646 end:
647 g_free(build_id);
648 return;
649 }
650
651 static
652 void handle_event_statedump_debug_link(struct debug_info *debug_info,
653 const bt_event *event)
654 {
655 struct proc_debug_info_sources *proc_dbg_info_src;
656 struct bin_info *bin = NULL;
657 int64_t vpid;
658 uint64_t baddr;
659 const char *filename = NULL;
660 uint32_t crc32;
661 uint64_t crc_field_value;
662
663 event_get_common_context_signed_integer_field_value(event,
664 VPID_FIELD_NAME, &vpid);
665
666 event_get_payload_unsigned_integer_field_value(event,
667 BADDR_FIELD_NAME, &baddr);
668
669 event_get_payload_unsigned_integer_field_value(event,
670 CRC32_FIELD_NAME, &crc_field_value);
671
672 crc32 = (uint32_t) crc_field_value;
673
674 event_get_payload_string_field_value(event,
675 FILENAME_FIELD_NAME, &filename);
676
677 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
678 debug_info->vpid_to_proc_dbg_info_src, vpid);
679 if (!proc_dbg_info_src) {
680 goto end;
681 }
682
683 bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info,
684 (gpointer) &baddr);
685 if (!bin) {
686 /*
687 * The debug_link event comes after the bin has been
688 * created. If it isn't found, just ignore this event.
689 */
690 goto end;
691 }
692
693 bin_info_set_debug_link(bin, filename, crc32);
694
695 end:
696 return;
697 }
698
699 static
700 void handle_bin_info_event(struct debug_info *debug_info,
701 const bt_event *event, bool has_pic_field)
702 {
703 struct proc_debug_info_sources *proc_dbg_info_src;
704 struct bin_info *bin;
705 uint64_t baddr, memsz;
706 int64_t vpid;
707 const char *path;
708 gpointer key = NULL;
709 bool is_pic;
710
711 event_get_payload_unsigned_integer_field_value(event,
712 MEMSZ_FIELD_NAME, &memsz);
713 if (memsz == 0) {
714 /* Ignore VDSO. */
715 goto end;
716 }
717
718 event_get_payload_unsigned_integer_field_value(event,
719 BADDR_FIELD_NAME, &baddr);
720
721 /*
722 * This field is not produced by the dlopen event emitted before
723 * lttng-ust 2.9.
724 */
725 if (!event_has_payload_field(event, PATH_FIELD_NAME)) {
726 goto end;
727 }
728 event_get_payload_string_field_value(event, PATH_FIELD_NAME, &path);
729
730 if (has_pic_field) {
731 uint64_t is_pic_field_value;
732
733 event_get_payload_unsigned_integer_field_value(event,
734 IS_PIC_FIELD_NAME, &is_pic_field_value);
735 is_pic = is_pic_field_value == 1;
736 } else {
737 /*
738 * dlopen has no is_pic field, because the shared
739 * object is always PIC.
740 */
741 is_pic = true;
742 }
743
744 event_get_common_context_signed_integer_field_value(event,
745 VPID_FIELD_NAME, &vpid);
746
747 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
748 debug_info->vpid_to_proc_dbg_info_src, vpid);
749 if (!proc_dbg_info_src) {
750 goto end;
751 }
752
753 key = g_new0(uint64_t, 1);
754 if (!key) {
755 goto end;
756 }
757
758 *((uint64_t *) key) = baddr;
759
760 bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info, key);
761 if (bin) {
762 goto end;
763 }
764
765 bin = bin_info_create(debug_info->fd_cache, path, baddr, memsz, is_pic,
766 debug_info->comp->arg_debug_dir,
767 debug_info->comp->arg_target_prefix,
768 debug_info->log_level);
769 if (!bin) {
770 goto end;
771 }
772
773 g_hash_table_insert(proc_dbg_info_src->baddr_to_bin_info, key, bin);
774 /* Ownership passed to ht. */
775 key = NULL;
776
777 end:
778 g_free(key);
779 return;
780 }
781
782 static inline
783 void handle_event_statedump_bin_info(struct debug_info *debug_info,
784 const bt_event *event)
785 {
786 handle_bin_info_event(debug_info, event, true);
787 }
788
789 static inline
790 void handle_event_lib_load(struct debug_info *debug_info,
791 const bt_event *event)
792 {
793 handle_bin_info_event(debug_info, event, false);
794 }
795
796 static
797 void handle_event_lib_unload(struct debug_info *debug_info,
798 const bt_event *event)
799 {
800 gboolean ret;
801 struct proc_debug_info_sources *proc_dbg_info_src;
802 uint64_t baddr;
803 int64_t vpid;
804
805 event_get_payload_unsigned_integer_field_value(event, BADDR_FIELD_NAME,
806 &baddr);
807
808 event_get_common_context_signed_integer_field_value(event,
809 VPID_FIELD_NAME, &vpid);
810
811 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
812 debug_info->vpid_to_proc_dbg_info_src, vpid);
813 if (!proc_dbg_info_src) {
814 /*
815 * It's an unload event for a library for which no load event
816 * was previously received.
817 */
818 goto end;
819 }
820
821 ret = g_hash_table_remove(proc_dbg_info_src->baddr_to_bin_info,
822 (gpointer) &baddr);
823 BT_ASSERT(ret);
824 end:
825 return;
826 }
827
828 static
829 void handle_event_statedump_start(struct debug_info *debug_info,
830 const bt_event *event)
831 {
832 struct proc_debug_info_sources *proc_dbg_info_src;
833 int64_t vpid;
834
835 event_get_common_context_signed_integer_field_value(
836 event, VPID_FIELD_NAME, &vpid);
837
838 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
839 debug_info->vpid_to_proc_dbg_info_src, vpid);
840 if (!proc_dbg_info_src) {
841 goto end;
842 }
843
844 g_hash_table_remove_all(proc_dbg_info_src->baddr_to_bin_info);
845 g_hash_table_remove_all(proc_dbg_info_src->ip_to_debug_info_src);
846
847 end:
848 return;
849 }
850
851 void trace_debug_info_remove_func(const bt_trace *in_trace, void *data)
852 {
853 struct debug_info_msg_iter *debug_it = data;
854 if (debug_it->debug_info_map) {
855 gboolean ret;
856 ret = g_hash_table_remove(debug_it->debug_info_map,
857 (gpointer) in_trace);
858 BT_ASSERT(ret);
859 }
860 }
861
862 static
863 void handle_event_statedump(struct debug_info_msg_iter *debug_it,
864 const bt_event *event)
865 {
866 const bt_event_class *event_class;
867 const char *event_name;
868 GQuark q_event_name;
869 const bt_trace *trace;
870 struct debug_info *debug_info;
871
872 BT_ASSERT(debug_it);
873 BT_ASSERT(event);
874
875 event_class = bt_event_borrow_class_const(event);
876
877 event_name = bt_event_class_get_name(event_class);
878
879 trace = bt_stream_borrow_trace_const(
880 bt_event_borrow_stream_const(event));
881
882 debug_info = g_hash_table_lookup(debug_it->debug_info_map, trace);
883 if (!debug_info) {
884 debug_info = debug_info_create(debug_it->debug_info_component,
885 trace, &debug_it->fd_cache);
886 g_hash_table_insert(debug_it->debug_info_map, (gpointer) trace,
887 debug_info);
888 bt_trace_add_destruction_listener(trace,
889 trace_debug_info_remove_func, debug_it,
890 &debug_info->destruction_listener_id);
891 }
892
893 q_event_name = g_quark_try_string(event_name);
894
895 if (q_event_name == debug_info->q_statedump_bin_info) {
896 /* State dump */
897 handle_event_statedump_bin_info(debug_info, event);
898 } else if (q_event_name == debug_info->q_dl_open ||
899 q_event_name == debug_info->q_lib_load) {
900 /*
901 * dl_open and lib_load events are both checked for since
902 * only dl_open was produced as of lttng-ust 2.8.
903 *
904 * lib_load, which is produced from lttng-ust 2.9+, is a lot
905 * more reliable since it will be emitted when other functions
906 * of the dlopen family are called (e.g. dlmopen) and when
907 * library are transitively loaded.
908 */
909 handle_event_lib_load(debug_info, event);
910 } else if (q_event_name == debug_info->q_statedump_start) {
911 /* Start state dump */
912 handle_event_statedump_start(debug_info, event);
913 } else if (q_event_name == debug_info->q_statedump_debug_link) {
914 /* Debug link info */
915 handle_event_statedump_debug_link(debug_info, event);
916 } else if (q_event_name == debug_info->q_statedump_build_id) {
917 /* Build ID info */
918 handle_event_statedump_build_id(debug_info, event);
919 } else if (q_event_name == debug_info-> q_lib_unload) {
920 handle_event_lib_unload(debug_info, event);
921 }
922
923 return;
924 }
925
926 static
927 void destroy_debug_info_comp(struct debug_info_component *debug_info)
928 {
929 if (!debug_info) {
930 return;
931 }
932
933 g_free(debug_info->arg_debug_dir);
934 g_free(debug_info->arg_debug_info_field_name);
935 g_free(debug_info->arg_target_prefix);
936 g_free(debug_info);
937 }
938
939 static
940 void fill_debug_info_bin_field(struct debug_info_source *dbg_info_src,
941 bool full_path, bt_field *curr_field,
942 bt_logging_level log_level)
943 {
944 bt_field_status status;
945
946 BT_ASSERT(bt_field_get_class_type(curr_field) ==
947 BT_FIELD_CLASS_TYPE_STRING);
948
949 if (dbg_info_src) {
950 if (full_path) {
951 status = bt_field_string_set_value(curr_field,
952 dbg_info_src->bin_path);
953 } else {
954 status = bt_field_string_set_value(curr_field,
955 dbg_info_src->short_bin_path);
956 }
957 if (status != BT_FIELD_STATUS_OK) {
958 BT_LOGE("Cannot set path component of \"bin\" "
959 "curr_field field's value: str-fc-addr=%p",
960 curr_field);
961 }
962
963 status = bt_field_string_append(curr_field, dbg_info_src->bin_loc);
964 if (status != BT_FIELD_STATUS_OK) {
965 BT_LOGE("Cannot set bin location component of \"bin\" "
966 "curr_field field's value: str-fc-addr=%p",
967 curr_field);
968 }
969 } else {
970 status = bt_field_string_set_value(curr_field, "");
971 if (status != BT_FIELD_STATUS_OK) {
972 BT_LOGE("Cannot set \"bin\" curr_field field's value: "
973 "str-fc-addr=%p", curr_field);
974 }
975 }
976 }
977
978 static
979 void fill_debug_info_func_field(struct debug_info_source *dbg_info_src,
980 bt_field *curr_field, bt_logging_level log_level)
981 {
982 bt_field_status status;
983
984 BT_ASSERT(bt_field_get_class_type(curr_field) ==
985 BT_FIELD_CLASS_TYPE_STRING);
986 if (dbg_info_src && dbg_info_src->func) {
987 status = bt_field_string_set_value(curr_field,
988 dbg_info_src->func);
989 } else {
990 status = bt_field_string_set_value(curr_field, "");
991 }
992 if (status != BT_FIELD_STATUS_OK) {
993 BT_LOGE("Cannot set \"func\" curr_field field's value: "
994 "str-fc-addr=%p", curr_field);
995 }
996 }
997
998 static
999 void fill_debug_info_src_field(struct debug_info_source *dbg_info_src,
1000 bool full_path, bt_field *curr_field,
1001 bt_logging_level log_level)
1002 {
1003 bt_field_status status;
1004
1005 BT_ASSERT(bt_field_get_class_type(curr_field) ==
1006 BT_FIELD_CLASS_TYPE_STRING);
1007
1008 if (dbg_info_src && dbg_info_src->src_path) {
1009 if (full_path) {
1010 status = bt_field_string_set_value(curr_field,
1011 dbg_info_src->src_path);
1012 } else {
1013 status = bt_field_string_set_value(curr_field,
1014 dbg_info_src->short_src_path);
1015 }
1016 if (status != BT_FIELD_STATUS_OK) {
1017 BT_LOGE("Cannot set path component of \"src\" "
1018 "curr_field field's value: str-fc-addr=%p",
1019 curr_field);
1020 }
1021
1022 status = bt_field_string_append(curr_field, ":");
1023 if (status != BT_FIELD_STATUS_OK) {
1024 BT_LOGE("Cannot set colon component of \"src\" "
1025 "curr_field field's value: str-fc-addr=%p",
1026 curr_field);
1027 }
1028
1029 status = bt_field_string_append(curr_field, dbg_info_src->line_no);
1030 if (status != BT_FIELD_STATUS_OK) {
1031 BT_LOGE("Cannot set line number component of \"src\" "
1032 "curr_field field's value: str-fc-addr=%p",
1033 curr_field);
1034 }
1035 } else {
1036 status = bt_field_string_set_value(curr_field, "");
1037 if (status != BT_FIELD_STATUS_OK) {
1038 BT_LOGE("Cannot set \"src\" curr_field field's value: "
1039 "str-fc-addr=%p", curr_field);
1040 }
1041 }
1042 }
1043
1044 static
1045 void fill_debug_info_field_empty(bt_field *debug_info_field,
1046 bt_logging_level log_level)
1047 {
1048 bt_field_status status;
1049 bt_field *bin_field, *func_field, *src_field;
1050
1051 BT_ASSERT(bt_field_get_class_type(debug_info_field) ==
1052 BT_FIELD_CLASS_TYPE_STRUCTURE);
1053
1054 bin_field = bt_field_structure_borrow_member_field_by_name(
1055 debug_info_field, "bin");
1056 func_field = bt_field_structure_borrow_member_field_by_name(
1057 debug_info_field, "func");
1058 src_field = bt_field_structure_borrow_member_field_by_name(
1059 debug_info_field, "src");
1060
1061 BT_ASSERT(bt_field_get_class_type(bin_field) ==
1062 BT_FIELD_CLASS_TYPE_STRING);
1063 BT_ASSERT(bt_field_get_class_type(func_field) ==
1064 BT_FIELD_CLASS_TYPE_STRING);
1065 BT_ASSERT(bt_field_get_class_type(src_field) ==
1066 BT_FIELD_CLASS_TYPE_STRING);
1067
1068 status = bt_field_string_set_value(bin_field, "");
1069 if (status != BT_FIELD_STATUS_OK) {
1070 BT_LOGE("Cannot set \"bin\" bin_field field's value: "
1071 "str-fc-addr=%p", bin_field);
1072 }
1073
1074 status = bt_field_string_set_value(func_field, "");
1075 if (status != BT_FIELD_STATUS_OK) {
1076 BT_LOGE("Cannot set \"func\" func_field field's value: "
1077 "str-fc-addr=%p", func_field);
1078 }
1079
1080 status = bt_field_string_set_value(src_field, "");
1081 if (status != BT_FIELD_STATUS_OK) {
1082 BT_LOGE("Cannot set \"src\" src_field field's value: "
1083 "str-fc-addr=%p", src_field);
1084 }
1085 }
1086 static
1087 void fill_debug_info_field(struct debug_info *debug_info, int64_t vpid,
1088 uint64_t ip, bt_field *debug_info_field)
1089 {
1090 struct debug_info_source *dbg_info_src;
1091 const bt_field_class *debug_info_fc;
1092
1093 BT_ASSERT(bt_field_get_class_type(debug_info_field) ==
1094 BT_FIELD_CLASS_TYPE_STRUCTURE);
1095
1096 debug_info_fc = bt_field_borrow_class_const(debug_info_field);
1097
1098 BT_ASSERT(bt_field_class_structure_get_member_count(debug_info_fc) == 3);
1099
1100 dbg_info_src = debug_info_query(debug_info, vpid, ip);
1101
1102 fill_debug_info_bin_field(dbg_info_src,
1103 debug_info->comp->arg_full_path,
1104 bt_field_structure_borrow_member_field_by_name(
1105 debug_info_field, "bin"),
1106 debug_info->log_level);
1107 fill_debug_info_func_field(dbg_info_src,
1108 bt_field_structure_borrow_member_field_by_name(
1109 debug_info_field, "func"),
1110 debug_info->log_level);
1111 fill_debug_info_src_field(dbg_info_src,
1112 debug_info->comp->arg_full_path,
1113 bt_field_structure_borrow_member_field_by_name(
1114 debug_info_field, "src"),
1115 debug_info->log_level);
1116 }
1117
1118 static
1119 void fill_debug_info_event_if_needed(struct debug_info_msg_iter *debug_it,
1120 const bt_event *in_event, bt_event *out_event)
1121 {
1122 bt_field *out_common_ctx_field, *out_debug_info_field;
1123 const bt_field *vpid_field, *ip_field, *in_common_ctx_field;
1124 const bt_field_class *in_common_ctx_fc;
1125 struct debug_info *debug_info;
1126 uint64_t vpid;
1127 int64_t ip;
1128 gchar *debug_info_field_name =
1129 debug_it->debug_info_component->arg_debug_info_field_name;
1130 bt_logging_level log_level = debug_it->log_level;
1131
1132 in_common_ctx_field = bt_event_borrow_common_context_field_const(
1133 in_event);
1134 if (!in_common_ctx_field) {
1135 /*
1136 * There is no event common context so no need to add debug
1137 * info field.
1138 */
1139 goto end;
1140 }
1141
1142 in_common_ctx_fc = bt_field_borrow_class_const(in_common_ctx_field);
1143 if (!is_event_common_ctx_dbg_info_compatible(in_common_ctx_fc,
1144 debug_it->ir_maps->debug_info_field_class_name)) {
1145 /*
1146 * The input event common context does not have the necessary
1147 * fields to resolve debug information.
1148 */
1149 goto end;
1150 }
1151
1152 /* Borrow the debug-info field. */
1153 out_common_ctx_field = bt_event_borrow_common_context_field(out_event);
1154 if (!out_common_ctx_field) {
1155 goto end;
1156 }
1157
1158 out_debug_info_field = bt_field_structure_borrow_member_field_by_name(
1159 out_common_ctx_field, debug_info_field_name);
1160
1161 vpid_field = bt_field_structure_borrow_member_field_by_name_const(
1162 out_common_ctx_field, VPID_FIELD_NAME);
1163 ip_field = bt_field_structure_borrow_member_field_by_name_const(
1164 out_common_ctx_field, IP_FIELD_NAME);
1165
1166 vpid = bt_field_signed_integer_get_value(vpid_field);
1167 ip = bt_field_unsigned_integer_get_value(ip_field);
1168
1169 /*
1170 * Borrow the debug_info structure needed for the source
1171 * resolving.
1172 */
1173 debug_info = g_hash_table_lookup(debug_it->debug_info_map,
1174 bt_stream_borrow_trace_const(
1175 bt_event_borrow_stream_const(in_event)));
1176
1177 if (debug_info) {
1178 /*
1179 * Perform the debug-info resolving and set the event fields
1180 * accordingly.
1181 */
1182 fill_debug_info_field(debug_info, vpid, ip, out_debug_info_field);
1183 } else {
1184 BT_LOGD("No debug information for this trace. Setting debug "
1185 "info fields to empty strings.");
1186 fill_debug_info_field_empty(out_debug_info_field, log_level);
1187 }
1188 end:
1189 return;
1190 }
1191
1192 static
1193 void update_event_statedump_if_needed(struct debug_info_msg_iter *debug_it,
1194 const bt_event *in_event)
1195 {
1196 const bt_field *event_common_ctx;
1197 const bt_field_class *event_common_ctx_fc;
1198 const bt_event_class *in_event_class = bt_event_borrow_class_const(in_event);
1199
1200 /*
1201 * If the event is an lttng_ust_statedump event AND has the right event
1202 * common context fields update the debug-info view for this process.
1203 */
1204 event_common_ctx = bt_event_borrow_common_context_field_const(in_event);
1205 if (!event_common_ctx) {
1206 goto end;
1207 }
1208
1209 event_common_ctx_fc = bt_field_borrow_class_const(event_common_ctx);
1210 if (is_event_common_ctx_dbg_info_compatible(event_common_ctx_fc,
1211 debug_it->ir_maps->debug_info_field_class_name)) {
1212 /* Checkout if it might be a one of lttng ust statedump events. */
1213 const char *in_event_name = bt_event_class_get_name(in_event_class);
1214 if (strncmp(in_event_name, LTTNG_UST_STATEDUMP_PREFIX,
1215 strlen(LTTNG_UST_STATEDUMP_PREFIX)) == 0) {
1216 /* Handle statedump events. */
1217 handle_event_statedump(debug_it, in_event);
1218 }
1219 }
1220 end:
1221 return;
1222 }
1223
1224 static
1225 bt_message *handle_event_message(struct debug_info_msg_iter *debug_it,
1226 const bt_message *in_message)
1227 {
1228 const bt_clock_snapshot *cs;
1229 const bt_clock_class *default_cc;
1230 const bt_packet *in_packet;
1231 bt_event_class *out_event_class;
1232 bt_packet *out_packet;
1233 bt_event *out_event;
1234 bt_logging_level log_level = debug_it->log_level;
1235
1236 bt_message *out_message = NULL;
1237
1238 /* Borrow the input event and its event class. */
1239 const bt_event *in_event =
1240 bt_message_event_borrow_event_const(in_message);
1241 const bt_event_class *in_event_class =
1242 bt_event_borrow_class_const(in_event);
1243
1244 update_event_statedump_if_needed(debug_it, in_event);
1245
1246 out_event_class = trace_ir_mapping_borrow_mapped_event_class(
1247 debug_it->ir_maps, in_event_class);
1248 if (!out_event_class) {
1249 out_event_class = trace_ir_mapping_create_new_mapped_event_class(
1250 debug_it->ir_maps, in_event_class);
1251 }
1252 BT_ASSERT(out_event_class);
1253
1254 /* Borrow the input and output packets. */
1255 in_packet = bt_event_borrow_packet_const(in_event);
1256 out_packet = trace_ir_mapping_borrow_mapped_packet(debug_it->ir_maps,
1257 in_packet);
1258
1259 default_cc = bt_stream_class_borrow_default_clock_class_const(
1260 bt_event_class_borrow_stream_class_const(in_event_class));
1261 if (default_cc) {
1262 /* Borrow event clock snapshot. */
1263 cs = bt_message_event_borrow_default_clock_snapshot_const(
1264 in_message);
1265
1266 /* Create an output event message. */
1267 out_message = bt_message_event_create_with_default_clock_snapshot(
1268 debug_it->input_iterator,
1269 out_event_class, out_packet,
1270 bt_clock_snapshot_get_value(cs));
1271 } else {
1272 out_message = bt_message_event_create(debug_it->input_iterator,
1273 out_event_class, out_packet);
1274 }
1275
1276 if (!out_message) {
1277 BT_LOGE("Error creating output event message.");
1278 goto error;
1279 }
1280
1281 out_event = bt_message_event_borrow_event(out_message);
1282
1283 /* Copy the original fields to the output event. */
1284 copy_event_content(in_event, out_event, log_level);
1285
1286 /*
1287 * Try to set the debug-info fields based on debug information that is
1288 * gathered so far.
1289 */
1290 fill_debug_info_event_if_needed(debug_it, in_event, out_event);
1291
1292 error:
1293 return out_message;
1294 }
1295
1296 static
1297 bt_message *handle_stream_begin_message(struct debug_info_msg_iter *debug_it,
1298 const bt_message *in_message)
1299 {
1300 const bt_stream *in_stream;
1301 bt_message *out_message;
1302 bt_stream *out_stream;
1303 bt_logging_level log_level = debug_it->log_level;
1304
1305 in_stream = bt_message_stream_beginning_borrow_stream_const(in_message);
1306 BT_ASSERT(in_stream);
1307
1308 /* Create a duplicated output stream. */
1309 out_stream = trace_ir_mapping_create_new_mapped_stream(
1310 debug_it->ir_maps, in_stream);
1311 if (!out_stream) {
1312 out_message = NULL;
1313 goto error;
1314 }
1315
1316 /* Create an output stream beginning message. */
1317 out_message = bt_message_stream_beginning_create(
1318 debug_it->input_iterator, out_stream);
1319 if (!out_message) {
1320 BT_LOGE("Error creating output stream beginning message: "
1321 "out-s-addr=%p", out_stream);
1322 }
1323 error:
1324 return out_message;
1325 }
1326
1327 static
1328 bt_message *handle_stream_end_message(struct debug_info_msg_iter *debug_it,
1329 const bt_message *in_message)
1330 {
1331 const bt_stream *in_stream;
1332 bt_message *out_message = NULL;
1333 bt_stream *out_stream;
1334 bt_logging_level log_level = debug_it->log_level;
1335
1336 in_stream = bt_message_stream_end_borrow_stream_const(in_message);
1337 BT_ASSERT(in_stream);
1338
1339 out_stream = trace_ir_mapping_borrow_mapped_stream(
1340 debug_it->ir_maps, in_stream);
1341 BT_ASSERT(out_stream);
1342
1343 /* Create an output stream end message. */
1344 out_message = bt_message_stream_end_create(debug_it->input_iterator,
1345 out_stream);
1346 if (!out_message) {
1347 BT_LOGE("Error creating output stream end message: out-s-addr=%p",
1348 out_stream);
1349 }
1350
1351 /* Remove stream from trace mapping hashtable. */
1352 trace_ir_mapping_remove_mapped_stream(debug_it->ir_maps, in_stream);
1353
1354 return out_message;
1355 }
1356
1357 static
1358 bt_message *handle_packet_begin_message(struct debug_info_msg_iter *debug_it,
1359 const bt_message *in_message)
1360 {
1361 bool has_default_clock_snapshot;
1362 const bt_clock_snapshot *cs;
1363 bt_message *out_message = NULL;
1364 bt_packet *out_packet;
1365 bt_logging_level log_level = debug_it->log_level;
1366
1367 const bt_packet *in_packet =
1368 bt_message_packet_beginning_borrow_packet_const(in_message);
1369 BT_ASSERT(in_packet);
1370
1371 /* This packet should not be already mapped. */
1372 BT_ASSERT(!trace_ir_mapping_borrow_mapped_packet(
1373 debug_it->ir_maps, in_packet));
1374
1375 out_packet = trace_ir_mapping_create_new_mapped_packet(debug_it->ir_maps,
1376 in_packet);
1377
1378 BT_ASSERT(out_packet);
1379
1380 has_default_clock_snapshot =
1381 bt_stream_class_packets_have_beginning_default_clock_snapshot(
1382 bt_stream_borrow_class_const(
1383 bt_packet_borrow_stream_const(in_packet)));
1384 if (has_default_clock_snapshot) {
1385 /* Borrow clock snapshot. */
1386 cs = bt_message_packet_beginning_borrow_default_clock_snapshot_const(
1387 in_message);
1388
1389 /* Create an output packet beginning message. */
1390 out_message = bt_message_packet_beginning_create_with_default_clock_snapshot(
1391 debug_it->input_iterator, out_packet,
1392 bt_clock_snapshot_get_value(cs));
1393 } else {
1394 out_message = bt_message_packet_beginning_create(
1395 debug_it->input_iterator, out_packet);
1396 }
1397 if (!out_message) {
1398 BT_LOGE("Error creating output packet beginning message: "
1399 "out-p-addr=%p", out_packet);
1400 }
1401
1402 return out_message;
1403 }
1404
1405 static
1406 bt_message *handle_packet_end_message(struct debug_info_msg_iter *debug_it,
1407 const bt_message *in_message)
1408 {
1409 bool has_default_clock_snapshot;
1410 const bt_clock_snapshot *cs;
1411 const bt_packet *in_packet;
1412 bt_message *out_message = NULL;
1413 bt_packet *out_packet;
1414 bt_logging_level log_level = debug_it->log_level;
1415
1416 in_packet = bt_message_packet_end_borrow_packet_const(in_message);
1417 BT_ASSERT(in_packet);
1418
1419 out_packet = trace_ir_mapping_borrow_mapped_packet(debug_it->ir_maps, in_packet);
1420 BT_ASSERT(out_packet);
1421
1422 has_default_clock_snapshot =
1423 bt_stream_class_packets_have_end_default_clock_snapshot(
1424 bt_stream_borrow_class_const(
1425 bt_packet_borrow_stream_const(in_packet)));
1426 if (has_default_clock_snapshot) {
1427 /* Borrow clock snapshot. */
1428 cs = bt_message_packet_end_borrow_default_clock_snapshot_const(
1429 in_message);
1430
1431 /* Create an outpute packet end message. */
1432 out_message = bt_message_packet_end_create_with_default_clock_snapshot(
1433 debug_it->input_iterator, out_packet,
1434 bt_clock_snapshot_get_value(cs));
1435 } else {
1436 out_message = bt_message_packet_end_create(
1437 debug_it->input_iterator, out_packet);
1438 }
1439
1440 if (!out_message) {
1441 BT_LOGE("Error creating output packet end message: "
1442 "out-p-addr=%p", out_packet);
1443 }
1444
1445 /* Remove packet from data mapping hashtable. */
1446 trace_ir_mapping_remove_mapped_packet(debug_it->ir_maps, in_packet);
1447
1448 return out_message;
1449 }
1450
1451 static
1452 bt_message *handle_msg_iterator_inactivity(struct debug_info_msg_iter *debug_it,
1453 const bt_message *in_message)
1454 {
1455 /*
1456 * This message type can be forwarded directly because it does
1457 * not refer to any objects in the trace class.
1458 */
1459 bt_message_get_ref(in_message);
1460 return (bt_message*) in_message;
1461 }
1462
1463 static
1464 bt_message *handle_stream_act_begin_message(struct debug_info_msg_iter *debug_it,
1465 const bt_message *in_message)
1466 {
1467 const bt_clock_snapshot *cs;
1468 const bt_clock_class *default_cc;
1469 bt_message *out_message = NULL;
1470 bt_stream *out_stream;
1471 uint64_t cs_value;
1472 bt_message_stream_activity_clock_snapshot_state cs_state;
1473 bt_logging_level log_level = debug_it->log_level;
1474
1475 const bt_stream *in_stream =
1476 bt_message_stream_activity_beginning_borrow_stream_const(
1477 in_message);
1478 BT_ASSERT(in_stream);
1479
1480 out_stream = trace_ir_mapping_borrow_mapped_stream(debug_it->ir_maps,
1481 in_stream);
1482 BT_ASSERT(out_stream);
1483
1484 out_message = bt_message_stream_activity_beginning_create(
1485 debug_it->input_iterator, out_stream);
1486 if (!out_message) {
1487 BT_LOGE("Error creating output stream activity beginning "
1488 "message: out-s-addr=%p", out_stream);
1489 goto error;
1490 }
1491
1492 default_cc = bt_stream_class_borrow_default_clock_class_const(
1493 bt_stream_borrow_class_const(in_stream));
1494 if (default_cc) {
1495 /* Borrow clock snapshot. */
1496 cs_state =
1497 bt_message_stream_activity_beginning_borrow_default_clock_snapshot_const(
1498 in_message, &cs);
1499
1500 if (cs_state == BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_KNOWN) {
1501 cs_value = bt_clock_snapshot_get_value(cs);
1502 bt_message_stream_activity_beginning_set_default_clock_snapshot(
1503 out_message, cs_value);
1504 } else {
1505 bt_message_stream_activity_beginning_set_default_clock_snapshot_state(
1506 out_message, cs_state);
1507 }
1508 }
1509
1510 error:
1511 return out_message;
1512 }
1513
1514 static
1515 bt_message *handle_stream_act_end_message(struct debug_info_msg_iter *debug_it,
1516 const bt_message *in_message)
1517 {
1518 const bt_clock_snapshot *cs;
1519 const bt_clock_class *default_cc;
1520 const bt_stream *in_stream;
1521 bt_message *out_message;
1522 bt_stream *out_stream;
1523 uint64_t cs_value;
1524 bt_message_stream_activity_clock_snapshot_state cs_state;
1525 bt_logging_level log_level = debug_it->log_level;
1526
1527 in_stream = bt_message_stream_activity_end_borrow_stream_const(
1528 in_message);
1529 BT_ASSERT(in_stream);
1530
1531 out_stream = trace_ir_mapping_borrow_mapped_stream(debug_it->ir_maps,
1532 in_stream);
1533 BT_ASSERT(out_stream);
1534
1535 out_message = bt_message_stream_activity_end_create(
1536 debug_it->input_iterator, out_stream);
1537 if (!out_message) {
1538 BT_LOGE("Error creating output stream activity end message: "
1539 "out-s-addr=%p", out_stream);
1540 goto error;
1541 }
1542
1543 default_cc = bt_stream_class_borrow_default_clock_class_const(
1544 bt_stream_borrow_class_const(in_stream));
1545
1546 if (default_cc) {
1547 cs_state =
1548 bt_message_stream_activity_end_borrow_default_clock_snapshot_const(
1549 in_message, &cs);
1550
1551 if (cs_state == BT_MESSAGE_STREAM_ACTIVITY_CLOCK_SNAPSHOT_STATE_KNOWN ) {
1552 cs_value = bt_clock_snapshot_get_value(cs);
1553 bt_message_stream_activity_end_set_default_clock_snapshot(
1554 out_message, cs_value);
1555 } else {
1556 bt_message_stream_activity_end_set_default_clock_snapshot_state(
1557 out_message, cs_state);
1558 }
1559 }
1560
1561 error:
1562 return out_message;
1563 }
1564
1565 static
1566 bt_message *handle_discarded_events_message(struct debug_info_msg_iter *debug_it,
1567 const bt_message *in_message)
1568 {
1569 const bt_clock_snapshot *begin_cs, *end_cs;
1570 const bt_stream *in_stream;
1571 bool has_default_clock_snapshots;
1572 uint64_t discarded_events, begin_cs_value, end_cs_value;
1573 bt_property_availability prop_avail;
1574 bt_message *out_message = NULL;
1575 bt_stream *out_stream;
1576 bt_logging_level log_level = debug_it->log_level;
1577
1578 in_stream = bt_message_discarded_events_borrow_stream_const(
1579 in_message);
1580 BT_ASSERT(in_stream);
1581
1582 out_stream = trace_ir_mapping_borrow_mapped_stream(
1583 debug_it->ir_maps, in_stream);
1584 BT_ASSERT(out_stream);
1585
1586 has_default_clock_snapshots =
1587 bt_stream_class_discarded_events_have_default_clock_snapshots(
1588 bt_stream_borrow_class_const(in_stream));
1589 if (has_default_clock_snapshots) {
1590 begin_cs =
1591 bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
1592 in_message);
1593 end_cs =
1594 bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
1595 in_message);
1596
1597 begin_cs_value = bt_clock_snapshot_get_value(begin_cs);
1598 end_cs_value = bt_clock_snapshot_get_value(end_cs);
1599
1600 out_message =
1601 bt_message_discarded_events_create_with_default_clock_snapshots(
1602 debug_it->input_iterator, out_stream,
1603 begin_cs_value, end_cs_value);
1604 } else {
1605 out_message = bt_message_discarded_events_create(
1606 debug_it->input_iterator, out_stream);
1607 }
1608 if (!out_message) {
1609 BT_LOGE("Error creating output discarded events message: "
1610 "out-s-addr=%p", out_stream);
1611 goto error;
1612 }
1613
1614 prop_avail = bt_message_discarded_events_get_count(in_message,
1615 &discarded_events);
1616
1617 if (prop_avail == BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE) {
1618 bt_message_discarded_events_set_count(out_message,
1619 discarded_events);
1620 }
1621
1622 error:
1623 return out_message;
1624 }
1625
1626 static
1627 bt_message *handle_discarded_packets_message(struct debug_info_msg_iter *debug_it,
1628 const bt_message *in_message)
1629 {
1630 const bt_clock_snapshot *begin_cs, *end_cs;
1631 bool has_default_clock_snapshots;
1632 const bt_stream *in_stream;
1633 uint64_t discarded_packets, begin_cs_value, end_cs_value;
1634 bt_property_availability prop_avail;
1635 bt_message *out_message = NULL;
1636 bt_stream *out_stream;
1637 bt_logging_level log_level = debug_it->log_level;
1638
1639 in_stream = bt_message_discarded_packets_borrow_stream_const(
1640 in_message);
1641 BT_ASSERT(in_stream);
1642
1643 out_stream = trace_ir_mapping_borrow_mapped_stream(
1644 debug_it->ir_maps, in_stream);
1645 BT_ASSERT(out_stream);
1646
1647 has_default_clock_snapshots =
1648 bt_stream_class_discarded_packets_have_default_clock_snapshots(
1649 bt_stream_borrow_class_const(in_stream));
1650 if (has_default_clock_snapshots) {
1651 begin_cs =
1652 bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
1653 in_message);
1654
1655 end_cs =
1656 bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
1657 in_message);
1658
1659 begin_cs_value = bt_clock_snapshot_get_value(begin_cs);
1660 end_cs_value = bt_clock_snapshot_get_value(end_cs);
1661
1662 out_message = bt_message_discarded_packets_create_with_default_clock_snapshots(
1663 debug_it->input_iterator, out_stream,
1664 begin_cs_value, end_cs_value);
1665 } else {
1666 out_message = bt_message_discarded_packets_create(
1667 debug_it->input_iterator, out_stream);
1668 }
1669 if (!out_message) {
1670 BT_LOGE("Error creating output discarded packet message: "
1671 "out-s-addr=%p", out_stream);
1672 goto error;
1673 }
1674
1675 prop_avail = bt_message_discarded_packets_get_count(in_message,
1676 &discarded_packets);
1677 if (prop_avail == BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE) {
1678 bt_message_discarded_packets_set_count(out_message,
1679 discarded_packets);
1680 }
1681
1682 error:
1683 return out_message;
1684 }
1685
1686 static
1687 const bt_message *handle_message(struct debug_info_msg_iter *debug_it,
1688 const bt_message *in_message)
1689 {
1690 bt_message *out_message = NULL;
1691
1692 switch (bt_message_get_type(in_message)) {
1693 case BT_MESSAGE_TYPE_EVENT:
1694 out_message = handle_event_message(debug_it,
1695 in_message);
1696 break;
1697 case BT_MESSAGE_TYPE_PACKET_BEGINNING:
1698 out_message = handle_packet_begin_message(debug_it,
1699 in_message);
1700 break;
1701 case BT_MESSAGE_TYPE_PACKET_END:
1702 out_message = handle_packet_end_message(debug_it,
1703 in_message);
1704 break;
1705 case BT_MESSAGE_TYPE_STREAM_BEGINNING:
1706 out_message = handle_stream_begin_message(debug_it,
1707 in_message);
1708 break;
1709 case BT_MESSAGE_TYPE_STREAM_END:
1710 out_message = handle_stream_end_message(debug_it,
1711 in_message);
1712 break;
1713 case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY:
1714 out_message = handle_msg_iterator_inactivity(debug_it,
1715 in_message);
1716 break;
1717 case BT_MESSAGE_TYPE_STREAM_ACTIVITY_BEGINNING:
1718 out_message = handle_stream_act_begin_message(debug_it,
1719 in_message);
1720 break;
1721 case BT_MESSAGE_TYPE_STREAM_ACTIVITY_END:
1722 out_message = handle_stream_act_end_message(debug_it,
1723 in_message);
1724 break;
1725 case BT_MESSAGE_TYPE_DISCARDED_EVENTS:
1726 out_message = handle_discarded_events_message(debug_it,
1727 in_message);
1728 break;
1729 case BT_MESSAGE_TYPE_DISCARDED_PACKETS:
1730 out_message = handle_discarded_packets_message(debug_it,
1731 in_message);
1732 break;
1733 default:
1734 abort();
1735 break;
1736 }
1737
1738 return out_message;
1739 }
1740
1741 static
1742 int init_from_params(struct debug_info_component *debug_info_component,
1743 const bt_value *params)
1744 {
1745 const bt_value *value = NULL;
1746 int ret = 0;
1747
1748 BT_ASSERT(params);
1749
1750 value = bt_value_map_borrow_entry_value_const(params,
1751 "debug-info-field-name");
1752 if (value) {
1753 debug_info_component->arg_debug_info_field_name =
1754 g_strdup(bt_value_string_get(value));
1755 } else {
1756 debug_info_component->arg_debug_info_field_name =
1757 g_strdup(DEFAULT_DEBUG_INFO_FIELD_NAME);
1758 }
1759
1760 value = bt_value_map_borrow_entry_value_const(params, "debug-info-dir");
1761 if (value) {
1762 debug_info_component->arg_debug_dir =
1763 g_strdup(bt_value_string_get(value));
1764 } else {
1765 debug_info_component->arg_debug_dir = NULL;
1766 }
1767
1768
1769 value = bt_value_map_borrow_entry_value_const(params, "target-prefix");
1770 if (value) {
1771 debug_info_component->arg_target_prefix =
1772 g_strdup(bt_value_string_get(value));
1773 } else {
1774 debug_info_component->arg_target_prefix = NULL;
1775 }
1776
1777 value = bt_value_map_borrow_entry_value_const(params, "full-path");
1778 if (value) {
1779 debug_info_component->arg_full_path = bt_value_bool_get(value);
1780 } else {
1781 debug_info_component->arg_full_path = BT_FALSE;
1782 }
1783
1784 return ret;
1785 }
1786
1787 BT_HIDDEN
1788 bt_self_component_status debug_info_comp_init(
1789 bt_self_component_filter *self_comp,
1790 const bt_value *params, __attribute__((unused)) void *init_method_data)
1791 {
1792 int ret;
1793 struct debug_info_component *debug_info_comp;
1794 bt_self_component_status status = BT_SELF_COMPONENT_STATUS_OK;
1795 bt_logging_level log_level = bt_component_get_logging_level(
1796 bt_self_component_as_component(
1797 bt_self_component_filter_as_self_component(self_comp)));
1798
1799 BT_LOGI("Initializing debug_info component: "
1800 "comp-addr=%p, params-addr=%p", self_comp, params);
1801
1802 debug_info_comp = g_new0(struct debug_info_component, 1);
1803 if (!debug_info_comp) {
1804 BT_LOGE_STR("Failed to allocate one debug_info component.");
1805 goto error;
1806 }
1807
1808 debug_info_comp->log_level = log_level;
1809 bt_self_component_set_data(
1810 bt_self_component_filter_as_self_component(self_comp),
1811 debug_info_comp);
1812
1813 status = bt_self_component_filter_add_input_port(self_comp, "in",
1814 NULL, NULL);
1815 if (status != BT_SELF_COMPONENT_STATUS_OK) {
1816 goto error;
1817 }
1818
1819 status = bt_self_component_filter_add_output_port(self_comp, "out",
1820 NULL, NULL);
1821 if (status != BT_SELF_COMPONENT_STATUS_OK) {
1822 goto error;
1823 }
1824
1825 ret = init_from_params(debug_info_comp, params);
1826 if (ret) {
1827 BT_LOGE("Cannot configure debug_info component: "
1828 "debug_info-comp-addr=%p, params-addr=%p",
1829 debug_info_comp, params);
1830 goto error;
1831 }
1832
1833 goto end;
1834
1835 error:
1836 destroy_debug_info_comp(debug_info_comp);
1837 bt_self_component_set_data(
1838 bt_self_component_filter_as_self_component(self_comp),
1839 NULL);
1840
1841 if (status == BT_SELF_COMPONENT_STATUS_OK) {
1842 status = BT_SELF_COMPONENT_STATUS_ERROR;
1843 }
1844 end:
1845 return status;
1846 }
1847
1848 BT_HIDDEN
1849 void debug_info_comp_finalize(bt_self_component_filter *self_comp)
1850 {
1851 struct debug_info_component *debug_info =
1852 bt_self_component_get_data(
1853 bt_self_component_filter_as_self_component(
1854 self_comp));
1855 bt_logging_level log_level = debug_info->log_level;
1856
1857 BT_LOGI("Finalizing debug_info self_component: comp-addr=%p",
1858 self_comp);
1859
1860 destroy_debug_info_comp(debug_info);
1861 }
1862
1863 BT_HIDDEN
1864 bt_self_message_iterator_status debug_info_msg_iter_next(
1865 bt_self_message_iterator *self_msg_iter,
1866 const bt_message_array_const msgs, uint64_t capacity,
1867 uint64_t *count)
1868 {
1869 bt_self_component_port_input_message_iterator *upstream_iterator = NULL;
1870 bt_message_iterator_status upstream_iterator_ret_status;
1871 struct debug_info_msg_iter *debug_info_msg_iter;
1872 struct debug_info_component *debug_info = NULL;
1873 bt_self_message_iterator_status status;
1874 bt_self_component *self_comp = NULL;
1875 bt_message_array_const input_msgs;
1876 const bt_message *out_message;
1877 uint64_t curr_msg_idx, i;
1878
1879 status = BT_SELF_MESSAGE_ITERATOR_STATUS_OK;
1880
1881 self_comp = bt_self_message_iterator_borrow_component(self_msg_iter);
1882 BT_ASSERT(self_comp);
1883
1884 debug_info = bt_self_component_get_data(self_comp);
1885 BT_ASSERT(debug_info);
1886
1887 debug_info_msg_iter = bt_self_message_iterator_get_data(self_msg_iter);
1888 BT_ASSERT(debug_info_msg_iter);
1889
1890 upstream_iterator = debug_info_msg_iter->msg_iter;
1891 BT_ASSERT(upstream_iterator);
1892
1893 upstream_iterator_ret_status =
1894 bt_self_component_port_input_message_iterator_next(
1895 upstream_iterator, &input_msgs, count);
1896 if (upstream_iterator_ret_status != BT_MESSAGE_ITERATOR_STATUS_OK) {
1897 /*
1898 * No messages were returned. Not necessarily an error. Convert
1899 * the upstream message iterator status to a self status.
1900 */
1901 status = bt_common_message_iterator_status_to_self(
1902 upstream_iterator_ret_status);
1903 goto end;
1904 }
1905
1906 /*
1907 * There should never be more received messages than the capacity we
1908 * provided.
1909 */
1910 BT_ASSERT(*count <= capacity);
1911
1912 for (curr_msg_idx = 0; curr_msg_idx < *count; curr_msg_idx++) {
1913 out_message = handle_message(debug_info_msg_iter,
1914 input_msgs[curr_msg_idx]);
1915 if (!out_message) {
1916 goto handle_msg_error;
1917 }
1918
1919 msgs[curr_msg_idx] = out_message;
1920 /*
1921 * Drop our reference of the input message as we are done with
1922 * it and created a output copy.
1923 */
1924 bt_message_put_ref(input_msgs[curr_msg_idx]);
1925 }
1926
1927 goto end;
1928
1929 handle_msg_error:
1930 /*
1931 * Drop references of all the output messages created before the
1932 * failure.
1933 */
1934 for (i = 0; i < curr_msg_idx; i++) {
1935 bt_message_put_ref(msgs[i]);
1936 }
1937
1938 status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
1939 end:
1940 return status;
1941 }
1942
1943 static
1944 void debug_info_msg_iter_destroy(struct debug_info_msg_iter *debug_info_msg_iter)
1945 {
1946 if (!debug_info_msg_iter) {
1947 goto end;
1948 }
1949
1950 if (debug_info_msg_iter->msg_iter) {
1951 bt_self_component_port_input_message_iterator_put_ref(
1952 debug_info_msg_iter->msg_iter);
1953 }
1954
1955 if (debug_info_msg_iter->ir_maps) {
1956 trace_ir_maps_destroy(debug_info_msg_iter->ir_maps);
1957 }
1958
1959 if (debug_info_msg_iter->debug_info_map) {
1960 g_hash_table_destroy(debug_info_msg_iter->debug_info_map);
1961 }
1962
1963 bt_fd_cache_fini(&debug_info_msg_iter->fd_cache);
1964 g_free(debug_info_msg_iter);
1965
1966 end:
1967 return;
1968 }
1969
1970 BT_HIDDEN
1971 bt_self_message_iterator_status debug_info_msg_iter_init(
1972 bt_self_message_iterator *self_msg_iter,
1973 bt_self_component_filter *self_comp,
1974 bt_self_component_port_output *self_port)
1975 {
1976 bt_self_message_iterator_status status = BT_SELF_MESSAGE_ITERATOR_STATUS_OK;
1977 struct bt_self_component_port_input *input_port = NULL;
1978 bt_self_component_port_input_message_iterator *upstream_iterator = NULL;
1979 struct debug_info_msg_iter *debug_info_msg_iter = NULL;
1980 gchar *debug_info_field_name;
1981 int ret;
1982 bt_logging_level log_level = bt_component_get_logging_level(
1983 bt_self_component_as_component(
1984 bt_self_component_filter_as_self_component(self_comp)));
1985
1986 /* Borrow the upstream input port. */
1987 input_port = bt_self_component_filter_borrow_input_port_by_name(
1988 self_comp, "in");
1989 if (!input_port) {
1990 status = BT_SELF_MESSAGE_ITERATOR_STATUS_ERROR;
1991 goto error;
1992 }
1993
1994 debug_info_msg_iter = g_new0(struct debug_info_msg_iter, 1);
1995 if (!debug_info_msg_iter) {
1996 status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
1997 goto error;
1998 }
1999
2000 debug_info_msg_iter->log_level = log_level;
2001
2002 /* Create an iterator on the upstream component. */
2003 upstream_iterator = bt_self_component_port_input_message_iterator_create(
2004 input_port);
2005 if (!upstream_iterator) {
2006 status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
2007 goto error;
2008 }
2009
2010 BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_MOVE_REF(
2011 debug_info_msg_iter->msg_iter, upstream_iterator);
2012
2013 /* Create hashtable that will contain debug info mapping. */
2014 debug_info_msg_iter->debug_info_map = g_hash_table_new_full(
2015 g_direct_hash, g_direct_equal, (GDestroyNotify) NULL,
2016 (GDestroyNotify) debug_info_destroy);
2017 if (!debug_info_msg_iter->debug_info_map) {
2018 status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
2019 goto error;
2020 }
2021
2022 debug_info_msg_iter->self_comp =
2023 bt_self_component_filter_as_self_component(self_comp);
2024
2025 debug_info_msg_iter->debug_info_component = bt_self_component_get_data(
2026 bt_self_component_filter_as_self_component(
2027 self_comp));
2028
2029 debug_info_field_name =
2030 debug_info_msg_iter->debug_info_component->arg_debug_info_field_name;
2031
2032 debug_info_msg_iter->ir_maps = trace_ir_maps_create(
2033 bt_self_component_filter_as_self_component(self_comp),
2034 debug_info_field_name, log_level);
2035 if (!debug_info_msg_iter->ir_maps) {
2036 status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
2037 goto error;
2038 }
2039
2040 ret = bt_fd_cache_init(&debug_info_msg_iter->fd_cache, log_level);
2041 if (ret) {
2042 status = BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM;
2043 goto error;
2044 }
2045
2046 bt_self_message_iterator_set_data(self_msg_iter, debug_info_msg_iter);
2047 debug_info_msg_iter->input_iterator = self_msg_iter;
2048
2049 goto end;
2050
2051 error:
2052 debug_info_msg_iter_destroy(debug_info_msg_iter);
2053 end:
2054 return status;
2055 }
2056
2057 BT_HIDDEN
2058 bt_bool debug_info_msg_iter_can_seek_beginning(
2059 bt_self_message_iterator *self_msg_iter)
2060 {
2061 struct debug_info_msg_iter *debug_info_msg_iter =
2062 bt_self_message_iterator_get_data(self_msg_iter);
2063 BT_ASSERT(debug_info_msg_iter);
2064
2065 return bt_self_component_port_input_message_iterator_can_seek_beginning(
2066 debug_info_msg_iter->msg_iter);
2067 }
2068
2069 BT_HIDDEN
2070 bt_self_message_iterator_status debug_info_msg_iter_seek_beginning(
2071 bt_self_message_iterator *self_msg_iter)
2072 {
2073 struct debug_info_msg_iter *debug_info_msg_iter =
2074 bt_self_message_iterator_get_data(self_msg_iter);
2075 bt_message_iterator_status status = BT_MESSAGE_ITERATOR_STATUS_OK;
2076
2077 BT_ASSERT(debug_info_msg_iter);
2078
2079 /* Ask the upstream component to seek to the beginning. */
2080 status = bt_self_component_port_input_message_iterator_seek_beginning(
2081 debug_info_msg_iter->msg_iter);
2082 if (status != BT_MESSAGE_ITERATOR_STATUS_OK) {
2083 goto end;
2084 }
2085
2086 /* Clear this iterator data. */
2087 trace_ir_maps_clear(debug_info_msg_iter->ir_maps);
2088 g_hash_table_remove_all(debug_info_msg_iter->debug_info_map);
2089 end:
2090 return bt_common_message_iterator_status_to_self(status);
2091 }
2092
2093 BT_HIDDEN
2094 void debug_info_msg_iter_finalize(bt_self_message_iterator *it)
2095 {
2096 struct debug_info_msg_iter *debug_info_msg_iter;
2097
2098 debug_info_msg_iter = bt_self_message_iterator_get_data(it);
2099 BT_ASSERT(debug_info_msg_iter);
2100
2101 debug_info_msg_iter_destroy(debug_info_msg_iter);
2102 }
This page took 0.103562 seconds and 5 git commands to generate.