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)) 24 static void debuginfo_init(void) 25 { 26 qemu_mutex_init(&lock); 27 } 28 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 45 void debuginfo_lock(void) 46 { 47 qemu_mutex_lock(&lock); 48 } 49 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 93 void debuginfo_unlock(void) 94 { 95 qemu_mutex_unlock(&lock); 96 } 97