#define DEBUG_TYPE "msan"
-static const uint64_t kShadowMask32 = 1ULL << 31;
-static const uint64_t kShadowMask64 = 1ULL << 46;
-static const uint64_t kOriginOffset32 = 1ULL << 30;
-static const uint64_t kOriginOffset64 = 1ULL << 45;
static const unsigned kMinOriginAlignment = 4;
static const unsigned kShadowTLSAlignment = 8;
namespace {
+// Memory map parameters used in application-to-shadow address calculation.
+// Offset = (Addr & ~AndMask) ^ XorMask
+// Shadow = ShadowBase + Offset
+// Origin = OriginBase + Offset
+struct MemoryMapParams {
+ uint64_t AndMask;
+ uint64_t XorMask;
+ uint64_t ShadowBase;
+ uint64_t OriginBase;
+};
+
+struct PlatformMemoryMapParams {
+ const MemoryMapParams *bits32;
+ const MemoryMapParams *bits64;
+};
+
+// i386 Linux
+static const MemoryMapParams LinuxMemoryMapParams32 = {
+ 0x000080000000, // AndMask
+ 0, // XorMask (not used)
+ 0, // ShadowBase (not used)
+ 0x000040000000, // OriginBase
+};
+
+// x86_64 Linux
+static const MemoryMapParams LinuxMemoryMapParams64 = {
+ 0x400000000000, // AndMask
+ 0, // XorMask (not used)
+ 0, // ShadowBase (not used)
+ 0x200000000000, // OriginBase
+};
+
+// i386 FreeBSD
+static const MemoryMapParams FreeBSDMemoryMapParams32 = {
+ 0x000180000000, // AndMask
+ 0x000040000000, // XorMask
+ 0x000020000000, // ShadowBase
+ 0x000700000000, // OriginBase
+};
+
+// x86_64 FreeBSD
+static const MemoryMapParams FreeBSDMemoryMapParams64 = {
+ 0xc00000000000, // AndMask
+ 0x200000000000, // XorMask
+ 0x100000000000, // ShadowBase
+ 0x380000000000, // OriginBase
+};
+
+static const PlatformMemoryMapParams LinuxMemoryMapParams = {
+ &LinuxMemoryMapParams32,
+ &LinuxMemoryMapParams64,
+};
+
+static const PlatformMemoryMapParams FreeBSDMemoryMapParams = {
+ &FreeBSDMemoryMapParams32,
+ &FreeBSDMemoryMapParams64,
+};
+
/// \brief An instrumentation pass implementing detection of uninitialized
/// reads.
///
/// \brief MSan runtime replacements for memmove, memcpy and memset.
Value *MemmoveFn, *MemcpyFn, *MemsetFn;
- /// \brief Address mask used in application-to-shadow address calculation.
- /// ShadowAddr is computed as ApplicationAddr & ~ShadowMask.
- uint64_t ShadowMask;
- /// \brief Offset of the origin shadow from the "normal" shadow.
- /// OriginAddr is computed as (ShadowAddr + OriginOffset) & ~3ULL
- uint64_t OriginOffset;
- /// \brief Branch weights for error reporting.
+ /// \brief Memory map parameters used in application-to-shadow calculation.
+ const MemoryMapParams *MapParams;
+
MDNode *ColdCallWeights;
/// \brief Branch weights for origin store.
MDNode *OriginStoreWeights;
report_fatal_error("data layout missing");
DL = &DLP->getDataLayout();
+ Triple TargetTriple(M.getTargetTriple());
+ const PlatformMemoryMapParams *PlatformMapParams;
+ if (TargetTriple.getOS() == Triple::FreeBSD)
+ PlatformMapParams = &FreeBSDMemoryMapParams;
+ else
+ PlatformMapParams = &LinuxMemoryMapParams;
+
C = &(M.getContext());
unsigned PtrSize = DL->getPointerSizeInBits(/* AddressSpace */0);
switch (PtrSize) {
case 64:
- ShadowMask = kShadowMask64;
- OriginOffset = kOriginOffset64;
+ MapParams = PlatformMapParams->bits64;
break;
case 32:
- ShadowMask = kShadowMask32;
- OriginOffset = kOriginOffset32;
+ MapParams = PlatformMapParams->bits32;
break;
default:
report_fatal_error("unsupported pointer size");
void storeOrigin(IRBuilder<> &IRB, Value *Addr, Value *Shadow, Value *Origin,
unsigned Alignment, bool AsCall) {
+ unsigned OriginAlignment = std::max(kMinOriginAlignment, Alignment);
if (isa<StructType>(Shadow->getType())) {
- IRB.CreateAlignedStore(updateOrigin(Origin, IRB), getOriginPtr(Addr, IRB),
- Alignment);
+ IRB.CreateAlignedStore(updateOrigin(Origin, IRB),
+ getOriginPtr(Addr, IRB, Alignment),
+ OriginAlignment);
} else {
Value *ConvertedShadow = convertToShadowTyNoVec(Shadow, IRB);
// TODO(eugenis): handle non-zero constant shadow by inserting an
Cmp, IRB.GetInsertPoint(), false, MS.OriginStoreWeights);
IRBuilder<> IRBNew(CheckTerm);
IRBNew.CreateAlignedStore(updateOrigin(Origin, IRBNew),
- getOriginPtr(Addr, IRBNew), Alignment);
+ getOriginPtr(Addr, IRBNew, Alignment),
+ OriginAlignment);
}
}
}
if (SI.isAtomic()) SI.setOrdering(addReleaseOrdering(SI.getOrdering()));
- if (MS.TrackOrigins) {
- unsigned Alignment = std::max(kMinOriginAlignment, SI.getAlignment());
- storeOrigin(IRB, Addr, Shadow, getOrigin(Val), Alignment,
+ if (MS.TrackOrigins)
+ storeOrigin(IRB, Addr, Shadow, getOrigin(Val), SI.getAlignment(),
InstrumentWithCalls);
- }
}
}
return IRB.CreateBitCast(V, NoVecTy);
}
+ /// \brief Compute the integer shadow offset that corresponds to a given
+ /// application address.
+ ///
+ /// Offset = (Addr & ~AndMask) ^ XorMask
+ Value *getShadowPtrOffset(Value *Addr, IRBuilder<> &IRB) {
+ uint64_t AndMask = MS.MapParams->AndMask;
+ assert(AndMask != 0 && "AndMask shall be specified");
+ Value *OffsetLong =
+ IRB.CreateAnd(IRB.CreatePointerCast(Addr, MS.IntptrTy),
+ ConstantInt::get(MS.IntptrTy, ~AndMask));
+
+ uint64_t XorMask = MS.MapParams->XorMask;
+ if (XorMask != 0)
+ OffsetLong = IRB.CreateXor(OffsetLong,
+ ConstantInt::get(MS.IntptrTy, XorMask));
+ return OffsetLong;
+ }
+
/// \brief Compute the shadow address that corresponds to a given application
/// address.
///
- /// Shadow = Addr & ~ShadowMask.
+ /// Shadow = ShadowBase + Offset
Value *getShadowPtr(Value *Addr, Type *ShadowTy,
IRBuilder<> &IRB) {
- Value *ShadowLong =
- IRB.CreateAnd(IRB.CreatePointerCast(Addr, MS.IntptrTy),
- ConstantInt::get(MS.IntptrTy, ~MS.ShadowMask));
+ Value *ShadowLong = getShadowPtrOffset(Addr, IRB);
+ uint64_t ShadowBase = MS.MapParams->ShadowBase;
+ if (ShadowBase != 0)
+ ShadowLong =
+ IRB.CreateAdd(ShadowLong,
+ ConstantInt::get(MS.IntptrTy, ShadowBase));
return IRB.CreateIntToPtr(ShadowLong, PointerType::get(ShadowTy, 0));
}
/// \brief Compute the origin address that corresponds to a given application
/// address.
///
- /// OriginAddr = (ShadowAddr + OriginOffset) & ~3ULL
- Value *getOriginPtr(Value *Addr, IRBuilder<> &IRB) {
- Value *ShadowLong =
- IRB.CreateAnd(IRB.CreatePointerCast(Addr, MS.IntptrTy),
- ConstantInt::get(MS.IntptrTy, ~MS.ShadowMask));
- Value *Add =
- IRB.CreateAdd(ShadowLong,
- ConstantInt::get(MS.IntptrTy, MS.OriginOffset));
- Value *SecondAnd =
- IRB.CreateAnd(Add, ConstantInt::get(MS.IntptrTy, ~3ULL));
- return IRB.CreateIntToPtr(SecondAnd, PointerType::get(IRB.getInt32Ty(), 0));
+ /// OriginAddr = (OriginBase + Offset) & ~3ULL
+ Value *getOriginPtr(Value *Addr, IRBuilder<> &IRB, unsigned Alignment) {
+ Value *OriginLong = getShadowPtrOffset(Addr, IRB);
+ uint64_t OriginBase = MS.MapParams->OriginBase;
+ if (OriginBase != 0)
+ OriginLong =
+ IRB.CreateAdd(OriginLong,
+ ConstantInt::get(MS.IntptrTy, OriginBase));
+ if (Alignment < kMinOriginAlignment) {
+ uint64_t Mask = kMinOriginAlignment - 1;
+ OriginLong = IRB.CreateAnd(OriginLong,
+ ConstantInt::get(MS.IntptrTy, ~Mask));
+ }
+ return IRB.CreateIntToPtr(OriginLong,
+ PointerType::get(IRB.getInt32Ty(), 0));
}
/// \brief Compute the shadow address for a given function argument.
IRBuilder<> IRB(I.getNextNode());
Type *ShadowTy = getShadowTy(&I);
Value *Addr = I.getPointerOperand();
- if (PropagateShadow) {
+ if (PropagateShadow && !I.getMetadata("nosanitize")) {
Value *ShadowPtr = getShadowPtr(Addr, ShadowTy, IRB);
setShadow(&I,
IRB.CreateAlignedLoad(ShadowPtr, I.getAlignment(), "_msld"));
if (MS.TrackOrigins) {
if (PropagateShadow) {
- unsigned Alignment = std::max(kMinOriginAlignment, I.getAlignment());
- setOrigin(&I,
- IRB.CreateAlignedLoad(getOriginPtr(Addr, IRB), Alignment));
+ unsigned Alignment = I.getAlignment();
+ unsigned OriginAlignment = std::max(kMinOriginAlignment, Alignment);
+ setOrigin(&I, IRB.CreateAlignedLoad(getOriginPtr(Addr, IRB, Alignment),
+ OriginAlignment));
} else {
setOrigin(&I, getCleanOrigin());
}
// FIXME: use ClStoreCleanOrigin
// FIXME: factor out common code from materializeStores
if (MS.TrackOrigins)
- IRB.CreateStore(getOrigin(&I, 1), getOriginPtr(Addr, IRB));
+ IRB.CreateStore(getOrigin(&I, 1), getOriginPtr(Addr, IRB, 1));
return true;
}
if (MS.TrackOrigins) {
if (PropagateShadow)
- setOrigin(&I, IRB.CreateLoad(getOriginPtr(Addr, IRB)));
+ setOrigin(&I, IRB.CreateLoad(getOriginPtr(Addr, IRB, 1)));
else
setOrigin(&I, getCleanOrigin());
}
setOrigin(&I, getOrigin(CopyOp));
} else {
setShadow(&I, getCleanShadow(&I));
+ setOrigin(&I, getCleanOrigin());
}
}
IRBuilder<> IRB(&I);
if (!PropagateShadow) {
setShadow(&I, getCleanShadow(&I));
+ setOrigin(&I, getCleanOrigin());
return;
}
void visitAllocaInst(AllocaInst &I) {
setShadow(&I, getCleanShadow(&I));
+ setOrigin(&I, getCleanOrigin());
IRBuilder<> IRB(I.getNextNode());
uint64_t Size = MS.DL->getTypeAllocSize(I.getAllocatedType());
if (PoisonStack && ClPoisonStackWithCall) {
}
if (PoisonStack && MS.TrackOrigins) {
- setOrigin(&I, getCleanOrigin());
SmallString<2048> StackDescriptionStorage;
raw_svector_ostream StackDescription(StackDescriptionStorage);
// We create a string with a description of the stack allocation and