summaryrefslogtreecommitdiff
path: root/lld/ELF/MarkLive.cpp
diff options
context:
space:
mode:
authorRafael Espindola <rafael.espindola@gmail.com>2017-03-02 01:50:34 +0000
committerRafael Espindola <rafael.espindola@gmail.com>2017-03-02 01:50:34 +0000
commitf32828a9870f0e6e346c79ea2277e4cef6fa1372 (patch)
tree5909350c30a3dbf02f721f9e89971008015e0d32 /lld/ELF/MarkLive.cpp
parent4a32770b93b9b0a0002ebfc794c96b649696715f (diff)
Make gc a bit more aggressive.
We were not gcing any section whose name was a C identifier. Both gold and bfd only keep those if they are used. To avoid having to create the __start/__stop symbols early or doing string lookups in resolvedReloc, this patch just looks for undefined symbols __start/__stop to decide if a section is needed or not.
Diffstat (limited to 'lld/ELF/MarkLive.cpp')
-rw-r--r--lld/ELF/MarkLive.cpp23
1 files changed, 15 insertions, 8 deletions
diff --git a/lld/ELF/MarkLive.cpp b/lld/ELF/MarkLive.cpp
index 8f75de6dc30..9528708b584 100644
--- a/lld/ELF/MarkLive.cpp
+++ b/lld/ELF/MarkLive.cpp
@@ -170,12 +170,7 @@ template <class ELFT> static bool isReserved(InputSectionBase *Sec) {
if (!(Sec->Flags & SHF_ALLOC))
return true;
- // We do not want to reclaim sections if they can be referred
- // by __start_* and __stop_* symbols.
StringRef S = Sec->Name;
- if (isValidCIdentifier(S))
- return true;
-
return S.startswith(".ctors") || S.startswith(".dtors") ||
S.startswith(".init") || S.startswith(".fini") ||
S.startswith(".jcr");
@@ -226,11 +221,22 @@ template <class ELFT> void elf::markLive() {
for (StringRef S : Config->Undefined)
MarkSymbol(Symtab<ELFT>::X->find(S));
+ // Remember which __start_* or __stop_* symbols are used so that we don't gc
+ // those sections.
+ DenseSet<StringRef> UsedStartStopNames;
+
// Preserve externally-visible symbols if the symbols defined by this
// file can interrupt other ELF file's symbols at runtime.
- for (const Symbol *S : Symtab<ELFT>::X->getSymbols())
- if (S->includeInDynsym())
+ for (const Symbol *S : Symtab<ELFT>::X->getSymbols()) {
+ if (auto *U = dyn_cast_or_null<Undefined>(S->body())) {
+ StringRef Name = U->getName();
+ for (StringRef Prefix : {"__start_", "__stop_"})
+ if (Name.startswith(Prefix))
+ UsedStartStopNames.insert(Name.substr(Prefix.size()));
+ } else if (S->includeInDynsym()) {
MarkSymbol(S->body());
+ }
+ }
// Preserve special sections and those which are specified in linker
// script KEEP command.
@@ -240,7 +246,8 @@ template <class ELFT> void elf::markLive() {
// referred by .eh_frame here.
if (auto *EH = dyn_cast_or_null<EhInputSection<ELFT>>(Sec))
scanEhFrameSection<ELFT>(*EH, Enqueue);
- if (isReserved<ELFT>(Sec) || Script<ELFT>::X->shouldKeep(Sec))
+ if (isReserved<ELFT>(Sec) || Script<ELFT>::X->shouldKeep(Sec) ||
+ UsedStartStopNames.count(Sec->Name))
Enqueue({Sec, 0});
}