Bug 1854550 - pt 9. Move PHC interface from the bridge to PHC.h r=glandium

Building PHC in a unified build now also works.

Differential Revision: https://phabricator.services.mozilla.com/D191133
This commit is contained in:
Paul Bone 2023-10-19 06:38:42 +00:00
Родитель d2bdb850c2
Коммит d9dfdcc493
13 изменённых файлов: 173 добавлений и 238 удалений

Просмотреть файл

@ -110,7 +110,6 @@
#endif #endif
#include "mozjemalloc.h" #include "mozjemalloc.h"
#include "replace_malloc.h"
#include "mozjemalloc.h" #include "mozjemalloc.h"
#include "FdPrintf.h" #include "FdPrintf.h"
@ -1687,90 +1686,84 @@ void* MozJemallocPHC::moz_arena_memalign(arena_id_t aArenaId, size_t aAlignment,
return PageMemalign(Some(aArenaId), aAlignment, aReqSize); return PageMemalign(Some(aArenaId), aAlignment, aReqSize);
} }
class PHCBridge : public ReplaceMallocBridge { namespace mozilla::phc {
virtual bool IsPHCAllocation(const void* aPtr, phc::AddrInfo* aOut) override {
PtrKind pk = gConst->PtrKind(aPtr);
if (pk.IsNothing()) {
return false;
}
bool isGuardPage = false; bool IsPHCAllocation(const void* aPtr, AddrInfo* aOut) {
if (pk.IsGuardPage()) { PtrKind pk = gConst->PtrKind(aPtr);
if ((uintptr_t(aPtr) % kPageSize) < (kPageSize / 2)) { if (pk.IsNothing()) {
// The address is in the lower half of a guard page, so it's probably an return false;
// overflow. But first check that it is not on the very first guard }
// page, in which case it cannot be an overflow, and we ignore it.
if (gConst->IsInFirstGuardPage(aPtr)) {
return false;
}
// Get the allocation page preceding this guard page. bool isGuardPage = false;
pk = gConst->PtrKind(static_cast<const uint8_t*>(aPtr) - kPageSize); if (pk.IsGuardPage()) {
if ((uintptr_t(aPtr) % kPageSize) < (kPageSize / 2)) {
} else { // The address is in the lower half of a guard page, so it's probably an
// The address is in the upper half of a guard page, so it's probably an // overflow. But first check that it is not on the very first guard
// underflow. Get the allocation page following this guard page. // page, in which case it cannot be an overflow, and we ignore it.
pk = gConst->PtrKind(static_cast<const uint8_t*>(aPtr) + kPageSize); if (gConst->IsInFirstGuardPage(aPtr)) {
return false;
} }
// Make a note of the fact that we hit a guard page. // Get the allocation page preceding this guard page.
isGuardPage = true; pk = gConst->PtrKind(static_cast<const uint8_t*>(aPtr) - kPageSize);
}
// At this point we know we have an allocation page.
uintptr_t index = pk.AllocPageIndex();
if (aOut) {
if (GMut::sMutex.TryLock()) {
gMut->FillAddrInfo(index, aPtr, isGuardPage, *aOut);
LOG("IsPHCAllocation: %zu, %p, %zu, %zu, %zu\n", size_t(aOut->mKind),
aOut->mBaseAddr, aOut->mUsableSize,
aOut->mAllocStack.isSome() ? aOut->mAllocStack->mLength : 0,
aOut->mFreeStack.isSome() ? aOut->mFreeStack->mLength : 0);
GMut::sMutex.Unlock();
} else {
LOG("IsPHCAllocation: PHC is locked\n");
aOut->mPhcWasLocked = true;
}
}
return true;
}
virtual void DisablePHCOnCurrentThread() override {
GTls::DisableOnCurrentThread();
LOG("DisablePHCOnCurrentThread: %zu\n", 0ul);
}
virtual void ReenablePHCOnCurrentThread() override {
GTls::EnableOnCurrentThread();
LOG("ReenablePHCOnCurrentThread: %zu\n", 0ul);
}
virtual bool IsPHCEnabledOnCurrentThread() override {
bool enabled = !GTls::IsDisabledOnCurrentThread();
LOG("IsPHCEnabledOnCurrentThread: %zu\n", size_t(enabled));
return enabled;
}
virtual void PHCMemoryUsage(
mozilla::phc::MemoryUsage& aMemoryUsage) override {
aMemoryUsage.mMetadataBytes = metadata_size();
if (gMut) {
MutexAutoLock lock(GMut::sMutex);
aMemoryUsage.mFragmentationBytes = gMut->FragmentationBytes();
} else { } else {
aMemoryUsage.mFragmentationBytes = 0; // The address is in the upper half of a guard page, so it's probably an
// underflow. Get the allocation page following this guard page.
pk = gConst->PtrKind(static_cast<const uint8_t*>(aPtr) + kPageSize);
}
// Make a note of the fact that we hit a guard page.
isGuardPage = true;
}
// At this point we know we have an allocation page.
uintptr_t index = pk.AllocPageIndex();
if (aOut) {
if (GMut::sMutex.TryLock()) {
gMut->FillAddrInfo(index, aPtr, isGuardPage, *aOut);
LOG("IsPHCAllocation: %zu, %p, %zu, %zu, %zu\n", size_t(aOut->mKind),
aOut->mBaseAddr, aOut->mUsableSize,
aOut->mAllocStack.isSome() ? aOut->mAllocStack->mLength : 0,
aOut->mFreeStack.isSome() ? aOut->mFreeStack->mLength : 0);
GMut::sMutex.Unlock();
} else {
LOG("IsPHCAllocation: PHC is locked\n");
aOut->mPhcWasLocked = true;
} }
} }
return true;
// Enable or Disable PHC at runtime. If PHC is disabled it will still trap
// bad uses of previous allocations, but won't track any new allocations.
virtual void SetPHCState(mozilla::phc::PHCState aState) override {
gMut->SetState(aState);
}
};
ReplaceMallocBridge* GetPHCBridge() {
static PHCBridge bridge;
return &bridge;
} }
void DisablePHCOnCurrentThread() {
GTls::DisableOnCurrentThread();
LOG("DisablePHCOnCurrentThread: %zu\n", 0ul);
}
void ReenablePHCOnCurrentThread() {
GTls::EnableOnCurrentThread();
LOG("ReenablePHCOnCurrentThread: %zu\n", 0ul);
}
bool IsPHCEnabledOnCurrentThread() {
bool enabled = !GTls::IsDisabledOnCurrentThread();
LOG("IsPHCEnabledOnCurrentThread: %zu\n", size_t(enabled));
return enabled;
}
void PHCMemoryUsage(MemoryUsage& aMemoryUsage) {
aMemoryUsage.mMetadataBytes = metadata_size();
if (gMut) {
MutexAutoLock lock(GMut::sMutex);
aMemoryUsage.mFragmentationBytes = gMut->FragmentationBytes();
} else {
aMemoryUsage.mFragmentationBytes = 0;
}
}
// Enable or Disable PHC at runtime. If PHC is disabled it will still trap
// bad uses of previous allocations, but won't track any new allocations.
void SetPHCState(PHCState aState) { gMut->SetState(aState); }
} // namespace mozilla::phc

Просмотреть файл

@ -12,6 +12,8 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include "mozmemory_wrap.h"
namespace mozilla { namespace mozilla {
namespace phc { namespace phc {
@ -96,11 +98,50 @@ class AddrInfo {
// Global instance that is retrieved by the process generating the crash report // Global instance that is retrieved by the process generating the crash report
extern AddrInfo gAddrInfo; extern AddrInfo gAddrInfo;
// If this is a PHC-handled address, return true, and if an AddrInfo is
// provided, fill in all of its fields. Otherwise, return false and leave
// AddrInfo unchanged.
MOZ_JEMALLOC_API bool IsPHCAllocation(const void*, AddrInfo*);
// Disable PHC allocations on the current thread. Only useful for tests. Note
// that PHC deallocations will still occur as needed.
MOZ_JEMALLOC_API void DisablePHCOnCurrentThread();
// Re-enable PHC allocations on the current thread. Only useful for tests.
MOZ_JEMALLOC_API void ReenablePHCOnCurrentThread();
// Test whether PHC allocations are enabled on the current thread. Only
// useful for tests.
MOZ_JEMALLOC_API bool IsPHCEnabledOnCurrentThread();
// PHC has three different states:
// * Not compiled in
// * OnlyFree - The memory allocator is hooked but new allocations
// requests will be forwarded to mozjemalloc, free() will
// correctly free any PHC allocations and realloc() will
// "move" PHC allocations to mozjemalloc allocations.
// * Enabled - Full use.
enum PHCState {
OnlyFree,
Enabled,
};
MOZ_JEMALLOC_API void SetPHCState(PHCState aState);
struct MemoryUsage {
// The amount of memory used for PHC metadata, eg information about each
// allocation including stacks.
size_t mMetadataBytes = 0;
// The amount of memory lost due to rounding allocation sizes up to the
// nearest page. AKA internal fragmentation.
size_t mFragmentationBytes = 0;
};
MOZ_JEMALLOC_API void PHCMemoryUsage(MemoryUsage& aMemoryUsage);
} // namespace phc } // namespace phc
} // namespace mozilla } // namespace mozilla
struct ReplaceMallocBridge;
ReplaceMallocBridge* GetPHCBridge();
#endif /* PHC_h */ #endif /* PHC_h */

Просмотреть файл

@ -24,7 +24,7 @@ if CONFIG["MOZ_REPLACE_MALLOC"]:
if CONFIG["MOZ_PHC"]: if CONFIG["MOZ_PHC"]:
DEFINES["MOZ_PHC"] = True DEFINES["MOZ_PHC"] = True
SOURCES += [ UNIFIED_SOURCES += [
"FdPrintf.cpp", "FdPrintf.cpp",
"PHC.cpp", "PHC.cpp",
] ]

Просмотреть файл

@ -5182,14 +5182,6 @@ static void init() {
} }
gOriginalMallocTable = tempTable; gOriginalMallocTable = tempTable;
gMallocTablePtr = &gOriginalMallocTable; gMallocTablePtr = &gOriginalMallocTable;
# ifdef MOZ_PHC
// For now PHC still uses the bridge, so if no other allocator registered a
// bridge then register PHC's now.
if (!gReplaceMallocBridge) {
gReplaceMallocBridge = GetPHCBridge();
}
# endif
} }
// WARNING WARNING WARNING: this function should be used with extreme care. It // WARNING WARNING WARNING: this function should be used with extreme care. It

Просмотреть файл

@ -117,29 +117,8 @@ struct DMDFuncs;
namespace phc { namespace phc {
// PHC has three different states:
// * Not compiled in
// * OnlyFree - The memory allocator is hooked but new allocations
// requests will be forwarded to mozjemalloc, free() will
// correctly free any PHC allocations and realloc() will
// "move" PHC allocations to mozjemalloc allocations.
// * Enabled - Full use.
enum PHCState {
OnlyFree,
Enabled,
};
class AddrInfo; class AddrInfo;
struct MemoryUsage {
// The amount of memory used for PHC metadata, eg information about each
// allocation including stacks.
size_t mMetadataBytes = 0;
// The amount of memory lost due to rounding allocation sizes up to the
// nearest page. AKA internal fragmentation.
size_t mFragmentationBytes = 0;
};
} // namespace phc } // namespace phc
// Callbacks to register debug file handles for Poison IO interpose. // Callbacks to register debug file handles for Poison IO interpose.
@ -182,37 +161,6 @@ struct ReplaceMallocBridge {
return nullptr; return nullptr;
} }
// If this is a PHC-handled address, return true, and if an AddrInfo is
// provided, fill in all of its fields. Otherwise, return false and leave
// AddrInfo unchanged.
// This method was added in version 4 of the bridge.
virtual bool IsPHCAllocation(const void*, mozilla::phc::AddrInfo*) {
return false;
}
// Disable PHC allocations on the current thread. Only useful for tests. Note
// that PHC deallocations will still occur as needed.
// This method was added in version 4 of the bridge.
virtual void DisablePHCOnCurrentThread() {}
// Re-enable PHC allocations on the current thread. Only useful for tests.
// This method was added in version 4 of the bridge.
virtual void ReenablePHCOnCurrentThread() {}
// Test whether PHC allocations are enabled on the current thread. Only
// useful for tests.
// This method was added in version 4 of the bridge.
virtual bool IsPHCEnabledOnCurrentThread() { return false; }
// Return PHC memory usage information by filling in the supplied structure.
// This method was added in version 5 of the bridge.
virtual void PHCMemoryUsage(mozilla::phc::MemoryUsage& aMemoryUsage) {}
// Set PHC's state. See the comments above on `PHCState` for the meaning of
// each state.
// This method was added in version 6 of the bridge.
virtual void SetPHCState(mozilla::phc::PHCState aState) {}
# ifndef REPLACE_MALLOC_IMPL # ifndef REPLACE_MALLOC_IMPL
// Returns the replace-malloc bridge if its version is at least the // Returns the replace-malloc bridge if its version is at least the
// requested one. // requested one.
@ -256,44 +204,6 @@ struct ReplaceMalloc {
return singleton ? singleton->RegisterHook(aName, aTable, aHookTable) return singleton ? singleton->RegisterHook(aName, aTable, aHookTable)
: nullptr; : nullptr;
} }
static bool IsPHCAllocation(const void* aPtr, mozilla::phc::AddrInfo* aOut) {
auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 4);
return singleton ? singleton->IsPHCAllocation(aPtr, aOut) : false;
}
static void DisablePHCOnCurrentThread() {
auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 4);
if (singleton) {
singleton->DisablePHCOnCurrentThread();
}
}
static void ReenablePHCOnCurrentThread() {
auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 4);
if (singleton) {
singleton->ReenablePHCOnCurrentThread();
}
}
static bool IsPHCEnabledOnCurrentThread() {
auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 4);
return singleton ? singleton->IsPHCEnabledOnCurrentThread() : false;
}
static void PHCMemoryUsage(mozilla::phc::MemoryUsage& aMemoryUsage) {
auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 5);
if (singleton) {
singleton->PHCMemoryUsage(aMemoryUsage);
}
}
static void SetPHCState(mozilla::phc::PHCState aPHCState) {
auto singleton = ReplaceMallocBridge::Get(/* minimumVersion */ 6);
if (singleton) {
singleton->SetPHCState(aPHCState);
}
}
}; };
# endif # endif

