summaryrefslogtreecommitdiff
path: root/lld/ELF
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF')
-rw-r--r--lld/ELF/Driver.cpp13
-rw-r--r--lld/ELF/InputSection.cpp3
-rw-r--r--lld/ELF/InputSection.h4
-rw-r--r--lld/ELF/OutputSections.cpp8
-rw-r--r--lld/ELF/Writer.cpp27
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;
}
}