Skip to content

Commit 34554e6

Browse files
[DeviceSanitizer] Support "-fsanitize-ignorelist=" to disable sanitizing on some of kernels (#15294)
UR: oneapi-src/unified-runtime#2055 We reuse `-fsanitize-ignorelist=` to support kernel filtering. Usage: https://clang.llvm.org/docs/SanitizerSpecialCaseList.html We implement this feature by adding a device global "__AsanKernelMetadata" which records the sanitized kernel name, so that we can check if we need specially handle kernel in UR. --------- Co-authored-by: Callum Fare <[email protected]>
1 parent f04a30d commit 34554e6

File tree

15 files changed

+307
-73
lines changed

15 files changed

+307
-73
lines changed

clang/lib/Driver/OffloadBundler.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -687,12 +687,12 @@ class ObjectFileHandler final : public FileHandler {
687687
if (Error Err = Symbol.printName(NameOS))
688688
return std::move(Err);
689689

690-
// If we are dealing with a bitcode file do not add special globals
691-
// llvm.used and llvm.compiler.used and __AsanDeviceGlobalMetadata to
690+
// If we are dealing with a bitcode file do not add special globals to
692691
// the list of defined symbols.
693692
if (SF->isIR() &&
694693
(Name == "llvm.used" || Name == "llvm.compiler.used" ||
695-
Name == "__AsanDeviceGlobalMetadata"))
694+
Name == "__AsanDeviceGlobalMetadata" ||
695+
Name == "__AsanKernelMetadata"))
696696
continue;
697697

698698
// Add symbol name with the target prefix to the buffer.

clang/lib/Driver/SanitizerArgs.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1197,6 +1197,9 @@ void SanitizerArgs::addArgs(const ToolChain &TC, const llvm::opt::ArgList &Args,
11971197

11981198
CmdArgs.push_back("-mllvm");
11991199
CmdArgs.push_back("-asan-mapping-scale=4");
1200+
1201+
addSpecialCaseListOpt(Args, CmdArgs,
1202+
"-fsanitize-ignorelist=", UserIgnorelistFiles);
12001203
}
12011204
return;
12021205
}

libdevice/sanitizer/asan_rtl.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -665,11 +665,16 @@ constexpr size_t AlignMask(size_t n) { return n - 1; }
665665
///
666666
/// ASAN Load/Store Report Built-ins
667667
///
668+
/// NOTE:
669+
/// if __AsanLaunchInfo equals 0, the sanitizer is disabled for this launch
670+
///
668671

