@@ -411,6 +411,10 @@ static const MemoryMapParams Linux_X86_64_MemoryMapParams = {
411
411
0x100000000000 , // OriginBase
412
412
};
413
413
414
+ // mips32 Linux
415
+ // FIXME: Remove -msan-origin-base -msan-and-mask added by PR #109284 to tests
416
+ // after picking good constants
417
+
414
418
// mips64 Linux
415
419
static const MemoryMapParams Linux_MIPS64_MemoryMapParams = {
416
420
0 , // AndMask (not used)
@@ -419,6 +423,10 @@ static const MemoryMapParams Linux_MIPS64_MemoryMapParams = {
419
423
0x002000000000 , // OriginBase
420
424
};
421
425
426
+ // ppc32 Linux
427
+ // FIXME: Remove -msan-origin-base -msan-and-mask added by PR #109284 to tests
428
+ // after picking good constants
429
+
422
430
// ppc64 Linux
423
431
static const MemoryMapParams Linux_PowerPC64_MemoryMapParams = {
424
432
0xE00000000000 , // AndMask
@@ -435,6 +443,10 @@ static const MemoryMapParams Linux_S390X_MemoryMapParams = {
435
443
0x1C0000000000 , // OriginBase
436
444
};
437
445
446
+ // arm32 Linux
447
+ // FIXME: Remove -msan-origin-base -msan-and-mask added by PR #109284 to tests
448
+ // after picking good constants
449
+
438
450
// aarch64 Linux
439
451
static const MemoryMapParams Linux_AArch64_MemoryMapParams = {
440
452
0 , // AndMask (not used)
@@ -451,6 +463,10 @@ static const MemoryMapParams Linux_LoongArch64_MemoryMapParams = {
451
463
0x100000000000 , // OriginBase
452
464
};
453
465
466
+ // riscv32 Linux
467
+ // FIXME: Remove -msan-origin-base -msan-and-mask added by PR #109284 to tests
468
+ // after picking good constants
469
+
454
470
// aarch64 FreeBSD
455
471
static const MemoryMapParams FreeBSD_AArch64_MemoryMapParams = {
456
472
0x1800000000000 , // AndMask
@@ -559,6 +575,7 @@ class MemorySanitizer {
559
575
friend struct VarArgAArch64Helper ;
560
576
friend struct VarArgPowerPCHelper ;
561
577
friend struct VarArgSystemZHelper ;
578
+ friend struct VarArgI386Helper ;
562
579
friend struct VarArgGenericHelper ;
563
580
564
581
void initializeModule (Module &M);
@@ -5606,10 +5623,15 @@ struct VarArgPowerPCHelper : public VarArgHelperBase {
5606
5623
// Parameter save area starts at 48 bytes from frame pointer for ABIv1,
5607
5624
// and 32 bytes for ABIv2. This is usually determined by target
5608
5625
// 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
+ }
5613
5635
unsigned VAArgOffset = VAArgBase;
5614
5636
const DataLayout &DL = F.getDataLayout ();
5615
5637
for (const auto &[ArgNo, A] : llvm::enumerate (CB.args ())) {
@@ -5674,7 +5696,7 @@ struct VarArgPowerPCHelper : public VarArgHelperBase {
5674
5696
}
5675
5697
5676
5698
Constant *TotalVAArgSize =
5677
- ConstantInt::get (IRB. getInt64Ty () , VAArgOffset - VAArgBase);
5699
+ ConstantInt::get (MS. IntptrTy , VAArgOffset - VAArgBase);
5678
5700
// Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
5679
5701
// a new class member i.e. it is the total size of all VarArgs.
5680
5702
IRB.CreateStore (TotalVAArgSize, MS.VAArgOverflowSizeTLS );
@@ -5705,14 +5727,24 @@ struct VarArgPowerPCHelper : public VarArgHelperBase {
5705
5727
5706
5728
// Instrument va_start.
5707
5729
// Copy va_list shadow from the backup copy of the TLS contents.
5730
+ Triple TargetTriple (F.getParent ()->getTargetTriple ());
5708
5731
for (CallInst *OrigInst : VAStartInstrumentationList) {
5709
5732
NextNodeIRBuilder IRB (OrigInst);
5710
5733
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
+
5713
5743
Value *RegSaveAreaPtr = IRB.CreateLoad (MS.PtrTy , RegSaveAreaPtrPtr);
5714
5744
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);
5716
5748
std::tie (RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
5717
5749
MSV.getShadowOriginPtr (RegSaveAreaPtr, IRB, IRB.getInt8Ty (),
5718
5750
Alignment, /* isStore*/ true );
@@ -6003,8 +6035,118 @@ struct VarArgSystemZHelper : public VarArgHelperBase {
6003
6035
}
6004
6036
};
6005
6037
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.
6008
6150
struct VarArgGenericHelper : public VarArgHelperBase {
6009
6151
AllocaInst *VAArgTLSCopy = nullptr ;
6010
6152
Value *VAArgSize = nullptr ;
@@ -6016,24 +6158,25 @@ struct VarArgGenericHelper : public VarArgHelperBase {
6016
6158
void visitCallBase (CallBase &CB, IRBuilder<> &IRB) override {
6017
6159
unsigned VAArgOffset = 0 ;
6018
6160
const DataLayout &DL = F.getDataLayout ();
6161
+ unsigned IntptrSize = DL.getTypeStoreSize (MS.IntptrTy );
6019
6162
for (Value *A :
6020
6163
llvm::drop_begin (CB.args (), CB.getFunctionType ()->getNumParams ())) {
6021
6164
uint64_t ArgSize = DL.getTypeAllocSize (A->getType ());
6022
6165
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
6024
6167
// placement of bits in big endian system
6025
- if (ArgSize < 8 )
6026
- VAArgOffset += (8 - ArgSize);
6168
+ if (ArgSize < IntptrSize )
6169
+ VAArgOffset += (IntptrSize - ArgSize);
6027
6170
}
6028
6171
Value *Base = getShadowPtrForVAArgument (IRB, VAArgOffset, ArgSize);
6029
6172
VAArgOffset += ArgSize;
6030
- VAArgOffset = alignTo (VAArgOffset, 8 );
6173
+ VAArgOffset = alignTo (VAArgOffset, IntptrSize );
6031
6174
if (!Base)
6032
6175
continue ;
6033
6176
IRB.CreateAlignedStore (MSV.getShadow (A), Base, kShadowTLSAlignment );
6034
6177
}
6035
6178
6036
- Constant *TotalVAArgSize = ConstantInt::get (IRB. getInt64Ty () , VAArgOffset);
6179
+ Constant *TotalVAArgSize = ConstantInt::get (MS. IntptrTy , VAArgOffset);
6037
6180
// Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
6038
6181
// a new class member i.e. it is the total size of all VarArgs.
6039
6182
IRB.CreateStore (TotalVAArgSize, MS.VAArgOverflowSizeTLS );
@@ -6066,11 +6209,16 @@ struct VarArgGenericHelper : public VarArgHelperBase {
6066
6209
for (CallInst *OrigInst : VAStartInstrumentationList) {
6067
6210
NextNodeIRBuilder IRB (OrigInst);
6068
6211
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);
6072
6218
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);
6074
6222
std::tie (RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
6075
6223
MSV.getShadowOriginPtr (RegSaveAreaPtr, IRB, IRB.getInt8Ty (),
6076
6224
Alignment, /* isStore*/ true );
@@ -6080,8 +6228,10 @@ struct VarArgGenericHelper : public VarArgHelperBase {
6080
6228
}
6081
6229
};
6082
6230
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;
6085
6235
using VarArgMIPSHelper = VarArgGenericHelper;
6086
6236
using VarArgLoongArch64Helper = VarArgGenericHelper;
6087
6237
@@ -6106,18 +6256,39 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
6106
6256
// VarArg handling is only implemented on AMD64. False positives are possible
6107
6257
// on other platforms.
6108
6258
Triple TargetTriple (Func.getParent ()->getTargetTriple ());
6259
+
6260
+ if (TargetTriple.getArch () == Triple::x86)
6261
+ return new VarArgI386Helper (Func, Msan, Visitor);
6262
+
6109
6263
if (TargetTriple.getArch () == Triple::x86_64)
6110
6264
return new VarArgAMD64Helper (Func, Msan, Visitor);
6111
6265
6266
+ if (TargetTriple.isARM ())
6267
+ return new VarArgARM32Helper (Func, Msan, Visitor, /* VAListTagSize=*/ 4 );
6268
+
6112
6269
if (TargetTriple.isAArch64 ())
6113
6270
return new VarArgAArch64Helper (Func, Msan, Visitor);
6114
6271
6115
6272
if (TargetTriple.isSystemZ ())
6116
6273
return new VarArgSystemZHelper (Func, Msan, Visitor);
6117
6274
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
+
6118
6280
if (TargetTriple.isPPC64 ())
6119
6281
return new VarArgPowerPCHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 8 );
6120
6282
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
+
6121
6292
if (TargetTriple.isMIPS64 ())
6122
6293
return new VarArgMIPSHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 8 );
6123
6294
0 commit comments