Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 1 | //===- SyntheticSections.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 contains linker-synthesized sections. Currently, |
| 11 | // synthetic sections are created either output sections or input sections, |
| 12 | // but we are rewriting code so that all synthetic sections are created as |
| 13 | // input sections. |
| 14 | // |
| 15 | //===----------------------------------------------------------------------===// |
| 16 | |
| 17 | #include "SyntheticSections.h" |
| 18 | #include "Config.h" |
| 19 | #include "Error.h" |
| 20 | #include "InputFiles.h" |
Rui Ueyama | e288eef | 2016-11-02 18:58:44 +0000 | [diff] [blame] | 21 | #include "Memory.h" |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 22 | #include "OutputSections.h" |
| 23 | #include "Strings.h" |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 24 | #include "SymbolTable.h" |
Simon Atanasyan | ce02cf0 | 2016-11-09 21:36:56 +0000 | [diff] [blame] | 25 | #include "Target.h" |
Simon Atanasyan | fa03b0f | 2016-11-09 21:37:06 +0000 | [diff] [blame] | 26 | #include "Writer.h" |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 27 | |
Rui Ueyama | 3da3f06 | 2016-11-10 20:20:37 +0000 | [diff] [blame] | 28 | #include "lld/Config/Version.h" |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 29 | #include "lld/Core/Parallel.h" |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 30 | #include "llvm/Support/Endian.h" |
| 31 | #include "llvm/Support/MD5.h" |
| 32 | #include "llvm/Support/RandomNumberGenerator.h" |
| 33 | #include "llvm/Support/SHA1.h" |
| 34 | #include "llvm/Support/xxhash.h" |
Rui Ueyama | 3da3f06 | 2016-11-10 20:20:37 +0000 | [diff] [blame] | 35 | #include <cstdlib> |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 36 | |
| 37 | using namespace llvm; |
| 38 | using namespace llvm::ELF; |
| 39 | using namespace llvm::object; |
| 40 | using namespace llvm::support; |
| 41 | using namespace llvm::support::endian; |
| 42 | |
| 43 | using namespace lld; |
| 44 | using namespace lld::elf; |
| 45 | |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 46 | template <class ELFT> static std::vector<DefinedCommon *> getCommonSymbols() { |
| 47 | std::vector<DefinedCommon *> V; |
| 48 | for (Symbol *S : Symtab<ELFT>::X->getSymbols()) |
| 49 | if (auto *B = dyn_cast<DefinedCommon>(S->body())) |
| 50 | V.push_back(B); |
| 51 | return V; |
| 52 | } |
| 53 | |
| 54 | // Find all common symbols and allocate space for them. |
Rafael Espindola | 682a5bc | 2016-11-08 14:42:34 +0000 | [diff] [blame] | 55 | template <class ELFT> InputSection<ELFT> *elf::createCommonSection() { |
| 56 | auto *Ret = make<InputSection<ELFT>>(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, 1, |
| 57 | ArrayRef<uint8_t>(), "COMMON"); |
| 58 | Ret->Live = true; |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 59 | |
| 60 | // Sort the common symbols by alignment as an heuristic to pack them better. |
| 61 | std::vector<DefinedCommon *> Syms = getCommonSymbols<ELFT>(); |
| 62 | std::stable_sort(Syms.begin(), Syms.end(), |
| 63 | [](const DefinedCommon *A, const DefinedCommon *B) { |
| 64 | return A->Alignment > B->Alignment; |
| 65 | }); |
| 66 | |
| 67 | // Assign offsets to symbols. |
| 68 | size_t Size = 0; |
| 69 | size_t Alignment = 1; |
| 70 | for (DefinedCommon *Sym : Syms) { |
Rui Ueyama | 1c78682 | 2016-11-05 23:14:54 +0000 | [diff] [blame] | 71 | Alignment = std::max<size_t>(Alignment, Sym->Alignment); |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 72 | Size = alignTo(Size, Sym->Alignment); |
| 73 | |
| 74 | // Compute symbol offset relative to beginning of input section. |
| 75 | Sym->Offset = Size; |
| 76 | Size += Sym->Size; |
| 77 | } |
Rafael Espindola | 682a5bc | 2016-11-08 14:42:34 +0000 | [diff] [blame] | 78 | Ret->Alignment = Alignment; |
| 79 | Ret->Data = makeArrayRef<uint8_t>(nullptr, Size); |
| 80 | return Ret; |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 81 | } |
| 82 | |
Rui Ueyama | 3da3f06 | 2016-11-10 20:20:37 +0000 | [diff] [blame] | 83 | // Returns an LLD version string. |
| 84 | static ArrayRef<uint8_t> getVersion() { |
| 85 | // Check LLD_VERSION first for ease of testing. |
| 86 | // You can get consitent output by using the environment variable. |
| 87 | // This is only for testing. |
| 88 | StringRef S = getenv("LLD_VERSION"); |
| 89 | if (S.empty()) |
| 90 | S = Saver.save(Twine("Linker: ") + getLLDVersion()); |
| 91 | |
| 92 | // +1 to include the terminating '\0'. |
| 93 | return {(const uint8_t *)S.data(), S.size() + 1}; |
Davide Italiano | b69f38f | 2016-11-11 00:05:41 +0000 | [diff] [blame] | 94 | } |
Rui Ueyama | 3da3f06 | 2016-11-10 20:20:37 +0000 | [diff] [blame] | 95 | |
| 96 | // Creates a .comment section containing LLD version info. |
| 97 | // With this feature, you can identify LLD-generated binaries easily |
| 98 | // by "objdump -s -j .comment <file>". |
| 99 | // The returned object is a mergeable string section. |
| 100 | template <class ELFT> MergeInputSection<ELFT> *elf::createCommentSection() { |
| 101 | typename ELFT::Shdr Hdr = {}; |
| 102 | Hdr.sh_flags = SHF_MERGE | SHF_STRINGS; |
| 103 | Hdr.sh_type = SHT_PROGBITS; |
| 104 | Hdr.sh_entsize = 1; |
| 105 | Hdr.sh_addralign = 1; |
| 106 | |
| 107 | auto *Ret = make<MergeInputSection<ELFT>>(/*file=*/nullptr, &Hdr, ".comment"); |
| 108 | Ret->Data = getVersion(); |
| 109 | Ret->splitIntoPieces(); |
| 110 | return Ret; |
| 111 | } |
| 112 | |
Simon Atanasyan | ce02cf0 | 2016-11-09 21:36:56 +0000 | [diff] [blame] | 113 | // Iterate over sections of the specified type. For each section call |
| 114 | // provided function. After that "kill" the section by turning off |
| 115 | // "Live" flag, so that they won't be included in the final output. |
| 116 | template <class ELFT> |
| 117 | static void iterateSectionContents( |
| 118 | uint32_t Type, |
Simon Atanasyan | 93214b7 | 2016-11-09 21:46:42 +0000 | [diff] [blame] | 119 | std::function<void(elf::ObjectFile<ELFT> *, ArrayRef<uint8_t>)> F) { |
Simon Atanasyan | ce02cf0 | 2016-11-09 21:36:56 +0000 | [diff] [blame] | 120 | for (InputSectionBase<ELFT> *Sec : Symtab<ELFT>::X->Sections) { |
| 121 | if (Sec && Sec->Live && Sec->Type == Type) { |
| 122 | Sec->Live = false; |
| 123 | F(Sec->getFile(), Sec->Data); |
| 124 | } |
| 125 | } |
| 126 | } |
| 127 | |
Simon Atanasyan | fa03b0f | 2016-11-09 21:37:06 +0000 | [diff] [blame] | 128 | // .MIPS.abiflags section. |
| 129 | template <class ELFT> |
| 130 | MipsAbiFlagsSection<ELFT>::MipsAbiFlagsSection() |
| 131 | : InputSection<ELFT>(SHF_ALLOC, SHT_MIPS_ABIFLAGS, 8, ArrayRef<uint8_t>(), |
| 132 | ".MIPS.abiflags") { |
| 133 | auto Func = [this](ObjectFile<ELFT> *F, ArrayRef<uint8_t> D) { |
| 134 | if (D.size() != sizeof(Elf_Mips_ABIFlags)) { |
| 135 | error(getFilename(F) + ": invalid size of .MIPS.abiflags section"); |
| 136 | return; |
| 137 | } |
| 138 | auto *S = reinterpret_cast<const Elf_Mips_ABIFlags *>(D.data()); |
| 139 | if (S->version != 0) { |
| 140 | error(getFilename(F) + ": unexpected .MIPS.abiflags version " + |
| 141 | Twine(S->version)); |
| 142 | return; |
| 143 | } |
| 144 | // LLD checks ISA compatibility in getMipsEFlags(). Here we just |
| 145 | // select the highest number of ISA/Rev/Ext. |
| 146 | Flags.isa_level = std::max(Flags.isa_level, S->isa_level); |
| 147 | Flags.isa_rev = std::max(Flags.isa_rev, S->isa_rev); |
| 148 | Flags.isa_ext = std::max(Flags.isa_ext, S->isa_ext); |
| 149 | Flags.gpr_size = std::max(Flags.gpr_size, S->gpr_size); |
| 150 | Flags.cpr1_size = std::max(Flags.cpr1_size, S->cpr1_size); |
| 151 | Flags.cpr2_size = std::max(Flags.cpr2_size, S->cpr2_size); |
| 152 | Flags.ases |= S->ases; |
| 153 | Flags.flags1 |= S->flags1; |
| 154 | Flags.flags2 |= S->flags2; |
| 155 | Flags.fp_abi = |
| 156 | elf::getMipsFpAbiFlag(Flags.fp_abi, S->fp_abi, getFilename(F)); |
| 157 | }; |
| 158 | iterateSectionContents<ELFT>(SHT_MIPS_ABIFLAGS, Func); |
| 159 | |
| 160 | this->Data = ArrayRef<uint8_t>((const uint8_t *)&Flags, sizeof(Flags)); |
| 161 | this->Live = true; |
| 162 | } |
| 163 | |
Simon Atanasyan | ce02cf0 | 2016-11-09 21:36:56 +0000 | [diff] [blame] | 164 | // .MIPS.options section. |
| 165 | template <class ELFT> |
| 166 | MipsOptionsSection<ELFT>::MipsOptionsSection() |
| 167 | : InputSection<ELFT>(SHF_ALLOC, SHT_MIPS_OPTIONS, 8, ArrayRef<uint8_t>(), |
| 168 | ".MIPS.options") { |
| 169 | Buf.resize(sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo)); |
| 170 | getOptions()->kind = ODK_REGINFO; |
| 171 | getOptions()->size = Buf.size(); |
| 172 | auto Func = [this](ObjectFile<ELFT> *F, ArrayRef<uint8_t> D) { |
| 173 | while (!D.empty()) { |
| 174 | if (D.size() < sizeof(Elf_Mips_Options)) { |
| 175 | error(getFilename(F) + ": invalid size of .MIPS.options section"); |
| 176 | break; |
| 177 | } |
| 178 | auto *O = reinterpret_cast<const Elf_Mips_Options *>(D.data()); |
| 179 | if (O->kind == ODK_REGINFO) { |
| 180 | if (Config->Relocatable && O->getRegInfo().ri_gp_value) |
| 181 | error(getFilename(F) + ": unsupported non-zero ri_gp_value"); |
| 182 | getOptions()->getRegInfo().ri_gprmask |= O->getRegInfo().ri_gprmask; |
| 183 | F->MipsGp0 = O->getRegInfo().ri_gp_value; |
| 184 | break; |
| 185 | } |
| 186 | if (!O->size) |
| 187 | fatal(getFilename(F) + ": zero option descriptor size"); |
| 188 | D = D.slice(O->size); |
| 189 | } |
| 190 | }; |
| 191 | iterateSectionContents<ELFT>(SHT_MIPS_OPTIONS, Func); |
| 192 | |
| 193 | this->Data = ArrayRef<uint8_t>(Buf); |
| 194 | // Section should be alive for N64 ABI only. |
| 195 | this->Live = ELFT::Is64Bits; |
| 196 | } |
| 197 | |
| 198 | template <class ELFT> void MipsOptionsSection<ELFT>::finalize() { |
| 199 | if (!Config->Relocatable) |
| 200 | getOptions()->getRegInfo().ri_gp_value = |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 201 | In<ELFT>::MipsGot->getVA() + MipsGPOffset; |
Simon Atanasyan | ce02cf0 | 2016-11-09 21:36:56 +0000 | [diff] [blame] | 202 | } |
| 203 | |
| 204 | // MIPS .reginfo section. |
| 205 | template <class ELFT> |
| 206 | MipsReginfoSection<ELFT>::MipsReginfoSection() |
| 207 | : InputSection<ELFT>(SHF_ALLOC, SHT_MIPS_REGINFO, 4, ArrayRef<uint8_t>(), |
| 208 | ".reginfo") { |
| 209 | auto Func = [this](ObjectFile<ELFT> *F, ArrayRef<uint8_t> D) { |
| 210 | if (D.size() != sizeof(Elf_Mips_RegInfo)) { |
| 211 | error(getFilename(F) + ": invalid size of .reginfo section"); |
| 212 | return; |
| 213 | } |
| 214 | auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(D.data()); |
| 215 | if (Config->Relocatable && R->ri_gp_value) |
| 216 | error(getFilename(F) + ": unsupported non-zero ri_gp_value"); |
| 217 | Reginfo.ri_gprmask |= R->ri_gprmask; |
| 218 | F->MipsGp0 = R->ri_gp_value; |
| 219 | }; |
| 220 | iterateSectionContents<ELFT>(SHT_MIPS_REGINFO, Func); |
| 221 | |
| 222 | this->Data = ArrayRef<uint8_t>((const uint8_t *)&Reginfo, sizeof(Reginfo)); |
| 223 | // Section should be alive for O32 and N32 ABIs only. |
| 224 | this->Live = !ELFT::Is64Bits; |
| 225 | } |
| 226 | |
| 227 | template <class ELFT> void MipsReginfoSection<ELFT>::finalize() { |
| 228 | if (!Config->Relocatable) |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 229 | Reginfo.ri_gp_value = In<ELFT>::MipsGot->getVA() + MipsGPOffset; |
Simon Atanasyan | ce02cf0 | 2016-11-09 21:36:56 +0000 | [diff] [blame] | 230 | } |
| 231 | |
Rui Ueyama | e288eef | 2016-11-02 18:58:44 +0000 | [diff] [blame] | 232 | static ArrayRef<uint8_t> createInterp() { |
| 233 | // StringSaver guarantees that the returned string ends with '\0'. |
| 234 | StringRef S = Saver.save(Config->DynamicLinker); |
Rui Ueyama | 6294a24 | 2016-11-04 17:41:29 +0000 | [diff] [blame] | 235 | return {(const uint8_t *)S.data(), S.size() + 1}; |
Rui Ueyama | e288eef | 2016-11-02 18:58:44 +0000 | [diff] [blame] | 236 | } |
| 237 | |
Rafael Espindola | c0e47fb | 2016-11-08 14:56:27 +0000 | [diff] [blame] | 238 | template <class ELFT> InputSection<ELFT> *elf::createInterpSection() { |
| 239 | auto *Ret = make<InputSection<ELFT>>(SHF_ALLOC, SHT_PROGBITS, 1, |
| 240 | createInterp(), ".interp"); |
| 241 | Ret->Live = true; |
| 242 | return Ret; |
Rui Ueyama | a9ee8d6 | 2016-11-04 22:25:39 +0000 | [diff] [blame] | 243 | } |
Rui Ueyama | e288eef | 2016-11-02 18:58:44 +0000 | [diff] [blame] | 244 | |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 245 | template <class ELFT> |
| 246 | BuildIdSection<ELFT>::BuildIdSection(size_t HashSize) |
| 247 | : InputSection<ELFT>(SHF_ALLOC, SHT_NOTE, 1, ArrayRef<uint8_t>(), |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 248 | ".note.gnu.build-id"), |
| 249 | HashSize(HashSize) { |
Rui Ueyama | a9ee8d6 | 2016-11-04 22:25:39 +0000 | [diff] [blame] | 250 | this->Live = true; |
| 251 | |
Rafael Espindola | 0e876cf | 2016-11-10 15:41:34 +0000 | [diff] [blame] | 252 | Buf.resize(HeaderSize + HashSize); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 253 | const endianness E = ELFT::TargetEndianness; |
Rafael Espindola | 1a54112 | 2016-11-08 14:47:16 +0000 | [diff] [blame] | 254 | write32<E>(Buf.data(), 4); // Name size |
| 255 | write32<E>(Buf.data() + 4, HashSize); // Content size |
| 256 | write32<E>(Buf.data() + 8, NT_GNU_BUILD_ID); // Type |
| 257 | memcpy(Buf.data() + 12, "GNU", 4); // Name string |
| 258 | this->Data = ArrayRef<uint8_t>(Buf); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 259 | } |
| 260 | |
Rui Ueyama | 35e0075 | 2016-11-10 00:12:28 +0000 | [diff] [blame] | 261 | // Returns the location of the build-id hash value in the output. |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 262 | template <class ELFT> |
| 263 | uint8_t *BuildIdSection<ELFT>::getOutputLoc(uint8_t *Start) const { |
Rafael Espindola | 0e876cf | 2016-11-10 15:41:34 +0000 | [diff] [blame] | 264 | return Start + this->OutSec->Offset + this->OutSecOff + HeaderSize; |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 265 | } |
| 266 | |
Rui Ueyama | 35e0075 | 2016-11-10 00:12:28 +0000 | [diff] [blame] | 267 | // Split one uint8 array into small pieces of uint8 arrays. |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 268 | static std::vector<ArrayRef<uint8_t>> split(ArrayRef<uint8_t> Arr, |
| 269 | size_t ChunkSize) { |
| 270 | std::vector<ArrayRef<uint8_t>> Ret; |
| 271 | while (Arr.size() > ChunkSize) { |
| 272 | Ret.push_back(Arr.take_front(ChunkSize)); |
| 273 | Arr = Arr.drop_front(ChunkSize); |
| 274 | } |
| 275 | if (!Arr.empty()) |
| 276 | Ret.push_back(Arr); |
| 277 | return Ret; |
| 278 | } |
| 279 | |
Rui Ueyama | 35e0075 | 2016-11-10 00:12:28 +0000 | [diff] [blame] | 280 | // Computes a hash value of Data using a given hash function. |
| 281 | // In order to utilize multiple cores, we first split data into 1MB |
| 282 | // chunks, compute a hash for each chunk, and then compute a hash value |
| 283 | // of the hash values. |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 284 | template <class ELFT> |
| 285 | void BuildIdSection<ELFT>::computeHash( |
George Rimar | 828787a | 2016-11-06 08:39:46 +0000 | [diff] [blame] | 286 | llvm::MutableArrayRef<uint8_t> Data, |
Rui Ueyama | 35e0075 | 2016-11-10 00:12:28 +0000 | [diff] [blame] | 287 | std::function<void(ArrayRef<uint8_t> Arr, uint8_t *Dest)> HashFn) { |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 288 | std::vector<ArrayRef<uint8_t>> Chunks = split(Data, 1024 * 1024); |
| 289 | std::vector<uint8_t> HashList(Chunks.size() * HashSize); |
| 290 | |
Rui Ueyama | 35e0075 | 2016-11-10 00:12:28 +0000 | [diff] [blame] | 291 | auto Fn = [&](ArrayRef<uint8_t> &Chunk) { |
| 292 | size_t Idx = &Chunk - Chunks.data(); |
| 293 | HashFn(Chunk, HashList.data() + Idx * HashSize); |
| 294 | }; |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 295 | |
Rui Ueyama | 35e0075 | 2016-11-10 00:12:28 +0000 | [diff] [blame] | 296 | if (Config->Threads) |
| 297 | parallel_for_each(Chunks.begin(), Chunks.end(), Fn); |
| 298 | else |
| 299 | std::for_each(Chunks.begin(), Chunks.end(), Fn); |
| 300 | |
| 301 | HashFn(HashList, this->getOutputLoc(Data.begin())); |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 302 | } |
| 303 | |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 304 | template <class ELFT> |
| 305 | void BuildIdFastHash<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
George Rimar | 5020971 | 2016-11-06 08:26:53 +0000 | [diff] [blame] | 306 | this->computeHash(Buf, [](ArrayRef<uint8_t> Arr, uint8_t *Dest) { |
Rui Ueyama | 35e0075 | 2016-11-10 00:12:28 +0000 | [diff] [blame] | 307 | write64le(Dest, xxHash64(toStringRef(Arr))); |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 308 | }); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 309 | } |
| 310 | |
| 311 | template <class ELFT> |
| 312 | void BuildIdMd5<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
Rui Ueyama | 35e0075 | 2016-11-10 00:12:28 +0000 | [diff] [blame] | 313 | this->computeHash(Buf, [](ArrayRef<uint8_t> Arr, uint8_t *Dest) { |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 314 | MD5 Hash; |
| 315 | Hash.update(Arr); |
| 316 | MD5::MD5Result Res; |
| 317 | Hash.final(Res); |
Rui Ueyama | 35e0075 | 2016-11-10 00:12:28 +0000 | [diff] [blame] | 318 | memcpy(Dest, Res, 16); |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 319 | }); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 320 | } |
| 321 | |
| 322 | template <class ELFT> |
| 323 | void BuildIdSha1<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
Rui Ueyama | 35e0075 | 2016-11-10 00:12:28 +0000 | [diff] [blame] | 324 | this->computeHash(Buf, [](ArrayRef<uint8_t> Arr, uint8_t *Dest) { |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 325 | SHA1 Hash; |
| 326 | Hash.update(Arr); |
Rui Ueyama | 35e0075 | 2016-11-10 00:12:28 +0000 | [diff] [blame] | 327 | memcpy(Dest, Hash.final().data(), 20); |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 328 | }); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 329 | } |
| 330 | |
| 331 | template <class ELFT> |
| 332 | void BuildIdUuid<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
Rui Ueyama | 35e0075 | 2016-11-10 00:12:28 +0000 | [diff] [blame] | 333 | if (getRandomBytes(this->getOutputLoc(Buf.data()), this->HashSize)) |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 334 | error("entropy source failure"); |
| 335 | } |
| 336 | |
| 337 | template <class ELFT> |
| 338 | BuildIdHexstring<ELFT>::BuildIdHexstring() |
| 339 | : BuildIdSection<ELFT>(Config->BuildIdVector.size()) {} |
| 340 | |
| 341 | template <class ELFT> |
| 342 | void BuildIdHexstring<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
Rui Ueyama | 35e0075 | 2016-11-10 00:12:28 +0000 | [diff] [blame] | 343 | memcpy(this->getOutputLoc(Buf.data()), Config->BuildIdVector.data(), |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 344 | Config->BuildIdVector.size()); |
| 345 | } |
| 346 | |
Eugene Leviant | 41ca327 | 2016-11-10 09:48:29 +0000 | [diff] [blame] | 347 | template <class ELFT> |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 348 | GotSection<ELFT>::GotSection() |
| 349 | : SyntheticSection<ELFT>(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 350 | Target->GotEntrySize, ".got") {} |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 351 | |
| 352 | template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody &Sym) { |
| 353 | Sym.GotIndex = Entries.size(); |
| 354 | Entries.push_back(&Sym); |
| 355 | } |
| 356 | |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 357 | template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) { |
| 358 | if (Sym.GlobalDynIndex != -1U) |
| 359 | return false; |
| 360 | Sym.GlobalDynIndex = Entries.size(); |
| 361 | // Global Dynamic TLS entries take two GOT slots. |
| 362 | Entries.push_back(nullptr); |
| 363 | Entries.push_back(&Sym); |
| 364 | return true; |
| 365 | } |
| 366 | |
| 367 | // Reserves TLS entries for a TLS module ID and a TLS block offset. |
| 368 | // In total it takes two GOT slots. |
| 369 | template <class ELFT> bool GotSection<ELFT>::addTlsIndex() { |
| 370 | if (TlsIndexOff != uint32_t(-1)) |
| 371 | return false; |
| 372 | TlsIndexOff = Entries.size() * sizeof(uintX_t); |
| 373 | Entries.push_back(nullptr); |
| 374 | Entries.push_back(nullptr); |
| 375 | return true; |
| 376 | } |
| 377 | |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 378 | template <class ELFT> |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 379 | typename GotSection<ELFT>::uintX_t |
| 380 | GotSection<ELFT>::getGlobalDynAddr(const SymbolBody &B) const { |
| 381 | return this->getVA() + B.GlobalDynIndex * sizeof(uintX_t); |
| 382 | } |
| 383 | |
| 384 | template <class ELFT> |
| 385 | typename GotSection<ELFT>::uintX_t |
| 386 | GotSection<ELFT>::getGlobalDynOffset(const SymbolBody &B) const { |
| 387 | return B.GlobalDynIndex * sizeof(uintX_t); |
| 388 | } |
| 389 | |
| 390 | template <class ELFT> void GotSection<ELFT>::finalize() { |
| 391 | Size = Entries.size() * sizeof(uintX_t); |
| 392 | } |
| 393 | |
| 394 | template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) { |
| 395 | for (const SymbolBody *B : Entries) { |
| 396 | uint8_t *Entry = Buf; |
| 397 | Buf += sizeof(uintX_t); |
| 398 | if (!B) |
| 399 | continue; |
| 400 | if (B->isPreemptible()) |
| 401 | continue; // The dynamic linker will take care of it. |
| 402 | uintX_t VA = B->getVA<ELFT>(); |
| 403 | write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA); |
| 404 | } |
| 405 | } |
| 406 | |
| 407 | template <class ELFT> |
| 408 | MipsGotSection<ELFT>::MipsGotSection() |
| 409 | : SyntheticSection<ELFT>(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, |
| 410 | SHT_PROGBITS, Target->GotEntrySize, ".got") {} |
| 411 | |
| 412 | template <class ELFT> |
| 413 | void MipsGotSection<ELFT>::addEntry(SymbolBody &Sym, uintX_t Addend, |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 414 | RelExpr Expr) { |
| 415 | // For "true" local symbols which can be referenced from the same module |
| 416 | // only compiler creates two instructions for address loading: |
| 417 | // |
| 418 | // lw $8, 0($gp) # R_MIPS_GOT16 |
| 419 | // addi $8, $8, 0 # R_MIPS_LO16 |
| 420 | // |
| 421 | // The first instruction loads high 16 bits of the symbol address while |
| 422 | // the second adds an offset. That allows to reduce number of required |
| 423 | // GOT entries because only one global offset table entry is necessary |
| 424 | // for every 64 KBytes of local data. So for local symbols we need to |
| 425 | // allocate number of GOT entries to hold all required "page" addresses. |
| 426 | // |
| 427 | // All global symbols (hidden and regular) considered by compiler uniformly. |
| 428 | // It always generates a single `lw` instruction and R_MIPS_GOT16 relocation |
| 429 | // to load address of the symbol. So for each such symbol we need to |
| 430 | // allocate dedicated GOT entry to store its address. |
| 431 | // |
| 432 | // If a symbol is preemptible we need help of dynamic linker to get its |
| 433 | // final address. The corresponding GOT entries are allocated in the |
| 434 | // "global" part of GOT. Entries for non preemptible global symbol allocated |
| 435 | // in the "local" part of GOT. |
| 436 | // |
| 437 | // See "Global Offset Table" in Chapter 5: |
| 438 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf |
| 439 | if (Expr == R_MIPS_GOT_LOCAL_PAGE) { |
| 440 | // At this point we do not know final symbol value so to reduce number |
| 441 | // of allocated GOT entries do the following trick. Save all output |
| 442 | // sections referenced by GOT relocations. Then later in the `finalize` |
| 443 | // method calculate number of "pages" required to cover all saved output |
| 444 | // section and allocate appropriate number of GOT entries. |
| 445 | auto *OutSec = cast<DefinedRegular<ELFT>>(&Sym)->Section->OutSec; |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 446 | OutSections.insert(OutSec); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 447 | return; |
| 448 | } |
| 449 | if (Sym.isTls()) { |
| 450 | // GOT entries created for MIPS TLS relocations behave like |
| 451 | // almost GOT entries from other ABIs. They go to the end |
| 452 | // of the global offset table. |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 453 | Sym.GotIndex = TlsEntries.size(); |
| 454 | TlsEntries.push_back(&Sym); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 455 | return; |
| 456 | } |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 457 | auto AddEntry = [&](SymbolBody &S, uintX_t A, GotEntries &Items) { |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 458 | if (S.isInGot() && !A) |
| 459 | return; |
| 460 | size_t NewIndex = Items.size(); |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 461 | if (!EntryIndexMap.insert({{&S, A}, NewIndex}).second) |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 462 | return; |
| 463 | Items.emplace_back(&S, A); |
| 464 | if (!A) |
| 465 | S.GotIndex = NewIndex; |
| 466 | }; |
| 467 | if (Sym.isPreemptible()) { |
| 468 | // Ignore addends for preemptible symbols. They got single GOT entry anyway. |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 469 | AddEntry(Sym, 0, GlobalEntries); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 470 | Sym.IsInGlobalMipsGot = true; |
| 471 | } else if (Expr == R_MIPS_GOT_OFF32) { |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 472 | AddEntry(Sym, Addend, LocalEntries32); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 473 | Sym.Is32BitMipsGot = true; |
| 474 | } else { |
| 475 | // Hold local GOT entries accessed via a 16-bit index separately. |
| 476 | // That allows to write them in the beginning of the GOT and keep |
| 477 | // their indexes as less as possible to escape relocation's overflow. |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 478 | AddEntry(Sym, Addend, LocalEntries); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 479 | } |
| 480 | } |
| 481 | |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 482 | template <class ELFT> bool MipsGotSection<ELFT>::addDynTlsEntry(SymbolBody &Sym) { |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 483 | if (Sym.GlobalDynIndex != -1U) |
| 484 | return false; |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 485 | Sym.GlobalDynIndex = TlsEntries.size(); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 486 | // Global Dynamic TLS entries take two GOT slots. |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 487 | TlsEntries.push_back(nullptr); |
| 488 | TlsEntries.push_back(&Sym); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 489 | return true; |
| 490 | } |
| 491 | |
| 492 | // Reserves TLS entries for a TLS module ID and a TLS block offset. |
| 493 | // In total it takes two GOT slots. |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 494 | template <class ELFT> bool MipsGotSection<ELFT>::addTlsIndex() { |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 495 | if (TlsIndexOff != uint32_t(-1)) |
| 496 | return false; |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 497 | TlsIndexOff = TlsEntries.size() * sizeof(uintX_t); |
| 498 | TlsEntries.push_back(nullptr); |
| 499 | TlsEntries.push_back(nullptr); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 500 | return true; |
| 501 | } |
| 502 | |
| 503 | template <class ELFT> |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 504 | typename MipsGotSection<ELFT>::uintX_t |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 505 | MipsGotSection<ELFT>::getPageEntryOffset(uintX_t EntryValue) { |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 506 | // Initialize the entry by the %hi(EntryValue) expression |
| 507 | // but without right-shifting. |
| 508 | EntryValue = (EntryValue + 0x8000) & ~0xffff; |
| 509 | // Take into account MIPS GOT header. |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 510 | // See comment in the MipsGotSection::writeTo. |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 511 | size_t NewIndex = PageIndexMap.size() + 2; |
| 512 | auto P = PageIndexMap.insert(std::make_pair(EntryValue, NewIndex)); |
| 513 | assert(!P.second || PageIndexMap.size() <= PageEntriesNum); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 514 | return (uintX_t)P.first->second * sizeof(uintX_t) - MipsGPOffset; |
| 515 | } |
| 516 | |
| 517 | template <class ELFT> |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 518 | typename MipsGotSection<ELFT>::uintX_t |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 519 | MipsGotSection<ELFT>::getBodyEntryOffset(const SymbolBody &B, |
| 520 | uintX_t Addend) const { |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 521 | // Calculate offset of the GOT entries block: TLS, global, local. |
| 522 | uintX_t GotBlockOff; |
| 523 | if (B.isTls()) |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 524 | GotBlockOff = getTlsOffset(); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 525 | else if (B.IsInGlobalMipsGot) |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 526 | GotBlockOff = getLocalEntriesNum() * sizeof(uintX_t); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 527 | else if (B.Is32BitMipsGot) |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 528 | GotBlockOff = (PageEntriesNum + LocalEntries.size()) * sizeof(uintX_t); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 529 | else |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 530 | GotBlockOff = PageEntriesNum * sizeof(uintX_t); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 531 | // Calculate index of the GOT entry in the block. |
| 532 | uintX_t GotIndex; |
| 533 | if (B.isInGot()) |
| 534 | GotIndex = B.GotIndex; |
| 535 | else { |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 536 | auto It = EntryIndexMap.find({&B, Addend}); |
| 537 | assert(It != EntryIndexMap.end()); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 538 | GotIndex = It->second; |
| 539 | } |
| 540 | return GotBlockOff + GotIndex * sizeof(uintX_t) - MipsGPOffset; |
| 541 | } |
| 542 | |
| 543 | template <class ELFT> |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 544 | typename MipsGotSection<ELFT>::uintX_t |
| 545 | MipsGotSection<ELFT>::getTlsOffset() const { |
| 546 | return (getLocalEntriesNum() + GlobalEntries.size()) * sizeof(uintX_t); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 547 | } |
| 548 | |
| 549 | template <class ELFT> |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 550 | typename MipsGotSection<ELFT>::uintX_t |
| 551 | MipsGotSection<ELFT>::getGlobalDynOffset(const SymbolBody &B) const { |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 552 | return B.GlobalDynIndex * sizeof(uintX_t); |
| 553 | } |
| 554 | |
| 555 | template <class ELFT> |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 556 | const SymbolBody *MipsGotSection<ELFT>::getFirstGlobalEntry() const { |
| 557 | return GlobalEntries.empty() ? nullptr : GlobalEntries.front().first; |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 558 | } |
| 559 | |
| 560 | template <class ELFT> |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 561 | unsigned MipsGotSection<ELFT>::getLocalEntriesNum() const { |
| 562 | return PageEntriesNum + LocalEntries.size() + LocalEntries32.size(); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 563 | } |
| 564 | |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 565 | template <class ELFT> void MipsGotSection<ELFT>::finalize() { |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 566 | size_t EntriesNum = TlsEntries.size(); |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 567 | // Take into account MIPS GOT header. |
| 568 | // See comment in the MipsGotSection::writeTo. |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 569 | PageEntriesNum += 2; |
| 570 | for (const OutputSectionBase *OutSec : OutSections) { |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 571 | // Calculate an upper bound of MIPS GOT entries required to store page |
| 572 | // addresses of local symbols. We assume the worst case - each 64kb |
| 573 | // page of the output section has at least one GOT relocation against it. |
| 574 | // Add 0x8000 to the section's size because the page address stored |
| 575 | // in the GOT entry is calculated as (value + 0x8000) & ~0xffff. |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 576 | PageEntriesNum += (OutSec->Size + 0x8000 + 0xfffe) / 0xffff; |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 577 | } |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 578 | EntriesNum += getLocalEntriesNum() + GlobalEntries.size(); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 579 | Size = EntriesNum * sizeof(uintX_t); |
| 580 | } |
| 581 | |
| 582 | template <class ELFT> |
| 583 | static void writeUint(uint8_t *Buf, typename ELFT::uint Val) { |
| 584 | typedef typename ELFT::uint uintX_t; |
| 585 | write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Buf, Val); |
| 586 | } |
| 587 | |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 588 | template <class ELFT> void MipsGotSection<ELFT>::writeTo(uint8_t *Buf) { |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 589 | // Set the MSB of the second GOT slot. This is not required by any |
| 590 | // MIPS ABI documentation, though. |
| 591 | // |
| 592 | // There is a comment in glibc saying that "The MSB of got[1] of a |
| 593 | // gnu object is set to identify gnu objects," and in GNU gold it |
| 594 | // says "the second entry will be used by some runtime loaders". |
| 595 | // But how this field is being used is unclear. |
| 596 | // |
| 597 | // We are not really willing to mimic other linkers behaviors |
| 598 | // without understanding why they do that, but because all files |
| 599 | // generated by GNU tools have this special GOT value, and because |
| 600 | // we've been doing this for years, it is probably a safe bet to |
| 601 | // keep doing this for now. We really need to revisit this to see |
| 602 | // if we had to do this. |
| 603 | auto *P = reinterpret_cast<typename ELFT::Off *>(Buf); |
| 604 | P[1] = uintX_t(1) << (ELFT::Is64Bits ? 63 : 31); |
| 605 | // Write 'page address' entries to the local part of the GOT. |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 606 | for (std::pair<uintX_t, size_t> &L : PageIndexMap) { |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 607 | uint8_t *Entry = Buf + L.second * sizeof(uintX_t); |
| 608 | writeUint<ELFT>(Entry, L.first); |
| 609 | } |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 610 | Buf += PageEntriesNum * sizeof(uintX_t); |
| 611 | auto AddEntry = [&](const GotEntry &SA) { |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 612 | uint8_t *Entry = Buf; |
| 613 | Buf += sizeof(uintX_t); |
| 614 | const SymbolBody *Body = SA.first; |
| 615 | uintX_t VA = Body->template getVA<ELFT>(SA.second); |
| 616 | writeUint<ELFT>(Entry, VA); |
| 617 | }; |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 618 | std::for_each(std::begin(LocalEntries), std::end(LocalEntries), AddEntry); |
| 619 | std::for_each(std::begin(LocalEntries32), std::end(LocalEntries32), AddEntry); |
| 620 | std::for_each(std::begin(GlobalEntries), std::end(GlobalEntries), AddEntry); |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 621 | // Initialize TLS-related GOT entries. If the entry has a corresponding |
| 622 | // dynamic relocations, leave it initialized by zero. Write down adjusted |
| 623 | // TLS symbol's values otherwise. To calculate the adjustments use offsets |
| 624 | // for thread-local storage. |
| 625 | // https://www.linux-mips.org/wiki/NPTL |
| 626 | if (TlsIndexOff != -1U && !Config->Pic) |
| 627 | writeUint<ELFT>(Buf + TlsIndexOff, 1); |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 628 | for (const SymbolBody *B : TlsEntries) { |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 629 | if (!B || B->isPreemptible()) |
| 630 | continue; |
| 631 | uintX_t VA = B->getVA<ELFT>(); |
| 632 | if (B->GotIndex != -1U) { |
| 633 | uint8_t *Entry = Buf + B->GotIndex * sizeof(uintX_t); |
| 634 | writeUint<ELFT>(Entry, VA - 0x7000); |
| 635 | } |
| 636 | if (B->GlobalDynIndex != -1U) { |
| 637 | uint8_t *Entry = Buf + B->GlobalDynIndex * sizeof(uintX_t); |
| 638 | writeUint<ELFT>(Entry, 1); |
| 639 | Entry += sizeof(uintX_t); |
| 640 | writeUint<ELFT>(Entry, VA - 0x8000); |
| 641 | } |
| 642 | } |
| 643 | } |
| 644 | |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 645 | template <class ELFT> |
Eugene Leviant | 41ca327 | 2016-11-10 09:48:29 +0000 | [diff] [blame] | 646 | GotPltSection<ELFT>::GotPltSection() |
| 647 | : SyntheticSection<ELFT>(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, |
George Rimar | d8b2776 | 2016-11-14 10:14:18 +0000 | [diff] [blame] | 648 | Target->GotPltEntrySize, ".got.plt") {} |
Eugene Leviant | 41ca327 | 2016-11-10 09:48:29 +0000 | [diff] [blame] | 649 | |
| 650 | template <class ELFT> void GotPltSection<ELFT>::addEntry(SymbolBody &Sym) { |
| 651 | Sym.GotPltIndex = Target->GotPltHeaderEntriesNum + Entries.size(); |
| 652 | Entries.push_back(&Sym); |
| 653 | } |
| 654 | |
| 655 | template <class ELFT> bool GotPltSection<ELFT>::empty() const { |
| 656 | return Entries.empty(); |
| 657 | } |
| 658 | |
| 659 | template <class ELFT> size_t GotPltSection<ELFT>::getSize() const { |
| 660 | return (Target->GotPltHeaderEntriesNum + Entries.size()) * |
| 661 | Target->GotPltEntrySize; |
| 662 | } |
| 663 | |
| 664 | template <class ELFT> void GotPltSection<ELFT>::writeTo(uint8_t *Buf) { |
| 665 | Target->writeGotPltHeader(Buf); |
| 666 | Buf += Target->GotPltHeaderEntriesNum * Target->GotPltEntrySize; |
| 667 | for (const SymbolBody *B : Entries) { |
| 668 | Target->writeGotPlt(Buf, *B); |
| 669 | Buf += sizeof(uintX_t); |
| 670 | } |
| 671 | } |
| 672 | |
Eugene Leviant | 22eb026 | 2016-11-14 09:16:00 +0000 | [diff] [blame] | 673 | template <class ELFT> |
| 674 | StringTableSection<ELFT>::StringTableSection(StringRef Name, bool Dynamic) |
| 675 | : SyntheticSection<ELFT>(Dynamic ? (uintX_t)SHF_ALLOC : 0, SHT_STRTAB, 1, |
| 676 | Name), |
| 677 | Dynamic(Dynamic) {} |
| 678 | |
| 679 | // Adds a string to the string table. If HashIt is true we hash and check for |
| 680 | // duplicates. It is optional because the name of global symbols are already |
| 681 | // uniqued and hashing them again has a big cost for a small value: uniquing |
| 682 | // them with some other string that happens to be the same. |
| 683 | template <class ELFT> |
| 684 | unsigned StringTableSection<ELFT>::addString(StringRef S, bool HashIt) { |
| 685 | if (HashIt) { |
| 686 | auto R = StringMap.insert(std::make_pair(S, this->Size)); |
| 687 | if (!R.second) |
| 688 | return R.first->second; |
| 689 | } |
| 690 | unsigned Ret = this->Size; |
| 691 | this->Size = this->Size + S.size() + 1; |
| 692 | Strings.push_back(S); |
| 693 | return Ret; |
| 694 | } |
| 695 | |
| 696 | template <class ELFT> void StringTableSection<ELFT>::writeTo(uint8_t *Buf) { |
| 697 | // ELF string tables start with NUL byte, so advance the pointer by one. |
| 698 | ++Buf; |
| 699 | for (StringRef S : Strings) { |
| 700 | memcpy(Buf, S.data(), S.size()); |
| 701 | Buf += S.size() + 1; |
| 702 | } |
| 703 | } |
| 704 | |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 705 | static unsigned getVerDefNum() { return Config->VersionDefinitions.size() + 1; } |
| 706 | |
| 707 | template <class ELFT> |
| 708 | DynamicSection<ELFT>::DynamicSection() |
| 709 | : SyntheticSection<ELFT>(SHF_ALLOC | SHF_WRITE, SHT_DYNAMIC, |
| 710 | sizeof(uintX_t), ".dynamic") { |
| 711 | this->Entsize = ELFT::Is64Bits ? 16 : 8; |
| 712 | // .dynamic section is not writable on MIPS. |
| 713 | // See "Special Section" in Chapter 4 in the following document: |
| 714 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf |
| 715 | if (Config->EMachine == EM_MIPS) |
| 716 | this->Flags = SHF_ALLOC; |
| 717 | |
| 718 | addEntries(); |
| 719 | } |
| 720 | |
| 721 | // There are some dynamic entries that don't depend on other sections. |
| 722 | // Such entries can be set early. |
| 723 | template <class ELFT> void DynamicSection<ELFT>::addEntries() { |
| 724 | // Add strings to .dynstr early so that .dynstr's size will be |
| 725 | // fixed early. |
| 726 | for (StringRef S : Config->AuxiliaryList) |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 727 | add({DT_AUXILIARY, In<ELFT>::DynStrTab->addString(S)}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 728 | if (!Config->RPath.empty()) |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 729 | add({Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 730 | In<ELFT>::DynStrTab->addString(Config->RPath)}); |
| 731 | for (SharedFile<ELFT> *F : Symtab<ELFT>::X->getSharedFiles()) |
| 732 | if (F->isNeeded()) |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 733 | add({DT_NEEDED, In<ELFT>::DynStrTab->addString(F->getSoName())}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 734 | if (!Config->SoName.empty()) |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 735 | add({DT_SONAME, In<ELFT>::DynStrTab->addString(Config->SoName)}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 736 | |
| 737 | // Set DT_FLAGS and DT_FLAGS_1. |
| 738 | uint32_t DtFlags = 0; |
| 739 | uint32_t DtFlags1 = 0; |
| 740 | if (Config->Bsymbolic) |
| 741 | DtFlags |= DF_SYMBOLIC; |
| 742 | if (Config->ZNodelete) |
| 743 | DtFlags1 |= DF_1_NODELETE; |
| 744 | if (Config->ZNow) { |
| 745 | DtFlags |= DF_BIND_NOW; |
| 746 | DtFlags1 |= DF_1_NOW; |
| 747 | } |
| 748 | if (Config->ZOrigin) { |
| 749 | DtFlags |= DF_ORIGIN; |
| 750 | DtFlags1 |= DF_1_ORIGIN; |
| 751 | } |
| 752 | |
| 753 | if (DtFlags) |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 754 | add({DT_FLAGS, DtFlags}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 755 | if (DtFlags1) |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 756 | add({DT_FLAGS_1, DtFlags1}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 757 | |
| 758 | if (!Config->Entry.empty()) |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 759 | add({DT_DEBUG, (uint64_t)0}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 760 | } |
| 761 | |
| 762 | // Add remaining entries to complete .dynamic contents. |
| 763 | template <class ELFT> void DynamicSection<ELFT>::finalize() { |
| 764 | if (this->Size) |
| 765 | return; // Already finalized. |
| 766 | |
| 767 | this->Link = In<ELFT>::DynStrTab->OutSec->SectionIndex; |
| 768 | |
Eugene Leviant | a96d902 | 2016-11-16 10:02:27 +0000 | [diff] [blame] | 769 | if (In<ELFT>::RelaDyn->hasRelocs()) { |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 770 | bool IsRela = Config->Rela; |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 771 | add({IsRela ? DT_RELA : DT_REL, In<ELFT>::RelaDyn}); |
| 772 | add({IsRela ? DT_RELASZ : DT_RELSZ, In<ELFT>::RelaDyn->getSize()}); |
| 773 | add({IsRela ? DT_RELAENT : DT_RELENT, |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 774 | uintX_t(IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel))}); |
| 775 | |
| 776 | // MIPS dynamic loader does not support RELCOUNT tag. |
| 777 | // The problem is in the tight relation between dynamic |
| 778 | // relocations and GOT. So do not emit this tag on MIPS. |
| 779 | if (Config->EMachine != EM_MIPS) { |
Eugene Leviant | a96d902 | 2016-11-16 10:02:27 +0000 | [diff] [blame] | 780 | size_t NumRelativeRels = In<ELFT>::RelaDyn->getRelativeRelocCount(); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 781 | if (Config->ZCombreloc && NumRelativeRels) |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 782 | add({IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 783 | } |
| 784 | } |
Eugene Leviant | a96d902 | 2016-11-16 10:02:27 +0000 | [diff] [blame] | 785 | if (In<ELFT>::RelaPlt->hasRelocs()) { |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 786 | add({DT_JMPREL, In<ELFT>::RelaPlt}); |
| 787 | add({DT_PLTRELSZ, In<ELFT>::RelaPlt->getSize()}); |
| 788 | add({Config->EMachine == EM_MIPS ? DT_MIPS_PLTGOT : DT_PLTGOT, |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 789 | In<ELFT>::GotPlt}); |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 790 | add({DT_PLTREL, uint64_t(Config->Rela ? DT_RELA : DT_REL)}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 791 | } |
| 792 | |
Eugene Leviant | 9230db9 | 2016-11-17 09:16:34 +0000 | [diff] [blame] | 793 | add({DT_SYMTAB, In<ELFT>::DynSymTab}); |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 794 | add({DT_SYMENT, sizeof(Elf_Sym)}); |
| 795 | add({DT_STRTAB, In<ELFT>::DynStrTab}); |
| 796 | add({DT_STRSZ, In<ELFT>::DynStrTab->getSize()}); |
Eugene Leviant | be809a7 | 2016-11-18 06:44:18 +0000 | [diff] [blame] | 797 | if (In<ELFT>::GnuHashTab) |
| 798 | add({DT_GNU_HASH, In<ELFT>::GnuHashTab}); |
Eugene Leviant | b96e809 | 2016-11-18 09:06:47 +0000 | [diff] [blame] | 799 | if (In<ELFT>::HashTab) |
| 800 | add({DT_HASH, In<ELFT>::HashTab}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 801 | |
| 802 | if (Out<ELFT>::PreinitArray) { |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 803 | add({DT_PREINIT_ARRAY, Out<ELFT>::PreinitArray}); |
| 804 | add({DT_PREINIT_ARRAYSZ, Out<ELFT>::PreinitArray, Entry::SecSize}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 805 | } |
| 806 | if (Out<ELFT>::InitArray) { |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 807 | add({DT_INIT_ARRAY, Out<ELFT>::InitArray}); |
| 808 | add({DT_INIT_ARRAYSZ, Out<ELFT>::InitArray, Entry::SecSize}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 809 | } |
| 810 | if (Out<ELFT>::FiniArray) { |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 811 | add({DT_FINI_ARRAY, Out<ELFT>::FiniArray}); |
| 812 | add({DT_FINI_ARRAYSZ, Out<ELFT>::FiniArray, Entry::SecSize}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 813 | } |
| 814 | |
| 815 | if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Init)) |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 816 | add({DT_INIT, B}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 817 | if (SymbolBody *B = Symtab<ELFT>::X->find(Config->Fini)) |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 818 | add({DT_FINI, B}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 819 | |
| 820 | bool HasVerNeed = Out<ELFT>::VerNeed->getNeedNum() != 0; |
| 821 | if (HasVerNeed || Out<ELFT>::VerDef) |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 822 | add({DT_VERSYM, Out<ELFT>::VerSym}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 823 | if (Out<ELFT>::VerDef) { |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 824 | add({DT_VERDEF, Out<ELFT>::VerDef}); |
| 825 | add({DT_VERDEFNUM, getVerDefNum()}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 826 | } |
| 827 | if (HasVerNeed) { |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 828 | add({DT_VERNEED, Out<ELFT>::VerNeed}); |
| 829 | add({DT_VERNEEDNUM, Out<ELFT>::VerNeed->getNeedNum()}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 830 | } |
| 831 | |
| 832 | if (Config->EMachine == EM_MIPS) { |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 833 | add({DT_MIPS_RLD_VERSION, 1}); |
| 834 | add({DT_MIPS_FLAGS, RHF_NOTPOT}); |
| 835 | add({DT_MIPS_BASE_ADDRESS, Config->ImageBase}); |
Eugene Leviant | 9230db9 | 2016-11-17 09:16:34 +0000 | [diff] [blame] | 836 | add({DT_MIPS_SYMTABNO, In<ELFT>::DynSymTab->getNumSymbols()}); |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 837 | add({DT_MIPS_LOCAL_GOTNO, In<ELFT>::MipsGot->getLocalEntriesNum()}); |
| 838 | if (const SymbolBody *B = In<ELFT>::MipsGot->getFirstGlobalEntry()) |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 839 | add({DT_MIPS_GOTSYM, B->DynsymIndex}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 840 | else |
Eugene Leviant | 9230db9 | 2016-11-17 09:16:34 +0000 | [diff] [blame] | 841 | add({DT_MIPS_GOTSYM, In<ELFT>::DynSymTab->getNumSymbols()}); |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 842 | add({DT_PLTGOT, In<ELFT>::MipsGot}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 843 | if (Out<ELFT>::MipsRldMap) |
Rui Ueyama | 729ac79 | 2016-11-17 04:10:09 +0000 | [diff] [blame] | 844 | add({DT_MIPS_RLD_MAP, Out<ELFT>::MipsRldMap}); |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 845 | } |
| 846 | |
| 847 | this->OutSec->Entsize = this->Entsize; |
| 848 | this->OutSec->Link = this->Link; |
| 849 | |
| 850 | // +1 for DT_NULL |
| 851 | this->Size = (Entries.size() + 1) * this->Entsize; |
| 852 | } |
| 853 | |
| 854 | template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) { |
| 855 | auto *P = reinterpret_cast<Elf_Dyn *>(Buf); |
| 856 | |
| 857 | for (const Entry &E : Entries) { |
| 858 | P->d_tag = E.Tag; |
| 859 | switch (E.Kind) { |
| 860 | case Entry::SecAddr: |
| 861 | P->d_un.d_ptr = E.OutSec->Addr; |
| 862 | break; |
| 863 | case Entry::InSecAddr: |
| 864 | P->d_un.d_ptr = E.InSec->OutSec->Addr + E.InSec->OutSecOff; |
| 865 | break; |
| 866 | case Entry::SecSize: |
| 867 | P->d_un.d_val = E.OutSec->Size; |
| 868 | break; |
| 869 | case Entry::SymAddr: |
| 870 | P->d_un.d_ptr = E.Sym->template getVA<ELFT>(); |
| 871 | break; |
| 872 | case Entry::PlainInt: |
| 873 | P->d_un.d_val = E.Val; |
| 874 | break; |
| 875 | } |
| 876 | ++P; |
| 877 | } |
| 878 | } |
| 879 | |
Eugene Leviant | a96d902 | 2016-11-16 10:02:27 +0000 | [diff] [blame] | 880 | template <class ELFT> |
| 881 | typename ELFT::uint DynamicReloc<ELFT>::getOffset() const { |
| 882 | if (OutputSec) |
| 883 | return OutputSec->Addr + OffsetInSec; |
| 884 | return InputSec->OutSec->Addr + InputSec->getOffset(OffsetInSec); |
| 885 | } |
| 886 | |
| 887 | template <class ELFT> |
| 888 | typename ELFT::uint DynamicReloc<ELFT>::getAddend() const { |
| 889 | if (UseSymVA) |
| 890 | return Sym->getVA<ELFT>(Addend); |
| 891 | return Addend; |
| 892 | } |
| 893 | |
| 894 | template <class ELFT> uint32_t DynamicReloc<ELFT>::getSymIndex() const { |
| 895 | if (Sym && !UseSymVA) |
| 896 | return Sym->DynsymIndex; |
| 897 | return 0; |
| 898 | } |
| 899 | |
| 900 | template <class ELFT> |
| 901 | RelocationSection<ELFT>::RelocationSection(StringRef Name, bool Sort) |
| 902 | : SyntheticSection<ELFT>(SHF_ALLOC, Config->Rela ? SHT_RELA : SHT_REL, |
| 903 | sizeof(uintX_t), Name), |
| 904 | Sort(Sort) { |
| 905 | this->Entsize = Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); |
| 906 | } |
| 907 | |
| 908 | template <class ELFT> |
| 909 | void RelocationSection<ELFT>::addReloc(const DynamicReloc<ELFT> &Reloc) { |
| 910 | if (Reloc.Type == Target->RelativeRel) |
| 911 | ++NumRelativeRelocs; |
| 912 | Relocs.push_back(Reloc); |
| 913 | } |
| 914 | |
| 915 | template <class ELFT, class RelTy> |
| 916 | static bool compRelocations(const RelTy &A, const RelTy &B) { |
| 917 | bool AIsRel = A.getType(Config->Mips64EL) == Target->RelativeRel; |
| 918 | bool BIsRel = B.getType(Config->Mips64EL) == Target->RelativeRel; |
| 919 | if (AIsRel != BIsRel) |
| 920 | return AIsRel; |
| 921 | |
| 922 | return A.getSymbol(Config->Mips64EL) < B.getSymbol(Config->Mips64EL); |
| 923 | } |
| 924 | |
| 925 | template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) { |
| 926 | uint8_t *BufBegin = Buf; |
| 927 | for (const DynamicReloc<ELFT> &Rel : Relocs) { |
| 928 | auto *P = reinterpret_cast<Elf_Rela *>(Buf); |
| 929 | Buf += Config->Rela ? sizeof(Elf_Rela) : sizeof(Elf_Rel); |
| 930 | |
| 931 | if (Config->Rela) |
| 932 | P->r_addend = Rel.getAddend(); |
| 933 | P->r_offset = Rel.getOffset(); |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 934 | if (Config->EMachine == EM_MIPS && Rel.getInputSec() == In<ELFT>::MipsGot) |
Eugene Leviant | a96d902 | 2016-11-16 10:02:27 +0000 | [diff] [blame] | 935 | // Dynamic relocation against MIPS GOT section make deal TLS entries |
| 936 | // allocated in the end of the GOT. We need to adjust the offset to take |
| 937 | // in account 'local' and 'global' GOT entries. |
Simon Atanasyan | b8bfec6 | 2016-11-17 21:49:14 +0000 | [diff] [blame] | 938 | P->r_offset += In<ELFT>::MipsGot->getTlsOffset(); |
Eugene Leviant | a96d902 | 2016-11-16 10:02:27 +0000 | [diff] [blame] | 939 | P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->Mips64EL); |
| 940 | } |
| 941 | |
| 942 | if (Sort) { |
| 943 | if (Config->Rela) |
| 944 | std::stable_sort((Elf_Rela *)BufBegin, |
| 945 | (Elf_Rela *)BufBegin + Relocs.size(), |
| 946 | compRelocations<ELFT, Elf_Rela>); |
| 947 | else |
| 948 | std::stable_sort((Elf_Rel *)BufBegin, (Elf_Rel *)BufBegin + Relocs.size(), |
| 949 | compRelocations<ELFT, Elf_Rel>); |
| 950 | } |
| 951 | } |
| 952 | |
| 953 | template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() { |
| 954 | return this->Entsize * Relocs.size(); |
| 955 | } |
| 956 | |
| 957 | template <class ELFT> void RelocationSection<ELFT>::finalize() { |
Eugene Leviant | 9230db9 | 2016-11-17 09:16:34 +0000 | [diff] [blame] | 958 | this->Link = In<ELFT>::DynSymTab ? In<ELFT>::DynSymTab->OutSec->SectionIndex |
| 959 | : In<ELFT>::SymTab->OutSec->SectionIndex; |
Eugene Leviant | a96d902 | 2016-11-16 10:02:27 +0000 | [diff] [blame] | 960 | |
| 961 | // Set required output section properties. |
| 962 | this->OutSec->Link = this->Link; |
| 963 | this->OutSec->Entsize = this->Entsize; |
| 964 | } |
| 965 | |
Eugene Leviant | 9230db9 | 2016-11-17 09:16:34 +0000 | [diff] [blame] | 966 | template <class ELFT> |
| 967 | SymbolTableSection<ELFT>::SymbolTableSection( |
| 968 | StringTableSection<ELFT> &StrTabSec) |
| 969 | : SyntheticSection<ELFT>(StrTabSec.isDynamic() ? (uintX_t)SHF_ALLOC : 0, |
| 970 | StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB, |
| 971 | sizeof(uintX_t), |
| 972 | StrTabSec.isDynamic() ? ".dynsym" : ".symtab"), |
| 973 | StrTabSec(StrTabSec) { |
| 974 | this->Entsize = sizeof(Elf_Sym); |
| 975 | } |
| 976 | |
| 977 | // Orders symbols according to their positions in the GOT, |
| 978 | // in compliance with MIPS ABI rules. |
| 979 | // See "Global Offset Table" in Chapter 5 in the following document |
| 980 | // for detailed description: |
| 981 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf |
| 982 | static bool sortMipsSymbols(const SymbolBody *L, const SymbolBody *R) { |
| 983 | // Sort entries related to non-local preemptible symbols by GOT indexes. |
| 984 | // All other entries go to the first part of GOT in arbitrary order. |
| 985 | bool LIsInLocalGot = !L->IsInGlobalMipsGot; |
| 986 | bool RIsInLocalGot = !R->IsInGlobalMipsGot; |
| 987 | if (LIsInLocalGot || RIsInLocalGot) |
| 988 | return !RIsInLocalGot; |
| 989 | return L->GotIndex < R->GotIndex; |
| 990 | } |
| 991 | |
| 992 | static uint8_t getSymbolBinding(SymbolBody *Body) { |
| 993 | Symbol *S = Body->symbol(); |
| 994 | if (Config->Relocatable) |
| 995 | return S->Binding; |
| 996 | uint8_t Visibility = S->Visibility; |
| 997 | if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) |
| 998 | return STB_LOCAL; |
| 999 | if (Config->NoGnuUnique && S->Binding == STB_GNU_UNIQUE) |
| 1000 | return STB_GLOBAL; |
| 1001 | return S->Binding; |
| 1002 | } |
| 1003 | |
| 1004 | template <class ELFT> void SymbolTableSection<ELFT>::finalize() { |
| 1005 | this->OutSec->Link = this->Link = StrTabSec.OutSec->SectionIndex; |
| 1006 | this->OutSec->Info = this->Info = NumLocals + 1; |
| 1007 | this->OutSec->Entsize = this->Entsize; |
| 1008 | |
| 1009 | if (Config->Relocatable) { |
| 1010 | size_t I = NumLocals; |
| 1011 | for (const SymbolTableEntry &S : Symbols) |
| 1012 | S.Symbol->DynsymIndex = ++I; |
| 1013 | return; |
| 1014 | } |
| 1015 | |
| 1016 | if (!StrTabSec.isDynamic()) { |
| 1017 | std::stable_sort(Symbols.begin(), Symbols.end(), |
| 1018 | [](const SymbolTableEntry &L, const SymbolTableEntry &R) { |
| 1019 | return getSymbolBinding(L.Symbol) == STB_LOCAL && |
| 1020 | getSymbolBinding(R.Symbol) != STB_LOCAL; |
| 1021 | }); |
| 1022 | return; |
| 1023 | } |
Eugene Leviant | be809a7 | 2016-11-18 06:44:18 +0000 | [diff] [blame] | 1024 | if (In<ELFT>::GnuHashTab) |
Eugene Leviant | 9230db9 | 2016-11-17 09:16:34 +0000 | [diff] [blame] | 1025 | // NB: It also sorts Symbols to meet the GNU hash table requirements. |
Eugene Leviant | be809a7 | 2016-11-18 06:44:18 +0000 | [diff] [blame] | 1026 | In<ELFT>::GnuHashTab->addSymbols(Symbols); |
Eugene Leviant | 9230db9 | 2016-11-17 09:16:34 +0000 | [diff] [blame] | 1027 | else if (Config->EMachine == EM_MIPS) |
| 1028 | std::stable_sort(Symbols.begin(), Symbols.end(), |
| 1029 | [](const SymbolTableEntry &L, const SymbolTableEntry &R) { |
| 1030 | return sortMipsSymbols(L.Symbol, R.Symbol); |
| 1031 | }); |
| 1032 | size_t I = 0; |
| 1033 | for (const SymbolTableEntry &S : Symbols) |
| 1034 | S.Symbol->DynsymIndex = ++I; |
| 1035 | } |
| 1036 | |
| 1037 | template <class ELFT> void SymbolTableSection<ELFT>::addSymbol(SymbolBody *B) { |
| 1038 | Symbols.push_back({B, StrTabSec.addString(B->getName(), false)}); |
| 1039 | } |
| 1040 | |
| 1041 | template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) { |
| 1042 | Buf += sizeof(Elf_Sym); |
| 1043 | |
| 1044 | // All symbols with STB_LOCAL binding precede the weak and global symbols. |
| 1045 | // .dynsym only contains global symbols. |
| 1046 | if (Config->Discard != DiscardPolicy::All && !StrTabSec.isDynamic()) |
| 1047 | writeLocalSymbols(Buf); |
| 1048 | |
| 1049 | writeGlobalSymbols(Buf); |
| 1050 | } |
| 1051 | |
| 1052 | template <class ELFT> |
| 1053 | void SymbolTableSection<ELFT>::writeLocalSymbols(uint8_t *&Buf) { |
| 1054 | // Iterate over all input object files to copy their local symbols |
| 1055 | // to the output symbol table pointed by Buf. |
| 1056 | for (ObjectFile<ELFT> *File : Symtab<ELFT>::X->getObjectFiles()) { |
| 1057 | for (const std::pair<const DefinedRegular<ELFT> *, size_t> &P : |
| 1058 | File->KeptLocalSyms) { |
| 1059 | const DefinedRegular<ELFT> &Body = *P.first; |
| 1060 | InputSectionBase<ELFT> *Section = Body.Section; |
| 1061 | auto *ESym = reinterpret_cast<Elf_Sym *>(Buf); |
| 1062 | |
| 1063 | if (!Section) { |
| 1064 | ESym->st_shndx = SHN_ABS; |
| 1065 | ESym->st_value = Body.Value; |
| 1066 | } else { |
| 1067 | const OutputSectionBase *OutSec = Section->OutSec; |
| 1068 | ESym->st_shndx = OutSec->SectionIndex; |
| 1069 | ESym->st_value = OutSec->Addr + Section->getOffset(Body); |
| 1070 | } |
| 1071 | ESym->st_name = P.second; |
| 1072 | ESym->st_size = Body.template getSize<ELFT>(); |
| 1073 | ESym->setBindingAndType(STB_LOCAL, Body.Type); |
| 1074 | Buf += sizeof(*ESym); |
| 1075 | } |
| 1076 | } |
| 1077 | } |
| 1078 | |
| 1079 | template <class ELFT> |
| 1080 | void SymbolTableSection<ELFT>::writeGlobalSymbols(uint8_t *Buf) { |
| 1081 | // Write the internal symbol table contents to the output symbol table |
| 1082 | // pointed by Buf. |
| 1083 | auto *ESym = reinterpret_cast<Elf_Sym *>(Buf); |
| 1084 | for (const SymbolTableEntry &S : Symbols) { |
| 1085 | SymbolBody *Body = S.Symbol; |
| 1086 | size_t StrOff = S.StrTabOffset; |
| 1087 | |
| 1088 | uint8_t Type = Body->Type; |
| 1089 | uintX_t Size = Body->getSize<ELFT>(); |
| 1090 | |
| 1091 | ESym->setBindingAndType(getSymbolBinding(Body), Type); |
| 1092 | ESym->st_size = Size; |
| 1093 | ESym->st_name = StrOff; |
| 1094 | ESym->setVisibility(Body->symbol()->Visibility); |
| 1095 | ESym->st_value = Body->getVA<ELFT>(); |
| 1096 | |
| 1097 | if (const OutputSectionBase *OutSec = getOutputSection(Body)) |
| 1098 | ESym->st_shndx = OutSec->SectionIndex; |
| 1099 | else if (isa<DefinedRegular<ELFT>>(Body)) |
| 1100 | ESym->st_shndx = SHN_ABS; |
| 1101 | |
| 1102 | if (Config->EMachine == EM_MIPS) { |
| 1103 | // On MIPS we need to mark symbol which has a PLT entry and requires |
| 1104 | // pointer equality by STO_MIPS_PLT flag. That is necessary to help |
| 1105 | // dynamic linker distinguish such symbols and MIPS lazy-binding stubs. |
| 1106 | // https://sourceware.org/ml/binutils/2008-07/txt00000.txt |
| 1107 | if (Body->isInPlt() && Body->NeedsCopyOrPltAddr) |
| 1108 | ESym->st_other |= STO_MIPS_PLT; |
| 1109 | if (Config->Relocatable) { |
| 1110 | auto *D = dyn_cast<DefinedRegular<ELFT>>(Body); |
| 1111 | if (D && D->isMipsPIC()) |
| 1112 | ESym->st_other |= STO_MIPS_PIC; |
| 1113 | } |
| 1114 | } |
| 1115 | ++ESym; |
| 1116 | } |
| 1117 | } |
| 1118 | |
| 1119 | template <class ELFT> |
| 1120 | const OutputSectionBase * |
| 1121 | SymbolTableSection<ELFT>::getOutputSection(SymbolBody *Sym) { |
| 1122 | switch (Sym->kind()) { |
| 1123 | case SymbolBody::DefinedSyntheticKind: |
| 1124 | return cast<DefinedSynthetic<ELFT>>(Sym)->Section; |
| 1125 | case SymbolBody::DefinedRegularKind: { |
| 1126 | auto &D = cast<DefinedRegular<ELFT>>(*Sym); |
| 1127 | if (D.Section) |
| 1128 | return D.Section->OutSec; |
| 1129 | break; |
| 1130 | } |
| 1131 | case SymbolBody::DefinedCommonKind: |
| 1132 | return In<ELFT>::Common->OutSec; |
| 1133 | case SymbolBody::SharedKind: |
| 1134 | if (cast<SharedSymbol<ELFT>>(Sym)->needsCopy()) |
| 1135 | return Out<ELFT>::Bss; |
| 1136 | break; |
| 1137 | case SymbolBody::UndefinedKind: |
| 1138 | case SymbolBody::LazyArchiveKind: |
| 1139 | case SymbolBody::LazyObjectKind: |
| 1140 | break; |
| 1141 | } |
| 1142 | return nullptr; |
| 1143 | } |
| 1144 | |
Eugene Leviant | be809a7 | 2016-11-18 06:44:18 +0000 | [diff] [blame] | 1145 | template <class ELFT> |
| 1146 | GnuHashTableSection<ELFT>::GnuHashTableSection() |
| 1147 | : SyntheticSection<ELFT>(SHF_ALLOC, SHT_GNU_HASH, sizeof(uintX_t), |
| 1148 | ".gnu.hash") { |
| 1149 | this->Entsize = ELFT::Is64Bits ? 0 : 4; |
| 1150 | } |
| 1151 | |
| 1152 | template <class ELFT> |
| 1153 | unsigned GnuHashTableSection<ELFT>::calcNBuckets(unsigned NumHashed) { |
| 1154 | if (!NumHashed) |
| 1155 | return 0; |
| 1156 | |
| 1157 | // These values are prime numbers which are not greater than 2^(N-1) + 1. |
| 1158 | // In result, for any particular NumHashed we return a prime number |
| 1159 | // which is not greater than NumHashed. |
| 1160 | static const unsigned Primes[] = { |
| 1161 | 1, 1, 3, 3, 7, 13, 31, 61, 127, 251, |
| 1162 | 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071}; |
| 1163 | |
| 1164 | return Primes[std::min<unsigned>(Log2_32_Ceil(NumHashed), |
| 1165 | array_lengthof(Primes) - 1)]; |
| 1166 | } |
| 1167 | |
| 1168 | // Bloom filter estimation: at least 8 bits for each hashed symbol. |
| 1169 | // GNU Hash table requirement: it should be a power of 2, |
| 1170 | // the minimum value is 1, even for an empty table. |
| 1171 | // Expected results for a 32-bit target: |
| 1172 | // calcMaskWords(0..4) = 1 |
| 1173 | // calcMaskWords(5..8) = 2 |
| 1174 | // calcMaskWords(9..16) = 4 |
| 1175 | // For a 64-bit target: |
| 1176 | // calcMaskWords(0..8) = 1 |
| 1177 | // calcMaskWords(9..16) = 2 |
| 1178 | // calcMaskWords(17..32) = 4 |
| 1179 | template <class ELFT> |
| 1180 | unsigned GnuHashTableSection<ELFT>::calcMaskWords(unsigned NumHashed) { |
| 1181 | if (!NumHashed) |
| 1182 | return 1; |
| 1183 | return NextPowerOf2((NumHashed - 1) / sizeof(Elf_Off)); |
| 1184 | } |
| 1185 | |
| 1186 | template <class ELFT> void GnuHashTableSection<ELFT>::finalize() { |
| 1187 | unsigned NumHashed = Symbols.size(); |
| 1188 | NBuckets = calcNBuckets(NumHashed); |
| 1189 | MaskWords = calcMaskWords(NumHashed); |
| 1190 | // Second hash shift estimation: just predefined values. |
| 1191 | Shift2 = ELFT::Is64Bits ? 6 : 5; |
| 1192 | |
| 1193 | this->OutSec->Entsize = this->Entsize; |
| 1194 | this->OutSec->Link = this->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex; |
| 1195 | this->Size = sizeof(Elf_Word) * 4 // Header |
| 1196 | + sizeof(Elf_Off) * MaskWords // Bloom Filter |
| 1197 | + sizeof(Elf_Word) * NBuckets // Hash Buckets |
| 1198 | + sizeof(Elf_Word) * NumHashed; // Hash Values |
| 1199 | } |
| 1200 | |
| 1201 | template <class ELFT> void GnuHashTableSection<ELFT>::writeTo(uint8_t *Buf) { |
| 1202 | writeHeader(Buf); |
| 1203 | if (Symbols.empty()) |
| 1204 | return; |
| 1205 | writeBloomFilter(Buf); |
| 1206 | writeHashTable(Buf); |
| 1207 | } |
| 1208 | |
| 1209 | template <class ELFT> |
| 1210 | void GnuHashTableSection<ELFT>::writeHeader(uint8_t *&Buf) { |
| 1211 | auto *P = reinterpret_cast<Elf_Word *>(Buf); |
| 1212 | *P++ = NBuckets; |
| 1213 | *P++ = In<ELFT>::DynSymTab->getNumSymbols() - Symbols.size(); |
| 1214 | *P++ = MaskWords; |
| 1215 | *P++ = Shift2; |
| 1216 | Buf = reinterpret_cast<uint8_t *>(P); |
| 1217 | } |
| 1218 | |
| 1219 | template <class ELFT> |
| 1220 | void GnuHashTableSection<ELFT>::writeBloomFilter(uint8_t *&Buf) { |
| 1221 | unsigned C = sizeof(Elf_Off) * 8; |
| 1222 | |
| 1223 | auto *Masks = reinterpret_cast<Elf_Off *>(Buf); |
| 1224 | for (const SymbolData &Sym : Symbols) { |
| 1225 | size_t Pos = (Sym.Hash / C) & (MaskWords - 1); |
| 1226 | uintX_t V = (uintX_t(1) << (Sym.Hash % C)) | |
| 1227 | (uintX_t(1) << ((Sym.Hash >> Shift2) % C)); |
| 1228 | Masks[Pos] |= V; |
| 1229 | } |
| 1230 | Buf += sizeof(Elf_Off) * MaskWords; |
| 1231 | } |
| 1232 | |
| 1233 | template <class ELFT> |
| 1234 | void GnuHashTableSection<ELFT>::writeHashTable(uint8_t *Buf) { |
| 1235 | Elf_Word *Buckets = reinterpret_cast<Elf_Word *>(Buf); |
| 1236 | Elf_Word *Values = Buckets + NBuckets; |
| 1237 | |
| 1238 | int PrevBucket = -1; |
| 1239 | int I = 0; |
| 1240 | for (const SymbolData &Sym : Symbols) { |
| 1241 | int Bucket = Sym.Hash % NBuckets; |
| 1242 | assert(PrevBucket <= Bucket); |
| 1243 | if (Bucket != PrevBucket) { |
| 1244 | Buckets[Bucket] = Sym.Body->DynsymIndex; |
| 1245 | PrevBucket = Bucket; |
| 1246 | if (I > 0) |
| 1247 | Values[I - 1] |= 1; |
| 1248 | } |
| 1249 | Values[I] = Sym.Hash & ~1; |
| 1250 | ++I; |
| 1251 | } |
| 1252 | if (I > 0) |
| 1253 | Values[I - 1] |= 1; |
| 1254 | } |
| 1255 | |
| 1256 | static uint32_t hashGnu(StringRef Name) { |
| 1257 | uint32_t H = 5381; |
| 1258 | for (uint8_t C : Name) |
| 1259 | H = (H << 5) + H + C; |
| 1260 | return H; |
| 1261 | } |
| 1262 | |
| 1263 | // Add symbols to this symbol hash table. Note that this function |
| 1264 | // destructively sort a given vector -- which is needed because |
| 1265 | // GNU-style hash table places some sorting requirements. |
| 1266 | template <class ELFT> |
| 1267 | void GnuHashTableSection<ELFT>::addSymbols(std::vector<SymbolTableEntry> &V) { |
| 1268 | // Ideally this will just be 'auto' but GCC 6.1 is not able |
| 1269 | // to deduce it correctly. |
| 1270 | std::vector<SymbolTableEntry>::iterator Mid = |
| 1271 | std::stable_partition(V.begin(), V.end(), [](const SymbolTableEntry &S) { |
| 1272 | return S.Symbol->isUndefined(); |
| 1273 | }); |
| 1274 | if (Mid == V.end()) |
| 1275 | return; |
| 1276 | for (auto I = Mid, E = V.end(); I != E; ++I) { |
| 1277 | SymbolBody *B = I->Symbol; |
| 1278 | size_t StrOff = I->StrTabOffset; |
| 1279 | Symbols.push_back({B, StrOff, hashGnu(B->getName())}); |
| 1280 | } |
| 1281 | |
| 1282 | unsigned NBuckets = calcNBuckets(Symbols.size()); |
| 1283 | std::stable_sort(Symbols.begin(), Symbols.end(), |
| 1284 | [&](const SymbolData &L, const SymbolData &R) { |
| 1285 | return L.Hash % NBuckets < R.Hash % NBuckets; |
| 1286 | }); |
| 1287 | |
| 1288 | V.erase(Mid, V.end()); |
| 1289 | for (const SymbolData &Sym : Symbols) |
| 1290 | V.push_back({Sym.Body, Sym.STName}); |
| 1291 | } |
| 1292 | |
Eugene Leviant | b96e809 | 2016-11-18 09:06:47 +0000 | [diff] [blame] | 1293 | template <class ELFT> |
| 1294 | HashTableSection<ELFT>::HashTableSection() |
| 1295 | : SyntheticSection<ELFT>(SHF_ALLOC, SHT_HASH, sizeof(Elf_Word), ".hash") { |
| 1296 | this->Entsize = sizeof(Elf_Word); |
| 1297 | } |
| 1298 | |
| 1299 | template <class ELFT> void HashTableSection<ELFT>::finalize() { |
| 1300 | this->OutSec->Link = this->Link = In<ELFT>::DynSymTab->OutSec->SectionIndex; |
| 1301 | this->OutSec->Entsize = this->Entsize; |
| 1302 | |
| 1303 | unsigned NumEntries = 2; // nbucket and nchain. |
| 1304 | NumEntries += In<ELFT>::DynSymTab->getNumSymbols(); // The chain entries. |
| 1305 | |
| 1306 | // Create as many buckets as there are symbols. |
| 1307 | // FIXME: This is simplistic. We can try to optimize it, but implementing |
| 1308 | // support for SHT_GNU_HASH is probably even more profitable. |
| 1309 | NumEntries += In<ELFT>::DynSymTab->getNumSymbols(); |
| 1310 | this->Size = NumEntries * sizeof(Elf_Word); |
| 1311 | } |
| 1312 | |
| 1313 | template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) { |
| 1314 | unsigned NumSymbols = In<ELFT>::DynSymTab->getNumSymbols(); |
| 1315 | auto *P = reinterpret_cast<Elf_Word *>(Buf); |
| 1316 | *P++ = NumSymbols; // nbucket |
| 1317 | *P++ = NumSymbols; // nchain |
| 1318 | |
| 1319 | Elf_Word *Buckets = P; |
| 1320 | Elf_Word *Chains = P + NumSymbols; |
| 1321 | |
| 1322 | for (const SymbolTableEntry &S : In<ELFT>::DynSymTab->getSymbols()) { |
| 1323 | SymbolBody *Body = S.Symbol; |
| 1324 | StringRef Name = Body->getName(); |
| 1325 | unsigned I = Body->DynsymIndex; |
| 1326 | uint32_t Hash = hashSysV(Name) % NumSymbols; |
| 1327 | Chains[I] = Buckets[Hash]; |
| 1328 | Buckets[Hash] = I; |
| 1329 | } |
| 1330 | } |
| 1331 | |
Eugene Leviant | ff23d3e | 2016-11-18 14:35:03 +0000 | [diff] [blame^] | 1332 | template <class ELFT> |
| 1333 | PltSection<ELFT>::PltSection() |
| 1334 | : SyntheticSection<ELFT>(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, |
| 1335 | ".plt") {} |
| 1336 | |
| 1337 | template <class ELFT> void PltSection<ELFT>::writeTo(uint8_t *Buf) { |
| 1338 | // At beginning of PLT, we have code to call the dynamic linker |
| 1339 | // to resolve dynsyms at runtime. Write such code. |
| 1340 | Target->writePltHeader(Buf); |
| 1341 | size_t Off = Target->PltHeaderSize; |
| 1342 | |
| 1343 | for (auto &I : Entries) { |
| 1344 | const SymbolBody *B = I.first; |
| 1345 | unsigned RelOff = I.second; |
| 1346 | uint64_t Got = B->getGotPltVA<ELFT>(); |
| 1347 | uint64_t Plt = this->getVA() + Off; |
| 1348 | Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff); |
| 1349 | Off += Target->PltEntrySize; |
| 1350 | } |
| 1351 | } |
| 1352 | |
| 1353 | template <class ELFT> void PltSection<ELFT>::addEntry(SymbolBody &Sym) { |
| 1354 | Sym.PltIndex = Entries.size(); |
| 1355 | unsigned RelOff = In<ELFT>::RelaPlt->getRelocOffset(); |
| 1356 | Entries.push_back(std::make_pair(&Sym, RelOff)); |
| 1357 | } |
| 1358 | |
| 1359 | template <class ELFT> size_t PltSection<ELFT>::getSize() const { |
| 1360 | return Target->PltHeaderSize + Entries.size() * Target->PltEntrySize; |
| 1361 | } |
| 1362 | |
Rafael Espindola | 682a5bc | 2016-11-08 14:42:34 +0000 | [diff] [blame] | 1363 | template InputSection<ELF32LE> *elf::createCommonSection(); |
| 1364 | template InputSection<ELF32BE> *elf::createCommonSection(); |
| 1365 | template InputSection<ELF64LE> *elf::createCommonSection(); |
| 1366 | template InputSection<ELF64BE> *elf::createCommonSection(); |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 1367 | |
Rafael Espindola | c0e47fb | 2016-11-08 14:56:27 +0000 | [diff] [blame] | 1368 | template InputSection<ELF32LE> *elf::createInterpSection(); |
| 1369 | template InputSection<ELF32BE> *elf::createInterpSection(); |
| 1370 | template InputSection<ELF64LE> *elf::createInterpSection(); |
| 1371 | template InputSection<ELF64BE> *elf::createInterpSection(); |
Rui Ueyama | e288eef | 2016-11-02 18:58:44 +0000 | [diff] [blame] | 1372 | |
Rui Ueyama | 3da3f06 | 2016-11-10 20:20:37 +0000 | [diff] [blame] | 1373 | template MergeInputSection<ELF32LE> *elf::createCommentSection(); |
| 1374 | template MergeInputSection<ELF32BE> *elf::createCommentSection(); |
| 1375 | template MergeInputSection<ELF64LE> *elf::createCommentSection(); |
| 1376 | template MergeInputSection<ELF64BE> *elf::createCommentSection(); |
| 1377 | |
Simon Atanasyan | fa03b0f | 2016-11-09 21:37:06 +0000 | [diff] [blame] | 1378 | template class elf::MipsAbiFlagsSection<ELF32LE>; |
| 1379 | template class elf::MipsAbiFlagsSection<ELF32BE>; |
| 1380 | template class elf::MipsAbiFlagsSection<ELF64LE>; |
| 1381 | template class elf::MipsAbiFlagsSection<ELF64BE>; |
| 1382 | |
Simon Atanasyan | ce02cf0 | 2016-11-09 21:36:56 +0000 | [diff] [blame] | 1383 | template class elf::MipsOptionsSection<ELF32LE>; |
| 1384 | template class elf::MipsOptionsSection<ELF32BE>; |
| 1385 | template class elf::MipsOptionsSection<ELF64LE>; |
| 1386 | template class elf::MipsOptionsSection<ELF64BE>; |
| 1387 | |
| 1388 | template class elf::MipsReginfoSection<ELF32LE>; |
| 1389 | template class elf::MipsReginfoSection<ELF32BE>; |
| 1390 | template class elf::MipsReginfoSection<ELF64LE>; |
| 1391 | template class elf::MipsReginfoSection<ELF64BE>; |
| 1392 | |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 1393 | template class elf::BuildIdSection<ELF32LE>; |
| 1394 | template class elf::BuildIdSection<ELF32BE>; |
| 1395 | template class elf::BuildIdSection<ELF64LE>; |
| 1396 | template class elf::BuildIdSection<ELF64BE>; |
| 1397 | |
| 1398 | template class elf::BuildIdFastHash<ELF32LE>; |
| 1399 | template class elf::BuildIdFastHash<ELF32BE>; |
| 1400 | template class elf::BuildIdFastHash<ELF64LE>; |
| 1401 | template class elf::BuildIdFastHash<ELF64BE>; |
| 1402 | |
| 1403 | template class elf::BuildIdMd5<ELF32LE>; |
| 1404 | template class elf::BuildIdMd5<ELF32BE>; |
| 1405 | template class elf::BuildIdMd5<ELF64LE>; |
| 1406 | template class elf::BuildIdMd5<ELF64BE>; |
| 1407 | |
| 1408 | template class elf::BuildIdSha1<ELF32LE>; |
| 1409 | template class elf::BuildIdSha1<ELF32BE>; |
| 1410 | template class elf::BuildIdSha1<ELF64LE>; |
| 1411 | template class elf::BuildIdSha1<ELF64BE>; |
| 1412 | |
| 1413 | template class elf::BuildIdUuid<ELF32LE>; |
| 1414 | template class elf::BuildIdUuid<ELF32BE>; |
| 1415 | template class elf::BuildIdUuid<ELF64LE>; |
| 1416 | template class elf::BuildIdUuid<ELF64BE>; |
| 1417 | |
| 1418 | template class elf::BuildIdHexstring<ELF32LE>; |
| 1419 | template class elf::BuildIdHexstring<ELF32BE>; |
| 1420 | template class elf::BuildIdHexstring<ELF64LE>; |
| 1421 | template class elf::BuildIdHexstring<ELF64BE>; |
Eugene Leviant | 41ca327 | 2016-11-10 09:48:29 +0000 | [diff] [blame] | 1422 | |
Eugene Leviant | ad4439e | 2016-11-11 11:33:32 +0000 | [diff] [blame] | 1423 | template class elf::GotSection<ELF32LE>; |
| 1424 | template class elf::GotSection<ELF32BE>; |
| 1425 | template class elf::GotSection<ELF64LE>; |
| 1426 | template class elf::GotSection<ELF64BE>; |
| 1427 | |
Simon Atanasyan | 725dc14 | 2016-11-16 21:01:02 +0000 | [diff] [blame] | 1428 | template class elf::MipsGotSection<ELF32LE>; |
| 1429 | template class elf::MipsGotSection<ELF32BE>; |
| 1430 | template class elf::MipsGotSection<ELF64LE>; |
| 1431 | template class elf::MipsGotSection<ELF64BE>; |
| 1432 | |
Eugene Leviant | 41ca327 | 2016-11-10 09:48:29 +0000 | [diff] [blame] | 1433 | template class elf::GotPltSection<ELF32LE>; |
| 1434 | template class elf::GotPltSection<ELF32BE>; |
| 1435 | template class elf::GotPltSection<ELF64LE>; |
| 1436 | template class elf::GotPltSection<ELF64BE>; |
Eugene Leviant | 22eb026 | 2016-11-14 09:16:00 +0000 | [diff] [blame] | 1437 | |
| 1438 | template class elf::StringTableSection<ELF32LE>; |
| 1439 | template class elf::StringTableSection<ELF32BE>; |
| 1440 | template class elf::StringTableSection<ELF64LE>; |
| 1441 | template class elf::StringTableSection<ELF64BE>; |
Eugene Leviant | 6380ce2 | 2016-11-15 12:26:55 +0000 | [diff] [blame] | 1442 | |
| 1443 | template class elf::DynamicSection<ELF32LE>; |
| 1444 | template class elf::DynamicSection<ELF32BE>; |
| 1445 | template class elf::DynamicSection<ELF64LE>; |
| 1446 | template class elf::DynamicSection<ELF64BE>; |
Eugene Leviant | a96d902 | 2016-11-16 10:02:27 +0000 | [diff] [blame] | 1447 | |
| 1448 | template class elf::RelocationSection<ELF32LE>; |
| 1449 | template class elf::RelocationSection<ELF32BE>; |
| 1450 | template class elf::RelocationSection<ELF64LE>; |
| 1451 | template class elf::RelocationSection<ELF64BE>; |
Eugene Leviant | 9230db9 | 2016-11-17 09:16:34 +0000 | [diff] [blame] | 1452 | |
| 1453 | template class elf::SymbolTableSection<ELF32LE>; |
| 1454 | template class elf::SymbolTableSection<ELF32BE>; |
| 1455 | template class elf::SymbolTableSection<ELF64LE>; |
| 1456 | template class elf::SymbolTableSection<ELF64BE>; |
Eugene Leviant | be809a7 | 2016-11-18 06:44:18 +0000 | [diff] [blame] | 1457 | |
| 1458 | template class elf::GnuHashTableSection<ELF32LE>; |
| 1459 | template class elf::GnuHashTableSection<ELF32BE>; |
| 1460 | template class elf::GnuHashTableSection<ELF64LE>; |
| 1461 | template class elf::GnuHashTableSection<ELF64BE>; |
Eugene Leviant | b96e809 | 2016-11-18 09:06:47 +0000 | [diff] [blame] | 1462 | |
| 1463 | template class elf::HashTableSection<ELF32LE>; |
| 1464 | template class elf::HashTableSection<ELF32BE>; |
| 1465 | template class elf::HashTableSection<ELF64LE>; |
| 1466 | template class elf::HashTableSection<ELF64BE>; |
Eugene Leviant | ff23d3e | 2016-11-18 14:35:03 +0000 | [diff] [blame^] | 1467 | |
| 1468 | template class elf::PltSection<ELF32LE>; |
| 1469 | template class elf::PltSection<ELF32BE>; |
| 1470 | template class elf::PltSection<ELF64LE>; |
| 1471 | template class elf::PltSection<ELF64BE>; |