summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF
diff options
context:
space:
mode:
authorSimon Atanasyan <simon@atanasyan.com>2015-07-03 11:25:37 +0000
committerSimon Atanasyan <simon@atanasyan.com>2015-07-03 11:25:37 +0000
commita87c17a2019986614fea015288f4cea4b7b173aa (patch)
treef4122facaffec7681d988f7d74988c40b3cd6040 /lld/lib/ReaderWriter/ELF
parentcec93c355a7b2f1a6be436f233b043bd2632d4bd (diff)
downloadbcm5719-llvm-a87c17a2019986614fea015288f4cea4b7b173aa.tar.gz
bcm5719-llvm-a87c17a2019986614fea015288f4cea4b7b173aa.zip
[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/lib/ReaderWriter/ELF')
-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
5 files changed, 50 insertions, 14 deletions
diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h b/lld/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h
index 45e0aff1f18..974dab63a12 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 0e35e458f18..4e1fd818bde 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 5e734b2f88c..361bd509fa8 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 14cd3c4323d..78729393393 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 c7909f5f75d..bb390101063 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
OpenPOWER on IntegriCloud