/Gs Use stack probes (default)
/Gs<value> Set stack probe size (default 4096)
/guard:<value> Enable Control Flow Guard with /guard:cf,
- or only the table with /guard:cf,nochecks
+ or only the table with /guard:cf,nochecks.
+ Enable EH Continuation Guard with /guard:ehcont
/Gv Set __vectorcall as a default calling convention
/Gw- Don't put each data item in its own section
/Gw Put each data item in its own section
CODEGENOPT(IgnoreXCOFFVisibility , 1, 0) ///< -mignore-xcoff-visibility
CODEGENOPT(ControlFlowGuardNoChecks , 1, 0) ///< -cfguard-no-checks
CODEGENOPT(ControlFlowGuard , 1, 0) ///< -cfguard
+CODEGENOPT(EHContGuard , 1, 0) ///< -ehcontguard
CODEGENOPT(CXAAtExit , 1, 1) ///< Use __cxa_atexit for calling destructors.
CODEGENOPT(RegisterGlobalDtorsWithAtExit, 1, 1) ///< Use atexit or __cxa_atexit to register global destructors.
CODEGENOPT(CXXCtorDtorAliases, 1, 0) ///< Emit complete ctors/dtors as linker
def cfguard : Flag<["-"], "cfguard">,
HelpText<"Emit Windows Control Flow Guard tables and checks">,
MarshallingInfoFlag<CodeGenOpts<"ControlFlowGuard">>;
+def ehcontguard : Flag<["-"], "ehcontguard">,
+ HelpText<"Emit Windows EH Continuation Guard tables">,
+ MarshallingInfoFlag<CodeGenOpts<"EHContGuard">>;
def fdenormal_fp_math_f32_EQ : Joined<["-"], "fdenormal-fp-math-f32=">,
Group<f_Group>;
HelpText<"Set output object file (with /c)">,
MetaVarName<"<file or dir/>">;
def _SLASH_guard : CLJoined<"guard:">,
- HelpText<"Enable Control Flow Guard with /guard:cf, or only the table with /guard:cf,nochecks">;
+ HelpText<"Enable Control Flow Guard with /guard:cf, or only the table with /guard:cf,nochecks. "
+ "Enable EH Continuation Guard with /guard:ehcont">;
def _SLASH_GX : CLFlag<"GX">,
HelpText<"Deprecated; use /EHsc">;
def _SLASH_GX_ : CLFlag<"GX-">,
// Function ID tables for Control Flow Guard (cfguard=1).
getModule().addModuleFlag(llvm::Module::Warning, "cfguard", 1);
}
+ if (CodeGenOpts.EHContGuard) {
+ // Function ID tables for EH Continuation Guard.
+ getModule().addModuleFlag(llvm::Module::Warning, "ehcontguard", 1);
+ }
if (CodeGenOpts.OptimizationLevel > 0 && CodeGenOpts.StrictVTablePointers) {
// We don't support LTO with 2 with different StrictVTablePointers
// FIXME: we could support it by stripping all the information introduced
if (Arg *A = Args.getLastArg(options::OPT__SLASH_guard)) {
StringRef GuardArgs = A->getValue();
- // The only valid options are "cf", "cf,nochecks", and "cf-".
+ // The only valid options are "cf", "cf,nochecks", "cf-", "ehcont" and
+ // "ehcont-".
if (GuardArgs.equals_lower("cf")) {
// Emit CFG instrumentation and the table of address-taken functions.
CmdArgs.push_back("-cfguard");
} else if (GuardArgs.equals_lower("cf,nochecks")) {
// Emit only the table of address-taken functions.
CmdArgs.push_back("-cfguard-no-checks");
- } else if (GuardArgs.equals_lower("cf-")) {
+ } else if (GuardArgs.equals_lower("ehcont")) {
+ // Emit EH continuation table.
+ CmdArgs.push_back("-ehcontguard");
+ } else if (GuardArgs.equals_lower("cf-") ||
+ GuardArgs.equals_lower("ehcont-")) {
// Do nothing, but we might want to emit a security warning in future.
} else {
D.Diag(diag::err_drv_invalid_value) << A->getSpelling() << GuardArgs;
CmdArgs.push_back("-guard:cf");
} else if (GuardArgs.equals_lower("cf-")) {
CmdArgs.push_back("-guard:cf-");
+ } else if (GuardArgs.equals_lower("ehcont")) {
+ CmdArgs.push_back("-guard:ehcont");
+ } else if (GuardArgs.equals_lower("ehcont-")) {
+ CmdArgs.push_back("-guard:ehcont-");
}
}
-// RUN: %clang_cc1 -cfguard-no-checks -emit-llvm %s -o - | FileCheck %s -check-prefix=CFGUARDNOCHECKS\r
-// RUN: %clang_cc1 -cfguard -emit-llvm %s -o - | FileCheck %s -check-prefix=CFGUARD\r
-\r
-void f() {}\r
-\r
-// Check that the cfguard metadata flag gets correctly set on the module.\r
-// CFGUARDNOCHECKS: !"cfguard", i32 1}\r
-// CFGUARD: !"cfguard", i32 2}\r
+// RUN: %clang_cc1 -cfguard-no-checks -emit-llvm %s -o - | FileCheck %s -check-prefix=CFGUARDNOCHECKS
+// RUN: %clang_cc1 -cfguard -emit-llvm %s -o - | FileCheck %s -check-prefix=CFGUARD
+// RUN: %clang_cc1 -ehcontguard -emit-llvm %s -o - | FileCheck %s -check-prefix=EHCONTGUARD
+
+void f() {}
+
+// Check that the cfguard metadata flag gets correctly set on the module.
+// CFGUARDNOCHECKS: !"cfguard", i32 1}
+// CFGUARD: !"cfguard", i32 2}
+// EHCONTGUARD: !"ehcontguard", i32 1}
// RUN: %clang_cl /guard:nochecks -### -- %s 2>&1 | FileCheck -check-prefix=CFGUARDNOCHECKSINVALID %s
// CFGUARDNOCHECKSINVALID: invalid value 'nochecks' in '/guard:'
+// RUN: %clang_cl -### -- %s 2>&1 | FileCheck -check-prefix=NOEHCONTGUARD %s
+// RUN: %clang_cl /guard:ehcont- -### -- %s 2>&1 | FileCheck -check-prefix=NOEHCONTGUARD %s
+// NOEHCONTGUARD-NOT: -ehcontguard
+
+// RUN: %clang_cl /guard:ehcont -### -- %s 2>&1 | FileCheck -check-prefix=EHCONTGUARD %s
+// EHCONTGUARD: -ehcontguard
+
// RUN: %clang_cl /guard:foo -### -- %s 2>&1 | FileCheck -check-prefix=CFGUARDINVALID %s
// CFGUARDINVALID: invalid value 'foo' in '/guard:'
Makes programs 10x faster by doing Special New Thing.
+* Windows Control-flow Enforcement Technology: the ``-ehcontguard`` option now
+ emits valid unwind entrypoints which are validated when the context is being
+ set during exception handling.
Changes to the LLVM IR
----------------------