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>
9 * Permission is hereby granted, free of charge, to any person obtaining a copy
10 * of this software and associated documentation files (the "Software"), to deal
11 * in the Software without restriction, including without limitation the rights
12 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13 * copies of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
28 #define BT_LOG_TAG "PLUGIN-CTF-LTTNG-UTILS-DEBUG-INFO-FLT"
31 #include <babeltrace/assert-internal.h>
33 #include "debug-info.h"
38 struct proc_debug_info_sources
{
40 * Hash table: base address (pointer to uint64_t) to bin info; owned by
41 * proc_debug_info_sources.
43 GHashTable
*baddr_to_bin_info
;
46 * Hash table: IP (pointer to uint64_t) to (struct debug_info_source *);
47 * owned by proc_debug_info_sources.
49 GHashTable
*ip_to_debug_info_src
;
53 struct debug_info_component
*comp
;
56 * Hash table of VPIDs (pointer to int64_t) to
57 * (struct ctf_proc_debug_infos*); owned by debug_info.
59 GHashTable
*vpid_to_proc_dbg_info_src
;
60 GQuark q_statedump_bin_info
;
61 GQuark q_statedump_debug_link
;
62 GQuark q_statedump_build_id
;
63 GQuark q_statedump_start
;
70 int debug_info_init(struct debug_info
*info
)
72 info
->q_statedump_bin_info
= g_quark_from_string(
73 "lttng_ust_statedump:bin_info");
74 info
->q_statedump_debug_link
= g_quark_from_string(
75 "lttng_ust_statedump:debug_link)");
76 info
->q_statedump_build_id
= g_quark_from_string(
77 "lttng_ust_statedump:build_id");
78 info
->q_statedump_start
= g_quark_from_string(
79 "lttng_ust_statedump:start");
80 info
->q_dl_open
= g_quark_from_string("lttng_ust_dl:dlopen");
81 info
->q_lib_load
= g_quark_from_string("lttng_ust_lib:load");
82 info
->q_lib_unload
= g_quark_from_string("lttng_ust_lib:unload");
84 return bin_info_init();
88 void debug_info_source_destroy(struct debug_info_source
*debug_info_src
)
90 if (!debug_info_src
) {
94 free(debug_info_src
->func
);
95 free(debug_info_src
->src_path
);
96 free(debug_info_src
->bin_path
);
97 free(debug_info_src
->bin_loc
);
98 g_free(debug_info_src
);
102 struct debug_info_source
*debug_info_source_create_from_bin(struct bin_info
*bin
,
106 struct debug_info_source
*debug_info_src
= NULL
;
107 struct source_location
*src_loc
= NULL
;
109 debug_info_src
= g_new0(struct debug_info_source
, 1);
111 if (!debug_info_src
) {
115 /* Lookup function name */
116 ret
= bin_info_lookup_function_name(bin
, ip
, &debug_info_src
->func
);
121 /* Can't retrieve src_loc from ELF, or could not find binary, skip. */
122 if (!bin
->is_elf_only
|| !debug_info_src
->func
) {
123 /* Lookup source location */
124 ret
= bin_info_lookup_source_location(bin
, ip
, &src_loc
);
125 BT_LOGD("Failed to lookup source location: ret=%d", ret
);
129 debug_info_src
->line_no
= src_loc
->line_no
;
131 if (src_loc
->filename
) {
132 debug_info_src
->src_path
= strdup(src_loc
->filename
);
133 if (!debug_info_src
->src_path
) {
137 debug_info_src
->short_src_path
= get_filename_from_path(
138 debug_info_src
->src_path
);
141 source_location_destroy(src_loc
);
145 debug_info_src
->bin_path
= strdup(bin
->elf_path
);
146 if (!debug_info_src
->bin_path
) {
150 debug_info_src
->short_bin_path
= get_filename_from_path(
151 debug_info_src
->bin_path
);
153 ret
= bin_info_get_bin_loc(bin
, ip
, &(debug_info_src
->bin_loc
));
160 return debug_info_src
;
163 debug_info_source_destroy(debug_info_src
);
168 void proc_debug_info_sources_destroy(
169 struct proc_debug_info_sources
*proc_dbg_info_src
)
171 if (!proc_dbg_info_src
) {
175 if (proc_dbg_info_src
->baddr_to_bin_info
) {
176 g_hash_table_destroy(proc_dbg_info_src
->baddr_to_bin_info
);
179 if (proc_dbg_info_src
->ip_to_debug_info_src
) {
180 g_hash_table_destroy(proc_dbg_info_src
->ip_to_debug_info_src
);
183 g_free(proc_dbg_info_src
);
187 struct proc_debug_info_sources
*proc_debug_info_sources_create(void)
189 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
191 proc_dbg_info_src
= g_new0(struct proc_debug_info_sources
, 1);
192 if (!proc_dbg_info_src
) {
196 proc_dbg_info_src
->baddr_to_bin_info
= g_hash_table_new_full(
197 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
198 (GDestroyNotify
) bin_info_destroy
);
199 if (!proc_dbg_info_src
->baddr_to_bin_info
) {
203 proc_dbg_info_src
->ip_to_debug_info_src
= g_hash_table_new_full(
204 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
205 (GDestroyNotify
) debug_info_source_destroy
);
206 if (!proc_dbg_info_src
->ip_to_debug_info_src
) {
211 return proc_dbg_info_src
;
214 proc_debug_info_sources_destroy(proc_dbg_info_src
);
219 struct proc_debug_info_sources
*proc_debug_info_sources_ht_get_entry(
220 GHashTable
*ht
, int64_t vpid
)
222 gpointer key
= g_new0(int64_t, 1);
223 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
229 *((int64_t *) key
) = vpid
;
231 /* Exists? Return it */
232 proc_dbg_info_src
= g_hash_table_lookup(ht
, key
);
233 if (proc_dbg_info_src
) {
237 /* Otherwise, create and return it */
238 proc_dbg_info_src
= proc_debug_info_sources_create();
239 if (!proc_dbg_info_src
) {
243 g_hash_table_insert(ht
, key
, proc_dbg_info_src
);
244 /* Ownership passed to ht */
248 return proc_dbg_info_src
;
252 struct debug_info_source
*proc_debug_info_sources_get_entry(
253 struct proc_debug_info_sources
*proc_dbg_info_src
, uint64_t ip
)
255 struct debug_info_source
*debug_info_src
= NULL
;
256 gpointer key
= g_new0(uint64_t, 1);
258 gpointer baddr
, value
;
264 *((uint64_t *) key
) = ip
;
266 /* Look in IP to debug infos hash table first. */
267 debug_info_src
= g_hash_table_lookup(
268 proc_dbg_info_src
->ip_to_debug_info_src
,
270 if (debug_info_src
) {
274 /* Check in all bin_infos. */
275 g_hash_table_iter_init(&iter
, proc_dbg_info_src
->baddr_to_bin_info
);
277 while (g_hash_table_iter_next(&iter
, &baddr
, &value
))
279 struct bin_info
*bin
= value
;
281 if (!bin_info_has_address(value
, ip
)) {
286 * Found; add it to cache.
288 * FIXME: this should be bounded in size (and implement
289 * a caching policy), and entries should be prunned when
290 * libraries are unmapped.
292 debug_info_src
= debug_info_source_create_from_bin(bin
, ip
);
293 if (debug_info_src
) {
295 proc_dbg_info_src
->ip_to_debug_info_src
,
296 key
, debug_info_src
);
297 /* Ownership passed to ht. */
305 return debug_info_src
;
309 struct debug_info_source
*debug_info_query(struct debug_info
*debug_info
,
310 int64_t vpid
, uint64_t ip
)
312 struct debug_info_source
*dbg_info_src
= NULL
;
313 struct proc_debug_info_sources
*proc_dbg_info_src
;
315 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
316 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
317 if (!proc_dbg_info_src
) {
321 dbg_info_src
= proc_debug_info_sources_get_entry(proc_dbg_info_src
, ip
);
328 struct debug_info
*debug_info_create(struct debug_info_component
*comp
)
331 struct debug_info
*debug_info
;
333 debug_info
= g_new0(struct debug_info
, 1);
338 debug_info
->vpid_to_proc_dbg_info_src
= g_hash_table_new_full(
339 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
340 (GDestroyNotify
) proc_debug_info_sources_destroy
);
341 if (!debug_info
->vpid_to_proc_dbg_info_src
) {
345 debug_info
->comp
= comp
;
346 ret
= debug_info_init(debug_info
);
359 void debug_info_destroy(struct debug_info
*debug_info
)
365 if (debug_info
->vpid_to_proc_dbg_info_src
) {
366 g_hash_table_destroy(debug_info
->vpid_to_proc_dbg_info_src
);
375 void handle_statedump_build_id_event(FILE *err
, struct debug_info
*debug_info
,
376 const bt_event
*event
)
378 struct proc_debug_info_sources
*proc_dbg_info_src
;
379 struct bin_info
*bin
= NULL
;
383 uint64_t build_id_len
;
385 ret
= get_stream_event_context_int_field_value(err
,
386 event
, VPID_FIELD_NAME
, &vpid
);
391 ret
= get_payload_unsigned_int_field_value(err
,
392 event
, BADDR_FIELD_NAME
, &baddr
);
394 BT_LOGE_STR("Failed to get unsigned int value for "
395 VPID_FIELD_NAME
" field.");
399 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
400 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
401 if (!proc_dbg_info_src
) {
405 bin
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_bin_info
,
409 * The build_id event comes after the bin has been
410 * created. If it isn't found, just ignore this event.
415 ret
= get_payload_build_id_field_value(err
, event
, BUILD_ID_FIELD_NAME
,
416 &bin
->build_id
, &build_id_len
);
418 BT_LOGE_STR("Failed to get " BUILD_ID_FIELD_NAME
422 if (build_id_len
> SIZE_MAX
) {
423 bin
->build_id_len
= (size_t) build_id_len
;
427 * Reset the is_elf_only flag in case it had been set
428 * previously, because we might find separate debug info using
429 * the new build id information.
431 bin
->is_elf_only
= false;
434 // bin_info_set_build_id(bin, build_id, build_id_len);
441 void handle_statedump_debug_link_event(FILE *err
, struct debug_info
*debug_info
,
442 const bt_event
*event
)
444 struct proc_debug_info_sources
*proc_dbg_info_src
;
445 struct bin_info
*bin
= NULL
;
448 const char *filename
= NULL
;
453 ret
= get_stream_event_context_int_field_value(err
, event
,
454 VPID_FIELD_NAME
, &vpid
);
459 ret
= get_payload_unsigned_int_field_value(err
,
460 event
, BADDR_FIELD_NAME
, &baddr
);
462 BT_LOGE_STR("Failed to get unsigned int value for "
463 BADDR_FIELD_NAME
" field.");
468 ret
= get_payload_unsigned_int_field_value(err
, event
, CRC32_FIELD_NAME
,
471 BT_LOGE_STR("Failed to get unsigned int value for "
472 CRC32_FIELD_NAME
" field.");
476 crc32
= (uint32_t) tmp
;
478 ret
= get_payload_string_field_value(err
,
479 event
, FILENAME_FIELD_NAME
, &filename
);
481 BT_LOGE_STR("Failed to get string value for "
482 FILENAME_FIELD_NAME
" field.");
487 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
488 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
489 if (!proc_dbg_info_src
) {
493 bin
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_bin_info
,
497 * The debug_link event comes after the bin has been
498 * created. If it isn't found, just ignore this event.
503 bin_info_set_debug_link(bin
, filename
, crc32
);
510 void handle_bin_info_event(FILE *err
, struct debug_info
*debug_info
,
511 const bt_event
*event
, bool has_pic_field
)
513 struct proc_debug_info_sources
*proc_dbg_info_src
;
514 struct bin_info
*bin
;
515 uint64_t baddr
, memsz
;
522 ret
= get_payload_unsigned_int_field_value(err
,
523 event
, BADDR_FIELD_NAME
, &baddr
);
525 BT_LOGE_STR("Failed to get unsigned int value for "
526 BADDR_FIELD_NAME
" field.");
530 ret
= get_payload_unsigned_int_field_value(err
,
531 event
, MEMSZ_FIELD_NAME
, &memsz
);
533 BT_LOGE_STR("Failed to get unsigned int value for "
534 MEMSZ_FIELD_NAME
" field.");
539 * This field is not produced by the dlopen event emitted before
542 ret
= get_payload_string_field_value(err
,
543 event
, PATH_FIELD_NAME
, &path
);
551 ret
= get_payload_unsigned_int_field_value(err
,
552 event
, IS_PIC_FIELD_NAME
, &tmp
);
554 BT_LOGE_STR("Failed to get unsigned int value for "
555 IS_PIC_FIELD_NAME
" field.");
562 * dlopen has no is_pic field, because the shared
563 * object is always PIC.
568 ret
= get_stream_event_context_int_field_value(err
, event
,
569 VPID_FIELD_NAME
, &vpid
);
579 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
580 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
581 if (!proc_dbg_info_src
) {
585 key
= g_new0(uint64_t, 1);
590 *((uint64_t *) key
) = baddr
;
592 bin
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_bin_info
,
598 bin
= bin_info_create(path
, baddr
, memsz
, is_pic
,
599 debug_info
->comp
->arg_debug_dir
,
600 debug_info
->comp
->arg_target_prefix
);
605 g_hash_table_insert(proc_dbg_info_src
->baddr_to_bin_info
,
607 /* Ownership passed to ht. */
616 void handle_statedump_bin_info_event(FILE *err
, struct debug_info
*debug_info
,
617 const bt_event
*event
)
619 handle_bin_info_event(err
, debug_info
, event
, true);
623 void handle_lib_load_event(FILE *err
, struct debug_info
*debug_info
,
624 const bt_event
*event
)
626 handle_bin_info_event(err
, debug_info
, event
, false);
630 void handle_lib_unload_event(FILE *err
, struct debug_info
*debug_info
,
631 const bt_event
*event
)
633 struct proc_debug_info_sources
*proc_dbg_info_src
;
636 gpointer key_ptr
= NULL
;
639 ret
= get_payload_unsigned_int_field_value(err
,
640 event
, BADDR_FIELD_NAME
, &baddr
);
642 BT_LOGE_STR("Failed to get unsigned int value for "
643 BADDR_FIELD_NAME
" field.");
648 ret
= get_stream_event_context_int_field_value(err
, event
,
649 VPID_FIELD_NAME
, &vpid
);
654 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
655 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
656 if (!proc_dbg_info_src
) {
660 key_ptr
= (gpointer
) &baddr
;
661 (void) g_hash_table_remove(proc_dbg_info_src
->baddr_to_bin_info
,
668 void handle_statedump_start(FILE *err
, struct debug_info
*debug_info
,
669 const bt_event
*event
)
671 struct proc_debug_info_sources
*proc_dbg_info_src
;
675 ret
= get_stream_event_context_int_field_value(err
, event
,
676 VPID_FIELD_NAME
, &vpid
);
681 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
682 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
683 if (!proc_dbg_info_src
) {
687 g_hash_table_remove_all(proc_dbg_info_src
->baddr_to_bin_info
);
688 g_hash_table_remove_all(proc_dbg_info_src
->ip_to_debug_info_src
);
695 void debug_info_handle_event(FILE *err
, const bt_event
*event
,
696 struct debug_info
*debug_info
)
698 const bt_event_class
*event_class
;
699 const char *event_name
;
702 if (!debug_info
|| !event
) {
705 event_class
= bt_event_get_class(event
);
709 event_name
= bt_event_class_get_name(event_class
);
713 q_event_name
= g_quark_try_string(event_name
);
715 if (q_event_name
== debug_info
->q_statedump_bin_info
) {
717 handle_statedump_bin_info_event(err
, debug_info
, event
);
718 } else if (q_event_name
== debug_info
->q_dl_open
||
719 q_event_name
== debug_info
->q_lib_load
) {
721 * dl_open and lib_load events are both checked for since
722 * only dl_open was produced as of lttng-ust 2.8.
724 * lib_load, which is produced from lttng-ust 2.9+, is a lot
725 * more reliable since it will be emitted when other functions
726 * of the dlopen family are called (e.g. dlmopen) and when
727 * library are transitively loaded.
729 handle_lib_load_event(err
, debug_info
, event
);
730 } else if (q_event_name
== debug_info
->q_statedump_start
) {
731 /* Start state dump */
732 handle_statedump_start(err
, debug_info
, event
);
733 } else if (q_event_name
== debug_info
->q_statedump_debug_link
) {
734 /* Debug link info */
735 handle_statedump_debug_link_event(err
, debug_info
, event
);
736 } else if (q_event_name
== debug_info
->q_statedump_build_id
) {
738 handle_statedump_build_id_event(err
, debug_info
, event
);
739 } else if (q_event_name
== debug_info
-> q_lib_unload
) {
740 handle_lib_unload_event(err
, debug_info
, event
);
744 bt_event_class_put_ref(event_class
);