55 #define DEBUG_TYPE "WinCOFFObjectWriter" 83 COFFSymbol *
Other =
nullptr;
92 int64_t getIndex()
const {
return Index; }
93 void setIndex(
int Value) {
96 MC->
setIndex(static_cast<uint32_t>(Value));
101 struct COFFRelocation {
103 COFFSymbol *Symb =
nullptr;
105 COFFRelocation() =
default;
110 using relocations = std::vector<COFFRelocation>;
119 COFFSymbol *
Symbol =
nullptr;
120 relocations Relocations;
129 using symbols = std::vector<std::unique_ptr<COFFSymbol>>;
130 using sections = std::vector<std::unique_ptr<COFFSection>>;
135 std::unique_ptr<MCWinCOFFObjectTargetWriter> TargetObjectWriter;
144 section_map SectionMap;
149 bool EmitAddrsigSection =
false;
151 std::vector<const MCSymbol *> AddrsigSyms;
153 WinCOFFObjectWriter(std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW,
156 void reset()
override {
157 memset(&Header, 0,
sizeof(Header));
158 Header.
Machine = TargetObjectWriter->getMachine();
169 COFFSection *createSection(
StringRef Name);
173 COFFSymbol *getLinkedSymbol(
const MCSymbol &Symbol);
177 void SetSymbolName(COFFSymbol &S);
178 void SetSectionName(COFFSection &S);
180 bool IsPhysicalSection(COFFSection *S);
185 void WriteSymbol(
const COFFSymbol &S);
187 void writeSectionHeaders();
192 const COFFSection &Sec,
const MCSection &MCSec);
199 bool isSymbolRefDifferenceFullyResolvedImpl(
const MCAssembler &Asm,
202 bool IsPCRel)
const override;
209 void assignSectionNumbers();
212 void emitAddrsigSection()
override { EmitAddrsigSection =
true; }
213 void addAddrsigSymbol(
const MCSymbol *Sym)
override {
214 AddrsigSyms.push_back(Sym);
236 WinCOFFObjectWriter::WinCOFFObjectWriter(
239 Header.Machine = TargetObjectWriter->getMachine();
242 COFFSymbol *WinCOFFObjectWriter::createSymbol(
StringRef Name) {
243 Symbols.push_back(make_unique<COFFSymbol>(Name));
244 return Symbols.back().get();
247 COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(
const MCSymbol *
Symbol) {
250 Ret = createSymbol(Symbol->
getName());
254 COFFSection *WinCOFFObjectWriter::createSection(
StringRef Name) {
255 Sections.emplace_back(make_unique<COFFSection>(Name));
256 return Sections.back().get();
295 void WinCOFFObjectWriter::defineSection(
const MCSectionCOFF &MCSec) {
305 COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(S);
306 if (COMDATSymbol->Section)
308 COMDATSymbol->Section =
Section;
313 Symbol->Aux.resize(1);
315 Symbol->Aux[0].AuxType = ATSectionDefinition;
316 Symbol->Aux[0].Aux.SectionDefinition.Selection = MCSec.
getSelection();
323 Section->MCSection = &MCSec;
339 COFFSymbol *WinCOFFObjectWriter::getLinkedSymbol(
const MCSymbol &Symbol) {
351 return GetOrCreateCOFFSymbol(&Aliasee);
356 void WinCOFFObjectWriter::DefineSymbol(
const MCSymbol &MCSym,
359 COFFSymbol *Sym = GetOrCreateCOFFSymbol(&MCSym);
361 COFFSection *Sec =
nullptr;
364 if (Sym->Section && Sym->Section != Sec)
368 COFFSymbol *Local =
nullptr;
369 if (cast<MCSymbolCOFF>(MCSym).isWeakExternal()) {
372 COFFSymbol *WeakDefault = getLinkedSymbol(MCSym);
374 std::string WeakName = (
".weak." + MCSym.
getName() +
".default").str();
375 WeakDefault = createSymbol(WeakName);
379 WeakDefault->Section = Sec;
383 Sym->Other = WeakDefault;
387 memset(&Sym->Aux[0], 0,
sizeof(Sym->Aux[0]));
388 Sym->Aux[0].AuxType = ATWeakExternal;
389 Sym->Aux[0].Aux.WeakExternal.TagIndex = 0;
390 Sym->Aux[0].Aux.WeakExternal.Characteristics =
403 const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(MCSym);
404 Local->Data.Type = SymbolCOFF.
getType();
405 Local->Data.StorageClass = SymbolCOFF.
getClass();
429 "Illegal section name encoding for value");
431 static const char Alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" 432 "abcdefghijklmnopqrstuvwxyz" 438 char *Ptr = Buffer + 7;
439 for (
unsigned i = 0; i < 6; ++i) {
440 unsigned Rem = Value % 64;
442 *(Ptr--) = Alphabet[Rem];
446 void WinCOFFObjectWriter::SetSectionName(COFFSection &S) {
448 std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
452 uint64_t StringTableEntry = Strings.getOffset(S.Name);
468 void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) {
470 S.set_name_offset(Strings.getOffset(S.Name));
472 std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
475 bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
483 void WinCOFFObjectWriter::WriteFileHeader(
const COFF::header &Header) {
486 W.write<uint16_t>(0xFFFF);
509 void WinCOFFObjectWriter::WriteSymbol(
const COFFSymbol &S) {
515 W.write<uint16_t>(
static_cast<int16_t
>(S.Data.SectionNumber));
516 W.write<uint16_t>(S.Data.Type);
517 W.OS <<
char(S.Data.StorageClass);
518 W.OS <<
char(S.Data.NumberOfAuxSymbols);
519 WriteAuxiliarySymbols(S.Aux);
522 void WinCOFFObjectWriter::WriteAuxiliarySymbols(
524 for (
const AuxSymbol &i : S) {
527 W.write<
uint32_t>(i.Aux.WeakExternal.TagIndex);
528 W.write<
uint32_t>(i.Aux.WeakExternal.Characteristics);
529 W.OS.write_zeros(
sizeof(i.Aux.WeakExternal.unused));
534 W.OS.write(reinterpret_cast<const char *>(&i.Aux),
537 case ATSectionDefinition:
538 W.write<
uint32_t>(i.Aux.SectionDefinition.Length);
539 W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfRelocations);
540 W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfLinenumbers);
541 W.write<
uint32_t>(i.Aux.SectionDefinition.CheckSum);
542 W.write<uint16_t>(
static_cast<int16_t
>(i.Aux.SectionDefinition.Number));
543 W.OS <<
char(i.Aux.SectionDefinition.Selection);
544 W.OS.write_zeros(
sizeof(i.Aux.SectionDefinition.unused));
545 W.write<uint16_t>(
static_cast<int16_t
>(i.Aux.SectionDefinition.Number >> 16));
554 void WinCOFFObjectWriter::writeSectionHeaders() {
558 std::vector<COFFSection *> Arr;
561 llvm::sort(Arr, [](
const COFFSection *A,
const COFFSection *
B) {
562 return A->Number < B->Number;
570 if (
Section->Relocations.size() >= 0xffff)
588 W.write<uint16_t>(R.
Type);
613 void WinCOFFObjectWriter::writeSection(
MCAssembler &Asm,
615 const COFFSection &Sec,
617 if (Sec.Number == -1)
621 if (Sec.Header.PointerToRawData != 0) {
622 assert(
W.OS.tell() == Sec.Header.PointerToRawData &&
623 "Section::PointerToRawData is insane!");
625 uint32_t CRC = writeSectionContents(Asm, Layout, MCSec);
628 COFFSection *Sec = SectionMap[&MCSec];
630 assert(AuxSyms.
size() == 1 && AuxSyms[0].AuxType == ATSectionDefinition);
631 AuxSymbol &SecDef = AuxSyms[0];
632 SecDef.Aux.SectionDefinition.CheckSum = CRC;
636 if (Sec.Relocations.empty()) {
637 assert(Sec.Header.PointerToRelocations == 0 &&
638 "Section::PointerToRelocations is insane!");
642 assert(
W.OS.tell() == Sec.Header.PointerToRelocations &&
643 "Section::PointerToRelocations is insane!");
645 if (Sec.Relocations.size() >= 0xffff) {
655 for (
const auto &Relocation : Sec.Relocations)
656 WriteRelocation(Relocation.Data);
662 void WinCOFFObjectWriter::executePostLayoutBinding(
MCAssembler &Asm,
664 if (EmitAddrsigSection) {
673 for (
const auto &
Section : Asm)
674 defineSection(static_cast<const MCSectionCOFF &>(
Section));
676 for (
const MCSymbol &Symbol : Asm.symbols())
678 DefineSymbol(Symbol, Asm, Layout);
681 bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
683 bool InSet,
bool IsPCRel)
const {
690 uint16_t
Type = cast<MCSymbolCOFF>(SymA).
getType();
697 void WinCOFFObjectWriter::recordRelocation(
MCAssembler &Asm,
701 uint64_t &FixedValue) {
702 assert(Target.
getSymA() &&
"Relocation must reference a symbol!");
705 if (!A.isRegistered()) {
707 Twine(
"symbol '") + A.getName() +
708 "' can not be undefined");
711 if (A.isTemporary() && A.isUndefined()) {
713 Twine(
"assembler label '") + A.getName() +
714 "' can not be undefined");
721 assert(SectionMap.find(MCSec) != SectionMap.end() &&
722 "Section must already have been defined in executePostLayoutBinding!");
724 COFFSection *Sec = SectionMap[MCSec];
733 "' can not be undefined in a subtraction expression");
741 int64_t OffsetOfRelocation =
744 FixedValue = (OffsetOfRelocation - OffsetOfB) + Target.
getConstant();
749 COFFRelocation Reloc;
751 Reloc.Data.SymbolTableIndex = 0;
755 if (A.isTemporary()) {
756 MCSection *TargetSection = &A.getSection();
758 SectionMap.find(TargetSection) != SectionMap.end() &&
759 "Section must already have been defined in executePostLayoutBinding!");
760 Reloc.Symb = SectionMap[TargetSection]->Symbol;
765 "Symbol must already have been defined in executePostLayoutBinding!");
769 ++Reloc.Symb->Relocations;
771 Reloc.Data.VirtualAddress += Fixup.
getOffset();
772 Reloc.Data.Type = TargetObjectWriter->getRelocType(
784 switch (Reloc.Data.Type) {
816 FixedValue = FixedValue + 4;
825 if (TargetObjectWriter->recordRelocation(Fixup))
826 Sec->Relocations.push_back(Reloc);
830 std::time_t Now = time(
nullptr);
837 void WinCOFFObjectWriter::createFileSymbols(
MCAssembler &Asm) {
841 unsigned Count = (Name.
size() + SymbolSize - 1) / SymbolSize;
843 COFFSymbol *
File = createSymbol(
".file");
846 File->Aux.resize(Count);
849 unsigned Length = Name.
size();
850 for (
auto &Aux : File->Aux) {
851 Aux.AuxType = ATFile;
853 if (Length > SymbolSize) {
855 Length = Length - SymbolSize;
858 memset((
char *)&Aux.Aux + Length, 0, SymbolSize - Length);
862 Offset += SymbolSize;
868 return Section.Symbol->Aux[0].Aux.SectionDefinition.Selection ==
872 void WinCOFFObjectWriter::assignSectionNumbers() {
874 auto Assign = [&](COFFSection &
Section) {
876 Section.Symbol->Data.SectionNumber =
I;
877 Section.Symbol->Aux[0].Aux.SectionDefinition.Number =
I;
884 for (
const std::unique_ptr<COFFSection> &
Section : Sections)
887 for (
const std::unique_ptr<COFFSection> &
Section : Sections)
893 void WinCOFFObjectWriter::assignFileOffsets(
MCAssembler &Asm,
895 unsigned Offset =
W.OS.tell();
900 for (
const auto &
Section : Asm) {
901 COFFSection *Sec = SectionMap[&
Section];
903 if (Sec->Number == -1)
908 if (IsPhysicalSection(Sec)) {
909 Sec->Header.PointerToRawData =
Offset;
910 Offset += Sec->Header.SizeOfRawData;
913 if (!Sec->Relocations.empty()) {
914 bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff;
916 if (RelocationsOverflow) {
919 Sec->Header.NumberOfRelocations = 0xffff;
921 Sec->Header.NumberOfRelocations = Sec->Relocations.size();
923 Sec->Header.PointerToRelocations =
Offset;
925 if (RelocationsOverflow) {
932 for (
auto &Relocation : Sec->Relocations) {
933 assert(Relocation.Symb->getIndex() != -1);
934 Relocation.Data.SymbolTableIndex = Relocation.Symb->getIndex();
938 assert(Sec->Symbol->Aux.size() == 1 &&
939 "Section's symbol must have one aux!");
940 AuxSymbol &Aux = Sec->Symbol->Aux[0];
941 assert(Aux.AuxType == ATSectionDefinition &&
942 "Section's symbol's aux symbol must be a Section Definition!");
943 Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData;
944 Aux.Aux.SectionDefinition.NumberOfRelocations =
945 Sec->Header.NumberOfRelocations;
946 Aux.Aux.SectionDefinition.NumberOfLinenumbers =
947 Sec->Header.NumberOfLineNumbers;
953 uint64_t WinCOFFObjectWriter::writeObject(
MCAssembler &Asm,
955 uint64_t StartOffset =
W.OS.tell();
957 if (Sections.size() > INT32_MAX)
959 "PE COFF object files can't have more than 2147483647 sections");
965 assignSectionNumbers();
966 createFileSymbols(Asm);
968 for (
auto &Symbol : Symbols) {
971 Symbol->Data.SectionNumber = Symbol->Section->Number;
974 Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size();
979 for (
const auto &S : Sections)
981 Strings.add(S->Name);
982 for (
const auto &S : Symbols)
984 Strings.add(S->Name);
988 for (
const auto &S : Sections)
990 for (
auto &S : Symbols)
994 for (
auto &Symbol : Symbols) {
997 assert(Symbol->Aux.size() == 1 &&
"Symbol must contain one aux symbol!");
998 assert(Symbol->Aux[0].AuxType == ATWeakExternal &&
999 "Symbol's aux symbol must be a Weak External!");
1000 Symbol->Aux[0].Aux.WeakExternal.TagIndex = Symbol->Other->
getIndex();
1005 for (
auto &
Section : Sections) {
1006 if (
Section->Symbol->Aux[0].Aux.SectionDefinition.Selection !=
1019 Twine(
" associative with sectionless symbol ") +
1024 const auto *AssocMCSec = cast<MCSectionCOFF>(&AssocMCSym->
getSection());
1025 assert(SectionMap.count(AssocMCSec));
1026 COFFSection *AssocSec = SectionMap[AssocMCSec];
1029 if (AssocSec->Number == -1)
1032 Section->Symbol->Aux[0].Aux.SectionDefinition.Number = AssocSec->Number;
1036 if (EmitAddrsigSection) {
1038 Frag->setLayoutOrder(0);
1040 for (
const MCSymbol *S : AddrsigSyms) {
1041 if (!S->isTemporary()) {
1046 MCSection *TargetSection = &S->getSection();
1047 assert(SectionMap.find(TargetSection) != SectionMap.end() &&
1048 "Section must already have been defined in " 1049 "executePostLayoutBinding!");
1054 assignFileOffsets(Asm, Layout);
1066 WriteFileHeader(Header);
1067 writeSectionHeaders();
1070 sections::iterator
I = Sections.begin();
1071 sections::iterator
IE = Sections.end();
1074 for (; I != IE && J != JE; ++
I, ++J)
1075 writeSection(Asm, Layout, **I, *J);
1078 "Header::PointerToSymbolTable is insane!");
1081 for (
auto &Symbol : Symbols)
1083 WriteSymbol(*Symbol);
1086 Strings.write(
W.OS);
1088 return W.OS.tell() - StartOffset;
1095 void MCWinCOFFObjectTargetWriter::anchor() {}
1102 return llvm::make_unique<WinCOFFObjectWriter>(std::move(MOTW), OS);
constexpr bool isUInt< 32 >(uint64_t x)
Instances of this class represent a uniqued identifier for a section in the current translation unit...
static uint64_t getSymbolValue(const MCSymbol &Symbol, const MCAsmLayout &Layout)
uint32_t getIndex() const
Get the (implementation defined) index.
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This class represents lattice values for constants.
bool isVariable() const
isVariable - Check if this is a variable symbol.
This represents an "assembler immediate".
uint64_t getSectionAddressSize(const MCSection *Sec) const
Get the address space size of the given section, as it effects layout.
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
static void encodeBase64StringEntry(char *Buffer, uint64_t Value)
static std::time_t getTime()
A raw_ostream that writes to an SmallVector or SmallString.
void write32le(void *P, uint32_t V)
bool isCommon() const
Is this a 'common' symbol.
Defines the object file and target independent interfaces used by the assembler backend to write nati...
static const char BigObjMagic[]
MCSectionCOFF * getCOFFSection(StringRef Section, unsigned Characteristics, SectionKind Kind, StringRef COMDATSymName, int Selection, unsigned UniqueID=GenericSectionID, const char *BeginSymName=nullptr)
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
unsigned getAlignment() const
This represents a section on Windows.
MCContext & getContext() const
int64_t getConstant() const
const MCSymbolRefExpr * getSymB() const
static uint32_t getAlignment(const MCSectionCOFF &Sec)
amdgpu Simplify well known AMD library false Value Value const Twine & Name
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Encapsulates the layout of an assembly file at a particular point in time.
bool isInSection() const
isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute)...
bool registerSection(MCSection &Section)
Represent a reference to a symbol from inside an expression.
const int32_t MaxNumberOfSections16
ArrayRef< std::string > getFileNames()
Utility for building string tables with deduplicated suffixes.
A two-byte section relative fixup.
unsigned getCharacteristics() const
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
COFF::MachineTypes Machine
Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
MCWinCOFFObjectTargetWriter(unsigned Machine_)
iterator find(const_arg_type_t< KeyT > Val)
uint32_t SymbolTableIndex
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
The instances of the Type class are immutable: once they are created, they are never changed...
virtual void reset()
lifetime management
bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const
Get the offset of the given symbol, as computed in the current layout.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
const MCSymbolRefExpr * getSymA() const
uint64_t getCommonSize() const
Return the size of a 'common' symbol.
void reportError(SMLoc L, const Twine &Msg)
DenseMap< SymbolStringPtr, JITEvaluatedSymbol > SymbolMap
A map from symbol names (as SymbolStringPtrs) to JITSymbols (address/flags pairs).
uint32_t getOffset() const
void writeSectionData(raw_ostream &OS, const MCSection *Section, const MCAsmLayout &Layout) const
Emit the section contents to OS.
void toVector(SmallVectorImpl< char > &Out) const
Append the concatenated string into the given SmallString or SmallVector.
StringRef getSectionName() const
static wasm::ValType getType(const TargetRegisterClass *RC)
uint16_t NumberOfLineNumbers
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::unique_ptr< MCObjectWriter > createWinCOFFObjectWriter(std::unique_ptr< MCWinCOFFObjectTargetWriter > MOTW, raw_pwrite_stream &OS)
Construct a new Win COFF writer instance.
uint64_t getFragmentOffset(const MCFragment *F) const
Get the offset of the given fragment inside its containing section.
void sort(IteratorTy Start, IteratorTy End)
PowerPC TLS Dynamic Call Fixup
COFFYAML::AuxSymbolType AuxType
auto size(R &&Range, typename std::enable_if< std::is_same< typename std::iterator_traits< decltype(Range.begin())>::iterator_category, std::random_access_iterator_tag >::value, void >::type *=nullptr) -> decltype(std::distance(Range.begin(), Range.end()))
Get the size of a range.
uint32_t PointerToRelocations
MCAsmBackend & getBackend() const
MCSymbol * getCOMDATSymbol() const
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
const MCSymbol & getSymbol() const
bool isUndefined(bool SetUsed=true) const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).
MCFragment * getFragment(bool SetUsed=true) const
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
An iterator type that allows iterating over the pointees via some other iterator. ...
static SectionKind getMetadata()
uint32_t PointerToRawData
Target - Wrapper for Target specific information.
MCSection * getParent() const
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
virtual bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, const MCSymbol &A, const MCSymbol &B, bool InSet) const
Adapter to write values to a stream in a particular byte order.
pointer data()
Return a pointer to the vector's buffer, even if empty().
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
uint16_t getClass() const
StringRef getName() const
getName - Get the symbol name.
An abstract base class for streams implementations that also support a pwrite operation.
Fragment for data and encoded instructions.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
uint16_t NumberOfRelocations
bool isIncrementalLinkerCompatible() const
const MCExpr * getVariableValue(bool SetUsed=true) const
getVariableValue - Get the value for variable symbols.
LLVM Value Representation.
void update(ArrayRef< char > Data)
uint32_t PointerToLineNumbers
StringRef - Represent a constant reference to a string, i.e.
Represents a location in source code.
static bool isAssociative(const COFFSection &Section)
void setIndex(uint32_t Value) const
Set the (implementation defined) index.
Twine concat(const Twine &Suffix) const
const MCSymbol * getBaseSymbol(const MCSymbol &Symbol) const
If this symbol is equivalent to A + Constant, return A.
A function that returns a base type.