summaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-02-16 20:13:02 +0000
commitb60736ec1405bb0a8dd40989f67ef4c93da068ab (patch)
tree5c43fbb7c9fc45f0f87e0e6795a86267dbd12f9d /llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
parentcfca06d7963fa0909f90483b42a6d7d194d01e08 (diff)
Diffstat (limited to 'llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp')
-rw-r--r--llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp53
1 files changed, 41 insertions, 12 deletions
diff --git a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
index 914308d9147e..1e3f33e70715 100644
--- a/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/WinCFGuard.cpp
@@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
//
// This file contains support for writing the metadata for Windows Control Flow
-// Guard, including address-taken functions, and valid longjmp targets.
+// Guard, including address-taken functions and valid longjmp targets.
//
//===----------------------------------------------------------------------===//
@@ -17,8 +17,8 @@
#include "llvm/CodeGen/MachineModuleInfo.h"
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/IR/Constants.h"
-#include "llvm/IR/Metadata.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Metadata.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCObjectFileInfo.h"
#include "llvm/MC/MCStreamer.h"
@@ -38,8 +38,7 @@ void WinCFGuard::endFunction(const MachineFunction *MF) {
return;
// Copy the function's longjmp targets to a module-level list.
- LongjmpTargets.insert(LongjmpTargets.end(), MF->getLongjmpTargets().begin(),
- MF->getLongjmpTargets().end());
+ llvm::append_range(LongjmpTargets, MF->getLongjmpTargets());
}
/// Returns true if this function's address is escaped in a way that might make
@@ -78,20 +77,50 @@ static bool isPossibleIndirectCallTarget(const Function *F) {
return false;
}
+MCSymbol *WinCFGuard::lookupImpSymbol(const MCSymbol *Sym) {
+ if (Sym->getName().startswith("__imp_"))
+ return nullptr;
+ return Asm->OutContext.lookupSymbol(Twine("__imp_") + Sym->getName());
+}
+
void WinCFGuard::endModule() {
const Module *M = Asm->MMI->getModule();
- std::vector<const Function *> Functions;
- for (const Function &F : *M)
- if (isPossibleIndirectCallTarget(&F))
- Functions.push_back(&F);
- if (Functions.empty() && LongjmpTargets.empty())
+ std::vector<const MCSymbol *> GFIDsEntries;
+ std::vector<const MCSymbol *> GIATsEntries;
+ for (const Function &F : *M) {
+ if (isPossibleIndirectCallTarget(&F)) {
+ // If F is a dllimport and has an "__imp_" symbol already defined, add the
+ // "__imp_" symbol to the .giats section.
+ if (F.hasDLLImportStorageClass()) {
+ if (MCSymbol *impSym = lookupImpSymbol(Asm->getSymbol(&F))) {
+ GIATsEntries.push_back(impSym);
+ }
+ }
+ // Add the function's symbol to the .gfids section.
+ // Note: For dllimport functions, MSVC sometimes does not add this symbol
+ // to the .gfids section, but only adds the corresponding "__imp_" symbol
+ // to the .giats section. Here we always add the symbol to the .gfids
+ // section, since this does not introduce security risks.
+ GFIDsEntries.push_back(Asm->getSymbol(&F));
+ }
+ }
+
+ if (GFIDsEntries.empty() && GIATsEntries.empty() && LongjmpTargets.empty())
return;
+
+ // Emit the symbol index of each GFIDs entry to form the .gfids section.
auto &OS = *Asm->OutStreamer;
OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGFIDsSection());
- for (const Function *F : Functions)
- OS.EmitCOFFSymbolIndex(Asm->getSymbol(F));
+ for (const MCSymbol *S : GFIDsEntries)
+ OS.EmitCOFFSymbolIndex(S);
+
+ // Emit the symbol index of each GIATs entry to form the .giats section.
+ OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGIATsSection());
+ for (const MCSymbol *S : GIATsEntries) {
+ OS.EmitCOFFSymbolIndex(S);
+ }
- // Emit the symbol index of each longjmp target.
+ // Emit the symbol index of each longjmp target to form the .gljmp section.
OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGLJMPSection());
for (const MCSymbol *S : LongjmpTargets) {
OS.EmitCOFFSymbolIndex(S);