Bug 249121

Summary: program compiled with -pg produces ld-elf abort
Product: Base System Reporter: wsh
Component: gnuAssignee: Konstantin Belousov <kib>
Status: Closed FIXED    
Severity: Affects Some People CC: dim, emaste, kevinz5000, kib, markj, toolchain, wsh
Priority: --- Flags: koobs: mfc-stable12+
markj: mfc-stable11+
Version: CURRENT   
Hardware: amd64   
OS: Any   

Description wsh 2020-09-05 01:13:16 UTC
Attempting to profile my code with gprof.

Currently compiling with clang with arguments; 
    -Weverything
    -Werror
    -Wpedantic
    -O2
    -g
    -pg

Without -pg program runs perfectly fine. With -pg lib-elf haults with message
ld-elf.so.1: /lib/libc.so.7: Undefined symbol "__progname".

On FreeBSD-12.1-p8 I received a different error of unsupported relocation type 37 in non-plt relocations with the same compile options on the same executable.

I have attached the executable compiled with pg and no pg.
Comment 1 wsh 2020-09-05 01:18:00 UTC
Unfortunately my upload has failed since it is to big. If you would like
you may pull the repo and modify CMakeLists.txt to compile with -pg.

Requires llvm>=10 and openssl>=1.1

https://github.com/riski-sh/crochet
Comment 2 Konstantin Belousov freebsd_committer freebsd_triage 2020-09-05 18:11:17 UTC
Can you create minimal self contained reproducer consisting of single .c or .c++ file and build script ?
Comment 3 wsh 2020-09-05 21:08:53 UTC
A minimal self contained recreation consisted of a main.c with contents


int main(int argc, char **argv) {
  return 0;
}


Building with `clang main.c -g -pg` and running a.out produced segfault
Building with `clang main.c` and running a.out returns 0 as normal.
Comment 4 Konstantin Belousov freebsd_committer freebsd_triage 2020-09-05 22:18:46 UTC
Clang+lld produce very strange binary when all linked libraries are static:

Elf file type is EXEC (Executable file)
Entry point 0x2237a0
There are 11 program headers, starting at offset 64

Program Headers:
  Type           Offset             VirtAddr           PhysAddr
                 FileSiz            MemSiz              Flg    Align
  PHDR           0x0000000000000040 0x0000000000200040 0x0000000000200040
                 0x0000000000000268 0x0000000000000268  R      0x8
  INTERP         0x00000000000002a8 0x00000000002002a8 0x00000000002002a8
                 0x0000000000000015 0x0000000000000015  R      0x1
      [Requesting program interpreter: /libexec/ld-elf.so.1]
  LOAD           0x0000000000000000 0x0000000000200000 0x0000000000200000
                 0x000000000002279c 0x000000000002279c  R      0x1000
  LOAD           0x00000000000227a0 0x00000000002237a0 0x00000000002237a0
                 0x0000000000091760 0x0000000000091760  R E    0x1000
  LOAD           0x00000000000b3f00 0x00000000002b5f00 0x00000000002b5f00
                 0x0000000000001898 0x0000000000001898  RW     0x1000
  LOAD           0x00000000000b57a0 0x00000000002b87a0 0x00000000002b87a0
                 0x00000000000037c0 0x00000000002247a9  RW     0x1000
  TLS            0x00000000000b3f00 0x00000000002b5f00 0x00000000002b5f00
                 0x0000000000001850 0x0000000000001870  R      0x10
  GNU_RELRO      0x00000000000b3f00 0x00000000002b5f00 0x00000000002b5f00
                 0x0000000000001898 0x0000000000002100  R      0x1
  GNU_EH_FRAME   0x000000000000fc80 0x000000000020fc80 0x000000000020fc80
                 0x000000000000300c 0x000000000000300c  R      0x4
  GNU_STACK      0x0000000000000000 0x0000000000000000 0x0000000000000000
                 0x0000000000000000 0x0000000000000000  RW     0
  NOTE           0x00000000000002c0 0x00000000002002c0 0x00000000002002c0
                 0x0000000000000048 0x0000000000000048  R      0x4

...

There is no dynamic section in this file.

Relocation section with addend (.rela.dyn):
r_offset     r_info       r_type              st_value         st_name + r_addend
0000002bbf50 000000000025 R_X86_64_IRELATIVE  0000000000000000  + 223dd0
0000002bbf58 000000000025 R_X86_64_IRELATIVE  0000000000000000  + 2a91e0

