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