17c10cb38SIlya Leoshkevich /*
27c10cb38SIlya Leoshkevich * Debug information support.
37c10cb38SIlya Leoshkevich *
47c10cb38SIlya Leoshkevich * SPDX-License-Identifier: GPL-2.0-or-later
57c10cb38SIlya Leoshkevich */
67c10cb38SIlya Leoshkevich
77c10cb38SIlya Leoshkevich #include "qemu/osdep.h"
87c10cb38SIlya Leoshkevich #include "qemu/lockable.h"
9*327b75a4SIlya Leoshkevich #include "tcg/debuginfo.h"
107c10cb38SIlya Leoshkevich
117c10cb38SIlya Leoshkevich #include <elfutils/libdwfl.h>
127c10cb38SIlya Leoshkevich
137c10cb38SIlya Leoshkevich static QemuMutex lock;
147c10cb38SIlya Leoshkevich static Dwfl *dwfl;
157c10cb38SIlya Leoshkevich static const Dwfl_Callbacks dwfl_callbacks = {
167c10cb38SIlya Leoshkevich .find_elf = NULL,
177c10cb38SIlya Leoshkevich .find_debuginfo = dwfl_standard_find_debuginfo,
187c10cb38SIlya Leoshkevich .section_address = NULL,
197c10cb38SIlya Leoshkevich .debuginfo_path = NULL,
207c10cb38SIlya Leoshkevich };
217c10cb38SIlya Leoshkevich
227c10cb38SIlya Leoshkevich __attribute__((constructor))
debuginfo_init(void)237c10cb38SIlya Leoshkevich static void debuginfo_init(void)
247c10cb38SIlya Leoshkevich {
257c10cb38SIlya Leoshkevich qemu_mutex_init(&lock);
267c10cb38SIlya Leoshkevich }
277c10cb38SIlya Leoshkevich
debuginfo_report_elf(const char * name,int fd,uint64_t bias)287c10cb38SIlya Leoshkevich void debuginfo_report_elf(const char *name, int fd, uint64_t bias)
297c10cb38SIlya Leoshkevich {
307c10cb38SIlya Leoshkevich QEMU_LOCK_GUARD(&lock);
317c10cb38SIlya Leoshkevich
327c10cb38SIlya Leoshkevich if (dwfl) {
337c10cb38SIlya Leoshkevich dwfl_report_begin_add(dwfl);
347c10cb38SIlya Leoshkevich } else {
357c10cb38SIlya Leoshkevich dwfl = dwfl_begin(&dwfl_callbacks);
367c10cb38SIlya Leoshkevich }
377c10cb38SIlya Leoshkevich
387c10cb38SIlya Leoshkevich if (dwfl) {
397c10cb38SIlya Leoshkevich dwfl_report_elf(dwfl, name, name, fd, bias, true);
407c10cb38SIlya Leoshkevich dwfl_report_end(dwfl, NULL, NULL);
417c10cb38SIlya Leoshkevich }
427c10cb38SIlya Leoshkevich }
437c10cb38SIlya Leoshkevich
debuginfo_lock(void)447c10cb38SIlya Leoshkevich void debuginfo_lock(void)
457c10cb38SIlya Leoshkevich {
467c10cb38SIlya Leoshkevich qemu_mutex_lock(&lock);
477c10cb38SIlya Leoshkevich }
487c10cb38SIlya Leoshkevich
debuginfo_query(struct debuginfo_query * q,size_t n)497c10cb38SIlya Leoshkevich void debuginfo_query(struct debuginfo_query *q, size_t n)
507c10cb38SIlya Leoshkevich {
517c10cb38SIlya Leoshkevich const char *symbol, *file;
527c10cb38SIlya Leoshkevich Dwfl_Module *dwfl_module;
537c10cb38SIlya Leoshkevich Dwfl_Line *dwfl_line;
547c10cb38SIlya Leoshkevich GElf_Off dwfl_offset;
557c10cb38SIlya Leoshkevich GElf_Sym dwfl_sym;
567c10cb38SIlya Leoshkevich size_t i;
577c10cb38SIlya Leoshkevich int line;
587c10cb38SIlya Leoshkevich
597c10cb38SIlya Leoshkevich if (!dwfl) {
607c10cb38SIlya Leoshkevich return;
617c10cb38SIlya Leoshkevich }
627c10cb38SIlya Leoshkevich
637c10cb38SIlya Leoshkevich for (i = 0; i < n; i++) {
647c10cb38SIlya Leoshkevich dwfl_module = dwfl_addrmodule(dwfl, q[i].address);
657c10cb38SIlya Leoshkevich if (!dwfl_module) {
667c10cb38SIlya Leoshkevich continue;
677c10cb38SIlya Leoshkevich }
687c10cb38SIlya Leoshkevich
697c10cb38SIlya Leoshkevich if (q[i].flags & DEBUGINFO_SYMBOL) {
707c10cb38SIlya Leoshkevich symbol = dwfl_module_addrinfo(dwfl_module, q[i].address,
717c10cb38SIlya Leoshkevich &dwfl_offset, &dwfl_sym,
727c10cb38SIlya Leoshkevich NULL, NULL, NULL);
737c10cb38SIlya Leoshkevich if (symbol) {
747c10cb38SIlya Leoshkevich q[i].symbol = symbol;
757c10cb38SIlya Leoshkevich q[i].offset = dwfl_offset;
767c10cb38SIlya Leoshkevich }
777c10cb38SIlya Leoshkevich }
787c10cb38SIlya Leoshkevich
797c10cb38SIlya Leoshkevich if (q[i].flags & DEBUGINFO_LINE) {
807c10cb38SIlya Leoshkevich dwfl_line = dwfl_module_getsrc(dwfl_module, q[i].address);
817c10cb38SIlya Leoshkevich if (dwfl_line) {
827c10cb38SIlya Leoshkevich file = dwfl_lineinfo(dwfl_line, NULL, &line, 0, NULL, NULL);
837c10cb38SIlya Leoshkevich if (file) {
847c10cb38SIlya Leoshkevich q[i].file = file;
857c10cb38SIlya Leoshkevich q[i].line = line;
867c10cb38SIlya Leoshkevich }
877c10cb38SIlya Leoshkevich }
887c10cb38SIlya Leoshkevich }
897c10cb38SIlya Leoshkevich }
907c10cb38SIlya Leoshkevich }
917c10cb38SIlya Leoshkevich
debuginfo_unlock(void)927c10cb38SIlya Leoshkevich void debuginfo_unlock(void)
937c10cb38SIlya Leoshkevich {
947c10cb38SIlya Leoshkevich qemu_mutex_unlock(&lock);
957c10cb38SIlya Leoshkevich }
96