|
64 | 64 | #include "llvm/IR/Use.h"
|
65 | 65 | #include "llvm/IR/Value.h"
|
66 | 66 | #include "llvm/MC/MCSectionMachO.h"
|
| 67 | +#include "llvm/SYCLLowerIR/DeviceGlobals.h" |
67 | 68 | #include "llvm/Support/Casting.h"
|
68 | 69 | #include "llvm/Support/CommandLine.h"
|
69 | 70 | #include "llvm/Support/Debug.h"
|
@@ -465,6 +466,10 @@ static cl::opt<bool>
|
465 | 466 | cl::desc("instrument generic pointer"), cl::Hidden,
|
466 | 467 | cl::init(true));
|
467 | 468 |
|
| 469 | +static cl::opt<bool> ClDeviceGlobals("asan-device-globals", |
| 470 | + cl::desc("instrument device globals"), |
| 471 | + cl::Hidden, cl::init(true)); |
| 472 | + |
468 | 473 | // Debug flags.
|
469 | 474 |
|
470 | 475 | static cl::opt<int> ClDebug("asan-debug", cl::desc("debug"), cl::Hidden,
|
@@ -970,6 +975,7 @@ class ModuleAddressSanitizer {
|
970 | 975 | private:
|
971 | 976 | void initializeCallbacks();
|
972 | 977 |
|
| 978 | + void instrumentDeviceGlobal(IRBuilder<> &IRB); |
973 | 979 | void instrumentGlobals(IRBuilder<> &IRB, bool *CtorComdat);
|
974 | 980 | void InstrumentGlobalsCOFF(IRBuilder<> &IRB,
|
975 | 981 | ArrayRef<GlobalVariable *> ExtendedGlobals,
|
@@ -1556,12 +1562,23 @@ static bool isJointMatrixAccess(Value *V) {
|
1556 | 1562 | return false;
|
1557 | 1563 | }
|
1558 | 1564 |
|
| 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 | + |
1559 | 1572 | static bool isUnsupportedSPIRAccess(Value *Addr, Instruction *Inst) {
|
1560 | 1573 | // Skip SPIR-V built-in varibles
|
1561 | 1574 | auto *OrigValue = Addr->stripInBoundsOffsets();
|
1562 | 1575 | if (OrigValue->getName().starts_with("__spirv_BuiltIn"))
|
1563 | 1576 | return true;
|
1564 | 1577 |
|
| 1578 | + GlobalVariable *GV = dyn_cast<GlobalVariable>(OrigValue); |
| 1579 | + if (GV && isUnsupportedDeviceGlobal(GV)) |
| 1580 | + return true; |
| 1581 | + |
1565 | 1582 | // Ignore load/store for target ext type since we can't know exactly what size
|
1566 | 1583 | // it is.
|
1567 | 1584 | if (auto *SI = dyn_cast<StoreInst>(Inst))
|
@@ -2766,6 +2783,71 @@ Instruction *ModuleAddressSanitizer::CreateAsanModuleDtor() {
|
2766 | 2783 | return ReturnInst::Create(*C, AsanDtorBB);
|
2767 | 2784 | }
|
2768 | 2785 |
|
| 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 | + |
2769 | 2851 | void ModuleAddressSanitizer::InstrumentGlobalsCOFF(
|
2770 | 2852 | IRBuilder<> &IRB, ArrayRef<GlobalVariable *> ExtendedGlobals,
|
2771 | 2853 | ArrayRef<Constant *> MetadataInitializers) {
|
@@ -3234,6 +3316,11 @@ bool ModuleAddressSanitizer::instrumentModule() {
|
3234 | 3316 | auto *MD = M.getOrInsertNamedMetadata("device.sanitizer");
|
3235 | 3317 | Metadata *MDVals[] = {MDString::get(Ctx, "asan")};
|
3236 | 3318 | MD->addOperand(MDNode::get(Ctx, MDVals));
|
| 3319 | + |
| 3320 | + if (ClDeviceGlobals) { |
| 3321 | + IRBuilder<> IRB(*C); |
| 3322 | + instrumentDeviceGlobal(IRB); |
| 3323 | + } |
3237 | 3324 | }
|
3238 | 3325 |
|
3239 | 3326 | const uint64_t Priority = GetCtorAndDtorPriority(TargetTriple);
|
|
0 commit comments