This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG5d64dd8e3c22: [Clang][ASan] Introduce 
`-fsanitize-address-destructor-kind=` driver & frontend… (authored by 
delcypher).

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D96572/new/

https://reviews.llvm.org/D96572

Files:
  clang/docs/ClangCommandLineReference.rst
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Basic/CodeGenOptions.h
  clang/include/clang/Basic/Sanitizers.h
  clang/include/clang/Driver/Options.td
  clang/include/clang/Driver/SanitizerArgs.h
  clang/lib/Basic/Sanitizers.cpp
  clang/lib/CodeGen/BackendUtil.cpp
  clang/lib/Driver/SanitizerArgs.cpp
  clang/lib/Frontend/CompilerInvocation.cpp
  clang/test/CodeGen/asan-destructor-kind.cpp
  clang/test/Driver/fsanitize-address-destructor-kind.c

Index: clang/test/Driver/fsanitize-address-destructor-kind.c
===================================================================
--- /dev/null
+++ clang/test/Driver/fsanitize-address-destructor-kind.c
@@ -0,0 +1,20 @@
+// Option should not be passed to the frontend by default.
+// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address %s \
+// RUN:   -### 2>&1 | \
+// RUN:   FileCheck %s
+// CHECK-NOT: -fsanitize-address-destructor-kind
+
+// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address \
+// RUN:   -fsanitize-address-destructor-kind=none %s -### 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-NONE-ARG %s
+// CHECK-NONE-ARG: "-fsanitize-address-destructor-kind=none"
+
+// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address \
+// RUN:   -fsanitize-address-destructor-kind=global %s -### 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-GLOBAL-ARG %s
+// CHECK-GLOBAL-ARG: "-fsanitize-address-destructor-kind=global"
+
+// RUN: %clang -target x86_64-apple-macosx10.15-gnu -fsanitize=address \
+// RUN:   -fsanitize-address-destructor-kind=bad_arg %s -### 2>&1 | \
+// RUN:   FileCheck -check-prefix=CHECK-INVALID-ARG %s
+// CHECK-INVALID-ARG: error: unsupported argument 'bad_arg' to option 'fsanitize-address-destructor-kind='
Index: clang/test/CodeGen/asan-destructor-kind.cpp
===================================================================
--- /dev/null
+++ clang/test/CodeGen/asan-destructor-kind.cpp
@@ -0,0 +1,49 @@
+// Frontend rejects invalid option
+// RUN: not %clang_cc1 -fsanitize=address \
+// RUN:   -fsanitize-address-destructor-kind=bad_arg -emit-llvm -o - \
+// RUN:   -triple x86_64-apple-macosx10.15 %s 2>&1 | \
+// RUN:   FileCheck %s --check-prefixes=CHECK-BAD-ARG
+// CHECK-BAD-ARG: unsupported argument 'bad_arg' to option 'fsanitize-address-destructor-kind='
+
+// Default is global dtor
+// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-apple-macosx10.15 \
+// RUN:   -fno-legacy-pass-manager %s \
+// RUN:   | FileCheck %s --check-prefixes=CHECK-GLOBAL-DTOR
+//
+// RUN: %clang_cc1 -fsanitize=address -emit-llvm -o - -triple x86_64-apple-macosx10.15 \
+// RUN:   -flegacy-pass-manager %s \
+// RUN:   | FileCheck %s --check-prefixes=CHECK-GLOBAL-DTOR
+
+// Explictly ask for global dtor
+// RUN: %clang_cc1 -fsanitize=address \
+// RUN:   -fsanitize-address-destructor-kind=global -emit-llvm -o - \
+// RUN:   -triple x86_64-apple-macosx10.15 -fno-legacy-pass-manager %s | \
+// RUN:   FileCheck %s --check-prefixes=CHECK-GLOBAL-DTOR
+//
+// RUN: %clang_cc1 -fsanitize=address \
+// RUN:   -fsanitize-address-destructor-kind=global -emit-llvm -o - \
+// RUN:   -triple x86_64-apple-macosx10.15 -flegacy-pass-manager %s | \
+// RUN:   FileCheck %s --check-prefixes=CHECK-GLOBAL-DTOR
+
+// CHECK-GLOBAL-DTOR: llvm.global_dtor{{.+}}asan.module_dtor
+// CHECK-GLOBAL-DTOR: define internal void @asan.module_dtor
+
+// Explictly ask for no dtors
+// RUN: %clang_cc1 -fsanitize=address \
+// RUN:   -fsanitize-address-destructor-kind=none -emit-llvm -o - \
+// RUN:   -triple x86_64-apple-macosx10.15 -fno-legacy-pass-manager %s | \
+// RUN:   FileCheck %s --check-prefixes=CHECK-NONE-DTOR
+//
+// RUN: %clang_cc1 -fsanitize=address \
+// RUN:   -fsanitize-address-destructor-kind=none -emit-llvm -o - \
+// RUN:   -triple x86_64-apple-macosx10.15 -flegacy-pass-manager %s | \
+// RUN:   FileCheck %s --check-prefixes=CHECK-NONE-DTOR
+
+int global;
+
+int main() {
+  return global;
+}
+
+// CHECK-NONE-DTOR-NOT: llvm.global_dtor{{.+}}asan.module_dtor
+// CHECK-NONE-DTOR-NOT: define internal void @asan.module_dtor
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -1937,6 +1937,19 @@
 
   Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true);
 
+  if (LangOptsRef.Sanitize.has(SanitizerKind::Address)) {
+    if (Arg *A =
+            Args.getLastArg(options::OPT_sanitize_address_destructor_kind_EQ)) {
+      auto destructorKind = AsanDtorKindFromString(A->getValue());
+      if (destructorKind == llvm::AsanDtorKind::Invalid) {
+        Diags.Report(clang::diag::err_drv_unsupported_option_argument)
+            << A->getOption().getName() << A->getValue();
+      } else {
+        Opts.setSanitizeAddressDtorKind(destructorKind);
+      }
+    }
+  }
+
   if (Args.hasArg(options::OPT_ffinite_loops))
     Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Always;
   else if (Args.hasArg(options::OPT_fno_finite_loops))
Index: clang/lib/Driver/SanitizerArgs.cpp
===================================================================
--- clang/lib/Driver/SanitizerArgs.cpp
+++ clang/lib/Driver/SanitizerArgs.cpp
@@ -825,6 +825,16 @@
       AsanInvalidPointerSub = true;
     }
 
+    if (const auto *Arg =
+            Args.getLastArg(options::OPT_sanitize_address_destructor_kind_EQ)) {
+      auto parsedAsanDtorKind = AsanDtorKindFromString(Arg->getValue());
+      if (parsedAsanDtorKind == llvm::AsanDtorKind::Invalid) {
+        TC.getDriver().Diag(clang::diag::err_drv_unsupported_option_argument)
+            << Arg->getOption().getName() << Arg->getValue();
+      }
+      AsanDtorKind = parsedAsanDtorKind;
+    }
+
   } else {
     AsanUseAfterScope = false;
     // -fsanitize=pointer-compare/pointer-subtract requires -fsanitize=address.
@@ -1079,6 +1089,13 @@
     CmdArgs.push_back("-asan-detect-invalid-pointer-sub");
   }
 
+  // Only pass the option to the frontend if the user requested,
+  // otherwise the frontend will just use the codegen default.
+  if (AsanDtorKind != llvm::AsanDtorKind::Invalid) {
+    CmdArgs.push_back(Args.MakeArgString("-fsanitize-address-destructor-kind=" +
+                                         AsanDtorKindToString(AsanDtorKind)));
+  }
+
   if (!HwasanAbi.empty()) {
     CmdArgs.push_back("-default-function-attr");
     CmdArgs.push_back(Args.MakeArgString("hwasan-abi=" + HwasanAbi));
Index: clang/lib/CodeGen/BackendUtil.cpp
===================================================================
--- clang/lib/CodeGen/BackendUtil.cpp
+++ clang/lib/CodeGen/BackendUtil.cpp
@@ -287,10 +287,12 @@
   bool UseAfterScope = CGOpts.SanitizeAddressUseAfterScope;
   bool UseOdrIndicator = CGOpts.SanitizeAddressUseOdrIndicator;
   bool UseGlobalsGC = asanUseGlobalsGC(T, CGOpts);
+  llvm::AsanDtorKind DestructorKind = CGOpts.getSanitizeAddressDtorKind();
   PM.add(createAddressSanitizerFunctionPass(/*CompileKernel*/ false, Recover,
                                             UseAfterScope));
   PM.add(createModuleAddressSanitizerLegacyPassPass(
-      /*CompileKernel*/ false, Recover, UseGlobalsGC, UseOdrIndicator));
+      /*CompileKernel*/ false, Recover, UseGlobalsGC, UseOdrIndicator,
+      DestructorKind));
 }
 
 static void addKernelAddressSanitizerPasses(const PassManagerBuilder &Builder,
@@ -1111,9 +1113,12 @@
         bool UseAfterScope = CodeGenOpts.SanitizeAddressUseAfterScope;
         bool ModuleUseAfterScope = asanUseGlobalsGC(TargetTriple, CodeGenOpts);
         bool UseOdrIndicator = CodeGenOpts.SanitizeAddressUseOdrIndicator;
+        llvm::AsanDtorKind DestructorKind =
+            CodeGenOpts.getSanitizeAddressDtorKind();
         MPM.addPass(RequireAnalysisPass<ASanGlobalsMetadataAnalysis, Module>());
         MPM.addPass(ModuleAddressSanitizerPass(
-            CompileKernel, Recover, ModuleUseAfterScope, UseOdrIndicator));
+            CompileKernel, Recover, ModuleUseAfterScope, UseOdrIndicator,
+            DestructorKind));
         MPM.addPass(createModuleToFunctionPassAdaptor(
             AddressSanitizerPass(CompileKernel, Recover, UseAfterScope)));
       }
Index: clang/lib/Basic/Sanitizers.cpp
===================================================================
--- clang/lib/Basic/Sanitizers.cpp
+++ clang/lib/Basic/Sanitizers.cpp
@@ -60,4 +60,23 @@
 llvm::hash_code hash_value(const clang::SanitizerMask &Arg) {
   return Arg.hash_value();
 }
