Hi Omar, On Sat, 2020-03-21 at 11:21 -0700, Omar Sandoval wrote: > I encountered this in drgn on a vmcore for a large server created by > makedumpfile,
That makes sense since [vm]cores contain lots of segments. > but I was able to put together a minimal reproducer. > Generate the ELF file with this python script: > [...] > > And run this program: > [...] > > This should output 66000, but it outputs 65535 instead. That is a really nice testcase. If we tweak it a little (so all segments have the same load address) then it compresses to just 188 bytes with bzip2. Would you mind, and give your signed-off-by, for adding the attached to the testsuite? It fails before, and passes after your fix. > Looking at file_read_elf, the cache is only initialized from > elf_begin > from ELF_C_RDWR_MMAP and ELF_C_READ_MMAP_PRIVATE as long as > endianness > matches the host and the section headers are properly aligned: > > if (map_address != NULL && e_ident[EI_DATA] == MY_ELFDATA > && cmd != ELF_C_READ_MMAP /* We need a copy to be able to > write. */ > && (ALLOW_UNALIGNED > || (((uintptr_t) ((char *) ehdr + e_shoff) > & (__alignof__ (Elf64_Shdr) - 1)) == 0))) I had missed that part. So it is actually common to not have the phdrs cache. Thanks, Mark
From 28734adeb8cd51c7124330f88c1dc49c9c187865 Mon Sep 17 00:00:00 2001 From: Mark Wielaard <m...@klomp.org> Date: Sun, 22 Mar 2020 23:14:24 +0100 Subject: [PATCH] tests: Add testcase for elf_getphdrnum with more than 65535 entries. Signed-off-by: Mark Wielaard <m...@klomp.org> --- tests/ChangeLog | 11 +++ tests/Makefile.am | 10 ++- tests/getphdrnum.c | 42 +++++++++++ tests/run-getphdrnum.sh | 137 +++++++++++++++++++++++++++++++++++ tests/testfile-phdrs.elf.bz2 | Bin 0 -> 188 bytes 5 files changed, 197 insertions(+), 3 deletions(-) create mode 100644 tests/getphdrnum.c create mode 100755 tests/run-getphdrnum.sh create mode 100644 tests/testfile-phdrs.elf.bz2 diff --git a/tests/ChangeLog b/tests/ChangeLog index 33a5cf62..887c233a 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,14 @@ +2020-03-22 Omar Sandoval <osan...@fb.com> + Mark Wielaard <m...@klomp.org> + + * getphdrnum.c: New file. + * run-getphdrnum.sh: New test. + * testfile-phdrs.elf.bz2: New test file. + * Makefile.am (check_PROGRAMS): Add getphdrnum. + (TESTS): Add run-getphdrnum.sh. + (EXTRA_DIST): Add run-getphdrnum.sh and testfile-phdrs.elf.bz2. + (getphdrnum_LDADD): New variable. + 2020-02-19 Aaron Merey <ame...@redhat.com> * run-debuginfod-find.sh: Run tests for verifying default diff --git a/tests/Makefile.am b/tests/Makefile.am index a83c3d67..934110e0 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -62,7 +62,8 @@ check_PROGRAMS = arextract arsymtest newfile saridx scnnames sectiondump \ get-units-invalid get-units-split attr-integrate-skel \ all-dwarf-ranges unit-info next_cfi \ elfcopy addsections xlate_notes elfrdwrnop \ - dwelf_elf_e_machine_string + dwelf_elf_e_machine_string \ + getphdrnum asm_TESTS = asm-tst1 asm-tst2 asm-tst3 asm-tst4 asm-tst5 \ asm-tst6 asm-tst7 asm-tst8 asm-tst9 @@ -168,7 +169,8 @@ TESTS = run-arextract.sh run-arsymtest.sh run-ar.sh newfile test-nlist \ run-dwelf_elf_e_machine_string.sh \ run-elfclassify.sh run-elfclassify-self.sh \ run-disasm-riscv64.sh \ - run-pt_gnu_prop-tests.sh + run-pt_gnu_prop-tests.sh \ + run-getphdrnum.sh if !BIARCH export ELFUTILS_DISABLE_BIARCH = 1 @@ -476,7 +478,8 @@ EXTRA_DIST = run-arextract.sh run-arsymtest.sh run-ar.sh \ debuginfod-tars/pacman-sources/README.md \ debuginfod-tars/pacman-sources/hello.c \ run-pt_gnu_prop-tests.sh \ - testfile_pt_gnu_prop.bz2 testfile_pt_gnu_prop32.bz2 + testfile_pt_gnu_prop.bz2 testfile_pt_gnu_prop32.bz2 \ + run-getphdrnum.sh testfile-phdrs.elf.bz2 if USE_VALGRIND @@ -654,6 +657,7 @@ debuginfod_build_id_find_LDADD = $(libelf) $(libdw) xlate_notes_LDADD = $(libelf) elfrdwrnop_LDADD = $(libelf) dwelf_elf_e_machine_string_LDADD = $(libelf) $(libdw) +getphdrnum_LDADD = $(libelf) $(libdw) # We want to test the libelf header against the system elf.h header. # Don't include any -I CPPFLAGS. Except when we install our own elf.h. diff --git a/tests/getphdrnum.c b/tests/getphdrnum.c new file mode 100644 index 00000000..6ab51e22 --- /dev/null +++ b/tests/getphdrnum.c @@ -0,0 +1,42 @@ +#include <elfutils/libdwelf.h> +#include <fcntl.h> +#include <libelf.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <sys/types.h> + +int main(int argc, const char **argv) +{ + int fd; + Elf *elf; + size_t phnum; + + if (argc != 2) + { + fprintf(stderr, "usage: %s FILE\n", argv[0]); + return EXIT_FAILURE; + } + + fd = open(argv[1], O_RDONLY); + if (fd == -1) + { + perror("open"); + return EXIT_FAILURE; + } + elf_version(EV_CURRENT); + elf = elf_begin(fd, ELF_C_READ, NULL); + if (!elf) + { + fprintf(stderr, "elf_begin: %s\n", elf_errmsg(-1)); + return EXIT_FAILURE; + } + if (elf_getphdrnum(elf, &phnum)) + { + fprintf(stderr, "elf_getphdrnum: %s\n", elf_errmsg(-1)); + return EXIT_FAILURE; + } + + printf("%zu\n", phnum); + return EXIT_SUCCESS; +} diff --git a/tests/run-getphdrnum.sh b/tests/run-getphdrnum.sh new file mode 100755 index 00000000..889cdaf1 --- /dev/null +++ b/tests/run-getphdrnum.sh @@ -0,0 +1,137 @@ +#! /bin/sh + +# testfile-phdrs.elf generated with python3 script +# import struct +# import sys +# +# phnum = 66000 +# +# sys.stdout.buffer.write( +# struct.pack( +# "<16BHHIQQQIHHHHHH", +# # EI_MAG +# *b"\x7fELF", +# # EI_CLASS = ELFCLASS64 +# 2, +# # EI_DATA = ELFDATA2LSB +# 1, +# # EI_VERSION +# 1, +# # EI_OSABI = ELFOSABI_SYSV +# 0, +# # EI_ABIVERSION +# 0, +# # EI_PAD +# *bytes(7), +# # e_type = ET_CORE +# 4, +# # e_machine = EM_X86_64 +# 62, +# # e_version +# 1, +# # e_entry +# 0, +# # e_phoff = sizeof(Elf64_Ehdr) + sizeof(Elf64_Shdr) +# 128, +# # e_shoff = sizeof(Elf64_Ehdr) +# 64, +# # e_flags +# 0, +# # e_ehsize +# 64, +# # e_phentsize +# 56, +# # e_phnum = PN_XNUM +# 0xFFFF, +# # e_shentsize +# 64, +# # e_shnum +# 1, +# # e_shstrndx +# 0, +# ) +# ) +# +# sys.stdout.buffer.write( +# struct.pack( +# "<IIQQQQIIQQ", +# # sh_name +# 0, +# # sh_type = SHT_NULL +# 0, +# # sh_flags +# 0, +# # sh_addr +# 0, +# # sh_offset +# 0, +# # sh_size +# 0, +# # sh_link +# 0, +# # sh_info +# phnum, +# # sh_addralign +# 0, +# # sh_entsize +# 0, +# ) +# ) +# +# for i in range(phnum): +# sys.stdout.buffer.write( +# struct.pack( +# "<IIQQQQQQ", +# # p_type = PT_LOAD +# 1, +# # p_flags = PF_X|PF_W|PF_R +# 0x7, +# # p_offset +# 0, +# # p_vaddr +# # i * 4096, +# 4096, +# # p_paddr +# 0, +# # p_filesz +# 0, +# # p_memsz +# 4096, +# # p_align +# 0, +# ) +# ) + +. $srcdir/test-subr.sh + +testfiles testfile-phdrs.elf + +testrun_compare ${abs_top_builddir}/src/readelf -h testfile-phdrs.elf<<\EOF +ELF Header: + Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 + Class: ELF64 + Data: 2's complement, little endian + Ident Version: 1 (current) + OS/ABI: UNIX - System V + ABI Version: 0 + Type: CORE (Core file) + Machine: AMD x86-64 + Version: 1 (current) + Entry point address: 0 + Start of program headers: 128 (bytes into file) + Start of section headers: 64 (bytes into file) + Flags: + Size of this header: 64 (bytes) + Size of program header entries: 56 (bytes) + Number of program headers entries: 65535 (66000 in [0].sh_info) + Size of section header entries: 64 (bytes) + Number of section headers entries: 1 + Section header string table index: 0 + +EOF + +testrun_compare ${abs_builddir}/getphdrnum testfile-phdrs.elf<<\EOF +66000 +EOF + +exit 0 diff --git a/tests/testfile-phdrs.elf.bz2 b/tests/testfile-phdrs.elf.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..024ed79de1632f4e82daf9fb25d7bd4fb2680c05 GIT binary patch literal 188 zcmV;t07L&mT4*^jL0KkKS>yw)-v-^p{KEdyNB{r`06{|p006)MKmY&$umHG3AQ}MB zdW8TOjWp4qnx!Q4CX8eUtv1ebPzwK2fL56$0Ib%@C<SCHK`Pr_5hw*`?%MulcI>49 zukU_!?~0-XZlwUN<e(LzC=ASrLVywCDf1K+l4UiU#j@ofIy1fi1`Py&0ssdDFab)9 q2Gj&D$^sTB2w5Q%pz45ysvx2@<pB%I0v0F;Ul(#kI8cyuTy^czheuBU literal 0 HcmV?d00001 -- 2.18.2