diff --git a/lld/ELF/DWARF.cpp b/lld/ELF/DWARF.cpp index 6ebe7247e904..6b90a038e873 100644 --- a/lld/ELF/DWARF.cpp +++ b/lld/ELF/DWARF.cpp @@ -93,11 +93,8 @@ LLDDwarfObj::findAux(const InputSectionBase &Sec, uint64_t Pos, uint32_t SecIndex = File->getSectionIndex(Sym); // Broken debug info can point to a non-Defined symbol. - Symbol &S = File->getRelocTargetSym(Rel); - auto *DR = dyn_cast(&S); + auto *DR = dyn_cast(&File->getRelocTargetSym(Rel)); if (!DR) { - if (S.isSection()) - return None; RelType Type = Rel.getType(Config->IsMips64EL); if (Type != Target->NoneRel) error(toString(File) + ": relocation " + lld::toString(Type) + " at 0x" + diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index d1a72f0adc4c..0c36ef141ae0 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -1080,9 +1080,6 @@ template void ObjFile::initializeSymbols() { if (ESym.st_shndx == SHN_UNDEF) this->Symbols[I] = make(this, Name, Binding, StOther, Type); - else if (Sec == &InputSection::Discarded) - this->Symbols[I] = make(this, Name, Binding, StOther, Type, - /*DiscardedSecIdx=*/SecIdx); else this->Symbols[I] = make(this, Name, Binding, StOther, Type, Value, Size, Sec); diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index d077c017ca71..3e8d093e6d2d 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -412,8 +412,7 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef Rels) { for (const RelTy &Rel : Rels) { RelType Type = Rel.getType(Config->IsMips64EL); - const ObjFile *File = getFile(); - Symbol &Sym = File->getRelocTargetSym(Rel); + Symbol &Sym = getFile()->getRelocTargetSym(Rel); auto *P = reinterpret_cast(Buf); Buf += sizeof(RelTy); @@ -436,23 +435,10 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef Rels) { // .eh_frame is horribly special and can reference discarded sections. To // avoid having to parse and recreate .eh_frame, we just replace any // relocation in it pointing to discarded sections with R_*_NONE, which - // hopefully creates a frame that is ignored at runtime. Also, don't warn - // on .gcc_except_table and debug sections. - // - // See the comment in maybeReportUndefined for PPC64 .toc . + // hopefully creates a frame that is ignored at runtime. auto *D = dyn_cast(&Sym); if (!D) { - if (!Sec->Name.startswith(".debug") && - !Sec->Name.startswith(".zdebug") && Sec->Name != ".eh_frame" && - Sec->Name != ".gcc_except_table" && Sec->Name != ".toc") { - uint32_t SecIdx = cast(Sym).DiscardedSecIdx; - Elf_Shdr_Impl Sec = - CHECK(File->getObj().sections(), File)[SecIdx]; - warn("relocation refers to a discarded section: " + - CHECK(File->getObj().getSectionName(&Sec), File) + - "\n>>> referenced by " + getObjMsg(P->r_offset)); - } - P->setSymbolAndType(0, 0, false); + error("STT_SECTION symbol should be defined"); continue; } SectionBase *Section = D->Section->Repl; diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index 8b8a3b1d4f91..639a3c5555e5 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -653,17 +653,9 @@ static std::string maybeReportDiscarded(Undefined &Sym) { return ""; ArrayRef> ObjSections = CHECK(File->getObj().sections(), File); - - std::string Msg; - if (Sym.Type == ELF::STT_SECTION) { - Msg = "relocation refers to a discarded section: "; - Msg += CHECK( - File->getObj().getSectionName(&ObjSections[Sym.DiscardedSecIdx]), File); - } else { - Msg = "relocation refers to a symbol in a discarded section: " + - toString(Sym); - } - Msg += "\n>>> defined in " + toString(File); + std::string Msg = + "relocation refers to a symbol in a discarded section: " + toString(Sym) + + "\n>>> defined in " + toString(File); Elf_Shdr_Impl ELFSec = ObjSections[Sym.DiscardedSecIdx - 1]; if (ELFSec.sh_type != SHT_GROUP) diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp index 9a4de4faf106..5300aafaff8a 100644 --- a/lld/ELF/Symbols.cpp +++ b/lld/ELF/Symbols.cpp @@ -48,11 +48,17 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) { auto &D = cast(Sym); SectionBase *IS = D.Section; + // According to the ELF spec reference to a local symbol from outside + // the group are not allowed. Unfortunately .eh_frame breaks that rule + // and must be treated specially. For now we just replace the symbol with + // 0. + if (IS == &InputSection::Discarded) + return 0; + // This is an absolute symbol. if (!IS) return D.Value; - assert(IS != &InputSection::Discarded); IS = IS->Repl; uint64_t Offset = D.Value; diff --git a/lld/test/ELF/Inputs/comdat-discarded-reloc.s b/lld/test/ELF/Inputs/comdat-discarded-reloc.s index d89575f27e94..9526f5ac95c0 100644 --- a/lld/test/ELF/Inputs/comdat-discarded-reloc.s +++ b/lld/test/ELF/Inputs/comdat-discarded-reloc.s @@ -1,8 +1,6 @@ -.global bar, _start +.section .text.bar1,"aG",@progbits,group,comdat -.section .text.foo,"aG",@progbits,group,comdat - -.section .text -_start: - .quad .text.foo - .quad bar +.section .text.bar2 +.global bar +bar: + .quad .text.bar1 diff --git a/lld/test/ELF/comdat-discarded-error.s b/lld/test/ELF/comdat-discarded-error.s index d5aa4aa68df7..afefdaf02c8d 100644 --- a/lld/test/ELF/comdat-discarded-error.s +++ b/lld/test/ELF/comdat-discarded-error.s @@ -5,7 +5,7 @@ # RUN: echo '.section .text.foo,"axG",@progbits,foo,comdat; .globl bar; bar:' |\ # RUN: llvm-mc -filetype=obj -triple=x86_64 - -o %t3.o -# RUN: not ld.lld %t2.o %t3.o %t1.o -o /dev/null 2>&1 | FileCheck %s +# RUN: not ld.lld %t1.o %t2.o %t3.o -o /dev/null 2>&1 | FileCheck %s # CHECK: error: relocation refers to a symbol in a discarded section: bar # CHECK-NEXT: >>> defined in {{.*}}3.o @@ -13,16 +13,6 @@ # CHECK-NEXT: >>> prevailing definition is in {{.*}}2.o # CHECK-NEXT: >>> referenced by {{.*}}1.o:(.text+0x1) -# CHECK: error: relocation refers to a discarded section: .text.foo -# CHECK-NEXT: >>> defined in {{.*}}1.o -# CHECK-NEXT: >>> section group signature: foo -# CHECK-NEXT: >>> prevailing definition is in {{.*}}2.o -# CHECK-NEXT: >>> referenced by {{.*}}1.o:(.data+0x0) - .globl _start _start: jmp bar - -.section .text.foo,"axG",@progbits,foo,comdat -.data - .quad .text.foo diff --git a/lld/test/ELF/comdat-discarded-gdb-index.s b/lld/test/ELF/comdat-discarded-gdb-index.s deleted file mode 100644 index 43505960498a..000000000000 --- a/lld/test/ELF/comdat-discarded-gdb-index.s +++ /dev/null @@ -1,63 +0,0 @@ -# REQUIRES: x86 -# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o -# RUN: ld.lld --gdb-index %t.o %t.o -o %t - -## .debug_info has a relocation to .text.foo . The second %t.o is discarded. -## Check we don't error on the relocation. -# CHECK: .rela.debug_info { -# CHECK-NEXT: 0xC R_X86_64_64 .text.foo 0x0 - -.section .text.foo,"axG",@progbits,foo,comdat -.globl foo -.Lfunc_begin0: -foo: - ret -.Lfunc_end0: - -.section .debug_abbrev,"",@progbits - .byte 1 # Abbreviation Code - .byte 17 # DW_TAG_compile_unit - .byte 1 # DW_CHILDREN_yes - .byte 17 # DW_AT_low_pc - .byte 1 # DW_FORM_addr - .byte 18 # DW_AT_high_pc - .byte 6 # DW_FORM_data4 - .ascii "\264B" # DW_AT_GNU_pubnames - .byte 25 # DW_FORM_flag_present - .byte 0 # EOM(1) - .byte 0 # EOM(2) - .byte 2 # Abbreviation Code - .byte 46 # DW_TAG_subprogram - .byte 0 # DW_CHILDREN_no - .byte 3 # DW_AT_name - .byte 8 # DW_FORM_string - .byte 0 # EOM(1) - .byte 0 # EOM(2) - .byte 0 - -.section .debug_info,"",@progbits -.Lcu_begin0: - .long .Lcu_end0 - .Lcu_begin0 - 4 - .short 4 # DWARF version number - .long 0 # Offset Into Abbrev. Section - .byte 4 # Address Size -.Ldie0: - .byte 1 # Abbrev [1] DW_TAG_compile_unit - .quad .Lfunc_begin0 # DW_AT_low_pc - .long .Lfunc_end0 - .Lfunc_begin0 # DW_AT_high_pc - .byte 2 # Abbrev [2] DW_TAG_subprogram - .asciz "foo" # DW_AT_name - .byte 0 -.Lcu_end0: - -.section .debug_gnu_pubnames,"",@progbits - .long .LpubNames_end0 - .LpubNames_begin0 -.LpubNames_begin0: - .short 2 # Version - .long .Lcu_begin0 # CU Offset - .long .Lcu_end0 - .Lcu_begin0 - .long .Ldie0 - .Lcu_begin0 - .byte 48 # Attributes: FUNCTION, EXTERNAL - .asciz "foo" # External Name - .long 0 -.LpubNames_end0: diff --git a/lld/test/ELF/comdat-discarded-reloc.s b/lld/test/ELF/comdat-discarded-reloc.s index 4d50ab10e512..d23baf386e92 100644 --- a/lld/test/ELF/comdat-discarded-reloc.s +++ b/lld/test/ELF/comdat-discarded-reloc.s @@ -1,42 +1,17 @@ # REQUIRES: x86 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/comdat-discarded-reloc.s -o %t2.o -# RUN: ld.lld -gc-sections --noinhibit-exec %t2.o %t.o -o /dev/null -# RUN: ld.lld -r %t2.o %t.o -o %t 2>&1 | FileCheck --check-prefix=WARN %s -# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s +# RUN: ld.lld -gc-sections %t.o %t2.o -o %t ## ELF spec doesn't allow a relocation to point to a deduplicated ## COMDAT section. Unfortunately this happens in practice (e.g. .eh_frame) ## Test case checks we do not crash. -# WARN: warning: relocation refers to a discarded section: .text.bar1 -# WARN-NEXT: >>> referenced by {{.*}}.o:(.rela.text.bar2+0x0) -# WARN-NOT: warning +.global bar, _start -# RELOC: .rela.eh_frame { -# RELOC-NEXT: R_X86_64_NONE -# RELOC-NEXT: } -# RELOC-NEXT: .rela.debug_foo { -# RELOC-NEXT: R_X86_64_NONE -# RELOC-NEXT: } -# RELOC-NEXT: .rela.gcc_except_table { -# RELOC-NEXT: R_X86_64_NONE -# RELOC-NEXT: } +.section .text.foo,"aG",@progbits,group,comdat -.section .text.bar1,"aG",@progbits,group,comdat - -## .text.bar1 in this file is discarded. Warn on the relocation. -.section .text.bar2,"ax" -.globl bar -bar: - .quad .text.bar1 - -## Don't warn on .eh_frame, .debug*, .zdebug*, or .gcc_except_table -.section .eh_frame,"a" - .quad .text.bar1 - -.section .debug_foo - .quad .text.bar1 - -.section .gcc_except_table,"a" - .quad .text.bar1 +.section .text +_start: + .quad .text.foo + .quad bar diff --git a/lld/test/ELF/comdat.s b/lld/test/ELF/comdat.s index 9e3f5a81d300..86103e5d9eb7 100644 --- a/lld/test/ELF/comdat.s +++ b/lld/test/ELF/comdat.s @@ -1,7 +1,7 @@ // REQUIRES: x86 // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/comdat.s -o %t2.o -// RUN: ld.lld -shared %t.o %t2.o -o %t +// RUN: ld.lld -shared %t.o %t.o %t2.o -o %t // RUN: llvm-objdump -d %t | FileCheck %s // RUN: llvm-readobj -S --symbols %t | FileCheck --check-prefix=READ %s @@ -31,7 +31,9 @@ foo: // CHECK-EMPTY: // CHECK-NEXT: bar: // 0x1000 - 0x1001 - 5 = -6 +// 0 - 0x1006 - 5 = -4107 // CHECK-NEXT: 1001: {{.*}} callq -6 +// CHECK-NEXT: 1006: {{.*}} callq -4107 .section .text3,"axG",@progbits,zed,comdat,unique,0 diff --git a/lld/test/ELF/invalid-undef-section-symbol.test b/lld/test/ELF/invalid-undef-section-symbol.test new file mode 100644 index 000000000000..1d66885eadf8 --- /dev/null +++ b/lld/test/ELF/invalid-undef-section-symbol.test @@ -0,0 +1,26 @@ +# RUN: yaml2obj %s -o %t.o +# RUN: not ld.lld -r %t.o -o /dev/null 2>&1 | FileCheck %s + +# We used to crash at this. +# CHECK: STT_SECTION symbol should be defined + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .text + Type: SHT_PROGBITS + - Name: .rela.text + Type: SHT_RELA + AddressAlign: 0x0000000000000008 + Info: .text + Relocations: + - Offset: 0x0000000000000000 + Symbol: .text + Type: R_X86_64_NONE +Symbols: + - Name: .text + Type: STT_SECTION diff --git a/lld/test/ELF/relocatable-eh-frame.s b/lld/test/ELF/relocatable-eh-frame.s new file mode 100644 index 000000000000..dee906acb87f --- /dev/null +++ b/lld/test/ELF/relocatable-eh-frame.s @@ -0,0 +1,19 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: ld.lld -r %t.o %t.o -o %t +# RUN: llvm-readobj -r %t | FileCheck %s +# RUN: ld.lld %t -o %t.so -shared +# RUN: llvm-objdump -h %t.so | FileCheck --check-prefix=DSO %s + +# DSO: .eh_frame 00000034 + +# CHECK: Relocations [ +# CHECK-NEXT: Section ({{.*}}) .rela.eh_frame { +# CHECK-NEXT: 0x20 R_X86_64_PC32 .foo 0x0 +# CHECK-NEXT: 0x50 R_X86_64_NONE - 0x0 +# CHECK-NEXT: } +# CHECK-NEXT: ] + +.section .foo,"aG",@progbits,bar,comdat +.cfi_startproc +.cfi_endproc