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