Bug 827150 - Notify ASan/Valgrind when moving entries in and out of a PresArena free list. r=roc,choller

This commit is contained in:
Mats Palmgren 2013-02-03 02:04:29 +01:00
parent 674e9f8aa3
commit 3d35f89082

View File

@ -25,6 +25,23 @@
#include "mozilla/StandardInteger.h"
#if defined(MOZ_ASAN)
// XXX These come from sanitizer/asan_interface.h but that header doesn't seem
// to be installed by default?
extern "C" {
void __asan_poison_memory_region(void const volatile *addr, size_t size)
__attribute__((visibility("default")));
void __asan_unpoison_memory_region(void const volatile *addr, size_t size)
__attribute__((visibility("default")));
#define ASAN_POISON_MEMORY_REGION(addr, size) \
__asan_poison_memory_region((addr), (size))
#define ASAN_UNPOISON_MEMORY_REGION(addr, size) \
__asan_unpoison_memory_region((addr), (size))
}
#elif defined(MOZ_VALGRIND)
#include "valgrind/memcheck.h"
#endif
// Even on 32-bit systems, we allocate objects from the frame arena
// that require 8-byte alignment. The cast to uintptr_t is needed
// because plarena isn't as careful about mask construction as it
@ -285,8 +302,28 @@ struct nsPresArena::State {
PR_CallOnce(&ARENA_POISON_guard, ARENA_POISON_init);
}
#if defined(MOZ_ASAN) || defined(MOZ_VALGRIND)
static PLDHashOperator UnpoisonFreeList(FreeList* aEntry, void*)
{
nsTArray<void*>::index_type len;
while ((len = aEntry->mEntries.Length())) {
void* result = aEntry->mEntries.ElementAt(len - 1);
aEntry->mEntries.RemoveElementAt(len - 1);
#if defined(MOZ_ASAN)
ASAN_UNPOISON_MEMORY_REGION(result, aEntry->mEntrySize);
#elif defined(MOZ_VALGRIND)
VALGRIND_MAKE_MEM_UNDEFINED(result, aEntry->mEntrySize);
#endif
}
return PL_DHASH_NEXT;
}
#endif
~State()
{
#if defined(MOZ_ASAN) || defined(MOZ_VALGRIND)
mFreeLists.EnumerateEntries(UnpoisonFreeList, nullptr);
#endif
PL_FinishArenaPool(&mPool);
}
@ -315,7 +352,11 @@ struct nsPresArena::State {
// LIFO behavior for best cache utilization
result = list->mEntries.ElementAt(len - 1);
list->mEntries.RemoveElementAt(len - 1);
#ifdef DEBUG
#if defined(MOZ_ASAN)
ASAN_UNPOISON_MEMORY_REGION(result, list->mEntrySize);
#elif defined(MOZ_VALGRIND)
VALGRIND_MAKE_MEM_UNDEFINED(result, list->mEntrySize);
#elif defined(DEBUG)
{
char* p = reinterpret_cast<char*>(result);
char* limit = p + list->mEntrySize;
@ -358,6 +399,11 @@ struct nsPresArena::State {
*reinterpret_cast<uintptr_t*>(p) = ARENA_POISON;
}
#if defined(MOZ_ASAN)
ASAN_POISON_MEMORY_REGION(aPtr, list->mEntrySize);
#elif defined(MOZ_VALGRIND)
VALGRIND_MAKE_MEM_NOACCESS(aPtr, list->mEntrySize);
#endif
list->mEntries.AppendElement(aPtr);
}