aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp')
-rw-r--r--contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp195
1 files changed, 97 insertions, 98 deletions
diff --git a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp
index 9f1db46939c7..9ffecd99df68 100644
--- a/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/contrib/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -125,6 +125,8 @@ public:
class WinCOFFObjectWriter : public MCObjectWriter {
public:
+ support::endian::Writer W;
+
using symbols = std::vector<std::unique_ptr<COFFSymbol>>;
using sections = std::vector<std::unique_ptr<COFFSection>>;
@@ -204,7 +206,7 @@ public:
void assignSectionNumbers();
void assignFileOffsets(MCAssembler &Asm, const MCAsmLayout &Layout);
- void writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
+ uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout) override;
};
} // end anonymous namespace
@@ -225,7 +227,7 @@ void COFFSymbol::set_name_offset(uint32_t Offset) {
WinCOFFObjectWriter::WinCOFFObjectWriter(
std::unique_ptr<MCWinCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
- : MCObjectWriter(OS, true), TargetObjectWriter(std::move(MOTW)) {
+ : W(OS, support::little), TargetObjectWriter(std::move(MOTW)) {
Header.Machine = TargetObjectWriter->getMachine();
}
@@ -472,40 +474,40 @@ bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
void WinCOFFObjectWriter::WriteFileHeader(const COFF::header &Header) {
if (UseBigObj) {
- writeLE16(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
- writeLE16(0xFFFF);
- writeLE16(COFF::BigObjHeader::MinBigObjectVersion);
- writeLE16(Header.Machine);
- writeLE32(Header.TimeDateStamp);
- writeBytes(StringRef(COFF::BigObjMagic, sizeof(COFF::BigObjMagic)));
- writeLE32(0);
- writeLE32(0);
- writeLE32(0);
- writeLE32(0);
- writeLE32(Header.NumberOfSections);
- writeLE32(Header.PointerToSymbolTable);
- writeLE32(Header.NumberOfSymbols);
+ W.write<uint16_t>(COFF::IMAGE_FILE_MACHINE_UNKNOWN);
+ W.write<uint16_t>(0xFFFF);
+ W.write<uint16_t>(COFF::BigObjHeader::MinBigObjectVersion);
+ W.write<uint16_t>(Header.Machine);
+ W.write<uint32_t>(Header.TimeDateStamp);
+ W.OS.write(COFF::BigObjMagic, sizeof(COFF::BigObjMagic));
+ W.write<uint32_t>(0);
+ W.write<uint32_t>(0);
+ W.write<uint32_t>(0);
+ W.write<uint32_t>(0);
+ W.write<uint32_t>(Header.NumberOfSections);
+ W.write<uint32_t>(Header.PointerToSymbolTable);
+ W.write<uint32_t>(Header.NumberOfSymbols);
} else {
- writeLE16(Header.Machine);
- writeLE16(static_cast<int16_t>(Header.NumberOfSections));
- writeLE32(Header.TimeDateStamp);
- writeLE32(Header.PointerToSymbolTable);
- writeLE32(Header.NumberOfSymbols);
- writeLE16(Header.SizeOfOptionalHeader);
- writeLE16(Header.Characteristics);
+ W.write<uint16_t>(Header.Machine);
+ W.write<uint16_t>(static_cast<int16_t>(Header.NumberOfSections));
+ W.write<uint32_t>(Header.TimeDateStamp);
+ W.write<uint32_t>(Header.PointerToSymbolTable);
+ W.write<uint32_t>(Header.NumberOfSymbols);
+ W.write<uint16_t>(Header.SizeOfOptionalHeader);
+ W.write<uint16_t>(Header.Characteristics);
}
}
void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) {
- writeBytes(StringRef(S.Data.Name, COFF::NameSize));
- writeLE32(S.Data.Value);
+ W.OS.write(S.Data.Name, COFF::NameSize);
+ W.write<uint32_t>(S.Data.Value);
if (UseBigObj)
- writeLE32(S.Data.SectionNumber);
+ W.write<uint32_t>(S.Data.SectionNumber);
else
- writeLE16(static_cast<int16_t>(S.Data.SectionNumber));
- writeLE16(S.Data.Type);
- write8(S.Data.StorageClass);
- write8(S.Data.NumberOfAuxSymbols);
+ W.write<uint16_t>(static_cast<int16_t>(S.Data.SectionNumber));
+ W.write<uint16_t>(S.Data.Type);
+ W.OS << char(S.Data.StorageClass);
+ W.OS << char(S.Data.NumberOfAuxSymbols);
WriteAuxiliarySymbols(S.Aux);
}
@@ -514,46 +516,45 @@ void WinCOFFObjectWriter::WriteAuxiliarySymbols(
for (const AuxSymbol &i : S) {
switch (i.AuxType) {
case ATFunctionDefinition:
- writeLE32(i.Aux.FunctionDefinition.TagIndex);
- writeLE32(i.Aux.FunctionDefinition.TotalSize);
- writeLE32(i.Aux.FunctionDefinition.PointerToLinenumber);
- writeLE32(i.Aux.FunctionDefinition.PointerToNextFunction);
- WriteZeros(sizeof(i.Aux.FunctionDefinition.unused));
+ W.write<uint32_t>(i.Aux.FunctionDefinition.TagIndex);
+ W.write<uint32_t>(i.Aux.FunctionDefinition.TotalSize);
+ W.write<uint32_t>(i.Aux.FunctionDefinition.PointerToLinenumber);
+ W.write<uint32_t>(i.Aux.FunctionDefinition.PointerToNextFunction);
+ W.OS.write_zeros(sizeof(i.Aux.FunctionDefinition.unused));
if (UseBigObj)
- WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
+ W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
case ATbfAndefSymbol:
- WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused1));
- writeLE16(i.Aux.bfAndefSymbol.Linenumber);
- WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused2));
- writeLE32(i.Aux.bfAndefSymbol.PointerToNextFunction);
- WriteZeros(sizeof(i.Aux.bfAndefSymbol.unused3));
+ W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused1));
+ W.write<uint16_t>(i.Aux.bfAndefSymbol.Linenumber);
+ W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused2));
+ W.write<uint32_t>(i.Aux.bfAndefSymbol.PointerToNextFunction);
+ W.OS.write_zeros(sizeof(i.Aux.bfAndefSymbol.unused3));
if (UseBigObj)
- WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
+ W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
case ATWeakExternal:
- writeLE32(i.Aux.WeakExternal.TagIndex);
- writeLE32(i.Aux.WeakExternal.Characteristics);
- WriteZeros(sizeof(i.Aux.WeakExternal.unused));
+ W.write<uint32_t>(i.Aux.WeakExternal.TagIndex);
+ W.write<uint32_t>(i.Aux.WeakExternal.Characteristics);
+ W.OS.write_zeros(sizeof(i.Aux.WeakExternal.unused));
if (UseBigObj)
- WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
+ W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
case ATFile:
- writeBytes(
- StringRef(reinterpret_cast<const char *>(&i.Aux),
- UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size));
+ W.OS.write(reinterpret_cast<const char *>(&i.Aux),
+ UseBigObj ? COFF::Symbol32Size : COFF::Symbol16Size);
break;
case ATSectionDefinition:
- writeLE32(i.Aux.SectionDefinition.Length);
- writeLE16(i.Aux.SectionDefinition.NumberOfRelocations);
- writeLE16(i.Aux.SectionDefinition.NumberOfLinenumbers);
- writeLE32(i.Aux.SectionDefinition.CheckSum);
- writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number));
- write8(i.Aux.SectionDefinition.Selection);
- WriteZeros(sizeof(i.Aux.SectionDefinition.unused));
- writeLE16(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16));
+ W.write<uint32_t>(i.Aux.SectionDefinition.Length);
+ W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfRelocations);
+ W.write<uint16_t>(i.Aux.SectionDefinition.NumberOfLinenumbers);
+ W.write<uint32_t>(i.Aux.SectionDefinition.CheckSum);
+ W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number));
+ W.OS << char(i.Aux.SectionDefinition.Selection);
+ W.OS.write_zeros(sizeof(i.Aux.SectionDefinition.unused));
+ W.write<uint16_t>(static_cast<int16_t>(i.Aux.SectionDefinition.Number >> 16));
if (UseBigObj)
- WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
+ W.OS.write_zeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
}
}
@@ -567,10 +568,10 @@ void WinCOFFObjectWriter::writeSectionHeaders() {
std::vector<COFFSection *> Arr;
for (auto &Section : Sections)
Arr.push_back(Section.get());
- std::sort(Arr.begin(), Arr.end(),
- [](const COFFSection *A, const COFFSection *B) {
- return A->Number < B->Number;
- });
+ llvm::sort(Arr.begin(), Arr.end(),
+ [](const COFFSection *A, const COFFSection *B) {
+ return A->Number < B->Number;
+ });
for (auto &Section : Arr) {
if (Section->Number == -1)
@@ -579,23 +580,23 @@ void WinCOFFObjectWriter::writeSectionHeaders() {
COFF::section &S = Section->Header;
if (Section->Relocations.size() >= 0xffff)
S.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL;
- writeBytes(StringRef(S.Name, COFF::NameSize));
- writeLE32(S.VirtualSize);
- writeLE32(S.VirtualAddress);
- writeLE32(S.SizeOfRawData);
- writeLE32(S.PointerToRawData);
- writeLE32(S.PointerToRelocations);
- writeLE32(S.PointerToLineNumbers);
- writeLE16(S.NumberOfRelocations);
- writeLE16(S.NumberOfLineNumbers);
- writeLE32(S.Characteristics);
+ W.OS.write(S.Name, COFF::NameSize);
+ W.write<uint32_t>(S.VirtualSize);
+ W.write<uint32_t>(S.VirtualAddress);
+ W.write<uint32_t>(S.SizeOfRawData);
+ W.write<uint32_t>(S.PointerToRawData);
+ W.write<uint32_t>(S.PointerToRelocations);
+ W.write<uint32_t>(S.PointerToLineNumbers);
+ W.write<uint16_t>(S.NumberOfRelocations);
+ W.write<uint16_t>(S.NumberOfLineNumbers);
+ W.write<uint32_t>(S.Characteristics);
}
}
void WinCOFFObjectWriter::WriteRelocation(const COFF::relocation &R) {
- writeLE32(R.VirtualAddress);
- writeLE32(R.SymbolTableIndex);
- writeLE16(R.Type);
+ W.write<uint32_t>(R.VirtualAddress);
+ W.write<uint32_t>(R.SymbolTableIndex);
+ W.write<uint16_t>(R.Type);
}
// Write MCSec's contents. What this function does is essentially
@@ -608,18 +609,10 @@ uint32_t WinCOFFObjectWriter::writeSectionContents(MCAssembler &Asm,
// to CRC the data before we dump it into the object file.
SmallVector<char, 128> Buf;
raw_svector_ostream VecOS(Buf);
- raw_pwrite_stream &OldStream = getStream();
-
- // Redirect the output stream to our buffer and fill our buffer with
- // the section data.
- setStream(VecOS);
- Asm.writeSectionData(&MCSec, Layout);
-
- // Reset the stream back to what it was before.
- setStream(OldStream);
+ Asm.writeSectionData(VecOS, &MCSec, Layout);
// Write the section contents to the object file.
- getStream() << Buf;
+ W.OS << Buf;
// Calculate our CRC with an initial value of '0', this is not how
// JamCRC is specified but it aligns with the expected output.
@@ -637,13 +630,13 @@ void WinCOFFObjectWriter::writeSection(MCAssembler &Asm,
// Write the section contents.
if (Sec.Header.PointerToRawData != 0) {
- assert(getStream().tell() <= Sec.Header.PointerToRawData &&
+ assert(W.OS.tell() <= Sec.Header.PointerToRawData &&
"Section::PointerToRawData is insane!");
- unsigned PaddingSize = Sec.Header.PointerToRawData - getStream().tell();
+ unsigned PaddingSize = Sec.Header.PointerToRawData - W.OS.tell();
assert(PaddingSize < 4 &&
"Should only need at most three bytes of padding!");
- WriteZeros(PaddingSize);
+ W.OS.write_zeros(PaddingSize);
uint32_t CRC = writeSectionContents(Asm, Layout, MCSec);
@@ -662,7 +655,7 @@ void WinCOFFObjectWriter::writeSection(MCAssembler &Asm,
return;
}
- assert(getStream().tell() == Sec.Header.PointerToRelocations &&
+ assert(W.OS.tell() == Sec.Header.PointerToRelocations &&
"Section::PointerToRelocations is insane!");
if (Sec.Relocations.size() >= 0xffff) {
@@ -697,12 +690,14 @@ void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
bool InSet, bool IsPCRel) const {
- // MS LINK expects to be able to replace all references to a function with a
- // thunk to implement their /INCREMENTAL feature. Make sure we don't optimize
- // away any relocations to functions.
+ // Don't drop relocations between functions, even if they are in the same text
+ // section. Multiple Visual C++ linker features depend on having the
+ // relocations present. The /INCREMENTAL flag will cause these relocations to
+ // point to thunks, and the /GUARD:CF flag assumes that it can use relocations
+ // to approximate the set of all address taken functions. LLD's implementation
+ // of /GUARD:CF also relies on the existance of these relocations.
uint16_t Type = cast<MCSymbolCOFF>(SymA).getType();
- if (Asm.isIncrementalLinkerCompatible() &&
- (Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
+ if ((Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
return false;
return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
InSet, IsPCRel);
@@ -906,7 +901,7 @@ void WinCOFFObjectWriter::assignSectionNumbers() {
// Assign file offsets to COFF object file structures.
void WinCOFFObjectWriter::assignFileOffsets(MCAssembler &Asm,
const MCAsmLayout &Layout) {
- unsigned Offset = getInitialOffset();
+ unsigned Offset = W.OS.tell();
Offset += UseBigObj ? COFF::Header32Size : COFF::Header16Size;
Offset += COFF::SectionSize * Header.NumberOfSections;
@@ -967,8 +962,10 @@ void WinCOFFObjectWriter::assignFileOffsets(MCAssembler &Asm,
Header.PointerToSymbolTable = Offset;
}
-void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
- const MCAsmLayout &Layout) {
+uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
+ const MCAsmLayout &Layout) {
+ uint64_t StartOffset = W.OS.tell();
+
if (Sections.size() > INT32_MAX)
report_fatal_error(
"PE COFF object files can't have more than 2147483647 sections");
@@ -1064,7 +1061,7 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
for (; I != IE && J != JE; ++I, ++J)
writeSection(Asm, Layout, **I, *J);
- assert(getStream().tell() == Header.PointerToSymbolTable &&
+ assert(W.OS.tell() == Header.PointerToSymbolTable &&
"Header::PointerToSymbolTable is insane!");
// Write a symbol table.
@@ -1073,7 +1070,9 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
WriteSymbol(*Symbol);
// Write a string table, which completes the entire COFF file.
- Strings.write(getStream());
+ Strings.write(W.OS);
+
+ return W.OS.tell() - StartOffset;
}
MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_)