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 "debug-info.h"
35 struct proc_debug_info_sources
{
37 * Hash table: base address (pointer to uint64_t) to bin info; owned by
38 * proc_debug_info_sources.
40 GHashTable
*baddr_to_bin_info
;
43 * Hash table: IP (pointer to uint64_t) to (struct debug_info_source *);
44 * owned by proc_debug_info_sources.
46 GHashTable
*ip_to_debug_info_src
;
50 struct debug_info_component
*comp
;
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
;
67 int debug_info_init(struct debug_info
*info
)
69 info
->q_statedump_bin_info
= g_quark_from_string(
70 "lttng_ust_statedump:bin_info");
71 info
->q_statedump_debug_link
= g_quark_from_string(
72 "lttng_ust_statedump:debug_link)");
73 info
->q_statedump_build_id
= g_quark_from_string(
74 "lttng_ust_statedump:build_id");
75 info
->q_statedump_start
= g_quark_from_string(
76 "lttng_ust_statedump:start");
77 info
->q_dl_open
= g_quark_from_string("lttng_ust_dl:dlopen");
78 info
->q_lib_load
= g_quark_from_string("lttng_ust_lib:load");
79 info
->q_lib_unload
= g_quark_from_string("lttng_ust_lib:unload");
81 return bin_info_init();
85 void debug_info_source_destroy(struct debug_info_source
*debug_info_src
)
87 if (!debug_info_src
) {
91 free(debug_info_src
->func
);
92 free(debug_info_src
->src_path
);
93 free(debug_info_src
->bin_path
);
94 free(debug_info_src
->bin_loc
);
95 g_free(debug_info_src
);
99 struct debug_info_source
*debug_info_source_create_from_bin(struct bin_info
*bin
,
103 struct debug_info_source
*debug_info_src
= NULL
;
104 struct source_location
*src_loc
= NULL
;
106 debug_info_src
= g_new0(struct debug_info_source
, 1);
108 if (!debug_info_src
) {
112 /* Lookup function name */
113 ret
= bin_info_lookup_function_name(bin
, ip
, &debug_info_src
->func
);
118 /* Can't retrieve src_loc from ELF, or could not find binary, skip. */
119 if (!bin
->is_elf_only
|| !debug_info_src
->func
) {
120 /* Lookup source location */
121 ret
= bin_info_lookup_source_location(bin
, ip
, &src_loc
);
122 printf_verbose("Failed to lookup source location (err: %i)\n", ret
);
126 debug_info_src
->line_no
= src_loc
->line_no
;
128 if (src_loc
->filename
) {
129 debug_info_src
->src_path
= strdup(src_loc
->filename
);
130 if (!debug_info_src
->src_path
) {
134 debug_info_src
->short_src_path
= get_filename_from_path(
135 debug_info_src
->src_path
);
138 source_location_destroy(src_loc
);
142 debug_info_src
->bin_path
= strdup(bin
->elf_path
);
143 if (!debug_info_src
->bin_path
) {
147 debug_info_src
->short_bin_path
= get_filename_from_path(
148 debug_info_src
->bin_path
);
150 ret
= bin_info_get_bin_loc(bin
, ip
, &(debug_info_src
->bin_loc
));
157 return debug_info_src
;
160 debug_info_source_destroy(debug_info_src
);
165 void proc_debug_info_sources_destroy(
166 struct proc_debug_info_sources
*proc_dbg_info_src
)
168 if (!proc_dbg_info_src
) {
172 if (proc_dbg_info_src
->baddr_to_bin_info
) {
173 g_hash_table_destroy(proc_dbg_info_src
->baddr_to_bin_info
);
176 if (proc_dbg_info_src
->ip_to_debug_info_src
) {
177 g_hash_table_destroy(proc_dbg_info_src
->ip_to_debug_info_src
);
180 g_free(proc_dbg_info_src
);
184 struct proc_debug_info_sources
*proc_debug_info_sources_create(void)
186 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
188 proc_dbg_info_src
= g_new0(struct proc_debug_info_sources
, 1);
189 if (!proc_dbg_info_src
) {
193 proc_dbg_info_src
->baddr_to_bin_info
= g_hash_table_new_full(
194 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
195 (GDestroyNotify
) bin_info_destroy
);
196 if (!proc_dbg_info_src
->baddr_to_bin_info
) {
200 proc_dbg_info_src
->ip_to_debug_info_src
= g_hash_table_new_full(
201 g_int64_hash
, g_int64_equal
, (GDestroyNotify
) g_free
,
202 (GDestroyNotify
) debug_info_source_destroy
);
203 if (!proc_dbg_info_src
->ip_to_debug_info_src
) {
208 return proc_dbg_info_src
;
211 proc_debug_info_sources_destroy(proc_dbg_info_src
);
216 struct proc_debug_info_sources
*proc_debug_info_sources_ht_get_entry(
217 GHashTable
*ht
, int64_t vpid
)
219 gpointer key
= g_new0(int64_t, 1);
220 struct proc_debug_info_sources
*proc_dbg_info_src
= NULL
;
226 *((int64_t *) key
) = vpid
;
228 /* Exists? Return it */
229 proc_dbg_info_src
= g_hash_table_lookup(ht
, key
);
230 if (proc_dbg_info_src
) {
234 /* Otherwise, create and return it */
235 proc_dbg_info_src
= proc_debug_info_sources_create();
236 if (!proc_dbg_info_src
) {
240 g_hash_table_insert(ht
, key
, proc_dbg_info_src
);
241 /* Ownership passed to ht */
245 return proc_dbg_info_src
;
249 struct debug_info_source
*proc_debug_info_sources_get_entry(
250 struct proc_debug_info_sources
*proc_dbg_info_src
, uint64_t ip
)
252 struct debug_info_source
*debug_info_src
= NULL
;
253 gpointer key
= g_new0(uint64_t, 1);
255 gpointer baddr
, value
;
261 *((uint64_t *) key
) = ip
;
263 /* Look in IP to debug infos hash table first. */
264 debug_info_src
= g_hash_table_lookup(
265 proc_dbg_info_src
->ip_to_debug_info_src
,
267 if (debug_info_src
) {
271 /* Check in all bin_infos. */
272 g_hash_table_iter_init(&iter
, proc_dbg_info_src
->baddr_to_bin_info
);
274 while (g_hash_table_iter_next(&iter
, &baddr
, &value
))
276 struct bin_info
*bin
= value
;
278 if (!bin_info_has_address(value
, ip
)) {
283 * Found; add it to cache.
285 * FIXME: this should be bounded in size (and implement
286 * a caching policy), and entries should be prunned when
287 * libraries are unmapped.
289 debug_info_src
= debug_info_source_create_from_bin(bin
, ip
);
290 if (debug_info_src
) {
292 proc_dbg_info_src
->ip_to_debug_info_src
,
293 key
, debug_info_src
);
294 /* Ownership passed to ht. */
302 return debug_info_src
;
306 struct debug_info_source
*debug_info_query(struct debug_info
*debug_info
,
307 int64_t vpid
, uint64_t ip
)
309 struct debug_info_source
*dbg_info_src
= NULL
;
310 struct proc_debug_info_sources
*proc_dbg_info_src
;
312 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
313 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
314 if (!proc_dbg_info_src
) {
318 dbg_info_src
= proc_debug_info_sources_get_entry(proc_dbg_info_src
, ip
);
325 struct debug_info
*debug_info_create(struct debug_info_component
*comp
)
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 debug_info
->comp
= comp
;
343 ret
= debug_info_init(debug_info
);
356 void debug_info_destroy(struct debug_info
*debug_info
)
362 if (debug_info
->vpid_to_proc_dbg_info_src
) {
363 g_hash_table_destroy(debug_info
->vpid_to_proc_dbg_info_src
);
372 void handle_statedump_build_id_event(FILE *err
, struct debug_info
*debug_info
,
373 struct bt_ctf_event
*event
)
375 struct proc_debug_info_sources
*proc_dbg_info_src
;
376 struct bin_info
*bin
= NULL
;
381 ret
= get_stream_event_context_int_field_value(err
,
382 event
, "_vpid", &vpid
);
384 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
390 ret
= get_payload_unsigned_int_field_value(err
,
391 event
, "_baddr", &baddr
);
393 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
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",
416 &bin
->build_id
, &bin
->build_id_len
);
418 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
425 * Reset the is_elf_only flag in case it had been set
426 * previously, because we might find separate debug info using
427 * the new build id information.
429 bin
->is_elf_only
= false;
432 // bin_info_set_build_id(bin, build_id, build_id_len);
439 void handle_statedump_debug_link_event(FILE *err
, struct debug_info
*debug_info
,
440 struct bt_ctf_event
*event
)
442 struct proc_debug_info_sources
*proc_dbg_info_src
;
443 struct bin_info
*bin
= NULL
;
446 const char *filename
= NULL
;
451 ret
= get_stream_event_context_int_field_value(err
, event
,
454 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
460 ret
= get_payload_unsigned_int_field_value(err
,
461 event
, "_baddr", &baddr
);
463 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
469 ret
= get_payload_unsigned_int_field_value(err
, event
, "_crc32", &tmp
);
471 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
476 crc32
= (uint32_t) tmp
;
478 ret
= get_payload_string_field_value(err
,
479 event
, "_filename", &filename
);
481 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
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 struct bt_ctf_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", &baddr
);
525 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
531 ret
= get_payload_unsigned_int_field_value(err
,
532 event
, "_memsz", &memsz
);
534 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
540 ret
= get_payload_string_field_value(err
,
541 event
, "_path", &path
);
543 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
552 ret
= get_payload_unsigned_int_field_value(err
,
553 event
, "_is_pic", &tmp
);
555 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
563 * dlopen has no is_pic field, because the shared
564 * object is always PIC.
569 ret
= get_stream_event_context_int_field_value(err
, event
, "_vpid",
572 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
587 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
588 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
589 if (!proc_dbg_info_src
) {
593 key
= g_new0(uint64_t, 1);
598 *((uint64_t *) key
) = baddr
;
600 bin
= g_hash_table_lookup(proc_dbg_info_src
->baddr_to_bin_info
,
606 bin
= bin_info_create(path
, baddr
, memsz
, is_pic
,
607 debug_info
->comp
->arg_debug_dir
,
608 debug_info
->comp
->arg_target_prefix
);
613 g_hash_table_insert(proc_dbg_info_src
->baddr_to_bin_info
,
615 /* Ownership passed to ht. */
624 void handle_statedump_bin_info_event(FILE *err
, struct debug_info
*debug_info
,
625 struct bt_ctf_event
*event
)
627 handle_bin_info_event(err
, debug_info
, event
, true);
631 void handle_lib_load_event(FILE *err
, struct debug_info
*debug_info
,
632 struct bt_ctf_event
*event
)
634 handle_bin_info_event(err
, debug_info
, event
, false);
638 void handle_lib_unload_event(FILE *err
, struct debug_info
*debug_info
,
639 struct bt_ctf_event
*event
)
641 struct proc_debug_info_sources
*proc_dbg_info_src
;
644 gpointer key_ptr
= NULL
;
647 ret
= get_payload_unsigned_int_field_value(err
,
648 event
, "_baddr", &baddr
);
650 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
656 ret
= get_stream_event_context_int_field_value(err
, event
, "_vpid",
659 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
665 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
666 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
667 if (!proc_dbg_info_src
) {
671 key_ptr
= (gpointer
) &baddr
;
672 (void) g_hash_table_remove(proc_dbg_info_src
->baddr_to_bin_info
,
679 void handle_statedump_start(FILE *err
, struct debug_info
*debug_info
,
680 struct bt_ctf_event
*event
)
682 struct proc_debug_info_sources
*proc_dbg_info_src
;
686 ret
= get_stream_event_context_int_field_value(err
, event
,
689 fprintf(err
, "[error] %s in %s:%d\n", __func__
,
695 proc_dbg_info_src
= proc_debug_info_sources_ht_get_entry(
696 debug_info
->vpid_to_proc_dbg_info_src
, vpid
);
697 if (!proc_dbg_info_src
) {
701 g_hash_table_remove_all(proc_dbg_info_src
->baddr_to_bin_info
);
702 g_hash_table_remove_all(proc_dbg_info_src
->ip_to_debug_info_src
);
709 void debug_info_handle_event(FILE *err
, struct bt_ctf_event
*event
,
710 struct debug_info
*debug_info
)
712 struct bt_ctf_event_class
*event_class
;
713 const char *event_name
;
716 if (!debug_info
|| !event
) {
719 event_class
= bt_ctf_event_get_class(event
);
723 event_name
= bt_ctf_event_class_get_name(event_class
);
727 q_event_name
= g_quark_try_string(event_name
);
729 if (q_event_name
== debug_info
->q_statedump_bin_info
) {
731 handle_statedump_bin_info_event(err
, debug_info
, event
);
732 } else if (q_event_name
== debug_info
->q_dl_open
||
733 q_event_name
== debug_info
->q_lib_load
) {
735 * dl_open and lib_load events are both checked for since
736 * only dl_open was produced as of lttng-ust 2.8.
738 * lib_load, which is produced from lttng-ust 2.9+, is a lot
739 * more reliable since it will be emitted when other functions
740 * of the dlopen family are called (e.g. dlmopen) and when
741 * library are transitively loaded.
743 handle_lib_load_event(err
, debug_info
, event
);
744 } else if (q_event_name
== debug_info
->q_statedump_start
) {
745 /* Start state dump */
746 handle_statedump_start(err
, debug_info
, event
);
747 } else if (q_event_name
== debug_info
->q_statedump_debug_link
) {
748 /* Debug link info */
749 handle_statedump_debug_link_event(err
, debug_info
, event
);
750 } else if (q_event_name
== debug_info
->q_statedump_build_id
) {
752 handle_statedump_build_id_event(err
, debug_info
, event
);
753 } else if (q_event_name
== debug_info
-> q_lib_unload
) {
754 handle_lib_unload_event(err
, debug_info
, event
);