Skip to content

Commit 14b373d

Browse files
committed
wip
1 parent 426d921 commit 14b373d

File tree

8 files changed

+131
-40
lines changed

8 files changed

+131
-40
lines changed

libdevice/sanitizer/asan_rtl.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
#include "include/asan_rtl.hpp"
1010
#include "asan/asan_libdevice.hpp"
1111

12+
extern "C" __attribute__((weak)) const int __asan_check_shadow_bounds;
13+
1214
// Save the pointer to LaunchInfo
1315
__SYCL_GLOBAL__ uptr *__SYCL_LOCAL__ __AsanLaunchInfo;
1416

@@ -68,6 +70,8 @@ struct DebugInfo {
6870
uint32_t line;
6971
};
7072

73+
inline bool IsCheckShadowBounds() { return __asan_check_shadow_bounds; }
74+
7175
void ReportUnknownDevice(const DebugInfo *debug);
7276
void PrintShadowMemory(uptr addr, uptr shadow_address, uint32_t as);
7377
void SaveReport(ErrorType error_type, MemoryType memory_type, bool is_recover,
@@ -120,8 +124,9 @@ inline uptr MemToShadow_DG2(uptr addr, uint32_t as,
120124
launch_info->GlobalShadowOffset + (addr >> ASAN_SHADOW_SCALE);
121125
}
122126

123-
if (shadow_ptr < launch_info->GlobalShadowLowerBound ||
124-
shadow_ptr > launch_info->GlobalShadowUpperBound) {
127+
if (IsCheckShadowBounds() &&
128+
(shadow_ptr < launch_info->GlobalShadowLowerBound ||
129+
shadow_ptr > launch_info->GlobalShadowUpperBound)) {
125130
ASAN_DEBUG(__spirv_ocl_printf(__asan_print_shadow_bound, addr, shadow_ptr,
126131
launch_info->GlobalShadowLowerBound,
127132
launch_info->GlobalShadowUpperBound));
@@ -213,8 +218,9 @@ inline uptr MemToShadow_PVC(uptr addr, uint32_t as,
213218
((addr & 0x7FFFFFFFFFFF) >> ASAN_SHADOW_SCALE);
214219
}
215220

216-
if (shadow_ptr < launch_info->GlobalShadowLowerBound ||
217-
shadow_ptr > launch_info->GlobalShadowUpperBound) {
221+
if (IsCheckShadowBounds() &&
222+
(shadow_ptr < launch_info->GlobalShadowLowerBound ||
223+
shadow_ptr > launch_info->GlobalShadowUpperBound)) {
218224
ASAN_DEBUG(__spirv_ocl_printf(__asan_print_shadow_bound, addr, shadow_ptr,
219225
launch_info->GlobalShadowLowerBound,
220226
launch_info->GlobalShadowUpperBound));

llvm/include/llvm/Transforms/Instrumentation/SPIRVSanitizerCommonUtils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ enum SanitizedKernelFlags : uint32_t {
5050
CHECK_PRIVATES = 1U << 3,
5151
CHECK_GENERICS = 1U << 4,
5252
MSAN_TRACK_ORIGINS = 1U << 5,
53+
ASAN_CHECK_SHADOW_BOUNDS = 1U << 6,
5354
};
5455

5556
} // namespace llvm

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 49 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -441,27 +441,35 @@ static cl::opt<AsanDtorKind> ClOverrideDestructorKind(
441441
cl::init(AsanDtorKind::Invalid), cl::Hidden);
442442

443443
// SYCL flags
444+
static cl::opt<bool> ClSpirOffloadPrivates(
445+
"asan-spir-privates",
446+
cl::desc("Instrument private pointer on SPIR-V target"), cl::Hidden,
447+
cl::init(true));
448+
444449
static cl::opt<bool>
445-
ClSpirOffloadPrivates("asan-spir-privates",
446-
cl::desc("instrument private pointer"), cl::Hidden,
447-
cl::init(true));
450+
ClSpirOffloadGlobals("asan-spir-globals",
451+
cl::desc("Instrument global pointer on SPIR-V target"),
452+
cl::Hidden, cl::init(true));
448453

449-
static cl::opt<bool> ClSpirOffloadGlobals("asan-spir-globals",
450-
cl::desc("instrument global pointer"),
451-
cl::Hidden, cl::init(true));
454+
static cl::opt<bool>
455+
ClSpirOffloadLocals("asan-spir-locals",
456+
cl::desc("Instrument local pointer on SPIR-V target"),
457+
cl::Hidden, cl::init(true));
452458

453-
static cl::opt<bool> ClSpirOffloadLocals("asan-spir-locals",
454-
cl::desc("instrument local pointer"),
455-
cl::Hidden, cl::init(true));
459+
static cl::opt<bool> ClSpirOffloadGenerics(
460+
"asan-spir-generics",
461+
cl::desc("Instrument generic pointer on SPIR-V target"), cl::Hidden,
462+
cl::init(true));
456463

457464
static cl::opt<bool>
458-
ClSpirOffloadGenerics("asan-spir-generics",
459-
cl::desc("instrument generic pointer"), cl::Hidden,
460-
cl::init(true));
465+
ClDeviceGlobals("asan-device-globals",
466+
cl::desc("Instrument device globals on SPIR-V target"),
467+
cl::Hidden, cl::init(true));
461468

462-
static cl::opt<bool> ClDeviceGlobals("asan-device-globals",
463-
cl::desc("instrument device globals"),
464-
cl::Hidden, cl::init(true));
469+
static cl::opt<bool> ClSpirCheckShadowBounds(
470+
"asan-spir-shadow-bounds",
471+
cl::desc("Enable checking shadow bounds on SPIR-V target"), cl::Hidden,
472+
cl::init(false));
465473

466474
// Debug flags.
467475

@@ -1411,7 +1419,8 @@ static void ExtendSpirKernelArgs(Module &M, FunctionAnalysisManager &FAM,
14111419
// following structure:
14121420
// uptr unmangled_kernel_name
14131421
// uptr unmangled_kernel_name_size
1414-
StructType *StructTy = StructType::get(IntptrTy, IntptrTy);
1422+
// uptr sanitized_flags
1423+
StructType *StructTy = StructType::get(IntptrTy, IntptrTy, IntptrTy);
14151424

14161425
if (!HasESIMD)
14171426
for (Function &F : M) {
@@ -1442,9 +1451,21 @@ static void ExtendSpirKernelArgs(Module &M, FunctionAnalysisManager &FAM,
14421451
KernelNamesBytes.append(KernelName.begin(), KernelName.end());
14431452
auto *KernelNameGV = GetOrCreateGlobalString(
14441453
M, "__asan_kernel", KernelName, kSpirOffloadConstantAS);
1454+
1455+
uintptr_t SanitizerFlags = 0;
1456+
SanitizerFlags |= ClSpirOffloadLocals ? SanitizedKernelFlags::CHECK_LOCALS
1457+
: SanitizedKernelFlags::NO_CHECK;
1458+
SanitizerFlags |= ClSpirOffloadPrivates
1459+
? SanitizedKernelFlags::CHECK_PRIVATES
1460+
: SanitizedKernelFlags::NO_CHECK;
1461+
SanitizerFlags |= ClSpirCheckShadowBounds != 0
1462+
? SanitizedKernelFlags::ASAN_CHECK_SHADOW_BOUNDS
1463+
: SanitizedKernelFlags::NO_CHECK;
1464+
14451465
SpirKernelsMetadata.emplace_back(ConstantStruct::get(
14461466
StructTy, ConstantExpr::getPointerCast(KernelNameGV, IntptrTy),
1447-
ConstantInt::get(IntptrTy, KernelName.size())));
1467+
ConstantInt::get(IntptrTy, KernelName.size()),
1468+
ConstantInt::get(IntptrTy, SanitizerFlags)));
14481469
}
14491470

14501471
// Create global variable to record spirv kernels' information
@@ -1632,6 +1653,17 @@ PreservedAnalyses AddressSanitizerPass::run(Module &M,
16321653
ExtendSpirKernelArgs(M, FAM, HasESIMD);
16331654
Modified = true;
16341655

1656+
{
1657+
IRBuilder<> IRB(M.getContext());
1658+
M.getOrInsertGlobal("__asan_check_shadow_bounds", IRB.getInt32Ty(), [&] {
1659+
return new GlobalVariable(
1660+
M, IRB.getInt32Ty(), true, GlobalValue::WeakODRLinkage,
1661+
ConstantInt::get(IRB.getInt32Ty(), ClSpirCheckShadowBounds),
1662+
"__asan_check_shadow_bounds", nullptr,
1663+
llvm::GlobalValue::NotThreadLocal, kSpirOffloadGlobalAS);
1664+
});
1665+
}
1666+
16351667
if (HasESIMD) {
16361668
GlobalStringMap.clear();
16371669
return PreservedAnalyses::none();

unified-runtime/source/loader/layers/sanitizer/asan/asan_interceptor.cpp

Lines changed: 38 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -465,7 +465,7 @@ ur_result_t AsanInterceptor::unregisterProgram(ur_program_handle_t Program) {
465465
}
466466
ProgramInfo->AllocInfoForGlobals.clear();
467467

468-
ProgramInfo->InstrumentedKernels.clear();
468+
ProgramInfo->KernelMetadataMap.clear();
469469

470470
return UR_RESULT_SUCCESS;
471471
}
@@ -520,14 +520,21 @@ ur_result_t AsanInterceptor::registerSpirKernels(ur_program_handle_t Program) {
520520

521521
std::string KernelName =
522522
std::string(KernelNameV.begin(), KernelNameV.end());
523+
bool CheckLocals = SKI.Flags & SanitizedKernelFlags::CHECK_LOCALS;
524+
bool CheckPrivates = SKI.Flags & SanitizedKernelFlags::CHECK_PRIVATES;
525+
bool CheckShadowBounds =
526+
SKI.Flags & SanitizedKernelFlags::ASAN_CHECK_SHADOW_BOUNDS;
523527

524528
UR_LOG_L(getContext()->logger, INFO,
525-
"SpirKernel(name='{}', isInstrumented={})", KernelName, true);
529+
"SpirKernel(name='{}', isInstrumented={}, "
530+
"checkLocals={}, checkPrivates={}, checkShadowBounds={})",
531+
KernelName, true, CheckLocals, CheckPrivates, CheckShadowBounds);
526532

527-
PI->InstrumentedKernels.insert(std::move(KernelName));
533+
PI->KernelMetadataMap[KernelName] = ProgramInfo::KernelMetada{
534+
CheckLocals, CheckPrivates, CheckShadowBounds};
528535
}
529536
UR_LOG_L(getContext()->logger, INFO, "Number of sanitized kernel: {}",
530-
PI->InstrumentedKernels.size());
537+
PI->KernelMetadataMap.size());
531538
}
532539

533540
return UR_RESULT_SUCCESS;
@@ -691,11 +698,18 @@ KernelInfo &AsanInterceptor::getOrCreateKernelInfo(ur_kernel_handle_t Kernel) {
691698
auto Program = GetProgram(Kernel);
692699
auto PI = getProgramInfo(Program);
693700
assert(PI != nullptr && "unregistered program!");
694-
bool IsInstrumented = PI->isKernelInstrumented(Kernel);
701+
702+
auto KI = std::make_unique<KernelInfo>(Kernel);
703+
KI->IsInstrumented = PI->isKernelInstrumented(Kernel);
704+
if (KI->IsInstrumented) {
705+
auto &KM = PI->getKernelMetadata(Kernel);
706+
KI->IsCheckLocals = KM.CheckLocals;
707+
KI->IsCheckPrivates = KM.CheckPrivates;
708+
KI->IsCheckShadowBounds = KM.CheckShadowBounds;
709+
}
695710

696711
std::scoped_lock<ur_shared_mutex> Guard(m_KernelMapMutex);
697-
m_KernelMap.emplace(Kernel,
698-
std::make_unique<KernelInfo>(Kernel, IsInstrumented));
712+
m_KernelMap.emplace(Kernel, std::move(KI));
699713
return *m_KernelMap[Kernel].get();
700714
}
701715

@@ -837,14 +851,17 @@ ur_result_t AsanInterceptor::prepareLaunch(
837851
// Prepare asan runtime data
838852
LaunchInfo.Data.Host.GlobalShadowOffset = DeviceInfo->Shadow->ShadowBegin;
839853
LaunchInfo.Data.Host.GlobalShadowOffsetEnd = DeviceInfo->Shadow->ShadowEnd;
840-
LaunchInfo.Data.Host.GlobalShadowLowerBound =
841-
DeviceInfo->Shadow->ShadowLowerBound;
842-
LaunchInfo.Data.Host.GlobalShadowUpperBound =
843-
DeviceInfo->Shadow->ShadowUpperBound;
844854
LaunchInfo.Data.Host.Debug = getContext()->Options.Debug ? 1 : 0;
845855

856+
if (KernelInfo.IsCheckShadowBounds) {
857+
LaunchInfo.Data.Host.GlobalShadowLowerBound =
858+
DeviceInfo->Shadow->ShadowLowerBound;
859+
LaunchInfo.Data.Host.GlobalShadowUpperBound =
860+
DeviceInfo->Shadow->ShadowUpperBound;
861+
}
862+
846863
// Write shadow memory offset for local memory
847-
if (getContext()->Options.DetectLocals) {
864+
if (KernelInfo.IsCheckLocals) {
848865
if (DeviceInfo->Shadow->AllocLocalShadow(
849866
Queue, NumWG, LaunchInfo.Data.Host.LocalShadowOffset,
850867
LaunchInfo.Data.Host.LocalShadowOffsetEnd) != UR_RESULT_SUCCESS) {
@@ -864,7 +881,7 @@ ur_result_t AsanInterceptor::prepareLaunch(
864881
}
865882

866883
// Write shadow memory offset for private memory
867-
if (getContext()->Options.DetectPrivates) {
884+
if (KernelInfo.IsCheckPrivates) {
868885
if (DeviceInfo->Shadow->AllocPrivateShadow(
869886
Queue, NumSG, LaunchInfo.Data.Host.PrivateBase,
870887
LaunchInfo.Data.Host.PrivateShadowOffset,
@@ -950,7 +967,14 @@ AsanInterceptor::findAllocInfoByContext(ur_context_handle_t Context) {
950967

951968
bool ProgramInfo::isKernelInstrumented(ur_kernel_handle_t Kernel) const {
952969
const auto Name = GetKernelName(Kernel);
953-
return InstrumentedKernels.find(Name) != InstrumentedKernels.end();
970+
return KernelMetadataMap.find(Name) != KernelMetadataMap.end();
971+
}
972+
973+
const ProgramInfo::KernelMetada &
974+
ProgramInfo::getKernelMetadata(ur_kernel_handle_t Kernel) const {
975+
const auto Name = GetKernelName(Kernel);
976+
assert(KernelMetadataMap.find(Name) != KernelMetadataMap.end());
977+
return KernelMetadataMap.at(Name);
954978
}
955979

956980
ContextInfo::~ContextInfo() {

unified-runtime/source/loader/layers/sanitizer/asan/asan_interceptor.hpp

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,12 @@ struct KernelInfo {
8686

8787
// sanitized kernel
8888
bool IsInstrumented = false;
89+
// check local memory
90+
bool IsCheckLocals = true;
91+
// check private memory
92+
bool IsCheckPrivates = true;
93+
// check shadow bounds
94+
bool IsCheckShadowBounds = false;
8995

9096
// lock this mutex if following fields are accessed
9197
ur_shared_mutex Mutex;
@@ -95,8 +101,7 @@ struct KernelInfo {
95101
// Need preserve the order of local arguments
96102
std::map<uint32_t, LocalArgsInfo> LocalArgs;
97103

98-
explicit KernelInfo(ur_kernel_handle_t Kernel, bool IsInstrumented)
99-
: Handle(Kernel), IsInstrumented(IsInstrumented) {
104+
explicit KernelInfo(ur_kernel_handle_t Kernel) : Handle(Kernel) {
100105
[[maybe_unused]] auto Result =
101106
getContext()->urDdiTable.Kernel.pfnRetain(Kernel);
102107
assert(Result == UR_RESULT_SUCCESS);
@@ -113,9 +118,15 @@ struct ProgramInfo {
113118
ur_program_handle_t Handle;
114119
std::atomic<int32_t> RefCount = 1;
115120

121+
struct KernelMetada {
122+
bool CheckLocals;
123+
bool CheckPrivates;
124+
bool CheckShadowBounds;
125+
};
126+
116127
// Program is built only once, so we don't need to lock it
117128
std::unordered_set<std::shared_ptr<AllocInfo>> AllocInfoForGlobals;
118-
std::unordered_set<std::string> InstrumentedKernels;
129+
std::unordered_map<std::string, KernelMetada> KernelMetadataMap;
119130

120131
explicit ProgramInfo(ur_program_handle_t Program) : Handle(Program) {
121132
[[maybe_unused]] auto Result =
@@ -130,6 +141,7 @@ struct ProgramInfo {
130141
}
131142

132143
bool isKernelInstrumented(ur_kernel_handle_t Kernel) const;
144+
const KernelMetada &getKernelMetadata(ur_kernel_handle_t Kernel) const;
133145
};
134146

135147
struct ContextInfo {
@@ -277,6 +289,7 @@ struct DeviceGlobalInfo {
277289
struct SpirKernelInfo {
278290
uptr KernelName;
279291
uptr Size;
292+
uptr Flags;
280293
};
281294

282295
class AsanInterceptor {

unified-runtime/source/loader/layers/sanitizer/sanitizer_common/sanitizer_common.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ enum SanitizedKernelFlags : uint32_t {
157157
CHECK_PRIVATES = 1U << 3,
158158
CHECK_GENERICS = 1U << 4,
159159
MSAN_TRACK_ORIGINS = 1U << 5,
160+
ASAN_CHECK_SHADOW_BOUNDS = 1U << 6,
160161
};
161162

162163
} // namespace ur_sanitizer_layer

unified-runtime/source/loader/layers/sanitizer/sanitizer_common/sanitizer_options.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,24 @@ void SanitizerOptions::Init(const std::string &EnvName,
4141

4242
Parser.ParseBool("debug", Debug);
4343
Parser.ParseBool("detect_kernel_arguments", DetectKernelArguments);
44+
45+
bool DetectLocals = true;
4446
Parser.ParseBool("detect_locals", DetectLocals);
47+
if (!DetectLocals) {
48+
UR_LOG_L(Logger, WARN,
49+
"Option `detect_locals` has been deprecated. Just using compiler "
50+
"flag is enough.");
51+
}
52+
53+
bool DetectPrivates = true;
4554
Parser.ParseBool("detect_privates", DetectPrivates);
55+
if (!DetectPrivates) {
56+
UR_LOG_L(
57+
Logger, WARN,
58+
"Option `detect_privates` has been deprecated. Just using compiler "
59+
"flag is enough.");
60+
}
61+
4662
Parser.ParseBool("print_stats", PrintStats);
4763
Parser.ParseBool("detect_leaks", DetectLeaks);
4864
Parser.ParseBool("halt_on_error", HaltOnError);

unified-runtime/source/loader/layers/sanitizer/sanitizer_common/sanitizer_options.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,6 @@ struct SanitizerOptions {
2525
bool Debug = false;
2626
uint64_t MinRZSize = 16;
2727
uint64_t MaxQuarantineSizeMB = 8;
28-
bool DetectLocals = true;
29-
bool DetectPrivates = true;
3028
bool PrintStats = false;
3129
bool DetectKernelArguments = true;
3230
bool DetectLeaks = true;

0 commit comments

Comments
 (0)