#include "llvm/MC/MCObjectWriter.h"
#include "llvm/MC/MCSection.h"
#include "llvm/MC/MCSectionCOFF.h"
-#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCSymbolCOFF.h"
#include "llvm/MC/MCValue.h"
#include "llvm/MC/StringTableBuilder.h"
#include "llvm/Support/COFF.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/JamCRC.h"
#include "llvm/Support/TimeValue.h"
#include <cstdio>
+#include <ctime>
using namespace llvm;
void WriteFileHeader(const COFF::header &Header);
void WriteSymbol(const COFFSymbol &S);
void WriteAuxiliarySymbols(const COFFSymbol::AuxiliarySymbols &S);
- void WriteSectionHeader(const COFF::section &S);
+ void writeSectionHeader(const COFF::section &S);
void WriteRelocation(const COFF::relocation &R);
// MCObjectWriter interface implementation.
- void ExecutePostLayoutBinding(MCAssembler &Asm,
+ void executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) override;
bool isSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
}
// if this is a safeseh handler, keep it
- if (MC && (MC->getFlags() & COFF::SF_SafeSEH))
+ if (MC && (cast<MCSymbolCOFF>(MC)->isSafeSEH()))
return true;
// if the section its in is being droped, drop it
COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol);
SymbolMap[&Symbol] = coff_symbol;
- if (Symbol.getFlags() & COFF::SF_WeakExternal) {
+ if (cast<MCSymbolCOFF>(Symbol).isWeakExternal()) {
coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
if (Symbol.isVariable()) {
const MCSymbol *Base = Layout.getBaseSymbol(Symbol);
coff_symbol->Data.Value = getSymbolValue(Symbol, Layout);
- coff_symbol->Data.Type =
- (Symbol.getFlags() & COFF::SF_TypeMask) >> COFF::SF_TypeShift;
- coff_symbol->Data.StorageClass =
- (Symbol.getFlags() & COFF::SF_ClassMask) >> COFF::SF_ClassShift;
+ const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(Symbol);
+ coff_symbol->Data.Type = SymbolCOFF.getType();
+ coff_symbol->Data.StorageClass = SymbolCOFF.getClass();
// If no storage class was specified in the streamer, define it here.
if (coff_symbol->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) {
if (!Symbol.isTemporary())
return true;
- // Absolute temporary labels are never visible.
- if (!Symbol.isInSection())
+ // Temporary variable symbols are invisible.
+ if (Symbol.isVariable())
return false;
- // For now, all non-variable symbols are exported,
- // the linker will sort the rest out for us.
- return !Symbol.isVariable();
+ // Absolute temporary labels are never visible.
+ return !Symbol.isAbsolute();
}
bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
}
}
-void WinCOFFObjectWriter::WriteSectionHeader(const COFF::section &S) {
+void WinCOFFObjectWriter::writeSectionHeader(const COFF::section &S) {
writeBytes(StringRef(S.Name, COFF::NameSize));
writeLE32(S.VirtualSize);
////////////////////////////////////////////////////////////////////////////////
// MCObjectWriter interface implementations
-void WinCOFFObjectWriter::ExecutePostLayoutBinding(MCAssembler &Asm,
+void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
const MCAsmLayout &Layout) {
// "Define" each section & symbol. This creates section & symbol
// entries in the staging area.
// 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.
- if ((((SymA.getFlags() & COFF::SF_TypeMask) >> COFF::SF_TypeShift) >>
- COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
+ uint16_t Type = cast<MCSymbolCOFF>(SymA).getType();
+ if ((Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
return false;
return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
InSet, IsPCRel);
// Mark this symbol as requiring an entry in the symbol table.
assert(SectionMap.find(Section) != SectionMap.end() &&
- "Section must already have been defined in ExecutePostLayoutBinding!");
+ "Section must already have been defined in executePostLayoutBinding!");
assert(SymbolMap.find(&A) != SymbolMap.end() &&
- "Symbol must already have been defined in ExecutePostLayoutBinding!");
+ "Symbol must already have been defined in executePostLayoutBinding!");
COFFSection *coff_section = SectionMap[Section];
COFFSymbol *coff_symbol = SymbolMap[&A];
Header.PointerToSymbolTable = offset;
+#if (ENABLE_TIMESTAMPS == 1)
+ // MS LINK expects to be able to use this timestamp to implement their
+ // /INCREMENTAL feature.
+ std::time_t Now = time(nullptr);
+ if (Now < 0 || !isUInt<32>(Now))
+ Now = UINT32_MAX;
+ Header.TimeDateStamp = Now;
+#else
// We want a deterministic output. It looks like GNU as also writes 0 in here.
Header.TimeDateStamp = 0;
+#endif
// Write it all to disk...
WriteFileHeader(Header);
if (Section->Number != -1) {
if (Section->Relocations.size() >= 0xffff)
Section->Header.Characteristics |= COFF::IMAGE_SCN_LNK_NRELOC_OVFL;
- WriteSectionHeader(Section->Header);
+ writeSectionHeader(Section->Header);
}
}
+ SmallVector<char, 128> SectionContents;
for (i = Sections.begin(), ie = Sections.end(), j = Asm.begin(),
je = Asm.end();
(i != ie) && (j != je); ++i, ++j) {
continue;
if ((*i)->Header.PointerToRawData != 0) {
- assert(OS.tell() <= (*i)->Header.PointerToRawData &&
+ assert(getStream().tell() <= (*i)->Header.PointerToRawData &&
"Section::PointerToRawData is insane!");
- unsigned SectionDataPadding = (*i)->Header.PointerToRawData - OS.tell();
+ unsigned SectionDataPadding =
+ (*i)->Header.PointerToRawData - getStream().tell();
assert(SectionDataPadding < 4 &&
"Should only need at most three bytes of padding!");
WriteZeros(SectionDataPadding);
+ // Save the contents of the section to a temporary buffer, we need this
+ // to CRC the data before we dump it into the object file.
+ SectionContents.clear();
+ raw_svector_ostream VecOS(SectionContents);
+ raw_pwrite_stream &OldStream = getStream();
+ // Redirect the output stream to our buffer.
+ setStream(VecOS);
+ // Fill our buffer with the section data.
Asm.writeSectionData(&*j, Layout);
+ // Reset the stream back to what it was before.
+ setStream(OldStream);
+
+ // Calculate our CRC with an initial value of '0', this is not how
+ // JamCRC is specified but it aligns with the expected output.
+ JamCRC JC(/*Init=*/0x00000000U);
+ JC.update(SectionContents);
+
+ // Write the section contents to the object file.
+ getStream() << SectionContents;
+
+ // Update the section definition auxiliary symbol to record the CRC.
+ COFFSection *Sec = SectionMap[&*j];
+ COFFSymbol::AuxiliarySymbols &AuxSyms = Sec->Symbol->Aux;
+ assert(AuxSyms.size() == 1 &&
+ AuxSyms[0].AuxType == ATSectionDefinition);
+ AuxSymbol &SecDef = AuxSyms[0];
+ SecDef.Aux.SectionDefinition.CheckSum = JC.getCRC();
}
if ((*i)->Relocations.size() > 0) {
- assert(OS.tell() == (*i)->Header.PointerToRelocations &&
+ assert(getStream().tell() == (*i)->Header.PointerToRelocations &&
"Section::PointerToRelocations is insane!");
if ((*i)->Relocations.size() >= 0xffff) {
}
}
- assert(OS.tell() == Header.PointerToSymbolTable &&
+ assert(getStream().tell() == Header.PointerToSymbolTable &&
"Header::PointerToSymbolTable is insane!");
for (auto &Symbol : Symbols)
if (Symbol->getIndex() != -1)
WriteSymbol(*Symbol);
- OS.write(Strings.data().data(), Strings.data().size());
+ getStream().write(Strings.data().data(), Strings.data().size());
}
MCWinCOFFObjectTargetWriter::MCWinCOFFObjectTargetWriter(unsigned Machine_)