Skip to content

Commit f9e8332

Browse files
authored
Merge pull request #10330 from swiftlang/reapply-asan-fix
2 parents 9835b7e + 1f3aa41 commit f9e8332

File tree

24 files changed

+687
-363
lines changed

24 files changed

+687
-363
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/include/llvm/Transforms/Instrumentation/AddressSanitizerCommon.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,12 @@ void getAddressSanitizerParams(const Triple &TargetTriple, int LongSize,
5858
bool IsKasan, uint64_t *ShadowBase,
5959
int *MappingScale, bool *OrShadowOffset);
6060

61+
/// Remove memory attributes that are incompatible with the instrumentation
62+
/// added by AddressSanitizer and HWAddressSanitizer.
63+
/// \p ReadsArgMem - indicates whether function arguments may be read by
64+
/// instrumentation and require removing `writeonly` attributes.
65+
void removeASanIncompatibleFnAttributes(Function &F, bool ReadsArgMem);
66+
6167
} // namespace llvm
6268

6369
#endif

llvm/lib/Passes/PassBuilder.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -743,6 +743,8 @@ Expected<AddressSanitizerOptions> parseASanPassOptions(StringRef Params) {
743743

744744
if (ParamName == "kernel") {
745745
Result.CompileKernel = true;
746+
} else if (ParamName == "use-after-scope") {
747+
Result.UseAfterScope = true;
746748
} else {
747749
return make_error<StringError>(
748750
formatv("invalid AddressSanitizer pass parameter '{0}' ", ParamName)

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,45 @@ void getAddressSanitizerParams(const Triple &TargetTriple, int LongSize,
612612
*OrShadowOffset = Mapping.OrShadowOffset;
613613
}
614614

615+
void removeASanIncompatibleFnAttributes(Function &F, bool ReadsArgMem) {
616+
// Sanitizer checks read from shadow, which invalidates memory(argmem: *).
617+
//
618+
// This is not only true for sanitized functions, because AttrInfer can
619+
// infer those attributes on libc functions, which is not true if those
620+
// are instrumented (Android) or intercepted.
621+
//
622+
// We might want to model ASan shadow memory more opaquely to get rid of
623+
// this problem altogether, by hiding the shadow memory write in an
624+
// intrinsic, essentially like in the AArch64StackTagging pass. But that's
625+
// for another day.
626+
627+
// The API is weird. `onlyReadsMemory` actually means "does not write", and
628+
// `onlyWritesMemory` actually means "does not read". So we reconstruct
629+
// "accesses memory" && "does not read" <=> "writes".
630+
bool Changed = false;
631+
if (!F.doesNotAccessMemory()) {
632+
bool WritesMemory = !F.onlyReadsMemory();
633+
bool ReadsMemory = !F.onlyWritesMemory();
634+
if ((WritesMemory && !ReadsMemory) || F.onlyAccessesArgMemory()) {
635+
F.removeFnAttr(Attribute::Memory);
636+
Changed = true;
637+
}
638+
}
639+
if (ReadsArgMem) {
640+
for (Argument &A : F.args()) {
641+
if (A.hasAttribute(Attribute::WriteOnly)) {
642+
A.removeAttr(Attribute::WriteOnly);
643+
Changed = true;
644+
}
645+
}
646+
}
647+
if (Changed) {
648+
// nobuiltin makes sure later passes don't restore assumptions about
649+
// the function.
650+
F.addFnAttr(Attribute::NoBuiltin);
651+
}
652+
}
653+
615654
ASanAccessInfo::ASanAccessInfo(int32_t Packed)
616655
: Packed(Packed),
617656
AccessSizeIndex((Packed >> kAccessSizeIndexShift) & kAccessSizeIndexMask),
@@ -1237,7 +1276,9 @@ void AddressSanitizerPass::printPipeline(
12371276
OS, MapClassName2PassName);
12381277
OS << '<';
12391278
if (Options.CompileKernel)
1240-
OS << "kernel";
1279+
OS << "kernel;";
1280+
if (Options.UseAfterScope)
1281+
OS << "use-after-scope";
12411282
OS << '>';
12421283
}
12431284

@@ -1251,6 +1292,11 @@ AddressSanitizerPass::AddressSanitizerPass(
12511292

12521293
PreservedAnalyses AddressSanitizerPass::run(Module &M,
12531294
ModuleAnalysisManager &MAM) {
1295+
// Return early if nosanitize_address module flag is present for the module.
1296+
// This implies that asan pass has already run before.
1297+
if (checkIfAlreadyInstrumented(M, "nosanitize_address"))
1298+
return PreservedAnalyses::all();
1299+
12541300
ModuleAddressSanitizer ModuleSanitizer(
12551301
M, Options.InsertVersionCheck, Options.CompileKernel, Options.Recover,
12561302
UseGlobalGC, UseOdrIndicator, DestructorKind, ConstructorKind);
@@ -2730,6 +2776,9 @@ int ModuleAddressSanitizer::GetAsanVersion(const Module &M) const {
27302776
bool ModuleAddressSanitizer::instrumentModule(Module &M) {
27312777
initializeCallbacks(M);
27322778

2779+
for (Function &F : M)
2780+
removeASanIncompatibleFnAttributes(F, /*ReadsArgMem=*/false);
2781+
27332782
// Create a module constructor. A destructor is created lazily because not all
27342783
// platforms, and not all modules need it.
27352784
if (ConstructorKind == AsanCtorKind::Global) {

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: 9 additions & 8 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))
@@ -594,6 +598,11 @@ void HWAddressSanitizer::initializeModule() {
594598
LLVM_DEBUG(dbgs() << "Init " << M.getName() << "\n");
595599
TargetTriple = Triple(M.getTargetTriple());
596600

601+
// HWASan may do short granule checks on function arguments read from the
602+
// argument memory (last byte of the granule), which invalidates writeonly.
603+
for (Function &F : M.functions())
604+
removeASanIncompatibleFnAttributes(F, /*ReadsArgMem=*/true);
605+
597606
// x86_64 currently has two modes:
598607
// - Intel LAM (default)
599608
// - pointer aliasing (heap only)
@@ -1613,14 +1622,6 @@ void HWAddressSanitizer::sanitizeFunction(Function &F,
16131622

16141623
assert(!ShadowBase);
16151624

1616-
// Remove memory attributes that are about to become invalid.
1617-
// HWASan checks read from shadow, which invalidates memory(argmem: *)
1618-
// Short granule checks on function arguments read from the argument memory
1619-
// (last byte of the granule), which invalidates writeonly.
1620-
F.removeFnAttr(llvm::Attribute::Memory);
1621-
for (auto &A : F.args())
1622-
A.removeAttr(llvm::Attribute::WriteOnly);
1623-
16241625
BasicBlock::iterator InsertPt = F.getEntryBlock().begin();
16251626
IRBuilder<> EntryIRB(&F.getEntryBlock(), InsertPt);
16261627
emitPrologue(EntryIRB,

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
}

llvm/test/Instrumentation/AddressSanitizer/AMDGPU/asan_instrument_mem_intrinsics.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,7 @@ declare void @llvm.memset.p5.i32(ptr addrspace(5) nocapture writeonly, i8, i32,
186186

187187
define void @test_mem_intrinsic_memcpy(ptr %dest0,ptr %src0,ptr addrspace(1) %dest1,ptr addrspace(1) %src1,ptr addrspace(2) %dest2,ptr addrspace(2) %src2,ptr addrspace(3) %dest3,ptr addrspace(3) %src3,ptr addrspace(4) %dest4,ptr addrspace(4) %src4,ptr addrspace(5) %dest5,ptr addrspace(5) %src5) #0 {
188188
entry:
189-
;CHECK: define void @test_mem_intrinsic_memcpy(ptr [[DEST0:%.*]], ptr [[SRC0:%.*]], ptr addrspace(1) [[DEST1:%.*]], ptr addrspace(1) [[SRC1:%.*]], ptr addrspace(2) [[DEST2:%.*]], ptr addrspace(2) [[SRC2:%.*]], ptr addrspace(3) [[DEST3:%.*]], ptr addrspace(3) [[SRC3:%.*]], ptr addrspace(4) [[DEST4:%.*]], ptr addrspace(4) [[SRC4:%.*]], ptr addrspace(5) [[DEST5:%.*]], ptr addrspace(5) [[SRC5:%.*]]) #2 {
189+
;CHECK: define void @test_mem_intrinsic_memcpy(ptr [[DEST0:%.*]], ptr [[SRC0:%.*]], ptr addrspace(1) [[DEST1:%.*]], ptr addrspace(1) [[SRC1:%.*]], ptr addrspace(2) [[DEST2:%.*]], ptr addrspace(2) [[SRC2:%.*]], ptr addrspace(3) [[DEST3:%.*]], ptr addrspace(3) [[SRC3:%.*]], ptr addrspace(4) [[DEST4:%.*]], ptr addrspace(4) [[SRC4:%.*]], ptr addrspace(5) [[DEST5:%.*]], ptr addrspace(5) [[SRC5:%.*]]){{.*}} {
190190
;CHECK-NEXT: entry:
191191
;CHECK-NEXT: [[VR0:%.*]] = call ptr @__asan_memcpy(ptr [[DEST0]], ptr [[SRC0]], i64 64)
192192
;CHECK-NEXT: [[VR1:%.*]] = addrspacecast ptr addrspace(1) [[SRC1]] to ptr
@@ -469,7 +469,7 @@ entry:
469469

470470
define void @test_mem_intrinsic_memmove(ptr %dest0,ptr %src0,ptr addrspace(1) %dest1,ptr addrspace(1) %src1,ptr addrspace(2) %dest2,ptr addrspace(2) %src2,ptr addrspace(3) %dest3,ptr addrspace(3) %src3,ptr addrspace(4) %dest4,ptr addrspace(4) %src4,ptr addrspace(5) %dest5,ptr addrspace(5) %src5) #0 {
471471
entry:
472-
;CHECK: define void @test_mem_intrinsic_memmove(ptr [[DEST0:%.*]], ptr [[SRC0:%.*]], ptr addrspace(1) [[DEST1:%.*]], ptr addrspace(1) [[SRC1:%.*]], ptr addrspace(2) [[DEST2:%.*]], ptr addrspace(2) [[SRC2:%.*]], ptr addrspace(3) [[DEST3:%.*]], ptr addrspace(3) [[SRC3:%.*]], ptr addrspace(4) [[DEST4:%.*]], ptr addrspace(4) [[SRC4:%.*]], ptr addrspace(5) [[DEST5:%.*]], ptr addrspace(5) [[SRC5:%.*]]) #2 {
472+
;CHECK: define void @test_mem_intrinsic_memmove(ptr [[DEST0:%.*]], ptr [[SRC0:%.*]], ptr addrspace(1) [[DEST1:%.*]], ptr addrspace(1) [[SRC1:%.*]], ptr addrspace(2) [[DEST2:%.*]], ptr addrspace(2) [[SRC2:%.*]], ptr addrspace(3) [[DEST3:%.*]], ptr addrspace(3) [[SRC3:%.*]], ptr addrspace(4) [[DEST4:%.*]], ptr addrspace(4) [[SRC4:%.*]], ptr addrspace(5) [[DEST5:%.*]], ptr addrspace(5) [[SRC5:%.*]]){{.*}} {
473473
;CHECK-NEXT: entry:
474474
;CHECK-NEXT: [[VR0:%.*]] = call ptr @__asan_memmove(ptr [[DEST0]], ptr [[SRC0]], i64 64)
475475
;CHECK-NEXT: [[VR1:%.*]] = addrspacecast ptr addrspace(1) [[SRC1]] to ptr
@@ -753,7 +753,7 @@ entry:
753753

754754
define void @test_mem_intrinsic_memset(ptr %ptr0,ptr addrspace(1) %ptr1,ptr addrspace(2) %ptr2,ptr addrspace(3) %ptr3,ptr addrspace(4) %ptr4,ptr addrspace(5) %ptr5) #0{
755755
entry:
756-
;CHECK: define void @test_mem_intrinsic_memset(ptr [[PTR0:%.*]], ptr addrspace(1) [[PTR1:%.*]], ptr addrspace(2) [[PTR2:%.*]], ptr addrspace(3) [[PTR3:%.*]], ptr addrspace(4) [[PTR4:%.*]], ptr addrspace(5) [[PTR5:%.*]]) #2 {
756+
;CHECK: define void @test_mem_intrinsic_memset(ptr [[PTR0:%.*]], ptr addrspace(1) [[PTR1:%.*]], ptr addrspace(2) [[PTR2:%.*]], ptr addrspace(3) [[PTR3:%.*]], ptr addrspace(4) [[PTR4:%.*]], ptr addrspace(5) [[PTR5:%.*]]){{.*}} {
757757
;CHECK-NEXT: entry:
758758
;CHECK-NEXT: [[VR0:%.*]] = call ptr @__asan_memset(ptr [[PTR0]], i32 1, i64 128)
759759
;CHECK-NEXT: [[VR1:%.*]] = addrspacecast ptr addrspace(1) [[PTR1]] to ptr
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)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
; Remove possible memory effects from functions that are invalidated by
2+
; AddressSanitizer instrumentation.
3+
4+
; RUN: opt -passes='asan<use-after-scope>' -S %s | FileCheck %s
5+
6+
; CHECK: @foo(ptr writeonly) #[[ATTRS_FOO:[0-9]+]]
7+
declare void @foo(ptr writeonly) memory(argmem: write)
8+
9+
; CHECK: @bar() #[[ATTRS_BAR:[0-9]+]]
10+
define void @bar() sanitize_address {
11+
entry:
12+
%x = alloca i32, align 4
13+
call void @llvm.lifetime.start.p0(i64 4, ptr %x)
14+
call void @foo(ptr %x)
15+
call void @llvm.lifetime.end.p0(i64 4, ptr %x)
16+
ret void
17+
}
18+
19+
; CHECK: attributes #[[ATTRS_FOO]] = { nobuiltin }
20+
; CHECK: attributes #[[ATTRS_BAR]] = { sanitize_address }
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
; RUN: opt < %s -passes=dfsan,dfsan -S | FileCheck %s
2+
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
3+
target triple = "x86_64-unknown-linux-gnu"
4+
5+
define i8 @add(i8 %a, i8 %b) {
6+
; CHECK: @add.dfsan
7+
; CHECK-DAG: %[[#ALABEL:]] = load i8, ptr @__dfsan_arg_tls, align [[ALIGN:2]]
8+
; CHECK-DAG: %[[#BLABEL:]] = load i8, ptr inttoptr (i64 add (i64 ptrtoint (ptr @__dfsan_arg_tls to i64), i64 2) to ptr), align [[ALIGN]]
9+
; CHECK: %[[#UNION:]] = or i8 %[[#ALABEL]], %[[#BLABEL]]
10+
; CHECK: %c = add i8 %a, %b
11+
; CHECK: store i8 %[[#UNION]], ptr @__dfsan_retval_tls, align [[ALIGN]]
12+
; CHECK: ret i8 %c
13+
%c = add i8 %a, %b
14+
ret i8 %c
15+
}
16+
17+
; CHECK: [[META0:![0-9]+]] = !{i32 4, !"nosanitize_dataflow", i32 1}

0 commit comments

Comments
 (0)