From nobody Thu Oct 2 02:12:28 2025 Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B38824BCE8 for ; Mon, 29 Sep 2025 19:08:42 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.202 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759172926; cv=none; b=UyTc81E1Tk5RLkDJwZ4Jtd/vTGepZq2MCyfM9AhupkKOQhS7U5TpbyQd5KKJ3339uBNkbawAcXOLEeA10I1ZYruh9XjdJAlwvkRJOsZQVM6F2d6Wv7pNLmdd7QBXzPJg+t1VMhaSCe2t7XSKO7f7CdfmSrsl9tk40jFq7BuSyxs= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759172926; c=relaxed/simple; bh=sG7GXj9dZWPgoweAiBVtaxLXGry2kM2zSMgSFDKWukw=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Content-Type; b=pH7kELT8K7orrNDxeVuXPiAT7YHQnIevw0pda8np+XF/Z77P7NR7kqMfnDIyMn57H3MM2NCW74ySX+3gisgf9iKp6S9FXxHxJdMaX4tdtxWZ+OBDlR98cpHdJXB15CfpW7MW7paocI0uYjmE0XpxsTBL+AIHeVWj3rAaGdiD/hc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=B4WogKpa; arc=none smtp.client-ip=209.85.214.202 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--irogers.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="B4WogKpa" Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-268149e1c28so46207165ad.1 for ; Mon, 29 Sep 2025 12:08:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1759172922; x=1759777722; darn=vger.kernel.org; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=J33L4M07H2Lw9WZtW+pVpjZvTY7fnFzmKJOxPiOQosU=; b=B4WogKpat9iZZopgka7/ZjDwfii4Rbl/mCp6pnEwIIES0OMRUjlslWRomgwMvft5CW Pu1GTmG1Kdh9WA2VMayrGOc89g2c3V8zG2w73XS3Bp1y9Fok9nNRaCV8nf5F16x84R9z u9sRhzu57rXzmdsQfDaBzz4Gj0+Asv+MjkmvLUYr8viS+KtqWm+Y+4E+x94nuP7PPL5e Gv7OIY1ZQlS2NCTKllXnVm1KWxpTFeAct8AGePRv1retaNzpq+HA3WKUrMJGkaApDMRK lRtIvW/iTNZ8H+FVMcsY5DRSGuPqgqD5GlOg7IrBxasPzoqiBxRP7e3NBr/KW+Jq3xJv 8OCA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1759172922; x=1759777722; h=to:from:subject:message-id:references:mime-version:in-reply-to:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=J33L4M07H2Lw9WZtW+pVpjZvTY7fnFzmKJOxPiOQosU=; b=Yvuomn0HGGE5oVsLi29BnL4Xsu+6FbMek09Jvdg/3WWYX/yIp8A6eGWJRVxbxYSCkG 9wKMW03BGv8tvLbVLEfi4YmmnmZjkAVx8vO5XfhnkrvIhguSvNOMWuR1aQw1Yp5fEuKD pXFq96U26IhDGiJhuDCx/s9/UVa9V0cfcsJfU9NnG/03gSJUym5oZq1ke/lXSqQGnf8T 9D7yVRSIlRcvT5LSONfUoiQHANP6k16PIPfIhnX4hqUdm/alRN/v5wvTmI06mxHfpR3F GyQ5FhimCy4RXnlfwKiIY3gMNMBCBII23iAta50suxtcX3n+ZzSAgohhDmlnc0pEabNF e0WQ== X-Forwarded-Encrypted: i=1; AJvYcCWhIwPRNgfnIrZ0ya4r4HQfEmPzr/2e5GQv3hn99bONZm2kL/Xvqtdp3vE8H7ax5kJrb+xoiUUAvbGBw0s=@vger.kernel.org X-Gm-Message-State: AOJu0YxRJe+A3kocVTKT+7Vv6kApuYAL81YKNich2Pw8+hZbDDQtbKxR 2Nss305+aSRVpSCC94ZF+J4yaGdWJfnj6rjG/Oo1DJJx1QnG++Jd1gFcb/Q9akUTKZ6gkkAAu1N E+woE7HUJjg== X-Google-Smtp-Source: AGHT+IEQjzs/CagmcVqOtXMdd616zkKpRk3siJg1YZORZiilUy81aMWHjOhgnzp447Lgxr4TMVOxzst/qaPz X-Received: from pgbcz14.prod.google.com ([2002:a05:6a02:230e:b0:b55:1827:9212]) (user=irogers job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:2c0d:b0:275:27ab:f6c4 with SMTP id d9443c01a7336-27ed4a315b5mr204239165ad.33.1759172921696; Mon, 29 Sep 2025 12:08:41 -0700 (PDT) Date: Mon, 29 Sep 2025 12:07:54 -0700 In-Reply-To: <20250929190805.201446-1-irogers@google.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20250929190805.201446-1-irogers@google.com> X-Mailer: git-send-email 2.51.0.570.gb178f27e6d-goog Message-ID: <20250929190805.201446-5-irogers@google.com> Subject: [PATCH v6 04/15] perf libbfd: Move libbfd functionality to its own file From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Mark Rutland , Alexander Shishkin , Jiri Olsa , Ian Rogers , Adrian Hunter , Nathan Chancellor , Nick Desaulniers , Bill Wendling , Justin Stitt , Charlie Jenkins , Eric Biggers , "Masami Hiramatsu (Google)" , James Clark , Collin Funk , "Dr. David Alan Gilbert" , Li Huafei , Athira Rajeev , Stephen Brennan , Dmitry Vyukov , Alexandre Ghiti , Haibo Xu , Andi Kleen , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, bpf@vger.kernel.org, llvm@lists.linux.dev, Song Liu Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move symbolization and srcline libbfd dependencies to a separate libbfd.c. This mirrors moving llvm and capstone code. While this code is deprecated as it is part of BUILD_NONDISTRO license incompatible code, moving the code to its own file minimizes disruption in the main files. disasm_bpf.c is moved to libbfd.c also except for symbol__disassemble_bpf_image which is currently more of a placeholder function rather than something that provides disassembly support. demangle-cxx.cpp code isn't migrated as it is very limited. Signed-off-by: Ian Rogers --- tools/perf/Makefile.config | 1 + tools/perf/util/Build | 2 +- tools/perf/util/disasm.c | 19 +- tools/perf/util/disasm_bpf.c | 195 ------------ tools/perf/util/disasm_bpf.h | 12 - tools/perf/util/libbfd.c | 600 +++++++++++++++++++++++++++++++++++ tools/perf/util/libbfd.h | 83 +++++ tools/perf/util/srcline.c | 232 +------------- tools/perf/util/srcline.h | 2 + tools/perf/util/symbol-elf.c | 100 +----- tools/perf/util/symbol.c | 131 -------- 11 files changed, 718 insertions(+), 659 deletions(-) delete mode 100644 tools/perf/util/disasm_bpf.c delete mode 100644 tools/perf/util/disasm_bpf.h create mode 100644 tools/perf/util/libbfd.c create mode 100644 tools/perf/util/libbfd.h diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config index 7bc2341295c3..1907d1c70b68 100644 --- a/tools/perf/Makefile.config +++ b/tools/perf/Makefile.config @@ -947,6 +947,7 @@ ifdef BUILD_NONDISTRO =20 CFLAGS +=3D -DHAVE_LIBBFD_SUPPORT CXXFLAGS +=3D -DHAVE_LIBBFD_SUPPORT + $(call detected,CONFIG_LIBBFD) =20 $(call feature_check,libbfd-buildid) =20 diff --git a/tools/perf/util/Build b/tools/perf/util/Build index 63160c4a517e..bb2023a3d0c9 100644 --- a/tools/perf/util/Build +++ b/tools/perf/util/Build @@ -14,7 +14,6 @@ perf-util-y +=3D copyfile.o perf-util-y +=3D ctype.o perf-util-y +=3D db-export.o perf-util-y +=3D disasm.o -perf-util-y +=3D disasm_bpf.o perf-util-y +=3D env.o perf-util-y +=3D event.o perf-util-y +=3D evlist.o @@ -26,6 +25,7 @@ perf-util-y +=3D evswitch.o perf-util-y +=3D find_bit.o perf-util-y +=3D get_current_dir_name.o perf-util-y +=3D levenshtein.o +perf-util-$(CONFIG_LIBBFD) +=3D libbfd.o perf-util-y +=3D llvm.o perf-util-y +=3D mmap.o perf-util-y +=3D memswap.o diff --git a/tools/perf/util/disasm.c b/tools/perf/util/disasm.c index fa6accd8d873..a1240543c89c 100644 --- a/tools/perf/util/disasm.c +++ b/tools/perf/util/disasm.c @@ -17,11 +17,11 @@ #include "capstone.h" #include "debug.h" #include "disasm.h" -#include "disasm_bpf.h" #include "dso.h" #include "dwarf-regs.h" #include "env.h" #include "evsel.h" +#include "libbfd.h" #include "llvm.h" #include "map.h" #include "maps.h" @@ -1480,6 +1480,23 @@ char *expand_tabs(char *line, char **storage, size_t= *storage_len) return new_line; } =20 +static int symbol__disassemble_bpf_image(struct symbol *sym, struct annota= te_args *args) +{ + struct annotation *notes =3D symbol__annotation(sym); + struct disasm_line *dl; + + args->offset =3D -1; + args->line =3D strdup("to be implemented"); + args->line_nr =3D 0; + args->fileloc =3D NULL; + dl =3D disasm_line__new(args); + if (dl) + annotation_line__add(&dl->al, ¬es->src->source); + + zfree(&args->line); + return 0; +} + static int symbol__disassemble_objdump(const char *filename, struct symbol= *sym, struct annotate_args *args) { diff --git a/tools/perf/util/disasm_bpf.c b/tools/perf/util/disasm_bpf.c deleted file mode 100644 index 1fee71c79b62..000000000000 --- a/tools/perf/util/disasm_bpf.c +++ /dev/null @@ -1,195 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -#include "util/annotate.h" -#include "util/disasm_bpf.h" -#include "util/symbol.h" -#include -#include - -#if defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT) -#define PACKAGE "perf" -#include -#include -#include -#include -#include -#include -#include -#include - -#include "util/bpf-event.h" -#include "util/bpf-utils.h" -#include "util/debug.h" -#include "util/dso.h" -#include "util/map.h" -#include "util/env.h" -#include "util/util.h" - -int symbol__disassemble_bpf(struct symbol *sym, struct annotate_args *args) -{ - struct annotation *notes =3D symbol__annotation(sym); - struct bpf_prog_linfo *prog_linfo =3D NULL; - struct bpf_prog_info_node *info_node; - int len =3D sym->end - sym->start; - disassembler_ftype disassemble; - struct map *map =3D args->ms.map; - struct perf_bpil *info_linear; - struct disassemble_info info; - struct dso *dso =3D map__dso(map); - int pc =3D 0, count, sub_id; - struct btf *btf =3D NULL; - char tpath[PATH_MAX]; - size_t buf_size; - int nr_skip =3D 0; - char *buf; - bfd *bfdf; - int ret; - FILE *s; - - if (dso__binary_type(dso) !=3D DSO_BINARY_TYPE__BPF_PROG_INFO) - return SYMBOL_ANNOTATE_ERRNO__BPF_INVALID_FILE; - - pr_debug("%s: handling sym %s addr %" PRIx64 " len %" PRIx64 "\n", __func= __, - sym->name, sym->start, sym->end - sym->start); - - memset(tpath, 0, sizeof(tpath)); - perf_exe(tpath, sizeof(tpath)); - - bfdf =3D bfd_openr(tpath, NULL); - if (bfdf =3D=3D NULL) - abort(); - - if (!bfd_check_format(bfdf, bfd_object)) - abort(); - - s =3D open_memstream(&buf, &buf_size); - if (!s) { - ret =3D errno; - goto out; - } - init_disassemble_info_compat(&info, s, - (fprintf_ftype) fprintf, - fprintf_styled); - info.arch =3D bfd_get_arch(bfdf); - info.mach =3D bfd_get_mach(bfdf); - - info_node =3D perf_env__find_bpf_prog_info(dso__bpf_prog(dso)->env, - dso__bpf_prog(dso)->id); - if (!info_node) { - ret =3D SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF; - goto out; - } - info_linear =3D info_node->info_linear; - sub_id =3D dso__bpf_prog(dso)->sub_id; - - info.buffer =3D (void *)(uintptr_t)(info_linear->info.jited_prog_insns); - info.buffer_length =3D info_linear->info.jited_prog_len; - - if (info_linear->info.nr_line_info) - prog_linfo =3D bpf_prog_linfo__new(&info_linear->info); - - if (info_linear->info.btf_id) { - struct btf_node *node; - - node =3D perf_env__find_btf(dso__bpf_prog(dso)->env, - info_linear->info.btf_id); - if (node) - btf =3D btf__new((__u8 *)(node->data), - node->data_size); - } - - disassemble_init_for_target(&info); - -#ifdef DISASM_FOUR_ARGS_SIGNATURE - disassemble =3D disassembler(info.arch, - bfd_big_endian(bfdf), - info.mach, - bfdf); -#else - disassemble =3D disassembler(bfdf); -#endif - if (disassemble =3D=3D NULL) - abort(); - - fflush(s); - do { - const struct bpf_line_info *linfo =3D NULL; - struct disasm_line *dl; - size_t prev_buf_size; - const char *srcline; - u64 addr; - - addr =3D pc + ((u64 *)(uintptr_t)(info_linear->info.jited_ksyms))[sub_id= ]; - count =3D disassemble(pc, &info); - - if (prog_linfo) - linfo =3D bpf_prog_linfo__lfind_addr_func(prog_linfo, - addr, sub_id, - nr_skip); - - if (linfo && btf) { - srcline =3D btf__name_by_offset(btf, linfo->line_off); - nr_skip++; - } else - srcline =3D NULL; - - fprintf(s, "\n"); - prev_buf_size =3D buf_size; - fflush(s); - - if (!annotate_opts.hide_src_code && srcline) { - args->offset =3D -1; - args->line =3D strdup(srcline); - args->line_nr =3D 0; - args->fileloc =3D NULL; - args->ms.sym =3D sym; - dl =3D disasm_line__new(args); - if (dl) { - annotation_line__add(&dl->al, - ¬es->src->source); - } - } - - args->offset =3D pc; - args->line =3D buf + prev_buf_size; - args->line_nr =3D 0; - args->fileloc =3D NULL; - args->ms.sym =3D sym; - dl =3D disasm_line__new(args); - if (dl) - annotation_line__add(&dl->al, ¬es->src->source); - - pc +=3D count; - } while (count > 0 && pc < len); - - ret =3D 0; -out: - free(prog_linfo); - btf__free(btf); - fclose(s); - bfd_close(bfdf); - return ret; -} -#else // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT) -int symbol__disassemble_bpf(struct symbol *sym __maybe_unused, struct anno= tate_args *args __maybe_unused) -{ - return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF; -} -#endif // defined(HAVE_LIBBFD_SUPPORT) && defined(HAVE_LIBBPF_SUPPORT) - -int symbol__disassemble_bpf_image(struct symbol *sym, struct annotate_args= *args) -{ - struct annotation *notes =3D symbol__annotation(sym); - struct disasm_line *dl; - - args->offset =3D -1; - args->line =3D strdup("to be implemented"); - args->line_nr =3D 0; - args->fileloc =3D NULL; - dl =3D disasm_line__new(args); - if (dl) - annotation_line__add(&dl->al, ¬es->src->source); - - zfree(&args->line); - return 0; -} diff --git a/tools/perf/util/disasm_bpf.h b/tools/perf/util/disasm_bpf.h deleted file mode 100644 index 2ecb19545388..000000000000 --- a/tools/perf/util/disasm_bpf.h +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-only - -#ifndef __PERF_DISASM_BPF_H -#define __PERF_DISASM_BPF_H - -struct symbol; -struct annotate_args; - -int symbol__disassemble_bpf(struct symbol *sym, struct annotate_args *args= ); -int symbol__disassemble_bpf_image(struct symbol *sym, struct annotate_args= *args); - -#endif /* __PERF_DISASM_BPF_H */ diff --git a/tools/perf/util/libbfd.c b/tools/perf/util/libbfd.c new file mode 100644 index 000000000000..09a0eeb78a1a --- /dev/null +++ b/tools/perf/util/libbfd.c @@ -0,0 +1,600 @@ +// SPDX-License-Identifier: GPL-2.0 +#include "libbfd.h" +#include "annotate.h" +#include "bpf-event.h" +#include "bpf-utils.h" +#include "debug.h" +#include "dso.h" +#include "env.h" +#include "map.h" +#include "srcline.h" +#include "symbol.h" +#include "symbol_conf.h" +#include "util.h" +#include +#ifdef HAVE_LIBBPF_SUPPORT +#include +#include +#endif +#include +#include +#include +#define PACKAGE "perf" +#include + +/* + * Implement addr2line using libbfd. + */ +struct a2l_data { + const char *input; + u64 addr; + + bool found; + const char *filename; + const char *funcname; + unsigned int line; + + bfd *abfd; + asymbol **syms; +}; + +static int bfd_error(const char *string) +{ + const char *errmsg; + + errmsg =3D bfd_errmsg(bfd_get_error()); + fflush(stdout); + + if (string) + pr_debug("%s: %s\n", string, errmsg); + else + pr_debug("%s\n", errmsg); + + return -1; +} + +static int slurp_symtab(bfd *abfd, struct a2l_data *a2l) +{ + long storage; + long symcount; + asymbol **syms; + bfd_boolean dynamic =3D FALSE; + + if ((bfd_get_file_flags(abfd) & HAS_SYMS) =3D=3D 0) + return bfd_error(bfd_get_filename(abfd)); + + storage =3D bfd_get_symtab_upper_bound(abfd); + if (storage =3D=3D 0L) { + storage =3D bfd_get_dynamic_symtab_upper_bound(abfd); + dynamic =3D TRUE; + } + if (storage < 0L) + return bfd_error(bfd_get_filename(abfd)); + + syms =3D malloc(storage); + if (dynamic) + symcount =3D bfd_canonicalize_dynamic_symtab(abfd, syms); + else + symcount =3D bfd_canonicalize_symtab(abfd, syms); + + if (symcount < 0) { + free(syms); + return bfd_error(bfd_get_filename(abfd)); + } + + a2l->syms =3D syms; + return 0; +} + +static void find_address_in_section(bfd *abfd, asection *section, void *da= ta) +{ + bfd_vma pc, vma; + bfd_size_type size; + struct a2l_data *a2l =3D data; + flagword flags; + + if (a2l->found) + return; + +#ifdef bfd_get_section_flags + flags =3D bfd_get_section_flags(abfd, section); +#else + flags =3D bfd_section_flags(section); +#endif + if ((flags & SEC_ALLOC) =3D=3D 0) + return; + + pc =3D a2l->addr; +#ifdef bfd_get_section_vma + vma =3D bfd_get_section_vma(abfd, section); +#else + vma =3D bfd_section_vma(section); +#endif +#ifdef bfd_get_section_size + size =3D bfd_get_section_size(section); +#else + size =3D bfd_section_size(section); +#endif + + if (pc < vma || pc >=3D vma + size) + return; + + a2l->found =3D bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma, + &a2l->filename, &a2l->funcname, + &a2l->line); + + if (a2l->filename && !strlen(a2l->filename)) + a2l->filename =3D NULL; +} + +static struct a2l_data *addr2line_init(const char *path) +{ + bfd *abfd; + struct a2l_data *a2l =3D NULL; + + abfd =3D bfd_openr(path, NULL); + if (abfd =3D=3D NULL) + return NULL; + + if (!bfd_check_format(abfd, bfd_object)) + goto out; + + a2l =3D zalloc(sizeof(*a2l)); + if (a2l =3D=3D NULL) + goto out; + + a2l->abfd =3D abfd; + a2l->input =3D strdup(path); + if (a2l->input =3D=3D NULL) + goto out; + + if (slurp_symtab(abfd, a2l)) + goto out; + + return a2l; + +out: + if (a2l) { + zfree((char **)&a2l->input); + free(a2l); + } + bfd_close(abfd); + return NULL; +} + +static void addr2line_cleanup(struct a2l_data *a2l) +{ + if (a2l->abfd) + bfd_close(a2l->abfd); + zfree((char **)&a2l->input); + zfree(&a2l->syms); + free(a2l); +} + +static int inline_list__append_dso_a2l(struct dso *dso, + struct inline_node *node, + struct symbol *sym) +{ + struct a2l_data *a2l =3D dso__a2l(dso); + struct symbol *inline_sym =3D new_inline_sym(dso, sym, a2l->funcname); + char *srcline =3D NULL; + + if (a2l->filename) + srcline =3D srcline_from_fileline(a2l->filename, a2l->line); + + return inline_list__append(inline_sym, srcline, node); +} + +int libbfd__addr2line(const char *dso_name, u64 addr, + char **file, unsigned int *line, struct dso *dso, + bool unwind_inlines, struct inline_node *node, + struct symbol *sym) +{ + int ret =3D 0; + struct a2l_data *a2l =3D dso__a2l(dso); + + if (!a2l) { + a2l =3D addr2line_init(dso_name); + dso__set_a2l(dso, a2l); + } + + if (a2l =3D=3D NULL) { + if (!symbol_conf.disable_add2line_warn) + pr_warning("addr2line_init failed for %s\n", dso_name); + return 0; + } + + a2l->addr =3D addr; + a2l->found =3D false; + + bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); + + if (!a2l->found) + return 0; + + if (unwind_inlines) { + int cnt =3D 0; + + if (node && inline_list__append_dso_a2l(dso, node, sym)) + return 0; + + while (bfd_find_inliner_info(a2l->abfd, &a2l->filename, + &a2l->funcname, &a2l->line) && + cnt++ < MAX_INLINE_NEST) { + + if (a2l->filename && !strlen(a2l->filename)) + a2l->filename =3D NULL; + + if (node !=3D NULL) { + if (inline_list__append_dso_a2l(dso, node, sym)) + return 0; + // found at least one inline frame + ret =3D 1; + } + } + } + + if (file) { + *file =3D a2l->filename ? strdup(a2l->filename) : NULL; + ret =3D *file ? 1 : 0; + } + + if (line) + *line =3D a2l->line; + + return ret; +} + +void dso__free_a2l_libbfd(struct dso *dso) +{ + struct a2l_data *a2l =3D dso__a2l(dso); + + if (!a2l) + return; + + addr2line_cleanup(a2l); + + dso__set_a2l(dso, NULL); +} + +static int bfd_symbols__cmpvalue(const void *a, const void *b) +{ + const asymbol *as =3D *(const asymbol **)a, *bs =3D *(const asymbol **)b; + + if (bfd_asymbol_value(as) !=3D bfd_asymbol_value(bs)) + return bfd_asymbol_value(as) - bfd_asymbol_value(bs); + + return bfd_asymbol_name(as)[0] - bfd_asymbol_name(bs)[0]; +} + +static int bfd2elf_binding(asymbol *symbol) +{ + if (symbol->flags & BSF_WEAK) + return STB_WEAK; + if (symbol->flags & BSF_GLOBAL) + return STB_GLOBAL; + if (symbol->flags & BSF_LOCAL) + return STB_LOCAL; + return -1; +} + +int dso__load_bfd_symbols(struct dso *dso, const char *debugfile) +{ + int err =3D -1; + long symbols_size, symbols_count, i; + asection *section; + asymbol **symbols, *sym; + struct symbol *symbol; + bfd *abfd; + u64 start, len; + + abfd =3D bfd_openr(debugfile, NULL); + if (!abfd) + return -1; + + if (!bfd_check_format(abfd, bfd_object)) { + pr_debug2("%s: cannot read %s bfd file.\n", __func__, + dso__long_name(dso)); + goto out_close; + } + + if (bfd_get_flavour(abfd) =3D=3D bfd_target_elf_flavour) + goto out_close; + + symbols_size =3D bfd_get_symtab_upper_bound(abfd); + if (symbols_size =3D=3D 0) { + bfd_close(abfd); + return 0; + } + + if (symbols_size < 0) + goto out_close; + + symbols =3D malloc(symbols_size); + if (!symbols) + goto out_close; + + symbols_count =3D bfd_canonicalize_symtab(abfd, symbols); + if (symbols_count < 0) + goto out_free; + + section =3D bfd_get_section_by_name(abfd, ".text"); + if (section) { + for (i =3D 0; i < symbols_count; ++i) { + if (!strcmp(bfd_asymbol_name(symbols[i]), "__ImageBase") || + !strcmp(bfd_asymbol_name(symbols[i]), "__image_base__")) + break; + } + if (i < symbols_count) { + /* PE symbols can only have 4 bytes, so use .text high bits */ + u64 text_offset =3D (section->vma - (u32)section->vma) + + (u32)bfd_asymbol_value(symbols[i]); + dso__set_text_offset(dso, text_offset); + dso__set_text_end(dso, (section->vma - text_offset) + section->size); + } else { + dso__set_text_offset(dso, section->vma - section->filepos); + dso__set_text_end(dso, section->filepos + section->size); + } + } + + qsort(symbols, symbols_count, sizeof(asymbol *), bfd_symbols__cmpvalue); + +#ifdef bfd_get_section +#define bfd_asymbol_section bfd_get_section +#endif + for (i =3D 0; i < symbols_count; ++i) { + sym =3D symbols[i]; + section =3D bfd_asymbol_section(sym); + if (bfd2elf_binding(sym) < 0) + continue; + + while (i + 1 < symbols_count && + bfd_asymbol_section(symbols[i + 1]) =3D=3D section && + bfd2elf_binding(symbols[i + 1]) < 0) + i++; + + if (i + 1 < symbols_count && + bfd_asymbol_section(symbols[i + 1]) =3D=3D section) + len =3D symbols[i + 1]->value - sym->value; + else + len =3D section->size - sym->value; + + start =3D bfd_asymbol_value(sym) - dso__text_offset(dso); + symbol =3D symbol__new(start, len, bfd2elf_binding(sym), STT_FUNC, + bfd_asymbol_name(sym)); + if (!symbol) + goto out_free; + + symbols__insert(dso__symbols(dso), symbol); + } +#ifdef bfd_get_section +#undef bfd_asymbol_section +#endif + + symbols__fixup_end(dso__symbols(dso), false); + symbols__fixup_duplicate(dso__symbols(dso)); + dso__set_adjust_symbols(dso, true); + + err =3D 0; +out_free: + free(symbols); +out_close: + bfd_close(abfd); + return err; +} + +int libbfd__read_build_id(const char *filename, struct build_id *bid, bool= block) +{ + size_t size =3D sizeof(bid->data); + int err =3D -1, fd; + bfd *abfd; + + fd =3D open(filename, block ? O_RDONLY : (O_RDONLY | O_NONBLOCK)); + if (fd < 0) + return -1; + + abfd =3D bfd_fdopenr(filename, /*target=3D*/NULL, fd); + if (!abfd) + return -1; + + if (!bfd_check_format(abfd, bfd_object)) { + pr_debug2("%s: cannot read %s bfd file.\n", __func__, filename); + goto out_close; + } + + if (!abfd->build_id || abfd->build_id->size > size) + goto out_close; + + memcpy(bid->data, abfd->build_id->data, abfd->build_id->size); + memset(bid->data + abfd->build_id->size, 0, size - abfd->build_id->size); + err =3D bid->size =3D abfd->build_id->size; + +out_close: + bfd_close(abfd); + return err; +} + +int libbfd_filename__read_debuglink(const char *filename, char *debuglink, + size_t size) +{ + int err =3D -1; + asection *section; + bfd *abfd; + + abfd =3D bfd_openr(filename, NULL); + if (!abfd) + return -1; + + if (!bfd_check_format(abfd, bfd_object)) { + pr_debug2("%s: cannot read %s bfd file.\n", __func__, filename); + goto out_close; + } + + section =3D bfd_get_section_by_name(abfd, ".gnu_debuglink"); + if (!section) + goto out_close; + + if (section->size > size) + goto out_close; + + if (!bfd_get_section_contents(abfd, section, debuglink, 0, + section->size)) + goto out_close; + + err =3D 0; + +out_close: + bfd_close(abfd); + return err; +} + +int symbol__disassemble_bpf(struct symbol *sym __maybe_unused, + struct annotate_args *args __maybe_unused) +{ +#ifdef HAVE_LIBBPF_SUPPORT + struct annotation *notes =3D symbol__annotation(sym); + struct bpf_prog_linfo *prog_linfo =3D NULL; + struct bpf_prog_info_node *info_node; + int len =3D sym->end - sym->start; + disassembler_ftype disassemble; + struct map *map =3D args->ms.map; + struct perf_bpil *info_linear; + struct disassemble_info info; + struct dso *dso =3D map__dso(map); + int pc =3D 0, count, sub_id; + struct btf *btf =3D NULL; + char tpath[PATH_MAX]; + size_t buf_size; + int nr_skip =3D 0; + char *buf; + bfd *bfdf; + int ret; + FILE *s; + + if (dso__binary_type(dso) !=3D DSO_BINARY_TYPE__BPF_PROG_INFO) + return SYMBOL_ANNOTATE_ERRNO__BPF_INVALID_FILE; + + pr_debug("%s: handling sym %s addr %" PRIx64 " len %" PRIx64 "\n", __func= __, + sym->name, sym->start, sym->end - sym->start); + + memset(tpath, 0, sizeof(tpath)); + perf_exe(tpath, sizeof(tpath)); + + bfdf =3D bfd_openr(tpath, NULL); + if (bfdf =3D=3D NULL) + abort(); + + if (!bfd_check_format(bfdf, bfd_object)) + abort(); + + s =3D open_memstream(&buf, &buf_size); + if (!s) { + ret =3D errno; + goto out; + } + init_disassemble_info_compat(&info, s, + (fprintf_ftype) fprintf, + fprintf_styled); + info.arch =3D bfd_get_arch(bfdf); + info.mach =3D bfd_get_mach(bfdf); + + info_node =3D perf_env__find_bpf_prog_info(dso__bpf_prog(dso)->env, + dso__bpf_prog(dso)->id); + if (!info_node) { + ret =3D SYMBOL_ANNOTATE_ERRNO__BPF_MISSING_BTF; + goto out; + } + info_linear =3D info_node->info_linear; + sub_id =3D dso__bpf_prog(dso)->sub_id; + + info.buffer =3D (void *)(uintptr_t)(info_linear->info.jited_prog_insns); + info.buffer_length =3D info_linear->info.jited_prog_len; + + if (info_linear->info.nr_line_info) + prog_linfo =3D bpf_prog_linfo__new(&info_linear->info); + + if (info_linear->info.btf_id) { + struct btf_node *node; + + node =3D perf_env__find_btf(dso__bpf_prog(dso)->env, + info_linear->info.btf_id); + if (node) + btf =3D btf__new((__u8 *)(node->data), + node->data_size); + } + + disassemble_init_for_target(&info); + +#ifdef DISASM_FOUR_ARGS_SIGNATURE + disassemble =3D disassembler(info.arch, + bfd_big_endian(bfdf), + info.mach, + bfdf); +#else + disassemble =3D disassembler(bfdf); +#endif + if (disassemble =3D=3D NULL) + abort(); + + fflush(s); + do { + const struct bpf_line_info *linfo =3D NULL; + struct disasm_line *dl; + size_t prev_buf_size; + const char *srcline; + u64 addr; + + addr =3D pc + ((u64 *)(uintptr_t)(info_linear->info.jited_ksyms))[sub_id= ]; + count =3D disassemble(pc, &info); + + if (prog_linfo) + linfo =3D bpf_prog_linfo__lfind_addr_func(prog_linfo, + addr, sub_id, + nr_skip); + + if (linfo && btf) { + srcline =3D btf__name_by_offset(btf, linfo->line_off); + nr_skip++; + } else + srcline =3D NULL; + + fprintf(s, "\n"); + prev_buf_size =3D buf_size; + fflush(s); + + if (!annotate_opts.hide_src_code && srcline) { + args->offset =3D -1; + args->line =3D strdup(srcline); + args->line_nr =3D 0; + args->fileloc =3D NULL; + args->ms.sym =3D sym; + dl =3D disasm_line__new(args); + if (dl) { + annotation_line__add(&dl->al, + ¬es->src->source); + } + } + + args->offset =3D pc; + args->line =3D buf + prev_buf_size; + args->line_nr =3D 0; + args->fileloc =3D NULL; + args->ms.sym =3D sym; + dl =3D disasm_line__new(args); + if (dl) + annotation_line__add(&dl->al, ¬es->src->source); + + pc +=3D count; + } while (count > 0 && pc < len); + + ret =3D 0; +out: + free(prog_linfo); + btf__free(btf); + fclose(s); + bfd_close(bfdf); + return ret; +#else + return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF; +#endif +} diff --git a/tools/perf/util/libbfd.h b/tools/perf/util/libbfd.h new file mode 100644 index 000000000000..7441e95f8ec0 --- /dev/null +++ b/tools/perf/util/libbfd.h @@ -0,0 +1,83 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __PERF_LIBBFD_H +#define __PERF_LIBBFD_H + +#include +#include +#include +#include + +struct annotate_args; +struct build_id; +struct dso; +struct inline_node; +struct symbol; + +#ifdef HAVE_LIBBFD_SUPPORT +int libbfd__addr2line(const char *dso_name, u64 addr, + char **file, unsigned int *line, struct dso *dso, + bool unwind_inlines, struct inline_node *node, + struct symbol *sym); + + +void dso__free_a2l_libbfd(struct dso *dso); + +int symbol__disassemble_libbfd(const char *filename, struct symbol *sym, + struct annotate_args *args); + +int libbfd__read_build_id(const char *filename, struct build_id *bid, bool= block); + +int libbfd_filename__read_debuglink(const char *filename, char *debuglink,= size_t size); + +int symbol__disassemble_bpf(struct symbol *sym, struct annotate_args *args= ); + +#else // !defined(HAVE_LIBBFD_SUPPORT) +#include "annotate.h" + +static inline int libbfd__addr2line(const char *dso_name __always_unused, + u64 addr __always_unused, + char **file __always_unused, + unsigned int *line __always_unused, + struct dso *dso __always_unused, + bool unwind_inlines __always_unused, + struct inline_node *node __always_unused, + struct symbol *sym __always_unused) +{ + return -1; +} + + +static inline void dso__free_a2l_libbfd(struct dso *dso __always_unused) +{ +} + +static inline int symbol__disassemble_libbfd(const char *filename __always= _unused, + struct symbol *sym __always_unused, + struct annotate_args *args __always_unused) +{ + return -1; +} + +static inline int libbfd__read_build_id(const char *filename __always_unus= ed, + struct build_id *bid __always_unused, + bool block __always_unused) +{ + return -1; +} + +static inline int libbfd_filename__read_debuglink(const char *filename __a= lways_unused, + char *debuglink __always_unused, + size_t size __always_unused) +{ + return -1; +} + +static inline int symbol__disassemble_bpf(struct symbol *sym __always_unus= ed, + struct annotate_args *args __always_unused) +{ + return SYMBOL_ANNOTATE_ERRNO__NO_LIBOPCODES_FOR_BPF; +} + +#endif // defined(HAVE_LIBBFD_SUPPORT) + +#endif /* __PERF_LIBBFD_H */ diff --git a/tools/perf/util/srcline.c b/tools/perf/util/srcline.c index 45e138ff3e52..23b942d4729e 100644 --- a/tools/perf/util/srcline.c +++ b/tools/perf/util/srcline.c @@ -129,8 +129,6 @@ struct symbol *new_inline_sym(struct dso *dso, return inline_sym; } =20 -#define MAX_INLINE_NEST 1024 - #ifdef HAVE_LIBLLVM_SUPPORT #include "llvm.h" =20 @@ -147,243 +145,19 @@ void dso__free_a2l(struct dso *dso) dso__free_a2l_llvm(dso); } #elif defined(HAVE_LIBBFD_SUPPORT) - -/* - * Implement addr2line using libbfd. - */ -#define PACKAGE "perf" -#include - -struct a2l_data { - const char *input; - u64 addr; - - bool found; - const char *filename; - const char *funcname; - unsigned line; - - bfd *abfd; - asymbol **syms; -}; - -static int bfd_error(const char *string) -{ - const char *errmsg; - - errmsg =3D bfd_errmsg(bfd_get_error()); - fflush(stdout); - - if (string) - pr_debug("%s: %s\n", string, errmsg); - else - pr_debug("%s\n", errmsg); - - return -1; -} - -static int slurp_symtab(bfd *abfd, struct a2l_data *a2l) -{ - long storage; - long symcount; - asymbol **syms; - bfd_boolean dynamic =3D FALSE; - - if ((bfd_get_file_flags(abfd) & HAS_SYMS) =3D=3D 0) - return bfd_error(bfd_get_filename(abfd)); - - storage =3D bfd_get_symtab_upper_bound(abfd); - if (storage =3D=3D 0L) { - storage =3D bfd_get_dynamic_symtab_upper_bound(abfd); - dynamic =3D TRUE; - } - if (storage < 0L) - return bfd_error(bfd_get_filename(abfd)); - - syms =3D malloc(storage); - if (dynamic) - symcount =3D bfd_canonicalize_dynamic_symtab(abfd, syms); - else - symcount =3D bfd_canonicalize_symtab(abfd, syms); - - if (symcount < 0) { - free(syms); - return bfd_error(bfd_get_filename(abfd)); - } - - a2l->syms =3D syms; - return 0; -} - -static void find_address_in_section(bfd *abfd, asection *section, void *da= ta) -{ - bfd_vma pc, vma; - bfd_size_type size; - struct a2l_data *a2l =3D data; - flagword flags; - - if (a2l->found) - return; - -#ifdef bfd_get_section_flags - flags =3D bfd_get_section_flags(abfd, section); -#else - flags =3D bfd_section_flags(section); -#endif - if ((flags & SEC_ALLOC) =3D=3D 0) - return; - - pc =3D a2l->addr; -#ifdef bfd_get_section_vma - vma =3D bfd_get_section_vma(abfd, section); -#else - vma =3D bfd_section_vma(section); -#endif -#ifdef bfd_get_section_size - size =3D bfd_get_section_size(section); -#else - size =3D bfd_section_size(section); -#endif - - if (pc < vma || pc >=3D vma + size) - return; - - a2l->found =3D bfd_find_nearest_line(abfd, section, a2l->syms, pc - vma, - &a2l->filename, &a2l->funcname, - &a2l->line); - - if (a2l->filename && !strlen(a2l->filename)) - a2l->filename =3D NULL; -} - -static struct a2l_data *addr2line_init(const char *path) -{ - bfd *abfd; - struct a2l_data *a2l =3D NULL; - - abfd =3D bfd_openr(path, NULL); - if (abfd =3D=3D NULL) - return NULL; - - if (!bfd_check_format(abfd, bfd_object)) - goto out; - - a2l =3D zalloc(sizeof(*a2l)); - if (a2l =3D=3D NULL) - goto out; - - a2l->abfd =3D abfd; - a2l->input =3D strdup(path); - if (a2l->input =3D=3D NULL) - goto out; - - if (slurp_symtab(abfd, a2l)) - goto out; - - return a2l; - -out: - if (a2l) { - zfree((char **)&a2l->input); - free(a2l); - } - bfd_close(abfd); - return NULL; -} - -static void addr2line_cleanup(struct a2l_data *a2l) -{ - if (a2l->abfd) - bfd_close(a2l->abfd); - zfree((char **)&a2l->input); - zfree(&a2l->syms); - free(a2l); -} - -static int inline_list__append_dso_a2l(struct dso *dso, - struct inline_node *node, - struct symbol *sym) -{ - struct a2l_data *a2l =3D dso__a2l(dso); - struct symbol *inline_sym =3D new_inline_sym(dso, sym, a2l->funcname); - char *srcline =3D NULL; - - if (a2l->filename) - srcline =3D srcline_from_fileline(a2l->filename, a2l->line); - - return inline_list__append(inline_sym, srcline, node); -} +#include "libbfd.h" =20 static int addr2line(const char *dso_name, u64 addr, char **file, unsigned int *line, struct dso *dso, bool unwind_inlines, struct inline_node *node, struct symbol *sym) { - int ret =3D 0; - struct a2l_data *a2l =3D dso__a2l(dso); - - if (!a2l) { - a2l =3D addr2line_init(dso_name); - dso__set_a2l(dso, a2l); - } - - if (a2l =3D=3D NULL) { - if (!symbol_conf.disable_add2line_warn) - pr_warning("addr2line_init failed for %s\n", dso_name); - return 0; - } - - a2l->addr =3D addr; - a2l->found =3D false; - - bfd_map_over_sections(a2l->abfd, find_address_in_section, a2l); - - if (!a2l->found) - return 0; - - if (unwind_inlines) { - int cnt =3D 0; - - if (node && inline_list__append_dso_a2l(dso, node, sym)) - return 0; - - while (bfd_find_inliner_info(a2l->abfd, &a2l->filename, - &a2l->funcname, &a2l->line) && - cnt++ < MAX_INLINE_NEST) { - - if (a2l->filename && !strlen(a2l->filename)) - a2l->filename =3D NULL; - - if (node !=3D NULL) { - if (inline_list__append_dso_a2l(dso, node, sym)) - return 0; - // found at least one inline frame - ret =3D 1; - } - } - } - - if (file) { - *file =3D a2l->filename ? strdup(a2l->filename) : NULL; - ret =3D *file ? 1 : 0; - } - - if (line) - *line =3D a2l->line; - - return ret; + return libbfd__addr2line(dso_name, addr, file, line, dso, unwind_inlines,= node, sym); } =20 void dso__free_a2l(struct dso *dso) { - struct a2l_data *a2l =3D dso__a2l(dso); - - if (!a2l) - return; - - addr2line_cleanup(a2l); - - dso__set_a2l(dso, NULL); + dso__free_a2l_libbfd(dso); } =20 #else /* HAVE_LIBBFD_SUPPORT */ diff --git a/tools/perf/util/srcline.h b/tools/perf/util/srcline.h index 80c20169e250..6e66ddbcc879 100644 --- a/tools/perf/util/srcline.h +++ b/tools/perf/util/srcline.h @@ -29,6 +29,8 @@ void srcline__tree_delete(struct rb_root_cached *tree); extern char *srcline__unknown; #define SRCLINE_UNKNOWN srcline__unknown =20 +#define MAX_INLINE_NEST 1024 + struct inline_list { struct symbol *symbol; char *srcline; diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c index 1346fd180653..9e820599bab3 100644 --- a/tools/perf/util/symbol-elf.c +++ b/tools/perf/util/symbol-elf.c @@ -9,6 +9,7 @@ =20 #include "compress.h" #include "dso.h" +#include "libbfd.h" #include "map.h" #include "maps.h" #include "symbol.h" @@ -24,18 +25,6 @@ #include #include =20 -#ifdef HAVE_LIBBFD_SUPPORT -#define PACKAGE 'perf' -#include -#endif - -#if defined(HAVE_LIBBFD_SUPPORT) || defined(HAVE_CPLUS_DEMANGLE_SUPPORT) -#ifndef DMGL_PARAMS -#define DMGL_PARAMS (1 << 0) /* Include function args */ -#define DMGL_ANSI (1 << 1) /* Include const, volatile, etc */ -#endif -#endif - #ifndef EM_AARCH64 #define EM_AARCH64 183 /* ARM 64 bit */ #endif @@ -871,47 +860,16 @@ static int elf_read_build_id(Elf *elf, void *bf, size= _t size) return err; } =20 -#ifdef HAVE_LIBBFD_BUILDID_SUPPORT - -static int read_build_id(const char *filename, struct build_id *bid, bool = block) -{ - size_t size =3D sizeof(bid->data); - int err =3D -1, fd; - bfd *abfd; - - fd =3D open(filename, block ? O_RDONLY : (O_RDONLY | O_NONBLOCK)); - if (fd < 0) - return -1; - - abfd =3D bfd_fdopenr(filename, /*target=3D*/NULL, fd); - if (!abfd) - return -1; - - if (!bfd_check_format(abfd, bfd_object)) { - pr_debug2("%s: cannot read %s bfd file.\n", __func__, filename); - goto out_close; - } - - if (!abfd->build_id || abfd->build_id->size > size) - goto out_close; - - memcpy(bid->data, abfd->build_id->data, abfd->build_id->size); - memset(bid->data + abfd->build_id->size, 0, size - abfd->build_id->size); - err =3D bid->size =3D abfd->build_id->size; - -out_close: - bfd_close(abfd); - return err; -} - -#else // HAVE_LIBBFD_BUILDID_SUPPORT - static int read_build_id(const char *filename, struct build_id *bid, bool = block) { size_t size =3D sizeof(bid->data); - int fd, err =3D -1; + int fd, err; Elf *elf; =20 + err =3D libbfd__read_build_id(filename, bid, block); + if (err >=3D 0) + goto out; + if (size < BUILD_ID_SIZE) goto out; =20 @@ -936,8 +894,6 @@ static int read_build_id(const char *filename, struct b= uild_id *bid, bool block) return err; } =20 -#endif // HAVE_LIBBFD_BUILDID_SUPPORT - int filename__read_build_id(const char *filename, struct build_id *bid, bo= ol block) { struct kmod_path m =3D { .name =3D NULL, }; @@ -1022,44 +978,6 @@ int sysfs__read_build_id(const char *filename, struct= build_id *bid) return err; } =20 -#ifdef HAVE_LIBBFD_SUPPORT - -int filename__read_debuglink(const char *filename, char *debuglink, - size_t size) -{ - int err =3D -1; - asection *section; - bfd *abfd; - - abfd =3D bfd_openr(filename, NULL); - if (!abfd) - return -1; - - if (!bfd_check_format(abfd, bfd_object)) { - pr_debug2("%s: cannot read %s bfd file.\n", __func__, filename); - goto out_close; - } - - section =3D bfd_get_section_by_name(abfd, ".gnu_debuglink"); - if (!section) - goto out_close; - - if (section->size > size) - goto out_close; - - if (!bfd_get_section_contents(abfd, section, debuglink, 0, - section->size)) - goto out_close; - - err =3D 0; - -out_close: - bfd_close(abfd); - return err; -} - -#else - int filename__read_debuglink(const char *filename, char *debuglink, size_t size) { @@ -1071,6 +989,10 @@ int filename__read_debuglink(const char *filename, ch= ar *debuglink, Elf_Scn *sec; Elf_Kind ek; =20 + err =3D libbfd_filename__read_debuglink(filename, debuglink, size); + if (err >=3D 0) + goto out; + fd =3D open(filename, O_RDONLY); if (fd < 0) goto out; @@ -1112,8 +1034,6 @@ int filename__read_debuglink(const char *filename, ch= ar *debuglink, return err; } =20 -#endif - bool symsrc__possibly_runtime(struct symsrc *ss) { return ss->dynsym || ss->opdsec; diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 3d04382687d1..cc26b7bf302b 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1589,137 +1589,6 @@ static int dso__load_perf_map(const char *map_path,= struct dso *dso) return -1; } =20 -#ifdef HAVE_LIBBFD_SUPPORT -#define PACKAGE 'perf' -#include - -static int bfd_symbols__cmpvalue(const void *a, const void *b) -{ - const asymbol *as =3D *(const asymbol **)a, *bs =3D *(const asymbol **)b; - - if (bfd_asymbol_value(as) !=3D bfd_asymbol_value(bs)) - return bfd_asymbol_value(as) - bfd_asymbol_value(bs); - - return bfd_asymbol_name(as)[0] - bfd_asymbol_name(bs)[0]; -} - -static int bfd2elf_binding(asymbol *symbol) -{ - if (symbol->flags & BSF_WEAK) - return STB_WEAK; - if (symbol->flags & BSF_GLOBAL) - return STB_GLOBAL; - if (symbol->flags & BSF_LOCAL) - return STB_LOCAL; - return -1; -} - -int dso__load_bfd_symbols(struct dso *dso, const char *debugfile) -{ - int err =3D -1; - long symbols_size, symbols_count, i; - asection *section; - asymbol **symbols, *sym; - struct symbol *symbol; - bfd *abfd; - u64 start, len; - - abfd =3D bfd_openr(debugfile, NULL); - if (!abfd) - return -1; - - if (!bfd_check_format(abfd, bfd_object)) { - pr_debug2("%s: cannot read %s bfd file.\n", __func__, - dso__long_name(dso)); - goto out_close; - } - - if (bfd_get_flavour(abfd) =3D=3D bfd_target_elf_flavour) - goto out_close; - - symbols_size =3D bfd_get_symtab_upper_bound(abfd); - if (symbols_size =3D=3D 0) { - bfd_close(abfd); - return 0; - } - - if (symbols_size < 0) - goto out_close; - - symbols =3D malloc(symbols_size); - if (!symbols) - goto out_close; - - symbols_count =3D bfd_canonicalize_symtab(abfd, symbols); - if (symbols_count < 0) - goto out_free; - - section =3D bfd_get_section_by_name(abfd, ".text"); - if (section) { - for (i =3D 0; i < symbols_count; ++i) { - if (!strcmp(bfd_asymbol_name(symbols[i]), "__ImageBase") || - !strcmp(bfd_asymbol_name(symbols[i]), "__image_base__")) - break; - } - if (i < symbols_count) { - /* PE symbols can only have 4 bytes, so use .text high bits */ - u64 text_offset =3D (section->vma - (u32)section->vma) - + (u32)bfd_asymbol_value(symbols[i]); - dso__set_text_offset(dso, text_offset); - dso__set_text_end(dso, (section->vma - text_offset) + section->size); - } else { - dso__set_text_offset(dso, section->vma - section->filepos); - dso__set_text_end(dso, section->filepos + section->size); - } - } - - qsort(symbols, symbols_count, sizeof(asymbol *), bfd_symbols__cmpvalue); - -#ifdef bfd_get_section -#define bfd_asymbol_section bfd_get_section -#endif - for (i =3D 0; i < symbols_count; ++i) { - sym =3D symbols[i]; - section =3D bfd_asymbol_section(sym); - if (bfd2elf_binding(sym) < 0) - continue; - - while (i + 1 < symbols_count && - bfd_asymbol_section(symbols[i + 1]) =3D=3D section && - bfd2elf_binding(symbols[i + 1]) < 0) - i++; - - if (i + 1 < symbols_count && - bfd_asymbol_section(symbols[i + 1]) =3D=3D section) - len =3D symbols[i + 1]->value - sym->value; - else - len =3D section->size - sym->value; - - start =3D bfd_asymbol_value(sym) - dso__text_offset(dso); - symbol =3D symbol__new(start, len, bfd2elf_binding(sym), STT_FUNC, - bfd_asymbol_name(sym)); - if (!symbol) - goto out_free; - - symbols__insert(dso__symbols(dso), symbol); - } -#ifdef bfd_get_section -#undef bfd_asymbol_section -#endif - - symbols__fixup_end(dso__symbols(dso), false); - symbols__fixup_duplicate(dso__symbols(dso)); - dso__set_adjust_symbols(dso, true); - - err =3D 0; -out_free: - free(symbols); -out_close: - bfd_close(abfd); - return err; -} -#endif - static bool dso__is_compatible_symtab_type(struct dso *dso, bool kmod, enum dso_binary_type type) { --=20 2.51.0.570.gb178f27e6d-goog