| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 1 | //===- MarkLive.cpp -------------------------------------------------------===// |
| 2 | // |
| 3 | // The LLVM Linker |
| 4 | // |
| 5 | // This file is distributed under the University of Illinois Open Source |
| 6 | // License. See LICENSE.TXT for details. |
| 7 | // |
| 8 | //===----------------------------------------------------------------------===// |
| 9 | // |
| 10 | // This file implements --gc-sections, which is a feature to remove unused |
| 11 | // sections from output. Unused sections are sections that are not reachable |
| 12 | // from known GC-root symbols or sections. Naturally the feature is |
| 13 | // implemented as a mark-sweep garbage collector. |
| 14 | // |
| 15 | // Here's how it works. Each InputSectionBase has a "Live" bit. The bit is off |
| 16 | // by default. Starting with GC-root symbols or sections, markLive function |
| 17 | // defined in this file visits all reachable sections to set their Live |
| 18 | // bits. Writer will then ignore sections whose Live bits are off, so that |
| Rui Ueyama | f53b1b7 | 2016-01-05 16:35:46 +0000 | [diff] [blame] | 19 | // such sections are not included into output. |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 20 | // |
| 21 | //===----------------------------------------------------------------------===// |
| 22 | |
| 23 | #include "InputSection.h" |
| George Rimar | 481c2ce | 2016-02-23 07:47:54 +0000 | [diff] [blame] | 24 | #include "LinkerScript.h" |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 25 | #include "OutputSections.h" |
| 26 | #include "SymbolTable.h" |
| 27 | #include "Symbols.h" |
| Peter Collingbourne | 676c7cd | 2016-04-26 23:52:44 +0000 | [diff] [blame] | 28 | #include "Target.h" |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 29 | #include "Writer.h" |
| 30 | #include "llvm/ADT/STLExtras.h" |
| 31 | #include "llvm/Object/ELF.h" |
| 32 | #include <functional> |
| 33 | #include <vector> |
| 34 | |
| 35 | using namespace llvm; |
| 36 | using namespace llvm::ELF; |
| 37 | using namespace llvm::object; |
| 38 | |
| 39 | using namespace lld; |
| Rafael Espindola | e0df00b | 2016-02-28 00:25:54 +0000 | [diff] [blame] | 40 | using namespace lld::elf; |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 41 | |
| Peter Collingbourne | 676c7cd | 2016-04-26 23:52:44 +0000 | [diff] [blame] | 42 | // A resolved relocation. The Sec and Offset fields are set if the relocation |
| 43 | // was resolved to an offset within a section. |
| 44 | template <class ELFT> |
| 45 | struct ResolvedReloc { |
| 46 | InputSectionBase<ELFT> *Sec; |
| 47 | typename ELFT::uint Offset; |
| 48 | }; |
| 49 | |
| 50 | template <class ELFT> |
| 51 | static typename ELFT::uint getAddend(InputSectionBase<ELFT> *Sec, |
| 52 | const typename ELFT::Rel &Rel) { |
| 53 | return Target->getImplicitAddend(Sec->getSectionData().begin(), |
| 54 | Rel.getType(Config->Mips64EL)); |
| 55 | } |
| 56 | |
| 57 | template <class ELFT> |
| 58 | static typename ELFT::uint getAddend(InputSectionBase<ELFT> *Sec, |
| 59 | const typename ELFT::Rela &Rel) { |
| 60 | return Rel.r_addend; |
| 61 | } |
| 62 | |
| 63 | template <class ELFT, class RelT> |
| George Rimar | af90d54 | 2016-05-02 13:49:42 +0000 | [diff] [blame] | 64 | static ResolvedReloc<ELFT> resolveReloc(InputSectionBase<ELFT> *Sec, |
| 65 | RelT &Rel) { |
| Peter Collingbourne | 676c7cd | 2016-04-26 23:52:44 +0000 | [diff] [blame] | 66 | SymbolBody &B = Sec->getFile()->getRelocTargetSym(Rel); |
| 67 | auto *D = dyn_cast<DefinedRegular<ELFT>>(&B); |
| 68 | if (!D || !D->Section) |
| 69 | return {nullptr, 0}; |
| 70 | typename ELFT::uint Offset = D->Value; |
| 71 | if (D->isSection()) |
| 72 | Offset += getAddend(Sec, Rel); |
| 73 | return {D->Section->Repl, Offset}; |
| 74 | } |
| 75 | |
| George Rimar | af90d54 | 2016-05-02 13:49:42 +0000 | [diff] [blame] | 76 | template <class ELFT, class Elf_Shdr> |
| 77 | static void run(ELFFile<ELFT> &Obj, InputSectionBase<ELFT> *Sec, |
| 78 | Elf_Shdr *RelSec, std::function<void(ResolvedReloc<ELFT>)> Fn) { |
| 79 | if (RelSec->sh_type == SHT_RELA) { |
| 80 | for (const typename ELFT::Rela &RI : Obj.relas(RelSec)) |
| 81 | Fn(resolveReloc(Sec, RI)); |
| 82 | } else { |
| 83 | for (const typename ELFT::Rel &RI : Obj.rels(RelSec)) |
| 84 | Fn(resolveReloc(Sec, RI)); |
| 85 | } |
| 86 | } |
| 87 | |
| Rui Ueyama | f53b1b7 | 2016-01-05 16:35:46 +0000 | [diff] [blame] | 88 | // Calls Fn for each section that Sec refers to via relocations. |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 89 | template <class ELFT> |
| Peter Collingbourne | 676c7cd | 2016-04-26 23:52:44 +0000 | [diff] [blame] | 90 | static void forEachSuccessor(InputSection<ELFT> *Sec, |
| 91 | std::function<void(ResolvedReloc<ELFT>)> Fn) { |
| Rafael Espindola | 197d6a8 | 2016-04-22 16:39:59 +0000 | [diff] [blame] | 92 | ELFFile<ELFT> &Obj = Sec->getFile()->getObj(); |
| George Rimar | af90d54 | 2016-05-02 13:49:42 +0000 | [diff] [blame] | 93 | for (const typename ELFT::Shdr *RelSec : Sec->RelocSections) |
| 94 | run(Obj, Sec, RelSec, Fn); |
| 95 | } |
| 96 | |
| Rafael Espindola | d89fbca | 2016-05-05 13:51:14 +0000 | [diff] [blame] | 97 | template <class ELFT> |
| 98 | static void scanEhFrameSection(EHInputSection<ELFT> &EH, |
| 99 | std::function<void(ResolvedReloc<ELFT>)> Fn) { |
| George Rimar | af90d54 | 2016-05-02 13:49:42 +0000 | [diff] [blame] | 100 | if (!EH.RelocSection) |
| 101 | return; |
| 102 | ELFFile<ELFT> &EObj = EH.getFile()->getObj(); |
| 103 | run<ELFT>(EObj, &EH, EH.RelocSection, [&](ResolvedReloc<ELFT> R) { |
| 104 | if (!R.Sec || R.Sec == &InputSection<ELFT>::Discarded) |
| 105 | return; |
| 106 | if (R.Sec->getSectionHdr()->sh_flags & SHF_EXECINSTR) |
| 107 | return; |
| Rafael Espindola | d89fbca | 2016-05-05 13:51:14 +0000 | [diff] [blame] | 108 | Fn({R.Sec, 0}); |
| George Rimar | af90d54 | 2016-05-02 13:49:42 +0000 | [diff] [blame] | 109 | }); |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 110 | } |
| 111 | |
| 112 | // Sections listed below are special because they are used by the loader |
| 113 | // just by being in an ELF file. They should not be garbage-collected. |
| 114 | template <class ELFT> static bool isReserved(InputSectionBase<ELFT> *Sec) { |
| 115 | switch (Sec->getSectionHdr()->sh_type) { |
| 116 | case SHT_FINI_ARRAY: |
| 117 | case SHT_INIT_ARRAY: |
| 118 | case SHT_NOTE: |
| 119 | case SHT_PREINIT_ARRAY: |
| 120 | return true; |
| 121 | default: |
| 122 | StringRef S = Sec->getSectionName(); |
| George Rimar | 12737b7 | 2016-02-25 08:40:26 +0000 | [diff] [blame] | 123 | |
| 124 | // We do not want to reclaim sections if they can be referred |
| 125 | // by __start_* and __stop_* symbols. |
| 126 | if (isValidCIdentifier(S)) |
| 127 | return true; |
| 128 | |
| Davide Italiano | bcbfedc | 2015-12-24 09:52:11 +0000 | [diff] [blame] | 129 | return S.startswith(".ctors") || S.startswith(".dtors") || |
| 130 | S.startswith(".init") || S.startswith(".fini") || |
| Rafael Espindola | 8ea46e0 | 2015-11-09 17:44:10 +0000 | [diff] [blame] | 131 | S.startswith(".jcr"); |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 132 | } |
| 133 | } |
| 134 | |
| Rui Ueyama | 7924fb8 | 2015-12-24 09:50:22 +0000 | [diff] [blame] | 135 | // This is the main function of the garbage collector. |
| 136 | // Starting from GC-root sections, this function visits all reachable |
| 137 | // sections to set their "Live" bits. |
| Rui Ueyama | 4f8d21f | 2016-05-02 19:30:42 +0000 | [diff] [blame] | 138 | template <class ELFT> void elf::markLive() { |
| Rafael Espindola | 0b9531c | 2016-04-22 22:09:35 +0000 | [diff] [blame] | 139 | typedef typename ELFT::uint uintX_t; |
| Rui Ueyama | 92ce0e9 | 2015-11-12 19:42:43 +0000 | [diff] [blame] | 140 | SmallVector<InputSection<ELFT> *, 256> Q; |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 141 | |
| Peter Collingbourne | 676c7cd | 2016-04-26 23:52:44 +0000 | [diff] [blame] | 142 | auto Enqueue = [&](ResolvedReloc<ELFT> R) { |
| 143 | if (!R.Sec) |
| Rafael Espindola | 0b9531c | 2016-04-22 22:09:35 +0000 | [diff] [blame] | 144 | return; |
| Peter Collingbourne | 676c7cd | 2016-04-26 23:52:44 +0000 | [diff] [blame] | 145 | if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(R.Sec)) { |
| Rui Ueyama | 3ea8727 | 2016-05-22 00:13:04 +0000 | [diff] [blame] | 146 | std::pair<SectionPiece *, uintX_t> T = MS->getRangeAndSize(R.Offset); |
| 147 | T.first->Live = true; |
| Rafael Espindola | 0b9531c | 2016-04-22 22:09:35 +0000 | [diff] [blame] | 148 | } |
| Peter Collingbourne | 676c7cd | 2016-04-26 23:52:44 +0000 | [diff] [blame] | 149 | if (R.Sec->Live) |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 150 | return; |
| Peter Collingbourne | 676c7cd | 2016-04-26 23:52:44 +0000 | [diff] [blame] | 151 | R.Sec->Live = true; |
| 152 | if (InputSection<ELFT> *S = dyn_cast<InputSection<ELFT>>(R.Sec)) |
| Rui Ueyama | 92ce0e9 | 2015-11-12 19:42:43 +0000 | [diff] [blame] | 153 | Q.push_back(S); |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 154 | }; |
| 155 | |
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 156 | auto MarkSymbol = [&](const SymbolBody *Sym) { |
| 157 | if (auto *D = dyn_cast_or_null<DefinedRegular<ELFT>>(Sym)) |
| 158 | Enqueue({D->Section, D->Value}); |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 159 | }; |
| 160 | |
| 161 | // Add GC root symbols. |
| Rafael Espindola | 38c67a2 | 2016-04-15 14:41:56 +0000 | [diff] [blame] | 162 | if (Config->EntrySym) |
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 163 | MarkSymbol(Config->EntrySym->body()); |
| Rui Ueyama | 4f8d21f | 2016-05-02 19:30:42 +0000 | [diff] [blame] | 164 | MarkSymbol(Symtab<ELFT>::X->find(Config->Init)); |
| 165 | MarkSymbol(Symtab<ELFT>::X->find(Config->Fini)); |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 166 | for (StringRef S : Config->Undefined) |
| Rui Ueyama | 4f8d21f | 2016-05-02 19:30:42 +0000 | [diff] [blame] | 167 | MarkSymbol(Symtab<ELFT>::X->find(S)); |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 168 | |
| 169 | // Preserve externally-visible symbols if the symbols defined by this |
| Rui Ueyama | f53b1b7 | 2016-01-05 16:35:46 +0000 | [diff] [blame] | 170 | // file can interrupt other ELF file's symbols at runtime. |
| Rui Ueyama | 4f8d21f | 2016-05-02 19:30:42 +0000 | [diff] [blame] | 171 | for (const Symbol *S : Symtab<ELFT>::X->getSymbols()) |
| Rafael Espindola | 1b65ad1 | 2016-04-26 16:26:45 +0000 | [diff] [blame] | 172 | if (S->includeInDynsym()) |
| Peter Collingbourne | 4f95270 | 2016-05-01 04:55:03 +0000 | [diff] [blame] | 173 | MarkSymbol(S->body()); |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 174 | |
| George Rimar | 481c2ce | 2016-02-23 07:47:54 +0000 | [diff] [blame] | 175 | // Preserve special sections and those which are specified in linker |
| 176 | // script KEEP command. |
| Rui Ueyama | 4f8d21f | 2016-05-02 19:30:42 +0000 | [diff] [blame] | 177 | for (const std::unique_ptr<ObjectFile<ELFT>> &F : |
| 178 | Symtab<ELFT>::X->getObjectFiles()) |
| Rui Ueyama | 74f598b | 2015-12-24 10:14:05 +0000 | [diff] [blame] | 179 | for (InputSectionBase<ELFT> *Sec : F->getSections()) |
| George Rimar | af90d54 | 2016-05-02 13:49:42 +0000 | [diff] [blame] | 180 | if (Sec && Sec != &InputSection<ELFT>::Discarded) { |
| 181 | // .eh_frame is always marked as live now, but also it can reference to |
| 182 | // sections that contain personality. We preserve all non-text sections |
| 183 | // referred by .eh_frame here. |
| 184 | if (auto *EH = dyn_cast_or_null<EHInputSection<ELFT>>(Sec)) |
| Rafael Espindola | d89fbca | 2016-05-05 13:51:14 +0000 | [diff] [blame] | 185 | scanEhFrameSection<ELFT>(*EH, Enqueue); |
| Rui Ueyama | 07320e4 | 2016-04-20 20:13:41 +0000 | [diff] [blame] | 186 | if (isReserved(Sec) || Script<ELFT>::X->shouldKeep(Sec)) |
| Peter Collingbourne | 676c7cd | 2016-04-26 23:52:44 +0000 | [diff] [blame] | 187 | Enqueue({Sec, 0}); |
| George Rimar | af90d54 | 2016-05-02 13:49:42 +0000 | [diff] [blame] | 188 | } |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 189 | |
| 190 | // Mark all reachable sections. |
| 191 | while (!Q.empty()) |
| Rui Ueyama | 92ce0e9 | 2015-11-12 19:42:43 +0000 | [diff] [blame] | 192 | forEachSuccessor<ELFT>(Q.pop_back_val(), Enqueue); |
| Rui Ueyama | c4aaed9 | 2015-10-22 18:49:53 +0000 | [diff] [blame] | 193 | } |
| 194 | |
| Rui Ueyama | 4f8d21f | 2016-05-02 19:30:42 +0000 | [diff] [blame] | 195 | template void elf::markLive<ELF32LE>(); |
| 196 | template void elf::markLive<ELF32BE>(); |
| 197 | template void elf::markLive<ELF64LE>(); |
| 198 | template void elf::markLive<ELF64BE>(); |