LLVM  14.0.0git
WinCFGuard.cpp
Go to the documentation of this file.
1 //===-- CodeGen/AsmPrinter/WinCFGuard.cpp - Control Flow Guard Impl ------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file contains support for writing the metadata for Windows Control Flow
10 // Guard, including address-taken functions and valid longjmp targets.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "WinCFGuard.h"
19 #include "llvm/IR/Constants.h"
20 #include "llvm/IR/Instructions.h"
21 #include "llvm/IR/Metadata.h"
22 #include "llvm/MC/MCAsmInfo.h"
24 #include "llvm/MC/MCStreamer.h"
25 
26 #include <vector>
27 
28 using namespace llvm;
29 
31 
33 
35 
36  // Skip functions without any longjmp targets.
37  if (MF->getLongjmpTargets().empty())
38  return;
39 
40  // Copy the function's longjmp targets to a module-level list.
41  llvm::append_range(LongjmpTargets, MF->getLongjmpTargets());
42 }
43 
44 /// Returns true if this function's address is escaped in a way that might make
45 /// it an indirect call target. Function::hasAddressTaken gives different
46 /// results when a function is called directly with a function prototype
47 /// mismatch, which requires a cast.
50  while (!Users.empty()) {
51  const Value *FnOrCast = Users.pop_back_val();
52  for (const Use &U : FnOrCast->uses()) {
53  const User *FnUser = U.getUser();
54  if (isa<BlockAddress>(FnUser))
55  continue;
56  if (const auto *Call = dyn_cast<CallBase>(FnUser)) {
57  if (!Call->isCallee(&U))
58  return true;
59  } else if (isa<Instruction>(FnUser)) {
60  // Consider any other instruction to be an escape. This has some weird
61  // consequences like no-op intrinsics being an escape or a store *to* a
62  // function address being an escape.
63  return true;
64  } else if (const auto *C = dyn_cast<Constant>(FnUser)) {
65  // If this is a constant pointer cast of the function, don't consider
66  // this escape. Analyze the uses of the cast as well. This ensures that
67  // direct calls with mismatched prototypes don't end up in the CFG
68  // table. Consider other constants, such as vtable initializers, to
69  // escape the function.
70  if (C->stripPointerCasts() == F)
71  Users.push_back(FnUser);
72  else
73  return true;
74  }
75  }
76  }
77  return false;
78 }
79 
80 MCSymbol *WinCFGuard::lookupImpSymbol(const MCSymbol *Sym) {
81  if (Sym->getName().startswith("__imp_"))
82  return nullptr;
83  return Asm->OutContext.lookupSymbol(Twine("__imp_") + Sym->getName());
84 }
85 
87  const Module *M = Asm->MMI->getModule();
88  std::vector<const MCSymbol *> GFIDsEntries;
89  std::vector<const MCSymbol *> GIATsEntries;
90  for (const Function &F : *M) {
92  // If F is a dllimport and has an "__imp_" symbol already defined, add the
93  // "__imp_" symbol to the .giats section.
94  if (F.hasDLLImportStorageClass()) {
95  if (MCSymbol *impSym = lookupImpSymbol(Asm->getSymbol(&F))) {
96  GIATsEntries.push_back(impSym);
97  }
98  }
99  // Add the function's symbol to the .gfids section.
100  // Note: For dllimport functions, MSVC sometimes does not add this symbol
101  // to the .gfids section, but only adds the corresponding "__imp_" symbol
102  // to the .giats section. Here we always add the symbol to the .gfids
103  // section, since this does not introduce security risks.
104  GFIDsEntries.push_back(Asm->getSymbol(&F));
105  }
106  }
107 
108  if (GFIDsEntries.empty() && GIATsEntries.empty() && LongjmpTargets.empty())
109  return;
110 
111  // Emit the symbol index of each GFIDs entry to form the .gfids section.
112  auto &OS = *Asm->OutStreamer;
113  OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGFIDsSection());
114  for (const MCSymbol *S : GFIDsEntries)
115  OS.EmitCOFFSymbolIndex(S);
116 
117  // Emit the symbol index of each GIATs entry to form the .giats section.
118  OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGIATsSection());
119  for (const MCSymbol *S : GIATsEntries) {
120  OS.EmitCOFFSymbolIndex(S);
121  }
122 
123  // Emit the symbol index of each longjmp target to form the .gljmp section.
124  OS.SwitchSection(Asm->OutContext.getObjectFileInfo()->getGLJMPSection());
125  for (const MCSymbol *S : LongjmpTargets) {
126  OS.EmitCOFFSymbolIndex(S);
127  }
128 }
AsmPrinter.h
llvm::MCContext::getObjectFileInfo
const MCObjectFileInfo * getObjectFileInfo() const
Definition: MCContext.h:427
llvm::StringRef::startswith
LLVM_NODISCARD bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:286
llvm
---------------------— PointerInfo ------------------------------------—
Definition: AllocatorList.h:23
llvm::MCSymbol
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
Definition: MCSymbol.h:41
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
Metadata.h
llvm::Function
Definition: Function.h:61
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
llvm::WinCFGuard::WinCFGuard
WinCFGuard(AsmPrinter *A)
Definition: WinCFGuard.cpp:30
MCObjectFileInfo.h
llvm::MCContext::lookupSymbol
MCSymbol * lookupSymbol(const Twine &Name) const
Get the symbol for Name, or null.
Definition: MCContext.cpp:344
llvm::MCObjectFileInfo::getGFIDsSection
MCSection * getGFIDsSection() const
Definition: MCObjectFileInfo.h:415
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::WinCFGuard::endFunction
void endFunction(const MachineFunction *MF) override
Gather post-function debug information.
Definition: WinCFGuard.cpp:34
Constants.h
llvm::User
Definition: User.h:44
llvm::MCObjectFileInfo::getGLJMPSection
MCSection * getGLJMPSection() const
Definition: MCObjectFileInfo.h:417
llvm::AsmPrinter::OutStreamer
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:97
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
llvm::Value::uses
iterator_range< use_iterator > uses()
Definition: Value.h:377
llvm::WinCFGuard::~WinCFGuard
~WinCFGuard() override
Definition: WinCFGuard.cpp:32
llvm::MCSymbol::getName
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:198
llvm::MCObjectFileInfo::getGIATsSection
MCSection * getGIATsSection() const
Definition: MCObjectFileInfo.h:416
llvm::AsmPrinter::getSymbol
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:486
llvm::AsmPrinter::OutContext
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:92
MachineModuleInfo.h
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::MachineFunction
Definition: MachineFunction.h:230
MCAsmInfo.h
llvm::append_range
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Definition: STLExtras.h:1744
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
WinCFGuard.h
llvm::AsmPrinter::MMI
MachineModuleInfo * MMI
This is a pointer to the current MachineModuleInfo.
Definition: AsmPrinter.h:103
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:83
llvm::WinCFGuard::endModule
void endModule() override
Emit the Control Flow Guard function ID table.
Definition: WinCFGuard.cpp:86
llvm::AsmPrinter
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:82
llvm::AsmPrinterHandler
Collects and handles AsmPrinter objects required to build debug or EH information.
Definition: AsmPrinterHandler.h:33
Instructions.h
MCStreamer.h
Users
iv Induction Variable Users
Definition: IVUsers.cpp:52
MachineOperand.h
isPossibleIndirectCallTarget
static bool isPossibleIndirectCallTarget(const Function *F)
Returns true if this function's address is escaped in a way that might make it an indirect call targe...
Definition: WinCFGuard.cpp:48
llvm::HexStyle::Asm
@ Asm
0ffh
Definition: MCInstPrinter.h:34
MachineFunction.h
llvm::MachineModuleInfo::getModule
const Module * getModule() const
Definition: MachineModuleInfo.h:174
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::Use
A Use represents the edge between a Value definition and its users.
Definition: Use.h:44
llvm::MachineFunction::getLongjmpTargets
const std::vector< MCSymbol * > & getLongjmpTargets() const
Returns a reference to a list of symbols immediately following calls to _setjmp in the function.
Definition: MachineFunction.h:1015