dvyukov updated this revision to Diff 468816.
dvyukov added a comment.
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
@@ -67,14 +67,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};
-const MetadataInfo MetadataInfo::Atomics{"__sanitizer_metadata_atomics",
- "sanmd_atomics", 0};
+const MetadataInfo MetadataInfo::Covered{
+ "__sanitizer_metadata_covered", "sanmd_covered", kSanitizerMetadataNone};
+const MetadataInfo MetadataInfo::Atomics{
+ "__sanitizer_metadata_atomics", "sanmd_atomics", kSanitizerMetadataAtomics};
// 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 +89,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 +107,7 @@
transformOptionsFromCl(SanitizerBinaryMetadataOptions &&Opts) {
Opts.Covered |= ClEmitCovered;
Opts.Atomics |= ClEmitAtomics;
+ Opts.UAR |= ClEmitUAR;
return std::move(Opts);
}
@@ -142,7 +148,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,16 +242,21 @@
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 &= ~kSanitizerMetadataUAR;
+ if (PerInstrFeatureMask & kSanitizerMetadataUAR)
+ 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.
- if (Options.Covered || RequiresCovered) {
+ if (Options.Covered || (PerInstrFeatureMask && RequiresCovered)) {
NumMetadataCovered++;
const auto *MI = &MetadataInfo::Covered;
MIS.insert(MI);
@@ -258,10 +270,25 @@
}
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 V is an address of alloca/function arg.
+ // See isSafeAndProfitableToSinkLoad for addr-taken allocas
+ // and DeadArgumentEliminationPass::removeDeadStuffFromFunction
+ // for iteration over function args.
+ if (V) {
+ RequiresCovered = true;
+ PerInstrFeatureMask |= kSanitizerMetadataUAR;
+ }
+ }
+ }
+
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,8 @@
AuxMDs.reserve(AuxConsts.size());
for (Constant *C : AuxConsts)
AuxMDs.push_back(createConstant(C));
- Ops.push_back(MDNode::get(Context, AuxMDs));
+ // MachineSanitizerMetadata pass may modify it later.
+ 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,65 @@
+//===- 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/Passes.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/MDBuilder.h"
+#include "llvm/InitializePasses.h"
+#include "llvm/Pass.h"
+#include "llvm/Transforms/Instrumentation.h"
+#include <algorithm>
+
+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) {
+ MDNode *MD = MF.getFunction().getMetadata(LLVMContext::MD_pcsections);
+ if (!MD)
+ return false;
+ auto &AuxMDs = *cast<MDTuple>(MD->getOperand(1));
+ const auto &Features = cast<ConstantAsMetadata>(AuxMDs.getOperand(0))
+ ->getValue()
+ ->getUniqueInteger();
+ if (!Features[kSanitizerMetadataUARBit])
+ return false;
+ // Append stack args size to the function metadata.
+ int64_t ArgsSize = 0;
+ const MachineFrameInfo &MFI = MF.getFrameInfo();
+ for (int i = -1; i >= (int)-MFI.getNumFixedObjects(); --i)
+ ArgsSize =
+ std::max(ArgsSize, MFI.getObjectOffset(i) + MFI.getObjectSize(i));
+ auto &F = MF.getFunction();
+ IRBuilder<> IRB(F.getContext());
+ MDBuilder MDB(F.getContext());
+ AuxMDs.push_back(MDB.createConstant(IRB.getInt32(ArgsSize)));
+ 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,9 +159,18 @@
struct SanitizerBinaryMetadataOptions {
bool Covered = false;
bool Atomics = false;
+ bool UAR = false;
SanitizerBinaryMetadataOptions() = default;
};
+constexpr int kSanitizerMetadataAtomicsBit = 0;
+constexpr int kSanitizerMetadataUARBit = 1;
+
+constexpr uint32_t kSanitizerMetadataNone = 0;
+constexpr uint32_t kSanitizerMetadataAtomics = 1
+ << kSanitizerMetadataAtomicsBit;
+constexpr uint32_t kSanitizerMetadataUAR = 1 << kSanitizerMetadataUARBit;
+
/// Calculate what to divide by to scale counts.
///
/// Given the maximum count, calculate a divisor that will scale all the
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
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits