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>
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
29 #include <babeltrace/types.h>
30 #include <babeltrace/ctf-ir/metadata.h>
31 #include <babeltrace/debuginfo.h>
32 #include <babeltrace/so-info.h>
34 struct proc_debug_info_sources
{
36 * Hash table: base address to so info; owned by
37 * proc_debug_info_sources.
39 GHashTable
*baddr_to_so_info
;
42 * Hash table: IP to (struct debug_info_source *); owned by
43 * proc_debug_info_sources.
45 GHashTable
*ip_to_debug_info_src
;
50 * Hash table of VPIDs (int64_t) to (struct ctf_proc_debug_infos*);
51 * owned by debug_info.
53 GHashTable
*vpid_to_proc_dbg_info_src
;
54 GQuark q_statedump_soinfo
;
55 GQuark q_statedump_debug_link
;
56 GQuark q_statedump_build_id
;
57 GQuark q_statedump_start
;
62 int debug_info_init(struct debug_info
*info
)
64 info
->q_statedump_soinfo
= g_quark_from_string(
65 "lttng_ust_statedump:soinfo");
66 info
->q_statedump_debug_link
= g_quark_from_string(
67 "lttng_ust_statedump:debug_link)");
68 info
->q_statedump_build_id
= g_quark_from_string(
69 "lttng_ust_statedump:build_id");
70 info
->q_statedump_start
= g_quark_from_string(
71 "lttng_ust_statedump:start");
72 info
->q_dl_open
= g_quark_from_string("lttng_ust_dl:dlopen");
74 return so_info_init();
78 void debug_info_source_destroy(struct debug_info_source
*debug_info_src
)
80 if (!debug_info_src
) {
84 free(debug_info_src
->func
);
85 free(debug_info_src
->filename
);
86 g_free(debug_info_src
);
90 struct debug_info_source
*debug_info_source_create_from_so(struct so_info
*so
,
94 struct debug_info_source
*debug_info_src
= NULL
;
95 struct source_location
*src_loc
= NULL
;
97 debug_info_src
= g_new0(struct debug_info_source
, 1);
99 if (!debug_info_src
) {
103 /* Lookup function name */
104 ret
= so_info_lookup_function_name(so
, ip
, &debug_info_src
->func
);
109 /* Can't retrieve src_loc from ELF only, skip it */
110 if (so
->is_elf_only
) {
114 /* Lookup source location */
115 ret
= so_info_lookup_source_location(so
, ip
, &src_loc
);
121 debug_info_src
->line_no
= src_loc
->line_no
;
123 if (src_loc
->filename
) {
124 debug_info_src
->filename
= strdup(src_loc
->filename
);
126 if (!debug_info_src
->filename
) {
131 source_location_destroy(src_loc
);
135 return debug_info_src
;
138 debug_info_source_destroy(debug_info_src
);
143 void proc_debug_info_sources_destroy(
144 struct proc_debug_info_sources
*proc_dbg_info_src
)
146 if (!proc_dbg_info_src
) {
150 if (proc_dbg_info_src
->baddr_to_so_info
) {
151 g_hash_table_destroy(proc_dbg_info_src
->baddr_to_so_info
);
154 if (proc_dbg_info_src
->ip_to_debug_info_src
) {
155 g_hash_table_destroy(proc_dbg_info_src
->ip_to_debug_info_src
);
158 g_free(proc_dbg_info_src
);
162 struct proc_debug_info_sources
*proc_debug_info_sources_create(void)
164 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
166 proc_dbg_info_src
= g_new0(struct proc_debug_info_sources
, 1);
167 if (!proc_dbg_info_src
) {
171 proc_dbg_info_src
->baddr_to_so_info
= g_hash_table_new_full(
172 NULL
, NULL
, NULL
, (GDestroyNotify
) so_info_destroy
);
173 if (!proc_dbg_info_src
->baddr_to_so_info
) {
177 proc_dbg_info_src
->ip_to_debug_info_src
= g_hash_table_new_full(
179 (GDestroyNotify
) debug_info_source_destroy
);
180 if (!proc_dbg_info_src
->ip_to_debug_info_src
) {
185 return proc_dbg_info_src
;
188 proc_debug_info_sources_destroy(proc_dbg_info_src
);
193 struct proc_debug_info_sources
*proc_debug_info_sources_ht_get_entry(
194 GHashTable
*ht
, int64_t vpid
)
196 gpointer key
= (gpointer
) vpid
;
197 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
199 /* Exists? Return it */
200 proc_dbg_info_src
= g_hash_table_lookup(ht
, key
);
201 if (proc_dbg_info_src
) {
205 /* Otherwise, create and return it */
206 proc_dbg_info_src
= proc_debug_info_sources_create();
207 if (!proc_dbg_info_src
) {
211 g_hash_table_insert(ht
, key
, proc_dbg_info_src
);
213 return proc_dbg_info_src
;
217 struct debug_info_source
*proc_debug_info_sources_get_entry(
218 struct proc_debug_info_sources
*proc_dbg_info_src
, uint64_t ip
)
220 struct debug_info_source
*debug_info_src
= NULL
;
221 gint64 key
= (gint64
) ip
;
223 gpointer baddr
, value
;
225 /* Look in IP to debug infos hash table first. */
226 debug_info_src
= g_hash_table_lookup(
227 proc_dbg_info_src
->ip_to_debug_info_src
,
229 if (debug_info_src
) {
233 /* Check in all so_infos. */
234 g_hash_table_iter_init(&iter
, proc_dbg_info_src
->baddr_to_so_info
);
236 while (g_hash_table_iter_next(&iter
, &baddr
, &value
))
238 struct so_info
*so
= value
;
240 if (!so_info_has_address(value
, ip
)) {
244 /* Found; add it to cache. */
245 debug_info_src
= debug_info_source_create_from_so(so
, ip
);
246 if (debug_info_src
) {
248 proc_dbg_info_src
->ip_to_debug_info_src
,
249 (gpointer
) key
, debug_info_src
);
255 return debug_info_src
;
259 struct debug_info_source
*debug_info_query(struct debug_info
*debug_info
,
260 int64_t vpid
, uint64_t ip
)
262 struct debug_info_source
*dbg_info_src
= NULL
;
263 struct proc_debug_info_sources
*proc_dbg_info_src
;
265 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
266 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
267 if (!proc_dbg_info_src
) {
271 dbg_info_src
= proc_debug_info_sources_get_entry(
272 proc_dbg_info_src
, ip
);
282 struct debug_info
*debug_info_create(void)
285 struct debug_info
*debug_info
;
287 debug_info
= g_new0(struct debug_info
, 1);
292 debug_info
->vpid_to_proc_dbg_info_src
= g_hash_table_new_full(NULL
,
294 (GDestroyNotify
) proc_debug_info_sources_destroy
);
295 if (!debug_info
->vpid_to_proc_dbg_info_src
) {
299 ret
= debug_info_init(debug_info
);
312 void debug_info_destroy(struct debug_info
*debug_info
)
318 if (debug_info
->vpid_to_proc_dbg_info_src
) {
319 g_hash_table_destroy(debug_info
->vpid_to_proc_dbg_info_src
);
328 void handle_statedump_build_id_event(struct debug_info
*debug_info
,
329 struct ctf_event_definition
*event_def
)
331 struct proc_debug_info_sources
*proc_dbg_info_src
;
332 struct bt_definition
*event_fields_def
= NULL
;
333 struct bt_definition
*sec_def
= NULL
;
334 struct bt_definition
*baddr_def
= NULL
;
335 struct bt_definition
*vpid_def
= NULL
;
336 struct bt_definition
*build_id_def
= NULL
;
337 struct definition_sequence
*build_id_seq
;
338 struct so_info
*so
= NULL
;
342 uint8_t *build_id
= NULL
;
343 uint64_t build_id_len
;
345 event_fields_def
= (struct bt_definition
*) event_def
->event_fields
;
346 sec_def
= (struct bt_definition
*)
347 event_def
->stream
->stream_event_context
;
349 if (!event_fields_def
|| !sec_def
) {
353 baddr_def
= bt_lookup_definition(event_fields_def
, "_baddr");
358 vpid_def
= bt_lookup_definition(sec_def
, "_vpid");
363 build_id_def
= bt_lookup_definition(event_fields_def
, "_build_id");
368 if (baddr_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
372 if (vpid_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
376 if (build_id_def
->declaration
->id
!= BT_CTF_TYPE_ID_SEQUENCE
) {
380 baddr
= bt_get_unsigned_int(baddr_def
);
381 vpid
= bt_get_signed_int(vpid_def
);
382 build_id_seq
= container_of(build_id_def
,
383 struct definition_sequence
, p
);
384 build_id_len
= build_id_seq
->length
->value
._unsigned
;
386 build_id
= g_malloc(build_id_len
);
391 for (i
= 0; i
< build_id_len
; ++i
) {
392 struct bt_definition
**field
;
394 field
= (struct bt_definition
**) &g_ptr_array_index(
395 build_id_seq
->elems
, i
);
396 build_id
[i
] = bt_get_unsigned_int(*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 so
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_so_info
,
409 * The build_id event comes after the so has been
410 * created. If it isn't found, just ignore this event.
415 so_info_set_build_id(so
, build_id
, build_id_len
);
423 void handle_statedump_debug_link_event(struct debug_info
*debug_info
,
424 struct ctf_event_definition
*event_def
)
426 struct proc_debug_info_sources
*proc_dbg_info_src
;
427 struct bt_definition
*event_fields_def
= NULL
;
428 struct bt_definition
*sec_def
= NULL
;
429 struct bt_definition
*baddr_def
= NULL
;
430 struct bt_definition
*vpid_def
= NULL
;
431 struct bt_definition
*filename_def
= NULL
;
432 struct bt_definition
*crc32_def
= NULL
;
433 struct so_info
*so
= NULL
;
436 char *filename
= NULL
;
439 event_fields_def
= (struct bt_definition
*) event_def
->event_fields
;
440 sec_def
= (struct bt_definition
*)
441 event_def
->stream
->stream_event_context
;
443 if (!event_fields_def
|| !sec_def
) {
447 baddr_def
= bt_lookup_definition(event_fields_def
, "_baddr");
452 vpid_def
= bt_lookup_definition(sec_def
, "_vpid");
457 filename_def
= bt_lookup_definition(event_fields_def
, "_filename");
462 crc32_def
= bt_lookup_definition(event_fields_def
, "_crc32");
467 if (baddr_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
471 if (vpid_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
475 if (filename_def
->declaration
->id
!= BT_CTF_TYPE_ID_STRING
) {
479 if (crc32_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
483 baddr
= bt_get_unsigned_int(baddr_def
);
484 vpid
= bt_get_signed_int(vpid_def
);
486 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
487 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
488 if (!proc_dbg_info_src
) {
492 so
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_so_info
,
496 * The debug_link event comes after the so has been
497 * created. If it isn't found, just ignore this event.
502 filename
= bt_get_string(filename_def
);
503 crc32
= bt_get_unsigned_int(crc32_def
);
505 so_info_set_debug_link(so
, filename
, crc32
);
512 void handle_statedump_soinfo_event(struct debug_info
*debug_info
,
513 struct ctf_event_definition
*event_def
)
515 struct bt_definition
*baddr_def
= NULL
;
516 struct bt_definition
*memsz_def
= NULL
;
517 struct bt_definition
*sopath_def
= NULL
;
518 struct bt_definition
*vpid_def
= NULL
;
519 struct bt_definition
*event_fields_def
= NULL
;
520 struct bt_definition
*sec_def
= NULL
;
521 struct proc_debug_info_sources
*proc_dbg_info_src
;
523 uint64_t baddr
, memsz
;
527 event_fields_def
= (struct bt_definition
*) event_def
->event_fields
;
528 sec_def
= (struct bt_definition
*)
529 event_def
->stream
->stream_event_context
;
531 if (!event_fields_def
|| !sec_def
) {
535 baddr_def
= bt_lookup_definition(event_fields_def
, "_baddr");
540 memsz_def
= bt_lookup_definition(event_fields_def
, "_memsz");
545 sopath_def
= bt_lookup_definition(event_fields_def
, "_sopath");
550 vpid_def
= bt_lookup_definition(sec_def
, "_vpid");
555 if (baddr_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
559 if (memsz_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
563 if (sopath_def
->declaration
->id
!= BT_CTF_TYPE_ID_STRING
) {
567 if (vpid_def
->declaration
->id
!= BT_CTF_TYPE_ID_INTEGER
) {
571 baddr
= bt_get_unsigned_int(baddr_def
);
572 memsz
= bt_get_unsigned_int(memsz_def
);
573 sopath
= bt_get_string(sopath_def
);
574 vpid
= bt_get_signed_int(vpid_def
);
585 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
586 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
587 if (!proc_dbg_info_src
) {
591 so
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_so_info
,
597 so
= so_info_create(sopath
, baddr
, memsz
);
602 g_hash_table_insert(proc_dbg_info_src
->baddr_to_so_info
,
603 (gpointer
) baddr
, so
);
610 void handle_statedump_start(struct debug_info
*debug_info
,
611 struct ctf_event_definition
*event_def
)
613 struct bt_definition
*vpid_def
= NULL
;
614 struct bt_definition
*sec_def
= NULL
;
615 struct proc_debug_info_sources
*proc_dbg_info_src
;
618 sec_def
= (struct bt_definition
*)
619 event_def
->stream
->stream_event_context
;
624 vpid_def
= bt_lookup_definition(sec_def
, "_vpid");
629 vpid
= bt_get_signed_int(vpid_def
);
631 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
632 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
633 if (!proc_dbg_info_src
) {
637 g_hash_table_remove_all(proc_dbg_info_src
->baddr_to_so_info
);
638 g_hash_table_remove_all(proc_dbg_info_src
->ip_to_debug_info_src
);
645 void register_event_debug_infos(struct debug_info
*debug_info
,
646 struct ctf_event_definition
*event
)
648 struct bt_definition
*ip_def
, *vpid_def
;
651 struct bt_definition
*sec_def
;
653 /* Get stream event context definition. */
654 sec_def
= (struct bt_definition
*) event
->stream
->stream_event_context
;
659 /* Get "ip" and "vpid" definitions. */
660 vpid_def
= bt_lookup_definition((struct bt_definition
*) sec_def
,
662 ip_def
= bt_lookup_definition((struct bt_definition
*) sec_def
, "_ip");
664 if (!vpid_def
|| !ip_def
) {
668 vpid
= bt_get_signed_int(vpid_def
);
669 ip
= bt_get_unsigned_int(ip_def
);
671 /* Get debug info for this context. */
672 ((struct definition_integer
*) ip_def
)->debug_info_src
=
673 debug_info_query(debug_info
, vpid
, ip
);
680 void debug_info_handle_event(struct debug_info
*debug_info
,
681 struct ctf_event_definition
*event
)
683 struct ctf_event_declaration
*event_class
;
684 struct ctf_stream_declaration
*stream_class
;
686 if (!debug_info
|| !event
) {
690 stream_class
= event
->stream
->stream_class
;
691 event_class
= g_ptr_array_index(stream_class
->events_by_id
,
692 event
->stream
->event_id
);
694 if (event_class
->name
== debug_info
->q_statedump_soinfo
||
695 event_class
->name
== debug_info
->q_dl_open
) {
696 /* State dump/dlopen() */
697 handle_statedump_soinfo_event(debug_info
, event
);
698 } else if (event_class
->name
== debug_info
->q_statedump_start
) {
699 /* Start state dump */
700 handle_statedump_start(debug_info
, event
);
701 } else if (event_class
->name
== debug_info
->q_statedump_debug_link
) {
702 /* Debug link info */
703 handle_statedump_debug_link_event(debug_info
, event
);
704 } else if (event_class
->name
== debug_info
->q_statedump_build_id
) {
706 handle_statedump_build_id_event(debug_info
, event
);
708 /* Other events: register debug infos */
709 register_event_debug_infos(debug_info
, event
);