Skip to content

Commit 9bea432

Browse files
skc7guy-david
authored andcommitted
[Sanitizer] Make sanitizer passes idempotent (llvm#99439)
This PR changes the sanitizer passes to be idempotent. When any sanitizer pass is run after it has already been run before, double instrumentation is seen in the resulting IR. This happens because there is no check in the pass, to verify if IR has been instrumented before. This PR checks if "nosanitize_*" module flag is already present and if true, return early without running the pass again.
1 parent d56b360 commit 9bea432

File tree

14 files changed

+244
-2
lines changed

14 files changed

+244
-2
lines changed

clang/test/CodeGenObjC/no-sanitize.m

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
@interface I0 @end
44
@implementation I0
5-
// CHECK-NOT: sanitize_address
5+
// CHECK-NOT: Function Attrs: sanitize_address
66
- (void) im0: (int) a0 __attribute__((no_sanitize("address"))) {
77
int (^blockName)(void) = ^int(void) { return 0; };
88
}

llvm/include/llvm/Transforms/Instrumentation.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,10 @@ class Triple;
3030
class OptimizationRemarkEmitter;
3131
class Comdat;
3232
class CallBase;
33+
class Module;
34+
35+
/// Check if module has flag attached, if not add the flag.
36+
bool checkIfAlreadyInstrumented(Module &M, StringRef Flag);
3337

3438
/// Instrumentation passes often insert conditional checks into entry blocks.
3539
/// Call this function before splitting the entry block to move instructions

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1251,6 +1251,11 @@ AddressSanitizerPass::AddressSanitizerPass(
12511251

12521252
PreservedAnalyses AddressSanitizerPass::run(Module &M,
12531253
ModuleAnalysisManager &MAM) {
1254+
// Return early if nosanitize_address module flag is present for the module.
1255+
// This implies that asan pass has already run before.
1256+
if (checkIfAlreadyInstrumented(M, "nosanitize_address"))
1257+
return PreservedAnalyses::all();
1258+
12541259
ModuleAddressSanitizer ModuleSanitizer(
12551260
M, Options.InsertVersionCheck, Options.CompileKernel, Options.Recover,
12561261
UseGlobalGC, UseOdrIndicator, DestructorKind, ConstructorKind);

llvm/lib/Transforms/Instrumentation/DataFlowSanitizer.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3473,6 +3473,9 @@ void DFSanVisitor::visitPHINode(PHINode &PN) {
34733473

34743474
PreservedAnalyses DataFlowSanitizerPass::run(Module &M,
34753475
ModuleAnalysisManager &AM) {
3476+
// Return early if nosanitize_dataflow module flag is present for the module.
3477+
if (checkIfAlreadyInstrumented(M, "nosanitize_dataflow"))
3478+
return PreservedAnalyses::all();
34763479
auto GetTLI = [&](Function &F) -> TargetLibraryInfo & {
34773480
auto &FAM =
34783481
AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();

llvm/lib/Transforms/Instrumentation/HWAddressSanitizer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
#include "llvm/Support/RandomNumberGenerator.h"
5858
#include "llvm/Support/raw_ostream.h"
5959
#include "llvm/TargetParser/Triple.h"
60+
#include "llvm/Transforms/Instrumentation.h"
6061
#include "llvm/Transforms/Instrumentation/AddressSanitizerCommon.h"
6162
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
6263
#include "llvm/Transforms/Utils/Local.h"
@@ -455,6 +456,9 @@ class HWAddressSanitizer {
455456

456457
PreservedAnalyses HWAddressSanitizerPass::run(Module &M,
457458
ModuleAnalysisManager &MAM) {
459+
// Return early if nosanitize_hwaddress module flag is present for the module.
460+
if (checkIfAlreadyInstrumented(M, "nosanitize_hwaddress"))
461+
return PreservedAnalyses::all();
458462
const StackSafetyGlobalInfo *SSI = nullptr;
459463
auto TargetTriple = llvm::Triple(M.getTargetTriple());
460464
if (shouldUseStackSafetyAnalysis(TargetTriple, Options.DisableOptimization))

llvm/lib/Transforms/Instrumentation/Instrumentation.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,47 @@
1212
//===----------------------------------------------------------------------===//
1313

1414
#include "llvm/Transforms/Instrumentation.h"
15+
#include "llvm/IR/DiagnosticInfo.h"
16+
#include "llvm/IR/DiagnosticPrinter.h"
1517
#include "llvm/IR/IntrinsicInst.h"
1618
#include "llvm/IR/Module.h"
1719
#include "llvm/TargetParser/Triple.h"
1820

1921
using namespace llvm;
2022

23+
static cl::opt<bool> ClIgnoreRedundantInstrumentation(
24+
"ignore-redundant-instrumentation",
25+
cl::desc("Ignore redundant instrumentation"), cl::Hidden, cl::init(false));
26+
27+
namespace {
28+
/// Diagnostic information for IR instrumentation reporting.
29+
class DiagnosticInfoInstrumentation : public DiagnosticInfo {
30+
const Twine &Msg;
31+
32+
public:
33+
DiagnosticInfoInstrumentation(const Twine &DiagMsg,
34+
DiagnosticSeverity Severity = DS_Warning)
35+
: DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {}
36+
void print(DiagnosticPrinter &DP) const override { DP << Msg; }
37+
};
38+
} // namespace
39+
40+
/// Check if module has flag attached, if not add the flag.
41+
bool llvm::checkIfAlreadyInstrumented(Module &M, StringRef Flag) {
42+
if (!M.getModuleFlag(Flag)) {
43+
M.addModuleFlag(Module::ModFlagBehavior::Override, Flag, 1);
44+
return false;
45+
}
46+
if (ClIgnoreRedundantInstrumentation)
47+
return true;
48+
std::string diagInfo =
49+
"Redundant instrumentation detected, with module flag: " +
50+
std::string(Flag);
51+
M.getContext().diagnose(
52+
DiagnosticInfoInstrumentation(diagInfo, DiagnosticSeverity::DS_Warning));
53+
return true;
54+
}
55+
2156
/// Moves I before IP. Returns new insert point.
2257
static BasicBlock::iterator moveBeforeInsertPoint(BasicBlock::iterator I, BasicBlock::iterator IP) {
2358
// If I is IP, move the insert point down.

llvm/lib/Transforms/Instrumentation/MemorySanitizer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,7 @@
198198
#include "llvm/Support/MathExtras.h"
199199
#include "llvm/Support/raw_ostream.h"
200200
#include "llvm/TargetParser/Triple.h"
201+
#include "llvm/Transforms/Instrumentation.h"
201202
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
202203
#include "llvm/Transforms/Utils/Local.h"
203204
#include "llvm/Transforms/Utils/ModuleUtils.h"
@@ -706,6 +707,9 @@ MemorySanitizerOptions::MemorySanitizerOptions(int TO, bool R, bool K,
706707

707708
PreservedAnalyses MemorySanitizerPass::run(Module &M,
708709
ModuleAnalysisManager &AM) {
710+
// Return early if nosanitize_memory module flag is present for the module.
711+
if (checkIfAlreadyInstrumented(M, "nosanitize_memory"))
712+
return PreservedAnalyses::all();
709713
bool Modified = false;
710714
if (!Options.Kernel) {
711715
insertModuleCtor(M);

llvm/lib/Transforms/Instrumentation/ThreadSanitizer.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,9 @@ PreservedAnalyses ThreadSanitizerPass::run(Function &F,
191191

192192
PreservedAnalyses ModuleThreadSanitizerPass::run(Module &M,
193193
ModuleAnalysisManager &MAM) {
194+
// Return early if nosanitize_thread module flag is present for the module.
195+
if (checkIfAlreadyInstrumented(M, "nosanitize_thread"))
196+
return PreservedAnalyses::all();
194197
insertModuleCtor(M);
195198
return PreservedAnalyses::none();
196199
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals all --version 5
2+
; This test checks in the second run, function is not instrumented again.
3+
; RUN: opt < %s -passes=asan,asan -S | FileCheck %s
4+
5+
target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
6+
target triple = "x86_64-unknown-linux-gnu"
7+
8+
; Function with sanitize_address is instrumented.
9+
; Function Attrs: nounwind uwtable
10+
;.
11+
; CHECK: @___asan_globals_registered = common hidden global i64 0
12+
; CHECK: @__start_asan_globals = extern_weak hidden global i64
13+
; CHECK: @__stop_asan_globals = extern_weak hidden global i64
14+
;.
15+
define void @instr_sa(ptr %a) sanitize_address {
16+
; CHECK: Function Attrs: sanitize_address
17+
; CHECK-LABEL: define void @instr_sa(
18+
; CHECK-SAME: ptr [[A:%.*]]) #[[ATTR0:[0-9]+]] {
19+
; CHECK-NEXT: [[ENTRY:.*:]]
20+
; CHECK-NEXT: [[TMP0:%.*]] = ptrtoint ptr [[A]] to i64
21+
; CHECK-NEXT: [[TMP1:%.*]] = lshr i64 [[TMP0]], 3
22+
; CHECK-NEXT: [[TMP2:%.*]] = add i64 [[TMP1]], 2147450880
23+
; CHECK-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to ptr
24+
; CHECK-NEXT: [[TMP4:%.*]] = load i8, ptr [[TMP3]], align 1
25+
; CHECK-NEXT: [[TMP5:%.*]] = icmp ne i8 [[TMP4]], 0
26+
; CHECK-NEXT: br i1 [[TMP5]], label %[[BB6:.*]], label %[[BB12:.*]], !prof [[PROF1:![0-9]+]]
27+
; CHECK: [[BB6]]:
28+
; CHECK-NEXT: [[TMP7:%.*]] = and i64 [[TMP0]], 7
29+
; CHECK-NEXT: [[TMP8:%.*]] = add i64 [[TMP7]], 3
30+
; CHECK-NEXT: [[TMP9:%.*]] = trunc i64 [[TMP8]] to i8
31+
; CHECK-NEXT: [[TMP10:%.*]] = icmp sge i8 [[TMP9]], [[TMP4]]
32+
; CHECK-NEXT: br i1 [[TMP10]], label %[[BB11:.*]], label %[[BB12]]
33+
; CHECK: [[BB11]]:
34+
; CHECK-NEXT: call void @__asan_report_load4(i64 [[TMP0]]) #[[ATTR2:[0-9]+]]
35+
; CHECK-NEXT: unreachable
36+
; CHECK: [[BB12]]:
37+
; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[A]], align 4
38+
; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1
39+
; CHECK-NEXT: store i32 [[TMP2]], ptr [[A]], align 4
40+
; CHECK-NEXT: ret void
41+
;
42+
entry:
43+
%tmp1 = load i32, ptr %a, align 4
44+
%tmp2 = add i32 %tmp1, 1
45+
store i32 %tmp2, ptr %a, align 4
46+
ret void
47+
}
48+
;.
49+
; CHECK: attributes #[[ATTR0]] = { sanitize_address }
50+
; CHECK: attributes #[[ATTR1:[0-9]+]] = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
51+
; CHECK: attributes #[[ATTR2]] = { nomerge }
52+
;.
53+
; CHECK: [[META0:![0-9]+]] = !{i32 4, !"nosanitize_address", i32 1}
54+
; CHECK: [[PROF1]] = !{!"branch_weights", i32 1, i32 1048575}
55+
;.

llvm/test/Instrumentation/AddressSanitizer/missing_dbg.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,4 @@ entry:
3434
!4 = !DISubroutineType(types: !5)
3535
!5 = !{}
3636

37-
; CHECK: [[DBG]] = !DILocation(line: 0, scope: !3)
37+
; CHECK: [[DBG]] = !DILocation(line: 0, scope: !4)

0 commit comments

Comments
 (0)