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