Просмотреть файл

@ -5,10 +5,9 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "mozmemory.h" #include "mozmemory.h"
#include "replace_malloc_bridge.h"
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#include "mozilla/mozalloc.h" #include "mozilla/mozalloc.h"
#include "../../PHC.h" #include "PHC.h"
using namespace mozilla; using namespace mozilla;
@ -37,7 +36,7 @@ uint8_t* GetPHCAllocation(size_t aSize, size_t aAlignment = 1) {
for (int i = 0; i < 2000000; i++) { for (int i = 0; i < 2000000; i++) {
void* p = (aAlignment == 1) ? moz_xmalloc(aSize) void* p = (aAlignment == 1) ? moz_xmalloc(aSize)
: moz_xmemalign(aAlignment, aSize); : moz_xmemalign(aAlignment, aSize);
if (ReplaceMalloc::IsPHCAllocation(p, nullptr)) { if (mozilla::phc::IsPHCAllocation(p, nullptr)) {
return (uint8_t*)p; return (uint8_t*)p;
} }
free(p); free(p);
@ -49,7 +48,7 @@ static const size_t kPageSize = 4096;
TEST(PHC, TestPHCAllocations) TEST(PHC, TestPHCAllocations)
{ {
ReplaceMalloc::SetPHCState(phc::PHCState::Enabled); mozilla::phc::SetPHCState(phc::PHCState::Enabled);
// First, check that allocations of various sizes all get put at the end of // First, check that allocations of various sizes all get put at the end of
// their page as expected. Also, check their sizes are as expected. // their page as expected. Also, check their sizes are as expected.
@ -125,7 +124,7 @@ static void TestInUseAllocation(uint8_t* aPtr, size_t aSize) {
jemalloc_ptr_info_t jeInfo; jemalloc_ptr_info_t jeInfo;
// Test an in-use PHC allocation: first byte within it. // Test an in-use PHC allocation: first byte within it.
ASSERT_TRUE(ReplaceMalloc::IsPHCAllocation(aPtr, &phcInfo)); ASSERT_TRUE(mozilla::phc::IsPHCAllocation(aPtr, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::InUsePage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::InUsePage, aPtr, aSize,
true, false)); true, false));
ASSERT_EQ(moz_malloc_usable_size(aPtr), aSize); ASSERT_EQ(moz_malloc_usable_size(aPtr), aSize);
@ -133,7 +132,7 @@ static void TestInUseAllocation(uint8_t* aPtr, size_t aSize) {
ASSERT_TRUE(JeInfoEq(jeInfo, TagLiveAlloc, aPtr, aSize, 0)); ASSERT_TRUE(JeInfoEq(jeInfo, TagLiveAlloc, aPtr, aSize, 0));
// Test an in-use PHC allocation: last byte within it. // Test an in-use PHC allocation: last byte within it.
ASSERT_TRUE(ReplaceMalloc::IsPHCAllocation(aPtr + aSize - 1, &phcInfo)); ASSERT_TRUE(mozilla::phc::IsPHCAllocation(aPtr + aSize - 1, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::InUsePage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::InUsePage, aPtr, aSize,
true, false)); true, false));
ASSERT_EQ(moz_malloc_usable_size(aPtr + aSize - 1), aSize); ASSERT_EQ(moz_malloc_usable_size(aPtr + aSize - 1), aSize);
@ -141,7 +140,7 @@ static void TestInUseAllocation(uint8_t* aPtr, size_t aSize) {
ASSERT_TRUE(JeInfoEq(jeInfo, TagLiveAlloc, aPtr, aSize, 0)); ASSERT_TRUE(JeInfoEq(jeInfo, TagLiveAlloc, aPtr, aSize, 0));
// Test an in-use PHC allocation: last byte before it. // Test an in-use PHC allocation: last byte before it.
ASSERT_TRUE(ReplaceMalloc::IsPHCAllocation(aPtr - 1, &phcInfo)); ASSERT_TRUE(mozilla::phc::IsPHCAllocation(aPtr - 1, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::InUsePage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::InUsePage, aPtr, aSize,
true, false)); true, false));
ASSERT_EQ(moz_malloc_usable_size(aPtr - 1), 0ul); ASSERT_EQ(moz_malloc_usable_size(aPtr - 1), 0ul);
@ -150,14 +149,14 @@ static void TestInUseAllocation(uint8_t* aPtr, size_t aSize) {
// Test an in-use PHC allocation: first byte on its allocation page. // Test an in-use PHC allocation: first byte on its allocation page.
ASSERT_TRUE( ASSERT_TRUE(
ReplaceMalloc::IsPHCAllocation(aPtr + aSize - kPageSize, &phcInfo)); mozilla::phc::IsPHCAllocation(aPtr + aSize - kPageSize, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::InUsePage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::InUsePage, aPtr, aSize,
true, false)); true, false));
jemalloc_ptr_info(aPtr + aSize - kPageSize, &jeInfo); jemalloc_ptr_info(aPtr + aSize - kPageSize, &jeInfo);
ASSERT_TRUE(JeInfoEq(jeInfo, TagUnknown, nullptr, 0, 0)); ASSERT_TRUE(JeInfoEq(jeInfo, TagUnknown, nullptr, 0, 0));
// Test an in-use PHC allocation: first byte in the following guard page. // Test an in-use PHC allocation: first byte in the following guard page.
ASSERT_TRUE(ReplaceMalloc::IsPHCAllocation(aPtr + aSize, &phcInfo)); ASSERT_TRUE(mozilla::phc::IsPHCAllocation(aPtr + aSize, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize,
true, false)); true, false));
jemalloc_ptr_info(aPtr + aSize, &jeInfo); jemalloc_ptr_info(aPtr + aSize, &jeInfo);
@ -165,8 +164,8 @@ static void TestInUseAllocation(uint8_t* aPtr, size_t aSize) {
// Test an in-use PHC allocation: last byte in the lower half of the // Test an in-use PHC allocation: last byte in the lower half of the
// following guard page. // following guard page.
ASSERT_TRUE(ReplaceMalloc::IsPHCAllocation(aPtr + aSize + (kPageSize / 2 - 1), ASSERT_TRUE(mozilla::phc::IsPHCAllocation(aPtr + aSize + (kPageSize / 2 - 1),
&phcInfo)); &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize,
true, false)); true, false));
jemalloc_ptr_info(aPtr + aSize + (kPageSize / 2 - 1), &jeInfo); jemalloc_ptr_info(aPtr + aSize + (kPageSize / 2 - 1), &jeInfo);
@ -174,7 +173,7 @@ static void TestInUseAllocation(uint8_t* aPtr, size_t aSize) {
// Test an in-use PHC allocation: last byte in the preceding guard page. // Test an in-use PHC allocation: last byte in the preceding guard page.
ASSERT_TRUE( ASSERT_TRUE(
ReplaceMalloc::IsPHCAllocation(aPtr + aSize - 1 - kPageSize, &phcInfo)); mozilla::phc::IsPHCAllocation(aPtr + aSize - 1 - kPageSize, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize,
true, false)); true, false));
jemalloc_ptr_info(aPtr + aSize - 1 - kPageSize, &jeInfo); jemalloc_ptr_info(aPtr + aSize - 1 - kPageSize, &jeInfo);
@ -182,7 +181,7 @@ static void TestInUseAllocation(uint8_t* aPtr, size_t aSize) {
// Test an in-use PHC allocation: first byte in the upper half of the // Test an in-use PHC allocation: first byte in the upper half of the
// preceding guard page. // preceding guard page.
ASSERT_TRUE(ReplaceMalloc::IsPHCAllocation( ASSERT_TRUE(mozilla::phc::IsPHCAllocation(
aPtr + aSize - 1 - kPageSize - (kPageSize / 2 - 1), &phcInfo)); aPtr + aSize - 1 - kPageSize - (kPageSize / 2 - 1), &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize,
true, false)); true, false));
@ -196,21 +195,21 @@ static void TestFreedAllocation(uint8_t* aPtr, size_t aSize) {
jemalloc_ptr_info_t jeInfo; jemalloc_ptr_info_t jeInfo;
// Test a freed PHC allocation: first byte within it. // Test a freed PHC allocation: first byte within it.
ASSERT_TRUE(ReplaceMalloc::IsPHCAllocation(aPtr, &phcInfo)); ASSERT_TRUE(mozilla::phc::IsPHCAllocation(aPtr, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::FreedPage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::FreedPage, aPtr, aSize,
true, true)); true, true));
jemalloc_ptr_info(aPtr, &jeInfo); jemalloc_ptr_info(aPtr, &jeInfo);
ASSERT_TRUE(JeInfoEq(jeInfo, TagFreedAlloc, aPtr, aSize, 0)); ASSERT_TRUE(JeInfoEq(jeInfo, TagFreedAlloc, aPtr, aSize, 0));
// Test a freed PHC allocation: last byte within it. // Test a freed PHC allocation: last byte within it.
ASSERT_TRUE(ReplaceMalloc::IsPHCAllocation(aPtr + aSize - 1, &phcInfo)); ASSERT_TRUE(mozilla::phc::IsPHCAllocation(aPtr + aSize - 1, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::FreedPage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::FreedPage, aPtr, aSize,
true, true)); true, true));
jemalloc_ptr_info(aPtr + aSize - 1, &jeInfo); jemalloc_ptr_info(aPtr + aSize - 1, &jeInfo);
ASSERT_TRUE(JeInfoEq(jeInfo, TagFreedAlloc, aPtr, aSize, 0)); ASSERT_TRUE(JeInfoEq(jeInfo, TagFreedAlloc, aPtr, aSize, 0));
// Test a freed PHC allocation: last byte before it. // Test a freed PHC allocation: last byte before it.
ASSERT_TRUE(ReplaceMalloc::IsPHCAllocation(aPtr - 1, &phcInfo)); ASSERT_TRUE(mozilla::phc::IsPHCAllocation(aPtr - 1, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::FreedPage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::FreedPage, aPtr, aSize,
true, true)); true, true));
jemalloc_ptr_info(aPtr - 1, &jeInfo); jemalloc_ptr_info(aPtr - 1, &jeInfo);
@ -218,14 +217,14 @@ static void TestFreedAllocation(uint8_t* aPtr, size_t aSize) {
// Test a freed PHC allocation: first byte on its allocation page. // Test a freed PHC allocation: first byte on its allocation page.
ASSERT_TRUE( ASSERT_TRUE(
ReplaceMalloc::IsPHCAllocation(aPtr + aSize - kPageSize, &phcInfo)); mozilla::phc::IsPHCAllocation(aPtr + aSize - kPageSize, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::FreedPage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::FreedPage, aPtr, aSize,
true, true)); true, true));
jemalloc_ptr_info(aPtr + aSize - kPageSize, &jeInfo); jemalloc_ptr_info(aPtr + aSize - kPageSize, &jeInfo);
ASSERT_TRUE(JeInfoEq(jeInfo, TagUnknown, nullptr, 0, 0)); ASSERT_TRUE(JeInfoEq(jeInfo, TagUnknown, nullptr, 0, 0));
// Test a freed PHC allocation: first byte in the following guard page. // Test a freed PHC allocation: first byte in the following guard page.
ASSERT_TRUE(ReplaceMalloc::IsPHCAllocation(aPtr + aSize, &phcInfo)); ASSERT_TRUE(mozilla::phc::IsPHCAllocation(aPtr + aSize, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize,
true, true)); true, true));
jemalloc_ptr_info(aPtr + aSize, &jeInfo); jemalloc_ptr_info(aPtr + aSize, &jeInfo);
@ -233,8 +232,8 @@ static void TestFreedAllocation(uint8_t* aPtr, size_t aSize) {
// Test a freed PHC allocation: last byte in the lower half of the following // Test a freed PHC allocation: last byte in the lower half of the following
// guard page. // guard page.
ASSERT_TRUE(ReplaceMalloc::IsPHCAllocation(aPtr + aSize + (kPageSize / 2 - 1), ASSERT_TRUE(mozilla::phc::IsPHCAllocation(aPtr + aSize + (kPageSize / 2 - 1),
&phcInfo)); &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize,
true, true)); true, true));
jemalloc_ptr_info(aPtr + aSize + (kPageSize / 2 - 1), &jeInfo); jemalloc_ptr_info(aPtr + aSize + (kPageSize / 2 - 1), &jeInfo);
@ -242,7 +241,7 @@ static void TestFreedAllocation(uint8_t* aPtr, size_t aSize) {
// Test a freed PHC allocation: last byte in the preceding guard page. // Test a freed PHC allocation: last byte in the preceding guard page.
ASSERT_TRUE( ASSERT_TRUE(
ReplaceMalloc::IsPHCAllocation(aPtr + aSize - 1 - kPageSize, &phcInfo)); mozilla::phc::IsPHCAllocation(aPtr + aSize - 1 - kPageSize, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize,
true, true)); true, true));
jemalloc_ptr_info(aPtr + aSize - 1 - kPageSize, &jeInfo); jemalloc_ptr_info(aPtr + aSize - 1 - kPageSize, &jeInfo);
@ -250,7 +249,7 @@ static void TestFreedAllocation(uint8_t* aPtr, size_t aSize) {
// Test a freed PHC allocation: first byte in the upper half of the preceding // Test a freed PHC allocation: first byte in the upper half of the preceding
// guard page. // guard page.
ASSERT_TRUE(ReplaceMalloc::IsPHCAllocation( ASSERT_TRUE(mozilla::phc::IsPHCAllocation(
aPtr + aSize - 1 - kPageSize - (kPageSize / 2 - 1), &phcInfo)); aPtr + aSize - 1 - kPageSize - (kPageSize / 2 - 1), &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::GuardPage, aPtr, aSize,
true, true)); true, true));
@ -261,7 +260,7 @@ static void TestFreedAllocation(uint8_t* aPtr, size_t aSize) {
TEST(PHC, TestPHCInfo) TEST(PHC, TestPHCInfo)
{ {
ReplaceMalloc::SetPHCState(phc::PHCState::Enabled); mozilla::phc::SetPHCState(phc::PHCState::Enabled);
int stackVar; int stackVar;
phc::AddrInfo phcInfo; phc::AddrInfo phcInfo;
@ -271,10 +270,10 @@ TEST(PHC, TestPHCInfo)
false, false)); false, false));
// Test some non-PHC allocation addresses. // Test some non-PHC allocation addresses.
ASSERT_FALSE(ReplaceMalloc::IsPHCAllocation(nullptr, &phcInfo)); ASSERT_FALSE(mozilla::phc::IsPHCAllocation(nullptr, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::Unknown, nullptr, 0, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::Unknown, nullptr, 0,
false, false)); false, false));
ASSERT_FALSE(ReplaceMalloc::IsPHCAllocation(&stackVar, &phcInfo)); ASSERT_FALSE(mozilla::phc::IsPHCAllocation(&stackVar, &phcInfo));
ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::Unknown, nullptr, 0, ASSERT_TRUE(PHCInfoEq(phcInfo, phc::AddrInfo::Kind::Unknown, nullptr, 0,
false, false)); false, false));
@ -295,7 +294,7 @@ TEST(PHC, TestPHCInfo)
TEST(PHC, TestPHCDisablingThread) TEST(PHC, TestPHCDisablingThread)
{ {
ReplaceMalloc::SetPHCState(phc::PHCState::Enabled); mozilla::phc::SetPHCState(phc::PHCState::Enabled);
uint8_t* p = GetPHCAllocation(32); uint8_t* p = GetPHCAllocation(32);
uint8_t* q = GetPHCAllocation(32); uint8_t* q = GetPHCAllocation(32);
@ -303,19 +302,19 @@ TEST(PHC, TestPHCDisablingThread)
MOZ_CRASH("failed to get a PHC allocation"); MOZ_CRASH("failed to get a PHC allocation");
} }
ASSERT_TRUE(ReplaceMalloc::IsPHCEnabledOnCurrentThread()); ASSERT_TRUE(mozilla::phc::IsPHCEnabledOnCurrentThread());
ReplaceMalloc::DisablePHCOnCurrentThread(); mozilla::phc::DisablePHCOnCurrentThread();
ASSERT_FALSE(ReplaceMalloc::IsPHCEnabledOnCurrentThread()); ASSERT_FALSE(mozilla::phc::IsPHCEnabledOnCurrentThread());
// Test realloc() on a PHC allocation while PHC is disabled on the thread. // Test realloc() on a PHC allocation while PHC is disabled on the thread.
uint8_t* p2 = (uint8_t*)realloc(p, 128); uint8_t* p2 = (uint8_t*)realloc(p, 128);
// The small realloc is fulfilled within the same page, but it does move. // The small realloc is fulfilled within the same page, but it does move.
ASSERT_TRUE(p2 == p - 96); ASSERT_TRUE(p2 == p - 96);
ASSERT_TRUE(ReplaceMalloc::IsPHCAllocation(p2, nullptr)); ASSERT_TRUE(mozilla::phc::IsPHCAllocation(p2, nullptr));
uint8_t* p3 = (uint8_t*)realloc(p2, 8192); uint8_t* p3 = (uint8_t*)realloc(p2, 8192);
// The big realloc is not in-place, and the result is not a PHC allocation. // The big realloc is not in-place, and the result is not a PHC allocation.
ASSERT_TRUE(p3 != p2); ASSERT_TRUE(p3 != p2);
ASSERT_FALSE(ReplaceMalloc::IsPHCAllocation(p3, nullptr)); ASSERT_FALSE(mozilla::phc::IsPHCAllocation(p3, nullptr));
free(p3); free(p3);
// Test free() on a PHC allocation while PHC is disabled on the thread. // Test free() on a PHC allocation while PHC is disabled on the thread.
@ -325,8 +324,8 @@ TEST(PHC, TestPHCDisablingThread)
uint8_t* r = GetPHCAllocation(32); // This will fail. uint8_t* r = GetPHCAllocation(32); // This will fail.
ASSERT_FALSE(!!r); ASSERT_FALSE(!!r);
ReplaceMalloc::ReenablePHCOnCurrentThread(); mozilla::phc::ReenablePHCOnCurrentThread();
ASSERT_TRUE(ReplaceMalloc::IsPHCEnabledOnCurrentThread()); ASSERT_TRUE(mozilla::phc::IsPHCEnabledOnCurrentThread());
// If it really was reenabled we should be able to get PHC allocations // If it really was reenabled we should be able to get PHC allocations
// again. // again.
@ -337,7 +336,7 @@ TEST(PHC, TestPHCDisablingThread)
TEST(PHC, TestPHCDisablingGlobal) TEST(PHC, TestPHCDisablingGlobal)
{ {
ReplaceMalloc::SetPHCState(phc::PHCState::Enabled); mozilla::phc::SetPHCState(phc::PHCState::Enabled);
uint8_t* p1 = GetPHCAllocation(32); uint8_t* p1 = GetPHCAllocation(32);
uint8_t* p2 = GetPHCAllocation(32); uint8_t* p2 = GetPHCAllocation(32);
@ -346,20 +345,20 @@ TEST(PHC, TestPHCDisablingGlobal)
MOZ_CRASH("failed to get a PHC allocation"); MOZ_CRASH("failed to get a PHC allocation");
} }
ReplaceMalloc::SetPHCState(phc::PHCState::OnlyFree); mozilla::phc::SetPHCState(phc::PHCState::OnlyFree);
// Test realloc() on a PHC allocation while PHC is disabled on the thread. // Test realloc() on a PHC allocation while PHC is disabled on the thread.
uint8_t* p3 = (uint8_t*)realloc(p1, 128); uint8_t* p3 = (uint8_t*)realloc(p1, 128);
// The small realloc is evicted from PHC because in "OnlyFree" state PHC // The small realloc is evicted from PHC because in "OnlyFree" state PHC
// tries to reduce its memory impact. // tries to reduce its memory impact.
ASSERT_TRUE(p3 != p1); ASSERT_TRUE(p3 != p1);
ASSERT_FALSE(ReplaceMalloc::IsPHCAllocation(p3, nullptr)); ASSERT_FALSE(mozilla::phc::IsPHCAllocation(p3, nullptr));
free(p3); free(p3);
uint8_t* p4 = (uint8_t*)realloc(p2, 8192); uint8_t* p4 = (uint8_t*)realloc(p2, 8192);
// The big realloc is not in-place, and the result is not a PHC // The big realloc is not in-place, and the result is not a PHC
// allocation, regardless of PHC's state. // allocation, regardless of PHC's state.
ASSERT_TRUE(p4 != p2); ASSERT_TRUE(p4 != p2);
ASSERT_FALSE(ReplaceMalloc::IsPHCAllocation(p4, nullptr)); ASSERT_FALSE(mozilla::phc::IsPHCAllocation(p4, nullptr));
free(p4); free(p4);
// Test free() on a PHC allocation while PHC is disabled on the thread. // Test free() on a PHC allocation while PHC is disabled on the thread.
@ -369,7 +368,7 @@ TEST(PHC, TestPHCDisablingGlobal)
uint8_t* r = GetPHCAllocation(32); // This will fail. uint8_t* r = GetPHCAllocation(32); // This will fail.
ASSERT_FALSE(!!r); ASSERT_FALSE(!!r);
ReplaceMalloc::SetPHCState(phc::PHCState::Enabled); mozilla::phc::SetPHCState(phc::PHCState::Enabled);
// If it really was reenabled we should be able to get PHC allocations // If it really was reenabled we should be able to get PHC allocations
// again. // again.

