https://github.com/ahatanak created https://github.com/llvm/llvm-project/pull/78763
The option allows users to enable libc++ hardening, which was discussed in the following RFC: https://discourse.llvm.org/t/rfc-hardening-in-libc/73925 Users specifiy the hardening mode by passing one of the following values as the argument to the option: none, fast, extensive, or debug. When the option is used, clang defines a macro for each of the hardening modes (_LIBCPP_HARDENING_MODE_{NONE,FAST,EXTENSIVE,DEBUG}) and sets macro _LIBCPP_HARDENING_MODE_ based on the hardening mode the user chose. It's an error to use the option if the stdlib used isn't libc++ or clang isn't compiling in C++ mode. >From 0d68286bd8b7206c5045062f65ccaf1c3fb54714 Mon Sep 17 00:00:00 2001 From: Akira Hatanaka <ahata...@gmail.com> Date: Thu, 18 Jan 2024 16:20:41 -0800 Subject: [PATCH] Add option -fstdlib-hardening= The option allows users to enable libc++ hardening, which was discussed in the following RFC: https://discourse.llvm.org/t/rfc-hardening-in-libc/73925 Users specifiy the hardening mode by passing one of the following values as the argument to the option: none, fast, extensive, or debug. When the option is used, clang defines a macro for each of the hardening modes (_LIBCPP_HARDENING_MODE_{NONE,FAST,EXTENSIVE,DEBUG}) and sets macro _LIBCPP_HARDENING_MODE_ based on the hardening mode the user chose. It's an error to use the option if the stdlib used isn't libc++ or clang isn't compiling in C++ mode. --- .../clang/Basic/DiagnosticDriverKinds.td | 2 ++ clang/include/clang/Basic/LangOptions.def | 1 + clang/include/clang/Basic/LangOptions.h | 8 ++++++ clang/include/clang/Driver/Options.td | 8 ++++++ clang/lib/Driver/ToolChains/Clang.cpp | 8 ++++++ clang/lib/Frontend/InitPreprocessor.cpp | 27 +++++++++++++++++++ clang/test/Driver/libcxx-hardening.cpp | 21 +++++++++++++++ 7 files changed, 75 insertions(+) create mode 100644 clang/test/Driver/libcxx-hardening.cpp diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td index 090b169a0e72408..2369ddc8a80ead3 100644 --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/clang/include/clang/Basic/DiagnosticDriverKinds.td @@ -275,6 +275,8 @@ def warn_drv_unknown_argument_clang_cl_with_suggestion : Warning< InGroup<UnknownArgument>; def err_drv_unknown_target_triple : Error<"unknown target triple '%0'">; +def err_drv_stdlib_hardening_unavailable : Error<"libc++ hardening is available only when libc++ is used">; + def warn_drv_ycyu_different_arg_clang_cl : Warning< "support for '/Yc' and '/Yu' with different filenames not implemented yet; flags ignored">, InGroup<ClangClPch>; diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 04ebffbcba69dbf..0db8ff04ad0d52d 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -281,6 +281,7 @@ LANGOPT(OffloadingNewDriver, 1, 0, "use the new driver for generating offloading LANGOPT(SYCLIsDevice , 1, 0, "Generate code for SYCL device") LANGOPT(SYCLIsHost , 1, 0, "SYCL host compilation") ENUM_LANGOPT(SYCLVersion , SYCLMajorVersion, 2, SYCL_None, "Version of the SYCL standard used") +ENUM_LANGOPT(LibcxxHardeningMode, LibcxxHardeningModeKind, 3, LIBCPP_HARDENING_MODE_NOT_SPECIFIED, "libc++ harderning mode") LANGOPT(HIPUseNewLaunchAPI, 1, 0, "Use new kernel launching API for HIP") LANGOPT(OffloadUniformBlock, 1, 0, "Assume that kernels are launched with uniform block sizes (default true for CUDA/HIP and false otherwise)") diff --git a/clang/include/clang/Basic/LangOptions.h b/clang/include/clang/Basic/LangOptions.h index 9f986fce2d44188..62e70a5cffafd61 100644 --- a/clang/include/clang/Basic/LangOptions.h +++ b/clang/include/clang/Basic/LangOptions.h @@ -174,6 +174,14 @@ class LangOptions : public LangOptionsBase { HLSL_202x = 2029, }; + enum LibcxxHardeningModeKind { + LIBCPP_HARDENING_MODE_NOT_SPECIFIED, + LIBCPP_HARDENING_MODE_NONE, + LIBCPP_HARDENING_MODE_FAST, + LIBCPP_HARDENING_MODE_EXTENSIVE, + LIBCPP_HARDENING_MODE_DEBUG + }; + /// Clang versions with different platform ABI conformance. enum class ClangABI { /// Attempt to be ABI-compatible with code generated by Clang 3.8.x diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index d2e6c3ff721c27e..7ce38f88d156441 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -7730,6 +7730,14 @@ def source_date_epoch : Separate<["-"], "source-date-epoch">, } // let Visibility = [CC1Option] +def stdlib_hardening_EQ : Joined<["-"], "fstdlib-hardening=">, + Values<"none,fast,extensive,debug">, + NormalizedValues<["LIBCPP_HARDENING_MODE_NONE", "LIBCPP_HARDENING_MODE_FAST", "LIBCPP_HARDENING_MODE_EXTENSIVE", "LIBCPP_HARDENING_MODE_DEBUG"]>, + Visibility<[ClangOption, CC1Option]>, + HelpText<"libc++ hardening mode">, + NormalizedValuesScope<"LangOptions">, + MarshallingInfoEnum<LangOpts<"LibcxxHardeningMode">, "LIBCPP_HARDENING_MODE_NOT_SPECIFIED">; + //===----------------------------------------------------------------------===// // CUDA Options //===----------------------------------------------------------------------===// diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index fead2e884030e21..560793958455ced 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1256,6 +1256,14 @@ void Clang::AddPreprocessingOptions(Compilation &C, const JobAction &JA, if (Arg *A = Args.getLastArg(options::OPT_I_)) D.Diag(diag::err_drv_I_dash_not_supported) << A->getAsString(Args); + if (Arg *A = Args.getLastArg(options::OPT_stdlib_hardening_EQ)) { + if (types::isCXX(Inputs[0].getType()) && + getToolChain().GetCXXStdlibType(Args) == ToolChain::CST_Libcxx) + A->render(Args, CmdArgs); + else + D.Diag(diag::err_drv_stdlib_hardening_unavailable); + } + // If we have a --sysroot, and don't have an explicit -isysroot flag, add an // -isysroot to the CC1 invocation. StringRef sysroot = C.getSysRoot(); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index d83128adb511ef4..fab4894dee4a219 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -851,6 +851,33 @@ static void InitializePredefinedMacros(const TargetInfo &TI, Twine(getClangFullCPPVersion()) + "\""); // Initialize language-specific preprocessor defines. + if (LangOpts.getLibcxxHardeningMode()) { + const char *LibcxxHardeningStr; + + Builder.defineMacro("_LIBCPP_HARDENING_MODE_NONE", "0"); + Builder.defineMacro("_LIBCPP_HARDENING_MODE_FAST", "1"); + Builder.defineMacro("_LIBCPP_HARDENING_MODE_EXTENSIVE", "2"); + Builder.defineMacro("_LIBCPP_HARDENING_MODE_DEBUG", "3"); + + switch (LangOpts.getLibcxxHardeningMode()) { + case clang::LangOptions::LIBCPP_HARDENING_MODE_NOT_SPECIFIED: + llvm_unreachable("Unexpected libc++ hardening mode value"); + case clang::LangOptions::LIBCPP_HARDENING_MODE_NONE: + LibcxxHardeningStr = "_LIBCPP_HARDENING_MODE_NONE"; + break; + case clang::LangOptions::LIBCPP_HARDENING_MODE_FAST: + LibcxxHardeningStr = "_LIBCPP_HARDENING_MODE_FAST"; + break; + case clang::LangOptions::LIBCPP_HARDENING_MODE_EXTENSIVE: + LibcxxHardeningStr = "_LIBCPP_HARDENING_MODE_EXTENSIVE"; + break; + case clang::LangOptions::LIBCPP_HARDENING_MODE_DEBUG: + LibcxxHardeningStr = "_LIBCPP_HARDENING_MODE_DEBUG"; + break; + } + + Builder.defineMacro("_LIBCPP_HARDENING_MODE", LibcxxHardeningStr); + } // Standard conforming mode? if (!LangOpts.GNUMode && !LangOpts.MSVCCompat) diff --git a/clang/test/Driver/libcxx-hardening.cpp b/clang/test/Driver/libcxx-hardening.cpp new file mode 100644 index 000000000000000..7400c986048de6c --- /dev/null +++ b/clang/test/Driver/libcxx-hardening.cpp @@ -0,0 +1,21 @@ +// RUN: %clang -E -dM -x c++ %s | FileCheck -check-prefix=UNSPECIFIED %s +// RUN: %clang -E -dM -x c++ -fstdlib-hardening=none -stdlib=libc++ %s | FileCheck -check-prefix=CHECK -check-prefix=NONE %s +// RUN: %clang -E -dM -x c++ -fstdlib-hardening=fast -stdlib=libc++ %s | FileCheck -check-prefix=CHECK -check-prefix=FAST %s +// RUN: %clang -E -dM -x c++ -fstdlib-hardening=extensive -stdlib=libc++ %s | FileCheck -check-prefix=CHECK -check-prefix=EXTENSIVE %s +// RUN: %clang -E -dM -x c++ -fstdlib-hardening=debug -stdlib=libc++ %s | FileCheck -check-prefix=CHECK -check-prefix=DEBUG %s +// RUN: not %clang -x c++ -fstdlib-hardening=debug -stdlib=libstdc++ %s 2>&1 | FileCheck -check-prefix=ERROR %s +// RUN: not %clang -x c -fstdlib-hardening=debug %s 2>&1 | FileCheck -check-prefix=ERROR %s + +// UNSPECIFIED-NOT: _LIBCPP_HARDENING_MODE + +// NONE: #define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_NONE +// FAST: #define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_FAST +// EXTENSIVE: #define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_EXTENSIVE +// DEBUG: #define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_DEBUG + +// CHECK: #define _LIBCPP_HARDENING_MODE_DEBUG 3 +// CHECK: #define _LIBCPP_HARDENING_MODE_EXTENSIVE 2 +// CHECK: #define _LIBCPP_HARDENING_MODE_FAST 1 +// CHECK: #define _LIBCPP_HARDENING_MODE_NONE 0 + +// ERROR: libc++ hardening is available only when libc++ is used _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits