@@ -839,8 +839,6 @@ struct AddressSanitizer {
839
839
bool maybeInsertAsanInitAtFunctionEntry (Function &F);
840
840
bool maybeInsertDynamicShadowAtFunctionEntry (Function &F);
841
841
void markEscapedLocalAllocas (Function &F);
842
- void instrumentSyclStaticLocalMemory (CallInst *CI,
843
- ArrayRef<Instruction *> RetVec);
844
842
bool instrumentSyclDynamicLocalMemory (Function &F,
845
843
ArrayRef<Instruction *> RetVec);
846
844
void instrumentInitAsanLaunchInfo (Function &F, const TargetLibraryInfo *TLI);
@@ -889,8 +887,6 @@ struct AddressSanitizer {
889
887
ShadowMapping Mapping;
890
888
FunctionCallee AsanHandleNoReturnFunc;
891
889
FunctionCallee AsanPtrCmpFunction, AsanPtrSubFunction;
892
- FunctionCallee AsanSetShadowStaticLocalFunc;
893
- FunctionCallee AsanUnpoisonShadowStaticLocalFunc;
894
890
FunctionCallee AsanSetShadowDynamicLocalFunc;
895
891
FunctionCallee AsanUnpoisonShadowDynamicLocalFunc;
896
892
Constant *AsanShadowGlobal;
@@ -972,6 +968,10 @@ class ModuleAddressSanitizer {
972
968
void initializeCallbacks ();
973
969
974
970
void instrumentDeviceGlobal (IRBuilder<> &IRB);
971
+ void instrumentSyclStaticLocalMemory (IRBuilder<> &IRB);
972
+ void initializeRetVecMap (Function *F);
973
+ void initializeKernelCallerMap (Function *F);
974
+
975
975
void instrumentGlobals (IRBuilder<> &IRB, bool *CtorComdat);
976
976
void InstrumentGlobalsCOFF (IRBuilder<> &IRB,
977
977
ArrayRef<GlobalVariable *> ExtendedGlobals,
@@ -1030,10 +1030,15 @@ class ModuleAddressSanitizer {
1030
1030
FunctionCallee AsanUnregisterImageGlobals;
1031
1031
FunctionCallee AsanRegisterElfGlobals;
1032
1032
FunctionCallee AsanUnregisterElfGlobals;
1033
+ FunctionCallee AsanSetShadowStaticLocalFunc;
1034
+ FunctionCallee AsanUnpoisonShadowStaticLocalFunc;
1033
1035
1034
1036
Function *AsanCtorFunction = nullptr ;
1035
1037
Function *AsanDtorFunction = nullptr ;
1036
1038
GlobalVariable *ModuleName = nullptr ;
1039
+
1040
+ DenseMap<Function *, SmallVector<Instruction *, 8 >> KernelToRetVecMap;
1041
+ DenseMap<Function *, DenseSet<Function *>> FuncToKernelCallerMap;
1037
1042
};
1038
1043
1039
1044
// Stack poisoning does not play well with exception handling.
@@ -1661,6 +1666,9 @@ static bool isUnsupportedDeviceGlobal(GlobalVariable *G) {
1661
1666
if (G->getName ().starts_with (" __Asan" ))
1662
1667
return true ;
1663
1668
1669
+ if (G->getAddressSpace () == kSpirOffloadLocalAS )
1670
+ return true ;
1671
+
1664
1672
Attribute Attr = G->getAttribute (" sycl-device-image-scope" );
1665
1673
return (!Attr.isStringAttribute () || Attr.getValueAsString () == " false" );
1666
1674
}
@@ -1765,68 +1773,6 @@ Value *AddressSanitizer::memToShadow(Value *Shadow, IRBuilder<> &IRB,
1765
1773
return IRB.CreateAdd (Shadow, ShadowBase);
1766
1774
}
1767
1775
1768
- static uint64_t getSizeAndRedzoneSizeForLocal (uint64_t Size,
1769
- uint64_t Granularity,
1770
- uint64_t Alignment) {
1771
- uint64_t Res = 0 ;
1772
- if (Size <= 4 )
1773
- Res = 16 ;
1774
- else if (Size <= 16 )
1775
- Res = 32 ;
1776
- else if (Size <= 128 )
1777
- Res = Size + 32 ;
1778
- else if (Size <= 512 )
1779
- Res = Size + 64 ;
1780
- else if (Size <= 4096 )
1781
- Res = Size + 128 ;
1782
- else
1783
- Res = Size + 256 ;
1784
- return alignTo (std::max (Res, 2 * Granularity), Alignment);
1785
- }
1786
-
1787
- // Instument static local memory
1788
- void AddressSanitizer::instrumentSyclStaticLocalMemory (
1789
- CallInst *CI, ArrayRef<Instruction *> RetVec) {
1790
- InstrumentationIRBuilder IRB (CI->getNextNode ());
1791
- auto *Size = cast<ConstantInt>(CI->getArgOperand (0 ));
1792
- auto *Alignment = cast<ConstantInt>(CI->getArgOperand (1 ));
1793
-
1794
- const auto Granularity = 1 << Mapping.Scale ;
1795
- // The base address of local memory needs to align to granularity
1796
- const auto Align = alignTo (Alignment->getZExtValue (), Granularity);
1797
-
1798
- auto *SizeWithRedZone = ConstantInt::get (
1799
- IntptrTy, getSizeAndRedzoneSizeForLocal (Size->getZExtValue (), Granularity,
1800
- Alignment->getZExtValue ()));
1801
-
1802
- auto *NewCI =
1803
- IRB.CreateCall (CI->getCalledFunction (),
1804
- {SizeWithRedZone, ConstantInt::get (IntptrTy, Align)});
1805
-
1806
- // __asan_set_shadow_static_local(
1807
- // uptr beg,
1808
- // size_t size,
1809
- // size_t size_with_redzone,
1810
- // )
1811
- auto LocalAddr = IRB.CreatePointerCast (NewCI, IntptrTy);
1812
- IRB.CreateCall (AsanSetShadowStaticLocalFunc,
1813
- {LocalAddr, Size, SizeWithRedZone});
1814
-
1815
- // __asan_unpoison_shadow_static_local(
1816
- // uptr beg,
1817
- // size_t size,
1818
- // size_t size_with_redzone,
1819
- // )
1820
- for (Instruction *Ret : RetVec) {
1821
- IRBuilder<> IRBRet (Ret);
1822
- IRBRet.CreateCall (AsanUnpoisonShadowStaticLocalFunc,
1823
- {LocalAddr, Size, SizeWithRedZone});
1824
- }
1825
-
1826
- CI->replaceAllUsesWith (NewCI);
1827
- CI->eraseFromParent ();
1828
- }
1829
-
1830
1776
// Instument dynamic local memory
1831
1777
bool AddressSanitizer::instrumentSyclDynamicLocalMemory (
1832
1778
Function &F, ArrayRef<Instruction *> RetVec) {
@@ -2810,6 +2756,24 @@ void ModuleAddressSanitizer::initializeCallbacks() {
2810
2756
AsanUnregisterElfGlobals =
2811
2757
M.getOrInsertFunction (kAsanUnregisterElfGlobalsName , IRB.getVoidTy (),
2812
2758
IntptrTy, IntptrTy, IntptrTy);
2759
+
2760
+ // __asan_set_shadow_static_local(
2761
+ // uptr ptr,
2762
+ // size_t size,
2763
+ // size_t size_with_redzone
2764
+ // )
2765
+ AsanSetShadowStaticLocalFunc =
2766
+ M.getOrInsertFunction (" __asan_set_shadow_static_local" , IRB.getVoidTy (),
2767
+ IntptrTy, IntptrTy, IntptrTy);
2768
+
2769
+ // __asan_unpoison_shadow_static_local(
2770
+ // uptr ptr,
2771
+ // size_t size,
2772
+ // size_t size_with_redzone
2773
+ // )
2774
+ AsanUnpoisonShadowStaticLocalFunc =
2775
+ M.getOrInsertFunction (" __asan_unpoison_shadow_static_local" ,
2776
+ IRB.getVoidTy (), IntptrTy, IntptrTy, IntptrTy);
2813
2777
}
2814
2778
2815
2779
// Put the metadata and the instrumented global in the same group. This ensures
@@ -2949,6 +2913,164 @@ void ModuleAddressSanitizer::instrumentDeviceGlobal(IRBuilder<> &IRB) {
2949
2913
G->eraseFromParent ();
2950
2914
}
2951
2915
2916
+ static void getFunctionsOfUser (User *User, DenseSet<Function *> &Functions) {
2917
+ if (Instruction *Inst = dyn_cast<Instruction>(User)) {
2918
+ Functions.insert (Inst->getFunction ());
2919
+ } else if (ConstantExpr *CE = dyn_cast<ConstantExpr>(User)) {
2920
+ for (auto *U : CE->users ())
2921
+ getFunctionsOfUser (U, Functions);
2922
+ }
2923
+ }
2924
+
2925
+ void ModuleAddressSanitizer::initializeRetVecMap (Function *F) {
2926
+ if (KernelToRetVecMap.find (F) != KernelToRetVecMap.end ())
2927
+ return ;
2928
+
2929
+ SmallVector<Instruction *, 8 > RetVec;
2930
+ for (auto &BB : *F) {
2931
+ for (auto &Inst : BB) {
2932
+ if (ReturnInst *RI = dyn_cast<ReturnInst>(&Inst)) {
2933
+ if (CallInst *CI = RI->getParent ()->getTerminatingMustTailCall ())
2934
+ RetVec.push_back (CI);
2935
+ else
2936
+ RetVec.push_back (RI);
2937
+ } else if (ResumeInst *RI = dyn_cast<ResumeInst>(&Inst)) {
2938
+ RetVec.push_back (RI);
2939
+ } else if (CleanupReturnInst *CRI = dyn_cast<CleanupReturnInst>(&Inst)) {
2940
+ RetVec.push_back (CRI);
2941
+ }
2942
+ }
2943
+ }
2944
+
2945
+ KernelToRetVecMap[F] = std::move (RetVec);
2946
+ }
2947
+
2948
+ void ModuleAddressSanitizer::initializeKernelCallerMap (Function *F) {
2949
+ if (FuncToKernelCallerMap.find (F) != FuncToKernelCallerMap.end ())
2950
+ return ;
2951
+
2952
+ for (auto *U : F->users ()) {
2953
+ if (Instruction *Inst = dyn_cast<Instruction>(U)) {
2954
+ Function *Caller = Inst->getFunction ();
2955
+ if (Caller->getCallingConv () == CallingConv::SPIR_KERNEL) {
2956
+ FuncToKernelCallerMap[F].insert (Caller);
2957
+ continue ;
2958
+ }
2959
+ initializeKernelCallerMap (Caller);
2960
+ FuncToKernelCallerMap[F].insert (FuncToKernelCallerMap[Caller].begin (),
2961
+ FuncToKernelCallerMap[Caller].end ());
2962
+ }
2963
+ }
2964
+ }
2965
+
2966
+ // Instument static local memory
2967
+ void ModuleAddressSanitizer::instrumentSyclStaticLocalMemory (IRBuilder<> &IRB) {
2968
+ auto &DL = M.getDataLayout ();
2969
+ SmallVector<GlobalVariable *, 8 > GlobalsToRemove;
2970
+ SmallVector<GlobalVariable *, 8 > LocalGlobals;
2971
+
2972
+ Type *IntptrTy = M.getDataLayout ().getIntPtrType (*C, kSpirOffloadGlobalAS );
2973
+
2974
+ // Step1. Create a new global variable with enough space for a redzone.
2975
+ for (auto &G : M.globals ()) {
2976
+ if (G.getAddressSpace () != kSpirOffloadLocalAS )
2977
+ continue ;
2978
+ if (G.getName ().starts_with (" __Asan" ))
2979
+ continue ;
2980
+
2981
+ Type *Ty = G.getValueType ();
2982
+ const uint64_t SizeInBytes = DL.getTypeAllocSize (Ty);
2983
+ const uint64_t RightRedzoneSize = getRedzoneSizeForGlobal (SizeInBytes);
2984
+ Type *RightRedZoneTy = ArrayType::get (IRB.getInt8Ty (), RightRedzoneSize);
2985
+ StructType *NewTy = StructType::get (Ty, RightRedZoneTy);
2986
+ Constant *NewInitializer =
2987
+ G.hasInitializer ()
2988
+ ? ConstantStruct::get (NewTy, G.getInitializer (),
2989
+ Constant::getNullValue (RightRedZoneTy))
2990
+ : nullptr ;
2991
+
2992
+ GlobalVariable *NewGlobal = new GlobalVariable (
2993
+ M, NewTy, G.isConstant (), G.getLinkage (), NewInitializer, " " , &G,
2994
+ G.getThreadLocalMode (), G.getAddressSpace ());
2995
+ NewGlobal->copyAttributesFrom (&G);
2996
+ NewGlobal->setComdat (G.getComdat ());
2997
+ NewGlobal->setAlignment (Align (getMinRedzoneSizeForGlobal ()));
2998
+ NewGlobal->copyMetadata (&G, 0 );
2999
+
3000
+ Value *Indices2[2 ];
3001
+ Indices2[0 ] = IRB.getInt32 (0 );
3002
+ Indices2[1 ] = IRB.getInt32 (0 );
3003
+
3004
+ G.replaceAllUsesWith (
3005
+ ConstantExpr::getGetElementPtr (NewTy, NewGlobal, Indices2, true ));
3006
+ NewGlobal->takeName (&G);
3007
+ GlobalsToRemove.push_back (&G);
3008
+ LocalGlobals.push_back (NewGlobal);
3009
+ }
3010
+
3011
+ if (GlobalsToRemove.empty ())
3012
+ return ;
3013
+
3014
+ for (auto *G : GlobalsToRemove)
3015
+ G->eraseFromParent ();
3016
+
3017
+ // Step2. Instrument initialization functions on kernel
3018
+ DenseMap<Function *, Instruction *> FuncToLaunchInfoMap;
3019
+ auto Instrument = [&](GlobalVariable *G, Function *F) {
3020
+ StructType *Type = cast<StructType>(G->getValueType ());
3021
+ const uint64_t Size = DL.getTypeAllocSize (Type->getElementType (0 ));
3022
+ const uint64_t SizeWithRedZone = DL.getTypeAllocSize (Type);
3023
+
3024
+ // Poison shadow of static local memory
3025
+ if (FuncToLaunchInfoMap.find (F) == FuncToLaunchInfoMap.end ()) {
3026
+ for (auto &Inst : F->getEntryBlock ()) {
3027
+ auto *SI = dyn_cast<StoreInst>(&Inst);
3028
+ if (SI && (SI->getPointerOperand ()->getName () == " __AsanLaunchInfo" )) {
3029
+ FuncToLaunchInfoMap[F] = &Inst;
3030
+ break ;
3031
+ }
3032
+ }
3033
+ }
3034
+ assert (FuncToLaunchInfoMap.find (F) != FuncToLaunchInfoMap.end () &&
3035
+ " All spir kernels should be instrumented." );
3036
+
3037
+ IRBuilder<> Builder (FuncToLaunchInfoMap[F]->getNextNode ());
3038
+ Builder.CreateCall (AsanSetShadowStaticLocalFunc,
3039
+ {Builder.CreatePointerCast (G, IntptrTy),
3040
+ ConstantInt::get (IntptrTy, Size),
3041
+ ConstantInt::get (IntptrTy, SizeWithRedZone)});
3042
+
3043
+ // Unpoison shadow of static local memory, required by CPU device
3044
+ initializeRetVecMap (F);
3045
+ for (auto *RI : KernelToRetVecMap[F]) {
3046
+ IRBuilder<> Builder (RI);
3047
+ Builder.CreateCall (AsanUnpoisonShadowStaticLocalFunc,
3048
+ {Builder.CreatePointerCast (G, IntptrTy),
3049
+ ConstantInt::get (IntptrTy, Size),
3050
+ ConstantInt::get (IntptrTy, SizeWithRedZone)});
3051
+ }
3052
+ };
3053
+
3054
+ // We only instrument on spir_kernel, because local variables are
3055
+ // kind of global variable
3056
+ for (auto *G : LocalGlobals) {
3057
+ DenseSet<Function *> InstrumentedFunc;
3058
+ for (auto *User : G->users ())
3059
+ getFunctionsOfUser (User, InstrumentedFunc);
3060
+ for (Function *F : InstrumentedFunc) {
3061
+ if (F->getCallingConv () == CallingConv::SPIR_KERNEL) {
3062
+ Instrument (G, F);
3063
+ continue ;
3064
+ }
3065
+ // Get root spir_kernel of spir_func
3066
+ initializeKernelCallerMap (F);
3067
+ for (Function *Kernel : FuncToKernelCallerMap[F])
3068
+ if (!InstrumentedFunc.contains (Kernel))
3069
+ Instrument (G, Kernel);
3070
+ }
3071
+ }
3072
+ }
3073
+
2952
3074
void ModuleAddressSanitizer::InstrumentGlobalsCOFF (
2953
3075
IRBuilder<> &IRB, ArrayRef<GlobalVariable *> ExtendedGlobals,
2954
3076
ArrayRef<Constant *> MetadataInitializers) {
@@ -3412,12 +3534,10 @@ bool ModuleAddressSanitizer::instrumentModule() {
3412
3534
}
3413
3535
3414
3536
if (TargetTriple.isSPIROrSPIRV ()) {
3415
- // Add module metadata "device.sanitizer" for sycl-post-link
3416
- LLVMContext &Ctx = M.getContext ();
3417
- auto *MD = M.getOrInsertNamedMetadata (" device.sanitizer" );
3418
- Metadata *MDVals[] = {MDString::get (Ctx, " asan" )};
3419
- MD->addOperand (MDNode::get (Ctx, MDVals));
3420
-
3537
+ if (ClSpirOffloadLocals) {
3538
+ IRBuilder<> IRB (*C);
3539
+ instrumentSyclStaticLocalMemory (IRB);
3540
+ }
3421
3541
if (ClDeviceGlobals) {
3422
3542
IRBuilder<> IRB (*C);
3423
3543
instrumentDeviceGlobal (IRB);
@@ -3564,23 +3684,6 @@ void AddressSanitizer::initializeCallbacks(const TargetLibraryInfo *TLI) {
3564
3684
ArrayType::get (IRB.getInt8Ty (), 0 ));
3565
3685
3566
3686
if (TargetTriple.isSPIROrSPIRV ()) {
3567
- // __asan_set_shadow_static_local(
3568
- // uptr ptr,
3569
- // size_t size,
3570
- // size_t size_with_redzone
3571
- // )
3572
- AsanSetShadowStaticLocalFunc =
3573
- M.getOrInsertFunction (" __asan_set_shadow_static_local" , IRB.getVoidTy (),
3574
- IntptrTy, IntptrTy, IntptrTy);
3575
-
3576
- // __asan_unpoison_shadow_static_local(
3577
- // uptr ptr,
3578
- // size_t size,
3579
- // )
3580
- AsanUnpoisonShadowStaticLocalFunc =
3581
- M.getOrInsertFunction (" __asan_unpoison_shadow_static_local" ,
3582
- IRB.getVoidTy (), IntptrTy, IntptrTy, IntptrTy);
3583
-
3584
3687
// __asan_set_shadow_dynamic_local(
3585
3688
// uptr ptr,
3586
3689
// uint32_t num_args
@@ -3747,7 +3850,6 @@ bool AddressSanitizer::instrumentFunction(Function &F,
3747
3850
SmallVector<Instruction *, 8 > NoReturnCalls;
3748
3851
SmallVector<BasicBlock *, 16 > AllBlocks;
3749
3852
SmallVector<Instruction *, 16 > PointerComparisonsOrSubtracts;
3750
- SmallVector<CallInst *, 8 > SyclAllocateLocalMemoryCalls;
3751
3853
3752
3854
// Fill the set of memory operations to instrument.
3753
3855
for (auto &BB : F) {
@@ -3800,16 +3902,8 @@ bool AddressSanitizer::instrumentFunction(Function &F,
3800
3902
NoReturnCalls.push_back (CB);
3801
3903
}
3802
3904
}
3803
- if (CallInst *CI = dyn_cast<CallInst>(&Inst)) {
3804
- if (TargetTriple.isSPIROrSPIRV () && CI->getCalledFunction () &&
3805
- CI->getCalledFunction ()->getCallingConv () ==
3806
- llvm::CallingConv::SPIR_FUNC &&
3807
- CI->getCalledFunction ()->getName () ==
3808
- " __sycl_allocateLocalMemory" )
3809
- SyclAllocateLocalMemoryCalls.push_back (CI);
3810
- else
3811
- maybeMarkSanitizerLibraryCallNoBuiltin (CI, TLI);
3812
- }
3905
+ if (CallInst *CI = dyn_cast<CallInst>(&Inst))
3906
+ maybeMarkSanitizerLibraryCallNoBuiltin (CI, TLI);
3813
3907
}
3814
3908
if (NumInsnsPerBB >= ClMaxInsnsToInstrumentPerBB) break ;
3815
3909
}
@@ -3855,13 +3949,9 @@ bool AddressSanitizer::instrumentFunction(Function &F,
3855
3949
if (ChangedStack || !NoReturnCalls.empty ())
3856
3950
FunctionModified = true ;
3857
3951
3858
- // We need to instrument dynamic/static local arguments after stack poisoner
3952
+ // We need to instrument dynamic local arguments after stack poisoner
3859
3953
if (TargetTriple.isSPIROrSPIRV ()) {
3860
- for (auto *CI : SyclAllocateLocalMemoryCalls) {
3861
- instrumentSyclStaticLocalMemory (CI, FSP.RetVec );
3862
- FunctionModified = true ;
3863
- }
3864
- if (F.getCallingConv () == CallingConv::SPIR_KERNEL) {
3954
+ if (ClSpirOffloadLocals && F.getCallingConv () == CallingConv::SPIR_KERNEL) {
3865
3955
FunctionModified |= instrumentSyclDynamicLocalMemory (F, FSP.RetVec );
3866
3956
}
3867
3957
}
0 commit comments