Skip to content

Commit 33fe64c

Browse files
[DeviceSanitizer] Do sanitize for device globals in AddressSanitizer pass (#13678)
Now UR already implemented API "urProgramGetGlobalVariablePointer", so we can use it to query the size of device globals and remove "__AsanDeviceGlobalCount". UR Part: oneapi-src/unified-runtime#1584 --------- Co-authored-by: Callum Fare <callum@codeplay.com>
1 parent 1219972 commit 33fe64c

File tree

10 files changed

+123
-182
lines changed

10 files changed

+123
-182
lines changed

clang/lib/Driver/OffloadBundler.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -688,8 +688,11 @@ class ObjectFileHandler final : public FileHandler {
688688
return std::move(Err);
689689

690690
// If we are dealing with a bitcode file do not add special globals
691-
// llvm.used and llvm.compiler.used to the list of defined symbols.
692-
if (SF->isIR() && (Name == "llvm.used" || Name == "llvm.compiler.used"))
691+
// llvm.used and llvm.compiler.used and __AsanDeviceGlobalMetadata to
692+
// the list of defined symbols.
693+
if (SF->isIR() &&
694+
(Name == "llvm.used" || Name == "llvm.compiler.used" ||
695+
Name == "__AsanDeviceGlobalMetadata"))
693696
continue;
694697

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

llvm/include/llvm/SYCLLowerIR/SanitizeDeviceGlobal.h

Lines changed: 0 additions & 23 deletions
This file was deleted.

llvm/lib/SYCLLowerIR/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ add_llvm_component_library(LLVMSYCLLowerIR
6969
SYCLPropagateJointMatrixUsage.cpp
7070
SYCLVirtualFunctionsAnalysis.cpp
7171
SYCLUtils.cpp
72-
SanitizeDeviceGlobal.cpp
7372

7473
LocalAccessorToSharedMemory.cpp
7574
GlobalOffset.cpp

llvm/lib/SYCLLowerIR/SanitizeDeviceGlobal.cpp

Lines changed: 0 additions & 144 deletions
This file was deleted.

llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include "llvm/IR/Use.h"
6565
#include "llvm/IR/Value.h"
6666
#include "llvm/MC/MCSectionMachO.h"
67+
#include "llvm/SYCLLowerIR/DeviceGlobals.h"
6768
#include "llvm/Support/Casting.h"
6869
#include "llvm/Support/CommandLine.h"
6970
#include "llvm/Support/Debug.h"
@@ -465,6 +466,10 @@ static cl::opt<bool>
465466
cl::desc("instrument generic pointer"), cl::Hidden,
466467
cl::init(true));
467468

469+
static cl::opt<bool> ClDeviceGlobals("asan-device-globals",
470+
cl::desc("instrument device globals"),
471+
cl::Hidden, cl::init(true));
472+
468473
// Debug flags.
469474

470475
static cl::opt<int> ClDebug("asan-debug", cl::desc("debug"), cl::Hidden,
@@ -970,6 +975,7 @@ class ModuleAddressSanitizer {
970975
private:
971976
void initializeCallbacks();
972977

978+
void instrumentDeviceGlobal(IRBuilder<> &IRB);
973979
void instrumentGlobals(IRBuilder<> &IRB, bool *CtorComdat);
974980
void InstrumentGlobalsCOFF(IRBuilder<> &IRB,
975981
ArrayRef<GlobalVariable *> ExtendedGlobals,
@@ -1556,12 +1562,23 @@ static bool isJointMatrixAccess(Value *V) {
15561562
return false;
15571563
}
15581564

1565+
static bool isUnsupportedDeviceGlobal(GlobalVariable *G) {
1566+
// Non image scope device globals are implemented by device USM, and the
1567+
// out-of-bounds check for them will be done by sanitizer USM part. So we
1568+
// exclude them here.
1569+
return (!isDeviceGlobalVariable(*G) || !hasDeviceImageScopeProperty(*G));
1570+
}
1571+
15591572
static bool isUnsupportedSPIRAccess(Value *Addr, Instruction *Inst) {
15601573
// Skip SPIR-V built-in varibles
15611574
auto *OrigValue = Addr->stripInBoundsOffsets();
15621575
if (OrigValue->getName().starts_with("__spirv_BuiltIn"))
15631576
return true;
15641577

1578+
GlobalVariable *GV = dyn_cast<GlobalVariable>(OrigValue);
1579+
if (GV && isUnsupportedDeviceGlobal(GV))
1580+
return true;
1581+
15651582
// Ignore load/store for target ext type since we can't know exactly what size
15661583
// it is.
15671584
if (auto *SI = dyn_cast<StoreInst>(Inst))
@@ -2766,6 +2783,71 @@ Instruction *ModuleAddressSanitizer::CreateAsanModuleDtor() {
27662783
return ReturnInst::Create(*C, AsanDtorBB);
27672784
}
27682785

2786+
void ModuleAddressSanitizer::instrumentDeviceGlobal(IRBuilder<> &IRB) {
2787+
auto &DL = M.getDataLayout();
2788+
SmallVector<GlobalVariable *, 8> GlobalsToRemove;
2789+
SmallVector<Constant *, 8> DeviceGlobalMetadata;
2790+
2791+
Type *IntptrTy = M.getDataLayout().getIntPtrType(*C, kSpirOffloadGlobalAS);
2792+
2793+
// Device global meta data is described by a structure
2794+
// size_t device_global_size
2795+
// size_t device_global_size_with_red_zone
2796+
// size_t beginning address of the device global
2797+
StructType *StructTy = StructType::get(IntptrTy, IntptrTy, IntptrTy);
2798+
2799+
for (auto &G : M.globals()) {
2800+
if (isUnsupportedDeviceGlobal(&G))
2801+
continue;
2802+
2803+
Type *Ty = G.getValueType();
2804+
const uint64_t SizeInBytes = DL.getTypeAllocSize(Ty);
2805+
const uint64_t RightRedzoneSize = getRedzoneSizeForGlobal(SizeInBytes);
2806+
Type *RightRedZoneTy = ArrayType::get(IRB.getInt8Ty(), RightRedzoneSize);
2807+
StructType *NewTy = StructType::get(Ty, RightRedZoneTy);
2808+
Constant *NewInitializer = ConstantStruct::get(
2809+
NewTy, G.getInitializer(), Constant::getNullValue(RightRedZoneTy));
2810+
2811+
// Create a new global variable with enough space for a redzone.
2812+
GlobalVariable *NewGlobal = new GlobalVariable(
2813+
M, NewTy, G.isConstant(), G.getLinkage(), NewInitializer, "", &G,
2814+
G.getThreadLocalMode(), G.getAddressSpace());
2815+
NewGlobal->copyAttributesFrom(&G);
2816+
NewGlobal->setComdat(G.getComdat());
2817+
NewGlobal->setAlignment(Align(getMinRedzoneSizeForGlobal()));
2818+
NewGlobal->copyMetadata(&G, 0);
2819+
2820+
Value *Indices2[2];
2821+
Indices2[0] = IRB.getInt32(0);
2822+
Indices2[1] = IRB.getInt32(0);
2823+
2824+
G.replaceAllUsesWith(
2825+
ConstantExpr::getGetElementPtr(NewTy, NewGlobal, Indices2, true));
2826+
NewGlobal->takeName(&G);
2827+
GlobalsToRemove.push_back(&G);
2828+
DeviceGlobalMetadata.push_back(ConstantStruct::get(
2829+
StructTy, ConstantInt::get(IntptrTy, SizeInBytes),
2830+
ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize),
2831+
ConstantExpr::getPointerCast(NewGlobal, IntptrTy)));
2832+
}
2833+
2834+
if (GlobalsToRemove.empty())
2835+
return;
2836+
2837+
// Create meta data global to record device globals' information
2838+
ArrayType *ArrayTy = ArrayType::get(StructTy, DeviceGlobalMetadata.size());
2839+
Constant *MetadataInitializer =
2840+
ConstantArray::get(ArrayTy, DeviceGlobalMetadata);
2841+
GlobalVariable *AsanDeviceGlobalMetadata = new GlobalVariable(
2842+
M, MetadataInitializer->getType(), false, GlobalValue::AppendingLinkage,
2843+
MetadataInitializer, "__AsanDeviceGlobalMetadata", nullptr,
2844+
GlobalValue::NotThreadLocal, 1);
2845+
AsanDeviceGlobalMetadata->setUnnamedAddr(GlobalValue::UnnamedAddr::Local);
2846+
2847+
for (auto *G : GlobalsToRemove)
2848+
G->eraseFromParent();
2849+
}
2850+
27692851
void ModuleAddressSanitizer::InstrumentGlobalsCOFF(
27702852
IRBuilder<> &IRB, ArrayRef<GlobalVariable *> ExtendedGlobals,
27712853
ArrayRef<Constant *> MetadataInitializers) {
@@ -3234,6 +3316,11 @@ bool ModuleAddressSanitizer::instrumentModule() {
32343316
auto *MD = M.getOrInsertNamedMetadata("device.sanitizer");
32353317
Metadata *MDVals[] = {MDString::get(Ctx, "asan")};
32363318
MD->addOperand(MDNode::get(Ctx, MDVals));
3319+
3320+
if (ClDeviceGlobals) {
3321+
IRBuilder<> IRB(*C);
3322+
instrumentDeviceGlobal(IRB);
3323+
}
32373324
}
32383325

32393326
const uint64_t Priority = GetCtorAndDtorPriority(TargetTriple);

llvm/lib/Transforms/Instrumentation/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ add_llvm_component_library(LLVMInstrumentation
3939
Core
4040
Demangle
4141
MC
42+
SYCLLowerIR
4243
Support
4344
TargetParser
4445
TransformUtils
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
; RUN: opt < %s -passes=asan -asan-instrumentation-with-call-threshold=0 -asan-stack=0 -asan-globals=0 -asan-constructor-kind=none -S | FileCheck %s
2+
3+
; check that image scope device globals can be correctly instrumented.
4+
5+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
6+
target triple = "spir64-unknown-unknown"
7+
8+
@dev_global = addrspace(1) global { [4 x i32] } zeroinitializer #0
9+
10+
; CHECK: @dev_global = addrspace(1) global { { [4 x i32] }, [16 x i8] }
11+
; CHECK: @__AsanDeviceGlobalMetadata = appending local_unnamed_addr addrspace(1) global [1 x { i64, i64, i64 }] [{ i64, i64, i64 } { i64 16, i64 32, i64 ptrtoint (ptr addrspace(1) @dev_global to i64) }]
12+
13+
attributes #0 = { "sycl-device-global-size"="16" "sycl-device-image-scope" }
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
; RUN: opt < %s -passes=asan -asan-instrumentation-with-call-threshold=0 -asan-stack=0 -asan-globals=0 -asan-constructor-kind=none -S | FileCheck %s
2+
3+
; check non image scope device globals will not be instrumented.
4+
5+
target datalayout = "e-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-n8:16:32:64"
6+
target triple = "spir64-unknown-unknown"
7+
8+
@dev_global = addrspace(1) global { ptr addrspace(1), [4 x i32] } zeroinitializer
9+
10+
; CHECK: @dev_global = addrspace(1) global { ptr addrspace(1), [4 x i32] }
11+
; CHECK-NOT: @__AsanDeviceGlobalMetadata

llvm/tools/sycl-post-link/sycl-post-link.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,6 @@
4040
#include "llvm/SYCLLowerIR/ModuleSplitter.h"
4141
#include "llvm/SYCLLowerIR/SYCLJointMatrixTransform.h"
4242
#include "llvm/SYCLLowerIR/SYCLUtils.h"
43-
#include "llvm/SYCLLowerIR/SanitizeDeviceGlobal.h"
4443
#include "llvm/SYCLLowerIR/SpecConstants.h"
4544
#include "llvm/SYCLLowerIR/Support.h"
4645
#include "llvm/Support/CommandLine.h"
@@ -791,11 +790,6 @@ processInputModule(std::unique_ptr<Module> M) {
791790
if (M->getTargetTriple().find("spir") != std::string::npos)
792791
Modified |= removeDeviceGlobalFromCompilerUsed(*M.get());
793792

794-
// Instrument each image scope device globals if the module has been
795-
// instrumented by sanitizer pass.
796-
if (isModuleUsingAsan(*M))
797-
Modified |= runModulePass<SanitizeDeviceGlobalPass>(*M);
798-
799793
// Transform Joint Matrix builtin calls to align them with SPIR-V friendly
800794
// LLVM IR specification.
801795
Modified |= runModulePass<SYCLJointMatrixTransformPass>(*M);
Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# commit 30391c65d2d2ccc7ee3688a14815804bfb7fdf05
2-
# Merge: 5e6d79b3 58dabfe8
1+
# commit 0ea47d7c70b9a21a3d90612a0a0e7525034e62f7
2+
# Merge: e3247c23 e36941cb
33
# Author: Callum Fare <callum@codeplay.com>
4-
# Date: Fri Nov 15 15:13:20 2024 +0000
5-
# Merge pull request #2222 from RossBrunton/ross/cfi
6-
# Enable -flto and -fsanitize=cfi in clang
7-
set(UNIFIED_RUNTIME_TAG 30391c65d2d2ccc7ee3688a14815804bfb7fdf05)
4+
# Date: Tue Nov 19 10:24:08 2024 +0000
5+
# Merge pull request #1584 from zhaomaosu/simplify-device-global
6+
# [DeviceSanitizer] Remove device global "__AsanDeviceGlobalCount"
7+
set(UNIFIED_RUNTIME_TAG 0ea47d7c70b9a21a3d90612a0a0e7525034e62f7)

0 commit comments

Comments
 (0)