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