dvyukov updated this revision to Diff 468562.
dvyukov added a comment.
Herald added subscribers: llvm-commits, Enna1, hiraditya.
Herald added a project: LLVM.

WIP


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136078

Files:
  clang/include/clang/Basic/CodeGenOptions.def
  clang/include/clang/Basic/CodeGenOptions.h
  clang/include/clang/Driver/Options.td
  clang/lib/CodeGen/BackendUtil.cpp
  clang/lib/Driver/SanitizerArgs.cpp
  llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
  llvm/include/llvm/CodeGen/MachinePassRegistry.def
  llvm/include/llvm/CodeGen/Passes.h
  llvm/include/llvm/InitializePasses.h
  llvm/include/llvm/Transforms/Instrumentation.h
  llvm/lib/CodeGen/CMakeLists.txt
  llvm/lib/CodeGen/CodeGen.cpp
  llvm/lib/CodeGen/SanitizerMetadata.cpp
  llvm/lib/CodeGen/TargetPassConfig.cpp
  llvm/lib/IR/MDBuilder.cpp
  llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp

Index: llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp
===================================================================
--- llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp
+++ llvm/lib/Transforms/Instrumentation/SanitizerBinaryMetadata.cpp
@@ -51,6 +51,9 @@
 
 constexpr uint32_t kVersionBase = 1;                // occupies lower 16 bits
 constexpr uint32_t kVersionPtrSizeRel = (1u << 16); // offsets are pointer-sized
+constexpr uint32_t kFeatureNone = 0;
+constexpr uint32_t kFeatureAtomics = 1 << 0;
+constexpr uint32_t kFeatureUAR = 1 << 1;
 constexpr int kCtorDtorPriority = 2;
 
 // Pairs of names of initialization callback functions and which section
@@ -67,14 +70,14 @@
 private:
   // Forbid construction elsewhere.
   explicit constexpr MetadataInfo(StringRef FunctionPrefix,
-                                  StringRef SectionSuffix, int Feature)
+                                  StringRef SectionSuffix, uint32_t Feature)
       : FunctionPrefix(FunctionPrefix), SectionSuffix(SectionSuffix),
-        FeatureMask(Feature != -1 ? (1u << Feature) : 0) {}
+        FeatureMask(Feature) {}
 };
 const MetadataInfo MetadataInfo::Covered{"__sanitizer_metadata_covered",
-                                         "sanmd_covered", -1};
+                                         "sanmd_covered", kFeatureNone};
 const MetadataInfo MetadataInfo::Atomics{"__sanitizer_metadata_atomics",
-                                         "sanmd_atomics", 0};
+                                         "sanmd_atomics", kFeatureAtomics};
 
 // The only instances of MetadataInfo are the constants above, so a set of
 // them may simply store pointers to them. To deterministically generate code,
@@ -89,11 +92,16 @@
 cl::opt<bool> ClEmitAtomics("sanitizer-metadata-atomics",
                             cl::desc("Emit PCs for atomic operations."),
                             cl::Hidden, cl::init(false));
+cl::opt<bool> ClEmitUAR("sanitizer-metadata-uar",
+                        cl::desc("Emit PCs for start of functions that are "
+                                 "subject for use-after-return checking"),
+                        cl::Hidden, cl::init(false));
 
 //===--- Statistics -------------------------------------------------------===//
 
 STATISTIC(NumMetadataCovered, "Metadata attached to covered functions");
 STATISTIC(NumMetadataAtomics, "Metadata attached to atomics");
+STATISTIC(NumMetadataUAR, "Metadata attached to UAR functions");
 
 //===----------------------------------------------------------------------===//
 
@@ -102,6 +110,7 @@
 transformOptionsFromCl(SanitizerBinaryMetadataOptions &&Opts) {
   Opts.Covered |= ClEmitCovered;
   Opts.Atomics |= ClEmitAtomics;
+  Opts.UAR |= ClEmitUAR;
   return std::move(Opts);
 }
 
