diff --git a/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp b/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp --- a/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp +++ b/compiler-rt/lib/scudo/standalone/tests/wrappers_c_test.cpp @@ -16,6 +16,10 @@ #include #include +#ifndef __GLIBC_PREREQ +#define __GLIBC_PREREQ(x, y) 0 +#endif + extern "C" { void malloc_enable(void); void malloc_disable(void); @@ -258,8 +262,10 @@ #if !SCUDO_FUCHSIA TEST(ScudoWrappersCTest, MallInfo) { + // mallinfo is deprecated. +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" const size_t BypassQuarantineSize = 1024U; - struct mallinfo MI = mallinfo(); size_t Allocated = MI.uordblks; void *P = malloc(BypassQuarantineSize); @@ -271,6 +277,24 @@ free(P); MI = mallinfo(); EXPECT_GE(static_cast(MI.fordblks), Free + BypassQuarantineSize); +#pragma clang diagnostic pop +} +#endif + +#if __GLIBC_PREREQ(2, 33) +TEST(ScudoWrappersCTest, MallInfo2) { + const size_t BypassQuarantineSize = 1024U; + struct mallinfo2 MI = mallinfo2(); + size_t Allocated = MI.uordblks; + void *P = malloc(BypassQuarantineSize); + EXPECT_NE(P, nullptr); + MI = mallinfo2(); + EXPECT_GE(MI.uordblks, Allocated + BypassQuarantineSize); + EXPECT_GT(MI.hblkhd, 0U); + size_t Free = MI.fordblks; + free(P); + MI = mallinfo2(); + EXPECT_GE(MI.fordblks, Free + BypassQuarantineSize); } #endif diff --git a/compiler-rt/lib/scudo/standalone/wrappers_c.h b/compiler-rt/lib/scudo/standalone/wrappers_c.h --- a/compiler-rt/lib/scudo/standalone/wrappers_c.h +++ b/compiler-rt/lib/scudo/standalone/wrappers_c.h @@ -32,6 +32,19 @@ __scudo_mallinfo_data_t keepcost; }; +struct __scudo_mallinfo2 { + size_t arena; + size_t ordblks; + size_t smblks; + size_t hblks; + size_t hblkhd; + size_t usmblks; + size_t fsmblks; + size_t uordblks; + size_t fordblks; + size_t keepcost; +}; + // Android sometimes includes malloc.h no matter what, which yields to // conflicting return types for mallinfo() if we use our own structure. So if // struct mallinfo is declared (#define courtesy of malloc.h), use it directly. diff --git a/compiler-rt/lib/scudo/standalone/wrappers_c.inc b/compiler-rt/lib/scudo/standalone/wrappers_c.inc --- a/compiler-rt/lib/scudo/standalone/wrappers_c.inc +++ b/compiler-rt/lib/scudo/standalone/wrappers_c.inc @@ -17,6 +17,10 @@ #define SCUDO_MALLOC_ALIGNMENT FIRST_32_SECOND_64(8U, 16U) #endif +#ifndef __GLIBC_PREREQ +#define __GLIBC_PREREQ(x, y) 0 +#endif + extern "C" { INTERFACE WEAK void *SCUDO_PREFIX(calloc)(size_t nmemb, size_t size) { @@ -54,6 +58,25 @@ return Info; } +#if __GLIBC_PREREQ(2, 33) +INTERFACE WEAK struct __scudo_mallinfo2 SCUDO_PREFIX(mallinfo2)(void) { + struct __scudo_mallinfo2 Info = {}; + scudo::StatCounters Stats; + SCUDO_ALLOCATOR.getStats(Stats); + // Space allocated in mmapped regions (bytes) + Info.hblkhd = Stats[scudo::StatMapped]; + // Maximum total allocated space (bytes) + Info.usmblks = Info.hblkhd; + // Space in freed fastbin blocks (bytes) + Info.fsmblks = Stats[scudo::StatFree]; + // Total allocated space (bytes) + Info.uordblks = Stats[scudo::StatAllocated]; + // Total free space (bytes) + Info.fordblks = Info.fsmblks; + return Info; +} +#endif + INTERFACE WEAK void *SCUDO_PREFIX(malloc)(size_t size) { return scudo::setErrnoOnNull(SCUDO_ALLOCATOR.allocate( size, scudo::Chunk::Origin::Malloc, SCUDO_MALLOC_ALIGNMENT));