perf unwind-libunwind: Move flush/finish access out of local

Flush and finish access are relatively simple calls into libunwind,
move them out struct unwind_libunwind_ops. So that the correct version
can be called, add an e_machine variable to maps. This size regression
will go away when the unwind_libunwind_ops no longer need stashing in
the maps. To set the e_machine up pass it into unwind__prepare_access,
which no longer needs to determine the unwind operations based on a
map dso because of this. This also means the maps copying code can
call unwind__prepare_access once for the e_machine rather than once
per map.

Signed-off-by: Ian Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alexandre Ghiti <alex@ghiti.fr>
Cc: Andrew Jones <andrew.jones@oss.qualcomm.com>
Cc: Athira Rajeev <atrajeev@linux.ibm.com>
Cc: Dapeng Mi <dapeng1.mi@linux.intel.com>
Cc: Dmitrii Dolgov <9erthalion6@gmail.com>
Cc: Florian Fainelli <florian.fainelli@broadcom.com>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: John Garry <john.g.garry@oracle.com>
Cc: Leo Yan <leo.yan@linux.dev>
Cc: Li Guan <guanli.oerv@isrc.iscas.ac.cn>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Paul Walmsley <pjw@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Shimin Guo <shimin.guo@skydio.com>
Cc: Thomas Richter <tmricht@linux.ibm.com>
Cc: Tomas Glozar <tglozar@redhat.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Ian Rogers 2026-05-13 16:31:49 -07:00 committed by Arnaldo Carvalho de Melo
parent fdf08e4b5a
commit 2723e9f8b5
17 changed files with 309 additions and 90 deletions

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "libunwind-arch.h"
#include "../debug.h"
#include "../maps.h"
#include <elf.h>
#include <errno.h>
@ -30,3 +31,84 @@ int get_perf_regnum_for_unw_regnum(unsigned int e_machine, int unw_regnum)
return -EINVAL;
}
}
void libunwind_arch__flush_access(struct maps *maps)
{
unsigned int e_machine = maps__e_machine(maps);
switch (e_machine) {
case EM_NONE:
break; // No libunwind info on the maps.
case EM_ARM:
__libunwind_arch__flush_access_arm(maps);
break;
case EM_AARCH64:
__libunwind_arch__flush_access_arm64(maps);
break;
case EM_LOONGARCH:
__libunwind_arch__flush_access_loongarch(maps);
break;
case EM_MIPS:
__libunwind_arch__flush_access_mips(maps);
break;
case EM_PPC:
__libunwind_arch__flush_access_ppc32(maps);
break;
case EM_PPC64:
__libunwind_arch__flush_access_ppc64(maps);
break;
case EM_S390:
__libunwind_arch__flush_access_s390(maps);
break;
case EM_386:
__libunwind_arch__flush_access_i386(maps);
break;
case EM_X86_64:
__libunwind_arch__flush_access_x86_64(maps);
break;
default:
pr_err("ELF MACHINE %x is not supported.\n", e_machine);
break;
}
}
void libunwind_arch__finish_access(struct maps *maps)
{
unsigned int e_machine = maps__e_machine(maps);
switch (e_machine) {
case EM_NONE:
break; // No libunwind info on the maps.
case EM_ARM:
__libunwind_arch__finish_access_arm(maps);
break;
case EM_AARCH64:
__libunwind_arch__finish_access_arm64(maps);
break;
case EM_LOONGARCH:
__libunwind_arch__finish_access_loongarch(maps);
break;
case EM_MIPS:
__libunwind_arch__finish_access_mips(maps);
break;
case EM_PPC:
__libunwind_arch__finish_access_ppc32(maps);
break;
case EM_PPC64:
__libunwind_arch__finish_access_ppc64(maps);
break;
case EM_S390:
__libunwind_arch__finish_access_s390(maps);
break;
case EM_386:
__libunwind_arch__finish_access_i386(maps);
break;
case EM_X86_64:
__libunwind_arch__finish_access_x86_64(maps);
break;
default:
pr_err("ELF MACHINE %x is not supported.\n", e_machine);
break;
}
}

