From 27d036e9952387dff6eafe009f1769b575148454 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Thu, 1 Nov 2018 22:28:58 +0000 Subject: [PATCH] [ELF] Change sh_link of .rel{,a}.plt to make GNU strip happy Summary: D52830 sets sh_link to .symtab in static link, which breaks executable stripped by GNU strip. It may also be odd that .rela.plt (SHF_ALLOC) points to .symtab (non-SHF_ALLOC). Change the logic on pcc's suggestion. Before: % clang -fuse-ld=lld -static -xc =(printf 'int main(){}') # or gcc % strip a.out; ./a.out unexpected reloc type in static binary[1] 61634 segmentation fault ./a.out Reviewers: ruiu, grimar, emaste, espindola Reviewed By: ruiu Subscribers: pcc, arichardson, llvm-commits Differential Revision: https://reviews.llvm.org/D53993 llvm-svn: 345899 --- lld/ELF/SyntheticSections.cpp | 14 +++++--------- lld/test/ELF/aarch64-gnu-ifunc.s | 2 +- lld/test/ELF/gnu-ifunc-i386.s | 2 +- lld/test/ELF/gnu-ifunc.s | 5 +---- 4 files changed, 8 insertions(+), 15 deletions(-) diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index 2cca1fe..9d2e0a7 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -1491,15 +1491,11 @@ void RelocationBaseSection::addReloc(const DynamicReloc &Reloc) { } void RelocationBaseSection::finalizeContents() { - // If all relocations are R_*_{,I}RELATIVE they don't refer to any dynamic - // symbol and we don't need a dynamic symbol table. If that is the case, use - // the index of the regular symbol table section (if exists) or 0. - if (In.DynSymTab) - getParent()->Link = In.DynSymTab->getParent()->SectionIndex; - else if (In.SymTab) - getParent()->Link = In.SymTab->getParent()->SectionIndex; - else - getParent()->Link = 0; + // When linking glibc statically, .rel{,a}.plt contains R_*_IRELATIVE + // relocations due to IFUNC (e.g. strcpy). sh_link will be set to 0 in that + // case. + InputSection *SymTab = Config->Relocatable ? In.SymTab : In.DynSymTab; + getParent()->Link = SymTab ? SymTab->getParent()->SectionIndex : 0; if (In.RelaIplt == this || In.RelaPlt == this) getParent()->Info = In.GotPlt->getParent()->SectionIndex; diff --git a/lld/test/ELF/aarch64-gnu-ifunc.s b/lld/test/ELF/aarch64-gnu-ifunc.s index 0a38fba..9a15f13 100644 --- a/lld/test/ELF/aarch64-gnu-ifunc.s +++ b/lld/test/ELF/aarch64-gnu-ifunc.s @@ -15,7 +15,7 @@ // CHECK-NEXT: Address: [[RELA:.*]] // CHECK-NEXT: Offset: 0x158 // CHECK-NEXT: Size: 48 -// CHECK-NEXT: Link: 6 +// CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 4 // CHECK-NEXT: AddressAlignment: 8 // CHECK-NEXT: EntrySize: 24 diff --git a/lld/test/ELF/gnu-ifunc-i386.s b/lld/test/ELF/gnu-ifunc-i386.s index 2ddf80c..bfc1587 100644 --- a/lld/test/ELF/gnu-ifunc-i386.s +++ b/lld/test/ELF/gnu-ifunc-i386.s @@ -15,7 +15,7 @@ // CHECK-NEXT: Address: [[RELA:.*]] // CHECK-NEXT: Offset: 0xD4 // CHECK-NEXT: Size: 16 -// CHECK-NEXT: Link: 6 +// CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 4 // CHECK-NEXT: AddressAlignment: 4 // CHECK-NEXT: EntrySize: 8 diff --git a/lld/test/ELF/gnu-ifunc.s b/lld/test/ELF/gnu-ifunc.s index 5aa5b0a..25c71b0 100644 --- a/lld/test/ELF/gnu-ifunc.s +++ b/lld/test/ELF/gnu-ifunc.s @@ -15,16 +15,13 @@ // CHECK-NEXT: Address: [[RELA:.*]] // CHECK-NEXT: Offset: 0x158 // CHECK-NEXT: Size: 48 -// CHECK-NEXT: Link: [[SYMTAB:.*]] +// CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: [[GOTPLT:.*]] // CHECK-NEXT: AddressAlignment: 8 // CHECK-NEXT: EntrySize: 24 // CHECK-NEXT: } // CHECK: Index: [[GOTPLT]] // CHECK-NEXT: Name: .got.plt -// CHECK: Index: [[SYMTAB]] -// CHECK-NEXT: Name: .symtab -// CHECK-NEXT: Type: SHT_SYMTAB // CHECK: Relocations [ // CHECK-NEXT: Section ({{.*}}) .rela.plt { // CHECK-NEXT: 0x202000 R_X86_64_IRELATIVE -- 2.7.4