summaryrefslogtreecommitdiff
path: root/tools/perf/util/symbol-elf.c
diff options
context:
space:
mode:
authorAdrian Hunter <adrian.hunter@intel.com>2023-01-20 14:34:53 +0200
committerArnaldo Carvalho de Melo <acme@redhat.com>2023-01-22 18:10:28 -0300
commit698a0d1a1a6c095477b07b9fc2e8713ee642ed53 (patch)
treefa6ad2530b78e282bef7a63dc562c5a1397fbdea /tools/perf/util/symbol-elf.c
parent5fec9b171cd80616e52e463ae5ae155483078004 (diff)
perf symbols: Add symbol for .plt header
perf expands the _init symbol over .plt because there are no PLT symbols at that point, but then dso__synthesize_plt_symbols() creates them. Fix by truncating the previous symbol and inserting a symbol for .plt header. Example: Before: $ perf test --dso `which uname` -v Symbols 74: Symbols : --- start --- test child forked, pid 191028 Problems creating module maps, continuing anyway... Testing /usr/bin/uname Overlapping symbols: 2000-25f0 g _init 2040-2050 g free@plt test child finished with -1 ---- end ---- Symbols: FAILED! $ perf test --dso `which uname` -vv Symbols 2>/tmp/cmp1.txt After: $ perf test --dso `which uname` -v Symbols 74: Symbols : --- start --- test child forked, pid 194291 Testing /usr/bin/uname test child finished with 0 ---- end ---- Symbols: Ok $ perf test --dso `which uname` -vv Symbols 2>/tmp/cmp2.txt $ diff /tmp/cmp1.txt /tmp/cmp2.txt 4,5c4 < test child forked, pid 191031 < Problems creating module maps, continuing anyway... --- > test child forked, pid 194296 9c8,9 < 2000-25f0 g _init --- > 2000-2030 g _init > 2030-2040 g .plt 100,103c100 < Overlapping symbols: < 2000-25f0 g _init < 2040-2050 g free@plt < test child finished with -1 --- > test child finished with 0 105c102 < Symbols: FAILED! --- > Symbols: Ok $ Signed-off-by: Adrian Hunter <adrian.hunter@intel.com> Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com> Acked-by: Ian Rogers <irogers@google.com> Cc: Jiri Olsa <jolsa@kernel.org> Cc: Namhyung Kim <namhyung@kernel.org> Link: https://lore.kernel.org/r/20230120123456.12449-8-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Diffstat (limited to 'tools/perf/util/symbol-elf.c')
-rw-r--r--tools/perf/util/symbol-elf.c26
1 files changed, 21 insertions, 5 deletions
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index 87b82507c205..a8b7c3860b2d 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -389,6 +389,27 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
elf = ss->elf;
ehdr = ss->ehdr;
+ if (!elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL))
+ return 0;
+
+ /*
+ * A symbol from a previous section (e.g. .init) can have been expanded
+ * by symbols__fixup_end() to overlap .plt. Truncate it before adding
+ * a symbol for .plt header.
+ */
+ f = dso__find_symbol_nocache(dso, shdr_plt.sh_offset);
+ if (f && f->start < shdr_plt.sh_offset && f->end > shdr_plt.sh_offset)
+ f->end = shdr_plt.sh_offset;
+
+ if (!get_plt_sizes(dso, &ehdr, &shdr_plt, &plt_header_size, &plt_entry_size))
+ return 0;
+
+ /* Add a symbol for .plt header */
+ f = symbol__new(shdr_plt.sh_offset, plt_header_size, STB_GLOBAL, STT_FUNC, ".plt");
+ if (!f)
+ goto out_elf_end;
+ symbols__insert(&dso->symbols, f);
+
scn_dynsym = ss->dynsym;
shdr_dynsym = ss->dynshdr;
dynsym_idx = ss->dynsym_idx;
@@ -408,9 +429,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
if (shdr_rel_plt.sh_link != dynsym_idx)
goto out_elf_end;
- if (elf_section_by_name(elf, &ehdr, &shdr_plt, ".plt", NULL) == NULL)
- goto out_elf_end;
-
/*
* Fetch the relocation section to find the idxes to the GOT
* and the symbols in the .dynsym they refer to.
@@ -436,8 +454,6 @@ int dso__synthesize_plt_symbols(struct dso *dso, struct symsrc *ss)
nr_rel_entries = shdr_rel_plt.sh_size / shdr_rel_plt.sh_entsize;
plt_offset = shdr_plt.sh_offset;
- if (!get_plt_sizes(dso, &ehdr, &shdr_plt, &plt_header_size, &plt_entry_size))
- return 0;
plt_offset += plt_header_size;
if (shdr_rel_plt.sh_type == SHT_RELA) {