aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/MC/WinCOFFObjectWriter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/MC/WinCOFFObjectWriter.cpp')
-rw-r--r--llvm/lib/MC/WinCOFFObjectWriter.cpp49
1 files changed, 49 insertions, 0 deletions
diff --git a/llvm/lib/MC/WinCOFFObjectWriter.cpp b/llvm/lib/MC/WinCOFFObjectWriter.cpp
index cf755dc..6a0a11e 100644
--- a/llvm/lib/MC/WinCOFFObjectWriter.cpp
+++ b/llvm/lib/MC/WinCOFFObjectWriter.cpp
@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
@@ -131,6 +132,8 @@ public:
using symbol_map = DenseMap<MCSymbol const *, COFFSymbol *>;
using section_map = DenseMap<MCSection const *, COFFSection *>;
+ using symbol_list = DenseSet<COFFSymbol *>;
+
std::unique_ptr<MCWinCOFFObjectTargetWriter> TargetObjectWriter;
// Root level file contents.
@@ -143,6 +146,8 @@ public:
section_map SectionMap;
symbol_map SymbolMap;
+ symbol_list WeakDefaults;
+
bool UseBigObj;
bool EmitAddrsigSection = false;
@@ -205,6 +210,7 @@ public:
MCValue Target, uint64_t &FixedValue) override;
void createFileSymbols(MCAssembler &Asm);
+ void setWeakDefaultNames();
void assignSectionNumbers();
void assignFileOffsets(MCAssembler &Asm, const MCAsmLayout &Layout);
@@ -376,6 +382,7 @@ void WinCOFFObjectWriter::DefineSymbol(const MCSymbol &MCSym,
WeakDefault->Data.SectionNumber = COFF::IMAGE_SYM_ABSOLUTE;
else
WeakDefault->Section = Sec;
+ WeakDefaults.insert(WeakDefault);
Local = WeakDefault;
}
@@ -863,6 +870,47 @@ void WinCOFFObjectWriter::createFileSymbols(MCAssembler &Asm) {
}
}
+void WinCOFFObjectWriter::setWeakDefaultNames() {
+ if (WeakDefaults.empty())
+ return;
+
+ // If multiple object files use a weak symbol (either with a regular
+ // defined default, or an absolute zero symbol as default), the defaults
+ // cause duplicate definitions unless their names are made unique. Look
+ // for a defined extern symbol, that isn't comdat - that should be unique
+ // unless there are other duplicate definitions. And if none is found,
+ // allow picking a comdat symbol, as that's still better than nothing.
+
+ COFFSymbol *Unique = nullptr;
+ for (bool AllowComdat : {false, true}) {
+ for (auto &Sym : Symbols) {
+ // Don't include the names of the defaults themselves
+ if (WeakDefaults.count(Sym.get()))
+ continue;
+ // Only consider external symbols
+ if (Sym->Data.StorageClass != COFF::IMAGE_SYM_CLASS_EXTERNAL)
+ continue;
+ // Only consider symbols defined in a section or that are absolute
+ if (!Sym->Section && Sym->Data.SectionNumber != COFF::IMAGE_SYM_ABSOLUTE)
+ continue;
+ if (!AllowComdat && Sym->Section &&
+ Sym->Section->Header.Characteristics & COFF::IMAGE_SCN_LNK_COMDAT)
+ continue;
+ Unique = Sym.get();
+ break;
+ }
+ if (Unique)
+ break;
+ }
+ // If we didn't find any unique symbol to use for the names, just skip this.
+ if (!Unique)
+ return;
+ for (auto *Sym : WeakDefaults) {
+ Sym->Name.append(".");
+ Sym->Name.append(Unique->Name);
+ }
+}
+
static bool isAssociative(const COFFSection &Section) {
return Section.Symbol->Aux[0].Aux.SectionDefinition.Selection ==
COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE;
@@ -961,6 +1009,7 @@ uint64_t WinCOFFObjectWriter::writeObject(MCAssembler &Asm,
Header.NumberOfSections = Sections.size();
Header.NumberOfSymbols = 0;
+ setWeakDefaultNames();
assignSectionNumbers();
createFileSymbols(Asm);