View File

@ -2,6 +2,8 @@
#ifndef __LIBUNWIND_ARCH_H
#define __LIBUNWIND_ARCH_H
struct maps;
int __get_perf_regnum_for_unw_regnum_arm(int unw_regnum);
int __get_perf_regnum_for_unw_regnum_arm64(int unw_regnum);
int __get_perf_regnum_for_unw_regnum_loongarch(int unw_regnum);
@ -13,4 +15,26 @@ int __get_perf_regnum_for_unw_regnum_i386(int unw_regnum);
int __get_perf_regnum_for_unw_regnum_x86_64(int unw_regnum);
int get_perf_regnum_for_unw_regnum(unsigned int e_machine, int unw_regnum);
void __libunwind_arch__flush_access_arm(struct maps *maps);
void __libunwind_arch__flush_access_arm64(struct maps *maps);
void __libunwind_arch__flush_access_loongarch(struct maps *maps);
void __libunwind_arch__flush_access_mips(struct maps *maps);
void __libunwind_arch__flush_access_ppc32(struct maps *maps);
void __libunwind_arch__flush_access_ppc64(struct maps *maps);
void __libunwind_arch__flush_access_s390(struct maps *maps);
void __libunwind_arch__flush_access_i386(struct maps *maps);
void __libunwind_arch__flush_access_x86_64(struct maps *maps);
void libunwind_arch__flush_access(struct maps *maps);
void __libunwind_arch__finish_access_arm(struct maps *maps);
void __libunwind_arch__finish_access_arm64(struct maps *maps);
void __libunwind_arch__finish_access_loongarch(struct maps *maps);
void __libunwind_arch__finish_access_mips(struct maps *maps);
void __libunwind_arch__finish_access_ppc32(struct maps *maps);
void __libunwind_arch__finish_access_ppc64(struct maps *maps);
void __libunwind_arch__finish_access_s390(struct maps *maps);
void __libunwind_arch__finish_access_i386(struct maps *maps);
void __libunwind_arch__finish_access_x86_64(struct maps *maps);
void libunwind_arch__finish_access(struct maps *maps);
#endif /* __LIBUNWIND_ARCH_H */

View File

@ -1,10 +1,15 @@
// SPDX-License-Identifier: GPL-2.0
#include "libunwind-arch.h"
#include "../debug.h"
#include "../maps.h"
#include "../../../arch/arm/include/uapi/asm/perf_regs.h"
#include <linux/compiler.h>
#include <errno.h>
#ifdef HAVE_LIBUNWIND_ARM_SUPPORT
#include <libunwind-arm.h>
#endif
int __get_perf_regnum_for_unw_regnum_arm(int unw_regnum)
{
if (unw_regnum < 0 || unw_regnum >= PERF_REG_ARM_MAX) {
@ -13,3 +18,17 @@ int __get_perf_regnum_for_unw_regnum_arm(int unw_regnum)
}
return unw_regnum;
}
void __libunwind_arch__flush_access_arm(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_ARM_SUPPORT
unw_flush_cache(maps__addr_space(maps), 0, 0);
#endif
}
void __libunwind_arch__finish_access_arm(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_ARM_SUPPORT
unw_destroy_addr_space(maps__addr_space(maps));
#endif
}

View File

