libelf: Rewrite elf_scnshndx, extended index table handling
elf_scnshndx is a elfutils extension to libelf that given a SHT_SYMTAB
section returns the index to the corresponding SHT_SYMTAB_SHNDX
section, if it exists. This is needed when there are more than 64K
sections and there are symbols that have to refer to a section with an
index larger than 64K, because the Elf Sym st_shndx field is only
16 bits.
This was implemented by adding an shndx_index field to the Elf_Scn
struct which is updated when reading the section headers. This takes
up space in every section and is hard to proof correct. In the case of
using ELF_C_READ_MMAP the shndx_index field was only updated when the
shdrs needed to be converted from file to memory order.
And the two places were this function was used in readelf.c and
elf-print-reloc-syms.c the wrong section was used to lookup the
extended index table. There were also no tests for this functionality.
Replace the elf_scnshndx implementation with a simpler lookup over all
sections. This sounds inefficient, but in practice the
SHT_SYMTAB_SHNDX section is the next section after the SHT_SYMTAB
section. elf_scnshndx only needs to be called when there are more than
SHN_LORESERVE (0xff00) sections. And normally a user would just lookup
the SHT_SYMTAB and SHT_SYMTAB_SHNDX sections at the same time (which
is what readelf does when showing the symbol table, as does nm,
objcopy and libdwfl).
Add a testfile manyfuncs.c that when compiled contains 64K symbols and
sections. Make sure to use -fasynchronous-unwind-tables so there is at
least one relocatable section that uses all function symbols (e.g. on
arm32 where there is no .eh_frame by default). This can then be used
to verify the readelf --relocs support. Add another test,
test-manyfuncs that explicitly goes through the symbol table and
associated extended index table and verify each function symbol
matches the section name.
There are For riscv there are local, notype, symbols at the start of each
executable section which relocations refer to instead of the section
symbol. Since all these local symbols are called ".L0" this isn't very
useful, so print the section name instead. For powerpc ELFv1 all
function symbols go through the .opd section. Allow this in the new
test-manyfuncs test.
* libelf/elf32_getshdr.c (load_shdr_wrlock): Remove handling
of shndx_index.
* libelf/elf_begin.c (file_read_elf): Likewise.
* libelf/elf_scnshndx.c (elf_scnshndx): Rewritten.
* libelf/libelf.h (elf_scnshndx): Added full documentation.
* libelf/libelfP.h (struct Elf_Scn): Remove shndx_index field.
(__elf_scnshndx_internal): Removed.
* src/readelf.c (handle_relocs_rel): Use symscn in call to
elf_scnshndx. Print section name for local start section label.
(handle_relocs_rela): Likewise.
* tests/Makefile.am (check_PROGRAMS): Add test-manyfuncs.
(manyfuncs.o): New target.
(check-local): New target, depends on manyfuncs.o.
(TESTS): Add run-readelf-r-manyfuncs.sh and
run-test-manyfuncs.sh.
(EXTRA_DIST): Add run-readelf-r-manyfuncs.sh,
run-test-manyfuncs.sh and manyfuncs.c.
(test_manyfuncs_LDADD): New variable.
(EXTRA_test_manyfuncs_DEPENDENCIES): New variable.
(CLEANFILES): Add manyfuncs.o.
* tests/elf-print-reloc-syms.c (print_reloc_symnames):
Use symscn in call to elf_scnshndx.
* tests/manyfuncs.c: New test file to generate 64K symbols and
sections.
* tests/run-readelf-r-manyfuncs.sh: New test wrapper.
* tests/run-test-manyfuncs.sh: Likewise.
* tests/test-manyfuncs.c: New test.