@@ -581,7 +581,8 @@ class MemorySanitizer {
581
581
friend struct VarArgHelperBase ;
582
582
friend struct VarArgAMD64Helper ;
583
583
friend struct VarArgAArch64Helper ;
584
- friend struct VarArgPowerPCHelper ;
584
+ friend struct VarArgPowerPC64Helper ;
585
+ friend struct VarArgPowerPC32Helper ;
585
586
friend struct VarArgSystemZHelper ;
586
587
friend struct VarArgI386Helper ;
587
588
friend struct VarArgGenericHelper ;
@@ -6271,14 +6272,14 @@ struct VarArgAArch64Helper : public VarArgHelperBase {
6271
6272
}
6272
6273
};
6273
6274
6274
- // / PowerPC -specific implementation of VarArgHelper.
6275
- struct VarArgPowerPCHelper : public VarArgHelperBase {
6275
+ // / PowerPC64 -specific implementation of VarArgHelper.
6276
+ struct VarArgPowerPC64Helper : public VarArgHelperBase {
6276
6277
AllocaInst *VAArgTLSCopy = nullptr ;
6277
6278
Value *VAArgSize = nullptr ;
6278
6279
6279
- VarArgPowerPCHelper (Function &F, MemorySanitizer &MS,
6280
- MemorySanitizerVisitor &MSV, unsigned VAListTagSize )
6281
- : VarArgHelperBase(F, MS, MSV, VAListTagSize) {}
6280
+ VarArgPowerPC64Helper (Function &F, MemorySanitizer &MS,
6281
+ MemorySanitizerVisitor &MSV)
6282
+ : VarArgHelperBase(F, MS, MSV, /* VAListTagSize= */ 8 ) {}
6282
6283
6283
6284
void visitCallBase (CallBase &CB, IRBuilder<> &IRB) override {
6284
6285
// For PowerPC, we need to deal with alignment of stack arguments -
@@ -6292,15 +6293,10 @@ struct VarArgPowerPCHelper : public VarArgHelperBase {
6292
6293
// Parameter save area starts at 48 bytes from frame pointer for ABIv1,
6293
6294
// and 32 bytes for ABIv2. This is usually determined by target
6294
6295
// endianness, but in theory could be overridden by function attribute.
6295
- if (TargetTriple.isPPC64 ()) {
6296
- if (TargetTriple.isPPC64ELFv2ABI ())
6297
- VAArgBase = 32 ;
6298
- else
6299
- VAArgBase = 48 ;
6300
- } else {
6301
- // Parameter save area is 8 bytes from frame pointer in PPC32
6302
- VAArgBase = 8 ;
6303
- }
6296
+ if (TargetTriple.isPPC64ELFv2ABI ())
6297
+ VAArgBase = 32 ;
6298
+ else
6299
+ VAArgBase = 48 ;
6304
6300
unsigned VAArgOffset = VAArgBase;
6305
6301
const DataLayout &DL = F.getDataLayout ();
6306
6302
for (const auto &[ArgNo, A] : llvm::enumerate (CB.args ())) {
@@ -6402,11 +6398,6 @@ struct VarArgPowerPCHelper : public VarArgHelperBase {
6402
6398
Value *VAListTag = OrigInst->getArgOperand (0 );
6403
6399
Value *RegSaveAreaPtrPtr = IRB.CreatePtrToInt (VAListTag, MS.IntptrTy );
6404
6400
6405
- // In PPC32 va_list_tag is a struct, whereas in PPC64 it's a pointer
6406
- if (!TargetTriple.isPPC64 ()) {
6407
- RegSaveAreaPtrPtr =
6408
- IRB.CreateAdd (RegSaveAreaPtrPtr, ConstantInt::get (MS.IntptrTy , 8 ));
6409
- }
6410
6401
RegSaveAreaPtrPtr = IRB.CreateIntToPtr (RegSaveAreaPtrPtr, MS.PtrTy );
6411
6402
6412
6403
Value *RegSaveAreaPtr = IRB.CreateLoad (MS.PtrTy , RegSaveAreaPtrPtr);
@@ -6423,6 +6414,195 @@ struct VarArgPowerPCHelper : public VarArgHelperBase {
6423
6414
}
6424
6415
};
6425
6416
6417
+ // / PowerPC32-specific implementation of VarArgHelper.
6418
+ struct VarArgPowerPC32Helper : public VarArgHelperBase {
6419
+ AllocaInst *VAArgTLSCopy = nullptr ;
6420
+ Value *VAArgSize = nullptr ;
6421
+
6422
+ VarArgPowerPC32Helper (Function &F, MemorySanitizer &MS,
6423
+ MemorySanitizerVisitor &MSV)
6424
+ : VarArgHelperBase(F, MS, MSV, /* VAListTagSize=*/ 12 ) {}
6425
+
6426
+ void visitCallBase (CallBase &CB, IRBuilder<> &IRB) override {
6427
+ unsigned VAArgBase;
6428
+ Triple TargetTriple (F.getParent ()->getTargetTriple ());
6429
+ // Parameter save area is 8 bytes from frame pointer in PPC32
6430
+ VAArgBase = 8 ;
6431
+ unsigned VAArgOffset = VAArgBase;
6432
+ const DataLayout &DL = F.getDataLayout ();
6433
+ unsigned IntptrSize = DL.getTypeStoreSize (IRB.getInt32Ty ());
6434
+ for (const auto &[ArgNo, A] : llvm::enumerate (CB.args ())) {
6435
+ bool IsFixed = ArgNo < CB.getFunctionType ()->getNumParams ();
6436
+ bool IsByVal = CB.paramHasAttr (ArgNo, Attribute::ByVal);
6437
+ if (IsByVal) {
6438
+ assert (A->getType ()->isPointerTy ());
6439
+ Type *RealTy = CB.getParamByValType (ArgNo);
6440
+ uint64_t ArgSize = DL.getTypeAllocSize (RealTy);
6441
+ Align ArgAlign = CB.getParamAlign (ArgNo).value_or (Align (IntptrSize));
6442
+ if (ArgAlign < IntptrSize)
6443
+ ArgAlign = Align (IntptrSize);
6444
+ VAArgOffset = alignTo (VAArgOffset, ArgAlign);
6445
+ if (!IsFixed) {
6446
+ Value *Base =
6447
+ getShadowPtrForVAArgument (IRB, VAArgOffset - VAArgBase, ArgSize);
6448
+ if (Base) {
6449
+ Value *AShadowPtr, *AOriginPtr;
6450
+ std::tie (AShadowPtr, AOriginPtr) =
6451
+ MSV.getShadowOriginPtr (A, IRB, IRB.getInt8Ty (),
6452
+ kShadowTLSAlignment , /* isStore*/ false );
6453
+
6454
+ IRB.CreateMemCpy (Base, kShadowTLSAlignment , AShadowPtr,
6455
+ kShadowTLSAlignment , ArgSize);
6456
+ }
6457
+ }
6458
+ VAArgOffset += alignTo (ArgSize, Align (IntptrSize));
6459
+ } else {
6460
+ Value *Base;
6461
+ Type *ArgTy = A->getType ();
6462
+
6463
+ // On PPC 32 floating point variable arguments are stored in separate
6464
+ // area: fp_save_area = reg_save_area + 4*8. We do not copy shaodow for
6465
+ // them as they will be found when checking call arguments.
6466
+ if (!ArgTy->isFloatingPointTy ()) {
6467
+ uint64_t ArgSize = DL.getTypeAllocSize (ArgTy);
6468
+ Align ArgAlign = Align (IntptrSize);
6469
+ if (ArgTy->isArrayTy ()) {
6470
+ // Arrays are aligned to element size, except for long double
6471
+ // arrays, which are aligned to 8 bytes.
6472
+ Type *ElementTy = ArgTy->getArrayElementType ();
6473
+ if (!ElementTy->isPPC_FP128Ty ())
6474
+ ArgAlign = Align (DL.getTypeAllocSize (ElementTy));
6475
+ } else if (ArgTy->isVectorTy ()) {
6476
+ // Vectors are naturally aligned.
6477
+ ArgAlign = Align (ArgSize);
6478
+ }
6479
+ if (ArgAlign < IntptrSize)
6480
+ ArgAlign = Align (IntptrSize);
6481
+ VAArgOffset = alignTo (VAArgOffset, ArgAlign);
6482
+ if (DL.isBigEndian ()) {
6483
+ // Adjusting the shadow for argument with size < IntptrSize to match
6484
+ // the placement of bits in big endian system
6485
+ if (ArgSize < IntptrSize)
6486
+ VAArgOffset += (IntptrSize - ArgSize);
6487
+ }
6488
+ if (!IsFixed) {
6489
+ Base = getShadowPtrForVAArgument (IRB, VAArgOffset - VAArgBase,
6490
+ ArgSize);
6491
+ if (Base)
6492
+ IRB.CreateAlignedStore (MSV.getShadow (A), Base,
6493
+ kShadowTLSAlignment );
6494
+ }
6495
+ VAArgOffset += ArgSize;
6496
+ VAArgOffset = alignTo (VAArgOffset, Align (IntptrSize));
6497
+ }
6498
+ }
6499
+ }
6500
+
6501
+ Constant *TotalVAArgSize =
6502
+ ConstantInt::get (IRB.getInt32Ty (), VAArgOffset - VAArgBase);
6503
+ // Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
6504
+ // a new class member i.e. it is the total size of all VarArgs.
6505
+ IRB.CreateStore (TotalVAArgSize, MS.VAArgOverflowSizeTLS );
6506
+ }
6507
+
6508
+ void finalizeInstrumentation () override {
6509
+ assert (!VAArgSize && !VAArgTLSCopy &&
6510
+ " finalizeInstrumentation called twice" );
6511
+ IRBuilder<> IRB (MSV.FnPrologueEnd );
6512
+ VAArgSize = IRB.CreateLoad (IRB.getInt32Ty (), MS.VAArgOverflowSizeTLS );
6513
+ Value *CopySize = VAArgSize;
6514
+
6515
+ if (!VAStartInstrumentationList.empty ()) {
6516
+ // If there is a va_start in this function, make a backup copy of
6517
+ // va_arg_tls somewhere in the function entry block.
6518
+
6519
+ VAArgTLSCopy = IRB.CreateAlloca (Type::getInt8Ty (*MS.C ), CopySize);
6520
+ VAArgTLSCopy->setAlignment (kShadowTLSAlignment );
6521
+ IRB.CreateMemSet (VAArgTLSCopy, Constant::getNullValue (IRB.getInt8Ty ()),
6522
+ CopySize, kShadowTLSAlignment , false );
6523
+
6524
+ Value *SrcSize = IRB.CreateBinaryIntrinsic (
6525
+ Intrinsic::umin, CopySize,
6526
+ ConstantInt::get (IRB.getInt32Ty (), kParamTLSSize ));
6527
+ IRB.CreateMemCpy (VAArgTLSCopy, kShadowTLSAlignment , MS.VAArgTLS ,
6528
+ kShadowTLSAlignment , SrcSize);
6529
+ }
6530
+
6531
+ // Instrument va_start.
6532
+ // Copy va_list shadow from the backup copy of the TLS contents.
6533
+ Triple TargetTriple (F.getParent ()->getTargetTriple ());
6534
+ for (CallInst *OrigInst : VAStartInstrumentationList) {
6535
+ NextNodeIRBuilder IRB (OrigInst);
6536
+ Value *VAListTag = OrigInst->getArgOperand (0 );
6537
+ Value *RegSaveAreaPtrPtr =
6538
+ IRB.CreatePtrToInt (VAListTag, IRB.getInt32Ty ());
6539
+ Value *RegSaveAreaSize = CopySize;
6540
+
6541
+ // In PPC32 va_list_tag is a struct
6542
+ RegSaveAreaPtrPtr = IRB.CreateAdd (RegSaveAreaPtrPtr,
6543
+ ConstantInt::get (IRB.getInt32Ty (), 8 ));
6544
+
6545
+ // On PPC 32 reg_save_area can only hold 32 bytes of data
6546
+ RegSaveAreaSize = IRB.CreateBinaryIntrinsic (
6547
+ Intrinsic::umin, CopySize, ConstantInt::get (IRB.getInt32Ty (), 32 ));
6548
+
6549
+ RegSaveAreaPtrPtr = IRB.CreateIntToPtr (RegSaveAreaPtrPtr, MS.PtrTy );
6550
+ Value *RegSaveAreaPtr = IRB.CreateLoad (MS.PtrTy , RegSaveAreaPtrPtr);
6551
+
6552
+ const DataLayout &DL = F.getDataLayout ();
6553
+ unsigned IntptrSize = DL.getTypeStoreSize (IRB.getInt32Ty ());
6554
+ const Align Alignment = Align (IntptrSize);
6555
+
6556
+ { // Copy reg save area
6557
+ Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
6558
+ std::tie (RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
6559
+ MSV.getShadowOriginPtr (RegSaveAreaPtr, IRB, IRB.getInt8Ty (),
6560
+ Alignment, /* isStore*/ true );
6561
+ IRB.CreateMemCpy (RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy,
6562
+ Alignment, RegSaveAreaSize);
6563
+
6564
+ RegSaveAreaShadowPtr =
6565
+ IRB.CreatePtrToInt (RegSaveAreaShadowPtr, IRB.getInt32Ty ());
6566
+ Value *FPSaveArea = IRB.CreateAdd (
6567
+ RegSaveAreaShadowPtr, ConstantInt::get (IRB.getInt32Ty (), 32 ));
6568
+ FPSaveArea = IRB.CreateIntToPtr (FPSaveArea, MS.PtrTy );
6569
+ // We fill fp shadow with zeroes as uninitialized fp args should have
6570
+ // been found during call base check
6571
+ IRB.CreateMemSet (FPSaveArea, ConstantInt::getNullValue (IRB.getInt8Ty ()),
6572
+ ConstantInt::get (IRB.getInt32Ty (), 32 ), Alignment);
6573
+ }
6574
+
6575
+ { // Copy overflow area
6576
+ // RegSaveAreaSize is min(CopySize, 32) -> no overflow can occur
6577
+ Value *OverflowAreaSize = IRB.CreateSub (CopySize, RegSaveAreaSize);
6578
+
6579
+ Value *OverflowAreaPtrPtr =
6580
+ IRB.CreatePtrToInt (VAListTag, IRB.getInt32Ty ());
6581
+ OverflowAreaPtrPtr = IRB.CreateAdd (
6582
+ OverflowAreaPtrPtr, ConstantInt::get (IRB.getInt32Ty (), 4 ));
6583
+ OverflowAreaPtrPtr = IRB.CreateIntToPtr (OverflowAreaPtrPtr, MS.PtrTy );
6584
+
6585
+ Value *OverflowAreaPtr = IRB.CreateLoad (MS.PtrTy , OverflowAreaPtrPtr);
6586
+
6587
+ Value *OverflowAreaShadowPtr, *OverflowAreaOriginPtr;
6588
+ std::tie (OverflowAreaShadowPtr, OverflowAreaOriginPtr) =
6589
+ MSV.getShadowOriginPtr (OverflowAreaPtr, IRB, IRB.getInt8Ty (),
6590
+ Alignment, /* isStore*/ true );
6591
+
6592
+ Value *OverflowVAArgTLSCopyPtr =
6593
+ IRB.CreatePtrToInt (VAArgTLSCopy, IRB.getInt32Ty ());
6594
+ OverflowVAArgTLSCopyPtr =
6595
+ IRB.CreateAdd (OverflowVAArgTLSCopyPtr, RegSaveAreaSize);
6596
+
6597
+ OverflowVAArgTLSCopyPtr =
6598
+ IRB.CreateIntToPtr (OverflowVAArgTLSCopyPtr, MS.PtrTy );
6599
+ IRB.CreateMemCpy (OverflowAreaShadowPtr, Alignment,
6600
+ OverflowVAArgTLSCopyPtr, Alignment, OverflowAreaSize);
6601
+ }
6602
+ }
6603
+ }
6604
+ };
6605
+
6426
6606
// / SystemZ-specific implementation of VarArgHelper.
6427
6607
struct VarArgSystemZHelper : public VarArgHelperBase {
6428
6608
static const unsigned SystemZGpOffset = 16 ;
@@ -6946,10 +7126,10 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
6946
7126
// On PowerPC32 VAListTag is a struct
6947
7127
// {char, char, i16 padding, char *, char *}
6948
7128
if (TargetTriple.isPPC32 ())
6949
- return new VarArgPowerPCHelper (Func, Msan, Visitor, /* VAListTagSize= */ 12 );
7129
+ return new VarArgPowerPC32Helper (Func, Msan, Visitor);
6950
7130
6951
7131
if (TargetTriple.isPPC64 ())
6952
- return new VarArgPowerPCHelper (Func, Msan, Visitor, /* VAListTagSize= */ 8 );
7132
+ return new VarArgPowerPC64Helper (Func, Msan, Visitor);
6953
7133
6954
7134
if (TargetTriple.isRISCV32 ())
6955
7135
return new VarArgRISCVHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 4 );
0 commit comments