static bool verifyShadowScheme() { // Sanity checks for our shadow mapping scheme. uptr AppStart, AppEnd; if (Verbosity() >= 3) { for (int i = 0; getAppRegion(i, &AppStart, &AppEnd); ++i) { VPrintf(3, "App #%d: [%zx-%zx) (%zuGB)\n", i, AppStart, AppEnd, (AppEnd - AppStart) >> 30); } } for (int Scale = 0; Scale < 8; ++Scale) { Mapping.initialize(Scale); if (Verbosity() >= 3) { VPrintf(3, "\nChecking scale %d\n", Scale); uptr ShadowStart, ShadowEnd; for (int i = 0; getShadowRegion(i, &ShadowStart, &ShadowEnd); ++i) { VPrintf(3, "Shadow #%d: [%zx-%zx) (%zuGB)\n", i, ShadowStart, ShadowEnd, (ShadowEnd - ShadowStart) >> 30); } for (int i = 0; getShadowRegion(i, &ShadowStart, &ShadowEnd); ++i) { VPrintf(3, "Shadow(Shadow) #%d: [%zx-%zx)\n", i, appToShadow(ShadowStart), appToShadow(ShadowEnd - 1)+1); } } for (int i = 0; getAppRegion(i, &AppStart, &AppEnd); ++i) { DCHECK(isAppMem(AppStart)); DCHECK(!isAppMem(AppStart - 1)); DCHECK(isAppMem(AppEnd - 1)); DCHECK(!isAppMem(AppEnd)); DCHECK(!isShadowMem(AppStart)); DCHECK(!isShadowMem(AppEnd - 1)); DCHECK(isShadowMem(appToShadow(AppStart))); DCHECK(isShadowMem(appToShadow(AppEnd - 1))); // Double-shadow checks. DCHECK(!isShadowMem(appToShadow(appToShadow(AppStart)))); DCHECK(!isShadowMem(appToShadow(appToShadow(AppEnd - 1)))); } // Ensure no shadow regions overlap each other. uptr ShadowAStart, ShadowBStart, ShadowAEnd, ShadowBEnd; for (int i = 0; getShadowRegion(i, &ShadowAStart, &ShadowAEnd); ++i) { for (int j = 0; getShadowRegion(j, &ShadowBStart, &ShadowBEnd); ++j) { DCHECK(i == j || ShadowAStart >= ShadowBEnd || ShadowAEnd <= ShadowBStart); } } }
void processRangeAccessWorkingSet(uptr PC, uptr Addr, SIZE_T Size, bool IsWrite) { if (Size == 0) return; SIZE_T I = 0; uptr LineSize = getFlags()->cache_line_size; // As Addr+Size could overflow at the top of a 32-bit address space, // we avoid the simpler formula that rounds the start and end. SIZE_T NumLines = Size / LineSize + // Add any extra at the start or end adding on an extra line: (LineSize - 1 + Addr % LineSize + Size % LineSize) / LineSize; byte *Shadow = (byte *)appToShadow(Addr); // Write shadow bytes until we're word-aligned. while (I < NumLines && (uptr)Shadow % 4 != 0) { if ((*Shadow & ShadowAccessedVal) != ShadowAccessedVal) *Shadow |= ShadowAccessedVal; ++Shadow; ++I; } // Write whole shadow words at a time. // Using a word-stride loop improves the runtime of a microbenchmark of // memset calls by 10%. u32 WordValue = ShadowAccessedVal | ShadowAccessedVal << 8 | ShadowAccessedVal << 16 | ShadowAccessedVal << 24; while (I + 4 <= NumLines) { if ((*(u32*)Shadow & WordValue) != WordValue) *(u32*)Shadow |= WordValue; Shadow += 4; I += 4; } // Write any trailing shadow bytes. while (I < NumLines) { if ((*Shadow & ShadowAccessedVal) != ShadowAccessedVal) *Shadow |= ShadowAccessedVal; ++Shadow; ++I; } }