xref: /openbmc/qemu/tcg/debuginfo.c (revision b887b6b7)
1 /*
2  * Debug information support.
3  *
4  * SPDX-License-Identifier: GPL-2.0-or-later
5  */
6 
7 #include "qemu/osdep.h"
8 #include "qemu/lockable.h"
9 #include "tcg/debuginfo.h"
10 
11 #include <elfutils/libdwfl.h>
12 
13 static QemuMutex lock;
14 static Dwfl *dwfl;
15 static const Dwfl_Callbacks dwfl_callbacks = {
16     .find_elf = NULL,
17     .find_debuginfo = dwfl_standard_find_debuginfo,
18     .section_address = NULL,
19     .debuginfo_path = NULL,
20 };
21 
22 __attribute__((constructor))
23 static void debuginfo_init(void)
24 {
25     qemu_mutex_init(&lock);
26 }
27 
28 void debuginfo_report_elf(const char *name, int fd, uint64_t bias)
29 {
30     QEMU_LOCK_GUARD(&lock);
31 
32     if (dwfl) {
33         dwfl_report_begin_add(dwfl);
34     } else {
35         dwfl = dwfl_begin(&dwfl_callbacks);
36     }
37 
38     if (dwfl) {
39         dwfl_report_elf(dwfl, name, name, fd, bias, true);
40         dwfl_report_end(dwfl, NULL, NULL);
41     }
42 }
43 
44 void debuginfo_lock(void)
45 {
46     qemu_mutex_lock(&lock);
47 }
48 
49 void debuginfo_query(struct debuginfo_query *q, size_t n)
50 {
51     const char *symbol, *file;
52     Dwfl_Module *dwfl_module;
53     Dwfl_Line *dwfl_line;
54     GElf_Off dwfl_offset;
55     GElf_Sym dwfl_sym;
56     size_t i;
57     int line;
58 
59     if (!dwfl) {
60         return;
61     }
62 
63     for (i = 0; i < n; i++) {
64         dwfl_module = dwfl_addrmodule(dwfl, q[i].address);
65         if (!dwfl_module) {
66             continue;
67         }
68 
69         if (q[i].flags & DEBUGINFO_SYMBOL) {
70             symbol = dwfl_module_addrinfo(dwfl_module, q[i].address,
71                                           &dwfl_offset, &dwfl_sym,
72                                           NULL, NULL, NULL);
73             if (symbol) {
74                 q[i].symbol = symbol;
75                 q[i].offset = dwfl_offset;
76             }
77         }
78 
79         if (q[i].flags & DEBUGINFO_LINE) {
80             dwfl_line = dwfl_module_getsrc(dwfl_module, q[i].address);
81             if (dwfl_line) {
82                 file = dwfl_lineinfo(dwfl_line, NULL, &line, 0, NULL, NULL);
83                 if (file) {
84                     q[i].file = file;
85                     q[i].line = line;
86                 }
87             }
88         }
89     }
90 }
91 
92 void debuginfo_unlock(void)
93 {
94     qemu_mutex_unlock(&lock);
95 }
96