| 1 | //===- MarkLive.cpp -------------------------------------------------------===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | // |
| 9 | // This file implements --gc-sections, which is a feature to remove unused |
| 10 | // sections from output. Unused sections are sections that are not reachable |
| 11 | // from known GC-root symbols or sections. Naturally the feature is |
| 12 | // implemented as a mark-sweep garbage collector. |
| 13 | // |
| 14 | // Here's how it works. Each InputSectionBase has a "Live" bit. The bit is off |
| 15 | // by default. Starting with GC-root symbols or sections, markLive function |
| 16 | // defined in this file visits all reachable sections to set their Live |
| 17 | // bits. Writer will then ignore sections whose Live bits are off, so that |
| 18 | // such sections are not included into output. |
| 19 | // |
| 20 | //===----------------------------------------------------------------------===// |
| 21 | |
| 22 | #include "MarkLive.h" |
| 23 | #include "InputFiles.h" |
| 24 | #include "InputSection.h" |
| 25 | #include "LinkerScript.h" |
| 26 | #include "SymbolTable.h" |
| 27 | #include "Symbols.h" |
| 28 | #include "SyntheticSections.h" |
| 29 | #include "Target.h" |
| 30 | #include "lld/Common/Strings.h" |
| 31 | #include "llvm/ADT/DenseMapInfoVariant.h" |
| 32 | #include "llvm/ADT/STLExtras.h" |
| 33 | #include "llvm/Support/TimeProfiler.h" |
| 34 | #include <variant> |
| 35 | #include <vector> |
| 36 | |
| 37 | using namespace llvm; |
| 38 | using namespace llvm::ELF; |
| 39 | using namespace llvm::object; |
| 40 | using namespace llvm::support::endian; |
| 41 | using namespace lld; |
| 42 | using namespace lld::elf; |
| 43 | |
| 44 | namespace { |
| 45 | using SecOffset = std::pair<InputSectionBase *, unsigned>; |
| 46 | |
| 47 | // Something that can have an independent reason for being live. |
| 48 | using LiveItem = std::variant<InputSectionBase *, Symbol *, SecOffset>; |
| 49 | |
| 50 | // The most proximate reason that something is live. |
| 51 | struct LiveReason { |
| 52 | std::optional<LiveItem> item; |
| 53 | StringRef desc; |
| 54 | }; |
| 55 | |
| 56 | template <class ELFT, bool TrackWhyLive> class MarkLive { |
| 57 | public: |
| 58 | MarkLive(Ctx &ctx, unsigned partition) : ctx(ctx), partition(partition) {} |
| 59 | |
| 60 | void run(); |
| 61 | void moveToMain(); |
| 62 | void printWhyLive(Symbol *s) const; |
| 63 | |
| 64 | private: |
| 65 | void enqueue(InputSectionBase *sec, uint64_t offset, Symbol *sym, |
| 66 | LiveReason reason); |
| 67 | void markSymbol(Symbol *sym, StringRef reason); |
| 68 | void mark(); |
| 69 | |
| 70 | template <class RelTy> |
| 71 | void resolveReloc(InputSectionBase &sec, RelTy &rel, bool fromFDE); |
| 72 | |
| 73 | template <class RelTy> |
| 74 | void scanEhFrameSection(EhInputSection &eh, ArrayRef<RelTy> rels); |
| 75 | |
| 76 | Ctx &ctx; |
| 77 | // The index of the partition that we are currently processing. |
| 78 | unsigned partition; |
| 79 | |
| 80 | // A list of sections to visit. |
| 81 | SmallVector<InputSection *, 0> queue; |
| 82 | |
| 83 | // There are normally few input sections whose names are valid C |
| 84 | // identifiers, so we just store a SmallVector instead of a multimap. |
| 85 | DenseMap<StringRef, SmallVector<InputSectionBase *, 0>> cNamedSections; |
| 86 | |
| 87 | // The most proximate reason that something is live. This forms a DAG between |
| 88 | // LiveItems. Acyclicality is maintained by only admitting the first |
| 89 | // discovered reason for each LiveItem; this captures the acyclic region of |
| 90 | // the liveness graph around the GC roots. |
| 91 | DenseMap<LiveItem, LiveReason> whyLive; |
| 92 | }; |
| 93 | } // namespace |
| 94 | |
| 95 | template <class ELFT> |
| 96 | static uint64_t getAddend(Ctx &ctx, InputSectionBase &sec, |
| 97 | const typename ELFT::Rel &rel) { |
| 98 | return ctx.target->getImplicitAddend(buf: sec.content().begin() + rel.r_offset, |
| 99 | type: rel.getType(ctx.arg.isMips64EL)); |
| 100 | } |
| 101 | |
| 102 | template <class ELFT> |
| 103 | static uint64_t getAddend(Ctx &, InputSectionBase &sec, |
| 104 | const typename ELFT::Rela &rel) { |
| 105 | return rel.r_addend; |
| 106 | } |
| 107 | |
| 108 | // Currently, we assume all input CREL relocations have an explicit addend. |
| 109 | template <class ELFT> |
| 110 | static uint64_t getAddend(Ctx &, InputSectionBase &sec, |
| 111 | const typename ELFT::Crel &rel) { |
| 112 | return rel.r_addend; |
| 113 | } |
| 114 | |
| 115 | template <class ELFT, bool TrackWhyLive> |
| 116 | template <class RelTy> |
| 117 | void MarkLive<ELFT, TrackWhyLive>::resolveReloc(InputSectionBase &sec, |
| 118 | RelTy &rel, bool fromFDE) { |
| 119 | // If a symbol is referenced in a live section, it is used. |
| 120 | Symbol &sym = sec.file->getRelocTargetSym(rel); |
| 121 | sym.used = true; |
| 122 | |
| 123 | LiveReason reason; |
| 124 | if (TrackWhyLive) |
| 125 | reason = {.item: SecOffset(&sec, rel.r_offset), .desc: "referenced by" }; |
| 126 | |
| 127 | if (auto *d = dyn_cast<Defined>(Val: &sym)) { |
| 128 | auto *relSec = dyn_cast_or_null<InputSectionBase>(Val: d->section); |
| 129 | if (!relSec) |
| 130 | return; |
| 131 | |
| 132 | uint64_t offset = d->value; |
| 133 | if (d->isSection()) |
| 134 | offset += getAddend<ELFT>(ctx, sec, rel); |
| 135 | |
| 136 | // fromFDE being true means this is referenced by a FDE in a .eh_frame |
| 137 | // piece. The relocation points to the described function or to a LSDA. We |
| 138 | // only need to keep the LSDA live, so ignore anything that points to |
| 139 | // executable sections. If the LSDA is in a section group or has the |
| 140 | // SHF_LINK_ORDER flag, we ignore the relocation as well because (a) if the |
| 141 | // associated text section is live, the LSDA will be retained due to section |
| 142 | // group/SHF_LINK_ORDER rules (b) if the associated text section should be |
| 143 | // discarded, marking the LSDA will unnecessarily retain the text section. |
| 144 | if (!(fromFDE && ((relSec->flags & (SHF_EXECINSTR | SHF_LINK_ORDER)) || |
| 145 | relSec->nextInSectionGroup))) { |
| 146 | Symbol *canonicalSym = d; |
| 147 | if (TrackWhyLive && d->isSection()) { |
| 148 | // This is expensive, so ideally this would be deferred until it's known |
| 149 | // whether this reference contributes to a printed whyLive chain, but |
| 150 | // that determination cannot be made without knowing the enclosing |
| 151 | // symbol. |
| 152 | if (Symbol *s = relSec->getEnclosingSymbol(offset)) |
| 153 | canonicalSym = s; |
| 154 | else |
| 155 | canonicalSym = nullptr; |
| 156 | } |
| 157 | enqueue(sec: relSec, offset, sym: canonicalSym, reason); |
| 158 | } |
| 159 | return; |
| 160 | } |
| 161 | |
| 162 | if (auto *ss = dyn_cast<SharedSymbol>(Val: &sym)) { |
| 163 | if (!ss->isWeak()) { |
| 164 | cast<SharedFile>(Val: ss->file)->isNeeded = true; |
| 165 | if (TrackWhyLive) |
| 166 | whyLive.try_emplace(Key: &sym, Args&: reason); |
| 167 | } |
| 168 | } |
| 169 | |
| 170 | for (InputSectionBase *sec : cNamedSections.lookup(Val: sym.getName())) |
| 171 | enqueue(sec, /*offset=*/0, /*sym=*/nullptr, reason); |
| 172 | } |
| 173 | |
| 174 | // The .eh_frame section is an unfortunate special case. |
| 175 | // The section is divided in CIEs and FDEs and the relocations it can have are |
| 176 | // * CIEs can refer to a personality function. |
| 177 | // * FDEs can refer to a LSDA |
| 178 | // * FDEs refer to the function they contain information about |
| 179 | // The last kind of relocation cannot keep the referred section alive, or they |
| 180 | // would keep everything alive in a common object file. In fact, each FDE is |
| 181 | // alive if the section it refers to is alive. |
| 182 | // To keep things simple, in here we just ignore the last relocation kind. The |
| 183 | // other two keep the referred section alive. |
| 184 | // |
| 185 | // A possible improvement would be to fully process .eh_frame in the middle of |
| 186 | // the gc pass. With that we would be able to also gc some sections holding |
| 187 | // LSDAs and personality functions if we found that they were unused. |
| 188 | template <class ELFT, bool TrackWhyLive> |
| 189 | template <class RelTy> |
| 190 | void MarkLive<ELFT, TrackWhyLive>::scanEhFrameSection(EhInputSection &eh, |
| 191 | ArrayRef<RelTy> rels) { |
| 192 | for (const EhSectionPiece &cie : eh.cies) |
| 193 | if (cie.firstRelocation != unsigned(-1)) |
| 194 | resolveReloc(eh, rels[cie.firstRelocation], false); |
| 195 | for (const EhSectionPiece &fde : eh.fdes) { |
| 196 | size_t firstRelI = fde.firstRelocation; |
| 197 | if (firstRelI == (unsigned)-1) |
| 198 | continue; |
| 199 | uint64_t pieceEnd = fde.inputOff + fde.size; |
| 200 | for (size_t j = firstRelI, end2 = rels.size(); |
| 201 | j < end2 && rels[j].r_offset < pieceEnd; ++j) |
| 202 | resolveReloc(eh, rels[j], true); |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | // Some sections are used directly by the loader, so they should never be |
| 207 | // garbage-collected. This function returns true if a given section is such |
| 208 | // section. |
| 209 | static bool isReserved(InputSectionBase *sec) { |
| 210 | switch (sec->type) { |
| 211 | case SHT_FINI_ARRAY: |
| 212 | case SHT_INIT_ARRAY: |
| 213 | case SHT_PREINIT_ARRAY: |
| 214 | return true; |
| 215 | case SHT_NOTE: |
| 216 | // SHT_NOTE sections in a group are subject to garbage collection. |
| 217 | return !sec->nextInSectionGroup; |
| 218 | default: |
| 219 | // Support SHT_PROGBITS .init_array (https://golang.org/issue/50295) and |
| 220 | // .init_array.N (https://github.com/rust-lang/rust/issues/92181) for a |
| 221 | // while. |
| 222 | StringRef s = sec->name; |
| 223 | return s == ".init" || s == ".fini" || s.starts_with(Prefix: ".init_array" ) || |
| 224 | s == ".jcr" || s.starts_with(Prefix: ".ctors" ) || s.starts_with(Prefix: ".dtors" ); |
| 225 | } |
| 226 | } |
| 227 | |
| 228 | template <class ELFT, bool TrackWhyLive> |
| 229 | void MarkLive<ELFT, TrackWhyLive>::enqueue(InputSectionBase *sec, |
| 230 | uint64_t offset, Symbol *sym, |
| 231 | LiveReason reason) { |
| 232 | // Usually, a whole section is marked as live or dead, but in mergeable |
| 233 | // (splittable) sections, each piece of data has independent liveness bit. |
| 234 | // So we explicitly tell it which offset is in use. |
| 235 | if (auto *ms = dyn_cast<MergeInputSection>(Val: sec)) |
| 236 | ms->getSectionPiece(offset).live = true; |
| 237 | |
| 238 | // Set Sec->Partition to the meet (i.e. the "minimum") of Partition and |
| 239 | // Sec->Partition in the following lattice: 1 < other < 0. If Sec->Partition |
| 240 | // doesn't change, we don't need to do anything. |
| 241 | if (sec->partition == 1 || sec->partition == partition) |
| 242 | return; |
| 243 | sec->partition = sec->partition ? 1 : partition; |
| 244 | |
| 245 | if (TrackWhyLive) { |
| 246 | if (sym) { |
| 247 | // If a specific symbol is referenced, that keeps it live. The symbol then |
| 248 | // keeps its section live. |
| 249 | whyLive.try_emplace(Key: sym, Args&: reason); |
| 250 | whyLive.try_emplace(Key: sec, Args: LiveReason{.item: sym, .desc: "contained live symbol" }); |
| 251 | } else { |
| 252 | // Otherwise, the reference generically keeps the section live. |
| 253 | whyLive.try_emplace(Key: sec, Args&: reason); |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | // Add input section to the queue. |
| 258 | if (InputSection *s = dyn_cast<InputSection>(Val: sec)) |
| 259 | queue.push_back(Elt: s); |
| 260 | } |
| 261 | |
| 262 | // Print the stack of reasons that the given symbol is live. |
| 263 | template <class ELFT, bool TrackWhyLive> |
| 264 | void MarkLive<ELFT, TrackWhyLive>::printWhyLive(Symbol *s) const { |
| 265 | // Skip dead symbols. A symbol is dead if it belongs to a dead section. |
| 266 | if (auto *d = dyn_cast<Defined>(Val: s)) { |
| 267 | auto *sec = dyn_cast_or_null<InputSectionBase>(Val: d->section); |
| 268 | if (sec && !sec->isLive()) |
| 269 | return; |
| 270 | } |
| 271 | |
| 272 | auto msg = Msg(ctx); |
| 273 | |
| 274 | const auto printSymbol = [&](Symbol *s) { |
| 275 | msg << s->file << ":(" << s << ')'; |
| 276 | }; |
| 277 | |
| 278 | msg << "live symbol: " ; |
| 279 | printSymbol(s); |
| 280 | |
| 281 | LiveItem cur = s; |
| 282 | while (true) { |
| 283 | auto it = whyLive.find(Val: cur); |
| 284 | LiveReason reason; |
| 285 | // If there is a specific reason this item is live... |
| 286 | if (it != whyLive.end()) { |
| 287 | reason = it->second; |
| 288 | } else { |
| 289 | // This item is live, but it has no tracked reason. It must be an |
| 290 | // unreferenced symbol in a live section or a symbol with no section. |
| 291 | InputSectionBase *sec = nullptr; |
| 292 | if (auto *d = dyn_cast<Defined>(Val: std::get<Symbol *>(v&: cur))) |
| 293 | sec = dyn_cast_or_null<InputSectionBase>(Val: d->section); |
| 294 | reason = sec ? LiveReason{.item: sec, .desc: "in live section" } |
| 295 | : LiveReason{.item: std::nullopt, .desc: "no section" }; |
| 296 | } |
| 297 | |
| 298 | if (!reason.item) { |
| 299 | msg << " (" << reason.desc << ')'; |
| 300 | break; |
| 301 | } |
| 302 | |
| 303 | msg << "\n>>> " << reason.desc << ": " ; |
| 304 | // The reason may not yet have been resolved to a symbol; do so now. |
| 305 | if (std::holds_alternative<SecOffset>(v: *reason.item)) { |
| 306 | const auto &so = std::get<SecOffset>(v&: *reason.item); |
| 307 | InputSectionBase *sec = so.first; |
| 308 | Defined *sym = sec->getEnclosingSymbol(offset: so.second); |
| 309 | cur = sym ? LiveItem(sym) : LiveItem(sec); |
| 310 | } else { |
| 311 | cur = *reason.item; |
| 312 | } |
| 313 | |
| 314 | if (std::holds_alternative<Symbol *>(v: cur)) |
| 315 | printSymbol(std::get<Symbol *>(v&: cur)); |
| 316 | else |
| 317 | msg << std::get<InputSectionBase *>(v&: cur); |
| 318 | } |
| 319 | } |
| 320 | |
| 321 | template <class ELFT, bool TrackWhyLive> |
| 322 | void MarkLive<ELFT, TrackWhyLive>::markSymbol(Symbol *sym, StringRef reason) { |
| 323 | if (auto *d = dyn_cast_or_null<Defined>(Val: sym)) |
| 324 | if (auto *isec = dyn_cast_or_null<InputSectionBase>(Val: d->section)) |
| 325 | enqueue(sec: isec, offset: d->value, sym, reason: {std::nullopt, reason}); |
| 326 | } |
| 327 | |
| 328 | // This is the main function of the garbage collector. |
| 329 | // Starting from GC-root sections, this function visits all reachable |
| 330 | // sections to set their "Live" bits. |
| 331 | template <class ELFT, bool TrackWhyLive> |
| 332 | void MarkLive<ELFT, TrackWhyLive>::run() { |
| 333 | // Add GC root symbols. |
| 334 | |
| 335 | // Preserve externally-visible symbols if the symbols defined by this |
| 336 | // file can interpose other ELF file's symbols at runtime. |
| 337 | for (Symbol *sym : ctx.symtab->getSymbols()) |
| 338 | if (sym->isExported && sym->partition == partition) |
| 339 | markSymbol(sym, reason: "externally visible symbol; may interpose" ); |
| 340 | |
| 341 | // If this isn't the main partition, that's all that we need to preserve. |
| 342 | if (partition != 1) { |
| 343 | mark(); |
| 344 | return; |
| 345 | } |
| 346 | |
| 347 | markSymbol(sym: ctx.symtab->find(name: ctx.arg.entry), reason: "entry point" ); |
| 348 | markSymbol(sym: ctx.symtab->find(name: ctx.arg.init), reason: "initializer function" ); |
| 349 | markSymbol(sym: ctx.symtab->find(name: ctx.arg.fini), reason: "finalizer function" ); |
| 350 | for (StringRef s : ctx.arg.undefined) |
| 351 | markSymbol(sym: ctx.symtab->find(name: s), reason: "undefined command line flag" ); |
| 352 | for (StringRef s : ctx.script->referencedSymbols) |
| 353 | markSymbol(sym: ctx.symtab->find(name: s), reason: "referenced by linker script" ); |
| 354 | for (auto [symName, _] : ctx.symtab->cmseSymMap) { |
| 355 | markSymbol(sym: ctx.symtab->cmseSymMap[symName].sym, reason: "ARM CMSE symbol" ); |
| 356 | markSymbol(sym: ctx.symtab->cmseSymMap[symName].acleSeSym, reason: "ARM CMSE symbol" ); |
| 357 | } |
| 358 | |
| 359 | // Mark .eh_frame sections as live because there are usually no relocations |
| 360 | // that point to .eh_frames. Otherwise, the garbage collector would drop |
| 361 | // all of them. We also want to preserve personality routines and LSDA |
| 362 | // referenced by .eh_frame sections, so we scan them for that here. |
| 363 | for (EhInputSection *eh : ctx.ehInputSections) { |
| 364 | const RelsOrRelas<ELFT> rels = |
| 365 | eh->template relsOrRelas<ELFT>(/*supportsCrel=*/false); |
| 366 | if (rels.areRelocsRel()) |
| 367 | scanEhFrameSection(*eh, rels.rels); |
| 368 | else if (rels.relas.size()) |
| 369 | scanEhFrameSection(*eh, rels.relas); |
| 370 | } |
| 371 | for (InputSectionBase *sec : ctx.inputSections) { |
| 372 | if (sec->flags & SHF_GNU_RETAIN) { |
| 373 | enqueue(sec, /*offset=*/0, /*sym=*/nullptr, reason: {std::nullopt, "retained" }); |
| 374 | continue; |
| 375 | } |
| 376 | if (sec->flags & SHF_LINK_ORDER) |
| 377 | continue; |
| 378 | |
| 379 | // Usually, non-SHF_ALLOC sections are not removed even if they are |
| 380 | // unreachable through relocations because reachability is not a good signal |
| 381 | // whether they are garbage or not (e.g. there is usually no section |
| 382 | // referring to a .comment section, but we want to keep it.) When a |
| 383 | // non-SHF_ALLOC section is retained, we also retain sections dependent on |
| 384 | // it. |
| 385 | // |
| 386 | // Note on SHF_LINK_ORDER: Such sections contain metadata and they |
| 387 | // have a reverse dependency on the InputSection they are linked with. |
| 388 | // We are able to garbage collect them. |
| 389 | // |
| 390 | // Note on SHF_REL{,A}: Such sections reach here only when -r |
| 391 | // or --emit-reloc were given. And they are subject of garbage |
| 392 | // collection because, if we remove a text section, we also |
| 393 | // remove its relocation section. |
| 394 | // |
| 395 | // Note on nextInSectionGroup: The ELF spec says that group sections are |
| 396 | // included or omitted as a unit. We take the interpretation that: |
| 397 | // |
| 398 | // - Group members (nextInSectionGroup != nullptr) are subject to garbage |
| 399 | // collection. |
| 400 | // - Groups members are retained or discarded as a unit. |
| 401 | if (!(sec->flags & SHF_ALLOC)) { |
| 402 | if (!isStaticRelSecType(type: sec->type) && !sec->nextInSectionGroup) { |
| 403 | sec->markLive(); |
| 404 | for (InputSection *isec : sec->dependentSections) |
| 405 | isec->markLive(); |
| 406 | } |
| 407 | } |
| 408 | |
| 409 | // Preserve special sections and those which are specified in linker |
| 410 | // script KEEP command. |
| 411 | if (isReserved(sec)) { |
| 412 | enqueue(sec, /*offset=*/0, /*sym=*/nullptr, reason: {std::nullopt, "reserved" }); |
| 413 | } else if (ctx.script->shouldKeep(s: sec)) { |
| 414 | enqueue(sec, /*offset=*/0, /*sym=*/nullptr, |
| 415 | reason: {std::nullopt, "KEEP in linker script" }); |
| 416 | } else if ((!ctx.arg.zStartStopGC || sec->name.starts_with(Prefix: "__libc_" )) && |
| 417 | isValidCIdentifier(s: sec->name)) { |
| 418 | // As a workaround for glibc libc.a before 2.34 |
| 419 | // (https://sourceware.org/PR27492), retain __libc_atexit and similar |
| 420 | // sections regardless of zStartStopGC. |
| 421 | cNamedSections[ctx.saver.save(S: "__start_" + sec->name)].push_back(Elt: sec); |
| 422 | cNamedSections[ctx.saver.save(S: "__stop_" + sec->name)].push_back(Elt: sec); |
| 423 | } |
| 424 | } |
| 425 | |
| 426 | mark(); |
| 427 | |
| 428 | if (TrackWhyLive) { |
| 429 | const auto handleSym = [&](Symbol *sym) { |
| 430 | if (llvm::any_of(ctx.arg.whyLive, [sym](const llvm::GlobPattern &pat) { |
| 431 | return pat.match(S: sym->getName()); |
| 432 | })) |
| 433 | printWhyLive(s: sym); |
| 434 | }; |
| 435 | |
| 436 | for (Symbol *sym : ctx.symtab->getSymbols()) |
| 437 | handleSym(sym); |
| 438 | for (ELFFileBase *file : ctx.objectFiles) |
| 439 | for (Symbol *sym : file->getSymbols()) |
| 440 | if (sym->isLocal()) |
| 441 | handleSym(sym); |
| 442 | } |
| 443 | } |
| 444 | |
| 445 | template <class ELFT, bool TrackWhyLive> |
| 446 | void MarkLive<ELFT, TrackWhyLive>::mark() { |
| 447 | // Mark all reachable sections. |
| 448 | while (!queue.empty()) { |
| 449 | InputSectionBase &sec = *queue.pop_back_val(); |
| 450 | |
| 451 | const RelsOrRelas<ELFT> rels = sec.template relsOrRelas<ELFT>(); |
| 452 | for (const typename ELFT::Rel &rel : rels.rels) |
| 453 | resolveReloc(sec, rel, false); |
| 454 | for (const typename ELFT::Rela &rel : rels.relas) |
| 455 | resolveReloc(sec, rel, false); |
| 456 | for (const typename ELFT::Crel &rel : rels.crels) |
| 457 | resolveReloc(sec, rel, false); |
| 458 | |
| 459 | for (InputSectionBase *isec : sec.dependentSections) |
| 460 | enqueue(sec: isec, /*offset=*/0, /*sym=*/nullptr, |
| 461 | reason: {&sec, "depended on by section" }); |
| 462 | |
| 463 | // Mark the next group member. |
| 464 | if (sec.nextInSectionGroup) |
| 465 | enqueue(sec: sec.nextInSectionGroup, /*offset=*/0, /*sym=*/nullptr, |
| 466 | reason: {&sec, "in section group with" }); |
| 467 | } |
| 468 | } |
| 469 | |
| 470 | // Move the sections for some symbols to the main partition, specifically ifuncs |
| 471 | // (because they can result in an IRELATIVE being added to the main partition's |
| 472 | // GOT, which means that the ifunc must be available when the main partition is |
| 473 | // loaded) and TLS symbols (because we only know how to correctly process TLS |
| 474 | // relocations for the main partition). |
| 475 | // |
| 476 | // We also need to move sections whose names are C identifiers that are referred |
| 477 | // to from __start_/__stop_ symbols because there will only be one set of |
| 478 | // symbols for the whole program. |
| 479 | template <class ELFT, bool TrackWhyLive> |
| 480 | void MarkLive<ELFT, TrackWhyLive>::moveToMain() { |
| 481 | for (ELFFileBase *file : ctx.objectFiles) |
| 482 | for (Symbol *s : file->getSymbols()) |
| 483 | if (auto *d = dyn_cast<Defined>(Val: s)) |
| 484 | if ((d->type == STT_GNU_IFUNC || d->type == STT_TLS) && d->section && |
| 485 | d->section->isLive()) |
| 486 | markSymbol(sym: s, /*reason=*/{}); |
| 487 | |
| 488 | for (InputSectionBase *sec : ctx.inputSections) { |
| 489 | if (!sec->isLive() || !isValidCIdentifier(s: sec->name)) |
| 490 | continue; |
| 491 | if (ctx.symtab->find(name: ("__start_" + sec->name).str()) || |
| 492 | ctx.symtab->find(name: ("__stop_" + sec->name).str())) |
| 493 | enqueue(sec, /*offset=*/0, /*sym=*/nullptr, /*reason=*/{}); |
| 494 | } |
| 495 | |
| 496 | mark(); |
| 497 | } |
| 498 | |
| 499 | // Before calling this function, Live bits are off for all |
| 500 | // input sections. This function make some or all of them on |
| 501 | // so that they are emitted to the output file. |
| 502 | template <class ELFT> void elf::markLive(Ctx &ctx) { |
| 503 | llvm::TimeTraceScope timeScope("markLive" ); |
| 504 | // If --gc-sections is not given, retain all input sections. |
| 505 | if (!ctx.arg.gcSections) { |
| 506 | // If a DSO defines a symbol referenced in a regular object, it is needed. |
| 507 | for (Symbol *sym : ctx.symtab->getSymbols()) |
| 508 | if (auto *s = dyn_cast<SharedSymbol>(Val: sym)) |
| 509 | if (s->isUsedInRegularObj && !s->isWeak()) |
| 510 | cast<SharedFile>(Val: s->file)->isNeeded = true; |
| 511 | return; |
| 512 | } |
| 513 | |
| 514 | for (InputSectionBase *sec : ctx.inputSections) |
| 515 | sec->markDead(); |
| 516 | |
| 517 | // Follow the graph to mark all live sections. |
| 518 | for (unsigned i = 1, e = ctx.partitions.size(); i <= e; ++i) |
| 519 | if (ctx.arg.whyLive.empty()) |
| 520 | MarkLive<ELFT, false>(ctx, i).run(); |
| 521 | else |
| 522 | MarkLive<ELFT, true>(ctx, i).run(); |
| 523 | |
| 524 | // If we have multiple partitions, some sections need to live in the main |
| 525 | // partition even if they were allocated to a loadable partition. Move them |
| 526 | // there now. |
| 527 | if (ctx.partitions.size() != 1) |
| 528 | MarkLive<ELFT, false>(ctx, 1).moveToMain(); |
| 529 | |
| 530 | // Report garbage-collected sections. |
| 531 | if (ctx.arg.printGcSections) |
| 532 | for (InputSectionBase *sec : ctx.inputSections) |
| 533 | if (!sec->isLive()) |
| 534 | Msg(ctx) << "removing unused section " << sec; |
| 535 | } |
| 536 | |
| 537 | template void elf::markLive<ELF32LE>(Ctx &); |
| 538 | template void elf::markLive<ELF32BE>(Ctx &); |
| 539 | template void elf::markLive<ELF64LE>(Ctx &); |
| 540 | template void elf::markLive<ELF64BE>(Ctx &); |
| 541 | |