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