xref: /qemu/tcg/debuginfo.c (revision 327b75a469f2e7c3894e7b5c44f817df51064033)
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