@@ -142,7 +151,8 @@
   // function with memory operations (atomic or not) requires covered metadata
   // to determine if a memory operation is atomic or not in modules compiled
   // with SanitizerBinaryMetadata.
-  bool runOn(Instruction &I, MetadataInfoSet &MIS, MDBuilder &MDB);
+  bool runOn(Instruction &I, MetadataInfoSet &MIS, MDBuilder &MDB,
+             uint32_t &PerInstrFeatureMask);
 
   // Get start/end section marker pointer.
   GlobalVariable *getSectionMarker(const Twine &MarkerName, Type *Ty);
@@ -235,12 +245,17 @@
   uint32_t PerInstrFeatureMask = getEnabledPerInstructionFeature();
   // Don't emit unnecessary covered metadata for all functions to save space.
   bool RequiresCovered = false;
-  if (PerInstrFeatureMask) {
+  if (PerInstrFeatureMask || Options.UAR) {
     for (BasicBlock &BB : F)
       for (Instruction &I : BB)
-        RequiresCovered |= runOn(I, MIS, MDB);
+        RequiresCovered |= runOn(I, MIS, MDB, PerInstrFeatureMask);
   }
 
+  if (F.isVarArg())
+    PerInstrFeatureMask &= ~kFeatureUAR;
+  if (PerInstrFeatureMask & kFeatureUAR)
+    NumMetadataUAR++;
+
   // Covered metadata is always emitted if explicitly requested, otherwise only
   // if some other metadata requires it to unambiguously interpret it for
   // modules compiled with SanitizerBinaryMetadata.
@@ -258,10 +273,21 @@
 }
 
 bool SanitizerBinaryMetadata::runOn(Instruction &I, MetadataInfoSet &MIS,
-                                    MDBuilder &MDB) {
+                                    MDBuilder &MDB,
+                                    uint32_t &PerInstrFeatureMask) {
   SmallVector<const MetadataInfo *, 1> InstMetadata;
   bool RequiresCovered = false;
 
+  if (Options.UAR) {
+    for (unsigned i = 0; i < I.getNumOperands(); ++i) {
+      const Value *V = I.getOperand(i);
+      // TODO(dvyukov): check if use is an address of allocas/params.
+      (void)V;
+      RequiresCovered = true;
+      PerInstrFeatureMask |= kFeatureUAR;
+    }
+  }
+
   if (Options.Atomics && I.mayReadOrWriteMemory()) {
     auto SSID = getAtomicSyncScopeID(&I);
     if (SSID.has_value() && SSID.value() != SyncScope::SingleThread) {
Index: llvm/lib/IR/MDBuilder.cpp
===================================================================
--- llvm/lib/IR/MDBuilder.cpp
+++ llvm/lib/IR/MDBuilder.cpp
@@ -172,7 +172,7 @@
       AuxMDs.reserve(AuxConsts.size());
       for (Constant *C : AuxConsts)
         AuxMDs.push_back(createConstant(C));
-      Ops.push_back(MDNode::get(Context, AuxMDs));
+      Ops.push_back(MDNode::getDistinct(Context, AuxMDs));
     }
   }
 
Index: llvm/lib/CodeGen/TargetPassConfig.cpp
===================================================================
--- llvm/lib/CodeGen/TargetPassConfig.cpp
+++ llvm/lib/CodeGen/TargetPassConfig.cpp
@@ -1268,6 +1268,7 @@
 
   addPass(&StackMapLivenessID);
   addPass(&LiveDebugValuesID);
+  addPass(&MachineSanitizerMetadataID);
 
   if (TM->Options.EnableMachineOutliner && getOptLevel() != CodeGenOpt::None &&
       EnableMachineOutliner != RunOutliner::NeverOutline) {
Index: llvm/lib/CodeGen/SanitizerMetadata.cpp
===================================================================
--- /dev/null
+++ llvm/lib/CodeGen/SanitizerMetadata.cpp
@@ -0,0 +1,88 @@
+//===- SanitizerMetadata.cpp ----------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of SanitizerBinaryMetadata.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/CodeGen/MachineFrameInfo.h"
+#include "llvm/CodeGen/MachineFunction.h"
+#include "llvm/CodeGen/MachineFunctionPass.h"
+#include "llvm/CodeGen/MachineModuleInfo.h"
+#include "llvm/CodeGen/Passes.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/MDBuilder.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+
+using namespace llvm;
+
+class MachineSanitizerMetadata : public MachineFunctionPass {
+public:
+  static char ID;
+
+  MachineSanitizerMetadata();
+  bool runOnMachineFunction(MachineFunction &F) override;
+};
+
+INITIALIZE_PASS(MachineSanitizerMetadata, "machine-sanmd",
+                "Machine Sanitizer Binary Metadata", false, false)
+
+char MachineSanitizerMetadata::ID = 0;
+char &llvm::MachineSanitizerMetadataID = MachineSanitizerMetadata::ID;
+
+MachineSanitizerMetadata::MachineSanitizerMetadata() : MachineFunctionPass(ID) {
+  initializeMachineSanitizerMetadataPass(*PassRegistry::getPassRegistry());
+}
+
+bool MachineSanitizerMetadata::runOnMachineFunction(MachineFunction &MF) {
+  const Function &F = MF.getFunction();
+  MDNode *MD = F.getMetadata(LLVMContext::MD_pcsections);
+  if (!MD)
+    return false;
+
+  auto *AuxMDs = cast<MDTuple>(MD->getOperand(1));
+  auto &AuxMDO = AuxMDs->getOperand(0);
+  auto *C = cast<ConstantAsMetadata>(AuxMDO);
+  auto V = C->getValue()->getUniqueInteger();
+  if (!V[1])
+    return false;
+
+  auto &MMI = getAnalysis<MachineModuleInfoWrapperPass>().getMMI();
+  IRBuilder<> IRB(MMI.getModule()->getContext());
+  const MachineFrameInfo &MFI = MF.getFrameInfo();
+
+  bool supported = true;
+  uint64_t stackArgsSize = 0;
+  switch (MFI.getNumFixedObjects()) {
+  case 1:
+    supported &= MFI.getObjectSize(-1) == 8 && MFI.getObjectOffset(-1) == -16;
+    break;
+  case 2:
+    supported &= MFI.getObjectOffset(-1) == 0 && MFI.getObjectSize(-2) == 8 &&
+                 MFI.getObjectOffset(-2) == -16;
+    stackArgsSize = MFI.getObjectSize(-1);
+    break;
+  default:
+    supported = false;
+    break;
+  }
+  printf("func=%s vararg=%d fixed=%d supported=%d args=%lu\n",
+         F.getName().data(), F.isVarArg(), MFI.getNumFixedObjects(), supported,
+         stackArgsSize);
+  if (false)
+    for (int i = -1; i >= (int)-MFI.getNumFixedObjects(); --i) {
+      assert(MFI.isFixedObjectIndex(i));
+      printf("  fixed #%d: size=%ld offset=%ld immutable=%d varsize=%d\n", i,
+             MFI.getObjectSize(i), MFI.getObjectOffset(i),
+             MFI.isImmutableObjectIndex(i), MFI.isVariableSizedObjectIndex(i));
+    }
+  MDBuilder MDB(F.getContext());
+  AuxMDs->push_back(MDB.createConstant(IRB.getInt32(stackArgsSize)));
+  return false;
+}
Index: llvm/lib/CodeGen/CodeGen.cpp
===================================================================
--- llvm/lib/CodeGen/CodeGen.cpp
+++ llvm/lib/CodeGen/CodeGen.cpp
@@ -83,6 +83,7 @@
   initializeMachineOptimizationRemarkEmitterPassPass(Registry);
   initializeMachineOutlinerPass(Registry);
   initializeMachinePipelinerPass(Registry);
+  initializeMachineSanitizerMetadataPass(Registry);
   initializeModuloScheduleTestPass(Registry);
   initializeMachinePostDominatorTreePass(Registry);
   initializeMachineRegionInfoPassPass(Registry);
Index: llvm/lib/CodeGen/CMakeLists.txt
===================================================================
--- llvm/lib/CodeGen/CMakeLists.txt
+++ llvm/lib/CodeGen/CMakeLists.txt
@@ -195,6 +195,7 @@
   RegisterBankInfo.cpp
   SafeStack.cpp
   SafeStackLayout.cpp
+  SanitizerMetadata.cpp
   ScheduleDAG.cpp
   ScheduleDAGInstrs.cpp
   ScheduleDAGPrinter.cpp
Index: llvm/include/llvm/Transforms/Instrumentation.h
===================================================================
--- llvm/include/llvm/Transforms/Instrumentation.h
+++ llvm/include/llvm/Transforms/Instrumentation.h
@@ -159,6 +159,7 @@
 struct SanitizerBinaryMetadataOptions {
   bool Covered = false;
   bool Atomics = false;
+  bool UAR = false;
   SanitizerBinaryMetadataOptions() = default;
 };
 
Index: llvm/include/llvm/InitializePasses.h
===================================================================
--- llvm/include/llvm/InitializePasses.h
+++ llvm/include/llvm/InitializePasses.h
@@ -295,6 +295,7 @@
 void initializeMachinePipelinerPass(PassRegistry&);
 void initializeMachinePostDominatorTreePass(PassRegistry&);
 void initializeMachineRegionInfoPassPass(PassRegistry&);
+void initializeMachineSanitizerMetadataPass(PassRegistry &);
 void initializeMachineSchedulerPass(PassRegistry&);
 void initializeMachineSinkingPass(PassRegistry&);
 void initializeMachineTraceMetricsPass(PassRegistry&);
Index: llvm/include/llvm/CodeGen/Passes.h
===================================================================
--- llvm/include/llvm/CodeGen/Passes.h
+++ llvm/include/llvm/CodeGen/Passes.h
@@ -405,6 +405,8 @@
   /// the intrinsic for later emission to the StackMap.
   extern char &StackMapLivenessID;
 
+  extern char &MachineSanitizerMetadataID;
+
   /// RemoveRedundantDebugValues pass.
   extern char &RemoveRedundantDebugValuesID;
 
Index: llvm/include/llvm/CodeGen/MachinePassRegistry.def
===================================================================
--- llvm/include/llvm/CodeGen/MachinePassRegistry.def
+++ llvm/include/llvm/CodeGen/MachinePassRegistry.def
@@ -202,4 +202,5 @@
 DUMMY_MACHINE_FUNCTION_PASS("reset-machine-function", ResetMachineFunctionPass, ())
 DUMMY_MACHINE_FUNCTION_PASS("machineverifier", MachineVerifierPass, ())
 DUMMY_MACHINE_FUNCTION_PASS("print-machine-cycles", MachineCycleInfoPrinterPass, ())
+DUMMY_MACHINE_FUNCTION_PASS("machine-sanmd", MachineSanitizerMetadata, ())
 #undef DUMMY_MACHINE_FUNCTION_PASS
Index: llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
===================================================================
--- llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
+++ llvm/include/llvm/CodeGen/CodeGenPassBuilder.h
@@ -926,6 +926,7 @@
 
   addPass(StackMapLivenessPass());
   addPass(LiveDebugValuesPass());
+  addPass(MachineSanitizerMetadata());
 
   if (TM.Options.EnableMachineOutliner && getOptLevel() != CodeGenOpt::None &&
       Opt.EnableMachineOutliner != RunOutliner::NeverOutline) {
Index: clang/lib/Driver/SanitizerArgs.cpp
===================================================================
--- clang/lib/Driver/SanitizerArgs.cpp
+++ clang/lib/Driver/SanitizerArgs.cpp
@@ -104,6 +104,7 @@
 enum BinaryMetadataFeature {
   BinaryMetadataCovered = 1 << 0,
   BinaryMetadataAtomics = 1 << 1,
+  BinaryMetadataUAR = 1 << 2,
 };
 
 /// Parse a -fsanitize= or -fno-sanitize= argument's values, diagnosing any
@@ -1129,7 +1130,8 @@
   // flags. Does not depend on any other sanitizers.
   const std::pair<int, std::string> BinaryMetadataFlags[] = {
       std::make_pair(BinaryMetadataCovered, "covered"),
-      std::make_pair(BinaryMetadataAtomics, "atomics")};
+      std::make_pair(BinaryMetadataAtomics, "atomics"),
+      std::make_pair(BinaryMetadataUAR, "uar")};
   for (const auto &F : BinaryMetadataFlags) {
     if (BinaryMetadataFeatures & F.first)
       CmdArgs.push_back(
@@ -1395,6 +1397,7 @@
     int F = llvm::StringSwitch<int>(Value)
                 .Case("covered", BinaryMetadataCovered)
                 .Case("atomics", BinaryMetadataAtomics)
+                .Case("uar", BinaryMetadataUAR)
                 .Case("all", ~0)
                 .Default(0);
     if (F == 0 && DiagnoseErrors)
Index: clang/lib/CodeGen/BackendUtil.cpp
===================================================================
--- clang/lib/CodeGen/BackendUtil.cpp
+++ clang/lib/CodeGen/BackendUtil.cpp
@@ -234,6 +234,7 @@
   SanitizerBinaryMetadataOptions Opts;
   Opts.Covered = CGOpts.SanitizeBinaryMetadataCovered;
   Opts.Atomics = CGOpts.SanitizeBinaryMetadataAtomics;
+  Opts.UAR = CGOpts.SanitizeBinaryMetadataUAR;
   return Opts;
 }
 
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -5542,6 +5542,10 @@
     : Flag<["-"], "fexperimental-sanitize-metadata=atomics">,
       HelpText<"Emit PCs for atomic operations used by binary analysis sanitizers">,
       MarshallingInfoFlag<CodeGenOpts<"SanitizeBinaryMetadataAtomics">>;
+def fexperimental_sanitize_metadata_EQ_uar
+    : Flag<["-"], "fexperimental-sanitize-metadata=uar">,
+      HelpText<"Emit PCs for start of functions that are subject for use-after-return checking.">,
+      MarshallingInfoFlag<CodeGenOpts<"SanitizeBinaryMetadataUAR">>;
 def fpatchable_function_entry_offset_EQ
     : Joined<["-"], "fpatchable-function-entry-offset=">, MetaVarName<"<M>">,
       HelpText<"Generate M NOPs before function entry">,
Index: clang/include/clang/Basic/CodeGenOptions.h
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.h
+++ clang/include/clang/Basic/CodeGenOptions.h
@@ -494,7 +494,8 @@
 
   // Check if any one of SanitizeBinaryMetadata* is enabled.
   bool hasSanitizeBinaryMetadata() const {
-    return SanitizeBinaryMetadataCovered || SanitizeBinaryMetadataAtomics;
+    return SanitizeBinaryMetadataCovered || SanitizeBinaryMetadataAtomics ||
+           SanitizeBinaryMetadataUAR;
   }
 };
 
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -288,6 +288,8 @@
 CODEGENOPT(SanitizeCoverageTraceStores, 1, 0) ///< Enable tracing of stores.
 CODEGENOPT(SanitizeBinaryMetadataCovered, 1, 0) ///< Emit PCs for covered functions.
 CODEGENOPT(SanitizeBinaryMetadataAtomics, 1, 0) ///< Emit PCs for atomic operations.
+CODEGENOPT(SanitizeBinaryMetadataUAR, 1, 0) ///< Emit PCs for start of functions
+                                            ///< that are subject for use-after-return checking.
 CODEGENOPT(SanitizeStats     , 1, 0) ///< Collect statistics for sanitizers.
 CODEGENOPT(SimplifyLibCalls  , 1, 1) ///< Set when -fbuiltin is enabled.
 CODEGENOPT(SoftFloat         , 1, 0) ///< -soft-float.
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to