Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/llvm/llvm-project.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
authorSimon Atanasyan <simon@atanasyan.com>2015-07-03 14:25:37 +0300
committerSimon Atanasyan <simon@atanasyan.com>2015-07-03 14:25:37 +0300
commita87c17a2019986614fea015288f4cea4b7b173aa (patch)
treef4122facaffec7681d988f7d74988c40b3cd6040 /lld
parentcec93c355a7b2f1a6be436f233b043bd2632d4bd (diff)
[ELF] Define __start_XXX/__stop_XXX symbols where XXX is a section name
This is GNU ELF linker extension used particularly by LibC code. If input object files contain section named XXX, and the XXX is a valid C identifier, and there are undefined or weak symbols __start_XXX/__stop_XXX, linker should define __start_XXX/__stop_XXX symbols point to the begin/end of the XXX section correspondingly. For example, without support of this extension statically linked executables for X86_64 and Mips (maybe other) targets do not flush IO buffers at the end of executing. llvm-svn: 241341
Diffstat (limited to 'lld')
-rw-r--r--lld/include/lld/ReaderWriter/ELFLinkingContext.h8
-rw-r--r--lld/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h2
-rw-r--r--lld/lib/ReaderWriter/ELF/ELFFile.cpp4
-rw-r--r--lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp9
-rw-r--r--lld/lib/ReaderWriter/ELF/OutputELFWriter.cpp46
-rw-r--r--lld/lib/ReaderWriter/ELF/OutputELFWriter.h3
-rw-r--r--lld/test/elf/start-stop-sym.test108
7 files changed, 166 insertions, 14 deletions
diff --git a/lld/include/lld/ReaderWriter/ELFLinkingContext.h b/lld/include/lld/ReaderWriter/ELFLinkingContext.h
index 2ae59c0accb5..b59d3604cbca 100644
--- a/lld/include/lld/ReaderWriter/ELFLinkingContext.h
+++ b/lld/include/lld/ReaderWriter/ELFLinkingContext.h
@@ -346,6 +346,13 @@ public:
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 @@ protected:
std::map<std::string, uint64_t> _absoluteSymbols;
llvm::StringSet<> _dynamicallyExportedSymbols;
std::unique_ptr<File> _resolver;
+ llvm::StringSet<> _cidentSections;
// The linker script semantic object, which owns all script ASTs, is stored
// in the current linking context via _linkerScriptSema.
diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h b/lld/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h
index 45e0aff1f187..974dab63a126 100644
--- a/lld/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h
+++ b/lld/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h
@@ -50,6 +50,8 @@ void ARMExecutableWriter::createImplicitFiles(
void ARMExecutableWriter::processUndefinedSymbol(
StringRef symName, RuntimeFile<ELF32LE> &file) const {
+ ARMELFWriter<ExecutableWriter<ELF32LE>>::processUndefinedSymbol(symName,
+ file);
if (symName == gotSymbol) {
file.addAbsoluteAtom(gotSymbol);
} else if (symName.startswith("__exidx")) {
diff --git a/lld/lib/ReaderWriter/ELF/ELFFile.cpp b/lld/lib/ReaderWriter/ELF/ELFFile.cpp
index 0e35e458f188..4e1fd818bded 100644
--- a/lld/lib/ReaderWriter/ELF/ELFFile.cpp
+++ b/lld/lib/ReaderWriter/ELF/ELFFile.cpp
@@ -152,6 +152,10 @@ std::error_code ELFFile<ELFT>::createAtomizableSections() {
_relocationReferences[sHdr] = make_range(ri, re);
totalRelocs += std::distance(ri, re);
} else {
+ auto sectionName = _objFile->getSectionName(&section);
+ if (std::error_code ec = sectionName.getError())
+ return ec;
+ _ctx.notifyInputSectionName(*sectionName);
_sectionSymbols[&section];
}
}
diff --git a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
index 5e734b2f88c9..361bd509fa8e 100644
--- a/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
+++ b/lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
@@ -247,4 +247,13 @@ void ELFLinkingContext::setUndefinesResolver(std::unique_ptr<File> resolver) {
_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
diff --git a/lld/lib/ReaderWriter/ELF/OutputELFWriter.cpp b/lld/lib/ReaderWriter/ELF/OutputELFWriter.cpp
index 14cd3c4323de..78729393393b 100644
--- a/lld/lib/ReaderWriter/ELF/OutputELFWriter.cpp
+++ b/lld/lib/ReaderWriter/ELF/OutputELFWriter.cpp
@@ -246,6 +246,14 @@ template <class ELFT> void OutputELFWriter<ELFT>::finalizeDefaultAtomValues() {
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 <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() {
@@ -455,23 +463,35 @@ std::error_code OutputELFWriter<ELFT>::writeFile(const File &file,
}
template <class ELFT>
+void OutputELFWriter<ELFT>::processUndefinedSymbol(
+ StringRef symName, RuntimeFile<ELFT> &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 <class ELFT>
void OutputELFWriter<ELFT>::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 <class ELFT>
+void OutputELFWriter<ELFT>::updateScopeAtomValues(StringRef start,
+ StringRef end,
+ StringRef sec) {
AtomLayout *s = _layout.findAbsoluteAtom(start);
AtomLayout *e = _layout.findAbsoluteAtom(end);
- OutputSection<ELFT> *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<ELFT> *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<ELF32LE>;
diff --git a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h
index c7909f5f75da..bb3901010634 100644
--- a/lld/lib/ReaderWriter/ELF/OutputELFWriter.h
+++ b/lld/lib/ReaderWriter/ELF/OutputELFWriter.h
@@ -113,7 +113,7 @@ protected:
/// \brief Process undefined symbols that left after resolution step.
virtual void processUndefinedSymbol(StringRef symName,
- RuntimeFile<ELFT> &file) const {}
+ RuntimeFile<ELFT> &file) const;
/// \brief Assign addresses to atoms marking section's start and end.
void updateScopeAtomValues(StringRef sym, StringRef sec);
@@ -144,6 +144,7 @@ protected:
private:
static StringRef maybeGetSOName(Node *node);
+ void updateScopeAtomValues(StringRef start, StringRef end, StringRef sec);
};
} // namespace elf
diff --git a/lld/test/elf/start-stop-sym.test b/lld/test/elf/start-stop-sym.test
new file mode 100644
index 000000000000..3702eb738032
--- /dev/null
+++ b/lld/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
+...