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
30 #include <babeltrace/types.h>
31 #include <babeltrace/ctf-ir/metadata.h>
32 #include <babeltrace/debug-info.h>
33 #include <babeltrace/bin-info.h>
34 #include <babeltrace/babeltrace-internal.h>
35 #include <babeltrace/utils.h>
37 struct proc_debug_info_sources
{
39 * Hash table: base address (pointer to uint64_t) to bin info; owned by
40 * proc_debug_info_sources.
42 GHashTable
*baddr_to_bin_info
;
45 * Hash table: IP (pointer to uint64_t) to (struct debug_info_source *);
46 * owned by proc_debug_info_sources.
48 GHashTable
*ip_to_debug_info_src
;
53 * Hash table of VPIDs (pointer to int64_t) to
54 * (struct ctf_proc_debug_infos*); owned by debug_info.
56 GHashTable
*vpid_to_proc_dbg_info_src
;
57 GQuark q_statedump_bin_info
;
58 GQuark q_statedump_debug_link
;
59 GQuark q_statedump_build_id
;
60 GQuark q_statedump_start
;
65 int debug_info_init(struct debug_info
*info
)
67 info
->q_statedump_bin_info
= g_quark_from_string(
68 "lttng_ust_statedump:bin_info");
69 info
->q_statedump_debug_link
= g_quark_from_string(
70 "lttng_ust_statedump:debug_link)");
71 info
->q_statedump_build_id
= g_quark_from_string(
72 "lttng_ust_statedump:build_id");
73 info
->q_statedump_start
= g_quark_from_string(
74 "lttng_ust_statedump:start");
75 info
->q_dl_open
= g_quark_from_string("lttng_ust_dl:dlopen");
77 return bin_info_init();
81 void debug_info_source_destroy(struct debug_info_source
*debug_info_src
)
83 if (!debug_info_src
) {
87 free(debug_info_src
->func
);
88 free(debug_info_src
->src_path
);
89 free(debug_info_src
->bin_path
);
90 free(debug_info_src
->bin_loc
);
91 g_free(debug_info_src
);
95 struct debug_info_source
*debug_info_source_create_from_bin(struct bin_info
*bin
,
99 struct debug_info_source
*debug_info_src
= NULL
;
100 struct source_location
*src_loc
= NULL
;
102 debug_info_src
= g_new0(struct debug_info_source
, 1);
104 if (!debug_info_src
) {
108 /* Lookup function name */
109 ret
= bin_info_lookup_function_name(bin
, ip
, &debug_info_src
->func
);
114 /* Can't retrieve src_loc from ELF, or could not find binary, skip. */
115 if (!bin
->is_elf_only
|| !debug_info_src
->func
) {
116 /* Lookup source location */
117 ret
= bin_info_lookup_source_location(bin
, ip
, &src_loc
);
118 printf_verbose("Failed to lookup source location (err: %i)\n", ret
);
122 debug_info_src
->line_no
= src_loc
->line_no
;
124 if (src_loc
->filename
) {
125 debug_info_src
->src_path
= strdup(src_loc
->filename
);
126 if (!debug_info_src
->src_path
) {
130 debug_info_src
->short_src_path
= get_filename_from_path(
131 debug_info_src
->src_path
);
134 source_location_destroy(src_loc
);
138 debug_info_src
->bin_path
= strdup(bin
->elf_path
);
139 if (!debug_info_src
->bin_path
) {
143 debug_info_src
->short_bin_path
= get_filename_from_path(
144 debug_info_src
->bin_path
);
146 ret
= bin_info_get_bin_loc(bin
, ip
, &(debug_info_src
->bin_loc
));
153 return debug_info_src
;
156 debug_info_source_destroy(debug_info_src
);
161 void proc_debug_info_sources_destroy(
162 struct proc_debug_info_sources
*proc_dbg_info_src
)
164 if (!proc_dbg_info_src
) {
168 if (proc_dbg_info_src
->baddr_to_bin_info
) {
169 g_hash_table_destroy(proc_dbg_info_src
->baddr_to_bin_info
);
172 if (proc_dbg_info_src
->ip_to_debug_info_src
) {
173 g_hash_table_destroy(proc_dbg_info_src
->ip_to_debug_info_src
);
176 g_free(proc_dbg_info_src
);
180 struct proc_debug_info_sources
*proc_debug_info_sources_create(void)
182 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
184 proc_dbg_info_src
= g_new0(struct proc_debug_info_sources
, 1);
185 if (!proc_dbg_info_src
) {
189 proc_dbg_info_src
->baddr_to_bin_info
= g_hash_table_new_full(
190 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
191 (GDestroyNotify
) bin_info_destroy
);
192 if (!proc_dbg_info_src
->baddr_to_bin_info
) {
196 proc_dbg_info_src
->ip_to_debug_info_src
= g_hash_table_new_full(
197 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
198 (GDestroyNotify
) debug_info_source_destroy
);
199 if (!proc_dbg_info_src
->ip_to_debug_info_src
) {
204 return proc_dbg_info_src
;
207 proc_debug_info_sources_destroy(proc_dbg_info_src
);
212 struct proc_debug_info_sources
*proc_debug_info_sources_ht_get_entry(
213 GHashTable
*ht
, int64_t vpid
)
215 gpointer key
= g_new0(int64_t, 1);
216 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
222 *((int64_t *) key
) = vpid
;
224 /* Exists? Return it */
225 proc_dbg_info_src
= g_hash_table_lookup(ht
, key
);
226 if (proc_dbg_info_src
) {
230 /* Otherwise, create and return it */
231 proc_dbg_info_src
= proc_debug_info_sources_create();
232 if (!proc_dbg_info_src
) {
236 g_hash_table_insert(ht
, key
, proc_dbg_info_src
);
237 /* Ownership passed to ht */
241 return proc_dbg_info_src
;
245 struct debug_info_source
*proc_debug_info_sources_get_entry(
246 struct proc_debug_info_sources
*proc_dbg_info_src
, uint64_t ip
)
248 struct debug_info_source
*debug_info_src
= NULL
;
249 gpointer key
= g_new0(uint64_t, 1);
251 gpointer baddr
, value
;
257 *((uint64_t *) key
) = ip
;
259 /* Look in IP to debug infos hash table first. */
260 debug_info_src
= g_hash_table_lookup(
261 proc_dbg_info_src
->ip_to_debug_info_src
,
263 if (debug_info_src
) {
267 /* Check in all bin_infos. */
268 g_hash_table_iter_init(&iter
, proc_dbg_info_src
->baddr_to_bin_info
);
270 while (g_hash_table_iter_next(&iter
, &baddr
, &value
))
272 struct bin_info
*bin
= value
;
274 if (!bin_info_has_address(value
, ip
)) {
279 * Found; add it to cache.
281 * FIXME: this should be bounded in size (and implement
282 * a caching policy), and entries should be prunned when
283 * libraries are unmapped.
285 debug_info_src
= debug_info_source_create_from_bin(bin
, ip
);
286 if (debug_info_src
) {
288 proc_dbg_info_src
->ip_to_debug_info_src
,
289 key
, debug_info_src
);
290 /* Ownership passed to ht. */
298 return debug_info_src
;
302 struct debug_info_source
*debug_info_query(struct debug_info
*debug_info
,
303 int64_t vpid
, uint64_t ip
)
305 struct debug_info_source
*dbg_info_src
= NULL
;
306 struct proc_debug_info_sources
*proc_dbg_info_src
;
308 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
309 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
310 if (!proc_dbg_info_src
) {
314 dbg_info_src
= proc_debug_info_sources_get_entry(
315 proc_dbg_info_src
, ip
);
325 struct debug_info
*debug_info_create(void)
328 struct debug_info
*debug_info
;
330 debug_info
= g_new0(struct debug_info
, 1);
335 debug_info
->vpid_to_proc_dbg_info_src
= g_hash_table_new_full(
336 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
337 (GDestroyNotify
) proc_debug_info_sources_destroy
);
338 if (!debug_info
->vpid_to_proc_dbg_info_src
) {
342 ret
= debug_info_init(debug_info
);
355 void debug_info_destroy(struct debug_info
*debug_info
)
361 if (debug_info
->vpid_to_proc_dbg_info_src
) {
362 g_hash_table_destroy(debug_info
->vpid_to_proc_dbg_info_src
);
371 void handle_statedump_build_id_event(struct debug_info
*debug_info
,
372 struct ctf_event_definition
*event_def
)
374 struct proc_debug_info_sources
*proc_dbg_info_src
;
375 struct bt_definition
*event_fields_def
= NULL
;
376 struct bt_definition
*sec_def
= NULL
;
377 struct bt_definition
*baddr_def
= NULL
;
378 struct bt_definition
*vpid_def
= NULL
;
379 struct bt_definition
*build_id_def
= NULL
;
380 struct definition_sequence
*build_id_seq
;
381 struct bin_info
*bin
= NULL
;
385 uint8_t *build_id
= NULL
;
386 uint64_t build_id_len
;
388 event_fields_def
= (struct bt_definition
*) event_def
->event_fields
;
389 sec_def
= (struct bt_definition
*)
390 event_def
->stream
->stream_event_context
;
392 if (!event_fields_def
|| !sec_def
) {
396 baddr_def
= bt_lookup_definition(event_fields_def
, "_baddr");
401 vpid_def
= bt_lookup_definition(sec_def
, "_vpid");
406 build_id_def
= bt_lookup_definition(event_fields_def
, "_build_id");
411 if (baddr_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
415 if (vpid_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
419 if (build_id_def
->declaration
->id
!= BT_CTF_TYPE_ID_SEQUENCE
) {
423 baddr
= bt_get_unsigned_int(baddr_def
);
424 vpid
= bt_get_signed_int(vpid_def
);
425 build_id_seq
= container_of(build_id_def
,
426 struct definition_sequence
, p
);
427 build_id_len
= build_id_seq
->length
->value
._unsigned
;
429 build_id
= g_malloc(build_id_len
);
434 for (i
= 0; i
< build_id_len
; ++i
) {
435 struct bt_definition
**field
;
437 field
= (struct bt_definition
**) &g_ptr_array_index(
438 build_id_seq
->elems
, i
);
439 build_id
[i
] = bt_get_unsigned_int(*field
);
442 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
443 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
444 if (!proc_dbg_info_src
) {
448 bin
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_bin_info
,
452 * The build_id event comes after the bin has been
453 * created. If it isn't found, just ignore this event.
458 bin_info_set_build_id(bin
, build_id
, build_id_len
);
466 void handle_statedump_debug_link_event(struct debug_info
*debug_info
,
467 struct ctf_event_definition
*event_def
)
469 struct proc_debug_info_sources
*proc_dbg_info_src
;
470 struct bt_definition
*event_fields_def
= NULL
;
471 struct bt_definition
*sec_def
= NULL
;
472 struct bt_definition
*baddr_def
= NULL
;
473 struct bt_definition
*vpid_def
= NULL
;
474 struct bt_definition
*filename_def
= NULL
;
475 struct bt_definition
*crc32_def
= NULL
;
476 struct bin_info
*bin
= NULL
;
479 char *filename
= NULL
;
482 event_fields_def
= (struct bt_definition
*) event_def
->event_fields
;
483 sec_def
= (struct bt_definition
*)
484 event_def
->stream
->stream_event_context
;
486 if (!event_fields_def
|| !sec_def
) {
490 baddr_def
= bt_lookup_definition(event_fields_def
, "_baddr");
495 vpid_def
= bt_lookup_definition(sec_def
, "_vpid");
500 filename_def
= bt_lookup_definition(event_fields_def
, "_filename");
505 crc32_def
= bt_lookup_definition(event_fields_def
, "_crc32");
510 if (baddr_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
514 if (vpid_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
518 if (filename_def
->declaration
->id
!= BT_CTF_TYPE_ID_STRING
) {
522 if (crc32_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
526 baddr
= bt_get_unsigned_int(baddr_def
);
527 vpid
= bt_get_signed_int(vpid_def
);
529 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
530 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
531 if (!proc_dbg_info_src
) {
535 bin
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_bin_info
,
539 * The debug_link event comes after the bin has been
540 * created. If it isn't found, just ignore this event.
545 filename
= bt_get_string(filename_def
);
546 crc32
= bt_get_unsigned_int(crc32_def
);
548 bin_info_set_debug_link(bin
, filename
, crc32
);
555 void handle_bin_info_event(struct debug_info
*debug_info
,
556 struct ctf_event_definition
*event_def
, bool has_pic_field
)
558 struct bt_definition
*baddr_def
= NULL
;
559 struct bt_definition
*memsz_def
= NULL
;
560 struct bt_definition
*path_def
= NULL
;
561 struct bt_definition
*is_pic_def
= NULL
;
562 struct bt_definition
*vpid_def
= NULL
;
563 struct bt_definition
*event_fields_def
= NULL
;
564 struct bt_definition
*sec_def
= NULL
;
565 struct proc_debug_info_sources
*proc_dbg_info_src
;
566 struct bin_info
*bin
;
567 uint64_t baddr
, memsz
;
573 event_fields_def
= (struct bt_definition
*) event_def
->event_fields
;
574 sec_def
= (struct bt_definition
*)
575 event_def
->stream
->stream_event_context
;
577 if (!event_fields_def
|| !sec_def
) {
581 baddr_def
= bt_lookup_definition(event_fields_def
, "_baddr");
586 memsz_def
= bt_lookup_definition(event_fields_def
, "_memsz");
591 path_def
= bt_lookup_definition(event_fields_def
, "_path");
597 is_pic_def
= bt_lookup_definition(event_fields_def
, "_is_pic");
602 if (is_pic_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
606 is_pic
= (bt_get_unsigned_int(is_pic_def
) == 1);
609 * dlopen has no is_pic field, because the shared
610 * object is always PIC.
615 vpid_def
= bt_lookup_definition(sec_def
, "_vpid");
620 if (baddr_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
624 if (memsz_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
628 if (path_def
->declaration
->id
!= BT_CTF_TYPE_ID_STRING
) {
632 if (vpid_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
636 baddr
= bt_get_unsigned_int(baddr_def
);
637 memsz
= bt_get_unsigned_int(memsz_def
);
638 path
= bt_get_string(path_def
);
639 vpid
= bt_get_signed_int(vpid_def
);
650 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
651 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
652 if (!proc_dbg_info_src
) {
656 key
= g_new0(uint64_t, 1);
661 *((uint64_t *) key
) = baddr
;
663 bin
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_bin_info
,
669 bin
= bin_info_create(path
, baddr
, memsz
, is_pic
);
674 g_hash_table_insert(proc_dbg_info_src
->baddr_to_bin_info
,
676 /* Ownership passed to ht. */
685 void handle_statedump_bin_info_event(struct debug_info
*debug_info
,
686 struct ctf_event_definition
*event_def
)
688 handle_bin_info_event(debug_info
, event_def
, true);
692 void handle_dlopen_event(struct debug_info
*debug_info
,
693 struct ctf_event_definition
*event_def
)
695 handle_bin_info_event(debug_info
, event_def
, false);
700 void handle_statedump_start(struct debug_info
*debug_info
,
701 struct ctf_event_definition
*event_def
)
703 struct bt_definition
*vpid_def
= NULL
;
704 struct bt_definition
*sec_def
= NULL
;
705 struct proc_debug_info_sources
*proc_dbg_info_src
;
708 sec_def
= (struct bt_definition
*)
709 event_def
->stream
->stream_event_context
;
714 vpid_def
= bt_lookup_definition(sec_def
, "_vpid");
719 vpid
= bt_get_signed_int(vpid_def
);
721 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
722 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
723 if (!proc_dbg_info_src
) {
727 g_hash_table_remove_all(proc_dbg_info_src
->baddr_to_bin_info
);
728 g_hash_table_remove_all(proc_dbg_info_src
->ip_to_debug_info_src
);
735 void register_event_debug_infos(struct debug_info
*debug_info
,
736 struct ctf_event_definition
*event
)
738 struct bt_definition
*ip_def
, *vpid_def
;
741 struct bt_definition
*sec_def
;
743 /* Get stream event context definition. */
744 sec_def
= (struct bt_definition
*) event
->stream
->stream_event_context
;
749 /* Get "ip" and "vpid" definitions. */
750 vpid_def
= bt_lookup_definition((struct bt_definition
*) sec_def
,
752 ip_def
= bt_lookup_definition((struct bt_definition
*) sec_def
, "_ip");
754 if (!vpid_def
|| !ip_def
) {
758 vpid
= bt_get_signed_int(vpid_def
);
759 ip
= bt_get_unsigned_int(ip_def
);
761 /* Get debug info for this context. */
762 ((struct definition_integer
*) ip_def
)->debug_info_src
=
763 debug_info_query(debug_info
, vpid
, ip
);
770 void debug_info_handle_event(struct debug_info
*debug_info
,
771 struct ctf_event_definition
*event
)
773 struct ctf_event_declaration
*event_class
;
774 struct ctf_stream_declaration
*stream_class
;
776 if (!debug_info
|| !event
) {
780 stream_class
= event
->stream
->stream_class
;
781 event_class
= g_ptr_array_index(stream_class
->events_by_id
,
782 event
->stream
->event_id
);
784 if (event_class
->name
== debug_info
->q_statedump_bin_info
) {
786 handle_statedump_bin_info_event(debug_info
, event
);
787 } else if (event_class
->name
== debug_info
->q_dl_open
) {
788 handle_dlopen_event(debug_info
, event
);
789 } else if (event_class
->name
== debug_info
->q_statedump_start
) {
790 /* Start state dump */
791 handle_statedump_start(debug_info
, event
);
792 } else if (event_class
->name
== debug_info
->q_statedump_debug_link
) {
793 /* Debug link info */
794 handle_statedump_debug_link_event(debug_info
, event
);
795 } else if (event_class
->name
== debug_info
->q_statedump_build_id
) {
797 handle_statedump_build_id_event(debug_info
, event
);
799 /* Other events: register debug infos */
800 register_event_debug_infos(debug_info
, event
);