As you see, it specifies PHDR INTERP, which brings rtld into action.
But there is no dynamic segment, so rtld cannot see any relocs, which results
in the IRELATIVE relocation sites to still point to the resolver functions.
This is arguably a bug in lld.

There are also two bugs in rtld which fixes I will commit shortly.  I assumes
dynamic segment is there and dereferences NULL pointer otherwise.  Also, it
terminates the image if there is no dynamic symbol table.
Comment 5 commit-hook freebsd_committer freebsd_triage 2020-09-05 22:42:09 UTC
A commit references this bug:

Author: kib
Date: Sat Sep  5 22:41:31 UTC 2020
New revision: 365368
URL: https://svnweb.freebsd.org/changeset/base/365368

Log:
  rtld: do not process absent dynamic.

  If object has no dynamic phdr, do not try to dereference NULL.  This
  means that we cannot process any relocation, and that there cannot be
  symbols defined, but it is up to static linker to produce meaningful
  objects.

  PR:	249121
  Reported by:	wsh@riski.sh
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week

Changes:
  head/libexec/rtld-elf/rtld.c
Comment 6 commit-hook freebsd_committer freebsd_triage 2020-09-05 22:45:11 UTC
A commit references this bug:

Author: kib
Date: Sat Sep  5 22:44:38 UTC 2020
New revision: 365369
URL: https://svnweb.freebsd.org/changeset/base/365369

Log:
  rtld: do not refuse to relocate objects without dynamic symtabs.

  Such objects can still have valid relocations not requiring symbolic
  references.

  PR:	249121
  Reported by:	wsh@riski.sh
  Sponsored by:	The FreeBSD Foundation
  MFC after:	1 week

Changes:
  head/libexec/rtld-elf/rtld.c
Comment 7 Konstantin Belousov freebsd_committer freebsd_triage 2020-09-06 15:21:59 UTC
And there seems to be one more bug with lld, besides omitting dynamic.  It seems to be really confused about what type of binary (static/dynamic) it produces.

Since &_DYNAMIC is NULL, I realized that linker should have filled values for
__rela_iplt_start and __rela_iplt_end, which are used by csu to locate irelocs.
But apparently linker did not that either.

Dimitry, can you fill lld bugs, please ?
Comment 8 commit-hook freebsd_committer freebsd_triage 2020-09-12 09:45:41 UTC
A commit references this bug:

Author: kib
Date: Sat Sep 12 09:44:50 UTC 2020
New revision: 365653
URL: https://svnweb.freebsd.org/changeset/base/365653

Log:
  MFC r365368:
  rtld: do not process absent dynamic.

  PR:	249121

Changes:
_U  stable/12/
  stable/12/libexec/rtld-elf/rtld.c
Comment 9 commit-hook freebsd_committer freebsd_triage 2020-09-12 09:46:44 UTC
A commit references this bug:

Author: kib
Date: Sat Sep 12 09:46:14 UTC 2020
New revision: 365654
URL: https://svnweb.freebsd.org/changeset/base/365654

Log:
  MFC r365369:
  rtld: do not refuse to relocate objects without dynamic symtabs.

  PR:	249121

Changes:
_U  stable/12/
  stable/12/libexec/rtld-elf/rtld.c
Comment 10 commit-hook freebsd_committer freebsd_triage 2020-09-12 09:47:45 UTC
A commit references this bug:

Author: kib
Date: Sat Sep 12 09:47:25 UTC 2020
New revision: 365655
URL: https://svnweb.freebsd.org/changeset/base/365655

Log:
  MFC r365368:
  rtld: do not process absent dynamic.

  PR:	249121

Changes:
_U  stable/11/
  stable/11/libexec/rtld-elf/rtld.c
Comment 11 commit-hook freebsd_committer freebsd_triage 2020-09-12 09:48:47 UTC
A commit references this bug:

Author: kib
Date: Sat Sep 12 09:47:58 UTC 2020
New revision: 365656
URL: https://svnweb.freebsd.org/changeset/base/365656

Log:
  MFC r365369:
  rtld: do not refuse to relocate objects without dynamic symtabs.

  PR:	249121

Changes:
_U  stable/11/
  stable/11/libexec/rtld-elf/rtld.c
Comment 12 Kubilay Kocak freebsd_committer freebsd_triage 2020-09-21 04:11:38 UTC
^Triage: Assign to committer resolving

Is this now resolved (head+stable{11,12) or their more commits or merges to come?
Comment 13 Kevin Zheng 2020-12-24 18:32:37 UTC
I seem to have come across this issue in 12.2-REELASE. Will this fix be available in a 12.3-REELASE?