20 #include "llvm/Config/config.h"
42 #define DEBUG_TYPE "WinCOFFObjectWriter"
81 int64_t getIndex()
const {
return Index; }
82 void setIndex(
int Value) {
85 MC->setIndex(static_cast<uint32_t>(Value));
90 struct COFFRelocation {
94 COFFRelocation() : Symb(nullptr) {}
98 typedef std::vector<COFFRelocation> relocations;
108 relocations Relocations;
115 typedef std::vector<std::unique_ptr<COFFSymbol>> symbols;
116 typedef std::vector<std::unique_ptr<COFFSection>> sections;
121 std::unique_ptr<MCWinCOFFObjectTargetWriter> TargetObjectWriter;
130 section_map SectionMap;
131 symbol_map SymbolMap;
137 void reset()
override {
138 memset(&Header, 0,
sizeof(Header));
139 Header.Machine = TargetObjectWriter->getMachine();
152 template <
typename object_t,
typename list_t>
161 void SetSymbolName(COFFSymbol &S);
162 void SetSectionName(COFFSection &S);
164 bool IsPhysicalSection(COFFSection *S);
169 void WriteSymbol(
const COFFSymbol &S);
179 bool isSymbolRefDifferenceFullyResolvedImpl(
const MCAssembler &
Asm,
182 bool IsPCRel)
const override;
189 uint64_t &FixedValue)
override;
196 support::endian::write<uint32_t, support::little, support::unaligned>(Data,
205 Relocations(0), MC(nullptr) {
206 memset(&Data, 0,
sizeof(Data));
222 memset(&Header, 0,
sizeof(Header));
231 memset(&Header, 0,
sizeof(Header));
233 Header.Machine = TargetObjectWriter->getMachine();
236 COFFSymbol *WinCOFFObjectWriter::createSymbol(
StringRef Name) {
237 return createCOFFEntity<COFFSymbol>(
Name,
Symbols);
240 COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(
const MCSymbol *
Symbol) {
241 symbol_map::iterator
i = SymbolMap.find(Symbol);
242 if (i != SymbolMap.end())
244 COFFSymbol *RetSymbol =
246 SymbolMap[
Symbol] = RetSymbol;
250 COFFSection *WinCOFFObjectWriter::createSection(
StringRef Name) {
251 return createCOFFEntity<COFFSection>(
Name, Sections);
256 template <
typename object_t,
typename list_t>
258 List.push_back(make_unique<object_t>(Name));
260 return List.back().get();
265 void WinCOFFObjectWriter::defineSection(
MCSectionCOFF const &Sec) {
270 COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(S);
271 if (COMDATSymbol->Section)
273 COMDATSymbol->Section = coff_section;
277 coff_section->Symbol = coff_symbol;
278 coff_symbol->Section = coff_section;
282 coff_symbol->Aux.resize(1);
283 memset(&coff_symbol->Aux[0], 0,
sizeof(coff_symbol->Aux[0]));
284 coff_symbol->Aux[0].AuxType = ATSectionDefinition;
285 coff_symbol->Aux[0].Aux.SectionDefinition.Selection = Sec.
getSelection();
338 coff_section->MCSection = &Sec;
339 SectionMap[&Sec] = coff_section;
354 COFFSymbol *WinCOFFObjectWriter::getLinkedSymbol(
const MCSymbol &Symbol) {
366 return GetOrCreateCOFFSymbol(&Aliasee);
371 void WinCOFFObjectWriter::DefineSymbol(
const MCSymbol &Symbol,
374 COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol);
376 COFFSection *Sec =
nullptr;
379 if (coff_symbol->Section && coff_symbol->Section != Sec)
383 COFFSymbol *
Local =
nullptr;
384 if (cast<MCSymbolCOFF>(Symbol).isWeakExternal()) {
387 COFFSymbol *WeakDefault = getLinkedSymbol(Symbol);
389 std::string WeakName = (
".weak." + Symbol.
getName() +
".default").str();
390 WeakDefault = createSymbol(WeakName);
394 WeakDefault->Section = Sec;
398 coff_symbol->Other = WeakDefault;
401 coff_symbol->Aux.resize(1);
402 memset(&coff_symbol->Aux[0], 0,
sizeof(coff_symbol->Aux[0]));
403 coff_symbol->Aux[0].AuxType = ATWeakExternal;
404 coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0;
405 coff_symbol->Aux[0].Aux.WeakExternal.Characteristics =
411 coff_symbol->Section = Sec;
419 Local->Data.Type = SymbolCOFF.
getType();
420 Local->Data.StorageClass = SymbolCOFF.
getClass();
432 coff_symbol->MC = &
Symbol;
444 "Illegal section name encoding for value");
446 static const char Alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
447 "abcdefghijklmnopqrstuvwxyz"
453 char *
Ptr = Buffer + 7;
454 for (
unsigned i = 0; i < 6; ++
i) {
455 unsigned Rem = Value % 64;
457 *(Ptr--) = Alphabet[Rem];
461 void WinCOFFObjectWriter::SetSectionName(COFFSection &S) {
463 uint64_t StringTableEntry = Strings.getOffset(S.Name);
470 std::memcpy(S.Header.Name, Buffer.
data(), Buffer.
size());
478 std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
482 void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) {
484 S.set_name_offset(Strings.getOffset(S.Name));
486 std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
489 bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
497 void WinCOFFObjectWriter::WriteFileHeader(
const COFF::header &Header) {
501 writeLE16(COFF::BigObjHeader::MinBigObjectVersion);
523 void WinCOFFObjectWriter::WriteSymbol(
const COFFSymbol &S) {
525 writeLE32(S.Data.Value);
527 writeLE32(S.Data.SectionNumber);
529 writeLE16(static_cast<int16_t>(S.Data.SectionNumber));
530 writeLE16(S.Data.Type);
531 write8(S.Data.StorageClass);
532 write8(S.Data.NumberOfAuxSymbols);
533 WriteAuxiliarySymbols(S.Aux);
536 void WinCOFFObjectWriter::WriteAuxiliarySymbols(
538 for (
const AuxSymbol &i : S) {
540 case ATFunctionDefinition:
541 writeLE32(i.Aux.FunctionDefinition.TagIndex);
542 writeLE32(i.Aux.FunctionDefinition.TotalSize);
543 writeLE32(i.Aux.FunctionDefinition.PointerToLinenumber);
544 writeLE32(i.Aux.FunctionDefinition.PointerToNextFunction);
545 WriteZeros(
sizeof(i.Aux.FunctionDefinition.unused));
549 case ATbfAndefSymbol:
550 WriteZeros(
sizeof(i.Aux.bfAndefSymbol.unused1));
551 writeLE16(i.Aux.bfAndefSymbol.Linenumber);
552 WriteZeros(
sizeof(i.Aux.bfAndefSymbol.unused2));
553 writeLE32(i.Aux.bfAndefSymbol.PointerToNextFunction);
554 WriteZeros(
sizeof(i.Aux.bfAndefSymbol.unused3));
559 writeLE32(i.Aux.WeakExternal.TagIndex);
560 writeLE32(i.Aux.WeakExternal.Characteristics);
561 WriteZeros(
sizeof(i.Aux.WeakExternal.unused));
567 StringRef(reinterpret_cast<const char *>(&i.Aux),
570 case ATSectionDefinition:
571 writeLE32(i.Aux.SectionDefinition.Length);
572 writeLE16(i.Aux.SectionDefinition.NumberOfRelocations);
573 writeLE16(i.Aux.SectionDefinition.NumberOfLinenumbers);
574 writeLE32(i.Aux.SectionDefinition.CheckSum);
575 writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number));
576 write8(i.Aux.SectionDefinition.Selection);
577 WriteZeros(
sizeof(i.Aux.SectionDefinition.unused));
578 writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16));
586 void WinCOFFObjectWriter::writeSectionHeader(
const COFF::section &S) {
609 void WinCOFFObjectWriter::executePostLayoutBinding(
MCAssembler &
Asm,
613 for (
const auto &
Section : Asm)
614 defineSection(static_cast<const MCSectionCOFF &>(
Section));
616 for (
const MCSymbol &Symbol : Asm.symbols())
618 DefineSymbol(Symbol, Asm, Layout);
621 bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
623 bool InSet,
bool IsPCRel)
const {
627 uint16_t
Type = cast<MCSymbolCOFF>(SymA).
getType();
631 return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
642 const auto &Sec = cast<MCSectionCOFF>(Sym.
getSection());
643 if (!Sec.getCOMDATSymbol())
652 void WinCOFFObjectWriter::recordRelocation(
655 assert(Target.
getSymA() &&
"Relocation must reference a symbol!");
658 if (!A.isRegistered()) {
660 Twine(
"symbol '") + A.getName() +
661 "' can not be undefined");
664 if (A.isTemporary() && A.isUndefined()) {
666 Twine(
"assembler label '") + A.getName() +
667 "' can not be undefined");
674 assert(SectionMap.find(Section) != SectionMap.end() &&
675 "Section must already have been defined in executePostLayoutBinding!");
677 COFFSection *coff_section = SectionMap[
Section];
679 bool CrossSection =
false;
687 "' can not be undefined in a subtraction expression");
691 if (!A.getFragment()) {
694 Twine(
"symbol '") + A.getName() +
695 "' can not be undefined in a subtraction expression");
699 CrossSection = &A.getSection() != &B->
getSection();
709 FixedValue = (OffsetOfA - OffsetOfB) + Target.
getConstant();
714 int64_t OffsetOfRelocation =
717 FixedValue = (OffsetOfRelocation - OffsetOfB) + Target.
getConstant();
722 COFFRelocation Reloc;
724 Reloc.Data.SymbolTableIndex = 0;
728 if (A.isTemporary() || CrossSection) {
729 MCSection *TargetSection = &A.getSection();
731 SectionMap.find(TargetSection) != SectionMap.end() &&
732 "Section must already have been defined in executePostLayoutBinding!");
733 Reloc.Symb = SectionMap[TargetSection]->Symbol;
737 SymbolMap.find(&A) != SymbolMap.end() &&
738 "Symbol must already have been defined in executePostLayoutBinding!");
739 Reloc.Symb = SymbolMap[&
A];
742 ++Reloc.Symb->Relocations;
744 Reloc.Data.VirtualAddress += Fixup.
getOffset();
745 Reloc.Data.Type = TargetObjectWriter->getRelocType(
746 Target, Fixup, CrossSection, Asm.
getBackend());
757 switch (Reloc.Data.Type) {
789 FixedValue = FixedValue + 4;
798 if (TargetObjectWriter->recordRelocation(Fixup))
799 coff_section->Relocations.push_back(Reloc);
802 void WinCOFFObjectWriter::writeObject(
MCAssembler &Asm,
804 size_t SectionsSize = Sections.size();
805 if (SectionsSize > static_cast<size_t>(INT32_MAX))
807 "PE COFF object files can't have more than 2147483647 sections");
810 int32_t NumberOfSections =
static_cast<int32_t
>(SectionsSize);
816 for (
const auto &Section : Sections) {
817 Section->Number = Number;
818 Section->Symbol->Data.SectionNumber = Number;
819 Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Number;
829 unsigned Count = (Name.
size() + SymbolSize - 1) / SymbolSize;
831 COFFSymbol *
file = createSymbol(
".file");
834 file->Aux.resize(Count);
837 unsigned Length = Name.
size();
838 for (
auto &Aux : file->Aux) {
839 Aux.AuxType = ATFile;
841 if (Length > SymbolSize) {
842 memcpy(&Aux.Aux, Name.c_str() +
Offset, SymbolSize);
843 Length = Length - SymbolSize;
845 memcpy(&Aux.Aux, Name.c_str() +
Offset, Length);
846 memset((
char *)&Aux.Aux + Length, 0, SymbolSize - Length);
850 Offset += SymbolSize;
854 for (
auto &Symbol : Symbols) {
857 Symbol->Data.SectionNumber = Symbol->Section->Number;
860 Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size();
865 for (
const auto &S : Sections)
867 Strings.add(S->
Name);
868 for (
const auto &S : Symbols)
870 Strings.add(S->
Name);
874 for (
const auto &S : Sections)
876 for (
auto &S : Symbols)
880 for (
auto &Symbol : Symbols) {
883 assert(Symbol->Aux.size() == 1 &&
"Symbol must contain one aux symbol!");
884 assert(Symbol->Aux[0].AuxType == ATWeakExternal &&
885 "Symbol's aux symbol must be a Weak External!");
886 Symbol->Aux[0].Aux.WeakExternal.TagIndex = Symbol->Other->
getIndex();
891 for (
auto &Section : Sections) {
892 if (Section->Symbol->Aux[0].Aux.SectionDefinition.Selection !=
900 COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(COMDAT);
902 COFFSection *Assoc = COMDATSymbol->Section;
905 Twine(
"Missing associated COMDAT section for section ") +
909 if (Assoc->Number == -1)
912 Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Assoc->Number;
917 unsigned offset = getInitialOffset();
925 for (
const auto &Section : Asm) {
926 COFFSection *Sec = SectionMap[&
Section];
928 if (Sec->Number == -1)
933 if (IsPhysicalSection(Sec)) {
936 Sec->Header.PointerToRawData = offset;
938 offset += Sec->Header.SizeOfRawData;
941 if (Sec->Relocations.size() > 0) {
942 bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff;
944 if (RelocationsOverflow) {
947 Sec->Header.NumberOfRelocations = 0xffff;
949 Sec->Header.NumberOfRelocations = Sec->Relocations.size();
951 Sec->Header.PointerToRelocations = offset;
953 if (RelocationsOverflow) {
960 for (
auto &Relocation : Sec->Relocations) {
961 assert(Relocation.Symb->getIndex() != -1);
962 Relocation.Data.SymbolTableIndex = Relocation.Symb->getIndex();
966 assert(Sec->Symbol->Aux.size() == 1 &&
967 "Section's symbol must have one aux!");
968 AuxSymbol &Aux = Sec->Symbol->Aux[0];
969 assert(Aux.AuxType == ATSectionDefinition &&
970 "Section's symbol's aux symbol must be a Section Definition!");
971 Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData;
972 Aux.Aux.SectionDefinition.NumberOfRelocations =
973 Sec->Header.NumberOfRelocations;
974 Aux.Aux.SectionDefinition.NumberOfLinenumbers =
975 Sec->Header.NumberOfLineNumbers;
982 if (Asm.isIncrementalLinkerCompatible()) {
983 std::time_t Now = time(
nullptr);
993 WriteFileHeader(Header);
996 sections::iterator
i, ie;
999 for (
auto &Section : Sections) {
1000 if (Section->Number != -1) {
1001 if (Section->Relocations.size() >= 0xffff)
1003 writeSectionHeader(Section->Header);
1008 for (i = Sections.begin(), ie = Sections.end(), j = Asm.begin(),
1010 (i != ie) && (j != je); ++
i, ++j) {
1012 if ((*i)->Number == -1)
1015 if ((*i)->Header.PointerToRawData != 0) {
1016 assert(getStream().tell() <= (*i)->Header.PointerToRawData &&
1017 "Section::PointerToRawData is insane!");
1019 unsigned SectionDataPadding =
1020 (*i)->Header.PointerToRawData - getStream().tell();
1021 assert(SectionDataPadding < 4 &&
1022 "Should only need at most three bytes of padding!");
1024 WriteZeros(SectionDataPadding);
1028 SectionContents.
clear();
1034 Asm.writeSectionData(&*j, Layout);
1036 setStream(OldStream);
1041 JC.update(SectionContents);
1044 getStream() << SectionContents;
1047 COFFSection *Sec = SectionMap[&*j];
1050 AuxSyms[0].AuxType == ATSectionDefinition);
1051 AuxSymbol &SecDef = AuxSyms[0];
1052 SecDef.Aux.SectionDefinition.CheckSum = JC.getCRC();
1055 if ((*i)->Relocations.size() > 0) {
1056 assert(getStream().tell() == (*i)->Header.PointerToRelocations &&
1057 "Section::PointerToRelocations is insane!");
1059 if ((*i)->Relocations.size() >= 0xffff) {
1069 for (
const auto &Relocation : (*i)->Relocations)
1070 WriteRelocation(Relocation.Data);
1072 assert((*i)->Header.PointerToRelocations == 0 &&
1073 "Section::PointerToRelocations is insane!");
1078 "Header::PointerToSymbolTable is insane!");
1080 for (
auto &Symbol : Symbols)
1082 WriteSymbol(*Symbol);
1084 Strings.write(getStream());
1087 MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(
unsigned Machine_)
1091 void MCWinCOFFObjectTargetWriter::anchor() {}
1099 return new WinCOFFObjectWriter(MOTW, OS);
void toVector(SmallVectorImpl< char > &Out) const
Append the concatenated string into the given SmallString or SmallVector.
constexpr bool isUInt< 32 >(uint64_t x)
Instances of this class represent a uniqued identifier for a section in the current translation unit...
const_iterator end(StringRef path)
Get end iterator over path.
static void write_uint32_le(void *Data, uint32_t Value)
static uint64_t getSymbolValue(const MCSymbol &Symbol, const MCAsmLayout &Layout)
const MCSymbol & getSymbol() const
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
This represents an "assembler immediate".
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
static void encodeBase64StringEntry(char *Buffer, uint64_t Value)
bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const
Get the offset of the given symbol, as computed in the current layout.
A raw_ostream that writes to an SmallVector or SmallString.
const_iterator begin(StringRef path)
Get begin iterator over path.
FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > Tys=None)
Return the function type for an intrinsic.
unsigned getAlignment() const
MCContext & getContext() const
Defines the object file and target independent interfaces used by the assembler backend to write nati...
static const char BigObjMagic[]
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
This represents a section on Windows.
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.
Represent a reference to a symbol from inside an expression.
void setIndex(uint32_t Value) const
Set the (implementation defined) index.
const int32_t MaxNumberOfSections16
ArrayRef< std::string > getFileNames()
Utility for building string tables with deduplicated suffixes.
A two-byte section relative fixup.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
COFF::MachineTypes Machine
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE size_t size() const
size - Get the string size.
uint32_t getOffset() const
uint16_t getClass() const
uint32_t SymbolTableIndex
const MCSymbol * getBaseSymbol(const MCSymbol &Symbol) const
If this symbol is equivalent to A + Constant, return A.
The instances of the Type class are immutable: once they are created, they are never changed...
uint32_t getIndex() const
Get the (implementation defined) index.
MCSymbol * getCOMDATSymbol() const
Type is formed as (base + (derived << SCT_COMPLEX_TYPE_SHIFT))
virtual void reset()
lifetime management
uint64_t getSectionAddressSize(const MCSection *Sec) const
Get the address space size of the given section, as it effects layout.
void reportError(SMLoc L, const Twine &Msg)
A function that returns a base type.
dot regions Print regions of function to dot file(with no function bodies)"
bool isInSection(bool SetUsed=true) const
isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute)...
MCFixupKind getKind() const
const MCSymbolRefExpr * getSymB() const
unsigned getCharacteristics() const
uint16_t NumberOfLineNumbers
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
PowerPC TLS Dynamic Call Fixup
Twine concat(const Twine &Suffix) const
COFFYAML::AuxSymbolType AuxType
uint32_t PointerToRelocations
const MCSymbolRefExpr * getSymA() const
StringRef getSectionName() 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. ...
MCSection * getParent() const
uint32_t PointerToRawData
static int alignTo(int Num, int PowOf2)
Target - Wrapper for Target specific information.
static bool isWeak(const MCSymbolELF &Sym)
const MCExpr * getVariableValue(bool SetUsed=true) const
getVariableValue - Get the value for variable symbols.
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
uint64_t getCommonSize() const
Return the size of a 'common' symbol.
MCSection & getSection(bool SetUsed=true) const
Get the section associated with a defined, non-absolute symbol.
StringRef getName() const
getName - Get the symbol name.
pointer data()
Return a pointer to the vector's buffer, even if empty().
MCAsmBackend & getBackend() const
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
bool isCommon() const
Is this a 'common' symbol.
COFFYAML::WeakExternalCharacteristics Characteristics
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
uint64_t getFragmentOffset(const MCFragment *F) const
Get the offset of the given fragment inside its containing section.
bool isVariable() const
isVariable - Check if this is a variable symbol.
MCFragment * getFragment(bool SetUsed=true) const
An abstract base class for streams implementations that also support a pwrite operation.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
uint16_t NumberOfRelocations
bool isIncrementalLinkerCompatible() const
int64_t getConstant() const
LLVM Value Representation.
MCObjectWriter * createWinCOFFObjectWriter(MCWinCOFFObjectTargetWriter *MOTW, raw_pwrite_stream &OS)
Construct a new Win COFF writer instance.
uint32_t PointerToLineNumbers
StringRef - Represent a constant reference to a string, i.e.
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
bool isUndefined(bool SetUsed=true) const
isUndefined - Check if this symbol undefined (i.e., implicitly defined).