Changeset View
Changeset View
Standalone View
Standalone View
lib/scudo/scudo_allocator.cpp
Show All 31 Lines | |||||
// Global static cookie, initialized at start-up. | // Global static cookie, initialized at start-up. | ||||
static u32 Cookie; | static u32 Cookie; | ||||
// We default to software CRC32 if the alternatives are not supported, either | // We default to software CRC32 if the alternatives are not supported, either | ||||
// at compilation or at runtime. | // at compilation or at runtime. | ||||
static atomic_uint8_t HashAlgorithm = { CRC32Software }; | static atomic_uint8_t HashAlgorithm = { CRC32Software }; | ||||
#if !SANITIZER_SUPPORTS_WEAK_HOOKS | |||||
SANITIZER_WEAK_ATTRIBUTE u32 computeHardwareCRC32(u32 Crc, uptr Data) { | |||||
return computeSoftwareCRC32(Crc, Data); | |||||
} | |||||
#endif | |||||
INLINE u32 computeCRC32(u32 Crc, uptr Value, uptr *Array, uptr ArraySize) { | INLINE u32 computeCRC32(u32 Crc, uptr Value, uptr *Array, uptr ArraySize) { | ||||
// If the hardware CRC32 feature is defined here, it was enabled everywhere, | // If the hardware CRC32 feature is defined here, it was enabled everywhere, | ||||
// as opposed to only for scudo_crc32.cpp. This means that other hardware | // as opposed to only for scudo_crc32.cpp. This means that other hardware | ||||
// specific instructions were likely emitted at other places, and as a | // specific instructions were likely emitted at other places, and as a | ||||
// result there is no reason to not use it here. | // result there is no reason to not use it here. | ||||
#if defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) | #if defined(__SSE4_2__) || defined(__ARM_FEATURE_CRC32) | ||||
Crc = CRC32_INTRINSIC(Crc, Value); | Crc = CRC32_INTRINSIC(Crc, Value); | ||||
for (uptr i = 0; i < ArraySize; i++) | for (uptr i = 0; i < ArraySize; i++) | ||||
▲ Show 20 Lines • Show All 194 Lines • ▼ Show 20 Lines | void performSanityChecks() { | ||||
// offset will always be 0. In the case of the Primary, the worst case | // offset will always be 0. In the case of the Primary, the worst case | ||||
// scenario happens in the last size class, when the backend allocation | // scenario happens in the last size class, when the backend allocation | ||||
// would already be aligned on the requested alignment, which would happen | // would already be aligned on the requested alignment, which would happen | ||||
// to be the maximum alignment that would fit in that size class. As a | // to be the maximum alignment that would fit in that size class. As a | ||||
// result, the maximum offset will be at most the maximum alignment for the | // result, the maximum offset will be at most the maximum alignment for the | ||||
// last size class minus the header size, in multiples of MinAlignment. | // last size class minus the header size, in multiples of MinAlignment. | ||||
UnpackedHeader Header = {}; | UnpackedHeader Header = {}; | ||||
const uptr MaxPrimaryAlignment = | const uptr MaxPrimaryAlignment = | ||||
1 << MostSignificantSetBitIndex(SizeClassMap::kMaxSize - MinAlignment); | 1U << MostSignificantSetBitIndex(SizeClassMap::kMaxSize - MinAlignment); | ||||
const uptr MaxOffset = | const uptr MaxOffset = | ||||
(MaxPrimaryAlignment - Chunk::getHeaderSize()) >> MinAlignmentLog; | (MaxPrimaryAlignment - Chunk::getHeaderSize()) >> MinAlignmentLog; | ||||
Header.Offset = MaxOffset; | Header.Offset = MaxOffset; | ||||
if (Header.Offset != MaxOffset) { | if (Header.Offset != MaxOffset) { | ||||
dieWithMessage("ERROR: the maximum possible offset doesn't fit in the " | dieWithMessage("ERROR: the maximum possible offset doesn't fit in the " | ||||
"header\n"); | "header\n"); | ||||
} | } | ||||
// Verify that we can fit the maximum size or amount of unused bytes in the | // Verify that we can fit the maximum size or amount of unused bytes in the | ||||
▲ Show 20 Lines • Show All 68 Lines • ▼ Show 20 Lines | if (LIKELY(CurrentCheck < LastCheck + (100ULL * 1000000ULL))) | ||||
return atomic_load_relaxed(&RssLimitExceeded); | return atomic_load_relaxed(&RssLimitExceeded); | ||||
if (!atomic_compare_exchange_weak(&RssLastCheckedAtNS, &LastCheck, | if (!atomic_compare_exchange_weak(&RssLastCheckedAtNS, &LastCheck, | ||||
CurrentCheck, memory_order_relaxed)) | CurrentCheck, memory_order_relaxed)) | ||||
return atomic_load_relaxed(&RssLimitExceeded); | return atomic_load_relaxed(&RssLimitExceeded); | ||||
// TODO(kostyak): We currently use sanitizer_common's GetRSS which reads the | // TODO(kostyak): We currently use sanitizer_common's GetRSS which reads the | ||||
// RSS from /proc/self/statm by default. We might want to | // RSS from /proc/self/statm by default. We might want to | ||||
// call getrusage directly, even if it's less accurate. | // call getrusage directly, even if it's less accurate. | ||||
const uptr CurrentRssMb = GetRSS() >> 20; | const uptr CurrentRssMb = GetRSS() >> 20; | ||||
Printf("CurrentRssMb = %d\n", CurrentRssMb); | |||||
if (HardRssLimitMb && HardRssLimitMb < CurrentRssMb) { | if (HardRssLimitMb && HardRssLimitMb < CurrentRssMb) { | ||||
Report("%s: hard RSS limit exhausted (%zdMb vs %zdMb)\n", | Report("%s: hard RSS limit exhausted (%zdMb vs %zdMb)\n", | ||||
SanitizerToolName, HardRssLimitMb, CurrentRssMb); | SanitizerToolName, HardRssLimitMb, CurrentRssMb); | ||||
DumpProcessMap(); | DumpProcessMap(); | ||||
Die(); | Die(); | ||||
} | } | ||||
if (SoftRssLimitMb) { | if (SoftRssLimitMb) { | ||||
if (atomic_load_relaxed(&RssLimitExceeded)) { | if (atomic_load_relaxed(&RssLimitExceeded)) { | ||||
▲ Show 20 Lines • Show All 414 Lines • Show Last 20 Lines |