]>
Commit | Line | Data |
---|---|---|
7c10cb38 IL |
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" | |
327b75a4 | 9 | #include "tcg/debuginfo.h" |
7c10cb38 IL |
10 | |
11 | #include <elfutils/libdwfl.h> | |
12 | ||
7c10cb38 IL |
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 | } |