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

Reply via email to