diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -345,9 +345,10 @@ if (!file->archiveName.empty()) archive = " in archive " + file->archiveName; - // Find a symbol that encloses a given location. + // Find a symbol that encloses a given location. An out-of-order STB_LOCAL + // symbol is represented by a null entry. for (Symbol *b : file->getSymbols()) - if (auto *d = dyn_cast(b)) + if (auto *d = dyn_cast_or_null(b)) if (d->section == this && d->value <= off && off < d->value + d->size) return filename + ":(" + toString(*d) + ")" + archive; diff --git a/lld/test/ELF/invalid/broken-symtab-duplicate-symbol.test b/lld/test/ELF/invalid/broken-symtab-duplicate-symbol.test new file mode 100644 --- /dev/null +++ b/lld/test/ELF/invalid/broken-symtab-duplicate-symbol.test @@ -0,0 +1,28 @@ +# REQUIRES: x86 +## The ELF spec says all symbols with STB_LOCAL binding precede the weak and # +## global symbols. Out-of-order local symbols are represented by null entries in +## InputFile::symbols. Test that we don't crash. + +# RUN: yaml2obj %s -o %t.o +# RUN: not ld.lld %t.o %t.o -o /dev/null 2>&1 | FileCheck %s +# CHECK: error: duplicate symbol: _start +# CHECK-NEXT: >>> defined at {{.*}}.o:(.text+0x0) +# CHECK-NEXT: >>> defined at {{.*}}.o:(.text+0x0) + +!ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Type: SHT_PROGBITS + Name: .text + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] +Symbols: + - Name: _start + Section: .text + Binding: STB_GLOBAL + - Name: local + Section: .text + Binding: STB_LOCAL