@@ -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 ;
@@ -6392,13 +6393,165 @@ struct VarArgAArch64Helper : public VarArgHelperBase {
6392
6393
}
6393
6394
};
6394
6395
6395
- // / PowerPC -specific implementation of VarArgHelper.
6396
- struct VarArgPowerPCHelper : public VarArgHelperBase {
6396
+ // / PowerPC64 -specific implementation of VarArgHelper.
6397
+ struct VarArgPowerPC64Helper : public VarArgHelperBase {
6397
6398
AllocaInst *VAArgTLSCopy = nullptr ;
6398
6399
Value *VAArgSize = nullptr ;
6399
6400
6400
- VarArgPowerPCHelper (Function &F, MemorySanitizer &MS,
6401
- MemorySanitizerVisitor &MSV, unsigned VAListTagSize)
6401
+ VarArgPowerPC64Helper (Function &F, MemorySanitizer &MS,
6402
+ MemorySanitizerVisitor &MSV, unsigned VAListTagSize)
6403
+ : VarArgHelperBase(F, MS, MSV, VAListTagSize) {}
6404
+
6405
+ void visitCallBase (CallBase &CB, IRBuilder<> &IRB) override {
6406
+ // For PowerPC, we need to deal with alignment of stack arguments -
6407
+ // they are mostly aligned to 8 bytes, but vectors and i128 arrays
6408
+ // are aligned to 16 bytes, byvals can be aligned to 8 or 16 bytes,
6409
+ // For that reason, we compute current offset from stack pointer (which is
6410
+ // always properly aligned), and offset for the first vararg, then subtract
6411
+ // them.
6412
+ unsigned VAArgBase;
6413
+ Triple TargetTriple (F.getParent ()->getTargetTriple ());
6414
+ // Parameter save area starts at 48 bytes from frame pointer for ABIv1,
6415
+ // and 32 bytes for ABIv2. This is usually determined by target
6416
+ // endianness, but in theory could be overridden by function attribute.
6417
+ if (TargetTriple.isPPC64 ()) {
6418
+ if (TargetTriple.isPPC64ELFv2ABI ())
6419
+ VAArgBase = 32 ;
6420
+ else
6421
+ VAArgBase = 48 ;
6422
+ } else {
6423
+ // Parameter save area is 8 bytes from frame pointer in PPC32
6424
+ VAArgBase = 8 ;
6425
+ }
6426
+ unsigned VAArgOffset = VAArgBase;
6427
+ const DataLayout &DL = F.getDataLayout ();
6428
+ for (const auto &[ArgNo, A] : llvm::enumerate (CB.args ())) {
6429
+ bool IsFixed = ArgNo < CB.getFunctionType ()->getNumParams ();
6430
+ bool IsByVal = CB.paramHasAttr (ArgNo, Attribute::ByVal);
6431
+ if (IsByVal) {
6432
+ assert (A->getType ()->isPointerTy ());
6433
+ Type *RealTy = CB.getParamByValType (ArgNo);
6434
+ uint64_t ArgSize = DL.getTypeAllocSize (RealTy);
6435
+ Align ArgAlign = CB.getParamAlign (ArgNo).value_or (Align (8 ));
6436
+ if (ArgAlign < 8 )
6437
+ ArgAlign = Align (8 );
6438
+ VAArgOffset = alignTo (VAArgOffset, ArgAlign);
6439
+ if (!IsFixed) {
6440
+ Value *Base =
6441
+ getShadowPtrForVAArgument (IRB, VAArgOffset - VAArgBase, ArgSize);
6442
+ if (Base) {
6443
+ Value *AShadowPtr, *AOriginPtr;
6444
+ std::tie (AShadowPtr, AOriginPtr) =
6445
+ MSV.getShadowOriginPtr (A, IRB, IRB.getInt8Ty (),
6446
+ kShadowTLSAlignment , /* isStore*/ false );
6447
+
6448
+ IRB.CreateMemCpy (Base, kShadowTLSAlignment , AShadowPtr,
6449
+ kShadowTLSAlignment , ArgSize);
6450
+ }
6451
+ }
6452
+ VAArgOffset += alignTo (ArgSize, Align (8 ));
6453
+ } else {
6454
+ Value *Base;
6455
+ uint64_t ArgSize = DL.getTypeAllocSize (A->getType ());
6456
+ Align ArgAlign = Align (8 );
6457
+ if (A->getType ()->isArrayTy ()) {
6458
+ // Arrays are aligned to element size, except for long double
6459
+ // arrays, which are aligned to 8 bytes.
6460
+ Type *ElementTy = A->getType ()->getArrayElementType ();
6461
+ if (!ElementTy->isPPC_FP128Ty ())
6462
+ ArgAlign = Align (DL.getTypeAllocSize (ElementTy));
6463
+ } else if (A->getType ()->isVectorTy ()) {
6464
+ // Vectors are naturally aligned.
6465
+ ArgAlign = Align (ArgSize);
6466
+ }
6467
+ if (ArgAlign < 8 )
6468
+ ArgAlign = Align (8 );
6469
+ VAArgOffset = alignTo (VAArgOffset, ArgAlign);
6470
+ if (DL.isBigEndian ()) {
6471
+ // Adjusting the shadow for argument with size < 8 to match the
6472
+ // placement of bits in big endian system
6473
+ if (ArgSize < 8 )
6474
+ VAArgOffset += (8 - ArgSize);
6475
+ }
6476
+ if (!IsFixed) {
6477
+ Base =
6478
+ getShadowPtrForVAArgument (IRB, VAArgOffset - VAArgBase, ArgSize);
6479
+ if (Base)
6480
+ IRB.CreateAlignedStore (MSV.getShadow (A), Base, kShadowTLSAlignment );
6481
+ }
6482
+ VAArgOffset += ArgSize;
6483
+ VAArgOffset = alignTo (VAArgOffset, Align (8 ));
6484
+ }
6485
+ if (IsFixed)
6486
+ VAArgBase = VAArgOffset;
6487
+ }
6488
+
6489
+ Constant *TotalVAArgSize =
6490
+ ConstantInt::get (MS.IntptrTy , VAArgOffset - VAArgBase);
6491
+ // Here using VAArgOverflowSizeTLS as VAArgSizeTLS to avoid creation of
6492
+ // a new class member i.e. it is the total size of all VarArgs.
6493
+ IRB.CreateStore (TotalVAArgSize, MS.VAArgOverflowSizeTLS );
6494
+ }
6495
+
6496
+ void finalizeInstrumentation () override {
6497
+ assert (!VAArgSize && !VAArgTLSCopy &&
6498
+ " finalizeInstrumentation called twice" );
6499
+ IRBuilder<> IRB (MSV.FnPrologueEnd );
6500
+ VAArgSize = IRB.CreateLoad (IRB.getInt64Ty (), MS.VAArgOverflowSizeTLS );
6501
+ Value *CopySize = VAArgSize;
6502
+
6503
+ if (!VAStartInstrumentationList.empty ()) {
6504
+ // If there is a va_start in this function, make a backup copy of
6505
+ // va_arg_tls somewhere in the function entry block.
6506
+
6507
+ VAArgTLSCopy = IRB.CreateAlloca (Type::getInt8Ty (*MS.C ), CopySize);
6508
+ VAArgTLSCopy->setAlignment (kShadowTLSAlignment );
6509
+ IRB.CreateMemSet (VAArgTLSCopy, Constant::getNullValue (IRB.getInt8Ty ()),
6510
+ CopySize, kShadowTLSAlignment , false );
6511
+
6512
+ Value *SrcSize = IRB.CreateBinaryIntrinsic (
6513
+ Intrinsic::umin, CopySize,
6514
+ ConstantInt::get (IRB.getInt64Ty (), kParamTLSSize ));
6515
+ IRB.CreateMemCpy (VAArgTLSCopy, kShadowTLSAlignment , MS.VAArgTLS ,
6516
+ kShadowTLSAlignment , SrcSize);
6517
+ }
6518
+
6519
+ // Instrument va_start.
6520
+ // Copy va_list shadow from the backup copy of the TLS contents.
6521
+ Triple TargetTriple (F.getParent ()->getTargetTriple ());
6522
+ for (CallInst *OrigInst : VAStartInstrumentationList) {
6523
+ NextNodeIRBuilder IRB (OrigInst);
6524
+ Value *VAListTag = OrigInst->getArgOperand (0 );
6525
+ Value *RegSaveAreaPtrPtr = IRB.CreatePtrToInt (VAListTag, MS.IntptrTy );
6526
+
6527
+ // In PPC32 va_list_tag is a struct, whereas in PPC64 it's a pointer
6528
+ if (!TargetTriple.isPPC64 ()) {
6529
+ RegSaveAreaPtrPtr =
6530
+ IRB.CreateAdd (RegSaveAreaPtrPtr, ConstantInt::get (MS.IntptrTy , 8 ));
6531
+ }
6532
+ RegSaveAreaPtrPtr = IRB.CreateIntToPtr (RegSaveAreaPtrPtr, MS.PtrTy );
6533
+
6534
+ Value *RegSaveAreaPtr = IRB.CreateLoad (MS.PtrTy , RegSaveAreaPtrPtr);
6535
+ Value *RegSaveAreaShadowPtr, *RegSaveAreaOriginPtr;
6536
+ const DataLayout &DL = F.getDataLayout ();
6537
+ unsigned IntptrSize = DL.getTypeStoreSize (MS.IntptrTy );
6538
+ const Align Alignment = Align (IntptrSize);
6539
+ std::tie (RegSaveAreaShadowPtr, RegSaveAreaOriginPtr) =
6540
+ MSV.getShadowOriginPtr (RegSaveAreaPtr, IRB, IRB.getInt8Ty (),
6541
+ Alignment, /* isStore*/ true );
6542
+ IRB.CreateMemCpy (RegSaveAreaShadowPtr, Alignment, VAArgTLSCopy, Alignment,
6543
+ CopySize);
6544
+ }
6545
+ }
6546
+ };
6547
+
6548
+ // / PowerPC32-specific implementation of VarArgHelper.
6549
+ struct VarArgPowerPC32Helper : public VarArgHelperBase {
6550
+ AllocaInst *VAArgTLSCopy = nullptr ;
6551
+ Value *VAArgSize = nullptr ;
6552
+
6553
+ VarArgPowerPC32Helper (Function &F, MemorySanitizer &MS,
6554
+ MemorySanitizerVisitor &MSV, unsigned VAListTagSize)
6402
6555
: VarArgHelperBase(F, MS, MSV, VAListTagSize) {}
6403
6556
6404
6557
void visitCallBase (CallBase &CB, IRBuilder<> &IRB) override {
@@ -7067,10 +7220,10 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan,
7067
7220
// On PowerPC32 VAListTag is a struct
7068
7221
// {char, char, i16 padding, char *, char *}
7069
7222
if (TargetTriple.isPPC32 ())
7070
- return new VarArgPowerPCHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 12 );
7223
+ return new VarArgPowerPC32Helper (Func, Msan, Visitor, /* VAListTagSize=*/ 12 );
7071
7224
7072
7225
if (TargetTriple.isPPC64 ())
7073
- return new VarArgPowerPCHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 8 );
7226
+ return new VarArgPowerPC64Helper (Func, Msan, Visitor, /* VAListTagSize=*/ 8 );
7074
7227
7075
7228
if (TargetTriple.isRISCV32 ())
7076
7229
return new VarArgRISCVHelper (Func, Msan, Visitor, /* VAListTagSize=*/ 4 );
0 commit comments