Просмотреть файл

@ -16,7 +16,7 @@
#include "gtest/gtest.h" #include "gtest/gtest.h"
#ifdef MOZ_PHC #ifdef MOZ_PHC
# include "replace_malloc_bridge.h" # include "PHC.h"
#endif #endif
using namespace mozilla; using namespace mozilla;
@ -25,13 +25,13 @@ class AutoDisablePHCOnCurrentThread {
public: public:
AutoDisablePHCOnCurrentThread() { AutoDisablePHCOnCurrentThread() {
#ifdef MOZ_PHC #ifdef MOZ_PHC
ReplaceMalloc::DisablePHCOnCurrentThread(); mozilla::phc::DisablePHCOnCurrentThread();
#endif #endif
} }
~AutoDisablePHCOnCurrentThread() { ~AutoDisablePHCOnCurrentThread() {
#ifdef MOZ_PHC #ifdef MOZ_PHC
ReplaceMalloc::ReenablePHCOnCurrentThread(); mozilla::phc::ReenablePHCOnCurrentThread();
#endif #endif
} }
}; };
@ -364,7 +364,7 @@ static bool CanReallocInPlace(size_t aFromSize, size_t aToSize,
// PHC allocations must be disabled because PHC reallocs differently to // PHC allocations must be disabled because PHC reallocs differently to
// mozjemalloc. // mozjemalloc.
#ifdef MOZ_PHC #ifdef MOZ_PHC
MOZ_RELEASE_ASSERT(!ReplaceMalloc::IsPHCEnabledOnCurrentThread()); MOZ_RELEASE_ASSERT(!mozilla::phc::IsPHCEnabledOnCurrentThread());
#endif #endif
if (aFromSize == malloc_good_size(aToSize)) { if (aFromSize == malloc_good_size(aToSize)) {

Просмотреть файл

@ -102,7 +102,7 @@
#endif #endif
#ifdef MOZ_PHC #ifdef MOZ_PHC
#include "replace_malloc_bridge.h" #include "PHC.h"
#endif #endif
#if defined(__ANDROID__) #if defined(__ANDROID__)
@ -458,7 +458,7 @@ static void GetPHCAddrInfo(siginfo_t* siginfo,
mozilla::phc::AddrInfo* addr_info) { mozilla::phc::AddrInfo* addr_info) {
// Is this a crash involving a PHC allocation? // Is this a crash involving a PHC allocation?
if (siginfo->si_signo == SIGSEGV || siginfo->si_signo == SIGBUS) { if (siginfo->si_signo == SIGSEGV || siginfo->si_signo == SIGBUS) {
ReplaceMalloc::IsPHCAllocation(siginfo->si_addr, addr_info); mozilla::phc::IsPHCAllocation(siginfo->si_addr, addr_info);
} }
} }
#endif #endif

Просмотреть файл

@ -43,7 +43,7 @@
#include "mozilla/Assertions.h" #include "mozilla/Assertions.h"
#ifdef MOZ_PHC #ifdef MOZ_PHC
#include "replace_malloc_bridge.h" #include "PHC.h"
#endif #endif
#ifndef __EXCEPTIONS #ifndef __EXCEPTIONS
@ -421,7 +421,7 @@ static void GetPHCAddrInfo(int exception_type, int64_t exception_subcode,
// `exception_subcode` is only non-zero when it's a bad access, in which // `exception_subcode` is only non-zero when it's a bad access, in which
// case it holds the address of the bad access. // case it holds the address of the bad access.
char* addr = reinterpret_cast<char*>(exception_subcode); char* addr = reinterpret_cast<char*>(exception_subcode);
ReplaceMalloc::IsPHCAllocation(addr, addr_info); mozilla::phc::IsPHCAllocation(addr, addr_info);
} }
} }
#endif #endif