+
+StringRef AsanDtorKindToString(llvm::AsanDtorKind kind) {
+  switch (kind) {
+  case llvm::AsanDtorKind::None:
+    return "none";
+  case llvm::AsanDtorKind::Global:
+    return "global";
+  case llvm::AsanDtorKind::Invalid:
+    return "invalid";
+  }
+}
+
+llvm::AsanDtorKind AsanDtorKindFromString(StringRef kindStr) {
+  return llvm::StringSwitch<llvm::AsanDtorKind>(kindStr)
+      .Case("none", llvm::AsanDtorKind::None)
+      .Case("global", llvm::AsanDtorKind::Global)
+      .Default(llvm::AsanDtorKind::Invalid);
+}
+
 } // namespace clang
Index: clang/include/clang/Driver/SanitizerArgs.h
===================================================================
--- clang/include/clang/Driver/SanitizerArgs.h
+++ clang/include/clang/Driver/SanitizerArgs.h
@@ -43,6 +43,7 @@
   bool AsanUseOdrIndicator = false;
   bool AsanInvalidPointerCmp = false;
   bool AsanInvalidPointerSub = false;
+  llvm::AsanDtorKind AsanDtorKind = llvm::AsanDtorKind::Invalid;
   std::string HwasanAbi;
   bool LinkRuntimes = true;
   bool LinkCXXRuntimes = false;
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -1500,6 +1500,11 @@
             " reports in partially sanitized programs at the cost of an increase in binary size">,
   NegFlag<SetFalse, [], "Disable ODR indicator globals">>,
   Group<f_clang_Group>;
+def sanitize_address_destructor_kind_EQ : Joined<["-"], "fsanitize-address-destructor-kind=">,
+  MetaVarName<"<kind>">,
+  Flags<[CC1Option]>,
+  HelpText<"Set destructor type used in ASan instrumentation">,
+  Group<f_clang_Group>;
 // Note: This flag was introduced when it was necessary to distinguish between
 //       ABI for correct codegen.  This is no longer needed, but the flag is
 //       not removed since targeting either ABI will behave the same.
Index: clang/include/clang/Basic/Sanitizers.h
===================================================================
--- clang/include/clang/Basic/Sanitizers.h
+++ clang/include/clang/Basic/Sanitizers.h
@@ -17,6 +17,7 @@
 #include "clang/Basic/LLVM.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/MathExtras.h"
+#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
 #include <cassert>
 #include <cstdint>
 
@@ -193,6 +194,10 @@
          SanitizerKind::Undefined | SanitizerKind::FloatDivideByZero;
 }
 
+StringRef AsanDtorKindToString(llvm::AsanDtorKind kind);
+
+llvm::AsanDtorKind AsanDtorKindFromString(StringRef kind);
+
 } // namespace clang
 
 #endif // LLVM_CLANG_BASIC_SANITIZERS_H
Index: clang/include/clang/Basic/CodeGenOptions.h
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.h
+++ clang/include/clang/Basic/CodeGenOptions.h
@@ -20,6 +20,7 @@
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/Regex.h"
 #include "llvm/Target/TargetOptions.h"
+#include "llvm/Transforms/Instrumentation/AddressSanitizerOptions.h"
 #include <map>
 #include <memory>
 #include <string>
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -214,6 +214,9 @@
 CODEGENOPT(SanitizeAddressUseOdrIndicator, 1, 0) ///< Enable ODR indicator globals
 CODEGENOPT(SanitizeMemoryTrackOrigins, 2, 0) ///< Enable tracking origins in
                                              ///< MemorySanitizer
+ENUM_CODEGENOPT(SanitizeAddressDtorKind, llvm::AsanDtorKind, 2,
+                llvm::AsanDtorKind::Global)  ///< Set how ASan global
+                                             ///< destructors are emitted.
 CODEGENOPT(SanitizeMemoryUseAfterDtor, 1, 0) ///< Enable use-after-delete detection
                                              ///< in MemorySanitizer
 CODEGENOPT(SanitizeCfiCrossDso, 1, 0) ///< Enable cross-dso support in CFI.
Index: clang/docs/ClangCommandLineReference.rst
===================================================================
--- clang/docs/ClangCommandLineReference.rst
+++ clang/docs/ClangCommandLineReference.rst
@@ -870,6 +870,17 @@
 
 Enable ODR indicator globals to avoid false ODR violation reports in partially sanitized programs at the cost of an increase in binary size
 
+.. option:: -fsanitize-address-destructor-kind=<arg>
+
+Set the kind of module destructors emitted by AddressSanitizer instrumentation.
+These destructors are emitted to unregister instrumented global variables when
+code is unloaded (e.g. via `dlclose()`).
+
+Valid options are:
+
+* ``global`` - Emit module destructors that are called via a platform specific array (see `llvm.global_dtors`).
+* ``none`` - Do not emit module destructors.
+
 .. option:: -fsanitize-blacklist=<arg>
 
 Path to blacklist file for sanitizers
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to