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