LLVM  16.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"
18 #include "llvm/IR/Constants.h"
19 #include "llvm/IR/InstrTypes.h"
21 #include "llvm/MC/MCStreamer.h"
22 
23 #include <vector>
24 
25 using namespace llvm;
26 
28 
29 WinCFGuard::~WinCFGuard() = default;
30 
32 
33  // Skip functions without any longjmp targets.
34  if (MF->getLongjmpTargets().empty())
35  return;
36 
37  // Copy the function's longjmp targets to a module-level list.
38  llvm::append_range(LongjmpTargets, MF->getLongjmpTargets());
39 }
40 
41 /// Returns true if this function's address is escaped in a way that might make
42 /// it an indirect call target. Function::hasAddressTaken gives different
43 /// results when a function is called directly with a function prototype
44 /// mismatch, which requires a cast.
47  while (!Users.empty()) {
48  const Value *FnOrCast = Users.pop_back_val();
49  for (const Use &U : FnOrCast->uses()) {
50  const User *FnUser = U.getUser();
51  if (isa<BlockAddress>(FnUser))
52  continue;
53  if (const auto *Call = dyn_cast<CallBase>(FnUser)) {
54  if (!Call->isCallee(&U))
55  return true;
56  } else if (isa<Instruction>(FnUser)) {
57  // Consider any other instruction to be an escape. This has some weird
58  // consequences like no-op intrinsics being an escape or a store *to* a
59  // function address being an escape.
60  return true;
61  } else if (const auto *C = dyn_cast<Constant>(FnUser)) {
62  // If this is a constant pointer cast of the function, don't consider
63  // this escape. Analyze the uses of the cast as well. This ensures that
64  // direct calls with mismatched prototypes don't end up in the CFG
65  // table. Consider other constants, such as vtable initializers, to
66  // escape the function.
67  if (C->stripPointerCasts() == F)
68  Users.push_back(FnUser);
69  else
70  return true;
71  }
72  }
73  }
74  return false;
75 }
76 
77 MCSymbol *WinCFGuard::lookupImpSymbol(const MCSymbol *Sym) {
78  if (Sym->getName().startswith("__imp_"))
79  return nullptr;
80  return Asm->OutContext.lookupSymbol(Twine("__imp_") + Sym->getName());
81 }
82 
84  const Module *M = Asm->MMI->getModule();
85  std::vector<const MCSymbol *> GFIDsEntries;
86  std::vector<const MCSymbol *> GIATsEntries;
87  for (const Function &F : *M) {
89  // If F is a dllimport and has an "__imp_" symbol already defined, add the
90  // "__imp_" symbol to the .giats section.
91  if (F.hasDLLImportStorageClass()) {
92  if (MCSymbol *impSym = lookupImpSymbol(Asm->getSymbol(&F))) {
93  GIATsEntries.push_back(impSym);
94  }
95  }
96  // Add the function's symbol to the .gfids section.
97  // Note: For dllimport functions, MSVC sometimes does not add this symbol
98  // to the .gfids section, but only adds the corresponding "__imp_" symbol
99  // to the .giats section. Here we always add the symbol to the .gfids
100  // section, since this does not introduce security risks.
101  GFIDsEntries.push_back(Asm->getSymbol(&F));
102  }
103  }
104 
105  if (GFIDsEntries.empty() && GIATsEntries.empty() && LongjmpTargets.empty())
106  return;
107 
108  // Emit the symbol index of each GFIDs entry to form the .gfids section.
109  auto &OS = *Asm->OutStreamer;
110  OS.switchSection(Asm->OutContext.getObjectFileInfo()->getGFIDsSection());
111  for (const MCSymbol *S : GFIDsEntries)
112  OS.emitCOFFSymbolIndex(S);
113 
114  // Emit the symbol index of each GIATs entry to form the .giats section.
115  OS.switchSection(Asm->OutContext.getObjectFileInfo()->getGIATsSection());
116  for (const MCSymbol *S : GIATsEntries) {
117  OS.emitCOFFSymbolIndex(S);
118  }
119 
120  // Emit the symbol index of each longjmp target to form the .gljmp section.
121  OS.switchSection(Asm->OutContext.getObjectFileInfo()->getGLJMPSection());
122  for (const MCSymbol *S : LongjmpTargets) {
123  OS.emitCOFFSymbolIndex(S);
124  }
125 }
AsmPrinter.h
llvm::MCContext::getObjectFileInfo
const MCObjectFileInfo * getObjectFileInfo() const
Definition: MCContext.h:451
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
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
llvm::Function
Definition: Function.h:60
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
llvm::WinCFGuard::WinCFGuard
WinCFGuard(AsmPrinter *A)
Definition: WinCFGuard.cpp:27
MCObjectFileInfo.h
llvm::MCContext::lookupSymbol
MCSymbol * lookupSymbol(const Twine &Name) const
Get the symbol for Name, or null.
Definition: MCContext.cpp:359
llvm::MCObjectFileInfo::getGFIDsSection
MCSection * getGFIDsSection() const
Definition: MCObjectFileInfo.h:427
F
#define F(x, y, z)
Definition: MD5.cpp:55
llvm::WinCFGuard::endFunction
void endFunction(const MachineFunction *MF) override
Gather post-function debug information.
Definition: WinCFGuard.cpp:31
llvm::StringRef::startswith
bool startswith(StringRef Prefix) const
Definition: StringRef.h:260
Constants.h
llvm::User
Definition: User.h:44
llvm::MCObjectFileInfo::getGLJMPSection
MCSection * getGLJMPSection() const
Definition: MCObjectFileInfo.h:429
llvm::AsmPrinter::OutStreamer
std::unique_ptr< MCStreamer > OutStreamer
This is the MCStreamer object for the file we are generating.
Definition: AsmPrinter.h:99
C
(vector float) vec_cmpeq(*A, *B) C
Definition: README_ALTIVEC.txt:86
InstrTypes.h
llvm::Value::uses
iterator_range< use_iterator > uses()
Definition: Value.h:376
llvm::WinCFGuard::~WinCFGuard
~WinCFGuard() override
llvm::MCSymbol::getName
StringRef getName() const
getName - Get the symbol name.
Definition: MCSymbol.h:198
llvm::MCObjectFileInfo::getGIATsSection
MCSection * getGIATsSection() const
Definition: MCObjectFileInfo.h:428
llvm::AsmPrinter::getSymbol
MCSymbol * getSymbol(const GlobalValue *GV) const
Definition: AsmPrinter.cpp:656
llvm::AsmPrinter::OutContext
MCContext & OutContext
This is the context for the output file that we are streaming.
Definition: AsmPrinter.h:94
MachineModuleInfo.h
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:65
llvm::MachineFunction
Definition: MachineFunction.h:257
llvm::append_range
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Definition: STLExtras.h:1988
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:105
llvm::Twine
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:81
llvm::WinCFGuard::endModule
void endModule() override
Emit the Control Flow Guard function ID table.
Definition: WinCFGuard.cpp:83
llvm::AsmPrinter
This class is intended to be used as a driving class for all asm writers.
Definition: AsmPrinter.h:84
MCStreamer.h
Users
iv Induction Variable Users
Definition: IVUsers.cpp:48
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:45
llvm::HexStyle::Asm
@ Asm
0ffh
Definition: MCInstPrinter.h:34
MachineFunction.h
llvm::MachineModuleInfo::getModule
const Module * getModule() const
Definition: MachineModuleInfo.h:150
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::Use
A Use represents the edge between a Value definition and its users.
Definition: Use.h:43
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:1065