diff options
author | Adrian Hunter <adrian.hunter@intel.com> | 2023-01-20 14:34:53 +0200 |
---|---|---|
committer | Arnaldo Carvalho de Melo <acme@redhat.com> | 2023-01-22 18:10:28 -0300 |
commit | 698a0d1a1a6c095477b07b9fc2e8713ee642ed53 (patch) | |
tree | fa6ad2530b78e282bef7a63dc562c5a1397fbdea /tools/perf/util/symbol-elf.c | |
parent | 5fec9b171cd80616e52e463ae5ae155483078004 (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.c | 26 |
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) { |