diff options
Diffstat (limited to 'lld/ELF')
-rw-r--r-- | lld/ELF/Driver.cpp | 13 | ||||
-rw-r--r-- | lld/ELF/InputSection.cpp | 3 | ||||
-rw-r--r-- | lld/ELF/InputSection.h | 4 | ||||
-rw-r--r-- | lld/ELF/OutputSections.cpp | 8 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 27 |
5 files changed, 40 insertions, 15 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 25330832339c..6de9698bb2c8 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1906,8 +1906,17 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) { // We do not want to emit debug sections if --strip-all // or -strip-debug are given. - return config->strip != StripPolicy::None && - (s->name.startswith(".debug") || s->name.startswith(".zdebug")); + if (config->strip == StripPolicy::None) + return false; + + if (isDebugSection(*s)) + return true; + if (auto *isec = dyn_cast<InputSection>(s)) + if (InputSectionBase *rel = isec->getRelocatedSection()) + if (isDebugSection(*rel)) + return true; + + return false; }); // Now that the number of partitions is fixed, save a pointer to the main diff --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp index 147c51ab285e..d34abf641ed3 100644 --- a/lld/ELF/InputSection.cpp +++ b/lld/ELF/InputSection.cpp @@ -441,8 +441,7 @@ void InputSection::copyRelocations(uint8_t *buf, ArrayRef<RelTy> rels) { // See the comment in maybeReportUndefined for PPC64 .toc . auto *d = dyn_cast<Defined>(&sym); if (!d) { - if (!sec->name.startswith(".debug") && - !sec->name.startswith(".zdebug") && sec->name != ".eh_frame" && + if (!isDebugSection(*sec) && sec->name != ".eh_frame" && sec->name != ".gcc_except_table" && sec->name != ".toc") { uint32_t secIdx = cast<Undefined>(sym).discardedSecIdx; Elf_Shdr_Impl<ELFT> sec = diff --git a/lld/ELF/InputSection.h b/lld/ELF/InputSection.h index 3c42af7db7b4..fe2c3c516a96 100644 --- a/lld/ELF/InputSection.h +++ b/lld/ELF/InputSection.h @@ -357,6 +357,10 @@ private: template <class ELFT> void copyShtGroup(uint8_t *buf); }; +inline bool isDebugSection(const InputSectionBase &sec) { + return sec.name.startswith(".debug") || sec.name.startswith(".zdebug"); +} + // The list of all input sections. extern std::vector<InputSectionBase *> inputSections; diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 6142cb0783ce..b609878be319 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -114,8 +114,7 @@ void OutputSection::commitSection(InputSection *isec) { flags = isec->flags; } else { // Otherwise, check if new type or flags are compatible with existing ones. - unsigned mask = SHF_TLS | SHF_LINK_ORDER; - if ((flags & mask) != (isec->flags & mask)) + if ((flags ^ isec->flags) & SHF_TLS) error("incompatible section flags for " + name + "\n>>> " + toString(isec) + ": 0x" + utohexstr(isec->flags) + "\n>>> output section " + name + ": 0x" + utohexstr(flags)); @@ -367,8 +366,9 @@ void OutputSection::finalize() { // all InputSections in the OutputSection have the same dependency. if (auto *ex = dyn_cast<ARMExidxSyntheticSection>(first)) link = ex->getLinkOrderDep()->getParent()->sectionIndex; - else if (auto *d = first->getLinkOrderDep()) - link = d->getParent()->sectionIndex; + else if (first->flags & SHF_LINK_ORDER) + if (auto *d = first->getLinkOrderDep()) + link = d->getParent()->sectionIndex; } if (type == SHT_GROUP) { diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index ac332de2a057..713c54dee509 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1523,17 +1523,30 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() { // but sort must consider them all at once. std::vector<InputSection **> scriptSections; std::vector<InputSection *> sections; + bool started = false, stopped = false; for (BaseCommand *base : sec->sectionCommands) { if (auto *isd = dyn_cast<InputSectionDescription>(base)) { for (InputSection *&isec : isd->sections) { - scriptSections.push_back(&isec); - sections.push_back(isec); - - InputSection *link = isec->getLinkOrderDep(); - if (!link->getParent()) - error(toString(isec) + ": sh_link points to discarded section " + - toString(link)); + if (!(isec->flags & SHF_LINK_ORDER)) { + if (started) + stopped = true; + } else if (stopped) { + error(toString(isec) + ": SHF_LINK_ORDER sections in " + sec->name + + " are not contiguous"); + } else { + started = true; + + scriptSections.push_back(&isec); + sections.push_back(isec); + + InputSection *link = isec->getLinkOrderDep(); + if (!link->getParent()) + error(toString(isec) + ": sh_link points to discarded section " + + toString(link)); + } } + } else if (started) { + stopped = true; } } |