#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/MemoryBuiltins.h"
#include "llvm/Analysis/StackSafetyAnalysis.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
Modified |= FunctionSanitizer.instrumentFunction(F, &TLI);
}
Modified |= ModuleSanitizer.instrumentModule(M);
- return Modified ? PreservedAnalyses::none() : PreservedAnalyses::all();
+ if (!Modified)
+ return PreservedAnalyses::all();
+
+ PreservedAnalyses PA = PreservedAnalyses::none();
+ // GlobalsAA is considered stateless and does not get invalidated unless
+ // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
+ // make changes that require GlobalsAA to be invalidated.
+ PA.abandon<GlobalsAA>();
+ return PA;
}
static size_t TypeSizeToSizeIndex(uint32_t TypeSize) {
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/Triple.h"
#include "llvm/ADT/iterator.h"
+#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Argument.h"
PreservedAnalyses DataFlowSanitizerPass::run(Module &M,
ModuleAnalysisManager &AM) {
- if (DataFlowSanitizer(ABIListFiles).runImpl(M, &AM)) {
- return PreservedAnalyses::none();
- }
- return PreservedAnalyses::all();
+ if (!DataFlowSanitizer(ABIListFiles).runImpl(M, &AM))
+ return PreservedAnalyses::all();
+
+ PreservedAnalyses PA = PreservedAnalyses::none();
+ // GlobalsAA is considered stateless and does not get invalidated unless
+ // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
+ // make changes that require GlobalsAA to be invalidated.
+ PA.abandon<GlobalsAA>();
+ return PA;
}
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/Analysis/StackSafetyAnalysis.h"
#include "llvm/Analysis/ValueTracking.h"
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
for (Function &F : M)
Modified |= HWASan.sanitizeFunction(F, FAM);
- if (Modified)
- return PreservedAnalyses::none();
- return PreservedAnalyses::all();
+ if (!Modified)
+ return PreservedAnalyses::all();
+
+ PreservedAnalyses PA = PreservedAnalyses::none();
+ // GlobalsAA is considered stateless and does not get invalidated unless
+ // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
+ // make changes that require GlobalsAA to be invalidated.
+ PA.abandon<GlobalsAA>();
+ return PA;
}
void HWAddressSanitizerPass::printPipeline(
raw_ostream &OS, function_ref<StringRef(StringRef)> MapClassName2PassName) {
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/Analysis/ValueTracking.h"
#include "llvm/IR/Argument.h"
Modified |=
Msan.sanitizeFunction(F, FAM.getResult<TargetLibraryAnalysis>(F));
}
- return Modified ? PreservedAnalyses::none() : PreservedAnalyses::all();
+
+ if (!Modified)
+ return PreservedAnalyses::all();
+
+ PreservedAnalyses PA = PreservedAnalyses::none();
+ // GlobalsAA is considered stateless and does not get invalidated unless
+ // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
+ // make changes that require GlobalsAA to be invalidated.
+ PA.abandon<GlobalsAA>();
+ return PA;
}
void MemorySanitizerPass::printPipeline(
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/EHPersonalities.h"
+#include "llvm/Analysis/GlobalsModRef.h"
#include "llvm/Analysis/PostDominators.h"
#include "llvm/IR/Constant.h"
#include "llvm/IR/DataLayout.h"
auto PDTCallback = [&FAM](Function &F) -> const PostDominatorTree * {
return &FAM.getResult<PostDominatorTreeAnalysis>(F);
};
- if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
- return PreservedAnalyses::none();
- return PreservedAnalyses::all();
+ if (!ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
+ return PreservedAnalyses::all();
+
+ PreservedAnalyses PA = PreservedAnalyses::none();
+ // GlobalsAA is considered stateless and does not get invalidated unless
+ // explicitly invalidated; PreservedAnalyses::none() is not enough. Sanitizers
+ // make changes that require GlobalsAA to be invalidated.
+ PA.abandon<GlobalsAA>();
+ return PA;
}
std::pair<Value *, Value *>
--- /dev/null
+; Check that sanitizers invalidate GlobalsAA
+
+; Msan and Dfsan use globals for origin tracking and TLS for parameters.
+; RUN: opt < %s -S -passes='require<globals-aa>,module(msan)' -debug-pass-manager 2>&1 | FileCheck %s
+; RUN: opt < %s -S -passes='require<globals-aa>,module(dfsan)' -debug-pass-manager 2>&1 | FileCheck %s
+
+; Some types of coverage use globals.
+; RUN: opt < %s -S -passes='require<globals-aa>,module(sancov-module)' -sanitizer-coverage-level=2 -debug-pass-manager 2>&1 | FileCheck %s
+
+; Uses TLS for tags.
+; RUN: opt < %s -S -passes='require<globals-aa>,module(hwasan)' -debug-pass-manager 2>&1 | FileCheck %s
+
+; Modifies globals.
+; RUN: opt < %s -S -passes='require<globals-aa>,module(asan)' -debug-pass-manager 2>&1 | FileCheck %s
+
+; CHECK: Running analysis: GlobalsAA on [module]
+; CHECK: Running pass: {{.*}}Sanitizer{{.*}}Pass on [module]
+; CHECK: Invalidating analysis: GlobalsAA on [module]
+
+target triple = "x86_64-unknown-linux"
+
+define i32 @test(ptr readonly %a) local_unnamed_addr sanitize_address sanitize_hwaddress {
+entry:
+ %0 = load i32, ptr %a, align 4
+ ret i32 %0
+}
--- /dev/null
+; Regression test for msan not invalidating GlobalsAA.
+; RUN: opt < %s -S -passes='require<globals-aa>,module(msan),require<globals-aa>,early-cse<memssa>' 2>&1 | FileCheck %s
+
+target triple = "x86_64-unknown-linux"
+
+define ptr @foo(ptr %p) local_unnamed_addr sanitize_memory {
+entry:
+ ret ptr %p
+}
+
+define i32 @test() local_unnamed_addr sanitize_memory {
+entry:
+ ; CHECK-LABEL: define i32 @test()
+
+ %x = alloca i32
+ store i32 7, ptr %x
+
+ ; CHECK: store i64 0, ptr @__msan_retval_tls
+ ; CHECK-NEXT: call ptr @foo(
+
+ %call = call ptr @foo(ptr %x)
+
+ ; If GlobalsAA is eliminated correctly, early-cse should not remove next load.
+ ; CHECK-NEXT: %[[MSRET:.*]] = load i64, ptr @__msan_retval_tls
+ ; CHECK-NEXT: %[[MSCMP:.*]] = icmp ne i64 %[[MSRET]], 0
+ ; CHECK-NEXT: br i1 %[[MSCMP]],
+
+ %ret = load i32, ptr %call
+ ret i32 %ret
+}