summaryrefslogtreecommitdiffstats
path: root/lld/COFF/Writer.cpp
diff options
context:
space:
mode:
authorReid Kleckner <rnk@google.com>2018-11-27 01:50:17 +0000
committerReid Kleckner <rnk@google.com>2018-11-27 01:50:17 +0000
commita37d672da9978af59d1279cdec794f39f0d26d71 (patch)
treecc2543459174d07fd8f08ca9eb4b5c75b37032ea /lld/COFF/Writer.cpp
parent265cd31fbffb8c9812c3d3e3a95167155724bc92 (diff)
downloadbcm5719-llvm-a37d672da9978af59d1279cdec794f39f0d26d71.tar.gz
bcm5719-llvm-a37d672da9978af59d1279cdec794f39f0d26d71.zip
[COFF] Add exported functions to gfids table for /guard:cf
Summary: MSVC does this, and we should to. The .gfids table is a table of RVAs, so it's impossible for a DLL to indicate that an imported symbol is address taken. Therefore, exports appear to be listed as address taken by the DLL that exports them. This fixes an issue that Firefox ran into here: https://bugzilla.mozilla.org/show_bug.cgi?id=1485016#c12 In Firefox, the export directive came from a .def file, but we need to do this for any kind of export. Reviewers: dmajor, hans, amccarth, alex Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D54723 llvm-svn: 347623
Diffstat (limited to 'lld/COFF/Writer.cpp')
-rw-r--r--lld/COFF/Writer.cpp37
1 files changed, 25 insertions, 12 deletions
diff --git a/lld/COFF/Writer.cpp b/lld/COFF/Writer.cpp
index deb43768ddc..e5796d9bbd2 100644
--- a/lld/COFF/Writer.cpp
+++ b/lld/COFF/Writer.cpp
@@ -1304,6 +1304,25 @@ static void addSymbolToRVASet(SymbolRVASet &RVASet, Defined *S) {
RVASet.insert({C, Off});
}
+// Given a symbol, add it to the GFIDs table if it is a live, defined, function
+// symbol in an executable section.
+static void maybeAddAddressTakenFunction(SymbolRVASet &AddressTakenSyms,
+ Symbol *S) {
+ auto *D = dyn_cast_or_null<DefinedCOFF>(S);
+
+ // Ignore undefined symbols and references to non-functions (e.g. globals and
+ // labels).
+ if (!D ||
+ D->getCOFFSymbol().getComplexType() != COFF::IMAGE_SYM_DTYPE_FUNCTION)
+ return;
+
+ // Mark the symbol as address taken if it's in an executable section.
+ Chunk *RefChunk = D->getChunk();
+ OutputSection *OS = RefChunk ? RefChunk->getOutputSection() : nullptr;
+ if (OS && OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE)
+ addSymbolToRVASet(AddressTakenSyms, D);
+}
+
// Visit all relocations from all section contributions of this object file and
// mark the relocation target as address-taken.
static void markSymbolsWithRelocations(ObjFile *File,
@@ -1322,17 +1341,7 @@ static void markSymbolsWithRelocations(ObjFile *File,
continue;
Symbol *Ref = SC->File->getSymbol(Reloc.SymbolTableIndex);
- if (auto *D = dyn_cast_or_null<DefinedCOFF>(Ref)) {
- if (D->getCOFFSymbol().getComplexType() != COFF::IMAGE_SYM_DTYPE_FUNCTION)
- // Ignore relocations against non-functions (e.g. labels).
- continue;
-
- // Mark the symbol if it's in an executable section.
- Chunk *RefChunk = D->getChunk();
- OutputSection *OS = RefChunk ? RefChunk->getOutputSection() : nullptr;
- if (OS && OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE)
- addSymbolToRVASet(UsedSymbols, D);
- }
+ maybeAddAddressTakenFunction(UsedSymbols, Ref);
}
}
}
@@ -1359,7 +1368,11 @@ void Writer::createGuardCFTables() {
// Mark the image entry as address-taken.
if (Config->Entry)
- addSymbolToRVASet(AddressTakenSyms, cast<Defined>(Config->Entry));
+ maybeAddAddressTakenFunction(AddressTakenSyms, Config->Entry);
+
+ // Mark exported symbols in executable sections as address-taken.
+ for (Export &E : Config->Exports)
+ maybeAddAddressTakenFunction(AddressTakenSyms, E.Sym);
// Ensure sections referenced in the gfid table are 16-byte aligned.
for (const ChunkAndOffset &C : AddressTakenSyms)
OpenPOWER on IntegriCloud