Bug 233397

Summary: llvm-objdump doesn't work with statically linked binary: "index past the end of the symbol table"
Product: Base System Reporter: Li-Wen Hsu <lwhsu>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Some People CC: dim, emaste, kib
Priority: ---    
Version: 12.0-RELEASE   
Hardware: Any   
OS: Any   
URL: https://llvm.org/pr36634
Bug Depends on:    
Bug Blocks: 228911    

Description Li-Wen Hsu freebsd_committer freebsd_triage 2018-11-22 06:33:20 UTC
It is fixed in stable/12 but probably worth to merge to releng/12.

run script:

root@clinch1:~ # uname -a
FreeBSD clinch1.musec.engr.mun.ca 12.0-RC1 FreeBSD 12.0-RC1 r340470 GENERIC  amd64
root@clinch1:~ # cat a.c 
#include <stdio.h>

int main(int argc, const char *argv[])
{
        printf("hello world!\n");
        return 0;
}
root@clinch1:~ # clang -fuse-ld=lld -g -static a.c 
root@clinch1:~ # llvm-objdump -d a.out

a.out:  file format ELF64-x86-64

llvm-objdump: 'a.out': index past the end of the symbol table
Comment 1 Dimitry Andric freebsd_committer freebsd_triage 2018-11-23 06:40:31 UTC
Ed, any idea which revision in stable/12 fixed this? r339304 maybe? I'm unsure.
Comment 2 Li-Wen Hsu freebsd_committer freebsd_triage 2018-11-23 06:59:21 UTC
I'm locating the commit fixing this, with the artifacts available on hand: r340604 is bad, while r340608 is good.  I'm building and checking r340605, r340606, r340607.
Comment 3 Li-Wen Hsu freebsd_committer freebsd_triage 2018-11-24 05:02:14 UTC
r340608 fixes this.
Comment 4 Dimitry Andric freebsd_committer freebsd_triage 2018-11-24 10:42:52 UTC
That's strange... r340608 is the MFC of r339898 "Convert amd64_get/set_fs/gsbase to ifunc".  Which is an internal change in libc only, I don't see what it has to do with llvm-objdump.  Unless this changes the format of libc.a somehow?
Comment 5 Konstantin Belousov freebsd_committer freebsd_triage 2018-11-24 10:48:52 UTC
(In reply to Dimitry Andric from comment #4)
It is indeed _somewhat_ strange.  This merge introduced actual use of ifunc in libc, and in particular in the static binaries, which now have PLT.  Before that, csu contained code to process PLT and referenced weak start/stop symbols for the PLT bounds, which should be zeroes.
Comment 6 Li-Wen Hsu freebsd_committer freebsd_triage 2018-11-27 13:02:35 UTC
I've tried to build r340607 and r340608 cleanly and confirmed this.

Do we need to fix this in 12.0? Or maybe we can close this since it is fixed in 12-STABLE.
Comment 7 Ed Maste freebsd_committer freebsd_triage 2018-11-27 13:44:45 UTC
(In reply to Konstantin Belousov from comment #5)
We had some issues with lld and ifuncs with statically linked binaries that we brought in a fix or two for -- I wonder if the fix somehow introduced a regression for output _without_ ifuncs?

Does GNU objdump complain about a.out as well?

One thing to try: set LLD_REPRODUCE=hello.tar environment var and build the hello world on 12.0, then extract the hello.tar on stable/12, link with lld [ld.lld $(cat response.txt)] and check that output.
Comment 8 Li-Wen Hsu freebsd_committer freebsd_triage 2018-11-27 20:21:55 UTC
root@clinch1:~/hello # uname -a
FreeBSD clinch1.musec.engr.mun.ca 12.0-PRERELEASE FreeBSD 12.0-PRERELEASE r340752 GENERIC  amd64
root@clinch1:~/hello # cat response.txt
--chroot .
--eh-frame-hdr
-Bstatic
-o a.out
usr/lib/crt1.o
usr/lib/crti.o
usr/lib/crtbeginT.o
--library-path usr/lib
tmp/a-aa866f.o
--library gcc
--library gcc_eh
--library c
--library gcc
--library gcc_eh
usr/lib/crtend.o
usr/lib/crtn.o
root@clinch1:~/hello # ld.lld `cat response.txt `
root@clinch1:~/hello # llvm-objdump -d a.out

a.out:  file format ELF64-x86-64

llvm-objdump: 'a.out': index past the end of the symbol table
Comment 9 Li-Wen Hsu freebsd_committer freebsd_triage 2018-11-27 20:39:28 UTC
Reproducer: https://people.freebsd.org/~lwhsu/pr233397/hello.tar.xz
Comment 10 Ed Maste freebsd_committer freebsd_triage 2018-11-27 21:11:05 UTC
/usr/local/bin/objdump: a.out symbol number 1030 references nonexistent SHT_SYMTAB_SHNDX section
/usr/local/bin/objdump: a.out: File in wrong format

% readelf -s a.out | grep '^ *1030:'
  1030: 0000000000000000     0 NOTYPE  LOCAL  HIDDEN   65535 __rela_iplt_end

These symbols are added by:

// The beginning and the ending of .rel[a].plt section are marked
// with __rel[a]_iplt_{start,end} symbols if it is a statically linked
// executable. The runtime needs these symbols in order to resolve
// all IRELATIVE relocs on startup. For dynamic executables, we don't
// need these symbols, since IRELATIVE relocs are resolved through GOT
// and PLT. For details, see http://www.airs.com/blog/archives/403.
template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
  if (!Config->Static)
    return;
  StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start";
  addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK);

  S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end";
  addOptionalRegular(S, InX::RelaIplt, -1, STV_HIDDEN, STB_WEAK);
}

So what I think happens is when we have ifuncs these special symbols are emitted with Ndx set to the appropriate iplt section (.rela.plt), but when we have no ifuncs we still emit the symbols but there is no section for them to refer to.
Comment 11 Ed Maste freebsd_committer freebsd_triage 2018-11-27 21:15:28 UTC
This is https://llvm.org/pr36634
Comment 12 Ed Maste freebsd_committer freebsd_triage 2018-11-27 21:27:13 UTC
Linking with gold 1.15 (binutils 2.30):

nuc% readelf -s a.out | grep iplt
  1033: 000000000048b068     0 NOTYPE  LOCAL  HIDDEN     8 __rela_iplt_start
  1034: 000000000048b068     0 NOTYPE  LOCAL  HIDDEN     8 __rela_iplt_end

  [ 8] .tdata            PROGBITS         000000000048b070  0008a070
       0000000000001800  0000000000000000 WAT       0     0     16

with ld.bfd 2.30

nuc% readelf -s a.out | grep iplt
  1032: 00000000004001c0     0 NOTYPE  LOCAL  DEFAULT    1 __rela_iplt_end
  1034: 00000000004001c0     0 NOTYPE  LOCAL  DEFAULT    1 __rela_iplt_start

  [ 1] .note.tag         NOTE             0000000000400190  00000190
       0000000000000030  0000000000000000   A       0     0     4
Comment 13 Ed Maste freebsd_committer freebsd_triage 2018-11-28 02:27:41 UTC
Proposed patch in https://reviews.llvm.org/D54985.

This is probably only a cosmetic issue (i.e., when running objdump/readelf/etc. on the binary) unless it also causes tools like objcopy or strip to malfunction.
Comment 14 Dimitry Andric freebsd_committer freebsd_triage 2019-04-23 20:24:28 UTC
This was fixed in base r344779 (clang 8.0.0 rc3 import), which was merged into stable/12 in base r346168.