Bug 1817111

Summary: ldd reports "not a dynamic executable" on a dynamic executable with a large LOAD section
Product: Red Hat Enterprise Linux 8 Reporter: Jeff Bastian <jbastian>
Component: glibcAssignee: glibc team <glibc-bugzilla>
Status: CLOSED DUPLICATE QA Contact: qe-baseos-tools-bugs
Severity: low Docs Contact:
Priority: low    
Version: 8.2CC: ashankar, codonell, dj, efuller, fweimer, jhladky, mnewsome, pfrankli, sipoyare
Target Milestone: rc   
Target Release: 8.3   
Hardware: All   
OS: Linux   
Whiteboard:
Fixed In Version: Doc Type: If docs needed, set a value
Doc Text:
Story Points: ---
Clone Of: Environment:
Last Closed: 2020-03-28 02:55:52 UTC Type: Bug
Regression: --- Mount Type: ---
Documentation: --- CRM:
Verified Versions: Category: ---
oVirt Team: --- RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: --- Target Upstream Version:
Embargoed:

Description Jeff Bastian 2020-03-25 15:33:25 UTC
Description of problem:
ldd reports "not a dynamic executable" on a dynamic executable with a large LOAD section (larger than system RAM + swap).  If you add more swap space, ldd works correctly.

For example, the NAS Parallel Benchmark 'ft' has an 85 GB LOAD section when compiled as a "class D" benchmark (*):

~]# readelf -l bin/ft.D.x | grep -A1 -e Type -e LOAD
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flags  Align
--
  LOAD           0x0000000000000000 0x0000000000400000 0x0000000000400000
                 0x0000000000005df8 0x0000000000005df8  R E    0x200000
  LOAD           0x0000000000006dc0 0x0000000000606dc0 0x0000000000606dc0
                 0x00000000000003cc 0x0000001402a18a80  RW     0x200000
                                    ^^^^^^^^^^^^^^^^^^
                                          |
                                          +-- = ~85 GB

~]# ldd bin/ft.D.x
	not a dynamic executable

~]# free -g
              total        used        free      shared  buff/cache   available
Mem:             45           0          42           0           2          44
Swap:            22           0          22

~]# fallocate -l 64G swapfile

~]# chmod 600 swapfile

~]# mkswap swapfile 
Setting up swapspace version 1, size = 64 GiB (68719472640 bytes)
no label, UUID=54cc7016-55fa-47e0-acc8-726375c5be5b

~]# swapon swapfile

~]# free -g
              total        used        free      shared  buff/cache   available
Mem:             45           0          42           0           2          44
Swap:            86           0          86

~]# ldd bin/ft.D.x 
	linux-vdso.so.1 (0x00007ffd5b9f8000)
	libgfortran.so.5 => /lib64/libgfortran.so.5 (0x00007fd52b3bb000)
	libm.so.6 => /lib64/libm.so.6 (0x00007fd52b039000)
	libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00007fd52ae21000)
	libquadmath.so.0 => /lib64/libquadmath.so.0 (0x00007fd52abe0000)
	libc.so.6 => /lib64/libc.so.6 (0x00007fd52a81e000)
	libz.so.1 => /lib64/libz.so.1 (0x00007fd52a607000)
	/lib64/ld-linux-x86-64.so.2 (0x00007fd52b838000)


Version-Release number of selected component (if applicable):
glibc-2.28-101.el8.x86_64
gcc-gfortran-8.3.1-5.el8.x86_64

How reproducible:
always

Steps to Reproduce:
1. yum -y install gcc-gfortran openmpi openmpi-devel
2. wget https://www.nas.nasa.gov/assets/npb/NPB3.3.1.tar.gz
3. tar xf NPB3.3.1.tar.gz
4. cd NPB3.3.1/NPB3.3-OMP
5. cp config/make.def.template config/make.def
6. sed -i -e 's/f77/gfortran/' \
       -e '/^[CF]FLAGS/ s/$/ -mcmodel=medium/' config/make.def
7. make ft CLASS=D
8. ldd bin/ft.D.x

Actual results:
not a dynamic executable

Expected results:
list of the linked libraries

Additional info:
(*) NPB classes: https://www.nas.nasa.gov/publications/npb_problem_sizes.html

Comment 1 Eirik Fuller 2020-03-25 15:48:47 UTC
ldd is a bash script that uses the exit status of the dynamic linker invoked with --verify; an exit status of 1 leads to the " not a dynamic executable" report.

The following strace output shows the failed mmap which leads to the exit status of 1 for an executable with an oversize LOAD segment (that mmap failure is presumably related to the segfault reported in bug 1817106).

[root@RHEL1 NPB_sources]# strace -f /lib64/ld-linux-x86-64.so.2 --verify bin/ft.D.x
execve("/lib64/ld-linux-x86-64.so.2", ["/lib64/ld-linux-x86-64.so.2", "--verify", "bin/ft.D.x"], 0x7ffe379d6758 /* 29 vars */) = 0
brk(NULL)                               = 0x5555559e1000
arch_prctl(0x3001 /* ARCH_??? */, 0x7ffea098f140) = -1 EINVAL (Invalid argument)
openat(AT_FDCWD, "bin/ft.D.x", O_RDONLY|O_CLOEXEC) = 3
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\2\0>\0\1\0\0\0P\16@\0\0\0\0\0"..., 832) = 832
fstat(3, {st_mode=S_IFREG|0755, st_size=83168, ...}) = 0
getcwd("/root/BZ1815509/NPB_sources", 128) = 28
mmap(0x400000, 36864, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0) = 0x400000
mmap(0x608000, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x8000) = 0x608000
mmap(0x60a000, 85941318816, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = -1 ENOMEM (Cannot allocate memory)
close(3)                                = 0
exit_group(1)                           = ?
+++ exited with 1 +++
[root@RHEL1 NPB_sources]#

The 'file' command, on the other hand, recognizes such an executable as dynamically linked.

[root@RHEL1 NPB_sources]# file bin/ft.D.x
bin/ft.D.x: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=7d80b696366eb0d1d1e4980b3eb953520d45614d, with debug_info, not stripped
[root@RHEL1 NPB_sources]# 


Perhaps the dynamic linker needs a different exit code for the purpose of reporting mmap failures (in which case ldd would be modified to recognize it).

Comment 2 Jeff Bastian 2020-03-25 15:54:40 UTC
See also sibling bug 1817106 about the binary crashing with a seg fault in the loader.

Comment 3 Carlos O'Donell 2020-03-28 02:55:52 UTC
Jeff,

Thanks for submitting this!

The use of ldd to identify a binary requires being able to map the executable into memory.

Your alternatives to avoid this requirement are to use `file` or even better `eu-elfclassify` (from elfutils).

I'm closing this as a duplicate of bug 1085549 which already calls out this enhancement request.

*** This bug has been marked as a duplicate of bug 1085549 ***