@ -1,9 +1,15 @@
// SPDX-License-Identifier: GPL-2.0
#include "libunwind-arch.h"
#include "../debug.h"
#include "../maps.h"
#include "../../../arch/arm64/include/uapi/asm/perf_regs.h"
#include <linux/compiler.h>
#include <errno.h>
#ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT
#include <libunwind-aarch64.h>
#endif
int __get_perf_regnum_for_unw_regnum_arm64(int unw_regnum)
{
if (unw_regnum < 0 || unw_regnum >= PERF_REG_ARM64_EXTENDED_MAX) {
@ -12,3 +18,17 @@ int __get_perf_regnum_for_unw_regnum_arm64(int unw_regnum)
}
return unw_regnum;
}
void __libunwind_arch__flush_access_arm64(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT
unw_flush_cache(maps__addr_space(maps), 0, 0);
#endif
}
void __libunwind_arch__finish_access_arm64(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_AARCH64_SUPPORT
unw_destroy_addr_space(maps__addr_space(maps));
#endif
}

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "libunwind-arch.h"
#include "../debug.h"
#include "../maps.h"
#include "../../../arch/x86/include/uapi/asm/perf_regs.h"
#include <linux/compiler.h>
#include <linux/kernel.h>
@ -41,3 +42,17 @@ int __get_perf_regnum_for_unw_regnum_i386(int unw_regnum __maybe_unused)
return perf_i386_regnums[unw_regnum];
#endif // HAVE_LIBUNWIND_X86_SUPPORT
}
void __libunwind_arch__flush_access_i386(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_X86_SUPPORT
unw_flush_cache(maps__addr_space(maps), 0, 0);
#endif
}
void __libunwind_arch__finish_access_i386(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_X86_SUPPORT
unw_destroy_addr_space(maps__addr_space(maps));
#endif
}

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "libunwind-arch.h"
#include "../debug.h"
#include "../maps.h"
#include "../../../arch/loongarch/include/uapi/asm/perf_regs.h"
#include <linux/compiler.h>
#include <errno.h>
@ -25,3 +26,17 @@ int __get_perf_regnum_for_unw_regnum_loongarch(int unw_regnum __maybe_unused)
}
#endif // HAVE_LIBUNWIND_LOONGARCH64_SUPPORT
}
void __libunwind_arch__flush_access_loongarch(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_LOONGARCH64_SUPPORT
unw_flush_cache(maps__addr_space(maps), 0, 0);
#endif
}
void __libunwind_arch__finish_access_loongarch(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_LOONGARCH64_SUPPORT
unw_destroy_addr_space(maps__addr_space(maps));
#endif
}

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "libunwind-arch.h"
#include "../debug.h"
#include "../maps.h"
#include "../../../arch/mips/include/uapi/asm/perf_regs.h"
#include <linux/compiler.h>
#include <errno.h>
@ -27,3 +28,17 @@ int __get_perf_regnum_for_unw_regnum_mips(int unw_regnum __maybe_unused)
}
#endif // HAVE_LIBUNWIND_MIPS_SUPPORT
}
void __libunwind_arch__flush_access_mips(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_MIPS_SUPPORT
unw_flush_cache(maps__addr_space(maps), 0, 0);
#endif
}
void __libunwind_arch__finish_access_mips(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_MIPS_SUPPORT
unw_destroy_addr_space(maps__addr_space(maps));
#endif
}

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "libunwind-arch.h"
#include "../debug.h"
#include "../maps.h"
#include "../../../arch/powerpc/include/uapi/asm/perf_regs.h"
#include <linux/compiler.h>
#include <errno.h>
@ -31,3 +32,17 @@ int __get_perf_regnum_for_unw_regnum_ppc32(int unw_regnum __maybe_unused)
}
#endif // HAVE_LIBUNWIND_PPC32_SUPPORT
}
void __libunwind_arch__flush_access_ppc32(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_PPC32_SUPPORT
unw_flush_cache(maps__addr_space(maps), 0, 0);
#endif
}
void __libunwind_arch__finish_access_ppc32(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_PPC32_SUPPORT
unw_destroy_addr_space(maps__addr_space(maps));
#endif
}

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "libunwind-arch.h"
#include "../debug.h"
#include "../maps.h"
#include "../../../arch/powerpc/include/uapi/asm/perf_regs.h"
#include <linux/compiler.h>
#include <errno.h>
@ -31,3 +32,17 @@ int __get_perf_regnum_for_unw_regnum_ppc64(int unw_regnum __maybe_unused)
}
#endif // HAVE_LIBUNWIND_PPC64_SUPPORT
}
void __libunwind_arch__flush_access_ppc64(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_PPC64_SUPPORT
unw_flush_cache(maps__addr_space(maps), 0, 0);
#endif
}
void __libunwind_arch__finish_access_ppc64(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_PPC64_SUPPORT
unw_destroy_addr_space(maps__addr_space(maps));
#endif
}

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "libunwind-arch.h"
#include "../debug.h"
#include "../maps.h"
#include "../../../arch/s390/include/uapi/asm/perf_regs.h"
#include <linux/compiler.h>
#include <errno.h>
@ -27,3 +28,17 @@ int __get_perf_regnum_for_unw_regnum_s390(int unw_regnum __maybe_unused)
}
#endif // HAVE_LIBUNWIND_S390X_SUPPORT
}
void __libunwind_arch__flush_access_s390(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_S390X_SUPPORT
unw_flush_cache(maps__addr_space(maps), 0, 0);
#endif
}
void __libunwind_arch__finish_access_s390(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_S390X_SUPPORT
unw_destroy_addr_space(maps__addr_space(maps));
#endif
}

