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: Ian 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: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Ian Rogers 2025-05-28 14:08:58 -07:00 committed by Arnaldo Carvalho de Melo
parent c7a48ea9b9
commit 4d9b5146f0
4 changed files with 87 additions and 96 deletions

View File

@ -2,6 +2,8 @@
#ifndef __PERF_DEMANGLE_CXX
#define __PERF_DEMANGLE_CXX 1
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif

View File

@ -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;

View File

@ -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;

View File

@ -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);
}