/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/MC/ELFObjectWriter.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -----------------------===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | // |
10 | | // This file implements ELF object file writer information. |
11 | | // |
12 | | //===----------------------------------------------------------------------===// |
13 | | |
14 | | #include "llvm/ADT/ArrayRef.h" |
15 | | #include "llvm/ADT/DenseMap.h" |
16 | | #include "llvm/ADT/STLExtras.h" |
17 | | #include "llvm/ADT/SmallString.h" |
18 | | #include "llvm/ADT/SmallVector.h" |
19 | | #include "llvm/ADT/StringRef.h" |
20 | | #include "llvm/ADT/Twine.h" |
21 | | #include "llvm/BinaryFormat/ELF.h" |
22 | | #include "llvm/MC/MCAsmBackend.h" |
23 | | #include "llvm/MC/MCAsmInfo.h" |
24 | | #include "llvm/MC/MCAsmLayout.h" |
25 | | #include "llvm/MC/MCAssembler.h" |
26 | | #include "llvm/MC/MCContext.h" |
27 | | #include "llvm/MC/MCELFObjectWriter.h" |
28 | | #include "llvm/MC/MCExpr.h" |
29 | | #include "llvm/MC/MCFixup.h" |
30 | | #include "llvm/MC/MCFixupKindInfo.h" |
31 | | #include "llvm/MC/MCFragment.h" |
32 | | #include "llvm/MC/MCObjectWriter.h" |
33 | | #include "llvm/MC/MCSection.h" |
34 | | #include "llvm/MC/MCSectionELF.h" |
35 | | #include "llvm/MC/MCSymbol.h" |
36 | | #include "llvm/MC/MCSymbolELF.h" |
37 | | #include "llvm/MC/MCValue.h" |
38 | | #include "llvm/MC/StringTableBuilder.h" |
39 | | #include "llvm/Support/Allocator.h" |
40 | | #include "llvm/Support/Casting.h" |
41 | | #include "llvm/Support/Compression.h" |
42 | | #include "llvm/Support/Endian.h" |
43 | | #include "llvm/Support/Error.h" |
44 | | #include "llvm/Support/ErrorHandling.h" |
45 | | #include "llvm/Support/Host.h" |
46 | | #include "llvm/Support/MathExtras.h" |
47 | | #include "llvm/Support/SMLoc.h" |
48 | | #include "llvm/Support/StringSaver.h" |
49 | | #include "llvm/Support/SwapByteOrder.h" |
50 | | #include "llvm/Support/raw_ostream.h" |
51 | | #include <algorithm> |
52 | | #include <cassert> |
53 | | #include <cstddef> |
54 | | #include <cstdint> |
55 | | #include <map> |
56 | | #include <memory> |
57 | | #include <string> |
58 | | #include <utility> |
59 | | #include <vector> |
60 | | |
61 | | using namespace llvm; |
62 | | |
63 | | #undef DEBUG_TYPE |
64 | | #define DEBUG_TYPE "reloc-info" |
65 | | |
66 | | namespace { |
67 | | |
68 | | using SectionIndexMapTy = DenseMap<const MCSectionELF *, uint32_t>; |
69 | | |
70 | | class ELFObjectWriter; |
71 | | |
72 | | class SymbolTableWriter { |
73 | | ELFObjectWriter &EWriter; |
74 | | bool Is64Bit; |
75 | | |
76 | | // indexes we are going to write to .symtab_shndx. |
77 | | std::vector<uint32_t> ShndxIndexes; |
78 | | |
79 | | // The numbel of symbols written so far. |
80 | | unsigned NumWritten; |
81 | | |
82 | | void createSymtabShndx(); |
83 | | |
84 | | template <typename T> void write(T Value); |
85 | | |
86 | | public: |
87 | | SymbolTableWriter(ELFObjectWriter &EWriter, bool Is64Bit); |
88 | | |
89 | | void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size, |
90 | | uint8_t other, uint32_t shndx, bool Reserved); |
91 | | |
92 | 2.78k | ArrayRef<uint32_t> getShndxIndexes() const { return ShndxIndexes; } |
93 | | }; |
94 | | |
95 | | class ELFObjectWriter : public MCObjectWriter { |
96 | | static uint64_t SymbolValue(const MCSymbol &Sym, const MCAsmLayout &Layout); |
97 | | static bool isInSymtab(const MCAsmLayout &Layout, const MCSymbolELF &Symbol, |
98 | | bool Used, bool Renamed); |
99 | | |
100 | | /// Helper struct for containing some precomputed information on symbols. |
101 | | struct ELFSymbolData { |
102 | | const MCSymbolELF *Symbol; |
103 | | uint32_t SectionIndex; |
104 | | StringRef Name; |
105 | | |
106 | | // Support lexicographic sorting. |
107 | 28.4k | bool operator<(const ELFSymbolData &RHS) const { |
108 | 28.4k | unsigned LHSType = Symbol->getType(); |
109 | 28.4k | unsigned RHSType = RHS.Symbol->getType(); |
110 | 28.4k | if (LHSType == ELF::STT_SECTION && 28.4k RHSType != ELF::STT_SECTION2.69k ) |
111 | 819 | return false; |
112 | 27.6k | if (27.6k LHSType != ELF::STT_SECTION && 27.6k RHSType == ELF::STT_SECTION25.7k ) |
113 | 1.27k | return true; |
114 | 26.3k | if (26.3k LHSType == ELF::STT_SECTION && 26.3k RHSType == ELF::STT_SECTION1.87k ) |
115 | 1.87k | return SectionIndex < RHS.SectionIndex; |
116 | 24.4k | return Name < RHS.Name; |
117 | 24.4k | } |
118 | | }; |
119 | | |
120 | | /// The target specific ELF writer instance. |
121 | | std::unique_ptr<MCELFObjectTargetWriter> TargetObjectWriter; |
122 | | |
123 | | DenseMap<const MCSymbolELF *, const MCSymbolELF *> Renames; |
124 | | |
125 | | DenseMap<const MCSectionELF *, std::vector<ELFRelocationEntry>> Relocations; |
126 | | |
127 | | /// @} |
128 | | /// @name Symbol Table Data |
129 | | /// @{ |
130 | | |
131 | | BumpPtrAllocator Alloc; |
132 | | StringSaver VersionSymSaver{Alloc}; |
133 | | StringTableBuilder StrTabBuilder{StringTableBuilder::ELF}; |
134 | | |
135 | | /// @} |
136 | | |
137 | | // This holds the symbol table index of the last local symbol. |
138 | | unsigned LastLocalSymbolIndex; |
139 | | // This holds the .strtab section index. |
140 | | unsigned StringTableIndex; |
141 | | // This holds the .symtab section index. |
142 | | unsigned SymbolTableIndex; |
143 | | |
144 | | // Sections in the order they are to be output in the section table. |
145 | | std::vector<const MCSectionELF *> SectionTable; |
146 | | unsigned addToSectionTable(const MCSectionELF *Sec); |
147 | | |
148 | | // TargetObjectWriter wrappers. |
149 | 2.13M | bool is64Bit() const { return TargetObjectWriter->is64Bit(); } |
150 | 28.3k | bool hasRelocationAddend() const { |
151 | 28.3k | return TargetObjectWriter->hasRelocationAddend(); |
152 | 28.3k | } |
153 | | unsigned getRelocType(MCContext &Ctx, const MCValue &Target, |
154 | 9.71k | const MCFixup &Fixup, bool IsPCRel) const { |
155 | 9.71k | return TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel); |
156 | 9.71k | } |
157 | | |
158 | | void align(unsigned Alignment); |
159 | | |
160 | | bool maybeWriteCompression(uint64_t Size, |
161 | | SmallVectorImpl<char> &CompressedContents, |
162 | | bool ZLibStyle, unsigned Alignment); |
163 | | |
164 | | public: |
165 | | ELFObjectWriter(MCELFObjectTargetWriter *MOTW, raw_pwrite_stream &OS, |
166 | | bool IsLittleEndian) |
167 | 2.85k | : MCObjectWriter(OS, IsLittleEndian), TargetObjectWriter(MOTW) {} |
168 | | |
169 | 2.83k | ~ELFObjectWriter() override = default; |
170 | | |
171 | 661 | void reset() override { |
172 | 661 | Renames.clear(); |
173 | 661 | Relocations.clear(); |
174 | 661 | StrTabBuilder.clear(); |
175 | 661 | SectionTable.clear(); |
176 | 661 | MCObjectWriter::reset(); |
177 | 661 | } |
178 | | |
179 | 2.09M | void WriteWord(uint64_t W) { |
180 | 2.09M | if (is64Bit()) |
181 | 2.04M | write64(W); |
182 | 2.09M | else |
183 | 48.5k | write32(W); |
184 | 2.09M | } |
185 | | |
186 | 105k | template <typename T> void write(T Val) { |
187 | 105k | if (IsLittleEndian) |
188 | 90.9k | support::endian::Writer<support::little>(getStream()).write(Val); |
189 | 105k | else |
190 | 14.8k | support::endian::Writer<support::big>(getStream()).write(Val); |
191 | 105k | } ELFObjectWriter.cpp:void (anonymous namespace)::ELFObjectWriter::write<unsigned long long>(unsigned long long) Line | Count | Source | 186 | 32.5k | template <typename T> void write(T Val) { | 187 | 32.5k | if (IsLittleEndian) | 188 | 28.8k | support::endian::Writer<support::little>(getStream()).write(Val); | 189 | 32.5k | else | 190 | 3.66k | support::endian::Writer<support::big>(getStream()).write(Val); | 191 | 32.5k | } |
ELFObjectWriter.cpp:void (anonymous namespace)::ELFObjectWriter::write<llvm::ArrayRef<char> >(llvm::ArrayRef<char>) Line | Count | Source | 186 | 5 | template <typename T> void write(T Val) { | 187 | 5 | if (IsLittleEndian) | 188 | 5 | support::endian::Writer<support::little>(getStream()).write(Val); | 189 | 5 | else | 190 | 0 | support::endian::Writer<support::big>(getStream()).write(Val); | 191 | 5 | } |
ELFObjectWriter.cpp:void (anonymous namespace)::ELFObjectWriter::write<unsigned int>(unsigned int) Line | Count | Source | 186 | 32.7k | template <typename T> void write(T Val) { | 187 | 32.7k | if (IsLittleEndian) | 188 | 27.3k | support::endian::Writer<support::little>(getStream()).write(Val); | 189 | 32.7k | else | 190 | 5.38k | support::endian::Writer<support::big>(getStream()).write(Val); | 191 | 32.7k | } |
ELFObjectWriter.cpp:void (anonymous namespace)::ELFObjectWriter::write<unsigned char>(unsigned char) Line | Count | Source | 186 | 27.4k | template <typename T> void write(T Val) { | 187 | 27.4k | if (IsLittleEndian) | 188 | 23.3k | support::endian::Writer<support::little>(getStream()).write(Val); | 189 | 27.4k | else | 190 | 4.11k | support::endian::Writer<support::big>(getStream()).write(Val); | 191 | 27.4k | } |
ELFObjectWriter.cpp:void (anonymous namespace)::ELFObjectWriter::write<unsigned short>(unsigned short) Line | Count | Source | 186 | 13.1k | template <typename T> void write(T Val) { | 187 | 13.1k | if (IsLittleEndian) | 188 | 11.4k | support::endian::Writer<support::little>(getStream()).write(Val); | 189 | 13.1k | else | 190 | 1.72k | support::endian::Writer<support::big>(getStream()).write(Val); | 191 | 13.1k | } |
|
192 | | |
193 | | void writeHeader(const MCAssembler &Asm); |
194 | | |
195 | | void writeSymbol(SymbolTableWriter &Writer, uint32_t StringIndex, |
196 | | ELFSymbolData &MSD, const MCAsmLayout &Layout); |
197 | | |
198 | | // Start and end offset of each section |
199 | | using SectionOffsetsTy = |
200 | | std::map<const MCSectionELF *, std::pair<uint64_t, uint64_t>>; |
201 | | |
202 | | bool shouldRelocateWithSymbol(const MCAssembler &Asm, |
203 | | const MCSymbolRefExpr *RefA, |
204 | | const MCSymbol *Sym, uint64_t C, |
205 | | unsigned Type) const; |
206 | | |
207 | | void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, |
208 | | const MCFragment *Fragment, const MCFixup &Fixup, |
209 | | MCValue Target, uint64_t &FixedValue) override; |
210 | | |
211 | | // Map from a signature symbol to the group section index |
212 | | using RevGroupMapTy = DenseMap<const MCSymbol *, unsigned>; |
213 | | |
214 | | /// Compute the symbol table data |
215 | | /// |
216 | | /// \param Asm - The assembler. |
217 | | /// \param SectionIndexMap - Maps a section to its index. |
218 | | /// \param RevGroupMap - Maps a signature symbol to the group section. |
219 | | void computeSymbolTable(MCAssembler &Asm, const MCAsmLayout &Layout, |
220 | | const SectionIndexMapTy &SectionIndexMap, |
221 | | const RevGroupMapTy &RevGroupMap, |
222 | | SectionOffsetsTy &SectionOffsets); |
223 | | |
224 | | MCSectionELF *createRelocationSection(MCContext &Ctx, |
225 | | const MCSectionELF &Sec); |
226 | | |
227 | | const MCSectionELF *createStringTable(MCContext &Ctx); |
228 | | |
229 | | void executePostLayoutBinding(MCAssembler &Asm, |
230 | | const MCAsmLayout &Layout) override; |
231 | | |
232 | | void writeSectionHeader(const MCAsmLayout &Layout, |
233 | | const SectionIndexMapTy &SectionIndexMap, |
234 | | const SectionOffsetsTy &SectionOffsets); |
235 | | |
236 | | void writeSectionData(const MCAssembler &Asm, MCSection &Sec, |
237 | | const MCAsmLayout &Layout); |
238 | | |
239 | | void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, |
240 | | uint64_t Address, uint64_t Offset, uint64_t Size, |
241 | | uint32_t Link, uint32_t Info, uint64_t Alignment, |
242 | | uint64_t EntrySize); |
243 | | |
244 | | void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec); |
245 | | |
246 | | using MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl; |
247 | | bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, |
248 | | const MCSymbol &SymA, |
249 | | const MCFragment &FB, bool InSet, |
250 | | bool IsPCRel) const override; |
251 | | |
252 | | void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override; |
253 | | void writeSection(const SectionIndexMapTy &SectionIndexMap, |
254 | | uint32_t GroupSymbolIndex, uint64_t Offset, uint64_t Size, |
255 | | const MCSectionELF &Section); |
256 | | }; |
257 | | |
258 | | } // end anonymous namespace |
259 | | |
260 | 344k | void ELFObjectWriter::align(unsigned Alignment) { |
261 | 344k | uint64_t Padding = OffsetToAlignment(getStream().tell(), Alignment); |
262 | 344k | WriteZeros(Padding); |
263 | 344k | } |
264 | | |
265 | 344k | unsigned ELFObjectWriter::addToSectionTable(const MCSectionELF *Sec) { |
266 | 344k | SectionTable.push_back(Sec); |
267 | 344k | StrTabBuilder.add(Sec->getSectionName()); |
268 | 344k | return SectionTable.size(); |
269 | 344k | } |
270 | | |
271 | 6 | void SymbolTableWriter::createSymtabShndx() { |
272 | 6 | if (!ShndxIndexes.empty()) |
273 | 2 | return; |
274 | 4 | |
275 | 4 | ShndxIndexes.resize(NumWritten); |
276 | 4 | } |
277 | | |
278 | 79.0k | template <typename T> void SymbolTableWriter::write(T Value) { |
279 | 79.0k | EWriter.write(Value); |
280 | 79.0k | } ELFObjectWriter.cpp:void (anonymous namespace)::SymbolTableWriter::write<unsigned int>(unsigned int) Line | Count | Source | 278 | 24.0k | template <typename T> void SymbolTableWriter::write(T Value) { | 279 | 24.0k | EWriter.write(Value); | 280 | 24.0k | } |
ELFObjectWriter.cpp:void (anonymous namespace)::SymbolTableWriter::write<unsigned char>(unsigned char) Line | Count | Source | 278 | 26.3k | template <typename T> void SymbolTableWriter::write(T Value) { | 279 | 26.3k | EWriter.write(Value); | 280 | 26.3k | } |
ELFObjectWriter.cpp:void (anonymous namespace)::SymbolTableWriter::write<unsigned short>(unsigned short) Line | Count | Source | 278 | 13.1k | template <typename T> void SymbolTableWriter::write(T Value) { | 279 | 13.1k | EWriter.write(Value); | 280 | 13.1k | } |
ELFObjectWriter.cpp:void (anonymous namespace)::SymbolTableWriter::write<unsigned long long>(unsigned long long) Line | Count | Source | 278 | 15.4k | template <typename T> void SymbolTableWriter::write(T Value) { | 279 | 15.4k | EWriter.write(Value); | 280 | 15.4k | } |
|
281 | | |
282 | | SymbolTableWriter::SymbolTableWriter(ELFObjectWriter &EWriter, bool Is64Bit) |
283 | 2.78k | : EWriter(EWriter), Is64Bit(Is64Bit), NumWritten(0) {} |
284 | | |
285 | | void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value, |
286 | | uint64_t size, uint8_t other, |
287 | 13.1k | uint32_t shndx, bool Reserved) { |
288 | 981 | bool LargeIndex = shndx >= ELF::SHN_LORESERVE && !Reserved; |
289 | 13.1k | |
290 | 13.1k | if (LargeIndex) |
291 | 6 | createSymtabShndx(); |
292 | 13.1k | |
293 | 13.1k | if (!ShndxIndexes.empty()13.1k ) { |
294 | 6 | if (LargeIndex) |
295 | 6 | ShndxIndexes.push_back(shndx); |
296 | 6 | else |
297 | 0 | ShndxIndexes.push_back(0); |
298 | 6 | } |
299 | 13.1k | |
300 | 13.1k | uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX)6 : shndx13.1k ; |
301 | 13.1k | |
302 | 13.1k | if (Is64Bit13.1k ) { |
303 | 7.72k | write(name); // st_name |
304 | 7.72k | write(info); // st_info |
305 | 7.72k | write(other); // st_other |
306 | 7.72k | write(Index); // st_shndx |
307 | 7.72k | write(value); // st_value |
308 | 7.72k | write(size); // st_size |
309 | 13.1k | } else { |
310 | 5.44k | write(name); // st_name |
311 | 5.44k | write(uint32_t(value)); // st_value |
312 | 5.44k | write(uint32_t(size)); // st_size |
313 | 5.44k | write(info); // st_info |
314 | 5.44k | write(other); // st_other |
315 | 5.44k | write(Index); // st_shndx |
316 | 5.44k | } |
317 | 13.1k | |
318 | 13.1k | ++NumWritten; |
319 | 13.1k | } |
320 | | |
321 | | // Emit the ELF header. |
322 | 2.78k | void ELFObjectWriter::writeHeader(const MCAssembler &Asm) { |
323 | 2.78k | // ELF Header |
324 | 2.78k | // ---------- |
325 | 2.78k | // |
326 | 2.78k | // Note |
327 | 2.78k | // ---- |
328 | 2.78k | // emitWord method behaves differently for ELF32 and ELF64, writing |
329 | 2.78k | // 4 bytes in the former and 8 in the latter. |
330 | 2.78k | |
331 | 2.78k | writeBytes(ELF::ElfMagic); // e_ident[EI_MAG0] to e_ident[EI_MAG3] |
332 | 2.78k | |
333 | 2.78k | write8(is64Bit() ? ELF::ELFCLASS641.80k : ELF::ELFCLASS32984 ); // e_ident[EI_CLASS] |
334 | 2.78k | |
335 | 2.78k | // e_ident[EI_DATA] |
336 | 2.78k | write8(isLittleEndian() ? ELF::ELFDATA2LSB2.40k : ELF::ELFDATA2MSB385 ); |
337 | 2.78k | |
338 | 2.78k | write8(ELF::EV_CURRENT); // e_ident[EI_VERSION] |
339 | 2.78k | // e_ident[EI_OSABI] |
340 | 2.78k | write8(TargetObjectWriter->getOSABI()); |
341 | 2.78k | write8(0); // e_ident[EI_ABIVERSION] |
342 | 2.78k | |
343 | 2.78k | WriteZeros(ELF::EI_NIDENT - ELF::EI_PAD); |
344 | 2.78k | |
345 | 2.78k | write16(ELF::ET_REL); // e_type |
346 | 2.78k | |
347 | 2.78k | write16(TargetObjectWriter->getEMachine()); // e_machine = target |
348 | 2.78k | |
349 | 2.78k | write32(ELF::EV_CURRENT); // e_version |
350 | 2.78k | WriteWord(0); // e_entry, no entry point in .o file |
351 | 2.78k | WriteWord(0); // e_phoff, no program header for .o |
352 | 2.78k | WriteWord(0); // e_shoff = sec hdr table off in bytes |
353 | 2.78k | |
354 | 2.78k | // e_flags = whatever the target wants |
355 | 2.78k | write32(Asm.getELFHeaderEFlags()); |
356 | 2.78k | |
357 | 2.78k | // e_ehsize = ELF header size |
358 | 2.78k | write16(is64Bit() ? sizeof(ELF::Elf64_Ehdr)1.80k : sizeof(ELF::Elf32_Ehdr)984 ); |
359 | 2.78k | |
360 | 2.78k | write16(0); // e_phentsize = prog header entry size |
361 | 2.78k | write16(0); // e_phnum = # prog header entries = 0 |
362 | 2.78k | |
363 | 2.78k | // e_shentsize = Section header entry size |
364 | 2.78k | write16(is64Bit() ? sizeof(ELF::Elf64_Shdr)1.80k : sizeof(ELF::Elf32_Shdr)984 ); |
365 | 2.78k | |
366 | 2.78k | // e_shnum = # of section header ents |
367 | 2.78k | write16(0); |
368 | 2.78k | |
369 | 2.78k | // e_shstrndx = Section # of '.shstrtab' |
370 | 2.78k | assert(StringTableIndex < ELF::SHN_LORESERVE); |
371 | 2.78k | write16(StringTableIndex); |
372 | 2.78k | } |
373 | | |
374 | | uint64_t ELFObjectWriter::SymbolValue(const MCSymbol &Sym, |
375 | 9.71k | const MCAsmLayout &Layout) { |
376 | 9.71k | if (Sym.isCommon() && 9.71k Sym.isExternal()134 ) |
377 | 134 | return Sym.getCommonAlignment(); |
378 | 9.57k | |
379 | 9.57k | uint64_t Res; |
380 | 9.57k | if (!Layout.getSymbolOffset(Sym, Res)) |
381 | 1.45k | return 0; |
382 | 8.12k | |
383 | 8.12k | if (8.12k Layout.getAssembler().isThumbFunc(&Sym)8.12k ) |
384 | 306 | Res |= 1; |
385 | 9.71k | |
386 | 9.71k | return Res; |
387 | 9.71k | } |
388 | | |
389 | | void ELFObjectWriter::executePostLayoutBinding(MCAssembler &Asm, |
390 | 2.79k | const MCAsmLayout &Layout) { |
391 | 2.79k | // The presence of symbol versions causes undefined symbols and |
392 | 2.79k | // versions declared with @@@ to be renamed. |
393 | 356k | for (const MCSymbol &A : Asm.symbols()) { |
394 | 356k | const auto &Alias = cast<MCSymbolELF>(A); |
395 | 356k | // Not an alias. |
396 | 356k | if (!Alias.isVariable()) |
397 | 356k | continue; |
398 | 355 | auto *Ref = dyn_cast<MCSymbolRefExpr>(Alias.getVariableValue()); |
399 | 355 | if (!Ref) |
400 | 192 | continue; |
401 | 163 | const auto &Symbol = cast<MCSymbolELF>(Ref->getSymbol()); |
402 | 163 | |
403 | 163 | StringRef AliasName = Alias.getName(); |
404 | 163 | size_t Pos = AliasName.find('@'); |
405 | 163 | if (Pos == StringRef::npos) |
406 | 118 | continue; |
407 | 45 | |
408 | 45 | // Aliases defined with .symvar copy the binding from the symbol they alias. |
409 | 45 | // This is the first place we are able to copy this information. |
410 | 45 | Alias.setExternal(Symbol.isExternal()); |
411 | 45 | Alias.setBinding(Symbol.getBinding()); |
412 | 45 | |
413 | 45 | StringRef Rest = AliasName.substr(Pos); |
414 | 45 | if (!Symbol.isUndefined() && 45 !Rest.startswith("@@@")39 ) |
415 | 34 | continue; |
416 | 11 | |
417 | 11 | // FIXME: produce a better error message. |
418 | 11 | if (11 Symbol.isUndefined() && 11 Rest.startswith("@@")7 && |
419 | 4 | !Rest.startswith("@@@")) |
420 | 1 | report_fatal_error("A @@ version cannot be undefined"); |
421 | 10 | |
422 | 10 | Renames.insert(std::make_pair(&Symbol, &Alias)); |
423 | 10 | } |
424 | 2.79k | } |
425 | | |
426 | 9.54k | static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) { |
427 | 9.54k | uint8_t Type = newType; |
428 | 9.54k | |
429 | 9.54k | // Propagation rules: |
430 | 9.54k | // IFUNC > FUNC > OBJECT > NOTYPE |
431 | 9.54k | // TLS_OBJECT > OBJECT > NOTYPE |
432 | 9.54k | // |
433 | 9.54k | // dont let the new type degrade the old type |
434 | 9.54k | switch (origType) { |
435 | 6.64k | default: |
436 | 6.64k | break; |
437 | 259 | case ELF::STT_GNU_IFUNC: |
438 | 259 | if (Type == ELF::STT_FUNC || 259 Type == ELF::STT_OBJECT256 || |
439 | 259 | Type == ELF::STT_NOTYPE255 || Type == ELF::STT_TLS254 ) |
440 | 6 | Type = ELF::STT_GNU_IFUNC; |
441 | 259 | break; |
442 | 1.84k | case ELF::STT_FUNC: |
443 | 1.84k | if (Type == ELF::STT_OBJECT || 1.84k Type == ELF::STT_NOTYPE1.84k || |
444 | 1.84k | Type == ELF::STT_TLS) |
445 | 5 | Type = ELF::STT_FUNC; |
446 | 1.84k | break; |
447 | 531 | case ELF::STT_OBJECT: |
448 | 531 | if (Type == ELF::STT_NOTYPE) |
449 | 1 | Type = ELF::STT_OBJECT; |
450 | 531 | break; |
451 | 253 | case ELF::STT_TLS: |
452 | 253 | if (Type == ELF::STT_OBJECT || 253 Type == ELF::STT_NOTYPE252 || |
453 | 253 | Type == ELF::STT_GNU_IFUNC251 || Type == ELF::STT_FUNC250 ) |
454 | 4 | Type = ELF::STT_TLS; |
455 | 253 | break; |
456 | 9.53k | } |
457 | 9.53k | |
458 | 9.53k | return Type; |
459 | 9.53k | } |
460 | | |
461 | | void ELFObjectWriter::writeSymbol(SymbolTableWriter &Writer, |
462 | | uint32_t StringIndex, ELFSymbolData &MSD, |
463 | 9.71k | const MCAsmLayout &Layout) { |
464 | 9.71k | const auto &Symbol = cast<MCSymbolELF>(*MSD.Symbol); |
465 | 9.71k | const MCSymbolELF *Base = |
466 | 9.71k | cast_or_null<MCSymbolELF>(Layout.getBaseSymbol(Symbol)); |
467 | 9.71k | |
468 | 9.71k | // This has to be in sync with when computeSymbolTable uses SHN_ABS or |
469 | 9.71k | // SHN_COMMON. |
470 | 9.53k | bool IsReserved = !Base || Symbol.isCommon(); |
471 | 9.71k | |
472 | 9.71k | // Binding and Type share the same byte as upper and lower nibbles |
473 | 9.71k | uint8_t Binding = Symbol.getBinding(); |
474 | 9.71k | uint8_t Type = Symbol.getType(); |
475 | 9.71k | if (Base9.71k ) { |
476 | 9.54k | Type = mergeTypeForSet(Type, Base->getType()); |
477 | 9.54k | } |
478 | 9.71k | uint8_t Info = (Binding << 4) | Type; |
479 | 9.71k | |
480 | 9.71k | // Other and Visibility share the same byte with Visibility using the lower |
481 | 9.71k | // 2 bits |
482 | 9.71k | uint8_t Visibility = Symbol.getVisibility(); |
483 | 9.71k | uint8_t Other = Symbol.getOther() | Visibility; |
484 | 9.71k | |
485 | 9.71k | uint64_t Value = SymbolValue(*MSD.Symbol, Layout); |
486 | 9.71k | uint64_t Size = 0; |
487 | 9.71k | |
488 | 9.71k | const MCExpr *ESize = MSD.Symbol->getSize(); |
489 | 9.71k | if (!ESize && 9.71k Base7.57k ) |
490 | 7.40k | ESize = Base->getSize(); |
491 | 9.71k | |
492 | 9.71k | if (ESize9.71k ) { |
493 | 2.18k | int64_t Res; |
494 | 2.18k | if (!ESize->evaluateKnownAbsolute(Res, Layout)) |
495 | 0 | report_fatal_error("Size expression must be absolute."); |
496 | 2.18k | Size = Res; |
497 | 2.18k | } |
498 | 9.71k | |
499 | 9.71k | // Write out the symbol table entry |
500 | 9.71k | Writer.writeSymbol(StringIndex, Info, Value, Size, Other, MSD.SectionIndex, |
501 | 9.71k | IsReserved); |
502 | 9.71k | } |
503 | | |
504 | | // It is always valid to create a relocation with a symbol. It is preferable |
505 | | // to use a relocation with a section if that is possible. Using the section |
506 | | // allows us to omit some local symbols from the symbol table. |
507 | | bool ELFObjectWriter::shouldRelocateWithSymbol(const MCAssembler &Asm, |
508 | | const MCSymbolRefExpr *RefA, |
509 | | const MCSymbol *S, uint64_t C, |
510 | 9.70k | unsigned Type) const { |
511 | 9.70k | const auto *Sym = cast_or_null<MCSymbolELF>(S); |
512 | 9.70k | // A PCRel relocation to an absolute value has no symbol (or section). We |
513 | 9.70k | // represent that with a relocation to a null section. |
514 | 9.70k | if (!RefA) |
515 | 8 | return false; |
516 | 9.70k | |
517 | 9.70k | MCSymbolRefExpr::VariantKind Kind = RefA->getKind(); |
518 | 9.70k | switch (Kind) { |
519 | 9.23k | default: |
520 | 9.23k | break; |
521 | 9.70k | // The .odp creation emits a relocation against the symbol ".TOC." which |
522 | 9.70k | // create a R_PPC64_TOC relocation. However the relocation symbol name |
523 | 9.70k | // in final object creation should be NULL, since the symbol does not |
524 | 9.70k | // really exist, it is just the reference to TOC base for the current |
525 | 9.70k | // object file. Since the symbol is undefined, returning false results |
526 | 9.70k | // in a relocation with a null section which is the desired result. |
527 | 46 | case MCSymbolRefExpr::VK_PPC_TOCBASE: |
528 | 46 | return false; |
529 | 9.70k | |
530 | 9.70k | // These VariantKind cause the relocation to refer to something other than |
531 | 9.70k | // the symbol itself, like a linker generated table. Since the address of |
532 | 9.70k | // symbol is not relevant, we cannot replace the symbol with the |
533 | 9.70k | // section and patch the difference in the addend. |
534 | 418 | case MCSymbolRefExpr::VK_GOT: |
535 | 418 | case MCSymbolRefExpr::VK_PLT: |
536 | 418 | case MCSymbolRefExpr::VK_GOTPCREL: |
537 | 418 | case MCSymbolRefExpr::VK_PPC_GOT_LO: |
538 | 418 | case MCSymbolRefExpr::VK_PPC_GOT_HI: |
539 | 418 | case MCSymbolRefExpr::VK_PPC_GOT_HA: |
540 | 418 | return true; |
541 | 9.23k | } |
542 | 9.23k | |
543 | 9.23k | // An undefined symbol is not in any section, so the relocation has to point |
544 | 9.23k | // to the symbol itself. |
545 | 9.70k | assert(Sym && "Expected a symbol"); |
546 | 9.23k | if (Sym->isUndefined()) |
547 | 3.34k | return true; |
548 | 5.89k | |
549 | 5.89k | unsigned Binding = Sym->getBinding(); |
550 | 5.89k | switch(Binding) { |
551 | 0 | default: |
552 | 0 | llvm_unreachable("Invalid Binding"); |
553 | 5.13k | case ELF::STB_LOCAL: |
554 | 5.13k | break; |
555 | 46 | case ELF::STB_WEAK: |
556 | 46 | // If the symbol is weak, it might be overridden by a symbol in another |
557 | 46 | // file. The relocation has to point to the symbol so that the linker |
558 | 46 | // can update it. |
559 | 46 | return true; |
560 | 712 | case ELF::STB_GLOBAL: |
561 | 712 | // Global ELF symbols can be preempted by the dynamic linker. The relocation |
562 | 712 | // has to point to the symbol for a reason analogous to the STB_WEAK case. |
563 | 712 | return true; |
564 | 5.13k | } |
565 | 5.13k | |
566 | 5.13k | // If a relocation points to a mergeable section, we have to be careful. |
567 | 5.13k | // If the offset is zero, a relocation with the section will encode the |
568 | 5.13k | // same information. With a non-zero offset, the situation is different. |
569 | 5.13k | // For example, a relocation can point 42 bytes past the end of a string. |
570 | 5.13k | // If we change such a relocation to use the section, the linker would think |
571 | 5.13k | // that it pointed to another string and subtracting 42 at runtime will |
572 | 5.13k | // produce the wrong value. |
573 | 5.13k | if (5.13k Sym->isInSection()5.13k ) { |
574 | 5.13k | auto &Sec = cast<MCSectionELF>(Sym->getSection()); |
575 | 5.13k | unsigned Flags = Sec.getFlags(); |
576 | 5.13k | if (Flags & ELF::SHF_MERGE5.13k ) { |
577 | 1.27k | if (C != 0) |
578 | 31 | return true; |
579 | 1.24k | |
580 | 1.24k | // It looks like gold has a bug (http://sourceware.org/PR16794) and can |
581 | 1.24k | // only handle section relocations to mergeable sections if using RELA. |
582 | 1.24k | if (1.24k !hasRelocationAddend()1.24k ) |
583 | 181 | return true; |
584 | 4.92k | } |
585 | 4.92k | |
586 | 4.92k | // Most TLS relocations use a got, so they need the symbol. Even those that |
587 | 4.92k | // are just an offset (@tpoff), require a symbol in gold versions before |
588 | 4.92k | // 5efeedf61e4fe720fd3e9a08e6c91c10abb66d42 (2014-09-26) which fixed |
589 | 4.92k | // http://sourceware.org/PR16773. |
590 | 4.92k | if (4.92k Flags & ELF::SHF_TLS4.92k ) |
591 | 111 | return true; |
592 | 4.81k | } |
593 | 4.81k | |
594 | 4.81k | // If the symbol is a thumb function the final relocation must set the lowest |
595 | 4.81k | // bit. With a symbol that is done by just having the symbol have that bit |
596 | 4.81k | // set, so we would lose the bit if we relocated with the section. |
597 | 4.81k | // FIXME: We could use the section but add the bit to the relocation value. |
598 | 4.81k | if (4.81k Asm.isThumbFunc(Sym)4.81k ) |
599 | 20 | return true; |
600 | 4.79k | |
601 | 4.79k | if (4.79k TargetObjectWriter->needsRelocateWithSymbol(*Sym, Type)4.79k ) |
602 | 128 | return true; |
603 | 4.66k | return false; |
604 | 4.66k | } |
605 | | |
606 | | // True if the assembler knows nothing about the final value of the symbol. |
607 | | // This doesn't cover the comdat issues, since in those cases the assembler |
608 | | // can at least know that all symbols in the section will move together. |
609 | 1.32k | static bool isWeak(const MCSymbolELF &Sym) { |
610 | 1.32k | if (Sym.getType() == ELF::STT_GNU_IFUNC) |
611 | 29 | return true; |
612 | 1.29k | |
613 | 1.29k | switch (Sym.getBinding()) { |
614 | 0 | default: |
615 | 0 | llvm_unreachable("Unknown binding"); |
616 | 1.12k | case ELF::STB_LOCAL: |
617 | 1.12k | return false; |
618 | 141 | case ELF::STB_GLOBAL: |
619 | 141 | return false; |
620 | 25 | case ELF::STB_WEAK: |
621 | 25 | case ELF::STB_GNU_UNIQUE: |
622 | 25 | return true; |
623 | 0 | } |
624 | 0 | } |
625 | | |
626 | | void ELFObjectWriter::recordRelocation(MCAssembler &Asm, |
627 | | const MCAsmLayout &Layout, |
628 | | const MCFragment *Fragment, |
629 | | const MCFixup &Fixup, MCValue Target, |
630 | 9.72k | uint64_t &FixedValue) { |
631 | 9.72k | MCAsmBackend &Backend = Asm.getBackend(); |
632 | 9.72k | bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags & |
633 | 9.72k | MCFixupKindInfo::FKF_IsPCRel; |
634 | 9.72k | const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent()); |
635 | 9.72k | uint64_t C = Target.getConstant(); |
636 | 9.72k | uint64_t FixupOffset = Layout.getFragmentOffset(Fragment) + Fixup.getOffset(); |
637 | 9.72k | MCContext &Ctx = Asm.getContext(); |
638 | 9.72k | |
639 | 9.72k | if (const MCSymbolRefExpr *RefB9.72k = Target.getSymB()) { |
640 | 694 | // Let A, B and C being the components of Target and R be the location of |
641 | 694 | // the fixup. If the fixup is not pcrel, we want to compute (A - B + C). |
642 | 694 | // If it is pcrel, we want to compute (A - B + C - R). |
643 | 694 | |
644 | 694 | // In general, ELF has no relocations for -B. It can only represent (A + C) |
645 | 694 | // or (A + C - R). If B = R + K and the relocation is not pcrel, we can |
646 | 694 | // replace B to implement it: (A - R - K + C) |
647 | 694 | if (IsPCRel694 ) { |
648 | 3 | Ctx.reportError( |
649 | 3 | Fixup.getLoc(), |
650 | 3 | "No relocation available to represent this relative expression"); |
651 | 3 | return; |
652 | 3 | } |
653 | 691 | |
654 | 691 | const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol()); |
655 | 691 | |
656 | 691 | if (SymB.isUndefined()691 ) { |
657 | 6 | Ctx.reportError(Fixup.getLoc(), |
658 | 6 | Twine("symbol '") + SymB.getName() + |
659 | 6 | "' can not be undefined in a subtraction expression"); |
660 | 6 | return; |
661 | 6 | } |
662 | 685 | |
663 | 691 | assert(!SymB.isAbsolute() && "Should have been folded"); |
664 | 685 | const MCSection &SecB = SymB.getSection(); |
665 | 685 | if (&SecB != &FixupSection685 ) { |
666 | 7 | Ctx.reportError(Fixup.getLoc(), |
667 | 7 | "Cannot represent a difference across sections"); |
668 | 7 | return; |
669 | 7 | } |
670 | 678 | |
671 | 678 | uint64_t SymBOffset = Layout.getSymbolOffset(SymB); |
672 | 678 | uint64_t K = SymBOffset - FixupOffset; |
673 | 678 | IsPCRel = true; |
674 | 678 | C -= K; |
675 | 678 | } |
676 | 9.72k | |
677 | 9.72k | // We either rejected the fixup or folded B into C at this point. |
678 | 9.71k | const MCSymbolRefExpr *RefA = Target.getSymA(); |
679 | 9.71k | const auto *SymA = RefA ? cast<MCSymbolELF>(&RefA->getSymbol())9.70k : nullptr7 ; |
680 | 9.71k | |
681 | 9.71k | bool ViaWeakRef = false; |
682 | 9.71k | if (SymA && 9.71k SymA->isVariable()9.70k ) { |
683 | 35 | const MCExpr *Expr = SymA->getVariableValue(); |
684 | 35 | if (const auto *Inner35 = dyn_cast<MCSymbolRefExpr>(Expr)) { |
685 | 32 | if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF32 ) { |
686 | 14 | SymA = cast<MCSymbolELF>(&Inner->getSymbol()); |
687 | 14 | ViaWeakRef = true; |
688 | 14 | } |
689 | 32 | } |
690 | 35 | } |
691 | 9.71k | |
692 | 9.71k | unsigned Type = getRelocType(Ctx, Target, Fixup, IsPCRel); |
693 | 9.71k | uint64_t OriginalC = C; |
694 | 9.71k | bool RelocateWithSymbol = shouldRelocateWithSymbol(Asm, RefA, SymA, C, Type); |
695 | 9.71k | if (!RelocateWithSymbol && 9.71k SymA4.72k && !SymA->isUndefined()4.71k ) |
696 | 4.66k | C += Layout.getSymbolOffset(*SymA); |
697 | 9.71k | |
698 | 9.71k | uint64_t Addend = 0; |
699 | 9.71k | if (hasRelocationAddend()9.71k ) { |
700 | 6.09k | Addend = C; |
701 | 6.09k | C = 0; |
702 | 6.09k | } |
703 | 9.71k | |
704 | 9.71k | FixedValue = C; |
705 | 9.71k | |
706 | 9.71k | if (!RelocateWithSymbol9.71k ) { |
707 | 4.72k | const MCSection *SecA = |
708 | 4.72k | (SymA && !SymA->isUndefined()4.71k ) ? &SymA->getSection()4.66k : nullptr54 ; |
709 | 4.72k | auto *ELFSec = cast_or_null<MCSectionELF>(SecA); |
710 | 4.72k | const auto *SectionSymbol = |
711 | 4.72k | ELFSec ? cast<MCSymbolELF>(ELFSec->getBeginSymbol())4.66k : nullptr54 ; |
712 | 4.72k | if (SectionSymbol) |
713 | 4.66k | SectionSymbol->setUsedInReloc(); |
714 | 4.72k | ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend, SymA, |
715 | 4.72k | OriginalC); |
716 | 4.72k | Relocations[&FixupSection].push_back(Rec); |
717 | 4.72k | return; |
718 | 4.72k | } |
719 | 4.99k | |
720 | 4.99k | const auto *RenamedSymA = SymA; |
721 | 4.99k | if (SymA4.99k ) { |
722 | 4.98k | if (const MCSymbolELF *R = Renames.lookup(SymA)) |
723 | 6 | RenamedSymA = R; |
724 | 4.98k | |
725 | 4.98k | if (ViaWeakRef) |
726 | 12 | RenamedSymA->setIsWeakrefUsedInReloc(); |
727 | 4.98k | else |
728 | 4.97k | RenamedSymA->setUsedInReloc(); |
729 | 4.98k | } |
730 | 9.72k | ELFRelocationEntry Rec(FixupOffset, RenamedSymA, Type, Addend, SymA, |
731 | 9.72k | OriginalC); |
732 | 9.72k | Relocations[&FixupSection].push_back(Rec); |
733 | 9.72k | } |
734 | | |
735 | | bool ELFObjectWriter::isInSymtab(const MCAsmLayout &Layout, |
736 | | const MCSymbolELF &Symbol, bool Used, |
737 | 356k | bool Renamed) { |
738 | 356k | if (Symbol.isVariable()356k ) { |
739 | 354 | const MCExpr *Expr = Symbol.getVariableValue(); |
740 | 354 | if (const MCSymbolRefExpr *Ref354 = dyn_cast<MCSymbolRefExpr>(Expr)) { |
741 | 163 | if (Ref->getKind() == MCSymbolRefExpr::VK_WEAKREF) |
742 | 14 | return false; |
743 | 356k | } |
744 | 354 | } |
745 | 356k | |
746 | 356k | if (356k Used356k ) |
747 | 4.00k | return true; |
748 | 352k | |
749 | 352k | if (352k Renamed352k ) |
750 | 11 | return false; |
751 | 352k | |
752 | 352k | if (352k Symbol.isVariable() && 352k Symbol.isUndefined()325 ) { |
753 | 13 | // FIXME: this is here just to diagnose the case of a var = commmon_sym. |
754 | 13 | Layout.getBaseSymbol(Symbol); |
755 | 13 | return false; |
756 | 13 | } |
757 | 352k | |
758 | 352k | if (352k Symbol.isUndefined() && 352k !Symbol.isBindingSet()159 ) |
759 | 45 | return false; |
760 | 352k | |
761 | 352k | if (352k Symbol.isTemporary()352k ) |
762 | 12.7k | return false; |
763 | 339k | |
764 | 339k | if (339k Symbol.getType() == ELF::STT_SECTION339k ) |
765 | 333k | return false; |
766 | 5.70k | |
767 | 5.70k | return true; |
768 | 5.70k | } |
769 | | |
770 | | void ELFObjectWriter::computeSymbolTable( |
771 | | MCAssembler &Asm, const MCAsmLayout &Layout, |
772 | | const SectionIndexMapTy &SectionIndexMap, const RevGroupMapTy &RevGroupMap, |
773 | 2.78k | SectionOffsetsTy &SectionOffsets) { |
774 | 2.78k | MCContext &Ctx = Asm.getContext(); |
775 | 2.78k | SymbolTableWriter Writer(*this, is64Bit()); |
776 | 2.78k | |
777 | 2.78k | // Symbol table |
778 | 2.78k | unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE641.80k : ELF::SYMENTRY_SIZE32982 ; |
779 | 2.78k | MCSectionELF *SymtabSection = |
780 | 2.78k | Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize, ""); |
781 | 2.78k | SymtabSection->setAlignment(is64Bit() ? 81.80k : 4981 ); |
782 | 2.78k | SymbolTableIndex = addToSectionTable(SymtabSection); |
783 | 2.78k | |
784 | 2.78k | align(SymtabSection->getAlignment()); |
785 | 2.78k | uint64_t SecStart = getStream().tell(); |
786 | 2.78k | |
787 | 2.78k | // The first entry is the undefined symbol entry. |
788 | 2.78k | Writer.writeSymbol(0, 0, 0, 0, 0, 0, false); |
789 | 2.78k | |
790 | 2.78k | std::vector<ELFSymbolData> LocalSymbolData; |
791 | 2.78k | std::vector<ELFSymbolData> ExternalSymbolData; |
792 | 2.78k | |
793 | 2.78k | // Add the data for the symbols. |
794 | 2.78k | bool HasLargeSectionIndex = false; |
795 | 356k | for (const MCSymbol &S : Asm.symbols()) { |
796 | 356k | const auto &Symbol = cast<MCSymbolELF>(S); |
797 | 356k | bool Used = Symbol.isUsedInReloc(); |
798 | 356k | bool WeakrefUsed = Symbol.isWeakrefUsedInReloc(); |
799 | 356k | bool isSignature = Symbol.isSignature(); |
800 | 356k | |
801 | 356k | if (!isInSymtab(Layout, Symbol, Used || 356k WeakrefUsed352k || isSignature352k , |
802 | 356k | Renames.count(&Symbol))) |
803 | 346k | continue; |
804 | 9.71k | |
805 | 9.71k | if (9.71k Symbol.isTemporary() && 9.71k Symbol.isUndefined()170 ) { |
806 | 1 | Ctx.reportError(SMLoc(), "Undefined temporary symbol"); |
807 | 1 | continue; |
808 | 1 | } |
809 | 9.71k | |
810 | 9.71k | ELFSymbolData MSD; |
811 | 9.71k | MSD.Symbol = cast<MCSymbolELF>(&Symbol); |
812 | 9.71k | |
813 | 9.71k | bool Local = Symbol.getBinding() == ELF::STB_LOCAL; |
814 | 9.71k | assert(Local || !Symbol.isTemporary()); |
815 | 9.71k | |
816 | 9.71k | if (Symbol.isAbsolute()9.71k ) { |
817 | 174 | MSD.SectionIndex = ELF::SHN_ABS; |
818 | 9.71k | } else if (9.54k Symbol.isCommon()9.54k ) { |
819 | 134 | assert(!Local); |
820 | 134 | MSD.SectionIndex = ELF::SHN_COMMON; |
821 | 9.54k | } else if (9.40k Symbol.isUndefined()9.40k ) { |
822 | 1.45k | if (isSignature && 1.45k !Used47 ) { |
823 | 45 | MSD.SectionIndex = RevGroupMap.lookup(&Symbol); |
824 | 45 | if (MSD.SectionIndex >= ELF::SHN_LORESERVE) |
825 | 0 | HasLargeSectionIndex = true; |
826 | 1.45k | } else { |
827 | 1.41k | MSD.SectionIndex = ELF::SHN_UNDEF; |
828 | 1.41k | } |
829 | 9.40k | } else { |
830 | 7.95k | const MCSectionELF &Section = |
831 | 7.95k | static_cast<const MCSectionELF &>(Symbol.getSection()); |
832 | 7.95k | MSD.SectionIndex = SectionIndexMap.lookup(&Section); |
833 | 7.95k | assert(MSD.SectionIndex && "Invalid section index!"); |
834 | 7.95k | if (MSD.SectionIndex >= ELF::SHN_LORESERVE) |
835 | 6 | HasLargeSectionIndex = true; |
836 | 9.54k | } |
837 | 9.71k | |
838 | 9.71k | // The @@@ in symbol version is replaced with @ in undefined symbols and @@ |
839 | 9.71k | // in defined ones. |
840 | 9.71k | // |
841 | 9.71k | // FIXME: All name handling should be done before we get to the writer, |
842 | 9.71k | // including dealing with GNU-style version suffixes. Fixing this isn't |
843 | 9.71k | // trivial. |
844 | 9.71k | // |
845 | 9.71k | // We thus have to be careful to not perform the symbol version replacement |
846 | 9.71k | // blindly: |
847 | 9.71k | // |
848 | 9.71k | // The ELF format is used on Windows by the MCJIT engine. Thus, on |
849 | 9.71k | // Windows, the ELFObjectWriter can encounter symbols mangled using the MS |
850 | 9.71k | // Visual Studio C++ name mangling scheme. Symbols mangled using the MSVC |
851 | 9.71k | // C++ name mangling can legally have "@@@" as a sub-string. In that case, |
852 | 9.71k | // the EFLObjectWriter should not interpret the "@@@" sub-string as |
853 | 9.71k | // specifying GNU-style symbol versioning. The ELFObjectWriter therefore |
854 | 9.71k | // checks for the MSVC C++ name mangling prefix which is either "?", "@?", |
855 | 9.71k | // "__imp_?" or "__imp_@?". |
856 | 9.71k | // |
857 | 9.71k | // It would have been interesting to perform the MS mangling prefix check |
858 | 9.71k | // only when the target triple is of the form *-pc-windows-elf. But, it |
859 | 9.71k | // seems that this information is not easily accessible from the |
860 | 9.71k | // ELFObjectWriter. |
861 | 9.71k | StringRef Name = Symbol.getName(); |
862 | 9.71k | SmallString<32> Buf; |
863 | 9.71k | if (!Name.startswith("?") && 9.71k !Name.startswith("@?")9.71k && |
864 | 9.71k | !Name.startswith("__imp_?")9.71k && !Name.startswith("__imp_@?")9.71k ) { |
865 | 9.71k | // This symbol isn't following the MSVC C++ name mangling convention. We |
866 | 9.71k | // can thus safely interpret the @@@ in symbol names as specifying symbol |
867 | 9.71k | // versioning. |
868 | 9.71k | size_t Pos = Name.find("@@@"); |
869 | 9.71k | if (Pos != StringRef::npos9.71k ) { |
870 | 8 | Buf += Name.substr(0, Pos); |
871 | 8 | unsigned Skip = MSD.SectionIndex == ELF::SHN_UNDEF ? 23 : 15 ; |
872 | 8 | Buf += Name.substr(Pos + Skip); |
873 | 8 | Name = VersionSymSaver.save(Buf.c_str()); |
874 | 8 | } |
875 | 9.71k | } |
876 | 9.71k | |
877 | 9.71k | // Sections have their own string table |
878 | 9.71k | if (Symbol.getType() != ELF::STT_SECTION9.71k ) { |
879 | 8.01k | MSD.Name = Name; |
880 | 8.01k | StrTabBuilder.add(Name); |
881 | 8.01k | } |
882 | 9.71k | |
883 | 9.71k | if (Local) |
884 | 4.62k | LocalSymbolData.push_back(MSD); |
885 | 9.71k | else |
886 | 5.09k | ExternalSymbolData.push_back(MSD); |
887 | 356k | } |
888 | 2.78k | |
889 | 2.78k | // This holds the .symtab_shndx section index. |
890 | 2.78k | unsigned SymtabShndxSectionIndex = 0; |
891 | 2.78k | |
892 | 2.78k | if (HasLargeSectionIndex2.78k ) { |
893 | 4 | MCSectionELF *SymtabShndxSection = |
894 | 4 | Ctx.getELFSection(".symtab_shndxr", ELF::SHT_SYMTAB_SHNDX, 0, 4, ""); |
895 | 4 | SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection); |
896 | 4 | SymtabShndxSection->setAlignment(4); |
897 | 4 | } |
898 | 2.78k | |
899 | 2.78k | ArrayRef<std::string> FileNames = Asm.getFileNames(); |
900 | 2.78k | for (const std::string &Name : FileNames) |
901 | 666 | StrTabBuilder.add(Name); |
902 | 2.78k | |
903 | 2.78k | StrTabBuilder.finalize(); |
904 | 2.78k | |
905 | 2.78k | // File symbols are emitted first and handled separately from normal symbols, |
906 | 2.78k | // i.e. a non-STT_FILE symbol with the same name may appear. |
907 | 2.78k | for (const std::string &Name : FileNames) |
908 | 667 | Writer.writeSymbol(StrTabBuilder.getOffset(Name), |
909 | 667 | ELF::STT_FILE | ELF::STB_LOCAL, 0, 0, ELF::STV_DEFAULT, |
910 | 667 | ELF::SHN_ABS, true); |
911 | 2.78k | |
912 | 2.78k | // Symbols are required to be in lexicographic order. |
913 | 2.78k | array_pod_sort(LocalSymbolData.begin(), LocalSymbolData.end()); |
914 | 2.78k | array_pod_sort(ExternalSymbolData.begin(), ExternalSymbolData.end()); |
915 | 2.78k | |
916 | 2.78k | // Set the symbol indices. Local symbols must come before all other |
917 | 2.78k | // symbols with non-local bindings. |
918 | 2.78k | unsigned Index = FileNames.size() + 1; |
919 | 2.78k | |
920 | 4.62k | for (ELFSymbolData &MSD : LocalSymbolData) { |
921 | 4.62k | unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION |
922 | 1.70k | ? 0 |
923 | 2.92k | : StrTabBuilder.getOffset(MSD.Name); |
924 | 4.62k | MSD.Symbol->setIndex(Index++); |
925 | 4.62k | writeSymbol(Writer, StringIndex, MSD, Layout); |
926 | 4.62k | } |
927 | 2.78k | |
928 | 2.78k | // Write the symbol table entries. |
929 | 2.78k | LastLocalSymbolIndex = Index; |
930 | 2.78k | |
931 | 5.09k | for (ELFSymbolData &MSD : ExternalSymbolData) { |
932 | 5.09k | unsigned StringIndex = StrTabBuilder.getOffset(MSD.Name); |
933 | 5.09k | MSD.Symbol->setIndex(Index++); |
934 | 5.09k | writeSymbol(Writer, StringIndex, MSD, Layout); |
935 | 5.09k | assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL); |
936 | 5.09k | } |
937 | 2.78k | |
938 | 2.78k | uint64_t SecEnd = getStream().tell(); |
939 | 2.78k | SectionOffsets[SymtabSection] = std::make_pair(SecStart, SecEnd); |
940 | 2.78k | |
941 | 2.78k | ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes(); |
942 | 2.78k | if (ShndxIndexes.empty()2.78k ) { |
943 | 2.78k | assert(SymtabShndxSectionIndex == 0); |
944 | 2.78k | return; |
945 | 2.78k | } |
946 | 2.78k | assert(SymtabShndxSectionIndex != 0); |
947 | 3 | |
948 | 3 | SecStart = getStream().tell(); |
949 | 3 | const MCSectionELF *SymtabShndxSection = |
950 | 3 | SectionTable[SymtabShndxSectionIndex - 1]; |
951 | 3 | for (uint32_t Index : ShndxIndexes) |
952 | 10 | write(Index); |
953 | 2.78k | SecEnd = getStream().tell(); |
954 | 2.78k | SectionOffsets[SymtabShndxSection] = std::make_pair(SecStart, SecEnd); |
955 | 2.78k | } |
956 | | |
957 | | MCSectionELF * |
958 | | ELFObjectWriter::createRelocationSection(MCContext &Ctx, |
959 | 336k | const MCSectionELF &Sec) { |
960 | 336k | if (Relocations[&Sec].empty()) |
961 | 333k | return nullptr; |
962 | 2.56k | |
963 | 2.56k | const StringRef SectionName = Sec.getSectionName(); |
964 | 2.56k | std::string RelaSectionName = hasRelocationAddend() ? ".rela"1.79k : ".rel"773 ; |
965 | 2.56k | RelaSectionName += SectionName; |
966 | 2.56k | |
967 | 2.56k | unsigned EntrySize; |
968 | 2.56k | if (hasRelocationAddend()) |
969 | 1.79k | EntrySize = is64Bit() ? 1.79k sizeof(ELF::Elf64_Rela)1.69k : sizeof(ELF::Elf32_Rela)103 ; |
970 | 2.56k | else |
971 | 773 | EntrySize = is64Bit() ? 773 sizeof(ELF::Elf64_Rel)23 : sizeof(ELF::Elf32_Rel)750 ; |
972 | 2.56k | |
973 | 2.56k | unsigned Flags = 0; |
974 | 2.56k | if (Sec.getFlags() & ELF::SHF_GROUP) |
975 | 43 | Flags = ELF::SHF_GROUP; |
976 | 2.56k | |
977 | 2.56k | MCSectionELF *RelaSection = Ctx.createELFRelSection( |
978 | 2.56k | RelaSectionName, hasRelocationAddend() ? ELF::SHT_RELA1.79k : ELF::SHT_REL774 , |
979 | 2.56k | Flags, EntrySize, Sec.getGroup(), &Sec); |
980 | 2.56k | RelaSection->setAlignment(is64Bit() ? 81.71k : 4853 ); |
981 | 336k | return RelaSection; |
982 | 336k | } |
983 | | |
984 | | // Include the debug info compression header. |
985 | | bool ELFObjectWriter::maybeWriteCompression( |
986 | | uint64_t Size, SmallVectorImpl<char> &CompressedContents, bool ZLibStyle, |
987 | 19 | unsigned Alignment) { |
988 | 19 | if (ZLibStyle19 ) { |
989 | 9 | uint64_t HdrSize = |
990 | 9 | is64Bit() ? sizeof(ELF::Elf32_Chdr)5 : sizeof(ELF::Elf64_Chdr)4 ; |
991 | 9 | if (Size <= HdrSize + CompressedContents.size()) |
992 | 5 | return false; |
993 | 4 | // Platform specific header is followed by compressed data. |
994 | 4 | if (4 is64Bit()4 ) { |
995 | 3 | // Write Elf64_Chdr header. |
996 | 3 | write(static_cast<ELF::Elf64_Word>(ELF::ELFCOMPRESS_ZLIB)); |
997 | 3 | write(static_cast<ELF::Elf64_Word>(0)); // ch_reserved field. |
998 | 3 | write(static_cast<ELF::Elf64_Xword>(Size)); |
999 | 3 | write(static_cast<ELF::Elf64_Xword>(Alignment)); |
1000 | 4 | } else { |
1001 | 1 | // Write Elf32_Chdr header otherwise. |
1002 | 1 | write(static_cast<ELF::Elf32_Word>(ELF::ELFCOMPRESS_ZLIB)); |
1003 | 1 | write(static_cast<ELF::Elf32_Word>(Size)); |
1004 | 1 | write(static_cast<ELF::Elf32_Word>(Alignment)); |
1005 | 1 | } |
1006 | 9 | return true; |
1007 | 9 | } |
1008 | 10 | |
1009 | 10 | // "ZLIB" followed by 8 bytes representing the uncompressed size of the section, |
1010 | 10 | // useful for consumers to preallocate a buffer to decompress into. |
1011 | 10 | const StringRef Magic = "ZLIB"; |
1012 | 10 | if (Size <= Magic.size() + sizeof(Size) + CompressedContents.size()) |
1013 | 5 | return false; |
1014 | 5 | write(ArrayRef<char>(Magic.begin(), Magic.size())); |
1015 | 5 | writeBE64(Size); |
1016 | 5 | return true; |
1017 | 5 | } |
1018 | | |
1019 | | void ELFObjectWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec, |
1020 | 336k | const MCAsmLayout &Layout) { |
1021 | 336k | MCSectionELF &Section = static_cast<MCSectionELF &>(Sec); |
1022 | 336k | StringRef SectionName = Section.getSectionName(); |
1023 | 336k | |
1024 | 336k | auto &MC = Asm.getContext(); |
1025 | 336k | const auto &MAI = MC.getAsmInfo(); |
1026 | 336k | |
1027 | 336k | // Compressing debug_frame requires handling alignment fragments which is |
1028 | 336k | // more work (possibly generalizing MCAssembler.cpp:writeFragment to allow |
1029 | 336k | // for writing to arbitrary buffers) for little benefit. |
1030 | 336k | bool CompressionEnabled = |
1031 | 336k | MAI->compressDebugSections() != DebugCompressionType::None; |
1032 | 336k | if (!CompressionEnabled || 336k !SectionName.startswith(".debug_")30 || |
1033 | 336k | SectionName == ".debug_frame"23 ) { |
1034 | 336k | Asm.writeSectionData(&Section, Layout); |
1035 | 336k | return; |
1036 | 336k | } |
1037 | 15 | |
1038 | 336k | assert((MAI->compressDebugSections() == DebugCompressionType::Z || |
1039 | 15 | MAI->compressDebugSections() == DebugCompressionType::GNU) && |
1040 | 15 | "expected zlib or zlib-gnu style compression"); |
1041 | 15 | |
1042 | 15 | SmallVector<char, 128> UncompressedData; |
1043 | 15 | raw_svector_ostream VecOS(UncompressedData); |
1044 | 15 | raw_pwrite_stream &OldStream = getStream(); |
1045 | 15 | setStream(VecOS); |
1046 | 15 | Asm.writeSectionData(&Section, Layout); |
1047 | 15 | setStream(OldStream); |
1048 | 15 | |
1049 | 15 | SmallVector<char, 128> CompressedContents; |
1050 | 15 | if (Error E = zlib::compress( |
1051 | 15 | StringRef(UncompressedData.data(), UncompressedData.size()), |
1052 | 0 | CompressedContents)) { |
1053 | 0 | consumeError(std::move(E)); |
1054 | 0 | getStream() << UncompressedData; |
1055 | 0 | return; |
1056 | 0 | } |
1057 | 15 | |
1058 | 15 | bool ZlibStyle = MAI->compressDebugSections() == DebugCompressionType::Z; |
1059 | 15 | if (!maybeWriteCompression(UncompressedData.size(), CompressedContents, |
1060 | 15 | ZlibStyle, Sec.getAlignment())) { |
1061 | 10 | getStream() << UncompressedData; |
1062 | 10 | return; |
1063 | 10 | } |
1064 | 5 | |
1065 | 5 | if (5 ZlibStyle5 ) |
1066 | 5 | // Set the compressed flag. That is zlib style. |
1067 | 4 | Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED); |
1068 | 5 | else |
1069 | 5 | // Add "z" prefix to section name. This is zlib-gnu style. |
1070 | 1 | MC.renameELFSection(&Section, (".z" + SectionName.drop_front(1)).str()); |
1071 | 336k | getStream() << CompressedContents; |
1072 | 336k | } |
1073 | | |
1074 | | void ELFObjectWriter::WriteSecHdrEntry(uint32_t Name, uint32_t Type, |
1075 | | uint64_t Flags, uint64_t Address, |
1076 | | uint64_t Offset, uint64_t Size, |
1077 | | uint32_t Link, uint32_t Info, |
1078 | | uint64_t Alignment, |
1079 | 347k | uint64_t EntrySize) { |
1080 | 347k | write32(Name); // sh_name: index into string table |
1081 | 347k | write32(Type); // sh_type |
1082 | 347k | WriteWord(Flags); // sh_flags |
1083 | 347k | WriteWord(Address); // sh_addr |
1084 | 347k | WriteWord(Offset); // sh_offset |
1085 | 347k | WriteWord(Size); // sh_size |
1086 | 347k | write32(Link); // sh_link |
1087 | 347k | write32(Info); // sh_info |
1088 | 347k | WriteWord(Alignment); // sh_addralign |
1089 | 347k | WriteWord(EntrySize); // sh_entsize |
1090 | 347k | } |
1091 | | |
1092 | | void ELFObjectWriter::writeRelocations(const MCAssembler &Asm, |
1093 | 2.56k | const MCSectionELF &Sec) { |
1094 | 2.56k | std::vector<ELFRelocationEntry> &Relocs = Relocations[&Sec]; |
1095 | 2.56k | |
1096 | 2.56k | // We record relocations by pushing to the end of a vector. Reverse the vector |
1097 | 2.56k | // to get the relocations in the order they were created. |
1098 | 2.56k | // In most cases that is not important, but it can be for special sections |
1099 | 2.56k | // (.eh_frame) or specific relocations (TLS optimizations on SystemZ). |
1100 | 2.56k | std::reverse(Relocs.begin(), Relocs.end()); |
1101 | 2.56k | |
1102 | 2.56k | // Sort the relocation entries. MIPS needs this. |
1103 | 2.56k | TargetObjectWriter->sortRelocs(Asm, Relocs); |
1104 | 2.56k | |
1105 | 12.2k | for (unsigned i = 0, e = Relocs.size(); i != e12.2k ; ++i9.70k ) { |
1106 | 9.70k | const ELFRelocationEntry &Entry = Relocs[e - i - 1]; |
1107 | 9.70k | unsigned Index = Entry.Symbol ? Entry.Symbol->getIndex()9.65k : 054 ; |
1108 | 9.70k | |
1109 | 9.70k | if (is64Bit()9.70k ) { |
1110 | 5.80k | write(Entry.Offset); |
1111 | 5.80k | if (TargetObjectWriter->getEMachine() == ELF::EM_MIPS5.80k ) { |
1112 | 273 | write(uint32_t(Index)); |
1113 | 273 | |
1114 | 273 | write(TargetObjectWriter->getRSsym(Entry.Type)); |
1115 | 273 | write(TargetObjectWriter->getRType3(Entry.Type)); |
1116 | 273 | write(TargetObjectWriter->getRType2(Entry.Type)); |
1117 | 273 | write(TargetObjectWriter->getRType(Entry.Type)); |
1118 | 5.80k | } else { |
1119 | 5.53k | struct ELF::Elf64_Rela ERE64; |
1120 | 5.53k | ERE64.setSymbolAndType(Index, Entry.Type); |
1121 | 5.53k | write(ERE64.r_info); |
1122 | 5.53k | } |
1123 | 5.80k | if (hasRelocationAddend()) |
1124 | 5.73k | write(Entry.Addend); |
1125 | 9.70k | } else { |
1126 | 3.90k | write(uint32_t(Entry.Offset)); |
1127 | 3.90k | |
1128 | 3.90k | struct ELF::Elf32_Rela ERE32; |
1129 | 3.90k | ERE32.setSymbolAndType(Index, Entry.Type); |
1130 | 3.90k | write(ERE32.r_info); |
1131 | 3.90k | |
1132 | 3.90k | if (hasRelocationAddend()) |
1133 | 360 | write(uint32_t(Entry.Addend)); |
1134 | 3.90k | |
1135 | 3.90k | if (TargetObjectWriter->getEMachine() == ELF::EM_MIPS3.90k ) { |
1136 | 911 | if (uint32_t RType911 = TargetObjectWriter->getRType2(Entry.Type)) { |
1137 | 2 | write(uint32_t(Entry.Offset)); |
1138 | 2 | |
1139 | 2 | ERE32.setSymbolAndType(0, RType); |
1140 | 2 | write(ERE32.r_info); |
1141 | 2 | write(uint32_t(0)); |
1142 | 2 | } |
1143 | 911 | if (uint32_t RType911 = TargetObjectWriter->getRType3(Entry.Type)) { |
1144 | 2 | write(uint32_t(Entry.Offset)); |
1145 | 2 | |
1146 | 2 | ERE32.setSymbolAndType(0, RType); |
1147 | 2 | write(ERE32.r_info); |
1148 | 2 | write(uint32_t(0)); |
1149 | 2 | } |
1150 | 911 | } |
1151 | 3.90k | } |
1152 | 9.70k | } |
1153 | 2.56k | } |
1154 | | |
1155 | 2.78k | const MCSectionELF *ELFObjectWriter::createStringTable(MCContext &Ctx) { |
1156 | 2.78k | const MCSectionELF *StrtabSection = SectionTable[StringTableIndex - 1]; |
1157 | 2.78k | StrTabBuilder.write(getStream()); |
1158 | 2.78k | return StrtabSection; |
1159 | 2.78k | } |
1160 | | |
1161 | | void ELFObjectWriter::writeSection(const SectionIndexMapTy &SectionIndexMap, |
1162 | | uint32_t GroupSymbolIndex, uint64_t Offset, |
1163 | 344k | uint64_t Size, const MCSectionELF &Section) { |
1164 | 344k | uint64_t sh_link = 0; |
1165 | 344k | uint64_t sh_info = 0; |
1166 | 344k | |
1167 | 344k | switch(Section.getType()) { |
1168 | 339k | default: |
1169 | 339k | // Nothing to do. |
1170 | 339k | break; |
1171 | 344k | |
1172 | 0 | case ELF::SHT_DYNAMIC: |
1173 | 0 | llvm_unreachable("SHT_DYNAMIC in a relocatable object"); |
1174 | 344k | |
1175 | 2.56k | case ELF::SHT_REL: |
1176 | 2.56k | case ELF::SHT_RELA: { |
1177 | 2.56k | sh_link = SymbolTableIndex; |
1178 | 2.56k | assert(sh_link && ".symtab not found"); |
1179 | 2.56k | const MCSection *InfoSection = Section.getAssociatedSection(); |
1180 | 2.56k | sh_info = SectionIndexMap.lookup(cast<MCSectionELF>(InfoSection)); |
1181 | 2.56k | break; |
1182 | 2.56k | } |
1183 | 2.56k | |
1184 | 2.78k | case ELF::SHT_SYMTAB: |
1185 | 2.78k | case ELF::SHT_DYNSYM: |
1186 | 2.78k | sh_link = StringTableIndex; |
1187 | 2.78k | sh_info = LastLocalSymbolIndex; |
1188 | 2.78k | break; |
1189 | 2.78k | |
1190 | 4 | case ELF::SHT_SYMTAB_SHNDX: |
1191 | 4 | sh_link = SymbolTableIndex; |
1192 | 4 | break; |
1193 | 2.78k | |
1194 | 76 | case ELF::SHT_GROUP: |
1195 | 76 | sh_link = SymbolTableIndex; |
1196 | 76 | sh_info = GroupSymbolIndex; |
1197 | 76 | break; |
1198 | 344k | } |
1199 | 344k | |
1200 | 344k | if (344k Section.getFlags() & ELF::SHF_LINK_ORDER344k ) { |
1201 | 207 | const MCSymbol *Sym = Section.getAssociatedSymbol(); |
1202 | 207 | const MCSectionELF *Sec = cast<MCSectionELF>(&Sym->getSection()); |
1203 | 207 | sh_link = SectionIndexMap.lookup(Sec); |
1204 | 207 | } |
1205 | 344k | |
1206 | 344k | WriteSecHdrEntry(StrTabBuilder.getOffset(Section.getSectionName()), |
1207 | 344k | Section.getType(), Section.getFlags(), 0, Offset, Size, |
1208 | 344k | sh_link, sh_info, Section.getAlignment(), |
1209 | 344k | Section.getEntrySize()); |
1210 | 344k | } |
1211 | | |
1212 | | void ELFObjectWriter::writeSectionHeader( |
1213 | | const MCAsmLayout &Layout, const SectionIndexMapTy &SectionIndexMap, |
1214 | 2.78k | const SectionOffsetsTy &SectionOffsets) { |
1215 | 2.78k | const unsigned NumSections = SectionTable.size(); |
1216 | 2.78k | |
1217 | 2.78k | // Null section first. |
1218 | 2.78k | uint64_t FirstSectionSize = |
1219 | 2.78k | (NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 15 : 02.78k ; |
1220 | 2.78k | WriteSecHdrEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, 0, 0); |
1221 | 2.78k | |
1222 | 344k | for (const MCSectionELF *Section : SectionTable) { |
1223 | 344k | uint32_t GroupSymbolIndex; |
1224 | 344k | unsigned Type = Section->getType(); |
1225 | 344k | if (Type != ELF::SHT_GROUP) |
1226 | 344k | GroupSymbolIndex = 0; |
1227 | 344k | else |
1228 | 76 | GroupSymbolIndex = Section->getGroup()->getIndex(); |
1229 | 344k | |
1230 | 344k | const std::pair<uint64_t, uint64_t> &Offsets = |
1231 | 344k | SectionOffsets.find(Section)->second; |
1232 | 344k | uint64_t Size; |
1233 | 344k | if (Type == ELF::SHT_NOBITS) |
1234 | 657 | Size = Layout.getSectionAddressSize(Section); |
1235 | 344k | else |
1236 | 344k | Size = Offsets.second - Offsets.first; |
1237 | 344k | |
1238 | 344k | writeSection(SectionIndexMap, GroupSymbolIndex, Offsets.first, Size, |
1239 | 344k | *Section); |
1240 | 344k | } |
1241 | 2.78k | } |
1242 | | |
1243 | | void ELFObjectWriter::writeObject(MCAssembler &Asm, |
1244 | 2.78k | const MCAsmLayout &Layout) { |
1245 | 2.78k | MCContext &Ctx = Asm.getContext(); |
1246 | 2.78k | MCSectionELF *StrtabSection = |
1247 | 2.78k | Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0); |
1248 | 2.78k | StringTableIndex = addToSectionTable(StrtabSection); |
1249 | 2.78k | |
1250 | 2.78k | RevGroupMapTy RevGroupMap; |
1251 | 2.78k | SectionIndexMapTy SectionIndexMap; |
1252 | 2.78k | |
1253 | 2.78k | std::map<const MCSymbol *, std::vector<const MCSectionELF *>> GroupMembers; |
1254 | 2.78k | |
1255 | 2.78k | // Write out the ELF header ... |
1256 | 2.78k | writeHeader(Asm); |
1257 | 2.78k | |
1258 | 2.78k | // ... then the sections ... |
1259 | 2.78k | SectionOffsetsTy SectionOffsets; |
1260 | 2.78k | std::vector<MCSectionELF *> Groups; |
1261 | 2.78k | std::vector<MCSectionELF *> Relocations; |
1262 | 336k | for (MCSection &Sec : Asm) { |
1263 | 336k | MCSectionELF &Section = static_cast<MCSectionELF &>(Sec); |
1264 | 336k | |
1265 | 336k | align(Section.getAlignment()); |
1266 | 336k | |
1267 | 336k | // Remember the offset into the file for this section. |
1268 | 336k | uint64_t SecStart = getStream().tell(); |
1269 | 336k | |
1270 | 336k | const MCSymbolELF *SignatureSymbol = Section.getGroup(); |
1271 | 336k | writeSectionData(Asm, Section, Layout); |
1272 | 336k | |
1273 | 336k | uint64_t SecEnd = getStream().tell(); |
1274 | 336k | SectionOffsets[&Section] = std::make_pair(SecStart, SecEnd); |
1275 | 336k | |
1276 | 336k | MCSectionELF *RelSection = createRelocationSection(Ctx, Section); |
1277 | 336k | |
1278 | 336k | if (SignatureSymbol336k ) { |
1279 | 101 | Asm.registerSymbol(*SignatureSymbol); |
1280 | 101 | unsigned &GroupIdx = RevGroupMap[SignatureSymbol]; |
1281 | 101 | if (!GroupIdx101 ) { |
1282 | 76 | MCSectionELF *Group = Ctx.createELFGroupSection(SignatureSymbol); |
1283 | 76 | GroupIdx = addToSectionTable(Group); |
1284 | 76 | Group->setAlignment(4); |
1285 | 76 | Groups.push_back(Group); |
1286 | 76 | } |
1287 | 101 | std::vector<const MCSectionELF *> &Members = |
1288 | 101 | GroupMembers[SignatureSymbol]; |
1289 | 101 | Members.push_back(&Section); |
1290 | 101 | if (RelSection) |
1291 | 43 | Members.push_back(RelSection); |
1292 | 101 | } |
1293 | 336k | |
1294 | 336k | SectionIndexMap[&Section] = addToSectionTable(&Section); |
1295 | 336k | if (RelSection336k ) { |
1296 | 2.56k | SectionIndexMap[RelSection] = addToSectionTable(RelSection); |
1297 | 2.56k | Relocations.push_back(RelSection); |
1298 | 2.56k | } |
1299 | 336k | } |
1300 | 2.78k | |
1301 | 76 | for (MCSectionELF *Group : Groups) { |
1302 | 76 | align(Group->getAlignment()); |
1303 | 76 | |
1304 | 76 | // Remember the offset into the file for this section. |
1305 | 76 | uint64_t SecStart = getStream().tell(); |
1306 | 76 | |
1307 | 76 | const MCSymbol *SignatureSymbol = Group->getGroup(); |
1308 | 76 | assert(SignatureSymbol); |
1309 | 76 | write(uint32_t(ELF::GRP_COMDAT)); |
1310 | 144 | for (const MCSectionELF *Member : GroupMembers[SignatureSymbol]) { |
1311 | 144 | uint32_t SecIndex = SectionIndexMap.lookup(Member); |
1312 | 144 | write(SecIndex); |
1313 | 144 | } |
1314 | 76 | |
1315 | 76 | uint64_t SecEnd = getStream().tell(); |
1316 | 76 | SectionOffsets[Group] = std::make_pair(SecStart, SecEnd); |
1317 | 76 | } |
1318 | 2.78k | |
1319 | 2.78k | // Compute symbol table information. |
1320 | 2.78k | computeSymbolTable(Asm, Layout, SectionIndexMap, RevGroupMap, SectionOffsets); |
1321 | 2.78k | |
1322 | 2.56k | for (MCSectionELF *RelSection : Relocations) { |
1323 | 2.56k | align(RelSection->getAlignment()); |
1324 | 2.56k | |
1325 | 2.56k | // Remember the offset into the file for this section. |
1326 | 2.56k | uint64_t SecStart = getStream().tell(); |
1327 | 2.56k | |
1328 | 2.56k | writeRelocations(Asm, |
1329 | 2.56k | cast<MCSectionELF>(*RelSection->getAssociatedSection())); |
1330 | 2.56k | |
1331 | 2.56k | uint64_t SecEnd = getStream().tell(); |
1332 | 2.56k | SectionOffsets[RelSection] = std::make_pair(SecStart, SecEnd); |
1333 | 2.56k | } |
1334 | 2.78k | |
1335 | 2.78k | { |
1336 | 2.78k | uint64_t SecStart = getStream().tell(); |
1337 | 2.78k | const MCSectionELF *Sec = createStringTable(Ctx); |
1338 | 2.78k | uint64_t SecEnd = getStream().tell(); |
1339 | 2.78k | SectionOffsets[Sec] = std::make_pair(SecStart, SecEnd); |
1340 | 2.78k | } |
1341 | 2.78k | |
1342 | 2.78k | uint64_t NaturalAlignment = is64Bit() ? 81.80k : 4985 ; |
1343 | 2.78k | align(NaturalAlignment); |
1344 | 2.78k | |
1345 | 2.78k | const uint64_t SectionHeaderOffset = getStream().tell(); |
1346 | 2.78k | |
1347 | 2.78k | // ... then the section header table ... |
1348 | 2.78k | writeSectionHeader(Layout, SectionIndexMap, SectionOffsets); |
1349 | 2.78k | |
1350 | 2.78k | uint16_t NumSections = (SectionTable.size() + 1 >= ELF::SHN_LORESERVE) |
1351 | 5 | ? (uint16_t)ELF::SHN_UNDEF |
1352 | 2.78k | : SectionTable.size() + 1; |
1353 | 2.78k | if (sys::IsLittleEndianHost != IsLittleEndian) |
1354 | 385 | sys::swapByteOrder(NumSections); |
1355 | 2.78k | unsigned NumSectionsOffset; |
1356 | 2.78k | |
1357 | 2.78k | if (is64Bit()2.78k ) { |
1358 | 1.80k | uint64_t Val = SectionHeaderOffset; |
1359 | 1.80k | if (sys::IsLittleEndianHost != IsLittleEndian) |
1360 | 148 | sys::swapByteOrder(Val); |
1361 | 1.80k | getStream().pwrite(reinterpret_cast<char *>(&Val), sizeof(Val), |
1362 | 1.80k | offsetof(ELF::Elf64_Ehdr, e_shoff)); |
1363 | 1.80k | NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum); |
1364 | 2.78k | } else { |
1365 | 985 | uint32_t Val = SectionHeaderOffset; |
1366 | 985 | if (sys::IsLittleEndianHost != IsLittleEndian) |
1367 | 237 | sys::swapByteOrder(Val); |
1368 | 985 | getStream().pwrite(reinterpret_cast<char *>(&Val), sizeof(Val), |
1369 | 985 | offsetof(ELF::Elf32_Ehdr, e_shoff)); |
1370 | 985 | NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum); |
1371 | 985 | } |
1372 | 2.78k | getStream().pwrite(reinterpret_cast<char *>(&NumSections), |
1373 | 2.78k | sizeof(NumSections), NumSectionsOffset); |
1374 | 2.78k | } |
1375 | | |
1376 | | bool ELFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl( |
1377 | | const MCAssembler &Asm, const MCSymbol &SA, const MCFragment &FB, |
1378 | 10.8k | bool InSet, bool IsPCRel) const { |
1379 | 10.8k | const auto &SymA = cast<MCSymbolELF>(SA); |
1380 | 10.8k | if (IsPCRel10.8k ) { |
1381 | 1.32k | assert(!InSet); |
1382 | 1.32k | if (isWeak(SymA)) |
1383 | 54 | return false; |
1384 | 10.7k | } |
1385 | 10.7k | return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB, |
1386 | 10.7k | InSet, IsPCRel); |
1387 | 10.7k | } |
1388 | | |
1389 | | MCObjectWriter *llvm::createELFObjectWriter(MCELFObjectTargetWriter *MOTW, |
1390 | | raw_pwrite_stream &OS, |
1391 | 2.85k | bool IsLittleEndian) { |
1392 | 2.85k | return new ELFObjectWriter(MOTW, OS, IsLittleEndian); |
1393 | 2.85k | } |