Show binary path as part of debug info
[babeltrace.git] / lib / debuginfo.c
CommitLineData
b5a8598f
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>
458af89d 7 * Copyright (c) 2016 Jérémie Galarneau <jeremie.galarneau@efficios.com>
b5a8598f
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>
32#include <babeltrace/debuginfo.h>
33#include <babeltrace/so-info.h>
458af89d 34#include <babeltrace/babeltrace-internal.h>
b5a8598f
AB
35
36struct proc_debug_info_sources {
37 /*
71235b6d 38 * Hash table: base address (pointer to uint64_t) to so info; owned by
b5a8598f
AB
39 * proc_debug_info_sources.
40 */
41 GHashTable *baddr_to_so_info;
42
43 /*
71235b6d
JG
44 * Hash table: IP (pointer to uint64_t) to (struct debug_info_source *);
45 * owned by proc_debug_info_sources.
b5a8598f
AB
46 */
47 GHashTable *ip_to_debug_info_src;
48};
49
50struct debug_info {
51 /*
71235b6d
JG
52 * Hash table of VPIDs (pointer to int64_t) to
53 * (struct ctf_proc_debug_infos*); owned by debug_info.
b5a8598f
AB
54 */
55 GHashTable *vpid_to_proc_dbg_info_src;
56 GQuark q_statedump_soinfo;
57 GQuark q_statedump_debug_link;
58 GQuark q_statedump_build_id;
59 GQuark q_statedump_start;
60 GQuark q_dl_open;
61};
62
63static
64int debug_info_init(struct debug_info *info)
65{
66 info->q_statedump_soinfo = g_quark_from_string(
67 "lttng_ust_statedump:soinfo");
68 info->q_statedump_debug_link = g_quark_from_string(
69 "lttng_ust_statedump:debug_link)");
70 info->q_statedump_build_id = g_quark_from_string(
71 "lttng_ust_statedump:build_id");
72 info->q_statedump_start = g_quark_from_string(
73 "lttng_ust_statedump:start");
74 info->q_dl_open = g_quark_from_string("lttng_ust_dl:dlopen");
75
76 return so_info_init();
77}
78
79static
80void debug_info_source_destroy(struct debug_info_source *debug_info_src)
81{
82 if (!debug_info_src) {
83 return;
84 }
85
86 free(debug_info_src->func);
ad2b5b38
JG
87 free(debug_info_src->src_path);
88 free(debug_info_src->bin_path);
b5a8598f
AB
89 g_free(debug_info_src);
90}
91
458af89d
JG
92/*
93 * Returns the location of a path's file (the last element of the path).
94 * Returns the original path on error.
95 */
96static
97const char *get_filename_from_path(const char *path)
98{
99 size_t i = strlen(path);
100
101 if (i == 0) {
102 goto end;
103 }
104
105 if (path[i - 1] == '/') {
106 /*
107 * Path ends with a trailing slash, no filename to return.
108 * Return the original path.
109 */
110 goto end;
111 }
112
113 while (i-- > 0) {
114 if (path[i] == '/') {
115 path = &path[i + 1];
116 goto end;
117 }
118 }
119end:
120 return path;
121}
122
b5a8598f
AB
123static
124struct debug_info_source *debug_info_source_create_from_so(struct so_info *so,
125 uint64_t ip)
126{
127 int ret;
128 struct debug_info_source *debug_info_src = NULL;
129 struct source_location *src_loc = NULL;
130
131 debug_info_src = g_new0(struct debug_info_source, 1);
132
133 if (!debug_info_src) {
134 goto end;
135 }
136
137 /* Lookup function name */
138 ret = so_info_lookup_function_name(so, ip, &debug_info_src->func);
139 if (ret) {
140 goto error;
141 }
142
143 /* Can't retrieve src_loc from ELF only, skip it */
144 if (so->is_elf_only) {
145 goto end;
146 }
147
148 /* Lookup source location */
149 ret = so_info_lookup_source_location(so, ip, &src_loc);
150 if (ret) {
151 goto error;
152 }
153
154 if (src_loc) {
155 debug_info_src->line_no = src_loc->line_no;
156
157 if (src_loc->filename) {
ad2b5b38
JG
158 debug_info_src->src_path = strdup(src_loc->filename);
159 if (!debug_info_src->src_path) {
b5a8598f
AB
160 goto error;
161 }
458af89d 162
ad2b5b38 163 debug_info_src->short_src_path = get_filename_from_path(
458af89d
JG
164 src_loc->filename);
165
b5a8598f
AB
166 }
167
168 source_location_destroy(src_loc);
169 }
170
ad2b5b38
JG
171 if (so->elf_path) {
172 debug_info_src->bin_path = strdup(so->elf_path);
173 if (!debug_info_src->bin_path) {
174 goto error;
175 }
176
177 debug_info_src->short_bin_path = get_filename_from_path(
178 debug_info_src->bin_path);
179 }
180
b5a8598f
AB
181end:
182 return debug_info_src;
183
184error:
185 debug_info_source_destroy(debug_info_src);
186 return NULL;
187}
188
189static
190void proc_debug_info_sources_destroy(
191 struct proc_debug_info_sources *proc_dbg_info_src)
192{
193 if (!proc_dbg_info_src) {
194 return;
195 }
196
197 if (proc_dbg_info_src->baddr_to_so_info) {
198 g_hash_table_destroy(proc_dbg_info_src->baddr_to_so_info);
199 }
200
201 if (proc_dbg_info_src->ip_to_debug_info_src) {
202 g_hash_table_destroy(proc_dbg_info_src->ip_to_debug_info_src);
203 }
204
205 g_free(proc_dbg_info_src);
206}
207
208static
209struct proc_debug_info_sources *proc_debug_info_sources_create(void)
210{
211 struct proc_debug_info_sources *proc_dbg_info_src = NULL;
212
213 proc_dbg_info_src = g_new0(struct proc_debug_info_sources, 1);
214 if (!proc_dbg_info_src) {
215 goto end;
216 }
217
218 proc_dbg_info_src->baddr_to_so_info = g_hash_table_new_full(
71235b6d
JG
219 g_int64_hash, g_int64_equal, (GDestroyNotify) g_free,
220 (GDestroyNotify) so_info_destroy);
b5a8598f
AB
221 if (!proc_dbg_info_src->baddr_to_so_info) {
222 goto error;
223 }
224
225 proc_dbg_info_src->ip_to_debug_info_src = g_hash_table_new_full(
71235b6d 226 g_int64_hash, g_int64_equal, (GDestroyNotify) g_free,
b5a8598f
AB
227 (GDestroyNotify) debug_info_source_destroy);
228 if (!proc_dbg_info_src->ip_to_debug_info_src) {
229 goto error;
230 }
231
232end:
233 return proc_dbg_info_src;
234
235error:
236 proc_debug_info_sources_destroy(proc_dbg_info_src);
237 return NULL;
238}
239
240static
241struct proc_debug_info_sources *proc_debug_info_sources_ht_get_entry(
242 GHashTable *ht, int64_t vpid)
243{
71235b6d 244 gpointer key = g_new0(int64_t, 1);
b5a8598f
AB
245 struct proc_debug_info_sources *proc_dbg_info_src = NULL;
246
71235b6d
JG
247 if (!key) {
248 goto end;
249 }
250
251 *((int64_t *) key) = vpid;
252
b5a8598f
AB
253 /* Exists? Return it */
254 proc_dbg_info_src = g_hash_table_lookup(ht, key);
255 if (proc_dbg_info_src) {
256 goto end;
257 }
258
259 /* Otherwise, create and return it */
260 proc_dbg_info_src = proc_debug_info_sources_create();
261 if (!proc_dbg_info_src) {
262 goto end;
263 }
264
265 g_hash_table_insert(ht, key, proc_dbg_info_src);
71235b6d
JG
266 /* Ownership passed to ht */
267 key = NULL;
b5a8598f 268end:
71235b6d 269 g_free(key);
b5a8598f
AB
270 return proc_dbg_info_src;
271}
272
273static
274struct debug_info_source *proc_debug_info_sources_get_entry(
275 struct proc_debug_info_sources *proc_dbg_info_src, uint64_t ip)
276{
277 struct debug_info_source *debug_info_src = NULL;
71235b6d 278 gpointer key = g_new0(uint64_t, 1);
b5a8598f
AB
279 GHashTableIter iter;
280 gpointer baddr, value;
281
71235b6d
JG
282 if (!key) {
283 goto end;
284 }
285
286 *((uint64_t *) key) = ip;
287
b5a8598f
AB
288 /* Look in IP to debug infos hash table first. */
289 debug_info_src = g_hash_table_lookup(
290 proc_dbg_info_src->ip_to_debug_info_src,
71235b6d 291 key);
b5a8598f
AB
292 if (debug_info_src) {
293 goto end;
294 }
295
296 /* Check in all so_infos. */
297 g_hash_table_iter_init(&iter, proc_dbg_info_src->baddr_to_so_info);
298
299 while (g_hash_table_iter_next(&iter, &baddr, &value))
300 {
301 struct so_info *so = value;
302
303 if (!so_info_has_address(value, ip)) {
304 continue;
305 }
306
71235b6d
JG
307 /*
308 * Found; add it to cache.
309 *
310 * FIXME: this should be bounded in size (and implement
311 * a caching policy), and entries should be prunned when
312 * libraries are unmapped.
313 */
b5a8598f
AB
314 debug_info_src = debug_info_source_create_from_so(so, ip);
315 if (debug_info_src) {
316 g_hash_table_insert(
317 proc_dbg_info_src->ip_to_debug_info_src,
71235b6d
JG
318 key, debug_info_src);
319 /* Ownership passed to ht. */
320 key = NULL;
b5a8598f
AB
321 }
322 break;
323 }
324
325end:
71235b6d 326 free(key);
b5a8598f
AB
327 return debug_info_src;
328}
329
330BT_HIDDEN
331struct debug_info_source *debug_info_query(struct debug_info *debug_info,
332 int64_t vpid, uint64_t ip)
333{
334 struct debug_info_source *dbg_info_src = NULL;
335 struct proc_debug_info_sources *proc_dbg_info_src;
336
337 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
338 debug_info->vpid_to_proc_dbg_info_src, vpid);
339 if (!proc_dbg_info_src) {
340 goto end;
341 }
342
343 dbg_info_src = proc_debug_info_sources_get_entry(
344 proc_dbg_info_src, ip);
345 if (!dbg_info_src) {
346 goto end;
347 }
348
349end:
350 return dbg_info_src;
351}
352
353BT_HIDDEN
354struct debug_info *debug_info_create(void)
355{
356 int ret;
357 struct debug_info *debug_info;
358
359 debug_info = g_new0(struct debug_info, 1);
360 if (!debug_info) {
361 goto end;
362 }
363
71235b6d
JG
364 debug_info->vpid_to_proc_dbg_info_src = g_hash_table_new_full(
365 g_int64_hash, g_int64_equal, (GDestroyNotify) g_free,
b5a8598f
AB
366 (GDestroyNotify) proc_debug_info_sources_destroy);
367 if (!debug_info->vpid_to_proc_dbg_info_src) {
368 goto error;
369 }
370
371 ret = debug_info_init(debug_info);
372 if (ret) {
373 goto error;
374 }
375
376end:
377 return debug_info;
378error:
379 g_free(debug_info);
380 return NULL;
381}
382
383BT_HIDDEN
384void debug_info_destroy(struct debug_info *debug_info)
385{
386 if (!debug_info) {
387 goto end;
388 }
389
390 if (debug_info->vpid_to_proc_dbg_info_src) {
391 g_hash_table_destroy(debug_info->vpid_to_proc_dbg_info_src);
392 }
393
394 g_free(debug_info);
395end:
396 return;
397}
398
399static
400void handle_statedump_build_id_event(struct debug_info *debug_info,
401 struct ctf_event_definition *event_def)
402{
403 struct proc_debug_info_sources *proc_dbg_info_src;
404 struct bt_definition *event_fields_def = NULL;
405 struct bt_definition *sec_def = NULL;
406 struct bt_definition *baddr_def = NULL;
407 struct bt_definition *vpid_def = NULL;
408 struct bt_definition *build_id_def = NULL;
409 struct definition_sequence *build_id_seq;
410 struct so_info *so = NULL;
411 int i;
412 int64_t vpid;
413 uint64_t baddr;
414 uint8_t *build_id = NULL;
415 uint64_t build_id_len;
416
417 event_fields_def = (struct bt_definition *) event_def->event_fields;
418 sec_def = (struct bt_definition *)
419 event_def->stream->stream_event_context;
420
421 if (!event_fields_def || !sec_def) {
422 goto end;
423 }
424
425 baddr_def = bt_lookup_definition(event_fields_def, "_baddr");
426 if (!baddr_def) {
427 goto end;
428 }
429
430 vpid_def = bt_lookup_definition(sec_def, "_vpid");
431 if (!vpid_def) {
432 goto end;
433 }
434
435 build_id_def = bt_lookup_definition(event_fields_def, "_build_id");
436 if (!build_id_def) {
437 goto end;
438 }
439
440 if (baddr_def->declaration->id != CTF_TYPE_INTEGER) {
441 goto end;
442 }
443
444 if (vpid_def->declaration->id != CTF_TYPE_INTEGER) {
445 goto end;
446 }
447
448 if (build_id_def->declaration->id != CTF_TYPE_SEQUENCE) {
449 goto end;
450 }
451
452 baddr = bt_get_unsigned_int(baddr_def);
453 vpid = bt_get_signed_int(vpid_def);
454 build_id_seq = container_of(build_id_def,
455 struct definition_sequence, p);
456 build_id_len = build_id_seq->length->value._unsigned;
457
458 build_id = g_malloc(build_id_len);
459 if (!build_id) {
460 goto end;
461 }
462
463 for (i = 0; i < build_id_len; ++i) {
464 struct bt_definition **field;
465
466 field = (struct bt_definition **) &g_ptr_array_index(
467 build_id_seq->elems, i);
468 build_id[i] = bt_get_unsigned_int(*field);
469 }
470
471 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
472 debug_info->vpid_to_proc_dbg_info_src, vpid);
473 if (!proc_dbg_info_src) {
474 goto end;
475 }
476
477 so = g_hash_table_lookup(proc_dbg_info_src->baddr_to_so_info,
478 (gpointer) &baddr);
479 if (!so) {
480 /*
481 * The build_id event comes after the so has been
482 * created. If it isn't found, just ignore this event.
483 */
484 goto end;
485 }
486
487 so_info_set_build_id(so, build_id, build_id_len);
488
489end:
490 free(build_id);
491 return;
492}
493
494static
495void handle_statedump_debug_link_event(struct debug_info *debug_info,
496 struct ctf_event_definition *event_def)
497{
498 struct proc_debug_info_sources *proc_dbg_info_src;
499 struct bt_definition *event_fields_def = NULL;
500 struct bt_definition *sec_def = NULL;
501 struct bt_definition *baddr_def = NULL;
502 struct bt_definition *vpid_def = NULL;
503 struct bt_definition *filename_def = NULL;
504 struct bt_definition *crc32_def = NULL;
505 struct so_info *so = NULL;
506 int64_t vpid;
507 uint64_t baddr;
508 char *filename = NULL;
509 uint32_t crc32;
510
511 event_fields_def = (struct bt_definition *) event_def->event_fields;
512 sec_def = (struct bt_definition *)
513 event_def->stream->stream_event_context;
514
515 if (!event_fields_def || !sec_def) {
516 goto end;
517 }
518
519 baddr_def = bt_lookup_definition(event_fields_def, "_baddr");
520 if (!baddr_def) {
521 goto end;
522 }
523
524 vpid_def = bt_lookup_definition(sec_def, "_vpid");
525 if (!vpid_def) {
526 goto end;
527 }
528
529 filename_def = bt_lookup_definition(event_fields_def, "_filename");
530 if (!filename_def) {
531 goto end;
532 }
533
534 crc32_def = bt_lookup_definition(event_fields_def, "_crc32");
535 if (!crc32_def) {
536 goto end;
537 }
538
539 if (baddr_def->declaration->id != CTF_TYPE_INTEGER) {
540 goto end;
541 }
542
543 if (vpid_def->declaration->id != CTF_TYPE_INTEGER) {
544 goto end;
545 }
546
547 if (filename_def->declaration->id != CTF_TYPE_STRING) {
548 goto end;
549 }
550
551 if (crc32_def->declaration->id != CTF_TYPE_INTEGER) {
552 goto end;
553 }
554
555 baddr = bt_get_unsigned_int(baddr_def);
556 vpid = bt_get_signed_int(vpid_def);
557
558 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
559 debug_info->vpid_to_proc_dbg_info_src, vpid);
560 if (!proc_dbg_info_src) {
561 goto end;
562 }
563
564 so = g_hash_table_lookup(proc_dbg_info_src->baddr_to_so_info,
565 (gpointer) &baddr);
566 if (!so) {
567 /*
568 * The debug_link event comes after the so has been
569 * created. If it isn't found, just ignore this event.
570 */
571 goto end;
572 }
573
574 filename = bt_get_string(filename_def);
575 crc32 = bt_get_unsigned_int(crc32_def);
576
577 so_info_set_debug_link(so, filename, crc32);
578
579end:
580 return;
581}
582
583static
584void handle_statedump_soinfo_event(struct debug_info *debug_info,
585 struct ctf_event_definition *event_def)
586{
587 struct bt_definition *baddr_def = NULL;
588 struct bt_definition *memsz_def = NULL;
589 struct bt_definition *sopath_def = NULL;
590 struct bt_definition *vpid_def = NULL;
591 struct bt_definition *event_fields_def = NULL;
592 struct bt_definition *sec_def = NULL;
593 struct proc_debug_info_sources *proc_dbg_info_src;
594 struct so_info *so;
595 uint64_t baddr, memsz;
596 int64_t vpid;
597 const char *sopath;
71235b6d 598 gpointer key = NULL;
b5a8598f
AB
599
600 event_fields_def = (struct bt_definition *) event_def->event_fields;
601 sec_def = (struct bt_definition *)
602 event_def->stream->stream_event_context;
603
604 if (!event_fields_def || !sec_def) {
605 goto end;
606 }
607
608 baddr_def = bt_lookup_definition(event_fields_def, "_baddr");
609 if (!baddr_def) {
610 goto end;
611 }
612
613 memsz_def = bt_lookup_definition(event_fields_def, "_memsz");
614 if (!memsz_def) {
615 goto end;
616 }
617
618 sopath_def = bt_lookup_definition(event_fields_def, "_sopath");
619 if (!sopath_def) {
620 goto end;
621 }
622
623 vpid_def = bt_lookup_definition(sec_def, "_vpid");
624 if (!vpid_def) {
625 goto end;
626 }
627
628 if (baddr_def->declaration->id != CTF_TYPE_INTEGER) {
629 goto end;
630 }
631
632 if (memsz_def->declaration->id != CTF_TYPE_INTEGER) {
633 goto end;
634 }
635
636 if (sopath_def->declaration->id != CTF_TYPE_STRING) {
637 goto end;
638 }
639
640 if (vpid_def->declaration->id != CTF_TYPE_INTEGER) {
641 goto end;
642 }
643
644 baddr = bt_get_unsigned_int(baddr_def);
645 memsz = bt_get_unsigned_int(memsz_def);
646 sopath = bt_get_string(sopath_def);
647 vpid = bt_get_signed_int(vpid_def);
648
649 if (!sopath) {
650 goto end;
651 }
652
653 if (memsz == 0) {
654 /* Ignore VDSO. */
655 goto end;
656 }
657
658 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
659 debug_info->vpid_to_proc_dbg_info_src, vpid);
660 if (!proc_dbg_info_src) {
661 goto end;
662 }
663
71235b6d
JG
664 key = g_new0(uint64_t, 1);
665 if (!key) {
666 goto end;
667 }
668
669 *((uint64_t *) key) = baddr;
670
b5a8598f 671 so = g_hash_table_lookup(proc_dbg_info_src->baddr_to_so_info,
71235b6d 672 key);
b5a8598f
AB
673 if (so) {
674 goto end;
675 }
676
677 so = so_info_create(sopath, baddr, memsz);
678 if (!so) {
679 goto end;
680 }
681
682 g_hash_table_insert(proc_dbg_info_src->baddr_to_so_info,
71235b6d
JG
683 key, so);
684 /* Ownership passed to ht. */
685 key = NULL;
b5a8598f
AB
686
687end:
71235b6d 688 g_free(key);
b5a8598f
AB
689 return;
690}
691
692static
693void handle_statedump_start(struct debug_info *debug_info,
694 struct ctf_event_definition *event_def)
695{
696 struct bt_definition *vpid_def = NULL;
697 struct bt_definition *sec_def = NULL;
698 struct proc_debug_info_sources *proc_dbg_info_src;
699 int64_t vpid;
700
701 sec_def = (struct bt_definition *)
702 event_def->stream->stream_event_context;
703 if (!sec_def) {
704 goto end;
705 }
706
707 vpid_def = bt_lookup_definition(sec_def, "_vpid");
708 if (!vpid_def) {
709 goto end;
710 }
711
712 vpid = bt_get_signed_int(vpid_def);
713
714 proc_dbg_info_src = proc_debug_info_sources_ht_get_entry(
715 debug_info->vpid_to_proc_dbg_info_src, vpid);
716 if (!proc_dbg_info_src) {
717 goto end;
718 }
719
720 g_hash_table_remove_all(proc_dbg_info_src->baddr_to_so_info);
721 g_hash_table_remove_all(proc_dbg_info_src->ip_to_debug_info_src);
722
723end:
724 return;
725}
726
727static
728void register_event_debug_infos(struct debug_info *debug_info,
729 struct ctf_event_definition *event)
730{
731 struct bt_definition *ip_def, *vpid_def;
732 int64_t vpid;
733 uint64_t ip;
734 struct bt_definition *sec_def;
735
736 /* Get stream event context definition. */
737 sec_def = (struct bt_definition *) event->stream->stream_event_context;
738 if (!sec_def) {
739 goto end;
740 }
741
742 /* Get "ip" and "vpid" definitions. */
743 vpid_def = bt_lookup_definition((struct bt_definition *) sec_def,
744 "_vpid");
745 ip_def = bt_lookup_definition((struct bt_definition *) sec_def, "_ip");
746
747 if (!vpid_def || !ip_def) {
748 goto end;
749 }
750
751 vpid = bt_get_signed_int(vpid_def);
752 ip = bt_get_unsigned_int(ip_def);
753
754 /* Get debug info for this context. */
755 ((struct definition_integer *) ip_def)->debug_info_src =
756 debug_info_query(debug_info, vpid, ip);
757
758end:
759 return;
760}
761
762BT_HIDDEN
763void debug_info_handle_event(struct debug_info *debug_info,
764 struct ctf_event_definition *event)
765{
766 struct ctf_event_declaration *event_class;
767 struct ctf_stream_declaration *stream_class;
768
769 if (!debug_info || !event) {
770 goto end;
771 }
772
773 stream_class = event->stream->stream_class;
774 event_class = g_ptr_array_index(stream_class->events_by_id,
775 event->stream->event_id);
776
777 if (event_class->name == debug_info->q_statedump_soinfo ||
778 event_class->name == debug_info->q_dl_open) {
779 /* State dump/dlopen() */
780 handle_statedump_soinfo_event(debug_info, event);
781 } else if (event_class->name == debug_info->q_statedump_start) {
782 /* Start state dump */
783 handle_statedump_start(debug_info, event);
784 } else if (event_class->name == debug_info->q_statedump_debug_link) {
785 /* Debug link info */
786 handle_statedump_debug_link_event(debug_info, event);
787 } else if (event_class->name == debug_info->q_statedump_build_id) {
788 /* Build ID info */
789 handle_statedump_build_id_event(debug_info, event);
790 } else {
791 /* Other events: register debug infos */
792 register_event_debug_infos(debug_info, event);
793 }
794
795end:
796 return;
797}
This page took 0.050956 seconds and 4 git commands to generate.