View File

@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
#include "libunwind-arch.h"
#include "../debug.h"
#include "../maps.h"
#include "../../../arch/x86/include/uapi/asm/perf_regs.h"
#include <linux/compiler.h>
#include <linux/kernel.h>
@ -50,3 +51,17 @@ int __get_perf_regnum_for_unw_regnum_x86_64(int unw_regnum __maybe_unused)
return perf_x86_64_regnums[unw_regnum];
#endif // HAVE_LIBUNWIND_X86_64_SUPPORT
}
void __libunwind_arch__flush_access_x86_64(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_X86_64_SUPPORT
unw_flush_cache(maps__addr_space(maps), 0, 0);
#endif
}
void __libunwind_arch__finish_access_x86_64(struct maps *maps __maybe_unused)
{
#ifdef HAVE_LIBUNWIND_X86_64_SUPPORT
unw_destroy_addr_space(maps__addr_space(maps));
#endif
}

View File

@ -40,6 +40,7 @@ DECLARE_RC_STRUCT(maps) {
#ifdef HAVE_LIBUNWIND_SUPPORT
void *addr_space;
const struct unwind_libunwind_ops *unwind_libunwind_ops;
uint16_t e_machine;
#endif
#ifdef HAVE_LIBDW_SUPPORT
void *libdw_addr_space_dwfl;
@ -206,6 +207,16 @@ void maps__set_unwind_libunwind_ops(struct maps *maps, const struct unwind_libun
{
RC_CHK_ACCESS(maps)->unwind_libunwind_ops = ops;
}
uint16_t maps__e_machine(const struct maps *maps)
{
return RC_CHK_ACCESS(maps)->e_machine;
}
void maps__set_e_machine(struct maps *maps, uint16_t e_machine)
{
RC_CHK_ACCESS(maps)->e_machine = e_machine;
}
#endif
#ifdef HAVE_LIBDW_SUPPORT
void *maps__libdw_addr_space_dwfl(const struct maps *maps)
@ -1039,6 +1050,14 @@ int maps__copy_from(struct maps *dest, struct maps *parent)
down_write(maps__lock(dest));
down_read(maps__lock(parent));
#ifdef HAVE_LIBUNWIND_SUPPORT
err = unwind__prepare_access(dest, maps__e_machine(parent));
if (err) {
up_read(maps__lock(parent));
up_write(maps__lock(dest));
return err;
}
#endif
parent_maps_by_address = maps__maps_by_address(parent);
n = maps__nr_maps(parent);
if (maps__nr_maps(dest) == 0) {
@ -1068,14 +1087,11 @@ int maps__copy_from(struct maps *dest, struct maps *parent)
if (!new)
err = -ENOMEM;
else {
err = unwind__prepare_access(dest, new, NULL);
if (!err) {
dest_maps_by_address[i] = new;
map__set_kmap_maps(new, dest);
if (dest_maps_by_name)
dest_maps_by_name[i] = map__get(new);
RC_CHK_ACCESS(dest)->nr_maps = i + 1;
}
dest_maps_by_address[i] = new;
map__set_kmap_maps(new, dest);
if (dest_maps_by_name)
dest_maps_by_name[i] = map__get(new);
RC_CHK_ACCESS(dest)->nr_maps = i + 1;
}
if (err)
map__put(new);
@ -1093,9 +1109,7 @@ int maps__copy_from(struct maps *dest, struct maps *parent)
if (!new)
err = -ENOMEM;
else {
err = unwind__prepare_access(dest, new, NULL);
if (!err)
err = __maps__insert(dest, new);
err = __maps__insert(dest, new);
}
map__put(new);
}

View File

@ -51,6 +51,8 @@ void *maps__addr_space(const struct maps *maps);
void maps__set_addr_space(struct maps *maps, void *addr_space);
const struct unwind_libunwind_ops *maps__unwind_libunwind_ops(const struct maps *maps);
void maps__set_unwind_libunwind_ops(struct maps *maps, const struct unwind_libunwind_ops *ops);
uint16_t maps__e_machine(const struct maps *maps);
void maps__set_e_machine(struct maps *maps, uint16_t e_machine);
#endif
#ifdef HAVE_LIBDW_SUPPORT
void *maps__libdw_addr_space_dwfl(const struct maps *maps);

View File

@ -358,41 +358,21 @@ size_t thread__fprintf(struct thread *thread, FILE *fp)
int thread__insert_map(struct thread *thread, struct map *map)
{
int ret;
uint16_t e_machine;
ret = unwind__prepare_access(thread__maps(thread), map, NULL);
ret = maps__fixup_overlap_and_insert(thread__maps(thread), map);
if (ret)
return ret;
return maps__fixup_overlap_and_insert(thread__maps(thread), map);
}
struct thread__prepare_access_maps_cb_args {
int err;
struct maps *maps;
};
static int thread__prepare_access_maps_cb(struct map *map, void *data)
{
bool initialized = false;
struct thread__prepare_access_maps_cb_args *args = data;
args->err = unwind__prepare_access(args->maps, map, &initialized);
return (args->err || initialized) ? 1 : 0;
e_machine = thread__e_machine(thread, /*machine=*/NULL, /*e_flags=*/NULL);
return unwind__prepare_access(thread__maps(thread), e_machine);
}
static int thread__prepare_access(struct thread *thread)
{
struct thread__prepare_access_maps_cb_args args = {
.err = 0,
};
uint16_t e_machine = thread__e_machine(thread, /*machine=*/NULL, /*e_flags=*/NULL);
if (dwarf_callchain_users) {
args.maps = thread__maps(thread);
maps__for_each_map(thread__maps(thread), thread__prepare_access_maps_cb, &args);
}
return args.err;
return unwind__prepare_access(thread__maps(thread), e_machine);
}
static int thread__clone_maps(struct thread *thread, struct thread *parent, bool do_maps_clone)

View File

@ -721,16 +721,6 @@ static int _unwind__prepare_access(struct maps *maps)
return 0;
}
static void _unwind__flush_access(struct maps *maps)
{
unw_flush_cache(maps__addr_space(maps), 0, 0);
}
static void _unwind__finish_access(struct maps *maps)
{
unw_destroy_addr_space(maps__addr_space(maps));
}
static int get_entries(struct unwind_info *ui, unwind_entry_cb_t cb,
void *arg, int max_stack)
{
@ -835,8 +825,6 @@ static int _unwind__get_entries(unwind_entry_cb_t cb, void *arg,
static struct unwind_libunwind_ops
_unwind_libunwind_ops = {
.prepare_access = _unwind__prepare_access,
.flush_access = _unwind__flush_access,
.finish_access = _unwind__finish_access,
.get_entries = _unwind__get_entries,
};

View File

@ -7,76 +7,63 @@
#include "debug.h"
#include "env.h"
#include "callchain.h"
#include "libunwind-arch/libunwind-arch.h"
#include <dwarf-regs.h>
#include <elf.h>
struct unwind_libunwind_ops __weak *local_unwind_libunwind_ops;
struct unwind_libunwind_ops __weak *x86_32_unwind_libunwind_ops;
struct unwind_libunwind_ops __weak *arm64_unwind_libunwind_ops;
int unwind__prepare_access(struct maps *maps, struct map *map, bool *initialized)
int unwind__prepare_access(struct maps *maps, uint16_t e_machine)
{
const char *arch;
enum dso_type dso_type;
struct unwind_libunwind_ops *ops = local_unwind_libunwind_ops;
struct dso *dso = map__dso(map);
struct machine *machine;
int err;
if (!dwarf_callchain_users)
return 0;
if (maps__addr_space(maps)) {
pr_debug("unwind: thread map already set, dso=%s\n", dso__name(dso));
if (initialized)
*initialized = true;
pr_debug3("unwind: thread map already set\n");
return 0;
}
machine = maps__machine(maps);
/* env->arch is NULL for live-mode (i.e. perf top) */
if (!machine->env || !machine->env->arch)
goto out_register;
dso_type = dso__type(dso, machine);
if (dso_type == DSO__TYPE_UNKNOWN)
if (e_machine == EM_NONE)
return 0;
arch = perf_env__arch(machine->env);
if (!strcmp(arch, "x86")) {
if (dso_type != DSO__TYPE_64BIT)
if (e_machine != EM_HOST) {
/* If not live/local mode. */
switch (e_machine) {
case EM_386:
ops = x86_32_unwind_libunwind_ops;
} else if (!strcmp(arch, "arm64") || !strcmp(arch, "arm")) {
if (dso_type == DSO__TYPE_64BIT)
break;
case EM_AARCH64:
ops = arm64_unwind_libunwind_ops;
break;
default:
pr_warning_once("unwind: ELF machine type %d is not supported\n",
e_machine);
return 0;
}
}
if (!ops) {
pr_warning_once("unwind: target platform=%s is not supported\n", arch);
pr_warning_once("unwind: target platform is not supported\n");
return 0;
}
out_register:
maps__set_unwind_libunwind_ops(maps, ops);
maps__set_e_machine(maps, e_machine);
err = maps__unwind_libunwind_ops(maps)->prepare_access(maps);
if (initialized)
*initialized = err ? false : true;
return err;
return ops->prepare_access(maps);
}
void unwind__flush_access(struct maps *maps)
{
const struct unwind_libunwind_ops *ops = maps__unwind_libunwind_ops(maps);
if (ops)
ops->flush_access(maps);
libunwind_arch__flush_access(maps);
}
void unwind__finish_access(struct maps *maps)
{
const struct unwind_libunwind_ops *ops = maps__unwind_libunwind_ops(maps);
if (ops)
ops->finish_access(maps);
libunwind_arch__finish_access(maps);
}
int libunwind__get_entries(unwind_entry_cb_t cb, void *arg,

View File

@ -2,6 +2,7 @@
#ifndef __UNWIND_H
#define __UNWIND_H
#include <stdint.h>
#include <linux/compiler.h>
#include <linux/types.h>
#include "map_symbol.h"
@ -20,8 +21,6 @@ typedef int (*unwind_entry_cb_t)(struct unwind_entry *entry, void *arg);
struct unwind_libunwind_ops {
int (*prepare_access)(struct maps *maps);
void (*flush_access)(struct maps *maps);
void (*finish_access)(struct maps *maps);
int (*get_entries)(unwind_entry_cb_t cb, void *arg,
struct thread *thread,
struct perf_sample *data, int max_stack, bool best_effort);
@ -64,7 +63,7 @@ int libunwind__get_entries(unwind_entry_cb_t cb, void *arg,
struct thread *thread,
struct perf_sample *data, int max_stack,
bool best_effort);
int unwind__prepare_access(struct maps *maps, struct map *map, bool *initialized);
int unwind__prepare_access(struct maps *maps, uint16_t e_machine);
void unwind__flush_access(struct maps *maps);
void unwind__finish_access(struct maps *maps);
#else
@ -81,8 +80,7 @@ static inline int libunwind__get_entries(unwind_entry_cb_t cb __maybe_unused,
}
static inline int unwind__prepare_access(struct maps *maps __maybe_unused,
struct map *map __maybe_unused,
bool *initialized __maybe_unused)
uint16_t e_machine __maybe_unused)
{
return 0;
}