summaryrefslogtreecommitdiff
path: root/contrib/llvm-project/lld/ELF/MarkLive.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/lld/ELF/MarkLive.cpp')
-rw-r--r--contrib/llvm-project/lld/ELF/MarkLive.cpp58
1 files changed, 42 insertions, 16 deletions
diff --git a/contrib/llvm-project/lld/ELF/MarkLive.cpp b/contrib/llvm-project/lld/ELF/MarkLive.cpp
index 36b847f725b8..bb0105c28928 100644
--- a/contrib/llvm-project/lld/ELF/MarkLive.cpp
+++ b/contrib/llvm-project/lld/ELF/MarkLive.cpp
@@ -37,11 +37,11 @@
using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;
-using namespace llvm::support::endian;
-using namespace lld;
-using namespace lld::elf;
+namespace endian = llvm::support::endian;
+namespace lld {
+namespace elf {
namespace {
template <class ELFT> class MarkLive {
public:
@@ -141,7 +141,7 @@ void MarkLive<ELFT>::scanEhFrameSection(EhInputSection &eh,
if (firstRelI == (unsigned)-1)
continue;
- if (read32<ELFT::TargetEndianness>(piece.data().data() + 4) == 0) {
+ if (endian::read32<ELFT::TargetEndianness>(piece.data().data() + 4) == 0) {
// This is a CIE, we only need to worry about the first relocation. It is
// known to point to the personality function.
resolveReloc(eh, rels[firstRelI], false);
@@ -165,9 +165,11 @@ static bool isReserved(InputSectionBase *sec) {
switch (sec->type) {
case SHT_FINI_ARRAY:
case SHT_INIT_ARRAY:
- case SHT_NOTE:
case SHT_PREINIT_ARRAY:
return true;
+ case SHT_NOTE:
+ // SHT_NOTE sections in a group are subject to garbage collection.
+ return !sec->nextInSectionGroup;
default:
StringRef s = sec->name;
return s.startswith(".ctors") || s.startswith(".dtors") ||
@@ -217,10 +219,9 @@ template <class ELFT> void MarkLive<ELFT>::run() {
// Preserve externally-visible symbols if the symbols defined by this
// file can interrupt other ELF file's symbols at runtime.
- symtab->forEachSymbol([&](Symbol *sym) {
+ for (Symbol *sym : symtab->symbols())
if (sym->includeInDynsym() && sym->partition == partition)
markSymbol(sym);
- });
// If this isn't the main partition, that's all that we need to preserve.
if (partition != 1) {
@@ -283,6 +284,10 @@ template <class ELFT> void MarkLive<ELFT>::mark() {
for (InputSectionBase *isec : sec.dependentSections)
enqueue(isec, 0);
+
+ // Mark the next group member.
+ if (sec.nextInSectionGroup)
+ enqueue(sec.nextInSectionGroup, 0);
}
}
@@ -291,6 +296,10 @@ template <class ELFT> void MarkLive<ELFT>::mark() {
// GOT, which means that the ifunc must be available when the main partition is
// loaded) and TLS symbols (because we only know how to correctly process TLS
// relocations for the main partition).
+//
+// We also need to move sections whose names are C identifiers that are referred
+// to from __start_/__stop_ symbols because there will only be one set of
+// symbols for the whole program.
template <class ELFT> void MarkLive<ELFT>::moveToMain() {
for (InputFile *file : objectFiles)
for (Symbol *s : file->getSymbols())
@@ -299,28 +308,35 @@ template <class ELFT> void MarkLive<ELFT>::moveToMain() {
d->section->isLive())
markSymbol(s);
+ for (InputSectionBase *sec : inputSections) {
+ if (!sec->isLive() || !isValidCIdentifier(sec->name))
+ continue;
+ if (symtab->find(("__start_" + sec->name).str()) ||
+ symtab->find(("__stop_" + sec->name).str()))
+ enqueue(sec, 0);
+ }
+
mark();
}
// Before calling this function, Live bits are off for all
// input sections. This function make some or all of them on
// so that they are emitted to the output file.
-template <class ELFT> void elf::markLive() {
+template <class ELFT> void markLive() {
// If -gc-sections is not given, no sections are removed.
if (!config->gcSections) {
for (InputSectionBase *sec : inputSections)
sec->markLive();
// If a DSO defines a symbol referenced in a regular object, it is needed.
- symtab->forEachSymbol([](Symbol *sym) {
+ for (Symbol *sym : symtab->symbols())
if (auto *s = dyn_cast<SharedSymbol>(sym))
if (s->isUsedInRegularObj && !s->isWeak())
s->getFile().isNeeded = true;
- });
return;
}
- // Otheriwse, do mark-sweep GC.
+ // Otherwise, do mark-sweep GC.
//
// The -gc-sections option works only for SHF_ALLOC sections
// (sections that are memory-mapped at runtime). So we can
@@ -341,12 +357,19 @@ template <class ELFT> void elf::markLive() {
// or -emit-reloc were given. And they are subject of garbage
// collection because, if we remove a text section, we also
// remove its relocation section.
+ //
+ // Note on nextInSectionGroup: The ELF spec says that group sections are
+ // included or omitted as a unit. We take the interpretation that:
+ //
+ // - Group members (nextInSectionGroup != nullptr) are subject to garbage
+ // collection.
+ // - Groups members are retained or discarded as a unit.
for (InputSectionBase *sec : inputSections) {
bool isAlloc = (sec->flags & SHF_ALLOC);
bool isLinkOrder = (sec->flags & SHF_LINK_ORDER);
bool isRel = (sec->type == SHT_REL || sec->type == SHT_RELA);
- if (!isAlloc && !isLinkOrder && !isRel)
+ if (!isAlloc && !isLinkOrder && !isRel && !sec->nextInSectionGroup)
sec->markLive();
}
@@ -367,7 +390,10 @@ template <class ELFT> void elf::markLive() {
message("removing unused section " + toString(sec));
}
-template void elf::markLive<ELF32LE>();
-template void elf::markLive<ELF32BE>();
-template void elf::markLive<ELF64LE>();
-template void elf::markLive<ELF64BE>();
+template void markLive<ELF32LE>();
+template void markLive<ELF32BE>();
+template void markLive<ELF64LE>();
+template void markLive<ELF64BE>();
+
+} // namespace elf
+} // namespace lld