/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/ELF/SyntheticSections.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- SyntheticSections.cpp ----------------------------------------------===// |
2 | | // |
3 | | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | | // See https://llvm.org/LICENSE.txt for license information. |
5 | | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | | // |
7 | | //===----------------------------------------------------------------------===// |
8 | | // |
9 | | // This file contains linker-synthesized sections. Currently, |
10 | | // synthetic sections are created either output sections or input sections, |
11 | | // but we are rewriting code so that all synthetic sections are created as |
12 | | // input sections. |
13 | | // |
14 | | //===----------------------------------------------------------------------===// |
15 | | |
16 | | #include "SyntheticSections.h" |
17 | | #include "Config.h" |
18 | | #include "InputFiles.h" |
19 | | #include "LinkerScript.h" |
20 | | #include "OutputSections.h" |
21 | | #include "SymbolTable.h" |
22 | | #include "Symbols.h" |
23 | | #include "Target.h" |
24 | | #include "Writer.h" |
25 | | #include "lld/Common/ErrorHandler.h" |
26 | | #include "lld/Common/Memory.h" |
27 | | #include "lld/Common/Strings.h" |
28 | | #include "lld/Common/Threads.h" |
29 | | #include "lld/Common/Version.h" |
30 | | #include "llvm/ADT/SetOperations.h" |
31 | | #include "llvm/ADT/StringExtras.h" |
32 | | #include "llvm/BinaryFormat/Dwarf.h" |
33 | | #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" |
34 | | #include "llvm/Object/ELFObjectFile.h" |
35 | | #include "llvm/Support/Compression.h" |
36 | | #include "llvm/Support/Endian.h" |
37 | | #include "llvm/Support/LEB128.h" |
38 | | #include "llvm/Support/MD5.h" |
39 | | #include <cstdlib> |
40 | | #include <thread> |
41 | | |
42 | | using namespace llvm; |
43 | | using namespace llvm::dwarf; |
44 | | using namespace llvm::ELF; |
45 | | using namespace llvm::object; |
46 | | using namespace llvm::support; |
47 | | |
48 | | using namespace lld; |
49 | | using namespace lld::elf; |
50 | | |
51 | | using llvm::support::endian::read32le; |
52 | | using llvm::support::endian::write32le; |
53 | | using llvm::support::endian::write64le; |
54 | | |
55 | | constexpr size_t MergeNoTailSection::numShards; |
56 | | |
57 | 1.23k | static uint64_t readUint(uint8_t *buf) { |
58 | 1.23k | return config->is64 ? read64(buf)1.04k : read32(buf)196 ; |
59 | 1.23k | } |
60 | | |
61 | 11.5k | static void writeUint(uint8_t *buf, uint64_t val) { |
62 | 11.5k | if (config->is64) |
63 | 11.1k | write64(buf, val); |
64 | 419 | else |
65 | 419 | write32(buf, val); |
66 | 11.5k | } |
67 | | |
68 | | // Returns an LLD version string. |
69 | 2.66k | static ArrayRef<uint8_t> getVersion() { |
70 | 2.66k | // Check LLD_VERSION first for ease of testing. |
71 | 2.66k | // You can get consistent output by using the environment variable. |
72 | 2.66k | // This is only for testing. |
73 | 2.66k | StringRef s = getenv("LLD_VERSION"); |
74 | 2.66k | if (s.empty()) |
75 | 0 | s = saver.save(Twine("Linker: ") + getLLDVersion()); |
76 | 2.66k | |
77 | 2.66k | // +1 to include the terminating '\0'. |
78 | 2.66k | return {(const uint8_t *)s.data(), s.size() + 1}; |
79 | 2.66k | } |
80 | | |
81 | | // Creates a .comment section containing LLD version info. |
82 | | // With this feature, you can identify LLD-generated binaries easily |
83 | | // by "readelf --string-dump .comment <file>". |
84 | | // The returned object is a mergeable string section. |
85 | 2.66k | MergeInputSection *elf::createCommentSection() { |
86 | 2.66k | return make<MergeInputSection>(SHF_MERGE | SHF_STRINGS, SHT_PROGBITS, 1, |
87 | 2.66k | getVersion(), ".comment"); |
88 | 2.66k | } |
89 | | |
90 | | // .MIPS.abiflags section. |
91 | | template <class ELFT> |
92 | | MipsAbiFlagsSection<ELFT>::MipsAbiFlagsSection(Elf_Mips_ABIFlags flags) |
93 | | : SyntheticSection(SHF_ALLOC, SHT_MIPS_ABIFLAGS, 8, ".MIPS.abiflags"), |
94 | 192 | flags(flags) { |
95 | 192 | this->entsize = sizeof(Elf_Mips_ABIFlags); |
96 | 192 | } lld::elf::MipsAbiFlagsSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::MipsAbiFlagsSection(llvm::object::Elf_Mips_ABIFlags<llvm::object::ELFType<(llvm::support::endianness)1, false> >) Line | Count | Source | 94 | 23 | flags(flags) { | 95 | 23 | this->entsize = sizeof(Elf_Mips_ABIFlags); | 96 | 23 | } |
lld::elf::MipsAbiFlagsSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::MipsAbiFlagsSection(llvm::object::Elf_Mips_ABIFlags<llvm::object::ELFType<(llvm::support::endianness)0, false> >) Line | Count | Source | 94 | 123 | flags(flags) { | 95 | 123 | this->entsize = sizeof(Elf_Mips_ABIFlags); | 96 | 123 | } |
lld::elf::MipsAbiFlagsSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::MipsAbiFlagsSection(llvm::object::Elf_Mips_ABIFlags<llvm::object::ELFType<(llvm::support::endianness)1, true> >) Line | Count | Source | 94 | 3 | flags(flags) { | 95 | 3 | this->entsize = sizeof(Elf_Mips_ABIFlags); | 96 | 3 | } |
lld::elf::MipsAbiFlagsSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::MipsAbiFlagsSection(llvm::object::Elf_Mips_ABIFlags<llvm::object::ELFType<(llvm::support::endianness)0, true> >) Line | Count | Source | 94 | 43 | flags(flags) { | 95 | 43 | this->entsize = sizeof(Elf_Mips_ABIFlags); | 96 | 43 | } |
|
97 | | |
98 | 185 | template <class ELFT> void MipsAbiFlagsSection<ELFT>::writeTo(uint8_t *buf) { |
99 | 185 | memcpy(buf, &flags, sizeof(flags)); |
100 | 185 | } lld::elf::MipsAbiFlagsSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*) Line | Count | Source | 98 | 22 | template <class ELFT> void MipsAbiFlagsSection<ELFT>::writeTo(uint8_t *buf) { | 99 | 22 | memcpy(buf, &flags, sizeof(flags)); | 100 | 22 | } |
lld::elf::MipsAbiFlagsSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::writeTo(unsigned char*) Line | Count | Source | 98 | 122 | template <class ELFT> void MipsAbiFlagsSection<ELFT>::writeTo(uint8_t *buf) { | 99 | 122 | memcpy(buf, &flags, sizeof(flags)); | 100 | 122 | } |
lld::elf::MipsAbiFlagsSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeTo(unsigned char*) Line | Count | Source | 98 | 3 | template <class ELFT> void MipsAbiFlagsSection<ELFT>::writeTo(uint8_t *buf) { | 99 | 3 | memcpy(buf, &flags, sizeof(flags)); | 100 | 3 | } |
lld::elf::MipsAbiFlagsSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::writeTo(unsigned char*) Line | Count | Source | 98 | 38 | template <class ELFT> void MipsAbiFlagsSection<ELFT>::writeTo(uint8_t *buf) { | 99 | 38 | memcpy(buf, &flags, sizeof(flags)); | 100 | 38 | } |
|
101 | | |
102 | | template <class ELFT> |
103 | 198 | MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() { |
104 | 198 | Elf_Mips_ABIFlags flags = {}; |
105 | 198 | bool create = false; |
106 | 198 | |
107 | 1.93k | for (InputSectionBase *sec : inputSections) { |
108 | 1.93k | if (sec->type != SHT_MIPS_ABIFLAGS) |
109 | 1.68k | continue; |
110 | 254 | sec->markDead(); |
111 | 254 | create = true; |
112 | 254 | |
113 | 254 | std::string filename = toString(sec->file); |
114 | 254 | const size_t size = sec->data().size(); |
115 | 254 | // Older version of BFD (such as the default FreeBSD linker) concatenate |
116 | 254 | // .MIPS.abiflags instead of merging. To allow for this case (or potential |
117 | 254 | // zero padding) we ignore everything after the first Elf_Mips_ABIFlags |
118 | 254 | if (size < sizeof(Elf_Mips_ABIFlags)) { |
119 | 0 | error(filename + ": invalid size of .MIPS.abiflags section: got " + |
120 | 0 | Twine(size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags))); |
121 | 0 | return nullptr; |
122 | 0 | } |
123 | 254 | auto *s = reinterpret_cast<const Elf_Mips_ABIFlags *>(sec->data().data()); |
124 | 254 | if (s->version != 0) { |
125 | 0 | error(filename + ": unexpected .MIPS.abiflags version " + |
126 | 0 | Twine(s->version)); |
127 | 0 | return nullptr; |
128 | 0 | } |
129 | 254 | |
130 | 254 | // LLD checks ISA compatibility in calcMipsEFlags(). Here we just |
131 | 254 | // select the highest number of ISA/Rev/Ext. |
132 | 254 | flags.isa_level = std::max(flags.isa_level, s->isa_level); |
133 | 254 | flags.isa_rev = std::max(flags.isa_rev, s->isa_rev); |
134 | 254 | flags.isa_ext = std::max(flags.isa_ext, s->isa_ext); |
135 | 254 | flags.gpr_size = std::max(flags.gpr_size, s->gpr_size); |
136 | 254 | flags.cpr1_size = std::max(flags.cpr1_size, s->cpr1_size); |
137 | 254 | flags.cpr2_size = std::max(flags.cpr2_size, s->cpr2_size); |
138 | 254 | flags.ases |= s->ases; |
139 | 254 | flags.flags1 |= s->flags1; |
140 | 254 | flags.flags2 |= s->flags2; |
141 | 254 | flags.fp_abi = elf::getMipsFpAbiFlag(flags.fp_abi, s->fp_abi, filename); |
142 | 254 | }; |
143 | 198 | |
144 | 198 | if (create) |
145 | 192 | return make<MipsAbiFlagsSection<ELFT>>(flags); |
146 | 6 | return nullptr; |
147 | 6 | } lld::elf::MipsAbiFlagsSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::create() Line | Count | Source | 103 | 24 | MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() { | 104 | 24 | Elf_Mips_ABIFlags flags = {}; | 105 | 24 | bool create = false; | 106 | 24 | | 107 | 218 | for (InputSectionBase *sec : inputSections) { | 108 | 218 | if (sec->type != SHT_MIPS_ABIFLAGS) | 109 | 190 | continue; | 110 | 28 | sec->markDead(); | 111 | 28 | create = true; | 112 | 28 | | 113 | 28 | std::string filename = toString(sec->file); | 114 | 28 | const size_t size = sec->data().size(); | 115 | 28 | // Older version of BFD (such as the default FreeBSD linker) concatenate | 116 | 28 | // .MIPS.abiflags instead of merging. To allow for this case (or potential | 117 | 28 | // zero padding) we ignore everything after the first Elf_Mips_ABIFlags | 118 | 28 | if (size < sizeof(Elf_Mips_ABIFlags)) { | 119 | 0 | error(filename + ": invalid size of .MIPS.abiflags section: got " + | 120 | 0 | Twine(size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags))); | 121 | 0 | return nullptr; | 122 | 0 | } | 123 | 28 | auto *s = reinterpret_cast<const Elf_Mips_ABIFlags *>(sec->data().data()); | 124 | 28 | if (s->version != 0) { | 125 | 0 | error(filename + ": unexpected .MIPS.abiflags version " + | 126 | 0 | Twine(s->version)); | 127 | 0 | return nullptr; | 128 | 0 | } | 129 | 28 | | 130 | 28 | // LLD checks ISA compatibility in calcMipsEFlags(). Here we just | 131 | 28 | // select the highest number of ISA/Rev/Ext. | 132 | 28 | flags.isa_level = std::max(flags.isa_level, s->isa_level); | 133 | 28 | flags.isa_rev = std::max(flags.isa_rev, s->isa_rev); | 134 | 28 | flags.isa_ext = std::max(flags.isa_ext, s->isa_ext); | 135 | 28 | flags.gpr_size = std::max(flags.gpr_size, s->gpr_size); | 136 | 28 | flags.cpr1_size = std::max(flags.cpr1_size, s->cpr1_size); | 137 | 28 | flags.cpr2_size = std::max(flags.cpr2_size, s->cpr2_size); | 138 | 28 | flags.ases |= s->ases; | 139 | 28 | flags.flags1 |= s->flags1; | 140 | 28 | flags.flags2 |= s->flags2; | 141 | 28 | flags.fp_abi = elf::getMipsFpAbiFlag(flags.fp_abi, s->fp_abi, filename); | 142 | 28 | }; | 143 | 24 | | 144 | 24 | if (create) | 145 | 23 | return make<MipsAbiFlagsSection<ELFT>>(flags); | 146 | 1 | return nullptr; | 147 | 1 | } |
lld::elf::MipsAbiFlagsSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::create() Line | Count | Source | 103 | 126 | MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() { | 104 | 126 | Elf_Mips_ABIFlags flags = {}; | 105 | 126 | bool create = false; | 106 | 126 | | 107 | 1.28k | for (InputSectionBase *sec : inputSections) { | 108 | 1.28k | if (sec->type != SHT_MIPS_ABIFLAGS) | 109 | 1.11k | continue; | 110 | 168 | sec->markDead(); | 111 | 168 | create = true; | 112 | 168 | | 113 | 168 | std::string filename = toString(sec->file); | 114 | 168 | const size_t size = sec->data().size(); | 115 | 168 | // Older version of BFD (such as the default FreeBSD linker) concatenate | 116 | 168 | // .MIPS.abiflags instead of merging. To allow for this case (or potential | 117 | 168 | // zero padding) we ignore everything after the first Elf_Mips_ABIFlags | 118 | 168 | if (size < sizeof(Elf_Mips_ABIFlags)) { | 119 | 0 | error(filename + ": invalid size of .MIPS.abiflags section: got " + | 120 | 0 | Twine(size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags))); | 121 | 0 | return nullptr; | 122 | 0 | } | 123 | 168 | auto *s = reinterpret_cast<const Elf_Mips_ABIFlags *>(sec->data().data()); | 124 | 168 | if (s->version != 0) { | 125 | 0 | error(filename + ": unexpected .MIPS.abiflags version " + | 126 | 0 | Twine(s->version)); | 127 | 0 | return nullptr; | 128 | 0 | } | 129 | 168 | | 130 | 168 | // LLD checks ISA compatibility in calcMipsEFlags(). Here we just | 131 | 168 | // select the highest number of ISA/Rev/Ext. | 132 | 168 | flags.isa_level = std::max(flags.isa_level, s->isa_level); | 133 | 168 | flags.isa_rev = std::max(flags.isa_rev, s->isa_rev); | 134 | 168 | flags.isa_ext = std::max(flags.isa_ext, s->isa_ext); | 135 | 168 | flags.gpr_size = std::max(flags.gpr_size, s->gpr_size); | 136 | 168 | flags.cpr1_size = std::max(flags.cpr1_size, s->cpr1_size); | 137 | 168 | flags.cpr2_size = std::max(flags.cpr2_size, s->cpr2_size); | 138 | 168 | flags.ases |= s->ases; | 139 | 168 | flags.flags1 |= s->flags1; | 140 | 168 | flags.flags2 |= s->flags2; | 141 | 168 | flags.fp_abi = elf::getMipsFpAbiFlag(flags.fp_abi, s->fp_abi, filename); | 142 | 168 | }; | 143 | 126 | | 144 | 126 | if (create) | 145 | 123 | return make<MipsAbiFlagsSection<ELFT>>(flags); | 146 | 3 | return nullptr; | 147 | 3 | } |
lld::elf::MipsAbiFlagsSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::create() Line | Count | Source | 103 | 3 | MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() { | 104 | 3 | Elf_Mips_ABIFlags flags = {}; | 105 | 3 | bool create = false; | 106 | 3 | | 107 | 24 | for (InputSectionBase *sec : inputSections) { | 108 | 24 | if (sec->type != SHT_MIPS_ABIFLAGS) | 109 | 21 | continue; | 110 | 3 | sec->markDead(); | 111 | 3 | create = true; | 112 | 3 | | 113 | 3 | std::string filename = toString(sec->file); | 114 | 3 | const size_t size = sec->data().size(); | 115 | 3 | // Older version of BFD (such as the default FreeBSD linker) concatenate | 116 | 3 | // .MIPS.abiflags instead of merging. To allow for this case (or potential | 117 | 3 | // zero padding) we ignore everything after the first Elf_Mips_ABIFlags | 118 | 3 | if (size < sizeof(Elf_Mips_ABIFlags)) { | 119 | 0 | error(filename + ": invalid size of .MIPS.abiflags section: got " + | 120 | 0 | Twine(size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags))); | 121 | 0 | return nullptr; | 122 | 0 | } | 123 | 3 | auto *s = reinterpret_cast<const Elf_Mips_ABIFlags *>(sec->data().data()); | 124 | 3 | if (s->version != 0) { | 125 | 0 | error(filename + ": unexpected .MIPS.abiflags version " + | 126 | 0 | Twine(s->version)); | 127 | 0 | return nullptr; | 128 | 0 | } | 129 | 3 | | 130 | 3 | // LLD checks ISA compatibility in calcMipsEFlags(). Here we just | 131 | 3 | // select the highest number of ISA/Rev/Ext. | 132 | 3 | flags.isa_level = std::max(flags.isa_level, s->isa_level); | 133 | 3 | flags.isa_rev = std::max(flags.isa_rev, s->isa_rev); | 134 | 3 | flags.isa_ext = std::max(flags.isa_ext, s->isa_ext); | 135 | 3 | flags.gpr_size = std::max(flags.gpr_size, s->gpr_size); | 136 | 3 | flags.cpr1_size = std::max(flags.cpr1_size, s->cpr1_size); | 137 | 3 | flags.cpr2_size = std::max(flags.cpr2_size, s->cpr2_size); | 138 | 3 | flags.ases |= s->ases; | 139 | 3 | flags.flags1 |= s->flags1; | 140 | 3 | flags.flags2 |= s->flags2; | 141 | 3 | flags.fp_abi = elf::getMipsFpAbiFlag(flags.fp_abi, s->fp_abi, filename); | 142 | 3 | }; | 143 | 3 | | 144 | 3 | if (create) | 145 | 3 | return make<MipsAbiFlagsSection<ELFT>>(flags); | 146 | 0 | return nullptr; | 147 | 0 | } |
lld::elf::MipsAbiFlagsSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::create() Line | Count | Source | 103 | 45 | MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() { | 104 | 45 | Elf_Mips_ABIFlags flags = {}; | 105 | 45 | bool create = false; | 106 | 45 | | 107 | 409 | for (InputSectionBase *sec : inputSections) { | 108 | 409 | if (sec->type != SHT_MIPS_ABIFLAGS) | 109 | 354 | continue; | 110 | 55 | sec->markDead(); | 111 | 55 | create = true; | 112 | 55 | | 113 | 55 | std::string filename = toString(sec->file); | 114 | 55 | const size_t size = sec->data().size(); | 115 | 55 | // Older version of BFD (such as the default FreeBSD linker) concatenate | 116 | 55 | // .MIPS.abiflags instead of merging. To allow for this case (or potential | 117 | 55 | // zero padding) we ignore everything after the first Elf_Mips_ABIFlags | 118 | 55 | if (size < sizeof(Elf_Mips_ABIFlags)) { | 119 | 0 | error(filename + ": invalid size of .MIPS.abiflags section: got " + | 120 | 0 | Twine(size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags))); | 121 | 0 | return nullptr; | 122 | 0 | } | 123 | 55 | auto *s = reinterpret_cast<const Elf_Mips_ABIFlags *>(sec->data().data()); | 124 | 55 | if (s->version != 0) { | 125 | 0 | error(filename + ": unexpected .MIPS.abiflags version " + | 126 | 0 | Twine(s->version)); | 127 | 0 | return nullptr; | 128 | 0 | } | 129 | 55 | | 130 | 55 | // LLD checks ISA compatibility in calcMipsEFlags(). Here we just | 131 | 55 | // select the highest number of ISA/Rev/Ext. | 132 | 55 | flags.isa_level = std::max(flags.isa_level, s->isa_level); | 133 | 55 | flags.isa_rev = std::max(flags.isa_rev, s->isa_rev); | 134 | 55 | flags.isa_ext = std::max(flags.isa_ext, s->isa_ext); | 135 | 55 | flags.gpr_size = std::max(flags.gpr_size, s->gpr_size); | 136 | 55 | flags.cpr1_size = std::max(flags.cpr1_size, s->cpr1_size); | 137 | 55 | flags.cpr2_size = std::max(flags.cpr2_size, s->cpr2_size); | 138 | 55 | flags.ases |= s->ases; | 139 | 55 | flags.flags1 |= s->flags1; | 140 | 55 | flags.flags2 |= s->flags2; | 141 | 55 | flags.fp_abi = elf::getMipsFpAbiFlag(flags.fp_abi, s->fp_abi, filename); | 142 | 55 | }; | 143 | 45 | | 144 | 45 | if (create) | 145 | 43 | return make<MipsAbiFlagsSection<ELFT>>(flags); | 146 | 2 | return nullptr; | 147 | 2 | } |
|
148 | | |
149 | | // .MIPS.options section. |
150 | | template <class ELFT> |
151 | | MipsOptionsSection<ELFT>::MipsOptionsSection(Elf_Mips_RegInfo reginfo) |
152 | | : SyntheticSection(SHF_ALLOC, SHT_MIPS_OPTIONS, 8, ".MIPS.options"), |
153 | 42 | reginfo(reginfo) { |
154 | 42 | this->entsize = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo); |
155 | 42 | } Unexecuted instantiation: lld::elf::MipsOptionsSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::MipsOptionsSection(llvm::object::Elf_Mips_RegInfo<llvm::object::ELFType<(llvm::support::endianness)1, false> >) Unexecuted instantiation: lld::elf::MipsOptionsSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::MipsOptionsSection(llvm::object::Elf_Mips_RegInfo<llvm::object::ELFType<(llvm::support::endianness)0, false> >) lld::elf::MipsOptionsSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::MipsOptionsSection(llvm::object::Elf_Mips_RegInfo<llvm::object::ELFType<(llvm::support::endianness)1, true> >) Line | Count | Source | 153 | 3 | reginfo(reginfo) { | 154 | 3 | this->entsize = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo); | 155 | 3 | } |
lld::elf::MipsOptionsSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::MipsOptionsSection(llvm::object::Elf_Mips_RegInfo<llvm::object::ELFType<(llvm::support::endianness)0, true> >) Line | Count | Source | 153 | 39 | reginfo(reginfo) { | 154 | 39 | this->entsize = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo); | 155 | 39 | } |
|
156 | | |
157 | 41 | template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *buf) { |
158 | 41 | auto *options = reinterpret_cast<Elf_Mips_Options *>(buf); |
159 | 41 | options->kind = ODK_REGINFO; |
160 | 41 | options->size = getSize(); |
161 | 41 | |
162 | 41 | if (!config->relocatable) |
163 | 39 | reginfo.ri_gp_value = in.mipsGot->getGp(); |
164 | 41 | memcpy(buf + sizeof(Elf_Mips_Options), ®info, sizeof(reginfo)); |
165 | 41 | } Unexecuted instantiation: lld::elf::MipsOptionsSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*) Unexecuted instantiation: lld::elf::MipsOptionsSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::writeTo(unsigned char*) lld::elf::MipsOptionsSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeTo(unsigned char*) Line | Count | Source | 157 | 3 | template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *buf) { | 158 | 3 | auto *options = reinterpret_cast<Elf_Mips_Options *>(buf); | 159 | 3 | options->kind = ODK_REGINFO; | 160 | 3 | options->size = getSize(); | 161 | 3 | | 162 | 3 | if (!config->relocatable) | 163 | 3 | reginfo.ri_gp_value = in.mipsGot->getGp(); | 164 | 3 | memcpy(buf + sizeof(Elf_Mips_Options), ®info, sizeof(reginfo)); | 165 | 3 | } |
lld::elf::MipsOptionsSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::writeTo(unsigned char*) Line | Count | Source | 157 | 38 | template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *buf) { | 158 | 38 | auto *options = reinterpret_cast<Elf_Mips_Options *>(buf); | 159 | 38 | options->kind = ODK_REGINFO; | 160 | 38 | options->size = getSize(); | 161 | 38 | | 162 | 38 | if (!config->relocatable) | 163 | 36 | reginfo.ri_gp_value = in.mipsGot->getGp(); | 164 | 38 | memcpy(buf + sizeof(Elf_Mips_Options), ®info, sizeof(reginfo)); | 165 | 38 | } |
|
166 | | |
167 | | template <class ELFT> |
168 | 198 | MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() { |
169 | 198 | // N64 ABI only. |
170 | 198 | if (!ELFT::Is64Bits) |
171 | 150 | return nullptr; |
172 | 48 | |
173 | 48 | std::vector<InputSectionBase *> sections; |
174 | 48 | for (InputSectionBase *sec : inputSections) |
175 | 479 | if (sec->type == SHT_MIPS_OPTIONS) |
176 | 50 | sections.push_back(sec); |
177 | 48 | |
178 | 48 | if (sections.empty()) |
179 | 6 | return nullptr; |
180 | 42 | |
181 | 42 | Elf_Mips_RegInfo reginfo = {}; |
182 | 50 | for (InputSectionBase *sec : sections) { |
183 | 50 | sec->markDead(); |
184 | 50 | |
185 | 50 | std::string filename = toString(sec->file); |
186 | 50 | ArrayRef<uint8_t> d = sec->data(); |
187 | 50 | |
188 | 50 | while (!d.empty()) { |
189 | 50 | if (d.size() < sizeof(Elf_Mips_Options)) { |
190 | 0 | error(filename + ": invalid size of .MIPS.options section"); |
191 | 0 | break; |
192 | 0 | } |
193 | 50 | |
194 | 50 | auto *opt = reinterpret_cast<const Elf_Mips_Options *>(d.data()); |
195 | 50 | if (opt->kind == ODK_REGINFO) { |
196 | 50 | reginfo.ri_gprmask |= opt->getRegInfo().ri_gprmask; |
197 | 50 | sec->getFile<ELFT>()->mipsGp0 = opt->getRegInfo().ri_gp_value; |
198 | 50 | break; |
199 | 50 | } |
200 | 0 | |
201 | 0 | if (!opt->size) |
202 | 0 | fatal(filename + ": zero option descriptor size"); |
203 | 0 | d = d.slice(opt->size); |
204 | 0 | } |
205 | 50 | }; |
206 | 42 | |
207 | 42 | return make<MipsOptionsSection<ELFT>>(reginfo); |
208 | 42 | } lld::elf::MipsOptionsSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::create() Line | Count | Source | 168 | 24 | MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() { | 169 | 24 | // N64 ABI only. | 170 | 24 | if (!ELFT::Is64Bits) | 171 | 24 | return nullptr; | 172 | 0 | | 173 | 0 | std::vector<InputSectionBase *> sections; | 174 | 0 | for (InputSectionBase *sec : inputSections) | 175 | 0 | if (sec->type == SHT_MIPS_OPTIONS) | 176 | 0 | sections.push_back(sec); | 177 | 0 |
| 178 | 0 | if (sections.empty()) | 179 | 0 | return nullptr; | 180 | 0 | | 181 | 0 | Elf_Mips_RegInfo reginfo = {}; | 182 | 0 | for (InputSectionBase *sec : sections) { | 183 | 0 | sec->markDead(); | 184 | 0 |
| 185 | 0 | std::string filename = toString(sec->file); | 186 | 0 | ArrayRef<uint8_t> d = sec->data(); | 187 | 0 |
| 188 | 0 | while (!d.empty()) { | 189 | 0 | if (d.size() < sizeof(Elf_Mips_Options)) { | 190 | 0 | error(filename + ": invalid size of .MIPS.options section"); | 191 | 0 | break; | 192 | 0 | } | 193 | 0 | | 194 | 0 | auto *opt = reinterpret_cast<const Elf_Mips_Options *>(d.data()); | 195 | 0 | if (opt->kind == ODK_REGINFO) { | 196 | 0 | reginfo.ri_gprmask |= opt->getRegInfo().ri_gprmask; | 197 | 0 | sec->getFile<ELFT>()->mipsGp0 = opt->getRegInfo().ri_gp_value; | 198 | 0 | break; | 199 | 0 | } | 200 | 0 | | 201 | 0 | if (!opt->size) | 202 | 0 | fatal(filename + ": zero option descriptor size"); | 203 | 0 | d = d.slice(opt->size); | 204 | 0 | } | 205 | 0 | }; | 206 | 0 |
| 207 | 0 | return make<MipsOptionsSection<ELFT>>(reginfo); | 208 | 0 | } |
lld::elf::MipsOptionsSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::create() Line | Count | Source | 168 | 126 | MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() { | 169 | 126 | // N64 ABI only. | 170 | 126 | if (!ELFT::Is64Bits) | 171 | 126 | return nullptr; | 172 | 0 | | 173 | 0 | std::vector<InputSectionBase *> sections; | 174 | 0 | for (InputSectionBase *sec : inputSections) | 175 | 0 | if (sec->type == SHT_MIPS_OPTIONS) | 176 | 0 | sections.push_back(sec); | 177 | 0 |
| 178 | 0 | if (sections.empty()) | 179 | 0 | return nullptr; | 180 | 0 | | 181 | 0 | Elf_Mips_RegInfo reginfo = {}; | 182 | 0 | for (InputSectionBase *sec : sections) { | 183 | 0 | sec->markDead(); | 184 | 0 |
| 185 | 0 | std::string filename = toString(sec->file); | 186 | 0 | ArrayRef<uint8_t> d = sec->data(); | 187 | 0 |
| 188 | 0 | while (!d.empty()) { | 189 | 0 | if (d.size() < sizeof(Elf_Mips_Options)) { | 190 | 0 | error(filename + ": invalid size of .MIPS.options section"); | 191 | 0 | break; | 192 | 0 | } | 193 | 0 | | 194 | 0 | auto *opt = reinterpret_cast<const Elf_Mips_Options *>(d.data()); | 195 | 0 | if (opt->kind == ODK_REGINFO) { | 196 | 0 | reginfo.ri_gprmask |= opt->getRegInfo().ri_gprmask; | 197 | 0 | sec->getFile<ELFT>()->mipsGp0 = opt->getRegInfo().ri_gp_value; | 198 | 0 | break; | 199 | 0 | } | 200 | 0 | | 201 | 0 | if (!opt->size) | 202 | 0 | fatal(filename + ": zero option descriptor size"); | 203 | 0 | d = d.slice(opt->size); | 204 | 0 | } | 205 | 0 | }; | 206 | 0 |
| 207 | 0 | return make<MipsOptionsSection<ELFT>>(reginfo); | 208 | 0 | } |
lld::elf::MipsOptionsSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::create() Line | Count | Source | 168 | 3 | MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() { | 169 | 3 | // N64 ABI only. | 170 | 3 | if (!ELFT::Is64Bits) | 171 | 0 | return nullptr; | 172 | 3 | | 173 | 3 | std::vector<InputSectionBase *> sections; | 174 | 3 | for (InputSectionBase *sec : inputSections) | 175 | 27 | if (sec->type == SHT_MIPS_OPTIONS) | 176 | 3 | sections.push_back(sec); | 177 | 3 | | 178 | 3 | if (sections.empty()) | 179 | 0 | return nullptr; | 180 | 3 | | 181 | 3 | Elf_Mips_RegInfo reginfo = {}; | 182 | 3 | for (InputSectionBase *sec : sections) { | 183 | 3 | sec->markDead(); | 184 | 3 | | 185 | 3 | std::string filename = toString(sec->file); | 186 | 3 | ArrayRef<uint8_t> d = sec->data(); | 187 | 3 | | 188 | 3 | while (!d.empty()) { | 189 | 3 | if (d.size() < sizeof(Elf_Mips_Options)) { | 190 | 0 | error(filename + ": invalid size of .MIPS.options section"); | 191 | 0 | break; | 192 | 0 | } | 193 | 3 | | 194 | 3 | auto *opt = reinterpret_cast<const Elf_Mips_Options *>(d.data()); | 195 | 3 | if (opt->kind == ODK_REGINFO) { | 196 | 3 | reginfo.ri_gprmask |= opt->getRegInfo().ri_gprmask; | 197 | 3 | sec->getFile<ELFT>()->mipsGp0 = opt->getRegInfo().ri_gp_value; | 198 | 3 | break; | 199 | 3 | } | 200 | 0 | | 201 | 0 | if (!opt->size) | 202 | 0 | fatal(filename + ": zero option descriptor size"); | 203 | 0 | d = d.slice(opt->size); | 204 | 0 | } | 205 | 3 | }; | 206 | 3 | | 207 | 3 | return make<MipsOptionsSection<ELFT>>(reginfo); | 208 | 3 | } |
lld::elf::MipsOptionsSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::create() Line | Count | Source | 168 | 45 | MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() { | 169 | 45 | // N64 ABI only. | 170 | 45 | if (!ELFT::Is64Bits) | 171 | 0 | return nullptr; | 172 | 45 | | 173 | 45 | std::vector<InputSectionBase *> sections; | 174 | 45 | for (InputSectionBase *sec : inputSections) | 175 | 452 | if (sec->type == SHT_MIPS_OPTIONS) | 176 | 47 | sections.push_back(sec); | 177 | 45 | | 178 | 45 | if (sections.empty()) | 179 | 6 | return nullptr; | 180 | 39 | | 181 | 39 | Elf_Mips_RegInfo reginfo = {}; | 182 | 47 | for (InputSectionBase *sec : sections) { | 183 | 47 | sec->markDead(); | 184 | 47 | | 185 | 47 | std::string filename = toString(sec->file); | 186 | 47 | ArrayRef<uint8_t> d = sec->data(); | 187 | 47 | | 188 | 47 | while (!d.empty()) { | 189 | 47 | if (d.size() < sizeof(Elf_Mips_Options)) { | 190 | 0 | error(filename + ": invalid size of .MIPS.options section"); | 191 | 0 | break; | 192 | 0 | } | 193 | 47 | | 194 | 47 | auto *opt = reinterpret_cast<const Elf_Mips_Options *>(d.data()); | 195 | 47 | if (opt->kind == ODK_REGINFO) { | 196 | 47 | reginfo.ri_gprmask |= opt->getRegInfo().ri_gprmask; | 197 | 47 | sec->getFile<ELFT>()->mipsGp0 = opt->getRegInfo().ri_gp_value; | 198 | 47 | break; | 199 | 47 | } | 200 | 0 | | 201 | 0 | if (!opt->size) | 202 | 0 | fatal(filename + ": zero option descriptor size"); | 203 | 0 | d = d.slice(opt->size); | 204 | 0 | } | 205 | 47 | }; | 206 | 39 | | 207 | 39 | return make<MipsOptionsSection<ELFT>>(reginfo); | 208 | 39 | } |
|
209 | | |
210 | | // MIPS .reginfo section. |
211 | | template <class ELFT> |
212 | | MipsReginfoSection<ELFT>::MipsReginfoSection(Elf_Mips_RegInfo reginfo) |
213 | | : SyntheticSection(SHF_ALLOC, SHT_MIPS_REGINFO, 4, ".reginfo"), |
214 | 146 | reginfo(reginfo) { |
215 | 146 | this->entsize = sizeof(Elf_Mips_RegInfo); |
216 | 146 | } lld::elf::MipsReginfoSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::MipsReginfoSection(llvm::object::Elf_Mips_RegInfo<llvm::object::ELFType<(llvm::support::endianness)1, false> >) Line | Count | Source | 214 | 23 | reginfo(reginfo) { | 215 | 23 | this->entsize = sizeof(Elf_Mips_RegInfo); | 216 | 23 | } |
lld::elf::MipsReginfoSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::MipsReginfoSection(llvm::object::Elf_Mips_RegInfo<llvm::object::ELFType<(llvm::support::endianness)0, false> >) Line | Count | Source | 214 | 123 | reginfo(reginfo) { | 215 | 123 | this->entsize = sizeof(Elf_Mips_RegInfo); | 216 | 123 | } |
Unexecuted instantiation: lld::elf::MipsReginfoSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::MipsReginfoSection(llvm::object::Elf_Mips_RegInfo<llvm::object::ELFType<(llvm::support::endianness)1, true> >) Unexecuted instantiation: lld::elf::MipsReginfoSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::MipsReginfoSection(llvm::object::Elf_Mips_RegInfo<llvm::object::ELFType<(llvm::support::endianness)0, true> >) |
217 | | |
218 | 144 | template <class ELFT> void MipsReginfoSection<ELFT>::writeTo(uint8_t *buf) { |
219 | 144 | if (!config->relocatable) |
220 | 132 | reginfo.ri_gp_value = in.mipsGot->getGp(); |
221 | 144 | memcpy(buf, ®info, sizeof(reginfo)); |
222 | 144 | } lld::elf::MipsReginfoSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*) Line | Count | Source | 218 | 22 | template <class ELFT> void MipsReginfoSection<ELFT>::writeTo(uint8_t *buf) { | 219 | 22 | if (!config->relocatable) | 220 | 21 | reginfo.ri_gp_value = in.mipsGot->getGp(); | 221 | 22 | memcpy(buf, ®info, sizeof(reginfo)); | 222 | 22 | } |
lld::elf::MipsReginfoSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::writeTo(unsigned char*) Line | Count | Source | 218 | 122 | template <class ELFT> void MipsReginfoSection<ELFT>::writeTo(uint8_t *buf) { | 219 | 122 | if (!config->relocatable) | 220 | 111 | reginfo.ri_gp_value = in.mipsGot->getGp(); | 221 | 122 | memcpy(buf, ®info, sizeof(reginfo)); | 222 | 122 | } |
Unexecuted instantiation: lld::elf::MipsReginfoSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeTo(unsigned char*) Unexecuted instantiation: lld::elf::MipsReginfoSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::writeTo(unsigned char*) |
223 | | |
224 | | template <class ELFT> |
225 | 198 | MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() { |
226 | 198 | // Section should be alive for O32 and N32 ABIs only. |
227 | 198 | if (ELFT::Is64Bits) |
228 | 48 | return nullptr; |
229 | 150 | |
230 | 150 | std::vector<InputSectionBase *> sections; |
231 | 150 | for (InputSectionBase *sec : inputSections) |
232 | 1.65k | if (sec->type == SHT_MIPS_REGINFO) |
233 | 196 | sections.push_back(sec); |
234 | 150 | |
235 | 150 | if (sections.empty()) |
236 | 4 | return nullptr; |
237 | 146 | |
238 | 146 | Elf_Mips_RegInfo reginfo = {}; |
239 | 196 | for (InputSectionBase *sec : sections) { |
240 | 196 | sec->markDead(); |
241 | 196 | |
242 | 196 | if (sec->data().size() != sizeof(Elf_Mips_RegInfo)) { |
243 | 0 | error(toString(sec->file) + ": invalid size of .reginfo section"); |
244 | 0 | return nullptr; |
245 | 0 | } |
246 | 196 | |
247 | 196 | auto *r = reinterpret_cast<const Elf_Mips_RegInfo *>(sec->data().data()); |
248 | 196 | reginfo.ri_gprmask |= r->ri_gprmask; |
249 | 196 | sec->getFile<ELFT>()->mipsGp0 = r->ri_gp_value; |
250 | 196 | }; |
251 | 146 | |
252 | 146 | return make<MipsReginfoSection<ELFT>>(reginfo); |
253 | 146 | } lld::elf::MipsReginfoSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::create() Line | Count | Source | 225 | 24 | MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() { | 226 | 24 | // Section should be alive for O32 and N32 ABIs only. | 227 | 24 | if (ELFT::Is64Bits) | 228 | 0 | return nullptr; | 229 | 24 | | 230 | 24 | std::vector<InputSectionBase *> sections; | 231 | 24 | for (InputSectionBase *sec : inputSections) | 232 | 241 | if (sec->type == SHT_MIPS_REGINFO) | 233 | 28 | sections.push_back(sec); | 234 | 24 | | 235 | 24 | if (sections.empty()) | 236 | 1 | return nullptr; | 237 | 23 | | 238 | 23 | Elf_Mips_RegInfo reginfo = {}; | 239 | 28 | for (InputSectionBase *sec : sections) { | 240 | 28 | sec->markDead(); | 241 | 28 | | 242 | 28 | if (sec->data().size() != sizeof(Elf_Mips_RegInfo)) { | 243 | 0 | error(toString(sec->file) + ": invalid size of .reginfo section"); | 244 | 0 | return nullptr; | 245 | 0 | } | 246 | 28 | | 247 | 28 | auto *r = reinterpret_cast<const Elf_Mips_RegInfo *>(sec->data().data()); | 248 | 28 | reginfo.ri_gprmask |= r->ri_gprmask; | 249 | 28 | sec->getFile<ELFT>()->mipsGp0 = r->ri_gp_value; | 250 | 28 | }; | 251 | 23 | | 252 | 23 | return make<MipsReginfoSection<ELFT>>(reginfo); | 253 | 23 | } |
lld::elf::MipsReginfoSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::create() Line | Count | Source | 225 | 126 | MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() { | 226 | 126 | // Section should be alive for O32 and N32 ABIs only. | 227 | 126 | if (ELFT::Is64Bits) | 228 | 0 | return nullptr; | 229 | 126 | | 230 | 126 | std::vector<InputSectionBase *> sections; | 231 | 126 | for (InputSectionBase *sec : inputSections) | 232 | 1.41k | if (sec->type == SHT_MIPS_REGINFO) | 233 | 168 | sections.push_back(sec); | 234 | 126 | | 235 | 126 | if (sections.empty()) | 236 | 3 | return nullptr; | 237 | 123 | | 238 | 123 | Elf_Mips_RegInfo reginfo = {}; | 239 | 168 | for (InputSectionBase *sec : sections) { | 240 | 168 | sec->markDead(); | 241 | 168 | | 242 | 168 | if (sec->data().size() != sizeof(Elf_Mips_RegInfo)) { | 243 | 0 | error(toString(sec->file) + ": invalid size of .reginfo section"); | 244 | 0 | return nullptr; | 245 | 0 | } | 246 | 168 | | 247 | 168 | auto *r = reinterpret_cast<const Elf_Mips_RegInfo *>(sec->data().data()); | 248 | 168 | reginfo.ri_gprmask |= r->ri_gprmask; | 249 | 168 | sec->getFile<ELFT>()->mipsGp0 = r->ri_gp_value; | 250 | 168 | }; | 251 | 123 | | 252 | 123 | return make<MipsReginfoSection<ELFT>>(reginfo); | 253 | 123 | } |
lld::elf::MipsReginfoSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::create() Line | Count | Source | 225 | 3 | MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() { | 226 | 3 | // Section should be alive for O32 and N32 ABIs only. | 227 | 3 | if (ELFT::Is64Bits) | 228 | 3 | return nullptr; | 229 | 0 | | 230 | 0 | std::vector<InputSectionBase *> sections; | 231 | 0 | for (InputSectionBase *sec : inputSections) | 232 | 0 | if (sec->type == SHT_MIPS_REGINFO) | 233 | 0 | sections.push_back(sec); | 234 | 0 |
| 235 | 0 | if (sections.empty()) | 236 | 0 | return nullptr; | 237 | 0 | | 238 | 0 | Elf_Mips_RegInfo reginfo = {}; | 239 | 0 | for (InputSectionBase *sec : sections) { | 240 | 0 | sec->markDead(); | 241 | 0 |
| 242 | 0 | if (sec->data().size() != sizeof(Elf_Mips_RegInfo)) { | 243 | 0 | error(toString(sec->file) + ": invalid size of .reginfo section"); | 244 | 0 | return nullptr; | 245 | 0 | } | 246 | 0 | | 247 | 0 | auto *r = reinterpret_cast<const Elf_Mips_RegInfo *>(sec->data().data()); | 248 | 0 | reginfo.ri_gprmask |= r->ri_gprmask; | 249 | 0 | sec->getFile<ELFT>()->mipsGp0 = r->ri_gp_value; | 250 | 0 | }; | 251 | 0 |
| 252 | 0 | return make<MipsReginfoSection<ELFT>>(reginfo); | 253 | 0 | } |
lld::elf::MipsReginfoSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::create() Line | Count | Source | 225 | 45 | MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() { | 226 | 45 | // Section should be alive for O32 and N32 ABIs only. | 227 | 45 | if (ELFT::Is64Bits) | 228 | 45 | return nullptr; | 229 | 0 | | 230 | 0 | std::vector<InputSectionBase *> sections; | 231 | 0 | for (InputSectionBase *sec : inputSections) | 232 | 0 | if (sec->type == SHT_MIPS_REGINFO) | 233 | 0 | sections.push_back(sec); | 234 | 0 |
| 235 | 0 | if (sections.empty()) | 236 | 0 | return nullptr; | 237 | 0 | | 238 | 0 | Elf_Mips_RegInfo reginfo = {}; | 239 | 0 | for (InputSectionBase *sec : sections) { | 240 | 0 | sec->markDead(); | 241 | 0 |
| 242 | 0 | if (sec->data().size() != sizeof(Elf_Mips_RegInfo)) { | 243 | 0 | error(toString(sec->file) + ": invalid size of .reginfo section"); | 244 | 0 | return nullptr; | 245 | 0 | } | 246 | 0 | | 247 | 0 | auto *r = reinterpret_cast<const Elf_Mips_RegInfo *>(sec->data().data()); | 248 | 0 | reginfo.ri_gprmask |= r->ri_gprmask; | 249 | 0 | sec->getFile<ELFT>()->mipsGp0 = r->ri_gp_value; | 250 | 0 | }; | 251 | 0 |
| 252 | 0 | return make<MipsReginfoSection<ELFT>>(reginfo); | 253 | 0 | } |
|
254 | | |
255 | 8 | InputSection *elf::createInterpSection() { |
256 | 8 | // StringSaver guarantees that the returned string ends with '\0'. |
257 | 8 | StringRef s = saver.save(config->dynamicLinker); |
258 | 8 | ArrayRef<uint8_t> contents = {(const uint8_t *)s.data(), s.size() + 1}; |
259 | 8 | |
260 | 8 | auto *sec = make<InputSection>(nullptr, SHF_ALLOC, SHT_PROGBITS, 1, contents, |
261 | 8 | ".interp"); |
262 | 8 | sec->markLive(); |
263 | 8 | return sec; |
264 | 8 | } |
265 | | |
266 | | Defined *elf::addSyntheticLocal(StringRef name, uint8_t type, uint64_t value, |
267 | 567 | uint64_t size, InputSectionBase §ion) { |
268 | 567 | auto *s = make<Defined>(section.file, name, STB_LOCAL, STV_DEFAULT, type, |
269 | 567 | value, size, §ion); |
270 | 567 | if (in.symTab) |
271 | 567 | in.symTab->addSymbol(s); |
272 | 567 | return s; |
273 | 567 | } |
274 | | |
275 | 19 | static size_t getHashSize() { |
276 | 19 | switch (config->buildId) { |
277 | 19 | case BuildIdKind::Fast: |
278 | 6 | return 8; |
279 | 19 | case BuildIdKind::Md5: |
280 | 4 | case BuildIdKind::Uuid: |
281 | 4 | return 16; |
282 | 6 | case BuildIdKind::Sha1: |
283 | 6 | return 20; |
284 | 4 | case BuildIdKind::Hexstring: |
285 | 3 | return config->buildIdVector.size(); |
286 | 4 | default: |
287 | 0 | llvm_unreachable("unknown BuildIdKind"); |
288 | 19 | } |
289 | 19 | } |
290 | | |
291 | | // This class represents a linker-synthesized .note.gnu.property section. |
292 | | // |
293 | | // In x86 and AArch64, object files may contain feature flags indicating the |
294 | | // features that they have used. The flags are stored in a .note.gnu.property |
295 | | // section. |
296 | | // |
297 | | // lld reads the sections from input files and merges them by computing AND of |
298 | | // the flags. The result is written as a new .note.gnu.property section. |
299 | | // |
300 | | // If the flag is zero (which indicates that the intersection of the feature |
301 | | // sets is empty, or some input files didn't have .note.gnu.property sections), |
302 | | // we don't create this section. |
303 | | GnuPropertySection::GnuPropertySection() |
304 | | : SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE, 4, |
305 | 24 | ".note.gnu.property") {} |
306 | | |
307 | 24 | void GnuPropertySection::writeTo(uint8_t *buf) { |
308 | 24 | uint32_t featureAndType = config->emachine == EM_AARCH64 |
309 | 24 | ? GNU_PROPERTY_AARCH64_FEATURE_1_AND11 |
310 | 24 | : GNU_PROPERTY_X86_FEATURE_1_AND13 ; |
311 | 24 | |
312 | 24 | write32(buf, 4); // Name size |
313 | 24 | write32(buf + 4, config->is64 ? 1621 : 123 ); // Content size |
314 | 24 | write32(buf + 8, NT_GNU_PROPERTY_TYPE_0); // Type |
315 | 24 | memcpy(buf + 12, "GNU", 4); // Name string |
316 | 24 | write32(buf + 16, featureAndType); // Feature type |
317 | 24 | write32(buf + 20, 4); // Feature size |
318 | 24 | write32(buf + 24, config->andFeatures); // Feature flags |
319 | 24 | if (config->is64) |
320 | 21 | write32(buf + 28, 0); // Padding |
321 | 24 | } |
322 | | |
323 | 96 | size_t GnuPropertySection::getSize() const { return config->is64 ? 3284 : 2812 ; } |
324 | | |
325 | | BuildIdSection::BuildIdSection() |
326 | | : SyntheticSection(SHF_ALLOC, SHT_NOTE, 4, ".note.gnu.build-id"), |
327 | 19 | hashSize(getHashSize()) {} |
328 | | |
329 | 19 | void BuildIdSection::writeTo(uint8_t *buf) { |
330 | 19 | write32(buf, 4); // Name size |
331 | 19 | write32(buf + 4, hashSize); // Content size |
332 | 19 | write32(buf + 8, NT_GNU_BUILD_ID); // Type |
333 | 19 | memcpy(buf + 12, "GNU", 4); // Name string |
334 | 19 | hashBuf = buf + 16; |
335 | 19 | } |
336 | | |
337 | 19 | void BuildIdSection::writeBuildId(ArrayRef<uint8_t> buf) { |
338 | 19 | assert(buf.size() == hashSize); |
339 | 19 | memcpy(hashBuf, buf.data(), hashSize); |
340 | 19 | } |
341 | | |
342 | | BssSection::BssSection(StringRef name, uint64_t size, uint32_t alignment) |
343 | 5.67k | : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, alignment, name) { |
344 | 5.67k | this->bss = true; |
345 | 5.67k | this->size = size; |
346 | 5.67k | } |
347 | | |
348 | | EhFrameSection::EhFrameSection() |
349 | 2.68k | : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 1, ".eh_frame") {} |
350 | | |
351 | | // Search for an existing CIE record or create a new one. |
352 | | // CIE records from input object files are uniquified by their contents |
353 | | // and where their relocations point to. |
354 | | template <class ELFT, class RelTy> |
355 | 108 | CieRecord *EhFrameSection::addCie(EhSectionPiece &cie, ArrayRef<RelTy> rels) { |
356 | 108 | Symbol *personality = nullptr; |
357 | 108 | unsigned firstRelI = cie.firstRelocation; |
358 | 108 | if (firstRelI != (unsigned)-1) |
359 | 11 | personality = |
360 | 11 | &cie.sec->template getFile<ELFT>()->getRelocTargetSym(rels[firstRelI]); |
361 | 108 | |
362 | 108 | // Search for an existing CIE by CIE contents/relocation target pair. |
363 | 108 | CieRecord *&rec = cieMap[{cie.data(), personality}]; |
364 | 108 | |
365 | 108 | // If not found, create a new one. |
366 | 108 | if (!rec) { |
367 | 95 | rec = make<CieRecord>(); |
368 | 95 | rec->cie = &cie; |
369 | 95 | cieRecords.push_back(rec); |
370 | 95 | } |
371 | 108 | return rec; |
372 | 108 | } Unexecuted instantiation: lld::elf::CieRecord* lld::elf::EhFrameSection::addCie<llvm::object::ELFType<(llvm::support::endianness)1, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> >) lld::elf::CieRecord* lld::elf::EhFrameSection::addCie<llvm::object::ELFType<(llvm::support::endianness)1, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> >) Line | Count | Source | 355 | 4 | CieRecord *EhFrameSection::addCie(EhSectionPiece &cie, ArrayRef<RelTy> rels) { | 356 | 4 | Symbol *personality = nullptr; | 357 | 4 | unsigned firstRelI = cie.firstRelocation; | 358 | 4 | if (firstRelI != (unsigned)-1) | 359 | 2 | personality = | 360 | 2 | &cie.sec->template getFile<ELFT>()->getRelocTargetSym(rels[firstRelI]); | 361 | 4 | | 362 | 4 | // Search for an existing CIE by CIE contents/relocation target pair. | 363 | 4 | CieRecord *&rec = cieMap[{cie.data(), personality}]; | 364 | 4 | | 365 | 4 | // If not found, create a new one. | 366 | 4 | if (!rec) { | 367 | 3 | rec = make<CieRecord>(); | 368 | 3 | rec->cie = &cie; | 369 | 3 | cieRecords.push_back(rec); | 370 | 3 | } | 371 | 4 | return rec; | 372 | 4 | } |
Unexecuted instantiation: lld::elf::CieRecord* lld::elf::EhFrameSection::addCie<llvm::object::ELFType<(llvm::support::endianness)0, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> >) Unexecuted instantiation: lld::elf::CieRecord* lld::elf::EhFrameSection::addCie<llvm::object::ELFType<(llvm::support::endianness)0, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> >) lld::elf::CieRecord* lld::elf::EhFrameSection::addCie<llvm::object::ELFType<(llvm::support::endianness)1, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> >) Line | Count | Source | 355 | 93 | CieRecord *EhFrameSection::addCie(EhSectionPiece &cie, ArrayRef<RelTy> rels) { | 356 | 93 | Symbol *personality = nullptr; | 357 | 93 | unsigned firstRelI = cie.firstRelocation; | 358 | 93 | if (firstRelI != (unsigned)-1) | 359 | 8 | personality = | 360 | 8 | &cie.sec->template getFile<ELFT>()->getRelocTargetSym(rels[firstRelI]); | 361 | 93 | | 362 | 93 | // Search for an existing CIE by CIE contents/relocation target pair. | 363 | 93 | CieRecord *&rec = cieMap[{cie.data(), personality}]; | 364 | 93 | | 365 | 93 | // If not found, create a new one. | 366 | 93 | if (!rec) { | 367 | 81 | rec = make<CieRecord>(); | 368 | 81 | rec->cie = &cie; | 369 | 81 | cieRecords.push_back(rec); | 370 | 81 | } | 371 | 93 | return rec; | 372 | 93 | } |
lld::elf::CieRecord* lld::elf::EhFrameSection::addCie<llvm::object::ELFType<(llvm::support::endianness)1, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> >) Line | Count | Source | 355 | 7 | CieRecord *EhFrameSection::addCie(EhSectionPiece &cie, ArrayRef<RelTy> rels) { | 356 | 7 | Symbol *personality = nullptr; | 357 | 7 | unsigned firstRelI = cie.firstRelocation; | 358 | 7 | if (firstRelI != (unsigned)-1) | 359 | 0 | personality = | 360 | 0 | &cie.sec->template getFile<ELFT>()->getRelocTargetSym(rels[firstRelI]); | 361 | 7 | | 362 | 7 | // Search for an existing CIE by CIE contents/relocation target pair. | 363 | 7 | CieRecord *&rec = cieMap[{cie.data(), personality}]; | 364 | 7 | | 365 | 7 | // If not found, create a new one. | 366 | 7 | if (!rec) { | 367 | 7 | rec = make<CieRecord>(); | 368 | 7 | rec->cie = &cie; | 369 | 7 | cieRecords.push_back(rec); | 370 | 7 | } | 371 | 7 | return rec; | 372 | 7 | } |
lld::elf::CieRecord* lld::elf::EhFrameSection::addCie<llvm::object::ELFType<(llvm::support::endianness)0, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> >) Line | Count | Source | 355 | 3 | CieRecord *EhFrameSection::addCie(EhSectionPiece &cie, ArrayRef<RelTy> rels) { | 356 | 3 | Symbol *personality = nullptr; | 357 | 3 | unsigned firstRelI = cie.firstRelocation; | 358 | 3 | if (firstRelI != (unsigned)-1) | 359 | 1 | personality = | 360 | 1 | &cie.sec->template getFile<ELFT>()->getRelocTargetSym(rels[firstRelI]); | 361 | 3 | | 362 | 3 | // Search for an existing CIE by CIE contents/relocation target pair. | 363 | 3 | CieRecord *&rec = cieMap[{cie.data(), personality}]; | 364 | 3 | | 365 | 3 | // If not found, create a new one. | 366 | 3 | if (!rec) { | 367 | 3 | rec = make<CieRecord>(); | 368 | 3 | rec->cie = &cie; | 369 | 3 | cieRecords.push_back(rec); | 370 | 3 | } | 371 | 3 | return rec; | 372 | 3 | } |
lld::elf::CieRecord* lld::elf::EhFrameSection::addCie<llvm::object::ELFType<(llvm::support::endianness)0, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> >) Line | Count | Source | 355 | 1 | CieRecord *EhFrameSection::addCie(EhSectionPiece &cie, ArrayRef<RelTy> rels) { | 356 | 1 | Symbol *personality = nullptr; | 357 | 1 | unsigned firstRelI = cie.firstRelocation; | 358 | 1 | if (firstRelI != (unsigned)-1) | 359 | 0 | personality = | 360 | 0 | &cie.sec->template getFile<ELFT>()->getRelocTargetSym(rels[firstRelI]); | 361 | 1 | | 362 | 1 | // Search for an existing CIE by CIE contents/relocation target pair. | 363 | 1 | CieRecord *&rec = cieMap[{cie.data(), personality}]; | 364 | 1 | | 365 | 1 | // If not found, create a new one. | 366 | 1 | if (!rec) { | 367 | 1 | rec = make<CieRecord>(); | 368 | 1 | rec->cie = &cie; | 369 | 1 | cieRecords.push_back(rec); | 370 | 1 | } | 371 | 1 | return rec; | 372 | 1 | } |
|
373 | | |
374 | | // There is one FDE per function. Returns true if a given FDE |
375 | | // points to a live function. |
376 | | template <class ELFT, class RelTy> |
377 | 136 | bool EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) { |
378 | 136 | auto *sec = cast<EhInputSection>(fde.sec); |
379 | 136 | unsigned firstRelI = fde.firstRelocation; |
380 | 136 | |
381 | 136 | // An FDE should point to some function because FDEs are to describe |
382 | 136 | // functions. That's however not always the case due to an issue of |
383 | 136 | // ld.gold with -r. ld.gold may discard only functions and leave their |
384 | 136 | // corresponding FDEs, which results in creating bad .eh_frame sections. |
385 | 136 | // To deal with that, we ignore such FDEs. |
386 | 136 | if (firstRelI == (unsigned)-1) |
387 | 1 | return false; |
388 | 135 | |
389 | 135 | const RelTy &rel = rels[firstRelI]; |
390 | 135 | Symbol &b = sec->template getFile<ELFT>()->getRelocTargetSym(rel); |
391 | 135 | |
392 | 135 | // FDEs for garbage-collected or merged-by-ICF sections, or sections in |
393 | 135 | // another partition, are dead. |
394 | 135 | if (auto *d = dyn_cast<Defined>(&b)) |
395 | 133 | if (SectionBase *sec = d->section) |
396 | 133 | return sec->partition == partition; |
397 | 2 | return false; |
398 | 2 | } Unexecuted instantiation: bool lld::elf::EhFrameSection::isFdeLive<llvm::object::ELFType<(llvm::support::endianness)1, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> >) bool lld::elf::EhFrameSection::isFdeLive<llvm::object::ELFType<(llvm::support::endianness)1, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> >) Line | Count | Source | 377 | 4 | bool EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) { | 378 | 4 | auto *sec = cast<EhInputSection>(fde.sec); | 379 | 4 | unsigned firstRelI = fde.firstRelocation; | 380 | 4 | | 381 | 4 | // An FDE should point to some function because FDEs are to describe | 382 | 4 | // functions. That's however not always the case due to an issue of | 383 | 4 | // ld.gold with -r. ld.gold may discard only functions and leave their | 384 | 4 | // corresponding FDEs, which results in creating bad .eh_frame sections. | 385 | 4 | // To deal with that, we ignore such FDEs. | 386 | 4 | if (firstRelI == (unsigned)-1) | 387 | 0 | return false; | 388 | 4 | | 389 | 4 | const RelTy &rel = rels[firstRelI]; | 390 | 4 | Symbol &b = sec->template getFile<ELFT>()->getRelocTargetSym(rel); | 391 | 4 | | 392 | 4 | // FDEs for garbage-collected or merged-by-ICF sections, or sections in | 393 | 4 | // another partition, are dead. | 394 | 4 | if (auto *d = dyn_cast<Defined>(&b)) | 395 | 4 | if (SectionBase *sec = d->section) | 396 | 4 | return sec->partition == partition; | 397 | 0 | return false; | 398 | 0 | } |
Unexecuted instantiation: bool lld::elf::EhFrameSection::isFdeLive<llvm::object::ELFType<(llvm::support::endianness)0, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> >) Unexecuted instantiation: bool lld::elf::EhFrameSection::isFdeLive<llvm::object::ELFType<(llvm::support::endianness)0, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> >) bool lld::elf::EhFrameSection::isFdeLive<llvm::object::ELFType<(llvm::support::endianness)1, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> >) Line | Count | Source | 377 | 128 | bool EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) { | 378 | 128 | auto *sec = cast<EhInputSection>(fde.sec); | 379 | 128 | unsigned firstRelI = fde.firstRelocation; | 380 | 128 | | 381 | 128 | // An FDE should point to some function because FDEs are to describe | 382 | 128 | // functions. That's however not always the case due to an issue of | 383 | 128 | // ld.gold with -r. ld.gold may discard only functions and leave their | 384 | 128 | // corresponding FDEs, which results in creating bad .eh_frame sections. | 385 | 128 | // To deal with that, we ignore such FDEs. | 386 | 128 | if (firstRelI == (unsigned)-1) | 387 | 0 | return false; | 388 | 128 | | 389 | 128 | const RelTy &rel = rels[firstRelI]; | 390 | 128 | Symbol &b = sec->template getFile<ELFT>()->getRelocTargetSym(rel); | 391 | 128 | | 392 | 128 | // FDEs for garbage-collected or merged-by-ICF sections, or sections in | 393 | 128 | // another partition, are dead. | 394 | 128 | if (auto *d = dyn_cast<Defined>(&b)) | 395 | 126 | if (SectionBase *sec = d->section) | 396 | 126 | return sec->partition == partition; | 397 | 2 | return false; | 398 | 2 | } |
bool lld::elf::EhFrameSection::isFdeLive<llvm::object::ELFType<(llvm::support::endianness)1, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> >) Line | Count | Source | 377 | 1 | bool EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) { | 378 | 1 | auto *sec = cast<EhInputSection>(fde.sec); | 379 | 1 | unsigned firstRelI = fde.firstRelocation; | 380 | 1 | | 381 | 1 | // An FDE should point to some function because FDEs are to describe | 382 | 1 | // functions. That's however not always the case due to an issue of | 383 | 1 | // ld.gold with -r. ld.gold may discard only functions and leave their | 384 | 1 | // corresponding FDEs, which results in creating bad .eh_frame sections. | 385 | 1 | // To deal with that, we ignore such FDEs. | 386 | 1 | if (firstRelI == (unsigned)-1) | 387 | 1 | return false; | 388 | 0 | | 389 | 0 | const RelTy &rel = rels[firstRelI]; | 390 | 0 | Symbol &b = sec->template getFile<ELFT>()->getRelocTargetSym(rel); | 391 | 0 |
| 392 | 0 | // FDEs for garbage-collected or merged-by-ICF sections, or sections in | 393 | 0 | // another partition, are dead. | 394 | 0 | if (auto *d = dyn_cast<Defined>(&b)) | 395 | 0 | if (SectionBase *sec = d->section) | 396 | 0 | return sec->partition == partition; | 397 | 0 | return false; | 398 | 0 | } |
bool lld::elf::EhFrameSection::isFdeLive<llvm::object::ELFType<(llvm::support::endianness)0, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> >) Line | Count | Source | 377 | 3 | bool EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) { | 378 | 3 | auto *sec = cast<EhInputSection>(fde.sec); | 379 | 3 | unsigned firstRelI = fde.firstRelocation; | 380 | 3 | | 381 | 3 | // An FDE should point to some function because FDEs are to describe | 382 | 3 | // functions. That's however not always the case due to an issue of | 383 | 3 | // ld.gold with -r. ld.gold may discard only functions and leave their | 384 | 3 | // corresponding FDEs, which results in creating bad .eh_frame sections. | 385 | 3 | // To deal with that, we ignore such FDEs. | 386 | 3 | if (firstRelI == (unsigned)-1) | 387 | 0 | return false; | 388 | 3 | | 389 | 3 | const RelTy &rel = rels[firstRelI]; | 390 | 3 | Symbol &b = sec->template getFile<ELFT>()->getRelocTargetSym(rel); | 391 | 3 | | 392 | 3 | // FDEs for garbage-collected or merged-by-ICF sections, or sections in | 393 | 3 | // another partition, are dead. | 394 | 3 | if (auto *d = dyn_cast<Defined>(&b)) | 395 | 3 | if (SectionBase *sec = d->section) | 396 | 3 | return sec->partition == partition; | 397 | 0 | return false; | 398 | 0 | } |
Unexecuted instantiation: bool lld::elf::EhFrameSection::isFdeLive<llvm::object::ELFType<(llvm::support::endianness)0, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> >(lld::elf::EhSectionPiece&, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> >) |
399 | | |
400 | | // .eh_frame is a sequence of CIE or FDE records. In general, there |
401 | | // is one CIE record per input object file which is followed by |
402 | | // a list of FDEs. This function searches an existing CIE or create a new |
403 | | // one and associates FDEs to the CIE. |
404 | | template <class ELFT, class RelTy> |
405 | 114 | void EhFrameSection::addSectionAux(EhInputSection *sec, ArrayRef<RelTy> rels) { |
406 | 114 | offsetToCie.clear(); |
407 | 251 | for (EhSectionPiece &piece : sec->pieces) { |
408 | 251 | // The empty record is the end marker. |
409 | 251 | if (piece.size == 4) |
410 | 7 | return; |
411 | 244 | |
412 | 244 | size_t offset = piece.inputOff; |
413 | 244 | uint32_t id = read32(piece.data().data() + 4); |
414 | 244 | if (id == 0) { |
415 | 108 | offsetToCie[offset] = addCie<ELFT>(piece, rels); |
416 | 108 | continue; |
417 | 108 | } |
418 | 136 | |
419 | 136 | uint32_t cieOffset = offset + 4 - id; |
420 | 136 | CieRecord *rec = offsetToCie[cieOffset]; |
421 | 136 | if (!rec) |
422 | 0 | fatal(toString(sec) + ": invalid CIE reference"); |
423 | 136 | |
424 | 136 | if (!isFdeLive<ELFT>(piece, rels)) |
425 | 11 | continue; |
426 | 125 | rec->fdes.push_back(&piece); |
427 | 125 | numFdes++; |
428 | 125 | } |
429 | 114 | } Unexecuted instantiation: void lld::elf::EhFrameSection::addSectionAux<llvm::object::ELFType<(llvm::support::endianness)1, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> >(lld::elf::EhInputSection*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> >) void lld::elf::EhFrameSection::addSectionAux<llvm::object::ELFType<(llvm::support::endianness)1, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> >(lld::elf::EhInputSection*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> >) Line | Count | Source | 405 | 4 | void EhFrameSection::addSectionAux(EhInputSection *sec, ArrayRef<RelTy> rels) { | 406 | 4 | offsetToCie.clear(); | 407 | 8 | for (EhSectionPiece &piece : sec->pieces) { | 408 | 8 | // The empty record is the end marker. | 409 | 8 | if (piece.size == 4) | 410 | 0 | return; | 411 | 8 | | 412 | 8 | size_t offset = piece.inputOff; | 413 | 8 | uint32_t id = read32(piece.data().data() + 4); | 414 | 8 | if (id == 0) { | 415 | 4 | offsetToCie[offset] = addCie<ELFT>(piece, rels); | 416 | 4 | continue; | 417 | 4 | } | 418 | 4 | | 419 | 4 | uint32_t cieOffset = offset + 4 - id; | 420 | 4 | CieRecord *rec = offsetToCie[cieOffset]; | 421 | 4 | if (!rec) | 422 | 0 | fatal(toString(sec) + ": invalid CIE reference"); | 423 | 4 | | 424 | 4 | if (!isFdeLive<ELFT>(piece, rels)) | 425 | 0 | continue; | 426 | 4 | rec->fdes.push_back(&piece); | 427 | 4 | numFdes++; | 428 | 4 | } | 429 | 4 | } |
Unexecuted instantiation: void lld::elf::EhFrameSection::addSectionAux<llvm::object::ELFType<(llvm::support::endianness)0, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> >(lld::elf::EhInputSection*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> >) Unexecuted instantiation: void lld::elf::EhFrameSection::addSectionAux<llvm::object::ELFType<(llvm::support::endianness)0, false>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> >(lld::elf::EhInputSection*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> >) void lld::elf::EhFrameSection::addSectionAux<llvm::object::ELFType<(llvm::support::endianness)1, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> >(lld::elf::EhInputSection*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> >) Line | Count | Source | 405 | 93 | void EhFrameSection::addSectionAux(EhInputSection *sec, ArrayRef<RelTy> rels) { | 406 | 93 | offsetToCie.clear(); | 407 | 222 | for (EhSectionPiece &piece : sec->pieces) { | 408 | 222 | // The empty record is the end marker. | 409 | 222 | if (piece.size == 4) | 410 | 1 | return; | 411 | 221 | | 412 | 221 | size_t offset = piece.inputOff; | 413 | 221 | uint32_t id = read32(piece.data().data() + 4); | 414 | 221 | if (id == 0) { | 415 | 93 | offsetToCie[offset] = addCie<ELFT>(piece, rels); | 416 | 93 | continue; | 417 | 93 | } | 418 | 128 | | 419 | 128 | uint32_t cieOffset = offset + 4 - id; | 420 | 128 | CieRecord *rec = offsetToCie[cieOffset]; | 421 | 128 | if (!rec) | 422 | 0 | fatal(toString(sec) + ": invalid CIE reference"); | 423 | 128 | | 424 | 128 | if (!isFdeLive<ELFT>(piece, rels)) | 425 | 10 | continue; | 426 | 118 | rec->fdes.push_back(&piece); | 427 | 118 | numFdes++; | 428 | 118 | } | 429 | 93 | } |
void lld::elf::EhFrameSection::addSectionAux<llvm::object::ELFType<(llvm::support::endianness)1, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> >(lld::elf::EhInputSection*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> >) Line | Count | Source | 405 | 13 | void EhFrameSection::addSectionAux(EhInputSection *sec, ArrayRef<RelTy> rels) { | 406 | 13 | offsetToCie.clear(); | 407 | 14 | for (EhSectionPiece &piece : sec->pieces) { | 408 | 14 | // The empty record is the end marker. | 409 | 14 | if (piece.size == 4) | 410 | 6 | return; | 411 | 8 | | 412 | 8 | size_t offset = piece.inputOff; | 413 | 8 | uint32_t id = read32(piece.data().data() + 4); | 414 | 8 | if (id == 0) { | 415 | 7 | offsetToCie[offset] = addCie<ELFT>(piece, rels); | 416 | 7 | continue; | 417 | 7 | } | 418 | 1 | | 419 | 1 | uint32_t cieOffset = offset + 4 - id; | 420 | 1 | CieRecord *rec = offsetToCie[cieOffset]; | 421 | 1 | if (!rec) | 422 | 0 | fatal(toString(sec) + ": invalid CIE reference"); | 423 | 1 | | 424 | 1 | if (!isFdeLive<ELFT>(piece, rels)) | 425 | 1 | continue; | 426 | 0 | rec->fdes.push_back(&piece); | 427 | 0 | numFdes++; | 428 | 0 | } | 429 | 13 | } |
void lld::elf::EhFrameSection::addSectionAux<llvm::object::ELFType<(llvm::support::endianness)0, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> >(lld::elf::EhInputSection*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> >) Line | Count | Source | 405 | 3 | void EhFrameSection::addSectionAux(EhInputSection *sec, ArrayRef<RelTy> rels) { | 406 | 3 | offsetToCie.clear(); | 407 | 6 | for (EhSectionPiece &piece : sec->pieces) { | 408 | 6 | // The empty record is the end marker. | 409 | 6 | if (piece.size == 4) | 410 | 0 | return; | 411 | 6 | | 412 | 6 | size_t offset = piece.inputOff; | 413 | 6 | uint32_t id = read32(piece.data().data() + 4); | 414 | 6 | if (id == 0) { | 415 | 3 | offsetToCie[offset] = addCie<ELFT>(piece, rels); | 416 | 3 | continue; | 417 | 3 | } | 418 | 3 | | 419 | 3 | uint32_t cieOffset = offset + 4 - id; | 420 | 3 | CieRecord *rec = offsetToCie[cieOffset]; | 421 | 3 | if (!rec) | 422 | 0 | fatal(toString(sec) + ": invalid CIE reference"); | 423 | 3 | | 424 | 3 | if (!isFdeLive<ELFT>(piece, rels)) | 425 | 0 | continue; | 426 | 3 | rec->fdes.push_back(&piece); | 427 | 3 | numFdes++; | 428 | 3 | } | 429 | 3 | } |
void lld::elf::EhFrameSection::addSectionAux<llvm::object::ELFType<(llvm::support::endianness)0, true>, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> >(lld::elf::EhInputSection*, llvm::ArrayRef<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> >) Line | Count | Source | 405 | 1 | void EhFrameSection::addSectionAux(EhInputSection *sec, ArrayRef<RelTy> rels) { | 406 | 1 | offsetToCie.clear(); | 407 | 1 | for (EhSectionPiece &piece : sec->pieces) { | 408 | 1 | // The empty record is the end marker. | 409 | 1 | if (piece.size == 4) | 410 | 0 | return; | 411 | 1 | | 412 | 1 | size_t offset = piece.inputOff; | 413 | 1 | uint32_t id = read32(piece.data().data() + 4); | 414 | 1 | if (id == 0) { | 415 | 1 | offsetToCie[offset] = addCie<ELFT>(piece, rels); | 416 | 1 | continue; | 417 | 1 | } | 418 | 0 | | 419 | 0 | uint32_t cieOffset = offset + 4 - id; | 420 | 0 | CieRecord *rec = offsetToCie[cieOffset]; | 421 | 0 | if (!rec) | 422 | 0 | fatal(toString(sec) + ": invalid CIE reference"); | 423 | 0 | | 424 | 0 | if (!isFdeLive<ELFT>(piece, rels)) | 425 | 0 | continue; | 426 | 0 | rec->fdes.push_back(&piece); | 427 | 0 | numFdes++; | 428 | 0 | } | 429 | 1 | } |
|
430 | | |
431 | 117 | template <class ELFT> void EhFrameSection::addSection(InputSectionBase *c) { |
432 | 117 | auto *sec = cast<EhInputSection>(c); |
433 | 117 | sec->parent = this; |
434 | 117 | |
435 | 117 | alignment = std::max(alignment, sec->alignment); |
436 | 117 | sections.push_back(sec); |
437 | 117 | |
438 | 117 | for (auto *ds : sec->dependentSections) |
439 | 3 | dependentSections.push_back(ds); |
440 | 117 | |
441 | 117 | if (sec->pieces.empty()) |
442 | 3 | return; |
443 | 114 | |
444 | 114 | if (sec->areRelocsRela) |
445 | 96 | addSectionAux<ELFT>(sec, sec->template relas<ELFT>()); |
446 | 18 | else |
447 | 18 | addSectionAux<ELFT>(sec, sec->template rels<ELFT>()); |
448 | 114 | } void lld::elf::EhFrameSection::addSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >(lld::elf::InputSectionBase*) Line | Count | Source | 431 | 4 | template <class ELFT> void EhFrameSection::addSection(InputSectionBase *c) { | 432 | 4 | auto *sec = cast<EhInputSection>(c); | 433 | 4 | sec->parent = this; | 434 | 4 | | 435 | 4 | alignment = std::max(alignment, sec->alignment); | 436 | 4 | sections.push_back(sec); | 437 | 4 | | 438 | 4 | for (auto *ds : sec->dependentSections) | 439 | 0 | dependentSections.push_back(ds); | 440 | 4 | | 441 | 4 | if (sec->pieces.empty()) | 442 | 0 | return; | 443 | 4 | | 444 | 4 | if (sec->areRelocsRela) | 445 | 0 | addSectionAux<ELFT>(sec, sec->template relas<ELFT>()); | 446 | 4 | else | 447 | 4 | addSectionAux<ELFT>(sec, sec->template rels<ELFT>()); | 448 | 4 | } |
Unexecuted instantiation: void lld::elf::EhFrameSection::addSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >(lld::elf::InputSectionBase*) void lld::elf::EhFrameSection::addSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >(lld::elf::InputSectionBase*) Line | Count | Source | 431 | 109 | template <class ELFT> void EhFrameSection::addSection(InputSectionBase *c) { | 432 | 109 | auto *sec = cast<EhInputSection>(c); | 433 | 109 | sec->parent = this; | 434 | 109 | | 435 | 109 | alignment = std::max(alignment, sec->alignment); | 436 | 109 | sections.push_back(sec); | 437 | 109 | | 438 | 109 | for (auto *ds : sec->dependentSections) | 439 | 3 | dependentSections.push_back(ds); | 440 | 109 | | 441 | 109 | if (sec->pieces.empty()) | 442 | 3 | return; | 443 | 106 | | 444 | 106 | if (sec->areRelocsRela) | 445 | 93 | addSectionAux<ELFT>(sec, sec->template relas<ELFT>()); | 446 | 13 | else | 447 | 13 | addSectionAux<ELFT>(sec, sec->template rels<ELFT>()); | 448 | 106 | } |
void lld::elf::EhFrameSection::addSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >(lld::elf::InputSectionBase*) Line | Count | Source | 431 | 4 | template <class ELFT> void EhFrameSection::addSection(InputSectionBase *c) { | 432 | 4 | auto *sec = cast<EhInputSection>(c); | 433 | 4 | sec->parent = this; | 434 | 4 | | 435 | 4 | alignment = std::max(alignment, sec->alignment); | 436 | 4 | sections.push_back(sec); | 437 | 4 | | 438 | 4 | for (auto *ds : sec->dependentSections) | 439 | 0 | dependentSections.push_back(ds); | 440 | 4 | | 441 | 4 | if (sec->pieces.empty()) | 442 | 0 | return; | 443 | 4 | | 444 | 4 | if (sec->areRelocsRela) | 445 | 3 | addSectionAux<ELFT>(sec, sec->template relas<ELFT>()); | 446 | 1 | else | 447 | 1 | addSectionAux<ELFT>(sec, sec->template rels<ELFT>()); | 448 | 4 | } |
|
449 | | |
450 | 210 | static void writeCieFde(uint8_t *buf, ArrayRef<uint8_t> d) { |
451 | 210 | memcpy(buf, d.data(), d.size()); |
452 | 210 | |
453 | 210 | size_t aligned = alignTo(d.size(), config->wordsize); |
454 | 210 | |
455 | 210 | // Zero-clear trailing padding if it exists. |
456 | 210 | memset(buf + d.size(), 0, aligned - d.size()); |
457 | 210 | |
458 | 210 | // Fix the size field. -4 since size does not include the size field itself. |
459 | 210 | write32(buf, aligned - 4); |
460 | 210 | } |
461 | | |
462 | 100 | void EhFrameSection::finalizeContents() { |
463 | 100 | assert(!this->size); // Not finalized. |
464 | 100 | size_t off = 0; |
465 | 100 | for (CieRecord *rec : cieRecords) { |
466 | 93 | rec->cie->outputOff = off; |
467 | 93 | off += alignTo(rec->cie->size, config->wordsize); |
468 | 93 | |
469 | 123 | for (EhSectionPiece *fde : rec->fdes) { |
470 | 123 | fde->outputOff = off; |
471 | 123 | off += alignTo(fde->size, config->wordsize); |
472 | 123 | } |
473 | 93 | } |
474 | 100 | |
475 | 100 | // The LSB standard does not allow a .eh_frame section with zero |
476 | 100 | // Call Frame Information records. glibc unwind-dw2-fde.c |
477 | 100 | // classify_object_over_fdes expects there is a CIE record length 0 as a |
478 | 100 | // terminator. Thus we add one unconditionally. |
479 | 100 | off += 4; |
480 | 100 | |
481 | 100 | this->size = off; |
482 | 100 | } |
483 | | |
484 | | // Returns data for .eh_frame_hdr. .eh_frame_hdr is a binary search table |
485 | | // to get an FDE from an address to which FDE is applied. This function |
486 | | // returns a list of such pairs. |
487 | 30 | std::vector<EhFrameSection::FdeData> EhFrameSection::getFdeData() const { |
488 | 30 | uint8_t *buf = Out::bufferStart + getParent()->offset + outSecOff; |
489 | 30 | std::vector<FdeData> ret; |
490 | 30 | |
491 | 30 | uint64_t va = getPartition().ehFrameHdr->getVA(); |
492 | 30 | for (CieRecord *rec : cieRecords) { |
493 | 30 | uint8_t enc = getFdeEncoding(rec->cie); |
494 | 30 | for (EhSectionPiece *fde : rec->fdes) { |
495 | 26 | uint64_t pc = getFdePc(buf, fde->outputOff, enc); |
496 | 26 | uint64_t fdeVA = getParent()->addr + fde->outputOff; |
497 | 26 | if (!isInt<32>(pc - va)) |
498 | 0 | fatal(toString(fde->sec) + ": PC offset is too large: 0x" + |
499 | 0 | Twine::utohexstr(pc - va)); |
500 | 26 | ret.push_back({uint32_t(pc - va), uint32_t(fdeVA - va)}); |
501 | 26 | } |
502 | 30 | } |
503 | 30 | |
504 | 30 | // Sort the FDE list by their PC and uniqueify. Usually there is only |
505 | 30 | // one FDE for a PC (i.e. function), but if ICF merges two functions |
506 | 30 | // into one, there can be more than one FDEs pointing to the address. |
507 | 30 | auto less = [](const FdeData &a, const FdeData &b) { |
508 | 4 | return a.pcRel < b.pcRel; |
509 | 4 | }; |
510 | 30 | llvm::stable_sort(ret, less); |
511 | 30 | auto eq = [](const FdeData &a, const FdeData &b) { |
512 | 4 | return a.pcRel == b.pcRel; |
513 | 4 | }; |
514 | 30 | ret.erase(std::unique(ret.begin(), ret.end(), eq), ret.end()); |
515 | 30 | |
516 | 30 | return ret; |
517 | 30 | } |
518 | | |
519 | 26 | static uint64_t readFdeAddr(uint8_t *buf, int size) { |
520 | 26 | switch (size) { |
521 | 26 | case DW_EH_PE_udata2: |
522 | 1 | return read16(buf); |
523 | 26 | case DW_EH_PE_sdata2: |
524 | 1 | return (int16_t)read16(buf); |
525 | 26 | case DW_EH_PE_udata4: |
526 | 0 | return read32(buf); |
527 | 26 | case DW_EH_PE_sdata4: |
528 | 19 | return (int32_t)read32(buf); |
529 | 26 | case DW_EH_PE_udata8: |
530 | 3 | case DW_EH_PE_sdata8: |
531 | 3 | return read64(buf); |
532 | 3 | case DW_EH_PE_absptr: |
533 | 2 | return readUint(buf); |
534 | 0 | } |
535 | 0 | fatal("unknown FDE size encoding"); |
536 | 0 | } |
537 | | |
538 | | // Returns the VA to which a given FDE (on a mmap'ed buffer) is applied to. |
539 | | // We need it to create .eh_frame_hdr section. |
540 | | uint64_t EhFrameSection::getFdePc(uint8_t *buf, size_t fdeOff, |
541 | 26 | uint8_t enc) const { |
542 | 26 | // The starting address to which this FDE applies is |
543 | 26 | // stored at FDE + 8 byte. |
544 | 26 | size_t off = fdeOff + 8; |
545 | 26 | uint64_t addr = readFdeAddr(buf + off, enc & 0xf); |
546 | 26 | if ((enc & 0x70) == DW_EH_PE_absptr) |
547 | 5 | return addr; |
548 | 21 | if ((enc & 0x70) == DW_EH_PE_pcrel) |
549 | 21 | return addr + getParent()->addr + off; |
550 | 0 | fatal("unknown FDE size relative encoding"); |
551 | 0 | } |
552 | | |
553 | 97 | void EhFrameSection::writeTo(uint8_t *buf) { |
554 | 97 | // Write CIE and FDE records. |
555 | 97 | for (CieRecord *rec : cieRecords) { |
556 | 90 | size_t cieOffset = rec->cie->outputOff; |
557 | 90 | writeCieFde(buf + cieOffset, rec->cie->data()); |
558 | 90 | |
559 | 120 | for (EhSectionPiece *fde : rec->fdes) { |
560 | 120 | size_t off = fde->outputOff; |
561 | 120 | writeCieFde(buf + off, fde->data()); |
562 | 120 | |
563 | 120 | // FDE's second word should have the offset to an associated CIE. |
564 | 120 | // Write it. |
565 | 120 | write32(buf + off + 4, off + 4 - cieOffset); |
566 | 120 | } |
567 | 90 | } |
568 | 97 | |
569 | 97 | // Apply relocations. .eh_frame section contents are not contiguous |
570 | 97 | // in the output buffer, but relocateAlloc() still works because |
571 | 97 | // getOffset() takes care of discontiguous section pieces. |
572 | 97 | for (EhInputSection *s : sections) |
573 | 111 | s->relocateAlloc(buf, nullptr); |
574 | 97 | |
575 | 97 | if (getPartition().ehFrameHdr && getPartition().ehFrameHdr->getParent()30 ) |
576 | 30 | getPartition().ehFrameHdr->write(); |
577 | 97 | } |
578 | | |
579 | | GotSection::GotSection() |
580 | | : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize, |
581 | 2.55k | ".got") { |
582 | 2.55k | // If ElfSym::globalOffsetTable is relative to .got and is referenced, |
583 | 2.55k | // increase numEntries by the number of entries used to emit |
584 | 2.55k | // ElfSym::globalOffsetTable. |
585 | 2.55k | if (ElfSym::globalOffsetTable && !target->gotBaseSymInGotPlt118 ) |
586 | 87 | numEntries += target->gotHeaderEntriesNum; |
587 | 2.55k | } |
588 | | |
589 | 201 | void GotSection::addEntry(Symbol &sym) { |
590 | 201 | sym.gotIndex = numEntries; |
591 | 201 | ++numEntries; |
592 | 201 | } |
593 | | |
594 | 78 | bool GotSection::addDynTlsEntry(Symbol &sym) { |
595 | 78 | if (sym.globalDynIndex != -1U) |
596 | 24 | return false; |
597 | 54 | sym.globalDynIndex = numEntries; |
598 | 54 | // Global Dynamic TLS entries take two GOT slots. |
599 | 54 | numEntries += 2; |
600 | 54 | return true; |
601 | 54 | } |
602 | | |
603 | | // Reserves TLS entries for a TLS module ID and a TLS block offset. |
604 | | // In total it takes two GOT slots. |
605 | 31 | bool GotSection::addTlsIndex() { |
606 | 31 | if (tlsIndexOff != uint32_t(-1)) |
607 | 19 | return false; |
608 | 12 | tlsIndexOff = numEntries * config->wordsize; |
609 | 12 | numEntries += 2; |
610 | 12 | return true; |
611 | 12 | } |
612 | | |
613 | 74 | uint64_t GotSection::getGlobalDynAddr(const Symbol &b) const { |
614 | 74 | return this->getVA() + b.globalDynIndex * config->wordsize; |
615 | 74 | } |
616 | | |
617 | 64 | uint64_t GotSection::getGlobalDynOffset(const Symbol &b) const { |
618 | 64 | return b.globalDynIndex * config->wordsize; |
619 | 64 | } |
620 | | |
621 | 246 | void GotSection::finalizeContents() { |
622 | 246 | size = numEntries * config->wordsize; |
623 | 246 | } |
624 | | |
625 | 4.84k | bool GotSection::isNeeded() const { |
626 | 4.84k | // We need to emit a GOT even if it's empty if there's a relocation that is |
627 | 4.84k | // relative to GOT(such as GOTOFFREL). |
628 | 4.84k | return numEntries || hasGotOffRel4.37k ; |
629 | 4.84k | } |
630 | | |
631 | 245 | void GotSection::writeTo(uint8_t *buf) { |
632 | 245 | // Buf points to the start of this section's buffer, |
633 | 245 | // whereas InputSectionBase::relocateAlloc() expects its argument |
634 | 245 | // to point to the start of the output section. |
635 | 245 | target->writeGotHeader(buf); |
636 | 245 | relocateAlloc(buf - outSecOff, buf - outSecOff + size); |
637 | 245 | } |
638 | | |
639 | 71 | static uint64_t getMipsPageAddr(uint64_t addr) { |
640 | 71 | return (addr + 0x8000) & ~0xffff; |
641 | 71 | } |
642 | | |
643 | 14 | static uint64_t getMipsPageCount(uint64_t size) { |
644 | 14 | return (size + 0xfffe) / 0xffff + 1; |
645 | 14 | } |
646 | | |
647 | | MipsGotSection::MipsGotSection() |
648 | | : SyntheticSection(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, SHT_PROGBITS, 16, |
649 | 198 | ".got") {} |
650 | | |
651 | | void MipsGotSection::addEntry(InputFile &file, Symbol &sym, int64_t addend, |
652 | 10.1k | RelExpr expr) { |
653 | 10.1k | FileGot &g = getGot(file); |
654 | 10.1k | if (expr == R_MIPS_GOT_LOCAL_PAGE) { |
655 | 29 | if (const OutputSection *os = sym.getOutputSection()) |
656 | 25 | g.pagesMap.insert({os, {}}); |
657 | 4 | else |
658 | 4 | g.local16.insert({{nullptr, getMipsPageAddr(sym.getVA(addend))}, 0}); |
659 | 10.0k | } else if (sym.isTls()) |
660 | 13 | g.tls.insert({&sym, 0}); |
661 | 10.0k | else if (sym.isPreemptible && expr == R_ABS41 ) |
662 | 4 | g.relocs.insert({&sym, 0}); |
663 | 10.0k | else if (sym.isPreemptible) |
664 | 37 | g.global.insert({&sym, 0}); |
665 | 10.0k | else if (expr == R_MIPS_GOT_OFF32) |
666 | 12 | g.local32.insert({{&sym, addend}, 0}); |
667 | 10.0k | else |
668 | 10.0k | g.local16.insert({{&sym, addend}, 0}); |
669 | 10.1k | } |
670 | | |
671 | 12 | void MipsGotSection::addDynTlsEntry(InputFile &file, Symbol &sym) { |
672 | 12 | getGot(file).dynTlsSymbols.insert({&sym, 0}); |
673 | 12 | } |
674 | | |
675 | 6 | void MipsGotSection::addTlsIndex(InputFile &file) { |
676 | 6 | getGot(file).dynTlsSymbols.insert({nullptr, 0}); |
677 | 6 | } |
678 | | |
679 | 114 | size_t MipsGotSection::FileGot::getEntriesNum() const { |
680 | 114 | return getPageEntriesNum() + local16.size() + global.size() + relocs.size() + |
681 | 114 | tls.size() + dynTlsSymbols.size() * 2; |
682 | 114 | } |
683 | | |
684 | 218 | size_t MipsGotSection::FileGot::getPageEntriesNum() const { |
685 | 218 | size_t num = 0; |
686 | 218 | for (const std::pair<const OutputSection *, FileGot::PageBlock> &p : pagesMap) |
687 | 52 | num += p.second.count; |
688 | 218 | return num; |
689 | 218 | } |
690 | | |
691 | 59 | size_t MipsGotSection::FileGot::getIndexedEntriesNum() const { |
692 | 59 | size_t count = getPageEntriesNum() + local16.size() + global.size(); |
693 | 59 | // If there are relocation-only entries in the GOT, TLS entries |
694 | 59 | // are allocated after them. TLS entries should be addressable |
695 | 59 | // by 16-bit index so count both reloc-only and TLS entries. |
696 | 59 | if (!tls.empty() || !dynTlsSymbols.empty()50 ) |
697 | 10 | count += relocs.size() + tls.size() + dynTlsSymbols.size() * 2; |
698 | 59 | return count; |
699 | 59 | } |
700 | | |
701 | 10.1k | MipsGotSection::FileGot &MipsGotSection::getGot(InputFile &f) { |
702 | 10.1k | if (!f.mipsGotIndex.hasValue()) { |
703 | 58 | gots.emplace_back(); |
704 | 58 | gots.back().file = &f; |
705 | 58 | f.mipsGotIndex = gots.size() - 1; |
706 | 58 | } |
707 | 10.1k | return gots[*f.mipsGotIndex]; |
708 | 10.1k | } |
709 | | |
710 | | uint64_t MipsGotSection::getPageEntryOffset(const InputFile *f, |
711 | | const Symbol &sym, |
712 | 29 | int64_t addend) const { |
713 | 29 | const FileGot &g = gots[*f->mipsGotIndex]; |
714 | 29 | uint64_t index = 0; |
715 | 29 | if (const OutputSection *outSec = sym.getOutputSection()) { |
716 | 25 | uint64_t secAddr = getMipsPageAddr(outSec->addr); |
717 | 25 | uint64_t symAddr = getMipsPageAddr(sym.getVA(addend)); |
718 | 25 | index = g.pagesMap.lookup(outSec).firstIndex + (symAddr - secAddr) / 0xffff; |
719 | 25 | } else { |
720 | 4 | index = g.local16.lookup({nullptr, getMipsPageAddr(sym.getVA(addend))}); |
721 | 4 | } |
722 | 29 | return index * config->wordsize; |
723 | 29 | } |
724 | | |
725 | | uint64_t MipsGotSection::getSymEntryOffset(const InputFile *f, const Symbol &s, |
726 | 10.0k | int64_t addend) const { |
727 | 10.0k | const FileGot &g = gots[*f->mipsGotIndex]; |
728 | 10.0k | Symbol *sym = const_cast<Symbol *>(&s); |
729 | 10.0k | if (sym->isTls()) |
730 | 13 | return g.tls.lookup(sym) * config->wordsize; |
731 | 10.0k | if (sym->isPreemptible) |
732 | 37 | return g.global.lookup(sym) * config->wordsize; |
733 | 10.0k | return g.local16.lookup({sym, addend}) * config->wordsize; |
734 | 10.0k | } |
735 | | |
736 | 6 | uint64_t MipsGotSection::getTlsIndexOffset(const InputFile *f) const { |
737 | 6 | const FileGot &g = gots[*f->mipsGotIndex]; |
738 | 6 | return g.dynTlsSymbols.lookup(nullptr) * config->wordsize; |
739 | 6 | } |
740 | | |
741 | | uint64_t MipsGotSection::getGlobalDynOffset(const InputFile *f, |
742 | 12 | const Symbol &s) const { |
743 | 12 | const FileGot &g = gots[*f->mipsGotIndex]; |
744 | 12 | Symbol *sym = const_cast<Symbol *>(&s); |
745 | 12 | return g.dynTlsSymbols.lookup(sym) * config->wordsize; |
746 | 12 | } |
747 | | |
748 | 100 | const Symbol *MipsGotSection::getFirstGlobalEntry() const { |
749 | 100 | if (gots.empty()) |
750 | 55 | return nullptr; |
751 | 45 | const FileGot &primGot = gots.front(); |
752 | 45 | if (!primGot.global.empty()) |
753 | 27 | return primGot.global.front().first; |
754 | 18 | if (!primGot.relocs.empty()) |
755 | 5 | return primGot.relocs.front().first; |
756 | 13 | return nullptr; |
757 | 13 | } |
758 | | |
759 | 100 | unsigned MipsGotSection::getLocalEntriesNum() const { |
760 | 100 | if (gots.empty()) |
761 | 55 | return headerEntriesNum; |
762 | 45 | return headerEntriesNum + gots.front().getPageEntriesNum() + |
763 | 45 | gots.front().local16.size(); |
764 | 45 | } |
765 | | |
766 | 59 | bool MipsGotSection::tryMergeGots(FileGot &dst, FileGot &src, bool isPrimary) { |
767 | 59 | FileGot tmp = dst; |
768 | 59 | set_union(tmp.pagesMap, src.pagesMap); |
769 | 59 | set_union(tmp.local16, src.local16); |
770 | 59 | set_union(tmp.global, src.global); |
771 | 59 | set_union(tmp.relocs, src.relocs); |
772 | 59 | set_union(tmp.tls, src.tls); |
773 | 59 | set_union(tmp.dynTlsSymbols, src.dynTlsSymbols); |
774 | 59 | |
775 | 59 | size_t count = isPrimary ? headerEntriesNum58 : 01 ; |
776 | 59 | count += tmp.getIndexedEntriesNum(); |
777 | 59 | |
778 | 59 | if (count * config->wordsize > config->mipsGotSize) |
779 | 4 | return false; |
780 | 55 | |
781 | 55 | std::swap(tmp, dst); |
782 | 55 | return true; |
783 | 55 | } |
784 | | |
785 | 173 | void MipsGotSection::finalizeContents() { updateAllocSize(); } |
786 | | |
787 | 375 | bool MipsGotSection::updateAllocSize() { |
788 | 375 | size = headerEntriesNum * config->wordsize; |
789 | 375 | for (const FileGot &g : gots) |
790 | 114 | size += g.getEntriesNum() * config->wordsize; |
791 | 375 | return false; |
792 | 375 | } |
793 | | |
794 | 187 | void MipsGotSection::build() { |
795 | 187 | if (gots.empty()) |
796 | 133 | return; |
797 | 54 | |
798 | 54 | std::vector<FileGot> mergedGots(1); |
799 | 54 | |
800 | 54 | // For each GOT move non-preemptible symbols from the `Global` |
801 | 54 | // to `Local16` list. Preemptible symbol might become non-preemptible |
802 | 54 | // one if, for example, it gets a related copy relocation. |
803 | 58 | for (FileGot &got : gots) { |
804 | 58 | for (auto &p: got.global) |
805 | 35 | if (!p.first->isPreemptible) |
806 | 0 | got.local16.insert({{p.first, 0}, 0}); |
807 | 58 | got.global.remove_if([&](const std::pair<Symbol *, size_t> &p) { |
808 | 35 | return !p.first->isPreemptible; |
809 | 35 | }); |
810 | 58 | } |
811 | 54 | |
812 | 54 | // For each GOT remove "reloc-only" entry if there is "global" |
813 | 54 | // entry for the same symbol. And add local entries which indexed |
814 | 54 | // using 32-bit value at the end of 16-bit entries. |
815 | 58 | for (FileGot &got : gots) { |
816 | 58 | got.relocs.remove_if([&](const std::pair<Symbol *, size_t> &p) { |
817 | 4 | return got.global.count(p.first); |
818 | 4 | }); |
819 | 58 | set_union(got.local16, got.local32); |
820 | 58 | got.local32.clear(); |
821 | 58 | } |
822 | 54 | |
823 | 54 | // Evaluate number of "reloc-only" entries in the resulting GOT. |
824 | 54 | // To do that put all unique "reloc-only" and "global" entries |
825 | 54 | // from all GOTs to the future primary GOT. |
826 | 54 | FileGot *primGot = &mergedGots.front(); |
827 | 58 | for (FileGot &got : gots) { |
828 | 58 | set_union(primGot->relocs, got.global); |
829 | 58 | set_union(primGot->relocs, got.relocs); |
830 | 58 | got.relocs.clear(); |
831 | 58 | } |
832 | 54 | |
833 | 54 | // Evaluate number of "page" entries in each GOT. |
834 | 58 | for (FileGot &got : gots) { |
835 | 58 | for (std::pair<const OutputSection *, FileGot::PageBlock> &p : |
836 | 58 | got.pagesMap) { |
837 | 14 | const OutputSection *os = p.first; |
838 | 14 | uint64_t secSize = 0; |
839 | 16 | for (BaseCommand *cmd : os->sectionCommands) { |
840 | 16 | if (auto *isd = dyn_cast<InputSectionDescription>(cmd)) |
841 | 24 | for (InputSection *isec : isd->sections)15 { |
842 | 24 | uint64_t off = alignTo(secSize, isec->alignment); |
843 | 24 | secSize = off + isec->getSize(); |
844 | 24 | } |
845 | 16 | } |
846 | 14 | p.second.count = getMipsPageCount(secSize); |
847 | 14 | } |
848 | 58 | } |
849 | 54 | |
850 | 54 | // Merge GOTs. Try to join as much as possible GOTs but do not exceed |
851 | 54 | // maximum GOT size. At first, try to fill the primary GOT because |
852 | 54 | // the primary GOT can be accessed in the most effective way. If it |
853 | 54 | // is not possible, try to fill the last GOT in the list, and finally |
854 | 54 | // create a new GOT if both attempts failed. |
855 | 58 | for (FileGot &srcGot : gots) { |
856 | 58 | InputFile *file = srcGot.file; |
857 | 58 | if (tryMergeGots(mergedGots.front(), srcGot, true)) { |
858 | 54 | file->mipsGotIndex = 0; |
859 | 54 | } else { |
860 | 4 | // If this is the first time we failed to merge with the primary GOT, |
861 | 4 | // MergedGots.back() will also be the primary GOT. We must make sure not |
862 | 4 | // to try to merge again with isPrimary=false, as otherwise, if the |
863 | 4 | // inputs are just right, we could allow the primary GOT to become 1 or 2 |
864 | 4 | // words bigger due to ignoring the header size. |
865 | 4 | if (mergedGots.size() == 1 || |
866 | 4 | !tryMergeGots(mergedGots.back(), srcGot, false)1 ) { |
867 | 3 | mergedGots.emplace_back(); |
868 | 3 | std::swap(mergedGots.back(), srcGot); |
869 | 3 | } |
870 | 4 | file->mipsGotIndex = mergedGots.size() - 1; |
871 | 4 | } |
872 | 58 | } |
873 | 54 | std::swap(gots, mergedGots); |
874 | 54 | |
875 | 54 | // Reduce number of "reloc-only" entries in the primary GOT |
876 | 54 | // by substracting "global" entries exist in the primary GOT. |
877 | 54 | primGot = &gots.front(); |
878 | 54 | primGot->relocs.remove_if([&](const std::pair<Symbol *, size_t> &p) { |
879 | 38 | return primGot->global.count(p.first); |
880 | 38 | }); |
881 | 54 | |
882 | 54 | // Calculate indexes for each GOT entry. |
883 | 54 | size_t index = headerEntriesNum; |
884 | 57 | for (FileGot &got : gots) { |
885 | 57 | got.startIndex = &got == primGot ? 054 : index3 ; |
886 | 57 | for (std::pair<const OutputSection *, FileGot::PageBlock> &p : |
887 | 57 | got.pagesMap) { |
888 | 13 | // For each output section referenced by GOT page relocations calculate |
889 | 13 | // and save into pagesMap an upper bound of MIPS GOT entries required |
890 | 13 | // to store page addresses of local symbols. We assume the worst case - |
891 | 13 | // each 64kb page of the output section has at least one GOT relocation |
892 | 13 | // against it. And take in account the case when the section intersects |
893 | 13 | // page boundaries. |
894 | 13 | p.second.firstIndex = index; |
895 | 13 | index += p.second.count; |
896 | 13 | } |
897 | 57 | for (auto &p: got.local16) |
898 | 10.0k | p.second = index++; |
899 | 57 | for (auto &p: got.global) |
900 | 34 | p.second = index++; |
901 | 57 | for (auto &p: got.relocs) |
902 | 6 | p.second = index++; |
903 | 57 | for (auto &p: got.tls) |
904 | 12 | p.second = index++; |
905 | 57 | for (auto &p: got.dynTlsSymbols) { |
906 | 17 | p.second = index; |
907 | 17 | index += 2; |
908 | 17 | } |
909 | 57 | } |
910 | 54 | |
911 | 54 | // Update Symbol::gotIndex field to use this |
912 | 54 | // value later in the `sortMipsSymbols` function. |
913 | 54 | for (auto &p : primGot->global) |
914 | 32 | p.first->gotIndex = p.second; |
915 | 54 | for (auto &p : primGot->relocs) |
916 | 6 | p.first->gotIndex = p.second; |
917 | 54 | |
918 | 54 | // Create dynamic relocations. |
919 | 57 | for (FileGot &got : gots) { |
920 | 57 | // Create dynamic relocations for TLS entries. |
921 | 57 | for (std::pair<Symbol *, size_t> &p : got.tls) { |
922 | 12 | Symbol *s = p.first; |
923 | 12 | uint64_t offset = p.second * config->wordsize; |
924 | 12 | if (s->isPreemptible) |
925 | 9 | mainPart->relaDyn->addReloc(target->tlsGotRel, this, offset, s); |
926 | 12 | } |
927 | 57 | for (std::pair<Symbol *, size_t> &p : got.dynTlsSymbols) { |
928 | 17 | Symbol *s = p.first; |
929 | 17 | uint64_t offset = p.second * config->wordsize; |
930 | 17 | if (s == nullptr) { |
931 | 6 | if (!config->isPic) |
932 | 3 | continue; |
933 | 3 | mainPart->relaDyn->addReloc(target->tlsModuleIndexRel, this, offset, s); |
934 | 11 | } else { |
935 | 11 | // When building a shared library we still need a dynamic relocation |
936 | 11 | // for the module index. Therefore only checking for |
937 | 11 | // S->isPreemptible is not sufficient (this happens e.g. for |
938 | 11 | // thread-locals that have been marked as local through a linker script) |
939 | 11 | if (!s->isPreemptible && !config->isPic4 ) |
940 | 3 | continue; |
941 | 8 | mainPart->relaDyn->addReloc(target->tlsModuleIndexRel, this, offset, s); |
942 | 8 | // However, we can skip writing the TLS offset reloc for non-preemptible |
943 | 8 | // symbols since it is known even in shared libraries |
944 | 8 | if (!s->isPreemptible) |
945 | 1 | continue; |
946 | 7 | offset += config->wordsize; |
947 | 7 | mainPart->relaDyn->addReloc(target->tlsOffsetRel, this, offset, s); |
948 | 7 | } |
949 | 17 | } |
950 | 57 | |
951 | 57 | // Do not create dynamic relocations for non-TLS |
952 | 57 | // entries in the primary GOT. |
953 | 57 | if (&got == primGot) |
954 | 54 | continue; |
955 | 3 | |
956 | 3 | // Dynamic relocations for "global" entries. |
957 | 3 | for (const std::pair<Symbol *, size_t> &p : got.global) { |
958 | 2 | uint64_t offset = p.second * config->wordsize; |
959 | 2 | mainPart->relaDyn->addReloc(target->relativeRel, this, offset, p.first); |
960 | 2 | } |
961 | 3 | if (!config->isPic) |
962 | 1 | continue; |
963 | 2 | // Dynamic relocations for "local" entries in case of PIC. |
964 | 2 | for (const std::pair<const OutputSection *, FileGot::PageBlock> &l : |
965 | 2 | got.pagesMap) { |
966 | 1 | size_t pageCount = l.second.count; |
967 | 7 | for (size_t pi = 0; pi < pageCount; ++pi6 ) { |
968 | 6 | uint64_t offset = (l.second.firstIndex + pi) * config->wordsize; |
969 | 6 | mainPart->relaDyn->addReloc({target->relativeRel, this, offset, l.first, |
970 | 6 | int64_t(pi * 0x10000)}); |
971 | 6 | } |
972 | 1 | } |
973 | 2 | for (const std::pair<GotEntry, size_t> &p : got.local16) { |
974 | 1 | uint64_t offset = p.second * config->wordsize; |
975 | 1 | mainPart->relaDyn->addReloc({target->relativeRel, this, offset, true, |
976 | 1 | p.first.first, p.first.second}); |
977 | 1 | } |
978 | 2 | } |
979 | 54 | } |
980 | | |
981 | 374 | bool MipsGotSection::isNeeded() const { |
982 | 374 | // We add the .got section to the result for dynamic MIPS target because |
983 | 374 | // its address and properties are mentioned in the .dynamic section. |
984 | 374 | return !config->relocatable; |
985 | 374 | } |
986 | | |
987 | 10.3k | uint64_t MipsGotSection::getGp(const InputFile *f) const { |
988 | 10.3k | // For files without related GOT or files refer a primary GOT |
989 | 10.3k | // returns "common" _gp value. For secondary GOTs calculate |
990 | 10.3k | // individual _gp values. |
991 | 10.3k | if (!f || !f->mipsGotIndex.hasValue()10.1k || *f->mipsGotIndex == 010.1k ) |
992 | 338 | return ElfSym::mipsGp->getVA(0); |
993 | 10.0k | return getVA() + gots[*f->mipsGotIndex].startIndex * config->wordsize + |
994 | 10.0k | 0x7ff0; |
995 | 10.0k | } |
996 | | |
997 | 173 | void MipsGotSection::writeTo(uint8_t *buf) { |
998 | 173 | // Set the MSB of the second GOT slot. This is not required by any |
999 | 173 | // MIPS ABI documentation, though. |
1000 | 173 | // |
1001 | 173 | // There is a comment in glibc saying that "The MSB of got[1] of a |
1002 | 173 | // gnu object is set to identify gnu objects," and in GNU gold it |
1003 | 173 | // says "the second entry will be used by some runtime loaders". |
1004 | 173 | // But how this field is being used is unclear. |
1005 | 173 | // |
1006 | 173 | // We are not really willing to mimic other linkers behaviors |
1007 | 173 | // without understanding why they do that, but because all files |
1008 | 173 | // generated by GNU tools have this special GOT value, and because |
1009 | 173 | // we've been doing this for years, it is probably a safe bet to |
1010 | 173 | // keep doing this for now. We really need to revisit this to see |
1011 | 173 | // if we had to do this. |
1012 | 173 | writeUint(buf + config->wordsize, (uint64_t)1 << (config->wordsize * 8 - 1)); |
1013 | 173 | for (const FileGot &g : gots) { |
1014 | 10.1k | auto write = [&](size_t i, const Symbol *s, int64_t a) { |
1015 | 10.1k | uint64_t va = a; |
1016 | 10.1k | if (s) |
1017 | 10.0k | va = s->getVA(a); |
1018 | 10.1k | writeUint(buf + i * config->wordsize, va); |
1019 | 10.1k | }; |
1020 | 57 | // Write 'page address' entries to the local part of the GOT. |
1021 | 57 | for (const std::pair<const OutputSection *, FileGot::PageBlock> &l : |
1022 | 57 | g.pagesMap) { |
1023 | 13 | size_t pageCount = l.second.count; |
1024 | 13 | uint64_t firstPageAddr = getMipsPageAddr(l.first->addr); |
1025 | 49 | for (size_t pi = 0; pi < pageCount; ++pi36 ) |
1026 | 36 | write(l.second.firstIndex + pi, nullptr, firstPageAddr + pi * 0x10000); |
1027 | 13 | } |
1028 | 57 | // Local, global, TLS, reloc-only entries. |
1029 | 57 | // If TLS entry has a corresponding dynamic relocations, leave it |
1030 | 57 | // initialized by zero. Write down adjusted TLS symbol's values otherwise. |
1031 | 57 | // To calculate the adjustments use offsets for thread-local storage. |
1032 | 57 | // https://www.linux-mips.org/wiki/NPTL |
1033 | 57 | for (const std::pair<GotEntry, size_t> &p : g.local16) |
1034 | 10.0k | write(p.second, p.first.first, p.first.second); |
1035 | 57 | // Write VA to the primary GOT only. For secondary GOTs that |
1036 | 57 | // will be done by REL32 dynamic relocations. |
1037 | 57 | if (&g == &gots.front()) |
1038 | 54 | for (const std::pair<const Symbol *, size_t> &p : g.global) |
1039 | 32 | write(p.second, p.first, 0); |
1040 | 57 | for (const std::pair<Symbol *, size_t> &p : g.relocs) |
1041 | 6 | write(p.second, p.first, 0); |
1042 | 57 | for (const std::pair<Symbol *, size_t> &p : g.tls) |
1043 | 12 | write(p.second, p.first, p.first->isPreemptible ? 09 : -0x70003 ); |
1044 | 57 | for (const std::pair<Symbol *, size_t> &p : g.dynTlsSymbols) { |
1045 | 17 | if (p.first == nullptr && !config->isPic6 ) |
1046 | 3 | write(p.second, nullptr, 1); |
1047 | 14 | else if (p.first && !p.first->isPreemptible11 ) { |
1048 | 4 | // If we are emitting PIC code with relocations we mustn't write |
1049 | 4 | // anything to the GOT here. When using Elf_Rel relocations the value |
1050 | 4 | // one will be treated as an addend and will cause crashes at runtime |
1051 | 4 | if (!config->isPic) |
1052 | 3 | write(p.second, nullptr, 1); |
1053 | 4 | write(p.second + 1, p.first, -0x8000); |
1054 | 4 | } |
1055 | 17 | } |
1056 | 57 | } |
1057 | 173 | } |
1058 | | |
1059 | | // On PowerPC the .plt section is used to hold the table of function addresses |
1060 | | // instead of the .got.plt, and the type is SHT_NOBITS similar to a .bss |
1061 | | // section. I don't know why we have a BSS style type for the section but it is |
1062 | | // consitent across both 64-bit PowerPC ABIs as well as the 32-bit PowerPC ABI. |
1063 | | GotPltSection::GotPltSection() |
1064 | | : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize, |
1065 | 2.75k | ".got.plt") { |
1066 | 2.75k | if (config->emachine == EM_PPC) { |
1067 | 31 | name = ".plt"; |
1068 | 2.72k | } else if (config->emachine == EM_PPC64) { |
1069 | 152 | type = SHT_NOBITS; |
1070 | 152 | name = ".plt"; |
1071 | 152 | } |
1072 | 2.75k | } |
1073 | | |
1074 | 359 | void GotPltSection::addEntry(Symbol &sym) { |
1075 | 359 | assert(sym.pltIndex == entries.size()); |
1076 | 359 | entries.push_back(&sym); |
1077 | 359 | } |
1078 | | |
1079 | 1.28k | size_t GotPltSection::getSize() const { |
1080 | 1.28k | return (target->gotPltHeaderEntriesNum + entries.size()) * config->wordsize; |
1081 | 1.28k | } |
1082 | | |
1083 | 276 | void GotPltSection::writeTo(uint8_t *buf) { |
1084 | 276 | target->writeGotPltHeader(buf); |
1085 | 276 | buf += target->gotPltHeaderEntriesNum * config->wordsize; |
1086 | 332 | for (const Symbol *b : entries) { |
1087 | 332 | target->writeGotPlt(buf, *b); |
1088 | 332 | buf += config->wordsize; |
1089 | 332 | } |
1090 | 276 | } |
1091 | | |
1092 | 5.22k | bool GotPltSection::isNeeded() const { |
1093 | 5.22k | // We need to emit GOTPLT even if it's empty if there's a relocation relative |
1094 | 5.22k | // to it. |
1095 | 5.22k | return !entries.empty() || hasGotPltOffRel4.70k ; |
1096 | 5.22k | } |
1097 | | |
1098 | 2.75k | static StringRef getIgotPltName() { |
1099 | 2.75k | // On ARM the IgotPltSection is part of the GotSection. |
1100 | 2.75k | if (config->emachine == EM_ARM) |
1101 | 159 | return ".got"; |
1102 | 2.59k | |
1103 | 2.59k | // On PowerPC64 the GotPltSection is renamed to '.plt' so the IgotPltSection |
1104 | 2.59k | // needs to be named the same. |
1105 | 2.59k | if (config->emachine == EM_PPC64) |
1106 | 152 | return ".plt"; |
1107 | 2.44k | |
1108 | 2.44k | return ".got.plt"; |
1109 | 2.44k | } |
1110 | | |
1111 | | // On PowerPC64 the GotPltSection type is SHT_NOBITS so we have to follow suit |
1112 | | // with the IgotPltSection. |
1113 | | IgotPltSection::IgotPltSection() |
1114 | | : SyntheticSection(SHF_ALLOC | SHF_WRITE, |
1115 | | config->emachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS, |
1116 | 2.75k | config->wordsize, getIgotPltName()) {} |
1117 | | |
1118 | 62 | void IgotPltSection::addEntry(Symbol &sym) { |
1119 | 62 | assert(sym.pltIndex == entries.size()); |
1120 | 62 | entries.push_back(&sym); |
1121 | 62 | } |
1122 | | |
1123 | 194 | size_t IgotPltSection::getSize() const { |
1124 | 194 | return entries.size() * config->wordsize; |
1125 | 194 | } |
1126 | | |
1127 | 44 | void IgotPltSection::writeTo(uint8_t *buf) { |
1128 | 58 | for (const Symbol *b : entries) { |
1129 | 58 | target->writeIgotPlt(buf, *b); |
1130 | 58 | buf += config->wordsize; |
1131 | 58 | } |
1132 | 44 | } |
1133 | | |
1134 | | StringTableSection::StringTableSection(StringRef name, bool dynamic) |
1135 | | : SyntheticSection(dynamic ? (uint64_t)SHF_ALLOC : 0, SHT_STRTAB, 1, name), |
1136 | 8.27k | dynamic(dynamic) { |
1137 | 8.27k | // ELF string tables start with a NUL byte. |
1138 | 8.27k | addString(""); |
1139 | 8.27k | } |
1140 | | |
1141 | | // Adds a string to the string table. If `hashIt` is true we hash and check for |
1142 | | // duplicates. It is optional because the name of global symbols are already |
1143 | | // uniqued and hashing them again has a big cost for a small value: uniquing |
1144 | | // them with some other string that happens to be the same. |
1145 | 450k | unsigned StringTableSection::addString(StringRef s, bool hashIt) { |
1146 | 450k | if (hashIt) { |
1147 | 430k | auto r = stringMap.insert(std::make_pair(s, this->size)); |
1148 | 430k | if (!r.second) |
1149 | 66.2k | return r.first->second; |
1150 | 384k | } |
1151 | 384k | unsigned ret = this->size; |
1152 | 384k | this->size = this->size + s.size() + 1; |
1153 | 384k | strings.push_back(s); |
1154 | 384k | return ret; |
1155 | 384k | } |
1156 | | |
1157 | 6.39k | void StringTableSection::writeTo(uint8_t *buf) { |
1158 | 381k | for (StringRef s : strings) { |
1159 | 381k | memcpy(buf, s.data(), s.size()); |
1160 | 381k | buf[s.size()] = '\0'; |
1161 | 381k | buf += s.size() + 1; |
1162 | 381k | } |
1163 | 6.39k | } |
1164 | | |
1165 | | // Returns the number of version definition entries. Because the first entry |
1166 | | // is for the version definition itself, it is the number of versioned symbols |
1167 | | // plus one. Note that we don't support multiple versions yet. |
1168 | 376 | static unsigned getVerDefNum() { return config->versionDefinitions.size() + 1; } |
1169 | | |
1170 | | template <class ELFT> |
1171 | | DynamicSection<ELFT>::DynamicSection() |
1172 | | : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_DYNAMIC, config->wordsize, |
1173 | 2.77k | ".dynamic") { |
1174 | 2.77k | this->entsize = ELFT::Is64Bits ? 162.23k : 8537 ; |
1175 | 2.77k | |
1176 | 2.77k | // .dynamic section is not writable on MIPS and on Fuchsia OS |
1177 | 2.77k | // which passes -z rodynamic. |
1178 | 2.77k | // See "Special Section" in Chapter 4 in the following document: |
1179 | 2.77k | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf |
1180 | 2.77k | if (config->emachine == EM_MIPS || config->zRodynamic2.57k ) |
1181 | 202 | this->flags = SHF_ALLOC; |
1182 | 2.77k | } lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::DynamicSection() Line | Count | Source | 1173 | 380 | ".dynamic") { | 1174 | 380 | this->entsize = ELFT::Is64Bits ? 160 : 8; | 1175 | 380 | | 1176 | 380 | // .dynamic section is not writable on MIPS and on Fuchsia OS | 1177 | 380 | // which passes -z rodynamic. | 1178 | 380 | // See "Special Section" in Chapter 4 in the following document: | 1179 | 380 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf | 1180 | 380 | if (config->emachine == EM_MIPS || config->zRodynamic355 ) | 1181 | 25 | this->flags = SHF_ALLOC; | 1182 | 380 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::DynamicSection() Line | Count | Source | 1173 | 157 | ".dynamic") { | 1174 | 157 | this->entsize = ELFT::Is64Bits ? 160 : 8; | 1175 | 157 | | 1176 | 157 | // .dynamic section is not writable on MIPS and on Fuchsia OS | 1177 | 157 | // which passes -z rodynamic. | 1178 | 157 | // See "Special Section" in Chapter 4 in the following document: | 1179 | 157 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf | 1180 | 157 | if (config->emachine == EM_MIPS || config->zRodynamic31 ) | 1181 | 126 | this->flags = SHF_ALLOC; | 1182 | 157 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::DynamicSection() Line | Count | Source | 1173 | 2.12k | ".dynamic") { | 1174 | 2.12k | this->entsize = ELFT::Is64Bits ? 16 : 80 ; | 1175 | 2.12k | | 1176 | 2.12k | // .dynamic section is not writable on MIPS and on Fuchsia OS | 1177 | 2.12k | // which passes -z rodynamic. | 1178 | 2.12k | // See "Special Section" in Chapter 4 in the following document: | 1179 | 2.12k | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf | 1180 | 2.12k | if (config->emachine == EM_MIPS || config->zRodynamic2.12k ) | 1181 | 6 | this->flags = SHF_ALLOC; | 1182 | 2.12k | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::DynamicSection() Line | Count | Source | 1173 | 108 | ".dynamic") { | 1174 | 108 | this->entsize = ELFT::Is64Bits ? 16 : 80 ; | 1175 | 108 | | 1176 | 108 | // .dynamic section is not writable on MIPS and on Fuchsia OS | 1177 | 108 | // which passes -z rodynamic. | 1178 | 108 | // See "Special Section" in Chapter 4 in the following document: | 1179 | 108 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf | 1180 | 108 | if (config->emachine == EM_MIPS || config->zRodynamic63 ) | 1181 | 45 | this->flags = SHF_ALLOC; | 1182 | 108 | } |
|
1183 | | |
1184 | | template <class ELFT> |
1185 | 116 | void DynamicSection<ELFT>::add(int32_t tag, std::function<uint64_t()> fn) { |
1186 | 116 | entries.push_back({tag, fn}); |
1187 | 116 | } lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::add(int, std::__1::function<unsigned long long ()>) Line | Count | Source | 1185 | 8 | void DynamicSection<ELFT>::add(int32_t tag, std::function<uint64_t()> fn) { | 1186 | 8 | entries.push_back({tag, fn}); | 1187 | 8 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::add(int, std::__1::function<unsigned long long ()>) Line | Count | Source | 1185 | 85 | void DynamicSection<ELFT>::add(int32_t tag, std::function<uint64_t()> fn) { | 1186 | 85 | entries.push_back({tag, fn}); | 1187 | 85 | } |
Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::add(int, std::__1::function<unsigned long long ()>) lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::add(int, std::__1::function<unsigned long long ()>) Line | Count | Source | 1185 | 23 | void DynamicSection<ELFT>::add(int32_t tag, std::function<uint64_t()> fn) { | 1186 | 23 | entries.push_back({tag, fn}); | 1187 | 23 | } |
|
1188 | | |
1189 | | template <class ELFT> |
1190 | 5.85k | void DynamicSection<ELFT>::addInt(int32_t tag, uint64_t val) { |
1191 | 5.85k | entries.push_back({tag, [=] { return val; }5.81k }); lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::addInt(int, unsigned long long)::'lambda'()::operator()() const Line | Count | Source | 1191 | 833 | entries.push_back({tag, [=] { return val; }}); |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::addInt(int, unsigned long long)::'lambda'()::operator()() const Line | Count | Source | 1191 | 694 | entries.push_back({tag, [=] { return val; }}); |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::addInt(int, unsigned long long)::'lambda'()::operator()() const Line | Count | Source | 1191 | 3.96k | entries.push_back({tag, [=] { return val; }}); |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::addInt(int, unsigned long long)::'lambda'()::operator()() const Line | Count | Source | 1191 | 330 | entries.push_back({tag, [=] { return val; }}); |
|
1192 | 5.85k | } lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::addInt(int, unsigned long long) Line | Count | Source | 1190 | 833 | void DynamicSection<ELFT>::addInt(int32_t tag, uint64_t val) { | 1191 | 833 | entries.push_back({tag, [=] { return val; }}); | 1192 | 833 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::addInt(int, unsigned long long) Line | Count | Source | 1190 | 694 | void DynamicSection<ELFT>::addInt(int32_t tag, uint64_t val) { | 1191 | 694 | entries.push_back({tag, [=] { return val; }}); | 1192 | 694 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::addInt(int, unsigned long long) Line | Count | Source | 1190 | 3.99k | void DynamicSection<ELFT>::addInt(int32_t tag, uint64_t val) { | 1191 | 3.99k | entries.push_back({tag, [=] { return val; }}); | 1192 | 3.99k | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::addInt(int, unsigned long long) Line | Count | Source | 1190 | 330 | void DynamicSection<ELFT>::addInt(int32_t tag, uint64_t val) { | 1191 | 330 | entries.push_back({tag, [=] { return val; }}); | 1192 | 330 | } |
|
1193 | | |
1194 | | template <class ELFT> |
1195 | 5.89k | void DynamicSection<ELFT>::addInSec(int32_t tag, InputSection *sec) { |
1196 | 5.89k | entries.push_back({tag, [=] { return sec->getVA(0); }5.85k }); lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::addInSec(int, lld::elf::InputSection*)::'lambda'()::operator()() const Line | Count | Source | 1196 | 821 | entries.push_back({tag, [=] { return sec->getVA(0); }}); |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::addInSec(int, lld::elf::InputSection*)::'lambda'()::operator()() const Line | Count | Source | 1196 | 411 | entries.push_back({tag, [=] { return sec->getVA(0); }}); |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::addInSec(int, lld::elf::InputSection*)::'lambda'()::operator()() const Line | Count | Source | 1196 | 4.37k | entries.push_back({tag, [=] { return sec->getVA(0); }}); |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::addInSec(int, lld::elf::InputSection*)::'lambda'()::operator()() const Line | Count | Source | 1196 | 245 | entries.push_back({tag, [=] { return sec->getVA(0); }}); |
|
1197 | 5.89k | } lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::addInSec(int, lld::elf::InputSection*) Line | Count | Source | 1195 | 821 | void DynamicSection<ELFT>::addInSec(int32_t tag, InputSection *sec) { | 1196 | 821 | entries.push_back({tag, [=] { return sec->getVA(0); }}); | 1197 | 821 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::addInSec(int, lld::elf::InputSection*) Line | Count | Source | 1195 | 411 | void DynamicSection<ELFT>::addInSec(int32_t tag, InputSection *sec) { | 1196 | 411 | entries.push_back({tag, [=] { return sec->getVA(0); }}); | 1197 | 411 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::addInSec(int, lld::elf::InputSection*) Line | Count | Source | 1195 | 4.42k | void DynamicSection<ELFT>::addInSec(int32_t tag, InputSection *sec) { | 1196 | 4.42k | entries.push_back({tag, [=] { return sec->getVA(0); }}); | 1197 | 4.42k | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::addInSec(int, lld::elf::InputSection*) Line | Count | Source | 1195 | 245 | void DynamicSection<ELFT>::addInSec(int32_t tag, InputSection *sec) { | 1196 | 245 | entries.push_back({tag, [=] { return sec->getVA(0); }}); | 1197 | 245 | } |
|
1198 | | |
1199 | | template <class ELFT> |
1200 | 29 | void DynamicSection<ELFT>::addInSecRelative(int32_t tag, InputSection *sec) { |
1201 | 29 | size_t tagOffset = entries.size() * entsize; |
1202 | 29 | entries.push_back( |
1203 | 29 | {tag, [=] { return sec->getVA(0) - (getVA() + tagOffset); }}); lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::addInSecRelative(int, lld::elf::InputSection*)::'lambda'()::operator()() const Line | Count | Source | 1203 | 2 | {tag, [=] { return sec->getVA(0) - (getVA() + tagOffset); }}); |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::addInSecRelative(int, lld::elf::InputSection*)::'lambda'()::operator()() const Line | Count | Source | 1203 | 21 | {tag, [=] { return sec->getVA(0) - (getVA() + tagOffset); }}); |
Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::addInSecRelative(int, lld::elf::InputSection*)::'lambda'()::operator()() const lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::addInSecRelative(int, lld::elf::InputSection*)::'lambda'()::operator()() const Line | Count | Source | 1203 | 6 | {tag, [=] { return sec->getVA(0) - (getVA() + tagOffset); }}); |
|
1204 | 29 | } lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::addInSecRelative(int, lld::elf::InputSection*) Line | Count | Source | 1200 | 2 | void DynamicSection<ELFT>::addInSecRelative(int32_t tag, InputSection *sec) { | 1201 | 2 | size_t tagOffset = entries.size() * entsize; | 1202 | 2 | entries.push_back( | 1203 | 2 | {tag, [=] { return sec->getVA(0) - (getVA() + tagOffset); }}); | 1204 | 2 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::addInSecRelative(int, lld::elf::InputSection*) Line | Count | Source | 1200 | 21 | void DynamicSection<ELFT>::addInSecRelative(int32_t tag, InputSection *sec) { | 1201 | 21 | size_t tagOffset = entries.size() * entsize; | 1202 | 21 | entries.push_back( | 1203 | 21 | {tag, [=] { return sec->getVA(0) - (getVA() + tagOffset); }}); | 1204 | 21 | } |
Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::addInSecRelative(int, lld::elf::InputSection*) lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::addInSecRelative(int, lld::elf::InputSection*) Line | Count | Source | 1200 | 6 | void DynamicSection<ELFT>::addInSecRelative(int32_t tag, InputSection *sec) { | 1201 | 6 | size_t tagOffset = entries.size() * entsize; | 1202 | 6 | entries.push_back( | 1203 | 6 | {tag, [=] { return sec->getVA(0) - (getVA() + tagOffset); }}); | 1204 | 6 | } |
|
1205 | | |
1206 | | template <class ELFT> |
1207 | 9 | void DynamicSection<ELFT>::addOutSec(int32_t tag, OutputSection *sec) { |
1208 | 9 | entries.push_back({tag, [=] { return sec->addr; }}); Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::addOutSec(int, lld::elf::OutputSection*)::'lambda'()::operator()() const Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::addOutSec(int, lld::elf::OutputSection*)::'lambda'()::operator()() const lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::addOutSec(int, lld::elf::OutputSection*)::'lambda'()::operator()() const Line | Count | Source | 1208 | 9 | entries.push_back({tag, [=] { return sec->addr; }}); |
Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::addOutSec(int, lld::elf::OutputSection*)::'lambda'()::operator()() const |
1209 | 9 | } Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::addOutSec(int, lld::elf::OutputSection*) Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::addOutSec(int, lld::elf::OutputSection*) lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::addOutSec(int, lld::elf::OutputSection*) Line | Count | Source | 1207 | 9 | void DynamicSection<ELFT>::addOutSec(int32_t tag, OutputSection *sec) { | 1208 | 9 | entries.push_back({tag, [=] { return sec->addr; }}); | 1209 | 9 | } |
Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::addOutSec(int, lld::elf::OutputSection*) |
1210 | | |
1211 | | template <class ELFT> |
1212 | 295 | void DynamicSection<ELFT>::addSize(int32_t tag, OutputSection *sec) { |
1213 | 295 | entries.push_back({tag, [=] { return sec->size; }292 }); lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::addSize(int, lld::elf::OutputSection*)::'lambda'()::operator()() const Line | Count | Source | 1213 | 63 | entries.push_back({tag, [=] { return sec->size; }}); |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::addSize(int, lld::elf::OutputSection*)::'lambda'()::operator()() const Line | Count | Source | 1213 | 16 | entries.push_back({tag, [=] { return sec->size; }}); |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::addSize(int, lld::elf::OutputSection*)::'lambda'()::operator()() const Line | Count | Source | 1213 | 194 | entries.push_back({tag, [=] { return sec->size; }}); |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::addSize(int, lld::elf::OutputSection*)::'lambda'()::operator()() const Line | Count | Source | 1213 | 19 | entries.push_back({tag, [=] { return sec->size; }}); |
|
1214 | 295 | } lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::addSize(int, lld::elf::OutputSection*) Line | Count | Source | 1212 | 63 | void DynamicSection<ELFT>::addSize(int32_t tag, OutputSection *sec) { | 1213 | 63 | entries.push_back({tag, [=] { return sec->size; }}); | 1214 | 63 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::addSize(int, lld::elf::OutputSection*) Line | Count | Source | 1212 | 16 | void DynamicSection<ELFT>::addSize(int32_t tag, OutputSection *sec) { | 1213 | 16 | entries.push_back({tag, [=] { return sec->size; }}); | 1214 | 16 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::addSize(int, lld::elf::OutputSection*) Line | Count | Source | 1212 | 197 | void DynamicSection<ELFT>::addSize(int32_t tag, OutputSection *sec) { | 1213 | 197 | entries.push_back({tag, [=] { return sec->size; }}); | 1214 | 197 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::addSize(int, lld::elf::OutputSection*) Line | Count | Source | 1212 | 19 | void DynamicSection<ELFT>::addSize(int32_t tag, OutputSection *sec) { | 1213 | 19 | entries.push_back({tag, [=] { return sec->size; }}); | 1214 | 19 | } |
|
1215 | | |
1216 | | template <class ELFT> |
1217 | 8 | void DynamicSection<ELFT>::addSym(int32_t tag, Symbol *sym) { |
1218 | 8 | entries.push_back({tag, [=] { return sym->getVA(); }}); Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::addSym(int, lld::elf::Symbol*)::'lambda'()::operator()() const Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::addSym(int, lld::elf::Symbol*)::'lambda'()::operator()() const lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::addSym(int, lld::elf::Symbol*)::'lambda'()::operator()() const Line | Count | Source | 1218 | 8 | entries.push_back({tag, [=] { return sym->getVA(); }}); |
Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::addSym(int, lld::elf::Symbol*)::'lambda'()::operator()() const |
1219 | 8 | } Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::addSym(int, lld::elf::Symbol*) Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::addSym(int, lld::elf::Symbol*) lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::addSym(int, lld::elf::Symbol*) Line | Count | Source | 1217 | 8 | void DynamicSection<ELFT>::addSym(int32_t tag, Symbol *sym) { | 1218 | 8 | entries.push_back({tag, [=] { return sym->getVA(); }}); | 1219 | 8 | } |
Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::addSym(int, lld::elf::Symbol*) |
1220 | | |
1221 | | // A Linker script may assign the RELA relocation sections to the same |
1222 | | // output section. When this occurs we cannot just use the OutputSection |
1223 | | // Size. Moreover the [DT_JMPREL, DT_JMPREL + DT_PLTRELSZ) is permitted to |
1224 | | // overlap with the [DT_RELA, DT_RELA + DT_RELASZ). |
1225 | 269 | static uint64_t addPltRelSz() { |
1226 | 269 | size_t size = in.relaPlt->getSize(); |
1227 | 269 | if (in.relaIplt->getParent() == in.relaPlt->getParent() && |
1228 | 269 | in.relaIplt->name == in.relaPlt->name249 ) |
1229 | 248 | size += in.relaIplt->getSize(); |
1230 | 269 | return size; |
1231 | 269 | } |
1232 | | |
1233 | | // Add remaining entries to complete .dynamic contents. |
1234 | 1.26k | template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { |
1235 | 1.26k | elf::Partition &part = getPartition(); |
1236 | 1.26k | bool isMain = part.name.empty(); |
1237 | 1.26k | |
1238 | 1.26k | for (StringRef s : config->filterList) |
1239 | 6 | addInt(DT_FILTER, part.dynStrTab->addString(s)); |
1240 | 1.26k | for (StringRef s : config->auxiliaryList) |
1241 | 4 | addInt(DT_AUXILIARY, part.dynStrTab->addString(s)); |
1242 | 1.26k | |
1243 | 1.26k | if (!config->rpath.empty()) |
1244 | 7 | addInt(config->enableNewDtags ? DT_RUNPATH6 : DT_RPATH1 , |
1245 | 7 | part.dynStrTab->addString(config->rpath)); |
1246 | 1.26k | |
1247 | 1.26k | for (SharedFile *file : sharedFiles) |
1248 | 377 | if (file->isNeeded) |
1249 | 360 | addInt(DT_NEEDED, part.dynStrTab->addString(file->soName)); |
1250 | 1.26k | |
1251 | 1.26k | if (isMain) { |
1252 | 1.25k | if (!config->soName.empty()) |
1253 | 46 | addInt(DT_SONAME, part.dynStrTab->addString(config->soName)); |
1254 | 1.25k | } else { |
1255 | 11 | if (!config->soName.empty()) |
1256 | 1 | addInt(DT_NEEDED, part.dynStrTab->addString(config->soName)); |
1257 | 11 | addInt(DT_SONAME, part.dynStrTab->addString(part.name)); |
1258 | 11 | } |
1259 | 1.26k | |
1260 | 1.26k | // Set DT_FLAGS and DT_FLAGS_1. |
1261 | 1.26k | uint32_t dtFlags = 0; |
1262 | 1.26k | uint32_t dtFlags1 = 0; |
1263 | 1.26k | if (config->bsymbolic) |
1264 | 8 | dtFlags |= DF_SYMBOLIC; |
1265 | 1.26k | if (config->zGlobal) |
1266 | 1 | dtFlags1 |= DF_1_GLOBAL; |
1267 | 1.26k | if (config->zInitfirst) |
1268 | 1 | dtFlags1 |= DF_1_INITFIRST; |
1269 | 1.26k | if (config->zInterpose) |
1270 | 1 | dtFlags1 |= DF_1_INTERPOSE; |
1271 | 1.26k | if (config->zNodefaultlib) |
1272 | 1 | dtFlags1 |= DF_1_NODEFLIB; |
1273 | 1.26k | if (config->zNodelete) |
1274 | 1 | dtFlags1 |= DF_1_NODELETE; |
1275 | 1.26k | if (config->zNodlopen) |
1276 | 1 | dtFlags1 |= DF_1_NOOPEN; |
1277 | 1.26k | if (config->zNow) { |
1278 | 4 | dtFlags |= DF_BIND_NOW; |
1279 | 4 | dtFlags1 |= DF_1_NOW; |
1280 | 4 | } |
1281 | 1.26k | if (config->zOrigin) { |
1282 | 1 | dtFlags |= DF_ORIGIN; |
1283 | 1 | dtFlags1 |= DF_1_ORIGIN; |
1284 | 1 | } |
1285 | 1.26k | if (!config->zText) |
1286 | 11 | dtFlags |= DF_TEXTREL; |
1287 | 1.26k | if (config->hasStaticTlsModel) |
1288 | 18 | dtFlags |= DF_STATIC_TLS; |
1289 | 1.26k | |
1290 | 1.26k | if (dtFlags) |
1291 | 40 | addInt(DT_FLAGS, dtFlags); |
1292 | 1.26k | if (dtFlags1) |
1293 | 4 | addInt(DT_FLAGS_1, dtFlags1); |
1294 | 1.26k | |
1295 | 1.26k | // DT_DEBUG is a pointer to debug informaion used by debuggers at runtime. We |
1296 | 1.26k | // need it for each process, so we don't write it for DSOs. The loader writes |
1297 | 1.26k | // the pointer into this entry. |
1298 | 1.26k | // |
1299 | 1.26k | // DT_DEBUG is the only .dynamic entry that needs to be written to. Some |
1300 | 1.26k | // systems (currently only Fuchsia OS) provide other means to give the |
1301 | 1.26k | // debugger this information. Such systems may choose make .dynamic read-only. |
1302 | 1.26k | // If the target is such a system (used -z rodynamic) don't write DT_DEBUG. |
1303 | 1.26k | if (!config->shared && !config->relocatable382 && !config->zRodynamic380 ) |
1304 | 379 | addInt(DT_DEBUG, 0); |
1305 | 1.26k | |
1306 | 1.26k | if (OutputSection *sec = part.dynStrTab->getParent()) |
1307 | 1.26k | this->link = sec->sectionIndex; |
1308 | 1.26k | |
1309 | 1.26k | if (part.relaDyn->isNeeded()) { |
1310 | 281 | addInSec(part.relaDyn->dynamicTag, part.relaDyn); |
1311 | 281 | addSize(part.relaDyn->sizeDynamicTag, part.relaDyn->getParent()); |
1312 | 281 | |
1313 | 281 | bool isRela = config->isRela; |
1314 | 281 | addInt(isRela ? DT_RELAENT213 : DT_RELENT68 , |
1315 | 281 | isRela ? sizeof(Elf_Rela)213 : sizeof(Elf_Rel)68 ); |
1316 | 281 | |
1317 | 281 | // MIPS dynamic loader does not support RELCOUNT tag. |
1318 | 281 | // The problem is in the tight relation between dynamic |
1319 | 281 | // relocations and GOT. So do not emit this tag on MIPS. |
1320 | 281 | if (config->emachine != EM_MIPS) { |
1321 | 265 | size_t numRelativeRels = part.relaDyn->getRelativeRelocCount(); |
1322 | 265 | if (config->zCombreloc && numRelativeRels264 ) |
1323 | 59 | addInt(isRela ? DT_RELACOUNT45 : DT_RELCOUNT14 , numRelativeRels); |
1324 | 265 | } |
1325 | 281 | } |
1326 | 1.26k | if (part.relrDyn && !part.relrDyn->relocs.empty()6 ) { |
1327 | 5 | addInSec(config->useAndroidRelrTags ? DT_ANDROID_RELR0 : DT_RELR, |
1328 | 5 | part.relrDyn); |
1329 | 5 | addSize(config->useAndroidRelrTags ? DT_ANDROID_RELRSZ0 : DT_RELRSZ, |
1330 | 5 | part.relrDyn->getParent()); |
1331 | 5 | addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT0 : DT_RELRENT, |
1332 | 5 | sizeof(Elf_Relr)); |
1333 | 5 | } |
1334 | 1.26k | // .rel[a].plt section usually consists of two parts, containing plt and |
1335 | 1.26k | // iplt relocations. It is possible to have only iplt relocations in the |
1336 | 1.26k | // output. In that case relaPlt is empty and have zero offset, the same offset |
1337 | 1.26k | // as relaIplt has. And we still want to emit proper dynamic tags for that |
1338 | 1.26k | // case, so here we always use relaPlt as marker for the begining of |
1339 | 1.26k | // .rel[a].plt section. |
1340 | 1.26k | if (isMain && (1.25k in.relaPlt->isNeeded()1.25k || in.relaIplt->isNeeded()992 )) { |
1341 | 270 | addInSec(DT_JMPREL, in.relaPlt); |
1342 | 270 | entries.push_back({DT_PLTRELSZ, addPltRelSz}); |
1343 | 270 | switch (config->emachine) { |
1344 | 270 | case EM_MIPS: |
1345 | 15 | addInSec(DT_MIPS_PLTGOT, in.gotPlt); |
1346 | 15 | break; |
1347 | 270 | case EM_SPARCV9: |
1348 | 0 | addInSec(DT_PLTGOT, in.plt); |
1349 | 0 | break; |
1350 | 270 | default: |
1351 | 255 | addInSec(DT_PLTGOT, in.gotPlt); |
1352 | 255 | break; |
1353 | 270 | } |
1354 | 270 | addInt(DT_PLTREL, config->isRela ? DT_RELA219 : DT_REL51 ); |
1355 | 270 | } |
1356 | 1.26k | |
1357 | 1.26k | if (config->emachine == EM_AARCH64) { |
1358 | 53 | if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) |
1359 | 8 | addInt(DT_AARCH64_BTI_PLT, 0); |
1360 | 53 | if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC) |
1361 | 5 | addInt(DT_AARCH64_PAC_PLT, 0); |
1362 | 53 | } |
1363 | 1.26k | |
1364 | 1.26k | addInSec(DT_SYMTAB, part.dynSymTab); |
1365 | 1.26k | addInt(DT_SYMENT, sizeof(Elf_Sym)); |
1366 | 1.26k | addInSec(DT_STRTAB, part.dynStrTab); |
1367 | 1.26k | addInt(DT_STRSZ, part.dynStrTab->getSize()); |
1368 | 1.26k | if (!config->zText) |
1369 | 11 | addInt(DT_TEXTREL, 0); |
1370 | 1.26k | if (part.gnuHashTab) |
1371 | 1.02k | addInSec(DT_GNU_HASH, part.gnuHashTab); |
1372 | 1.26k | if (part.hashTab) |
1373 | 1.25k | addInSec(DT_HASH, part.hashTab); |
1374 | 1.26k | |
1375 | 1.26k | if (isMain) { |
1376 | 1.25k | if (Out::preinitArray) { |
1377 | 3 | addOutSec(DT_PREINIT_ARRAY, Out::preinitArray); |
1378 | 3 | addSize(DT_PREINIT_ARRAYSZ, Out::preinitArray); |
1379 | 3 | } |
1380 | 1.25k | if (Out::initArray) { |
1381 | 4 | addOutSec(DT_INIT_ARRAY, Out::initArray); |
1382 | 4 | addSize(DT_INIT_ARRAYSZ, Out::initArray); |
1383 | 4 | } |
1384 | 1.25k | if (Out::finiArray) { |
1385 | 2 | addOutSec(DT_FINI_ARRAY, Out::finiArray); |
1386 | 2 | addSize(DT_FINI_ARRAYSZ, Out::finiArray); |
1387 | 2 | } |
1388 | 1.25k | |
1389 | 1.25k | if (Symbol *b = symtab->find(config->init)) |
1390 | 6 | if (b->isDefined()) |
1391 | 4 | addSym(DT_INIT, b); |
1392 | 1.25k | if (Symbol *b = symtab->find(config->fini)) |
1393 | 6 | if (b->isDefined()) |
1394 | 4 | addSym(DT_FINI, b); |
1395 | 1.25k | } |
1396 | 1.26k | |
1397 | 1.26k | bool hasVerNeed = SharedFile::vernauxNum != 0; |
1398 | 1.26k | if (hasVerNeed || part.verDef1.25k ) |
1399 | 67 | addInSec(DT_VERSYM, part.verSym); |
1400 | 1.26k | if (part.verDef) { |
1401 | 60 | addInSec(DT_VERDEF, part.verDef); |
1402 | 60 | addInt(DT_VERDEFNUM, getVerDefNum()); |
1403 | 60 | } |
1404 | 1.26k | if (hasVerNeed) { |
1405 | 10 | addInSec(DT_VERNEED, part.verNeed); |
1406 | 10 | unsigned needNum = 0; |
1407 | 10 | for (SharedFile *f : sharedFiles) |
1408 | 11 | if (!f->vernauxs.empty()) |
1409 | 11 | ++needNum; |
1410 | 10 | addInt(DT_VERNEEDNUM, needNum); |
1411 | 10 | } |
1412 | 1.26k | |
1413 | 1.26k | if (config->emachine == EM_MIPS) { |
1414 | 100 | addInt(DT_MIPS_RLD_VERSION, 1); |
1415 | 100 | addInt(DT_MIPS_FLAGS, RHF_NOTPOT); |
1416 | 100 | addInt(DT_MIPS_BASE_ADDRESS, target->getImageBase()); |
1417 | 100 | addInt(DT_MIPS_SYMTABNO, part.dynSymTab->getNumSymbols()); |
1418 | 100 | |
1419 | 100 | add(DT_MIPS_LOCAL_GOTNO, [] { return in.mipsGot->getLocalEntriesNum(); }); lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::finalizeContents()::'lambda'()::operator()() const Line | Count | Source | 1419 | 8 | add(DT_MIPS_LOCAL_GOTNO, [] { return in.mipsGot->getLocalEntriesNum(); }); |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::finalizeContents()::'lambda'()::operator()() const Line | Count | Source | 1419 | 69 | add(DT_MIPS_LOCAL_GOTNO, [] { return in.mipsGot->getLocalEntriesNum(); }); |
Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::finalizeContents()::'lambda'()::operator()() const lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::finalizeContents()::'lambda'()::operator()() const Line | Count | Source | 1419 | 23 | add(DT_MIPS_LOCAL_GOTNO, [] { return in.mipsGot->getLocalEntriesNum(); }); |
|
1420 | 100 | |
1421 | 100 | if (const Symbol *b = in.mipsGot->getFirstGlobalEntry()) |
1422 | 32 | addInt(DT_MIPS_GOTSYM, b->dynsymIndex); |
1423 | 68 | else |
1424 | 68 | addInt(DT_MIPS_GOTSYM, part.dynSymTab->getNumSymbols()); |
1425 | 100 | addInSec(DT_PLTGOT, in.mipsGot); |
1426 | 100 | if (in.mipsRldMap) { |
1427 | 29 | if (!config->pie) |
1428 | 26 | addInSec(DT_MIPS_RLD_MAP, in.mipsRldMap); |
1429 | 29 | // Store the offset to the .rld_map section |
1430 | 29 | // relative to the address of the tag. |
1431 | 29 | addInSecRelative(DT_MIPS_RLD_MAP_REL, in.mipsRldMap); |
1432 | 29 | } |
1433 | 100 | } |
1434 | 1.26k | |
1435 | 1.26k | // DT_PPC_GOT indicates to glibc Secure PLT is used. If DT_PPC_GOT is absent, |
1436 | 1.26k | // glibc assumes the old-style BSS PLT layout which we don't support. |
1437 | 1.26k | if (config->emachine == EM_PPC) |
1438 | 16 | add(DT_PPC_GOT, [] { return in.got->getVA(); }); Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::finalizeContents()::'lambda0'()::operator()() const lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::finalizeContents()::'lambda0'()::operator()() const Line | Count | Source | 1438 | 16 | add(DT_PPC_GOT, [] { return in.got->getVA(); }); |
Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::finalizeContents()::'lambda0'()::operator()() const Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::finalizeContents()::'lambda0'()::operator()() const |
1439 | 1.26k | |
1440 | 1.26k | // Glink dynamic tag is required by the V2 abi if the plt section isn't empty. |
1441 | 1.26k | if (config->emachine == EM_PPC64 && in.plt->isNeeded()68 ) { |
1442 | 21 | // The Glink tag points to 32 bytes before the first lazy symbol resolution |
1443 | 21 | // stub, which starts directly after the header. |
1444 | 21 | entries.push_back({DT_PPC64_GLINK, [=] { |
1445 | 21 | unsigned offset = target->pltHeaderSize - 32; |
1446 | 21 | return in.plt->getVA(0) + offset; |
1447 | 21 | }}); Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::finalizeContents()::'lambda1'()::operator()() const Unexecuted instantiation: lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::finalizeContents()::'lambda1'()::operator()() const lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::finalizeContents()::'lambda1'()::operator()() const Line | Count | Source | 1444 | 12 | entries.push_back({DT_PPC64_GLINK, [=] { | 1445 | 12 | unsigned offset = target->pltHeaderSize - 32; | 1446 | 12 | return in.plt->getVA(0) + offset; | 1447 | 12 | }}); |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::finalizeContents()::'lambda1'()::operator()() const Line | Count | Source | 1444 | 9 | entries.push_back({DT_PPC64_GLINK, [=] { | 1445 | 9 | unsigned offset = target->pltHeaderSize - 32; | 1446 | 9 | return in.plt->getVA(0) + offset; | 1447 | 9 | }}); |
|
1448 | 21 | } |
1449 | 1.26k | |
1450 | 1.26k | addInt(DT_NULL, 0); |
1451 | 1.26k | |
1452 | 1.26k | getParent()->link = this->link; |
1453 | 1.26k | this->size = entries.size() * this->entsize; |
1454 | 1.26k | } lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::finalizeContents() Line | Count | Source | 1234 | 177 | template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { | 1235 | 177 | elf::Partition &part = getPartition(); | 1236 | 177 | bool isMain = part.name.empty(); | 1237 | 177 | | 1238 | 177 | for (StringRef s : config->filterList) | 1239 | 0 | addInt(DT_FILTER, part.dynStrTab->addString(s)); | 1240 | 177 | for (StringRef s : config->auxiliaryList) | 1241 | 0 | addInt(DT_AUXILIARY, part.dynStrTab->addString(s)); | 1242 | 177 | | 1243 | 177 | if (!config->rpath.empty()) | 1244 | 2 | addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH0 , | 1245 | 2 | part.dynStrTab->addString(config->rpath)); | 1246 | 177 | | 1247 | 177 | for (SharedFile *file : sharedFiles) | 1248 | 59 | if (file->isNeeded) | 1249 | 53 | addInt(DT_NEEDED, part.dynStrTab->addString(file->soName)); | 1250 | 177 | | 1251 | 177 | if (isMain) { | 1252 | 174 | if (!config->soName.empty()) | 1253 | 7 | addInt(DT_SONAME, part.dynStrTab->addString(config->soName)); | 1254 | 174 | } else { | 1255 | 3 | if (!config->soName.empty()) | 1256 | 0 | addInt(DT_NEEDED, part.dynStrTab->addString(config->soName)); | 1257 | 3 | addInt(DT_SONAME, part.dynStrTab->addString(part.name)); | 1258 | 3 | } | 1259 | 177 | | 1260 | 177 | // Set DT_FLAGS and DT_FLAGS_1. | 1261 | 177 | uint32_t dtFlags = 0; | 1262 | 177 | uint32_t dtFlags1 = 0; | 1263 | 177 | if (config->bsymbolic) | 1264 | 2 | dtFlags |= DF_SYMBOLIC; | 1265 | 177 | if (config->zGlobal) | 1266 | 0 | dtFlags1 |= DF_1_GLOBAL; | 1267 | 177 | if (config->zInitfirst) | 1268 | 0 | dtFlags1 |= DF_1_INITFIRST; | 1269 | 177 | if (config->zInterpose) | 1270 | 0 | dtFlags1 |= DF_1_INTERPOSE; | 1271 | 177 | if (config->zNodefaultlib) | 1272 | 0 | dtFlags1 |= DF_1_NODEFLIB; | 1273 | 177 | if (config->zNodelete) | 1274 | 0 | dtFlags1 |= DF_1_NODELETE; | 1275 | 177 | if (config->zNodlopen) | 1276 | 0 | dtFlags1 |= DF_1_NOOPEN; | 1277 | 177 | if (config->zNow) { | 1278 | 0 | dtFlags |= DF_BIND_NOW; | 1279 | 0 | dtFlags1 |= DF_1_NOW; | 1280 | 0 | } | 1281 | 177 | if (config->zOrigin) { | 1282 | 0 | dtFlags |= DF_ORIGIN; | 1283 | 0 | dtFlags1 |= DF_1_ORIGIN; | 1284 | 0 | } | 1285 | 177 | if (!config->zText) | 1286 | 1 | dtFlags |= DF_TEXTREL; | 1287 | 177 | if (config->hasStaticTlsModel) | 1288 | 11 | dtFlags |= DF_STATIC_TLS; | 1289 | 177 | | 1290 | 177 | if (dtFlags) | 1291 | 14 | addInt(DT_FLAGS, dtFlags); | 1292 | 177 | if (dtFlags1) | 1293 | 0 | addInt(DT_FLAGS_1, dtFlags1); | 1294 | 177 | | 1295 | 177 | // DT_DEBUG is a pointer to debug informaion used by debuggers at runtime. We | 1296 | 177 | // need it for each process, so we don't write it for DSOs. The loader writes | 1297 | 177 | // the pointer into this entry. | 1298 | 177 | // | 1299 | 177 | // DT_DEBUG is the only .dynamic entry that needs to be written to. Some | 1300 | 177 | // systems (currently only Fuchsia OS) provide other means to give the | 1301 | 177 | // debugger this information. Such systems may choose make .dynamic read-only. | 1302 | 177 | // If the target is such a system (used -z rodynamic) don't write DT_DEBUG. | 1303 | 177 | if (!config->shared && !config->relocatable60 && !config->zRodynamic60 ) | 1304 | 60 | addInt(DT_DEBUG, 0); | 1305 | 177 | | 1306 | 177 | if (OutputSection *sec = part.dynStrTab->getParent()) | 1307 | 177 | this->link = sec->sectionIndex; | 1308 | 177 | | 1309 | 177 | if (part.relaDyn->isNeeded()) { | 1310 | 61 | addInSec(part.relaDyn->dynamicTag, part.relaDyn); | 1311 | 61 | addSize(part.relaDyn->sizeDynamicTag, part.relaDyn->getParent()); | 1312 | 61 | | 1313 | 61 | bool isRela = config->isRela; | 1314 | 61 | addInt(isRela ? DT_RELAENT8 : DT_RELENT53 , | 1315 | 61 | isRela ? sizeof(Elf_Rela)8 : sizeof(Elf_Rel)53 ); | 1316 | 61 | | 1317 | 61 | // MIPS dynamic loader does not support RELCOUNT tag. | 1318 | 61 | // The problem is in the tight relation between dynamic | 1319 | 61 | // relocations and GOT. So do not emit this tag on MIPS. | 1320 | 61 | if (config->emachine != EM_MIPS) { | 1321 | 60 | size_t numRelativeRels = part.relaDyn->getRelativeRelocCount(); | 1322 | 60 | if (config->zCombreloc && numRelativeRels) | 1323 | 16 | addInt(isRela ? DT_RELACOUNT2 : DT_RELCOUNT14 , numRelativeRels); | 1324 | 60 | } | 1325 | 61 | } | 1326 | 177 | if (part.relrDyn && !part.relrDyn->relocs.empty()2 ) { | 1327 | 2 | addInSec(config->useAndroidRelrTags ? DT_ANDROID_RELR0 : DT_RELR, | 1328 | 2 | part.relrDyn); | 1329 | 2 | addSize(config->useAndroidRelrTags ? DT_ANDROID_RELRSZ0 : DT_RELRSZ, | 1330 | 2 | part.relrDyn->getParent()); | 1331 | 2 | addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT0 : DT_RELRENT, | 1332 | 2 | sizeof(Elf_Relr)); | 1333 | 2 | } | 1334 | 177 | // .rel[a].plt section usually consists of two parts, containing plt and | 1335 | 177 | // iplt relocations. It is possible to have only iplt relocations in the | 1336 | 177 | // output. In that case relaPlt is empty and have zero offset, the same offset | 1337 | 177 | // as relaIplt has. And we still want to emit proper dynamic tags for that | 1338 | 177 | // case, so here we always use relaPlt as marker for the begining of | 1339 | 177 | // .rel[a].plt section. | 1340 | 177 | if (isMain && (174 in.relaPlt->isNeeded()174 || in.relaIplt->isNeeded()131 )) { | 1341 | 43 | addInSec(DT_JMPREL, in.relaPlt); | 1342 | 43 | entries.push_back({DT_PLTRELSZ, addPltRelSz}); | 1343 | 43 | switch (config->emachine) { | 1344 | 43 | case EM_MIPS: | 1345 | 2 | addInSec(DT_MIPS_PLTGOT, in.gotPlt); | 1346 | 2 | break; | 1347 | 43 | case EM_SPARCV9: | 1348 | 0 | addInSec(DT_PLTGOT, in.plt); | 1349 | 0 | break; | 1350 | 43 | default: | 1351 | 41 | addInSec(DT_PLTGOT, in.gotPlt); | 1352 | 41 | break; | 1353 | 43 | } | 1354 | 43 | addInt(DT_PLTREL, config->isRela ? DT_RELA5 : DT_REL38 ); | 1355 | 43 | } | 1356 | 177 | | 1357 | 177 | if (config->emachine == EM_AARCH64) { | 1358 | 0 | if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) | 1359 | 0 | addInt(DT_AARCH64_BTI_PLT, 0); | 1360 | 0 | if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC) | 1361 | 0 | addInt(DT_AARCH64_PAC_PLT, 0); | 1362 | 0 | } | 1363 | 177 | | 1364 | 177 | addInSec(DT_SYMTAB, part.dynSymTab); | 1365 | 177 | addInt(DT_SYMENT, sizeof(Elf_Sym)); | 1366 | 177 | addInSec(DT_STRTAB, part.dynStrTab); | 1367 | 177 | addInt(DT_STRSZ, part.dynStrTab->getSize()); | 1368 | 177 | if (!config->zText) | 1369 | 1 | addInt(DT_TEXTREL, 0); | 1370 | 177 | if (part.gnuHashTab) | 1371 | 133 | addInSec(DT_GNU_HASH, part.gnuHashTab); | 1372 | 177 | if (part.hashTab) | 1373 | 175 | addInSec(DT_HASH, part.hashTab); | 1374 | 177 | | 1375 | 177 | if (isMain) { | 1376 | 174 | if (Out::preinitArray) { | 1377 | 0 | addOutSec(DT_PREINIT_ARRAY, Out::preinitArray); | 1378 | 0 | addSize(DT_PREINIT_ARRAYSZ, Out::preinitArray); | 1379 | 0 | } | 1380 | 174 | if (Out::initArray) { | 1381 | 0 | addOutSec(DT_INIT_ARRAY, Out::initArray); | 1382 | 0 | addSize(DT_INIT_ARRAYSZ, Out::initArray); | 1383 | 0 | } | 1384 | 174 | if (Out::finiArray) { | 1385 | 0 | addOutSec(DT_FINI_ARRAY, Out::finiArray); | 1386 | 0 | addSize(DT_FINI_ARRAYSZ, Out::finiArray); | 1387 | 0 | } | 1388 | 174 | | 1389 | 174 | if (Symbol *b = symtab->find(config->init)) | 1390 | 0 | if (b->isDefined()) | 1391 | 0 | addSym(DT_INIT, b); | 1392 | 174 | if (Symbol *b = symtab->find(config->fini)) | 1393 | 0 | if (b->isDefined()) | 1394 | 0 | addSym(DT_FINI, b); | 1395 | 174 | } | 1396 | 177 | | 1397 | 177 | bool hasVerNeed = SharedFile::vernauxNum != 0; | 1398 | 177 | if (hasVerNeed || part.verDef) | 1399 | 0 | addInSec(DT_VERSYM, part.verSym); | 1400 | 177 | if (part.verDef) { | 1401 | 0 | addInSec(DT_VERDEF, part.verDef); | 1402 | 0 | addInt(DT_VERDEFNUM, getVerDefNum()); | 1403 | 0 | } | 1404 | 177 | if (hasVerNeed) { | 1405 | 0 | addInSec(DT_VERNEED, part.verNeed); | 1406 | 0 | unsigned needNum = 0; | 1407 | 0 | for (SharedFile *f : sharedFiles) | 1408 | 0 | if (!f->vernauxs.empty()) | 1409 | 0 | ++needNum; | 1410 | 0 | addInt(DT_VERNEEDNUM, needNum); | 1411 | 0 | } | 1412 | 177 | | 1413 | 177 | if (config->emachine == EM_MIPS) { | 1414 | 8 | addInt(DT_MIPS_RLD_VERSION, 1); | 1415 | 8 | addInt(DT_MIPS_FLAGS, RHF_NOTPOT); | 1416 | 8 | addInt(DT_MIPS_BASE_ADDRESS, target->getImageBase()); | 1417 | 8 | addInt(DT_MIPS_SYMTABNO, part.dynSymTab->getNumSymbols()); | 1418 | 8 | | 1419 | 8 | add(DT_MIPS_LOCAL_GOTNO, [] { return in.mipsGot->getLocalEntriesNum(); }); | 1420 | 8 | | 1421 | 8 | if (const Symbol *b = in.mipsGot->getFirstGlobalEntry()) | 1422 | 3 | addInt(DT_MIPS_GOTSYM, b->dynsymIndex); | 1423 | 5 | else | 1424 | 5 | addInt(DT_MIPS_GOTSYM, part.dynSymTab->getNumSymbols()); | 1425 | 8 | addInSec(DT_PLTGOT, in.mipsGot); | 1426 | 8 | if (in.mipsRldMap) { | 1427 | 2 | if (!config->pie) | 1428 | 2 | addInSec(DT_MIPS_RLD_MAP, in.mipsRldMap); | 1429 | 2 | // Store the offset to the .rld_map section | 1430 | 2 | // relative to the address of the tag. | 1431 | 2 | addInSecRelative(DT_MIPS_RLD_MAP_REL, in.mipsRldMap); | 1432 | 2 | } | 1433 | 8 | } | 1434 | 177 | | 1435 | 177 | // DT_PPC_GOT indicates to glibc Secure PLT is used. If DT_PPC_GOT is absent, | 1436 | 177 | // glibc assumes the old-style BSS PLT layout which we don't support. | 1437 | 177 | if (config->emachine == EM_PPC) | 1438 | 0 | add(DT_PPC_GOT, [] { return in.got->getVA(); }); | 1439 | 177 | | 1440 | 177 | // Glink dynamic tag is required by the V2 abi if the plt section isn't empty. | 1441 | 177 | if (config->emachine == EM_PPC64 && in.plt->isNeeded()0 ) { | 1442 | 0 | // The Glink tag points to 32 bytes before the first lazy symbol resolution | 1443 | 0 | // stub, which starts directly after the header. | 1444 | 0 | entries.push_back({DT_PPC64_GLINK, [=] { | 1445 | 0 | unsigned offset = target->pltHeaderSize - 32; | 1446 | 0 | return in.plt->getVA(0) + offset; | 1447 | 0 | }}); | 1448 | 0 | } | 1449 | 177 | | 1450 | 177 | addInt(DT_NULL, 0); | 1451 | 177 | | 1452 | 177 | getParent()->link = this->link; | 1453 | 177 | this->size = entries.size() * this->entsize; | 1454 | 177 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::finalizeContents() Line | Count | Source | 1234 | 85 | template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { | 1235 | 85 | elf::Partition &part = getPartition(); | 1236 | 85 | bool isMain = part.name.empty(); | 1237 | 85 | | 1238 | 85 | for (StringRef s : config->filterList) | 1239 | 0 | addInt(DT_FILTER, part.dynStrTab->addString(s)); | 1240 | 85 | for (StringRef s : config->auxiliaryList) | 1241 | 0 | addInt(DT_AUXILIARY, part.dynStrTab->addString(s)); | 1242 | 85 | | 1243 | 85 | if (!config->rpath.empty()) | 1244 | 0 | addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH, | 1245 | 0 | part.dynStrTab->addString(config->rpath)); | 1246 | 85 | | 1247 | 85 | for (SharedFile *file : sharedFiles) | 1248 | 29 | if (file->isNeeded) | 1249 | 29 | addInt(DT_NEEDED, part.dynStrTab->addString(file->soName)); | 1250 | 85 | | 1251 | 85 | if (isMain) { | 1252 | 85 | if (!config->soName.empty()) | 1253 | 3 | addInt(DT_SONAME, part.dynStrTab->addString(config->soName)); | 1254 | 85 | } else { | 1255 | 0 | if (!config->soName.empty()) | 1256 | 0 | addInt(DT_NEEDED, part.dynStrTab->addString(config->soName)); | 1257 | 0 | addInt(DT_SONAME, part.dynStrTab->addString(part.name)); | 1258 | 0 | } | 1259 | 85 | | 1260 | 85 | // Set DT_FLAGS and DT_FLAGS_1. | 1261 | 85 | uint32_t dtFlags = 0; | 1262 | 85 | uint32_t dtFlags1 = 0; | 1263 | 85 | if (config->bsymbolic) | 1264 | 1 | dtFlags |= DF_SYMBOLIC; | 1265 | 85 | if (config->zGlobal) | 1266 | 0 | dtFlags1 |= DF_1_GLOBAL; | 1267 | 85 | if (config->zInitfirst) | 1268 | 0 | dtFlags1 |= DF_1_INITFIRST; | 1269 | 85 | if (config->zInterpose) | 1270 | 0 | dtFlags1 |= DF_1_INTERPOSE; | 1271 | 85 | if (config->zNodefaultlib) | 1272 | 0 | dtFlags1 |= DF_1_NODEFLIB; | 1273 | 85 | if (config->zNodelete) | 1274 | 0 | dtFlags1 |= DF_1_NODELETE; | 1275 | 85 | if (config->zNodlopen) | 1276 | 0 | dtFlags1 |= DF_1_NOOPEN; | 1277 | 85 | if (config->zNow) { | 1278 | 0 | dtFlags |= DF_BIND_NOW; | 1279 | 0 | dtFlags1 |= DF_1_NOW; | 1280 | 0 | } | 1281 | 85 | if (config->zOrigin) { | 1282 | 0 | dtFlags |= DF_ORIGIN; | 1283 | 0 | dtFlags1 |= DF_1_ORIGIN; | 1284 | 0 | } | 1285 | 85 | if (!config->zText) | 1286 | 0 | dtFlags |= DF_TEXTREL; | 1287 | 85 | if (config->hasStaticTlsModel) | 1288 | 0 | dtFlags |= DF_STATIC_TLS; | 1289 | 85 | | 1290 | 85 | if (dtFlags) | 1291 | 1 | addInt(DT_FLAGS, dtFlags); | 1292 | 85 | if (dtFlags1) | 1293 | 0 | addInt(DT_FLAGS_1, dtFlags1); | 1294 | 85 | | 1295 | 85 | // DT_DEBUG is a pointer to debug informaion used by debuggers at runtime. We | 1296 | 85 | // need it for each process, so we don't write it for DSOs. The loader writes | 1297 | 85 | // the pointer into this entry. | 1298 | 85 | // | 1299 | 85 | // DT_DEBUG is the only .dynamic entry that needs to be written to. Some | 1300 | 85 | // systems (currently only Fuchsia OS) provide other means to give the | 1301 | 85 | // debugger this information. Such systems may choose make .dynamic read-only. | 1302 | 85 | // If the target is such a system (used -z rodynamic) don't write DT_DEBUG. | 1303 | 85 | if (!config->shared && !config->relocatable26 && !config->zRodynamic26 ) | 1304 | 26 | addInt(DT_DEBUG, 0); | 1305 | 85 | | 1306 | 85 | if (OutputSection *sec = part.dynStrTab->getParent()) | 1307 | 85 | this->link = sec->sectionIndex; | 1308 | 85 | | 1309 | 85 | if (part.relaDyn->isNeeded()) { | 1310 | 16 | addInSec(part.relaDyn->dynamicTag, part.relaDyn); | 1311 | 16 | addSize(part.relaDyn->sizeDynamicTag, part.relaDyn->getParent()); | 1312 | 16 | | 1313 | 16 | bool isRela = config->isRela; | 1314 | 16 | addInt(isRela ? DT_RELAENT9 : DT_RELENT7 , | 1315 | 16 | isRela ? sizeof(Elf_Rela)9 : sizeof(Elf_Rel)7 ); | 1316 | 16 | | 1317 | 16 | // MIPS dynamic loader does not support RELCOUNT tag. | 1318 | 16 | // The problem is in the tight relation between dynamic | 1319 | 16 | // relocations and GOT. So do not emit this tag on MIPS. | 1320 | 16 | if (config->emachine != EM_MIPS) { | 1321 | 9 | size_t numRelativeRels = part.relaDyn->getRelativeRelocCount(); | 1322 | 9 | if (config->zCombreloc && numRelativeRels) | 1323 | 1 | addInt(isRela ? DT_RELACOUNT : DT_RELCOUNT0 , numRelativeRels); | 1324 | 9 | } | 1325 | 16 | } | 1326 | 85 | if (part.relrDyn && !part.relrDyn->relocs.empty()0 ) { | 1327 | 0 | addInSec(config->useAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR, | 1328 | 0 | part.relrDyn); | 1329 | 0 | addSize(config->useAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ, | 1330 | 0 | part.relrDyn->getParent()); | 1331 | 0 | addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT, | 1332 | 0 | sizeof(Elf_Relr)); | 1333 | 0 | } | 1334 | 85 | // .rel[a].plt section usually consists of two parts, containing plt and | 1335 | 85 | // iplt relocations. It is possible to have only iplt relocations in the | 1336 | 85 | // output. In that case relaPlt is empty and have zero offset, the same offset | 1337 | 85 | // as relaIplt has. And we still want to emit proper dynamic tags for that | 1338 | 85 | // case, so here we always use relaPlt as marker for the begining of | 1339 | 85 | // .rel[a].plt section. | 1340 | 85 | if (isMain && (in.relaPlt->isNeeded() || in.relaIplt->isNeeded()68 )) { | 1341 | 17 | addInSec(DT_JMPREL, in.relaPlt); | 1342 | 17 | entries.push_back({DT_PLTRELSZ, addPltRelSz}); | 1343 | 17 | switch (config->emachine) { | 1344 | 17 | case EM_MIPS: | 1345 | 11 | addInSec(DT_MIPS_PLTGOT, in.gotPlt); | 1346 | 11 | break; | 1347 | 17 | case EM_SPARCV9: | 1348 | 0 | addInSec(DT_PLTGOT, in.plt); | 1349 | 0 | break; | 1350 | 17 | default: | 1351 | 6 | addInSec(DT_PLTGOT, in.gotPlt); | 1352 | 6 | break; | 1353 | 17 | } | 1354 | 17 | addInt(DT_PLTREL, config->isRela ? DT_RELA6 : DT_REL11 ); | 1355 | 17 | } | 1356 | 85 | | 1357 | 85 | if (config->emachine == EM_AARCH64) { | 1358 | 0 | if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) | 1359 | 0 | addInt(DT_AARCH64_BTI_PLT, 0); | 1360 | 0 | if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC) | 1361 | 0 | addInt(DT_AARCH64_PAC_PLT, 0); | 1362 | 0 | } | 1363 | 85 | | 1364 | 85 | addInSec(DT_SYMTAB, part.dynSymTab); | 1365 | 85 | addInt(DT_SYMENT, sizeof(Elf_Sym)); | 1366 | 85 | addInSec(DT_STRTAB, part.dynStrTab); | 1367 | 85 | addInt(DT_STRSZ, part.dynStrTab->getSize()); | 1368 | 85 | if (!config->zText) | 1369 | 0 | addInt(DT_TEXTREL, 0); | 1370 | 85 | if (part.gnuHashTab) | 1371 | 16 | addInSec(DT_GNU_HASH, part.gnuHashTab); | 1372 | 85 | if (part.hashTab) | 1373 | 85 | addInSec(DT_HASH, part.hashTab); | 1374 | 85 | | 1375 | 85 | if (isMain) { | 1376 | 85 | if (Out::preinitArray) { | 1377 | 0 | addOutSec(DT_PREINIT_ARRAY, Out::preinitArray); | 1378 | 0 | addSize(DT_PREINIT_ARRAYSZ, Out::preinitArray); | 1379 | 0 | } | 1380 | 85 | if (Out::initArray) { | 1381 | 0 | addOutSec(DT_INIT_ARRAY, Out::initArray); | 1382 | 0 | addSize(DT_INIT_ARRAYSZ, Out::initArray); | 1383 | 0 | } | 1384 | 85 | if (Out::finiArray) { | 1385 | 0 | addOutSec(DT_FINI_ARRAY, Out::finiArray); | 1386 | 0 | addSize(DT_FINI_ARRAYSZ, Out::finiArray); | 1387 | 0 | } | 1388 | 85 | | 1389 | 85 | if (Symbol *b = symtab->find(config->init)) | 1390 | 0 | if (b->isDefined()) | 1391 | 0 | addSym(DT_INIT, b); | 1392 | 85 | if (Symbol *b = symtab->find(config->fini)) | 1393 | 0 | if (b->isDefined()) | 1394 | 0 | addSym(DT_FINI, b); | 1395 | 85 | } | 1396 | 85 | | 1397 | 85 | bool hasVerNeed = SharedFile::vernauxNum != 0; | 1398 | 85 | if (hasVerNeed || part.verDef84 ) | 1399 | 1 | addInSec(DT_VERSYM, part.verSym); | 1400 | 85 | if (part.verDef) { | 1401 | 0 | addInSec(DT_VERDEF, part.verDef); | 1402 | 0 | addInt(DT_VERDEFNUM, getVerDefNum()); | 1403 | 0 | } | 1404 | 85 | if (hasVerNeed) { | 1405 | 1 | addInSec(DT_VERNEED, part.verNeed); | 1406 | 1 | unsigned needNum = 0; | 1407 | 1 | for (SharedFile *f : sharedFiles) | 1408 | 1 | if (!f->vernauxs.empty()) | 1409 | 1 | ++needNum; | 1410 | 1 | addInt(DT_VERNEEDNUM, needNum); | 1411 | 1 | } | 1412 | 85 | | 1413 | 85 | if (config->emachine == EM_MIPS) { | 1414 | 69 | addInt(DT_MIPS_RLD_VERSION, 1); | 1415 | 69 | addInt(DT_MIPS_FLAGS, RHF_NOTPOT); | 1416 | 69 | addInt(DT_MIPS_BASE_ADDRESS, target->getImageBase()); | 1417 | 69 | addInt(DT_MIPS_SYMTABNO, part.dynSymTab->getNumSymbols()); | 1418 | 69 | | 1419 | 69 | add(DT_MIPS_LOCAL_GOTNO, [] { return in.mipsGot->getLocalEntriesNum(); }); | 1420 | 69 | | 1421 | 69 | if (const Symbol *b = in.mipsGot->getFirstGlobalEntry()) | 1422 | 23 | addInt(DT_MIPS_GOTSYM, b->dynsymIndex); | 1423 | 46 | else | 1424 | 46 | addInt(DT_MIPS_GOTSYM, part.dynSymTab->getNumSymbols()); | 1425 | 69 | addInSec(DT_PLTGOT, in.mipsGot); | 1426 | 69 | if (in.mipsRldMap) { | 1427 | 21 | if (!config->pie) | 1428 | 19 | addInSec(DT_MIPS_RLD_MAP, in.mipsRldMap); | 1429 | 21 | // Store the offset to the .rld_map section | 1430 | 21 | // relative to the address of the tag. | 1431 | 21 | addInSecRelative(DT_MIPS_RLD_MAP_REL, in.mipsRldMap); | 1432 | 21 | } | 1433 | 69 | } | 1434 | 85 | | 1435 | 85 | // DT_PPC_GOT indicates to glibc Secure PLT is used. If DT_PPC_GOT is absent, | 1436 | 85 | // glibc assumes the old-style BSS PLT layout which we don't support. | 1437 | 85 | if (config->emachine == EM_PPC) | 1438 | 16 | add(DT_PPC_GOT, [] { return in.got->getVA(); }); | 1439 | 85 | | 1440 | 85 | // Glink dynamic tag is required by the V2 abi if the plt section isn't empty. | 1441 | 85 | if (config->emachine == EM_PPC64 && in.plt->isNeeded()0 ) { | 1442 | 0 | // The Glink tag points to 32 bytes before the first lazy symbol resolution | 1443 | 0 | // stub, which starts directly after the header. | 1444 | 0 | entries.push_back({DT_PPC64_GLINK, [=] { | 1445 | 0 | unsigned offset = target->pltHeaderSize - 32; | 1446 | 0 | return in.plt->getVA(0) + offset; | 1447 | 0 | }}); | 1448 | 0 | } | 1449 | 85 | | 1450 | 85 | addInt(DT_NULL, 0); | 1451 | 85 | | 1452 | 85 | getParent()->link = this->link; | 1453 | 85 | this->size = entries.size() * this->entsize; | 1454 | 85 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::finalizeContents() Line | Count | Source | 1234 | 951 | template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { | 1235 | 951 | elf::Partition &part = getPartition(); | 1236 | 951 | bool isMain = part.name.empty(); | 1237 | 951 | | 1238 | 951 | for (StringRef s : config->filterList) | 1239 | 6 | addInt(DT_FILTER, part.dynStrTab->addString(s)); | 1240 | 951 | for (StringRef s : config->auxiliaryList) | 1241 | 4 | addInt(DT_AUXILIARY, part.dynStrTab->addString(s)); | 1242 | 951 | | 1243 | 951 | if (!config->rpath.empty()) | 1244 | 4 | addInt(config->enableNewDtags ? DT_RUNPATH3 : DT_RPATH1 , | 1245 | 4 | part.dynStrTab->addString(config->rpath)); | 1246 | 951 | | 1247 | 951 | for (SharedFile *file : sharedFiles) | 1248 | 275 | if (file->isNeeded) | 1249 | 264 | addInt(DT_NEEDED, part.dynStrTab->addString(file->soName)); | 1250 | 951 | | 1251 | 951 | if (isMain) { | 1252 | 943 | if (!config->soName.empty()) | 1253 | 35 | addInt(DT_SONAME, part.dynStrTab->addString(config->soName)); | 1254 | 943 | } else { | 1255 | 8 | if (!config->soName.empty()) | 1256 | 1 | addInt(DT_NEEDED, part.dynStrTab->addString(config->soName)); | 1257 | 8 | addInt(DT_SONAME, part.dynStrTab->addString(part.name)); | 1258 | 8 | } | 1259 | 951 | | 1260 | 951 | // Set DT_FLAGS and DT_FLAGS_1. | 1261 | 951 | uint32_t dtFlags = 0; | 1262 | 951 | uint32_t dtFlags1 = 0; | 1263 | 951 | if (config->bsymbolic) | 1264 | 4 | dtFlags |= DF_SYMBOLIC; | 1265 | 951 | if (config->zGlobal) | 1266 | 1 | dtFlags1 |= DF_1_GLOBAL; | 1267 | 951 | if (config->zInitfirst) | 1268 | 1 | dtFlags1 |= DF_1_INITFIRST; | 1269 | 951 | if (config->zInterpose) | 1270 | 1 | dtFlags1 |= DF_1_INTERPOSE; | 1271 | 951 | if (config->zNodefaultlib) | 1272 | 1 | dtFlags1 |= DF_1_NODEFLIB; | 1273 | 951 | if (config->zNodelete) | 1274 | 1 | dtFlags1 |= DF_1_NODELETE; | 1275 | 951 | if (config->zNodlopen) | 1276 | 1 | dtFlags1 |= DF_1_NOOPEN; | 1277 | 951 | if (config->zNow) { | 1278 | 4 | dtFlags |= DF_BIND_NOW; | 1279 | 4 | dtFlags1 |= DF_1_NOW; | 1280 | 4 | } | 1281 | 951 | if (config->zOrigin) { | 1282 | 1 | dtFlags |= DF_ORIGIN; | 1283 | 1 | dtFlags1 |= DF_1_ORIGIN; | 1284 | 1 | } | 1285 | 951 | if (!config->zText) | 1286 | 8 | dtFlags |= DF_TEXTREL; | 1287 | 951 | if (config->hasStaticTlsModel) | 1288 | 7 | dtFlags |= DF_STATIC_TLS; | 1289 | 951 | | 1290 | 951 | if (dtFlags) | 1291 | 22 | addInt(DT_FLAGS, dtFlags); | 1292 | 951 | if (dtFlags1) | 1293 | 4 | addInt(DT_FLAGS_1, dtFlags1); | 1294 | 951 | | 1295 | 951 | // DT_DEBUG is a pointer to debug informaion used by debuggers at runtime. We | 1296 | 951 | // need it for each process, so we don't write it for DSOs. The loader writes | 1297 | 951 | // the pointer into this entry. | 1298 | 951 | // | 1299 | 951 | // DT_DEBUG is the only .dynamic entry that needs to be written to. Some | 1300 | 951 | // systems (currently only Fuchsia OS) provide other means to give the | 1301 | 951 | // debugger this information. Such systems may choose make .dynamic read-only. | 1302 | 951 | // If the target is such a system (used -z rodynamic) don't write DT_DEBUG. | 1303 | 951 | if (!config->shared && !config->relocatable284 && !config->zRodynamic282 ) | 1304 | 281 | addInt(DT_DEBUG, 0); | 1305 | 951 | | 1306 | 951 | if (OutputSection *sec = part.dynStrTab->getParent()) | 1307 | 950 | this->link = sec->sectionIndex; | 1308 | 951 | | 1309 | 951 | if (part.relaDyn->isNeeded()) { | 1310 | 185 | addInSec(part.relaDyn->dynamicTag, part.relaDyn); | 1311 | 185 | addSize(part.relaDyn->sizeDynamicTag, part.relaDyn->getParent()); | 1312 | 185 | | 1313 | 185 | bool isRela = config->isRela; | 1314 | 185 | addInt(isRela ? DT_RELAENT : DT_RELENT0 , | 1315 | 185 | isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel)0 ); | 1316 | 185 | | 1317 | 185 | // MIPS dynamic loader does not support RELCOUNT tag. | 1318 | 185 | // The problem is in the tight relation between dynamic | 1319 | 185 | // relocations and GOT. So do not emit this tag on MIPS. | 1320 | 185 | if (config->emachine != EM_MIPS) { | 1321 | 185 | size_t numRelativeRels = part.relaDyn->getRelativeRelocCount(); | 1322 | 185 | if (config->zCombreloc && numRelativeRels184 ) | 1323 | 40 | addInt(isRela ? DT_RELACOUNT : DT_RELCOUNT0 , numRelativeRels); | 1324 | 185 | } | 1325 | 185 | } | 1326 | 951 | if (part.relrDyn && !part.relrDyn->relocs.empty()4 ) { | 1327 | 3 | addInSec(config->useAndroidRelrTags ? DT_ANDROID_RELR0 : DT_RELR, | 1328 | 3 | part.relrDyn); | 1329 | 3 | addSize(config->useAndroidRelrTags ? DT_ANDROID_RELRSZ0 : DT_RELRSZ, | 1330 | 3 | part.relrDyn->getParent()); | 1331 | 3 | addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT0 : DT_RELRENT, | 1332 | 3 | sizeof(Elf_Relr)); | 1333 | 3 | } | 1334 | 951 | // .rel[a].plt section usually consists of two parts, containing plt and | 1335 | 951 | // iplt relocations. It is possible to have only iplt relocations in the | 1336 | 951 | // output. In that case relaPlt is empty and have zero offset, the same offset | 1337 | 951 | // as relaIplt has. And we still want to emit proper dynamic tags for that | 1338 | 951 | // case, so here we always use relaPlt as marker for the begining of | 1339 | 951 | // .rel[a].plt section. | 1340 | 951 | if (isMain && (943 in.relaPlt->isNeeded()943 || in.relaIplt->isNeeded()754 )) { | 1341 | 199 | addInSec(DT_JMPREL, in.relaPlt); | 1342 | 199 | entries.push_back({DT_PLTRELSZ, addPltRelSz}); | 1343 | 199 | switch (config->emachine) { | 1344 | 199 | case EM_MIPS: | 1345 | 0 | addInSec(DT_MIPS_PLTGOT, in.gotPlt); | 1346 | 0 | break; | 1347 | 199 | case EM_SPARCV9: | 1348 | 0 | addInSec(DT_PLTGOT, in.plt); | 1349 | 0 | break; | 1350 | 199 | default: | 1351 | 199 | addInSec(DT_PLTGOT, in.gotPlt); | 1352 | 199 | break; | 1353 | 199 | } | 1354 | 199 | addInt(DT_PLTREL, config->isRela ? DT_RELA : DT_REL0 ); | 1355 | 199 | } | 1356 | 951 | | 1357 | 951 | if (config->emachine == EM_AARCH64) { | 1358 | 53 | if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) | 1359 | 8 | addInt(DT_AARCH64_BTI_PLT, 0); | 1360 | 53 | if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC) | 1361 | 5 | addInt(DT_AARCH64_PAC_PLT, 0); | 1362 | 53 | } | 1363 | 951 | | 1364 | 951 | addInSec(DT_SYMTAB, part.dynSymTab); | 1365 | 951 | addInt(DT_SYMENT, sizeof(Elf_Sym)); | 1366 | 951 | addInSec(DT_STRTAB, part.dynStrTab); | 1367 | 951 | addInt(DT_STRSZ, part.dynStrTab->getSize()); | 1368 | 951 | if (!config->zText) | 1369 | 8 | addInt(DT_TEXTREL, 0); | 1370 | 951 | if (part.gnuHashTab) | 1371 | 853 | addInSec(DT_GNU_HASH, part.gnuHashTab); | 1372 | 951 | if (part.hashTab) | 1373 | 944 | addInSec(DT_HASH, part.hashTab); | 1374 | 951 | | 1375 | 951 | if (isMain) { | 1376 | 943 | if (Out::preinitArray) { | 1377 | 3 | addOutSec(DT_PREINIT_ARRAY, Out::preinitArray); | 1378 | 3 | addSize(DT_PREINIT_ARRAYSZ, Out::preinitArray); | 1379 | 3 | } | 1380 | 943 | if (Out::initArray) { | 1381 | 4 | addOutSec(DT_INIT_ARRAY, Out::initArray); | 1382 | 4 | addSize(DT_INIT_ARRAYSZ, Out::initArray); | 1383 | 4 | } | 1384 | 943 | if (Out::finiArray) { | 1385 | 2 | addOutSec(DT_FINI_ARRAY, Out::finiArray); | 1386 | 2 | addSize(DT_FINI_ARRAYSZ, Out::finiArray); | 1387 | 2 | } | 1388 | 943 | | 1389 | 943 | if (Symbol *b = symtab->find(config->init)) | 1390 | 6 | if (b->isDefined()) | 1391 | 4 | addSym(DT_INIT, b); | 1392 | 943 | if (Symbol *b = symtab->find(config->fini)) | 1393 | 6 | if (b->isDefined()) | 1394 | 4 | addSym(DT_FINI, b); | 1395 | 943 | } | 1396 | 951 | | 1397 | 951 | bool hasVerNeed = SharedFile::vernauxNum != 0; | 1398 | 951 | if (hasVerNeed || part.verDef942 ) | 1399 | 66 | addInSec(DT_VERSYM, part.verSym); | 1400 | 951 | if (part.verDef) { | 1401 | 60 | addInSec(DT_VERDEF, part.verDef); | 1402 | 60 | addInt(DT_VERDEFNUM, getVerDefNum()); | 1403 | 60 | } | 1404 | 951 | if (hasVerNeed) { | 1405 | 9 | addInSec(DT_VERNEED, part.verNeed); | 1406 | 9 | unsigned needNum = 0; | 1407 | 9 | for (SharedFile *f : sharedFiles) | 1408 | 10 | if (!f->vernauxs.empty()) | 1409 | 10 | ++needNum; | 1410 | 9 | addInt(DT_VERNEEDNUM, needNum); | 1411 | 9 | } | 1412 | 951 | | 1413 | 951 | if (config->emachine == EM_MIPS) { | 1414 | 0 | addInt(DT_MIPS_RLD_VERSION, 1); | 1415 | 0 | addInt(DT_MIPS_FLAGS, RHF_NOTPOT); | 1416 | 0 | addInt(DT_MIPS_BASE_ADDRESS, target->getImageBase()); | 1417 | 0 | addInt(DT_MIPS_SYMTABNO, part.dynSymTab->getNumSymbols()); | 1418 | 0 |
| 1419 | 0 | add(DT_MIPS_LOCAL_GOTNO, [] { return in.mipsGot->getLocalEntriesNum(); }); | 1420 | 0 |
| 1421 | 0 | if (const Symbol *b = in.mipsGot->getFirstGlobalEntry()) | 1422 | 0 | addInt(DT_MIPS_GOTSYM, b->dynsymIndex); | 1423 | 0 | else | 1424 | 0 | addInt(DT_MIPS_GOTSYM, part.dynSymTab->getNumSymbols()); | 1425 | 0 | addInSec(DT_PLTGOT, in.mipsGot); | 1426 | 0 | if (in.mipsRldMap) { | 1427 | 0 | if (!config->pie) | 1428 | 0 | addInSec(DT_MIPS_RLD_MAP, in.mipsRldMap); | 1429 | 0 | // Store the offset to the .rld_map section | 1430 | 0 | // relative to the address of the tag. | 1431 | 0 | addInSecRelative(DT_MIPS_RLD_MAP_REL, in.mipsRldMap); | 1432 | 0 | } | 1433 | 0 | } | 1434 | 951 | | 1435 | 951 | // DT_PPC_GOT indicates to glibc Secure PLT is used. If DT_PPC_GOT is absent, | 1436 | 951 | // glibc assumes the old-style BSS PLT layout which we don't support. | 1437 | 951 | if (config->emachine == EM_PPC) | 1438 | 0 | add(DT_PPC_GOT, [] { return in.got->getVA(); }); | 1439 | 951 | | 1440 | 951 | // Glink dynamic tag is required by the V2 abi if the plt section isn't empty. | 1441 | 951 | if (config->emachine == EM_PPC64 && in.plt->isNeeded()41 ) { | 1442 | 12 | // The Glink tag points to 32 bytes before the first lazy symbol resolution | 1443 | 12 | // stub, which starts directly after the header. | 1444 | 12 | entries.push_back({DT_PPC64_GLINK, [=] { | 1445 | 12 | unsigned offset = target->pltHeaderSize - 32; | 1446 | 12 | return in.plt->getVA(0) + offset; | 1447 | 12 | }}); | 1448 | 12 | } | 1449 | 951 | | 1450 | 951 | addInt(DT_NULL, 0); | 1451 | 951 | | 1452 | 951 | getParent()->link = this->link; | 1453 | 951 | this->size = entries.size() * this->entsize; | 1454 | 951 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::finalizeContents() Line | Count | Source | 1234 | 50 | template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { | 1235 | 50 | elf::Partition &part = getPartition(); | 1236 | 50 | bool isMain = part.name.empty(); | 1237 | 50 | | 1238 | 50 | for (StringRef s : config->filterList) | 1239 | 0 | addInt(DT_FILTER, part.dynStrTab->addString(s)); | 1240 | 50 | for (StringRef s : config->auxiliaryList) | 1241 | 0 | addInt(DT_AUXILIARY, part.dynStrTab->addString(s)); | 1242 | 50 | | 1243 | 50 | if (!config->rpath.empty()) | 1244 | 1 | addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH0 , | 1245 | 1 | part.dynStrTab->addString(config->rpath)); | 1246 | 50 | | 1247 | 50 | for (SharedFile *file : sharedFiles) | 1248 | 14 | if (file->isNeeded) | 1249 | 14 | addInt(DT_NEEDED, part.dynStrTab->addString(file->soName)); | 1250 | 50 | | 1251 | 50 | if (isMain) { | 1252 | 50 | if (!config->soName.empty()) | 1253 | 1 | addInt(DT_SONAME, part.dynStrTab->addString(config->soName)); | 1254 | 50 | } else { | 1255 | 0 | if (!config->soName.empty()) | 1256 | 0 | addInt(DT_NEEDED, part.dynStrTab->addString(config->soName)); | 1257 | 0 | addInt(DT_SONAME, part.dynStrTab->addString(part.name)); | 1258 | 0 | } | 1259 | 50 | | 1260 | 50 | // Set DT_FLAGS and DT_FLAGS_1. | 1261 | 50 | uint32_t dtFlags = 0; | 1262 | 50 | uint32_t dtFlags1 = 0; | 1263 | 50 | if (config->bsymbolic) | 1264 | 1 | dtFlags |= DF_SYMBOLIC; | 1265 | 50 | if (config->zGlobal) | 1266 | 0 | dtFlags1 |= DF_1_GLOBAL; | 1267 | 50 | if (config->zInitfirst) | 1268 | 0 | dtFlags1 |= DF_1_INITFIRST; | 1269 | 50 | if (config->zInterpose) | 1270 | 0 | dtFlags1 |= DF_1_INTERPOSE; | 1271 | 50 | if (config->zNodefaultlib) | 1272 | 0 | dtFlags1 |= DF_1_NODEFLIB; | 1273 | 50 | if (config->zNodelete) | 1274 | 0 | dtFlags1 |= DF_1_NODELETE; | 1275 | 50 | if (config->zNodlopen) | 1276 | 0 | dtFlags1 |= DF_1_NOOPEN; | 1277 | 50 | if (config->zNow) { | 1278 | 0 | dtFlags |= DF_BIND_NOW; | 1279 | 0 | dtFlags1 |= DF_1_NOW; | 1280 | 0 | } | 1281 | 50 | if (config->zOrigin) { | 1282 | 0 | dtFlags |= DF_ORIGIN; | 1283 | 0 | dtFlags1 |= DF_1_ORIGIN; | 1284 | 0 | } | 1285 | 50 | if (!config->zText) | 1286 | 2 | dtFlags |= DF_TEXTREL; | 1287 | 50 | if (config->hasStaticTlsModel) | 1288 | 0 | dtFlags |= DF_STATIC_TLS; | 1289 | 50 | | 1290 | 50 | if (dtFlags) | 1291 | 3 | addInt(DT_FLAGS, dtFlags); | 1292 | 50 | if (dtFlags1) | 1293 | 0 | addInt(DT_FLAGS_1, dtFlags1); | 1294 | 50 | | 1295 | 50 | // DT_DEBUG is a pointer to debug informaion used by debuggers at runtime. We | 1296 | 50 | // need it for each process, so we don't write it for DSOs. The loader writes | 1297 | 50 | // the pointer into this entry. | 1298 | 50 | // | 1299 | 50 | // DT_DEBUG is the only .dynamic entry that needs to be written to. Some | 1300 | 50 | // systems (currently only Fuchsia OS) provide other means to give the | 1301 | 50 | // debugger this information. Such systems may choose make .dynamic read-only. | 1302 | 50 | // If the target is such a system (used -z rodynamic) don't write DT_DEBUG. | 1303 | 50 | if (!config->shared && !config->relocatable12 && !config->zRodynamic12 ) | 1304 | 12 | addInt(DT_DEBUG, 0); | 1305 | 50 | | 1306 | 50 | if (OutputSection *sec = part.dynStrTab->getParent()) | 1307 | 50 | this->link = sec->sectionIndex; | 1308 | 50 | | 1309 | 50 | if (part.relaDyn->isNeeded()) { | 1310 | 19 | addInSec(part.relaDyn->dynamicTag, part.relaDyn); | 1311 | 19 | addSize(part.relaDyn->sizeDynamicTag, part.relaDyn->getParent()); | 1312 | 19 | | 1313 | 19 | bool isRela = config->isRela; | 1314 | 19 | addInt(isRela ? DT_RELAENT11 : DT_RELENT8 , | 1315 | 19 | isRela ? sizeof(Elf_Rela)11 : sizeof(Elf_Rel)8 ); | 1316 | 19 | | 1317 | 19 | // MIPS dynamic loader does not support RELCOUNT tag. | 1318 | 19 | // The problem is in the tight relation between dynamic | 1319 | 19 | // relocations and GOT. So do not emit this tag on MIPS. | 1320 | 19 | if (config->emachine != EM_MIPS) { | 1321 | 11 | size_t numRelativeRels = part.relaDyn->getRelativeRelocCount(); | 1322 | 11 | if (config->zCombreloc && numRelativeRels) | 1323 | 2 | addInt(isRela ? DT_RELACOUNT : DT_RELCOUNT0 , numRelativeRels); | 1324 | 11 | } | 1325 | 19 | } | 1326 | 50 | if (part.relrDyn && !part.relrDyn->relocs.empty()0 ) { | 1327 | 0 | addInSec(config->useAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR, | 1328 | 0 | part.relrDyn); | 1329 | 0 | addSize(config->useAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ, | 1330 | 0 | part.relrDyn->getParent()); | 1331 | 0 | addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT, | 1332 | 0 | sizeof(Elf_Relr)); | 1333 | 0 | } | 1334 | 50 | // .rel[a].plt section usually consists of two parts, containing plt and | 1335 | 50 | // iplt relocations. It is possible to have only iplt relocations in the | 1336 | 50 | // output. In that case relaPlt is empty and have zero offset, the same offset | 1337 | 50 | // as relaIplt has. And we still want to emit proper dynamic tags for that | 1338 | 50 | // case, so here we always use relaPlt as marker for the begining of | 1339 | 50 | // .rel[a].plt section. | 1340 | 50 | if (isMain && (in.relaPlt->isNeeded() || in.relaIplt->isNeeded()39 )) { | 1341 | 11 | addInSec(DT_JMPREL, in.relaPlt); | 1342 | 11 | entries.push_back({DT_PLTRELSZ, addPltRelSz}); | 1343 | 11 | switch (config->emachine) { | 1344 | 11 | case EM_MIPS: | 1345 | 2 | addInSec(DT_MIPS_PLTGOT, in.gotPlt); | 1346 | 2 | break; | 1347 | 11 | case EM_SPARCV9: | 1348 | 0 | addInSec(DT_PLTGOT, in.plt); | 1349 | 0 | break; | 1350 | 11 | default: | 1351 | 9 | addInSec(DT_PLTGOT, in.gotPlt); | 1352 | 9 | break; | 1353 | 11 | } | 1354 | 11 | addInt(DT_PLTREL, config->isRela ? DT_RELA9 : DT_REL2 ); | 1355 | 11 | } | 1356 | 50 | | 1357 | 50 | if (config->emachine == EM_AARCH64) { | 1358 | 0 | if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) | 1359 | 0 | addInt(DT_AARCH64_BTI_PLT, 0); | 1360 | 0 | if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC) | 1361 | 0 | addInt(DT_AARCH64_PAC_PLT, 0); | 1362 | 0 | } | 1363 | 50 | | 1364 | 50 | addInSec(DT_SYMTAB, part.dynSymTab); | 1365 | 50 | addInt(DT_SYMENT, sizeof(Elf_Sym)); | 1366 | 50 | addInSec(DT_STRTAB, part.dynStrTab); | 1367 | 50 | addInt(DT_STRSZ, part.dynStrTab->getSize()); | 1368 | 50 | if (!config->zText) | 1369 | 2 | addInt(DT_TEXTREL, 0); | 1370 | 50 | if (part.gnuHashTab) | 1371 | 26 | addInSec(DT_GNU_HASH, part.gnuHashTab); | 1372 | 50 | if (part.hashTab) | 1373 | 50 | addInSec(DT_HASH, part.hashTab); | 1374 | 50 | | 1375 | 50 | if (isMain) { | 1376 | 50 | if (Out::preinitArray) { | 1377 | 0 | addOutSec(DT_PREINIT_ARRAY, Out::preinitArray); | 1378 | 0 | addSize(DT_PREINIT_ARRAYSZ, Out::preinitArray); | 1379 | 0 | } | 1380 | 50 | if (Out::initArray) { | 1381 | 0 | addOutSec(DT_INIT_ARRAY, Out::initArray); | 1382 | 0 | addSize(DT_INIT_ARRAYSZ, Out::initArray); | 1383 | 0 | } | 1384 | 50 | if (Out::finiArray) { | 1385 | 0 | addOutSec(DT_FINI_ARRAY, Out::finiArray); | 1386 | 0 | addSize(DT_FINI_ARRAYSZ, Out::finiArray); | 1387 | 0 | } | 1388 | 50 | | 1389 | 50 | if (Symbol *b = symtab->find(config->init)) | 1390 | 0 | if (b->isDefined()) | 1391 | 0 | addSym(DT_INIT, b); | 1392 | 50 | if (Symbol *b = symtab->find(config->fini)) | 1393 | 0 | if (b->isDefined()) | 1394 | 0 | addSym(DT_FINI, b); | 1395 | 50 | } | 1396 | 50 | | 1397 | 50 | bool hasVerNeed = SharedFile::vernauxNum != 0; | 1398 | 50 | if (hasVerNeed || part.verDef) | 1399 | 0 | addInSec(DT_VERSYM, part.verSym); | 1400 | 50 | if (part.verDef) { | 1401 | 0 | addInSec(DT_VERDEF, part.verDef); | 1402 | 0 | addInt(DT_VERDEFNUM, getVerDefNum()); | 1403 | 0 | } | 1404 | 50 | if (hasVerNeed) { | 1405 | 0 | addInSec(DT_VERNEED, part.verNeed); | 1406 | 0 | unsigned needNum = 0; | 1407 | 0 | for (SharedFile *f : sharedFiles) | 1408 | 0 | if (!f->vernauxs.empty()) | 1409 | 0 | ++needNum; | 1410 | 0 | addInt(DT_VERNEEDNUM, needNum); | 1411 | 0 | } | 1412 | 50 | | 1413 | 50 | if (config->emachine == EM_MIPS) { | 1414 | 23 | addInt(DT_MIPS_RLD_VERSION, 1); | 1415 | 23 | addInt(DT_MIPS_FLAGS, RHF_NOTPOT); | 1416 | 23 | addInt(DT_MIPS_BASE_ADDRESS, target->getImageBase()); | 1417 | 23 | addInt(DT_MIPS_SYMTABNO, part.dynSymTab->getNumSymbols()); | 1418 | 23 | | 1419 | 23 | add(DT_MIPS_LOCAL_GOTNO, [] { return in.mipsGot->getLocalEntriesNum(); }); | 1420 | 23 | | 1421 | 23 | if (const Symbol *b = in.mipsGot->getFirstGlobalEntry()) | 1422 | 6 | addInt(DT_MIPS_GOTSYM, b->dynsymIndex); | 1423 | 17 | else | 1424 | 17 | addInt(DT_MIPS_GOTSYM, part.dynSymTab->getNumSymbols()); | 1425 | 23 | addInSec(DT_PLTGOT, in.mipsGot); | 1426 | 23 | if (in.mipsRldMap) { | 1427 | 6 | if (!config->pie) | 1428 | 5 | addInSec(DT_MIPS_RLD_MAP, in.mipsRldMap); | 1429 | 6 | // Store the offset to the .rld_map section | 1430 | 6 | // relative to the address of the tag. | 1431 | 6 | addInSecRelative(DT_MIPS_RLD_MAP_REL, in.mipsRldMap); | 1432 | 6 | } | 1433 | 23 | } | 1434 | 50 | | 1435 | 50 | // DT_PPC_GOT indicates to glibc Secure PLT is used. If DT_PPC_GOT is absent, | 1436 | 50 | // glibc assumes the old-style BSS PLT layout which we don't support. | 1437 | 50 | if (config->emachine == EM_PPC) | 1438 | 0 | add(DT_PPC_GOT, [] { return in.got->getVA(); }); | 1439 | 50 | | 1440 | 50 | // Glink dynamic tag is required by the V2 abi if the plt section isn't empty. | 1441 | 50 | if (config->emachine == EM_PPC64 && in.plt->isNeeded()27 ) { | 1442 | 9 | // The Glink tag points to 32 bytes before the first lazy symbol resolution | 1443 | 9 | // stub, which starts directly after the header. | 1444 | 9 | entries.push_back({DT_PPC64_GLINK, [=] { | 1445 | 9 | unsigned offset = target->pltHeaderSize - 32; | 1446 | 9 | return in.plt->getVA(0) + offset; | 1447 | 9 | }}); | 1448 | 9 | } | 1449 | 50 | | 1450 | 50 | addInt(DT_NULL, 0); | 1451 | 50 | | 1452 | 50 | getParent()->link = this->link; | 1453 | 50 | this->size = entries.size() * this->entsize; | 1454 | 50 | } |
|
1455 | | |
1456 | 1.25k | template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *buf) { |
1457 | 1.25k | auto *p = reinterpret_cast<Elf_Dyn *>(buf); |
1458 | 1.25k | |
1459 | 12.4k | for (std::pair<int32_t, std::function<uint64_t()>> &kv : entries) { |
1460 | 12.4k | p->d_tag = kv.first; |
1461 | 12.4k | p->d_un.d_val = kv.second(); |
1462 | 12.4k | ++p; |
1463 | 12.4k | } |
1464 | 1.25k | } lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*) Line | Count | Source | 1456 | 177 | template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *buf) { | 1457 | 177 | auto *p = reinterpret_cast<Elf_Dyn *>(buf); | 1458 | 177 | | 1459 | 1.77k | for (std::pair<int32_t, std::function<uint64_t()>> &kv : entries) { | 1460 | 1.77k | p->d_tag = kv.first; | 1461 | 1.77k | p->d_un.d_val = kv.second(); | 1462 | 1.77k | ++p; | 1463 | 1.77k | } | 1464 | 177 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::writeTo(unsigned char*) Line | Count | Source | 1456 | 85 | template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *buf) { | 1457 | 85 | auto *p = reinterpret_cast<Elf_Dyn *>(buf); | 1458 | 85 | | 1459 | 1.24k | for (std::pair<int32_t, std::function<uint64_t()>> &kv : entries) { | 1460 | 1.24k | p->d_tag = kv.first; | 1461 | 1.24k | p->d_un.d_val = kv.second(); | 1462 | 1.24k | ++p; | 1463 | 1.24k | } | 1464 | 85 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeTo(unsigned char*) Line | Count | Source | 1456 | 942 | template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *buf) { | 1457 | 942 | auto *p = reinterpret_cast<Elf_Dyn *>(buf); | 1458 | 942 | | 1459 | 8.76k | for (std::pair<int32_t, std::function<uint64_t()>> &kv : entries) { | 1460 | 8.76k | p->d_tag = kv.first; | 1461 | 8.76k | p->d_un.d_val = kv.second(); | 1462 | 8.76k | ++p; | 1463 | 8.76k | } | 1464 | 942 | } |
lld::elf::DynamicSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::writeTo(unsigned char*) Line | Count | Source | 1456 | 50 | template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *buf) { | 1457 | 50 | auto *p = reinterpret_cast<Elf_Dyn *>(buf); | 1458 | 50 | | 1459 | 643 | for (std::pair<int32_t, std::function<uint64_t()>> &kv : entries) { | 1460 | 643 | p->d_tag = kv.first; | 1461 | 643 | p->d_un.d_val = kv.second(); | 1462 | 643 | ++p; | 1463 | 643 | } | 1464 | 50 | } |
|
1465 | | |
1466 | 2.24k | uint64_t DynamicReloc::getOffset() const { |
1467 | 2.24k | return inputSec->getVA(offsetInSec); |
1468 | 2.24k | } |
1469 | | |
1470 | 799 | int64_t DynamicReloc::computeAddend() const { |
1471 | 799 | if (useSymVA) |
1472 | 213 | return sym->getVA(addend); |
1473 | 586 | if (!outputSec) |
1474 | 586 | return addend; |
1475 | 0 | // See the comment in the DynamicReloc ctor. |
1476 | 0 | return getMipsPageAddr(outputSec->addr) + addend; |
1477 | 0 | } |
1478 | | |
1479 | 2.24k | uint32_t DynamicReloc::getSymIndex(SymbolTableBaseSection *symTab) const { |
1480 | 2.24k | if (sym && !useSymVA2.13k ) |
1481 | 1.49k | return symTab->getSymbolIndex(sym); |
1482 | 744 | return 0; |
1483 | 744 | } |
1484 | | |
1485 | | RelocationBaseSection::RelocationBaseSection(StringRef name, uint32_t type, |
1486 | | int32_t dynamicTag, |
1487 | | int32_t sizeDynamicTag) |
1488 | | : SyntheticSection(SHF_ALLOC, type, config->wordsize, name), |
1489 | 8.27k | dynamicTag(dynamicTag), sizeDynamicTag(sizeDynamicTag) {} |
1490 | | |
1491 | | void RelocationBaseSection::addReloc(RelType dynType, InputSectionBase *isec, |
1492 | 157 | uint64_t offsetInSec, Symbol *sym) { |
1493 | 157 | addReloc({dynType, isec, offsetInSec, false, sym, 0}); |
1494 | 157 | } |
1495 | | |
1496 | | void RelocationBaseSection::addReloc(RelType dynType, |
1497 | | InputSectionBase *inputSec, |
1498 | | uint64_t offsetInSec, Symbol *sym, |
1499 | | int64_t addend, RelExpr expr, |
1500 | 498 | RelType type) { |
1501 | 498 | // Write the addends to the relocated address if required. We skip |
1502 | 498 | // it if the written value would be zero. |
1503 | 498 | if (config->writeAddends && (149 expr != R_ADDEND149 || addend != 066 )) |
1504 | 96 | inputSec->relocations.push_back({expr, type, offsetInSec, addend, sym}); |
1505 | 498 | addReloc({dynType, inputSec, offsetInSec, expr != R_ADDEND, sym, addend}); |
1506 | 498 | } |
1507 | | |
1508 | 1.09k | void RelocationBaseSection::addReloc(const DynamicReloc &reloc) { |
1509 | 1.09k | if (reloc.type == target->relativeRel) |
1510 | 211 | ++numRelativeRelocs; |
1511 | 1.09k | relocs.push_back(reloc); |
1512 | 1.09k | } |
1513 | | |
1514 | 587 | void RelocationBaseSection::finalizeContents() { |
1515 | 587 | SymbolTableBaseSection *symTab = getPartition().dynSymTab; |
1516 | 587 | |
1517 | 587 | // When linking glibc statically, .rel{,a}.plt contains R_*_IRELATIVE |
1518 | 587 | // relocations due to IFUNC (e.g. strcpy). sh_link will be set to 0 in that |
1519 | 587 | // case. |
1520 | 587 | if (symTab && symTab->getParent()) |
1521 | 558 | getParent()->link = symTab->getParent()->sectionIndex; |
1522 | 29 | else |
1523 | 29 | getParent()->link = 0; |
1524 | 587 | |
1525 | 587 | if (in.relaPlt == this) |
1526 | 260 | getParent()->info = in.gotPlt->getParent()->sectionIndex; |
1527 | 587 | if (in.relaIplt == this) |
1528 | 46 | getParent()->info = in.igotPlt->getParent()->sectionIndex; |
1529 | 587 | } |
1530 | | |
1531 | | RelrBaseSection::RelrBaseSection() |
1532 | | : SyntheticSection(SHF_ALLOC, |
1533 | | config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR, |
1534 | 6 | config->wordsize, ".relr.dyn") {} |
1535 | | |
1536 | | template <class ELFT> |
1537 | | static void encodeDynamicReloc(SymbolTableBaseSection *symTab, |
1538 | | typename ELFT::Rela *p, |
1539 | 1.13k | const DynamicReloc &rel) { |
1540 | 1.13k | if (config->isRela) |
1541 | 799 | p->r_addend = rel.computeAddend(); |
1542 | 1.13k | p->r_offset = rel.getOffset(); |
1543 | 1.13k | p->setSymbolAndType(rel.getSymIndex(symTab), rel.type, config->isMips64EL); |
1544 | 1.13k | } SyntheticSections.cpp:void encodeDynamicReloc<llvm::object::ELFType<(llvm::support::endianness)1, false> >(lld::elf::SymbolTableBaseSection*, llvm::object::ELFType<(llvm::support::endianness)1, false>::Rela*, lld::elf::DynamicReloc const&) Line | Count | Source | 1539 | 298 | const DynamicReloc &rel) { | 1540 | 298 | if (config->isRela) | 1541 | 21 | p->r_addend = rel.computeAddend(); | 1542 | 298 | p->r_offset = rel.getOffset(); | 1543 | 298 | p->setSymbolAndType(rel.getSymIndex(symTab), rel.type, config->isMips64EL); | 1544 | 298 | } |
SyntheticSections.cpp:void encodeDynamicReloc<llvm::object::ELFType<(llvm::support::endianness)0, false> >(lld::elf::SymbolTableBaseSection*, llvm::object::ELFType<(llvm::support::endianness)0, false>::Rela*, lld::elf::DynamicReloc const&) Line | Count | Source | 1539 | 78 | const DynamicReloc &rel) { | 1540 | 78 | if (config->isRela) | 1541 | 34 | p->r_addend = rel.computeAddend(); | 1542 | 78 | p->r_offset = rel.getOffset(); | 1543 | 78 | p->setSymbolAndType(rel.getSymIndex(symTab), rel.type, config->isMips64EL); | 1544 | 78 | } |
SyntheticSections.cpp:void encodeDynamicReloc<llvm::object::ELFType<(llvm::support::endianness)1, true> >(lld::elf::SymbolTableBaseSection*, llvm::object::ELFType<(llvm::support::endianness)1, true>::Rela*, lld::elf::DynamicReloc const&) Line | Count | Source | 1539 | 711 | const DynamicReloc &rel) { | 1540 | 711 | if (config->isRela) | 1541 | 711 | p->r_addend = rel.computeAddend(); | 1542 | 711 | p->r_offset = rel.getOffset(); | 1543 | 711 | p->setSymbolAndType(rel.getSymIndex(symTab), rel.type, config->isMips64EL); | 1544 | 711 | } |
SyntheticSections.cpp:void encodeDynamicReloc<llvm::object::ELFType<(llvm::support::endianness)0, true> >(lld::elf::SymbolTableBaseSection*, llvm::object::ELFType<(llvm::support::endianness)0, true>::Rela*, lld::elf::DynamicReloc const&) Line | Count | Source | 1539 | 52 | const DynamicReloc &rel) { | 1540 | 52 | if (config->isRela) | 1541 | 33 | p->r_addend = rel.computeAddend(); | 1542 | 52 | p->r_offset = rel.getOffset(); | 1543 | 52 | p->setSymbolAndType(rel.getSymIndex(symTab), rel.type, config->isMips64EL); | 1544 | 52 | } |
|
1545 | | |
1546 | | template <class ELFT> |
1547 | | RelocationSection<ELFT>::RelocationSection(StringRef name, bool sort) |
1548 | | : RelocationBaseSection(name, config->isRela ? SHT_RELA : SHT_REL, |
1549 | | config->isRela ? DT_RELA : DT_REL, |
1550 | | config->isRela ? DT_RELASZ : DT_RELSZ), |
1551 | 8.27k | sort(sort) { |
1552 | 8.27k | this->entsize = config->isRela ? sizeof(Elf_Rela)6.77k : sizeof(Elf_Rel)1.49k ; |
1553 | 8.27k | } lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::RelocationSection(llvm::StringRef, bool) Line | Count | Source | 1551 | 1.13k | sort(sort) { | 1552 | 1.13k | this->entsize = config->isRela ? sizeof(Elf_Rela)159 : sizeof(Elf_Rel)972 ; | 1553 | 1.13k | } |
lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::RelocationSection(llvm::StringRef, bool) Line | Count | Source | 1551 | 471 | sort(sort) { | 1552 | 471 | this->entsize = config->isRela ? sizeof(Elf_Rela)93 : sizeof(Elf_Rel)378 ; | 1553 | 471 | } |
lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::RelocationSection(llvm::StringRef, bool) Line | Count | Source | 1551 | 6.34k | sort(sort) { | 1552 | 6.34k | this->entsize = config->isRela ? sizeof(Elf_Rela)6.33k : sizeof(Elf_Rel)9 ; | 1553 | 6.34k | } |
lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::RelocationSection(llvm::StringRef, bool) Line | Count | Source | 1551 | 324 | sort(sort) { | 1552 | 324 | this->entsize = config->isRela ? sizeof(Elf_Rela)186 : sizeof(Elf_Rel)138 ; | 1553 | 324 | } |
|
1554 | | |
1555 | 575 | template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) { |
1556 | 575 | SymbolTableBaseSection *symTab = getPartition().dynSymTab; |
1557 | 575 | |
1558 | 575 | // Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to |
1559 | 575 | // place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset |
1560 | 575 | // is to make results easier to read. |
1561 | 575 | if (sort) |
1562 | 270 | llvm::stable_sort( |
1563 | 551 | relocs, [&](const DynamicReloc &a, const DynamicReloc &b) { |
1564 | 551 | return std::make_tuple(a.type != target->relativeRel, |
1565 | 551 | a.getSymIndex(symTab), a.getOffset()) < |
1566 | 551 | std::make_tuple(b.type != target->relativeRel, |
1567 | 551 | b.getSymIndex(symTab), b.getOffset()); |
1568 | 551 | }); lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*)::'lambda'(lld::elf::DynamicReloc const&, lld::elf::DynamicReloc const&)::operator()(lld::elf::DynamicReloc const&, lld::elf::DynamicReloc const&) const Line | Count | Source | 1563 | 150 | relocs, [&](const DynamicReloc &a, const DynamicReloc &b) { | 1564 | 150 | return std::make_tuple(a.type != target->relativeRel, | 1565 | 150 | a.getSymIndex(symTab), a.getOffset()) < | 1566 | 150 | std::make_tuple(b.type != target->relativeRel, | 1567 | 150 | b.getSymIndex(symTab), b.getOffset()); | 1568 | 150 | }); |
lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::writeTo(unsigned char*)::'lambda'(lld::elf::DynamicReloc const&, lld::elf::DynamicReloc const&)::operator()(lld::elf::DynamicReloc const&, lld::elf::DynamicReloc const&) const Line | Count | Source | 1563 | 110 | relocs, [&](const DynamicReloc &a, const DynamicReloc &b) { | 1564 | 110 | return std::make_tuple(a.type != target->relativeRel, | 1565 | 110 | a.getSymIndex(symTab), a.getOffset()) < | 1566 | 110 | std::make_tuple(b.type != target->relativeRel, | 1567 | 110 | b.getSymIndex(symTab), b.getOffset()); | 1568 | 110 | }); |
lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeTo(unsigned char*)::'lambda'(lld::elf::DynamicReloc const&, lld::elf::DynamicReloc const&)::operator()(lld::elf::DynamicReloc const&, lld::elf::DynamicReloc const&) const Line | Count | Source | 1563 | 261 | relocs, [&](const DynamicReloc &a, const DynamicReloc &b) { | 1564 | 261 | return std::make_tuple(a.type != target->relativeRel, | 1565 | 261 | a.getSymIndex(symTab), a.getOffset()) < | 1566 | 261 | std::make_tuple(b.type != target->relativeRel, | 1567 | 261 | b.getSymIndex(symTab), b.getOffset()); | 1568 | 261 | }); |
lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::writeTo(unsigned char*)::'lambda'(lld::elf::DynamicReloc const&, lld::elf::DynamicReloc const&)::operator()(lld::elf::DynamicReloc const&, lld::elf::DynamicReloc const&) const Line | Count | Source | 1563 | 30 | relocs, [&](const DynamicReloc &a, const DynamicReloc &b) { | 1564 | 30 | return std::make_tuple(a.type != target->relativeRel, | 1565 | 30 | a.getSymIndex(symTab), a.getOffset()) < | 1566 | 30 | std::make_tuple(b.type != target->relativeRel, | 1567 | 30 | b.getSymIndex(symTab), b.getOffset()); | 1568 | 30 | }); |
|
1569 | 575 | |
1570 | 1.01k | for (const DynamicReloc &rel : relocs) { |
1571 | 1.01k | encodeDynamicReloc<ELFT>(symTab, reinterpret_cast<Elf_Rela *>(buf), rel); |
1572 | 1.01k | buf += config->isRela ? sizeof(Elf_Rela)729 : sizeof(Elf_Rel)286 ; |
1573 | 1.01k | } |
1574 | 575 | } lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*) Line | Count | Source | 1555 | 109 | template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) { | 1556 | 109 | SymbolTableBaseSection *symTab = getPartition().dynSymTab; | 1557 | 109 | | 1558 | 109 | // Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to | 1559 | 109 | // place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset | 1560 | 109 | // is to make results easier to read. | 1561 | 109 | if (sort) | 1562 | 60 | llvm::stable_sort( | 1563 | 60 | relocs, [&](const DynamicReloc &a, const DynamicReloc &b) { | 1564 | 60 | return std::make_tuple(a.type != target->relativeRel, | 1565 | 60 | a.getSymIndex(symTab), a.getOffset()) < | 1566 | 60 | std::make_tuple(b.type != target->relativeRel, | 1567 | 60 | b.getSymIndex(symTab), b.getOffset()); | 1568 | 60 | }); | 1569 | 109 | | 1570 | 244 | for (const DynamicReloc &rel : relocs) { | 1571 | 244 | encodeDynamicReloc<ELFT>(symTab, reinterpret_cast<Elf_Rela *>(buf), rel); | 1572 | 244 | buf += config->isRela ? sizeof(Elf_Rela)21 : sizeof(Elf_Rel)223 ; | 1573 | 244 | } | 1574 | 109 | } |
lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::writeTo(unsigned char*) Line | Count | Source | 1555 | 35 | template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) { | 1556 | 35 | SymbolTableBaseSection *symTab = getPartition().dynSymTab; | 1557 | 35 | | 1558 | 35 | // Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to | 1559 | 35 | // place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset | 1560 | 35 | // is to make results easier to read. | 1561 | 35 | if (sort) | 1562 | 16 | llvm::stable_sort( | 1563 | 16 | relocs, [&](const DynamicReloc &a, const DynamicReloc &b) { | 1564 | 16 | return std::make_tuple(a.type != target->relativeRel, | 1565 | 16 | a.getSymIndex(symTab), a.getOffset()) < | 1566 | 16 | std::make_tuple(b.type != target->relativeRel, | 1567 | 16 | b.getSymIndex(symTab), b.getOffset()); | 1568 | 16 | }); | 1569 | 35 | | 1570 | 78 | for (const DynamicReloc &rel : relocs) { | 1571 | 78 | encodeDynamicReloc<ELFT>(symTab, reinterpret_cast<Elf_Rela *>(buf), rel); | 1572 | 78 | buf += config->isRela ? sizeof(Elf_Rela)34 : sizeof(Elf_Rel)44 ; | 1573 | 78 | } | 1574 | 35 | } |
lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeTo(unsigned char*) Line | Count | Source | 1555 | 400 | template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) { | 1556 | 400 | SymbolTableBaseSection *symTab = getPartition().dynSymTab; | 1557 | 400 | | 1558 | 400 | // Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to | 1559 | 400 | // place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset | 1560 | 400 | // is to make results easier to read. | 1561 | 400 | if (sort) | 1562 | 175 | llvm::stable_sort( | 1563 | 175 | relocs, [&](const DynamicReloc &a, const DynamicReloc &b) { | 1564 | 175 | return std::make_tuple(a.type != target->relativeRel, | 1565 | 175 | a.getSymIndex(symTab), a.getOffset()) < | 1566 | 175 | std::make_tuple(b.type != target->relativeRel, | 1567 | 175 | b.getSymIndex(symTab), b.getOffset()); | 1568 | 175 | }); | 1569 | 400 | | 1570 | 641 | for (const DynamicReloc &rel : relocs) { | 1571 | 641 | encodeDynamicReloc<ELFT>(symTab, reinterpret_cast<Elf_Rela *>(buf), rel); | 1572 | 641 | buf += config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel)0 ; | 1573 | 641 | } | 1574 | 400 | } |
lld::elf::RelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::writeTo(unsigned char*) Line | Count | Source | 1555 | 31 | template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) { | 1556 | 31 | SymbolTableBaseSection *symTab = getPartition().dynSymTab; | 1557 | 31 | | 1558 | 31 | // Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to | 1559 | 31 | // place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset | 1560 | 31 | // is to make results easier to read. | 1561 | 31 | if (sort) | 1562 | 19 | llvm::stable_sort( | 1563 | 19 | relocs, [&](const DynamicReloc &a, const DynamicReloc &b) { | 1564 | 19 | return std::make_tuple(a.type != target->relativeRel, | 1565 | 19 | a.getSymIndex(symTab), a.getOffset()) < | 1566 | 19 | std::make_tuple(b.type != target->relativeRel, | 1567 | 19 | b.getSymIndex(symTab), b.getOffset()); | 1568 | 19 | }); | 1569 | 31 | | 1570 | 52 | for (const DynamicReloc &rel : relocs) { | 1571 | 52 | encodeDynamicReloc<ELFT>(symTab, reinterpret_cast<Elf_Rela *>(buf), rel); | 1572 | 52 | buf += config->isRela ? sizeof(Elf_Rela)33 : sizeof(Elf_Rel)19 ; | 1573 | 52 | } | 1574 | 31 | } |
|
1575 | | |
1576 | | template <class ELFT> |
1577 | | AndroidPackedRelocationSection<ELFT>::AndroidPackedRelocationSection( |
1578 | | StringRef name) |
1579 | | : RelocationBaseSection( |
1580 | | name, config->isRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL, |
1581 | | config->isRela ? DT_ANDROID_RELA : DT_ANDROID_REL, |
1582 | 7 | config->isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ) { |
1583 | 7 | this->entsize = 1; |
1584 | 7 | } lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::AndroidPackedRelocationSection(llvm::StringRef) Line | Count | Source | 1582 | 1 | config->isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ) { | 1583 | 1 | this->entsize = 1; | 1584 | 1 | } |
Unexecuted instantiation: lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::AndroidPackedRelocationSection(llvm::StringRef) lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::AndroidPackedRelocationSection(llvm::StringRef) Line | Count | Source | 1582 | 6 | config->isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ) { | 1583 | 6 | this->entsize = 1; | 1584 | 6 | } |
Unexecuted instantiation: lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::AndroidPackedRelocationSection(llvm::StringRef) |
1585 | | |
1586 | | template <class ELFT> |
1587 | 14 | bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() { |
1588 | 14 | // This function computes the contents of an Android-format packed relocation |
1589 | 14 | // section. |
1590 | 14 | // |
1591 | 14 | // This format compresses relocations by using relocation groups to factor out |
1592 | 14 | // fields that are common between relocations and storing deltas from previous |
1593 | 14 | // relocations in SLEB128 format (which has a short representation for small |
1594 | 14 | // numbers). A good example of a relocation type with common fields is |
1595 | 14 | // R_*_RELATIVE, which is normally used to represent function pointers in |
1596 | 14 | // vtables. In the REL format, each relative relocation has the same r_info |
1597 | 14 | // field, and is only different from other relative relocations in terms of |
1598 | 14 | // the r_offset field. By sorting relocations by offset, grouping them by |
1599 | 14 | // r_info and representing each relocation with only the delta from the |
1600 | 14 | // previous offset, each 8-byte relocation can be compressed to as little as 1 |
1601 | 14 | // byte (or less with run-length encoding). This relocation packer was able to |
1602 | 14 | // reduce the size of the relocation section in an Android Chromium DSO from |
1603 | 14 | // 2,911,184 bytes to 174,693 bytes, or 6% of the original size. |
1604 | 14 | // |
1605 | 14 | // A relocation section consists of a header containing the literal bytes |
1606 | 14 | // 'APS2' followed by a sequence of SLEB128-encoded integers. The first two |
1607 | 14 | // elements are the total number of relocations in the section and an initial |
1608 | 14 | // r_offset value. The remaining elements define a sequence of relocation |
1609 | 14 | // groups. Each relocation group starts with a header consisting of the |
1610 | 14 | // following elements: |
1611 | 14 | // |
1612 | 14 | // - the number of relocations in the relocation group |
1613 | 14 | // - flags for the relocation group |
1614 | 14 | // - (if RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG is set) the r_offset delta |
1615 | 14 | // for each relocation in the group. |
1616 | 14 | // - (if RELOCATION_GROUPED_BY_INFO_FLAG is set) the value of the r_info |
1617 | 14 | // field for each relocation in the group. |
1618 | 14 | // - (if RELOCATION_GROUP_HAS_ADDEND_FLAG and |
1619 | 14 | // RELOCATION_GROUPED_BY_ADDEND_FLAG are set) the r_addend delta for |
1620 | 14 | // each relocation in the group. |
1621 | 14 | // |
1622 | 14 | // Following the relocation group header are descriptions of each of the |
1623 | 14 | // relocations in the group. They consist of the following elements: |
1624 | 14 | // |
1625 | 14 | // - (if RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG is not set) the r_offset |
1626 | 14 | // delta for this relocation. |
1627 | 14 | // - (if RELOCATION_GROUPED_BY_INFO_FLAG is not set) the value of the r_info |
1628 | 14 | // field for this relocation. |
1629 | 14 | // - (if RELOCATION_GROUP_HAS_ADDEND_FLAG is set and |
1630 | 14 | // RELOCATION_GROUPED_BY_ADDEND_FLAG is not set) the r_addend delta for |
1631 | 14 | // this relocation. |
1632 | 14 | |
1633 | 14 | size_t oldSize = relocData.size(); |
1634 | 14 | |
1635 | 14 | relocData = {'A', 'P', 'S', '2'}; |
1636 | 14 | raw_svector_ostream os(relocData); |
1637 | 278 | auto add = [&](int64_t v) { encodeSLEB128(v, os); }; lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::updateAllocSize()::'lambda'(long long)::operator()(long long) const Line | Count | Source | 1637 | 70 | auto add = [&](int64_t v) { encodeSLEB128(v, os); }; |
Unexecuted instantiation: lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::updateAllocSize()::'lambda'(long long)::operator()(long long) const lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::updateAllocSize()::'lambda'(long long)::operator()(long long) const Line | Count | Source | 1637 | 208 | auto add = [&](int64_t v) { encodeSLEB128(v, os); }; |
Unexecuted instantiation: lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::updateAllocSize()::'lambda'(long long)::operator()(long long) const |
1638 | 14 | |
1639 | 14 | // The format header includes the number of relocations and the initial |
1640 | 14 | // offset (we set this to zero because the first relocation group will |
1641 | 14 | // perform the initial adjustment). |
1642 | 14 | add(relocs.size()); |
1643 | 14 | add(0); |
1644 | 14 | |
1645 | 14 | std::vector<Elf_Rela> relatives, nonRelatives; |
1646 | 14 | |
1647 | 124 | for (const DynamicReloc &rel : relocs) { |
1648 | 124 | Elf_Rela r; |
1649 | 124 | encodeDynamicReloc<ELFT>(getPartition().dynSymTab, &r, rel); |
1650 | 124 | |
1651 | 124 | if (r.getType(config->isMips64EL) == target->relativeRel) |
1652 | 106 | relatives.push_back(r); |
1653 | 18 | else |
1654 | 18 | nonRelatives.push_back(r); |
1655 | 124 | } |
1656 | 14 | |
1657 | 100 | llvm::sort(relatives, [](const Elf_Rel &a, const Elf_Rel &b) { |
1658 | 100 | return a.r_offset < b.r_offset; |
1659 | 100 | }); lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::updateAllocSize()::'lambda'(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> const&)::operator()(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, false> const&) const Line | Count | Source | 1657 | 48 | llvm::sort(relatives, [](const Elf_Rel &a, const Elf_Rel &b) { | 1658 | 48 | return a.r_offset < b.r_offset; | 1659 | 48 | }); |
Unexecuted instantiation: lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::updateAllocSize()::'lambda'(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> const&)::operator()(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, false> const&) const lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::updateAllocSize()::'lambda'(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> const&)::operator()(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, false> const&) const Line | Count | Source | 1657 | 52 | llvm::sort(relatives, [](const Elf_Rel &a, const Elf_Rel &b) { | 1658 | 52 | return a.r_offset < b.r_offset; | 1659 | 52 | }); |
Unexecuted instantiation: lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::updateAllocSize()::'lambda'(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> const&)::operator()(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, false> const&) const |
1660 | 14 | |
1661 | 14 | // Try to find groups of relative relocations which are spaced one word |
1662 | 14 | // apart from one another. These generally correspond to vtable entries. The |
1663 | 14 | // format allows these groups to be encoded using a sort of run-length |
1664 | 14 | // encoding, but each group will cost 7 bytes in addition to the offset from |
1665 | 14 | // the previous group, so it is only profitable to do this for groups of |
1666 | 14 | // size 8 or larger. |
1667 | 14 | std::vector<Elf_Rela> ungroupedRelatives; |
1668 | 14 | std::vector<std::vector<Elf_Rela>> relativeGroups; |
1669 | 32 | for (auto i = relatives.begin(), e = relatives.end(); i != e;) { |
1670 | 18 | std::vector<Elf_Rela> group; |
1671 | 106 | do { |
1672 | 106 | group.push_back(*i++); |
1673 | 106 | } while (i != e && (i - 1)->r_offset + config->wordsize == i->r_offset100 ); |
1674 | 18 | |
1675 | 18 | if (group.size() < 8) |
1676 | 10 | ungroupedRelatives.insert(ungroupedRelatives.end(), group.begin(), |
1677 | 10 | group.end()); |
1678 | 8 | else |
1679 | 8 | relativeGroups.emplace_back(std::move(group)); |
1680 | 18 | } |
1681 | 14 | |
1682 | 14 | unsigned hasAddendIfRela = |
1683 | 14 | config->isRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG12 : 02 ; |
1684 | 14 | |
1685 | 14 | uint64_t offset = 0; |
1686 | 14 | uint64_t addend = 0; |
1687 | 14 | |
1688 | 14 | // Emit the run-length encoding for the groups of adjacent relative |
1689 | 14 | // relocations. Each group is represented using two groups in the packed |
1690 | 14 | // format. The first is used to set the current offset to the start of the |
1691 | 14 | // group (and also encodes the first relocation), and the second encodes the |
1692 | 14 | // remaining relocations. |
1693 | 14 | for (std::vector<Elf_Rela> &g : relativeGroups) { |
1694 | 8 | // The first relocation in the group. |
1695 | 8 | add(1); |
1696 | 8 | add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG | |
1697 | 8 | RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela); |
1698 | 8 | add(g[0].r_offset - offset); |
1699 | 8 | add(target->relativeRel); |
1700 | 8 | if (config->isRela) { |
1701 | 4 | add(g[0].r_addend - addend); |
1702 | 4 | addend = g[0].r_addend; |
1703 | 4 | } |
1704 | 8 | |
1705 | 8 | // The remaining relocations. |
1706 | 8 | add(g.size() - 1); |
1707 | 8 | add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG | |
1708 | 8 | RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela); |
1709 | 8 | add(config->wordsize); |
1710 | 8 | add(target->relativeRel); |
1711 | 8 | if (config->isRela) { |
1712 | 34 | for (auto i = g.begin() + 1, e = g.end(); i != e; ++i30 ) { |
1713 | 30 | add(i->r_addend - addend); |
1714 | 30 | addend = i->r_addend; |
1715 | 30 | } |
1716 | 4 | } |
1717 | 8 | |
1718 | 8 | offset = g.back().r_offset; |
1719 | 8 | } |
1720 | 14 | |
1721 | 14 | // Now the ungrouped relatives. |
1722 | 14 | if (!ungroupedRelatives.empty()) { |
1723 | 6 | add(ungroupedRelatives.size()); |
1724 | 6 | add(RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela); |
1725 | 6 | add(target->relativeRel); |
1726 | 38 | for (Elf_Rela &r : ungroupedRelatives) { |
1727 | 38 | add(r.r_offset - offset); |
1728 | 38 | offset = r.r_offset; |
1729 | 38 | if (config->isRela) { |
1730 | 22 | add(r.r_addend - addend); |
1731 | 22 | addend = r.r_addend; |
1732 | 22 | } |
1733 | 38 | } |
1734 | 6 | } |
1735 | 14 | |
1736 | 14 | // Finally the non-relative relocations. |
1737 | 14 | llvm::sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) { |
1738 | 6 | return a.r_offset < b.r_offset; |
1739 | 6 | }); lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::updateAllocSize()::'lambda'(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> const&)::operator()(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, false>, true> const&) const Line | Count | Source | 1737 | 2 | llvm::sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) { | 1738 | 2 | return a.r_offset < b.r_offset; | 1739 | 2 | }); |
Unexecuted instantiation: lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::updateAllocSize()::'lambda'(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> const&)::operator()(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, false>, true> const&) const lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::updateAllocSize()::'lambda'(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> const&)::operator()(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1, true>, true> const&) const Line | Count | Source | 1737 | 4 | llvm::sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) { | 1738 | 4 | return a.r_offset < b.r_offset; | 1739 | 4 | }); |
Unexecuted instantiation: lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::updateAllocSize()::'lambda'(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> const&)::operator()(llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> const&, llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)0, true>, true> const&) const |
1740 | 14 | if (!nonRelatives.empty()) { |
1741 | 12 | add(nonRelatives.size()); |
1742 | 12 | add(hasAddendIfRela); |
1743 | 18 | for (Elf_Rela &r : nonRelatives) { |
1744 | 18 | add(r.r_offset - offset); |
1745 | 18 | offset = r.r_offset; |
1746 | 18 | add(r.r_info); |
1747 | 18 | if (config->isRela) { |
1748 | 14 | add(r.r_addend - addend); |
1749 | 14 | addend = r.r_addend; |
1750 | 14 | } |
1751 | 18 | } |
1752 | 12 | } |
1753 | 14 | |
1754 | 14 | // Don't allow the section to shrink; otherwise the size of the section can |
1755 | 14 | // oscillate infinitely. |
1756 | 14 | if (relocData.size() < oldSize) |
1757 | 1 | relocData.append(oldSize - relocData.size(), 0); |
1758 | 14 | |
1759 | 14 | // Returns whether the section size changed. We need to keep recomputing both |
1760 | 14 | // section layout and the contents of this section until the size converges |
1761 | 14 | // because changing this section's size can affect section layout, which in |
1762 | 14 | // turn can affect the sizes of the LEB-encoded integers stored in this |
1763 | 14 | // section. |
1764 | 14 | return relocData.size() != oldSize; |
1765 | 14 | } lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::updateAllocSize() Line | Count | Source | 1587 | 2 | bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() { | 1588 | 2 | // This function computes the contents of an Android-format packed relocation | 1589 | 2 | // section. | 1590 | 2 | // | 1591 | 2 | // This format compresses relocations by using relocation groups to factor out | 1592 | 2 | // fields that are common between relocations and storing deltas from previous | 1593 | 2 | // relocations in SLEB128 format (which has a short representation for small | 1594 | 2 | // numbers). A good example of a relocation type with common fields is | 1595 | 2 | // R_*_RELATIVE, which is normally used to represent function pointers in | 1596 | 2 | // vtables. In the REL format, each relative relocation has the same r_info | 1597 | 2 | // field, and is only different from other relative relocations in terms of | 1598 | 2 | // the r_offset field. By sorting relocations by offset, grouping them by | 1599 | 2 | // r_info and representing each relocation with only the delta from the | 1600 | 2 | // previous offset, each 8-byte relocation can be compressed to as little as 1 | 1601 | 2 | // byte (or less with run-length encoding). This relocation packer was able to | 1602 | 2 | // reduce the size of the relocation section in an Android Chromium DSO from | 1603 | 2 | // 2,911,184 bytes to 174,693 bytes, or 6% of the original size. | 1604 | 2 | // | 1605 | 2 | // A relocation section consists of a header containing the literal bytes | 1606 | 2 | // 'APS2' followed by a sequence of SLEB128-encoded integers. The first two | 1607 | 2 | // elements are the total number of relocations in the section and an initial | 1608 | 2 | // r_offset value. The remaining elements define a sequence of relocation | 1609 | 2 | // groups. Each relocation group starts with a header consisting of the | 1610 | 2 | // following elements: | 1611 | 2 | // | 1612 | 2 | // - the number of relocations in the relocation group | 1613 | 2 | // - flags for the relocation group | 1614 | 2 | // - (if RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG is set) the r_offset delta | 1615 | 2 | // for each relocation in the group. | 1616 | 2 | // - (if RELOCATION_GROUPED_BY_INFO_FLAG is set) the value of the r_info | 1617 | 2 | // field for each relocation in the group. | 1618 | 2 | // - (if RELOCATION_GROUP_HAS_ADDEND_FLAG and | 1619 | 2 | // RELOCATION_GROUPED_BY_ADDEND_FLAG are set) the r_addend delta for | 1620 | 2 | // each relocation in the group. | 1621 | 2 | // | 1622 | 2 | // Following the relocation group header are descriptions of each of the | 1623 | 2 | // relocations in the group. They consist of the following elements: | 1624 | 2 | // | 1625 | 2 | // - (if RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG is not set) the r_offset | 1626 | 2 | // delta for this relocation. | 1627 | 2 | // - (if RELOCATION_GROUPED_BY_INFO_FLAG is not set) the value of the r_info | 1628 | 2 | // field for this relocation. | 1629 | 2 | // - (if RELOCATION_GROUP_HAS_ADDEND_FLAG is set and | 1630 | 2 | // RELOCATION_GROUPED_BY_ADDEND_FLAG is not set) the r_addend delta for | 1631 | 2 | // this relocation. | 1632 | 2 | | 1633 | 2 | size_t oldSize = relocData.size(); | 1634 | 2 | | 1635 | 2 | relocData = {'A', 'P', 'S', '2'}; | 1636 | 2 | raw_svector_ostream os(relocData); | 1637 | 2 | auto add = [&](int64_t v) { encodeSLEB128(v, os); }; | 1638 | 2 | | 1639 | 2 | // The format header includes the number of relocations and the initial | 1640 | 2 | // offset (we set this to zero because the first relocation group will | 1641 | 2 | // perform the initial adjustment). | 1642 | 2 | add(relocs.size()); | 1643 | 2 | add(0); | 1644 | 2 | | 1645 | 2 | std::vector<Elf_Rela> relatives, nonRelatives; | 1646 | 2 | | 1647 | 54 | for (const DynamicReloc &rel : relocs) { | 1648 | 54 | Elf_Rela r; | 1649 | 54 | encodeDynamicReloc<ELFT>(getPartition().dynSymTab, &r, rel); | 1650 | 54 | | 1651 | 54 | if (r.getType(config->isMips64EL) == target->relativeRel) | 1652 | 50 | relatives.push_back(r); | 1653 | 4 | else | 1654 | 4 | nonRelatives.push_back(r); | 1655 | 54 | } | 1656 | 2 | | 1657 | 2 | llvm::sort(relatives, [](const Elf_Rel &a, const Elf_Rel &b) { | 1658 | 2 | return a.r_offset < b.r_offset; | 1659 | 2 | }); | 1660 | 2 | | 1661 | 2 | // Try to find groups of relative relocations which are spaced one word | 1662 | 2 | // apart from one another. These generally correspond to vtable entries. The | 1663 | 2 | // format allows these groups to be encoded using a sort of run-length | 1664 | 2 | // encoding, but each group will cost 7 bytes in addition to the offset from | 1665 | 2 | // the previous group, so it is only profitable to do this for groups of | 1666 | 2 | // size 8 or larger. | 1667 | 2 | std::vector<Elf_Rela> ungroupedRelatives; | 1668 | 2 | std::vector<std::vector<Elf_Rela>> relativeGroups; | 1669 | 10 | for (auto i = relatives.begin(), e = relatives.end(); i != e;) { | 1670 | 8 | std::vector<Elf_Rela> group; | 1671 | 50 | do { | 1672 | 50 | group.push_back(*i++); | 1673 | 50 | } while (i != e && (i - 1)->r_offset + config->wordsize == i->r_offset48 ); | 1674 | 8 | | 1675 | 8 | if (group.size() < 8) | 1676 | 4 | ungroupedRelatives.insert(ungroupedRelatives.end(), group.begin(), | 1677 | 4 | group.end()); | 1678 | 4 | else | 1679 | 4 | relativeGroups.emplace_back(std::move(group)); | 1680 | 8 | } | 1681 | 2 | | 1682 | 2 | unsigned hasAddendIfRela = | 1683 | 2 | config->isRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG0 : 0; | 1684 | 2 | | 1685 | 2 | uint64_t offset = 0; | 1686 | 2 | uint64_t addend = 0; | 1687 | 2 | | 1688 | 2 | // Emit the run-length encoding for the groups of adjacent relative | 1689 | 2 | // relocations. Each group is represented using two groups in the packed | 1690 | 2 | // format. The first is used to set the current offset to the start of the | 1691 | 2 | // group (and also encodes the first relocation), and the second encodes the | 1692 | 2 | // remaining relocations. | 1693 | 4 | for (std::vector<Elf_Rela> &g : relativeGroups) { | 1694 | 4 | // The first relocation in the group. | 1695 | 4 | add(1); | 1696 | 4 | add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG | | 1697 | 4 | RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela); | 1698 | 4 | add(g[0].r_offset - offset); | 1699 | 4 | add(target->relativeRel); | 1700 | 4 | if (config->isRela) { | 1701 | 0 | add(g[0].r_addend - addend); | 1702 | 0 | addend = g[0].r_addend; | 1703 | 0 | } | 1704 | 4 | | 1705 | 4 | // The remaining relocations. | 1706 | 4 | add(g.size() - 1); | 1707 | 4 | add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG | | 1708 | 4 | RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela); | 1709 | 4 | add(config->wordsize); | 1710 | 4 | add(target->relativeRel); | 1711 | 4 | if (config->isRela) { | 1712 | 0 | for (auto i = g.begin() + 1, e = g.end(); i != e; ++i) { | 1713 | 0 | add(i->r_addend - addend); | 1714 | 0 | addend = i->r_addend; | 1715 | 0 | } | 1716 | 0 | } | 1717 | 4 | | 1718 | 4 | offset = g.back().r_offset; | 1719 | 4 | } | 1720 | 2 | | 1721 | 2 | // Now the ungrouped relatives. | 1722 | 2 | if (!ungroupedRelatives.empty()) { | 1723 | 2 | add(ungroupedRelatives.size()); | 1724 | 2 | add(RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela); | 1725 | 2 | add(target->relativeRel); | 1726 | 16 | for (Elf_Rela &r : ungroupedRelatives) { | 1727 | 16 | add(r.r_offset - offset); | 1728 | 16 | offset = r.r_offset; | 1729 | 16 | if (config->isRela) { | 1730 | 0 | add(r.r_addend - addend); | 1731 | 0 | addend = r.r_addend; | 1732 | 0 | } | 1733 | 16 | } | 1734 | 2 | } | 1735 | 2 | | 1736 | 2 | // Finally the non-relative relocations. | 1737 | 2 | llvm::sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) { | 1738 | 2 | return a.r_offset < b.r_offset; | 1739 | 2 | }); | 1740 | 2 | if (!nonRelatives.empty()) { | 1741 | 2 | add(nonRelatives.size()); | 1742 | 2 | add(hasAddendIfRela); | 1743 | 4 | for (Elf_Rela &r : nonRelatives) { | 1744 | 4 | add(r.r_offset - offset); | 1745 | 4 | offset = r.r_offset; | 1746 | 4 | add(r.r_info); | 1747 | 4 | if (config->isRela) { | 1748 | 0 | add(r.r_addend - addend); | 1749 | 0 | addend = r.r_addend; | 1750 | 0 | } | 1751 | 4 | } | 1752 | 2 | } | 1753 | 2 | | 1754 | 2 | // Don't allow the section to shrink; otherwise the size of the section can | 1755 | 2 | // oscillate infinitely. | 1756 | 2 | if (relocData.size() < oldSize) | 1757 | 0 | relocData.append(oldSize - relocData.size(), 0); | 1758 | 2 | | 1759 | 2 | // Returns whether the section size changed. We need to keep recomputing both | 1760 | 2 | // section layout and the contents of this section until the size converges | 1761 | 2 | // because changing this section's size can affect section layout, which in | 1762 | 2 | // turn can affect the sizes of the LEB-encoded integers stored in this | 1763 | 2 | // section. | 1764 | 2 | return relocData.size() != oldSize; | 1765 | 2 | } |
Unexecuted instantiation: lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::updateAllocSize() lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::updateAllocSize() Line | Count | Source | 1587 | 12 | bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() { | 1588 | 12 | // This function computes the contents of an Android-format packed relocation | 1589 | 12 | // section. | 1590 | 12 | // | 1591 | 12 | // This format compresses relocations by using relocation groups to factor out | 1592 | 12 | // fields that are common between relocations and storing deltas from previous | 1593 | 12 | // relocations in SLEB128 format (which has a short representation for small | 1594 | 12 | // numbers). A good example of a relocation type with common fields is | 1595 | 12 | // R_*_RELATIVE, which is normally used to represent function pointers in | 1596 | 12 | // vtables. In the REL format, each relative relocation has the same r_info | 1597 | 12 | // field, and is only different from other relative relocations in terms of | 1598 | 12 | // the r_offset field. By sorting relocations by offset, grouping them by | 1599 | 12 | // r_info and representing each relocation with only the delta from the | 1600 | 12 | // previous offset, each 8-byte relocation can be compressed to as little as 1 | 1601 | 12 | // byte (or less with run-length encoding). This relocation packer was able to | 1602 | 12 | // reduce the size of the relocation section in an Android Chromium DSO from | 1603 | 12 | // 2,911,184 bytes to 174,693 bytes, or 6% of the original size. | 1604 | 12 | // | 1605 | 12 | // A relocation section consists of a header containing the literal bytes | 1606 | 12 | // 'APS2' followed by a sequence of SLEB128-encoded integers. The first two | 1607 | 12 | // elements are the total number of relocations in the section and an initial | 1608 | 12 | // r_offset value. The remaining elements define a sequence of relocation | 1609 | 12 | // groups. Each relocation group starts with a header consisting of the | 1610 | 12 | // following elements: | 1611 | 12 | // | 1612 | 12 | // - the number of relocations in the relocation group | 1613 | 12 | // - flags for the relocation group | 1614 | 12 | // - (if RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG is set) the r_offset delta | 1615 | 12 | // for each relocation in the group. | 1616 | 12 | // - (if RELOCATION_GROUPED_BY_INFO_FLAG is set) the value of the r_info | 1617 | 12 | // field for each relocation in the group. | 1618 | 12 | // - (if RELOCATION_GROUP_HAS_ADDEND_FLAG and | 1619 | 12 | // RELOCATION_GROUPED_BY_ADDEND_FLAG are set) the r_addend delta for | 1620 | 12 | // each relocation in the group. | 1621 | 12 | // | 1622 | 12 | // Following the relocation group header are descriptions of each of the | 1623 | 12 | // relocations in the group. They consist of the following elements: | 1624 | 12 | // | 1625 | 12 | // - (if RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG is not set) the r_offset | 1626 | 12 | // delta for this relocation. | 1627 | 12 | // - (if RELOCATION_GROUPED_BY_INFO_FLAG is not set) the value of the r_info | 1628 | 12 | // field for this relocation. | 1629 | 12 | // - (if RELOCATION_GROUP_HAS_ADDEND_FLAG is set and | 1630 | 12 | // RELOCATION_GROUPED_BY_ADDEND_FLAG is not set) the r_addend delta for | 1631 | 12 | // this relocation. | 1632 | 12 | | 1633 | 12 | size_t oldSize = relocData.size(); | 1634 | 12 | | 1635 | 12 | relocData = {'A', 'P', 'S', '2'}; | 1636 | 12 | raw_svector_ostream os(relocData); | 1637 | 12 | auto add = [&](int64_t v) { encodeSLEB128(v, os); }; | 1638 | 12 | | 1639 | 12 | // The format header includes the number of relocations and the initial | 1640 | 12 | // offset (we set this to zero because the first relocation group will | 1641 | 12 | // perform the initial adjustment). | 1642 | 12 | add(relocs.size()); | 1643 | 12 | add(0); | 1644 | 12 | | 1645 | 12 | std::vector<Elf_Rela> relatives, nonRelatives; | 1646 | 12 | | 1647 | 70 | for (const DynamicReloc &rel : relocs) { | 1648 | 70 | Elf_Rela r; | 1649 | 70 | encodeDynamicReloc<ELFT>(getPartition().dynSymTab, &r, rel); | 1650 | 70 | | 1651 | 70 | if (r.getType(config->isMips64EL) == target->relativeRel) | 1652 | 56 | relatives.push_back(r); | 1653 | 14 | else | 1654 | 14 | nonRelatives.push_back(r); | 1655 | 70 | } | 1656 | 12 | | 1657 | 12 | llvm::sort(relatives, [](const Elf_Rel &a, const Elf_Rel &b) { | 1658 | 12 | return a.r_offset < b.r_offset; | 1659 | 12 | }); | 1660 | 12 | | 1661 | 12 | // Try to find groups of relative relocations which are spaced one word | 1662 | 12 | // apart from one another. These generally correspond to vtable entries. The | 1663 | 12 | // format allows these groups to be encoded using a sort of run-length | 1664 | 12 | // encoding, but each group will cost 7 bytes in addition to the offset from | 1665 | 12 | // the previous group, so it is only profitable to do this for groups of | 1666 | 12 | // size 8 or larger. | 1667 | 12 | std::vector<Elf_Rela> ungroupedRelatives; | 1668 | 12 | std::vector<std::vector<Elf_Rela>> relativeGroups; | 1669 | 22 | for (auto i = relatives.begin(), e = relatives.end(); i != e;) { | 1670 | 10 | std::vector<Elf_Rela> group; | 1671 | 56 | do { | 1672 | 56 | group.push_back(*i++); | 1673 | 56 | } while (i != e && (i - 1)->r_offset + config->wordsize == i->r_offset52 ); | 1674 | 10 | | 1675 | 10 | if (group.size() < 8) | 1676 | 6 | ungroupedRelatives.insert(ungroupedRelatives.end(), group.begin(), | 1677 | 6 | group.end()); | 1678 | 4 | else | 1679 | 4 | relativeGroups.emplace_back(std::move(group)); | 1680 | 10 | } | 1681 | 12 | | 1682 | 12 | unsigned hasAddendIfRela = | 1683 | 12 | config->isRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 00 ; | 1684 | 12 | | 1685 | 12 | uint64_t offset = 0; | 1686 | 12 | uint64_t addend = 0; | 1687 | 12 | | 1688 | 12 | // Emit the run-length encoding for the groups of adjacent relative | 1689 | 12 | // relocations. Each group is represented using two groups in the packed | 1690 | 12 | // format. The first is used to set the current offset to the start of the | 1691 | 12 | // group (and also encodes the first relocation), and the second encodes the | 1692 | 12 | // remaining relocations. | 1693 | 12 | for (std::vector<Elf_Rela> &g : relativeGroups) { | 1694 | 4 | // The first relocation in the group. | 1695 | 4 | add(1); | 1696 | 4 | add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG | | 1697 | 4 | RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela); | 1698 | 4 | add(g[0].r_offset - offset); | 1699 | 4 | add(target->relativeRel); | 1700 | 4 | if (config->isRela) { | 1701 | 4 | add(g[0].r_addend - addend); | 1702 | 4 | addend = g[0].r_addend; | 1703 | 4 | } | 1704 | 4 | | 1705 | 4 | // The remaining relocations. | 1706 | 4 | add(g.size() - 1); | 1707 | 4 | add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG | | 1708 | 4 | RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela); | 1709 | 4 | add(config->wordsize); | 1710 | 4 | add(target->relativeRel); | 1711 | 4 | if (config->isRela) { | 1712 | 34 | for (auto i = g.begin() + 1, e = g.end(); i != e; ++i30 ) { | 1713 | 30 | add(i->r_addend - addend); | 1714 | 30 | addend = i->r_addend; | 1715 | 30 | } | 1716 | 4 | } | 1717 | 4 | | 1718 | 4 | offset = g.back().r_offset; | 1719 | 4 | } | 1720 | 12 | | 1721 | 12 | // Now the ungrouped relatives. | 1722 | 12 | if (!ungroupedRelatives.empty()) { | 1723 | 4 | add(ungroupedRelatives.size()); | 1724 | 4 | add(RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela); | 1725 | 4 | add(target->relativeRel); | 1726 | 22 | for (Elf_Rela &r : ungroupedRelatives) { | 1727 | 22 | add(r.r_offset - offset); | 1728 | 22 | offset = r.r_offset; | 1729 | 22 | if (config->isRela) { | 1730 | 22 | add(r.r_addend - addend); | 1731 | 22 | addend = r.r_addend; | 1732 | 22 | } | 1733 | 22 | } | 1734 | 4 | } | 1735 | 12 | | 1736 | 12 | // Finally the non-relative relocations. | 1737 | 12 | llvm::sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) { | 1738 | 12 | return a.r_offset < b.r_offset; | 1739 | 12 | }); | 1740 | 12 | if (!nonRelatives.empty()) { | 1741 | 10 | add(nonRelatives.size()); | 1742 | 10 | add(hasAddendIfRela); | 1743 | 14 | for (Elf_Rela &r : nonRelatives) { | 1744 | 14 | add(r.r_offset - offset); | 1745 | 14 | offset = r.r_offset; | 1746 | 14 | add(r.r_info); | 1747 | 14 | if (config->isRela) { | 1748 | 14 | add(r.r_addend - addend); | 1749 | 14 | addend = r.r_addend; | 1750 | 14 | } | 1751 | 14 | } | 1752 | 10 | } | 1753 | 12 | | 1754 | 12 | // Don't allow the section to shrink; otherwise the size of the section can | 1755 | 12 | // oscillate infinitely. | 1756 | 12 | if (relocData.size() < oldSize) | 1757 | 1 | relocData.append(oldSize - relocData.size(), 0); | 1758 | 12 | | 1759 | 12 | // Returns whether the section size changed. We need to keep recomputing both | 1760 | 12 | // section layout and the contents of this section until the size converges | 1761 | 12 | // because changing this section's size can affect section layout, which in | 1762 | 12 | // turn can affect the sizes of the LEB-encoded integers stored in this | 1763 | 12 | // section. | 1764 | 12 | return relocData.size() != oldSize; | 1765 | 12 | } |
Unexecuted instantiation: lld::elf::AndroidPackedRelocationSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::updateAllocSize() |
1766 | | |
1767 | 6 | template <class ELFT> RelrSection<ELFT>::RelrSection() { |
1768 | 6 | this->entsize = config->wordsize; |
1769 | 6 | } lld::elf::RelrSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::RelrSection() Line | Count | Source | 1767 | 2 | template <class ELFT> RelrSection<ELFT>::RelrSection() { | 1768 | 2 | this->entsize = config->wordsize; | 1769 | 2 | } |
Unexecuted instantiation: lld::elf::RelrSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::RelrSection() lld::elf::RelrSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::RelrSection() Line | Count | Source | 1767 | 4 | template <class ELFT> RelrSection<ELFT>::RelrSection() { | 1768 | 4 | this->entsize = config->wordsize; | 1769 | 4 | } |
Unexecuted instantiation: lld::elf::RelrSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::RelrSection() |
1770 | | |
1771 | 11 | template <class ELFT> bool RelrSection<ELFT>::updateAllocSize() { |
1772 | 11 | // This function computes the contents of an SHT_RELR packed relocation |
1773 | 11 | // section. |
1774 | 11 | // |
1775 | 11 | // Proposal for adding SHT_RELR sections to generic-abi is here: |
1776 | 11 | // https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg |
1777 | 11 | // |
1778 | 11 | // The encoded sequence of Elf64_Relr entries in a SHT_RELR section looks |
1779 | 11 | // like [ AAAAAAAA BBBBBBB1 BBBBBBB1 ... AAAAAAAA BBBBBB1 ... ] |
1780 | 11 | // |
1781 | 11 | // i.e. start with an address, followed by any number of bitmaps. The address |
1782 | 11 | // entry encodes 1 relocation. The subsequent bitmap entries encode up to 63 |
1783 | 11 | // relocations each, at subsequent offsets following the last address entry. |
1784 | 11 | // |
1785 | 11 | // The bitmap entries must have 1 in the least significant bit. The assumption |
1786 | 11 | // here is that an address cannot have 1 in lsb. Odd addresses are not |
1787 | 11 | // supported. |
1788 | 11 | // |
1789 | 11 | // Excluding the least significant bit in the bitmap, each non-zero bit in |
1790 | 11 | // the bitmap represents a relocation to be applied to a corresponding machine |
1791 | 11 | // word that follows the base address word. The second least significant bit |
1792 | 11 | // represents the machine word immediately following the initial address, and |
1793 | 11 | // each bit that follows represents the next word, in linear order. As such, |
1794 | 11 | // a single bitmap can encode up to 31 relocations in a 32-bit object, and |
1795 | 11 | // 63 relocations in a 64-bit object. |
1796 | 11 | // |
1797 | 11 | // This encoding has a couple of interesting properties: |
1798 | 11 | // 1. Looking at any entry, it is clear whether it's an address or a bitmap: |
1799 | 11 | // even means address, odd means bitmap. |
1800 | 11 | // 2. Just a simple list of addresses is a valid encoding. |
1801 | 11 | |
1802 | 11 | size_t oldSize = relrRelocs.size(); |
1803 | 11 | relrRelocs.clear(); |
1804 | 11 | |
1805 | 11 | // Same as Config->Wordsize but faster because this is a compile-time |
1806 | 11 | // constant. |
1807 | 11 | const size_t wordsize = sizeof(typename ELFT::uint); |
1808 | 11 | |
1809 | 11 | // Number of bits to use for the relocation offsets bitmap. |
1810 | 11 | // Must be either 63 or 31. |
1811 | 11 | const size_t nBits = wordsize * 8 - 1; |
1812 | 11 | |
1813 | 11 | // Get offsets for all relative relocations and sort them. |
1814 | 11 | std::vector<uint64_t> offsets; |
1815 | 11 | for (const RelativeReloc &rel : relocs) |
1816 | 168 | offsets.push_back(rel.getOffset()); |
1817 | 11 | llvm::sort(offsets); |
1818 | 11 | |
1819 | 11 | // For each leading relocation, find following ones that can be folded |
1820 | 11 | // as a bitmap and fold them. |
1821 | 21 | for (size_t i = 0, e = offsets.size(); i < e;) { |
1822 | 10 | // Add a leading relocation. |
1823 | 10 | relrRelocs.push_back(Elf_Relr(offsets[i])); |
1824 | 10 | uint64_t base = offsets[i] + wordsize; |
1825 | 10 | ++i; |
1826 | 10 | |
1827 | 10 | // Find foldable relocations to construct bitmaps. |
1828 | 18 | while (i < e) { |
1829 | 8 | uint64_t bitmap = 0; |
1830 | 8 | |
1831 | 166 | while (i < e) { |
1832 | 160 | uint64_t delta = offsets[i] - base; |
1833 | 160 | |
1834 | 160 | // If it is too far, it cannot be folded. |
1835 | 160 | if (delta >= nBits * wordsize) |
1836 | 2 | break; |
1837 | 158 | |
1838 | 158 | // If it is not a multiple of wordsize away, it cannot be folded. |
1839 | 158 | if (delta % wordsize) |
1840 | 0 | break; |
1841 | 158 | |
1842 | 158 | // Fold it. |
1843 | 158 | bitmap |= 1ULL << (delta / wordsize); |
1844 | 158 | ++i; |
1845 | 158 | } |
1846 | 8 | |
1847 | 8 | if (!bitmap) |
1848 | 0 | break; |
1849 | 8 | |
1850 | 8 | relrRelocs.push_back(Elf_Relr((bitmap << 1) | 1)); |
1851 | 8 | base += nBits * wordsize; |
1852 | 8 | } |
1853 | 10 | } |
1854 | 11 | |
1855 | 11 | return relrRelocs.size() != oldSize; |
1856 | 11 | } lld::elf::RelrSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::updateAllocSize() Line | Count | Source | 1771 | 4 | template <class ELFT> bool RelrSection<ELFT>::updateAllocSize() { | 1772 | 4 | // This function computes the contents of an SHT_RELR packed relocation | 1773 | 4 | // section. | 1774 | 4 | // | 1775 | 4 | // Proposal for adding SHT_RELR sections to generic-abi is here: | 1776 | 4 | // https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg | 1777 | 4 | // | 1778 | 4 | // The encoded sequence of Elf64_Relr entries in a SHT_RELR section looks | 1779 | 4 | // like [ AAAAAAAA BBBBBBB1 BBBBBBB1 ... AAAAAAAA BBBBBB1 ... ] | 1780 | 4 | // | 1781 | 4 | // i.e. start with an address, followed by any number of bitmaps. The address | 1782 | 4 | // entry encodes 1 relocation. The subsequent bitmap entries encode up to 63 | 1783 | 4 | // relocations each, at subsequent offsets following the last address entry. | 1784 | 4 | // | 1785 | 4 | // The bitmap entries must have 1 in the least significant bit. The assumption | 1786 | 4 | // here is that an address cannot have 1 in lsb. Odd addresses are not | 1787 | 4 | // supported. | 1788 | 4 | // | 1789 | 4 | // Excluding the least significant bit in the bitmap, each non-zero bit in | 1790 | 4 | // the bitmap represents a relocation to be applied to a corresponding machine | 1791 | 4 | // word that follows the base address word. The second least significant bit | 1792 | 4 | // represents the machine word immediately following the initial address, and | 1793 | 4 | // each bit that follows represents the next word, in linear order. As such, | 1794 | 4 | // a single bitmap can encode up to 31 relocations in a 32-bit object, and | 1795 | 4 | // 63 relocations in a 64-bit object. | 1796 | 4 | // | 1797 | 4 | // This encoding has a couple of interesting properties: | 1798 | 4 | // 1. Looking at any entry, it is clear whether it's an address or a bitmap: | 1799 | 4 | // even means address, odd means bitmap. | 1800 | 4 | // 2. Just a simple list of addresses is a valid encoding. | 1801 | 4 | | 1802 | 4 | size_t oldSize = relrRelocs.size(); | 1803 | 4 | relrRelocs.clear(); | 1804 | 4 | | 1805 | 4 | // Same as Config->Wordsize but faster because this is a compile-time | 1806 | 4 | // constant. | 1807 | 4 | const size_t wordsize = sizeof(typename ELFT::uint); | 1808 | 4 | | 1809 | 4 | // Number of bits to use for the relocation offsets bitmap. | 1810 | 4 | // Must be either 63 or 31. | 1811 | 4 | const size_t nBits = wordsize * 8 - 1; | 1812 | 4 | | 1813 | 4 | // Get offsets for all relative relocations and sort them. | 1814 | 4 | std::vector<uint64_t> offsets; | 1815 | 4 | for (const RelativeReloc &rel : relocs) | 1816 | 116 | offsets.push_back(rel.getOffset()); | 1817 | 4 | llvm::sort(offsets); | 1818 | 4 | | 1819 | 4 | // For each leading relocation, find following ones that can be folded | 1820 | 4 | // as a bitmap and fold them. | 1821 | 8 | for (size_t i = 0, e = offsets.size(); i < e;) { | 1822 | 4 | // Add a leading relocation. | 1823 | 4 | relrRelocs.push_back(Elf_Relr(offsets[i])); | 1824 | 4 | uint64_t base = offsets[i] + wordsize; | 1825 | 4 | ++i; | 1826 | 4 | | 1827 | 4 | // Find foldable relocations to construct bitmaps. | 1828 | 10 | while (i < e) { | 1829 | 6 | uint64_t bitmap = 0; | 1830 | 6 | | 1831 | 118 | while (i < e) { | 1832 | 114 | uint64_t delta = offsets[i] - base; | 1833 | 114 | | 1834 | 114 | // If it is too far, it cannot be folded. | 1835 | 114 | if (delta >= nBits * wordsize) | 1836 | 2 | break; | 1837 | 112 | | 1838 | 112 | // If it is not a multiple of wordsize away, it cannot be folded. | 1839 | 112 | if (delta % wordsize) | 1840 | 0 | break; | 1841 | 112 | | 1842 | 112 | // Fold it. | 1843 | 112 | bitmap |= 1ULL << (delta / wordsize); | 1844 | 112 | ++i; | 1845 | 112 | } | 1846 | 6 | | 1847 | 6 | if (!bitmap) | 1848 | 0 | break; | 1849 | 6 | | 1850 | 6 | relrRelocs.push_back(Elf_Relr((bitmap << 1) | 1)); | 1851 | 6 | base += nBits * wordsize; | 1852 | 6 | } | 1853 | 4 | } | 1854 | 4 | | 1855 | 4 | return relrRelocs.size() != oldSize; | 1856 | 4 | } |
Unexecuted instantiation: lld::elf::RelrSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::updateAllocSize() lld::elf::RelrSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::updateAllocSize() Line | Count | Source | 1771 | 7 | template <class ELFT> bool RelrSection<ELFT>::updateAllocSize() { | 1772 | 7 | // This function computes the contents of an SHT_RELR packed relocation | 1773 | 7 | // section. | 1774 | 7 | // | 1775 | 7 | // Proposal for adding SHT_RELR sections to generic-abi is here: | 1776 | 7 | // https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg | 1777 | 7 | // | 1778 | 7 | // The encoded sequence of Elf64_Relr entries in a SHT_RELR section looks | 1779 | 7 | // like [ AAAAAAAA BBBBBBB1 BBBBBBB1 ... AAAAAAAA BBBBBB1 ... ] | 1780 | 7 | // | 1781 | 7 | // i.e. start with an address, followed by any number of bitmaps. The address | 1782 | 7 | // entry encodes 1 relocation. The subsequent bitmap entries encode up to 63 | 1783 | 7 | // relocations each, at subsequent offsets following the last address entry. | 1784 | 7 | // | 1785 | 7 | // The bitmap entries must have 1 in the least significant bit. The assumption | 1786 | 7 | // here is that an address cannot have 1 in lsb. Odd addresses are not | 1787 | 7 | // supported. | 1788 | 7 | // | 1789 | 7 | // Excluding the least significant bit in the bitmap, each non-zero bit in | 1790 | 7 | // the bitmap represents a relocation to be applied to a corresponding machine | 1791 | 7 | // word that follows the base address word. The second least significant bit | 1792 | 7 | // represents the machine word immediately following the initial address, and | 1793 | 7 | // each bit that follows represents the next word, in linear order. As such, | 1794 | 7 | // a single bitmap can encode up to 31 relocations in a 32-bit object, and | 1795 | 7 | // 63 relocations in a 64-bit object. | 1796 | 7 | // | 1797 | 7 | // This encoding has a couple of interesting properties: | 1798 | 7 | // 1. Looking at any entry, it is clear whether it's an address or a bitmap: | 1799 | 7 | // even means address, odd means bitmap. | 1800 | 7 | // 2. Just a simple list of addresses is a valid encoding. | 1801 | 7 | | 1802 | 7 | size_t oldSize = relrRelocs.size(); | 1803 | 7 | relrRelocs.clear(); | 1804 | 7 | | 1805 | 7 | // Same as Config->Wordsize but faster because this is a compile-time | 1806 | 7 | // constant. | 1807 | 7 | const size_t wordsize = sizeof(typename ELFT::uint); | 1808 | 7 | | 1809 | 7 | // Number of bits to use for the relocation offsets bitmap. | 1810 | 7 | // Must be either 63 or 31. | 1811 | 7 | const size_t nBits = wordsize * 8 - 1; | 1812 | 7 | | 1813 | 7 | // Get offsets for all relative relocations and sort them. | 1814 | 7 | std::vector<uint64_t> offsets; | 1815 | 7 | for (const RelativeReloc &rel : relocs) | 1816 | 52 | offsets.push_back(rel.getOffset()); | 1817 | 7 | llvm::sort(offsets); | 1818 | 7 | | 1819 | 7 | // For each leading relocation, find following ones that can be folded | 1820 | 7 | // as a bitmap and fold them. | 1821 | 13 | for (size_t i = 0, e = offsets.size(); i < e;) { | 1822 | 6 | // Add a leading relocation. | 1823 | 6 | relrRelocs.push_back(Elf_Relr(offsets[i])); | 1824 | 6 | uint64_t base = offsets[i] + wordsize; | 1825 | 6 | ++i; | 1826 | 6 | | 1827 | 6 | // Find foldable relocations to construct bitmaps. | 1828 | 8 | while (i < e) { | 1829 | 2 | uint64_t bitmap = 0; | 1830 | 2 | | 1831 | 48 | while (i < e) { | 1832 | 46 | uint64_t delta = offsets[i] - base; | 1833 | 46 | | 1834 | 46 | // If it is too far, it cannot be folded. | 1835 | 46 | if (delta >= nBits * wordsize) | 1836 | 0 | break; | 1837 | 46 | | 1838 | 46 | // If it is not a multiple of wordsize away, it cannot be folded. | 1839 | 46 | if (delta % wordsize) | 1840 | 0 | break; | 1841 | 46 | | 1842 | 46 | // Fold it. | 1843 | 46 | bitmap |= 1ULL << (delta / wordsize); | 1844 | 46 | ++i; | 1845 | 46 | } | 1846 | 2 | | 1847 | 2 | if (!bitmap) | 1848 | 0 | break; | 1849 | 2 | | 1850 | 2 | relrRelocs.push_back(Elf_Relr((bitmap << 1) | 1)); | 1851 | 2 | base += nBits * wordsize; | 1852 | 2 | } | 1853 | 6 | } | 1854 | 7 | | 1855 | 7 | return relrRelocs.size() != oldSize; | 1856 | 7 | } |
Unexecuted instantiation: lld::elf::RelrSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::updateAllocSize() |
1857 | | |
1858 | | SymbolTableBaseSection::SymbolTableBaseSection(StringTableSection &strTabSec) |
1859 | | : SyntheticSection(strTabSec.isDynamic() ? (uint64_t)SHF_ALLOC : 0, |
1860 | | strTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB, |
1861 | | config->wordsize, |
1862 | | strTabSec.isDynamic() ? ".dynsym" : ".symtab"), |
1863 | 6.87k | strTabSec(strTabSec) {} |
1864 | | |
1865 | | // Orders symbols according to their positions in the GOT, |
1866 | | // in compliance with MIPS ABI rules. |
1867 | | // See "Global Offset Table" in Chapter 5 in the following document |
1868 | | // for detailed description: |
1869 | | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf |
1870 | | static bool sortMipsSymbols(const SymbolTableEntry &l, |
1871 | 153 | const SymbolTableEntry &r) { |
1872 | 153 | // Sort entries related to non-local preemptible symbols by GOT indexes. |
1873 | 153 | // All other entries go to the beginning of a dynsym in arbitrary order. |
1874 | 153 | if (l.sym->isInGot() && r.sym->isInGot()21 ) |
1875 | 6 | return l.sym->gotIndex < r.sym->gotIndex; |
1876 | 147 | if (!l.sym->isInGot() && !r.sym->isInGot()132 ) |
1877 | 108 | return false; |
1878 | 39 | return !l.sym->isInGot(); |
1879 | 39 | } |
1880 | | |
1881 | 3.86k | void SymbolTableBaseSection::finalizeContents() { |
1882 | 3.86k | if (OutputSection *sec = strTabSec.getParent()) |
1883 | 3.86k | getParent()->link = sec->sectionIndex; |
1884 | 3.86k | |
1885 | 3.86k | if (this->type != SHT_DYNSYM) { |
1886 | 2.60k | sortSymTabSymbols(); |
1887 | 2.60k | return; |
1888 | 2.60k | } |
1889 | 1.26k | |
1890 | 1.26k | // If it is a .dynsym, there should be no local symbols, but we need |
1891 | 1.26k | // to do a few things for the dynamic linker. |
1892 | 1.26k | |
1893 | 1.26k | // Section's Info field has the index of the first non-local symbol. |
1894 | 1.26k | // Because the first symbol entry is a null entry, 1 is the first. |
1895 | 1.26k | getParent()->info = 1; |
1896 | 1.26k | |
1897 | 1.26k | if (getPartition().gnuHashTab) { |
1898 | 1.02k | // NB: It also sorts Symbols to meet the GNU hash table requirements. |
1899 | 1.02k | getPartition().gnuHashTab->addSymbols(symbols); |
1900 | 1.02k | } else if (235 config->emachine == EM_MIPS235 ) { |
1901 | 100 | llvm::stable_sort(symbols, sortMipsSymbols); |
1902 | 100 | } |
1903 | 1.26k | |
1904 | 1.26k | // Only the main partition's dynsym indexes are stored in the symbols |
1905 | 1.26k | // themselves. All other partitions use a lookup table. |
1906 | 1.26k | if (this == mainPart->dynSymTab) { |
1907 | 1.25k | size_t i = 0; |
1908 | 1.25k | for (const SymbolTableEntry &s : symbols) |
1909 | 2.14k | s.sym->dynsymIndex = ++i; |
1910 | 1.25k | } |
1911 | 1.26k | } |
1912 | | |
1913 | | // The ELF spec requires that all local symbols precede global symbols, so we |
1914 | | // sort symbol entries in this function. (For .dynsym, we don't do that because |
1915 | | // symbols for dynamic linking are inherently all globals.) |
1916 | | // |
1917 | | // Aside from above, we put local symbols in groups starting with the STT_FILE |
1918 | | // symbol. That is convenient for purpose of identifying where are local symbols |
1919 | | // coming from. |
1920 | 2.60k | void SymbolTableBaseSection::sortSymTabSymbols() { |
1921 | 2.60k | // Move all local symbols before global symbols. |
1922 | 2.60k | auto e = std::stable_partition( |
1923 | 85.8k | symbols.begin(), symbols.end(), [](const SymbolTableEntry &s) { |
1924 | 85.8k | return s.sym->isLocal() || s.sym->computeBinding() == STB_LOCAL17.4k ; |
1925 | 85.8k | }); |
1926 | 2.60k | size_t numLocals = e - symbols.begin(); |
1927 | 2.60k | getParent()->info = numLocals + 1; |
1928 | 2.60k | |
1929 | 2.60k | // We want to group the local symbols by file. For that we rebuild the local |
1930 | 2.60k | // part of the symbols vector. We do not need to care about the STT_FILE |
1931 | 2.60k | // symbols, they are already naturally placed first in each group. That |
1932 | 2.60k | // happens because STT_FILE is always the first symbol in the object and hence |
1933 | 2.60k | // precede all other local symbols we add for a file. |
1934 | 2.60k | MapVector<InputFile *, std::vector<SymbolTableEntry>> arr; |
1935 | 2.60k | for (const SymbolTableEntry &s : llvm::make_range(symbols.begin(), e)) |
1936 | 70.2k | arr[s.sym->file].push_back(s); |
1937 | 2.60k | |
1938 | 2.60k | auto i = symbols.begin(); |
1939 | 2.60k | for (std::pair<InputFile *, std::vector<SymbolTableEntry>> &p : arr) |
1940 | 2.48k | for (SymbolTableEntry &entry : p.second) |
1941 | 70.2k | *i++ = entry; |
1942 | 2.60k | } |
1943 | | |
1944 | 88.5k | void SymbolTableBaseSection::addSymbol(Symbol *b) { |
1945 | 88.5k | // Adding a local symbol to a .dynsym is a bug. |
1946 | 88.5k | assert(this->type != SHT_DYNSYM || !b->isLocal()); |
1947 | 88.5k | |
1948 | 88.5k | bool hashIt = b->isLocal(); |
1949 | 88.5k | symbols.push_back({b, strTabSec.addString(b->getName(), hashIt)}); |
1950 | 88.5k | } |
1951 | | |
1952 | 2.33k | size_t SymbolTableBaseSection::getSymbolIndex(Symbol *sym) { |
1953 | 2.33k | if (this == mainPart->dynSymTab) |
1954 | 2.13k | return sym->dynsymIndex; |
1955 | 201 | |
1956 | 201 | // Initializes symbol lookup tables lazily. This is used only for -r, |
1957 | 201 | // -emit-relocs and dynsyms in partitions other than the main one. |
1958 | 201 | llvm::call_once(onceFlag, [&] { |
1959 | 80 | symbolIndexMap.reserve(symbols.size()); |
1960 | 80 | size_t i = 0; |
1961 | 412 | for (const SymbolTableEntry &e : symbols) { |
1962 | 412 | if (e.sym->type == STT_SECTION) |
1963 | 203 | sectionIndexMap[e.sym->getOutputSection()] = ++i; |
1964 | 209 | else |
1965 | 209 | symbolIndexMap[e.sym] = ++i; |
1966 | 412 | } |
1967 | 80 | }); |
1968 | 201 | |
1969 | 201 | // Section symbols are mapped based on their output sections |
1970 | 201 | // to maintain their semantics. |
1971 | 201 | if (sym->type == STT_SECTION) |
1972 | 93 | return sectionIndexMap.lookup(sym->getOutputSection()); |
1973 | 108 | return symbolIndexMap.lookup(sym); |
1974 | 108 | } |
1975 | | |
1976 | | template <class ELFT> |
1977 | | SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &strTabSec) |
1978 | 6.87k | : SymbolTableBaseSection(strTabSec) { |
1979 | 6.87k | this->entsize = sizeof(Elf_Sym); |
1980 | 6.87k | } lld::elf::SymbolTableSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::SymbolTableSection(lld::elf::StringTableSection&) Line | Count | Source | 1978 | 941 | : SymbolTableBaseSection(strTabSec) { | 1979 | 941 | this->entsize = sizeof(Elf_Sym); | 1980 | 941 | } |
lld::elf::SymbolTableSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::SymbolTableSection(lld::elf::StringTableSection&) Line | Count | Source | 1978 | 401 | : SymbolTableBaseSection(strTabSec) { | 1979 | 401 | this->entsize = sizeof(Elf_Sym); | 1980 | 401 | } |
lld::elf::SymbolTableSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::SymbolTableSection(lld::elf::StringTableSection&) Line | Count | Source | 1978 | 5.26k | : SymbolTableBaseSection(strTabSec) { | 1979 | 5.26k | this->entsize = sizeof(Elf_Sym); | 1980 | 5.26k | } |
lld::elf::SymbolTableSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::SymbolTableSection(lld::elf::StringTableSection&) Line | Count | Source | 1978 | 272 | : SymbolTableBaseSection(strTabSec) { | 1979 | 272 | this->entsize = sizeof(Elf_Sym); | 1980 | 272 | } |
|
1981 | | |
1982 | 241k | static BssSection *getCommonSec(Symbol *sym) { |
1983 | 241k | if (!config->defineCommon) |
1984 | 197k | if (auto *d = dyn_cast<Defined>(sym)) |
1985 | 197k | return dyn_cast_or_null<BssSection>(d->section); |
1986 | 44.0k | return nullptr; |
1987 | 44.0k | } |
1988 | | |
1989 | 153k | static uint32_t getSymSectionIndex(Symbol *sym) { |
1990 | 153k | if (getCommonSec(sym)) |
1991 | 2 | return SHN_COMMON; |
1992 | 153k | if (!isa<Defined>(sym) || sym->needsPltAddr152k ) |
1993 | 1.28k | return SHN_UNDEF; |
1994 | 152k | if (const OutputSection *os = sym->getOutputSection()) |
1995 | 151k | return os->sectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX522 |
1996 | 151k | : os->sectionIndex150k ; |
1997 | 720 | return SHN_ABS; |
1998 | 720 | } |
1999 | | |
2000 | | // Write the internal symbol table contents to the output symbol table. |
2001 | 3.82k | template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) { |
2002 | 3.82k | // The first entry is a null entry as per the ELF spec. |
2003 | 3.82k | memset(buf, 0, sizeof(Elf_Sym)); |
2004 | 3.82k | buf += sizeof(Elf_Sym); |
2005 | 3.82k | |
2006 | 3.82k | auto *eSym = reinterpret_cast<Elf_Sym *>(buf); |
2007 | 3.82k | |
2008 | 87.9k | for (SymbolTableEntry &ent : symbols) { |
2009 | 87.9k | Symbol *sym = ent.sym; |
2010 | 87.9k | bool isDefinedHere = type == SHT_SYMTAB || sym->partition == partition2.13k ; |
2011 | 87.9k | |
2012 | 87.9k | // Set st_info and st_other. |
2013 | 87.9k | eSym->st_other = 0; |
2014 | 87.9k | if (sym->isLocal()) { |
2015 | 68.3k | eSym->setBindingAndType(STB_LOCAL, sym->type); |
2016 | 68.3k | } else { |
2017 | 19.5k | eSym->setBindingAndType(sym->computeBinding(), sym->type); |
2018 | 19.5k | eSym->setVisibility(sym->visibility); |
2019 | 19.5k | } |
2020 | 87.9k | |
2021 | 87.9k | // The 3 most significant bits of st_other are used by OpenPOWER ABI. |
2022 | 87.9k | // See getPPC64GlobalEntryToLocalEntryOffset() for more details. |
2023 | 87.9k | if (config->emachine == EM_PPC64) |
2024 | 814 | eSym->st_other |= sym->stOther & 0xe0; |
2025 | 87.9k | |
2026 | 87.9k | eSym->st_name = ent.strTabOffset; |
2027 | 87.9k | if (isDefinedHere) |
2028 | 87.9k | eSym->st_shndx = getSymSectionIndex(ent.sym); |
2029 | 2 | else |
2030 | 2 | eSym->st_shndx = 0; |
2031 | 87.9k | |
2032 | 87.9k | // Copy symbol size if it is a defined symbol. st_size is not significant |
2033 | 87.9k | // for undefined symbols, so whether copying it or not is up to us if that's |
2034 | 87.9k | // the case. We'll leave it as zero because by not setting a value, we can |
2035 | 87.9k | // get the exact same outputs for two sets of input files that differ only |
2036 | 87.9k | // in undefined symbol size in DSOs. |
2037 | 87.9k | if (eSym->st_shndx == SHN_UNDEF || !isDefinedHere86.6k ) |
2038 | 1.28k | eSym->st_size = 0; |
2039 | 86.6k | else |
2040 | 86.6k | eSym->st_size = sym->getSize(); |
2041 | 87.9k | |
2042 | 87.9k | // st_value is usually an address of a symbol, but that has a |
2043 | 87.9k | // special meaining for uninstantiated common symbols (this can |
2044 | 87.9k | // occur if -r is given). |
2045 | 87.9k | if (BssSection *commonSec = getCommonSec(ent.sym)) |
2046 | 2 | eSym->st_value = commonSec->alignment; |
2047 | 87.9k | else if (isDefinedHere) |
2048 | 87.9k | eSym->st_value = sym->getVA(); |
2049 | 2 | else |
2050 | 2 | eSym->st_value = 0; |
2051 | 87.9k | |
2052 | 87.9k | ++eSym; |
2053 | 87.9k | } |
2054 | 3.82k | |
2055 | 3.82k | // On MIPS we need to mark symbol which has a PLT entry and requires |
2056 | 3.82k | // pointer equality by STO_MIPS_PLT flag. That is necessary to help |
2057 | 3.82k | // dynamic linker distinguish such symbols and MIPS lazy-binding stubs. |
2058 | 3.82k | // https://sourceware.org/ml/binutils/2008-07/txt00000.txt |
2059 | 3.82k | if (config->emachine == EM_MIPS) { |
2060 | 287 | auto *eSym = reinterpret_cast<Elf_Sym *>(buf); |
2061 | 287 | |
2062 | 11.1k | for (SymbolTableEntry &ent : symbols) { |
2063 | 11.1k | Symbol *sym = ent.sym; |
2064 | 11.1k | if (sym->isInPlt() && sym->needsPltAddr34 ) |
2065 | 8 | eSym->st_other |= STO_MIPS_PLT; |
2066 | 11.1k | if (isMicroMips()) { |
2067 | 147 | // We already set the less-significant bit for symbols |
2068 | 147 | // marked by the `STO_MIPS_MICROMIPS` flag and for microMIPS PLT |
2069 | 147 | // records. That allows us to distinguish such symbols in |
2070 | 147 | // the `MIPS<ELFT>::relocateOne()` routine. Now we should |
2071 | 147 | // clear that bit for non-dynamic symbol table, so tools |
2072 | 147 | // like `objdump` will be able to deal with a correct |
2073 | 147 | // symbol position. |
2074 | 147 | if (sym->isDefined() && |
2075 | 147 | (135 (sym->stOther & STO_MIPS_MICROMIPS)135 || sym->needsPltAddr94 )) { |
2076 | 43 | if (!strTabSec.isDynamic()) |
2077 | 37 | eSym->st_value &= ~1; |
2078 | 43 | eSym->st_other |= STO_MIPS_MICROMIPS; |
2079 | 43 | } |
2080 | 147 | } |
2081 | 11.1k | if (config->relocatable) |
2082 | 82 | if (auto *d = dyn_cast<Defined>(sym)) |
2083 | 82 | if (isMipsPIC<ELFT>(d)) |
2084 | 7 | eSym->st_other |= STO_MIPS_PIC; |
2085 | 11.1k | ++eSym; |
2086 | 11.1k | } |
2087 | 287 | } |
2088 | 3.82k | } lld::elf::SymbolTableSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*) Line | Count | Source | 2001 | 542 | template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) { | 2002 | 542 | // The first entry is a null entry as per the ELF spec. | 2003 | 542 | memset(buf, 0, sizeof(Elf_Sym)); | 2004 | 542 | buf += sizeof(Elf_Sym); | 2005 | 542 | | 2006 | 542 | auto *eSym = reinterpret_cast<Elf_Sym *>(buf); | 2007 | 542 | | 2008 | 2.84k | for (SymbolTableEntry &ent : symbols) { | 2009 | 2.84k | Symbol *sym = ent.sym; | 2010 | 2.84k | bool isDefinedHere = type == SHT_SYMTAB || sym->partition == partition351 ; | 2011 | 2.84k | | 2012 | 2.84k | // Set st_info and st_other. | 2013 | 2.84k | eSym->st_other = 0; | 2014 | 2.84k | if (sym->isLocal()) { | 2015 | 1.14k | eSym->setBindingAndType(STB_LOCAL, sym->type); | 2016 | 1.70k | } else { | 2017 | 1.70k | eSym->setBindingAndType(sym->computeBinding(), sym->type); | 2018 | 1.70k | eSym->setVisibility(sym->visibility); | 2019 | 1.70k | } | 2020 | 2.84k | | 2021 | 2.84k | // The 3 most significant bits of st_other are used by OpenPOWER ABI. | 2022 | 2.84k | // See getPPC64GlobalEntryToLocalEntryOffset() for more details. | 2023 | 2.84k | if (config->emachine == EM_PPC64) | 2024 | 0 | eSym->st_other |= sym->stOther & 0xe0; | 2025 | 2.84k | | 2026 | 2.84k | eSym->st_name = ent.strTabOffset; | 2027 | 2.84k | if (isDefinedHere) | 2028 | 2.84k | eSym->st_shndx = getSymSectionIndex(ent.sym); | 2029 | 0 | else | 2030 | 0 | eSym->st_shndx = 0; | 2031 | 2.84k | | 2032 | 2.84k | // Copy symbol size if it is a defined symbol. st_size is not significant | 2033 | 2.84k | // for undefined symbols, so whether copying it or not is up to us if that's | 2034 | 2.84k | // the case. We'll leave it as zero because by not setting a value, we can | 2035 | 2.84k | // get the exact same outputs for two sets of input files that differ only | 2036 | 2.84k | // in undefined symbol size in DSOs. | 2037 | 2.84k | if (eSym->st_shndx == SHN_UNDEF || !isDefinedHere2.63k ) | 2038 | 208 | eSym->st_size = 0; | 2039 | 2.63k | else | 2040 | 2.63k | eSym->st_size = sym->getSize(); | 2041 | 2.84k | | 2042 | 2.84k | // st_value is usually an address of a symbol, but that has a | 2043 | 2.84k | // special meaining for uninstantiated common symbols (this can | 2044 | 2.84k | // occur if -r is given). | 2045 | 2.84k | if (BssSection *commonSec = getCommonSec(ent.sym)) | 2046 | 0 | eSym->st_value = commonSec->alignment; | 2047 | 2.84k | else if (isDefinedHere) | 2048 | 2.84k | eSym->st_value = sym->getVA(); | 2049 | 0 | else | 2050 | 0 | eSym->st_value = 0; | 2051 | 2.84k | | 2052 | 2.84k | ++eSym; | 2053 | 2.84k | } | 2054 | 542 | | 2055 | 542 | // On MIPS we need to mark symbol which has a PLT entry and requires | 2056 | 542 | // pointer equality by STO_MIPS_PLT flag. That is necessary to help | 2057 | 542 | // dynamic linker distinguish such symbols and MIPS lazy-binding stubs. | 2058 | 542 | // https://sourceware.org/ml/binutils/2008-07/txt00000.txt | 2059 | 542 | if (config->emachine == EM_MIPS) { | 2060 | 31 | auto *eSym = reinterpret_cast<Elf_Sym *>(buf); | 2061 | 31 | | 2062 | 95 | for (SymbolTableEntry &ent : symbols) { | 2063 | 95 | Symbol *sym = ent.sym; | 2064 | 95 | if (sym->isInPlt() && sym->needsPltAddr4 ) | 2065 | 0 | eSym->st_other |= STO_MIPS_PLT; | 2066 | 95 | if (isMicroMips()) { | 2067 | 41 | // We already set the less-significant bit for symbols | 2068 | 41 | // marked by the `STO_MIPS_MICROMIPS` flag and for microMIPS PLT | 2069 | 41 | // records. That allows us to distinguish such symbols in | 2070 | 41 | // the `MIPS<ELFT>::relocateOne()` routine. Now we should | 2071 | 41 | // clear that bit for non-dynamic symbol table, so tools | 2072 | 41 | // like `objdump` will be able to deal with a correct | 2073 | 41 | // symbol position. | 2074 | 41 | if (sym->isDefined() && | 2075 | 41 | (37 (sym->stOther & STO_MIPS_MICROMIPS)37 || sym->needsPltAddr21 )) { | 2076 | 16 | if (!strTabSec.isDynamic()) | 2077 | 14 | eSym->st_value &= ~1; | 2078 | 16 | eSym->st_other |= STO_MIPS_MICROMIPS; | 2079 | 16 | } | 2080 | 41 | } | 2081 | 95 | if (config->relocatable) | 2082 | 5 | if (auto *d = dyn_cast<Defined>(sym)) | 2083 | 5 | if (isMipsPIC<ELFT>(d)) | 2084 | 0 | eSym->st_other |= STO_MIPS_PIC; | 2085 | 95 | ++eSym; | 2086 | 95 | } | 2087 | 31 | } | 2088 | 542 | } |
lld::elf::SymbolTableSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::writeTo(unsigned char*) Line | Count | Source | 2001 | 239 | template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) { | 2002 | 239 | // The first entry is a null entry as per the ELF spec. | 2003 | 239 | memset(buf, 0, sizeof(Elf_Sym)); | 2004 | 239 | buf += sizeof(Elf_Sym); | 2005 | 239 | | 2006 | 239 | auto *eSym = reinterpret_cast<Elf_Sym *>(buf); | 2007 | 239 | | 2008 | 972 | for (SymbolTableEntry &ent : symbols) { | 2009 | 972 | Symbol *sym = ent.sym; | 2010 | 972 | bool isDefinedHere = type == SHT_SYMTAB || sym->partition == partition194 ; | 2011 | 972 | | 2012 | 972 | // Set st_info and st_other. | 2013 | 972 | eSym->st_other = 0; | 2014 | 972 | if (sym->isLocal()) { | 2015 | 169 | eSym->setBindingAndType(STB_LOCAL, sym->type); | 2016 | 803 | } else { | 2017 | 803 | eSym->setBindingAndType(sym->computeBinding(), sym->type); | 2018 | 803 | eSym->setVisibility(sym->visibility); | 2019 | 803 | } | 2020 | 972 | | 2021 | 972 | // The 3 most significant bits of st_other are used by OpenPOWER ABI. | 2022 | 972 | // See getPPC64GlobalEntryToLocalEntryOffset() for more details. | 2023 | 972 | if (config->emachine == EM_PPC64) | 2024 | 0 | eSym->st_other |= sym->stOther & 0xe0; | 2025 | 972 | | 2026 | 972 | eSym->st_name = ent.strTabOffset; | 2027 | 972 | if (isDefinedHere) | 2028 | 972 | eSym->st_shndx = getSymSectionIndex(ent.sym); | 2029 | 0 | else | 2030 | 0 | eSym->st_shndx = 0; | 2031 | 972 | | 2032 | 972 | // Copy symbol size if it is a defined symbol. st_size is not significant | 2033 | 972 | // for undefined symbols, so whether copying it or not is up to us if that's | 2034 | 972 | // the case. We'll leave it as zero because by not setting a value, we can | 2035 | 972 | // get the exact same outputs for two sets of input files that differ only | 2036 | 972 | // in undefined symbol size in DSOs. | 2037 | 972 | if (eSym->st_shndx == SHN_UNDEF || !isDefinedHere872 ) | 2038 | 100 | eSym->st_size = 0; | 2039 | 872 | else | 2040 | 872 | eSym->st_size = sym->getSize(); | 2041 | 972 | | 2042 | 972 | // st_value is usually an address of a symbol, but that has a | 2043 | 972 | // special meaining for uninstantiated common symbols (this can | 2044 | 972 | // occur if -r is given). | 2045 | 972 | if (BssSection *commonSec = getCommonSec(ent.sym)) | 2046 | 0 | eSym->st_value = commonSec->alignment; | 2047 | 972 | else if (isDefinedHere) | 2048 | 972 | eSym->st_value = sym->getVA(); | 2049 | 0 | else | 2050 | 0 | eSym->st_value = 0; | 2051 | 972 | | 2052 | 972 | ++eSym; | 2053 | 972 | } | 2054 | 239 | | 2055 | 239 | // On MIPS we need to mark symbol which has a PLT entry and requires | 2056 | 239 | // pointer equality by STO_MIPS_PLT flag. That is necessary to help | 2057 | 239 | // dynamic linker distinguish such symbols and MIPS lazy-binding stubs. | 2058 | 239 | // https://sourceware.org/ml/binutils/2008-07/txt00000.txt | 2059 | 239 | if (config->emachine == EM_MIPS) { | 2060 | 192 | auto *eSym = reinterpret_cast<Elf_Sym *>(buf); | 2061 | 192 | | 2062 | 829 | for (SymbolTableEntry &ent : symbols) { | 2063 | 829 | Symbol *sym = ent.sym; | 2064 | 829 | if (sym->isInPlt() && sym->needsPltAddr26 ) | 2065 | 8 | eSym->st_other |= STO_MIPS_PLT; | 2066 | 829 | if (isMicroMips()) { | 2067 | 106 | // We already set the less-significant bit for symbols | 2068 | 106 | // marked by the `STO_MIPS_MICROMIPS` flag and for microMIPS PLT | 2069 | 106 | // records. That allows us to distinguish such symbols in | 2070 | 106 | // the `MIPS<ELFT>::relocateOne()` routine. Now we should | 2071 | 106 | // clear that bit for non-dynamic symbol table, so tools | 2072 | 106 | // like `objdump` will be able to deal with a correct | 2073 | 106 | // symbol position. | 2074 | 106 | if (sym->isDefined() && | 2075 | 106 | (98 (sym->stOther & STO_MIPS_MICROMIPS)98 || sym->needsPltAddr73 )) { | 2076 | 27 | if (!strTabSec.isDynamic()) | 2077 | 23 | eSym->st_value &= ~1; | 2078 | 27 | eSym->st_other |= STO_MIPS_MICROMIPS; | 2079 | 27 | } | 2080 | 106 | } | 2081 | 829 | if (config->relocatable) | 2082 | 66 | if (auto *d = dyn_cast<Defined>(sym)) | 2083 | 66 | if (isMipsPIC<ELFT>(d)) | 2084 | 7 | eSym->st_other |= STO_MIPS_PIC; | 2085 | 829 | ++eSym; | 2086 | 829 | } | 2087 | 192 | } | 2088 | 239 | } |
lld::elf::SymbolTableSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeTo(unsigned char*) Line | Count | Source | 2001 | 2.89k | template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) { | 2002 | 2.89k | // The first entry is a null entry as per the ELF spec. | 2003 | 2.89k | memset(buf, 0, sizeof(Elf_Sym)); | 2004 | 2.89k | buf += sizeof(Elf_Sym); | 2005 | 2.89k | | 2006 | 2.89k | auto *eSym = reinterpret_cast<Elf_Sym *>(buf); | 2007 | 2.89k | | 2008 | 73.5k | for (SymbolTableEntry &ent : symbols) { | 2009 | 73.5k | Symbol *sym = ent.sym; | 2010 | 73.5k | bool isDefinedHere = type == SHT_SYMTAB || sym->partition == partition1.49k ; | 2011 | 73.5k | | 2012 | 73.5k | // Set st_info and st_other. | 2013 | 73.5k | eSym->st_other = 0; | 2014 | 73.5k | if (sym->isLocal()) { | 2015 | 66.9k | eSym->setBindingAndType(STB_LOCAL, sym->type); | 2016 | 66.9k | } else { | 2017 | 6.58k | eSym->setBindingAndType(sym->computeBinding(), sym->type); | 2018 | 6.58k | eSym->setVisibility(sym->visibility); | 2019 | 6.58k | } | 2020 | 73.5k | | 2021 | 73.5k | // The 3 most significant bits of st_other are used by OpenPOWER ABI. | 2022 | 73.5k | // See getPPC64GlobalEntryToLocalEntryOffset() for more details. | 2023 | 73.5k | if (config->emachine == EM_PPC64) | 2024 | 496 | eSym->st_other |= sym->stOther & 0xe0; | 2025 | 73.5k | | 2026 | 73.5k | eSym->st_name = ent.strTabOffset; | 2027 | 73.5k | if (isDefinedHere) | 2028 | 73.5k | eSym->st_shndx = getSymSectionIndex(ent.sym); | 2029 | 2 | else | 2030 | 2 | eSym->st_shndx = 0; | 2031 | 73.5k | | 2032 | 73.5k | // Copy symbol size if it is a defined symbol. st_size is not significant | 2033 | 73.5k | // for undefined symbols, so whether copying it or not is up to us if that's | 2034 | 73.5k | // the case. We'll leave it as zero because by not setting a value, we can | 2035 | 73.5k | // get the exact same outputs for two sets of input files that differ only | 2036 | 73.5k | // in undefined symbol size in DSOs. | 2037 | 73.5k | if (eSym->st_shndx == SHN_UNDEF || !isDefinedHere72.6k ) | 2038 | 914 | eSym->st_size = 0; | 2039 | 72.6k | else | 2040 | 72.6k | eSym->st_size = sym->getSize(); | 2041 | 73.5k | | 2042 | 73.5k | // st_value is usually an address of a symbol, but that has a | 2043 | 73.5k | // special meaining for uninstantiated common symbols (this can | 2044 | 73.5k | // occur if -r is given). | 2045 | 73.5k | if (BssSection *commonSec = getCommonSec(ent.sym)) | 2046 | 2 | eSym->st_value = commonSec->alignment; | 2047 | 73.5k | else if (isDefinedHere) | 2048 | 73.5k | eSym->st_value = sym->getVA(); | 2049 | 2 | else | 2050 | 2 | eSym->st_value = 0; | 2051 | 73.5k | | 2052 | 73.5k | ++eSym; | 2053 | 73.5k | } | 2054 | 2.89k | | 2055 | 2.89k | // On MIPS we need to mark symbol which has a PLT entry and requires | 2056 | 2.89k | // pointer equality by STO_MIPS_PLT flag. That is necessary to help | 2057 | 2.89k | // dynamic linker distinguish such symbols and MIPS lazy-binding stubs. | 2058 | 2.89k | // https://sourceware.org/ml/binutils/2008-07/txt00000.txt | 2059 | 2.89k | if (config->emachine == EM_MIPS) { | 2060 | 3 | auto *eSym = reinterpret_cast<Elf_Sym *>(buf); | 2061 | 3 | | 2062 | 6 | for (SymbolTableEntry &ent : symbols) { | 2063 | 6 | Symbol *sym = ent.sym; | 2064 | 6 | if (sym->isInPlt() && sym->needsPltAddr0 ) | 2065 | 0 | eSym->st_other |= STO_MIPS_PLT; | 2066 | 6 | if (isMicroMips()) { | 2067 | 0 | // We already set the less-significant bit for symbols | 2068 | 0 | // marked by the `STO_MIPS_MICROMIPS` flag and for microMIPS PLT | 2069 | 0 | // records. That allows us to distinguish such symbols in | 2070 | 0 | // the `MIPS<ELFT>::relocateOne()` routine. Now we should | 2071 | 0 | // clear that bit for non-dynamic symbol table, so tools | 2072 | 0 | // like `objdump` will be able to deal with a correct | 2073 | 0 | // symbol position. | 2074 | 0 | if (sym->isDefined() && | 2075 | 0 | ((sym->stOther & STO_MIPS_MICROMIPS) || sym->needsPltAddr)) { | 2076 | 0 | if (!strTabSec.isDynamic()) | 2077 | 0 | eSym->st_value &= ~1; | 2078 | 0 | eSym->st_other |= STO_MIPS_MICROMIPS; | 2079 | 0 | } | 2080 | 0 | } | 2081 | 6 | if (config->relocatable) | 2082 | 0 | if (auto *d = dyn_cast<Defined>(sym)) | 2083 | 0 | if (isMipsPIC<ELFT>(d)) | 2084 | 0 | eSym->st_other |= STO_MIPS_PIC; | 2085 | 6 | ++eSym; | 2086 | 6 | } | 2087 | 3 | } | 2088 | 2.89k | } |
lld::elf::SymbolTableSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::writeTo(unsigned char*) Line | Count | Source | 2001 | 151 | template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) { | 2002 | 151 | // The first entry is a null entry as per the ELF spec. | 2003 | 151 | memset(buf, 0, sizeof(Elf_Sym)); | 2004 | 151 | buf += sizeof(Elf_Sym); | 2005 | 151 | | 2006 | 151 | auto *eSym = reinterpret_cast<Elf_Sym *>(buf); | 2007 | 151 | | 2008 | 10.5k | for (SymbolTableEntry &ent : symbols) { | 2009 | 10.5k | Symbol *sym = ent.sym; | 2010 | 10.5k | bool isDefinedHere = type == SHT_SYMTAB || sym->partition == partition98 ; | 2011 | 10.5k | | 2012 | 10.5k | // Set st_info and st_other. | 2013 | 10.5k | eSym->st_other = 0; | 2014 | 10.5k | if (sym->isLocal()) { | 2015 | 83 | eSym->setBindingAndType(STB_LOCAL, sym->type); | 2016 | 10.4k | } else { | 2017 | 10.4k | eSym->setBindingAndType(sym->computeBinding(), sym->type); | 2018 | 10.4k | eSym->setVisibility(sym->visibility); | 2019 | 10.4k | } | 2020 | 10.5k | | 2021 | 10.5k | // The 3 most significant bits of st_other are used by OpenPOWER ABI. | 2022 | 10.5k | // See getPPC64GlobalEntryToLocalEntryOffset() for more details. | 2023 | 10.5k | if (config->emachine == EM_PPC64) | 2024 | 318 | eSym->st_other |= sym->stOther & 0xe0; | 2025 | 10.5k | | 2026 | 10.5k | eSym->st_name = ent.strTabOffset; | 2027 | 10.5k | if (isDefinedHere) | 2028 | 10.5k | eSym->st_shndx = getSymSectionIndex(ent.sym); | 2029 | 0 | else | 2030 | 0 | eSym->st_shndx = 0; | 2031 | 10.5k | | 2032 | 10.5k | // Copy symbol size if it is a defined symbol. st_size is not significant | 2033 | 10.5k | // for undefined symbols, so whether copying it or not is up to us if that's | 2034 | 10.5k | // the case. We'll leave it as zero because by not setting a value, we can | 2035 | 10.5k | // get the exact same outputs for two sets of input files that differ only | 2036 | 10.5k | // in undefined symbol size in DSOs. | 2037 | 10.5k | if (eSym->st_shndx == SHN_UNDEF || !isDefinedHere10.4k ) | 2038 | 61 | eSym->st_size = 0; | 2039 | 10.4k | else | 2040 | 10.4k | eSym->st_size = sym->getSize(); | 2041 | 10.5k | | 2042 | 10.5k | // st_value is usually an address of a symbol, but that has a | 2043 | 10.5k | // special meaining for uninstantiated common symbols (this can | 2044 | 10.5k | // occur if -r is given). | 2045 | 10.5k | if (BssSection *commonSec = getCommonSec(ent.sym)) | 2046 | 0 | eSym->st_value = commonSec->alignment; | 2047 | 10.5k | else if (isDefinedHere) | 2048 | 10.5k | eSym->st_value = sym->getVA(); | 2049 | 0 | else | 2050 | 0 | eSym->st_value = 0; | 2051 | 10.5k | | 2052 | 10.5k | ++eSym; | 2053 | 10.5k | } | 2054 | 151 | | 2055 | 151 | // On MIPS we need to mark symbol which has a PLT entry and requires | 2056 | 151 | // pointer equality by STO_MIPS_PLT flag. That is necessary to help | 2057 | 151 | // dynamic linker distinguish such symbols and MIPS lazy-binding stubs. | 2058 | 151 | // https://sourceware.org/ml/binutils/2008-07/txt00000.txt | 2059 | 151 | if (config->emachine == EM_MIPS) { | 2060 | 61 | auto *eSym = reinterpret_cast<Elf_Sym *>(buf); | 2061 | 61 | | 2062 | 10.2k | for (SymbolTableEntry &ent : symbols) { | 2063 | 10.2k | Symbol *sym = ent.sym; | 2064 | 10.2k | if (sym->isInPlt() && sym->needsPltAddr4 ) | 2065 | 0 | eSym->st_other |= STO_MIPS_PLT; | 2066 | 10.2k | if (isMicroMips()) { | 2067 | 0 | // We already set the less-significant bit for symbols | 2068 | 0 | // marked by the `STO_MIPS_MICROMIPS` flag and for microMIPS PLT | 2069 | 0 | // records. That allows us to distinguish such symbols in | 2070 | 0 | // the `MIPS<ELFT>::relocateOne()` routine. Now we should | 2071 | 0 | // clear that bit for non-dynamic symbol table, so tools | 2072 | 0 | // like `objdump` will be able to deal with a correct | 2073 | 0 | // symbol position. | 2074 | 0 | if (sym->isDefined() && | 2075 | 0 | ((sym->stOther & STO_MIPS_MICROMIPS) || sym->needsPltAddr)) { | 2076 | 0 | if (!strTabSec.isDynamic()) | 2077 | 0 | eSym->st_value &= ~1; | 2078 | 0 | eSym->st_other |= STO_MIPS_MICROMIPS; | 2079 | 0 | } | 2080 | 0 | } | 2081 | 10.2k | if (config->relocatable) | 2082 | 11 | if (auto *d = dyn_cast<Defined>(sym)) | 2083 | 11 | if (isMipsPIC<ELFT>(d)) | 2084 | 0 | eSym->st_other |= STO_MIPS_PIC; | 2085 | 10.2k | ++eSym; | 2086 | 10.2k | } | 2087 | 61 | } | 2088 | 151 | } |
|
2089 | | |
2090 | | SymtabShndxSection::SymtabShndxSection() |
2091 | 2.74k | : SyntheticSection(0, SHT_SYMTAB_SHNDX, 4, ".symtab_shndx") { |
2092 | 2.74k | this->entsize = 4; |
2093 | 2.74k | } |
2094 | | |
2095 | 5 | void SymtabShndxSection::writeTo(uint8_t *buf) { |
2096 | 5 | // We write an array of 32 bit values, where each value has 1:1 association |
2097 | 5 | // with an entry in .symtab. If the corresponding entry contains SHN_XINDEX, |
2098 | 5 | // we need to write actual index, otherwise, we must write SHN_UNDEF(0). |
2099 | 5 | buf += 4; // Ignore .symtab[0] entry. |
2100 | 65.5k | for (const SymbolTableEntry &entry : in.symTab->getSymbols()) { |
2101 | 65.5k | if (getSymSectionIndex(entry.sym) == SHN_XINDEX) |
2102 | 261 | write32(buf, entry.sym->getOutputSection()->sectionIndex); |
2103 | 65.5k | buf += 4; |
2104 | 65.5k | } |
2105 | 5 | } |
2106 | | |
2107 | 5.21k | bool SymtabShndxSection::isNeeded() const { |
2108 | 5.21k | // SHT_SYMTAB can hold symbols with section indices values up to |
2109 | 5.21k | // SHN_LORESERVE. If we need more, we want to use extension SHT_SYMTAB_SHNDX |
2110 | 5.21k | // section. Problem is that we reveal the final section indices a bit too |
2111 | 5.21k | // late, and we do not know them here. For simplicity, we just always create |
2112 | 5.21k | // a .symtab_shndx section when the amount of output sections is huge. |
2113 | 5.21k | size_t size = 0; |
2114 | 5.21k | for (BaseCommand *base : script->sectionCommands) |
2115 | 729k | if (isa<OutputSection>(base)) |
2116 | 728k | ++size; |
2117 | 5.21k | return size >= SHN_LORESERVE; |
2118 | 5.21k | } |
2119 | | |
2120 | 5 | void SymtabShndxSection::finalizeContents() { |
2121 | 5 | getParent()->link = in.symTab->getParent()->sectionIndex; |
2122 | 5 | } |
2123 | | |
2124 | 22 | size_t SymtabShndxSection::getSize() const { |
2125 | 22 | return in.symTab->getNumSymbols() * 4; |
2126 | 22 | } |
2127 | | |
2128 | | // .hash and .gnu.hash sections contain on-disk hash tables that map |
2129 | | // symbol names to their dynamic symbol table indices. Their purpose |
2130 | | // is to help the dynamic linker resolve symbols quickly. If ELF files |
2131 | | // don't have them, the dynamic linker has to do linear search on all |
2132 | | // dynamic symbols, which makes programs slower. Therefore, a .hash |
2133 | | // section is added to a DSO by default. A .gnu.hash is added if you |
2134 | | // give the -hash-style=gnu or -hash-style=both option. |
2135 | | // |
2136 | | // The Unix semantics of resolving dynamic symbols is somewhat expensive. |
2137 | | // Each ELF file has a list of DSOs that the ELF file depends on and a |
2138 | | // list of dynamic symbols that need to be resolved from any of the |
2139 | | // DSOs. That means resolving all dynamic symbols takes O(m)*O(n) |
2140 | | // where m is the number of DSOs and n is the number of dynamic |
2141 | | // symbols. For modern large programs, both m and n are large. So |
2142 | | // making each step faster by using hash tables substiantially |
2143 | | // improves time to load programs. |
2144 | | // |
2145 | | // (Note that this is not the only way to design the shared library. |
2146 | | // For instance, the Windows DLL takes a different approach. On |
2147 | | // Windows, each dynamic symbol has a name of DLL from which the symbol |
2148 | | // has to be resolved. That makes the cost of symbol resolution O(n). |
2149 | | // This disables some hacky techniques you can use on Unix such as |
2150 | | // LD_PRELOAD, but this is arguably better semantics than the Unix ones.) |
2151 | | // |
2152 | | // Due to historical reasons, we have two different hash tables, .hash |
2153 | | // and .gnu.hash. They are for the same purpose, and .gnu.hash is a new |
2154 | | // and better version of .hash. .hash is just an on-disk hash table, but |
2155 | | // .gnu.hash has a bloom filter in addition to a hash table to skip |
2156 | | // DSOs very quickly. If you are sure that your dynamic linker knows |
2157 | | // about .gnu.hash, you want to specify -hash-style=gnu. Otherwise, a |
2158 | | // safe bet is to specify -hash-style=both for backward compatibilty. |
2159 | | GnuHashTableSection::GnuHashTableSection() |
2160 | 1.11k | : SyntheticSection(SHF_ALLOC, SHT_GNU_HASH, config->wordsize, ".gnu.hash") { |
2161 | 1.11k | } |
2162 | | |
2163 | 1.02k | void GnuHashTableSection::finalizeContents() { |
2164 | 1.02k | if (OutputSection *sec = getPartition().dynSymTab->getParent()) |
2165 | 1.02k | getParent()->link = sec->sectionIndex; |
2166 | 1.02k | |
2167 | 1.02k | // Computes bloom filter size in word size. We want to allocate 12 |
2168 | 1.02k | // bits for each symbol. It must be a power of two. |
2169 | 1.02k | if (symbols.empty()) { |
2170 | 374 | maskWords = 1; |
2171 | 655 | } else { |
2172 | 655 | uint64_t numBits = symbols.size() * 12; |
2173 | 655 | maskWords = NextPowerOf2(numBits / (config->wordsize * 8)); |
2174 | 655 | } |
2175 | 1.02k | |
2176 | 1.02k | size = 16; // Header |
2177 | 1.02k | size += config->wordsize * maskWords; // Bloom filter |
2178 | 1.02k | size += nBuckets * 4; // Hash buckets |
2179 | 1.02k | size += symbols.size() * 4; // Hash values |
2180 | 1.02k | } |
2181 | | |
2182 | 1.02k | void GnuHashTableSection::writeTo(uint8_t *buf) { |
2183 | 1.02k | // The output buffer is not guaranteed to be zero-cleared because we pre- |
2184 | 1.02k | // fill executable sections with trap instructions. This is a precaution |
2185 | 1.02k | // for that case, which happens only when -no-rosegment is given. |
2186 | 1.02k | memset(buf, 0, size); |
2187 | 1.02k | |
2188 | 1.02k | // Write a header. |
2189 | 1.02k | write32(buf, nBuckets); |
2190 | 1.02k | write32(buf + 4, getPartition().dynSymTab->getNumSymbols() - symbols.size()); |
2191 | 1.02k | write32(buf + 8, maskWords); |
2192 | 1.02k | write32(buf + 12, Shift2); |
2193 | 1.02k | buf += 16; |
2194 | 1.02k | |
2195 | 1.02k | // Write a bloom filter and a hash table. |
2196 | 1.02k | writeBloomFilter(buf); |
2197 | 1.02k | buf += config->wordsize * maskWords; |
2198 | 1.02k | writeHashTable(buf); |
2199 | 1.02k | } |
2200 | | |
2201 | | // This function writes a 2-bit bloom filter. This bloom filter alone |
2202 | | // usually filters out 80% or more of all symbol lookups [1]. |
2203 | | // The dynamic linker uses the hash table only when a symbol is not |
2204 | | // filtered out by a bloom filter. |
2205 | | // |
2206 | | // [1] Ulrich Drepper (2011), "How To Write Shared Libraries" (Ver. 4.1.2), |
2207 | | // p.9, https://www.akkadia.org/drepper/dsohowto.pdf |
2208 | 1.02k | void GnuHashTableSection::writeBloomFilter(uint8_t *buf) { |
2209 | 1.02k | unsigned c = config->is64 ? 64871 : 32149 ; |
2210 | 1.23k | for (const Entry &sym : symbols) { |
2211 | 1.23k | // When C = 64, we choose a word with bits [6:...] and set 1 to two bits in |
2212 | 1.23k | // the word using bits [0:5] and [26:31]. |
2213 | 1.23k | size_t i = (sym.hash / c) & (maskWords - 1); |
2214 | 1.23k | uint64_t val = readUint(buf + i * config->wordsize); |
2215 | 1.23k | val |= uint64_t(1) << (sym.hash % c); |
2216 | 1.23k | val |= uint64_t(1) << ((sym.hash >> Shift2) % c); |
2217 | 1.23k | writeUint(buf + i * config->wordsize, val); |
2218 | 1.23k | } |
2219 | 1.02k | } |
2220 | | |
2221 | 1.02k | void GnuHashTableSection::writeHashTable(uint8_t *buf) { |
2222 | 1.02k | uint32_t *buckets = reinterpret_cast<uint32_t *>(buf); |
2223 | 1.02k | uint32_t oldBucket = -1; |
2224 | 1.02k | uint32_t *values = buckets + nBuckets; |
2225 | 2.25k | for (auto i = symbols.begin(), e = symbols.end(); i != e; ++i1.23k ) { |
2226 | 1.23k | // Write a hash value. It represents a sequence of chains that share the |
2227 | 1.23k | // same hash modulo value. The last element of each chain is terminated by |
2228 | 1.23k | // LSB 1. |
2229 | 1.23k | uint32_t hash = i->hash; |
2230 | 1.23k | bool isLastInChain = (i + 1) == e || i->bucketIdx != (i + 1)->bucketIdx587 ; |
2231 | 1.23k | hash = isLastInChain ? hash | 1663 : hash & ~1573 ; |
2232 | 1.23k | write32(values++, hash); |
2233 | 1.23k | |
2234 | 1.23k | if (i->bucketIdx == oldBucket) |
2235 | 573 | continue; |
2236 | 663 | // Write a hash bucket. Hash buckets contain indices in the following hash |
2237 | 663 | // value table. |
2238 | 663 | write32(buckets + i->bucketIdx, |
2239 | 663 | getPartition().dynSymTab->getSymbolIndex(i->sym)); |
2240 | 663 | oldBucket = i->bucketIdx; |
2241 | 663 | } |
2242 | 1.02k | } |
2243 | | |
2244 | 1.25k | static uint32_t hashGnu(StringRef name) { |
2245 | 1.25k | uint32_t h = 5381; |
2246 | 1.25k | for (uint8_t c : name) |
2247 | 5.98k | h = (h << 5) + h + c; |
2248 | 1.25k | return h; |
2249 | 1.25k | } |
2250 | | |
2251 | | // Add symbols to this symbol hash table. Note that this function |
2252 | | // destructively sort a given vector -- which is needed because |
2253 | | // GNU-style hash table places some sorting requirements. |
2254 | 1.02k | void GnuHashTableSection::addSymbols(std::vector<SymbolTableEntry> &v) { |
2255 | 1.02k | // We cannot use 'auto' for Mid because GCC 6.1 cannot deduce |
2256 | 1.02k | // its type correctly. |
2257 | 1.02k | std::vector<SymbolTableEntry>::iterator mid = |
2258 | 1.65k | std::stable_partition(v.begin(), v.end(), [&](const SymbolTableEntry &s) { |
2259 | 1.65k | return !s.sym->isDefined() || s.sym->partition != partition1.25k ; |
2260 | 1.65k | }); |
2261 | 1.02k | |
2262 | 1.02k | // We chose load factor 4 for the on-disk hash table. For each hash |
2263 | 1.02k | // collision, the dynamic linker will compare a uint32_t hash value. |
2264 | 1.02k | // Since the integer comparison is quite fast, we believe we can |
2265 | 1.02k | // make the load factor even larger. 4 is just a conservative choice. |
2266 | 1.02k | // |
2267 | 1.02k | // Note that we don't want to create a zero-sized hash table because |
2268 | 1.02k | // Android loader as of 2018 doesn't like a .gnu.hash containing such |
2269 | 1.02k | // table. If that's the case, we create a hash table with one unused |
2270 | 1.02k | // dummy slot. |
2271 | 1.02k | nBuckets = std::max<size_t>((v.end() - mid) / 4, 1); |
2272 | 1.02k | |
2273 | 1.02k | if (mid == v.end()) |
2274 | 373 | return; |
2275 | 655 | |
2276 | 1.25k | for (SymbolTableEntry &ent : llvm::make_range(mid, v.end()))655 { |
2277 | 1.25k | Symbol *b = ent.sym; |
2278 | 1.25k | uint32_t hash = hashGnu(b->getName()); |
2279 | 1.25k | uint32_t bucketIdx = hash % nBuckets; |
2280 | 1.25k | symbols.push_back({b, ent.strTabOffset, hash, bucketIdx}); |
2281 | 1.25k | } |
2282 | 655 | |
2283 | 930 | llvm::stable_sort(symbols, [](const Entry &l, const Entry &r) { |
2284 | 930 | return l.bucketIdx < r.bucketIdx; |
2285 | 930 | }); |
2286 | 655 | |
2287 | 655 | v.erase(mid, v.end()); |
2288 | 655 | for (const Entry &ent : symbols) |
2289 | 1.25k | v.push_back({ent.sym, ent.strTabOffset}); |
2290 | 655 | } |
2291 | | |
2292 | | HashTableSection::HashTableSection() |
2293 | 1.34k | : SyntheticSection(SHF_ALLOC, SHT_HASH, 4, ".hash") { |
2294 | 1.34k | this->entsize = 4; |
2295 | 1.34k | } |
2296 | | |
2297 | 1.25k | void HashTableSection::finalizeContents() { |
2298 | 1.25k | SymbolTableBaseSection *symTab = getPartition().dynSymTab; |
2299 | 1.25k | |
2300 | 1.25k | if (OutputSection *sec = symTab->getParent()) |
2301 | 1.25k | getParent()->link = sec->sectionIndex; |
2302 | 1.25k | |
2303 | 1.25k | unsigned numEntries = 2; // nbucket and nchain. |
2304 | 1.25k | numEntries += symTab->getNumSymbols(); // The chain entries. |
2305 | 1.25k | |
2306 | 1.25k | // Create as many buckets as there are symbols. |
2307 | 1.25k | numEntries += symTab->getNumSymbols(); |
2308 | 1.25k | this->size = numEntries * 4; |
2309 | 1.25k | } |
2310 | | |
2311 | 1.24k | void HashTableSection::writeTo(uint8_t *buf) { |
2312 | 1.24k | SymbolTableBaseSection *symTab = getPartition().dynSymTab; |
2313 | 1.24k | |
2314 | 1.24k | // See comment in GnuHashTableSection::writeTo. |
2315 | 1.24k | memset(buf, 0, size); |
2316 | 1.24k | |
2317 | 1.24k | unsigned numSymbols = symTab->getNumSymbols(); |
2318 | 1.24k | |
2319 | 1.24k | uint32_t *p = reinterpret_cast<uint32_t *>(buf); |
2320 | 1.24k | write32(p++, numSymbols); // nbucket |
2321 | 1.24k | write32(p++, numSymbols); // nchain |
2322 | 1.24k | |
2323 | 1.24k | uint32_t *buckets = p; |
2324 | 1.24k | uint32_t *chains = p + numSymbols; |
2325 | 1.24k | |
2326 | 2.10k | for (const SymbolTableEntry &s : symTab->getSymbols()) { |
2327 | 2.10k | Symbol *sym = s.sym; |
2328 | 2.10k | StringRef name = sym->getName(); |
2329 | 2.10k | unsigned i = sym->dynsymIndex; |
2330 | 2.10k | uint32_t hash = hashSysV(name) % numSymbols; |
2331 | 2.10k | chains[i] = buckets[hash]; |
2332 | 2.10k | write32(buckets + hash, i); |
2333 | 2.10k | } |
2334 | 1.24k | } |
2335 | | |
2336 | | // On PowerPC64 the lazy symbol resolvers go into the `global linkage table` |
2337 | | // in the .glink section, rather then the typical .plt section. |
2338 | | PltSection::PltSection(bool isIplt) |
2339 | | : SyntheticSection( |
2340 | | SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, |
2341 | | (config->emachine == EM_PPC || config->emachine == EM_PPC64) |
2342 | | ? ".glink" |
2343 | | : ".plt"), |
2344 | | headerSize(!isIplt || config->zRetpolineplt ? target->pltHeaderSize : 0), |
2345 | 5.50k | isIplt(isIplt) { |
2346 | 5.50k | // The PLT needs to be writable on SPARC as the dynamic linker will |
2347 | 5.50k | // modify the instructions in the PLT entries. |
2348 | 5.50k | if (config->emachine == EM_SPARCV9) |
2349 | 2 | this->flags |= SHF_WRITE; |
2350 | 5.50k | } |
2351 | | |
2352 | 305 | void PltSection::writeTo(uint8_t *buf) { |
2353 | 305 | if (config->emachine == EM_PPC) { |
2354 | 8 | writePPC32GlinkSection(buf, entries.size()); |
2355 | 8 | return; |
2356 | 8 | } |
2357 | 297 | |
2358 | 297 | // At beginning of PLT or retpoline IPLT, we have code to call the dynamic |
2359 | 297 | // linker to resolve dynsyms at runtime. Write such code. |
2360 | 297 | if (headerSize) |
2361 | 255 | target->writePltHeader(buf); |
2362 | 297 | size_t off = headerSize; |
2363 | 297 | |
2364 | 297 | RelocationBaseSection *relSec = isIplt ? in.relaIplt44 : in.relaPlt253 ; |
2365 | 297 | |
2366 | 297 | // The IPlt is immediately after the Plt, account for this in relOff |
2367 | 297 | size_t pltOff = isIplt ? in.plt->getSize()44 : 0253 ; |
2368 | 297 | |
2369 | 701 | for (size_t i = 0, e = entries.size(); i != e; ++i404 ) { |
2370 | 404 | const Symbol *b = entries[i]; |
2371 | 404 | unsigned relOff = relSec->entsize * i + pltOff; |
2372 | 404 | uint64_t got = b->getGotPltVA(); |
2373 | 404 | uint64_t plt = this->getVA() + off; |
2374 | 404 | target->writePlt(buf + off, got, plt, b->pltIndex, relOff); |
2375 | 404 | off += target->pltEntrySize; |
2376 | 404 | } |
2377 | 297 | } |
2378 | | |
2379 | 421 | template <class ELFT> void PltSection::addEntry(Symbol &sym) { |
2380 | 421 | sym.pltIndex = entries.size(); |
2381 | 421 | entries.push_back(&sym); |
2382 | 421 | } void lld::elf::PltSection::addEntry<llvm::object::ELFType<(llvm::support::endianness)1, false> >(lld::elf::Symbol&) Line | Count | Source | 2379 | 92 | template <class ELFT> void PltSection::addEntry(Symbol &sym) { | 2380 | 92 | sym.pltIndex = entries.size(); | 2381 | 92 | entries.push_back(&sym); | 2382 | 92 | } |
void lld::elf::PltSection::addEntry<llvm::object::ELFType<(llvm::support::endianness)0, false> >(lld::elf::Symbol&) Line | Count | Source | 2379 | 26 | template <class ELFT> void PltSection::addEntry(Symbol &sym) { | 2380 | 26 | sym.pltIndex = entries.size(); | 2381 | 26 | entries.push_back(&sym); | 2382 | 26 | } |
void lld::elf::PltSection::addEntry<llvm::object::ELFType<(llvm::support::endianness)1, true> >(lld::elf::Symbol&) Line | Count | Source | 2379 | 289 | template <class ELFT> void PltSection::addEntry(Symbol &sym) { | 2380 | 289 | sym.pltIndex = entries.size(); | 2381 | 289 | entries.push_back(&sym); | 2382 | 289 | } |
void lld::elf::PltSection::addEntry<llvm::object::ELFType<(llvm::support::endianness)0, true> >(lld::elf::Symbol&) Line | Count | Source | 2379 | 14 | template <class ELFT> void PltSection::addEntry(Symbol &sym) { | 2380 | 14 | sym.pltIndex = entries.size(); | 2381 | 14 | entries.push_back(&sym); | 2382 | 14 | } |
|
2383 | | |
2384 | 1.79k | size_t PltSection::getSize() const { |
2385 | 1.79k | return headerSize + entries.size() * target->pltEntrySize; |
2386 | 1.79k | } |
2387 | | |
2388 | | // Some architectures such as additional symbols in the PLT section. For |
2389 | | // example ARM uses mapping symbols to aid disassembly |
2390 | 309 | void PltSection::addSymbols() { |
2391 | 309 | // The PLT may have symbols defined for the Header, the IPLT has no header |
2392 | 309 | if (!isIplt) |
2393 | 263 | target->addPltHeaderSymbols(*this); |
2394 | 309 | |
2395 | 309 | size_t off = headerSize; |
2396 | 730 | for (size_t i = 0; i < entries.size(); ++i421 ) { |
2397 | 421 | target->addPltSymbols(*this, off); |
2398 | 421 | off += target->pltEntrySize; |
2399 | 421 | } |
2400 | 309 | } |
2401 | | |
2402 | | // The string hash function for .gdb_index. |
2403 | 13 | static uint32_t computeGdbHash(StringRef s) { |
2404 | 13 | uint32_t h = 0; |
2405 | 13 | for (uint8_t c : s) |
2406 | 85 | h = h * 67 + toLower(c) - 113; |
2407 | 13 | return h; |
2408 | 13 | } |
2409 | | |
2410 | | GdbIndexSection::GdbIndexSection() |
2411 | 19 | : SyntheticSection(0, SHT_PROGBITS, 1, ".gdb_index") {} |
2412 | | |
2413 | | // Returns the desired size of an on-disk hash table for a .gdb_index section. |
2414 | | // There's a tradeoff between size and collision rate. We aim 75% utilization. |
2415 | 34 | size_t GdbIndexSection::computeSymtabSize() const { |
2416 | 34 | return std::max<size_t>(NextPowerOf2(symbols.size() * 4 / 3), 1024); |
2417 | 34 | } |
2418 | | |
2419 | | // Compute the output section size. |
2420 | 19 | void GdbIndexSection::initOutputSize() { |
2421 | 19 | size = sizeof(GdbIndexHeader) + computeSymtabSize() * 8; |
2422 | 19 | |
2423 | 19 | for (GdbChunk &chunk : chunks) |
2424 | 21 | size += chunk.compilationUnits.size() * 16 + chunk.addressAreas.size() * 20; |
2425 | 19 | |
2426 | 19 | // Add the constant pool size if exists. |
2427 | 19 | if (!symbols.empty()) { |
2428 | 5 | GdbSymbol &sym = symbols.back(); |
2429 | 5 | size += sym.nameOff + sym.name.size() + 1; |
2430 | 5 | } |
2431 | 19 | } |
2432 | | |
2433 | 19 | static std::vector<InputSection *> getDebugInfoSections() { |
2434 | 19 | std::vector<InputSection *> ret; |
2435 | 19 | for (InputSectionBase *s : inputSections) |
2436 | 251 | if (InputSection *isec = dyn_cast<InputSection>(s)) |
2437 | 250 | if (isec->name == ".debug_info") |
2438 | 21 | ret.push_back(isec); |
2439 | 19 | return ret; |
2440 | 19 | } |
2441 | | |
2442 | 21 | static std::vector<GdbIndexSection::CuEntry> readCuList(DWARFContext &dwarf) { |
2443 | 21 | std::vector<GdbIndexSection::CuEntry> ret; |
2444 | 21 | for (std::unique_ptr<DWARFUnit> &cu : dwarf.compile_units()) |
2445 | 22 | ret.push_back({cu->getOffset(), cu->getLength() + 4}); |
2446 | 21 | return ret; |
2447 | 21 | } |
2448 | | |
2449 | | static std::vector<GdbIndexSection::AddressEntry> |
2450 | 21 | readAddressAreas(DWARFContext &dwarf, InputSection *sec) { |
2451 | 21 | std::vector<GdbIndexSection::AddressEntry> ret; |
2452 | 21 | |
2453 | 21 | uint32_t cuIdx = 0; |
2454 | 22 | for (std::unique_ptr<DWARFUnit> &cu : dwarf.compile_units()) { |
2455 | 22 | Expected<DWARFAddressRangesVector> ranges = cu->collectAddressRanges(); |
2456 | 22 | if (!ranges) { |
2457 | 2 | error(toString(sec) + ": " + toString(ranges.takeError())); |
2458 | 2 | return {}; |
2459 | 2 | } |
2460 | 20 | |
2461 | 20 | ArrayRef<InputSectionBase *> sections = sec->file->getSections(); |
2462 | 20 | for (DWARFAddressRange &r : *ranges) { |
2463 | 18 | if (r.SectionIndex == -1ULL) |
2464 | 0 | continue; |
2465 | 18 | InputSectionBase *s = sections[r.SectionIndex]; |
2466 | 18 | if (!s || s == &InputSection::discarded || !s->isLive()16 ) |
2467 | 3 | continue; |
2468 | 15 | // Range list with zero size has no effect. |
2469 | 15 | if (r.LowPC == r.HighPC) |
2470 | 2 | continue; |
2471 | 13 | auto *isec = cast<InputSection>(s); |
2472 | 13 | uint64_t offset = isec->getOffsetInFile(); |
2473 | 13 | ret.push_back({isec, r.LowPC - offset, r.HighPC - offset, cuIdx}); |
2474 | 13 | } |
2475 | 20 | ++cuIdx; |
2476 | 20 | } |
2477 | 21 | |
2478 | 21 | return ret19 ; |
2479 | 21 | } |
2480 | | |
2481 | | template <class ELFT> |
2482 | | static std::vector<GdbIndexSection::NameAttrEntry> |
2483 | | readPubNamesAndTypes(const LLDDwarfObj<ELFT> &obj, |
2484 | 21 | const std::vector<GdbIndexSection::CuEntry> &cUs) { |
2485 | 21 | const DWARFSection &pubNames = obj.getGnuPubNamesSection(); |
2486 | 21 | const DWARFSection &pubTypes = obj.getGnuPubTypesSection(); |
2487 | 21 | |
2488 | 21 | std::vector<GdbIndexSection::NameAttrEntry> ret; |
2489 | 42 | for (const DWARFSection *pub : {&pubNames, &pubTypes}) { |
2490 | 42 | DWARFDebugPubTable table(obj, *pub, config->isLE, true); |
2491 | 42 | for (const DWARFDebugPubTable::Set &set : table.getData()) { |
2492 | 12 | // The value written into the constant pool is kind << 24 | cuIndex. As we |
2493 | 12 | // don't know how many compilation units precede this object to compute |
2494 | 12 | // cuIndex, we compute (kind << 24 | cuIndexInThisObject) instead, and add |
2495 | 12 | // the number of preceding compilation units later. |
2496 | 12 | uint32_t i = |
2497 | 12 | lower_bound(cUs, set.Offset, |
2498 | 15 | [](GdbIndexSection::CuEntry cu, uint32_t offset) { |
2499 | 15 | return cu.cuOffset < offset; |
2500 | 15 | }) - Unexecuted instantiation: SyntheticSections.cpp:std::__1::vector<lld::elf::GdbIndexSection::NameAttrEntry, std::__1::allocator<lld::elf::GdbIndexSection::NameAttrEntry> > readPubNamesAndTypes<llvm::object::ELFType<(llvm::support::endianness)1, false> >(lld::elf::LLDDwarfObj<llvm::object::ELFType<(llvm::support::endianness)1, false> > const&, std::__1::vector<lld::elf::GdbIndexSection::CuEntry, std::__1::allocator<lld::elf::GdbIndexSection::CuEntry> > const&)::'lambda'(lld::elf::GdbIndexSection::CuEntry, unsigned int)::operator()(lld::elf::GdbIndexSection::CuEntry, unsigned int) const Unexecuted instantiation: SyntheticSections.cpp:std::__1::vector<lld::elf::GdbIndexSection::NameAttrEntry, std::__1::allocator<lld::elf::GdbIndexSection::NameAttrEntry> > readPubNamesAndTypes<llvm::object::ELFType<(llvm::support::endianness)0, false> >(lld::elf::LLDDwarfObj<llvm::object::ELFType<(llvm::support::endianness)0, false> > const&, std::__1::vector<lld::elf::GdbIndexSection::CuEntry, std::__1::allocator<lld::elf::GdbIndexSection::CuEntry> > const&)::'lambda'(lld::elf::GdbIndexSection::CuEntry, unsigned int)::operator()(lld::elf::GdbIndexSection::CuEntry, unsigned int) const SyntheticSections.cpp:std::__1::vector<lld::elf::GdbIndexSection::NameAttrEntry, std::__1::allocator<lld::elf::GdbIndexSection::NameAttrEntry> > readPubNamesAndTypes<llvm::object::ELFType<(llvm::support::endianness)1, true> >(lld::elf::LLDDwarfObj<llvm::object::ELFType<(llvm::support::endianness)1, true> > const&, std::__1::vector<lld::elf::GdbIndexSection::CuEntry, std::__1::allocator<lld::elf::GdbIndexSection::CuEntry> > const&)::'lambda'(lld::elf::GdbIndexSection::CuEntry, unsigned int)::operator()(lld::elf::GdbIndexSection::CuEntry, unsigned int) const Line | Count | Source | 2498 | 15 | [](GdbIndexSection::CuEntry cu, uint32_t offset) { | 2499 | 15 | return cu.cuOffset < offset; | 2500 | 15 | }) - |
Unexecuted instantiation: SyntheticSections.cpp:std::__1::vector<lld::elf::GdbIndexSection::NameAttrEntry, std::__1::allocator<lld::elf::GdbIndexSection::NameAttrEntry> > readPubNamesAndTypes<llvm::object::ELFType<(llvm::support::endianness)0, true> >(lld::elf::LLDDwarfObj<llvm::object::ELFType<(llvm::support::endianness)0, true> > const&, std::__1::vector<lld::elf::GdbIndexSection::CuEntry, std::__1::allocator<lld::elf::GdbIndexSection::CuEntry> > const&)::'lambda'(lld::elf::GdbIndexSection::CuEntry, unsigned int)::operator()(lld::elf::GdbIndexSection::CuEntry, unsigned int) const |
2501 | 12 | cUs.begin(); |
2502 | 12 | for (const DWARFDebugPubTable::Entry &ent : set.Entries) |
2503 | 13 | ret.push_back({{ent.Name, computeGdbHash(ent.Name)}, |
2504 | 13 | (ent.Descriptor.toBits() << 24) | i}); |
2505 | 12 | } |
2506 | 42 | } |
2507 | 21 | return ret; |
2508 | 21 | } SyntheticSections.cpp:std::__1::vector<lld::elf::GdbIndexSection::NameAttrEntry, std::__1::allocator<lld::elf::GdbIndexSection::NameAttrEntry> > readPubNamesAndTypes<llvm::object::ELFType<(llvm::support::endianness)1, false> >(lld::elf::LLDDwarfObj<llvm::object::ELFType<(llvm::support::endianness)1, false> > const&, std::__1::vector<lld::elf::GdbIndexSection::CuEntry, std::__1::allocator<lld::elf::GdbIndexSection::CuEntry> > const&) Line | Count | Source | 2484 | 1 | const std::vector<GdbIndexSection::CuEntry> &cUs) { | 2485 | 1 | const DWARFSection &pubNames = obj.getGnuPubNamesSection(); | 2486 | 1 | const DWARFSection &pubTypes = obj.getGnuPubTypesSection(); | 2487 | 1 | | 2488 | 1 | std::vector<GdbIndexSection::NameAttrEntry> ret; | 2489 | 2 | for (const DWARFSection *pub : {&pubNames, &pubTypes}) { | 2490 | 2 | DWARFDebugPubTable table(obj, *pub, config->isLE, true); | 2491 | 2 | for (const DWARFDebugPubTable::Set &set : table.getData()) { | 2492 | 0 | // The value written into the constant pool is kind << 24 | cuIndex. As we | 2493 | 0 | // don't know how many compilation units precede this object to compute | 2494 | 0 | // cuIndex, we compute (kind << 24 | cuIndexInThisObject) instead, and add | 2495 | 0 | // the number of preceding compilation units later. | 2496 | 0 | uint32_t i = | 2497 | 0 | lower_bound(cUs, set.Offset, | 2498 | 0 | [](GdbIndexSection::CuEntry cu, uint32_t offset) { | 2499 | 0 | return cu.cuOffset < offset; | 2500 | 0 | }) - | 2501 | 0 | cUs.begin(); | 2502 | 0 | for (const DWARFDebugPubTable::Entry &ent : set.Entries) | 2503 | 0 | ret.push_back({{ent.Name, computeGdbHash(ent.Name)}, | 2504 | 0 | (ent.Descriptor.toBits() << 24) | i}); | 2505 | 0 | } | 2506 | 2 | } | 2507 | 1 | return ret; | 2508 | 1 | } |
Unexecuted instantiation: SyntheticSections.cpp:std::__1::vector<lld::elf::GdbIndexSection::NameAttrEntry, std::__1::allocator<lld::elf::GdbIndexSection::NameAttrEntry> > readPubNamesAndTypes<llvm::object::ELFType<(llvm::support::endianness)0, false> >(lld::elf::LLDDwarfObj<llvm::object::ELFType<(llvm::support::endianness)0, false> > const&, std::__1::vector<lld::elf::GdbIndexSection::CuEntry, std::__1::allocator<lld::elf::GdbIndexSection::CuEntry> > const&) SyntheticSections.cpp:std::__1::vector<lld::elf::GdbIndexSection::NameAttrEntry, std::__1::allocator<lld::elf::GdbIndexSection::NameAttrEntry> > readPubNamesAndTypes<llvm::object::ELFType<(llvm::support::endianness)1, true> >(lld::elf::LLDDwarfObj<llvm::object::ELFType<(llvm::support::endianness)1, true> > const&, std::__1::vector<lld::elf::GdbIndexSection::CuEntry, std::__1::allocator<lld::elf::GdbIndexSection::CuEntry> > const&) Line | Count | Source | 2484 | 20 | const std::vector<GdbIndexSection::CuEntry> &cUs) { | 2485 | 20 | const DWARFSection &pubNames = obj.getGnuPubNamesSection(); | 2486 | 20 | const DWARFSection &pubTypes = obj.getGnuPubTypesSection(); | 2487 | 20 | | 2488 | 20 | std::vector<GdbIndexSection::NameAttrEntry> ret; | 2489 | 40 | for (const DWARFSection *pub : {&pubNames, &pubTypes}) { | 2490 | 40 | DWARFDebugPubTable table(obj, *pub, config->isLE, true); | 2491 | 40 | for (const DWARFDebugPubTable::Set &set : table.getData()) { | 2492 | 12 | // The value written into the constant pool is kind << 24 | cuIndex. As we | 2493 | 12 | // don't know how many compilation units precede this object to compute | 2494 | 12 | // cuIndex, we compute (kind << 24 | cuIndexInThisObject) instead, and add | 2495 | 12 | // the number of preceding compilation units later. | 2496 | 12 | uint32_t i = | 2497 | 12 | lower_bound(cUs, set.Offset, | 2498 | 12 | [](GdbIndexSection::CuEntry cu, uint32_t offset) { | 2499 | 12 | return cu.cuOffset < offset; | 2500 | 12 | }) - | 2501 | 12 | cUs.begin(); | 2502 | 12 | for (const DWARFDebugPubTable::Entry &ent : set.Entries) | 2503 | 13 | ret.push_back({{ent.Name, computeGdbHash(ent.Name)}, | 2504 | 13 | (ent.Descriptor.toBits() << 24) | i}); | 2505 | 12 | } | 2506 | 40 | } | 2507 | 20 | return ret; | 2508 | 20 | } |
Unexecuted instantiation: SyntheticSections.cpp:std::__1::vector<lld::elf::GdbIndexSection::NameAttrEntry, std::__1::allocator<lld::elf::GdbIndexSection::NameAttrEntry> > readPubNamesAndTypes<llvm::object::ELFType<(llvm::support::endianness)0, true> >(lld::elf::LLDDwarfObj<llvm::object::ELFType<(llvm::support::endianness)0, true> > const&, std::__1::vector<lld::elf::GdbIndexSection::CuEntry, std::__1::allocator<lld::elf::GdbIndexSection::CuEntry> > const&) |
2509 | | |
2510 | | // Create a list of symbols from a given list of symbol names and types |
2511 | | // by uniquifying them by name. |
2512 | | static std::vector<GdbIndexSection::GdbSymbol> |
2513 | | createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> nameAttrs, |
2514 | 19 | const std::vector<GdbIndexSection::GdbChunk> &chunks) { |
2515 | 19 | using GdbSymbol = GdbIndexSection::GdbSymbol; |
2516 | 19 | using NameAttrEntry = GdbIndexSection::NameAttrEntry; |
2517 | 19 | |
2518 | 19 | // For each chunk, compute the number of compilation units preceding it. |
2519 | 19 | uint32_t cuIdx = 0; |
2520 | 19 | std::vector<uint32_t> cuIdxs(chunks.size()); |
2521 | 40 | for (uint32_t i = 0, e = chunks.size(); i != e; ++i21 ) { |
2522 | 21 | cuIdxs[i] = cuIdx; |
2523 | 21 | cuIdx += chunks[i].compilationUnits.size(); |
2524 | 21 | } |
2525 | 19 | |
2526 | 19 | // The number of symbols we will handle in this function is of the order |
2527 | 19 | // of millions for very large executables, so we use multi-threading to |
2528 | 19 | // speed it up. |
2529 | 19 | size_t numShards = 32; |
2530 | 19 | size_t concurrency = 1; |
2531 | 19 | if (threadsEnabled) |
2532 | 19 | concurrency = |
2533 | 19 | std::min<size_t>(PowerOf2Floor(hardware_concurrency()), numShards); |
2534 | 19 | |
2535 | 19 | // A sharded map to uniquify symbols by name. |
2536 | 19 | std::vector<DenseMap<CachedHashStringRef, size_t>> map(numShards); |
2537 | 19 | size_t shift = 32 - countTrailingZeros(numShards); |
2538 | 19 | |
2539 | 19 | // Instantiate GdbSymbols while uniqufying them by name. |
2540 | 19 | std::vector<std::vector<GdbSymbol>> symbols(numShards); |
2541 | 76 | parallelForEachN(0, concurrency, [&](size_t threadId) { |
2542 | 76 | uint32_t i = 0; |
2543 | 84 | for (ArrayRef<NameAttrEntry> entries : nameAttrs) { |
2544 | 84 | for (const NameAttrEntry &ent : entries) { |
2545 | 52 | size_t shardId = ent.name.hash() >> shift; |
2546 | 52 | if ((shardId & (concurrency - 1)) != threadId) |
2547 | 39 | continue; |
2548 | 13 | |
2549 | 13 | uint32_t v = ent.cuIndexAndAttrs + cuIdxs[i]; |
2550 | 13 | size_t &idx = map[shardId][ent.name]; |
2551 | 13 | if (idx) { |
2552 | 3 | symbols[shardId][idx - 1].cuVector.push_back(v); |
2553 | 3 | continue; |
2554 | 3 | } |
2555 | 10 | |
2556 | 10 | idx = symbols[shardId].size() + 1; |
2557 | 10 | symbols[shardId].push_back({ent.name, {v}, 0, 0}); |
2558 | 10 | } |
2559 | 84 | ++i; |
2560 | 84 | } |
2561 | 76 | }); |
2562 | 19 | |
2563 | 19 | size_t numSymbols = 0; |
2564 | 19 | for (ArrayRef<GdbSymbol> v : symbols) |
2565 | 608 | numSymbols += v.size(); |
2566 | 19 | |
2567 | 19 | // The return type is a flattened vector, so we'll copy each vector |
2568 | 19 | // contents to Ret. |
2569 | 19 | std::vector<GdbSymbol> ret; |
2570 | 19 | ret.reserve(numSymbols); |
2571 | 19 | for (std::vector<GdbSymbol> &vec : symbols) |
2572 | 608 | for (GdbSymbol &sym : vec) |
2573 | 10 | ret.push_back(std::move(sym)); |
2574 | 19 | |
2575 | 19 | // CU vectors and symbol names are adjacent in the output file. |
2576 | 19 | // We can compute their offsets in the output file now. |
2577 | 19 | size_t off = 0; |
2578 | 19 | for (GdbSymbol &sym : ret) { |
2579 | 10 | sym.cuVectorOff = off; |
2580 | 10 | off += (sym.cuVector.size() + 1) * 4; |
2581 | 10 | } |
2582 | 19 | for (GdbSymbol &sym : ret) { |
2583 | 10 | sym.nameOff = off; |
2584 | 10 | off += sym.name.size() + 1; |
2585 | 10 | } |
2586 | 19 | |
2587 | 19 | return ret; |
2588 | 19 | } |
2589 | | |
2590 | | // Returns a newly-created .gdb_index section. |
2591 | 19 | template <class ELFT> GdbIndexSection *GdbIndexSection::create() { |
2592 | 19 | std::vector<InputSection *> sections = getDebugInfoSections(); |
2593 | 19 | |
2594 | 19 | // .debug_gnu_pub{names,types} are useless in executables. |
2595 | 19 | // They are present in input object files solely for creating |
2596 | 19 | // a .gdb_index. So we can remove them from the output. |
2597 | 19 | for (InputSectionBase *s : inputSections) |
2598 | 251 | if (s->name == ".debug_gnu_pubnames" || s->name == ".debug_gnu_pubtypes"242 ) |
2599 | 14 | s->markDead(); |
2600 | 19 | |
2601 | 19 | std::vector<GdbChunk> chunks(sections.size()); |
2602 | 19 | std::vector<std::vector<NameAttrEntry>> nameAttrs(sections.size()); |
2603 | 19 | |
2604 | 21 | parallelForEachN(0, sections.size(), [&](size_t i) { |
2605 | 21 | ObjFile<ELFT> *file = sections[i]->getFile<ELFT>(); |
2606 | 21 | DWARFContext dwarf(make_unique<LLDDwarfObj<ELFT>>(file)); |
2607 | 21 | |
2608 | 21 | chunks[i].sec = sections[i]; |
2609 | 21 | chunks[i].compilationUnits = readCuList(dwarf); |
2610 | 21 | chunks[i].addressAreas = readAddressAreas(dwarf, sections[i]); |
2611 | 21 | nameAttrs[i] = readPubNamesAndTypes<ELFT>( |
2612 | 21 | static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj()), |
2613 | 21 | chunks[i].compilationUnits); |
2614 | 21 | }); lld::elf::GdbIndexSection* lld::elf::GdbIndexSection::create<llvm::object::ELFType<(llvm::support::endianness)1, false> >()::'lambda'(unsigned long)::operator()(unsigned long) const Line | Count | Source | 2604 | 1 | parallelForEachN(0, sections.size(), [&](size_t i) { | 2605 | 1 | ObjFile<ELFT> *file = sections[i]->getFile<ELFT>(); | 2606 | 1 | DWARFContext dwarf(make_unique<LLDDwarfObj<ELFT>>(file)); | 2607 | 1 | | 2608 | 1 | chunks[i].sec = sections[i]; | 2609 | 1 | chunks[i].compilationUnits = readCuList(dwarf); | 2610 | 1 | chunks[i].addressAreas = readAddressAreas(dwarf, sections[i]); | 2611 | 1 | nameAttrs[i] = readPubNamesAndTypes<ELFT>( | 2612 | 1 | static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj()), | 2613 | 1 | chunks[i].compilationUnits); | 2614 | 1 | }); |
Unexecuted instantiation: lld::elf::GdbIndexSection* lld::elf::GdbIndexSection::create<llvm::object::ELFType<(llvm::support::endianness)0, false> >()::'lambda'(unsigned long)::operator()(unsigned long) const lld::elf::GdbIndexSection* lld::elf::GdbIndexSection::create<llvm::object::ELFType<(llvm::support::endianness)1, true> >()::'lambda'(unsigned long)::operator()(unsigned long) const Line | Count | Source | 2604 | 20 | parallelForEachN(0, sections.size(), [&](size_t i) { | 2605 | 20 | ObjFile<ELFT> *file = sections[i]->getFile<ELFT>(); | 2606 | 20 | DWARFContext dwarf(make_unique<LLDDwarfObj<ELFT>>(file)); | 2607 | 20 | | 2608 | 20 | chunks[i].sec = sections[i]; | 2609 | 20 | chunks[i].compilationUnits = readCuList(dwarf); | 2610 | 20 | chunks[i].addressAreas = readAddressAreas(dwarf, sections[i]); | 2611 | 20 | nameAttrs[i] = readPubNamesAndTypes<ELFT>( | 2612 | 20 | static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj()), | 2613 | 20 | chunks[i].compilationUnits); | 2614 | 20 | }); |
Unexecuted instantiation: lld::elf::GdbIndexSection* lld::elf::GdbIndexSection::create<llvm::object::ELFType<(llvm::support::endianness)0, true> >()::'lambda'(unsigned long)::operator()(unsigned long) const |
2615 | 19 | |
2616 | 19 | auto *ret = make<GdbIndexSection>(); |
2617 | 19 | ret->chunks = std::move(chunks); |
2618 | 19 | ret->symbols = createSymbols(nameAttrs, ret->chunks); |
2619 | 19 | ret->initOutputSize(); |
2620 | 19 | return ret; |
2621 | 19 | } lld::elf::GdbIndexSection* lld::elf::GdbIndexSection::create<llvm::object::ELFType<(llvm::support::endianness)1, false> >() Line | Count | Source | 2591 | 1 | template <class ELFT> GdbIndexSection *GdbIndexSection::create() { | 2592 | 1 | std::vector<InputSection *> sections = getDebugInfoSections(); | 2593 | 1 | | 2594 | 1 | // .debug_gnu_pub{names,types} are useless in executables. | 2595 | 1 | // They are present in input object files solely for creating | 2596 | 1 | // a .gdb_index. So we can remove them from the output. | 2597 | 1 | for (InputSectionBase *s : inputSections) | 2598 | 9 | if (s->name == ".debug_gnu_pubnames" || s->name == ".debug_gnu_pubtypes") | 2599 | 0 | s->markDead(); | 2600 | 1 | | 2601 | 1 | std::vector<GdbChunk> chunks(sections.size()); | 2602 | 1 | std::vector<std::vector<NameAttrEntry>> nameAttrs(sections.size()); | 2603 | 1 | | 2604 | 1 | parallelForEachN(0, sections.size(), [&](size_t i) { | 2605 | 1 | ObjFile<ELFT> *file = sections[i]->getFile<ELFT>(); | 2606 | 1 | DWARFContext dwarf(make_unique<LLDDwarfObj<ELFT>>(file)); | 2607 | 1 | | 2608 | 1 | chunks[i].sec = sections[i]; | 2609 | 1 | chunks[i].compilationUnits = readCuList(dwarf); | 2610 | 1 | chunks[i].addressAreas = readAddressAreas(dwarf, sections[i]); | 2611 | 1 | nameAttrs[i] = readPubNamesAndTypes<ELFT>( | 2612 | 1 | static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj()), | 2613 | 1 | chunks[i].compilationUnits); | 2614 | 1 | }); | 2615 | 1 | | 2616 | 1 | auto *ret = make<GdbIndexSection>(); | 2617 | 1 | ret->chunks = std::move(chunks); | 2618 | 1 | ret->symbols = createSymbols(nameAttrs, ret->chunks); | 2619 | 1 | ret->initOutputSize(); | 2620 | 1 | return ret; | 2621 | 1 | } |
Unexecuted instantiation: lld::elf::GdbIndexSection* lld::elf::GdbIndexSection::create<llvm::object::ELFType<(llvm::support::endianness)0, false> >() lld::elf::GdbIndexSection* lld::elf::GdbIndexSection::create<llvm::object::ELFType<(llvm::support::endianness)1, true> >() Line | Count | Source | 2591 | 18 | template <class ELFT> GdbIndexSection *GdbIndexSection::create() { | 2592 | 18 | std::vector<InputSection *> sections = getDebugInfoSections(); | 2593 | 18 | | 2594 | 18 | // .debug_gnu_pub{names,types} are useless in executables. | 2595 | 18 | // They are present in input object files solely for creating | 2596 | 18 | // a .gdb_index. So we can remove them from the output. | 2597 | 18 | for (InputSectionBase *s : inputSections) | 2598 | 242 | if (s->name == ".debug_gnu_pubnames" || s->name == ".debug_gnu_pubtypes"233 ) | 2599 | 14 | s->markDead(); | 2600 | 18 | | 2601 | 18 | std::vector<GdbChunk> chunks(sections.size()); | 2602 | 18 | std::vector<std::vector<NameAttrEntry>> nameAttrs(sections.size()); | 2603 | 18 | | 2604 | 18 | parallelForEachN(0, sections.size(), [&](size_t i) { | 2605 | 18 | ObjFile<ELFT> *file = sections[i]->getFile<ELFT>(); | 2606 | 18 | DWARFContext dwarf(make_unique<LLDDwarfObj<ELFT>>(file)); | 2607 | 18 | | 2608 | 18 | chunks[i].sec = sections[i]; | 2609 | 18 | chunks[i].compilationUnits = readCuList(dwarf); | 2610 | 18 | chunks[i].addressAreas = readAddressAreas(dwarf, sections[i]); | 2611 | 18 | nameAttrs[i] = readPubNamesAndTypes<ELFT>( | 2612 | 18 | static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj()), | 2613 | 18 | chunks[i].compilationUnits); | 2614 | 18 | }); | 2615 | 18 | | 2616 | 18 | auto *ret = make<GdbIndexSection>(); | 2617 | 18 | ret->chunks = std::move(chunks); | 2618 | 18 | ret->symbols = createSymbols(nameAttrs, ret->chunks); | 2619 | 18 | ret->initOutputSize(); | 2620 | 18 | return ret; | 2621 | 18 | } |
Unexecuted instantiation: lld::elf::GdbIndexSection* lld::elf::GdbIndexSection::create<llvm::object::ELFType<(llvm::support::endianness)0, true> >() |
2622 | | |
2623 | 15 | void GdbIndexSection::writeTo(uint8_t *buf) { |
2624 | 15 | // Write the header. |
2625 | 15 | auto *hdr = reinterpret_cast<GdbIndexHeader *>(buf); |
2626 | 15 | uint8_t *start = buf; |
2627 | 15 | hdr->version = 7; |
2628 | 15 | buf += sizeof(*hdr); |
2629 | 15 | |
2630 | 15 | // Write the CU list. |
2631 | 15 | hdr->cuListOff = buf - start; |
2632 | 19 | for (GdbChunk &chunk : chunks) { |
2633 | 20 | for (CuEntry &cu : chunk.compilationUnits) { |
2634 | 20 | write64le(buf, chunk.sec->outSecOff + cu.cuOffset); |
2635 | 20 | write64le(buf + 8, cu.cuLength); |
2636 | 20 | buf += 16; |
2637 | 20 | } |
2638 | 19 | } |
2639 | 15 | |
2640 | 15 | // Write the address area. |
2641 | 15 | hdr->cuTypesOff = buf - start; |
2642 | 15 | hdr->addressAreaOff = buf - start; |
2643 | 15 | uint32_t cuOff = 0; |
2644 | 19 | for (GdbChunk &chunk : chunks) { |
2645 | 19 | for (AddressEntry &e : chunk.addressAreas) { |
2646 | 13 | uint64_t baseAddr = e.section->getVA(0); |
2647 | 13 | write64le(buf, baseAddr + e.lowAddress); |
2648 | 13 | write64le(buf + 8, baseAddr + e.highAddress); |
2649 | 13 | write32le(buf + 16, e.cuIndex + cuOff); |
2650 | 13 | buf += 20; |
2651 | 13 | } |
2652 | 19 | cuOff += chunk.compilationUnits.size(); |
2653 | 19 | } |
2654 | 15 | |
2655 | 15 | // Write the on-disk open-addressing hash table containing symbols. |
2656 | 15 | hdr->symtabOff = buf - start; |
2657 | 15 | size_t symtabSize = computeSymtabSize(); |
2658 | 15 | uint32_t mask = symtabSize - 1; |
2659 | 15 | |
2660 | 15 | for (GdbSymbol &sym : symbols) { |
2661 | 10 | uint32_t h = sym.name.hash(); |
2662 | 10 | uint32_t i = h & mask; |
2663 | 10 | uint32_t step = ((h * 17) & mask) | 1; |
2664 | 10 | |
2665 | 10 | while (read32le(buf + i * 8)) |
2666 | 0 | i = (i + step) & mask; |
2667 | 10 | |
2668 | 10 | write32le(buf + i * 8, sym.nameOff); |
2669 | 10 | write32le(buf + i * 8 + 4, sym.cuVectorOff); |
2670 | 10 | } |
2671 | 15 | |
2672 | 15 | buf += symtabSize * 8; |
2673 | 15 | |
2674 | 15 | // Write the string pool. |
2675 | 15 | hdr->constantPoolOff = buf - start; |
2676 | 15 | parallelForEach(symbols, [&](GdbSymbol &sym) { |
2677 | 10 | memcpy(buf + sym.nameOff, sym.name.data(), sym.name.size()); |
2678 | 10 | }); |
2679 | 15 | |
2680 | 15 | // Write the CU vectors. |
2681 | 15 | for (GdbSymbol &sym : symbols) { |
2682 | 10 | write32le(buf, sym.cuVector.size()); |
2683 | 10 | buf += 4; |
2684 | 13 | for (uint32_t val : sym.cuVector) { |
2685 | 13 | write32le(buf, val); |
2686 | 13 | buf += 4; |
2687 | 13 | } |
2688 | 10 | } |
2689 | 15 | } |
2690 | | |
2691 | 17 | bool GdbIndexSection::isNeeded() const { return !chunks.empty(); } |
2692 | | |
2693 | | EhFrameHeader::EhFrameHeader() |
2694 | 32 | : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".eh_frame_hdr") {} |
2695 | | |
2696 | 30 | void EhFrameHeader::writeTo(uint8_t *buf) { |
2697 | 30 | // Unlike most sections, the EhFrameHeader section is written while writing |
2698 | 30 | // another section, namely EhFrameSection, which calls the write() function |
2699 | 30 | // below from its writeTo() function. This is necessary because the contents |
2700 | 30 | // of EhFrameHeader depend on the relocated contents of EhFrameSection and we |
2701 | 30 | // don't know which order the sections will be written in. |
2702 | 30 | } |
2703 | | |
2704 | | // .eh_frame_hdr contains a binary search table of pointers to FDEs. |
2705 | | // Each entry of the search table consists of two values, |
2706 | | // the starting PC from where FDEs covers, and the FDE's address. |
2707 | | // It is sorted by PC. |
2708 | 30 | void EhFrameHeader::write() { |
2709 | 30 | uint8_t *buf = Out::bufferStart + getParent()->offset + outSecOff; |
2710 | 30 | using FdeData = EhFrameSection::FdeData; |
2711 | 30 | |
2712 | 30 | std::vector<FdeData> fdes = getPartition().ehFrame->getFdeData(); |
2713 | 30 | |
2714 | 30 | buf[0] = 1; |
2715 | 30 | buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; |
2716 | 30 | buf[2] = DW_EH_PE_udata4; |
2717 | 30 | buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; |
2718 | 30 | write32(buf + 4, |
2719 | 30 | getPartition().ehFrame->getParent()->addr - this->getVA() - 4); |
2720 | 30 | write32(buf + 8, fdes.size()); |
2721 | 30 | buf += 12; |
2722 | 30 | |
2723 | 30 | for (FdeData &fde : fdes) { |
2724 | 25 | write32(buf, fde.pcRel); |
2725 | 25 | write32(buf + 4, fde.fdeVARel); |
2726 | 25 | buf += 8; |
2727 | 25 | } |
2728 | 30 | } |
2729 | | |
2730 | 120 | size_t EhFrameHeader::getSize() const { |
2731 | 120 | // .eh_frame_hdr has a 12 bytes header followed by an array of FDEs. |
2732 | 120 | return 12 + getPartition().ehFrame->numFdes * 8; |
2733 | 120 | } |
2734 | | |
2735 | 63 | bool EhFrameHeader::isNeeded() const { |
2736 | 63 | return isLive() && getPartition().ehFrame->isNeeded()62 ; |
2737 | 63 | } |
2738 | | |
2739 | | VersionDefinitionSection::VersionDefinitionSection() |
2740 | | : SyntheticSection(SHF_ALLOC, SHT_GNU_verdef, sizeof(uint32_t), |
2741 | 61 | ".gnu.version_d") {} |
2742 | | |
2743 | 120 | StringRef VersionDefinitionSection::getFileDefName() { |
2744 | 120 | if (!getPartition().name.empty()) |
2745 | 2 | return getPartition().name; |
2746 | 118 | if (!config->soName.empty()) |
2747 | 20 | return config->soName; |
2748 | 98 | return config->outputFile; |
2749 | 98 | } |
2750 | | |
2751 | 60 | void VersionDefinitionSection::finalizeContents() { |
2752 | 60 | fileDefNameOff = getPartition().dynStrTab->addString(getFileDefName()); |
2753 | 60 | for (VersionDefinition &v : config->versionDefinitions) |
2754 | 92 | verDefNameOffs.push_back(getPartition().dynStrTab->addString(v.name)); |
2755 | 60 | |
2756 | 60 | if (OutputSection *sec = getPartition().dynStrTab->getParent()) |
2757 | 60 | getParent()->link = sec->sectionIndex; |
2758 | 60 | |
2759 | 60 | // sh_info should be set to the number of definitions. This fact is missed in |
2760 | 60 | // documentation, but confirmed by binutils community: |
2761 | 60 | // https://sourceware.org/ml/binutils/2014-11/msg00355.html |
2762 | 60 | getParent()->info = getVerDefNum(); |
2763 | 60 | } |
2764 | | |
2765 | | void VersionDefinitionSection::writeOne(uint8_t *buf, uint32_t index, |
2766 | 152 | StringRef name, size_t nameOff) { |
2767 | 152 | uint16_t flags = index == 1 ? VER_FLG_BASE60 : 092 ; |
2768 | 152 | |
2769 | 152 | // Write a verdef. |
2770 | 152 | write16(buf, 1); // vd_version |
2771 | 152 | write16(buf + 2, flags); // vd_flags |
2772 | 152 | write16(buf + 4, index); // vd_ndx |
2773 | 152 | write16(buf + 6, 1); // vd_cnt |
2774 | 152 | write32(buf + 8, hashSysV(name)); // vd_hash |
2775 | 152 | write32(buf + 12, 20); // vd_aux |
2776 | 152 | write32(buf + 16, 28); // vd_next |
2777 | 152 | |
2778 | 152 | // Write a veraux. |
2779 | 152 | write32(buf + 20, nameOff); // vda_name |
2780 | 152 | write32(buf + 24, 0); // vda_next |
2781 | 152 | } |
2782 | | |
2783 | 60 | void VersionDefinitionSection::writeTo(uint8_t *buf) { |
2784 | 60 | writeOne(buf, 1, getFileDefName(), fileDefNameOff); |
2785 | 60 | |
2786 | 60 | auto nameOffIt = verDefNameOffs.begin(); |
2787 | 92 | for (VersionDefinition &v : config->versionDefinitions) { |
2788 | 92 | buf += EntrySize; |
2789 | 92 | writeOne(buf, v.id, v.name, *nameOffIt++); |
2790 | 92 | } |
2791 | 60 | |
2792 | 60 | // Need to terminate the last version definition. |
2793 | 60 | write32(buf + 16, 0); // vd_next |
2794 | 60 | } |
2795 | | |
2796 | 240 | size_t VersionDefinitionSection::getSize() const { |
2797 | 240 | return EntrySize * getVerDefNum(); |
2798 | 240 | } |
2799 | | |
2800 | | // .gnu.version is a table where each entry is 2 byte long. |
2801 | | VersionTableSection::VersionTableSection() |
2802 | | : SyntheticSection(SHF_ALLOC, SHT_GNU_versym, sizeof(uint16_t), |
2803 | 1.35k | ".gnu.version") { |
2804 | 1.35k | this->entsize = 2; |
2805 | 1.35k | } |
2806 | | |
2807 | 67 | void VersionTableSection::finalizeContents() { |
2808 | 67 | // At the moment of june 2016 GNU docs does not mention that sh_link field |
2809 | 67 | // should be set, but Sun docs do. Also readelf relies on this field. |
2810 | 67 | getParent()->link = getPartition().dynSymTab->getParent()->sectionIndex; |
2811 | 67 | } |
2812 | | |
2813 | 268 | size_t VersionTableSection::getSize() const { |
2814 | 268 | return (getPartition().dynSymTab->getSymbols().size() + 1) * 2; |
2815 | 268 | } |
2816 | | |
2817 | 67 | void VersionTableSection::writeTo(uint8_t *buf) { |
2818 | 67 | buf += 2; |
2819 | 154 | for (const SymbolTableEntry &s : getPartition().dynSymTab->getSymbols()) { |
2820 | 154 | write16(buf, s.sym->versionId); |
2821 | 154 | buf += 2; |
2822 | 154 | } |
2823 | 67 | } |
2824 | | |
2825 | 2.52k | bool VersionTableSection::isNeeded() const { |
2826 | 2.52k | return getPartition().verDef || getPartition().verNeed->isNeeded()2.40k ; |
2827 | 2.52k | } |
2828 | | |
2829 | 427 | void elf::addVerneed(Symbol *ss) { |
2830 | 427 | auto &file = cast<SharedFile>(*ss->file); |
2831 | 427 | if (ss->verdefIndex == VER_NDX_GLOBAL) { |
2832 | 409 | ss->versionId = VER_NDX_GLOBAL; |
2833 | 409 | return; |
2834 | 409 | } |
2835 | 18 | |
2836 | 18 | if (file.vernauxs.empty()) |
2837 | 10 | file.vernauxs.resize(file.verdefs.size()); |
2838 | 18 | |
2839 | 18 | // Select a version identifier for the vernaux data structure, if we haven't |
2840 | 18 | // already allocated one. The verdef identifiers cover the range |
2841 | 18 | // [1..getVerDefNum()]; this causes the vernaux identifiers to start from |
2842 | 18 | // getVerDefNum()+1. |
2843 | 18 | if (file.vernauxs[ss->verdefIndex] == 0) |
2844 | 16 | file.vernauxs[ss->verdefIndex] = ++SharedFile::vernauxNum + getVerDefNum(); |
2845 | 18 | |
2846 | 18 | ss->versionId = file.vernauxs[ss->verdefIndex]; |
2847 | 18 | } |
2848 | | |
2849 | | template <class ELFT> |
2850 | | VersionNeedSection<ELFT>::VersionNeedSection() |
2851 | | : SyntheticSection(SHF_ALLOC, SHT_GNU_verneed, sizeof(uint32_t), |
2852 | 1.35k | ".gnu.version_r") {} lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::VersionNeedSection() Line | Count | Source | 2852 | 185 | ".gnu.version_r") {} |
lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::VersionNeedSection() Line | Count | Source | 2852 | 87 | ".gnu.version_r") {} |
lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::VersionNeedSection() Line | Count | Source | 2852 | 1.02k | ".gnu.version_r") {} |
lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::VersionNeedSection() Line | Count | Source | 2852 | 56 | ".gnu.version_r") {} |
|
2853 | | |
2854 | 10 | template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() { |
2855 | 11 | for (SharedFile *f : sharedFiles) { |
2856 | 11 | if (f->vernauxs.empty()) |
2857 | 0 | continue; |
2858 | 11 | verneeds.emplace_back(); |
2859 | 11 | Verneed &vn = verneeds.back(); |
2860 | 11 | vn.nameStrTab = getPartition().dynStrTab->addString(f->soName); |
2861 | 57 | for (unsigned i = 0; i != f->vernauxs.size(); ++i46 ) { |
2862 | 46 | if (f->vernauxs[i] == 0) |
2863 | 28 | continue; |
2864 | 18 | auto *verdef = |
2865 | 18 | reinterpret_cast<const typename ELFT::Verdef *>(f->verdefs[i]); |
2866 | 18 | vn.vernauxs.push_back( |
2867 | 18 | {verdef->vd_hash, f->vernauxs[i], |
2868 | 18 | getPartition().dynStrTab->addString(f->getStringTable().data() + |
2869 | 18 | verdef->getAux()->vda_name)}); |
2870 | 18 | } |
2871 | 11 | } |
2872 | 10 | |
2873 | 10 | if (OutputSection *sec = getPartition().dynStrTab->getParent()) |
2874 | 10 | getParent()->link = sec->sectionIndex; |
2875 | 10 | getParent()->info = verneeds.size(); |
2876 | 10 | } Unexecuted instantiation: lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::finalizeContents() lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::finalizeContents() Line | Count | Source | 2854 | 1 | template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() { | 2855 | 1 | for (SharedFile *f : sharedFiles) { | 2856 | 1 | if (f->vernauxs.empty()) | 2857 | 0 | continue; | 2858 | 1 | verneeds.emplace_back(); | 2859 | 1 | Verneed &vn = verneeds.back(); | 2860 | 1 | vn.nameStrTab = getPartition().dynStrTab->addString(f->soName); | 2861 | 4 | for (unsigned i = 0; i != f->vernauxs.size(); ++i3 ) { | 2862 | 3 | if (f->vernauxs[i] == 0) | 2863 | 2 | continue; | 2864 | 1 | auto *verdef = | 2865 | 1 | reinterpret_cast<const typename ELFT::Verdef *>(f->verdefs[i]); | 2866 | 1 | vn.vernauxs.push_back( | 2867 | 1 | {verdef->vd_hash, f->vernauxs[i], | 2868 | 1 | getPartition().dynStrTab->addString(f->getStringTable().data() + | 2869 | 1 | verdef->getAux()->vda_name)}); | 2870 | 1 | } | 2871 | 1 | } | 2872 | 1 | | 2873 | 1 | if (OutputSection *sec = getPartition().dynStrTab->getParent()) | 2874 | 1 | getParent()->link = sec->sectionIndex; | 2875 | 1 | getParent()->info = verneeds.size(); | 2876 | 1 | } |
lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::finalizeContents() Line | Count | Source | 2854 | 9 | template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() { | 2855 | 10 | for (SharedFile *f : sharedFiles) { | 2856 | 10 | if (f->vernauxs.empty()) | 2857 | 0 | continue; | 2858 | 10 | verneeds.emplace_back(); | 2859 | 10 | Verneed &vn = verneeds.back(); | 2860 | 10 | vn.nameStrTab = getPartition().dynStrTab->addString(f->soName); | 2861 | 53 | for (unsigned i = 0; i != f->vernauxs.size(); ++i43 ) { | 2862 | 43 | if (f->vernauxs[i] == 0) | 2863 | 26 | continue; | 2864 | 17 | auto *verdef = | 2865 | 17 | reinterpret_cast<const typename ELFT::Verdef *>(f->verdefs[i]); | 2866 | 17 | vn.vernauxs.push_back( | 2867 | 17 | {verdef->vd_hash, f->vernauxs[i], | 2868 | 17 | getPartition().dynStrTab->addString(f->getStringTable().data() + | 2869 | 17 | verdef->getAux()->vda_name)}); | 2870 | 17 | } | 2871 | 10 | } | 2872 | 9 | | 2873 | 9 | if (OutputSection *sec = getPartition().dynStrTab->getParent()) | 2874 | 9 | getParent()->link = sec->sectionIndex; | 2875 | 9 | getParent()->info = verneeds.size(); | 2876 | 9 | } |
Unexecuted instantiation: lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::finalizeContents() |
2877 | | |
2878 | 10 | template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *buf) { |
2879 | 10 | // The Elf_Verneeds need to appear first, followed by the Elf_Vernauxs. |
2880 | 10 | auto *verneed = reinterpret_cast<Elf_Verneed *>(buf); |
2881 | 10 | auto *vernaux = reinterpret_cast<Elf_Vernaux *>(verneed + verneeds.size()); |
2882 | 10 | |
2883 | 11 | for (auto &vn : verneeds) { |
2884 | 11 | // Create an Elf_Verneed for this DSO. |
2885 | 11 | verneed->vn_version = 1; |
2886 | 11 | verneed->vn_cnt = vn.vernauxs.size(); |
2887 | 11 | verneed->vn_file = vn.nameStrTab; |
2888 | 11 | verneed->vn_aux = |
2889 | 11 | reinterpret_cast<char *>(vernaux) - reinterpret_cast<char *>(verneed); |
2890 | 11 | verneed->vn_next = sizeof(Elf_Verneed); |
2891 | 11 | ++verneed; |
2892 | 11 | |
2893 | 11 | // Create the Elf_Vernauxs for this Elf_Verneed. |
2894 | 18 | for (auto &vna : vn.vernauxs) { |
2895 | 18 | vernaux->vna_hash = vna.hash; |
2896 | 18 | vernaux->vna_flags = 0; |
2897 | 18 | vernaux->vna_other = vna.verneedIndex; |
2898 | 18 | vernaux->vna_name = vna.nameStrTab; |
2899 | 18 | vernaux->vna_next = sizeof(Elf_Vernaux); |
2900 | 18 | ++vernaux; |
2901 | 18 | } |
2902 | 11 | |
2903 | 11 | vernaux[-1].vna_next = 0; |
2904 | 11 | } |
2905 | 10 | verneed[-1].vn_next = 0; |
2906 | 10 | } Unexecuted instantiation: lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*) lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::writeTo(unsigned char*) Line | Count | Source | 2878 | 1 | template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *buf) { | 2879 | 1 | // The Elf_Verneeds need to appear first, followed by the Elf_Vernauxs. | 2880 | 1 | auto *verneed = reinterpret_cast<Elf_Verneed *>(buf); | 2881 | 1 | auto *vernaux = reinterpret_cast<Elf_Vernaux *>(verneed + verneeds.size()); | 2882 | 1 | | 2883 | 1 | for (auto &vn : verneeds) { | 2884 | 1 | // Create an Elf_Verneed for this DSO. | 2885 | 1 | verneed->vn_version = 1; | 2886 | 1 | verneed->vn_cnt = vn.vernauxs.size(); | 2887 | 1 | verneed->vn_file = vn.nameStrTab; | 2888 | 1 | verneed->vn_aux = | 2889 | 1 | reinterpret_cast<char *>(vernaux) - reinterpret_cast<char *>(verneed); | 2890 | 1 | verneed->vn_next = sizeof(Elf_Verneed); | 2891 | 1 | ++verneed; | 2892 | 1 | | 2893 | 1 | // Create the Elf_Vernauxs for this Elf_Verneed. | 2894 | 1 | for (auto &vna : vn.vernauxs) { | 2895 | 1 | vernaux->vna_hash = vna.hash; | 2896 | 1 | vernaux->vna_flags = 0; | 2897 | 1 | vernaux->vna_other = vna.verneedIndex; | 2898 | 1 | vernaux->vna_name = vna.nameStrTab; | 2899 | 1 | vernaux->vna_next = sizeof(Elf_Vernaux); | 2900 | 1 | ++vernaux; | 2901 | 1 | } | 2902 | 1 | | 2903 | 1 | vernaux[-1].vna_next = 0; | 2904 | 1 | } | 2905 | 1 | verneed[-1].vn_next = 0; | 2906 | 1 | } |
lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeTo(unsigned char*) Line | Count | Source | 2878 | 9 | template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *buf) { | 2879 | 9 | // The Elf_Verneeds need to appear first, followed by the Elf_Vernauxs. | 2880 | 9 | auto *verneed = reinterpret_cast<Elf_Verneed *>(buf); | 2881 | 9 | auto *vernaux = reinterpret_cast<Elf_Vernaux *>(verneed + verneeds.size()); | 2882 | 9 | | 2883 | 10 | for (auto &vn : verneeds) { | 2884 | 10 | // Create an Elf_Verneed for this DSO. | 2885 | 10 | verneed->vn_version = 1; | 2886 | 10 | verneed->vn_cnt = vn.vernauxs.size(); | 2887 | 10 | verneed->vn_file = vn.nameStrTab; | 2888 | 10 | verneed->vn_aux = | 2889 | 10 | reinterpret_cast<char *>(vernaux) - reinterpret_cast<char *>(verneed); | 2890 | 10 | verneed->vn_next = sizeof(Elf_Verneed); | 2891 | 10 | ++verneed; | 2892 | 10 | | 2893 | 10 | // Create the Elf_Vernauxs for this Elf_Verneed. | 2894 | 17 | for (auto &vna : vn.vernauxs) { | 2895 | 17 | vernaux->vna_hash = vna.hash; | 2896 | 17 | vernaux->vna_flags = 0; | 2897 | 17 | vernaux->vna_other = vna.verneedIndex; | 2898 | 17 | vernaux->vna_name = vna.nameStrTab; | 2899 | 17 | vernaux->vna_next = sizeof(Elf_Vernaux); | 2900 | 17 | ++vernaux; | 2901 | 17 | } | 2902 | 10 | | 2903 | 10 | vernaux[-1].vna_next = 0; | 2904 | 10 | } | 2905 | 9 | verneed[-1].vn_next = 0; | 2906 | 9 | } |
Unexecuted instantiation: lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::writeTo(unsigned char*) |
2907 | | |
2908 | 40 | template <class ELFT> size_t VersionNeedSection<ELFT>::getSize() const { |
2909 | 40 | return verneeds.size() * sizeof(Elf_Verneed) + |
2910 | 40 | SharedFile::vernauxNum * sizeof(Elf_Vernaux); |
2911 | 40 | } Unexecuted instantiation: lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::getSize() const lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::getSize() const Line | Count | Source | 2908 | 4 | template <class ELFT> size_t VersionNeedSection<ELFT>::getSize() const { | 2909 | 4 | return verneeds.size() * sizeof(Elf_Verneed) + | 2910 | 4 | SharedFile::vernauxNum * sizeof(Elf_Vernaux); | 2911 | 4 | } |
lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::getSize() const Line | Count | Source | 2908 | 36 | template <class ELFT> size_t VersionNeedSection<ELFT>::getSize() const { | 2909 | 36 | return verneeds.size() * sizeof(Elf_Verneed) + | 2910 | 36 | SharedFile::vernauxNum * sizeof(Elf_Vernaux); | 2911 | 36 | } |
Unexecuted instantiation: lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::getSize() const |
2912 | | |
2913 | 4.93k | template <class ELFT> bool VersionNeedSection<ELFT>::isNeeded() const { |
2914 | 4.93k | return SharedFile::vernauxNum != 0; |
2915 | 4.93k | } lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::isNeeded() const Line | Count | Source | 2913 | 708 | template <class ELFT> bool VersionNeedSection<ELFT>::isNeeded() const { | 2914 | 708 | return SharedFile::vernauxNum != 0; | 2915 | 708 | } |
lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::isNeeded() const Line | Count | Source | 2913 | 340 | template <class ELFT> bool VersionNeedSection<ELFT>::isNeeded() const { | 2914 | 340 | return SharedFile::vernauxNum != 0; | 2915 | 340 | } |
lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::isNeeded() const Line | Count | Source | 2913 | 3.68k | template <class ELFT> bool VersionNeedSection<ELFT>::isNeeded() const { | 2914 | 3.68k | return SharedFile::vernauxNum != 0; | 2915 | 3.68k | } |
lld::elf::VersionNeedSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::isNeeded() const Line | Count | Source | 2913 | 200 | template <class ELFT> bool VersionNeedSection<ELFT>::isNeeded() const { | 2914 | 200 | return SharedFile::vernauxNum != 0; | 2915 | 200 | } |
|
2916 | | |
2917 | 2.77k | void MergeSyntheticSection::addSection(MergeInputSection *ms) { |
2918 | 2.77k | ms->parent = this; |
2919 | 2.77k | sections.push_back(ms); |
2920 | 2.77k | assert(alignment == ms->alignment || !(ms->flags & SHF_STRINGS)); |
2921 | 2.77k | alignment = std::max(alignment, ms->alignment); |
2922 | 2.77k | } |
2923 | | |
2924 | | MergeTailSection::MergeTailSection(StringRef name, uint32_t type, |
2925 | | uint64_t flags, uint32_t alignment) |
2926 | | : MergeSyntheticSection(name, type, flags, alignment), |
2927 | 9 | builder(StringTableBuilder::RAW, alignment) {} |
2928 | | |
2929 | 36 | size_t MergeTailSection::getSize() const { return builder.getSize(); } |
2930 | | |
2931 | 9 | void MergeTailSection::writeTo(uint8_t *buf) { builder.write(buf); } |
2932 | | |
2933 | 9 | void MergeTailSection::finalizeContents() { |
2934 | 9 | // Add all string pieces to the string table builder to create section |
2935 | 9 | // contents. |
2936 | 9 | for (MergeInputSection *sec : sections) |
2937 | 26 | for (size_t i = 0, e = sec->pieces.size(); 11 i != e; ++i15 ) |
2938 | 15 | if (sec->pieces[i].live) |
2939 | 14 | builder.add(sec->getData(i)); |
2940 | 9 | |
2941 | 9 | // Fix the string table content. After this, the contents will never change. |
2942 | 9 | builder.finalize(); |
2943 | 9 | |
2944 | 9 | // finalize() fixed tail-optimized strings, so we can now get |
2945 | 9 | // offsets of strings. Get an offset for each string and save it |
2946 | 9 | // to a corresponding SectionPiece for easy access. |
2947 | 9 | for (MergeInputSection *sec : sections) |
2948 | 26 | for (size_t i = 0, e = sec->pieces.size(); 11 i != e; ++i15 ) |
2949 | 15 | if (sec->pieces[i].live) |
2950 | 14 | sec->pieces[i].outputOff = builder.getOffset(sec->getData(i)); |
2951 | 9 | } |
2952 | | |
2953 | 2.55k | void MergeNoTailSection::writeTo(uint8_t *buf) { |
2954 | 84.3k | for (size_t i = 0; i < numShards; ++i81.8k ) |
2955 | 81.8k | shards[i].write(buf + shardOffsets[i]); |
2956 | 2.55k | } |
2957 | | |
2958 | | // This function is very hot (i.e. it can take several seconds to finish) |
2959 | | // because sometimes the number of inputs is in an order of magnitude of |
2960 | | // millions. So, we use multi-threading. |
2961 | | // |
2962 | | // For any strings S and T, we know S is not mergeable with T if S's hash |
2963 | | // value is different from T's. If that's the case, we can safely put S and |
2964 | | // T into different string builders without worrying about merge misses. |
2965 | | // We do it in parallel. |
2966 | 2.74k | void MergeNoTailSection::finalizeContents() { |
2967 | 2.74k | // Initializes string table builders. |
2968 | 90.5k | for (size_t i = 0; i < numShards; ++i87.8k ) |
2969 | 87.8k | shards.emplace_back(StringTableBuilder::RAW, alignment); |
2970 | 2.74k | |
2971 | 2.74k | // Concurrency level. Must be a power of 2 to avoid expensive modulo |
2972 | 2.74k | // operations in the following tight loop. |
2973 | 2.74k | size_t concurrency = 1; |
2974 | 2.74k | if (threadsEnabled) |
2975 | 2.73k | concurrency = |
2976 | 2.73k | std::min<size_t>(PowerOf2Floor(hardware_concurrency()), numShards); |
2977 | 2.74k | |
2978 | 2.74k | // Add section pieces to the builders. |
2979 | 10.9k | parallelForEachN(0, concurrency, [&](size_t threadId) { |
2980 | 11.0k | for (MergeInputSection *sec : sections) { |
2981 | 22.4k | for (size_t i = 0, e = sec->pieces.size(); i != e; ++i11.4k ) { |
2982 | 11.4k | if (!sec->pieces[i].live) |
2983 | 28 | continue; |
2984 | 11.4k | size_t shardId = getShardId(sec->pieces[i].hash); |
2985 | 11.4k | if ((shardId & (concurrency - 1)) == threadId) |
2986 | 2.85k | sec->pieces[i].outputOff = shards[shardId].add(sec->getData(i)); |
2987 | 11.4k | } |
2988 | 11.0k | } |
2989 | 10.9k | }); |
2990 | 2.74k | |
2991 | 2.74k | // Compute an in-section offset for each shard. |
2992 | 2.74k | size_t off = 0; |
2993 | 90.5k | for (size_t i = 0; i < numShards; ++i87.8k ) { |
2994 | 87.8k | shards[i].finalizeInOrder(); |
2995 | 87.8k | if (shards[i].getSize() > 0) |
2996 | 2.81k | off = alignTo(off, alignment); |
2997 | 87.8k | shardOffsets[i] = off; |
2998 | 87.8k | off += shards[i].getSize(); |
2999 | 87.8k | } |
3000 | 2.74k | size = off; |
3001 | 2.74k | |
3002 | 2.74k | // So far, section pieces have offsets from beginning of shards, but |
3003 | 2.74k | // we want offsets from beginning of the whole section. Fix them. |
3004 | 2.76k | parallelForEach(sections, [&](MergeInputSection *sec) { |
3005 | 5.63k | for (size_t i = 0, e = sec->pieces.size(); i != e; ++i2.86k ) |
3006 | 2.86k | if (sec->pieces[i].live) |
3007 | 2.86k | sec->pieces[i].outputOff += |
3008 | 2.86k | shardOffsets[getShardId(sec->pieces[i].hash)]; |
3009 | 2.76k | }); |
3010 | 2.74k | } |
3011 | | |
3012 | | static MergeSyntheticSection *createMergeSynthetic(StringRef name, |
3013 | | uint32_t type, |
3014 | | uint64_t flags, |
3015 | 2.75k | uint32_t alignment) { |
3016 | 2.75k | bool shouldTailMerge = (flags & SHF_STRINGS) && config->optimize >= 22.72k ; |
3017 | 2.75k | if (shouldTailMerge) |
3018 | 9 | return make<MergeTailSection>(name, type, flags, alignment); |
3019 | 2.74k | return make<MergeNoTailSection>(name, type, flags, alignment); |
3020 | 2.74k | } |
3021 | | |
3022 | 2.75k | template <class ELFT> void elf::splitSections() { |
3023 | 2.75k | // splitIntoPieces needs to be called on each MergeInputSection |
3024 | 2.75k | // before calling finalizeContents(). |
3025 | 318k | parallelForEach(inputSections, [](InputSectionBase *sec) { |
3026 | 318k | if (auto *s = dyn_cast<MergeInputSection>(sec)) |
3027 | 2.78k | s->splitIntoPieces(); |
3028 | 315k | else if (auto *eh = dyn_cast<EhInputSection>(sec)) |
3029 | 116 | eh->split<ELFT>(); |
3030 | 318k | }); void lld::elf::splitSections<llvm::object::ELFType<(llvm::support::endianness)1, false> >()::'lambda'(lld::elf::InputSectionBase*)::operator()(lld::elf::InputSectionBase*) const Line | Count | Source | 3025 | 1.74k | parallelForEach(inputSections, [](InputSectionBase *sec) { | 3026 | 1.74k | if (auto *s = dyn_cast<MergeInputSection>(sec)) | 3027 | 370 | s->splitIntoPieces(); | 3028 | 1.37k | else if (auto *eh = dyn_cast<EhInputSection>(sec)) | 3029 | 4 | eh->split<ELFT>(); | 3030 | 1.74k | }); |
void lld::elf::splitSections<llvm::object::ELFType<(llvm::support::endianness)0, false> >()::'lambda'(lld::elf::InputSectionBase*)::operator()(lld::elf::InputSectionBase*) const Line | Count | Source | 3025 | 1.11k | parallelForEach(inputSections, [](InputSectionBase *sec) { | 3026 | 1.11k | if (auto *s = dyn_cast<MergeInputSection>(sec)) | 3027 | 147 | s->splitIntoPieces(); | 3028 | 963 | else if (auto *eh = dyn_cast<EhInputSection>(sec)) | 3029 | 0 | eh->split<ELFT>(); | 3030 | 1.11k | }); |
void lld::elf::splitSections<llvm::object::ELFType<(llvm::support::endianness)1, true> >()::'lambda'(lld::elf::InputSectionBase*)::operator()(lld::elf::InputSectionBase*) const Line | Count | Source | 3025 | 315k | parallelForEach(inputSections, [](InputSectionBase *sec) { | 3026 | 315k | if (auto *s = dyn_cast<MergeInputSection>(sec)) | 3027 | 2.16k | s->splitIntoPieces(); | 3028 | 312k | else if (auto *eh = dyn_cast<EhInputSection>(sec)) | 3029 | 108 | eh->split<ELFT>(); | 3030 | 315k | }); |
void lld::elf::splitSections<llvm::object::ELFType<(llvm::support::endianness)0, true> >()::'lambda'(lld::elf::InputSectionBase*)::operator()(lld::elf::InputSectionBase*) const Line | Count | Source | 3025 | 512 | parallelForEach(inputSections, [](InputSectionBase *sec) { | 3026 | 512 | if (auto *s = dyn_cast<MergeInputSection>(sec)) | 3027 | 105 | s->splitIntoPieces(); | 3028 | 407 | else if (auto *eh = dyn_cast<EhInputSection>(sec)) | 3029 | 4 | eh->split<ELFT>(); | 3030 | 512 | }); |
|
3031 | 2.75k | } void lld::elf::splitSections<llvm::object::ELFType<(llvm::support::endianness)1, false> >() Line | Count | Source | 3022 | 376 | template <class ELFT> void elf::splitSections() { | 3023 | 376 | // splitIntoPieces needs to be called on each MergeInputSection | 3024 | 376 | // before calling finalizeContents(). | 3025 | 376 | parallelForEach(inputSections, [](InputSectionBase *sec) { | 3026 | 376 | if (auto *s = dyn_cast<MergeInputSection>(sec)) | 3027 | 376 | s->splitIntoPieces(); | 3028 | 376 | else if (auto *eh = dyn_cast<EhInputSection>(sec)) | 3029 | 376 | eh->split<ELFT>(); | 3030 | 376 | }); | 3031 | 376 | } |
void lld::elf::splitSections<llvm::object::ELFType<(llvm::support::endianness)0, false> >() Line | Count | Source | 3022 | 157 | template <class ELFT> void elf::splitSections() { | 3023 | 157 | // splitIntoPieces needs to be called on each MergeInputSection | 3024 | 157 | // before calling finalizeContents(). | 3025 | 157 | parallelForEach(inputSections, [](InputSectionBase *sec) { | 3026 | 157 | if (auto *s = dyn_cast<MergeInputSection>(sec)) | 3027 | 157 | s->splitIntoPieces(); | 3028 | 157 | else if (auto *eh = dyn_cast<EhInputSection>(sec)) | 3029 | 157 | eh->split<ELFT>(); | 3030 | 157 | }); | 3031 | 157 | } |
void lld::elf::splitSections<llvm::object::ELFType<(llvm::support::endianness)1, true> >() Line | Count | Source | 3022 | 2.11k | template <class ELFT> void elf::splitSections() { | 3023 | 2.11k | // splitIntoPieces needs to be called on each MergeInputSection | 3024 | 2.11k | // before calling finalizeContents(). | 3025 | 2.11k | parallelForEach(inputSections, [](InputSectionBase *sec) { | 3026 | 2.11k | if (auto *s = dyn_cast<MergeInputSection>(sec)) | 3027 | 2.11k | s->splitIntoPieces(); | 3028 | 2.11k | else if (auto *eh = dyn_cast<EhInputSection>(sec)) | 3029 | 2.11k | eh->split<ELFT>(); | 3030 | 2.11k | }); | 3031 | 2.11k | } |
void lld::elf::splitSections<llvm::object::ELFType<(llvm::support::endianness)0, true> >() Line | Count | Source | 3022 | 108 | template <class ELFT> void elf::splitSections() { | 3023 | 108 | // splitIntoPieces needs to be called on each MergeInputSection | 3024 | 108 | // before calling finalizeContents(). | 3025 | 108 | parallelForEach(inputSections, [](InputSectionBase *sec) { | 3026 | 108 | if (auto *s = dyn_cast<MergeInputSection>(sec)) | 3027 | 108 | s->splitIntoPieces(); | 3028 | 108 | else if (auto *eh = dyn_cast<EhInputSection>(sec)) | 3029 | 108 | eh->split<ELFT>(); | 3030 | 108 | }); | 3031 | 108 | } |
|
3032 | | |
3033 | | // This function scans over the inputsections to create mergeable |
3034 | | // synthetic sections. |
3035 | | // |
3036 | | // It removes MergeInputSections from the input section array and adds |
3037 | | // new synthetic sections at the location of the first input section |
3038 | | // that it replaces. It then finalizes each synthetic section in order |
3039 | | // to compute an output offset for each piece of each input section. |
3040 | 2.75k | void elf::mergeSections() { |
3041 | 2.75k | std::vector<MergeSyntheticSection *> mergeSections; |
3042 | 340k | for (InputSectionBase *&s : inputSections) { |
3043 | 340k | MergeInputSection *ms = dyn_cast<MergeInputSection>(s); |
3044 | 340k | if (!ms) |
3045 | 337k | continue; |
3046 | 2.78k | |
3047 | 2.78k | // We do not want to handle sections that are not alive, so just remove |
3048 | 2.78k | // them instead of trying to merge. |
3049 | 2.78k | if (!ms->isLive()) { |
3050 | 9 | s = nullptr; |
3051 | 9 | continue; |
3052 | 9 | } |
3053 | 2.77k | |
3054 | 2.77k | StringRef outsecName = getOutputSectionName(ms); |
3055 | 2.77k | |
3056 | 2.77k | auto i = llvm::find_if(mergeSections, [=](MergeSyntheticSection *sec) { |
3057 | 135 | // While we could create a single synthetic section for two different |
3058 | 135 | // values of Entsize, it is better to take Entsize into consideration. |
3059 | 135 | // |
3060 | 135 | // With a single synthetic section no two pieces with different Entsize |
3061 | 135 | // could be equal, so we may as well have two sections. |
3062 | 135 | // |
3063 | 135 | // Using Entsize in here also allows us to propagate it to the synthetic |
3064 | 135 | // section. |
3065 | 135 | // |
3066 | 135 | // SHF_STRINGS section with different alignments should not be merged. |
3067 | 135 | return sec->name == outsecName && sec->flags == ms->flags35 && |
3068 | 135 | sec->entsize == ms->entsize34 && |
3069 | 135 | (27 sec->alignment == ms->alignment27 || !(sec->flags & SHF_STRINGS)7 ); |
3070 | 135 | }); |
3071 | 2.77k | if (i == mergeSections.end()) { |
3072 | 2.75k | MergeSyntheticSection *syn = |
3073 | 2.75k | createMergeSynthetic(outsecName, ms->type, ms->flags, ms->alignment); |
3074 | 2.75k | mergeSections.push_back(syn); |
3075 | 2.75k | i = std::prev(mergeSections.end()); |
3076 | 2.75k | s = syn; |
3077 | 2.75k | syn->entsize = ms->entsize; |
3078 | 2.75k | } else { |
3079 | 24 | s = nullptr; |
3080 | 24 | } |
3081 | 2.77k | (*i)->addSection(ms); |
3082 | 2.77k | } |
3083 | 2.75k | for (auto *ms : mergeSections) |
3084 | 2.75k | ms->finalizeContents(); |
3085 | 2.75k | |
3086 | 2.75k | std::vector<InputSectionBase *> &v = inputSections; |
3087 | 2.75k | v.erase(std::remove(v.begin(), v.end(), nullptr), v.end()); |
3088 | 2.75k | } |
3089 | | |
3090 | | MipsRldMapSection::MipsRldMapSection() |
3091 | | : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize, |
3092 | 30 | ".rld_map") {} |
3093 | | |
3094 | | ARMExidxSyntheticSection::ARMExidxSyntheticSection() |
3095 | | : SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX, |
3096 | 157 | config->wordsize, ".ARM.exidx") {} |
3097 | | |
3098 | 725 | static InputSection *findExidxSection(InputSection *isec) { |
3099 | 725 | for (InputSection *d : isec->dependentSections) |
3100 | 178 | if (d->type == SHT_ARM_EXIDX) |
3101 | 178 | return d; |
3102 | 725 | return nullptr547 ; |
3103 | 725 | } |
3104 | | |
3105 | 846 | bool ARMExidxSyntheticSection::addSection(InputSection *isec) { |
3106 | 846 | if (isec->type == SHT_ARM_EXIDX) { |
3107 | 68 | exidxSections.push_back(isec); |
3108 | 68 | return true; |
3109 | 68 | } |
3110 | 778 | |
3111 | 778 | if ((isec->flags & SHF_ALLOC) && (isec->flags & SHF_EXECINSTR)708 && |
3112 | 778 | isec->getSize() > 0651 ) { |
3113 | 585 | executableSections.push_back(isec); |
3114 | 585 | if (empty && findExidxSection(isec)533 ) |
3115 | 27 | empty = false; |
3116 | 585 | return false; |
3117 | 585 | } |
3118 | 193 | |
3119 | 193 | // FIXME: we do not output a relocation section when --emit-relocs is used |
3120 | 193 | // as we do not have relocation sections for linker generated table entries |
3121 | 193 | // and we would have to erase at a late stage relocations from merged entries. |
3122 | 193 | // Given that exception tables are already position independent and a binary |
3123 | 193 | // analyzer could derive the relocations we choose to erase the relocations. |
3124 | 193 | if (config->emitRelocs && isec->type == SHT_REL8 ) |
3125 | 5 | if (InputSectionBase *ex = isec->getRelocatedSection()) |
3126 | 5 | if (isa<InputSection>(ex) && ex->type == SHT_ARM_EXIDX) |
3127 | 5 | return true; |
3128 | 188 | |
3129 | 188 | return false; |
3130 | 188 | } |
3131 | | |
3132 | | // References to .ARM.Extab Sections have bit 31 clear and are not the |
3133 | | // special EXIDX_CANTUNWIND bit-pattern. |
3134 | 48 | static bool isExtabRef(uint32_t unwind) { |
3135 | 48 | return (unwind & 0x80000000) == 0 && unwind != 0x131 ; |
3136 | 48 | } |
3137 | | |
3138 | | // Return true if the .ARM.exidx section Cur can be merged into the .ARM.exidx |
3139 | | // section Prev, where Cur follows Prev in the table. This can be done if the |
3140 | | // unwinding instructions in Cur are identical to Prev. Linker generated |
3141 | | // EXIDX_CANTUNWIND entries are represented by nullptr as they do not have an |
3142 | | // InputSection. |
3143 | 28 | static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) { |
3144 | 28 | |
3145 | 28 | struct ExidxEntry { |
3146 | 28 | ulittle32_t fn; |
3147 | 28 | ulittle32_t unwind; |
3148 | 28 | }; |
3149 | 28 | // Get the last table Entry from the previous .ARM.exidx section. If Prev is |
3150 | 28 | // nullptr then it will be a synthesized EXIDX_CANTUNWIND entry. |
3151 | 28 | ExidxEntry prevEntry = {ulittle32_t(0), ulittle32_t(1)}; |
3152 | 28 | if (prev) |
3153 | 22 | prevEntry = prev->getDataAs<ExidxEntry>().back(); |
3154 | 28 | if (isExtabRef(prevEntry.unwind)) |
3155 | 4 | return false; |
3156 | 24 | |
3157 | 24 | // We consider the unwind instructions of an .ARM.exidx table entry |
3158 | 24 | // a duplicate if the previous unwind instructions if: |
3159 | 24 | // - Both are the special EXIDX_CANTUNWIND. |
3160 | 24 | // - Both are the same inline unwind instructions. |
3161 | 24 | // We do not attempt to follow and check links into .ARM.extab tables as |
3162 | 24 | // consecutive identical entries are rare and the effort to check that they |
3163 | 24 | // are identical is high. |
3164 | 24 | |
3165 | 24 | // If Cur is nullptr then this is synthesized EXIDX_CANTUNWIND entry. |
3166 | 24 | if (cur == nullptr) |
3167 | 6 | return prevEntry.unwind == 1; |
3168 | 18 | |
3169 | 18 | for (const ExidxEntry entry : cur->getDataAs<ExidxEntry>()) |
3170 | 20 | if (isExtabRef(entry.unwind) || entry.unwind != prevEntry.unwind17 ) |
3171 | 8 | return false; |
3172 | 18 | |
3173 | 18 | // All table entries in this .ARM.exidx Section can be merged into the |
3174 | 18 | // previous Section. |
3175 | 18 | return true10 ; |
3176 | 18 | } |
3177 | | |
3178 | | // The .ARM.exidx table must be sorted in ascending order of the address of the |
3179 | | // functions the table describes. Optionally duplicate adjacent table entries |
3180 | | // can be removed. At the end of the function the ExecutableSections must be |
3181 | | // sorted in ascending order of address, Sentinel is set to the InputSection |
3182 | | // with the highest address and any InputSections that have mergeable |
3183 | | // .ARM.exidx table entries are removed from it. |
3184 | 26 | void ARMExidxSyntheticSection::finalizeContents() { |
3185 | 26 | // Sort the executable sections that may or may not have associated |
3186 | 26 | // .ARM.exidx sections by order of ascending address. This requires the |
3187 | 26 | // relative positions of InputSections to be known. |
3188 | 26 | auto compareByFilePosition = [](const InputSection *a, |
3189 | 64 | const InputSection *b) { |
3190 | 64 | OutputSection *aOut = a->getParent(); |
3191 | 64 | OutputSection *bOut = b->getParent(); |
3192 | 64 | |
3193 | 64 | if (aOut != bOut) |
3194 | 16 | return aOut->sectionIndex < bOut->sectionIndex; |
3195 | 48 | return a->outSecOff < b->outSecOff; |
3196 | 48 | }; |
3197 | 26 | llvm::stable_sort(executableSections, compareByFilePosition); |
3198 | 26 | sentinel = executableSections.back(); |
3199 | 26 | // Optionally merge adjacent duplicate entries. |
3200 | 26 | if (config->mergeArmExidx) { |
3201 | 18 | std::vector<InputSection *> selectedSections; |
3202 | 18 | selectedSections.reserve(executableSections.size()); |
3203 | 18 | selectedSections.push_back(executableSections[0]); |
3204 | 18 | size_t prev = 0; |
3205 | 46 | for (size_t i = 1; i < executableSections.size(); ++i28 ) { |
3206 | 28 | InputSection *ex1 = findExidxSection(executableSections[prev]); |
3207 | 28 | InputSection *ex2 = findExidxSection(executableSections[i]); |
3208 | 28 | if (!isDuplicateArmExidxSec(ex1, ex2)) { |
3209 | 15 | selectedSections.push_back(executableSections[i]); |
3210 | 15 | prev = i; |
3211 | 15 | } |
3212 | 28 | } |
3213 | 18 | executableSections = std::move(selectedSections); |
3214 | 18 | } |
3215 | 26 | |
3216 | 26 | size_t offset = 0; |
3217 | 26 | size = 0; |
3218 | 68 | for (InputSection *isec : executableSections) { |
3219 | 68 | if (InputSection *d = findExidxSection(isec)) { |
3220 | 55 | d->outSecOff = offset; |
3221 | 55 | d->parent = getParent(); |
3222 | 55 | offset += d->getSize(); |
3223 | 55 | } else { |
3224 | 13 | offset += 8; |
3225 | 13 | } |
3226 | 68 | } |
3227 | 26 | // Size includes Sentinel. |
3228 | 26 | size = offset + 8; |
3229 | 26 | } |
3230 | | |
3231 | 26 | InputSection *ARMExidxSyntheticSection::getLinkOrderDep() const { |
3232 | 26 | return executableSections.front(); |
3233 | 26 | } |
3234 | | |
3235 | | // To write the .ARM.exidx table from the ExecutableSections we have three cases |
3236 | | // 1.) The InputSection has a .ARM.exidx InputSection in its dependent sections. |
3237 | | // We write the .ARM.exidx section contents and apply its relocations. |
3238 | | // 2.) The InputSection does not have a dependent .ARM.exidx InputSection. We |
3239 | | // must write the contents of an EXIDX_CANTUNWIND directly. We use the |
3240 | | // start of the InputSection as the purpose of the linker generated |
3241 | | // section is to terminate the address range of the previous entry. |
3242 | | // 3.) A trailing EXIDX_CANTUNWIND sentinel section is required at the end of |
3243 | | // the table to terminate the address range of the final entry. |
3244 | 26 | void ARMExidxSyntheticSection::writeTo(uint8_t *buf) { |
3245 | 26 | |
3246 | 26 | const uint8_t cantUnwindData[8] = {0, 0, 0, 0, // PREL31 to target |
3247 | 26 | 1, 0, 0, 0}; // EXIDX_CANTUNWIND |
3248 | 26 | |
3249 | 26 | uint64_t offset = 0; |
3250 | 68 | for (InputSection *isec : executableSections) { |
3251 | 68 | assert(isec->getParent() != nullptr); |
3252 | 68 | if (InputSection *d = findExidxSection(isec)) { |
3253 | 55 | memcpy(buf + offset, d->data().data(), d->data().size()); |
3254 | 55 | d->relocateAlloc(buf, buf + d->getSize()); |
3255 | 55 | offset += d->getSize(); |
3256 | 55 | } else { |
3257 | 13 | // A Linker generated CANTUNWIND section. |
3258 | 13 | memcpy(buf + offset, cantUnwindData, sizeof(cantUnwindData)); |
3259 | 13 | uint64_t s = isec->getVA(); |
3260 | 13 | uint64_t p = getVA() + offset; |
3261 | 13 | target->relocateOne(buf + offset, R_ARM_PREL31, s - p); |
3262 | 13 | offset += 8; |
3263 | 13 | } |
3264 | 68 | } |
3265 | 26 | // Write Sentinel. |
3266 | 26 | memcpy(buf + offset, cantUnwindData, sizeof(cantUnwindData)); |
3267 | 26 | uint64_t s = sentinel->getVA(sentinel->getSize()); |
3268 | 26 | uint64_t p = getVA() + offset; |
3269 | 26 | target->relocateOne(buf + offset, R_ARM_PREL31, s - p); |
3270 | 26 | assert(size == offset + 8); |
3271 | 26 | } |
3272 | | |
3273 | 44 | bool ARMExidxSyntheticSection::classof(const SectionBase *d) { |
3274 | 44 | return d->kind() == InputSectionBase::Synthetic && d->type == SHT_ARM_EXIDX26 ; |
3275 | 44 | } |
3276 | | |
3277 | | ThunkSection::ThunkSection(OutputSection *os, uint64_t off) |
3278 | | : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, |
3279 | 767 | config->wordsize, ".text.thunk") { |
3280 | 767 | this->parent = os; |
3281 | 767 | this->outSecOff = off; |
3282 | 767 | } |
3283 | | |
3284 | 214 | void ThunkSection::addThunk(Thunk *t) { |
3285 | 214 | thunks.push_back(t); |
3286 | 214 | t->addSymbols(*this); |
3287 | 214 | } |
3288 | | |
3289 | 144 | void ThunkSection::writeTo(uint8_t *buf) { |
3290 | 144 | for (Thunk *t : thunks) |
3291 | 214 | t->writeTo(buf + t->offset); |
3292 | 144 | } |
3293 | | |
3294 | 109 | InputSection *ThunkSection::getTargetInputSection() const { |
3295 | 109 | if (thunks.empty()) |
3296 | 0 | return nullptr; |
3297 | 109 | const Thunk *t = thunks.front(); |
3298 | 109 | return t->getTargetInputSection(); |
3299 | 109 | } |
3300 | | |
3301 | 976 | bool ThunkSection::assignOffsets() { |
3302 | 976 | uint64_t off = 0; |
3303 | 976 | for (Thunk *t : thunks) { |
3304 | 512 | off = alignTo(off, t->alignment); |
3305 | 512 | t->setOffset(off); |
3306 | 512 | uint32_t size = t->size(); |
3307 | 512 | t->getThunkTargetSym()->size = size; |
3308 | 512 | off += size; |
3309 | 512 | } |
3310 | 976 | bool changed = off != size; |
3311 | 976 | size = off; |
3312 | 976 | return changed; |
3313 | 976 | } |
3314 | | |
3315 | | PPC32Got2Section::PPC32Got2Section() |
3316 | 31 | : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, 4, ".got2") {} |
3317 | | |
3318 | 62 | bool PPC32Got2Section::isNeeded() const { |
3319 | 62 | // See the comment below. This is not needed if there is no other |
3320 | 62 | // InputSection. |
3321 | 62 | for (BaseCommand *base : getParent()->sectionCommands) |
3322 | 62 | if (auto *isd = dyn_cast<InputSectionDescription>(base)) |
3323 | 62 | for (InputSection *isec : isd->sections) |
3324 | 34 | if (isec != this) |
3325 | 6 | return true; |
3326 | 62 | return false56 ; |
3327 | 62 | } |
3328 | | |
3329 | 3 | void PPC32Got2Section::finalizeContents() { |
3330 | 3 | // PPC32 may create multiple GOT sections for -fPIC/-fPIE, one per file in |
3331 | 3 | // .got2 . This function computes outSecOff of each .got2 to be used in |
3332 | 3 | // PPC32PltCallStub::writeTo(). The purpose of this empty synthetic section is |
3333 | 3 | // to collect input sections named ".got2". |
3334 | 3 | uint32_t offset = 0; |
3335 | 3 | for (BaseCommand *base : getParent()->sectionCommands) |
3336 | 3 | if (auto *isd = dyn_cast<InputSectionDescription>(base)) { |
3337 | 6 | for (InputSection *isec : isd->sections) { |
3338 | 6 | if (isec == this) |
3339 | 3 | continue; |
3340 | 3 | isec->file->ppc32Got2OutSecOff = offset; |
3341 | 3 | offset += (uint32_t)isec->getSize(); |
3342 | 3 | } |
3343 | 3 | } |
3344 | 3 | } |
3345 | | |
3346 | | // If linking position-dependent code then the table will store the addresses |
3347 | | // directly in the binary so the section has type SHT_PROGBITS. If linking |
3348 | | // position-independent code the section has type SHT_NOBITS since it will be |
3349 | | // allocated and filled in by the dynamic linker. |
3350 | | PPC64LongBranchTargetSection::PPC64LongBranchTargetSection() |
3351 | | : SyntheticSection(SHF_ALLOC | SHF_WRITE, |
3352 | | config->isPic ? SHT_NOBITS : SHT_PROGBITS, 8, |
3353 | 152 | ".branch_lt") {} |
3354 | | |
3355 | 9 | void PPC64LongBranchTargetSection::addEntry(Symbol &sym) { |
3356 | 9 | assert(sym.ppc64BranchltIndex == 0xffff); |
3357 | 9 | sym.ppc64BranchltIndex = entries.size(); |
3358 | 9 | entries.push_back(&sym); |
3359 | 9 | } |
3360 | | |
3361 | 659 | size_t PPC64LongBranchTargetSection::getSize() const { |
3362 | 659 | return entries.size() * 8; |
3363 | 659 | } |
3364 | | |
3365 | 99 | void PPC64LongBranchTargetSection::writeTo(uint8_t *buf) { |
3366 | 99 | // If linking non-pic we have the final addresses of the targets and they get |
3367 | 99 | // written to the table directly. For pic the dynamic linker will allocate |
3368 | 99 | // the section and fill it it. |
3369 | 99 | if (config->isPic) |
3370 | 0 | return; |
3371 | 99 | |
3372 | 99 | for (const Symbol *sym : entries) { |
3373 | 8 | assert(sym->getVA()); |
3374 | 8 | // Need calls to branch to the local entry-point since a long-branch |
3375 | 8 | // must be a local-call. |
3376 | 8 | write64(buf, |
3377 | 8 | sym->getVA() + getPPC64GlobalEntryToLocalEntryOffset(sym->stOther)); |
3378 | 8 | buf += 8; |
3379 | 8 | } |
3380 | 99 | } |
3381 | | |
3382 | 298 | bool PPC64LongBranchTargetSection::isNeeded() const { |
3383 | 298 | // `removeUnusedSyntheticSections()` is called before thunk allocation which |
3384 | 298 | // is too early to determine if this section will be empty or not. We need |
3385 | 298 | // Finalized to keep the section alive until after thunk creation. Finalized |
3386 | 298 | // only gets set to true once `finalizeSections()` is called after thunk |
3387 | 298 | // creation. Becuase of this, if we don't create any long-branch thunks we end |
3388 | 298 | // up with an empty .branch_lt section in the binary. |
3389 | 298 | return !finalized || !entries.empty()0 ; |
3390 | 298 | } |
3391 | | |
3392 | | RISCVSdataSection::RISCVSdataSection() |
3393 | 90 | : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, 1, ".sdata") {} |
3394 | | |
3395 | 174 | bool RISCVSdataSection::isNeeded() const { |
3396 | 174 | if (!ElfSym::riscvGlobalPointer) |
3397 | 166 | return false; |
3398 | 8 | |
3399 | 8 | // __global_pointer$ is defined relative to .sdata . If the section does not |
3400 | 8 | // exist, create a dummy one. |
3401 | 8 | for (BaseCommand *base : getParent()->sectionCommands) |
3402 | 8 | if (auto *isd = dyn_cast<InputSectionDescription>(base)) |
3403 | 8 | for (InputSection *isec : isd->sections) |
3404 | 8 | if (isec != this) |
3405 | 4 | return false; |
3406 | 8 | return true4 ; |
3407 | 8 | } |
3408 | | |
3409 | 2.58k | static uint8_t getAbiVersion() { |
3410 | 2.58k | // MIPS non-PIC executable gets ABI version 1. |
3411 | 2.58k | if (config->emachine == EM_MIPS) { |
3412 | 187 | if (!config->isPic && !config->relocatable113 && |
3413 | 187 | (config->eflags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC99 ) |
3414 | 91 | return 1; |
3415 | 96 | return 0; |
3416 | 96 | } |
3417 | 2.39k | |
3418 | 2.39k | if (config->emachine == EM_AMDGPU) { |
3419 | 8 | uint8_t ver = objectFiles[0]->abiVersion; |
3420 | 8 | for (InputFile *file : makeArrayRef(objectFiles).slice(1)) |
3421 | 2 | if (file->abiVersion != ver) |
3422 | 1 | error("incompatible ABI version: " + toString(file)); |
3423 | 8 | return ver; |
3424 | 8 | } |
3425 | 2.38k | |
3426 | 2.38k | return 0; |
3427 | 2.38k | } |
3428 | | |
3429 | 2.58k | template <typename ELFT> void elf::writeEhdr(uint8_t *buf, Partition &part) { |
3430 | 2.58k | // For executable segments, the trap instructions are written before writing |
3431 | 2.58k | // the header. Setting Elf header bytes to zero ensures that any unused bytes |
3432 | 2.58k | // in header are zero-cleared, instead of having trap instructions. |
3433 | 2.58k | memset(buf, 0, sizeof(typename ELFT::Ehdr)); |
3434 | 2.58k | memcpy(buf, "\177ELF", 4); |
3435 | 2.58k | |
3436 | 2.58k | auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf); |
3437 | 2.58k | eHdr->e_ident[EI_CLASS] = config->is64 ? ELFCLASS642.06k : ELFCLASS32522 ; |
3438 | 2.58k | eHdr->e_ident[EI_DATA] = config->isLE ? ELFDATA2LSB2.32k : ELFDATA2MSB255 ; |
3439 | 2.58k | eHdr->e_ident[EI_VERSION] = EV_CURRENT; |
3440 | 2.58k | eHdr->e_ident[EI_OSABI] = config->osabi; |
3441 | 2.58k | eHdr->e_ident[EI_ABIVERSION] = getAbiVersion(); |
3442 | 2.58k | eHdr->e_machine = config->emachine; |
3443 | 2.58k | eHdr->e_version = EV_CURRENT; |
3444 | 2.58k | eHdr->e_flags = config->eflags; |
3445 | 2.58k | eHdr->e_ehsize = sizeof(typename ELFT::Ehdr); |
3446 | 2.58k | eHdr->e_phnum = part.phdrs.size(); |
3447 | 2.58k | eHdr->e_shentsize = sizeof(typename ELFT::Shdr); |
3448 | 2.58k | |
3449 | 2.58k | if (!config->relocatable) { |
3450 | 2.49k | eHdr->e_phoff = sizeof(typename ELFT::Ehdr); |
3451 | 2.49k | eHdr->e_phentsize = sizeof(typename ELFT::Phdr); |
3452 | 2.49k | } |
3453 | 2.58k | } void lld::elf::writeEhdr<llvm::object::ELFType<(llvm::support::endianness)1, false> >(unsigned char*, lld::elf::Partition&) Line | Count | Source | 3429 | 368 | template <typename ELFT> void elf::writeEhdr(uint8_t *buf, Partition &part) { | 3430 | 368 | // For executable segments, the trap instructions are written before writing | 3431 | 368 | // the header. Setting Elf header bytes to zero ensures that any unused bytes | 3432 | 368 | // in header are zero-cleared, instead of having trap instructions. | 3433 | 368 | memset(buf, 0, sizeof(typename ELFT::Ehdr)); | 3434 | 368 | memcpy(buf, "\177ELF", 4); | 3435 | 368 | | 3436 | 368 | auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf); | 3437 | 368 | eHdr->e_ident[EI_CLASS] = config->is64 ? ELFCLASS640 : ELFCLASS32; | 3438 | 368 | eHdr->e_ident[EI_DATA] = config->isLE ? ELFDATA2LSB : ELFDATA2MSB0 ; | 3439 | 368 | eHdr->e_ident[EI_VERSION] = EV_CURRENT; | 3440 | 368 | eHdr->e_ident[EI_OSABI] = config->osabi; | 3441 | 368 | eHdr->e_ident[EI_ABIVERSION] = getAbiVersion(); | 3442 | 368 | eHdr->e_machine = config->emachine; | 3443 | 368 | eHdr->e_version = EV_CURRENT; | 3444 | 368 | eHdr->e_flags = config->eflags; | 3445 | 368 | eHdr->e_ehsize = sizeof(typename ELFT::Ehdr); | 3446 | 368 | eHdr->e_phnum = part.phdrs.size(); | 3447 | 368 | eHdr->e_shentsize = sizeof(typename ELFT::Shdr); | 3448 | 368 | | 3449 | 368 | if (!config->relocatable) { | 3450 | 357 | eHdr->e_phoff = sizeof(typename ELFT::Ehdr); | 3451 | 357 | eHdr->e_phentsize = sizeof(typename ELFT::Phdr); | 3452 | 357 | } | 3453 | 368 | } |
void lld::elf::writeEhdr<llvm::object::ELFType<(llvm::support::endianness)0, false> >(unsigned char*, lld::elf::Partition&) Line | Count | Source | 3429 | 154 | template <typename ELFT> void elf::writeEhdr(uint8_t *buf, Partition &part) { | 3430 | 154 | // For executable segments, the trap instructions are written before writing | 3431 | 154 | // the header. Setting Elf header bytes to zero ensures that any unused bytes | 3432 | 154 | // in header are zero-cleared, instead of having trap instructions. | 3433 | 154 | memset(buf, 0, sizeof(typename ELFT::Ehdr)); | 3434 | 154 | memcpy(buf, "\177ELF", 4); | 3435 | 154 | | 3436 | 154 | auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf); | 3437 | 154 | eHdr->e_ident[EI_CLASS] = config->is64 ? ELFCLASS640 : ELFCLASS32; | 3438 | 154 | eHdr->e_ident[EI_DATA] = config->isLE ? ELFDATA2LSB0 : ELFDATA2MSB; | 3439 | 154 | eHdr->e_ident[EI_VERSION] = EV_CURRENT; | 3440 | 154 | eHdr->e_ident[EI_OSABI] = config->osabi; | 3441 | 154 | eHdr->e_ident[EI_ABIVERSION] = getAbiVersion(); | 3442 | 154 | eHdr->e_machine = config->emachine; | 3443 | 154 | eHdr->e_version = EV_CURRENT; | 3444 | 154 | eHdr->e_flags = config->eflags; | 3445 | 154 | eHdr->e_ehsize = sizeof(typename ELFT::Ehdr); | 3446 | 154 | eHdr->e_phnum = part.phdrs.size(); | 3447 | 154 | eHdr->e_shentsize = sizeof(typename ELFT::Shdr); | 3448 | 154 | | 3449 | 154 | if (!config->relocatable) { | 3450 | 143 | eHdr->e_phoff = sizeof(typename ELFT::Ehdr); | 3451 | 143 | eHdr->e_phentsize = sizeof(typename ELFT::Phdr); | 3452 | 143 | } | 3453 | 154 | } |
void lld::elf::writeEhdr<llvm::object::ELFType<(llvm::support::endianness)1, true> >(unsigned char*, lld::elf::Partition&) Line | Count | Source | 3429 | 1.96k | template <typename ELFT> void elf::writeEhdr(uint8_t *buf, Partition &part) { | 3430 | 1.96k | // For executable segments, the trap instructions are written before writing | 3431 | 1.96k | // the header. Setting Elf header bytes to zero ensures that any unused bytes | 3432 | 1.96k | // in header are zero-cleared, instead of having trap instructions. | 3433 | 1.96k | memset(buf, 0, sizeof(typename ELFT::Ehdr)); | 3434 | 1.96k | memcpy(buf, "\177ELF", 4); | 3435 | 1.96k | | 3436 | 1.96k | auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf); | 3437 | 1.96k | eHdr->e_ident[EI_CLASS] = config->is64 ? ELFCLASS64 : ELFCLASS320 ; | 3438 | 1.96k | eHdr->e_ident[EI_DATA] = config->isLE ? ELFDATA2LSB : ELFDATA2MSB0 ; | 3439 | 1.96k | eHdr->e_ident[EI_VERSION] = EV_CURRENT; | 3440 | 1.96k | eHdr->e_ident[EI_OSABI] = config->osabi; | 3441 | 1.96k | eHdr->e_ident[EI_ABIVERSION] = getAbiVersion(); | 3442 | 1.96k | eHdr->e_machine = config->emachine; | 3443 | 1.96k | eHdr->e_version = EV_CURRENT; | 3444 | 1.96k | eHdr->e_flags = config->eflags; | 3445 | 1.96k | eHdr->e_ehsize = sizeof(typename ELFT::Ehdr); | 3446 | 1.96k | eHdr->e_phnum = part.phdrs.size(); | 3447 | 1.96k | eHdr->e_shentsize = sizeof(typename ELFT::Shdr); | 3448 | 1.96k | | 3449 | 1.96k | if (!config->relocatable) { | 3450 | 1.89k | eHdr->e_phoff = sizeof(typename ELFT::Ehdr); | 3451 | 1.89k | eHdr->e_phentsize = sizeof(typename ELFT::Phdr); | 3452 | 1.89k | } | 3453 | 1.96k | } |
void lld::elf::writeEhdr<llvm::object::ELFType<(llvm::support::endianness)0, true> >(unsigned char*, lld::elf::Partition&) Line | Count | Source | 3429 | 101 | template <typename ELFT> void elf::writeEhdr(uint8_t *buf, Partition &part) { | 3430 | 101 | // For executable segments, the trap instructions are written before writing | 3431 | 101 | // the header. Setting Elf header bytes to zero ensures that any unused bytes | 3432 | 101 | // in header are zero-cleared, instead of having trap instructions. | 3433 | 101 | memset(buf, 0, sizeof(typename ELFT::Ehdr)); | 3434 | 101 | memcpy(buf, "\177ELF", 4); | 3435 | 101 | | 3436 | 101 | auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf); | 3437 | 101 | eHdr->e_ident[EI_CLASS] = config->is64 ? ELFCLASS64 : ELFCLASS320 ; | 3438 | 101 | eHdr->e_ident[EI_DATA] = config->isLE ? ELFDATA2LSB0 : ELFDATA2MSB; | 3439 | 101 | eHdr->e_ident[EI_VERSION] = EV_CURRENT; | 3440 | 101 | eHdr->e_ident[EI_OSABI] = config->osabi; | 3441 | 101 | eHdr->e_ident[EI_ABIVERSION] = getAbiVersion(); | 3442 | 101 | eHdr->e_machine = config->emachine; | 3443 | 101 | eHdr->e_version = EV_CURRENT; | 3444 | 101 | eHdr->e_flags = config->eflags; | 3445 | 101 | eHdr->e_ehsize = sizeof(typename ELFT::Ehdr); | 3446 | 101 | eHdr->e_phnum = part.phdrs.size(); | 3447 | 101 | eHdr->e_shentsize = sizeof(typename ELFT::Shdr); | 3448 | 101 | | 3449 | 101 | if (!config->relocatable) { | 3450 | 98 | eHdr->e_phoff = sizeof(typename ELFT::Ehdr); | 3451 | 98 | eHdr->e_phentsize = sizeof(typename ELFT::Phdr); | 3452 | 98 | } | 3453 | 101 | } |
|
3454 | | |
3455 | 2.58k | template <typename ELFT> void elf::writePhdrs(uint8_t *buf, Partition &part) { |
3456 | 2.58k | // Write the program header table. |
3457 | 2.58k | auto *hBuf = reinterpret_cast<typename ELFT::Phdr *>(buf); |
3458 | 13.7k | for (PhdrEntry *p : part.phdrs) { |
3459 | 13.7k | hBuf->p_type = p->p_type; |
3460 | 13.7k | hBuf->p_flags = p->p_flags; |
3461 | 13.7k | hBuf->p_offset = p->p_offset; |
3462 | 13.7k | hBuf->p_vaddr = p->p_vaddr; |
3463 | 13.7k | hBuf->p_paddr = p->p_paddr; |
3464 | 13.7k | hBuf->p_filesz = p->p_filesz; |
3465 | 13.7k | hBuf->p_memsz = p->p_memsz; |
3466 | 13.7k | hBuf->p_align = p->p_align; |
3467 | 13.7k | ++hBuf; |
3468 | 13.7k | } |
3469 | 2.58k | } void lld::elf::writePhdrs<llvm::object::ELFType<(llvm::support::endianness)1, false> >(unsigned char*, lld::elf::Partition&) Line | Count | Source | 3455 | 368 | template <typename ELFT> void elf::writePhdrs(uint8_t *buf, Partition &part) { | 3456 | 368 | // Write the program header table. | 3457 | 368 | auto *hBuf = reinterpret_cast<typename ELFT::Phdr *>(buf); | 3458 | 2.03k | for (PhdrEntry *p : part.phdrs) { | 3459 | 2.03k | hBuf->p_type = p->p_type; | 3460 | 2.03k | hBuf->p_flags = p->p_flags; | 3461 | 2.03k | hBuf->p_offset = p->p_offset; | 3462 | 2.03k | hBuf->p_vaddr = p->p_vaddr; | 3463 | 2.03k | hBuf->p_paddr = p->p_paddr; | 3464 | 2.03k | hBuf->p_filesz = p->p_filesz; | 3465 | 2.03k | hBuf->p_memsz = p->p_memsz; | 3466 | 2.03k | hBuf->p_align = p->p_align; | 3467 | 2.03k | ++hBuf; | 3468 | 2.03k | } | 3469 | 368 | } |
void lld::elf::writePhdrs<llvm::object::ELFType<(llvm::support::endianness)0, false> >(unsigned char*, lld::elf::Partition&) Line | Count | Source | 3455 | 154 | template <typename ELFT> void elf::writePhdrs(uint8_t *buf, Partition &part) { | 3456 | 154 | // Write the program header table. | 3457 | 154 | auto *hBuf = reinterpret_cast<typename ELFT::Phdr *>(buf); | 3458 | 1.02k | for (PhdrEntry *p : part.phdrs) { | 3459 | 1.02k | hBuf->p_type = p->p_type; | 3460 | 1.02k | hBuf->p_flags = p->p_flags; | 3461 | 1.02k | hBuf->p_offset = p->p_offset; | 3462 | 1.02k | hBuf->p_vaddr = p->p_vaddr; | 3463 | 1.02k | hBuf->p_paddr = p->p_paddr; | 3464 | 1.02k | hBuf->p_filesz = p->p_filesz; | 3465 | 1.02k | hBuf->p_memsz = p->p_memsz; | 3466 | 1.02k | hBuf->p_align = p->p_align; | 3467 | 1.02k | ++hBuf; | 3468 | 1.02k | } | 3469 | 154 | } |
void lld::elf::writePhdrs<llvm::object::ELFType<(llvm::support::endianness)1, true> >(unsigned char*, lld::elf::Partition&) Line | Count | Source | 3455 | 1.96k | template <typename ELFT> void elf::writePhdrs(uint8_t *buf, Partition &part) { | 3456 | 1.96k | // Write the program header table. | 3457 | 1.96k | auto *hBuf = reinterpret_cast<typename ELFT::Phdr *>(buf); | 3458 | 10.0k | for (PhdrEntry *p : part.phdrs) { | 3459 | 10.0k | hBuf->p_type = p->p_type; | 3460 | 10.0k | hBuf->p_flags = p->p_flags; | 3461 | 10.0k | hBuf->p_offset = p->p_offset; | 3462 | 10.0k | hBuf->p_vaddr = p->p_vaddr; | 3463 | 10.0k | hBuf->p_paddr = p->p_paddr; | 3464 | 10.0k | hBuf->p_filesz = p->p_filesz; | 3465 | 10.0k | hBuf->p_memsz = p->p_memsz; | 3466 | 10.0k | hBuf->p_align = p->p_align; | 3467 | 10.0k | ++hBuf; | 3468 | 10.0k | } | 3469 | 1.96k | } |
void lld::elf::writePhdrs<llvm::object::ELFType<(llvm::support::endianness)0, true> >(unsigned char*, lld::elf::Partition&) Line | Count | Source | 3455 | 101 | template <typename ELFT> void elf::writePhdrs(uint8_t *buf, Partition &part) { | 3456 | 101 | // Write the program header table. | 3457 | 101 | auto *hBuf = reinterpret_cast<typename ELFT::Phdr *>(buf); | 3458 | 682 | for (PhdrEntry *p : part.phdrs) { | 3459 | 682 | hBuf->p_type = p->p_type; | 3460 | 682 | hBuf->p_flags = p->p_flags; | 3461 | 682 | hBuf->p_offset = p->p_offset; | 3462 | 682 | hBuf->p_vaddr = p->p_vaddr; | 3463 | 682 | hBuf->p_paddr = p->p_paddr; | 3464 | 682 | hBuf->p_filesz = p->p_filesz; | 3465 | 682 | hBuf->p_memsz = p->p_memsz; | 3466 | 682 | hBuf->p_align = p->p_align; | 3467 | 682 | ++hBuf; | 3468 | 682 | } | 3469 | 101 | } |
|
3470 | | |
3471 | | template <typename ELFT> |
3472 | | PartitionElfHeaderSection<ELFT>::PartitionElfHeaderSection() |
3473 | 18 | : SyntheticSection(SHF_ALLOC, SHT_LLVM_PART_EHDR, 1, "") {} lld::elf::PartitionElfHeaderSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::PartitionElfHeaderSection() Line | Count | Source | 3473 | 4 | : SyntheticSection(SHF_ALLOC, SHT_LLVM_PART_EHDR, 1, "") {} |
Unexecuted instantiation: lld::elf::PartitionElfHeaderSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::PartitionElfHeaderSection() lld::elf::PartitionElfHeaderSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::PartitionElfHeaderSection() Line | Count | Source | 3473 | 14 | : SyntheticSection(SHF_ALLOC, SHT_LLVM_PART_EHDR, 1, "") {} |
Unexecuted instantiation: lld::elf::PartitionElfHeaderSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::PartitionElfHeaderSection() |
3474 | | |
3475 | | template <typename ELFT> |
3476 | 50 | size_t PartitionElfHeaderSection<ELFT>::getSize() const { |
3477 | 50 | return sizeof(typename ELFT::Ehdr); |
3478 | 50 | } lld::elf::PartitionElfHeaderSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::getSize() const Line | Count | Source | 3476 | 16 | size_t PartitionElfHeaderSection<ELFT>::getSize() const { | 3477 | 16 | return sizeof(typename ELFT::Ehdr); | 3478 | 16 | } |
Unexecuted instantiation: lld::elf::PartitionElfHeaderSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::getSize() const lld::elf::PartitionElfHeaderSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::getSize() const Line | Count | Source | 3476 | 34 | size_t PartitionElfHeaderSection<ELFT>::getSize() const { | 3477 | 34 | return sizeof(typename ELFT::Ehdr); | 3478 | 34 | } |
Unexecuted instantiation: lld::elf::PartitionElfHeaderSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::getSize() const |
3479 | | |
3480 | | template <typename ELFT> |
3481 | 11 | void PartitionElfHeaderSection<ELFT>::writeTo(uint8_t *buf) { |
3482 | 11 | writeEhdr<ELFT>(buf, getPartition()); |
3483 | 11 | |
3484 | 11 | // Loadable partitions are always ET_DYN. |
3485 | 11 | auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf); |
3486 | 11 | eHdr->e_type = ET_DYN; |
3487 | 11 | } lld::elf::PartitionElfHeaderSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*) Line | Count | Source | 3481 | 3 | void PartitionElfHeaderSection<ELFT>::writeTo(uint8_t *buf) { | 3482 | 3 | writeEhdr<ELFT>(buf, getPartition()); | 3483 | 3 | | 3484 | 3 | // Loadable partitions are always ET_DYN. | 3485 | 3 | auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf); | 3486 | 3 | eHdr->e_type = ET_DYN; | 3487 | 3 | } |
Unexecuted instantiation: lld::elf::PartitionElfHeaderSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::writeTo(unsigned char*) lld::elf::PartitionElfHeaderSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeTo(unsigned char*) Line | Count | Source | 3481 | 8 | void PartitionElfHeaderSection<ELFT>::writeTo(uint8_t *buf) { | 3482 | 8 | writeEhdr<ELFT>(buf, getPartition()); | 3483 | 8 | | 3484 | 8 | // Loadable partitions are always ET_DYN. | 3485 | 8 | auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf); | 3486 | 8 | eHdr->e_type = ET_DYN; | 3487 | 8 | } |
Unexecuted instantiation: lld::elf::PartitionElfHeaderSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::writeTo(unsigned char*) |
3488 | | |
3489 | | template <typename ELFT> |
3490 | | PartitionProgramHeadersSection<ELFT>::PartitionProgramHeadersSection() |
3491 | 18 | : SyntheticSection(SHF_ALLOC, SHT_LLVM_PART_PHDR, 1, ".phdrs") {} lld::elf::PartitionProgramHeadersSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::PartitionProgramHeadersSection() Line | Count | Source | 3491 | 4 | : SyntheticSection(SHF_ALLOC, SHT_LLVM_PART_PHDR, 1, ".phdrs") {} |
Unexecuted instantiation: lld::elf::PartitionProgramHeadersSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::PartitionProgramHeadersSection() lld::elf::PartitionProgramHeadersSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::PartitionProgramHeadersSection() Line | Count | Source | 3491 | 14 | : SyntheticSection(SHF_ALLOC, SHT_LLVM_PART_PHDR, 1, ".phdrs") {} |
Unexecuted instantiation: lld::elf::PartitionProgramHeadersSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::PartitionProgramHeadersSection() |
3492 | | |
3493 | | template <typename ELFT> |
3494 | 50 | size_t PartitionProgramHeadersSection<ELFT>::getSize() const { |
3495 | 50 | return sizeof(typename ELFT::Phdr) * getPartition().phdrs.size(); |
3496 | 50 | } lld::elf::PartitionProgramHeadersSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::getSize() const Line | Count | Source | 3494 | 16 | size_t PartitionProgramHeadersSection<ELFT>::getSize() const { | 3495 | 16 | return sizeof(typename ELFT::Phdr) * getPartition().phdrs.size(); | 3496 | 16 | } |
Unexecuted instantiation: lld::elf::PartitionProgramHeadersSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::getSize() const lld::elf::PartitionProgramHeadersSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::getSize() const Line | Count | Source | 3494 | 34 | size_t PartitionProgramHeadersSection<ELFT>::getSize() const { | 3495 | 34 | return sizeof(typename ELFT::Phdr) * getPartition().phdrs.size(); | 3496 | 34 | } |
Unexecuted instantiation: lld::elf::PartitionProgramHeadersSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::getSize() const |
3497 | | |
3498 | | template <typename ELFT> |
3499 | 11 | void PartitionProgramHeadersSection<ELFT>::writeTo(uint8_t *buf) { |
3500 | 11 | writePhdrs<ELFT>(buf, getPartition()); |
3501 | 11 | } lld::elf::PartitionProgramHeadersSection<llvm::object::ELFType<(llvm::support::endianness)1, false> >::writeTo(unsigned char*) Line | Count | Source | 3499 | 3 | void PartitionProgramHeadersSection<ELFT>::writeTo(uint8_t *buf) { | 3500 | 3 | writePhdrs<ELFT>(buf, getPartition()); | 3501 | 3 | } |
Unexecuted instantiation: lld::elf::PartitionProgramHeadersSection<llvm::object::ELFType<(llvm::support::endianness)0, false> >::writeTo(unsigned char*) lld::elf::PartitionProgramHeadersSection<llvm::object::ELFType<(llvm::support::endianness)1, true> >::writeTo(unsigned char*) Line | Count | Source | 3499 | 8 | void PartitionProgramHeadersSection<ELFT>::writeTo(uint8_t *buf) { | 3500 | 8 | writePhdrs<ELFT>(buf, getPartition()); | 3501 | 8 | } |
Unexecuted instantiation: lld::elf::PartitionProgramHeadersSection<llvm::object::ELFType<(llvm::support::endianness)0, true> >::writeTo(unsigned char*) |
3502 | | |
3503 | | PartitionIndexSection::PartitionIndexSection() |
3504 | 15 | : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".rodata") {} |
3505 | | |
3506 | 51 | size_t PartitionIndexSection::getSize() const { |
3507 | 51 | return 12 * (partitions.size() - 1); |
3508 | 51 | } |
3509 | | |
3510 | 8 | void PartitionIndexSection::finalizeContents() { |
3511 | 19 | for (size_t i = 1; i != partitions.size(); ++i11 ) |
3512 | 11 | partitions[i].nameStrTab = mainPart->dynStrTab->addString(partitions[i].name); |
3513 | 8 | } |
3514 | | |
3515 | 8 | void PartitionIndexSection::writeTo(uint8_t *buf) { |
3516 | 8 | uint64_t va = getVA(); |
3517 | 19 | for (size_t i = 1; i != partitions.size(); ++i11 ) { |
3518 | 11 | write32(buf, mainPart->dynStrTab->getVA() + partitions[i].nameStrTab - va); |
3519 | 11 | write32(buf + 4, partitions[i].elfHeader->getVA() - (va + 4)); |
3520 | 11 | |
3521 | 11 | SyntheticSection *next = |
3522 | 11 | i == partitions.size() - 1 ? in.partEnd8 : partitions[i + 1].elfHeader3 ; |
3523 | 11 | write32(buf + 8, next->getVA() - partitions[i].elfHeader->getVA()); |
3524 | 11 | |
3525 | 11 | va += 12; |
3526 | 11 | buf += 12; |
3527 | 11 | } |
3528 | 8 | } |
3529 | | |
3530 | | InStruct elf::in; |
3531 | | |
3532 | | std::vector<Partition> elf::partitions; |
3533 | | Partition *elf::mainPart; |
3534 | | |
3535 | | template GdbIndexSection *GdbIndexSection::create<ELF32LE>(); |
3536 | | template GdbIndexSection *GdbIndexSection::create<ELF32BE>(); |
3537 | | template GdbIndexSection *GdbIndexSection::create<ELF64LE>(); |
3538 | | template GdbIndexSection *GdbIndexSection::create<ELF64BE>(); |
3539 | | |
3540 | | template void elf::splitSections<ELF32LE>(); |
3541 | | template void elf::splitSections<ELF32BE>(); |
3542 | | template void elf::splitSections<ELF64LE>(); |
3543 | | template void elf::splitSections<ELF64BE>(); |
3544 | | |
3545 | | template void EhFrameSection::addSection<ELF32LE>(InputSectionBase *); |
3546 | | template void EhFrameSection::addSection<ELF32BE>(InputSectionBase *); |
3547 | | template void EhFrameSection::addSection<ELF64LE>(InputSectionBase *); |
3548 | | template void EhFrameSection::addSection<ELF64BE>(InputSectionBase *); |
3549 | | |
3550 | | template void PltSection::addEntry<ELF32LE>(Symbol &Sym); |
3551 | | template void PltSection::addEntry<ELF32BE>(Symbol &Sym); |
3552 | | template void PltSection::addEntry<ELF64LE>(Symbol &Sym); |
3553 | | template void PltSection::addEntry<ELF64BE>(Symbol &Sym); |
3554 | | |
3555 | | template class elf::MipsAbiFlagsSection<ELF32LE>; |
3556 | | template class elf::MipsAbiFlagsSection<ELF32BE>; |
3557 | | template class elf::MipsAbiFlagsSection<ELF64LE>; |
3558 | | template class elf::MipsAbiFlagsSection<ELF64BE>; |
3559 | | |
3560 | | template class elf::MipsOptionsSection<ELF32LE>; |
3561 | | template class elf::MipsOptionsSection<ELF32BE>; |
3562 | | template class elf::MipsOptionsSection<ELF64LE>; |
3563 | | template class elf::MipsOptionsSection<ELF64BE>; |
3564 | | |
3565 | | template class elf::MipsReginfoSection<ELF32LE>; |
3566 | | template class elf::MipsReginfoSection<ELF32BE>; |
3567 | | template class elf::MipsReginfoSection<ELF64LE>; |
3568 | | template class elf::MipsReginfoSection<ELF64BE>; |
3569 | | |
3570 | | template class elf::DynamicSection<ELF32LE>; |
3571 | | template class elf::DynamicSection<ELF32BE>; |
3572 | | template class elf::DynamicSection<ELF64LE>; |
3573 | | template class elf::DynamicSection<ELF64BE>; |
3574 | | |
3575 | | template class elf::RelocationSection<ELF32LE>; |
3576 | | template class elf::RelocationSection<ELF32BE>; |
3577 | | template class elf::RelocationSection<ELF64LE>; |
3578 | | template class elf::RelocationSection<ELF64BE>; |
3579 | | |
3580 | | template class elf::AndroidPackedRelocationSection<ELF32LE>; |
3581 | | template class elf::AndroidPackedRelocationSection<ELF32BE>; |
3582 | | template class elf::AndroidPackedRelocationSection<ELF64LE>; |
3583 | | template class elf::AndroidPackedRelocationSection<ELF64BE>; |
3584 | | |
3585 | | template class elf::RelrSection<ELF32LE>; |
3586 | | template class elf::RelrSection<ELF32BE>; |
3587 | | template class elf::RelrSection<ELF64LE>; |
3588 | | template class elf::RelrSection<ELF64BE>; |
3589 | | |
3590 | | template class elf::SymbolTableSection<ELF32LE>; |
3591 | | template class elf::SymbolTableSection<ELF32BE>; |
3592 | | template class elf::SymbolTableSection<ELF64LE>; |
3593 | | template class elf::SymbolTableSection<ELF64BE>; |
3594 | | |
3595 | | template class elf::VersionNeedSection<ELF32LE>; |
3596 | | template class elf::VersionNeedSection<ELF32BE>; |
3597 | | template class elf::VersionNeedSection<ELF64LE>; |
3598 | | template class elf::VersionNeedSection<ELF64BE>; |
3599 | | |
3600 | | template void elf::writeEhdr<ELF32LE>(uint8_t *Buf, Partition &Part); |
3601 | | template void elf::writeEhdr<ELF32BE>(uint8_t *Buf, Partition &Part); |
3602 | | template void elf::writeEhdr<ELF64LE>(uint8_t *Buf, Partition &Part); |
3603 | | template void elf::writeEhdr<ELF64BE>(uint8_t *Buf, Partition &Part); |
3604 | | |
3605 | | template void elf::writePhdrs<ELF32LE>(uint8_t *Buf, Partition &Part); |
3606 | | template void elf::writePhdrs<ELF32BE>(uint8_t *Buf, Partition &Part); |
3607 | | template void elf::writePhdrs<ELF64LE>(uint8_t *Buf, Partition &Part); |
3608 | | template void elf::writePhdrs<ELF64BE>(uint8_t *Buf, Partition &Part); |
3609 | | |
3610 | | template class elf::PartitionElfHeaderSection<ELF32LE>; |
3611 | | template class elf::PartitionElfHeaderSection<ELF32BE>; |
3612 | | template class elf::PartitionElfHeaderSection<ELF64LE>; |
3613 | | template class elf::PartitionElfHeaderSection<ELF64BE>; |
3614 | | |
3615 | | template class elf::PartitionProgramHeadersSection<ELF32LE>; |
3616 | | template class elf::PartitionProgramHeadersSection<ELF32BE>; |
3617 | | template class elf::PartitionProgramHeadersSection<ELF64LE>; |
3618 | | template class elf::PartitionProgramHeadersSection<ELF64BE>; |