diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp --- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp +++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp @@ -537,7 +537,7 @@ return Mapping; } -static size_t RedzoneSizeForScale(int MappingScale) { +static uint64_t getRedzoneSizeForScale(int MappingScale) { // Redzone used for stack and globals is at least 32 bytes. // For scales 6 and 7, the redzone has to be 64 and 128 bytes respectively. return std::max(32U, 1U << MappingScale); @@ -797,9 +797,10 @@ StringRef getGlobalMetadataSection() const; void poisonOneInitializer(Function &GlobalInit, GlobalValue *ModuleName); void createInitializerPoisonCalls(Module &M, GlobalValue *ModuleName); - size_t MinRedzoneSizeForGlobal() const { - return RedzoneSizeForScale(Mapping.Scale); + uint64_t getMinRedzoneSizeForGlobal() const { + return getRedzoneSizeForScale(Mapping.Scale); } + uint64_t getRedzoneSizeForGlobal(uint64_t SizeInBytes) const; int GetAsanVersion(const Module &M) const; const GlobalsMetadata &GlobalsMD; @@ -1824,7 +1825,7 @@ // - Need to poison all copies, not just the main thread's one. if (G->isThreadLocal()) return false; // For now, just ignore this Global if the alignment is large. - if (G->getAlignment() > MinRedzoneSizeForGlobal()) return false; + if (G->getAlignment() > getMinRedzoneSizeForGlobal()) return false; // For non-COFF targets, only instrument globals known to be defined by this // TU. @@ -2312,7 +2313,6 @@ M, M.getModuleIdentifier(), /*AllowMerging*/ false, kAsanGenPrefix); for (size_t i = 0; i < n; i++) { - static const uint64_t kMaxGlobalRedzone = 1 << 18; GlobalVariable *G = GlobalsToChange[i]; // FIXME: Metadata should be attched directly to the global directly instead @@ -2326,16 +2326,8 @@ /*AllowMerging*/ true, kAsanGenPrefix); Type *Ty = G->getValueType(); - uint64_t SizeInBytes = DL.getTypeAllocSize(Ty); - uint64_t MinRZ = MinRedzoneSizeForGlobal(); - // MinRZ <= RZ <= kMaxGlobalRedzone - // and trying to make RZ to be ~ 1/4 of SizeInBytes. - uint64_t RZ = std::max( - MinRZ, std::min(kMaxGlobalRedzone, (SizeInBytes / MinRZ / 4) * MinRZ)); - uint64_t RightRedzoneSize = RZ; - // Round up to MinRZ - if (SizeInBytes % MinRZ) RightRedzoneSize += MinRZ - (SizeInBytes % MinRZ); - assert(((RightRedzoneSize + SizeInBytes) % MinRZ) == 0); + const uint64_t SizeInBytes = DL.getTypeAllocSize(Ty); + const uint64_t RightRedzoneSize = getRedzoneSizeForGlobal(SizeInBytes); Type *RightRedZoneTy = ArrayType::get(IRB.getInt8Ty(), RightRedzoneSize); StructType *NewTy = StructType::get(Ty, RightRedZoneTy); @@ -2351,7 +2343,7 @@ "", G, G->getThreadLocalMode()); NewGlobal->copyAttributesFrom(G); NewGlobal->setComdat(G->getComdat()); - NewGlobal->setAlignment(MaybeAlign(MinRZ)); + NewGlobal->setAlignment(MaybeAlign(getMinRedzoneSizeForGlobal())); // Don't fold globals with redzones. ODR violation detector and redzone // poisoning implicitly creates a dependence on the global's address, so it // is no longer valid for it to be marked unnamed_addr. @@ -2473,6 +2465,23 @@ return true; } +uint64_t +ModuleAddressSanitizer::getRedzoneSizeForGlobal(uint64_t SizeInBytes) const { + constexpr uint64_t kMaxRZ = 1 << 18; + const uint64_t MinRZ = getMinRedzoneSizeForGlobal(); + + // Calculate RZ, where MinRZ <= RZ <= MaxRZ, and RZ ~ 1/4 * SizeInBytes. + uint64_t RZ = + std::max(MinRZ, std::min(kMaxRZ, (SizeInBytes / MinRZ / 4) * MinRZ)); + + // Round up to multiple of MinRZ. + if (SizeInBytes % MinRZ) + RZ += MinRZ - (SizeInBytes % MinRZ); + assert((RZ + SizeInBytes) % MinRZ == 0); + + return RZ; +} + int ModuleAddressSanitizer::GetAsanVersion(const Module &M) const { int LongSize = M.getDataLayout().getPointerSizeInBits(); bool isAndroid = Triple(M.getTargetTriple()).isAndroid();