@@ -80,8 +80,8 @@ struct TypeSanitizer {
8080
8181 void initializeCallbacks (Module &M);
8282
83- Value *getShadowBase (Function &F);
84- Value *getAppMemMask (Function &F);
83+ Instruction *getShadowBase (Function &F);
84+ Instruction *getAppMemMask (Function &F);
8585
8686 bool instrumentWithShadowUpdate (IRBuilder<> &IRB, const MDNode *TBAAMD,
8787 Value *Ptr, uint64_t AccessSize, bool IsRead,
@@ -93,8 +93,8 @@ struct TypeSanitizer {
9393
9494 // / Memory-related intrinsics/instructions reset the type of the destination
9595 // / memory (including allocas and byval arguments).
96- bool instrumentMemInst (Value *I, Value *& ShadowBase, Value *&AppMemMask ,
97- const DataLayout &DL);
96+ bool instrumentMemInst (Value *I, Instruction * ShadowBase,
97+ Instruction *AppMemMask, const DataLayout &DL);
9898
9999 std::string getAnonymousStructIdentifier (const MDNode *MD,
100100 TypeNameMapTy &TypeNames);
@@ -450,14 +450,14 @@ bool TypeSanitizer::generateTypeDescriptor(
450450 return true ;
451451}
452452
453- Value *TypeSanitizer::getShadowBase (Function &F) {
453+ Instruction *TypeSanitizer::getShadowBase (Function &F) {
454454 IRBuilder<> IRB (&F.front ().front ());
455455 Constant *GlobalShadowAddress =
456456 F.getParent ()->getOrInsertGlobal (kTysanShadowMemoryAddress , IntptrTy);
457457 return IRB.CreateLoad (IntptrTy, GlobalShadowAddress, " shadow.base" );
458458}
459459
460- Value *TypeSanitizer::getAppMemMask (Function &F) {
460+ Instruction *TypeSanitizer::getAppMemMask (Function &F) {
461461 IRBuilder<> IRB (&F.front ().front ());
462462 Value *GlobalAppMemMask =
463463 F.getParent ()->getOrInsertGlobal (kTysanAppMemMask , IntptrTy);
@@ -548,8 +548,8 @@ bool TypeSanitizer::run(Function &F, const TargetLibraryInfo &TLI) {
548548 bool SanitizeFunction = F.hasFnAttribute (Attribute::SanitizeType);
549549 bool NeedsInstrumentation =
550550 MemTypeResetInsts.empty () && MemoryAccesses.empty ();
551- Value *ShadowBase = NeedsInstrumentation ? nullptr : getShadowBase (F);
552- Value *AppMemMask = NeedsInstrumentation ? nullptr : getAppMemMask (F);
551+ Instruction *ShadowBase = NeedsInstrumentation ? nullptr : getShadowBase (F);
552+ Instruction *AppMemMask = NeedsInstrumentation ? nullptr : getAppMemMask (F);
553553 for (const auto &[I, MLoc] : MemoryAccesses) {
554554 IRBuilder<> IRB (I);
555555 assert (MLoc.Size .isPrecise ());
@@ -569,7 +569,7 @@ bool TypeSanitizer::run(Function &F, const TargetLibraryInfo &TLI) {
569569 return Res;
570570}
571571
572- static Value *ConvertToShadowDataInt (IRBuilder<> &IRB, Value *Ptr,
572+ static Value *convertToShadowDataInt (IRBuilder<> &IRB, Value *Ptr,
573573 Type *IntptrTy, uint64_t PtrShift,
574574 Value *ShadowBase, Value *AppMemMask) {
575575 return IRB.CreateAdd (
@@ -593,7 +593,7 @@ bool TypeSanitizer::instrumentWithShadowUpdate(
593593
594594 Value *TD = IRB.CreateBitCast (TDGV, IRB.getPtrTy ());
595595
596- Value *ShadowDataInt = ConvertToShadowDataInt (IRB, Ptr, IntptrTy, PtrShift,
596+ Value *ShadowDataInt = convertToShadowDataInt (IRB, Ptr, IntptrTy, PtrShift,
597597 ShadowBase, AppMemMask);
598598 Type *Int8PtrPtrTy = PointerType::get (IRB.getPtrTy (), 0 );
599599 Value *ShadowData =
@@ -620,105 +620,155 @@ bool TypeSanitizer::instrumentWithShadowUpdate(
620620 }
621621 };
622622
623- if (!ForceSetType && (!ClWritesAlwaysSetType || IsRead)) {
624- // We need to check the type here. If the type is unknown, then the read
625- // sets the type. If the type is known, then it is checked. If the type
626- // doesn't match, then we call the runtime (which may yet determine that
627- // the mismatch is okay).
628- LLVMContext &C = IRB.getContext ();
629- MDNode *UnlikelyBW = MDBuilder (C).createBranchWeights (1 , 100000 );
623+ if (ForceSetType || (ClWritesAlwaysSetType && IsWrite)) {
624+ // In the mode where writes always set the type, for a write (which does
625+ // not also read), we just set the type.
626+ SetType ();
627+ return true ;
628+ }
630629
631- Constant *Flags =
632- ConstantInt::get (OrdTy, (int )IsRead | (((int )IsWrite) << 1 ));
630+ assert ((!ClWritesAlwaysSetType || IsRead) &&
631+ " should have handled case above" );
632+ LLVMContext &C = IRB.getContext ();
633+ MDNode *UnlikelyBW = MDBuilder (C).createBranchWeights (1 , 100000 );
633634
635+ if (!SanitizeFunction) {
636+ // If we're not sanitizing this function, then we only care whether we
637+ // need to *set* the type.
634638 Value *LoadedTD = IRB.CreateLoad (IRB.getPtrTy (), ShadowData, " shadow.desc" );
635- if (SanitizeFunction) {
636- Value *BadTDCmp = IRB.CreateICmpNE (LoadedTD, TD, " bad.desc" );
637- Instruction *BadTDTerm, *GoodTDTerm;
638- SplitBlockAndInsertIfThenElse (BadTDCmp, &*IRB.GetInsertPoint (),
639- &BadTDTerm, &GoodTDTerm, UnlikelyBW);
640- IRB.SetInsertPoint (BadTDTerm);
641-
642- // We now know that the types did not match (we're on the slow path). If
643- // the type is unknown, then set it.
644- Value *NullTDCmp = IRB.CreateIsNull (LoadedTD);
645- Instruction *NullTDTerm, *MismatchTerm;
646- SplitBlockAndInsertIfThenElse (NullTDCmp, &*IRB.GetInsertPoint (),
647- &NullTDTerm, &MismatchTerm);
648-
649- // If the type is unknown, then set the type.
650- IRB.SetInsertPoint (NullTDTerm);
651-
652- // We're about to set the type. Make sure that all bytes in the value are
653- // also of unknown type.
654- Value *Size = ConstantInt::get (OrdTy, AccessSize);
655- Value *NotAllUnkTD = IRB.getFalse ();
656- for (uint64_t i = 1 ; i < AccessSize; ++i) {
657- Value *UnkShadowData = IRB.CreateIntToPtr (
658- IRB.CreateAdd (ShadowDataInt,
659- ConstantInt::get (IntptrTy, i << PtrShift)),
660- Int8PtrPtrTy);
661- Value *ILdTD = IRB.CreateLoad (IRB.getPtrTy (), UnkShadowData);
662- NotAllUnkTD = IRB.CreateOr (NotAllUnkTD, IRB.CreateIsNotNull (ILdTD));
663- }
664-
665- Instruction *BeforeSetType = &*IRB.GetInsertPoint ();
666- Instruction *BadUTDTerm = SplitBlockAndInsertIfThen (
667- NotAllUnkTD, BeforeSetType, false , UnlikelyBW);
668- IRB.SetInsertPoint (BadUTDTerm);
669- IRB.CreateCall (TysanCheck, {IRB.CreateBitCast (Ptr, IRB.getPtrTy ()), Size,
670- (Value *)TD, (Value *)Flags});
671-
672- IRB.SetInsertPoint (BeforeSetType);
673- SetType ();
674-
675- // We have a non-trivial mismatch. Call the runtime.
676- IRB.SetInsertPoint (MismatchTerm);
677- IRB.CreateCall (TysanCheck, {IRB.CreateBitCast (Ptr, IRB.getPtrTy ()), Size,
678- (Value *)TD, (Value *)Flags});
679-
680- // We appear to have the right type. Make sure that all other bytes in
681- // the type are still marked as interior bytes. If not, call the runtime.
682- IRB.SetInsertPoint (GoodTDTerm);
683- Value *NotAllBadTD = IRB.getFalse ();
684- for (uint64_t i = 1 ; i < AccessSize; ++i) {
685- Value *BadShadowData = IRB.CreateIntToPtr (
686- IRB.CreateAdd (ShadowDataInt,
687- ConstantInt::get (IntptrTy, i << PtrShift)),
688- Int8PtrPtrTy);
689- Value *ILdTD = IRB.CreatePtrToInt (
690- IRB.CreateLoad (IRB.getPtrTy (), BadShadowData), IntptrTy);
691- NotAllBadTD = IRB.CreateOr (
692- NotAllBadTD,
693- IRB.CreateICmpSGE (ILdTD, ConstantInt::get (IntptrTy, 0 )));
694- }
695-
696- Instruction *BadITDTerm = SplitBlockAndInsertIfThen (
697- NotAllBadTD, &*IRB.GetInsertPoint (), false , UnlikelyBW);
698- IRB.SetInsertPoint (BadITDTerm);
699- IRB.CreateCall (TysanCheck, {IRB.CreateBitCast (Ptr, IRB.getPtrTy ()), Size,
700- (Value *)TD, (Value *)Flags});
701- } else {
702- // If we're not sanitizing this function, then we only care whether we
703- // need to *set* the type.
704- Value *NullTDCmp = IRB.CreateIsNull (LoadedTD, " desc.set" );
705- Instruction *NullTDTerm = SplitBlockAndInsertIfThen (
706- NullTDCmp, &*IRB.GetInsertPoint (), false , UnlikelyBW);
707- IRB.SetInsertPoint (NullTDTerm);
708- NullTDTerm->getParent ()->setName (" set.type" );
709- SetType ();
710- }
711- } else if (ForceSetType || IsWrite) {
712- // In the mode where writes always set the type, for a write (which does
713- // not also read), we just set the type.
639+ Value *NullTDCmp = IRB.CreateIsNull (LoadedTD, " desc.set" );
640+ Instruction *NullTDTerm = SplitBlockAndInsertIfThen (
641+ NullTDCmp, &*IRB.GetInsertPoint (), false , UnlikelyBW);
642+ IRB.SetInsertPoint (NullTDTerm);
643+ NullTDTerm->getParent ()->setName (" set.type" );
714644 SetType ();
645+ return true ;
646+ }
647+ // We need to check the type here. If the type is unknown, then the read
648+ // sets the type. If the type is known, then it is checked. If the type
649+ // doesn't match, then we call the runtime (which may yet determine that
650+ // the mismatch is okay).
651+ //
652+ // The checks generated below have the following strucutre.
653+ //
654+ // ; First we load the descriptor for the load from shadow memory and
655+ // ; compare it against the type descriptor for the current access type.
656+ // %shadow.desc = load ptr %shadow.data
657+ // %bad.desc = icmp ne %shadow.desc, %td
658+ // br %bad.desc, %bad.bb, %good.bb
659+ //
660+ // bad.bb:
661+ // %shadow.desc.null = icmp eq %shadow.desc, null
662+ // br %shadow.desc.null, %null.td.bb, %good.td.bb
663+ //
664+ // null.td.bb:
665+ // ; The typ is unknown, set it if all bytes in the value are also unknown.
666+ // ; To check, we load the shadow data for all bytes of the access. For the
667+ // ; pseudo code below, assume an access of size 1.
668+ // %shadow.data.int = add %shadow.data.int, 0
669+ // %l = load (inttoptr %shadow.data.int)
670+ // %is.not.null = icmp ne %l, null
671+ // %not.all.unknown = %is.not.null
672+ // br %no.all.unknown, before.set.type.bb
673+ //
674+ // before.set.type.bb:
675+ // ; Call runtime to check mismatch.
676+ // call void @__tysan_check()
677+ // br %set.type.bb
678+ //
679+ // set.type.bb:
680+ // ; Now fill the remainder of the shadow memory corresponding to the
681+ // ; remainder of the the bytes of the type with a bad type descriptor.
682+ // store %TD, %shadow.data
683+ // br %continue.bb
684+ //
685+ // good.td.bb::
686+ // ; We have a non-trivial mismatch. Call the runtime.
687+ // call void @__tysan_check()
688+ // br %continue.bb
689+ //
690+ // good.bb:
691+ // ; We appear to have the right type. Make sure that all other bytes in
692+ // ; the type are still marked as interior bytes. If not, call the runtime.
693+ // %shadow.data.int = add %shadow.data.int, 0
694+ // %l = load (inttoptr %shadow.data.int)
695+ // %not.all.interior = icmp sge %l, 0
696+ // br %not.all.interior, label %check.rt.bb, label %continue.bb
697+ //
698+ // check.rt.bb:
699+ // call void @__tysan_check()
700+ // br %continue.bb
701+
702+ Constant *Flags = ConstantInt::get (OrdTy, int (IsRead) | (int (IsWrite) << 1 ));
703+
704+ Value *LoadedTD = IRB.CreateLoad (IRB.getPtrTy (), ShadowData, " shadow.desc" );
705+ Value *BadTDCmp = IRB.CreateICmpNE (LoadedTD, TD, " bad.desc" );
706+ Instruction *BadTDTerm, *GoodTDTerm;
707+ SplitBlockAndInsertIfThenElse (BadTDCmp, &*IRB.GetInsertPoint (), &BadTDTerm,
708+ &GoodTDTerm, UnlikelyBW);
709+ IRB.SetInsertPoint (BadTDTerm);
710+
711+ // We now know that the types did not match (we're on the slow path). If
712+ // the type is unknown, then set it.
713+ Value *NullTDCmp = IRB.CreateIsNull (LoadedTD);
714+ Instruction *NullTDTerm, *MismatchTerm;
715+ SplitBlockAndInsertIfThenElse (NullTDCmp, &*IRB.GetInsertPoint (), &NullTDTerm,
716+ &MismatchTerm);
717+
718+ // If the type is unknown, then set the type.
719+ IRB.SetInsertPoint (NullTDTerm);
720+
721+ // We're about to set the type. Make sure that all bytes in the value are
722+ // also of unknown type.
723+ Value *Size = ConstantInt::get (OrdTy, AccessSize);
724+ Value *NotAllUnkTD = IRB.getFalse ();
725+ for (uint64_t i = 1 ; i < AccessSize; ++i) {
726+ Value *UnkShadowData = IRB.CreateIntToPtr (
727+ IRB.CreateAdd (ShadowDataInt, ConstantInt::get (IntptrTy, i << PtrShift)),
728+ Int8PtrPtrTy);
729+ Value *ILdTD = IRB.CreateLoad (IRB.getPtrTy (), UnkShadowData);
730+ NotAllUnkTD = IRB.CreateOr (NotAllUnkTD, IRB.CreateIsNotNull (ILdTD));
715731 }
716732
733+ Instruction *BeforeSetType = &*IRB.GetInsertPoint ();
734+ Instruction *BadUTDTerm =
735+ SplitBlockAndInsertIfThen (NotAllUnkTD, BeforeSetType, false , UnlikelyBW);
736+ IRB.SetInsertPoint (BadUTDTerm);
737+ IRB.CreateCall (TysanCheck, {IRB.CreateBitCast (Ptr, IRB.getPtrTy ()), Size,
738+ (Value *)TD, (Value *)Flags});
739+
740+ IRB.SetInsertPoint (BeforeSetType);
741+ SetType ();
742+
743+ // We have a non-trivial mismatch. Call the runtime.
744+ IRB.SetInsertPoint (MismatchTerm);
745+ IRB.CreateCall (TysanCheck, {IRB.CreateBitCast (Ptr, IRB.getPtrTy ()), Size,
746+ (Value *)TD, (Value *)Flags});
747+
748+ // We appear to have the right type. Make sure that all other bytes in
749+ // the type are still marked as interior bytes. If not, call the runtime.
750+ IRB.SetInsertPoint (GoodTDTerm);
751+ Value *NotAllBadTD = IRB.getFalse ();
752+ for (uint64_t i = 1 ; i < AccessSize; ++i) {
753+ Value *BadShadowData = IRB.CreateIntToPtr (
754+ IRB.CreateAdd (ShadowDataInt, ConstantInt::get (IntptrTy, i << PtrShift)),
755+ Int8PtrPtrTy);
756+ Value *ILdTD = IRB.CreatePtrToInt (
757+ IRB.CreateLoad (IRB.getPtrTy (), BadShadowData), IntptrTy);
758+ NotAllBadTD = IRB.CreateOr (
759+ NotAllBadTD, IRB.CreateICmpSGE (ILdTD, ConstantInt::get (IntptrTy, 0 )));
760+ }
761+
762+ Instruction *BadITDTerm = SplitBlockAndInsertIfThen (
763+ NotAllBadTD, &*IRB.GetInsertPoint (), false , UnlikelyBW);
764+ IRB.SetInsertPoint (BadITDTerm);
765+ IRB.CreateCall (TysanCheck, {IRB.CreateBitCast (Ptr, IRB.getPtrTy ()), Size,
766+ (Value *)TD, (Value *)Flags});
717767 return true ;
718768}
719769
720- bool TypeSanitizer::instrumentMemInst (Value *V, Value *& ShadowBase,
721- Value *& AppMemMask,
770+ bool TypeSanitizer::instrumentMemInst (Value *V, Instruction * ShadowBase,
771+ Instruction * AppMemMask,
722772 const DataLayout &DL) {
723773 BasicBlock::iterator IP;
724774 BasicBlock *BB;
@@ -734,14 +784,11 @@ bool TypeSanitizer::instrumentMemInst(Value *V, Value *&ShadowBase,
734784 BB = &F->getEntryBlock ();
735785 IP = BB->getFirstInsertionPt ();
736786
737- if (auto *I = cast_or_null<Instruction>(ShadowBase)) {
738- if (IP->comesBefore (I))
739- IP = I->getNextNode ()->getIterator ();
740- }
741- if (auto *I = cast_or_null<Instruction>(AppMemMask)) {
742- if (IP->comesBefore (I))
743- IP = I->getNextNode ()->getIterator ();
744- }
787+ // Find the next insert point after both ShadowBase and AppMemMask.
788+ if (IP->comesBefore (ShadowBase))
789+ IP = ShadowBase->getNextNode ()->getIterator ();
790+ if (IP->comesBefore (AppMemMask))
791+ IP = AppMemMask->getNextNode ()->getIterator ();
745792 }
746793
747794 Value *Dest, *Size, *Src = nullptr ;
0 commit comments