669672
#define ASAN_REPORT_ERROR_BASE(type, is_write, size, as) \
670673
DEVICE_EXTERN_C_NOINLINE void __asan_##type##size##_as##as( \
671674
uptr addr, const char __SYCL_CONSTANT__ *file, uint32_t line, \
672675
const char __SYCL_CONSTANT__ *func) { \
676+
if (!__AsanLaunchInfo) \
677+
return; \
673678
if (addr & AlignMask(size)) { \
674679
__asan_report_misalign_error(addr, as, size, is_write, addr, file, line, \
675680
func); \
@@ -682,6 +687,8 @@ constexpr size_t AlignMask(size_t n) { return n - 1; }
682687
DEVICE_EXTERN_C_NOINLINE void __asan_##type##size##_as##as##_noabort( \
683688
uptr addr, const char __SYCL_CONSTANT__ *file, uint32_t line, \
684689
const char __SYCL_CONSTANT__ *func) { \
690+
if (!__AsanLaunchInfo) \
691+
return; \
685692
if (addr & AlignMask(size)) { \
686693
__asan_report_misalign_error(addr, as, size, is_write, addr, file, line, \
687694
func, true); \
@@ -714,6 +721,8 @@ ASAN_REPORT_ERROR(store, true, 16)
714721
DEVICE_EXTERN_C_NOINLINE void __asan_##type##N_as##as( \
715722
uptr addr, size_t size, const char __SYCL_CONSTANT__ *file, \
716723
uint32_t line, const char __SYCL_CONSTANT__ *func) { \
724+
if (!__AsanLaunchInfo) \
725+
return; \
717726
if (auto poisoned_addr = __asan_region_is_poisoned(addr, as, size)) { \
718727
__asan_report_access_error(addr, as, size, is_write, poisoned_addr, \
719728
file, line, func); \
@@ -722,6 +731,8 @@ ASAN_REPORT_ERROR(store, true, 16)
722731
DEVICE_EXTERN_C_NOINLINE void __asan_##type##N_as##as##_noabort( \
723732
uptr addr, size_t size, const char __SYCL_CONSTANT__ *file, \
724733
uint32_t line, const char __SYCL_CONSTANT__ *func) { \
734+
if (!__AsanLaunchInfo) \
735+
return; \
725736
if (auto poisoned_addr = __asan_region_is_poisoned(addr, as, size)) { \
726737
__asan_report_access_error(addr, as, size, is_write, poisoned_addr, \
727738
file, line, func, true); \
@@ -743,6 +754,9 @@ ASAN_REPORT_ERROR_N(store, true)
743754
///
744755

745756
DEVICE_EXTERN_C_NOINLINE uptr __asan_mem_to_shadow(uptr ptr, uint32_t as) {
757+
if (!__AsanLaunchInfo)
758+
return 0;
759+
746760
return MemToShadow(ptr, as);
747761
}
748762

@@ -756,6 +770,9 @@ static __SYCL_CONSTANT__ const char __mem_set_shadow_local[] =
756770
DEVICE_EXTERN_C_NOINLINE void
757771
__asan_set_shadow_static_local(uptr ptr, size_t size,
758772
size_t size_with_redzone) {
773+
if (!__AsanLaunchInfo)
774+
return;
775+
759776
// Since ptr is aligned to ASAN_SHADOW_GRANULARITY,
760777
// if size != aligned_size, then the buffer tail of ptr is not aligned
761778
uptr aligned_size = RoundUpTo(size, ASAN_SHADOW_GRANULARITY);
@@ -795,6 +812,9 @@ static __SYCL_CONSTANT__ const char __mem_unpoison_shadow_static_local_end[] =
795812
DEVICE_EXTERN_C_NOINLINE void
796813
__asan_unpoison_shadow_static_local(uptr ptr, size_t size,
797814
size_t size_with_redzone) {
815+
if (!__AsanLaunchInfo)
816+
return;
817+
798818
ASAN_DEBUG(__spirv_ocl_printf(__mem_unpoison_shadow_static_local_begin));
799819

800820
auto shadow_begin = MemToShadow(ptr + size, ADDRESS_SPACE_LOCAL);
@@ -828,6 +848,9 @@ static __SYCL_CONSTANT__ const char __mem_report_arg_count_incorrect[] =
828848

829849
DEVICE_EXTERN_C_NOINLINE void
830850
__asan_set_shadow_dynamic_local(uptr ptr, uint32_t num_args) {
851+
if (!__AsanLaunchInfo)
852+
return;
853+
831854
ASAN_DEBUG(__spirv_ocl_printf(__mem_set_shadow_dynamic_local_begin));
832855

833856
auto *launch_info = (__SYCL_GLOBAL__ const LaunchInfo *)__AsanLaunchInfo;
@@ -859,6 +882,9 @@ static __SYCL_CONSTANT__ const char __mem_unpoison_shadow_dynamic_local_end[] =
859882

860883
DEVICE_EXTERN_C_NOINLINE void
861884
__asan_unpoison_shadow_dynamic_local(uptr ptr, uint32_t num_args) {
885+
if (!__AsanLaunchInfo)
886+
return;
887+
862888
ASAN_DEBUG(__spirv_ocl_printf(__mem_unpoison_shadow_dynamic_local_begin));
863889

864890
auto *launch_info = (__SYCL_GLOBAL__ const LaunchInfo *)__AsanLaunchInfo;
@@ -895,6 +921,9 @@ static __SYCL_CONSTANT__ const char __mem_set_shadow_private[] =
895921

896922
DEVICE_EXTERN_C_NOINLINE void __asan_set_shadow_private(uptr begin, uptr size,
897923
char val) {
924+
if (!__AsanLaunchInfo)
925+
return;
926+
898927
ASAN_DEBUG(__spirv_ocl_printf(__mem_set_shadow_private_begin));
899928

900929
auto *launch_info = (__SYCL_GLOBAL__ const LaunchInfo *)__AsanLaunchInfo;
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//===-- AsanKernelMetadata.h - fix kernel medatadata for sanitizer ---===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
// This pass fixes attributes and metadata of the global variable
9+
// "__AsanKernelMetadata"
10+
//===----------------------------------------------------------------------===//
11+
12+
#pragma once
13+
14+
#include "llvm/IR/PassManager.h"
15+
16+
namespace llvm {
17+
18+
class AsanKernelMetadataPass : public PassInfoMixin<AsanKernelMetadataPass> {
19+
public:
20+
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
21+
};
22+
23+
} // namespace llvm
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//===-- AsanKernelMetadata.cpp - fix kernel medatadata for sanitizer -===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
// This pass fixes attributes and metadata of global variable
9+
// "__AsanKernelMetadata".
10+
// We treat "__AsanKernelMetadata" as a device global variable, so that it can
11+
// be read by runtime.
12+
// "spirv.Decorations" is removed by llvm-link, so we add it here again.
13+
//===----------------------------------------------------------------------===//
14+
15+
#include "llvm/SYCLLowerIR/AsanKernelMetadata.h"
16+
17+
#include "llvm/IR/IRBuilder.h"
18+
19+
#define DEBUG_TYPE "AsanKernelMetadata"
20+
21+
using namespace llvm;
22+
23+
namespace llvm {
24+
25+
constexpr StringRef SPIRV_DECOR_MD_KIND = "spirv.Decorations";
26+
constexpr uint32_t SPIRV_HOST_ACCESS_DECOR = 6147;
27+
28+
PreservedAnalyses AsanKernelMetadataPass::run(Module &M,
29+
ModuleAnalysisManager &MAM) {
30+
auto *KernelMetadata = M.getNamedGlobal("__AsanKernelMetadata");
31+
if (!KernelMetadata) {
32+
return PreservedAnalyses::all();
33+
}
34+
35+
auto &DL = M.getDataLayout();
36+
auto &Ctx = M.getContext();
37+
38+
// Fix attributes
39+
KernelMetadata->addAttribute(
40+
"sycl-device-global-size",
41+
std::to_string(DL.getTypeAllocSize(KernelMetadata->getValueType())));
42+
43+
// Fix metadata
44+
unsigned MDKindID = Ctx.getMDKindID(SPIRV_DECOR_MD_KIND);
45+
46+
SmallVector<Metadata *, 1> MDOps;
47+
48+
SmallVector<Metadata *, 3> MD;
49+
auto *Ty = Type::getInt32Ty(Ctx);
50+
MD.push_back(ConstantAsMetadata::get(
51+
Constant::getIntegerValue(Ty, APInt(32, SPIRV_HOST_ACCESS_DECOR))));
52+
MD.push_back(
53+
ConstantAsMetadata::get(Constant::getIntegerValue(Ty, APInt(32, 0))));
54+
MD.push_back(MDString::get(Ctx, "_Z20__AsanKernelMetadata"));
55+
56+
MDOps.push_back(MDNode::get(Ctx, MD));
57+
58+
KernelMetadata->addMetadata(MDKindID, *MDNode::get(Ctx, MDOps));
59+
60+
return PreservedAnalyses::none();
61+
}
62+
63+
} // namespace llvm

llvm/lib/SYCLLowerIR/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ add_llvm_component_library(LLVMSYCLLowerIR
6969
SYCLPropagateJointMatrixUsage.cpp
7070
SYCLVirtualFunctionsAnalysis.cpp
7171
SYCLUtils.cpp
72+
AsanKernelMetadata.cpp
7273

7374
LocalAccessorToSharedMemory.cpp
7475
GlobalOffset.cpp

llvm/lib/SYCLLowerIR/ComputeModuleRuntimeInfo.cpp

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,7 @@ getSYCLESIMDSplitStatusFromMetadata(const Module &M) {
4646
} // namespace
4747

4848
bool isModuleUsingAsan(const Module &M) {
49-
for (const auto &F : M) {
50-
if (F.getCallingConv() != CallingConv::SPIR_KERNEL)
51-
continue;
52-
if (F.arg_size() == 0)
53-
continue;
54-
const auto *LastArg = F.getArg(F.arg_size() - 1);
55-
if (LastArg->getName() == "__asan_launch")
56-
return true;
57-
}
58-
return false;
49+
return M.getNamedGlobal("__AsanKernelMetadata");
5950
}
6051

6152
// This function traverses over reversed call graph by BFS algorithm.

0 commit comments

Comments
 (0)