aboutsummaryrefslogtreecommitdiff
path: root/lib/MC/WinCOFFObjectWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/MC/WinCOFFObjectWriter.cpp')
-rw-r--r--lib/MC/WinCOFFObjectWriter.cpp193
1 files changed, 97 insertions, 96 deletions
diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp
index 56ef1c7a2735..a3820906b76b 100644
--- a/lib/MC/WinCOFFObjectWriter.cpp
+++ b/lib/MC/WinCOFFObjectWriter.cpp
@@ -17,6 +17,7 @@
#include "llvm/ADT/StringMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Config/config.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
@@ -32,8 +33,10 @@
#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;
@@ -76,8 +79,6 @@ public:
COFFSymbol(StringRef name);
void set_name_offset(uint32_t Offset);
- bool should_keep() const;
-
int64_t getIndex() const { return Index; }
void setIndex(int Value) {
Index = Value;
@@ -125,7 +126,7 @@ public:
COFF::header Header;
sections Sections;
symbols Symbols;
- StringTableBuilder Strings;
+ StringTableBuilder Strings{StringTableBuilder::WinCOFF};
// Maps used during object file creation.
section_map SectionMap;
@@ -160,8 +161,6 @@ public:
void SetSymbolName(COFFSymbol &S);
void SetSectionName(COFFSection &S);
- bool ExportSymbol(const MCSymbol &Symbol, MCAssembler &Asm);
-
bool IsPhysicalSection(COFFSection *S);
// Entity writing methods.
@@ -215,38 +214,6 @@ void COFFSymbol::set_name_offset(uint32_t Offset) {
write_uint32_le(Data.Name + 4, Offset);
}
-/// logic to decide if the symbol should be reported in the symbol table
-bool COFFSymbol::should_keep() const {
- // no section means its external, keep it
- if (!Section)
- return true;
-
- // if it has relocations pointing at it, keep it
- if (Relocations > 0) {
- assert(Section->Number != -1 && "Sections with relocations must be real!");
- return true;
- }
-
- // if this is a safeseh handler, keep it
- if (MC && (cast<MCSymbolCOFF>(MC)->isSafeSEH()))
- return true;
-
- // if the section its in is being droped, drop it
- if (Section->Number == -1)
- return false;
-
- // if it is the section symbol, keep it
- if (Section->Symbol == this)
- return true;
-
- // if its temporary, drop it
- if (MC && MC->isTemporary())
- return false;
-
- // otherwise, keep it
- return true;
-}
-
//------------------------------------------------------------------------------
// Section class implementation
@@ -392,7 +359,6 @@ void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol,
MCAssembler &Assembler,
const MCAsmLayout &Layout) {
COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol);
- SymbolMap[&Symbol] = coff_symbol;
if (cast<MCSymbolCOFF>(Symbol).isWeakExternal()) {
coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
@@ -515,25 +481,6 @@ void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) {
std::memcpy(S.Data.Name, S.Name.c_str(), S.Name.size());
}
-bool WinCOFFObjectWriter::ExportSymbol(const MCSymbol &Symbol,
- MCAssembler &Asm) {
- // This doesn't seem to be right. Strings referred to from the .data section
- // need symbols so they can be linked to code in the .text section right?
-
- // return Asm.isSymbolLinkerVisible(Symbol);
-
- // Non-temporary labels should always be visible to the linker.
- if (!Symbol.isTemporary())
- return true;
-
- // Temporary variable symbols are invisible.
- if (Symbol.isVariable())
- return false;
-
- // Absolute temporary labels are never visible.
- return !Symbol.isAbsolute();
-}
-
bool WinCOFFObjectWriter::IsPhysicalSection(COFFSection *S) {
return (S->Header.Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) ==
0;
@@ -663,7 +610,7 @@ void WinCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
defineSection(static_cast<const MCSectionCOFF &>(Section));
for (const MCSymbol &Symbol : Asm.symbols())
- if (ExportSymbol(Symbol, Asm))
+ if (!Symbol.isTemporary())
DefineSymbol(Symbol, Asm, Layout);
}
@@ -674,7 +621,8 @@ bool WinCOFFObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
// thunk to implement their /INCREMENTAL feature. Make sure we don't optimize
// away any relocations to functions.
uint16_t Type = cast<MCSymbolCOFF>(SymA).getType();
- if ((Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
+ if (Asm.isIncrementalLinkerCompatible() &&
+ (Type >> COFF::SCT_COMPLEX_TYPE_SHIFT) == COFF::IMAGE_SYM_DTYPE_FUNCTION)
return false;
return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, SymA, FB,
InSet, IsPCRel);
@@ -702,41 +650,49 @@ void WinCOFFObjectWriter::recordRelocation(
const MCFixup &Fixup, MCValue Target, bool &IsPCRel, uint64_t &FixedValue) {
assert(Target.getSymA() && "Relocation must reference a symbol!");
- const MCSymbol &Symbol = Target.getSymA()->getSymbol();
- const MCSymbol &A = Symbol;
- if (!A.isRegistered())
- Asm.getContext().reportFatalError(Fixup.getLoc(),
+ const MCSymbol &A = Target.getSymA()->getSymbol();
+ if (!A.isRegistered()) {
+ Asm.getContext().reportError(Fixup.getLoc(),
Twine("symbol '") + A.getName() +
"' can not be undefined");
+ return;
+ }
+ if (A.isTemporary() && A.isUndefined()) {
+ Asm.getContext().reportError(Fixup.getLoc(),
+ Twine("assembler label '") + A.getName() +
+ "' can not be undefined");
+ return;
+ }
MCSection *Section = Fragment->getParent();
// 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!");
- assert(SymbolMap.find(&A) != SymbolMap.end() &&
- "Symbol must already have been defined in executePostLayoutBinding!");
COFFSection *coff_section = SectionMap[Section];
- COFFSymbol *coff_symbol = SymbolMap[&A];
const MCSymbolRefExpr *SymB = Target.getSymB();
bool CrossSection = false;
if (SymB) {
const MCSymbol *B = &SymB->getSymbol();
- if (!B->getFragment())
- Asm.getContext().reportFatalError(
+ if (!B->getFragment()) {
+ Asm.getContext().reportError(
Fixup.getLoc(),
Twine("symbol '") + B->getName() +
"' can not be undefined in a subtraction expression");
+ return;
+ }
- if (!A.getFragment())
- Asm.getContext().reportFatalError(
+ if (!A.getFragment()) {
+ Asm.getContext().reportError(
Fixup.getLoc(),
- Twine("symbol '") + Symbol.getName() +
+ Twine("symbol '") + A.getName() +
"' can not be undefined in a subtraction expression");
+ return;
+ }
- CrossSection = &Symbol.getSection() != &B->getSection();
+ CrossSection = &A.getSection() != &B->getSection();
// Offset of the symbol in the section
int64_t OffsetOfB = Layout.getSymbolOffset(*B);
@@ -765,12 +721,19 @@ void WinCOFFObjectWriter::recordRelocation(
Reloc.Data.VirtualAddress = Layout.getFragmentOffset(Fragment);
// Turn relocations for temporary symbols into section relocations.
- if (coff_symbol->MC->isTemporary() || CrossSection) {
- Reloc.Symb = coff_symbol->Section->Symbol;
- FixedValue += Layout.getFragmentOffset(coff_symbol->MC->getFragment()) +
- coff_symbol->MC->getOffset();
- } else
- Reloc.Symb = coff_symbol;
+ if (A.isTemporary() || CrossSection) {
+ MCSection *TargetSection = &A.getSection();
+ assert(
+ SectionMap.find(TargetSection) != SectionMap.end() &&
+ "Section must already have been defined in executePostLayoutBinding!");
+ Reloc.Symb = SectionMap[TargetSection]->Symbol;
+ FixedValue += Layout.getSymbolOffset(A);
+ } else {
+ assert(
+ SymbolMap.find(&A) != SymbolMap.end() &&
+ "Symbol must already have been defined in executePostLayoutBinding!");
+ Reloc.Symb = SymbolMap[&A];
+ }
++Reloc.Symb->Relocations;
@@ -884,14 +847,10 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
// Update section number & offset for symbols that have them.
if (Symbol->Section)
Symbol->Data.SectionNumber = Symbol->Section->Number;
- if (Symbol->should_keep()) {
- Symbol->setIndex(Header.NumberOfSymbols++);
- // Update auxiliary symbol info.
- Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size();
- Header.NumberOfSymbols += Symbol->Data.NumberOfAuxSymbols;
- } else {
- Symbol->setIndex(-1);
- }
+ Symbol->setIndex(Header.NumberOfSymbols++);
+ // Update auxiliary symbol info.
+ Symbol->Data.NumberOfAuxSymbols = Symbol->Aux.size();
+ Header.NumberOfSymbols += Symbol->Data.NumberOfAuxSymbols;
}
// Build string table.
@@ -899,16 +858,15 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
if (S->Name.size() > COFF::NameSize)
Strings.add(S->Name);
for (const auto &S : Symbols)
- if (S->should_keep() && S->Name.size() > COFF::NameSize)
+ if (S->Name.size() > COFF::NameSize)
Strings.add(S->Name);
- Strings.finalize(StringTableBuilder::WinCOFF);
+ Strings.finalize();
// Set names.
for (const auto &S : Sections)
SetSectionName(*S);
for (auto &S : Symbols)
- if (S->should_keep())
- SetSymbolName(*S);
+ SetSymbolName(*S);
// Fixup weak external references.
for (auto &Symbol : Symbols) {
@@ -948,7 +906,7 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
// Assign file offsets to COFF object file structures.
- unsigned offset = 0;
+ unsigned offset = getInitialOffset();
if (UseBigObj)
offset += COFF::Header32Size;
@@ -1011,8 +969,23 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
Header.PointerToSymbolTable = offset;
+ // FIXME: Remove the #else branch and make the #if branch unconditional once
+ // LLVM's self host configuration is aware of /Brepro.
+#if (ENABLE_TIMESTAMPS == 1)
+ // MS LINK expects to be able to use this timestamp to implement their
+ // /INCREMENTAL feature.
+ if (Asm.isIncrementalLinkerCompatible()) {
+ std::time_t Now = time(nullptr);
+ if (Now < 0 || !isUInt<32>(Now))
+ Now = UINT32_MAX;
+ Header.TimeDateStamp = Now;
+ } else {
+ Header.TimeDateStamp = 0;
+ }
+#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);
@@ -1029,6 +1002,7 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
}
}
+ SmallVector<char, 128> SectionContents;
for (i = Sections.begin(), ie = Sections.end(), j = Asm.begin(),
je = Asm.end();
(i != ie) && (j != je); ++i, ++j) {
@@ -1037,20 +1011,47 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
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) {
@@ -1071,14 +1072,14 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
}
}
- 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_)