summaryrefslogtreecommitdiffstats
path: root/lld
diff options
context:
space:
mode:
authorHans Wennborg <hans@hanshq.net>2018-08-07 07:46:29 +0000
committerHans Wennborg <hans@hanshq.net>2018-08-07 07:46:29 +0000
commit1c21f5b4292dc4bd99e05c5bd397a4fea9468954 (patch)
tree2117d80a44fcc54f11bbf439e2c28a73fbaa72d4 /lld
parent57c21c9592ce63af90556aeb0c37805f20c2d19a (diff)
downloadbcm5719-llvm-1c21f5b4292dc4bd99e05c5bd397a4fea9468954.tar.gz
bcm5719-llvm-1c21f5b4292dc4bd99e05c5bd397a4fea9468954.zip
Merging r339058:
------------------------------------------------------------------------ r339058 | mstorsjo | 2018-08-06 23:26:09 +0200 (Mon, 06 Aug 2018) | 16 lines [COFF] Treat .xdata/.pdata$<sym> as implicitly associative to <sym> for MinGW MinGW configurations don't use associative comdats, as GNU ld doesn't support that. Instead they produce normal comdats named .text$sym, .xdata$sym and .pdata$sym. GNU ld doesn't discard any comdats starting with .xdata or .pdata, even if --gc-sections is used (while it does discard other unreferenced comdats), regardless of what symbol name is used after the $ separator. For LLD, treat any such comdat as implicitly associative to the base symbol. This requires maintaining a map from symbol name to section number, but that is only maintained when the MinGW flag has been enabled. Differential Revision: https://reviews.llvm.org/D49700 ------------------------------------------------------------------------ llvm-svn: 339108
Diffstat (limited to 'lld')
-rw-r--r--lld/COFF/InputFiles.cpp54
-rw-r--r--lld/COFF/InputFiles.h17
-rw-r--r--lld/test/COFF/Inputs/associative-comdat-mingw-2.s34
-rw-r--r--lld/test/COFF/associative-comdat-mingw.s73
4 files changed, 172 insertions, 6 deletions
diff --git a/lld/COFF/InputFiles.cpp b/lld/COFF/InputFiles.cpp
index 2b3e65fae04..289cdb1f6cd 100644
--- a/lld/COFF/InputFiles.cpp
+++ b/lld/COFF/InputFiles.cpp
@@ -205,7 +205,13 @@ SectionChunk *ObjFile::readSection(uint32_t SectionNumber,
void ObjFile::readAssociativeDefinition(
COFFSymbolRef Sym, const coff_aux_section_definition *Def) {
- SectionChunk *Parent = SparseChunks[Def->getNumber(Sym.isBigObj())];
+ readAssociativeDefinition(Sym, Def, Def->getNumber(Sym.isBigObj()));
+}
+
+void ObjFile::readAssociativeDefinition(COFFSymbolRef Sym,
+ const coff_aux_section_definition *Def,
+ uint32_t ParentSection) {
+ SectionChunk *Parent = SparseChunks[ParentSection];
// If the parent is pending, it probably means that its section definition
// appears after us in the symbol table. Leave the associated section as
@@ -225,6 +231,35 @@ void ObjFile::readAssociativeDefinition(
}
}
+void ObjFile::recordPrevailingSymbolForMingw(
+ COFFSymbolRef Sym, DenseMap<StringRef, uint32_t> &PrevailingSectionMap) {
+ // For comdat symbols in executable sections, where this is the copy
+ // of the section chunk we actually include instead of discarding it,
+ // add the symbol to a map to allow using it for implicitly
+ // associating .[px]data$<func> sections to it.
+ int32_t SectionNumber = Sym.getSectionNumber();
+ SectionChunk *SC = SparseChunks[SectionNumber];
+ if (SC && SC->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) {
+ StringRef Name;
+ COFFObj->getSymbolName(Sym, Name);
+ PrevailingSectionMap[Name] = SectionNumber;
+ }
+}
+
+void ObjFile::maybeAssociateSEHForMingw(
+ COFFSymbolRef Sym, const coff_aux_section_definition *Def,
+ const DenseMap<StringRef, uint32_t> &PrevailingSectionMap) {
+ StringRef Name;
+ COFFObj->getSymbolName(Sym, Name);
+ if (Name.consume_front(".pdata$") || Name.consume_front(".xdata$")) {
+ // For MinGW, treat .[px]data$<func> as implicitly associative to
+ // the symbol <func>.
+ auto ParentSym = PrevailingSectionMap.find(Name);
+ if (ParentSym != PrevailingSectionMap.end())
+ readAssociativeDefinition(Sym, Def, ParentSym->second);
+ }
+}
+
Symbol *ObjFile::createRegular(COFFSymbolRef Sym) {
SectionChunk *SC = SparseChunks[Sym.getSectionNumber()];
if (Sym.isExternal()) {
@@ -248,19 +283,24 @@ void ObjFile::initializeSymbols() {
std::vector<uint32_t> PendingIndexes;
PendingIndexes.reserve(NumSymbols);
+ DenseMap<StringRef, uint32_t> PrevailingSectionMap;
std::vector<const coff_aux_section_definition *> ComdatDefs(
COFFObj->getNumberOfSections() + 1);
for (uint32_t I = 0; I < NumSymbols; ++I) {
COFFSymbolRef COFFSym = check(COFFObj->getSymbol(I));
+ bool PrevailingComdat;
if (COFFSym.isUndefined()) {
Symbols[I] = createUndefined(COFFSym);
} else if (COFFSym.isWeakExternal()) {
Symbols[I] = createUndefined(COFFSym);
uint32_t TagIndex = COFFSym.getAux<coff_aux_weak_external>()->TagIndex;
WeakAliases.emplace_back(Symbols[I], TagIndex);
- } else if (Optional<Symbol *> OptSym = createDefined(COFFSym, ComdatDefs)) {
+ } else if (Optional<Symbol *> OptSym =
+ createDefined(COFFSym, ComdatDefs, PrevailingComdat)) {
Symbols[I] = *OptSym;
+ if (Config->MinGW && PrevailingComdat)
+ recordPrevailingSymbolForMingw(COFFSym, PrevailingSectionMap);
} else {
// createDefined() returns None if a symbol belongs to a section that
// was pending at the point when the symbol was read. This can happen in
@@ -278,9 +318,12 @@ void ObjFile::initializeSymbols() {
for (uint32_t I : PendingIndexes) {
COFFSymbolRef Sym = check(COFFObj->getSymbol(I));
- if (auto *Def = Sym.getSectionDefinition())
+ if (auto *Def = Sym.getSectionDefinition()) {
if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE)
readAssociativeDefinition(Sym, Def);
+ else if (Config->MinGW)
+ maybeAssociateSEHForMingw(Sym, Def, PrevailingSectionMap);
+ }
if (SparseChunks[Sym.getSectionNumber()] == PendingComdat) {
StringRef Name;
COFFObj->getSymbolName(Sym, Name);
@@ -306,7 +349,9 @@ Symbol *ObjFile::createUndefined(COFFSymbolRef Sym) {
Optional<Symbol *> ObjFile::createDefined(
COFFSymbolRef Sym,
- std::vector<const coff_aux_section_definition *> &ComdatDefs) {
+ std::vector<const coff_aux_section_definition *> &ComdatDefs,
+ bool &Prevailing) {
+ Prevailing = false;
auto GetName = [&]() {
StringRef S;
COFFObj->getSymbolName(Sym, S);
@@ -352,7 +397,6 @@ Optional<Symbol *> ObjFile::createDefined(
if (const coff_aux_section_definition *Def = ComdatDefs[SectionNumber]) {
ComdatDefs[SectionNumber] = nullptr;
Symbol *Leader;
- bool Prevailing;
if (Sym.isExternal()) {
std::tie(Leader, Prevailing) =
Symtab->addComdat(this, GetName(), Sym.getGeneric());
diff --git a/lld/COFF/InputFiles.h b/lld/COFF/InputFiles.h
index 4ee4b363886..2bfb9e4b002 100644
--- a/lld/COFF/InputFiles.h
+++ b/lld/COFF/InputFiles.h
@@ -13,6 +13,7 @@
#include "Config.h"
#include "lld/Common/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/LTO/LTO.h"
#include "llvm/Object/Archive.h"
@@ -157,10 +158,24 @@ private:
COFFSymbolRef COFFSym,
const llvm::object::coff_aux_section_definition *Def);
+ void readAssociativeDefinition(
+ COFFSymbolRef COFFSym,
+ const llvm::object::coff_aux_section_definition *Def,
+ uint32_t ParentSection);
+
+ void recordPrevailingSymbolForMingw(
+ COFFSymbolRef COFFSym,
+ llvm::DenseMap<StringRef, uint32_t> &PrevailingSectionMap);
+
+ void maybeAssociateSEHForMingw(
+ COFFSymbolRef Sym, const llvm::object::coff_aux_section_definition *Def,
+ const llvm::DenseMap<StringRef, uint32_t> &PrevailingSectionMap);
+
llvm::Optional<Symbol *>
createDefined(COFFSymbolRef Sym,
std::vector<const llvm::object::coff_aux_section_definition *>
- &ComdatDefs);
+ &ComdatDefs,
+ bool &PrevailingComdat);
Symbol *createRegular(COFFSymbolRef Sym);
Symbol *createUndefined(COFFSymbolRef Sym);
diff --git a/lld/test/COFF/Inputs/associative-comdat-mingw-2.s b/lld/test/COFF/Inputs/associative-comdat-mingw-2.s
new file mode 100644
index 00000000000..edb6a82da84
--- /dev/null
+++ b/lld/test/COFF/Inputs/associative-comdat-mingw-2.s
@@ -0,0 +1,34 @@
+ .section .xdata$foo,"dr"
+ .linkonce discard
+ .p2align 3
+ .long 42
+
+ .section .xdata$bar,"dr"
+ .linkonce discard
+ .p2align 3
+ .long 43
+
+ .section .xdata$baz,"dr"
+ .linkonce discard
+ .p2align 3
+ .long 44
+
+ .def foo;
+ .scl 2;
+ .type 32;
+ .endef
+ .section .text$foo,"xr",discard,foo
+ .globl foo
+ .p2align 4
+foo:
+ ret
+
+ .def bar;
+ .scl 2;
+ .type 32;
+ .endef
+ .section .text$bar,"xr",discard,bar
+ .globl bar
+ .p2align 4
+bar:
+ ret
diff --git a/lld/test/COFF/associative-comdat-mingw.s b/lld/test/COFF/associative-comdat-mingw.s
new file mode 100644
index 00000000000..09cba9c4c6f
--- /dev/null
+++ b/lld/test/COFF/associative-comdat-mingw.s
@@ -0,0 +1,73 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t1.obj
+# RUN: llvm-mc -triple=x86_64-windows-gnu %S/Inputs/associative-comdat-mingw-2.s -filetype=obj -o %t2.obj
+
+# RUN: lld-link -lldmingw -entry:main %t1.obj %t2.obj -out:%t.gc.exe -verbose
+# RUN: llvm-readobj -sections %t.gc.exe | FileCheck %s
+
+# CHECK: Sections [
+# CHECK: Section {
+# CHECK: Number: 2
+# CHECK-LABEL: Name: .rdata (2E 72 64 61 74 61 00 00)
+# This is the critical check to show that only *one* definition of
+# .xdata$foo was retained. This *must* be 4.
+# Make sure that no other .xdata sections get included, which would
+# increase the size here.
+# CHECK-NEXT: VirtualSize: 0x4
+
+ .text
+ .def main;
+ .scl 2;
+ .type 32;
+ .endef
+ .globl main
+ .p2align 4, 0x90
+main:
+ call foo
+ retq
+
+# Defines .text$foo (which has a leader symbol and is referenced like
+# normally), and .xdata$foo (which lacks a leader symbol, which normally
+# would be declared associative to the symbol foo).
+# .xdata$foo should be implicitly treated as associative to foo and brought
+# in, while .xdata$bar, implicitly associative to bar, not included, and
+# .xdata$baz not included since there's no symbol baz.
+
+# GNU binutils ld doesn't do this at all, but always includes all .xdata/.pdata
+# comdat sections, even if --gc-sections is used.
+
+ .section .xdata$foo,"dr"
+ .linkonce discard
+ .p2align 3
+ .long 42
+
+ .section .xdata$bar,"dr"
+ .linkonce discard
+ .p2align 3
+ .long 43
+
+ .section .xdata$baz,"dr"
+ .linkonce discard
+ .p2align 3
+ .long 44
+
+ .def foo;
+ .scl 2;
+ .type 32;
+ .endef
+ .section .text$foo,"xr",discard,foo
+ .globl foo
+ .p2align 4
+foo:
+ ret
+
+ .def bar;
+ .scl 2;
+ .type 32;
+ .endef
+ .section .text$bar,"xr",discard,bar
+ .globl bar
+ .p2align 4
+bar:
+ ret
OpenPOWER on IntegriCloud