Ilya Leoshkevich writes:
> Add ability to dump /tmp/perf-.map and jit-.dump.
> The first one allows the perf tool to map samples to each individual
> translation block. The second one adds the ability to resolve symbol
> names, line numbers and inspect JITed code.
>
> Example of use:
>
> perf record qemu-x86_64 -perfmap ./a.out
> perf report
>
> or
>
> perf record -k 1 qemu-x86_64 -jitdump ./a.out
> perf inject -j -i perf.data -o perf.data.jitted
> perf report -i perf.data.jitted
>
> Co-developed-by: Vanderson M. do Rosario
> Co-developed-by: Alex Bennée
> Signed-off-by: Ilya Leoshkevich
> ---
> accel/tcg/debuginfo.c | 108 +
> accel/tcg/debuginfo.h | 54 +++
> accel/tcg/meson.build | 2 +
> accel/tcg/perf.c | 333 ++
> accel/tcg/perf.h | 28
> accel/tcg/translate-all.c | 3 +
> docs/devel/tcg.rst| 20 +++
> linux-user/elfload.c | 3 +
> linux-user/exit.c | 2 +
> linux-user/main.c | 15 ++
> linux-user/meson.build| 1 +
> meson.build | 8 +
> qemu-options.hx | 20 +++
> softmmu/vl.c | 11 ++
> tcg/tcg.c | 2 +
> 15 files changed, 610 insertions(+)
> create mode 100644 accel/tcg/debuginfo.c
> create mode 100644 accel/tcg/debuginfo.h
> create mode 100644 accel/tcg/perf.c
> create mode 100644 accel/tcg/perf.h
>
> diff --git a/accel/tcg/debuginfo.c b/accel/tcg/debuginfo.c
> new file mode 100644
> index 00..904eb23103
> --- /dev/null
> +++ b/accel/tcg/debuginfo.c
> @@ -0,0 +1,108 @@
> +/*
> + * Debug information support.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +
> +#include
> +
> +#include "debuginfo.h"
> +
> +static QemuMutex lock;
> +static Dwfl *dwfl;
> +static const Dwfl_Callbacks dwfl_callbacks = {
> +.find_elf = NULL,
> +.find_debuginfo = dwfl_standard_find_debuginfo,
> +.section_address = NULL,
> +.debuginfo_path = NULL,
> +};
> +
> +__attribute__((constructor))
> +static void debuginfo_init(void)
> +{
> +qemu_mutex_init();
> +}
> +
> +bool debuginfo_report_elf(const char *image_name, int image_fd,
> + target_ulong load_bias)
> +{
> +qemu_mutex_lock();
You can wrap this up with a QEMU_LOCK_GUARD() { and avoid having to
catch all your exit cases.
> +
> +if (dwfl == NULL) {
> +dwfl = dwfl_begin(_callbacks);
> +} else {
> +dwfl_report_begin_add(dwfl);
> +}
> +
> +if (dwfl == NULL) {
> +qemu_mutex_unlock();
> +return false;
> +}
> +
> +dwfl_report_elf(dwfl, image_name, image_name, image_fd, load_bias, true);
> +dwfl_report_end(dwfl, NULL, NULL);
> +qemu_mutex_unlock();
> +return true;
> +}
> +
> +bool debuginfo_get_symbol(target_ulong address,
> + const char **symbol, target_ulong *offset)
> +{
> +Dwfl_Module *dwfl_module;
> +GElf_Off dwfl_offset;
> +GElf_Sym dwfl_sym;
> +
> +qemu_mutex_lock();
> +
> +if (dwfl == NULL) {
> +qemu_mutex_unlock();
> +return false;
> +}
> +
> +dwfl_module = dwfl_addrmodule(dwfl, address);
> +if (dwfl_module == NULL) {
> +qemu_mutex_unlock();
> +return false;
> +}
> +
> +*symbol = dwfl_module_addrinfo(dwfl_module, address, _offset,
> + _sym, NULL, NULL, NULL);
> +if (*symbol == NULL) {
> +qemu_mutex_unlock();
> +return false;
> +}
> +*offset = dwfl_offset;
> +qemu_mutex_unlock();
> +return true;
> +}
> +
> +bool debuginfo_get_line(target_ulong address,
> +const char **file, int *line)
> +{
> +Dwfl_Module *dwfl_module;
> +Dwfl_Line *dwfl_line;
> +
> +qemu_mutex_lock();
ditto.
> +
> +if (dwfl == NULL) {
> +qemu_mutex_unlock();
> +return false;
> +}
> +
> +dwfl_module = dwfl_addrmodule(dwfl, address);
> +if (dwfl_module == NULL) {
> +qemu_mutex_unlock();
> +return false;
> +}
> +
> +dwfl_line = dwfl_module_getsrc(dwfl_module, address);
> +if (dwfl_line == NULL) {
> +qemu_mutex_unlock();
> +return false;
> +}
> +*file = dwfl_lineinfo(dwfl_line, NULL, line, 0, NULL, NULL);
> +qemu_mutex_unlock();
> +return true;
> +}
> diff --git a/accel/tcg/debuginfo.h b/accel/tcg/debuginfo.h
> new file mode 100644
> index 00..f4f22aa786
> --- /dev/null
> +++ b/accel/tcg/debuginfo.h
> @@ -0,0 +1,54 @@
> +/*
> + * Debug information support.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#ifndef ACCEL_TCG_DEBUGINFO_H
> +#define ACCEL_TCG_DEBUGINFO_H
> +
> +#include "exec/cpu-defs.h"
> +
> +#ifdef CONFIG_LIBDW
> +/*
> + * Load debuginfo for the specified guest ELF image.
> + * Return true on success, false on failure.
> + */
> +bool debuginfo_report_elf(const char *image_name, int