40 #define DEBUG_TYPE "WinCOFFObjectWriter"
77 void set_name_offset(uint32_t Offset);
79 bool should_keep()
const;
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;
111 static size_t size();
116 typedef std::vector<std::unique_ptr<COFFSymbol>> symbols;
117 typedef std::vector<std::unique_ptr<COFFSection>> sections;
122 std::unique_ptr<MCWinCOFFObjectTargetWriter> TargetObjectWriter;
131 section_map SectionMap;
132 symbol_map SymbolMap;
138 void reset()
override {
139 memset(&Header, 0,
sizeof(Header));
140 Header.Machine = TargetObjectWriter->getMachine();
153 template <
typename object_t,
typename list_t>
160 void SetSymbolName(COFFSymbol &S);
161 void SetSectionName(COFFSection &S);
165 bool IsPhysicalSection(COFFSection *S);
170 void WriteSymbol(
const COFFSymbol &S);
180 bool isSymbolRefDifferenceFullyResolvedImpl(
const MCAssembler &
Asm,
183 bool IsPCRel)
const override;
190 uint64_t &FixedValue)
override;
197 support::endian::write<uint32_t, support::little, support::unaligned>(Data,
206 Relocations(0), MC(nullptr) {
207 memset(&Data, 0,
sizeof(Data));
213 void COFFSymbol::set_name_offset(uint32_t Offset) {
219 bool COFFSymbol::should_keep()
const {
225 if (Relocations > 0) {
226 assert(
Section->Number != -1 &&
"Sections with relocations must be real!");
231 if (MC && (cast<MCSymbolCOFF>(MC)->isSafeSEH()))
243 if (MC && MC->isTemporary())
255 memset(&Header, 0,
sizeof(Header));
266 memset(&Header, 0,
sizeof(Header));
268 Header.Machine = TargetObjectWriter->getMachine();
271 COFFSymbol *WinCOFFObjectWriter::createSymbol(
StringRef Name) {
272 return createCOFFEntity<COFFSymbol>(
Name,
Symbols);
275 COFFSymbol *WinCOFFObjectWriter::GetOrCreateCOFFSymbol(
const MCSymbol *
Symbol) {
276 symbol_map::iterator i = SymbolMap.find(Symbol);
277 if (i != SymbolMap.end())
279 COFFSymbol *RetSymbol =
281 SymbolMap[
Symbol] = RetSymbol;
285 COFFSection *WinCOFFObjectWriter::createSection(
StringRef Name) {
286 return createCOFFEntity<COFFSection>(
Name, Sections);
291 template <
typename object_t,
typename list_t>
293 List.push_back(make_unique<object_t>(Name));
295 return List.back().get();
300 void WinCOFFObjectWriter::defineSection(
MCSectionCOFF const &Sec) {
305 COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(S);
306 if (COMDATSymbol->Section)
308 COMDATSymbol->Section = coff_section;
312 coff_section->Symbol = coff_symbol;
313 coff_symbol->Section = coff_section;
317 coff_symbol->Aux.resize(1);
318 memset(&coff_symbol->Aux[0], 0,
sizeof(coff_symbol->Aux[0]));
319 coff_symbol->Aux[0].AuxType = ATSectionDefinition;
320 coff_symbol->Aux[0].Aux.SectionDefinition.Selection = Sec.
getSelection();
373 coff_section->MCSection = &Sec;
374 SectionMap[&Sec] = coff_section;
391 void WinCOFFObjectWriter::DefineSymbol(
const MCSymbol &Symbol,
394 COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol);
395 SymbolMap[&
Symbol] = coff_symbol;
397 if (cast<MCSymbolCOFF>(Symbol).isWeakExternal()) {
407 coff_symbol->Other = GetOrCreateCOFFSymbol(&SymRef->
getSymbol());
409 std::string WeakName = (
".weak." + Symbol.
getName() +
".default").str();
410 COFFSymbol *WeakDefault = createSymbol(WeakName);
413 WeakDefault->Data.Type = 0;
414 WeakDefault->Data.Value = 0;
415 coff_symbol->Other = WeakDefault;
419 coff_symbol->Aux.resize(1);
420 memset(&coff_symbol->Aux[0], 0,
sizeof(coff_symbol->Aux[0]));
421 coff_symbol->Aux[0].AuxType = ATWeakExternal;
422 coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0;
423 coff_symbol->Aux[0].Aux.WeakExternal.Characteristics =
426 coff_symbol->MC = &
Symbol;
432 coff_symbol->Data.Type = SymbolCOFF.
getType();
433 coff_symbol->Data.StorageClass = SymbolCOFF.
getClass();
440 coff_symbol->Data.StorageClass = IsExternal
451 if (coff_symbol->Section && coff_symbol->Section != Sec)
454 coff_symbol->Section = Sec;
458 coff_symbol->MC = &
Symbol;
472 "Illegal section name encoding for value");
474 static const char Alphabet[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
475 "abcdefghijklmnopqrstuvwxyz"
481 char *Ptr = Buffer + 7;
482 for (
unsigned i = 0; i < 6; ++i) {
483 unsigned Rem = Value % 64;
485 *(Ptr--) = Alphabet[Rem];
489 void WinCOFFObjectWriter::SetSectionName(COFFSection &S) {
491 uint64_t StringTableEntry = Strings.getOffset(S.Name);
494 std::sprintf(S.Header.Name,
"/%d",
unsigned(StringTableEntry));
499 std::sprintf(buffer,
"/%d",
unsigned(StringTableEntry));
500 std::memcpy(S.Header.Name, buffer, 8);
508 std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
511 void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) {
513 S.set_name_offset(Strings.getOffset(S.Name));
515 std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
518 bool WinCOFFObjectWriter::ExportSymbol(
const MCSymbol &Symbol,
537 bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
545 void WinCOFFObjectWriter::WriteFileHeader(
const COFF::header &Header) {
549 writeLE16(COFF::BigObjHeader::MinBigObjectVersion);
571 void WinCOFFObjectWriter::WriteSymbol(
const COFFSymbol &S) {
573 writeLE32(S.Data.Value);
575 writeLE32(S.Data.SectionNumber);
577 writeLE16(static_cast<int16_t>(S.Data.SectionNumber));
578 writeLE16(S.Data.Type);
579 write8(S.Data.StorageClass);
580 write8(S.Data.NumberOfAuxSymbols);
581 WriteAuxiliarySymbols(S.Aux);
584 void WinCOFFObjectWriter::WriteAuxiliarySymbols(
588 switch (i->AuxType) {
589 case ATFunctionDefinition:
590 writeLE32(i->Aux.FunctionDefinition.TagIndex);
591 writeLE32(i->Aux.FunctionDefinition.TotalSize);
592 writeLE32(i->Aux.FunctionDefinition.PointerToLinenumber);
593 writeLE32(i->Aux.FunctionDefinition.PointerToNextFunction);
594 WriteZeros(
sizeof(i->Aux.FunctionDefinition.unused));
598 case ATbfAndefSymbol:
599 WriteZeros(
sizeof(i->Aux.bfAndefSymbol.unused1));
600 writeLE16(i->Aux.bfAndefSymbol.Linenumber);
601 WriteZeros(
sizeof(i->Aux.bfAndefSymbol.unused2));
602 writeLE32(i->Aux.bfAndefSymbol.PointerToNextFunction);
603 WriteZeros(
sizeof(i->Aux.bfAndefSymbol.unused3));
608 writeLE32(i->Aux.WeakExternal.TagIndex);
609 writeLE32(i->Aux.WeakExternal.Characteristics);
610 WriteZeros(
sizeof(i->Aux.WeakExternal.unused));
616 StringRef(reinterpret_cast<const char *>(&i->Aux),
619 case ATSectionDefinition:
620 writeLE32(i->Aux.SectionDefinition.Length);
621 writeLE16(i->Aux.SectionDefinition.NumberOfRelocations);
622 writeLE16(i->Aux.SectionDefinition.NumberOfLinenumbers);
623 writeLE32(i->Aux.SectionDefinition.CheckSum);
624 writeLE16(static_cast<int16_t>(i->Aux.SectionDefinition.Number));
625 write8(i->Aux.SectionDefinition.Selection);
626 WriteZeros(
sizeof(i->Aux.SectionDefinition.unused));
627 writeLE16(static_cast<int16_t>(i->Aux.SectionDefinition.Number >> 16));
635 void WinCOFFObjectWriter::writeSectionHeader(
const COFF::section &S) {
658 void WinCOFFObjectWriter::executePostLayoutBinding(
MCAssembler &Asm,
662 for (
const auto &
Section : Asm)
663 defineSection(static_cast<const MCSectionCOFF &>(
Section));
665 for (
const MCSymbol &Symbol : Asm.symbols())
666 if (ExportSymbol(Symbol, Asm))
667 DefineSymbol(Symbol, Asm, Layout);
670 bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
672 bool InSet,
bool IsPCRel)
const {
676 uint16_t
Type = cast<MCSymbolCOFF>(SymA).
getType();
679 return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
690 const auto &Sec = cast<MCSectionCOFF>(Sym.
getSection());
700 void WinCOFFObjectWriter::recordRelocation(
703 assert(Target.
getSymA() &&
"Relocation must reference a symbol!");
710 "' can not be undefined");
715 assert(SectionMap.find(Section) != SectionMap.end() &&
716 "Section must already have been defined in executePostLayoutBinding!");
717 assert(SymbolMap.find(&A) != SymbolMap.end() &&
718 "Symbol must already have been defined in executePostLayoutBinding!");
720 COFFSection *coff_section = SectionMap[
Section];
721 COFFSymbol *coff_symbol = SymbolMap[&
A];
723 bool CrossSection =
false;
731 "' can not be undefined in a subtraction expression");
736 Twine(
"symbol '") + Symbol.getName() +
737 "' can not be undefined in a subtraction expression");
739 CrossSection = &Symbol.getSection() != &B->
getSection();
749 FixedValue = (OffsetOfA - OffsetOfB) + Target.
getConstant();
754 int64_t OffsetOfRelocation =
757 FixedValue = (OffsetOfRelocation - OffsetOfB) + Target.
getConstant();
762 COFFRelocation Reloc;
764 Reloc.Data.SymbolTableIndex = 0;
768 if (coff_symbol->MC->isTemporary() || CrossSection) {
769 Reloc.Symb = coff_symbol->Section->Symbol;
771 coff_symbol->MC->getOffset();
773 Reloc.Symb = coff_symbol;
775 ++Reloc.Symb->Relocations;
777 Reloc.Data.VirtualAddress += Fixup.
getOffset();
778 Reloc.Data.Type = TargetObjectWriter->getRelocType(
779 Target, Fixup, CrossSection, Asm.
getBackend());
790 switch (Reloc.Data.Type) {
822 FixedValue = FixedValue + 4;
827 if (TargetObjectWriter->recordRelocation(Fixup))
828 coff_section->Relocations.push_back(Reloc);
831 void WinCOFFObjectWriter::writeObject(
MCAssembler &Asm,
833 size_t SectionsSize = Sections.size();
834 if (SectionsSize > static_cast<size_t>(INT32_MAX))
836 "PE COFF object files can't have more than 2147483647 sections");
839 int32_t NumberOfSections =
static_cast<int32_t
>(SectionsSize);
845 for (
const auto &Section : Sections) {
846 Section->Number = Number;
847 Section->Symbol->Data.SectionNumber = Number;
848 Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Number;
858 unsigned Count = (Name.
size() + SymbolSize - 1) / SymbolSize;
860 COFFSymbol *
file = createSymbol(
".file");
863 file->Aux.resize(Count);
866 unsigned Length = Name.
size();
867 for (
auto &Aux : file->Aux) {
868 Aux.AuxType = ATFile;
870 if (Length > SymbolSize) {
871 memcpy(&Aux.Aux, Name.c_str() + Offset, SymbolSize);
872 Length = Length - SymbolSize;
874 memcpy(&Aux.Aux, Name.c_str() + Offset, Length);
875 memset((
char *)&Aux.Aux + Length, 0, SymbolSize - Length);
879 Offset += SymbolSize;
883 for (
auto &Symbol : Symbols) {
886 Symbol->Data.SectionNumber = Symbol->Section->Number;
887 if (Symbol->should_keep()) {
890 Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size();
893 Symbol->setIndex(-1);
898 for (
const auto &S : Sections)
900 Strings.add(S->
Name);
901 for (
const auto &S : Symbols)
903 Strings.add(S->
Name);
904 Strings.finalize(StringTableBuilder::WinCOFF);
907 for (
const auto &S : Sections)
909 for (
auto &S : Symbols)
910 if (S->should_keep())
914 for (
auto &Symbol : Symbols) {
916 assert(Symbol->getIndex() != -1);
917 assert(Symbol->Aux.size() == 1 &&
"Symbol must contain one aux symbol!");
918 assert(Symbol->Aux[0].AuxType == ATWeakExternal &&
919 "Symbol's aux symbol must be a Weak External!");
920 Symbol->Aux[0].Aux.WeakExternal.TagIndex = Symbol->Other->getIndex();
925 for (
auto &Section : Sections) {
926 if (Section->Symbol->Aux[0].Aux.SectionDefinition.Selection !=
934 COFFSymbol *COMDATSymbol = GetOrCreateCOFFSymbol(COMDAT);
935 assert(COMDATSymbol);
936 COFFSection *Assoc = COMDATSymbol->Section;
939 Twine(
"Missing associated COMDAT section for section ") +
943 if (Assoc->Number == -1)
946 Section->Symbol->Aux[0].Aux.SectionDefinition.Number = Assoc->Number;
959 for (
const auto &Section : Asm) {
960 COFFSection *Sec = SectionMap[&
Section];
962 if (Sec->Number == -1)
967 if (IsPhysicalSection(Sec)) {
970 Sec->Header.PointerToRawData = offset;
972 offset += Sec->Header.SizeOfRawData;
975 if (Sec->Relocations.size() > 0) {
976 bool RelocationsOverflow = Sec->Relocations.size() >= 0xffff;
978 if (RelocationsOverflow) {
981 Sec->Header.NumberOfRelocations = 0xffff;
983 Sec->Header.NumberOfRelocations = Sec->Relocations.size();
985 Sec->Header.PointerToRelocations = offset;
987 if (RelocationsOverflow) {
994 for (
auto &Relocation : Sec->Relocations) {
995 assert(Relocation.Symb->getIndex() != -1);
996 Relocation.Data.SymbolTableIndex = Relocation.Symb->getIndex();
1000 assert(Sec->Symbol->Aux.size() == 1 &&
1001 "Section's symbol must have one aux!");
1002 AuxSymbol &Aux = Sec->Symbol->Aux[0];
1003 assert(Aux.AuxType == ATSectionDefinition &&
1004 "Section's symbol's aux symbol must be a Section Definition!");
1005 Aux.Aux.SectionDefinition.Length = Sec->Header.SizeOfRawData;
1006 Aux.Aux.SectionDefinition.NumberOfRelocations =
1007 Sec->Header.NumberOfRelocations;
1008 Aux.Aux.SectionDefinition.NumberOfLinenumbers =
1009 Sec->Header.NumberOfLineNumbers;
1018 WriteFileHeader(Header);
1021 sections::iterator i, ie;
1024 for (
auto &Section : Sections) {
1025 if (Section->Number != -1) {
1026 if (Section->Relocations.size() >= 0xffff)
1028 writeSectionHeader(Section->Header);
1032 for (i = Sections.begin(), ie = Sections.end(), j = Asm.begin(),
1034 (i != ie) && (j != je); ++i, ++j) {
1036 if ((*i)->Number == -1)
1039 if ((*i)->Header.PointerToRawData != 0) {
1040 assert(OS.
tell() <= (*i)->Header.PointerToRawData &&
1041 "Section::PointerToRawData is insane!");
1043 unsigned SectionDataPadding = (*i)->Header.PointerToRawData - OS.
tell();
1044 assert(SectionDataPadding < 4 &&
1045 "Should only need at most three bytes of padding!");
1047 WriteZeros(SectionDataPadding);
1049 Asm.writeSectionData(&*j, Layout);
1052 if ((*i)->Relocations.size() > 0) {
1053 assert(OS.
tell() == (*i)->Header.PointerToRelocations &&
1054 "Section::PointerToRelocations is insane!");
1056 if ((*i)->Relocations.size() >= 0xffff) {
1066 for (
const auto &Relocation : (*i)->Relocations)
1067 WriteRelocation(Relocation.Data);
1069 assert((*i)->Header.PointerToRelocations == 0 &&
1070 "Section::PointerToRelocations is insane!");
1075 "Header::PointerToSymbolTable is insane!");
1077 for (
auto &Symbol : Symbols)
1078 if (Symbol->getIndex() != -1)
1079 WriteSymbol(*Symbol);
1081 OS.
write(Strings.data().data(), Strings.data().size());
1084 MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(
unsigned Machine_)
1088 void MCWinCOFFObjectTargetWriter::anchor() {}
1096 return new WinCOFFObjectWriter(MOTW, OS);
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
size_t size() const
size - Get the string size.
This represents an "assembler immediate".
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
bool isRegistered() const
LLVM_ATTRIBUTE_NORETURN void reportFatalError(SMLoc L, const Twine &Msg) const
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.
const_iterator begin(StringRef path)
Get begin iterator over path.
static const unsigned Max6DecimalOffset
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[]
LLVM_ATTRIBUTE_NORETURN void report_fatal_error(const char *reason, bool gen_crash_diag=true)
Reports a serious error, calling any installed error handler.
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
MCSectionCOFF - 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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
const MCExpr * getVariableValue() const
getVariableValue() - Get the value for variable symbols.
Number of individual test Apply this number of consecutive mutations to each input exit after the first new interesting input is found the minimized corpus is saved into the first input directory Number of jobs to run If Reload the main corpus periodically to get new units discovered by other processes Read the given input file
Represent a reference to a symbol from inside an expression.
const int32_t MaxNumberOfSections16
ArrayRef< std::string > getFileNames()
uint64_t tell() const
tell - Return the current offset with the file.
bool isInSection() const
isInSection - Check if this symbol is defined in some section (i.e., it is defined but not absolute)...
Utility for building string tables with deduplicated suffixes.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
COFF::MachineTypes Machine
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.
static const unsigned Max7DecimalOffset
The instances of the Type class are immutable: once they are created, they are never changed...
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.
MCFragment * getFragment() const
A function that returns a base type.
const MCSymbolRefExpr * getSymB() const
unsigned getCharacteristics() const
bool isAbsolute() const
isAbsolute - Check if this is an absolute symbol.
uint16_t NumberOfLineNumbers
raw_ostream & write(unsigned char C)
PowerPC TLS Dynamic Call Fixup
COFFYAML::AuxSymbolType AuxType
uint32_t PointerToRelocations
const MCSymbolRefExpr * getSymA() const
StringRef getSectionName() const
static const uint64_t MaxBase64Offset
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
MCSection & getSection() const
Get the section associated with a defined, non-absolute symbol.
An iterator type that allows iterating over the pointees via some other iterator. ...
MCSection * getParent() const
uint32_t PointerToRawData
Target - Wrapper for Target specific information.
static bool isWeak(const MCSymbolELF &Sym)
bool isTemporary() const
isTemporary - Check if this is an assembler temporary symbol.
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
uint64_t getCommonSize() const
Return the size of a 'common' symbol.
uint64_t RoundUpToAlignment(uint64_t Value, uint64_t Align)
Returns the next integer (mod 2**64) that is greater than or equal to Value and is a multiple of Alig...
StringRef getName() const
getName - Get the symbol name.
MCAsmBackend & getBackend() const
bool isCommon() const
Is this a 'common' symbol.
COFFYAML::WeakExternalCharacteristics Characteristics
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.
An abstract base class for streams implementations that also support a pwrite operation.
uint16_t NumberOfRelocations
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.