Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

__rela_iplt_{start,end} get bogus section index if .rela.iplt section is discarded #35982

Closed
rui314 opened this issue Mar 7, 2018 · 6 comments
Labels
bugzilla Issues migrated from bugzilla lld:ELF

Comments

@rui314
Copy link
Member

rui314 commented Mar 7, 2018

Bugzilla Link 36634
Resolution FIXED
Resolved on Apr 21, 2019 05:47
Version unspecified
OS All
CC @DimitryAndric,@emaste,@MaskRay

Extended Description

For static linking, we synthesize __rela_iplt_start and __rela_iplt_end symbols which point to the beginning and ending of .rela.iplt. If .rela.iplt is discarded after that, then the symbols get bogus section index 0xffff. If that happens, no one really uses the symbols, so the symbols' section value doesn't matter, but it should at least be a sane value (0xffff is a reserved value).

@emaste
Copy link
Member

emaste commented Nov 27, 2018

We've been investigating an issue with lld 6.0 in upcoming FreeBSD 12.0 which turns out to be this.

https://bugs.freebsd.org/233397

@emaste
Copy link
Member

emaste commented Nov 27, 2018

From the FreeBSD PR, ld.bfd and gold pick different arbitrary sections for Ndx for these symbols:

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

@MaskRay
Copy link
Member

MaskRay commented Nov 28, 2018

This is tricky.

I have tried several approaches:

  • Leave __rela_iplt_start undefined if .rela.plt (IPLT) is empty. This should work as the two implementations I know use weak references:

// freebsd/src/lib/csu/common/ignore_init.c
extern const Elf_Rela __rela_iplt_start[] __weak_symbol __hidden;
extern const Elf_Rela __rela_iplt_end[] __weak_symbol __hidden;

#include "reloc.c"

static void
process_irelocs(void)
{
const Elf_Rela *r;

for (r = &__rela_iplt_start[0]; r < &__rela_iplt_end[0]; r++)
	crt1_handle_rela(r);

}

// glibc/csu/libc-start.c
static void
apply_irel (void)
{

ifdef IREL

/* We use weak references for these so that we'll still work with a linker
   that doesn't define them.  Such a linker doesn't support IFUNC at all
   and so uses won't work, but a statically-linked program that doesn't
   use any IFUNC symbols won't have a problem.  */
extern const IREL_T IPLT_START[] __attribute__ ((weak));
extern const IREL_T IPLT_END[] __attribute__ ((weak));
for (const IREL_T *ipltent = IPLT_START; ipltent < IPLT_END; ++ipltent)
  IREL (ipltent);

endif

}
#endif

I've seen a weird glibc R_X86_64_GOTPCRELX relocation error.
Using 0 is not as good as using an arbitrary section as the distance between the section and the relocation site is smaller.

In lld/ELF/Writer.cpp finalizeSections, there is some nuance when the following processes are reordered:

  • addRelIpltSymbols

  • forEachRelSec(scanRelocations);

  • In.Iplt->addSymbols();

  • ...

  • https://reviews.llvm.org/D54985 [ELF] Keep empty In.RelaIplt so that _rela_iplt{start,end} have valid st_shndx

This requires a change in llvm-readobj as otherwise it would complain .rela.plt is not in any segment

--- c/tools/llvm-readobj/ELFDumper.cpp
+++ i/tools/llvm-readobj/ELFDumper.cpp
@@ -1489,7 +1489,8 @@ void ELFDumper::parseDynamicTable(
const Elf_Phdr &Phdr = **I;
uint64_t Delta = VAddr - Phdr.p_vaddr;
if (Delta >= Phdr.p_filesz)

  •  report_fatal_error("Virtual address is not in any segment");
    
  •  return nullptr;
    

After that, ninja check-lld-elf reports:

Expected Passes : 1113
Unsupported Tests : 8
Unexpected Failures: 271

This place also needs patching:

PltRelSec = findNotEmptySectionByAddress(Obj, *DtJmpRel);
if (!PltRelSec)
  report_fatal_error("There is no not empty RELPLT section at 0x" +
                     Twine::utohexstr(*DtJmpRel));

@emaste
Copy link
Member

emaste commented Nov 28, 2018

The first option (leaving them undefined in the absence of ifuncs) is my preference.

@rui314
Copy link
Member Author

rui314 commented Nov 28, 2018

Maybe we can scan all symbols to make sure that there is at least one ifunc symbol before adding _rela_iplt{start,end} symbols.

@MaskRay
Copy link
Member

MaskRay commented Apr 21, 2019

Fixed by https://reviews.llvm.org/D56623

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla lld:ELF
Projects
None yet
Development

No branches or pull requests

3 participants