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/debuginfo.h>
33 #include <babeltrace/so-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 so info; owned by
40 * proc_debug_info_sources.
42 GHashTable
*baddr_to_so_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_soinfo
;
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_soinfo
= g_quark_from_string(
68 "lttng_ust_statedump:soinfo");
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 so_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 g_free(debug_info_src
);
94 struct debug_info_source
*debug_info_source_create_from_so(struct so_info
*so
,
98 struct debug_info_source
*debug_info_src
= NULL
;
99 struct source_location
*src_loc
= NULL
;
101 debug_info_src
= g_new0(struct debug_info_source
, 1);
103 if (!debug_info_src
) {
107 /* Lookup function name */
108 ret
= so_info_lookup_function_name(so
, ip
, &debug_info_src
->func
);
113 /* Can't retrieve src_loc from ELF only, skip it */
114 if (!so
->is_elf_only
) {
115 /* Lookup source location */
116 ret
= so_info_lookup_source_location(so
, ip
, &src_loc
);
123 debug_info_src
->line_no
= src_loc
->line_no
;
125 if (src_loc
->filename
) {
126 debug_info_src
->src_path
= strdup(src_loc
->filename
);
127 if (!debug_info_src
->src_path
) {
131 debug_info_src
->short_src_path
= get_filename_from_path(
132 debug_info_src
->src_path
);
135 source_location_destroy(src_loc
);
139 debug_info_src
->bin_path
= strdup(so
->elf_path
);
140 if (!debug_info_src
->bin_path
) {
144 debug_info_src
->short_bin_path
= get_filename_from_path(
145 debug_info_src
->bin_path
);
149 return debug_info_src
;
152 debug_info_source_destroy(debug_info_src
);
157 void proc_debug_info_sources_destroy(
158 struct proc_debug_info_sources
*proc_dbg_info_src
)
160 if (!proc_dbg_info_src
) {
164 if (proc_dbg_info_src
->baddr_to_so_info
) {
165 g_hash_table_destroy(proc_dbg_info_src
->baddr_to_so_info
);
168 if (proc_dbg_info_src
->ip_to_debug_info_src
) {
169 g_hash_table_destroy(proc_dbg_info_src
->ip_to_debug_info_src
);
172 g_free(proc_dbg_info_src
);
176 struct proc_debug_info_sources
*proc_debug_info_sources_create(void)
178 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
180 proc_dbg_info_src
= g_new0(struct proc_debug_info_sources
, 1);
181 if (!proc_dbg_info_src
) {
185 proc_dbg_info_src
->baddr_to_so_info
= g_hash_table_new_full(
186 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
187 (GDestroyNotify
) so_info_destroy
);
188 if (!proc_dbg_info_src
->baddr_to_so_info
) {
192 proc_dbg_info_src
->ip_to_debug_info_src
= g_hash_table_new_full(
193 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
194 (GDestroyNotify
) debug_info_source_destroy
);
195 if (!proc_dbg_info_src
->ip_to_debug_info_src
) {
200 return proc_dbg_info_src
;
203 proc_debug_info_sources_destroy(proc_dbg_info_src
);
208 struct proc_debug_info_sources
*proc_debug_info_sources_ht_get_entry(
209 GHashTable
*ht
, int64_t vpid
)
211 gpointer key
= g_new0(int64_t, 1);
212 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
218 *((int64_t *) key
) = vpid
;
220 /* Exists? Return it */
221 proc_dbg_info_src
= g_hash_table_lookup(ht
, key
);
222 if (proc_dbg_info_src
) {
226 /* Otherwise, create and return it */
227 proc_dbg_info_src
= proc_debug_info_sources_create();
228 if (!proc_dbg_info_src
) {
232 g_hash_table_insert(ht
, key
, proc_dbg_info_src
);
233 /* Ownership passed to ht */
237 return proc_dbg_info_src
;
241 struct debug_info_source
*proc_debug_info_sources_get_entry(
242 struct proc_debug_info_sources
*proc_dbg_info_src
, uint64_t ip
)
244 struct debug_info_source
*debug_info_src
= NULL
;
245 gpointer key
= g_new0(uint64_t, 1);
247 gpointer baddr
, value
;
253 *((uint64_t *) key
) = ip
;
255 /* Look in IP to debug infos hash table first. */
256 debug_info_src
= g_hash_table_lookup(
257 proc_dbg_info_src
->ip_to_debug_info_src
,
259 if (debug_info_src
) {
263 /* Check in all so_infos. */
264 g_hash_table_iter_init(&iter
, proc_dbg_info_src
->baddr_to_so_info
);
266 while (g_hash_table_iter_next(&iter
, &baddr
, &value
))
268 struct so_info
*so
= value
;
270 if (!so_info_has_address(value
, ip
)) {
275 * Found; add it to cache.
277 * FIXME: this should be bounded in size (and implement
278 * a caching policy), and entries should be prunned when
279 * libraries are unmapped.
281 debug_info_src
= debug_info_source_create_from_so(so
, ip
);
282 if (debug_info_src
) {
284 proc_dbg_info_src
->ip_to_debug_info_src
,
285 key
, debug_info_src
);
286 /* Ownership passed to ht. */
294 return debug_info_src
;
298 struct debug_info_source
*debug_info_query(struct debug_info
*debug_info
,
299 int64_t vpid
, uint64_t ip
)
301 struct debug_info_source
*dbg_info_src
= NULL
;
302 struct proc_debug_info_sources
*proc_dbg_info_src
;
304 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
305 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
306 if (!proc_dbg_info_src
) {
310 dbg_info_src
= proc_debug_info_sources_get_entry(
311 proc_dbg_info_src
, ip
);
321 struct debug_info
*debug_info_create(void)
324 struct debug_info
*debug_info
;
326 debug_info
= g_new0(struct debug_info
, 1);
331 debug_info
->vpid_to_proc_dbg_info_src
= g_hash_table_new_full(
332 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
333 (GDestroyNotify
) proc_debug_info_sources_destroy
);
334 if (!debug_info
->vpid_to_proc_dbg_info_src
) {
338 ret
= debug_info_init(debug_info
);
351 void debug_info_destroy(struct debug_info
*debug_info
)
357 if (debug_info
->vpid_to_proc_dbg_info_src
) {
358 g_hash_table_destroy(debug_info
->vpid_to_proc_dbg_info_src
);
367 void handle_statedump_build_id_event(struct debug_info
*debug_info
,
368 struct ctf_event_definition
*event_def
)
370 struct proc_debug_info_sources
*proc_dbg_info_src
;
371 struct bt_definition
*event_fields_def
= NULL
;
372 struct bt_definition
*sec_def
= NULL
;
373 struct bt_definition
*baddr_def
= NULL
;
374 struct bt_definition
*vpid_def
= NULL
;
375 struct bt_definition
*build_id_def
= NULL
;
376 struct definition_sequence
*build_id_seq
;
377 struct so_info
*so
= NULL
;
381 uint8_t *build_id
= NULL
;
382 uint64_t build_id_len
;
384 event_fields_def
= (struct bt_definition
*) event_def
->event_fields
;
385 sec_def
= (struct bt_definition
*)
386 event_def
->stream
->stream_event_context
;
388 if (!event_fields_def
|| !sec_def
) {
392 baddr_def
= bt_lookup_definition(event_fields_def
, "_baddr");
397 vpid_def
= bt_lookup_definition(sec_def
, "_vpid");
402 build_id_def
= bt_lookup_definition(event_fields_def
, "_build_id");
407 if (baddr_def
->declaration
->id
!= CTF_TYPE_INTEGER
) {
411 if (vpid_def
->declaration
->id
!= CTF_TYPE_INTEGER
) {
415 if (build_id_def
->declaration
->id
!= CTF_TYPE_SEQUENCE
) {
419 baddr
= bt_get_unsigned_int(baddr_def
);
420 vpid
= bt_get_signed_int(vpid_def
);
421 build_id_seq
= container_of(build_id_def
,
422 struct definition_sequence
, p
);
423 build_id_len
= build_id_seq
->length
->value
._unsigned
;
425 build_id
= g_malloc(build_id_len
);
430 for (i
= 0; i
< build_id_len
; ++i
) {
431 struct bt_definition
**field
;
433 field
= (struct bt_definition
**) &g_ptr_array_index(
434 build_id_seq
->elems
, i
);
435 build_id
[i
] = bt_get_unsigned_int(*field
);
438 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
439 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
440 if (!proc_dbg_info_src
) {
444 so
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_so_info
,
448 * The build_id event comes after the so has been
449 * created. If it isn't found, just ignore this event.
454 so_info_set_build_id(so
, build_id
, build_id_len
);
462 void handle_statedump_debug_link_event(struct debug_info
*debug_info
,
463 struct ctf_event_definition
*event_def
)
465 struct proc_debug_info_sources
*proc_dbg_info_src
;
466 struct bt_definition
*event_fields_def
= NULL
;
467 struct bt_definition
*sec_def
= NULL
;
468 struct bt_definition
*baddr_def
= NULL
;
469 struct bt_definition
*vpid_def
= NULL
;
470 struct bt_definition
*filename_def
= NULL
;
471 struct bt_definition
*crc32_def
= NULL
;
472 struct so_info
*so
= NULL
;
475 char *filename
= NULL
;
478 event_fields_def
= (struct bt_definition
*) event_def
->event_fields
;
479 sec_def
= (struct bt_definition
*)
480 event_def
->stream
->stream_event_context
;
482 if (!event_fields_def
|| !sec_def
) {
486 baddr_def
= bt_lookup_definition(event_fields_def
, "_baddr");
491 vpid_def
= bt_lookup_definition(sec_def
, "_vpid");
496 filename_def
= bt_lookup_definition(event_fields_def
, "_filename");
501 crc32_def
= bt_lookup_definition(event_fields_def
, "_crc32");
506 if (baddr_def
->declaration
->id
!= CTF_TYPE_INTEGER
) {
510 if (vpid_def
->declaration
->id
!= CTF_TYPE_INTEGER
) {
514 if (filename_def
->declaration
->id
!= CTF_TYPE_STRING
) {
518 if (crc32_def
->declaration
->id
!= CTF_TYPE_INTEGER
) {
522 baddr
= bt_get_unsigned_int(baddr_def
);
523 vpid
= bt_get_signed_int(vpid_def
);
525 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
526 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
527 if (!proc_dbg_info_src
) {
531 so
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_so_info
,
535 * The debug_link event comes after the so has been
536 * created. If it isn't found, just ignore this event.
541 filename
= bt_get_string(filename_def
);
542 crc32
= bt_get_unsigned_int(crc32_def
);
544 so_info_set_debug_link(so
, filename
, crc32
);
551 void handle_statedump_soinfo_event(struct debug_info
*debug_info
,
552 struct ctf_event_definition
*event_def
)
554 struct bt_definition
*baddr_def
= NULL
;
555 struct bt_definition
*memsz_def
= NULL
;
556 struct bt_definition
*sopath_def
= NULL
;
557 struct bt_definition
*vpid_def
= NULL
;
558 struct bt_definition
*event_fields_def
= NULL
;
559 struct bt_definition
*sec_def
= NULL
;
560 struct proc_debug_info_sources
*proc_dbg_info_src
;
562 uint64_t baddr
, memsz
;
567 event_fields_def
= (struct bt_definition
*) event_def
->event_fields
;
568 sec_def
= (struct bt_definition
*)
569 event_def
->stream
->stream_event_context
;
571 if (!event_fields_def
|| !sec_def
) {
575 baddr_def
= bt_lookup_definition(event_fields_def
, "_baddr");
580 memsz_def
= bt_lookup_definition(event_fields_def
, "_memsz");
585 sopath_def
= bt_lookup_definition(event_fields_def
, "_sopath");
590 vpid_def
= bt_lookup_definition(sec_def
, "_vpid");
595 if (baddr_def
->declaration
->id
!= CTF_TYPE_INTEGER
) {
599 if (memsz_def
->declaration
->id
!= CTF_TYPE_INTEGER
) {
603 if (sopath_def
->declaration
->id
!= CTF_TYPE_STRING
) {
607 if (vpid_def
->declaration
->id
!= CTF_TYPE_INTEGER
) {
611 baddr
= bt_get_unsigned_int(baddr_def
);
612 memsz
= bt_get_unsigned_int(memsz_def
);
613 sopath
= bt_get_string(sopath_def
);
614 vpid
= bt_get_signed_int(vpid_def
);
625 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
626 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
627 if (!proc_dbg_info_src
) {
631 key
= g_new0(uint64_t, 1);
636 *((uint64_t *) key
) = baddr
;
638 so
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_so_info
,
644 so
= so_info_create(sopath
, baddr
, memsz
);
649 g_hash_table_insert(proc_dbg_info_src
->baddr_to_so_info
,
651 /* Ownership passed to ht. */
660 void handle_statedump_start(struct debug_info
*debug_info
,
661 struct ctf_event_definition
*event_def
)
663 struct bt_definition
*vpid_def
= NULL
;
664 struct bt_definition
*sec_def
= NULL
;
665 struct proc_debug_info_sources
*proc_dbg_info_src
;
668 sec_def
= (struct bt_definition
*)
669 event_def
->stream
->stream_event_context
;
674 vpid_def
= bt_lookup_definition(sec_def
, "_vpid");
679 vpid
= bt_get_signed_int(vpid_def
);
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_so_info
);
688 g_hash_table_remove_all(proc_dbg_info_src
->ip_to_debug_info_src
);
695 void register_event_debug_infos(struct debug_info
*debug_info
,
696 struct ctf_event_definition
*event
)
698 struct bt_definition
*ip_def
, *vpid_def
;
701 struct bt_definition
*sec_def
;
703 /* Get stream event context definition. */
704 sec_def
= (struct bt_definition
*) event
->stream
->stream_event_context
;
709 /* Get "ip" and "vpid" definitions. */
710 vpid_def
= bt_lookup_definition((struct bt_definition
*) sec_def
,
712 ip_def
= bt_lookup_definition((struct bt_definition
*) sec_def
, "_ip");
714 if (!vpid_def
|| !ip_def
) {
718 vpid
= bt_get_signed_int(vpid_def
);
719 ip
= bt_get_unsigned_int(ip_def
);
721 /* Get debug info for this context. */
722 ((struct definition_integer
*) ip_def
)->debug_info_src
=
723 debug_info_query(debug_info
, vpid
, ip
);
730 void debug_info_handle_event(struct debug_info
*debug_info
,
731 struct ctf_event_definition
*event
)
733 struct ctf_event_declaration
*event_class
;
734 struct ctf_stream_declaration
*stream_class
;
736 if (!debug_info
|| !event
) {
740 stream_class
= event
->stream
->stream_class
;
741 event_class
= g_ptr_array_index(stream_class
->events_by_id
,
742 event
->stream
->event_id
);
744 if (event_class
->name
== debug_info
->q_statedump_soinfo
||
745 event_class
->name
== debug_info
->q_dl_open
) {
746 /* State dump/dlopen() */
747 handle_statedump_soinfo_event(debug_info
, event
);
748 } else if (event_class
->name
== debug_info
->q_statedump_start
) {
749 /* Start state dump */
750 handle_statedump_start(debug_info
, event
);
751 } else if (event_class
->name
== debug_info
->q_statedump_debug_link
) {
752 /* Debug link info */
753 handle_statedump_debug_link_event(debug_info
, event
);
754 } else if (event_class
->name
== debug_info
->q_statedump_build_id
) {
756 handle_statedump_build_id_event(debug_info
, event
);
758 /* Other events: register debug infos */
759 register_event_debug_infos(debug_info
, event
);