@@ -411,6 +411,10 @@ static const MemoryMapParams Linux_X86_64_MemoryMapParams = {
411411 0x100000000000 , // OriginBase
412412};
413413
414+ // mips32 Linux
415+ // FIXME: Remove -msan-origin-base -msan-and-mask added by PR #109284 to tests
416+ // after picking good constants
417+
414418// mips64 Linux
415419static const MemoryMapParams Linux_MIPS64_MemoryMapParams = {
416420 0 , // AndMask (not used)
@@ -419,6 +423,10 @@ static const MemoryMapParams Linux_MIPS64_MemoryMapParams = {
419423 0x002000000000 , // OriginBase
420424};
421425
426+ // ppc32 Linux
427+ // FIXME: Remove -msan-origin-base -msan-and-mask added by PR #109284 to tests
428+ // after picking good constants
429+
422430// ppc64 Linux
423431static const MemoryMapParams Linux_PowerPC64_MemoryMapParams = {
424432 0xE00000000000 , // AndMask
@@ -435,6 +443,10 @@ static const MemoryMapParams Linux_S390X_MemoryMapParams = {
435443 0x1C0000000000 , // OriginBase
436444};
437445
446+ // arm32 Linux
447+ // FIXME: Remove -msan-origin-base -msan-and-mask added by PR #109284 to tests
448+ // after picking good constants
449+
438450// aarch64 Linux
439451static const MemoryMapParams Linux_AArch64_MemoryMapParams = {
440452 0 , // AndMask (not used)
@@ -451,6 +463,10 @@ static const MemoryMapParams Linux_LoongArch64_MemoryMapParams = {
451463 0x100000000000 , // OriginBase
452464};
453465
466+ // riscv32 Linux
467+ // FIXME: Remove -msan-origin-base -msan-and-mask added by PR #109284 to tests
468+ // after picking good constants
469+
454470// aarch64 FreeBSD
455471static const MemoryMapParams FreeBSD_AArch64_MemoryMapParams = {
456472 0x1800000000000 , // AndMask
@@ -559,6 +575,7 @@ class MemorySanitizer {
559575 friend struct VarArgAArch64Helper ;
560576 friend struct VarArgPowerPCHelper ;
561577 friend struct VarArgSystemZHelper ;
578+ friend struct VarArgI386Helper ;
562579 friend struct VarArgGenericHelper ;
563580
564581 void initializeModule (Module &M);
@@ -5606,10 +5623,15 @@ struct VarArgPowerPCHelper : public VarArgHelperBase {
56065623 // Parameter save area starts at 48 bytes from frame pointer for ABIv1,
56075624 // and 32 bytes for ABIv2. This is usually determined by target
56085625 // endianness, but in theory could be overridden by function attribute.
5609- if (TargetTriple.getArch () == Triple::ppc64)
5610- VAArgBase = 48 ;
5611- else
5612- VAArgBase = 32 ;
5626+ if (TargetTriple.isPPC64 ()) {
5627+ if (TargetTriple.isPPC64ELFv2ABI ())
5628+ VAArgBase = 32 ;
5629+ else
5630+ VAArgBase = 48 ;
5631+ } else {
5632+ // Parameter save area is 8 bytes from frame pointer in PPC32
5633+ VAArgBase = 8 ;
5634+ }
56135635 unsigned VAArgOffset = VAArgBase;
56145636 const DataLayout &DL = F.getDataLayout ();
56155637 for (const auto &[ArgNo, A] : llvm::enumerate (CB.args ())) {
@@ -5674,7 +5696,7 @@ struct VarArgPowerPCHelper : public VarArgHelperBase {
56745696 }
56755697
56765698 Constant *TotalVAArgSize =
5677- ConstantInt::get (IRB. getInt64Ty () , VAArgOffset - VAArgBase);
5699+ ConstantInt::get (MS. IntptrTy , VAArgOffset - VAArgBase);
56785700 // Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
56795701 // a new class member i.e. it is the total size of all VarArgs.
56805702 IRB.CreateStore (TotalVAArgSize, MS.VAArgOverflowSizeTLS );
@@ -5705,14 +5727,24 @@ struct VarArgPowerPCHelper : public VarArgHelperBase {
57055727
57065728 // Instrument va_start.
57075729 // Copy va_list shadow from the backup copy of the TLS contents.
5730+ Triple TargetTriple (F.getParent ()->getTargetTriple ());
57085731 for (CallInst *OrigInst : VAStartInstrumentationList) {
57095732 NextNodeIRBuilder IRB (OrigInst);
57105733 Value *VAListTag = OrigInst->getArgOperand (0 );
5711- Value *RegSaveAreaPtrPtr = IRB.CreateIntToPtr (
5712- IRB.CreatePtrToInt (VAListTag, MS.IntptrTy ), MS.PtrTy );
5734+ Value *RegSaveAreaPtrPtr = IRB.CreatePtrToInt (VAListTag, MS.IntptrTy );
5735+
5736+ // In PPC32 va_list_tag is a struct, whereas in PPC64 it's a pointer
5737+ if (!TargetTriple.isPPC64 ()) {
5738+ RegSaveAreaPtrPtr =
5739+ IRB.CreateAdd (RegSaveAreaPtrPtr, ConstantInt::get (MS.IntptrTy , 8 ));
5740+ }
5741+ RegSaveAreaPtrPtr = IRB.CreateIntToPtr (RegSaveAreaPtrPtr, MS.PtrTy );
5742+
57135743 Value *RegSaveAreaPtr = IRB.CreateLoad (MS.PtrTy , RegSaveAreaPtrPtr);
57145744 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
5715- const Align Alignment = Align (8 );
5745+ const DataLayout &DL = F.getDataLayout ();
5746+ unsigned IntptrSize = DL.getTypeStoreSize (MS.IntptrTy );
5747+ const Align Alignment = Align (IntptrSize);
57165748 std::tie (RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
57175749 MSV.getShadowOriginPtr (RegSaveAreaPtr, IRB, IRB.getInt8Ty (),
57185750 Alignment, /* isStore*/ true );
@@ -6003,8 +6035,118 @@ struct VarArgSystemZHelper : public VarArgHelperBase {
60036035 }
60046036};
60056037
6006- // / MIPS-specific implementation of VarArgHelper.
6007- // / NOTE: This is also used for LoongArch64.
6038+ // / i386-specific implementation of VarArgHelper.
6039+ struct VarArgI386Helper : public VarArgHelperBase {
6040+ AllocaInst *VAArgTLSCopy = nullptr ;
6041+ Value *VAArgSize = nullptr ;
6042+
6043+ VarArgI386Helper (Function &F, MemorySanitizer &MS,
6044+ MemorySanitizerVisitor &MSV)
6045+ : VarArgHelperBase(F, MS, MSV, /* VAListTagSize=*/ 4 ) {}
6046+
6047+ void visitCallBase (CallBase &CB, IRBuilder<> &IRB) override {
6048+ const DataLayout &DL = F.getDataLayout ();
6049+ unsigned IntptrSize = DL.getTypeStoreSize (MS.IntptrTy );
6050+ unsigned VAArgOffset = 0 ;
6051+ for (const auto &[ArgNo, A] : llvm::enumerate (CB.args ())) {
6052+ bool IsFixed = ArgNo < CB.getFunctionType ()->getNumParams ();
6053+ bool IsByVal = CB.paramHasAttr (ArgNo, Attribute::ByVal);
6054+ if (IsByVal) {
6055+ assert (A->getType ()->isPointerTy ());
6056+ Type *RealTy = CB.getParamByValType (ArgNo);
6057+ uint64_t ArgSize = DL.getTypeAllocSize (RealTy);
6058+ Align ArgAlign = CB.getParamAlign (ArgNo).value_or (Align (IntptrSize));
6059+ if (ArgAlign < IntptrSize)
6060+ ArgAlign = Align (IntptrSize);
6061+ VAArgOffset = alignTo (VAArgOffset, ArgAlign);
6062+ if (!IsFixed) {
6063+ Value *Base = getShadowPtrForVAArgument (IRB, VAArgOffset, ArgSize);
6064+ if (Base) {
6065+ Value *AShadowPtr, *AOriginPtr;
6066+ std::tie (AShadowPtr, AOriginPtr) =
6067+ MSV.getShadowOriginPtr (A, IRB, IRB.getInt8Ty (),
6068+ kShadowTLSAlignment , /* isStore*/ false );
6069+
6070+ IRB.CreateMemCpy (Base, kShadowTLSAlignment , AShadowPtr,
6071+ kShadowTLSAlignment , ArgSize);
6072+ }
6073+ VAArgOffset += alignTo (ArgSize, Align (IntptrSize));
6074+ }
6075+ } else {
6076+ Value *Base;
6077+ uint64_t ArgSize = DL.getTypeAllocSize (A->getType ());
6078+ Align ArgAlign = Align (IntptrSize);
6079+ VAArgOffset = alignTo (VAArgOffset, ArgAlign);
6080+ if (DL.isBigEndian ()) {
6081+ // Adjusting the shadow for argument with size < IntptrSize to match
6082+ // the placement of bits in big endian system
6083+ if (ArgSize < IntptrSize)
6084+ VAArgOffset += (IntptrSize - ArgSize);
6085+ }
6086+ if (!IsFixed) {
6087+ Base = getShadowPtrForVAArgument (IRB, VAArgOffset, ArgSize);
6088+ if (Base)
6089+ IRB.CreateAlignedStore (MSV.getShadow (A), Base, kShadowTLSAlignment );
6090+ VAArgOffset += ArgSize;
6091+ VAArgOffset = alignTo (VAArgOffset, Align (IntptrSize));
6092+ }
6093+ }
6094+ }
6095+
6096+ Constant *TotalVAArgSize = ConstantInt::get (MS.IntptrTy , VAArgOffset);
6097+ // Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
6098+ // a new class member i.e. it is the total size of all VarArgs.
6099+ IRB.CreateStore (TotalVAArgSize, MS.VAArgOverflowSizeTLS );
6100+ }
6101+
6102+ void finalizeInstrumentation () override {
6103+ assert (!VAArgSize && !VAArgTLSCopy &&
6104+ " finalizeInstrumentation called twice" );
6105+ IRBuilder<> IRB (MSV.FnPrologueEnd );
6106+ VAArgSize = IRB.CreateLoad (IRB.getInt64Ty (), MS.VAArgOverflowSizeTLS );
6107+ Value *CopySize = VAArgSize;
6108+
6109+ if (!VAStartInstrumentationList.empty ()) {
6110+ // If there is a va_start in this function, make a backup copy of
6111+ // va_arg_tls somewhere in the function entry block.
6112+ VAArgTLSCopy = IRB.CreateAlloca (Type::getInt8Ty (*MS.C ), CopySize);
6113+ VAArgTLSCopy->setAlignment (kShadowTLSAlignment );
6114+ IRB.CreateMemSet (VAArgTLSCopy, Constant::getNullValue (IRB.getInt8Ty ()),
6115+ CopySize, kShadowTLSAlignment , false );
6116+
6117+ Value *SrcSize = IRB.CreateBinaryIntrinsic (
6118+ Intrinsic::umin, CopySize,
6119+ ConstantInt::get (IRB.getInt64Ty (), kParamTLSSize ));
6120+ IRB.CreateMemCpy (VAArgTLSCopy, kShadowTLSAlignment , MS.VAArgTLS ,
6121+ kShadowTLSAlignment , SrcSize);
6122+ }
6123+
6124+ // Instrument va_start.
6125+ // Copy va_list shadow from the backup copy of the TLS contents.
6126+ for (CallInst *OrigInst : VAStartInstrumentationList) {
6127+ NextNodeIRBuilder IRB (OrigInst);
6128+ Value *VAListTag = OrigInst->getArgOperand (0 );
6129+ Type *RegSaveAreaPtrTy = PointerType::getUnqual (*MS.C );
6130+ Value *RegSaveAreaPtrPtr =
6131+ IRB.CreateIntToPtr (IRB.CreatePtrToInt (VAListTag, MS.IntptrTy ),
6132+ PointerType::get (RegSaveAreaPtrTy, 0 ));
6133+ Value *RegSaveAreaPtr =
6134+ IRB.CreateLoad (RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
6135+ Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
6136+ const DataLayout &DL = F.getDataLayout ();
6137+ unsigned IntptrSize = DL.getTypeStoreSize (MS.IntptrTy );
6138+ const Align Alignment = Align (IntptrSize);
6139+ std::tie (RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
6140+ MSV.getShadowOriginPtr (RegSaveAreaPtr, IRB, IRB.getInt8Ty (),
6141+ Alignment, /* isStore*/ true );
6142+ IRB.CreateMemCpy (RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
6143+ CopySize);
6144+ }
6145+ }
6146+ };
6147+
6148+ // / Implementation of VarArgHelper that is used for ARM32, MIPS, RISCV,
6149+ // / LoongArch64.
60086150struct VarArgGenericHelper : public VarArgHelperBase {
60096151 AllocaInst *VAArgTLSCopy = nullptr ;
60106152 Value *VAArgSize = nullptr ;
@@ -6016,24 +6158,25 @@ struct VarArgGenericHelper : public VarArgHelperBase {
60166158 void visitCallBase (CallBase &CB, IRBuilder<> &IRB) override {
60176159 unsigned VAArgOffset = 0 ;
60186160 const DataLayout &DL = F.getDataLayout ();
6161+ unsigned IntptrSize = DL.getTypeStoreSize (MS.IntptrTy );
60196162 for (Value *A :
60206163 llvm::drop_begin (CB.args (), CB.getFunctionType ()->getNumParams ())) {
60216164 uint64_t ArgSize = DL.getTypeAllocSize (A->getType ());
60226165 if (DL.isBigEndian ()) {
6023- // Adjusting the shadow for argument with size < 8 to match the
6166+ // Adjusting the shadow for argument with size < IntptrSize to match the
60246167 // placement of bits in big endian system
6025- if (ArgSize < 8 )
6026- VAArgOffset += (8 - ArgSize);
6168+ if (ArgSize < IntptrSize )
6169+ VAArgOffset += (IntptrSize - ArgSize);
60276170 }
60286171 Value *Base = getShadowPtrForVAArgument (IRB, VAArgOffset, ArgSize);
60296172 VAArgOffset += ArgSize;
6030- VAArgOffset = alignTo (VAArgOffset, 8 );
6173+ VAArgOffset = alignTo (VAArgOffset, IntptrSize );
60316174 if (!Base)
60326175 continue ;
60336176 IRB.CreateAlignedStore (MSV.getShadow (A), Base, kShadowTLSAlignment );
60346177 }
60356178
6036- Constant *TotalVAArgSize = ConstantInt::get (IRB. getInt64Ty () , VAArgOffset);
6179+ Constant *TotalVAArgSize = ConstantInt::get (MS. IntptrTy , VAArgOffset);
60376180 // Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
60386181 // a new class member i.e. it is the total size of all VarArgs.
60396182 IRB.CreateStore (TotalVAArgSize, MS.VAArgOverflowSizeTLS );
@@ -6066,11 +6209,16 @@ struct VarArgGenericHelper : public VarArgHelperBase {
60666209 for (CallInst *OrigInst : VAStartInstrumentationList) {
60676210 NextNodeIRBuilder IRB (OrigInst);
60686211 Value *VAListTag = OrigInst->getArgOperand (0 );
6069- Value *RegSaveAreaPtrPtr = IRB.CreateIntToPtr (
6070- IRB.CreatePtrToInt (VAListTag, MS.IntptrTy ), MS.PtrTy );
6071- Value *RegSaveAreaPtr = IRB.CreateLoad (MS.PtrTy , RegSaveAreaPtrPtr);
6212+ Type *RegSaveAreaPtrTy = PointerType::getUnqual (*MS.C );
6213+ Value *RegSaveAreaPtrPtr =
6214+ IRB.CreateIntToPtr (IRB.CreatePtrToInt (VAListTag, MS.IntptrTy ),
6215+ PointerType::get (RegSaveAreaPtrTy, 0 ));
6216+ Value *RegSaveAreaPtr =
6217+ IRB.CreateLoad (RegSaveAreaPtrTy, RegSaveAreaPtrPtr);
60726218 Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
6073- const Align Alignment = Align (8 );
6219+ const DataLayout &DL = F.getDataLayout ();
6220+ unsigned IntptrSize = DL.getTypeStoreSize (MS.IntptrTy );
6221+ const Align Alignment = Align (IntptrSize);
60746222 std::tie (RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
60756223 MSV.getShadowOriginPtr (RegSaveAreaPtr, IRB, IRB.getInt8Ty (),
60766224 Alignment, /* isStore*/ true );
@@ -6080,8 +6228,10 @@ struct VarArgGenericHelper : public VarArgHelperBase {
60806228 }
60816229};
60826230
6083- // Loongarch64 is not a MIPS, but the current vargs calling convention matches
6084- // the MIPS.
6231+ // ARM32, Loongarch64, MIPS and RISCV share the same calling conventions
6232+ // regarding VAArgs.
6233+ using VarArgARM32Helper = VarArgGenericHelper;
6234+ using VarArgRISCVHelper = VarArgGenericHelper;
60856235using VarArgMIPSHelper = VarArgGenericHelper;
60866236using VarArgLoongArch64Helper = VarArgGenericHelper;
60876237
@@ -6106,18 +6256,39 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
61066256 // VarArg handling is only implemented on AMD64. False positives are possible
61076257 // on other platforms.
61086258 Triple TargetTriple (Func.getParent ()->getTargetTriple ());
6259+
6260+ if (TargetTriple.getArch () == Triple::x86)
6261+ return new VarArgI386Helper (Func, Msan, Visitor);
6262+
61096263 if (TargetTriple.getArch () == Triple::x86_64)
61106264 return new VarArgAMD64Helper (Func, Msan, Visitor);
61116265
6266+ if (TargetTriple.isARM ())
6267+ return new VarArgARM32Helper (Func, Msan, Visitor, /* VAListTagSize=*/ 4 );
6268+
61126269 if (TargetTriple.isAArch64 ())
61136270 return new VarArgAArch64Helper (Func, Msan, Visitor);
61146271
61156272 if (TargetTriple.isSystemZ ())
61166273 return new VarArgSystemZHelper (Func, Msan, Visitor);
61176274
6275+ // On PowerPC32 VAListTag is a struct
6276+ // {char, char, i16 padding, char *, char *}
6277+ if (TargetTriple.isPPC32 ())
6278+ return new VarArgPowerPCHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 12 );
6279+
61186280 if (TargetTriple.isPPC64 ())
61196281 return new VarArgPowerPCHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 8 );
61206282
6283+ if (TargetTriple.isRISCV32 ())
6284+ return new VarArgRISCVHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 4 );
6285+
6286+ if (TargetTriple.isRISCV64 ())
6287+ return new VarArgRISCVHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 8 );
6288+
6289+ if (TargetTriple.isMIPS32 ())
6290+ return new VarArgMIPSHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 4 );
6291+
61216292 if (TargetTriple.isMIPS64 ())
61226293 return new VarArgMIPSHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 8 );
61236294
0 commit comments