Commit 4d9b5146 authored by Ian Rogers's avatar Ian Rogers Committed by Arnaldo Carvalho de Melo
Browse files

perf symbol: Move demangling code out of symbol-elf.c



symbol-elf.c is used when building with libelf, symbol-minimal is used
otherwise.

There is no reason the demangling code with no dependencies on libelf is
part of symbol-elf.c so move to symbol.c.

This allows demangling tests to pass with NO_LIBELF=1.

Structurally, while moving the functions rename demangle_sym() to
dso__demangle_sym() which is already a function exposed in symbol.h and
the only purpose of which in symbol-elf.c was to call demangle_sym().

Change the calls to demangle_sym() in symbol-elf.c to calls to
dso__demangle_sym().

Signed-off-by: default avatarIan Rogers <irogers@google.com>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Alex Gaynor <alex.gaynor@gmail.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Alice Ryhl <aliceryhl@google.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Andreas Hindborg <a.hindborg@kernel.org>
Cc: Benno Lossin <benno.lossin@proton.me>
Cc: Björn Roy Baron <bjorn3_gh@protonmail.com>
Cc: Boqun Feng <boqun.feng@gmail.com>
Cc: Danilo Krummrich <dakr@kernel.org>
Cc: Dmitriy Vyukov <dvyukov@google.com>
Cc: Gary Guo <gary@garyguo.net>
Cc: Howard Chu <howardchu95@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: James Clark <james.clark@linaro.org>
Cc: Jiapeng Chong <jiapeng.chong@linux.alibaba.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Kan Liang <kan.liang@linux.intel.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Miguel Ojeda <ojeda@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephen Brennan <stephen.s.brennan@oracle.com>
Cc: Trevor Gross <tmgross@umich.edu>
Cc: Weilin Wang <weilin.wang@intel.com>
Link: https://lore.kernel.org/r/20250528210858.499898-1-irogers@google.com


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent c7a48ea9
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -2,6 +2,8 @@
#ifndef __PERF_DEMANGLE_CXX
#define __PERF_DEMANGLE_CXX 1

#include <stdbool.h>

#ifdef __cplusplus
extern "C" {
#endif
+3 −89
Original line number Diff line number Diff line
@@ -13,17 +13,12 @@
#include "maps.h"
#include "symbol.h"
#include "symsrc.h"
#include "demangle-cxx.h"
#include "demangle-ocaml.h"
#include "demangle-java.h"
#include "demangle-rust-v0.h"
#include "machine.h"
#include "vdso.h"
#include "debug.h"
#include "util/copyfile.h"
#include <linux/ctype.h>
#include <linux/kernel.h>
#include <linux/log2.h>
#include <linux/zalloc.h>
#include <linux/string.h>
#include <symbol/kallsyms.h>
@@ -280,82 +275,6 @@ static int elf_read_program_header(Elf *elf, u64 vaddr, GElf_Phdr *phdr)
	return -1;
}

static bool want_demangle(bool is_kernel_sym)
{
	return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
}

/*
 * Demangle C++ function signature, typically replaced by demangle-cxx.cpp
 * version.
 */
#ifndef HAVE_CXA_DEMANGLE_SUPPORT
char *cxx_demangle_sym(const char *str __maybe_unused, bool params __maybe_unused,
		       bool modifiers __maybe_unused)
{
#ifdef HAVE_LIBBFD_SUPPORT
	int flags = (params ? DMGL_PARAMS : 0) | (modifiers ? DMGL_ANSI : 0);

	return bfd_demangle(NULL, str, flags);
#elif defined(HAVE_CPLUS_DEMANGLE_SUPPORT)
	int flags = (params ? DMGL_PARAMS : 0) | (modifiers ? DMGL_ANSI : 0);

	return cplus_demangle(str, flags);
#else
	return NULL;
#endif
}
#endif /* !HAVE_CXA_DEMANGLE_SUPPORT */

static char *demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
{
	struct demangle rust_demangle = {
		.style = DemangleStyleUnknown,
	};
	char *demangled = NULL;

	/*
	 * We need to figure out if the object was created from C++ sources
	 * DWARF DW_compile_unit has this, but we don't always have access
	 * to it...
	 */
	if (!want_demangle((dso && dso__kernel(dso)) || kmodule))
		return demangled;

	rust_demangle_demangle(elf_name, &rust_demangle);
	if (rust_demangle_is_known(&rust_demangle)) {
		/* A rust mangled name. */
		if (rust_demangle.mangled_len == 0)
			return demangled;

		for (size_t buf_len = roundup_pow_of_two(rust_demangle.mangled_len * 2);
		     buf_len < 1024 * 1024; buf_len += 32) {
			char *tmp = realloc(demangled, buf_len);

			if (!tmp) {
				/* Failure to grow output buffer, return what is there. */
				return demangled;
			}
			demangled = tmp;
			if (rust_demangle_display_demangle(&rust_demangle, demangled, buf_len,
							   /*alternate=*/true) == OverflowOk)
				return demangled;
		}
		/* Buffer exceeded sensible bounds, return what is there. */
		return demangled;
	}

	demangled = cxx_demangle_sym(elf_name, verbose > 0, verbose > 0);
	if (demangled)
		return demangled;

	demangled = ocaml_demangle_sym(elf_name);
	if (demangled)
		return demangled;

	return java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET);
}

