diff options
Diffstat (limited to 'common/dlmalloc.c')
-rw-r--r-- | common/dlmalloc.c | 154 |
1 files changed, 129 insertions, 25 deletions
diff --git a/common/dlmalloc.c b/common/dlmalloc.c index de3f04225f4..a0616217d49 100644 --- a/common/dlmalloc.c +++ b/common/dlmalloc.c @@ -32,6 +32,21 @@ void malloc_stats(); DECLARE_GLOBAL_DATA_PTR; +#ifdef MCHECK_HEAP_PROTECTION + #define STATIC_IF_MCHECK static + #undef MALLOC_COPY + #undef MALLOC_ZERO +static inline void MALLOC_ZERO(void *p, size_t sz) { memset(p, 0, sz); } +static inline void MALLOC_COPY(void *dest, const void *src, size_t sz) { memcpy(dest, src, sz); } +#else + #define STATIC_IF_MCHECK + #define mALLOc_impl mALLOc + #define fREe_impl fREe + #define rEALLOc_impl rEALLOc + #define mEMALIGn_impl mEMALIGn + #define cALLOc_impl cALLOc +#endif + /* Emulation of sbrk for WIN32 All code within the ifdef WIN32 is untested by me. @@ -1270,10 +1285,11 @@ static void malloc_extend_top(nb) INTERNAL_SIZE_T nb; */ +STATIC_IF_MCHECK #if __STD_C -Void_t* mALLOc(size_t bytes) +Void_t* mALLOc_impl(size_t bytes) #else -Void_t* mALLOc(bytes) size_t bytes; +Void_t* mALLOc_impl(bytes) size_t bytes; #endif { mchunkptr victim; /* inspected/selected chunk */ @@ -1555,10 +1571,11 @@ Void_t* mALLOc(bytes) size_t bytes; */ +STATIC_IF_MCHECK #if __STD_C -void fREe(Void_t* mem) +void fREe_impl(Void_t* mem) #else -void fREe(mem) Void_t* mem; +void fREe_impl(mem) Void_t* mem; #endif { mchunkptr p; /* chunk corresponding to mem */ @@ -1696,10 +1713,11 @@ void fREe(mem) Void_t* mem; */ +STATIC_IF_MCHECK #if __STD_C -Void_t* rEALLOc(Void_t* oldmem, size_t bytes) +Void_t* rEALLOc_impl(Void_t* oldmem, size_t bytes) #else -Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; +Void_t* rEALLOc_impl(oldmem, bytes) Void_t* oldmem; size_t bytes; #endif { INTERNAL_SIZE_T nb; /* padded request size */ @@ -1725,7 +1743,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; #ifdef REALLOC_ZERO_BYTES_FREES if (!bytes) { - fREe(oldmem); + fREe_impl(oldmem); return NULL; } #endif @@ -1733,7 +1751,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; if ((long)bytes < 0) return NULL; /* realloc of null is supposed to be same as malloc */ - if (oldmem == NULL) return mALLOc(bytes); + if (oldmem == NULL) return mALLOc_impl(bytes); #if CONFIG_IS_ENABLED(SYS_MALLOC_F) if (!(gd->flags & GD_FLG_FULL_MALLOC_INIT)) { @@ -1758,7 +1776,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; /* Note the extra SIZE_SZ overhead. */ if(oldsize - SIZE_SZ >= nb) return oldmem; /* do nothing */ /* Must alloc, copy, free. */ - newmem = mALLOc(bytes); + newmem = mALLOc_impl(bytes); if (!newmem) return NULL; /* propagate failure */ MALLOC_COPY(newmem, oldmem, oldsize - 2*SIZE_SZ); @@ -1869,7 +1887,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; /* Must allocate */ - newmem = mALLOc (bytes); + newmem = mALLOc_impl (bytes); if (newmem == NULL) /* propagate failure */ return NULL; @@ -1886,7 +1904,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; /* Otherwise copy, free, and exit */ MALLOC_COPY(newmem, oldmem, oldsize - SIZE_SZ); - fREe(oldmem); + fREe_impl(oldmem); return newmem; } else { VALGRIND_RESIZEINPLACE_BLOCK(oldmem, 0, bytes, SIZE_SZ); @@ -1905,7 +1923,7 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; set_inuse_bit_at_offset(remainder, remainder_size); VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(remainder), remainder_size, SIZE_SZ, false); - fREe(chunk2mem(remainder)); /* let free() deal with it */ + fREe_impl(chunk2mem(remainder)); /* let free() deal with it */ } else { @@ -1939,10 +1957,11 @@ Void_t* rEALLOc(oldmem, bytes) Void_t* oldmem; size_t bytes; */ +STATIC_IF_MCHECK #if __STD_C -Void_t* mEMALIGn(size_t alignment, size_t bytes) +Void_t* mEMALIGn_impl(size_t alignment, size_t bytes) #else -Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; +Void_t* mEMALIGn_impl(alignment, bytes) size_t alignment; size_t bytes; #endif { INTERNAL_SIZE_T nb; /* padded request size */ @@ -1965,7 +1984,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; /* If need less alignment than we give anyway, just relay to malloc */ - if (alignment <= MALLOC_ALIGNMENT) return mALLOc(bytes); + if (alignment <= MALLOC_ALIGNMENT) return mALLOc_impl(bytes); /* Otherwise, ensure that it is at least a minimum chunk size */ @@ -1974,7 +1993,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; /* Call malloc with worst case padding to hit alignment. */ nb = request2size(bytes); - m = (char*)(mALLOc(nb + alignment + MINSIZE)); + m = (char*)(mALLOc_impl(nb + alignment + MINSIZE)); /* * The attempt to over-allocate (with a size large enough to guarantee the @@ -1990,7 +2009,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; * Use bytes not nb, since mALLOc internally calls request2size too, and * each call increases the size to allocate, to account for the header. */ - m = (char*)(mALLOc(bytes)); + m = (char*)(mALLOc_impl(bytes)); /* Aligned -> return it */ if ((((unsigned long)(m)) % alignment) == 0) return m; @@ -1998,10 +2017,10 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; * Otherwise, try again, requesting enough extra space to be able to * acquire alignment. */ - fREe(m); + fREe_impl(m); /* Add in extra bytes to match misalignment of unexpanded allocation */ extra = alignment - (((unsigned long)(m)) % alignment); - m = (char*)(mALLOc(bytes + extra)); + m = (char*)(mALLOc_impl(bytes + extra)); /* * m might not be the same as before. Validate that the previous value of * extra still works for the current value of m. @@ -2010,7 +2029,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; if (m) { extra2 = alignment - (((unsigned long)(m)) % alignment); if (extra2 > extra) { - fREe(m); + fREe_impl(m); m = NULL; } } @@ -2060,7 +2079,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; set_head(newp, newsize | PREV_INUSE); set_inuse_bit_at_offset(newp, newsize); set_head_size(p, leadsize); - fREe(chunk2mem(p)); + fREe_impl(chunk2mem(p)); p = newp; VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(p), bytes, SIZE_SZ, false); @@ -2078,7 +2097,7 @@ Void_t* mEMALIGn(alignment, bytes) size_t alignment; size_t bytes; set_head_size(p, nb); VALGRIND_MALLOCLIKE_BLOCK(chunk2mem(remainder), remainder_size, SIZE_SZ, false); - fREe(chunk2mem(remainder)); + fREe_impl(chunk2mem(remainder)); } check_inuse_chunk(p); @@ -2126,10 +2145,11 @@ Void_t* pvALLOc(bytes) size_t bytes; */ +STATIC_IF_MCHECK #if __STD_C -Void_t* cALLOc(size_t n, size_t elem_size) +Void_t* cALLOc_impl(size_t n, size_t elem_size) #else -Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size; +Void_t* cALLOc_impl(n, elem_size) size_t n; size_t elem_size; #endif { mchunkptr p; @@ -2145,7 +2165,7 @@ Void_t* cALLOc(n, elem_size) size_t n; size_t elem_size; INTERNAL_SIZE_T oldtopsize = chunksize(top); #endif #endif - Void_t* mem = mALLOc (sz); + Void_t* mem = mALLOc_impl (sz); if ((long)n < 0) return NULL; @@ -2205,6 +2225,90 @@ void cfree(mem) Void_t *mem; #endif +#ifdef MCHECK_HEAP_PROTECTION + #include "mcheck_core.inc.h" + #if !__STD_C + #error "must have __STD_C" + #endif + +Void_t *mALLOc(size_t bytes) +{ + mcheck_pedantic_prehook(); + size_t fullsz = mcheck_alloc_prehook(bytes); + void *p = mALLOc_impl(fullsz); + + if (!p) + return p; + return mcheck_alloc_posthook(p, bytes); +} + +void fREe(Void_t *mem) { fREe_impl(mcheck_free_prehook(mem)); } + +Void_t *rEALLOc(Void_t *oldmem, size_t bytes) +{ + mcheck_pedantic_prehook(); + if (bytes == 0) { + if (oldmem) + fREe(oldmem); + return NULL; + } + + if (oldmem == NULL) + return mALLOc(bytes); + + void *p = mcheck_reallocfree_prehook(oldmem); + size_t newsz = mcheck_alloc_prehook(bytes); + + p = rEALLOc_impl(p, newsz); + if (!p) + return p; + return mcheck_alloc_noclean_posthook(p, bytes); +} + +Void_t *mEMALIGn(size_t alignment, size_t bytes) +{ + mcheck_pedantic_prehook(); + size_t fullsz = mcheck_memalign_prehook(alignment, bytes); + void *p = mEMALIGn_impl(alignment, fullsz); + + if (!p) + return p; + return mcheck_memalign_posthook(alignment, p, bytes); +} + +// pvALLOc, vALLOc - redirect to mEMALIGn, defined here, so they need no wrapping. + +Void_t *cALLOc(size_t n, size_t elem_size) +{ + mcheck_pedantic_prehook(); + // NB: here is no overflow check. + size_t fullsz = mcheck_alloc_prehook(n * elem_size); + void *p = cALLOc_impl(1, fullsz); + + if (!p) + return p; + return mcheck_alloc_noclean_posthook(p, n * elem_size); +} + +// mcheck API { +int mcheck_pedantic(mcheck_abortfunc_t f) +{ + mcheck_initialize(f, 1); + return 0; +} + +int mcheck(mcheck_abortfunc_t f) +{ + mcheck_initialize(f, 0); + return 0; +} + +void mcheck_check_all(void) { mcheck_pedantic_check(); } + +enum mcheck_status mprobe(void *__ptr) { return mcheck_mprobe(__ptr); } +// mcheck API } +#endif + /* |