2 * Babeltrace - Debug Information State Tracker
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 * 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:
17 * The above copyright notice and this permission notice shall be included in
18 * all copies or substantial portions of the Software.
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
29 #define BT_LOG_OUTPUT_LEVEL log_level
30 #define BT_LOG_TAG "PLUGIN/FLT.LTTNG-UTILS.DEBUG-INFO"
31 #include "logging/log.h"
35 #include "common/assert.h"
36 #include "common/common.h"
37 #include "fd-cache/fd-cache.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"
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"
58 struct debug_info_component
{
59 bt_logging_level log_level
;
61 gchar
*arg_debug_info_field_name
;
62 gchar
*arg_target_prefix
;
63 bt_bool arg_full_path
;
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
;
73 struct trace_ir_maps
*ir_maps
;
74 /* in_trace -> debug_info_mapping. */
75 GHashTable
*debug_info_map
;
77 struct bt_fd_cache fd_cache
;
80 struct debug_info_source
{
81 /* Strings are owned by debug_info_source. */
84 * Store the line number as a string so that the allocation and
85 * conversion to string is only done once.
89 /* short_src_path points inside src_path, no need to free. */
90 const gchar
*short_src_path
;
92 /* short_bin_path points inside bin_path, no need to free. */
93 const gchar
*short_bin_path
;
95 * Location within the binary. Either absolute (@0x1234) or
101 struct proc_debug_info_sources
{
103 * Hash table: base address (pointer to uint64_t) to bin info; owned by
104 * proc_debug_info_sources.
106 GHashTable
*baddr_to_bin_info
;
109 * Hash table: IP (pointer to uint64_t) to (struct debug_info_source *);
110 * owned by proc_debug_info_sources.
112 GHashTable
*ip_to_debug_info_src
;
116 bt_logging_level log_level
;
117 struct debug_info_component
*comp
;
118 const bt_trace
*input_trace
;
119 uint64_t destruction_listener_id
;
122 * Hash table of VPIDs (pointer to int64_t) to
123 * (struct proc_debug_info_sources*); owned by debug_info.
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
;
133 struct bt_fd_cache
*fd_cache
; /* Weak ref. Owned by the iterator. */
137 int debug_info_init(struct debug_info
*info
)
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");
151 return bin_info_init(info
->log_level
);
155 void debug_info_source_destroy(struct debug_info_source
*debug_info_src
)
157 if (!debug_info_src
) {
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
);
170 struct debug_info_source
*debug_info_source_create_from_bin(
171 struct bin_info
*bin
, uint64_t ip
)
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
;
178 debug_info_src
= g_new0(struct debug_info_source
, 1);
180 if (!debug_info_src
) {
184 /* Lookup function name */
185 ret
= bin_info_lookup_function_name(bin
, ip
, &debug_info_src
->func
);
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
);
195 BT_LOGI("Failed to lookup source location: ret=%d", ret
);
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.");
207 if (src_loc
->filename
) {
208 debug_info_src
->src_path
= g_strdup(src_loc
->filename
);
209 if (!debug_info_src
->src_path
) {
213 debug_info_src
->short_src_path
= get_filename_from_path(
214 debug_info_src
->src_path
);
216 source_location_destroy(src_loc
);
220 debug_info_src
->bin_path
= g_strdup(bin
->elf_path
);
221 if (!debug_info_src
->bin_path
) {
225 debug_info_src
->short_bin_path
= get_filename_from_path(
226 debug_info_src
->bin_path
);
228 ret
= bin_info_get_bin_loc(bin
, ip
, &(debug_info_src
->bin_loc
));
235 return debug_info_src
;
238 debug_info_source_destroy(debug_info_src
);
243 void proc_debug_info_sources_destroy(
244 struct proc_debug_info_sources
*proc_dbg_info_src
)
246 if (!proc_dbg_info_src
) {
250 if (proc_dbg_info_src
->baddr_to_bin_info
) {
251 g_hash_table_destroy(proc_dbg_info_src
->baddr_to_bin_info
);
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
);
258 g_free(proc_dbg_info_src
);
262 struct proc_debug_info_sources
*proc_debug_info_sources_create(void)
264 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
266 proc_dbg_info_src
= g_new0(struct proc_debug_info_sources
, 1);
267 if (!proc_dbg_info_src
) {
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
) {
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
) {
286 return proc_dbg_info_src
;
289 proc_debug_info_sources_destroy(proc_dbg_info_src
);
294 struct proc_debug_info_sources
*proc_debug_info_sources_ht_get_entry(
295 GHashTable
*ht
, int64_t vpid
)
297 gpointer key
= g_new0(int64_t, 1);
298 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
304 *((int64_t *) key
) = vpid
;
306 /* Exists? Return it */
307 proc_dbg_info_src
= g_hash_table_lookup(ht
, key
);
308 if (proc_dbg_info_src
) {
312 /* Otherwise, create and return it */
313 proc_dbg_info_src
= proc_debug_info_sources_create();
314 if (!proc_dbg_info_src
) {
318 g_hash_table_insert(ht
, key
, proc_dbg_info_src
);
319 /* Ownership passed to ht */
323 return proc_dbg_info_src
;
327 const bt_field
*event_borrow_payload_field(const bt_event
*event
,
328 const char *field_name
)
330 const bt_field
*event_payload
, *field
;
332 event_payload
= bt_event_borrow_payload_field_const(event
);
333 BT_ASSERT(event_payload
);
335 field
= bt_field_structure_borrow_member_field_by_name_const(
336 event_payload
, field_name
);
341 const bt_field
*event_borrow_common_context_field(const bt_event
*event
,
342 const char *field_name
)
344 const bt_field
*event_common_ctx
, *field
= NULL
;
346 event_common_ctx
= bt_event_borrow_common_context_field_const(event
);
347 if (!event_common_ctx
) {
351 field
= bt_field_structure_borrow_member_field_by_name_const(
352 event_common_ctx
, field_name
);
359 void event_get_common_context_signed_integer_field_value(
360 const bt_event
*event
, const char *field_name
, int64_t *value
)
362 *value
= bt_field_signed_integer_get_value(
363 event_borrow_common_context_field(event
, field_name
));
367 int event_get_payload_build_id_length(const bt_event
*event
,
368 const char *field_name
, uint64_t *build_id_len
)
370 const bt_field
*build_id_field
;
371 const bt_field_class
*build_id_field_class
;
373 build_id_field
= event_borrow_payload_field(event
, field_name
);
374 build_id_field_class
= bt_field_borrow_class_const(build_id_field
);
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
);
383 *build_id_len
= bt_field_array_get_length(build_id_field
);
389 int event_get_payload_build_id_value(const bt_event
*event
,
390 const char *field_name
, uint8_t *build_id
)
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
;
399 build_id_field
= event_borrow_payload_field(event
, field_name
);
400 build_id_field_class
= bt_field_borrow_class_const(build_id_field
);
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
);
409 build_id_len
= bt_field_array_get_length(build_id_field
);
411 for (i
= 0; i
< build_id_len
; i
++) {
413 bt_field_array_borrow_element_field_by_index_const(
416 build_id
[i
] = bt_field_unsigned_integer_get_value(curr_field
);
423 void event_get_payload_unsigned_integer_field_value(const bt_event
*event
,
424 const char *field_name
, uint64_t *value
)
426 *value
= bt_field_unsigned_integer_get_value(
427 event_borrow_payload_field(event
, field_name
));
431 void event_get_payload_string_field_value(const bt_event
*event
,
432 const char *field_name
, const char **value
)
434 *value
= bt_field_string_get_value(
435 event_borrow_payload_field(event
, field_name
));
439 bool event_has_payload_field(const bt_event
*event
,
440 const char *field_name
)
442 return event_borrow_payload_field(event
, field_name
) != NULL
;
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
)
450 struct debug_info_source
*debug_info_src
= NULL
;
451 gpointer key
= g_new0(uint64_t, 1);
453 gpointer baddr
, value
;
459 *((uint64_t *) key
) = ip
;
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
,
465 if (debug_info_src
) {
469 /* Check in all bin_infos. */
470 g_hash_table_iter_init(&iter
, proc_dbg_info_src
->baddr_to_bin_info
);
472 while (g_hash_table_iter_next(&iter
, &baddr
, &value
))
474 struct bin_info
*bin
= value
;
476 if (!bin_info_has_address(value
, ip
)) {
481 * Found; add it to cache.
483 * FIXME: this should be bounded in size (and implement
484 * a caching policy), and entries should be prunned when
485 * libraries are unmapped.
487 debug_info_src
= debug_info_source_create_from_bin(bin
, ip
);
488 if (debug_info_src
) {
490 proc_dbg_info_src
->ip_to_debug_info_src
,
491 key
, debug_info_src
);
492 /* Ownership passed to ht. */
500 return debug_info_src
;
504 struct debug_info_source
*debug_info_query(struct debug_info
*debug_info
,
505 int64_t vpid
, uint64_t ip
)
507 struct debug_info_source
*dbg_info_src
= NULL
;
508 struct proc_debug_info_sources
*proc_dbg_info_src
;
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
) {
516 dbg_info_src
= proc_debug_info_sources_get_entry(debug_info
,
517 proc_dbg_info_src
, ip
);
524 struct debug_info
*debug_info_create(struct debug_info_component
*comp
,
525 const bt_trace
*trace
, struct bt_fd_cache
*fdc
)
528 struct debug_info
*debug_info
;
534 debug_info
= g_new0(struct debug_info
, 1);
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
) {
547 debug_info
->comp
= comp
;
548 ret
= debug_info_init(debug_info
);
553 debug_info
->input_trace
= trace
;
554 debug_info
->fd_cache
= fdc
;
564 void debug_info_destroy(struct debug_info
*debug_info
)
566 bt_logging_level log_level
;
567 bt_trace_status status
;
572 log_level
= debug_info
->log_level
;
574 if (debug_info
->vpid_to_proc_dbg_info_src
) {
575 g_hash_table_destroy(debug_info
->vpid_to_proc_dbg_info_src
);
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.");
590 void handle_event_statedump_build_id(struct debug_info
*debug_info
,
591 const bt_event
*event
)
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
;
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
);
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
) {
611 bin
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_bin_info
,
615 * The build_id event comes after the bin has been
616 * created. If it isn't found, just ignore this event.
620 ret
= event_get_payload_build_id_length(event
, BUILD_ID_FIELD_NAME
,
623 build_id
= g_new0(uint8_t, build_id_len
);
628 ret
= event_get_payload_build_id_value(event
, BUILD_ID_FIELD_NAME
,
634 ret
= bin_info_set_build_id(bin
, build_id
, build_id_len
);
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.
644 bin
->is_elf_only
= false;
652 void handle_event_statedump_debug_link(struct debug_info
*debug_info
,
653 const bt_event
*event
)
655 struct proc_debug_info_sources
*proc_dbg_info_src
;
656 struct bin_info
*bin
= NULL
;
659 const char *filename
= NULL
;
661 uint64_t crc_field_value
;
663 event_get_common_context_signed_integer_field_value(event
,
664 VPID_FIELD_NAME
, &vpid
);
666 event_get_payload_unsigned_integer_field_value(event
,
667 BADDR_FIELD_NAME
, &baddr
);
669 event_get_payload_unsigned_integer_field_value(event
,
670 CRC32_FIELD_NAME
, &crc_field_value
);
672 crc32
= (uint32_t) crc_field_value
;
674 event_get_payload_string_field_value(event
,
675 FILENAME_FIELD_NAME
, &filename
);
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
) {
683 bin
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_bin_info
,
687 * The debug_link event comes after the bin has been
688 * created. If it isn't found, just ignore this event.
693 bin_info_set_debug_link(bin
, filename
, crc32
);
700 void handle_bin_info_event(struct debug_info
*debug_info
,
701 const bt_event
*event
, bool has_pic_field
)
703 struct proc_debug_info_sources
*proc_dbg_info_src
;
704 struct bin_info
*bin
;
705 uint64_t baddr
, memsz
;
711 event_get_payload_unsigned_integer_field_value(event
,
712 MEMSZ_FIELD_NAME
, &memsz
);
718 event_get_payload_unsigned_integer_field_value(event
,
719 BADDR_FIELD_NAME
, &baddr
);
722 * This field is not produced by the dlopen event emitted before
725 if (!event_has_payload_field(event
, PATH_FIELD_NAME
)) {
728 event_get_payload_string_field_value(event
, PATH_FIELD_NAME
, &path
);
731 uint64_t is_pic_field_value
;
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;
738 * dlopen has no is_pic field, because the shared
739 * object is always PIC.
744 event_get_common_context_signed_integer_field_value(event
,
745 VPID_FIELD_NAME
, &vpid
);
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
) {
753 key
= g_new0(uint64_t, 1);
758 *((uint64_t *) key
) = baddr
;
760 bin
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_bin_info
, key
);
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
);
773 g_hash_table_insert(proc_dbg_info_src
->baddr_to_bin_info
, key
, bin
);
774 /* Ownership passed to ht. */
783 void handle_event_statedump_bin_info(struct debug_info
*debug_info
,
784 const bt_event
*event
)
786 handle_bin_info_event(debug_info
, event
, true);
790 void handle_event_lib_load(struct debug_info
*debug_info
,
791 const bt_event
*event
)
793 handle_bin_info_event(debug_info
, event
, false);
797 void handle_event_lib_unload(struct debug_info
*debug_info
,
798 const bt_event
*event
)
801 struct proc_debug_info_sources
*proc_dbg_info_src
;
805 event_get_payload_unsigned_integer_field_value(event
, BADDR_FIELD_NAME
,
808 event_get_common_context_signed_integer_field_value(event
,
809 VPID_FIELD_NAME
, &vpid
);
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
) {
815 * It's an unload event for a library for which no load event
816 * was previously received.
821 ret
= g_hash_table_remove(proc_dbg_info_src
->baddr_to_bin_info
,
829 void handle_event_statedump_start(struct debug_info
*debug_info
,
830 const bt_event
*event
)
832 struct proc_debug_info_sources
*proc_dbg_info_src
;
835 event_get_common_context_signed_integer_field_value(
836 event
, VPID_FIELD_NAME
, &vpid
);
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
) {
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
);
851 void trace_debug_info_remove_func(const bt_trace
*in_trace
, void *data
)
853 struct debug_info_msg_iter
*debug_it
= data
;
854 if (debug_it
->debug_info_map
) {
856 ret
= g_hash_table_remove(debug_it
->debug_info_map
,
857 (gpointer
) in_trace
);
863 void handle_event_statedump(struct debug_info_msg_iter
*debug_it
,
864 const bt_event
*event
)
866 const bt_event_class
*event_class
;
867 const char *event_name
;
869 const bt_trace
*trace
;
870 struct debug_info
*debug_info
;
875 event_class
= bt_event_borrow_class_const(event
);
877 event_name
= bt_event_class_get_name(event_class
);
879 trace
= bt_stream_borrow_trace_const(
880 bt_event_borrow_stream_const(event
));
882 debug_info
= g_hash_table_lookup(debug_it
->debug_info_map
, trace
);
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
,
888 bt_trace_add_destruction_listener(trace
,
889 trace_debug_info_remove_func
, debug_it
,
890 &debug_info
->destruction_listener_id
);
893 q_event_name
= g_quark_try_string(event_name
);
895 if (q_event_name
== debug_info
->q_statedump_bin_info
) {
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
) {
901 * dl_open and lib_load events are both checked for since
902 * only dl_open was produced as of lttng-ust 2.8.
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.
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
) {
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
);
927 void destroy_debug_info_comp(struct debug_info_component
*debug_info
)
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
);
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
)
944 bt_field_status status
;
946 BT_ASSERT(bt_field_get_class_type(curr_field
) ==
947 BT_FIELD_CLASS_TYPE_STRING
);
951 status
= bt_field_string_set_value(curr_field
,
952 dbg_info_src
->bin_path
);
954 status
= bt_field_string_set_value(curr_field
,
955 dbg_info_src
->short_bin_path
);
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",
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",
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
);
979 void fill_debug_info_func_field(struct debug_info_source
*dbg_info_src
,
980 bt_field
*curr_field
, bt_logging_level log_level
)
982 bt_field_status status
;
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
,
990 status
= bt_field_string_set_value(curr_field
, "");
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
);
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
)
1003 bt_field_status status
;
1005 BT_ASSERT(bt_field_get_class_type(curr_field
) ==
1006 BT_FIELD_CLASS_TYPE_STRING
);
1008 if (dbg_info_src
&& dbg_info_src
->src_path
) {
1010 status
= bt_field_string_set_value(curr_field
,
1011 dbg_info_src
->src_path
);
1013 status
= bt_field_string_set_value(curr_field
,
1014 dbg_info_src
->short_src_path
);
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",
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",
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",
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
);
1045 void fill_debug_info_field_empty(bt_field
*debug_info_field
,
1046 bt_logging_level log_level
)
1048 bt_field_status status
;
1049 bt_field
*bin_field
, *func_field
, *src_field
;
1051 BT_ASSERT(bt_field_get_class_type(debug_info_field
) ==
1052 BT_FIELD_CLASS_TYPE_STRUCTURE
);
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");
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
);
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
);
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
);
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
);
1087 void fill_debug_info_field(struct debug_info
*debug_info
, int64_t vpid
,
1088 uint64_t ip
, bt_field
*debug_info_field
)
1090 struct debug_info_source
*dbg_info_src
;
1091 const bt_field_class
*debug_info_fc
;
1093 BT_ASSERT(bt_field_get_class_type(debug_info_field
) ==
1094 BT_FIELD_CLASS_TYPE_STRUCTURE
);
1096 debug_info_fc
= bt_field_borrow_class_const(debug_info_field
);
1098 BT_ASSERT(bt_field_class_structure_get_member_count(debug_info_fc
) == 3);
1100 dbg_info_src
= debug_info_query(debug_info
, vpid
, ip
);
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
);
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
)
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
;
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
;
1132 in_common_ctx_field
= bt_event_borrow_common_context_field_const(
1134 if (!in_common_ctx_field
) {
1136 * There is no event common context so no need to add debug
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
)) {
1146 * The input event common context does not have the necessary
1147 * fields to resolve debug information.
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
) {
1158 out_debug_info_field
= bt_field_structure_borrow_member_field_by_name(
1159 out_common_ctx_field
, debug_info_field_name
);
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
);
1166 vpid
= bt_field_signed_integer_get_value(vpid_field
);
1167 ip
= bt_field_unsigned_integer_get_value(ip_field
);
1170 * Borrow the debug_info structure needed for the source
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
)));
1179 * Perform the debug-info resolving and set the event fields
1182 fill_debug_info_field(debug_info
, vpid
, ip
, out_debug_info_field
);
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
);
1193 void update_event_statedump_if_needed(struct debug_info_msg_iter
*debug_it
,
1194 const bt_event
*in_event
)
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
);
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.
1204 event_common_ctx
= bt_event_borrow_common_context_field_const(in_event
);
1205 if (!event_common_ctx
) {
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
);
1225 bt_message
*handle_event_message(struct debug_info_msg_iter
*debug_it
,
1226 const bt_message
*in_message
)
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
;
1236 bt_message
*out_message
= NULL
;
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
);
1244 update_event_statedump_if_needed(debug_it
, in_event
);
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
);
1252 BT_ASSERT(out_event_class
);
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
,
1259 default_cc
= bt_stream_class_borrow_default_clock_class_const(
1260 bt_event_class_borrow_stream_class_const(in_event_class
));
1262 /* Borrow event clock snapshot. */
1263 cs
= bt_message_event_borrow_default_clock_snapshot_const(
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
));
1272 out_message
= bt_message_event_create(debug_it
->input_iterator
,
1273 out_event_class
, out_packet
);
1277 BT_LOGE("Error creating output event message.");
1281 out_event
= bt_message_event_borrow_event(out_message
);
1283 /* Copy the original fields to the output event. */
1284 copy_event_content(in_event
, out_event
, log_level
);
1287 * Try to set the debug-info fields based on debug information that is
1290 fill_debug_info_event_if_needed(debug_it
, in_event
, out_event
);
1297 bt_message
*handle_stream_begin_message(struct debug_info_msg_iter
*debug_it
,
1298 const bt_message
*in_message
)
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
;
1305 in_stream
= bt_message_stream_beginning_borrow_stream_const(in_message
);
1306 BT_ASSERT(in_stream
);
1308 /* Create a duplicated output stream. */
1309 out_stream
= trace_ir_mapping_create_new_mapped_stream(
1310 debug_it
->ir_maps
, in_stream
);
1316 /* Create an output stream beginning message. */
1317 out_message
= bt_message_stream_beginning_create(
1318 debug_it
->input_iterator
, out_stream
);
1320 BT_LOGE("Error creating output stream beginning message: "
1321 "out-s-addr=%p", out_stream
);
1328 bt_message
*handle_stream_end_message(struct debug_info_msg_iter
*debug_it
,
1329 const bt_message
*in_message
)
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
;
1336 in_stream
= bt_message_stream_end_borrow_stream_const(in_message
);
1337 BT_ASSERT(in_stream
);
1339 out_stream
= trace_ir_mapping_borrow_mapped_stream(
1340 debug_it
->ir_maps
, in_stream
);
1341 BT_ASSERT(out_stream
);
1343 /* Create an output stream end message. */
1344 out_message
= bt_message_stream_end_create(debug_it
->input_iterator
,
1347 BT_LOGE("Error creating output stream end message: out-s-addr=%p",
1351 /* Remove stream from trace mapping hashtable. */
1352 trace_ir_mapping_remove_mapped_stream(debug_it
->ir_maps
, in_stream
);
1358 bt_message
*handle_packet_begin_message(struct debug_info_msg_iter
*debug_it
,
1359 const bt_message
*in_message
)
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
;
1367 const bt_packet
*in_packet
=
1368 bt_message_packet_beginning_borrow_packet_const(in_message
);
1369 BT_ASSERT(in_packet
);
1371 /* This packet should not be already mapped. */
1372 BT_ASSERT(!trace_ir_mapping_borrow_mapped_packet(
1373 debug_it
->ir_maps
, in_packet
));
1375 out_packet
= trace_ir_mapping_create_new_mapped_packet(debug_it
->ir_maps
,
1378 BT_ASSERT(out_packet
);
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(
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
));
1394 out_message
= bt_message_packet_beginning_create(
1395 debug_it
->input_iterator
, out_packet
);
1398 BT_LOGE("Error creating output packet beginning message: "
1399 "out-p-addr=%p", out_packet
);
1406 bt_message
*handle_packet_end_message(struct debug_info_msg_iter
*debug_it
,
1407 const bt_message
*in_message
)
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
;
1416 in_packet
= bt_message_packet_end_borrow_packet_const(in_message
);
1417 BT_ASSERT(in_packet
);
1419 out_packet
= trace_ir_mapping_borrow_mapped_packet(debug_it
->ir_maps
, in_packet
);
1420 BT_ASSERT(out_packet
);
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(
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
));
1436 out_message
= bt_message_packet_end_create(
1437 debug_it
->input_iterator
, out_packet
);
1441 BT_LOGE("Error creating output packet end message: "
1442 "out-p-addr=%p", out_packet
);
1445 /* Remove packet from data mapping hashtable. */
1446 trace_ir_mapping_remove_mapped_packet(debug_it
->ir_maps
, in_packet
);
1452 bt_message
*handle_msg_iterator_inactivity(struct debug_info_msg_iter
*debug_it
,
1453 const bt_message
*in_message
)
1456 * This message type can be forwarded directly because it does
1457 * not refer to any objects in the trace class.
1459 bt_message_get_ref(in_message
);
1460 return (bt_message
*) in_message
;
1464 bt_message
*handle_stream_act_begin_message(struct debug_info_msg_iter
*debug_it
,
1465 const bt_message
*in_message
)
1467 const bt_clock_snapshot
*cs
;
1468 const bt_clock_class
*default_cc
;
1469 bt_message
*out_message
= NULL
;
1470 bt_stream
*out_stream
;
1472 bt_message_stream_activity_clock_snapshot_state cs_state
;
1473 bt_logging_level log_level
= debug_it
->log_level
;
1475 const bt_stream
*in_stream
=
1476 bt_message_stream_activity_beginning_borrow_stream_const(
1478 BT_ASSERT(in_stream
);
1480 out_stream
= trace_ir_mapping_borrow_mapped_stream(debug_it
->ir_maps
,
1482 BT_ASSERT(out_stream
);
1484 out_message
= bt_message_stream_activity_beginning_create(
1485 debug_it
->input_iterator
, out_stream
);
1487 BT_LOGE("Error creating output stream activity beginning "
1488 "message: out-s-addr=%p", out_stream
);
1492 default_cc
= bt_stream_class_borrow_default_clock_class_const(
1493 bt_stream_borrow_class_const(in_stream
));
1495 /* Borrow clock snapshot. */
1497 bt_message_stream_activity_beginning_borrow_default_clock_snapshot_const(
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
);
1505 bt_message_stream_activity_beginning_set_default_clock_snapshot_state(
1506 out_message
, cs_state
);
1515 bt_message
*handle_stream_act_end_message(struct debug_info_msg_iter
*debug_it
,
1516 const bt_message
*in_message
)
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
;
1524 bt_message_stream_activity_clock_snapshot_state cs_state
;
1525 bt_logging_level log_level
= debug_it
->log_level
;
1527 in_stream
= bt_message_stream_activity_end_borrow_stream_const(
1529 BT_ASSERT(in_stream
);
1531 out_stream
= trace_ir_mapping_borrow_mapped_stream(debug_it
->ir_maps
,
1533 BT_ASSERT(out_stream
);
1535 out_message
= bt_message_stream_activity_end_create(
1536 debug_it
->input_iterator
, out_stream
);
1538 BT_LOGE("Error creating output stream activity end message: "
1539 "out-s-addr=%p", out_stream
);
1543 default_cc
= bt_stream_class_borrow_default_clock_class_const(
1544 bt_stream_borrow_class_const(in_stream
));
1548 bt_message_stream_activity_end_borrow_default_clock_snapshot_const(
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
);
1556 bt_message_stream_activity_end_set_default_clock_snapshot_state(
1557 out_message
, cs_state
);
1566 bt_message
*handle_discarded_events_message(struct debug_info_msg_iter
*debug_it
,
1567 const bt_message
*in_message
)
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
;
1578 in_stream
= bt_message_discarded_events_borrow_stream_const(
1580 BT_ASSERT(in_stream
);
1582 out_stream
= trace_ir_mapping_borrow_mapped_stream(
1583 debug_it
->ir_maps
, in_stream
);
1584 BT_ASSERT(out_stream
);
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
) {
1591 bt_message_discarded_events_borrow_beginning_default_clock_snapshot_const(
1594 bt_message_discarded_events_borrow_end_default_clock_snapshot_const(
1597 begin_cs_value
= bt_clock_snapshot_get_value(begin_cs
);
1598 end_cs_value
= bt_clock_snapshot_get_value(end_cs
);
1601 bt_message_discarded_events_create_with_default_clock_snapshots(
1602 debug_it
->input_iterator
, out_stream
,
1603 begin_cs_value
, end_cs_value
);
1605 out_message
= bt_message_discarded_events_create(
1606 debug_it
->input_iterator
, out_stream
);
1609 BT_LOGE("Error creating output discarded events message: "
1610 "out-s-addr=%p", out_stream
);
1614 prop_avail
= bt_message_discarded_events_get_count(in_message
,
1617 if (prop_avail
== BT_PROPERTY_AVAILABILITY_NOT_AVAILABLE
) {
1618 bt_message_discarded_events_set_count(out_message
,
1627 bt_message
*handle_discarded_packets_message(struct debug_info_msg_iter
*debug_it
,
1628 const bt_message
*in_message
)
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
;
1639 in_stream
= bt_message_discarded_packets_borrow_stream_const(
1641 BT_ASSERT(in_stream
);
1643 out_stream
= trace_ir_mapping_borrow_mapped_stream(
1644 debug_it
->ir_maps
, in_stream
);
1645 BT_ASSERT(out_stream
);
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
) {
1652 bt_message_discarded_packets_borrow_beginning_default_clock_snapshot_const(
1656 bt_message_discarded_packets_borrow_end_default_clock_snapshot_const(
1659 begin_cs_value
= bt_clock_snapshot_get_value(begin_cs
);
1660 end_cs_value
= bt_clock_snapshot_get_value(end_cs
);
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
);
1666 out_message
= bt_message_discarded_packets_create(
1667 debug_it
->input_iterator
, out_stream
);
1670 BT_LOGE("Error creating output discarded packet message: "
1671 "out-s-addr=%p", out_stream
);
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
,
1687 const bt_message
*handle_message(struct debug_info_msg_iter
*debug_it
,
1688 const bt_message
*in_message
)
1690 bt_message
*out_message
= NULL
;
1692 switch (bt_message_get_type(in_message
)) {
1693 case BT_MESSAGE_TYPE_EVENT
:
1694 out_message
= handle_event_message(debug_it
,
1697 case BT_MESSAGE_TYPE_PACKET_BEGINNING
:
1698 out_message
= handle_packet_begin_message(debug_it
,
1701 case BT_MESSAGE_TYPE_PACKET_END
:
1702 out_message
= handle_packet_end_message(debug_it
,
1705 case BT_MESSAGE_TYPE_STREAM_BEGINNING
:
1706 out_message
= handle_stream_begin_message(debug_it
,
1709 case BT_MESSAGE_TYPE_STREAM_END
:
1710 out_message
= handle_stream_end_message(debug_it
,
1713 case BT_MESSAGE_TYPE_MESSAGE_ITERATOR_INACTIVITY
:
1714 out_message
= handle_msg_iterator_inactivity(debug_it
,
1717 case BT_MESSAGE_TYPE_STREAM_ACTIVITY_BEGINNING
:
1718 out_message
= handle_stream_act_begin_message(debug_it
,
1721 case BT_MESSAGE_TYPE_STREAM_ACTIVITY_END
:
1722 out_message
= handle_stream_act_end_message(debug_it
,
1725 case BT_MESSAGE_TYPE_DISCARDED_EVENTS
:
1726 out_message
= handle_discarded_events_message(debug_it
,
1729 case BT_MESSAGE_TYPE_DISCARDED_PACKETS
:
1730 out_message
= handle_discarded_packets_message(debug_it
,
1742 int init_from_params(struct debug_info_component
*debug_info_component
,
1743 const bt_value
*params
)
1745 const bt_value
*value
= NULL
;
1750 value
= bt_value_map_borrow_entry_value_const(params
,
1751 "debug-info-field-name");
1753 debug_info_component
->arg_debug_info_field_name
=
1754 g_strdup(bt_value_string_get(value
));
1756 debug_info_component
->arg_debug_info_field_name
=
1757 g_strdup(DEFAULT_DEBUG_INFO_FIELD_NAME
);
1760 value
= bt_value_map_borrow_entry_value_const(params
, "debug-info-dir");
1762 debug_info_component
->arg_debug_dir
=
1763 g_strdup(bt_value_string_get(value
));
1765 debug_info_component
->arg_debug_dir
= NULL
;
1769 value
= bt_value_map_borrow_entry_value_const(params
, "target-prefix");
1771 debug_info_component
->arg_target_prefix
=
1772 g_strdup(bt_value_string_get(value
));
1774 debug_info_component
->arg_target_prefix
= NULL
;
1777 value
= bt_value_map_borrow_entry_value_const(params
, "full-path");
1779 debug_info_component
->arg_full_path
= bt_value_bool_get(value
);
1781 debug_info_component
->arg_full_path
= BT_FALSE
;
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
)
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
)));
1799 BT_LOGI("Initializing debug_info component: "
1800 "comp-addr=%p, params-addr=%p", self_comp
, params
);
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.");
1808 debug_info_comp
->log_level
= log_level
;
1809 bt_self_component_set_data(
1810 bt_self_component_filter_as_self_component(self_comp
),
1813 status
= bt_self_component_filter_add_input_port(self_comp
, "in",
1815 if (status
!= BT_SELF_COMPONENT_STATUS_OK
) {
1819 status
= bt_self_component_filter_add_output_port(self_comp
, "out",
1821 if (status
!= BT_SELF_COMPONENT_STATUS_OK
) {
1825 ret
= init_from_params(debug_info_comp
, params
);
1827 BT_LOGE("Cannot configure debug_info component: "
1828 "debug_info-comp-addr=%p, params-addr=%p",
1829 debug_info_comp
, params
);
1836 destroy_debug_info_comp(debug_info_comp
);
1837 bt_self_component_set_data(
1838 bt_self_component_filter_as_self_component(self_comp
),
1841 if (status
== BT_SELF_COMPONENT_STATUS_OK
) {
1842 status
= BT_SELF_COMPONENT_STATUS_ERROR
;
1849 void debug_info_comp_finalize(bt_self_component_filter
*self_comp
)
1851 struct debug_info_component
*debug_info
=
1852 bt_self_component_get_data(
1853 bt_self_component_filter_as_self_component(
1855 bt_logging_level log_level
= debug_info
->log_level
;
1857 BT_LOGI("Finalizing debug_info self_component: comp-addr=%p",
1860 destroy_debug_info_comp(debug_info
);
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
,
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
;
1879 status
= BT_SELF_MESSAGE_ITERATOR_STATUS_OK
;
1881 self_comp
= bt_self_message_iterator_borrow_component(self_msg_iter
);
1882 BT_ASSERT(self_comp
);
1884 debug_info
= bt_self_component_get_data(self_comp
);
1885 BT_ASSERT(debug_info
);
1887 debug_info_msg_iter
= bt_self_message_iterator_get_data(self_msg_iter
);
1888 BT_ASSERT(debug_info_msg_iter
);
1890 upstream_iterator
= debug_info_msg_iter
->msg_iter
;
1891 BT_ASSERT(upstream_iterator
);
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
) {
1898 * No messages were returned. Not necessarily an error. Convert
1899 * the upstream message iterator status to a self status.
1901 status
= bt_common_message_iterator_status_to_self(
1902 upstream_iterator_ret_status
);
1907 * There should never be more received messages than the capacity we
1910 BT_ASSERT(*count
<= capacity
);
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
]);
1916 goto handle_msg_error
;
1919 msgs
[curr_msg_idx
] = out_message
;
1921 * Drop our reference of the input message as we are done with
1922 * it and created a output copy.
1924 bt_message_put_ref(input_msgs
[curr_msg_idx
]);
1931 * Drop references of all the output messages created before the
1934 for (i
= 0; i
< curr_msg_idx
; i
++) {
1935 bt_message_put_ref(msgs
[i
]);
1938 status
= BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM
;
1944 void debug_info_msg_iter_destroy(struct debug_info_msg_iter
*debug_info_msg_iter
)
1946 if (!debug_info_msg_iter
) {
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
);
1955 if (debug_info_msg_iter
->ir_maps
) {
1956 trace_ir_maps_destroy(debug_info_msg_iter
->ir_maps
);
1959 if (debug_info_msg_iter
->debug_info_map
) {
1960 g_hash_table_destroy(debug_info_msg_iter
->debug_info_map
);
1963 bt_fd_cache_fini(&debug_info_msg_iter
->fd_cache
);
1964 g_free(debug_info_msg_iter
);
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
)
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
;
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
)));
1986 /* Borrow the upstream input port. */
1987 input_port
= bt_self_component_filter_borrow_input_port_by_name(
1990 status
= BT_SELF_MESSAGE_ITERATOR_STATUS_ERROR
;
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
;
2000 debug_info_msg_iter
->log_level
= log_level
;
2002 /* Create an iterator on the upstream component. */
2003 upstream_iterator
= bt_self_component_port_input_message_iterator_create(
2005 if (!upstream_iterator
) {
2006 status
= BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM
;
2010 BT_SELF_COMPONENT_PORT_INPUT_MESSAGE_ITERATOR_MOVE_REF(
2011 debug_info_msg_iter
->msg_iter
, upstream_iterator
);
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
;
2022 debug_info_msg_iter
->self_comp
=
2023 bt_self_component_filter_as_self_component(self_comp
);
2025 debug_info_msg_iter
->debug_info_component
= bt_self_component_get_data(
2026 bt_self_component_filter_as_self_component(
2029 debug_info_field_name
=
2030 debug_info_msg_iter
->debug_info_component
->arg_debug_info_field_name
;
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
;
2040 ret
= bt_fd_cache_init(&debug_info_msg_iter
->fd_cache
, log_level
);
2042 status
= BT_SELF_MESSAGE_ITERATOR_STATUS_NOMEM
;
2046 bt_self_message_iterator_set_data(self_msg_iter
, debug_info_msg_iter
);
2047 debug_info_msg_iter
->input_iterator
= self_msg_iter
;
2052 debug_info_msg_iter_destroy(debug_info_msg_iter
);
2058 bt_bool
debug_info_msg_iter_can_seek_beginning(
2059 bt_self_message_iterator
*self_msg_iter
)
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
);
2065 return bt_self_component_port_input_message_iterator_can_seek_beginning(
2066 debug_info_msg_iter
->msg_iter
);
2070 bt_self_message_iterator_status
debug_info_msg_iter_seek_beginning(
2071 bt_self_message_iterator
*self_msg_iter
)
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
;
2077 BT_ASSERT(debug_info_msg_iter
);
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
) {
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
);
2090 return bt_common_message_iterator_status_to_self(status
);
2094 void debug_info_msg_iter_finalize(bt_self_message_iterator
*it
)
2096 struct debug_info_msg_iter
*debug_info_msg_iter
;
2098 debug_info_msg_iter
= bt_self_message_iterator_get_data(it
);
2099 BT_ASSERT(debug_info_msg_iter
);
2101 debug_info_msg_iter_destroy(debug_info_msg_iter
);