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" |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 26 | |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 27 | #include "lld/Core/Parallel.h" |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 28 | #include "llvm/Support/Endian.h" |
| 29 | #include "llvm/Support/MD5.h" |
| 30 | #include "llvm/Support/RandomNumberGenerator.h" |
| 31 | #include "llvm/Support/SHA1.h" |
| 32 | #include "llvm/Support/xxhash.h" |
| 33 | |
| 34 | using namespace llvm; |
| 35 | using namespace llvm::ELF; |
| 36 | using namespace llvm::object; |
| 37 | using namespace llvm::support; |
| 38 | using namespace llvm::support::endian; |
| 39 | |
| 40 | using namespace lld; |
| 41 | using namespace lld::elf; |
| 42 | |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 43 | template <class ELFT> static std::vector<DefinedCommon *> getCommonSymbols() { |
| 44 | std::vector<DefinedCommon *> V; |
| 45 | for (Symbol *S : Symtab<ELFT>::X->getSymbols()) |
| 46 | if (auto *B = dyn_cast<DefinedCommon>(S->body())) |
| 47 | V.push_back(B); |
| 48 | return V; |
| 49 | } |
| 50 | |
| 51 | // Find all common symbols and allocate space for them. |
Rafael Espindola | 682a5bc | 2016-11-08 14:42:34 +0000 | [diff] [blame] | 52 | template <class ELFT> InputSection<ELFT> *elf::createCommonSection() { |
| 53 | auto *Ret = make<InputSection<ELFT>>(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, 1, |
| 54 | ArrayRef<uint8_t>(), "COMMON"); |
| 55 | Ret->Live = true; |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 56 | |
| 57 | // Sort the common symbols by alignment as an heuristic to pack them better. |
| 58 | std::vector<DefinedCommon *> Syms = getCommonSymbols<ELFT>(); |
| 59 | std::stable_sort(Syms.begin(), Syms.end(), |
| 60 | [](const DefinedCommon *A, const DefinedCommon *B) { |
| 61 | return A->Alignment > B->Alignment; |
| 62 | }); |
| 63 | |
| 64 | // Assign offsets to symbols. |
| 65 | size_t Size = 0; |
| 66 | size_t Alignment = 1; |
| 67 | for (DefinedCommon *Sym : Syms) { |
Rui Ueyama | 1c78682 | 2016-11-05 23:14:54 +0000 | [diff] [blame] | 68 | Alignment = std::max<size_t>(Alignment, Sym->Alignment); |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 69 | Size = alignTo(Size, Sym->Alignment); |
| 70 | |
| 71 | // Compute symbol offset relative to beginning of input section. |
| 72 | Sym->Offset = Size; |
| 73 | Size += Sym->Size; |
| 74 | } |
Rafael Espindola | 682a5bc | 2016-11-08 14:42:34 +0000 | [diff] [blame] | 75 | Ret->Alignment = Alignment; |
| 76 | Ret->Data = makeArrayRef<uint8_t>(nullptr, Size); |
| 77 | return Ret; |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 78 | } |
| 79 | |
Simon Atanasyan | ce02cf0 | 2016-11-09 21:36:56 +0000 | [diff] [blame^] | 80 | // Iterate over sections of the specified type. For each section call |
| 81 | // provided function. After that "kill" the section by turning off |
| 82 | // "Live" flag, so that they won't be included in the final output. |
| 83 | template <class ELFT> |
| 84 | static void iterateSectionContents( |
| 85 | uint32_t Type, |
| 86 | std::function<void(ObjectFile<ELFT> *, ArrayRef<uint8_t>)> F) { |
| 87 | for (InputSectionBase<ELFT> *Sec : Symtab<ELFT>::X->Sections) { |
| 88 | if (Sec && Sec->Live && Sec->Type == Type) { |
| 89 | Sec->Live = false; |
| 90 | F(Sec->getFile(), Sec->Data); |
| 91 | } |
| 92 | } |
| 93 | } |
| 94 | |
| 95 | // .MIPS.options section. |
| 96 | template <class ELFT> |
| 97 | MipsOptionsSection<ELFT>::MipsOptionsSection() |
| 98 | : InputSection<ELFT>(SHF_ALLOC, SHT_MIPS_OPTIONS, 8, ArrayRef<uint8_t>(), |
| 99 | ".MIPS.options") { |
| 100 | Buf.resize(sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo)); |
| 101 | getOptions()->kind = ODK_REGINFO; |
| 102 | getOptions()->size = Buf.size(); |
| 103 | auto Func = [this](ObjectFile<ELFT> *F, ArrayRef<uint8_t> D) { |
| 104 | while (!D.empty()) { |
| 105 | if (D.size() < sizeof(Elf_Mips_Options)) { |
| 106 | error(getFilename(F) + ": invalid size of .MIPS.options section"); |
| 107 | break; |
| 108 | } |
| 109 | auto *O = reinterpret_cast<const Elf_Mips_Options *>(D.data()); |
| 110 | if (O->kind == ODK_REGINFO) { |
| 111 | if (Config->Relocatable && O->getRegInfo().ri_gp_value) |
| 112 | error(getFilename(F) + ": unsupported non-zero ri_gp_value"); |
| 113 | getOptions()->getRegInfo().ri_gprmask |= O->getRegInfo().ri_gprmask; |
| 114 | F->MipsGp0 = O->getRegInfo().ri_gp_value; |
| 115 | break; |
| 116 | } |
| 117 | if (!O->size) |
| 118 | fatal(getFilename(F) + ": zero option descriptor size"); |
| 119 | D = D.slice(O->size); |
| 120 | } |
| 121 | }; |
| 122 | iterateSectionContents<ELFT>(SHT_MIPS_OPTIONS, Func); |
| 123 | |
| 124 | this->Data = ArrayRef<uint8_t>(Buf); |
| 125 | // Section should be alive for N64 ABI only. |
| 126 | this->Live = ELFT::Is64Bits; |
| 127 | } |
| 128 | |
| 129 | template <class ELFT> void MipsOptionsSection<ELFT>::finalize() { |
| 130 | if (!Config->Relocatable) |
| 131 | getOptions()->getRegInfo().ri_gp_value = |
| 132 | Out<ELFT>::Got->Addr + MipsGPOffset; |
| 133 | } |
| 134 | |
| 135 | // MIPS .reginfo section. |
| 136 | template <class ELFT> |
| 137 | MipsReginfoSection<ELFT>::MipsReginfoSection() |
| 138 | : InputSection<ELFT>(SHF_ALLOC, SHT_MIPS_REGINFO, 4, ArrayRef<uint8_t>(), |
| 139 | ".reginfo") { |
| 140 | auto Func = [this](ObjectFile<ELFT> *F, ArrayRef<uint8_t> D) { |
| 141 | if (D.size() != sizeof(Elf_Mips_RegInfo)) { |
| 142 | error(getFilename(F) + ": invalid size of .reginfo section"); |
| 143 | return; |
| 144 | } |
| 145 | auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(D.data()); |
| 146 | if (Config->Relocatable && R->ri_gp_value) |
| 147 | error(getFilename(F) + ": unsupported non-zero ri_gp_value"); |
| 148 | Reginfo.ri_gprmask |= R->ri_gprmask; |
| 149 | F->MipsGp0 = R->ri_gp_value; |
| 150 | }; |
| 151 | iterateSectionContents<ELFT>(SHT_MIPS_REGINFO, Func); |
| 152 | |
| 153 | this->Data = ArrayRef<uint8_t>((const uint8_t *)&Reginfo, sizeof(Reginfo)); |
| 154 | // Section should be alive for O32 and N32 ABIs only. |
| 155 | this->Live = !ELFT::Is64Bits; |
| 156 | } |
| 157 | |
| 158 | template <class ELFT> void MipsReginfoSection<ELFT>::finalize() { |
| 159 | if (!Config->Relocatable) |
| 160 | Reginfo.ri_gp_value = Out<ELFT>::Got->Addr + MipsGPOffset; |
| 161 | } |
| 162 | |
Rui Ueyama | e288eef | 2016-11-02 18:58:44 +0000 | [diff] [blame] | 163 | static ArrayRef<uint8_t> createInterp() { |
| 164 | // StringSaver guarantees that the returned string ends with '\0'. |
| 165 | StringRef S = Saver.save(Config->DynamicLinker); |
Rui Ueyama | 6294a24 | 2016-11-04 17:41:29 +0000 | [diff] [blame] | 166 | return {(const uint8_t *)S.data(), S.size() + 1}; |
Rui Ueyama | e288eef | 2016-11-02 18:58:44 +0000 | [diff] [blame] | 167 | } |
| 168 | |
Rafael Espindola | c0e47fb | 2016-11-08 14:56:27 +0000 | [diff] [blame] | 169 | template <class ELFT> InputSection<ELFT> *elf::createInterpSection() { |
| 170 | auto *Ret = make<InputSection<ELFT>>(SHF_ALLOC, SHT_PROGBITS, 1, |
| 171 | createInterp(), ".interp"); |
| 172 | Ret->Live = true; |
| 173 | return Ret; |
Rui Ueyama | a9ee8d6 | 2016-11-04 22:25:39 +0000 | [diff] [blame] | 174 | } |
Rui Ueyama | e288eef | 2016-11-02 18:58:44 +0000 | [diff] [blame] | 175 | |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 176 | template <class ELFT> |
| 177 | BuildIdSection<ELFT>::BuildIdSection(size_t HashSize) |
| 178 | : InputSection<ELFT>(SHF_ALLOC, SHT_NOTE, 1, ArrayRef<uint8_t>(), |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 179 | ".note.gnu.build-id"), |
| 180 | HashSize(HashSize) { |
Rui Ueyama | a9ee8d6 | 2016-11-04 22:25:39 +0000 | [diff] [blame] | 181 | this->Live = true; |
| 182 | |
Rafael Espindola | 1a54112 | 2016-11-08 14:47:16 +0000 | [diff] [blame] | 183 | Buf.resize(16 + HashSize); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 184 | const endianness E = ELFT::TargetEndianness; |
Rafael Espindola | 1a54112 | 2016-11-08 14:47:16 +0000 | [diff] [blame] | 185 | write32<E>(Buf.data(), 4); // Name size |
| 186 | write32<E>(Buf.data() + 4, HashSize); // Content size |
| 187 | write32<E>(Buf.data() + 8, NT_GNU_BUILD_ID); // Type |
| 188 | memcpy(Buf.data() + 12, "GNU", 4); // Name string |
| 189 | this->Data = ArrayRef<uint8_t>(Buf); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 190 | } |
| 191 | |
| 192 | template <class ELFT> |
| 193 | uint8_t *BuildIdSection<ELFT>::getOutputLoc(uint8_t *Start) const { |
Rafael Espindola | 04a2e34 | 2016-11-09 01:42:41 +0000 | [diff] [blame] | 194 | return Start + this->OutSec->Offset + this->OutSecOff; |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 195 | } |
| 196 | |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 197 | static std::vector<ArrayRef<uint8_t>> split(ArrayRef<uint8_t> Arr, |
| 198 | size_t ChunkSize) { |
| 199 | std::vector<ArrayRef<uint8_t>> Ret; |
| 200 | while (Arr.size() > ChunkSize) { |
| 201 | Ret.push_back(Arr.take_front(ChunkSize)); |
| 202 | Arr = Arr.drop_front(ChunkSize); |
| 203 | } |
| 204 | if (!Arr.empty()) |
| 205 | Ret.push_back(Arr); |
| 206 | return Ret; |
| 207 | } |
| 208 | |
| 209 | template <class ELFT> |
| 210 | void BuildIdSection<ELFT>::computeHash( |
George Rimar | 828787a | 2016-11-06 08:39:46 +0000 | [diff] [blame] | 211 | llvm::MutableArrayRef<uint8_t> Data, |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 212 | std::function<void(ArrayRef<uint8_t> Arr, uint8_t *Hash)> Hash) { |
| 213 | std::vector<ArrayRef<uint8_t>> Chunks = split(Data, 1024 * 1024); |
| 214 | std::vector<uint8_t> HashList(Chunks.size() * HashSize); |
| 215 | |
| 216 | if (Config->Threads) |
| 217 | parallel_for_each(Chunks.begin(), Chunks.end(), |
| 218 | [&](ArrayRef<uint8_t> &Chunk) { |
| 219 | size_t Id = &Chunk - Chunks.data(); |
| 220 | Hash(Chunk, HashList.data() + Id * HashSize); |
| 221 | }); |
| 222 | else |
| 223 | std::for_each(Chunks.begin(), Chunks.end(), [&](ArrayRef<uint8_t> &Chunk) { |
| 224 | size_t Id = &Chunk - Chunks.data(); |
| 225 | Hash(Chunk, HashList.data() + Id * HashSize); |
| 226 | }); |
| 227 | |
George Rimar | 828787a | 2016-11-06 08:39:46 +0000 | [diff] [blame] | 228 | Hash(HashList, this->getOutputLoc(Data.begin()) + 16); |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 229 | } |
| 230 | |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 231 | template <class ELFT> |
| 232 | void BuildIdFastHash<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
George Rimar | 5020971 | 2016-11-06 08:26:53 +0000 | [diff] [blame] | 233 | this->computeHash(Buf, [](ArrayRef<uint8_t> Arr, uint8_t *Dest) { |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 234 | uint64_t Hash = xxHash64(toStringRef(Arr)); |
| 235 | write64<ELFT::TargetEndianness>(Dest, Hash); |
| 236 | }); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 237 | } |
| 238 | |
| 239 | template <class ELFT> |
| 240 | void BuildIdMd5<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
George Rimar | 5020971 | 2016-11-06 08:26:53 +0000 | [diff] [blame] | 241 | this->computeHash(Buf, [&](ArrayRef<uint8_t> Arr, uint8_t *Dest) { |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 242 | MD5 Hash; |
| 243 | Hash.update(Arr); |
| 244 | MD5::MD5Result Res; |
| 245 | Hash.final(Res); |
George Rimar | 5020971 | 2016-11-06 08:26:53 +0000 | [diff] [blame] | 246 | memcpy(Dest, Res, this->HashSize); |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 247 | }); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 248 | } |
| 249 | |
| 250 | template <class ELFT> |
| 251 | void BuildIdSha1<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
George Rimar | 5020971 | 2016-11-06 08:26:53 +0000 | [diff] [blame] | 252 | this->computeHash(Buf, [&](ArrayRef<uint8_t> Arr, uint8_t *Dest) { |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 253 | SHA1 Hash; |
| 254 | Hash.update(Arr); |
George Rimar | 5020971 | 2016-11-06 08:26:53 +0000 | [diff] [blame] | 255 | memcpy(Dest, Hash.final().data(), this->HashSize); |
George Rimar | 364b59e2 | 2016-11-06 07:42:55 +0000 | [diff] [blame] | 256 | }); |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 257 | } |
| 258 | |
| 259 | template <class ELFT> |
| 260 | void BuildIdUuid<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
| 261 | if (getRandomBytes(this->getOutputLoc(Buf.begin()) + 16, 16)) |
| 262 | error("entropy source failure"); |
| 263 | } |
| 264 | |
| 265 | template <class ELFT> |
| 266 | BuildIdHexstring<ELFT>::BuildIdHexstring() |
| 267 | : BuildIdSection<ELFT>(Config->BuildIdVector.size()) {} |
| 268 | |
| 269 | template <class ELFT> |
| 270 | void BuildIdHexstring<ELFT>::writeBuildId(MutableArrayRef<uint8_t> Buf) { |
| 271 | memcpy(this->getOutputLoc(Buf.begin()) + 16, Config->BuildIdVector.data(), |
| 272 | Config->BuildIdVector.size()); |
| 273 | } |
| 274 | |
Rafael Espindola | 682a5bc | 2016-11-08 14:42:34 +0000 | [diff] [blame] | 275 | template InputSection<ELF32LE> *elf::createCommonSection(); |
| 276 | template InputSection<ELF32BE> *elf::createCommonSection(); |
| 277 | template InputSection<ELF64LE> *elf::createCommonSection(); |
| 278 | template InputSection<ELF64BE> *elf::createCommonSection(); |
Rui Ueyama | e8a6102 | 2016-11-05 23:05:47 +0000 | [diff] [blame] | 279 | |
Rafael Espindola | c0e47fb | 2016-11-08 14:56:27 +0000 | [diff] [blame] | 280 | template InputSection<ELF32LE> *elf::createInterpSection(); |
| 281 | template InputSection<ELF32BE> *elf::createInterpSection(); |
| 282 | template InputSection<ELF64LE> *elf::createInterpSection(); |
| 283 | template InputSection<ELF64BE> *elf::createInterpSection(); |
Rui Ueyama | e288eef | 2016-11-02 18:58:44 +0000 | [diff] [blame] | 284 | |
Simon Atanasyan | ce02cf0 | 2016-11-09 21:36:56 +0000 | [diff] [blame^] | 285 | template class elf::MipsOptionsSection<ELF32LE>; |
| 286 | template class elf::MipsOptionsSection<ELF32BE>; |
| 287 | template class elf::MipsOptionsSection<ELF64LE>; |
| 288 | template class elf::MipsOptionsSection<ELF64BE>; |
| 289 | |
| 290 | template class elf::MipsReginfoSection<ELF32LE>; |
| 291 | template class elf::MipsReginfoSection<ELF32BE>; |
| 292 | template class elf::MipsReginfoSection<ELF64LE>; |
| 293 | template class elf::MipsReginfoSection<ELF64BE>; |
| 294 | |
Rui Ueyama | 6dc7fcb | 2016-11-01 20:28:21 +0000 | [diff] [blame] | 295 | template class elf::BuildIdSection<ELF32LE>; |
| 296 | template class elf::BuildIdSection<ELF32BE>; |
| 297 | template class elf::BuildIdSection<ELF64LE>; |
| 298 | template class elf::BuildIdSection<ELF64BE>; |
| 299 | |
| 300 | template class elf::BuildIdFastHash<ELF32LE>; |
| 301 | template class elf::BuildIdFastHash<ELF32BE>; |
| 302 | template class elf::BuildIdFastHash<ELF64LE>; |
| 303 | template class elf::BuildIdFastHash<ELF64BE>; |
| 304 | |
| 305 | template class elf::BuildIdMd5<ELF32LE>; |
| 306 | template class elf::BuildIdMd5<ELF32BE>; |
| 307 | template class elf::BuildIdMd5<ELF64LE>; |
| 308 | template class elf::BuildIdMd5<ELF64BE>; |
| 309 | |
| 310 | template class elf::BuildIdSha1<ELF32LE>; |
| 311 | template class elf::BuildIdSha1<ELF32BE>; |
| 312 | template class elf::BuildIdSha1<ELF64LE>; |
| 313 | template class elf::BuildIdSha1<ELF64BE>; |
| 314 | |
| 315 | template class elf::BuildIdUuid<ELF32LE>; |
| 316 | template class elf::BuildIdUuid<ELF32BE>; |
| 317 | template class elf::BuildIdUuid<ELF64LE>; |
| 318 | template class elf::BuildIdUuid<ELF64BE>; |
| 319 | |
| 320 | template class elf::BuildIdHexstring<ELF32LE>; |
| 321 | template class elf::BuildIdHexstring<ELF32BE>; |
| 322 | template class elf::BuildIdHexstring<ELF64LE>; |
| 323 | template class elf::BuildIdHexstring<ELF64BE>; |