diff options
Diffstat (limited to 'lld/ELF/InputFiles.cpp')
| -rw-r--r-- | lld/ELF/InputFiles.cpp | 70 |
1 files changed, 58 insertions, 12 deletions
diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index fdf935a30856..43978cd66c61 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -13,6 +13,7 @@ #include "SymbolTable.h" #include "Symbols.h" #include "SyntheticSections.h" +#include "lld/Common/DWARF.h" #include "lld/Common/ErrorHandler.h" #include "lld/Common/Memory.h" #include "llvm/ADT/STLExtras.h" @@ -295,7 +296,7 @@ Optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *s, } } - // Use fake address calcuated by adding section file offset and offset in + // Use fake address calculated by adding section file offset and offset in // section. See comments for ObjectInfo class. return dwarf->getDILineInfo(s->getOffsetInFile() + offset, sectionIndex); } @@ -496,6 +497,44 @@ static void addDependentLibrary(StringRef specifier, const InputFile *f) { specifier); } +// Record the membership of a section group so that in the garbage collection +// pass, section group members are kept or discarded as a unit. +template <class ELFT> +static void handleSectionGroup(ArrayRef<InputSectionBase *> sections, + ArrayRef<typename ELFT::Word> entries) { + bool hasAlloc = false; + for (uint32_t index : entries.slice(1)) { + if (index >= sections.size()) + return; + if (InputSectionBase *s = sections[index]) + if (s != &InputSection::discarded && s->flags & SHF_ALLOC) + hasAlloc = true; + } + + // If any member has the SHF_ALLOC flag, the whole group is subject to garbage + // collection. See the comment in markLive(). This rule retains .debug_types + // and .rela.debug_types. + if (!hasAlloc) + return; + + // Connect the members in a circular doubly-linked list via + // nextInSectionGroup. + InputSectionBase *head; + InputSectionBase *prev = nullptr; + for (uint32_t index : entries.slice(1)) { + InputSectionBase *s = sections[index]; + if (!s || s == &InputSection::discarded) + continue; + if (prev) + prev->nextInSectionGroup = s; + else + head = s; + prev = s; + } + if (prev) + prev->nextInSectionGroup = head; +} + template <class ELFT> void ObjFile<ELFT>::initializeSections(bool ignoreComdats) { const ELFFile<ELFT> &obj = this->getObj(); @@ -506,6 +545,8 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) { this->sectionStringTable = CHECK(obj.getSectionStringTable(objSections), this); + std::vector<ArrayRef<Elf_Word>> selectedGroups; + for (size_t i = 0, e = objSections.size(); i < e; ++i) { if (this->sections[i] == &InputSection::discarded) continue; @@ -563,6 +604,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) { if (isNew) { if (config->relocatable) this->sections[i] = createInputSection(sec); + selectedGroups.push_back(entries); continue; } @@ -587,6 +629,7 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) { } } + // This block handles SHF_LINK_ORDER. for (size_t i = 0, e = objSections.size(); i < e; ++i) { if (this->sections[i] == &InputSection::discarded) continue; @@ -609,6 +652,9 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats) { " with SHF_LINK_ORDER should not refer a non-regular section: " + toString(linkSec)); } + + for (ArrayRef<Elf_Word> entries : selectedGroups) + handleSectionGroup<ELFT>(this->sections, entries); } // For ARM only, to set the EF_ARM_ABI_FLOAT_SOFT or EF_ARM_ABI_FLOAT_HARD @@ -741,7 +787,7 @@ static uint32_t readAndFeatures(ObjFile<ELFT> *obj, ArrayRef<uint8_t> data) { if (type == featureAndType) { // We found a FEATURE_1_AND field. There may be more than one of these - // in a .note.gnu.propery section, for a relocatable object we + // in a .note.gnu.property section, for a relocatable object we // accumulate the bits set. featuresSet |= read32le(desc.data() + 8); } @@ -838,6 +884,16 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &sec) { if (!target) return nullptr; + // ELF spec allows mergeable sections with relocations, but they are + // rare, and it is in practice hard to merge such sections by contents, + // because applying relocations at end of linking changes section + // contents. So, we simply handle such sections as non-mergeable ones. + // Degrading like this is acceptable because section merging is optional. + if (auto *ms = dyn_cast<MergeInputSection>(target)) { + target = toRegularSection(ms); + this->sections[sec.sh_info] = target; + } + // This section contains relocation information. // If -r is given, we do not interpret or apply relocation // but just copy relocation sections to output. @@ -856,16 +912,6 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &sec) { fatal(toString(this) + ": multiple relocation sections to one section are not supported"); - // ELF spec allows mergeable sections with relocations, but they are - // rare, and it is in practice hard to merge such sections by contents, - // because applying relocations at end of linking changes section - // contents. So, we simply handle such sections as non-mergeable ones. - // Degrading like this is acceptable because section merging is optional. - if (auto *ms = dyn_cast<MergeInputSection>(target)) { - target = toRegularSection(ms); - this->sections[sec.sh_info] = target; - } - if (sec.sh_type == SHT_RELA) { ArrayRef<Elf_Rela> rels = CHECK(getObj().relas(&sec), this); target->firstRelocation = rels.begin(); |
