2 * SPDX-License-Identifier: MIT
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>
10 * Babeltrace - Debug Information State Tracker
13 #define BT_COMP_LOG_SELF_COMP self_comp
14 #define BT_LOG_OUTPUT_LEVEL log_level
15 #define BT_LOG_TAG "PLUGIN/FLT.LTTNG-UTILS.DEBUG-INFO"
16 #include "logging/comp-logging.h"
22 #include "common/assert.h"
23 #include "common/common.h"
24 #include "fd-cache/fd-cache.h"
27 #include "debug-info.h"
28 #include "trace-ir-data-copy.h"
29 #include "trace-ir-mapping.h"
30 #include "trace-ir-metadata-copy.h"
32 #include "plugins/common/param-validation/param-validation.h"
34 #define DEFAULT_DEBUG_INFO_FIELD_NAME "debug_info"
35 #define LTTNG_UST_STATEDUMP_PREFIX "lttng_ust"
37 struct debug_info_component
{
38 bt_logging_level log_level
;
39 bt_self_component
*self_comp
;
40 bt_self_component_filter
*self_comp_filter
;
42 gchar
*arg_debug_info_field_name
;
43 gchar
*arg_target_prefix
;
44 bt_bool arg_full_path
;
47 struct debug_info_msg_iter
{
48 bt_logging_level log_level
;
49 struct debug_info_component
*debug_info_component
;
50 bt_self_message_iterator
*input_iterator
;
51 bt_self_component
*self_comp
;
52 bt_message_iterator
*msg_iter
;
54 struct trace_ir_maps
*ir_maps
;
55 /* in_trace -> debug_info_mapping. */
56 GHashTable
*debug_info_map
;
58 struct bt_fd_cache fd_cache
;
61 struct debug_info_source
{
62 /* Strings are owned by debug_info_source. */
65 * Store the line number as a string so that the allocation and
66 * conversion to string is only done once.
70 /* short_src_path points inside src_path, no need to free. */
71 const gchar
*short_src_path
;
73 /* short_bin_path points inside bin_path, no need to free. */
74 const gchar
*short_bin_path
;
76 * Location within the binary. Either absolute (@0x1234) or
82 struct proc_debug_info_sources
{
84 * Hash table: base address (pointer to uint64_t) to bin info; owned by
85 * proc_debug_info_sources.
87 GHashTable
*baddr_to_bin_info
;
90 * Hash table: IP (pointer to uint64_t) to (struct debug_info_source *);
91 * owned by proc_debug_info_sources.
93 GHashTable
*ip_to_debug_info_src
;
97 bt_logging_level log_level
;
98 bt_self_component
*self_comp
;
99 struct debug_info_component
*comp
;
100 const bt_trace
*input_trace
;
101 bt_listener_id destruction_listener_id
;
104 * Hash table of VPIDs (pointer to int64_t) to
105 * (struct proc_debug_info_sources*); owned by debug_info.
107 GHashTable
*vpid_to_proc_dbg_info_src
;
108 GQuark q_statedump_bin_info
;
109 GQuark q_statedump_debug_link
;
110 GQuark q_statedump_build_id
;
111 GQuark q_statedump_start
;
115 struct bt_fd_cache
*fd_cache
; /* Weak ref. Owned by the iterator. */
119 int debug_info_init(struct debug_info
*info
)
121 info
->q_statedump_bin_info
= g_quark_from_string(
122 "lttng_ust_statedump:bin_info");
123 info
->q_statedump_debug_link
= g_quark_from_string(
124 "lttng_ust_statedump:debug_link");
125 info
->q_statedump_build_id
= g_quark_from_string(
126 "lttng_ust_statedump:build_id");
127 info
->q_statedump_start
= g_quark_from_string(
128 "lttng_ust_statedump:start");
129 info
->q_dl_open
= g_quark_from_string("lttng_ust_dl:dlopen");
130 info
->q_lib_load
= g_quark_from_string("lttng_ust_lib:load");
131 info
->q_lib_unload
= g_quark_from_string("lttng_ust_lib:unload");
133 return bin_info_init(info
->log_level
, info
->self_comp
);
137 void debug_info_source_destroy(struct debug_info_source
*debug_info_src
)
139 if (!debug_info_src
) {
143 g_free(debug_info_src
->func
);
144 g_free(debug_info_src
->line_no
);
145 g_free(debug_info_src
->src_path
);
146 g_free(debug_info_src
->bin_path
);
147 g_free(debug_info_src
->bin_loc
);
148 g_free(debug_info_src
);
152 struct debug_info_source
*debug_info_source_create_from_bin(
153 struct bin_info
*bin
, uint64_t ip
,
154 bt_self_component
*self_comp
)
157 struct debug_info_source
*debug_info_src
= NULL
;
158 struct source_location
*src_loc
= NULL
;
159 bt_logging_level log_level
;
163 log_level
= bin
->log_level
;
165 debug_info_src
= g_new0(struct debug_info_source
, 1);
167 if (!debug_info_src
) {
171 /* Lookup function name */
172 ret
= bin_info_lookup_function_name(bin
, ip
, &debug_info_src
->func
);
177 /* Can't retrieve src_loc from ELF, or could not find binary, skip. */
178 if (!bin
->is_elf_only
|| !debug_info_src
->func
) {
179 /* Lookup source location */
180 ret
= bin_info_lookup_source_location(bin
, ip
, &src_loc
);
182 BT_COMP_LOGI("Failed to lookup source location: ret=%d", ret
);
187 debug_info_src
->line_no
=
188 g_strdup_printf("%"PRId64
, src_loc
->line_no
);
189 if (!debug_info_src
->line_no
) {
190 BT_COMP_LOGE_APPEND_CAUSE(self_comp
,
191 "Error occurred when setting `line_no` field.");
195 if (src_loc
->filename
) {
196 debug_info_src
->src_path
= g_strdup(src_loc
->filename
);
197 if (!debug_info_src
->src_path
) {
201 debug_info_src
->short_src_path
= get_filename_from_path(
202 debug_info_src
->src_path
);
204 source_location_destroy(src_loc
);
208 debug_info_src
->bin_path
= g_strdup(bin
->elf_path
);
209 if (!debug_info_src
->bin_path
) {
213 debug_info_src
->short_bin_path
= get_filename_from_path(
214 debug_info_src
->bin_path
);
216 ret
= bin_info_get_bin_loc(bin
, ip
, &(debug_info_src
->bin_loc
));
223 return debug_info_src
;
226 debug_info_source_destroy(debug_info_src
);
231 void proc_debug_info_sources_destroy(
232 struct proc_debug_info_sources
*proc_dbg_info_src
)
234 if (!proc_dbg_info_src
) {
238 if (proc_dbg_info_src
->baddr_to_bin_info
) {
239 g_hash_table_destroy(proc_dbg_info_src
->baddr_to_bin_info
);
242 if (proc_dbg_info_src
->ip_to_debug_info_src
) {
243 g_hash_table_destroy(proc_dbg_info_src
->ip_to_debug_info_src
);
246 g_free(proc_dbg_info_src
);
250 struct proc_debug_info_sources
*proc_debug_info_sources_create(void)
252 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
254 proc_dbg_info_src
= g_new0(struct proc_debug_info_sources
, 1);
255 if (!proc_dbg_info_src
) {
259 proc_dbg_info_src
->baddr_to_bin_info
= g_hash_table_new_full(
260 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
261 (GDestroyNotify
) bin_info_destroy
);
262 if (!proc_dbg_info_src
->baddr_to_bin_info
) {
266 proc_dbg_info_src
->ip_to_debug_info_src
= g_hash_table_new_full(
267 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
268 (GDestroyNotify
) debug_info_source_destroy
);
269 if (!proc_dbg_info_src
->ip_to_debug_info_src
) {
274 return proc_dbg_info_src
;
277 proc_debug_info_sources_destroy(proc_dbg_info_src
);
282 struct proc_debug_info_sources
*proc_debug_info_sources_ht_get_entry(
283 GHashTable
*ht
, int64_t vpid
)
285 gpointer key
= g_new0(int64_t, 1);
286 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
292 *((int64_t *) key
) = vpid
;
294 /* Exists? Return it */
295 proc_dbg_info_src
= g_hash_table_lookup(ht
, key
);
296 if (proc_dbg_info_src
) {
300 /* Otherwise, create and return it */
301 proc_dbg_info_src
= proc_debug_info_sources_create();
302 if (!proc_dbg_info_src
) {
306 g_hash_table_insert(ht
, key
, proc_dbg_info_src
);
307 /* Ownership passed to ht */
311 return proc_dbg_info_src
;
315 const bt_field
*event_borrow_payload_field(const bt_event
*event
,
316 const char *field_name
)
318 const bt_field
*event_payload
, *field
;
320 event_payload
= bt_event_borrow_payload_field_const(event
);
321 BT_ASSERT_DBG(event_payload
);
323 field
= bt_field_structure_borrow_member_field_by_name_const(
324 event_payload
, field_name
);
329 const bt_field
*event_borrow_common_context_field(const bt_event
*event
,
330 const char *field_name
)
332 const bt_field
*event_common_ctx
, *field
= NULL
;
334 event_common_ctx
= bt_event_borrow_common_context_field_const(event
);
335 if (!event_common_ctx
) {
339 field
= bt_field_structure_borrow_member_field_by_name_const(
340 event_common_ctx
, field_name
);
347 void event_get_common_context_signed_integer_field_value(
348 const bt_event
*event
, const char *field_name
, int64_t *value
)
350 *value
= bt_field_integer_signed_get_value(
351 event_borrow_common_context_field(event
, field_name
));
355 void event_get_payload_build_id_length(const bt_event
*event
,
356 const char *field_name
, uint64_t *build_id_len
)
358 const bt_field
*build_id_field
;
359 const bt_field_class
*build_id_field_class
;
361 build_id_field
= event_borrow_payload_field(event
, field_name
);
362 build_id_field_class
= bt_field_borrow_class_const(build_id_field
);
364 BT_ASSERT(bt_field_class_get_type(build_id_field_class
) ==
365 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITHOUT_LENGTH_FIELD
||
366 bt_field_class_get_type(build_id_field_class
) ==
367 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD
);
368 BT_ASSERT(bt_field_class_get_type(
369 bt_field_class_array_borrow_element_field_class_const(
370 build_id_field_class
)) ==
371 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
);
373 *build_id_len
= bt_field_array_get_length(build_id_field
);
377 void event_get_payload_build_id_value(const bt_event
*event
,
378 const char *field_name
, uint8_t *build_id
)
380 const bt_field
*curr_field
, *build_id_field
;
381 const bt_field_class
*build_id_field_class
;
382 uint64_t i
, build_id_len
;
384 build_id_field
= event_borrow_payload_field(event
, field_name
);
385 build_id_field_class
= bt_field_borrow_class_const(build_id_field
);
387 BT_ASSERT(bt_field_class_get_type(build_id_field_class
) ==
388 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITHOUT_LENGTH_FIELD
||
389 bt_field_class_get_type(build_id_field_class
) ==
390 BT_FIELD_CLASS_TYPE_DYNAMIC_ARRAY_WITH_LENGTH_FIELD
);
391 BT_ASSERT(bt_field_class_get_type(
392 bt_field_class_array_borrow_element_field_class_const(
393 build_id_field_class
)) ==
394 BT_FIELD_CLASS_TYPE_UNSIGNED_INTEGER
);
396 build_id_len
= bt_field_array_get_length(build_id_field
);
398 for (i
= 0; i
< build_id_len
; i
++) {
399 curr_field
= bt_field_array_borrow_element_field_by_index_const(
402 build_id
[i
] = bt_field_integer_unsigned_get_value(curr_field
);
407 void event_get_payload_unsigned_integer_field_value(const bt_event
*event
,
408 const char *field_name
, uint64_t *value
)
410 *value
= bt_field_integer_unsigned_get_value(
411 event_borrow_payload_field(event
, field_name
));
415 void event_get_payload_string_field_value(const bt_event
*event
,
416 const char *field_name
, const char **value
)
418 *value
= bt_field_string_get_value(
419 event_borrow_payload_field(event
, field_name
));
423 bool event_has_payload_field(const bt_event
*event
,
424 const char *field_name
)
426 return event_borrow_payload_field(event
, field_name
);
430 struct debug_info_source
*proc_debug_info_sources_get_entry(
431 struct debug_info
*debug_info
,
432 struct proc_debug_info_sources
*proc_dbg_info_src
, uint64_t ip
)
434 struct debug_info_source
*debug_info_src
= NULL
;
435 gpointer key
= g_new0(uint64_t, 1);
437 gpointer baddr
, value
;
443 *((uint64_t *) key
) = ip
;
445 /* Look in IP to debug infos hash table first. */
446 debug_info_src
= g_hash_table_lookup(
447 proc_dbg_info_src
->ip_to_debug_info_src
, key
);
448 if (debug_info_src
) {
452 /* Check in all bin_infos. */
453 g_hash_table_iter_init(&iter
, proc_dbg_info_src
->baddr_to_bin_info
);
455 while (g_hash_table_iter_next(&iter
, &baddr
, &value
))
457 struct bin_info
*bin
= value
;
459 if (!bin_info_has_address(value
, ip
)) {
464 * Found; add it to cache.
466 * FIXME: this should be bounded in size (and implement
467 * a caching policy), and entries should be prunned when
468 * libraries are unmapped.
470 debug_info_src
= debug_info_source_create_from_bin(bin
, ip
,
471 debug_info
->self_comp
);
472 if (debug_info_src
) {
474 proc_dbg_info_src
->ip_to_debug_info_src
, key
,
476 /* Ownership passed to ht. */
484 return debug_info_src
;
488 struct debug_info_source
*debug_info_query(struct debug_info
*debug_info
,
489 int64_t vpid
, uint64_t ip
)
491 struct debug_info_source
*dbg_info_src
= NULL
;
492 struct proc_debug_info_sources
*proc_dbg_info_src
;
494 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
495 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
496 if (!proc_dbg_info_src
) {
500 dbg_info_src
= proc_debug_info_sources_get_entry(debug_info
,
501 proc_dbg_info_src
, ip
);
508 struct debug_info
*debug_info_create(struct debug_info_component
*comp
,
509 const bt_trace
*trace
, struct bt_fd_cache
*fdc
)
512 struct debug_info
*debug_info
;
518 debug_info
= g_new0(struct debug_info
, 1);
523 debug_info
->log_level
= comp
->log_level
;
524 debug_info
->self_comp
= comp
->self_comp
;
525 debug_info
->vpid_to_proc_dbg_info_src
= g_hash_table_new_full(
526 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
527 (GDestroyNotify
) proc_debug_info_sources_destroy
);
528 if (!debug_info
->vpid_to_proc_dbg_info_src
) {
532 debug_info
->comp
= comp
;
533 ret
= debug_info_init(debug_info
);
538 debug_info
->input_trace
= trace
;
539 debug_info
->fd_cache
= fdc
;
549 void debug_info_destroy(struct debug_info
*debug_info
)
551 bt_logging_level log_level
;
552 bt_self_component
*self_comp
;
553 bt_trace_remove_listener_status remove_listener_status
;
558 log_level
= debug_info
->log_level
;
559 self_comp
= debug_info
->self_comp
;
561 if (debug_info
->vpid_to_proc_dbg_info_src
) {
562 g_hash_table_destroy(debug_info
->vpid_to_proc_dbg_info_src
);
565 remove_listener_status
= bt_trace_remove_destruction_listener(
566 debug_info
->input_trace
,
567 debug_info
->destruction_listener_id
);
568 if (remove_listener_status
!= BT_TRACE_REMOVE_LISTENER_STATUS_OK
) {
569 BT_COMP_LOGE("Trace destruction listener removal failed.");
570 bt_current_thread_clear_error();
579 void handle_event_statedump_build_id(struct debug_info
*debug_info
,
580 const bt_event
*event
)
582 struct proc_debug_info_sources
*proc_dbg_info_src
;
583 uint64_t build_id_len
, baddr
;
584 uint8_t *build_id
= NULL
;
585 struct bin_info
*bin
;
589 event_get_common_context_signed_integer_field_value(event
,
590 VPID_FIELD_NAME
, &vpid
);
591 event_get_payload_unsigned_integer_field_value(event
,
592 BADDR_FIELD_NAME
, &baddr
);
594 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
595 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
596 if (!proc_dbg_info_src
) {
600 bin
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_bin_info
,
604 * The build_id event comes after the bin has been
605 * created. If it isn't found, just ignore this event.
610 event_get_payload_build_id_length(event
, BUILD_ID_FIELD_NAME
,
613 build_id
= g_new0(uint8_t, build_id_len
);
618 event_get_payload_build_id_value(event
, BUILD_ID_FIELD_NAME
, build_id
);
620 ret
= bin_info_set_build_id(bin
, build_id
, build_id_len
);
626 * Reset the is_elf_only flag in case it had been set
627 * previously, because we might find separate debug info using
628 * the new build id information.
630 bin
->is_elf_only
= false;
638 void handle_event_statedump_debug_link(struct debug_info
*debug_info
,
639 const bt_event
*event
)
641 struct proc_debug_info_sources
*proc_dbg_info_src
;
642 struct bin_info
*bin
= NULL
;
645 const char *filename
= NULL
;
647 uint64_t crc_field_value
;
649 event_get_common_context_signed_integer_field_value(event
,
650 VPID_FIELD_NAME
, &vpid
);
652 event_get_payload_unsigned_integer_field_value(event
,
653 BADDR_FIELD_NAME
, &baddr
);
655 event_get_payload_unsigned_integer_field_value(event
,
656 CRC32_FIELD_NAME
, &crc_field_value
);
658 crc32
= (uint32_t) crc_field_value
;
660 event_get_payload_string_field_value(event
,
661 FILENAME_FIELD_NAME
, &filename
);
663 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
664 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
665 if (!proc_dbg_info_src
) {
669 bin
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_bin_info
,
673 * The debug_link event comes after the bin has been
674 * created. If it isn't found, just ignore this event.
679 bin_info_set_debug_link(bin
, filename
, crc32
);
686 void handle_bin_info_event(struct debug_info
*debug_info
,
687 const bt_event
*event
, bool has_pic_field
)
689 struct proc_debug_info_sources
*proc_dbg_info_src
;
690 struct bin_info
*bin
;
691 uint64_t baddr
, memsz
;
697 event_get_payload_unsigned_integer_field_value(event
,
698 MEMSZ_FIELD_NAME
, &memsz
);
704 event_get_payload_unsigned_integer_field_value(event
,
705 BADDR_FIELD_NAME
, &baddr
);
708 * This field is not produced by the dlopen event emitted before
711 if (!event_has_payload_field(event
, PATH_FIELD_NAME
)) {
714 event_get_payload_string_field_value(event
, PATH_FIELD_NAME
, &path
);
717 uint64_t is_pic_field_value
;
719 event_get_payload_unsigned_integer_field_value(event
,
720 IS_PIC_FIELD_NAME
, &is_pic_field_value
);
721 is_pic
= is_pic_field_value
== 1;
724 * dlopen has no is_pic field, because the shared
725 * object is always PIC.
730 event_get_common_context_signed_integer_field_value(event
,
731 VPID_FIELD_NAME
, &vpid
);
733 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
734 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
735 if (!proc_dbg_info_src
) {
739 key
= g_new0(uint64_t, 1);
744 *((uint64_t *) key
) = baddr
;
746 bin
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_bin_info
, key
);
751 bin
= bin_info_create(debug_info
->fd_cache
, path
, baddr
, memsz
, is_pic
,
752 debug_info
->comp
->arg_debug_dir
,
753 debug_info
->comp
->arg_target_prefix
,
754 debug_info
->log_level
, debug_info
->self_comp
);
759 g_hash_table_insert(proc_dbg_info_src
->baddr_to_bin_info
, key
, bin
);
760 /* Ownership passed to ht. */
769 void handle_event_statedump_bin_info(struct debug_info
*debug_info
,
770 const bt_event
*event
)
772 handle_bin_info_event(debug_info
, event
, true);
776 void handle_event_lib_load(struct debug_info
*debug_info
,
777 const bt_event
*event
)
779 handle_bin_info_event(debug_info
, event
, false);
783 void handle_event_lib_unload(struct debug_info
*debug_info
,
784 const bt_event
*event
)
787 struct proc_debug_info_sources
*proc_dbg_info_src
;
791 event_get_payload_unsigned_integer_field_value(event
, BADDR_FIELD_NAME
,
794 event_get_common_context_signed_integer_field_value(event
,
795 VPID_FIELD_NAME
, &vpid
);
797 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
798 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
799 if (!proc_dbg_info_src
) {
801 * It's an unload event for a library for which no load event
802 * was previously received.
807 ret
= g_hash_table_remove(proc_dbg_info_src
->baddr_to_bin_info
,
815 void handle_event_statedump_start(struct debug_info
*debug_info
,
816 const bt_event
*event
)
818 struct proc_debug_info_sources
*proc_dbg_info_src
;
821 event_get_common_context_signed_integer_field_value(
822 event
, VPID_FIELD_NAME
, &vpid
);
824 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
825 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
826 if (!proc_dbg_info_src
) {
830 g_hash_table_remove_all(proc_dbg_info_src
->baddr_to_bin_info
);
831 g_hash_table_remove_all(proc_dbg_info_src
->ip_to_debug_info_src
);
838 void trace_debug_info_remove_func(const bt_trace
*in_trace
, void *data
)
840 struct debug_info_msg_iter
*debug_it
= data
;
841 if (debug_it
->debug_info_map
) {
843 ret
= g_hash_table_remove(debug_it
->debug_info_map
,
844 (gpointer
) in_trace
);
850 void handle_event_statedump(struct debug_info_msg_iter
*debug_it
,
851 const bt_event
*event
)
853 const bt_event_class
*event_class
;
854 const char *event_name
;
856 const bt_trace
*trace
;
857 struct debug_info
*debug_info
;
862 event_class
= bt_event_borrow_class_const(event
);
864 event_name
= bt_event_class_get_name(event_class
);
866 trace
= bt_stream_borrow_trace_const(
867 bt_event_borrow_stream_const(event
));
869 debug_info
= g_hash_table_lookup(debug_it
->debug_info_map
, trace
);
871 bt_trace_add_listener_status add_listener_status
;
873 debug_info
= debug_info_create(debug_it
->debug_info_component
,
874 trace
, &debug_it
->fd_cache
);
875 g_hash_table_insert(debug_it
->debug_info_map
, (gpointer
) trace
,
877 add_listener_status
= bt_trace_add_destruction_listener(
878 trace
, trace_debug_info_remove_func
, debug_it
,
879 &debug_info
->destruction_listener_id
);
880 BT_ASSERT(add_listener_status
== BT_TRACE_ADD_LISTENER_STATUS_OK
);
883 q_event_name
= g_quark_try_string(event_name
);
885 if (q_event_name
== debug_info
->q_statedump_bin_info
) {
887 handle_event_statedump_bin_info(debug_info
, event
);
888 } else if (q_event_name
== debug_info
->q_dl_open
||
889 q_event_name
== debug_info
->q_lib_load
) {
891 * dl_open and lib_load events are both checked for since
892 * only dl_open was produced as of lttng-ust 2.8.
894 * lib_load, which is produced from lttng-ust 2.9+, is a lot
895 * more reliable since it will be emitted when other functions
896 * of the dlopen family are called (e.g. dlmopen) and when
897 * library are transitively loaded.
899 handle_event_lib_load(debug_info
, event
);
900 } else if (q_event_name
== debug_info
->q_statedump_start
) {
901 /* Start state dump */
902 handle_event_statedump_start(debug_info
, event
);
903 } else if (q_event_name
== debug_info
->q_statedump_debug_link
) {
904 /* Debug link info */
905 handle_event_statedump_debug_link(debug_info
, event
);
906 } else if (q_event_name
== debug_info
->q_statedump_build_id
) {
908 handle_event_statedump_build_id(debug_info
, event
);
909 } else if (q_event_name
== debug_info
->q_lib_unload
) {
910 handle_event_lib_unload(debug_info
, event
);
917 void destroy_debug_info_comp(struct debug_info_component
*debug_info
)
923 g_free(debug_info
->arg_debug_dir
);
924 g_free(debug_info
->arg_debug_info_field_name
);
925 g_free(debug_info
->arg_target_prefix
);
930 void fill_debug_info_bin_field(struct debug_info_source
*dbg_info_src
,
931 bool full_path
, bt_field
*curr_field
,
932 bt_logging_level log_level
, bt_self_component
*self_comp
)
934 bt_field_string_set_value_status set_status
;
935 bt_field_string_append_status append_status
;
937 BT_ASSERT_DBG(bt_field_get_class_type(curr_field
) ==
938 BT_FIELD_CLASS_TYPE_STRING
);
942 set_status
= bt_field_string_set_value(curr_field
,
943 dbg_info_src
->bin_path
);
945 set_status
= bt_field_string_set_value(curr_field
,
946 dbg_info_src
->short_bin_path
);
948 if (set_status
!= BT_FIELD_STRING_SET_VALUE_STATUS_OK
) {
949 BT_COMP_LOGE("Cannot set path component of `bin` "
950 "curr_field field's value: str-fc-addr=%p",
952 bt_current_thread_clear_error();
955 append_status
= bt_field_string_append(curr_field
,
956 dbg_info_src
->bin_loc
);
957 if (append_status
!= BT_FIELD_STRING_APPEND_STATUS_OK
) {
958 BT_COMP_LOGE("Cannot set bin location component of `bin` "
959 "curr_field field's value: str-fc-addr=%p",
961 bt_current_thread_clear_error();
964 set_status
= bt_field_string_set_value(curr_field
, "");
965 if (set_status
!= BT_FIELD_STRING_SET_VALUE_STATUS_OK
) {
966 BT_COMP_LOGE("Cannot set `bin` curr_field field's value: "
967 "str-fc-addr=%p", curr_field
);
968 bt_current_thread_clear_error();
974 void fill_debug_info_func_field(struct debug_info_source
*dbg_info_src
,
975 bt_field
*curr_field
, bt_logging_level log_level
,
976 bt_self_component
*self_comp
)
978 bt_field_string_set_value_status status
;
980 BT_ASSERT_DBG(bt_field_get_class_type(curr_field
) ==
981 BT_FIELD_CLASS_TYPE_STRING
);
982 if (dbg_info_src
&& dbg_info_src
->func
) {
983 status
= bt_field_string_set_value(curr_field
,
986 status
= bt_field_string_set_value(curr_field
, "");
988 if (status
!= BT_FIELD_STRING_SET_VALUE_STATUS_OK
) {
989 BT_COMP_LOGE("Cannot set `func` curr_field field's value: "
990 "str-fc-addr=%p", curr_field
);
991 bt_current_thread_clear_error();
996 void fill_debug_info_src_field(struct debug_info_source
*dbg_info_src
,
997 bool full_path
, bt_field
*curr_field
,
998 bt_logging_level log_level
,
999 bt_self_component
*self_comp
)
1001 bt_field_string_set_value_status set_status
;
1002 bt_field_string_append_status append_status
;
1004 BT_ASSERT_DBG(bt_field_get_class_type(curr_field
) ==
1005 BT_FIELD_CLASS_TYPE_STRING
);
1007 if (dbg_info_src
&& dbg_info_src
->src_path
) {
1009 set_status
= bt_field_string_set_value(curr_field
,
1010 dbg_info_src
->src_path
);
1012 set_status
= bt_field_string_set_value(curr_field
,
1013 dbg_info_src
->short_src_path
);
1015 if (set_status
!= BT_FIELD_STRING_SET_VALUE_STATUS_OK
) {
1016 BT_COMP_LOGE("Cannot set path component of `src` "
1017 "curr_field field's value: str-fc-addr=%p",
1019 bt_current_thread_clear_error();
1022 append_status
= bt_field_string_append(curr_field
, ":");
1023 if (append_status
!= BT_FIELD_STRING_APPEND_STATUS_OK
) {
1024 BT_COMP_LOGE("Cannot set colon component of `src` "
1025 "curr_field field's value: str-fc-addr=%p",
1027 bt_current_thread_clear_error();
1030 append_status
= bt_field_string_append(curr_field
,
1031 dbg_info_src
->line_no
);
1032 if (append_status
!= BT_FIELD_STRING_APPEND_STATUS_OK
) {
1033 BT_COMP_LOGE("Cannot set line number component of `src` "
1034 "curr_field field's value: str-fc-addr=%p",
1036 bt_current_thread_clear_error();
1039 set_status
= bt_field_string_set_value(curr_field
, "");
1040 if (set_status
!= BT_FIELD_STRING_SET_VALUE_STATUS_OK
) {
1041 BT_COMP_LOGE("Cannot set `src` curr_field field's value: "
1042 "str-fc-addr=%p", curr_field
);
1043 bt_current_thread_clear_error();
1049 void fill_debug_info_field_empty(bt_field
*debug_info_field
,
1050 bt_logging_level log_level
, bt_self_component
*self_comp
)
1052 bt_field_string_set_value_status status
;
1053 bt_field
*bin_field
, *func_field
, *src_field
;
1055 BT_ASSERT_DBG(bt_field_get_class_type(debug_info_field
) ==
1056 BT_FIELD_CLASS_TYPE_STRUCTURE
);
1058 bin_field
= bt_field_structure_borrow_member_field_by_name(
1059 debug_info_field
, "bin");
1060 func_field
= bt_field_structure_borrow_member_field_by_name(
1061 debug_info_field
, "func");
1062 src_field
= bt_field_structure_borrow_member_field_by_name(
1063 debug_info_field
, "src");
1065 BT_ASSERT_DBG(bt_field_get_class_type(bin_field
) ==
1066 BT_FIELD_CLASS_TYPE_STRING
);
1067 BT_ASSERT_DBG(bt_field_get_class_type(func_field
) ==
1068 BT_FIELD_CLASS_TYPE_STRING
);
1069 BT_ASSERT_DBG(bt_field_get_class_type(src_field
) ==
1070 BT_FIELD_CLASS_TYPE_STRING
);
1072 status
= bt_field_string_set_value(bin_field
, "");
1073 if (status
!= BT_FIELD_STRING_SET_VALUE_STATUS_OK
) {
1074 BT_COMP_LOGE("Cannot set `bin` field's value: "
1075 "str-fc-addr=%p", bin_field
);
1076 bt_current_thread_clear_error();
1079 status
= bt_field_string_set_value(func_field
, "");
1080 if (status
!= BT_FIELD_STRING_SET_VALUE_STATUS_OK
) {
1081 BT_COMP_LOGE("Cannot set `func` field's value: "
1082 "str-fc-addr=%p", func_field
);
1083 bt_current_thread_clear_error();
1086 status
= bt_field_string_set_value(src_field
, "");
1087 if (status
!= BT_FIELD_STRING_SET_VALUE_STATUS_OK
) {
1088 BT_COMP_LOGE("Cannot set `src` field's value: "
1089 "str-fc-addr=%p", src_field
);
1090 bt_current_thread_clear_error();
1094 void fill_debug_info_field(struct debug_info
*debug_info
, int64_t vpid
,
1095 uint64_t ip
, bt_field
*debug_info_field
)
1097 struct debug_info_source
*dbg_info_src
;
1098 const bt_field_class
*debug_info_fc
;
1100 BT_ASSERT_DBG(bt_field_get_class_type(debug_info_field
) ==
1101 BT_FIELD_CLASS_TYPE_STRUCTURE
);
1103 debug_info_fc
= bt_field_borrow_class_const(debug_info_field
);
1105 BT_ASSERT_DBG(bt_field_class_structure_get_member_count(
1106 debug_info_fc
) == 3);
1108 dbg_info_src
= debug_info_query(debug_info
, vpid
, ip
);
1110 fill_debug_info_bin_field(dbg_info_src
,
1111 debug_info
->comp
->arg_full_path
,
1112 bt_field_structure_borrow_member_field_by_name(
1113 debug_info_field
, "bin"),
1114 debug_info
->log_level
, debug_info
->self_comp
);
1115 fill_debug_info_func_field(dbg_info_src
,
1116 bt_field_structure_borrow_member_field_by_name(
1117 debug_info_field
, "func"),
1118 debug_info
->log_level
, debug_info
->self_comp
);
1119 fill_debug_info_src_field(dbg_info_src
,
1120 debug_info
->comp
->arg_full_path
,
1121 bt_field_structure_borrow_member_field_by_name(
1122 debug_info_field
, "src"),
1123 debug_info
->log_level
, debug_info
->self_comp
);
1127 void fill_debug_info_event_if_needed(struct debug_info_msg_iter
*debug_it
,
1128 const bt_event
*in_event
, bt_event
*out_event
)
1130 bt_field
*out_common_ctx_field
, *out_debug_info_field
;
1131 const bt_field
*vpid_field
, *ip_field
, *in_common_ctx_field
;
1132 const bt_field_class
*in_common_ctx_fc
;
1133 struct debug_info
*debug_info
;
1136 gchar
*debug_info_field_name
=
1137 debug_it
->debug_info_component
->arg_debug_info_field_name
;
1138 bt_logging_level log_level
= debug_it
->log_level
;
1139 bt_self_component
*self_comp
= debug_it
->self_comp
;
1141 in_common_ctx_field
= bt_event_borrow_common_context_field_const(
1143 if (!in_common_ctx_field
) {
1145 * There is no event common context so no need to add debug
1151 in_common_ctx_fc
= bt_field_borrow_class_const(in_common_ctx_field
);
1152 if (!is_event_common_ctx_dbg_info_compatible(in_common_ctx_fc
,
1153 debug_it
->ir_maps
->debug_info_field_class_name
)) {
1155 * The input event common context does not have the necessary
1156 * fields to resolve debug information.
1161 /* Borrow the debug-info field. */
1162 out_common_ctx_field
= bt_event_borrow_common_context_field(out_event
);
1163 if (!out_common_ctx_field
) {
1167 out_debug_info_field
= bt_field_structure_borrow_member_field_by_name(
1168 out_common_ctx_field
, debug_info_field_name
);
1170 vpid_field
= bt_field_structure_borrow_member_field_by_name_const(
1171 out_common_ctx_field
, VPID_FIELD_NAME
);
1172 ip_field
= bt_field_structure_borrow_member_field_by_name_const(
1173 out_common_ctx_field
, IP_FIELD_NAME
);
1175 vpid
= bt_field_integer_signed_get_value(vpid_field
);
1176 ip
= bt_field_integer_unsigned_get_value(ip_field
);
1179 * Borrow the debug_info structure needed for the source
1182 debug_info
= g_hash_table_lookup(debug_it
->debug_info_map
,
1183 bt_stream_borrow_trace_const(
1184 bt_event_borrow_stream_const(in_event
)));
1188 * Perform the debug-info resolving and set the event fields
1191 fill_debug_info_field(debug_info
, vpid
, ip
, out_debug_info_field
);
1193 BT_COMP_LOGD("No debug information for this trace. Setting debug "
1194 "info fields to empty strings.");
1195 fill_debug_info_field_empty(out_debug_info_field
,
1196 log_level
, self_comp
);
1203 void update_event_statedump_if_needed(struct debug_info_msg_iter
*debug_it
,
1204 const bt_event
*in_event
)
1206 const bt_field
*event_common_ctx
;
1207 const bt_field_class
*event_common_ctx_fc
;
1208 const bt_event_class
*in_event_class
= bt_event_borrow_class_const(in_event
);
1211 * If the event is an lttng_ust_statedump event AND has the right event
1212 * common context fields update the debug-info view for this process.
1214 event_common_ctx
= bt_event_borrow_common_context_field_const(in_event
);
1215 if (!event_common_ctx
) {
1219 event_common_ctx_fc
= bt_field_borrow_class_const(event_common_ctx
);
1220 if (is_event_common_ctx_dbg_info_compatible(event_common_ctx_fc
,
1221 debug_it
->ir_maps
->debug_info_field_class_name
)) {
1222 /* Checkout if it might be a one of lttng ust statedump events. */
1223 const char *in_event_name
= bt_event_class_get_name(in_event_class
);
1224 if (strncmp(in_event_name
, LTTNG_UST_STATEDUMP_PREFIX
,
1225 strlen(LTTNG_UST_STATEDUMP_PREFIX
)) == 0) {
1226 /* Handle statedump events. */
1227 handle_event_statedump(debug_it
, in_event
);
1235 bt_message
*handle_event_message(struct debug_info_msg_iter
*debug_it
,
1236 const bt_message
*in_message
)
1238 const bt_clock_snapshot
*cs
;
1239 const bt_clock_class
*default_cc
;
1240 const bt_packet
*in_packet
;
1241 const bt_stream
*in_stream
;
1242 const bt_stream
*out_stream
;
1243 bt_event_class
*out_event_class
;
1244 bt_packet
*out_packet
= NULL
;
1245 bt_event
*out_event
;
1246 bt_logging_level log_level
= debug_it
->log_level
;
1247 bt_self_component
*self_comp
= debug_it
->self_comp
;
1249 bt_message
*out_message
= NULL
;
1251 /* Borrow the input event and its event class. */
1252 const bt_event
*in_event
=
1253 bt_message_event_borrow_event_const(in_message
);
1254 const bt_event_class
*in_event_class
=
1255 bt_event_borrow_class_const(in_event
);
1257 update_event_statedump_if_needed(debug_it
, in_event
);
1259 out_event_class
= trace_ir_mapping_borrow_mapped_event_class(
1260 debug_it
->ir_maps
, in_event_class
);
1261 if (!out_event_class
) {
1262 out_event_class
= trace_ir_mapping_create_new_mapped_event_class(
1263 debug_it
->ir_maps
, in_event_class
);
1265 BT_ASSERT_DBG(out_event_class
);
1267 /* Borrow the input stream. */
1268 in_stream
= bt_event_borrow_stream_const(in_event
);
1269 BT_ASSERT_DBG(in_stream
);
1270 out_stream
= trace_ir_mapping_borrow_mapped_stream(debug_it
->ir_maps
,
1272 BT_ASSERT_DBG(in_stream
);
1274 /* Borrow the input and output packets. */
1275 in_packet
= bt_event_borrow_packet_const(in_event
);
1277 out_packet
= trace_ir_mapping_borrow_mapped_packet(
1278 debug_it
->ir_maps
, in_packet
);
1281 default_cc
= bt_stream_class_borrow_default_clock_class_const(
1282 bt_event_class_borrow_stream_class_const(in_event_class
));
1284 /* Borrow event clock snapshot. */
1285 cs
= bt_message_event_borrow_default_clock_snapshot_const(
1288 /* Create an output event message. */
1291 bt_message_event_create_with_packet_and_default_clock_snapshot(
1292 debug_it
->input_iterator
,
1293 out_event_class
, out_packet
,
1294 bt_clock_snapshot_get_value(cs
));
1297 bt_message_event_create_with_default_clock_snapshot(
1298 debug_it
->input_iterator
,
1299 out_event_class
, out_stream
,
1300 bt_clock_snapshot_get_value(cs
));
1304 out_message
= bt_message_event_create_with_packet(
1305 debug_it
->input_iterator
, out_event_class
,
1308 out_message
= bt_message_event_create(
1309 debug_it
->input_iterator
, out_event_class
,
1315 BT_COMP_LOGE_APPEND_CAUSE(self_comp
,
1316 "Error creating output event message.");
1320 out_event
= bt_message_event_borrow_event(out_message
);
1322 /* Copy the original fields to the output event. */
1323 if (copy_event_content(in_event
, out_event
, log_level
, self_comp
) !=
1324 DEBUG_INFO_TRACE_IR_MAPPING_STATUS_OK
) {
1325 BT_COMP_LOGE_APPEND_CAUSE(self_comp
,
1326 "Error copying event message content output event message: "
1327 "in-ev-addr=%p, out-ev-addr=%p", in_event
, out_event
);
1332 * Try to set the debug-info fields based on debug information that is
1335 fill_debug_info_event_if_needed(debug_it
, in_event
, out_event
);
1340 BT_MESSAGE_PUT_REF_AND_RESET(out_message
);
1346 bt_message
*handle_stream_begin_message(struct debug_info_msg_iter
*debug_it
,
1347 const bt_message
*in_message
)
1349 const bt_stream
*in_stream
;
1350 bt_message
*out_message
;
1351 bt_stream
*out_stream
;
1352 bt_logging_level log_level
= debug_it
->log_level
;
1353 bt_self_component
*self_comp
= debug_it
->self_comp
;
1355 in_stream
= bt_message_stream_beginning_borrow_stream_const(in_message
);
1356 BT_ASSERT(in_stream
);
1358 /* Create a duplicated output stream. */
1359 out_stream
= trace_ir_mapping_create_new_mapped_stream(
1360 debug_it
->ir_maps
, in_stream
);
1366 /* Create an output stream beginning message. */
1367 out_message
= bt_message_stream_beginning_create(
1368 debug_it
->input_iterator
, out_stream
);
1370 BT_COMP_LOGE_APPEND_CAUSE(self_comp
,
1371 "Error creating output stream beginning message: "
1372 "out-s-addr=%p", out_stream
);
1379 bt_message
*handle_stream_end_message(struct debug_info_msg_iter
*debug_it
,
1380 const bt_message
*in_message
)
1382 const bt_stream
*in_stream
;
1383 bt_message
*out_message
= NULL
;
1384 bt_stream
*out_stream
;
1385 bt_logging_level log_level
= debug_it
->log_level
;
1386 bt_self_component
*self_comp
= debug_it
->self_comp
;
1388 in_stream
= bt_message_stream_end_borrow_stream_const(in_message
);
1389 BT_ASSERT(in_stream
);
1391 out_stream
= trace_ir_mapping_borrow_mapped_stream(
1392 debug_it
->ir_maps
, in_stream
);
1393 BT_ASSERT(out_stream
);
1395 /* Create an output stream end message. */
1396 out_message
= bt_message_stream_end_create(debug_it
->input_iterator
,
1399 BT_COMP_LOGE_APPEND_CAUSE(self_comp
,
1400 "Error creating output stream end message: "
1401 "out-s-addr=%p", out_stream
);
1405 /* Remove stream from trace mapping hashtable. */
1406 trace_ir_mapping_remove_mapped_stream(debug_it
->ir_maps
, in_stream
);
1413 bt_message
*handle_packet_begin_message(struct debug_info_msg_iter
*debug_it
,
1414 const bt_message
*in_message
)
1416 bool has_default_clock_snapshot
;
1417 const bt_clock_snapshot
*cs
;
1418 bt_message
*out_message
= NULL
;
1419 bt_packet
*out_packet
;
1420 bt_logging_level log_level
= debug_it
->log_level
;
1421 bt_self_component
*self_comp
= debug_it
->self_comp
;
1423 const bt_packet
*in_packet
=
1424 bt_message_packet_beginning_borrow_packet_const(in_message
);
1425 BT_ASSERT(in_packet
);
1427 /* This packet should not be already mapped. */
1428 BT_ASSERT(!trace_ir_mapping_borrow_mapped_packet(
1429 debug_it
->ir_maps
, in_packet
));
1431 out_packet
= trace_ir_mapping_create_new_mapped_packet(debug_it
->ir_maps
,
1434 BT_ASSERT(out_packet
);
1436 has_default_clock_snapshot
=
1437 bt_stream_class_packets_have_beginning_default_clock_snapshot(
1438 bt_stream_borrow_class_const(
1439 bt_packet_borrow_stream_const(in_packet
)));
1440 if (has_default_clock_snapshot
) {
1441 /* Borrow clock snapshot. */
1442 cs
= bt_message_packet_beginning_borrow_default_clock_snapshot_const(
1445 /* Create an output packet beginning message. */
1446 out_message
= bt_message_packet_beginning_create_with_default_clock_snapshot(
1447 debug_it
->input_iterator
, out_packet
,
1448 bt_clock_snapshot_get_value(cs
));
1450 out_message
= bt_message_packet_beginning_create(
1451 debug_it
->input_iterator
, out_packet
);
1454 BT_COMP_LOGE_APPEND_CAUSE(self_comp
,
1455 "Error creating output packet beginning message: "
1456 "out-p-addr=%p", out_packet
);
1463 bt_message
*handle_packet_end_message(struct debug_info_msg_iter
*debug_it
,
1464 const bt_message
*in_message
)
1466 bool has_default_clock_snapshot
;
1467 const bt_clock_snapshot
*cs
;
1468 const bt_packet
*in_packet
;
1469 bt_message
*out_message
= NULL
;
1470 bt_packet
*out_packet
;
1471 bt_logging_level log_level
= debug_it
->log_level
;
1472 bt_self_component
*self_comp
= debug_it
->self_comp
;
1474 in_packet
= bt_message_packet_end_borrow_packet_const(in_message
);
1475 BT_ASSERT(in_packet
);
1477 out_packet
= trace_ir_mapping_borrow_mapped_packet(debug_it
->ir_maps
, in_packet
);
1478 BT_ASSERT(out_packet
);
1480 has_default_clock_snapshot
=
1481 bt_stream_class_packets_have_end_default_clock_snapshot(
1482 bt_stream_borrow_class_const(
1483 bt_packet_borrow_stream_const(in_packet
)));
1484 if (has_default_clock_snapshot
) {
1485 /* Borrow clock snapshot. */
1486 cs
= bt_message_packet_end_borrow_default_clock_snapshot_const(
1489 /* Create an outpute packet end message. */
1490 out_message
= bt_message_packet_end_create_with_default_clock_snapshot(
1491 debug_it
->input_iterator
, out_packet
,
1492 bt_clock_snapshot_get_value(cs
));
1494 out_message
= bt_message_packet_end_create(
1495 debug_it
->input_iterator
, out_packet
);
1499 BT_COMP_LOGE_APPEND_CAUSE(self_comp
,
1500 "Error creating output packet end message: "
1501 "out-p-addr=%p", out_packet
);
1505 /* Remove packet from data mapping hashtable. */
1506 trace_ir_mapping_remove_mapped_packet(debug_it
->ir_maps
, in_packet
);
1513 bt_message
*handle_msg_iterator_inactivity(
1514 struct debug_info_msg_iter
*debug_it
__attribute__((unused
)),
1515 const bt_message
*in_message
)
1518 * This message type can be forwarded directly because it does
1519 * not refer to any objects in the trace class.
1521 bt_message_get_ref(in_message
);
1522 return (bt_message
*) in_message
;
1526 bt_message
*handle_discarded_events_message(struct debug_info_msg_iter
*debug_it
,
1527 const bt_message
*in_message
)
1529 const bt_clock_snapshot
*begin_cs
, *end_cs
;
1530 const bt_stream
*in_stream
;
1531 bool has_default_clock_snapshots
;
1532 uint64_t discarded_events
, begin_cs_value
, end_cs_value
;
1533 bt_property_availability prop_avail
;
1534 bt_message
*out_message
= NULL
;
1535 bt_stream
*out_stream
;
1536 bt_logging_level log_level
= debug_it
->log_level
;
1537 bt_self_component
*self_comp
= debug_it
->self_comp
;
1539 in_stream
= bt_message_discarded_events_borrow_stream_const(
1541 BT_ASSERT(in_stream
);
1543 out_stream
= trace_ir_mapping_borrow_mapped_stream( debug_it
->ir_maps
,
1545 BT_ASSERT(out_stream
);
1547 has_default_clock_snapshots
=
1548 bt_stream_class_discarded_events_have_default_clock_snapshots(
1549 bt_stream_borrow_class_const(in_stream
));
1550 if (has_default_clock_snapshots
) {
1551 begin_cs
= bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
1553 end_cs
= bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
1556 begin_cs_value
= bt_clock_snapshot_get_value(begin_cs
);
1557 end_cs_value
= bt_clock_snapshot_get_value(end_cs
);
1559 out_message
= bt_message_discarded_events_create_with_default_clock_snapshots(
1560 debug_it
->input_iterator
, out_stream
,
1561 begin_cs_value
, end_cs_value
);
1563 out_message
= bt_message_discarded_events_create(
1564 debug_it
->input_iterator
, out_stream
);
1567 BT_COMP_LOGE_APPEND_CAUSE(self_comp
,
1568 "Error creating output discarded events message: "
1569 "out-s-addr=%p", out_stream
);
1573 prop_avail
= bt_message_discarded_events_get_count(in_message
,
1576 if (prop_avail
== BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE
) {
1577 bt_message_discarded_events_set_count(out_message
,
1586 bt_message
*handle_discarded_packets_message(struct debug_info_msg_iter
*debug_it
,
1587 const bt_message
*in_message
)
1589 const bt_clock_snapshot
*begin_cs
, *end_cs
;
1590 bool has_default_clock_snapshots
;
1591 const bt_stream
*in_stream
;
1592 uint64_t discarded_packets
, begin_cs_value
, end_cs_value
;
1593 bt_property_availability prop_avail
;
1594 bt_message
*out_message
= NULL
;
1595 bt_stream
*out_stream
;
1596 bt_logging_level log_level
= debug_it
->log_level
;
1597 bt_self_component
*self_comp
= debug_it
->self_comp
;
1599 in_stream
= bt_message_discarded_packets_borrow_stream_const(
1601 BT_ASSERT(in_stream
);
1603 out_stream
= trace_ir_mapping_borrow_mapped_stream( debug_it
->ir_maps
,
1605 BT_ASSERT(out_stream
);
1607 has_default_clock_snapshots
=
1608 bt_stream_class_discarded_packets_have_default_clock_snapshots(
1609 bt_stream_borrow_class_const(in_stream
));
1610 if (has_default_clock_snapshots
) {
1611 begin_cs
= bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
1614 end_cs
= bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
1617 begin_cs_value
= bt_clock_snapshot_get_value(begin_cs
);
1618 end_cs_value
= bt_clock_snapshot_get_value(end_cs
);
1620 out_message
= bt_message_discarded_packets_create_with_default_clock_snapshots(
1621 debug_it
->input_iterator
, out_stream
,
1622 begin_cs_value
, end_cs_value
);
1624 out_message
= bt_message_discarded_packets_create(
1625 debug_it
->input_iterator
, out_stream
);
1628 BT_COMP_LOGE_APPEND_CAUSE(self_comp
,
1629 "Error creating output discarded packet message: "
1630 "out-s-addr=%p", out_stream
);
1634 prop_avail
= bt_message_discarded_packets_get_count(in_message
,
1635 &discarded_packets
);
1636 if (prop_avail
== BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE
) {
1637 bt_message_discarded_packets_set_count(out_message
,
1646 const bt_message
*handle_message(struct debug_info_msg_iter
*debug_it
,
1647 const bt_message
*in_message
)
1649 bt_message
*out_message
= NULL
;
1651 switch (bt_message_get_type(in_message
)) {
1652 case BT_MESSAGE_TYPE_EVENT
:
1653 out_message
= handle_event_message(debug_it
, in_message
);
1655 case BT_MESSAGE_TYPE_PACKET_BEGINNING
:
1656 out_message
= handle_packet_begin_message(debug_it
, in_message
);
1658 case BT_MESSAGE_TYPE_PACKET_END
:
1659 out_message
= handle_packet_end_message(debug_it
, in_message
);
1661 case BT_MESSAGE_TYPE_STREAM_BEGINNING
:
1662 out_message
= handle_stream_begin_message(debug_it
, in_message
);
1664 case BT_MESSAGE_TYPE_STREAM_END
:
1665 out_message
= handle_stream_end_message(debug_it
, in_message
);
1667 case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY
:
1668 out_message
= handle_msg_iterator_inactivity(debug_it
, in_message
);
1670 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
1671 out_message
= handle_discarded_events_message(debug_it
, in_message
);
1673 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
1674 out_message
= handle_discarded_packets_message(debug_it
, in_message
);
1685 struct bt_param_validation_map_value_entry_descr debug_info_params
[] = {
1686 { "debug-info-field-name", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_OPTIONAL
, { .type
= BT_VALUE_TYPE_STRING
} },
1687 { "debug-info-dir", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_OPTIONAL
, { .type
= BT_VALUE_TYPE_STRING
} },
1688 { "target-prefix", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_OPTIONAL
, { .type
= BT_VALUE_TYPE_STRING
} },
1689 { "full-path", BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_OPTIONAL
, { .type
= BT_VALUE_TYPE_BOOL
} },
1690 BT_PARAM_VALIDATION_MAP_VALUE_ENTRY_END
1694 bt_component_class_initialize_method_status
init_from_params(
1695 struct debug_info_component
*debug_info_component
,
1696 const bt_value
*params
)
1698 const bt_value
*value
;
1699 bt_component_class_initialize_method_status status
;
1700 bt_logging_level log_level
= debug_info_component
->log_level
;
1701 enum bt_param_validation_status validation_status
;
1702 gchar
*validate_error
= NULL
;
1704 validation_status
= bt_param_validation_validate(params
,
1705 debug_info_params
, &validate_error
);
1706 if (validation_status
== BT_PARAM_VALIDATION_STATUS_MEMORY_ERROR
) {
1707 status
= BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR
;
1709 } else if (validation_status
== BT_PARAM_VALIDATION_STATUS_VALIDATION_ERROR
) {
1710 status
= BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR
;
1711 BT_COMP_LOGE_APPEND_CAUSE(debug_info_component
->self_comp
,
1712 "%s", validate_error
);
1718 value
= bt_value_map_borrow_entry_value_const(params
,
1719 "debug-info-field-name");
1721 debug_info_component
->arg_debug_info_field_name
=
1722 g_strdup(bt_value_string_get(value
));
1724 debug_info_component
->arg_debug_info_field_name
=
1725 g_strdup(DEFAULT_DEBUG_INFO_FIELD_NAME
);
1728 value
= bt_value_map_borrow_entry_value_const(params
, "debug-info-dir");
1730 debug_info_component
->arg_debug_dir
=
1731 g_strdup(bt_value_string_get(value
));
1733 debug_info_component
->arg_debug_dir
= NULL
;
1737 value
= bt_value_map_borrow_entry_value_const(params
, "target-prefix");
1739 debug_info_component
->arg_target_prefix
=
1740 g_strdup(bt_value_string_get(value
));
1742 debug_info_component
->arg_target_prefix
= NULL
;
1745 value
= bt_value_map_borrow_entry_value_const(params
, "full-path");
1747 debug_info_component
->arg_full_path
= bt_value_bool_get(value
);
1749 debug_info_component
->arg_full_path
= BT_FALSE
;
1752 status
= BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK
;
1755 g_free(validate_error
);
1760 bt_component_class_initialize_method_status
debug_info_comp_init(
1761 bt_self_component_filter
*self_comp_flt
,
1762 bt_self_component_filter_configuration
*config
__attribute__((unused
)),
1763 const bt_value
*params
, void *init_method_data
__attribute__((unused
)))
1765 struct debug_info_component
*debug_info_comp
;
1766 bt_component_class_initialize_method_status status
=
1767 BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK
;
1768 bt_self_component_add_port_status add_port_status
;
1769 bt_self_component
*self_comp
=
1770 bt_self_component_filter_as_self_component(self_comp_flt
);
1771 bt_logging_level log_level
= bt_component_get_logging_level(
1772 bt_self_component_as_component(self_comp
));
1774 BT_COMP_LOGI("Initializing debug_info component: "
1775 "comp-addr=%p, params-addr=%p", self_comp
, params
);
1777 debug_info_comp
= g_new0(struct debug_info_component
, 1);
1778 if (!debug_info_comp
) {
1779 BT_COMP_LOGE_APPEND_CAUSE(self_comp
,
1780 "Failed to allocate one debug_info component.");
1784 debug_info_comp
->log_level
= log_level
;
1785 debug_info_comp
->self_comp
= self_comp
;
1786 debug_info_comp
->self_comp_filter
= self_comp_flt
;
1787 bt_self_component_set_data(self_comp
, debug_info_comp
);
1789 add_port_status
= bt_self_component_filter_add_input_port(
1790 self_comp_flt
, "in", NULL
, NULL
);
1791 if (add_port_status
!= BT_SELF_COMPONENT_ADD_PORT_STATUS_OK
) {
1792 status
= (int) add_port_status
;
1796 add_port_status
= bt_self_component_filter_add_output_port(
1797 self_comp_flt
, "out", NULL
, NULL
);
1798 if (add_port_status
!= BT_SELF_COMPONENT_ADD_PORT_STATUS_OK
) {
1799 status
= (int) add_port_status
;
1803 status
= init_from_params(debug_info_comp
, params
);
1804 if (status
!= BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK
) {
1805 BT_COMP_LOGE_APPEND_CAUSE(self_comp
,
1806 "Cannot configure debug_info component: "
1807 "debug_info-comp-addr=%p, params-addr=%p",
1808 debug_info_comp
, params
);
1815 destroy_debug_info_comp(debug_info_comp
);
1816 bt_self_component_set_data(self_comp
, NULL
);
1818 if (status
== BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_OK
) {
1819 status
= BT_COMPONENT_CLASS_INITIALIZE_METHOD_STATUS_ERROR
;
1825 void debug_info_comp_finalize(bt_self_component_filter
*self_comp_flt
)
1827 struct debug_info_component
*debug_info
=
1828 bt_self_component_get_data(
1829 bt_self_component_filter_as_self_component(
1831 bt_logging_level log_level
= debug_info
->log_level
;
1832 bt_self_component
*self_comp
= debug_info
->self_comp
;
1834 BT_COMP_LOGI("Finalizing debug_info self_component: comp-addr=%p",
1837 destroy_debug_info_comp(debug_info
);
1840 bt_message_iterator_class_next_method_status
debug_info_msg_iter_next(
1841 bt_self_message_iterator
*self_msg_iter
,
1842 const bt_message_array_const msgs
, uint64_t capacity
,
1845 bt_message_iterator
*upstream_iterator
= NULL
;
1846 bt_message_iterator_next_status upstream_iterator_ret_status
;
1847 struct debug_info_msg_iter
*debug_info_msg_iter
;
1848 struct debug_info_component
*debug_info
= NULL
;
1849 bt_message_iterator_class_next_method_status status
;
1850 bt_self_component
*self_comp
= NULL
;
1851 bt_message_array_const input_msgs
;
1852 const bt_message
*out_message
;
1853 uint64_t curr_msg_idx
, i
;
1855 status
= BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_OK
;
1857 self_comp
= bt_self_message_iterator_borrow_component(self_msg_iter
);
1858 BT_ASSERT_DBG(self_comp
);
1860 debug_info
= bt_self_component_get_data(self_comp
);
1861 BT_ASSERT_DBG(debug_info
);
1863 debug_info_msg_iter
= bt_self_message_iterator_get_data(self_msg_iter
);
1864 BT_ASSERT_DBG(debug_info_msg_iter
);
1866 upstream_iterator
= debug_info_msg_iter
->msg_iter
;
1867 BT_ASSERT_DBG(upstream_iterator
);
1869 upstream_iterator_ret_status
=
1870 bt_message_iterator_next(
1871 upstream_iterator
, &input_msgs
, count
);
1872 if (upstream_iterator_ret_status
!=
1873 BT_MESSAGE_ITERATOR_NEXT_STATUS_OK
) {
1875 * No messages were returned. Not necessarily an error.
1876 * Convert the upstream message iterator status to a
1879 status
= (int) upstream_iterator_ret_status
;
1884 * There should never be more received messages than the capacity we
1887 BT_ASSERT_DBG(*count
<= capacity
);
1889 for (curr_msg_idx
= 0; curr_msg_idx
< *count
; curr_msg_idx
++) {
1890 out_message
= handle_message(debug_info_msg_iter
,
1891 input_msgs
[curr_msg_idx
]);
1893 goto handle_msg_error
;
1896 msgs
[curr_msg_idx
] = out_message
;
1898 * Drop our reference of the input message as we are done with
1899 * it and created a output copy.
1901 bt_message_put_ref(input_msgs
[curr_msg_idx
]);
1908 * Drop references of all the output messages created before the
1911 for (i
= 0; i
< curr_msg_idx
; i
++) {
1912 bt_message_put_ref(msgs
[i
]);
1916 * Drop references of all the input messages not dropped before the
1919 for (i
= curr_msg_idx
; i
< *count
; i
++) {
1920 bt_message_put_ref(input_msgs
[i
]);
1923 status
= BT_MESSAGE_ITERATOR_CLASS_NEXT_METHOD_STATUS_MEMORY_ERROR
;
1930 void debug_info_msg_iter_destroy(struct debug_info_msg_iter
*debug_info_msg_iter
)
1932 if (!debug_info_msg_iter
) {
1936 if (debug_info_msg_iter
->msg_iter
) {
1937 bt_message_iterator_put_ref(
1938 debug_info_msg_iter
->msg_iter
);
1941 if (debug_info_msg_iter
->ir_maps
) {
1942 trace_ir_maps_destroy(debug_info_msg_iter
->ir_maps
);
1945 if (debug_info_msg_iter
->debug_info_map
) {
1946 g_hash_table_destroy(debug_info_msg_iter
->debug_info_map
);
1949 bt_fd_cache_fini(&debug_info_msg_iter
->fd_cache
);
1950 g_free(debug_info_msg_iter
);
1956 bt_message_iterator_class_initialize_method_status
debug_info_msg_iter_init(
1957 bt_self_message_iterator
*self_msg_iter
,
1958 bt_self_message_iterator_configuration
*config
,
1959 bt_self_component_port_output
*self_port
__attribute__((unused
)))
1961 bt_message_iterator_class_initialize_method_status status
;
1962 bt_message_iterator_create_from_message_iterator_status
1964 struct bt_self_component_port_input
*input_port
= NULL
;
1965 bt_message_iterator
*upstream_iterator
= NULL
;
1966 struct debug_info_msg_iter
*debug_info_msg_iter
= NULL
;
1967 gchar
*debug_info_field_name
;
1969 bt_self_component
*self_comp
=
1970 bt_self_message_iterator_borrow_component(self_msg_iter
);
1971 bt_logging_level log_level
= bt_component_get_logging_level(
1972 bt_self_component_as_component(self_comp
));
1974 debug_info_msg_iter
= g_new0(struct debug_info_msg_iter
, 1);
1975 if (!debug_info_msg_iter
) {
1976 status
= BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR
;
1980 debug_info_msg_iter
->log_level
= log_level
;
1981 debug_info_msg_iter
->self_comp
= self_comp
;
1983 debug_info_msg_iter
->debug_info_component
=
1984 bt_self_component_get_data(self_comp
);
1986 /* Borrow the upstream input port. */
1987 input_port
= bt_self_component_filter_borrow_input_port_by_name(
1988 debug_info_msg_iter
->debug_info_component
->self_comp_filter
,
1991 status
= BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_ERROR
;
1995 /* Create an iterator on the upstream component. */
1996 msg_iter_status
= bt_message_iterator_create_from_message_iterator(
1997 self_msg_iter
, input_port
, &upstream_iterator
);
1998 if (msg_iter_status
!= BT_MESSAGE_ITERATOR_CREATE_FROM_MESSAGE_ITERATOR_STATUS_OK
) {
1999 status
= (int) msg_iter_status
;
2003 BT_MESSAGE_ITERATOR_MOVE_REF(
2004 debug_info_msg_iter
->msg_iter
, upstream_iterator
);
2006 /* Create hashtable that will contain debug info mapping. */
2007 debug_info_msg_iter
->debug_info_map
= g_hash_table_new_full(
2008 g_direct_hash
, g_direct_equal
, (GDestroyNotify
) NULL
,
2009 (GDestroyNotify
) debug_info_destroy
);
2010 if (!debug_info_msg_iter
->debug_info_map
) {
2011 status
= BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR
;
2015 debug_info_field_name
=
2016 debug_info_msg_iter
->debug_info_component
->arg_debug_info_field_name
;
2018 debug_info_msg_iter
->ir_maps
= trace_ir_maps_create(self_comp
,
2019 debug_info_field_name
, log_level
);
2020 if (!debug_info_msg_iter
->ir_maps
) {
2021 status
= BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR
;
2025 ret
= bt_fd_cache_init(&debug_info_msg_iter
->fd_cache
, log_level
);
2027 status
= BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_MEMORY_ERROR
;
2031 bt_self_message_iterator_configuration_set_can_seek_forward(config
,
2032 bt_message_iterator_can_seek_forward(
2033 debug_info_msg_iter
->msg_iter
));
2035 bt_self_message_iterator_set_data(self_msg_iter
, debug_info_msg_iter
);
2036 debug_info_msg_iter
->input_iterator
= self_msg_iter
;
2038 status
= BT_MESSAGE_ITERATOR_CLASS_INITIALIZE_METHOD_STATUS_OK
;
2042 debug_info_msg_iter_destroy(debug_info_msg_iter
);
2048 bt_message_iterator_class_can_seek_beginning_method_status
2049 debug_info_msg_iter_can_seek_beginning(bt_self_message_iterator
*self_msg_iter
,
2052 struct debug_info_msg_iter
*debug_info_msg_iter
=
2053 bt_self_message_iterator_get_data(self_msg_iter
);
2054 BT_ASSERT(debug_info_msg_iter
);
2056 return (int) bt_message_iterator_can_seek_beginning(
2057 debug_info_msg_iter
->msg_iter
, can_seek
);
2060 bt_message_iterator_class_seek_beginning_method_status
2061 debug_info_msg_iter_seek_beginning(bt_self_message_iterator
*self_msg_iter
)
2063 struct debug_info_msg_iter
*debug_info_msg_iter
=
2064 bt_self_message_iterator_get_data(self_msg_iter
);
2065 bt_message_iterator_class_seek_beginning_method_status status
=
2066 BT_MESSAGE_ITERATOR_CLASS_SEEK_BEGINNING_METHOD_STATUS_OK
;
2067 bt_message_iterator_seek_beginning_status seek_beg_status
;
2069 BT_ASSERT(debug_info_msg_iter
);
2071 /* Ask the upstream component to seek to the beginning. */
2072 seek_beg_status
= bt_message_iterator_seek_beginning(
2073 debug_info_msg_iter
->msg_iter
);
2074 if (seek_beg_status
!= BT_MESSAGE_ITERATOR_SEEK_BEGINNING_STATUS_OK
) {
2075 status
= (int) seek_beg_status
;
2079 /* Clear this iterator data. */
2080 trace_ir_maps_clear(debug_info_msg_iter
->ir_maps
);
2081 g_hash_table_remove_all(debug_info_msg_iter
->debug_info_map
);
2087 void debug_info_msg_iter_finalize(bt_self_message_iterator
*it
)
2089 struct debug_info_msg_iter
*debug_info_msg_iter
;
2091 debug_info_msg_iter
= bt_self_message_iterator_get_data(it
);
2092 BT_ASSERT(debug_info_msg_iter
);
2094 debug_info_msg_iter_destroy(debug_info_msg_iter
);