Index: include/lld/ReaderWriter/ELFLinkingContext.h =================================================================== --- include/lld/ReaderWriter/ELFLinkingContext.h +++ include/lld/ReaderWriter/ELFLinkingContext.h @@ -346,6 +346,13 @@ script::Sema &linkerScriptSema() { return _linkerScriptSema; } const script::Sema &linkerScriptSema() const { return _linkerScriptSema; } + /// Notify the ELFLinkingContext when the new ELF section is read. + void notifyInputSectionName(StringRef name); + /// Encountered C-ident input section names. + const llvm::StringSet<> &cidentSectionNames() const { + return _cidentSections; + } + // Set R_ARM_TARGET1 relocation behaviour bool armTarget1Rel() const { return _armTarget1Rel; } void setArmTarget1Rel(bool value) { _armTarget1Rel = value; } @@ -401,6 +408,7 @@ std::map _absoluteSymbols; llvm::StringSet<> _dynamicallyExportedSymbols; std::unique_ptr _resolver; + llvm::StringSet<> _cidentSections; // The linker script semantic object, which owns all script ASTs, is stored // in the current linking context via _linkerScriptSema. Index: lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h =================================================================== --- lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h +++ lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h @@ -50,6 +50,8 @@ void ARMExecutableWriter::processUndefinedSymbol( StringRef symName, RuntimeFile &file) const { + ARMELFWriter>::processUndefinedSymbol(symName, + file); if (symName == gotSymbol) { file.addAbsoluteAtom(gotSymbol); } else if (symName.startswith("__exidx")) { Index: lib/ReaderWriter/ELF/ELFFile.cpp =================================================================== --- lib/ReaderWriter/ELF/ELFFile.cpp +++ lib/ReaderWriter/ELF/ELFFile.cpp @@ -152,6 +152,10 @@ _relocationReferences[sHdr] = make_range(ri, re); totalRelocs += std::distance(ri, re); } else { + auto sectionName = _objFile->getSectionName(§ion); + if (std::error_code ec = sectionName.getError()) + return ec; + _ctx.notifyInputSectionName(*sectionName); _sectionSymbols[§ion]; } } Index: lib/ReaderWriter/ELF/ELFLinkingContext.cpp =================================================================== --- lib/ReaderWriter/ELF/ELFLinkingContext.cpp +++ lib/ReaderWriter/ELF/ELFLinkingContext.cpp @@ -247,4 +247,13 @@ _resolver = std::move(resolver); } +void ELFLinkingContext::notifyInputSectionName(StringRef name) { + // Save sections names which can be represented as a C identifier. + if (name.find_first_not_of("0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "_") == StringRef::npos) + _cidentSections.insert(name); +} + } // end namespace lld Index: lib/ReaderWriter/ELF/OutputELFWriter.h =================================================================== --- lib/ReaderWriter/ELF/OutputELFWriter.h +++ lib/ReaderWriter/ELF/OutputELFWriter.h @@ -113,7 +113,7 @@ /// \brief Process undefined symbols that left after resolution step. virtual void processUndefinedSymbol(StringRef symName, - RuntimeFile &file) const {} + RuntimeFile &file) const; /// \brief Assign addresses to atoms marking section's start and end. void updateScopeAtomValues(StringRef sym, StringRef sec); @@ -144,6 +144,7 @@ private: static StringRef maybeGetSOName(Node *node); + void updateScopeAtomValues(StringRef start, StringRef end, StringRef sec); }; } // namespace elf Index: lib/ReaderWriter/ELF/OutputELFWriter.cpp =================================================================== --- lib/ReaderWriter/ELF/OutputELFWriter.cpp +++ lib/ReaderWriter/ELF/OutputELFWriter.cpp @@ -246,6 +246,14 @@ assert(a); a->_virtualAddr = res; } + // If there is a section named XXX, and XXX is a valid C identifier, + // and there are undefined or weak __start_XXX/__stop_XXX symbols, + // set the symbols values to the begin/end of the XXX section + // correspondingly. + for (const auto &name : _ctx.cidentSectionNames()) + updateScopeAtomValues((Twine("__start_") + name.getKey()).str(), + (Twine("__stop_") + name.getKey()).str(), + name.getKey()); } template void OutputELFWriter::createDefaultSections() { @@ -455,23 +463,35 @@ } template +void OutputELFWriter::processUndefinedSymbol( + StringRef symName, RuntimeFile &file) const { + if (symName.startswith("__start_")) { + if (_ctx.cidentSectionNames().count(symName.drop_front(8))) + file.addAbsoluteAtom(symName); + } else if (symName.startswith("__stop_")) { + if (_ctx.cidentSectionNames().count(symName.drop_front(7))) + file.addAbsoluteAtom(symName); + } +} + +template void OutputELFWriter::updateScopeAtomValues(StringRef sym, StringRef sec) { - std::string start = ("__" + sym + "_start").str(); - std::string end = ("__" + sym + "_end").str(); + updateScopeAtomValues(("__" + sym + "_start").str().c_str(), + ("__" + sym + "_end").str().c_str(), sec); +} + +template +void OutputELFWriter::updateScopeAtomValues(StringRef start, + StringRef end, + StringRef sec) { AtomLayout *s = _layout.findAbsoluteAtom(start); AtomLayout *e = _layout.findAbsoluteAtom(end); - OutputSection *section = _layout.findOutputSection(sec); - if (!s || !e) - return; - - if (section) { - s->_virtualAddr = section->virtualAddr(); - e->_virtualAddr = section->virtualAddr() + section->memSize(); - } else { - s->_virtualAddr = 0; - e->_virtualAddr = 0; - } + const OutputSection *section = _layout.findOutputSection(sec); + if (s) + s->_virtualAddr = section ? section->virtualAddr() : 0; + if (e) + e->_virtualAddr = section ? section->virtualAddr() + section->memSize() : 0; } template class OutputELFWriter; Index: test/elf/start-stop-sym.test =================================================================== --- /dev/null +++ test/elf/start-stop-sym.test @@ -0,0 +1,108 @@ +# Check __start_XXX and __stop_XXX symbols handling where XXX +# is a section name which can be represented as a C identifier. + +# RUN: yaml2obj -format=elf -docnum 1 %s > %t1.o +# RUN: yaml2obj -format=elf -docnum 2 %s > %t2.o +# RUN: lld -flavor gnu -target mipsel -static -e T0 -o %t.exe %t1.o %t2.o +# RUN: llvm-objdump -s -t %t.exe | FileCheck %s + +# CHECK: Contents of section .text: +# CHECK-NEXT: 400080 a0004000 b4004000 00000000 00000000 +# ^ start of _csec section +# ^ end of _csec section +# CHECK-NEXT: 400090 a0004000 b4004000 +# CHECK-NEXT: Contents of section _csec: +# CHECK-NEXT: 4000a0 00000000 00000000 00000000 00000000 +# CHECK-NEXT: 4000b0 00000000 + +# CHECK: 004000a0 g *ABS* 00000000 __start__csec +# CHECK: 004000b4 g *ABS* 00000000 __stop__csec + +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32] + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 16 + Size: 8 + + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 4 + Info: .text + Relocations: + - Offset: 0 + Symbol: __start__csec + Type: R_MIPS_32 + - Offset: 4 + Symbol: __stop__csec + Type: R_MIPS_32 + + - Name: _csec + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + AddressAlign: 16 + Size: 4 + +Symbols: + Weak: + - Name: __start__csec + - Name: __stop__csec + Global: + - Name: T0 + Type: STT_FUNC + Section: .text + Size: 8 + +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_MIPS + Flags: [EF_MIPS_CPIC, EF_MIPS_ABI_O32, EF_MIPS_ARCH_32] + +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 16 + Size: 8 + + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 4 + Info: .text + Relocations: + - Offset: 0 + Symbol: __start__csec + Type: R_MIPS_32 + - Offset: 4 + Symbol: __stop__csec + Type: R_MIPS_32 + + - Name: _csec + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + AddressAlign: 16 + Size: 4 + +Symbols: + Weak: + - Name: __start__csec + - Name: __stop__csec + Global: + - Name: T1 + Type: STT_FUNC + Section: .text + Size: 8 +...