Void_t *mALLOc(size_t bytes)
{
+ mcheck_pedantic_prehook();
size_t fullsz = mcheck_alloc_prehook(bytes);
void *p = mALLOc_impl(fullsz);
Void_t *rEALLOc(Void_t *oldmem, size_t bytes)
{
+ mcheck_pedantic_prehook();
if (bytes == 0) {
if (oldmem)
fREe(oldmem);
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);
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);
}
// 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
* Unlike glibc-clients, U-Boot has limited malloc-usage, and only one thread.
* So it's better to make the protection heavier.
* Thus overflow canary here is greater, than glibc's one. Underflow canary is bigger too.
+ * U-Boot also allows to use fixed-size heap-registry, instead of double-linked list in glibc.
+ *
* Heavy canary allows to catch not only memset(..)-errors,
* but overflow/underflow of struct-array access:
* {
#define FREEFLOOD ((char)0xf5)
#define PADDINGFLOOD ((char)0x58)
+// my normal run demands 4427-6449 chunks:
+#define REGISTRY_SZ 6608
#define CANARY_DEPTH 2
+// avoid problems with BSS at early stage:
+static char mcheck_pedantic_flag __section(".data") = 0;
+static void *mcheck_registry[REGISTRY_SZ] __section(".data") = {0};
+
typedef unsigned long long mcheck_elem;
typedef struct {
mcheck_elem elems[CANARY_DEPTH];
if (clean_content)
mcheck_flood(ptr, FREEFLOOD, mcheck_allign_customer_size(hdr->size));
+ for (i = 0; i < REGISTRY_SZ; ++i)
+ if (mcheck_registry[i] == hdr) {
+ mcheck_registry[i] = 0;
+ break;
+ }
+
return (char *)hdr - hdr->aln_skip;
}
for (i = 0; i < CANARY_DEPTH; ++i)
tail->elems[i] = MAGICTAIL;
+
+ for (i = 0; i < REGISTRY_SZ; ++i)
+ if (!mcheck_registry[i]) {
+ mcheck_registry[i] = hdr;
+ return payload; // normal end
+ }
+
+ static char *overflow_msg = "\n\n\nERROR: mcheck registry overflow, pedantic check would be incomplete!!\n\n\n\n";
+
+ printf("%s", overflow_msg);
+ overflow_msg = "(mcheck registry full)";
return payload;
}
return mcheck_checkhdr(hdr);
}
+static void mcheck_pedantic_check(void)
+{
+ int i;
+
+ for (i = 0; i < REGISTRY_SZ; ++i)
+ if (mcheck_registry[i])
+ mcheck_checkhdr(mcheck_registry[i]);
+}
+
+static void mcheck_pedantic_prehook(void)
+{
+ if (mcheck_pedantic_flag)
+ mcheck_pedantic_check();
+}
+
static void mcheck_initialize(mcheck_abortfunc_t new_func, char pedantic_flag)
{
mcheck_abortfunc = (new_func) ? new_func : &mcheck_default_abort;
+ mcheck_pedantic_flag = pedantic_flag;
}
#endif
int mcheck(mcheck_abortfunc_t func);
+/*
+ * Similar to `mcheck' but performs checks for all block whenever one of
+ * the memory handling functions is called. This can be very slow.
+ */
+int mcheck_pedantic(mcheck_abortfunc_t f);
+
+/* Force check of all blocks now. */
+void mcheck_check_all(void);
+
/*
* Check for aberrations in a particular malloc'd block. These are the
* same checks that `mcheck' does, when you free or reallocate a block.