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.cpp171
1 files changed, 90 insertions, 81 deletions
diff --git a/lib/MC/WinCOFFObjectWriter.cpp b/lib/MC/WinCOFFObjectWriter.cpp
index a76cbdbd5447..f316a5af387d 100644
--- a/lib/MC/WinCOFFObjectWriter.cpp
+++ b/lib/MC/WinCOFFObjectWriter.cpp
@@ -109,7 +109,6 @@ public:
relocations Relocations;
COFFSection(StringRef name);
- static size_t size();
};
class WinCOFFObjectWriter : public MCObjectWriter {
@@ -155,6 +154,8 @@ public:
object_t *createCOFFEntity(StringRef Name, list_t &List);
void defineSection(MCSectionCOFF const &Sec);
+
+ COFFSymbol *getLinkedSymbol(const MCSymbol &Symbol);
void DefineSymbol(const MCSymbol &Symbol, MCAssembler &Assembler,
const MCAsmLayout &Layout);
@@ -222,8 +223,6 @@ COFFSection::COFFSection(StringRef name)
memset(&Header, 0, sizeof(Header));
}
-size_t COFFSection::size() { return COFF::SectionSize; }
-
//------------------------------------------------------------------------------
// WinCOFFObjectWriter class implementation
@@ -353,34 +352,52 @@ static uint64_t getSymbolValue(const MCSymbol &Symbol,
return Res;
}
+COFFSymbol *WinCOFFObjectWriter::getLinkedSymbol(const MCSymbol &Symbol) {
+ if (!Symbol.isVariable())
+ return nullptr;
+
+ const MCSymbolRefExpr *SymRef =
+ dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue());
+ if (!SymRef)
+ return nullptr;
+
+ const MCSymbol &Aliasee = SymRef->getSymbol();
+ if (!Aliasee.isUndefined())
+ return nullptr;
+ return GetOrCreateCOFFSymbol(&Aliasee);
+}
+
/// This function takes a symbol data object from the assembler
/// and creates the associated COFF symbol staging object.
void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol,
MCAssembler &Assembler,
const MCAsmLayout &Layout) {
COFFSymbol *coff_symbol = GetOrCreateCOFFSymbol(&Symbol);
+ const MCSymbol *Base = Layout.getBaseSymbol(Symbol);
+ COFFSection *Sec = nullptr;
+ if (Base && Base->getFragment()) {
+ Sec = SectionMap[Base->getFragment()->getParent()];
+ if (coff_symbol->Section && coff_symbol->Section != Sec)
+ report_fatal_error("conflicting sections for symbol");
+ }
+ COFFSymbol *Local = nullptr;
if (cast<MCSymbolCOFF>(Symbol).isWeakExternal()) {
coff_symbol->Data.StorageClass = COFF::IMAGE_SYM_CLASS_WEAK_EXTERNAL;
- if (Symbol.isVariable()) {
- const MCSymbolRefExpr *SymRef =
- dyn_cast<MCSymbolRefExpr>(Symbol.getVariableValue());
-
- if (!SymRef)
- report_fatal_error("Weak externals may only alias symbols");
-
- coff_symbol->Other = GetOrCreateCOFFSymbol(&SymRef->getSymbol());
- } else {
+ COFFSymbol *WeakDefault = getLinkedSymbol(Symbol);
+ if (!WeakDefault) {
std::string WeakName = (".weak." + Symbol.getName() + ".default").str();
- COFFSymbol *WeakDefault = createSymbol(WeakName);
- WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
- WeakDefault->Data.StorageClass = COFF::IMAGE_SYM_CLASS_EXTERNAL;
- WeakDefault->Data.Type = 0;
- WeakDefault->Data.Value = 0;
- coff_symbol->Other = WeakDefault;
+ WeakDefault = createSymbol(WeakName);
+ if (!Sec)
+ WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
+ else
+ WeakDefault->Section = Sec;
+ Local = WeakDefault;
}
+ coff_symbol->Other = WeakDefault;
+
// Setup the Weak External auxiliary symbol.
coff_symbol->Aux.resize(1);
memset(&coff_symbol->Aux[0], 0, sizeof(coff_symbol->Aux[0]));
@@ -388,47 +405,37 @@ void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &Symbol,
coff_symbol->Aux[0].Aux.WeakExternal.TagIndex = 0;
coff_symbol->Aux[0].Aux.WeakExternal.Characteristics =
COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY;
-
- coff_symbol->MC = &Symbol;
} else {
- const MCSymbol *Base = Layout.getBaseSymbol(Symbol);
- coff_symbol->Data.Value = getSymbolValue(Symbol, Layout);
+ if (!Base)
+ coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
+ else
+ coff_symbol->Section = Sec;
+ Local = coff_symbol;
+ }
+
+ if (Local) {
+ Local->Data.Value = getSymbolValue(Symbol, Layout);
const MCSymbolCOFF &SymbolCOFF = cast<MCSymbolCOFF>(Symbol);
- coff_symbol->Data.Type = SymbolCOFF.getType();
- coff_symbol->Data.StorageClass = SymbolCOFF.getClass();
+ Local->Data.Type = SymbolCOFF.getType();
+ Local->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 (Local->Data.StorageClass == COFF::IMAGE_SYM_CLASS_NULL) {
bool IsExternal = Symbol.isExternal() ||
(!Symbol.getFragment() && !Symbol.isVariable());
- coff_symbol->Data.StorageClass = IsExternal
- ? COFF::IMAGE_SYM_CLASS_EXTERNAL
- : COFF::IMAGE_SYM_CLASS_STATIC;
- }
-
- if (!Base) {
- coff_symbol->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
- } else {
- if (Base->getFragment()) {
- COFFSection *Sec = SectionMap[Base->getFragment()->getParent()];
-
- if (coff_symbol->Section && coff_symbol->Section != Sec)
- report_fatal_error("conflicting sections for symbol");
-
- coff_symbol->Section = Sec;
- }
+ Local->Data.StorageClass = IsExternal ? COFF::IMAGE_SYM_CLASS_EXTERNAL
+ : COFF::IMAGE_SYM_CLASS_STATIC;
}
-
- coff_symbol->MC = &Symbol;
}
+
+ coff_symbol->MC = &Symbol;
}
// Maximum offsets for different string table entry encodings.
-static const unsigned Max6DecimalOffset = 999999;
-static const unsigned Max7DecimalOffset = 9999999;
-static const uint64_t MaxBase64Offset = 0xFFFFFFFFFULL; // 64^6, including 0
+enum : unsigned { Max7DecimalOffset = 9999999U };
+enum : uint64_t { MaxBase64Offset = 0xFFFFFFFFFULL }; // 64^6, including 0
// Encode a string table entry offset in base 64, padded to 6 chars, and
// prefixed with a double slash: '//AAAAAA', '//AAAAAB', ...
@@ -456,22 +463,21 @@ void WinCOFFObjectWriter::SetSectionName(COFFSection &S) {
if (S.Name.size() > COFF::NameSize) {
uint64_t StringTableEntry = Strings.getOffset(S.Name);
- if (StringTableEntry <= Max6DecimalOffset) {
- std::sprintf(S.Header.Name, "/%d", unsigned(StringTableEntry));
- } else if (StringTableEntry <= Max7DecimalOffset) {
- // With seven digits, we have to skip the terminating null. Because
- // sprintf always appends it, we use a larger temporary buffer.
- char buffer[9] = {};
- std::sprintf(buffer, "/%d", unsigned(StringTableEntry));
- std::memcpy(S.Header.Name, buffer, 8);
+ if (StringTableEntry <= Max7DecimalOffset) {
+ SmallVector<char, COFF::NameSize> Buffer;
+ Twine('/').concat(Twine(StringTableEntry)).toVector(Buffer);
+ assert(Buffer.size() <= COFF::NameSize && Buffer.size() >= 2);
+
+ std::memcpy(S.Header.Name, Buffer.data(), Buffer.size());
} else if (StringTableEntry <= MaxBase64Offset) {
// Starting with 10,000,000, offsets are encoded as base64.
encodeBase64StringEntry(S.Header.Name, StringTableEntry);
} else {
report_fatal_error("COFF string table is greater than 64 GB.");
}
- } else
+ } else {
std::memcpy(S.Header.Name, S.Name.c_str(), S.Name.size());
+ }
}
void WinCOFFObjectWriter::SetSymbolName(COFFSymbol &S) {
@@ -530,48 +536,47 @@ void WinCOFFObjectWriter::WriteSymbol(const COFFSymbol &S) {
void WinCOFFObjectWriter::WriteAuxiliarySymbols(
const COFFSymbol::AuxiliarySymbols &S) {
- for (COFFSymbol::AuxiliarySymbols::const_iterator i = S.begin(), e = S.end();
- i != e; ++i) {
- switch (i->AuxType) {
+ 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));
+ 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));
if (UseBigObj)
WriteZeros(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));
+ 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));
if (UseBigObj)
WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
case ATWeakExternal:
- writeLE32(i->Aux.WeakExternal.TagIndex);
- writeLE32(i->Aux.WeakExternal.Characteristics);
- WriteZeros(sizeof(i->Aux.WeakExternal.unused));
+ writeLE32(i.Aux.WeakExternal.TagIndex);
+ writeLE32(i.Aux.WeakExternal.Characteristics);
+ WriteZeros(sizeof(i.Aux.WeakExternal.unused));
if (UseBigObj)
WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
case ATFile:
writeBytes(
- StringRef(reinterpret_cast<const char *>(&i->Aux),
+ StringRef(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));
+ 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));
if (UseBigObj)
WriteZeros(COFF::Symbol32Size - COFF::Symbol16Size);
break;
@@ -787,6 +792,10 @@ void WinCOFFObjectWriter::recordRelocation(
}
}
+ // The fixed value never makes sense for section indicies, ignore it.
+ if (Fixup.getKind() == FK_SecRel_2)
+ FixedValue = 0;
+
if (TargetObjectWriter->recordRelocation(Fixup))
coff_section->Relocations.push_back(Reloc);
}
@@ -924,7 +933,7 @@ void WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
if (IsPhysicalSection(Sec)) {
// Align the section data to a four byte boundary.
- offset = RoundUpToAlignment(offset, 4);
+ offset = alignTo(offset, 4);
Sec->Header.PointerToRawData = offset;
offset += Sec->Header.SizeOfRawData;