add more detailed block info for heap visiting

This commit is contained in:
daan 2020-04-06 23:39:09 -07:00
parent 120af372ab
commit 173978c122
5 changed files with 89 additions and 12 deletions

View file

@ -18,6 +18,7 @@ terms of the MIT license. A copy of the license can be found in the file
#include "alloc-override.c"
#undef MI_IN_ALLOC_C
#define MI_PADDING_MAX_VALIDATE (4*1024) // max. bytes validated for overwrites
// ----------------------------------------------------------------------------------------
// Allocation
@ -58,7 +59,7 @@ extern inline void* _mi_page_malloc(mi_heap_t* heap, mi_page_t* page, size_t siz
padding->delta = (uint32_t)(delta);
padding->source = __mi_source;
uint8_t* fill = (uint8_t*)padding - delta;
const size_t maxpad = (delta > 4096 ? 4096 : delta); // set at most N initial padding bytes
const size_t maxpad = (delta > MI_PADDING_MAX_VALIDATE ? MI_PADDING_MAX_VALIDATE : delta); // set at most N initial padding bytes
for (size_t i = 0; i < maxpad; i++) { fill[i] = MI_DEBUG_PADDING; }
#endif
return block;
@ -211,9 +212,13 @@ static inline bool mi_check_is_double_free(const mi_page_t* page, const mi_block
#if defined(MI_PADDING) && defined(MI_ENCODE_FREELIST)
static void mi_check_padding(const mi_page_t* page, const mi_block_t* block);
static bool mi_page_decode_padding(const mi_page_t* page, const mi_block_t* block, size_t* delta, size_t* bsize) {
static const mi_padding_t* mi_page_get_padding(const mi_page_t* page, const mi_block_t* block, size_t* bsize) {
*bsize = mi_page_usable_block_size(page);
const mi_padding_t* const padding = (mi_padding_t*)((uint8_t*)block + *bsize);
return (mi_padding_t*)((uint8_t*)block + *bsize);
}
static bool mi_page_decode_padding(const mi_page_t* page, const mi_block_t* block, size_t* delta, size_t* bsize) {
const mi_padding_t* const padding = mi_page_get_padding(page, block, bsize);
*delta = padding->delta;
return ((uint32_t)mi_ptr_encode(page,block,page->keys) == padding->canary && *delta <= *bsize);
}
@ -237,7 +242,7 @@ static bool mi_verify_padding(const mi_page_t* page, const mi_block_t* block, si
mi_assert_internal(bsize >= delta);
*size = bsize - delta;
uint8_t* fill = (uint8_t*)block + bsize - delta;
const size_t maxpad = (delta > MI_MAX_ALIGN_SIZE ? MI_MAX_ALIGN_SIZE : delta); // check at most the first N padding bytes
const size_t maxpad = (delta > MI_PADDING_MAX_VALIDATE ? MI_PADDING_MAX_VALIDATE : delta); // check at most the first N padding bytes
for (size_t i = 0; i < maxpad; i++) {
if (fill[i] != MI_DEBUG_PADDING) {
*wrong = bsize - delta + i;
@ -323,6 +328,25 @@ static void mi_padding_shrink(const mi_page_t* page, const mi_block_t* block, co
}
#endif
void _mi_page_block_info(const mi_page_t* page, const mi_block_t* block, mi_block_info_t* info) {
mi_assert_internal(page!=NULL);
mi_assert_internal(block!=NULL);
mi_assert_internal(info!=NULL);
memset(info, 0, sizeof(*info));
info->block = (void*)block;
info->size = mi_page_block_size(page);
#if MI_PADDING
const mi_padding_t* padding = mi_page_get_padding(page, block, &info->usable_size);
info->source = padding->source;
size_t wrong;
info->valid = mi_verify_padding(page, block, &info->allocated_size, &wrong);
#else
info->usable_size = mi_usable_size(block);
info->allocated_size = info->usable_size;
#endif
}
// ------------------------------------------------------
// Free
// ------------------------------------------------------

View file

@ -468,7 +468,10 @@ static bool mi_heap_area_visit_blocks(const mi_heap_area_ex_t* xarea, mi_block_v
if (page->capacity == 1) {
// optimize page with one block
mi_assert_internal(page->used == 1 && page->free == NULL);
return visitor(mi_page_heap(page), area, pstart, bsize, arg);
mi_block_info_t info;
mi_block_t* block = (mi_block_t*)(pstart);
_mi_page_block_info(page, block, &info);
return visitor(mi_page_heap(page), area, &info, arg);
}
// create a bitmap of free blocks.
@ -501,8 +504,10 @@ static bool mi_heap_area_visit_blocks(const mi_heap_area_ex_t* xarea, mi_block_v
}
else if ((m & ((uintptr_t)1 << bit)) == 0) {
used_count++;
uint8_t* block = pstart + (i * bsize);
if (!visitor(mi_page_heap(page), area, block, bsize, arg)) return false;
mi_block_info_t info;
mi_block_t* block = (mi_block_t*)(pstart + (i * bsize));
_mi_page_block_info(page, block, &info);
if (!visitor(mi_page_heap(page), area, &info, arg)) return false;
}
}
mi_assert_internal(page->used == used_count);
@ -522,7 +527,7 @@ static bool mi_heap_visit_areas_page(mi_heap_t* heap, mi_page_queue_t* pq, mi_pa
xarea.area.reserved = page->reserved * bsize;
xarea.area.committed = page->capacity * bsize;
xarea.area.blocks = _mi_page_start(_mi_page_segment(page), page, NULL);
xarea.area.used = page->used;
xarea.area.used = page->used * bsize;
xarea.area.block_size = bsize;
return fun(heap, &xarea, arg);
}
@ -542,7 +547,7 @@ typedef struct mi_visit_blocks_args_s {
static bool mi_heap_area_visitor(const mi_heap_t* heap, const mi_heap_area_ex_t* xarea, void* arg) {
mi_visit_blocks_args_t* args = (mi_visit_blocks_args_t*)arg;
if (!args->visitor(heap, &xarea->area, NULL, xarea->area.block_size, args->arg)) return false;
if (!args->visitor(heap, &xarea->area, NULL, args->arg)) return false;
if (args->visit_blocks) {
return mi_heap_area_visit_blocks(xarea, args->visitor, args->arg);
}