@@ -227,6 +227,9 @@ class Writer {
227
227
void markSymbolsForRVATable (ObjFile *file,
228
228
ArrayRef<SectionChunk *> symIdxChunks,
229
229
SymbolRVASet &tableSymbols);
230
+ void getSymbolsFromSections (ObjFile *file,
231
+ ArrayRef<SectionChunk *> symIdxChunks,
232
+ std::vector<Symbol *> &symbols);
230
233
void maybeAddRVATable (SymbolRVASet tableSymbols, StringRef tableSym,
231
234
StringRef countSym);
232
235
void setSectionPermissions ();
@@ -605,8 +608,9 @@ void Writer::run() {
605
608
606
609
createImportTables ();
607
610
createSections ();
608
- createMiscChunks ();
609
611
appendImportThunks ();
612
+ // Import thunks must be added before the Control Flow Guard tables are added.
613
+ createMiscChunks ();
610
614
createExportTable ();
611
615
mergeSections ();
612
616
removeUnusedSections ();
@@ -1618,6 +1622,8 @@ static void markSymbolsWithRelocations(ObjFile *file,
1618
1622
// table.
1619
1623
void Writer::createGuardCFTables () {
1620
1624
SymbolRVASet addressTakenSyms;
1625
+ SymbolRVASet giatsRVASet;
1626
+ std::vector<Symbol *> giatsSymbols;
1621
1627
SymbolRVASet longJmpTargets;
1622
1628
for (ObjFile *file : ObjFile::instances) {
1623
1629
// If the object was compiled with /guard:cf, the address taken symbols
@@ -1627,6 +1633,8 @@ void Writer::createGuardCFTables() {
1627
1633
// possibly address-taken.
1628
1634
if (file->hasGuardCF ()) {
1629
1635
markSymbolsForRVATable (file, file->getGuardFidChunks (), addressTakenSyms);
1636
+ markSymbolsForRVATable (file, file->getGuardIATChunks (), giatsRVASet);
1637
+ getSymbolsFromSections (file, file->getGuardIATChunks (), giatsSymbols);
1630
1638
markSymbolsForRVATable (file, file->getGuardLJmpChunks (), longJmpTargets);
1631
1639
} else {
1632
1640
markSymbolsWithRelocations (file, addressTakenSyms);
@@ -1641,6 +1649,16 @@ void Writer::createGuardCFTables() {
1641
1649
for (Export &e : config->exports )
1642
1650
maybeAddAddressTakenFunction (addressTakenSyms, e.sym );
1643
1651
1652
+ // For each entry in the .giats table, check if it has a corresponding load
1653
+ // thunk (e.g. because the DLL that defines it will be delay-loaded) and, if
1654
+ // so, add the load thunk to the address taken (.gfids) table.
1655
+ for (Symbol *s : giatsSymbols) {
1656
+ if (auto *di = dyn_cast<DefinedImportData>(s)) {
1657
+ if (di->loadThunkSym )
1658
+ addSymbolToRVASet (addressTakenSyms, di->loadThunkSym );
1659
+ }
1660
+ }
1661
+
1644
1662
// Ensure sections referenced in the gfid table are 16-byte aligned.
1645
1663
for (const ChunkAndOffset &c : addressTakenSyms)
1646
1664
if (c.inputChunk ->getAlignment () < 16 )
@@ -1649,6 +1667,10 @@ void Writer::createGuardCFTables() {
1649
1667
maybeAddRVATable (std::move (addressTakenSyms), " __guard_fids_table" ,
1650
1668
" __guard_fids_count" );
1651
1669
1670
+ // Add the Guard Address Taken IAT Entry Table (.giats).
1671
+ maybeAddRVATable (std::move (giatsRVASet), " __guard_iat_table" ,
1672
+ " __guard_iat_count" );
1673
+
1652
1674
// Add the longjmp target table unless the user told us not to.
1653
1675
if (config->guardCF == GuardCFLevel::Full)
1654
1676
maybeAddRVATable (std::move (longJmpTargets), " __guard_longjmp_table" ,
@@ -1665,11 +1687,11 @@ void Writer::createGuardCFTables() {
1665
1687
}
1666
1688
1667
1689
// Take a list of input sections containing symbol table indices and add those
1668
- // symbols to an RVA table . The challenge is that symbol RVAs are not known and
1690
+ // symbols to a vector . The challenge is that symbol RVAs are not known and
1669
1691
// depend on the table size, so we can't directly build a set of integers.
1670
- void Writer::markSymbolsForRVATable (ObjFile *file,
1692
+ void Writer::getSymbolsFromSections (ObjFile *file,
1671
1693
ArrayRef<SectionChunk *> symIdxChunks,
1672
- SymbolRVASet &tableSymbols ) {
1694
+ std::vector<Symbol *> &symbols ) {
1673
1695
for (SectionChunk *c : symIdxChunks) {
1674
1696
// Skip sections discarded by linker GC. This comes up when a .gfids section
1675
1697
// is associated with something like a vtable and the vtable is discarded.
@@ -1687,7 +1709,7 @@ void Writer::markSymbolsForRVATable(ObjFile *file,
1687
1709
}
1688
1710
1689
1711
// Read each symbol table index and check if that symbol was included in the
1690
- // final link. If so, add it to the table symbol set .
1712
+ // final link. If so, add it to the vector of symbols .
1691
1713
ArrayRef<ulittle32_t > symIndices (
1692
1714
reinterpret_cast <const ulittle32_t *>(data.data ()), data.size () / 4 );
1693
1715
ArrayRef<Symbol *> objSymbols = file->getSymbols ();
@@ -1699,12 +1721,24 @@ void Writer::markSymbolsForRVATable(ObjFile *file,
1699
1721
}
1700
1722
if (Symbol *s = objSymbols[symIndex]) {
1701
1723
if (s->isLive ())
1702
- addSymbolToRVASet (tableSymbols, cast<Defined >(s));
1724
+ symbols. push_back ( cast<Symbol >(s));
1703
1725
}
1704
1726
}
1705
1727
}
1706
1728
}
1707
1729
1730
+ // Take a list of input sections containing symbol table indices and add those
1731
+ // symbols to an RVA table.
1732
+ void Writer::markSymbolsForRVATable (ObjFile *file,
1733
+ ArrayRef<SectionChunk *> symIdxChunks,
1734
+ SymbolRVASet &tableSymbols) {
1735
+ std::vector<Symbol *> syms;
1736
+ getSymbolsFromSections (file, symIdxChunks, syms);
1737
+
1738
+ for (Symbol *s : syms)
1739
+ addSymbolToRVASet (tableSymbols, cast<Defined>(s));
1740
+ }
1741
+
1708
1742
// Replace the absolute table symbol with a synthetic symbol pointing to
1709
1743
// tableChunk so that we can emit base relocations for it and resolve section
1710
1744
// relative relocations.
0 commit comments