Index: MemorySanitizer.cpp =================================================================== --- MemorySanitizer.cpp +++ MemorySanitizer.cpp @@ -130,6 +130,17 @@ // Accesses sizes are powers of two: 1, 2, 4, 8. static const size_t kNumberOfAccessSizes = 4; +// Used on Android only: the offsets of these variables in struct MsanTLSSlot +// These offsets are statically asserted in msan_linux.cc +// (MsanThread *GetCurrentThread()) +static const unsigned offsetof__msan_param_tls = 0; +static const unsigned offsetof__msan_retval_tls = 1600; +static const unsigned offsetof__msan_param_origin_tls = 800; +static const unsigned offsetof__msan_retval_origin_tls = 2424; +static const unsigned offsetof__msan__va_arg_tls = 2448; +static const unsigned offsetof__msan_va_arg_overflow_size_tls = 2432; +static const unsigned offsetof__msan_origin_tls = 2428; + /// \brief Track origins of uninitialized values. /// /// Adds a section to MemorySanitizer report that points to the allocation @@ -324,6 +335,16 @@ bool doInitialization(Module &M) override; static char ID; // Pass identification, replacement for typeid. + Value* getAndroidTLSStructEntry(IRBuilder<> &IRB, unsigned long offset); + + Value* getParamTLS(IRBuilder<> &IRB); + Value* getRetvalTLS(IRBuilder<> &IRB); + Value* getParamOriginTLS(IRBuilder<> &IRB); + Value* getRetvalOriginTLS(IRBuilder<> &IRB); + Value* getVAArgTLS(IRBuilder<> &IRB); + Value* getVAArgOverflowSizeTLS(IRBuilder<> &IRB); + Value* getOriginTLS(IRBuilder<> &IRB); + private: void initializeCallbacks(Module &M); @@ -351,6 +372,12 @@ /// function. GlobalVariable *OriginTLS; + bool isAndroid; + Value *AndroidTLSStruct; + + // \brief Defined as 'static THREADLOCAL MsanTLSSlot' for non-Android. + Value *MsanTLSSlot; + /// \brief The run-time callback to print a warning. Value *WarningFn; // These arrays are indexed by log2(AccessSize). @@ -457,35 +484,37 @@ "__msan_memset", IRB.getInt8PtrTy(), IRB.getInt8PtrTy(), IRB.getInt32Ty(), IntptrTy, nullptr); - // Create globals. - RetvalTLS = new GlobalVariable( - M, ArrayType::get(IRB.getInt64Ty(), kRetvalTLSSize / 8), false, - GlobalVariable::ExternalLinkage, nullptr, "__msan_retval_tls", nullptr, - GlobalVariable::InitialExecTLSModel); - RetvalOriginTLS = new GlobalVariable( - M, OriginTy, false, GlobalVariable::ExternalLinkage, nullptr, - "__msan_retval_origin_tls", nullptr, GlobalVariable::InitialExecTLSModel); - - ParamTLS = new GlobalVariable( - M, ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8), false, - GlobalVariable::ExternalLinkage, nullptr, "__msan_param_tls", nullptr, - GlobalVariable::InitialExecTLSModel); - ParamOriginTLS = new GlobalVariable( - M, ArrayType::get(OriginTy, kParamTLSSize / 4), false, - GlobalVariable::ExternalLinkage, nullptr, "__msan_param_origin_tls", - nullptr, GlobalVariable::InitialExecTLSModel); - - VAArgTLS = new GlobalVariable( - M, ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8), false, - GlobalVariable::ExternalLinkage, nullptr, "__msan_va_arg_tls", nullptr, - GlobalVariable::InitialExecTLSModel); - VAArgOverflowSizeTLS = new GlobalVariable( - M, IRB.getInt64Ty(), false, GlobalVariable::ExternalLinkage, nullptr, - "__msan_va_arg_overflow_size_tls", nullptr, - GlobalVariable::InitialExecTLSModel); - OriginTLS = new GlobalVariable( - M, IRB.getInt32Ty(), false, GlobalVariable::ExternalLinkage, nullptr, - "__msan_origin_tls", nullptr, GlobalVariable::InitialExecTLSModel); + if (!isAndroid) { + // Create globals. + RetvalTLS = new GlobalVariable( + M, ArrayType::get(IRB.getInt64Ty(), kRetvalTLSSize / 8), false, + GlobalVariable::ExternalLinkage, nullptr, "__msan_retval_tls", nullptr, + GlobalVariable::InitialExecTLSModel); + RetvalOriginTLS = new GlobalVariable( + M, OriginTy, false, GlobalVariable::ExternalLinkage, nullptr, + "__msan_retval_origin_tls", nullptr, GlobalVariable::InitialExecTLSModel); + + ParamTLS = new GlobalVariable( + M, ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8), false, + GlobalVariable::ExternalLinkage, nullptr, "__msan_param_tls", nullptr, + GlobalVariable::InitialExecTLSModel); + ParamOriginTLS = new GlobalVariable( + M, ArrayType::get(OriginTy, kParamTLSSize / 4), false, + GlobalVariable::ExternalLinkage, nullptr, "__msan_param_origin_tls", + nullptr, GlobalVariable::InitialExecTLSModel); + + VAArgTLS = new GlobalVariable( + M, ArrayType::get(IRB.getInt64Ty(), kParamTLSSize / 8), false, + GlobalVariable::ExternalLinkage, nullptr, "__msan_va_arg_tls", nullptr, + GlobalVariable::InitialExecTLSModel); + VAArgOverflowSizeTLS = new GlobalVariable( + M, IRB.getInt64Ty(), false, GlobalVariable::ExternalLinkage, nullptr, + "__msan_va_arg_overflow_size_tls", nullptr, + GlobalVariable::InitialExecTLSModel); + OriginTLS = new GlobalVariable( + M, IRB.getInt32Ty(), false, GlobalVariable::ExternalLinkage, nullptr, + "__msan_origin_tls", nullptr, GlobalVariable::InitialExecTLSModel); + } // We insert an empty inline asm after __msan_report* to avoid callback merge. EmptyAsm = InlineAsm::get(FunctionType::get(IRB.getVoidTy(), false), @@ -493,6 +522,88 @@ /*hasSideEffects=*/true); } +// Only used if isAndroid +// Emits code equivalent to ((char*)GetMsanTls() + offset) +// i.e., (char*)(__get_tls()[TLS_SLOT_TSAN])+offset +Value* MemorySanitizer::getAndroidTLSStructEntry(IRBuilder<> &IRB, unsigned long offset) { + Value *AndroidTLSStruct0 = AndroidTLSStruct; + // Reset in MemorySanitizerVisitor::runOnFunction + if (AndroidTLSStruct == nullptr) { + // Based on AArch64TargetLowering::getIRStackGuard + // TLS_SLOT_TSAN = 8 + const unsigned TlsOffset = 0x40; + Module *M = IRB.GetInsertBlock()->getParent()->getParent(); + Function *ThreadPointerFunc = + Intrinsic::getDeclaration(M, Intrinsic::thread_pointer); + AndroidTLSStruct0 = + IRB.CreateLoad( + IRB.CreatePointerCast( + IRB.CreateConstGEP1_32(IRB.CreateCall(ThreadPointerFunc), TlsOffset), + Type::getInt8PtrTy(IRB.getContext())->getPointerTo(0))); + // AndroidTLSStruct = AndroidTLSStruct0; + } + + Value *Base = IRB.CreatePointerCast(AndroidTLSStruct0, IntptrTy); + Base = IRB.CreateAdd(Base, ConstantInt::get(IntptrTy, offset)); + return IRB.CreateIntToPtr(Base, PointerType::get(IntptrTy, 0)); +} + +Value* MemorySanitizer::getParamTLS(IRBuilder<> &IRB) { + if (isAndroid) { + return getAndroidTLSStructEntry (IRB, offsetof__msan_param_tls); + } else { + return ParamTLS; + } +} + +Value* MemorySanitizer::getRetvalTLS(IRBuilder<> &IRB) { + if (isAndroid) { + return getAndroidTLSStructEntry (IRB, offsetof__msan_retval_tls); + } else { + return RetvalTLS; + } +} + +Value* MemorySanitizer::getParamOriginTLS(IRBuilder<> &IRB) { + if (isAndroid) { + return getAndroidTLSStructEntry (IRB, offsetof__msan_param_origin_tls); + } else { + return ParamOriginTLS; + } +} + +Value* MemorySanitizer::getRetvalOriginTLS(IRBuilder<> &IRB) { + if (isAndroid) { + return getAndroidTLSStructEntry (IRB, offsetof__msan_retval_origin_tls); + } else { + return RetvalOriginTLS; + } +} + +Value* MemorySanitizer::getVAArgTLS(IRBuilder<> &IRB) { + if (isAndroid) { + return getAndroidTLSStructEntry (IRB, offsetof__msan__va_arg_tls); + } else { + return VAArgTLS; + } +} + +Value* MemorySanitizer::getVAArgOverflowSizeTLS(IRBuilder<> &IRB) { + if (isAndroid) { + return getAndroidTLSStructEntry (IRB, offsetof__msan_va_arg_overflow_size_tls); + } else { + return VAArgOverflowSizeTLS; + } +} + +Value* MemorySanitizer::getOriginTLS(IRBuilder<> &IRB) { + if (isAndroid) { + return getAndroidTLSStructEntry (IRB, offsetof__msan_origin_tls); + } else { + return OriginTLS; + } +} + /// \brief Module-level initialization. /// /// inserts a call to __msan_init to the module's constructor list. @@ -540,6 +651,7 @@ default: report_fatal_error("unsupported operating system"); } + isAndroid = TargetTriple.isAndroid(); C = &(M.getContext()); IRBuilder<> IRB(*C); @@ -788,7 +900,7 @@ if (ClCheckConstantShadow && !ConstantShadow->isZeroValue()) { if (MS.TrackOrigins) { IRB.CreateStore(Origin ? (Value *)Origin : (Value *)IRB.getInt32(0), - MS.OriginTLS); + MS.getOriginTLS(IRB)); } IRB.CreateCall(MS.WarningFn, {}); IRB.CreateCall(MS.EmptyAsm, {}); @@ -820,7 +932,7 @@ IRB.SetInsertPoint(CheckTerm); if (MS.TrackOrigins) { IRB.CreateStore(Origin ? (Value *)Origin : (Value *)IRB.getInt32(0), - MS.OriginTLS); + MS.getOriginTLS(IRB)); } IRB.CreateCall(MS.WarningFn, {}); IRB.CreateCall(MS.EmptyAsm, {}); @@ -840,6 +952,7 @@ /// \brief Add MemorySanitizer instrumentation to a function. bool runOnFunction() { + MS.AndroidTLSStruct = nullptr; MS.initializeCallbacks(*F.getParent()); // In the presence of unreachable blocks, we may see Phi nodes with @@ -992,7 +1105,7 @@ /// Shadow = ParamTLS+ArgOffset. Value *getShadowPtrForArgument(Value *A, IRBuilder<> &IRB, int ArgOffset) { - Value *Base = IRB.CreatePointerCast(MS.ParamTLS, MS.IntptrTy); + Value *Base = IRB.CreatePointerCast(MS.getParamTLS(IRB), MS.IntptrTy); Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset)); return IRB.CreateIntToPtr(Base, PointerType::get(getShadowTy(A), 0), "_msarg"); @@ -1002,7 +1115,7 @@ Value *getOriginPtrForArgument(Value *A, IRBuilder<> &IRB, int ArgOffset) { if (!MS.TrackOrigins) return nullptr; - Value *Base = IRB.CreatePointerCast(MS.ParamOriginTLS, MS.IntptrTy); + Value *Base = IRB.CreatePointerCast(MS.getParamOriginTLS(IRB), MS.IntptrTy); Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset)); return IRB.CreateIntToPtr(Base, PointerType::get(MS.OriginTy, 0), "_msarg_o"); @@ -1010,7 +1123,7 @@ /// \brief Compute the shadow address for a retval. Value *getShadowPtrForRetval(Value *A, IRBuilder<> &IRB) { - Value *Base = IRB.CreatePointerCast(MS.RetvalTLS, MS.IntptrTy); + Value *Base = IRB.CreatePointerCast(MS.getRetvalTLS(IRB), MS.IntptrTy); return IRB.CreateIntToPtr(Base, PointerType::get(getShadowTy(A), 0), "_msret"); } @@ -1018,7 +1131,7 @@ /// \brief Compute the origin address for a retval. Value *getOriginPtrForRetval(IRBuilder<> &IRB) { // We keep a single origin for the entire retval. Might be too optimistic. - return MS.RetvalOriginTLS; + return MS.getRetvalOriginTLS(IRB); } /// \brief Set SV to be the shadow value for V. @@ -2948,13 +3061,13 @@ } Constant *OverflowSize = ConstantInt::get(IRB.getInt64Ty(), OverflowOffset - AMD64FpEndOffset); - IRB.CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS); + IRB.CreateStore(OverflowSize, MS.getVAArgOverflowSizeTLS(IRB)); } /// \brief Compute the shadow address for a given va_arg. Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB, int ArgOffset) { - Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy); + Value *Base = IRB.CreatePointerCast(MS.getVAArgTLS(IRB), MS.IntptrTy); Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset)); return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0), "_msarg"); @@ -2994,12 +3107,12 @@ // If there is a va_start in this function, make a backup copy of // va_arg_tls somewhere in the function entry block. IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI()); - VAArgOverflowSize = IRB.CreateLoad(MS.VAArgOverflowSizeTLS); + VAArgOverflowSize = IRB.CreateLoad(MS.getVAArgOverflowSizeTLS(IRB)); Value *CopySize = IRB.CreateAdd(ConstantInt::get(MS.IntptrTy, AMD64FpEndOffset), VAArgOverflowSize); VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize); - IRB.CreateMemCpy(VAArgTLSCopy, MS.VAArgTLS, CopySize, 8); + IRB.CreateMemCpy(VAArgTLSCopy, MS.getVAArgTLS(IRB), CopySize, 8); } // Instrument va_start. @@ -3075,13 +3188,13 @@ Constant *TotalVAArgSize = ConstantInt::get(IRB.getInt64Ty(), VAArgOffset); // Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of // a new class member i.e. it is the total size of all VarArgs. - IRB.CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS); + IRB.CreateStore(TotalVAArgSize, MS.getVAArgOverflowSizeTLS(IRB)); } /// \brief Compute the shadow address for a given va_arg. Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB, int ArgOffset) { - Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy); + Value *Base = IRB.CreatePointerCast(MS.getVAArgTLS(IRB), MS.IntptrTy); Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset)); return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0), "_msarg"); @@ -3110,7 +3223,7 @@ assert(!VAArgSize && !VAArgTLSCopy && "finalizeInstrumentation called twice"); IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI()); - VAArgSize = IRB.CreateLoad(MS.VAArgOverflowSizeTLS); + VAArgSize = IRB.CreateLoad(MS.getVAArgOverflowSizeTLS(IRB)); Value *CopySize = IRB.CreateAdd(ConstantInt::get(MS.IntptrTy, 0), VAArgSize); @@ -3118,7 +3231,7 @@ // If there is a va_start in this function, make a backup copy of // va_arg_tls somewhere in the function entry block. VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize); - IRB.CreateMemCpy(VAArgTLSCopy, MS.VAArgTLS, CopySize, 8); + IRB.CreateMemCpy(VAArgTLSCopy, MS.getVAArgTLS(IRB), CopySize, 8); } // Instrument va_start. @@ -3230,13 +3343,13 @@ } Constant *OverflowSize = ConstantInt::get(IRB.getInt64Ty(), OverflowOffset - AArch64VAEndOffset); - IRB.CreateStore(OverflowSize, MS.VAArgOverflowSizeTLS); + IRB.CreateStore(OverflowSize, MS.getVAArgOverflowSizeTLS(IRB)); } /// Compute the shadow address for a given va_arg. Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB, int ArgOffset) { - Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy); + Value *Base = IRB.CreatePointerCast(MS.getVAArgTLS(IRB), MS.IntptrTy); Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset)); return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0), "_msarg"); @@ -3291,12 +3404,12 @@ // If there is a va_start in this function, make a backup copy of // va_arg_tls somewhere in the function entry block. IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI()); - VAArgOverflowSize = IRB.CreateLoad(MS.VAArgOverflowSizeTLS); + VAArgOverflowSize = IRB.CreateLoad(MS.getVAArgOverflowSizeTLS(IRB)); Value *CopySize = IRB.CreateAdd(ConstantInt::get(MS.IntptrTy, AArch64VAEndOffset), VAArgOverflowSize); VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize); - IRB.CreateMemCpy(VAArgTLSCopy, MS.VAArgTLS, CopySize, 8); + IRB.CreateMemCpy(VAArgTLSCopy, MS.getVAArgTLS(IRB), CopySize, 8); } Value *GrArgSize = ConstantInt::get(MS.IntptrTy, kAArch64GrArgSize); @@ -3478,13 +3591,13 @@ VAArgOffset - VAArgBase); // Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of // a new class member i.e. it is the total size of all VarArgs. - IRB.CreateStore(TotalVAArgSize, MS.VAArgOverflowSizeTLS); + IRB.CreateStore(TotalVAArgSize, MS.getVAArgOverflowSizeTLS(IRB)); } /// \brief Compute the shadow address for a given va_arg. Value *getShadowPtrForVAArgument(Type *Ty, IRBuilder<> &IRB, int ArgOffset) { - Value *Base = IRB.CreatePointerCast(MS.VAArgTLS, MS.IntptrTy); + Value *Base = IRB.CreatePointerCast(MS.getVAArgTLS(IRB), MS.IntptrTy); Base = IRB.CreateAdd(Base, ConstantInt::get(MS.IntptrTy, ArgOffset)); return IRB.CreateIntToPtr(Base, PointerType::get(MSV.getShadowTy(Ty), 0), "_msarg"); @@ -3513,7 +3626,7 @@ assert(!VAArgSize && !VAArgTLSCopy && "finalizeInstrumentation called twice"); IRBuilder<> IRB(F.getEntryBlock().getFirstNonPHI()); - VAArgSize = IRB.CreateLoad(MS.VAArgOverflowSizeTLS); + VAArgSize = IRB.CreateLoad(MS.getVAArgOverflowSizeTLS(IRB)); Value *CopySize = IRB.CreateAdd(ConstantInt::get(MS.IntptrTy, 0), VAArgSize); @@ -3521,7 +3634,7 @@ // If there is a va_start in this function, make a backup copy of // va_arg_tls somewhere in the function entry block. VAArgTLSCopy = IRB.CreateAlloca(Type::getInt8Ty(*MS.C), CopySize); - IRB.CreateMemCpy(VAArgTLSCopy, MS.VAArgTLS, CopySize, 8); + IRB.CreateMemCpy(VAArgTLSCopy, MS.getVAArgTLS(IRB), CopySize, 8); } // Instrument va_start.