LLVM 21.0.0git
ELFObjectWriter.cpp
Go to the documentation of this file.
1//===- lib/MC/ELFObjectWriter.cpp - ELF File Writer -----------------------===//
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 implements ELF object file writer information.
10//
11//===----------------------------------------------------------------------===//
12
13#include "llvm/ADT/ArrayRef.h"
14#include "llvm/ADT/DenseMap.h"
15#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/Statistic.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/Twine.h"
23#include "llvm/MC/MCAsmInfo.h"
24#include "llvm/MC/MCAssembler.h"
25#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCELFExtras.h"
28#include "llvm/MC/MCExpr.h"
29#include "llvm/MC/MCFixup.h"
31#include "llvm/MC/MCFragment.h"
33#include "llvm/MC/MCSection.h"
35#include "llvm/MC/MCSymbol.h"
36#include "llvm/MC/MCSymbolELF.h"
38#include "llvm/MC/MCValue.h"
43#include "llvm/Support/Endian.h"
46#include "llvm/Support/LEB128.h"
47#include "llvm/Support/SMLoc.h"
50#include <cassert>
51#include <cstddef>
52#include <cstdint>
53#include <memory>
54#include <string>
55#include <utility>
56#include <vector>
57
58using namespace llvm;
59
60#define DEBUG_TYPE "elf-object-writer"
61
62namespace {
63namespace stats {
64
65STATISTIC(ELFHeaderBytes, "Total size of ELF headers");
66STATISTIC(SectionHeaderBytes, "Total size of section headers table");
67STATISTIC(AllocTextBytes, "Total size of SHF_ALLOC text sections");
68STATISTIC(AllocROBytes, "Total size of SHF_ALLOC readonly sections");
69STATISTIC(AllocRWBytes, "Total size of SHF_ALLOC read-write sections");
70STATISTIC(StrtabBytes, "Total size of SHT_STRTAB sections");
71STATISTIC(SymtabBytes, "Total size of SHT_SYMTAB sections");
72STATISTIC(RelocationBytes, "Total size of relocation sections");
73STATISTIC(DynsymBytes, "Total size of SHT_DYNSYM sections");
75 DebugBytes,
76 "Total size of debug info sections (not including those written to .dwo)");
77STATISTIC(UnwindBytes, "Total size of unwind sections");
78STATISTIC(OtherBytes, "Total size of uncategorized sections");
79STATISTIC(DwoBytes, "Total size of sections written to .dwo file");
80
81} // namespace stats
82
83struct ELFWriter;
84
85bool isDwoSection(const MCSectionELF &Sec) {
86 return Sec.getName().ends_with(".dwo");
87}
88
89class SymbolTableWriter {
90 ELFWriter &EWriter;
91 bool Is64Bit;
92
93 // indexes we are going to write to .symtab_shndx.
94 std::vector<uint32_t> ShndxIndexes;
95
96 // The numbel of symbols written so far.
97 unsigned NumWritten;
98
99 void createSymtabShndx();
100
101 template <typename T> void write(T Value);
102
103public:
104 SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit);
105
106 void writeSymbol(uint32_t name, uint8_t info, uint64_t value, uint64_t size,
107 uint8_t other, uint32_t shndx, bool Reserved);
108
109 ArrayRef<uint32_t> getShndxIndexes() const { return ShndxIndexes; }
110};
111
112struct ELFWriter {
113 ELFObjectWriter &OWriter;
115
116 enum DwoMode {
117 AllSections,
118 NonDwoOnly,
119 DwoOnly,
120 } Mode;
121
122 static uint64_t symbolValue(const MCAssembler &Asm, const MCSymbol &Sym);
123 static bool isInSymtab(const MCAssembler &Asm, const MCSymbolELF &Symbol,
124 bool Used, bool Renamed);
125
126 /// Helper struct for containing some precomputed information on symbols.
127 struct ELFSymbolData {
128 const MCSymbolELF *Symbol;
130 uint32_t SectionIndex;
131 uint32_t Order;
132 };
133
134 /// @}
135 /// @name Symbol Table Data
136 /// @{
137
139
140 /// @}
141
142 // This holds the symbol table index of the last local symbol.
143 unsigned LastLocalSymbolIndex = ~0u;
144 // This holds the .strtab section index.
145 unsigned StringTableIndex = ~0u;
146 // This holds the .symtab section index.
147 unsigned SymbolTableIndex = ~0u;
148
149 // Sections in the order they are to be output in the section table.
150 std::vector<MCSectionELF *> SectionTable;
151 unsigned addToSectionTable(MCSectionELF *Sec);
152
153 // TargetObjectWriter wrappers.
154 bool is64Bit() const;
155
156 uint64_t align(Align Alignment);
157
158 bool maybeWriteCompression(uint32_t ChType, uint64_t Size,
159 SmallVectorImpl<uint8_t> &CompressedContents,
160 Align Alignment);
161
162public:
163 ELFWriter(ELFObjectWriter &OWriter, raw_pwrite_stream &OS,
164 bool IsLittleEndian, DwoMode Mode)
165 : OWriter(OWriter), W(OS, IsLittleEndian ? llvm::endianness::little
166 : llvm::endianness::big),
167 Mode(Mode) {}
168
169 void writeWord(uint64_t Word) {
170 if (is64Bit())
171 W.write<uint64_t>(Word);
172 else
173 W.write<uint32_t>(Word);
174 }
175
176 template <typename T> void write(T Val) {
177 W.write(Val);
178 }
179
180 void writeHeader(const MCAssembler &Asm);
181
182 void writeSymbol(const MCAssembler &Asm, SymbolTableWriter &Writer,
183 uint32_t StringIndex, ELFSymbolData &MSD);
184
185 // Map from a signature symbol to the group section index
186 using RevGroupMapTy = DenseMap<const MCSymbol *, unsigned>;
187
188 /// Compute the symbol table data
189 ///
190 /// \param Asm - The assembler.
191 /// \param RevGroupMap - Maps a signature symbol to the group section.
192 void computeSymbolTable(MCAssembler &Asm, const RevGroupMapTy &RevGroupMap);
193
194 void writeAddrsigSection();
195
196 MCSectionELF *createRelocationSection(MCContext &Ctx,
197 const MCSectionELF &Sec);
198
199 void writeSectionHeaders(const MCAssembler &Asm);
200
201 void writeSectionData(const MCAssembler &Asm, MCSection &Sec);
202
203 void writeSectionHeaderEntry(uint32_t Name, uint32_t Type, uint64_t Flags,
205 uint32_t Link, uint32_t Info,
206 MaybeAlign Alignment, uint64_t EntrySize);
207
208 void writeRelocations(const MCAssembler &Asm, const MCSectionELF &Sec);
209
210 uint64_t writeObject(MCAssembler &Asm);
211 void writeSectionHeader(uint32_t GroupSymbolIndex, uint64_t Offset,
212 uint64_t Size, const MCSectionELF &Section);
213};
214} // end anonymous namespace
215
216uint64_t ELFWriter::align(Align Alignment) {
217 uint64_t Offset = W.OS.tell();
218 uint64_t NewOffset = alignTo(Offset, Alignment);
219 W.OS.write_zeros(NewOffset - Offset);
220 return NewOffset;
221}
222
223unsigned ELFWriter::addToSectionTable(MCSectionELF *Sec) {
224 SectionTable.push_back(Sec);
225 StrTabBuilder.add(Sec->getName());
226 return SectionTable.size();
227}
228
229void SymbolTableWriter::createSymtabShndx() {
230 if (!ShndxIndexes.empty())
231 return;
232
233 ShndxIndexes.resize(NumWritten);
234}
235
236template <typename T> void SymbolTableWriter::write(T Value) {
237 EWriter.write(Value);
238}
239
240SymbolTableWriter::SymbolTableWriter(ELFWriter &EWriter, bool Is64Bit)
241 : EWriter(EWriter), Is64Bit(Is64Bit), NumWritten(0) {}
242
243void SymbolTableWriter::writeSymbol(uint32_t name, uint8_t info, uint64_t value,
244 uint64_t size, uint8_t other,
245 uint32_t shndx, bool Reserved) {
246 bool LargeIndex = shndx >= ELF::SHN_LORESERVE && !Reserved;
247
248 if (LargeIndex)
249 createSymtabShndx();
250
251 if (!ShndxIndexes.empty()) {
252 if (LargeIndex)
253 ShndxIndexes.push_back(shndx);
254 else
255 ShndxIndexes.push_back(0);
256 }
257
258 uint16_t Index = LargeIndex ? uint16_t(ELF::SHN_XINDEX) : shndx;
259
260 if (Is64Bit) {
261 write(name); // st_name
262 write(info); // st_info
263 write(other); // st_other
264 write(Index); // st_shndx
265 write(value); // st_value
266 write(size); // st_size
267 } else {
268 write(name); // st_name
269 write(uint32_t(value)); // st_value
270 write(uint32_t(size)); // st_size
271 write(info); // st_info
272 write(other); // st_other
273 write(Index); // st_shndx
274 }
275
276 ++NumWritten;
277}
278
279bool ELFWriter::is64Bit() const {
280 return OWriter.TargetObjectWriter->is64Bit();
281}
282
283// Emit the ELF header.
284void ELFWriter::writeHeader(const MCAssembler &Asm) {
285 // ELF Header
286 // ----------
287 //
288 // Note
289 // ----
290 // emitWord method behaves differently for ELF32 and ELF64, writing
291 // 4 bytes in the former and 8 in the latter.
292
293 W.OS << ELF::ElfMagic; // e_ident[EI_MAG0] to e_ident[EI_MAG3]
294
295 W.OS << char(is64Bit() ? ELF::ELFCLASS64 : ELF::ELFCLASS32); // e_ident[EI_CLASS]
296
297 // e_ident[EI_DATA]
300
301 W.OS << char(ELF::EV_CURRENT); // e_ident[EI_VERSION]
302 // e_ident[EI_OSABI]
303 uint8_t OSABI = OWriter.TargetObjectWriter->getOSABI();
304 W.OS << char(OSABI == ELF::ELFOSABI_NONE && OWriter.seenGnuAbi()
305 ? int(ELF::ELFOSABI_GNU)
306 : OSABI);
307 // e_ident[EI_ABIVERSION]
308 W.OS << char(OWriter.OverrideABIVersion
309 ? *OWriter.OverrideABIVersion
310 : OWriter.TargetObjectWriter->getABIVersion());
311
312 W.OS.write_zeros(ELF::EI_NIDENT - ELF::EI_PAD);
313
314 W.write<uint16_t>(ELF::ET_REL); // e_type
315
316 W.write<uint16_t>(OWriter.TargetObjectWriter->getEMachine()); // e_machine = target
317
318 W.write<uint32_t>(ELF::EV_CURRENT); // e_version
319 writeWord(0); // e_entry, no entry point in .o file
320 writeWord(0); // e_phoff, no program header for .o
321 writeWord(0); // e_shoff = sec hdr table off in bytes
322
323 // e_flags = whatever the target wants
324 W.write<uint32_t>(OWriter.getELFHeaderEFlags());
325
326 // e_ehsize = ELF header size
327 W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Ehdr)
328 : sizeof(ELF::Elf32_Ehdr));
329
330 W.write<uint16_t>(0); // e_phentsize = prog header entry size
331 W.write<uint16_t>(0); // e_phnum = # prog header entries = 0
332
333 // e_shentsize = Section header entry size
334 W.write<uint16_t>(is64Bit() ? sizeof(ELF::Elf64_Shdr)
335 : sizeof(ELF::Elf32_Shdr));
336
337 // e_shnum = # of section header ents
338 W.write<uint16_t>(0);
339
340 // e_shstrndx = Section # of '.strtab'
341 assert(StringTableIndex < ELF::SHN_LORESERVE);
342 W.write<uint16_t>(StringTableIndex);
343}
344
345uint64_t ELFWriter::symbolValue(const MCAssembler &Asm, const MCSymbol &Sym) {
346 if (Sym.isCommon())
347 return Sym.getCommonAlignment()->value();
348
349 uint64_t Res;
350 if (!Asm.getSymbolOffset(Sym, Res))
351 return 0;
352
353 if (Asm.isThumbFunc(&Sym))
354 Res |= 1;
355
356 return Res;
357}
358
359static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType) {
360 uint8_t Type = newType;
361
362 // Propagation rules:
363 // IFUNC > FUNC > OBJECT > NOTYPE
364 // TLS_OBJECT > OBJECT > NOTYPE
365 //
366 // dont let the new type degrade the old type
367 switch (origType) {
368 default:
369 break;
371 if (Type == ELF::STT_FUNC || Type == ELF::STT_OBJECT ||
374 break;
375 case ELF::STT_FUNC:
379 break;
380 case ELF::STT_OBJECT:
381 if (Type == ELF::STT_NOTYPE)
383 break;
384 case ELF::STT_TLS:
388 break;
389 }
390
391 return Type;
392}
393
394static bool isIFunc(const MCSymbolELF *Symbol) {
395 while (Symbol->getType() != ELF::STT_GNU_IFUNC) {
396 const MCSymbolRefExpr *Value;
397 if (!Symbol->isVariable() ||
398 !(Value = dyn_cast<MCSymbolRefExpr>(Symbol->getVariableValue())) ||
399 Value->getKind() != MCSymbolRefExpr::VK_None ||
401 return false;
402 Symbol = &cast<MCSymbolELF>(Value->getSymbol());
403 }
404 return true;
405}
406
407void ELFWriter::writeSymbol(const MCAssembler &Asm, SymbolTableWriter &Writer,
408 uint32_t StringIndex, ELFSymbolData &MSD) {
409 const auto &Symbol = cast<MCSymbolELF>(*MSD.Symbol);
410 const MCSymbolELF *Base =
411 cast_or_null<MCSymbolELF>(Asm.getBaseSymbol(Symbol));
412
413 // This has to be in sync with when computeSymbolTable uses SHN_ABS or
414 // SHN_COMMON.
415 bool IsReserved = !Base || Symbol.isCommon();
416
417 // Binding and Type share the same byte as upper and lower nibbles
418 uint8_t Binding = Symbol.getBinding();
419 uint8_t Type = Symbol.getType();
420 if (isIFunc(&Symbol))
422 if (Base) {
423 Type = mergeTypeForSet(Type, Base->getType());
424 }
425 uint8_t Info = (Binding << 4) | Type;
426
427 // Other and Visibility share the same byte with Visibility using the lower
428 // 2 bits
429 uint8_t Visibility = Symbol.getVisibility();
430 uint8_t Other = Symbol.getOther() | Visibility;
431
432 uint64_t Value = symbolValue(Asm, *MSD.Symbol);
433 uint64_t Size = 0;
434
435 const MCExpr *ESize = MSD.Symbol->getSize();
436 if (!ESize && Base) {
437 // For expressions like .set y, x+1, if y's size is unset, inherit from x.
438 ESize = Base->getSize();
439
440 // For `.size x, 2; y = x; .size y, 1; z = y; z1 = z; .symver y, y@v1`, z,
441 // z1, and y@v1's st_size equals y's. However, `Base` is `x` which will give
442 // us 2. Follow the MCSymbolRefExpr assignment chain, which covers most
443 // needs. MCBinaryExpr is not handled.
444 const MCSymbolELF *Sym = &Symbol;
445 while (Sym->isVariable()) {
446 if (auto *Expr =
447 dyn_cast<MCSymbolRefExpr>(Sym->getVariableValue(false))) {
448 Sym = cast<MCSymbolELF>(&Expr->getSymbol());
449 if (!Sym->getSize())
450 continue;
451 ESize = Sym->getSize();
452 }
453 break;
454 }
455 }
456
457 if (ESize) {
458 int64_t Res;
459 if (!ESize->evaluateKnownAbsolute(Res, Asm))
460 report_fatal_error("Size expression must be absolute.");
461 Size = Res;
462 }
463
464 // Write out the symbol table entry
465 Writer.writeSymbol(StringIndex, Info, Value, Size, Other, MSD.SectionIndex,
466 IsReserved);
467}
468
469bool ELFWriter::isInSymtab(const MCAssembler &Asm, const MCSymbolELF &Symbol,
470 bool Used, bool Renamed) {
471 if (Symbol.isVariable()) {
472 const MCExpr *Expr = Symbol.getVariableValue();
473 // Target Expressions that are always inlined do not appear in the symtab
474 if (const auto *T = dyn_cast<MCTargetExpr>(Expr))
475 if (T->inlineAssignedExpr())
476 return false;
477 if (const MCSymbolRefExpr *Ref = dyn_cast<MCSymbolRefExpr>(Expr)) {
478 if (Ref->getKind() == MCSymbolRefExpr::VK_WEAKREF)
479 return false;
480 }
481 }
482
483 if (Used)
484 return true;
485
486 if (Renamed)
487 return false;
488
489 if (Symbol.isVariable() && Symbol.isUndefined()) {
490 // FIXME: this is here just to diagnose the case of a var = commmon_sym.
491 Asm.getBaseSymbol(Symbol);
492 return false;
493 }
494
495 if (Symbol.isTemporary())
496 return false;
497
498 if (Symbol.getType() == ELF::STT_SECTION)
499 return false;
500
501 return true;
502}
503
504void ELFWriter::computeSymbolTable(MCAssembler &Asm,
505 const RevGroupMapTy &RevGroupMap) {
506 MCContext &Ctx = Asm.getContext();
507 SymbolTableWriter Writer(*this, is64Bit());
508
509 // Symbol table
510 unsigned EntrySize = is64Bit() ? ELF::SYMENTRY_SIZE64 : ELF::SYMENTRY_SIZE32;
511 MCSectionELF *SymtabSection =
512 Ctx.getELFSection(".symtab", ELF::SHT_SYMTAB, 0, EntrySize);
513 SymtabSection->setAlignment(is64Bit() ? Align(8) : Align(4));
514 SymbolTableIndex = addToSectionTable(SymtabSection);
515
516 uint64_t SecStart = align(SymtabSection->getAlign());
517
518 // The first entry is the undefined symbol entry.
519 Writer.writeSymbol(0, 0, 0, 0, 0, 0, false);
520
521 std::vector<ELFSymbolData> LocalSymbolData;
522 std::vector<ELFSymbolData> ExternalSymbolData;
524 OWriter.getFileNames();
525 for (const std::pair<std::string, size_t> &F : FileNames)
526 StrTabBuilder.add(F.first);
527
528 // Add the data for the symbols.
529 bool HasLargeSectionIndex = false;
530 for (auto It : llvm::enumerate(Asm.symbols())) {
531 const auto &Symbol = cast<MCSymbolELF>(It.value());
532 bool Used = Symbol.isUsedInReloc();
533 bool WeakrefUsed = Symbol.isWeakrefUsedInReloc();
534 bool isSignature = Symbol.isSignature();
535
536 if (!isInSymtab(Asm, Symbol, Used || WeakrefUsed || isSignature,
537 OWriter.Renames.count(&Symbol)))
538 continue;
539
540 if (Symbol.isTemporary() && Symbol.isUndefined()) {
541 Ctx.reportError(SMLoc(), "Undefined temporary symbol " + Symbol.getName());
542 continue;
543 }
544
545 ELFSymbolData MSD;
546 MSD.Symbol = cast<MCSymbolELF>(&Symbol);
547 MSD.Order = It.index();
548
549 bool Local = Symbol.getBinding() == ELF::STB_LOCAL;
550 assert(Local || !Symbol.isTemporary());
551
552 if (Symbol.isAbsolute()) {
553 MSD.SectionIndex = ELF::SHN_ABS;
554 } else if (Symbol.isCommon()) {
555 if (Symbol.isTargetCommon()) {
556 MSD.SectionIndex = Symbol.getIndex();
557 } else {
558 assert(!Local);
559 MSD.SectionIndex = ELF::SHN_COMMON;
560 }
561 } else if (Symbol.isUndefined()) {
562 if (isSignature && !Used) {
563 MSD.SectionIndex = RevGroupMap.lookup(&Symbol);
564 if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
565 HasLargeSectionIndex = true;
566 } else {
567 MSD.SectionIndex = ELF::SHN_UNDEF;
568 }
569 } else {
570 const MCSectionELF &Section =
571 static_cast<const MCSectionELF &>(Symbol.getSection());
572
573 // We may end up with a situation when section symbol is technically
574 // defined, but should not be. That happens because we explicitly
575 // pre-create few .debug_* sections to have accessors.
576 // And if these sections were not really defined in the code, but were
577 // referenced, we simply error out.
578 if (!Section.isRegistered()) {
579 assert(static_cast<const MCSymbolELF &>(Symbol).getType() ==
581 Ctx.reportError(SMLoc(),
582 "Undefined section reference: " + Symbol.getName());
583 continue;
584 }
585
586 if (Mode == NonDwoOnly && isDwoSection(Section))
587 continue;
588 MSD.SectionIndex = Section.getOrdinal();
589 assert(MSD.SectionIndex && "Invalid section index!");
590 if (MSD.SectionIndex >= ELF::SHN_LORESERVE)
591 HasLargeSectionIndex = true;
592 }
593
594 // Temporary symbols generated for certain assembler features (.eh_frame,
595 // .debug_line) of an empty name may be referenced by relocations due to
596 // linker relaxation. Rename them to ".L0 " to match the gas fake label name
597 // and allow ld/objcopy --discard-locals to discard such symbols.
598 StringRef Name = Symbol.getName();
599 if (Name.empty())
600 Name = ".L0 ";
601
602 // Sections have their own string table
603 if (Symbol.getType() != ELF::STT_SECTION) {
604 MSD.Name = Name;
605 StrTabBuilder.add(Name);
606 }
607
608 if (Local)
609 LocalSymbolData.push_back(MSD);
610 else
611 ExternalSymbolData.push_back(MSD);
612 }
613
614 // This holds the .symtab_shndx section index.
615 unsigned SymtabShndxSectionIndex = 0;
616
617 if (HasLargeSectionIndex) {
618 MCSectionELF *SymtabShndxSection =
619 Ctx.getELFSection(".symtab_shndx", ELF::SHT_SYMTAB_SHNDX, 0, 4);
620 SymtabShndxSectionIndex = addToSectionTable(SymtabShndxSection);
621 SymtabShndxSection->setAlignment(Align(4));
622 }
623
624 StrTabBuilder.finalize();
625
626 // Make the first STT_FILE precede previous local symbols.
627 unsigned Index = 1;
628 auto FileNameIt = FileNames.begin();
629 if (!FileNames.empty())
630 FileNames[0].second = 0;
631
632 for (ELFSymbolData &MSD : LocalSymbolData) {
633 // Emit STT_FILE symbols before their associated local symbols.
634 for (; FileNameIt != FileNames.end() && FileNameIt->second <= MSD.Order;
635 ++FileNameIt) {
636 Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),
638 ELF::SHN_ABS, true);
639 ++Index;
640 }
641
642 unsigned StringIndex = MSD.Symbol->getType() == ELF::STT_SECTION
643 ? 0
644 : StrTabBuilder.getOffset(MSD.Name);
645 MSD.Symbol->setIndex(Index++);
646 writeSymbol(Asm, Writer, StringIndex, MSD);
647 }
648 for (; FileNameIt != FileNames.end(); ++FileNameIt) {
649 Writer.writeSymbol(StrTabBuilder.getOffset(FileNameIt->first),
651 ELF::SHN_ABS, true);
652 ++Index;
653 }
654
655 // Write the symbol table entries.
656 LastLocalSymbolIndex = Index;
657
658 for (ELFSymbolData &MSD : ExternalSymbolData) {
659 unsigned StringIndex = StrTabBuilder.getOffset(MSD.Name);
660 MSD.Symbol->setIndex(Index++);
661 writeSymbol(Asm, Writer, StringIndex, MSD);
662 assert(MSD.Symbol->getBinding() != ELF::STB_LOCAL);
663 }
664
665 uint64_t SecEnd = W.OS.tell();
666 SymtabSection->setOffsets(SecStart, SecEnd);
667
668 ArrayRef<uint32_t> ShndxIndexes = Writer.getShndxIndexes();
669 if (ShndxIndexes.empty()) {
670 assert(SymtabShndxSectionIndex == 0);
671 return;
672 }
673 assert(SymtabShndxSectionIndex != 0);
674
675 SecStart = W.OS.tell();
676 MCSectionELF *SymtabShndxSection = SectionTable[SymtabShndxSectionIndex - 1];
677 for (uint32_t Index : ShndxIndexes)
678 write(Index);
679 SecEnd = W.OS.tell();
680 SymtabShndxSection->setOffsets(SecStart, SecEnd);
681}
682
683void ELFWriter::writeAddrsigSection() {
684 for (const MCSymbol *Sym : OWriter.getAddrsigSyms())
685 if (Sym->getIndex() != 0)
686 encodeULEB128(Sym->getIndex(), W.OS);
687}
688
689MCSectionELF *ELFWriter::createRelocationSection(MCContext &Ctx,
690 const MCSectionELF &Sec) {
691 if (OWriter.Relocations[&Sec].empty())
692 return nullptr;
693
694 unsigned Flags = ELF::SHF_INFO_LINK;
695 if (Sec.getFlags() & ELF::SHF_GROUP)
697
698 const StringRef SectionName = Sec.getName();
699 const MCTargetOptions *TO = Ctx.getTargetOptions();
700 if (TO && TO->Crel) {
701 MCSectionELF *RelaSection =
702 Ctx.createELFRelSection(".crel" + SectionName, ELF::SHT_CREL, Flags,
703 /*EntrySize=*/1, Sec.getGroup(), &Sec);
704 return RelaSection;
705 }
706
707 const bool Rela = OWriter.usesRela(TO, Sec);
708 unsigned EntrySize;
709 if (Rela)
710 EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rela) : sizeof(ELF::Elf32_Rela);
711 else
712 EntrySize = is64Bit() ? sizeof(ELF::Elf64_Rel) : sizeof(ELF::Elf32_Rel);
713
714 MCSectionELF *RelaSection =
715 Ctx.createELFRelSection(((Rela ? ".rela" : ".rel") + SectionName),
717 EntrySize, Sec.getGroup(), &Sec);
718 RelaSection->setAlignment(is64Bit() ? Align(8) : Align(4));
719 return RelaSection;
720}
721
722// Include the debug info compression header.
723bool ELFWriter::maybeWriteCompression(
724 uint32_t ChType, uint64_t Size,
725 SmallVectorImpl<uint8_t> &CompressedContents, Align Alignment) {
726 uint64_t HdrSize =
727 is64Bit() ? sizeof(ELF::Elf64_Chdr) : sizeof(ELF::Elf32_Chdr);
728 if (Size <= HdrSize + CompressedContents.size())
729 return false;
730 // Platform specific header is followed by compressed data.
731 if (is64Bit()) {
732 // Write Elf64_Chdr header.
733 write(static_cast<ELF::Elf64_Word>(ChType));
734 write(static_cast<ELF::Elf64_Word>(0)); // ch_reserved field.
735 write(static_cast<ELF::Elf64_Xword>(Size));
736 write(static_cast<ELF::Elf64_Xword>(Alignment.value()));
737 } else {
738 // Write Elf32_Chdr header otherwise.
739 write(static_cast<ELF::Elf32_Word>(ChType));
740 write(static_cast<ELF::Elf32_Word>(Size));
741 write(static_cast<ELF::Elf32_Word>(Alignment.value()));
742 }
743 return true;
744}
745
746void ELFWriter::writeSectionData(const MCAssembler &Asm, MCSection &Sec) {
747 MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
748 StringRef SectionName = Section.getName();
749 auto &Ctx = Asm.getContext();
750 const DebugCompressionType CompressionType =
752 : DebugCompressionType::None;
753 if (CompressionType == DebugCompressionType::None ||
754 !SectionName.starts_with(".debug_")) {
755 Asm.writeSectionData(W.OS, &Section);
756 return;
757 }
758
759 SmallVector<char, 128> UncompressedData;
760 raw_svector_ostream VecOS(UncompressedData);
761 Asm.writeSectionData(VecOS, &Section);
762 ArrayRef<uint8_t> Uncompressed =
763 ArrayRef(reinterpret_cast<uint8_t *>(UncompressedData.data()),
764 UncompressedData.size());
765
766 SmallVector<uint8_t, 128> Compressed;
767 uint32_t ChType;
768 switch (CompressionType) {
769 case DebugCompressionType::None:
770 llvm_unreachable("has been handled");
771 case DebugCompressionType::Zlib:
772 ChType = ELF::ELFCOMPRESS_ZLIB;
773 break;
774 case DebugCompressionType::Zstd:
775 ChType = ELF::ELFCOMPRESS_ZSTD;
776 break;
777 }
778 compression::compress(compression::Params(CompressionType), Uncompressed,
779 Compressed);
780 if (!maybeWriteCompression(ChType, UncompressedData.size(), Compressed,
781 Sec.getAlign())) {
782 W.OS << UncompressedData;
783 return;
784 }
785
786 Section.setFlags(Section.getFlags() | ELF::SHF_COMPRESSED);
787 // Alignment field should reflect the requirements of
788 // the compressed section header.
789 Section.setAlignment(is64Bit() ? Align(8) : Align(4));
790 W.OS << toStringRef(Compressed);
791}
792
793void ELFWriter::writeSectionHeaderEntry(uint32_t Name, uint32_t Type,
794 uint64_t Flags, uint64_t Address,
796 uint32_t Link, uint32_t Info,
797 MaybeAlign Alignment,
798 uint64_t EntrySize) {
799 W.write<uint32_t>(Name); // sh_name: index into string table
800 W.write<uint32_t>(Type); // sh_type
801 writeWord(Flags); // sh_flags
802 writeWord(Address); // sh_addr
803 writeWord(Offset); // sh_offset
804 writeWord(Size); // sh_size
805 W.write<uint32_t>(Link); // sh_link
806 W.write<uint32_t>(Info); // sh_info
807 writeWord(Alignment ? Alignment->value() : 0); // sh_addralign
808 writeWord(EntrySize); // sh_entsize
809}
810
811template <bool Is64>
813 using uint = std::conditional_t<Is64, uint64_t, uint32_t>;
814 ELF::encodeCrel<Is64>(OS, Relocs, [&](const ELFRelocationEntry &R) {
815 uint32_t SymIdx = R.Symbol ? R.Symbol->getIndex() : 0;
816 return ELF::Elf_Crel<Is64>{static_cast<uint>(R.Offset), SymIdx, R.Type,
817 std::make_signed_t<uint>(R.Addend)};
818 });
819}
820
821void ELFWriter::writeRelocations(const MCAssembler &Asm,
822 const MCSectionELF &Sec) {
823 std::vector<ELFRelocationEntry> &Relocs = OWriter.Relocations[&Sec];
824 const MCTargetOptions *TO = Asm.getContext().getTargetOptions();
825 const bool Rela = OWriter.usesRela(TO, Sec);
826
827 // Sort the relocation entries. MIPS needs this.
828 OWriter.TargetObjectWriter->sortRelocs(Asm, Relocs);
829
830 if (OWriter.TargetObjectWriter->getEMachine() == ELF::EM_MIPS) {
831 for (const ELFRelocationEntry &Entry : Relocs) {
832 uint32_t SymIdx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
833 if (is64Bit()) {
834 write(Entry.Offset);
835 write(uint32_t(SymIdx));
836 write(OWriter.TargetObjectWriter->getRSsym(Entry.Type));
837 write(OWriter.TargetObjectWriter->getRType3(Entry.Type));
838 write(OWriter.TargetObjectWriter->getRType2(Entry.Type));
839 write(OWriter.TargetObjectWriter->getRType(Entry.Type));
840 if (Rela)
841 write(Entry.Addend);
842 } else {
843 write(uint32_t(Entry.Offset));
844 ELF::Elf32_Rela ERE32;
845 ERE32.setSymbolAndType(SymIdx, Entry.Type);
846 write(ERE32.r_info);
847 if (Rela)
848 write(uint32_t(Entry.Addend));
849 if (uint32_t RType =
850 OWriter.TargetObjectWriter->getRType2(Entry.Type)) {
851 write(uint32_t(Entry.Offset));
852 ERE32.setSymbolAndType(0, RType);
853 write(ERE32.r_info);
854 write(uint32_t(0));
855 }
856 if (uint32_t RType =
857 OWriter.TargetObjectWriter->getRType3(Entry.Type)) {
858 write(uint32_t(Entry.Offset));
859 ERE32.setSymbolAndType(0, RType);
860 write(ERE32.r_info);
861 write(uint32_t(0));
862 }
863 }
864 }
865 } else if (TO && TO->Crel) {
866 if (is64Bit())
867 encodeCrel<true>(Relocs, W.OS);
868 else
869 encodeCrel<false>(Relocs, W.OS);
870 } else {
871 for (const ELFRelocationEntry &Entry : Relocs) {
872 uint32_t Symidx = Entry.Symbol ? Entry.Symbol->getIndex() : 0;
873 if (is64Bit()) {
874 write(Entry.Offset);
875 ELF::Elf64_Rela ERE;
876 ERE.setSymbolAndType(Symidx, Entry.Type);
877 write(ERE.r_info);
878 if (Rela)
879 write(Entry.Addend);
880 } else {
881 write(uint32_t(Entry.Offset));
882 ELF::Elf32_Rela ERE;
883 ERE.setSymbolAndType(Symidx, Entry.Type);
884 write(ERE.r_info);
885 if (Rela)
886 write(uint32_t(Entry.Addend));
887 }
888 }
889 }
890}
891
892void ELFWriter::writeSectionHeader(uint32_t GroupSymbolIndex, uint64_t Offset,
893 uint64_t Size, const MCSectionELF &Section) {
894 uint64_t sh_link = 0;
895 uint64_t sh_info = 0;
896
897 switch(Section.getType()) {
898 default:
899 // Nothing to do.
900 break;
901
902 case ELF::SHT_DYNAMIC:
903 llvm_unreachable("SHT_DYNAMIC in a relocatable object");
904
905 case ELF::SHT_REL:
906 case ELF::SHT_RELA:
907 case ELF::SHT_CREL: {
908 sh_link = SymbolTableIndex;
909 assert(sh_link && ".symtab not found");
910 const MCSection *InfoSection = Section.getLinkedToSection();
911 sh_info = InfoSection->getOrdinal();
912 break;
913 }
914
915 case ELF::SHT_SYMTAB:
916 sh_link = StringTableIndex;
917 sh_info = LastLocalSymbolIndex;
918 break;
919
923 sh_link = SymbolTableIndex;
924 break;
925
926 case ELF::SHT_GROUP:
927 sh_link = SymbolTableIndex;
928 sh_info = GroupSymbolIndex;
929 break;
930 }
931
932 if (Section.getFlags() & ELF::SHF_LINK_ORDER) {
933 // If the value in the associated metadata is not a definition, Sym will be
934 // undefined. Represent this with sh_link=0.
935 const MCSymbol *Sym = Section.getLinkedToSymbol();
936 if (Sym && Sym->isInSection())
937 sh_link = Sym->getSection().getOrdinal();
938 }
939
940 writeSectionHeaderEntry(StrTabBuilder.getOffset(Section.getName()),
941 Section.getType(), Section.getFlags(), 0, Offset,
942 Size, sh_link, sh_info, Section.getAlign(),
943 Section.getEntrySize());
944}
945
946void ELFWriter::writeSectionHeaders(const MCAssembler &Asm) {
947 uint64_t Start = W.OS.tell();
948 const unsigned NumSections = SectionTable.size();
949
950 // Null section first.
951 uint64_t FirstSectionSize =
952 (NumSections + 1) >= ELF::SHN_LORESERVE ? NumSections + 1 : 0;
953 writeSectionHeaderEntry(0, 0, 0, 0, 0, FirstSectionSize, 0, 0, std::nullopt,
954 0);
955
956 for (const MCSectionELF *Section : SectionTable) {
957 uint32_t GroupSymbolIndex;
958 unsigned Type = Section->getType();
959 if (Type != ELF::SHT_GROUP)
960 GroupSymbolIndex = 0;
961 else
962 GroupSymbolIndex = Section->getGroup()->getIndex();
963
964 std::pair<uint64_t, uint64_t> Offsets = Section->getOffsets();
966 if (Type == ELF::SHT_NOBITS)
967 Size = Asm.getSectionAddressSize(*Section);
968 else
969 Size = Offsets.second - Offsets.first;
970
971 auto SectionHasFlag = [&](uint64_t Flag) -> bool {
972 return Section->getFlags() & Flag;
973 };
974
975 if (Mode == DwoOnly) {
976 stats::DwoBytes += Size;
977 } else if (Section->getName().starts_with(".debug")) {
978 stats::DebugBytes += Size;
979 } else if (Section->getName().starts_with(".eh_frame")) {
980 stats::UnwindBytes += Size;
981 } else if (SectionHasFlag(ELF::SHF_ALLOC)) {
982 if (SectionHasFlag(ELF::SHF_EXECINSTR)) {
983 stats::AllocTextBytes += Size;
984 } else if (SectionHasFlag(ELF::SHF_WRITE)) {
985 stats::AllocRWBytes += Size;
986 } else {
987 stats::AllocROBytes += Size;
988 }
989 } else {
990 switch (Section->getType()) {
991 case ELF::SHT_STRTAB:
992 stats::StrtabBytes += Size;
993 break;
994 case ELF::SHT_SYMTAB:
995 stats::SymtabBytes += Size;
996 break;
997 case ELF::SHT_DYNSYM:
998 stats::DynsymBytes += Size;
999 break;
1000 case ELF::SHT_REL:
1001 case ELF::SHT_RELA:
1002 case ELF::SHT_CREL:
1003 stats::RelocationBytes += Size;
1004 break;
1005 default:
1006 stats::OtherBytes += Size;
1007 break;
1008 }
1009 }
1010
1011 writeSectionHeader(GroupSymbolIndex, Offsets.first, Size, *Section);
1012 }
1013
1014 stats::SectionHeaderBytes += W.OS.tell() - Start;
1015}
1016
1017uint64_t ELFWriter::writeObject(MCAssembler &Asm) {
1018 uint64_t StartOffset = W.OS.tell();
1019
1020 MCContext &Ctx = Asm.getContext();
1021 MCSectionELF *StrtabSection =
1022 Ctx.getELFSection(".strtab", ELF::SHT_STRTAB, 0);
1023 StringTableIndex = addToSectionTable(StrtabSection);
1024
1025 RevGroupMapTy RevGroupMap;
1026
1027 // Write out the ELF header ...
1028 writeHeader(Asm);
1029
1030 stats::ELFHeaderBytes += W.OS.tell() - StartOffset;
1031
1032 // ... then the sections ...
1034 // Map from group section index to group
1035 SmallVector<unsigned, 0> GroupMap;
1036 SmallVector<MCSectionELF *> Relocations;
1037 for (MCSection &Sec : Asm) {
1038 MCSectionELF &Section = static_cast<MCSectionELF &>(Sec);
1039 if (Mode == NonDwoOnly && isDwoSection(Section))
1040 continue;
1041 if (Mode == DwoOnly && !isDwoSection(Section))
1042 continue;
1043
1044 // Remember the offset into the file for this section.
1045 const uint64_t SecStart = align(Section.getAlign());
1046
1047 const MCSymbolELF *SignatureSymbol = Section.getGroup();
1048 writeSectionData(Asm, Section);
1049
1050 uint64_t SecEnd = W.OS.tell();
1051 Section.setOffsets(SecStart, SecEnd);
1052
1053 MCSectionELF *RelSection = createRelocationSection(Ctx, Section);
1054
1055 unsigned *GroupIdxEntry = nullptr;
1056 if (SignatureSymbol) {
1057 GroupIdxEntry = &RevGroupMap[SignatureSymbol];
1058 if (!*GroupIdxEntry) {
1059 MCSectionELF *Group =
1060 Ctx.createELFGroupSection(SignatureSymbol, Section.isComdat());
1061 *GroupIdxEntry = addToSectionTable(Group);
1062 Group->setAlignment(Align(4));
1063
1064 GroupMap.resize(*GroupIdxEntry + 1);
1065 GroupMap[*GroupIdxEntry] = Groups.size();
1066 Groups.emplace_back(Group, SmallVector<unsigned>{});
1067 }
1068 }
1069
1070 Section.setOrdinal(addToSectionTable(&Section));
1071 if (RelSection) {
1072 RelSection->setOrdinal(addToSectionTable(RelSection));
1073 Relocations.push_back(RelSection);
1074 }
1075
1076 if (GroupIdxEntry) {
1077 auto &Members = Groups[GroupMap[*GroupIdxEntry]];
1078 Members.second.push_back(Section.getOrdinal());
1079 if (RelSection)
1080 Members.second.push_back(RelSection->getOrdinal());
1081 }
1082 }
1083
1084 for (auto &[Group, Members] : Groups) {
1085 // Remember the offset into the file for this section.
1086 const uint64_t SecStart = align(Group->getAlign());
1087
1088 write(uint32_t(Group->isComdat() ? unsigned(ELF::GRP_COMDAT) : 0));
1089 W.write<unsigned>(Members);
1090
1091 uint64_t SecEnd = W.OS.tell();
1092 Group->setOffsets(SecStart, SecEnd);
1093 }
1094
1095 if (Mode == DwoOnly) {
1096 // dwo files don't have symbol tables or relocations, but they do have
1097 // string tables.
1098 StrTabBuilder.finalize();
1099 } else {
1100 MCSectionELF *AddrsigSection;
1101 if (OWriter.getEmitAddrsigSection()) {
1102 AddrsigSection = Ctx.getELFSection(".llvm_addrsig", ELF::SHT_LLVM_ADDRSIG,
1104 addToSectionTable(AddrsigSection);
1105 }
1106
1107 // Compute symbol table information.
1108 computeSymbolTable(Asm, RevGroupMap);
1109
1110 for (MCSectionELF *RelSection : Relocations) {
1111 // Remember the offset into the file for this section.
1112 const uint64_t SecStart = align(RelSection->getAlign());
1113
1114 writeRelocations(Asm,
1115 cast<MCSectionELF>(*RelSection->getLinkedToSection()));
1116
1117 uint64_t SecEnd = W.OS.tell();
1118 RelSection->setOffsets(SecStart, SecEnd);
1119 }
1120
1121 if (OWriter.getEmitAddrsigSection()) {
1122 uint64_t SecStart = W.OS.tell();
1123 writeAddrsigSection();
1124 uint64_t SecEnd = W.OS.tell();
1125 AddrsigSection->setOffsets(SecStart, SecEnd);
1126 }
1127 }
1128
1129 {
1130 uint64_t SecStart = W.OS.tell();
1131 StrTabBuilder.write(W.OS);
1132 StrtabSection->setOffsets(SecStart, W.OS.tell());
1133 }
1134
1135 const uint64_t SectionHeaderOffset = align(is64Bit() ? Align(8) : Align(4));
1136
1137 // ... then the section header table ...
1138 writeSectionHeaders(Asm);
1139
1140 uint16_t NumSections = support::endian::byte_swap<uint16_t>(
1141 (SectionTable.size() + 1 >= ELF::SHN_LORESERVE) ? (uint16_t)ELF::SHN_UNDEF
1142 : SectionTable.size() + 1,
1143 W.Endian);
1144 unsigned NumSectionsOffset;
1145
1146 auto &Stream = static_cast<raw_pwrite_stream &>(W.OS);
1147 if (is64Bit()) {
1148 uint64_t Val =
1149 support::endian::byte_swap<uint64_t>(SectionHeaderOffset, W.Endian);
1150 Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
1151 offsetof(ELF::Elf64_Ehdr, e_shoff));
1152 NumSectionsOffset = offsetof(ELF::Elf64_Ehdr, e_shnum);
1153 } else {
1154 uint32_t Val =
1155 support::endian::byte_swap<uint32_t>(SectionHeaderOffset, W.Endian);
1156 Stream.pwrite(reinterpret_cast<char *>(&Val), sizeof(Val),
1157 offsetof(ELF::Elf32_Ehdr, e_shoff));
1158 NumSectionsOffset = offsetof(ELF::Elf32_Ehdr, e_shnum);
1159 }
1160 Stream.pwrite(reinterpret_cast<char *>(&NumSections), sizeof(NumSections),
1161 NumSectionsOffset);
1162
1163 return W.OS.tell() - StartOffset;
1164}
1165
1166ELFObjectWriter::ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
1167 raw_pwrite_stream &OS, bool IsLittleEndian)
1168 : TargetObjectWriter(std::move(MOTW)), OS(OS),
1169 IsLittleEndian(IsLittleEndian) {}
1170ELFObjectWriter::ELFObjectWriter(std::unique_ptr<MCELFObjectTargetWriter> MOTW,
1172 raw_pwrite_stream &DwoOS, bool IsLittleEndian)
1173 : TargetObjectWriter(std::move(MOTW)), OS(OS), DwoOS(&DwoOS),
1174 IsLittleEndian(IsLittleEndian) {}
1175
1177 ELFHeaderEFlags = 0;
1178 SeenGnuAbi = false;
1179 OverrideABIVersion.reset();
1180 Relocations.clear();
1181 Renames.clear();
1182 Symvers.clear();
1184}
1185
1187 return TargetObjectWriter->hasRelocationAddend();
1188}
1189
1191 // The presence of symbol versions causes undefined symbols and
1192 // versions declared with @@@ to be renamed.
1193 for (const Symver &S : Symvers) {
1194 StringRef AliasName = S.Name;
1195 const auto &Symbol = cast<MCSymbolELF>(*S.Sym);
1196 size_t Pos = AliasName.find('@');
1197 assert(Pos != StringRef::npos);
1198
1199 StringRef Prefix = AliasName.substr(0, Pos);
1200 StringRef Rest = AliasName.substr(Pos);
1201 StringRef Tail = Rest;
1202 if (Rest.starts_with("@@@"))
1203 Tail = Rest.substr(Symbol.isUndefined() ? 2 : 1);
1204
1205 auto *Alias =
1206 cast<MCSymbolELF>(Asm.getContext().getOrCreateSymbol(Prefix + Tail));
1207 Asm.registerSymbol(*Alias);
1208 const MCExpr *Value = MCSymbolRefExpr::create(&Symbol, Asm.getContext());
1209 Alias->setVariableValue(Value);
1210
1211 // Aliases defined with .symvar copy the binding from the symbol they alias.
1212 // This is the first place we are able to copy this information.
1213 Alias->setBinding(Symbol.getBinding());
1214 Alias->setVisibility(Symbol.getVisibility());
1215 Alias->setOther(Symbol.getOther());
1216
1217 if (!Symbol.isUndefined() && S.KeepOriginalSym)
1218 continue;
1219
1220 if (Symbol.isUndefined() && Rest.starts_with("@@") &&
1221 !Rest.starts_with("@@@")) {
1222 Asm.getContext().reportError(S.Loc, "default version symbol " +
1223 AliasName + " must be defined");
1224 continue;
1225 }
1226
1227 if (auto It = Renames.find(&Symbol);
1228 It != Renames.end() && It->second != Alias) {
1229 Asm.getContext().reportError(S.Loc, Twine("multiple versions for ") +
1230 Symbol.getName());
1231 continue;
1232 }
1233
1234 Renames.insert(std::make_pair(&Symbol, Alias));
1235 }
1236
1237 for (const MCSymbol *&Sym : AddrsigSyms) {
1238 if (const MCSymbol *R = Renames.lookup(cast<MCSymbolELF>(Sym)))
1239 Sym = R;
1240 if (Sym->isInSection() && Sym->getName().starts_with(".L"))
1241 Sym = Sym->getSection().getBeginSymbol();
1242 Sym->setUsedInReloc();
1243 }
1244}
1245
1246// It is always valid to create a relocation with a symbol. It is preferable
1247// to use a relocation with a section if that is possible. Using the section
1248// allows us to omit some local symbols from the symbol table.
1250 const MCValue &Val,
1251 const MCSymbolELF *Sym,
1252 uint64_t C,
1253 unsigned Type) const {
1254 const MCSymbolRefExpr *RefA = Val.getSymA();
1255 // A PCRel relocation to an absolute value has no symbol (or section). We
1256 // represent that with a relocation to a null section.
1257 if (!RefA)
1258 return false;
1259
1261 switch (Kind) {
1262 default:
1263 break;
1264 // The .odp creation emits a relocation against the symbol ".TOC." which
1265 // create a R_PPC64_TOC relocation. However the relocation symbol name
1266 // in final object creation should be NULL, since the symbol does not
1267 // really exist, it is just the reference to TOC base for the current
1268 // object file. Since the symbol is undefined, returning false results
1269 // in a relocation with a null section which is the desired result.
1271 return false;
1272
1273 // These VariantKind cause the relocation to refer to something other than
1274 // the symbol itself, like a linker generated table. Since the address of
1275 // symbol is not relevant, we cannot replace the symbol with the
1276 // section and patch the difference in the addend.
1284 return true;
1285 }
1286
1287 // An undefined symbol is not in any section, so the relocation has to point
1288 // to the symbol itself.
1289 assert(Sym && "Expected a symbol");
1290 if (Sym->isUndefined())
1291 return true;
1292
1293 // For memory-tagged symbols, ensure that the relocation uses the symbol. For
1294 // tagged symbols, we emit an empty relocation (R_AARCH64_NONE) in a special
1295 // section (SHT_AARCH64_MEMTAG_GLOBALS_STATIC) to indicate to the linker that
1296 // this global needs to be tagged. In addition, the linker needs to know
1297 // whether to emit a special addend when relocating `end` symbols, and this
1298 // can only be determined by the attributes of the symbol itself.
1299 if (Sym->isMemtag())
1300 return true;
1301
1302 unsigned Binding = Sym->getBinding();
1303 switch(Binding) {
1304 default:
1305 llvm_unreachable("Invalid Binding");
1306 case ELF::STB_LOCAL:
1307 break;
1308 case ELF::STB_WEAK:
1309 // If the symbol is weak, it might be overridden by a symbol in another
1310 // file. The relocation has to point to the symbol so that the linker
1311 // can update it.
1312 return true;
1313 case ELF::STB_GLOBAL:
1315 // Global ELF symbols can be preempted by the dynamic linker. The relocation
1316 // has to point to the symbol for a reason analogous to the STB_WEAK case.
1317 return true;
1318 }
1319
1320 // Keep symbol type for a local ifunc because it may result in an IRELATIVE
1321 // reloc that the dynamic loader will use to resolve the address at startup
1322 // time.
1323 if (Sym->getType() == ELF::STT_GNU_IFUNC)
1324 return true;
1325
1326 // If a relocation points to a mergeable section, we have to be careful.
1327 // If the offset is zero, a relocation with the section will encode the
1328 // same information. With a non-zero offset, the situation is different.
1329 // For example, a relocation can point 42 bytes past the end of a string.
1330 // If we change such a relocation to use the section, the linker would think
1331 // that it pointed to another string and subtracting 42 at runtime will
1332 // produce the wrong value.
1333 if (Sym->isInSection()) {
1334 auto &Sec = cast<MCSectionELF>(Sym->getSection());
1335 unsigned Flags = Sec.getFlags();
1336 if (Flags & ELF::SHF_MERGE) {
1337 if (C != 0)
1338 return true;
1339
1340 // gold<2.34 incorrectly ignored the addend for R_386_GOTOFF (9)
1341 // (http://sourceware.org/PR16794).
1342 if (TargetObjectWriter->getEMachine() == ELF::EM_386 &&
1343 Type == ELF::R_386_GOTOFF)
1344 return true;
1345
1346 // ld.lld handles R_MIPS_HI16/R_MIPS_LO16 separately, not as a whole, so
1347 // it doesn't know that an R_MIPS_HI16 with implicit addend 1 and an
1348 // R_MIPS_LO16 with implicit addend -32768 represents 32768, which is in
1349 // range of a MergeInputSection. We could introduce a new RelExpr member
1350 // (like R_RISCV_PC_INDIRECT for R_RISCV_PCREL_HI20 / R_RISCV_PCREL_LO12)
1351 // but the complexity is unnecessary given that GNU as keeps the original
1352 // symbol for this case as well.
1353 if (TargetObjectWriter->getEMachine() == ELF::EM_MIPS &&
1355 return true;
1356 }
1357
1358 // Most TLS relocations use a got, so they need the symbol. Even those that
1359 // are just an offset (@tpoff), require a symbol in gold versions before
1360 // 5efeedf61e4fe720fd3e9a08e6c91c10abb66d42 (2014-09-26) which fixed
1361 // http://sourceware.org/PR16773.
1362 if (Flags & ELF::SHF_TLS)
1363 return true;
1364 }
1365
1366 // If the symbol is a thumb function the final relocation must set the lowest
1367 // bit. With a symbol that is done by just having the symbol have that bit
1368 // set, so we would lose the bit if we relocated with the section.
1369 // FIXME: We could use the section but add the bit to the relocation value.
1370 if (Asm.isThumbFunc(Sym))
1371 return true;
1372
1373 if (TargetObjectWriter->needsRelocateWithSymbol(Val, *Sym, Type))
1374 return true;
1375 return false;
1376}
1377
1379 const MCSectionELF *From,
1380 const MCSectionELF *To) {
1381 if (DwoOS) {
1382 if (isDwoSection(*From)) {
1383 Ctx.reportError(Loc, "A dwo section may not contain relocations");
1384 return false;
1385 }
1386 if (To && isDwoSection(*To)) {
1387 Ctx.reportError(Loc, "A relocation may not refer to a dwo section");
1388 return false;
1389 }
1390 }
1391 return true;
1392}
1393
1395 const MCFragment *Fragment,
1396 const MCFixup &Fixup, MCValue Target,
1397 uint64_t &FixedValue) {
1398 MCAsmBackend &Backend = Asm.getBackend();
1399 bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
1401 const MCSectionELF &FixupSection = cast<MCSectionELF>(*Fragment->getParent());
1402 uint64_t C = Target.getConstant();
1403 uint64_t FixupOffset = Asm.getFragmentOffset(*Fragment) + Fixup.getOffset();
1404 MCContext &Ctx = Asm.getContext();
1405 const MCTargetOptions *TO = Ctx.getTargetOptions();
1406
1407 if (const MCSymbolRefExpr *RefB = Target.getSymB()) {
1408 const auto &SymB = cast<MCSymbolELF>(RefB->getSymbol());
1409 if (SymB.isUndefined()) {
1410 Ctx.reportError(Fixup.getLoc(),
1411 Twine("symbol '") + SymB.getName() +
1412 "' can not be undefined in a subtraction expression");
1413 return;
1414 }
1415
1416 assert(!SymB.isAbsolute() && "Should have been folded");
1417 const MCSection &SecB = SymB.getSection();
1418 if (&SecB != &FixupSection) {
1419 Ctx.reportError(Fixup.getLoc(),
1420 "Cannot represent a difference across sections");
1421 return;
1422 }
1423
1424 assert(!IsPCRel && "should have been folded");
1425 IsPCRel = true;
1426 C += FixupOffset - Asm.getSymbolOffset(SymB);
1427 }
1428
1429 // We either rejected the fixup or folded B into C at this point.
1430 const MCSymbolRefExpr *RefA = Target.getSymA();
1431 const auto *SymA = RefA ? cast<MCSymbolELF>(&RefA->getSymbol()) : nullptr;
1432
1433 bool ViaWeakRef = false;
1434 if (SymA && SymA->isVariable()) {
1435 const MCExpr *Expr = SymA->getVariableValue();
1436 if (const auto *Inner = dyn_cast<MCSymbolRefExpr>(Expr)) {
1437 if (Inner->getKind() == MCSymbolRefExpr::VK_WEAKREF) {
1438 SymA = cast<MCSymbolELF>(&Inner->getSymbol());
1439 ViaWeakRef = true;
1440 }
1441 }
1442 }
1443
1444 const MCSectionELF *SecA = (SymA && SymA->isInSection())
1445 ? cast<MCSectionELF>(&SymA->getSection())
1446 : nullptr;
1447 if (!checkRelocation(Ctx, Fixup.getLoc(), &FixupSection, SecA))
1448 return;
1449
1450 unsigned Type = TargetObjectWriter->getRelocType(Ctx, Target, Fixup, IsPCRel);
1451 const auto *Parent = cast<MCSectionELF>(Fragment->getParent());
1452 // Emiting relocation with sybmol for CG Profile to help with --cg-profile.
1453 bool RelocateWithSymbol =
1454 shouldRelocateWithSymbol(Asm, Target, SymA, C, Type) ||
1455 (Parent->getType() == ELF::SHT_LLVM_CALL_GRAPH_PROFILE);
1456 uint64_t Addend = !RelocateWithSymbol && SymA && !SymA->isUndefined()
1457 ? C + Asm.getSymbolOffset(*SymA)
1458 : C;
1459 FixedValue = usesRela(TO, FixupSection) ? 0 : Addend;
1460
1461 if (!RelocateWithSymbol) {
1462 const auto *SectionSymbol =
1463 SecA ? cast<MCSymbolELF>(SecA->getBeginSymbol()) : nullptr;
1464 if (SectionSymbol)
1465 SectionSymbol->setUsedInReloc();
1466 ELFRelocationEntry Rec(FixupOffset, SectionSymbol, Type, Addend);
1467 Relocations[&FixupSection].push_back(Rec);
1468 return;
1469 }
1470
1471 const MCSymbolELF *RenamedSymA = SymA;
1472 if (SymA) {
1473 if (const MCSymbolELF *R = Renames.lookup(SymA))
1474 RenamedSymA = R;
1475
1476 if (ViaWeakRef)
1477 RenamedSymA->setIsWeakrefUsedInReloc();
1478 else
1479 RenamedSymA->setUsedInReloc();
1480 }
1481 ELFRelocationEntry Rec(FixupOffset, RenamedSymA, Type, Addend);
1482 Relocations[&FixupSection].push_back(Rec);
1483}
1484
1486 const MCSectionELF &Sec) const {
1487 return (hasRelocationAddend() &&
1489 (TO && TO->Crel);
1490}
1491
1493 const MCAssembler &Asm, const MCSymbol &SA, const MCFragment &FB,
1494 bool InSet, bool IsPCRel) const {
1495 const auto &SymA = cast<MCSymbolELF>(SA);
1496 if (IsPCRel) {
1497 assert(!InSet);
1498 if (SymA.getBinding() != ELF::STB_LOCAL ||
1499 SymA.getType() == ELF::STT_GNU_IFUNC)
1500 return false;
1501 }
1502 return &SymA.getSection() == FB.getParent();
1503}
1504
1506 uint64_t Size =
1507 ELFWriter(*this, OS, IsLittleEndian,
1508 DwoOS ? ELFWriter::NonDwoOnly : ELFWriter::AllSections)
1509 .writeObject(Asm);
1510 if (DwoOS)
1511 Size += ELFWriter(*this, *DwoOS, IsLittleEndian, ELFWriter::DwoOnly)
1512 .writeObject(Asm);
1513 return Size;
1514}
#define offsetof(TYPE, MEMBER)
BlockVerifier::State From
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
Given that RA is a live value
This file defines the DenseMap class.
std::string Name
uint64_t Size
static uint8_t mergeTypeForSet(uint8_t origType, uint8_t newType)
static void encodeCrel(ArrayRef< ELFRelocationEntry > Relocs, raw_ostream &OS)
static bool isIFunc(const MCSymbolELF *Symbol)
std::optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1315
Symbol * Sym
Definition: ELF_riscv.cpp:479
lazy value info
#define F(x, y, z)
Definition: MD5.cpp:55
PowerPC TLS Dynamic Call Fixup
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static const char * name
Definition: SMEABIPass.cpp:46
This file contains some templates that are useful if you are working with the STL at all.
raw_pwrite_stream & OS
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:166
This file contains some functions that are useful when dealing with strings.
static SymbolRef::Type getType(const Symbol *Sym)
Definition: TapiFile.cpp:39
static bool isInSymtab(const MCSymbolWasm &Sym)
static bool isDwoSection(const MCSection &Sec)
static bool is64Bit(const char *name)
static const X86InstrFMA3Group Groups[]
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:163
std::unique_ptr< MCELFObjectTargetWriter > TargetObjectWriter
ELFObjectWriter(std::unique_ptr< MCELFObjectTargetWriter > MOTW, raw_pwrite_stream &OS, bool IsLittleEndian)
unsigned getELFHeaderEFlags() const
bool shouldRelocateWithSymbol(const MCAssembler &Asm, const MCValue &Val, const MCSymbolELF *Sym, uint64_t C, unsigned Type) const
uint64_t writeObject(MCAssembler &Asm) override
Write the object file and returns the number of bytes written.
void executePostLayoutBinding(MCAssembler &Asm) override
Perform any late binding of symbols (for example, to assign symbol indices for use when generating re...
void reset() override
lifetime management
std::optional< uint8_t > OverrideABIVersion
void recordRelocation(MCAssembler &Asm, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue) override
Record a relocation entry.
DenseMap< const MCSectionELF *, std::vector< ELFRelocationEntry > > Relocations
SmallVector< Symver, 0 > Symvers
raw_pwrite_stream & OS
bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB, bool InSet, bool IsPCRel) const override
bool hasRelocationAddend() const
bool checkRelocation(MCContext &Ctx, SMLoc Loc, const MCSectionELF *From, const MCSectionELF *To)
raw_pwrite_stream * DwoOS
bool usesRela(const MCTargetOptions *TO, const MCSectionELF &Sec) const
DenseMap< const MCSymbolELF *, const MCSymbolELF * > Renames
Generic interface to target specific assembler backends.
Definition: MCAsmBackend.h:42
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
Context object for machine code objects.
Definition: MCContext.h:83
MCSectionELF * createELFRelSection(const Twine &Name, unsigned Type, unsigned Flags, unsigned EntrySize, const MCSymbolELF *Group, const MCSectionELF *RelInfoSection)
Definition: MCContext.cpp:539
MCSectionELF * getELFSection(const Twine &Section, unsigned Type, unsigned Flags)
Definition: MCContext.h:544
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1073
const MCTargetOptions * getTargetOptions() const
Definition: MCContext.h:420
MCSectionELF * createELFGroupSection(const MCSymbolELF *Group, bool IsComdat)
Definition: MCContext.cpp:629
Base class for the full range of assembler expressions which are needed for parsing.
Definition: MCExpr.h:34
bool evaluateKnownAbsolute(int64_t &Res, const MCAssembler &Asm) const
Aggressive variant of evaluateAsRelocatable when relocations are unavailable (e.g.
Definition: MCExpr.cpp:596
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
MCSection * getParent() const
Definition: MCFragment.h:99
MutableArrayRef< std::pair< std::string, size_t > > getFileNames()
std::vector< const MCSymbol * > & getAddrsigSyms()
virtual void reset()
lifetime management
std::vector< const MCSymbol * > AddrsigSyms
This represents a section on linux, lots of unix variants and some bare metal systems.
Definition: MCSectionELF.h:27
const MCSection * getLinkedToSection() const
Definition: MCSectionELF.h:96
unsigned getFlags() const
Definition: MCSectionELF.h:81
void setOffsets(uint64_t Start, uint64_t End)
Definition: MCSectionELF.h:101
const MCSymbolELF * getGroup() const
Definition: MCSectionELF.h:84
unsigned getType() const
Definition: MCSectionELF.h:80
bool isComdat() const
Definition: MCSectionELF.h:85
Instances of this class represent a uniqued identifier for a section in the current translation unit.
Definition: MCSection.h:36
void setAlignment(Align Value)
Definition: MCSection.h:147
unsigned getOrdinal() const
Definition: MCSection.h:155
Align getAlign() const
Definition: MCSection.h:146
void setOrdinal(unsigned Value)
Definition: MCSection.h:156
StringRef getName() const
Definition: MCSection.h:130
MCSymbol * getBeginSymbol()
Definition: MCSection.h:135
void setIsWeakrefUsedInReloc() const
Represent a reference to a symbol from inside an expression.
Definition: MCExpr.h:192
const MCSymbol & getSymbol() const
Definition: MCExpr.h:411
static const MCSymbolRefExpr * create(const MCSymbol *Symbol, MCContext &Ctx)
Definition: MCExpr.h:398
VariantKind getKind() const
Definition: MCExpr.h:413
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
void setUsedInReloc() const
Definition: MCSymbol.h:215
DebugCompressionType CompressDebugSections
This represents an "assembler immediate".
Definition: MCValue.h:36
const MCSymbolRefExpr * getSymA() const
Definition: MCValue.h:44
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:310
Represents a location in source code.
Definition: SMLoc.h:23
size_t size() const
Definition: SmallVector.h:78
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:573
void resize(size_type N)
Definition: SmallVector.h:638
void push_back(const T &Elt)
Definition: SmallVector.h:413
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:286
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1196
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:51
constexpr StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:571
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:265
size_t find(char C, size_t From=0) const
Search for the first character C in the string.
Definition: StringRef.h:297
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition: StringRef.h:277
static constexpr size_t npos
Definition: StringRef.h:53
Utility for building string tables with deduplicated suffixes.
Target - Wrapper for Target specific information.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:74
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
An abstract base class for streams implementations that also support a pwrite operation.
Definition: raw_ostream.h:434
A raw_ostream that writes to an SmallVector or SmallString.
Definition: raw_ostream.h:691
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Entry
Definition: COFF.h:844
@ Tail
Attemps to make calls as fast as possible while guaranteeing that tail call optimization can always b...
Definition: CallingConv.h:76
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
@ ELFOSABI_GNU
Definition: ELF.h:347
@ ELFOSABI_NONE
Definition: ELF.h:344
@ SHN_XINDEX
Definition: ELF.h:1101
@ SHN_ABS
Definition: ELF.h:1099
@ SHN_COMMON
Definition: ELF.h:1100
@ SHN_UNDEF
Definition: ELF.h:1093
@ SHN_LORESERVE
Definition: ELF.h:1094
@ ELFCOMPRESS_ZSTD
Definition: ELF.h:2003
@ ELFCOMPRESS_ZLIB
Definition: ELF.h:2002
@ ELFCLASS64
Definition: ELF.h:332
@ ELFCLASS32
Definition: ELF.h:331
@ SYMENTRY_SIZE32
Definition: ELF.h:1355
@ SYMENTRY_SIZE64
Definition: ELF.h:1356
@ EI_PAD
Definition: ELF.h:58
@ EI_NIDENT
Definition: ELF.h:59
@ EV_CURRENT
Definition: ELF.h:128
@ EM_386
Definition: ELF.h:139
@ EM_MIPS
Definition: ELF.h:144
static const char ElfMagic[]
Definition: ELF.h:45
@ SHT_STRTAB
Definition: ELF.h:1110
@ SHT_GROUP
Definition: ELF.h:1122
@ SHT_REL
Definition: ELF.h:1116
@ SHT_LLVM_CALL_GRAPH_PROFILE
Definition: ELF.h:1147
@ SHT_NOBITS
Definition: ELF.h:1115
@ SHT_SYMTAB
Definition: ELF.h:1109
@ SHT_CREL
Definition: ELF.h:1129
@ SHT_DYNAMIC
Definition: ELF.h:1113
@ SHT_SYMTAB_SHNDX
Definition: ELF.h:1123
@ SHT_LLVM_ADDRSIG
Definition: ELF.h:1137
@ SHT_RELA
Definition: ELF.h:1111
@ SHT_DYNSYM
Definition: ELF.h:1118
@ SHF_MERGE
Definition: ELF.h:1214
@ SHF_INFO_LINK
Definition: ELF.h:1220
@ SHF_EXCLUDE
Definition: ELF.h:1242
@ SHF_ALLOC
Definition: ELF.h:1208
@ SHF_LINK_ORDER
Definition: ELF.h:1223
@ SHF_GROUP
Definition: ELF.h:1230
@ SHF_COMPRESSED
Definition: ELF.h:1236
@ SHF_WRITE
Definition: ELF.h:1205
@ SHF_TLS
Definition: ELF.h:1233
@ SHF_EXECINSTR
Definition: ELF.h:1211
@ STB_GLOBAL
Definition: ELF.h:1362
@ STB_LOCAL
Definition: ELF.h:1361
@ STB_GNU_UNIQUE
Definition: ELF.h:1364
@ STB_WEAK
Definition: ELF.h:1363
@ ET_REL
Definition: ELF.h:117
@ STT_FUNC
Definition: ELF.h:1375
@ STT_NOTYPE
Definition: ELF.h:1373
@ STT_SECTION
Definition: ELF.h:1376
@ STT_FILE
Definition: ELF.h:1377
@ STT_GNU_IFUNC
Definition: ELF.h:1380
@ STT_OBJECT
Definition: ELF.h:1374
@ STT_TLS
Definition: ELF.h:1379
@ ELFDATA2MSB
Definition: ELF.h:339
@ ELFDATA2LSB
Definition: ELF.h:338
@ GRP_COMDAT
Definition: ELF.h:1308
@ STV_DEFAULT
Definition: ELF.h:1391
Flag
These should be considered private to the implementation of the MCInstrDesc class.
Definition: MCInstrDesc.h:148
Offsets
Offsets in bytes from the start of the input buffer.
Definition: SIInstrInfo.h:1613
void compress(Params P, ArrayRef< uint8_t > Input, SmallVectorImpl< uint8_t > &Output)
Definition: Compression.cpp:46
StringRef toStringRef(const std::optional< DWARFFormValue > &V, StringRef Default={})
Take an optional DWARFFormValue and try to extract a string value from it.
support::ulittle32_t Word
Definition: IRSymtab.h:52
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:480
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition: STLExtras.h:2448
Error write(MCStreamer &Out, ArrayRef< std::string > Inputs, OnCuIndexOverflow OverflowOptValue)
Definition: DWP.cpp:625
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
Definition: Error.cpp:167
@ Ref
The access may reference the value stored in memory.
DebugCompressionType
Definition: Compression.h:27
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1873
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
Definition: LEB128.h:80
endianness
Definition: bit.h:70
Implement std::hash so that hash_code can be used in STL containers.
Definition: BitVector.h:858
This struct is a compact representation of a valid (non-zero power of two) alignment.
Definition: Alignment.h:39
uint64_t value() const
This is a hole in the type system and should not be abused.
Definition: Alignment.h:85
Elf32_Word r_info
Definition: ELF.h:1427
void setSymbolAndType(Elf32_Word s, unsigned char t)
Definition: ELF.h:1436
void setSymbolAndType(Elf64_Word s, Elf64_Word t)
Definition: ELF.h:1472
Elf64_Xword r_info
Definition: ELF.h:1463
@ FKF_IsPCRel
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...
unsigned Flags
Flags describing additional information on this fixup kind.
This struct is a compact representation of a valid (power of two) or undefined (0) alignment.
Definition: Alignment.h:117
Adapter to write values to a stream in a particular byte order.
Definition: EndianStream.h:67