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" |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 25 | |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 26 | #include "lld/Core/Parallel.h" |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 27 | #include "llvm/Support/Endian.h" |
| 28 | #include "llvm/Support/MD5.h" |
| 29 | #include "llvm/Support/RandomNumberGenerator.h" |
| 30 | #include "llvm/Support/SHA1.h" |
| 31 | #include "llvm/Support/xxhash.h" |
| 32 | |
| 33 | using namespace llvm; |
| 34 | using namespace llvm::ELF; |
| 35 | using namespace llvm::object; |
| 36 | using namespace llvm::support; |
| 37 | using namespace llvm::support::endian; |
| 38 | |
| 39 | using namespace lld; |
| 40 | using namespace lld::elf; |
| 41 | |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 42 | template <class ELFT> static std::vector<DefinedCommon *> getCommonSymbols() { |
| 43 | std::vector<DefinedCommon *> V; |
| 44 | for (Symbol *S : Symtab<ELFT>::X->getSymbols()) |
| 45 | if (auto *B = dyn_cast<DefinedCommon>(S->body())) |
| 46 | V.push_back(B); |
| 47 | return V; |
| 48 | } |
| 49 | |
| 50 | // Find all common symbols and allocate space for them. |
Rafael Espindola | 682a5bc | 2016-11-08 14:42:34 +0000 | [diff] [blame] | 51 | template <class ELFT> InputSection<ELFT> *elf::createCommonSection() { |
| 52 | auto *Ret = make<InputSection<ELFT>>(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, 1, |
| 53 | ArrayRef<uint8_t>(), "COMMON"); |
| 54 | Ret->Live = true; |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 55 | |
| 56 | // Sort the common symbols by alignment as an heuristic to pack them better. |
| 57 | std::vector<DefinedCommon *> Syms = getCommonSymbols<ELFT>(); |
| 58 | std::stable_sort(Syms.begin(), Syms.end(), |
| 59 | [](const DefinedCommon *A, const DefinedCommon *B) { |
| 60 | return A->Alignment > B->Alignment; |
| 61 | }); |
| 62 | |
| 63 | // Assign offsets to symbols. |
| 64 | size_t Size = 0; |
| 65 | size_t Alignment = 1; |
| 66 | for (DefinedCommon *Sym : Syms) { |
Rui Ueyama | 1c78682 | 2016-11-05 23:14:54 +0000 | [diff] [blame] | 67 | Alignment = std::max<size_t>(Alignment, Sym->Alignment); |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 68 | Size = alignTo(Size, Sym->Alignment); |
| 69 | |
| 70 | // Compute symbol offset relative to beginning of input section. |
| 71 | Sym->Offset = Size; |
| 72 | Size += Sym->Size; |
| 73 | } |
Rafael Espindola | 682a5bc | 2016-11-08 14:42:34 +0000 | [diff] [blame] | 74 | Ret->Alignment = Alignment; |
| 75 | Ret->Data = makeArrayRef<uint8_t>(nullptr, Size); |
| 76 | return Ret; |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 77 | } |
| 78 | |
Rui Ueyama | e288eef | 2016-11-02 18:58:44 +0000 | [diff] [blame] | 79 | static ArrayRef<uint8_t> createInterp() { |
| 80 | // StringSaver guarantees that the returned string ends with '\0'. |
| 81 | StringRef S = Saver.save(Config->DynamicLinker); |
Rui Ueyama | 6294a24 | 2016-11-04 17:41:29 +0000 | [diff] [blame] | 82 | return {(const uint8_t *)S.data(), S.size() + 1}; |
Rui Ueyama | e288eef | 2016-11-02 18:58:44 +0000 | [diff] [blame] | 83 | } |
| 84 | |
Rafael Espindola | c0e47fb | 2016-11-08 14:56:27 +0000 | [diff] [blame] | 85 | template <class ELFT> InputSection<ELFT> *elf::createInterpSection() { |
| 86 | auto *Ret = make<InputSection<ELFT>>(SHF_ALLOC, SHT_PROGBITS, 1, |
| 87 | createInterp(), ".interp"); |
| 88 | Ret->Live = true; |
| 89 | return Ret; |
Rui Ueyama | a9ee8d6 | 2016-11-04 22:25:39 +0000 | [diff] [blame] | 90 | } |
Rui Ueyama | e288eef | 2016-11-02 18:58:44 +0000 | [diff] [blame] | 91 | |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 92 | template <class ELFT> |
| 93 | BuildIdSection<ELFT>::BuildIdSection(size_t HashSize) |
| 94 | : InputSection<ELFT>(SHF_ALLOC, SHT_NOTE, 1, ArrayRef<uint8_t>(), |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 95 | ".note.gnu.build-id"), |
| 96 | HashSize(HashSize) { |
Rui Ueyama | a9ee8d6 | 2016-11-04 22:25:39 +0000 | [diff] [blame] | 97 | this->Live = true; |
| 98 | |
Rafael Espindola | 1a54112 | 2016-11-08 14:47:16 +0000 | [diff] [blame] | 99 | Buf.resize(16 + HashSize); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 100 | const endianness E = ELFT::TargetEndianness; |
Rafael Espindola | 1a54112 | 2016-11-08 14:47:16 +0000 | [diff] [blame] | 101 | write32<E>(Buf.data(), 4); // Name size |
| 102 | write32<E>(Buf.data() + 4, HashSize); // Content size |
| 103 | write32<E>(Buf.data() + 8, NT_GNU_BUILD_ID); // Type |
| 104 | memcpy(Buf.data() + 12, "GNU", 4); // Name string |
| 105 | this->Data = ArrayRef<uint8_t>(Buf); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 106 | } |
| 107 | |
| 108 | template <class ELFT> |
| 109 | uint8_t *BuildIdSection<ELFT>::getOutputLoc(uint8_t *Start) const { |
Rafael Espindola | 04a2e34 | 2016-11-09 01:42:41 +0000 | [diff] [blame] | 110 | return Start + this->OutSec->Offset + this->OutSecOff; |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 111 | } |
| 112 | |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 113 | static std::vector<ArrayRef<uint8_t>> split(ArrayRef<uint8_t> Arr, |
| 114 | size_t ChunkSize) { |
| 115 | std::vector<ArrayRef<uint8_t>> Ret; |
| 116 | while (Arr.size() > ChunkSize) { |
| 117 | Ret.push_back(Arr.take_front(ChunkSize)); |
| 118 | Arr = Arr.drop_front(ChunkSize); |
| 119 | } |
| 120 | if (!Arr.empty()) |
| 121 | Ret.push_back(Arr); |
| 122 | return Ret; |
| 123 | } |
| 124 | |
| 125 | template <class ELFT> |
| 126 | void BuildIdSection<ELFT>::computeHash( |
George Rimar | 828787a | 2016-11-06 08:39:46 +0000 | [diff] [blame] | 127 | llvm::MutableArrayRef<uint8_t> Data, |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 128 | std::function<void(ArrayRef<uint8_t> Arr, uint8_t *Hash)> Hash) { |
| 129 | std::vector<ArrayRef<uint8_t>> Chunks = split(Data, 1024 * 1024); |
| 130 | std::vector<uint8_t> HashList(Chunks.size() * HashSize); |
| 131 | |
| 132 | if (Config->Threads) |
| 133 | parallel_for_each(Chunks.begin(), Chunks.end(), |
| 134 | [&](ArrayRef<uint8_t> &Chunk) { |
| 135 | size_t Id = &Chunk - Chunks.data(); |
| 136 | Hash(Chunk, HashList.data() + Id * HashSize); |
| 137 | }); |
| 138 | else |
| 139 | std::for_each(Chunks.begin(), Chunks.end(), [&](ArrayRef<uint8_t> &Chunk) { |
| 140 | size_t Id = &Chunk - Chunks.data(); |
| 141 | Hash(Chunk, HashList.data() + Id * HashSize); |
| 142 | }); |
| 143 | |
George Rimar | 828787a | 2016-11-06 08:39:46 +0000 | [diff] [blame] | 144 | Hash(HashList, this->getOutputLoc(Data.begin()) + 16); |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 145 | } |
| 146 | |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 147 | template <class ELFT> |
| 148 | void BuildIdFastHash<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
George Rimar | 5020971 | 2016-11-06 08:26:53 +0000 | [diff] [blame] | 149 | this->computeHash(Buf, [](ArrayRef<uint8_t> Arr, uint8_t *Dest) { |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 150 | uint64_t Hash = xxHash64(toStringRef(Arr)); |
| 151 | write64<ELFT::TargetEndianness>(Dest, Hash); |
| 152 | }); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 153 | } |
| 154 | |
| 155 | template <class ELFT> |
| 156 | void BuildIdMd5<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
George Rimar | 5020971 | 2016-11-06 08:26:53 +0000 | [diff] [blame] | 157 | this->computeHash(Buf, [&](ArrayRef<uint8_t> Arr, uint8_t *Dest) { |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 158 | MD5 Hash; |
| 159 | Hash.update(Arr); |
| 160 | MD5::MD5Result Res; |
| 161 | Hash.final(Res); |
George Rimar | 5020971 | 2016-11-06 08:26:53 +0000 | [diff] [blame] | 162 | memcpy(Dest, Res, this->HashSize); |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 163 | }); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 164 | } |
| 165 | |
| 166 | template <class ELFT> |
| 167 | void BuildIdSha1<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
George Rimar | 5020971 | 2016-11-06 08:26:53 +0000 | [diff] [blame] | 168 | this->computeHash(Buf, [&](ArrayRef<uint8_t> Arr, uint8_t *Dest) { |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 169 | SHA1 Hash; |
| 170 | Hash.update(Arr); |
George Rimar | 5020971 | 2016-11-06 08:26:53 +0000 | [diff] [blame] | 171 | memcpy(Dest, Hash.final().data(), this->HashSize); |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 172 | }); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 173 | } |
| 174 | |
| 175 | template <class ELFT> |
| 176 | void BuildIdUuid<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
| 177 | if (getRandomBytes(this->getOutputLoc(Buf.begin()) + 16, 16)) |
| 178 | error("entropy source failure"); |
| 179 | } |
| 180 | |
| 181 | template <class ELFT> |
| 182 | BuildIdHexstring<ELFT>::BuildIdHexstring() |
| 183 | : BuildIdSection<ELFT>(Config->BuildIdVector.size()) {} |
| 184 | |
| 185 | template <class ELFT> |
| 186 | void BuildIdHexstring<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
| 187 | memcpy(this->getOutputLoc(Buf.begin()) + 16, Config->BuildIdVector.data(), |
| 188 | Config->BuildIdVector.size()); |
| 189 | } |
| 190 | |
Rafael Espindola | 682a5bc | 2016-11-08 14:42:34 +0000 | [diff] [blame] | 191 | template InputSection<ELF32LE> *elf::createCommonSection(); |
| 192 | template InputSection<ELF32BE> *elf::createCommonSection(); |
| 193 | template InputSection<ELF64LE> *elf::createCommonSection(); |
| 194 | template InputSection<ELF64BE> *elf::createCommonSection(); |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 195 | |
Rafael Espindola | c0e47fb | 2016-11-08 14:56:27 +0000 | [diff] [blame] | 196 | template InputSection<ELF32LE> *elf::createInterpSection(); |
| 197 | template InputSection<ELF32BE> *elf::createInterpSection(); |
| 198 | template InputSection<ELF64LE> *elf::createInterpSection(); |
| 199 | template InputSection<ELF64BE> *elf::createInterpSection(); |
Rui Ueyama | e288eef | 2016-11-02 18:58:44 +0000 | [diff] [blame] | 200 | |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 201 | template class elf::BuildIdSection<ELF32LE>; |
| 202 | template class elf::BuildIdSection<ELF32BE>; |
| 203 | template class elf::BuildIdSection<ELF64LE>; |
| 204 | template class elf::BuildIdSection<ELF64BE>; |
| 205 | |
| 206 | template class elf::BuildIdFastHash<ELF32LE>; |
| 207 | template class elf::BuildIdFastHash<ELF32BE>; |
| 208 | template class elf::BuildIdFastHash<ELF64LE>; |
| 209 | template class elf::BuildIdFastHash<ELF64BE>; |
| 210 | |
| 211 | template class elf::BuildIdMd5<ELF32LE>; |
| 212 | template class elf::BuildIdMd5<ELF32BE>; |
| 213 | template class elf::BuildIdMd5<ELF64LE>; |
| 214 | template class elf::BuildIdMd5<ELF64BE>; |
| 215 | |
| 216 | template class elf::BuildIdSha1<ELF32LE>; |
| 217 | template class elf::BuildIdSha1<ELF32BE>; |
| 218 | template class elf::BuildIdSha1<ELF64LE>; |
| 219 | template class elf::BuildIdSha1<ELF64BE>; |
| 220 | |
| 221 | template class elf::BuildIdUuid<ELF32LE>; |
| 222 | template class elf::BuildIdUuid<ELF32BE>; |
| 223 | template class elf::BuildIdUuid<ELF64LE>; |
| 224 | template class elf::BuildIdUuid<ELF64BE>; |
| 225 | |
| 226 | template class elf::BuildIdHexstring<ELF32LE>; |
| 227 | template class elf::BuildIdHexstring<ELF32BE>; |
| 228 | template class elf::BuildIdHexstring<ELF64LE>; |
| 229 | template class elf::BuildIdHexstring<ELF64BE>; |