babeltrace(1): print value with colors
[babeltrace.git] / lib / debug-info.c
CommitLineData
c40a57e5
AB
1/*
2 * Babeltrace - Debug Information State Tracker
3 *
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>
ff9ce920 7 * Copyright (c) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
c40a57e5
AB
8 *
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:
15 *
16 * The above copyright notice and this permission notice shall be included in
17 * all copies or substantial portions of the Software.
18 *
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
25 * SOFTWARE.
26 */
27
28#include <assert.h>
29#include <glib.h>
30#include <babeltrace/types.h>
31#include <babeltrace/ctf-ir/metadata.h>
2748fb3b 32#include <babeltrace/debug-info.h>
d5ddf820 33#include <babeltrace/bin-info.h>
ff9ce920 34#include <babeltrace/babeltrace-internal.h>
55cd033d 35#include <babeltrace/utils.h>
c40a57e5
AB
36
37struct proc_debug_info_sources {
38 /*
d5ddf820 39 * Hash table: base address (pointer to uint64_t) to bin info; owned by
c40a57e5
AB
40 * proc_debug_info_sources.
41 */
d5ddf820 42 GHashTable *baddr_to_bin_info;
c40a57e5
AB
43
44 /*
47857613
JG
45 * Hash table: IP (pointer to uint64_t) to (struct debug_info_source *);
46 * owned by proc_debug_info_sources.
c40a57e5
AB
47 */
48 GHashTable *ip_to_debug_info_src;
49};
50
51struct debug_info {
52 /*
47857613
JG
53 * Hash table of VPIDs (pointer to int64_t) to
54 * (struct ctf_proc_debug_infos*); owned by debug_info.
c40a57e5
AB
55 */
56 GHashTable *vpid_to_proc_dbg_info_src;
9c713367 57 GQuark q_statedump_bin_info;
c40a57e5
AB
58 GQuark q_statedump_debug_link;
59 GQuark q_statedump_build_id;
60 GQuark q_statedump_start;
61 GQuark q_dl_open;
46d8a85a 62 GQuark q_lib_load;
ea94a8a7 63 GQuark q_lib_unload;
c40a57e5
AB
64};
65
66static
67int debug_info_init(struct debug_info *info)
68{
2ea5cc8b 69 info->q_statedump_bin_info = g_quark_from_string(
9c713367 70 "lttng_ust_statedump:bin_info");
2ea5cc8b 71 info->q_statedump_debug_link = g_quark_from_string(
c40a57e5 72 "lttng_ust_statedump:debug_link)");
2ea5cc8b 73 info->q_statedump_build_id = g_quark_from_string(
c40a57e5 74 "lttng_ust_statedump:build_id");
2ea5cc8b 75 info->q_statedump_start = g_quark_from_string(
c40a57e5 76 "lttng_ust_statedump:start");
2ea5cc8b
NL
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");
c40a57e5 80
d5ddf820 81 return bin_info_init();
c40a57e5
AB
82}
83
84static
85void debug_info_source_destroy(struct debug_info_source *debug_info_src)
86{
87 if (!debug_info_src) {
88 return;
89 }
90
91 free(debug_info_src->func);
a7a607cf
JG
92 free(debug_info_src->src_path);
93 free(debug_info_src->bin_path);
36ae9941 94 free(debug_info_src->bin_loc);
c40a57e5
AB
95 g_free(debug_info_src);
96}
97
98static
d5ddf820 99struct debug_info_source *debug_info_source_create_from_bin(struct bin_info *bin,
c40a57e5
AB
100 uint64_t ip)
101{
102 int ret;
103 struct debug_info_source *debug_info_src = NULL;
104 struct source_location *src_loc = NULL;
105
106 debug_info_src = g_new0(struct debug_info_source, 1);
107
108 if (!debug_info_src) {
109 goto end;
110 }
111
112 /* Lookup function name */
d5ddf820 113 ret = bin_info_lookup_function_name(bin, ip, &debug_info_src->func);
c40a57e5
AB
114 if (ret) {
115 goto error;
116 }
117
545e1e92
JG
118 /* Can't retrieve src_loc from ELF, or could not find binary, skip. */
119 if (!bin->is_elf_only || !debug_info_src->func) {
44148130 120 /* Lookup source location */
d5ddf820 121 ret = bin_info_lookup_source_location(bin, ip, &src_loc);
545e1e92 122 printf_verbose("Failed to lookup source location (err: %i)\n", ret);
c40a57e5
AB
123 }
124
125 if (src_loc) {
126 debug_info_src->line_no = src_loc->line_no;
127
128 if (src_loc->filename) {
a7a607cf
JG
129 debug_info_src->src_path = strdup(src_loc->filename);
130 if (!debug_info_src->src_path) {
c40a57e5
AB
131 goto error;
132 }
ff9ce920 133
a7a607cf 134 debug_info_src->short_src_path = get_filename_from_path(
51a9f65d 135 debug_info_src->src_path);
c40a57e5
AB
136 }
137
138 source_location_destroy(src_loc);
139 }
140
d5ddf820
AB
141 if (bin->elf_path) {
142 debug_info_src->bin_path = strdup(bin->elf_path);
a7a607cf
JG
143 if (!debug_info_src->bin_path) {
144 goto error;
145 }
146
147 debug_info_src->short_bin_path = get_filename_from_path(
148 debug_info_src->bin_path);
36ae9941 149
d5ddf820 150 ret = bin_info_get_bin_loc(bin, ip, &(debug_info_src->bin_loc));
36ae9941
AB
151 if (ret) {
152 goto error;
153 }
a7a607cf
JG
154 }
155
c40a57e5
AB
156end:
157 return debug_info_src;
158
159error:
160 debug_info_source_destroy(debug_info_src);
161 return NULL;
162}
163
164static
165void proc_debug_info_sources_destroy(
166 struct proc_debug_info_sources *proc_dbg_info_src)
167{
168 if (!proc_dbg_info_src) {
169 return;
170 }
171
d5ddf820
AB
172 if (proc_dbg_info_src->baddr_to_bin_info) {
173 g_hash_table_destroy(proc_dbg_info_src->baddr_to_bin_info);
c40a57e5
AB
174 }
175
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);
178 }
179
180 g_free(proc_dbg_info_src);
181}
182
183static
184struct proc_debug_info_sources *proc_debug_info_sources_create(void)
185{
186 struct proc_debug_info_sources *proc_dbg_info_src = NULL;
187
188 proc_dbg_info_src = g_new0(struct proc_debug_info_sources, 1);
189 if (!proc_dbg_info_src) {
190 goto end;
191 }
192
d5ddf820 193 proc_dbg_info_src->baddr_to_bin_info = g_hash_table_new_full(
47857613 194 g_int64_hash, g_int64_equal, (GDestroyNotify) g_free,
d5ddf820
AB
195 (GDestroyNotify) bin_info_destroy);
196 if (!proc_dbg_info_src->baddr_to_bin_info) {
c40a57e5
AB
197 goto error;
198 }
199
200 proc_dbg_info_src->ip_to_debug_info_src = g_hash_table_new_full(
47857613 201 g_int64_hash, g_int64_equal, (GDestroyNotify) g_free,
c40a57e5
AB
202 (GDestroyNotify) debug_info_source_destroy);
203 if (!proc_dbg_info_src->ip_to_debug_info_src) {
204 goto error;
205 }
206
207end:
208 return proc_dbg_info_src;
209
210error:
211 proc_debug_info_sources_destroy(proc_dbg_info_src);
212 return NULL;
213}
214
215static
216struct proc_debug_info_sources *proc_debug_info_sources_ht_get_entry(
217 GHashTable *ht, int64_t vpid)
218{
47857613 219 gpointer key = g_new0(int64_t, 1);
c40a57e5
AB
220 struct proc_debug_info_sources *proc_dbg_info_src = NULL;
221
47857613
JG
222 if (!key) {
223 goto end;
224 }
225
226 *((int64_t *) key) = vpid;
227
c40a57e5
AB
228 /* Exists? Return it */
229 proc_dbg_info_src = g_hash_table_lookup(ht, key);
230 if (proc_dbg_info_src) {
231 goto end;
232 }
233
234 /* Otherwise, create and return it */
235 proc_dbg_info_src = proc_debug_info_sources_create();
236 if (!proc_dbg_info_src) {
237 goto end;
238 }
239
240 g_hash_table_insert(ht, key, proc_dbg_info_src);
47857613
JG
241 /* Ownership passed to ht */
242 key = NULL;
c40a57e5 243end:
47857613 244 g_free(key);
c40a57e5
AB
245 return proc_dbg_info_src;
246}
247
248static
249struct debug_info_source *proc_debug_info_sources_get_entry(
250 struct proc_debug_info_sources *proc_dbg_info_src, uint64_t ip)
251{
252 struct debug_info_source *debug_info_src = NULL;
47857613 253 gpointer key = g_new0(uint64_t, 1);
c40a57e5
AB
254 GHashTableIter iter;
255 gpointer baddr, value;
256
47857613
JG
257 if (!key) {
258 goto end;
259 }
260
261 *((uint64_t *) key) = ip;
262
c40a57e5
AB
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,
47857613 266 key);
c40a57e5
AB
267 if (debug_info_src) {
268 goto end;
269 }
270
d5ddf820
AB
271 /* Check in all bin_infos. */
272 g_hash_table_iter_init(&iter, proc_dbg_info_src->baddr_to_bin_info);
c40a57e5
AB
273
274 while (g_hash_table_iter_next(&iter, &baddr, &value))
275 {
d5ddf820 276 struct bin_info *bin = value;
c40a57e5 277
d5ddf820 278 if (!bin_info_has_address(value, ip)) {
c40a57e5
AB
279 continue;
280 }
281
47857613
JG
282 /*
283 * Found; add it to cache.
284 *
285 * FIXME: this should be bounded in size (and implement
286 * a caching policy), and entries should be prunned when
287 * libraries are unmapped.
288 */
d5ddf820 289 debug_info_src = debug_info_source_create_from_bin(bin, ip);
c40a57e5
AB
290 if (debug_info_src) {
291 g_hash_table_insert(
292 proc_dbg_info_src->ip_to_debug_info_src,
47857613
JG
293 key, debug_info_src);
294 /* Ownership passed to ht. */
295 key = NULL;
c40a57e5
AB
296 }
297 break;
298 }
299
300end:
47857613 301 free(key);
c40a57e5
AB
302 return debug_info_src;
303}
304
305BT_HIDDEN
306struct debug_info_source *debug_info_query(struct debug_info *debug_info,
307 int64_t vpid, uint64_t ip)
308{
309 struct debug_info_source *dbg_info_src = NULL;
310 struct proc_debug_info_sources *proc_dbg_info_src;
311
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) {
315 goto end;
316 }
317
318 dbg_info_src = proc_debug_info_sources_get_entry(
319 proc_dbg_info_src, ip);
320 if (!dbg_info_src) {
321 goto end;
322 }
323
324end:
325 return dbg_info_src;
326}
327
328BT_HIDDEN
329struct debug_info *debug_info_create(void)
330{
331 int ret;
332 struct debug_info *debug_info;
333
334 debug_info = g_new0(struct debug_info, 1);
335 if (!debug_info) {
336 goto end;
337 }
338
47857613
JG
339 debug_info->vpid_to_proc_dbg_info_src = g_hash_table_new_full(
340 g_int64_hash, g_int64_equal, (GDestroyNotify) g_free,
c40a57e5
AB
341 (GDestroyNotify) proc_debug_info_sources_destroy);
342 if (!debug_info->vpid_to_proc_dbg_info_src) {
343 goto error;
344 }
345
346 ret = debug_info_init(debug_info);
347 if (ret) {
348 goto error;
349 }
350
351end:
352 return debug_info;
353error:
354 g_free(debug_info);
355 return NULL;
356}
357
358BT_HIDDEN
359void debug_info_destroy(struct debug_info *debug_info)
360{
361 if (!debug_info) {
362 goto end;
363 }
364
365 if (debug_info->vpid_to_proc_dbg_info_src) {
366 g_hash_table_destroy(debug_info->vpid_to_proc_dbg_info_src);
367 }
368
369 g_free(debug_info);
370end:
371 return;
372}
373
374static
375void handle_statedump_build_id_event(struct debug_info *debug_info,
376 struct ctf_event_definition *event_def)
377{
378 struct proc_debug_info_sources *proc_dbg_info_src;
379 struct bt_definition *event_fields_def = NULL;
380 struct bt_definition *sec_def = NULL;
381 struct bt_definition *baddr_def = NULL;
382 struct bt_definition *vpid_def = NULL;
383 struct bt_definition *build_id_def = NULL;
384 struct definition_sequence *build_id_seq;
d5ddf820 385 struct bin_info *bin = NULL;
c40a57e5
AB
386 int i;
387 int64_t vpid;
388 uint64_t baddr;
389 uint8_t *build_id = NULL;
390 uint64_t build_id_len;
391
392 event_fields_def = (struct bt_definition *) event_def->event_fields;
393 sec_def = (struct bt_definition *)
394 event_def->stream->stream_event_context;
395
396 if (!event_fields_def || !sec_def) {
397 goto end;
398 }
399
400 baddr_def = bt_lookup_definition(event_fields_def, "_baddr");
401 if (!baddr_def) {
402 goto end;
403 }
404
405 vpid_def = bt_lookup_definition(sec_def, "_vpid");
406 if (!vpid_def) {
407 goto end;
408 }
409
410 build_id_def = bt_lookup_definition(event_fields_def, "_build_id");
411 if (!build_id_def) {
412 goto end;
413 }
414
415 if (baddr_def->declaration->id != BT_CTF_TYPE_ID_INTEGER) {
416 goto end;
417 }
418
419 if (vpid_def->declaration->id != BT_CTF_TYPE_ID_INTEGER) {
420 goto end;
421 }
422
423 if (build_id_def->declaration->id != BT_CTF_TYPE_ID_SEQUENCE) {
424 goto end;
425 }
426
427 baddr = bt_get_unsigned_int(baddr_def);
428 vpid = bt_get_signed_int(vpid_def);
429 build_id_seq = container_of(build_id_def,
430 struct definition_sequence, p);
431 build_id_len = build_id_seq->length->value._unsigned;
432
433 build_id = g_malloc(build_id_len);
434 if (!build_id) {
435 goto end;
436 }
437
438 for (i = 0; i < build_id_len; ++i) {
439 struct bt_definition **field;
440
441 field = (struct bt_definition **) &g_ptr_array_index(
442 build_id_seq->elems, i);
443 build_id[i] = bt_get_unsigned_int(*field);
444 }
445
446 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
447 debug_info->vpid_to_proc_dbg_info_src, vpid);
448 if (!proc_dbg_info_src) {
449 goto end;
450 }
451
d5ddf820 452 bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info,
c40a57e5 453 (gpointer) &baddr);
d5ddf820 454 if (!bin) {
c40a57e5 455 /*
d5ddf820 456 * The build_id event comes after the bin has been
c40a57e5
AB
457 * created. If it isn't found, just ignore this event.
458 */
459 goto end;
460 }
461
d5ddf820 462 bin_info_set_build_id(bin, build_id, build_id_len);
c40a57e5
AB
463
464end:
465 free(build_id);
466 return;
467}
468
469static
470void handle_statedump_debug_link_event(struct debug_info *debug_info,
471 struct ctf_event_definition *event_def)
472{
473 struct proc_debug_info_sources *proc_dbg_info_src;
474 struct bt_definition *event_fields_def = NULL;
475 struct bt_definition *sec_def = NULL;
476 struct bt_definition *baddr_def = NULL;
477 struct bt_definition *vpid_def = NULL;
478 struct bt_definition *filename_def = NULL;
479 struct bt_definition *crc32_def = NULL;
d5ddf820 480 struct bin_info *bin = NULL;
c40a57e5
AB
481 int64_t vpid;
482 uint64_t baddr;
483 char *filename = NULL;
484 uint32_t crc32;
485
486 event_fields_def = (struct bt_definition *) event_def->event_fields;
487 sec_def = (struct bt_definition *)
488 event_def->stream->stream_event_context;
489
490 if (!event_fields_def || !sec_def) {
491 goto end;
492 }
493
494 baddr_def = bt_lookup_definition(event_fields_def, "_baddr");
495 if (!baddr_def) {
496 goto end;
497 }
498
499 vpid_def = bt_lookup_definition(sec_def, "_vpid");
500 if (!vpid_def) {
501 goto end;
502 }
503
504 filename_def = bt_lookup_definition(event_fields_def, "_filename");
505 if (!filename_def) {
506 goto end;
507 }
508
509 crc32_def = bt_lookup_definition(event_fields_def, "_crc32");
510 if (!crc32_def) {
511 goto end;
512 }
513
514 if (baddr_def->declaration->id != BT_CTF_TYPE_ID_INTEGER) {
515 goto end;
516 }
517
518 if (vpid_def->declaration->id != BT_CTF_TYPE_ID_INTEGER) {
519 goto end;
520 }
521
522 if (filename_def->declaration->id != BT_CTF_TYPE_ID_STRING) {
523 goto end;
524 }
525
526 if (crc32_def->declaration->id != BT_CTF_TYPE_ID_INTEGER) {
527 goto end;
528 }
529
530 baddr = bt_get_unsigned_int(baddr_def);
531 vpid = bt_get_signed_int(vpid_def);
532
533 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
534 debug_info->vpid_to_proc_dbg_info_src, vpid);
535 if (!proc_dbg_info_src) {
536 goto end;
537 }
538
d5ddf820 539 bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info,
c40a57e5 540 (gpointer) &baddr);
d5ddf820 541 if (!bin) {
c40a57e5 542 /*
d5ddf820 543 * The debug_link event comes after the bin has been
c40a57e5
AB
544 * created. If it isn't found, just ignore this event.
545 */
546 goto end;
547 }
548
549 filename = bt_get_string(filename_def);
550 crc32 = bt_get_unsigned_int(crc32_def);
551
d5ddf820 552 bin_info_set_debug_link(bin, filename, crc32);
c40a57e5
AB
553
554end:
555 return;
556}
557
558static
9f2b13ca
AB
559void handle_bin_info_event(struct debug_info *debug_info,
560 struct ctf_event_definition *event_def, bool has_pic_field)
c40a57e5
AB
561{
562 struct bt_definition *baddr_def = NULL;
563 struct bt_definition *memsz_def = NULL;
9c713367 564 struct bt_definition *path_def = NULL;
9f2b13ca 565 struct bt_definition *is_pic_def = NULL;
c40a57e5
AB
566 struct bt_definition *vpid_def = NULL;
567 struct bt_definition *event_fields_def = NULL;
568 struct bt_definition *sec_def = NULL;
569 struct proc_debug_info_sources *proc_dbg_info_src;
d5ddf820 570 struct bin_info *bin;
c40a57e5
AB
571 uint64_t baddr, memsz;
572 int64_t vpid;
9c713367 573 const char *path;
47857613 574 gpointer key = NULL;
9f2b13ca 575 bool is_pic;
c40a57e5
AB
576
577 event_fields_def = (struct bt_definition *) event_def->event_fields;
578 sec_def = (struct bt_definition *)
579 event_def->stream->stream_event_context;
580
581 if (!event_fields_def || !sec_def) {
582 goto end;
583 }
584
585 baddr_def = bt_lookup_definition(event_fields_def, "_baddr");
586 if (!baddr_def) {
587 goto end;
588 }
589
590 memsz_def = bt_lookup_definition(event_fields_def, "_memsz");
591 if (!memsz_def) {
592 goto end;
593 }
594
9c713367
AB
595 path_def = bt_lookup_definition(event_fields_def, "_path");
596 if (!path_def) {
c40a57e5
AB
597 goto end;
598 }
599
9f2b13ca
AB
600 if (has_pic_field) {
601 is_pic_def = bt_lookup_definition(event_fields_def, "_is_pic");
602 if (!is_pic_def) {
603 goto end;
604 }
605
606 if (is_pic_def->declaration->id != BT_CTF_TYPE_ID_INTEGER) {
607 goto end;
608 }
609
610 is_pic = (bt_get_unsigned_int(is_pic_def) == 1);
611 } else {
612 /*
613 * dlopen has no is_pic field, because the shared
614 * object is always PIC.
615 */
616 is_pic = true;
617 }
618
c40a57e5
AB
619 vpid_def = bt_lookup_definition(sec_def, "_vpid");
620 if (!vpid_def) {
621 goto end;
622 }
623
624 if (baddr_def->declaration->id != BT_CTF_TYPE_ID_INTEGER) {
625 goto end;
626 }
627
628 if (memsz_def->declaration->id != BT_CTF_TYPE_ID_INTEGER) {
629 goto end;
630 }
631
9c713367 632 if (path_def->declaration->id != BT_CTF_TYPE_ID_STRING) {
c40a57e5
AB
633 goto end;
634 }
635
636 if (vpid_def->declaration->id != BT_CTF_TYPE_ID_INTEGER) {
637 goto end;
638 }
639
640 baddr = bt_get_unsigned_int(baddr_def);
641 memsz = bt_get_unsigned_int(memsz_def);
9c713367 642 path = bt_get_string(path_def);
c40a57e5
AB
643 vpid = bt_get_signed_int(vpid_def);
644
9c713367 645 if (!path) {
c40a57e5
AB
646 goto end;
647 }
648
649 if (memsz == 0) {
650 /* Ignore VDSO. */
651 goto end;
652 }
653
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) {
657 goto end;
658 }
659
47857613
JG
660 key = g_new0(uint64_t, 1);
661 if (!key) {
662 goto end;
663 }
664
665 *((uint64_t *) key) = baddr;
666
d5ddf820 667 bin = g_hash_table_lookup(proc_dbg_info_src->baddr_to_bin_info,
47857613 668 key);
d5ddf820 669 if (bin) {
c40a57e5
AB
670 goto end;
671 }
672
d5ddf820
AB
673 bin = bin_info_create(path, baddr, memsz, is_pic);
674 if (!bin) {
c40a57e5
AB
675 goto end;
676 }
677
d5ddf820
AB
678 g_hash_table_insert(proc_dbg_info_src->baddr_to_bin_info,
679 key, bin);
47857613
JG
680 /* Ownership passed to ht. */
681 key = NULL;
c40a57e5
AB
682
683end:
47857613 684 g_free(key);
c40a57e5
AB
685 return;
686}
687
9f2b13ca 688static inline
9c713367 689void handle_statedump_bin_info_event(struct debug_info *debug_info,
9f2b13ca
AB
690 struct ctf_event_definition *event_def)
691{
692 handle_bin_info_event(debug_info, event_def, true);
693}
694
695static inline
afba0101 696void handle_lib_load_event(struct debug_info *debug_info,
9f2b13ca
AB
697 struct ctf_event_definition *event_def)
698{
699 handle_bin_info_event(debug_info, event_def, false);
700}
701
ea94a8a7
JG
702static inline
703void handle_lib_unload_event(struct debug_info *debug_info,
704 struct ctf_event_definition *event_def)
705{
706 struct bt_definition *baddr_def = NULL;
707 struct bt_definition *event_fields_def = NULL;
708 struct bt_definition *sec_def = NULL;
709 struct bt_definition *vpid_def = NULL;
710 struct proc_debug_info_sources *proc_dbg_info_src;
711 uint64_t baddr;
712 int64_t vpid;
713 gpointer key_ptr = NULL;
714
715 event_fields_def = (struct bt_definition *) event_def->event_fields;
716 sec_def = (struct bt_definition *)
717 event_def->stream->stream_event_context;
718 if (!event_fields_def || !sec_def) {
719 goto end;
720 }
721
722 baddr_def = bt_lookup_definition(event_fields_def, "_baddr");
723 if (!baddr_def) {
724 goto end;
725 }
726
727 vpid_def = bt_lookup_definition(sec_def, "_vpid");
728 if (!vpid_def) {
729 goto end;
730 }
731
732 if (baddr_def->declaration->id != BT_CTF_TYPE_ID_INTEGER) {
733 goto end;
734 }
735 if (vpid_def->declaration->id != BT_CTF_TYPE_ID_INTEGER) {
736 goto end;
737 }
738
739 baddr = bt_get_unsigned_int(baddr_def);
740 vpid = bt_get_signed_int(vpid_def);
741
742 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
743 debug_info->vpid_to_proc_dbg_info_src, vpid);
744 if (!proc_dbg_info_src) {
745 goto end;
746 }
747
748 key_ptr = (gpointer) &baddr;
93830bc1
JG
749 (void) g_hash_table_remove(proc_dbg_info_src->baddr_to_bin_info,
750 key_ptr);
ea94a8a7
JG
751end:
752 return;
753}
9f2b13ca 754
c40a57e5
AB
755static
756void handle_statedump_start(struct debug_info *debug_info,
757 struct ctf_event_definition *event_def)
758{
759 struct bt_definition *vpid_def = NULL;
760 struct bt_definition *sec_def = NULL;
761 struct proc_debug_info_sources *proc_dbg_info_src;
762 int64_t vpid;
763
764 sec_def = (struct bt_definition *)
765 event_def->stream->stream_event_context;
766 if (!sec_def) {
767 goto end;
768 }
769
770 vpid_def = bt_lookup_definition(sec_def, "_vpid");
771 if (!vpid_def) {
772 goto end;
773 }
774
775 vpid = bt_get_signed_int(vpid_def);
776
777 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
778 debug_info->vpid_to_proc_dbg_info_src, vpid);
779 if (!proc_dbg_info_src) {
780 goto end;
781 }
782
d5ddf820 783 g_hash_table_remove_all(proc_dbg_info_src->baddr_to_bin_info);
c40a57e5
AB
784 g_hash_table_remove_all(proc_dbg_info_src->ip_to_debug_info_src);
785
786end:
787 return;
788}
789
790static
791void register_event_debug_infos(struct debug_info *debug_info,
792 struct ctf_event_definition *event)
793{
794 struct bt_definition *ip_def, *vpid_def;
795 int64_t vpid;
796 uint64_t ip;
797 struct bt_definition *sec_def;
798
799 /* Get stream event context definition. */
800 sec_def = (struct bt_definition *) event->stream->stream_event_context;
801 if (!sec_def) {
802 goto end;
803 }
804
805 /* Get "ip" and "vpid" definitions. */
806 vpid_def = bt_lookup_definition((struct bt_definition *) sec_def,
807 "_vpid");
808 ip_def = bt_lookup_definition((struct bt_definition *) sec_def, "_ip");
809
810 if (!vpid_def || !ip_def) {
811 goto end;
812 }
813
814 vpid = bt_get_signed_int(vpid_def);
815 ip = bt_get_unsigned_int(ip_def);
816
817 /* Get debug info for this context. */
818 ((struct definition_integer *) ip_def)->debug_info_src =
819 debug_info_query(debug_info, vpid, ip);
820
821end:
822 return;
823}
824
825BT_HIDDEN
826void debug_info_handle_event(struct debug_info *debug_info,
827 struct ctf_event_definition *event)
828{
829 struct ctf_event_declaration *event_class;
830 struct ctf_stream_declaration *stream_class;
831
832 if (!debug_info || !event) {
833 goto end;
834 }
835
836 stream_class = event->stream->stream_class;
837 event_class = g_ptr_array_index(stream_class->events_by_id,
838 event->stream->event_id);
839
9c713367 840 if (event_class->name == debug_info->q_statedump_bin_info) {
9f2b13ca 841 /* State dump */
9c713367 842 handle_statedump_bin_info_event(debug_info, event);
46d8a85a
JG
843 } else if (event_class->name == debug_info->q_dl_open ||
844 event_class->name == debug_info->q_lib_load) {
845 /*
846 * dl_open and lib_load events are both checked for since
847 * only dl_open was produced as of lttng-ust 2.8.
848 *
849 * lib_load, which is produced from lttng-ust 2.9+, is a lot
850 * more reliable since it will be emitted when other functions
851 * of the dlopen family are called (e.g. dlmopen) and when
852 * library are transitively loaded.
853 */
afba0101 854 handle_lib_load_event(debug_info, event);
c40a57e5
AB
855 } else if (event_class->name == debug_info->q_statedump_start) {
856 /* Start state dump */
857 handle_statedump_start(debug_info, event);
858 } else if (event_class->name == debug_info->q_statedump_debug_link) {
859 /* Debug link info */
860 handle_statedump_debug_link_event(debug_info, event);
861 } else if (event_class->name == debug_info->q_statedump_build_id) {
862 /* Build ID info */
863 handle_statedump_build_id_event(debug_info, event);
ea94a8a7
JG
864 } else if (event_class->name == debug_info-> q_lib_unload) {
865 handle_lib_unload_event(debug_info, event);
c40a57e5 866 }
8ac5a9df
SM
867
868 /* All events: register debug infos */
869 register_event_debug_infos(debug_info, event);
870
c40a57e5
AB
871end:
872 return;
873}
This page took 0.064905 seconds and 4 git commands to generate.