diff options
author | George Rimar <grimar@accesssoftek.com> | 2018-11-01 09:20:06 +0000 |
---|---|---|
committer | George Rimar <grimar@accesssoftek.com> | 2018-11-01 09:20:06 +0000 |
commit | 3608decaa5285e5e2d60fade30b57b82d82c2fff (patch) | |
tree | 66e497a41ff0516e91c85c47f881fa11f268e0da | |
parent | 6749c24f408a3e1e1209c01ac9655eb5b302bd29 (diff) | |
download | bcm5719-llvm-3608decaa5285e5e2d60fade30b57b82d82c2fff.tar.gz bcm5719-llvm-3608decaa5285e5e2d60fade30b57b82d82c2fff.zip |
[ELF] - Do not crash when -r output uses linker script with `/DISCARD/`
This is https://bugs.llvm.org/show_bug.cgi?id=39493.
We crashed previously because did not handle /DISCARD/ properly
when -r was used. I think it is uncommon to use scripts with -r, though I see
nothing wrong to handle the /DISCARD/ so that we will not crash at least.
Differential revision: https://reviews.llvm.org/D53864
llvm-svn: 345819
-rw-r--r-- | lld/ELF/InputFiles.cpp | 12 | ||||
-rw-r--r-- | lld/ELF/InputSection.cpp | 6 | ||||
-rw-r--r-- | lld/test/ELF/linkerscript/relocatable-discard.s | 21 |
3 files changed, 34 insertions, 5 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 212cb853166..8a7e9276ea6 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -645,8 +645,16 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { // This section contains relocation information. // If -r is given, we do not interpret or apply relocation // but just copy relocation sections to output. - if (Config->Relocatable) - return make<InputSection>(*this, Sec, Name); + if (Config->Relocatable) { + InputSection *RelocSec = make<InputSection>(*this, Sec, Name); + // We want to add a dependency to target, similar like we do for + // -emit-relocs below. This is useful for the case when linker script + // contains the "/DISCARD/". It is perhaps uncommon to use a script with + // -r, but we faced it in the Linux kernel and have to handle such case + // and not to crash. + Target->DependentSections.push_back(RelocSec); + return RelocSec; + } if (Target->FirstRelocation) fatal(toString(this) + diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index cff011484ab..daff31bfc08 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -432,8 +432,8 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { error("STT_SECTION symbol should be defined"); continue; } - SectionBase *Section = D->Section; - if (Section == &InputSection::Discarded) { + SectionBase *Section = D->Section->Repl; + if (!Section->Live) { P->setSymbolAndType(0, 0, false); continue; } @@ -460,7 +460,7 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { } if (RelTy::IsRela) - P->r_addend = Sym.getVA(Addend) - Section->Repl->getOutputSection()->Addr; + P->r_addend = Sym.getVA(Addend) - Section->getOutputSection()->Addr; else if (Config->Relocatable) Sec->Relocations.push_back({R_ABS, Type, Rel.r_offset, Addend, &Sym}); } diff --git a/lld/test/ELF/linkerscript/relocatable-discard.s b/lld/test/ELF/linkerscript/relocatable-discard.s new file mode 100644 index 00000000000..d4f5826b72d --- /dev/null +++ b/lld/test/ELF/linkerscript/relocatable-discard.s @@ -0,0 +1,21 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "SECTIONS { /DISCARD/ : { *(.discard.*) }}" > %t.script +# RUN: ld.lld -o %t --script %t.script -r %t.o +# RUN: llvm-readobj -sections %t | FileCheck %s + +## Test shows that we do not crash after discarding the .discard.foo with -r. +## Previously it happened because of 2 reasons: +## 1) .rela.discard.foo was not handled properly and was not discarded. +## Remaining reference was invalid and caused the crash. +## 2) Third-party section .debug_info referencing discarded section +## did not handle this case properly and tried to apply the +## relocation instead of ignoring it. + +# CHECK-NOT: .discard + +.section .discard.foo,"ax" +callq fn@PLT + +.section .debug_info,"",@progbits +.long .discard.foo |