struct rel_info {
	u32		nr_entries;
	u32		*sorted;
@@ -641,7 +560,7 @@ static bool get_plt_got_name(GElf_Shdr *shdr, size_t i,
	/* Get the associated symbol */
	gelf_getsym(di->dynsym_data, vr->sym_idx, &sym);
	sym_name = elf_sym__name(&sym, di->dynstr_data);
	demangled = demangle_sym(di->dso, 0, sym_name);
	demangled = dso__demangle_sym(di->dso, /*kmodule=*/0, sym_name);
	if (demangled != NULL)
		sym_name = demangled;

@@ -839,7 +758,7 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
		gelf_getsym(syms, get_rel_symidx(&ri, idx), &sym);

		elf_name = elf_sym__name(&sym, symstrs);
		demangled = demangle_sym(dso, 0, elf_name);
		demangled = dso__demangle_sym(dso, /*kmodule=*/0, elf_name);
		if (demangled)
			elf_name = demangled;
		if (*elf_name)
@@ -868,11 +787,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
	return 0;
}

char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
{
	return demangle_sym(dso, kmodule, elf_name);
}

/*
 * Align offset to 4 bytes as needed for note name and descriptor data.
 */
@@ -1861,7 +1775,7 @@ dso__load_sym_internal(struct dso *dso, struct map *map, struct symsrc *syms_ss,
			}
		}

		demangled = demangle_sym(dso, kmodule, elf_name);
		demangled = dso__demangle_sym(dso, kmodule, elf_name);
		if (demangled != NULL)
			elf_name = demangled;

+0 −7
Original line number Diff line number Diff line
@@ -355,13 +355,6 @@ void symbol__elf_init(void)
{
}

char *dso__demangle_sym(struct dso *dso __maybe_unused,
			int kmodule __maybe_unused,
			const char *elf_name __maybe_unused)
{
	return NULL;
}

bool filename__has_section(const char *filename __maybe_unused, const char *sec __maybe_unused)
{
	return false;
+82 −0
Original line number Diff line number Diff line
@@ -19,6 +19,11 @@
#include "build-id.h"
#include "cap.h"
#include "cpumap.h"
#include "debug.h"
#include "demangle-cxx.h"
#include "demangle-java.h"
#include "demangle-ocaml.h"
#include "demangle-rust-v0.h"
#include "dso.h"
#include "util.h" // lsdir()
#include "debug.h"
@@ -36,6 +41,7 @@
#include "header.h"
#include "path.h"
#include <linux/ctype.h>
#include <linux/log2.h>
#include <linux/zalloc.h>

#include <elf.h>
@@ -2648,3 +2654,79 @@ int symbol__validate_sym_arguments(void)
	}
	return 0;
}

static bool want_demangle(bool is_kernel_sym)
{
	return is_kernel_sym ? symbol_conf.demangle_kernel : symbol_conf.demangle;
}

/*
 * Demangle C++ function signature, typically replaced by demangle-cxx.cpp
 * version.
 */
#ifndef HAVE_CXA_DEMANGLE_SUPPORT
char *cxx_demangle_sym(const char *str __maybe_unused, bool params __maybe_unused,
		       bool modifiers __maybe_unused)
{
#ifdef HAVE_LIBBFD_SUPPORT
	int flags = (params ? DMGL_PARAMS : 0) | (modifiers ? DMGL_ANSI : 0);

	return bfd_demangle(NULL, str, flags);
#elif defined(HAVE_CPLUS_DEMANGLE_SUPPORT)
	int flags = (params ? DMGL_PARAMS : 0) | (modifiers ? DMGL_ANSI : 0);

	return cplus_demangle(str, flags);
#else
	return NULL;
#endif
}
#endif /* !HAVE_CXA_DEMANGLE_SUPPORT */

char *dso__demangle_sym(struct dso *dso, int kmodule, const char *elf_name)
{
	struct demangle rust_demangle = {
		.style = DemangleStyleUnknown,
	};
	char *demangled = NULL;

	/*
	 * We need to figure out if the object was created from C++ sources
	 * DWARF DW_compile_unit has this, but we don't always have access
	 * to it...
	 */
	if (!want_demangle((dso && dso__kernel(dso)) || kmodule))
		return demangled;

	rust_demangle_demangle(elf_name, &rust_demangle);
	if (rust_demangle_is_known(&rust_demangle)) {
		/* A rust mangled name. */
		if (rust_demangle.mangled_len == 0)
			return demangled;

		for (size_t buf_len = roundup_pow_of_two(rust_demangle.mangled_len * 2);
		     buf_len < 1024 * 1024; buf_len += 32) {
			char *tmp = realloc(demangled, buf_len);

			if (!tmp) {
				/* Failure to grow output buffer, return what is there. */
				return demangled;
			}
			demangled = tmp;
			if (rust_demangle_display_demangle(&rust_demangle, demangled, buf_len,
							   /*alternate=*/true) == OverflowOk)
				return demangled;
		}
		/* Buffer exceeded sensible bounds, return what is there. */
		return demangled;
	}

	demangled = cxx_demangle_sym(elf_name, verbose > 0, verbose > 0);
	if (demangled)
		return demangled;

	demangled = ocaml_demangle_sym(elf_name);
	if (demangled)
		return demangled;

	return java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET);
}