Просмотреть файл

@ -40,7 +40,7 @@
#include "common/windows/guid_string.h" #include "common/windows/guid_string.h"
#ifdef MOZ_PHC #ifdef MOZ_PHC
#include "replace_malloc_bridge.h" #include "PHC.h"
#endif #endif
namespace google_breakpad { namespace google_breakpad {
@ -903,7 +903,7 @@ static void GetPHCAddrInfo(EXCEPTION_POINTERS* exinfo,
// operation it what, and rec->ExceptionInformation[1] contains the // operation it what, and rec->ExceptionInformation[1] contains the
// virtual address of the inaccessible data. // virtual address of the inaccessible data.
char* crashAddr = reinterpret_cast<char*>(rec->ExceptionInformation[1]); char* crashAddr = reinterpret_cast<char*>(rec->ExceptionInformation[1]);
ReplaceMalloc::IsPHCAllocation(crashAddr, addr_info); mozilla::phc::IsPHCAllocation(crashAddr, addr_info);
} }
} }
#endif #endif

Просмотреть файл

@ -31,7 +31,7 @@ typedef int (*guarded_open_np_t)(const char*, const guardid_t*, u_int, int,
#endif #endif
#ifdef MOZ_PHC #ifdef MOZ_PHC
# include "replace_malloc_bridge.h" # include "PHC.h"
#endif #endif
/* /*
@ -159,7 +159,7 @@ uint8_t* GetPHCAllocation(size_t aSize) {
// A crude but effective way to get a PHC allocation. // A crude but effective way to get a PHC allocation.
for (int i = 0; i < 2000000; i++) { for (int i = 0; i < 2000000; i++) {
uint8_t* p = (uint8_t*)malloc(aSize); uint8_t* p = (uint8_t*)malloc(aSize);
if (ReplaceMalloc::IsPHCAllocation(p, nullptr)) { if (mozilla::phc::IsPHCAllocation(p, nullptr)) {
return p; return p;
} }
free(p); free(p);
@ -325,7 +325,7 @@ extern "C" NS_EXPORT void Crash(int16_t how) {
extern "C" NS_EXPORT void EnablePHC() { extern "C" NS_EXPORT void EnablePHC() {
#ifdef MOZ_PHC #ifdef MOZ_PHC
ReplaceMalloc::SetPHCState(mozilla::phc::PHCState::Enabled); mozilla::phc::SetPHCState(mozilla::phc::PHCState::Enabled);
#endif #endif
}; };

Просмотреть файл

@ -6,7 +6,7 @@
#include "PHCManager.h" #include "PHCManager.h"
#include "replace_malloc_bridge.h" #include "PHC.h"
#include "mozilla/Preferences.h" #include "mozilla/Preferences.h"
#include "mozilla/StaticPrefs_memory.h" #include "mozilla/StaticPrefs_memory.h"
@ -23,11 +23,11 @@ static PHCState GetPHCStateFromPref() {
static void PrefChangeCallback(const char* aPrefName, void* aNull) { static void PrefChangeCallback(const char* aPrefName, void* aNull) {
MOZ_ASSERT(0 == strcmp(aPrefName, kPHCPref)); MOZ_ASSERT(0 == strcmp(aPrefName, kPHCPref));
ReplaceMalloc::SetPHCState(GetPHCStateFromPref()); SetPHCState(GetPHCStateFromPref());
} }
void InitPHCState() { void InitPHCState() {
ReplaceMalloc::SetPHCState(GetPHCStateFromPref()); SetPHCState(GetPHCStateFromPref());
Preferences::RegisterCallback(PrefChangeCallback, kPHCPref); Preferences::RegisterCallback(PrefChangeCallback, kPHCPref);
} }

Просмотреть файл

@ -44,7 +44,7 @@
#include "mozilla/ipc/UtilityProcessManager.h" #include "mozilla/ipc/UtilityProcessManager.h"
#include "mozilla/ipc/FileDescriptorUtils.h" #include "mozilla/ipc/FileDescriptorUtils.h"
#ifdef MOZ_PHC #ifdef MOZ_PHC
# include "replace_malloc_bridge.h" # include "PHC.h"
#endif #endif
#ifdef MOZ_WIDGET_ANDROID #ifdef MOZ_WIDGET_ANDROID
@ -1340,7 +1340,7 @@ class JemallocHeapReporter final : public nsIMemoryReporter {
#ifdef MOZ_PHC #ifdef MOZ_PHC
mozilla::phc::MemoryUsage usage; mozilla::phc::MemoryUsage usage;
ReplaceMalloc::PHCMemoryUsage(usage); mozilla::phc::PHCMemoryUsage(usage);
MOZ_COLLECT_REPORT( MOZ_COLLECT_REPORT(
"explicit/heap-overhead/phc/metadata", KIND_NONHEAP, UNITS_BYTES, "explicit/heap-overhead/phc/metadata", KIND_NONHEAP, UNITS_BYTES,