mirror of
https://github.com/microsoft/mimalloc.git
synced 2024-12-27 13:33:18 +08:00
add more detailed block info for heap visiting
This commit is contained in:
parent
120af372ab
commit
173978c122
@ -148,6 +148,7 @@ mi_block_t* _mi_page_ptr_unalign(const mi_segment_t* segment, const mi_page_t* p
|
||||
bool _mi_free_delayed_block(mi_block_t* block);
|
||||
void _mi_block_zero_init(const mi_page_t* page, void* p, size_t size);
|
||||
size_t _mi_path_max(void);
|
||||
void _mi_page_block_info(const mi_page_t* page, const mi_block_t* block, mi_block_info_t* info);
|
||||
|
||||
mi_decl_restrict void* _mi_base_malloc_zero(mi_heap_t* heap, size_t size, bool zero MI_SOURCE_XPARAM) mi_attr_malloc mi_attr_alloc_size(2);
|
||||
void* _mi_base_realloc_zero(mi_heap_t* heap, void* p, size_t newsize, bool zero MI_SOURCE_XPARAM) mi_attr_alloc_size(2);
|
||||
|
@ -282,7 +282,17 @@ typedef struct mi_heap_area_s {
|
||||
size_t block_size; // size in bytes of each block
|
||||
} mi_heap_area_t;
|
||||
|
||||
typedef bool (mi_cdecl mi_block_visit_fun)(const mi_heap_t* heap, const mi_heap_area_t* area, void* block, size_t block_size, void* arg);
|
||||
// Information about a block
|
||||
typedef struct mi_block_info_s {
|
||||
void* block; // start of the block
|
||||
size_t size; // full size including padding etc.
|
||||
size_t usable_size; // usable size (available for in-place realloc)
|
||||
size_t allocated_size; // actual allocated size (only precise in debug mode with padding)
|
||||
bool valid; // is the block valid? (only detects corrupt blocks with padding enabled)
|
||||
mi_source_t source; // the source location that allocated this block (only valid in debug mode with padding)
|
||||
} mi_block_info_t;
|
||||
|
||||
typedef bool (mi_cdecl mi_block_visit_fun)(const mi_heap_t* heap, const mi_heap_area_t* area, const mi_block_info_t* block_info, void* arg);
|
||||
|
||||
mi_decl_export bool mi_heap_visit_blocks(const mi_heap_t* heap, bool visit_all_blocks, mi_block_visit_fun* visitor, void* arg);
|
||||
|
||||
|
32
src/alloc.c
32
src/alloc.c
@ -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
|
||||
// ------------------------------------------------------
|
||||
|
15
src/heap.c
15
src/heap.c
@ -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);
|
||||
}
|
||||
|
@ -7,6 +7,44 @@
|
||||
#include <mimalloc.h>
|
||||
#include <mimalloc-override.h> // redefines malloc etc.
|
||||
|
||||
|
||||
typedef struct mi_visit_info_s {
|
||||
size_t area_count;
|
||||
size_t block_count;
|
||||
} mi_visit_info_t;
|
||||
|
||||
static bool visit(const mi_heap_t* heap, const mi_heap_area_t* area, const mi_block_info_t* info, void* arg) {
|
||||
mi_visit_info_t* varg = (mi_visit_info_t*)(arg);
|
||||
if (info==NULL) {
|
||||
printf(varg->area_count==0 ? " {" : " ]\n}\n,{");
|
||||
varg->area_count++;
|
||||
varg->block_count = 0;
|
||||
printf("\"area\": %zu, \"start\": 0x%p, \"block_size\": %zu, \"used_size\": %zu,\n \"reserved\": %zu, \"committed\": %zu,", varg->area_count, area->blocks, area->block_size, area->used, area->reserved, area->committed);
|
||||
printf(" \"blocks\": [\n");
|
||||
}
|
||||
else {
|
||||
printf(varg->block_count==0 ? " {" : " ,{");
|
||||
varg->block_count++;
|
||||
printf("\"block\": 0x%p, \"valid\": %s, \"size\": %zu, \"usable_size\": %zu, \"allocated_size\": %zu,\n ", info->block, info->valid ? "true" : "false", info->size, info->usable_size, info->allocated_size);
|
||||
int lineno;
|
||||
const char* fname;
|
||||
void* ret = mi_source_unpack(info->source, &fname, &lineno);
|
||||
if (fname!=NULL) printf("\"source\": \"%s:%i\" }\n", fname, lineno);
|
||||
else if (ret != NULL) printf("\"source\": \"(%p)\" }\n", ret);
|
||||
else printf("\"source\": \"\" }\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void mi_heap_to_json(mi_heap_t* heap) {
|
||||
if (heap==NULL) heap = mi_heap_get_default();
|
||||
mi_visit_info_t info = { 0, 0 };
|
||||
printf("[\n");
|
||||
mi_heap_visit_blocks(heap, true, &visit, &info);
|
||||
printf(info.area_count==0 ? "]\n" : " ] }\n]\n");
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void double_free1();
|
||||
static void double_free2();
|
||||
static void corrupt_free();
|
||||
@ -22,7 +60,7 @@ int main() {
|
||||
// double_free2();
|
||||
// corrupt_free();
|
||||
// block_overflow1();
|
||||
block_overflow2();
|
||||
// block_overflow2();
|
||||
// dangling_ptr_write();
|
||||
|
||||
void* p1 = malloc(78);
|
||||
@ -52,7 +90,6 @@ static void block_overflow1() {
|
||||
p[18] = 0;
|
||||
free(p);
|
||||
}
|
||||
|
||||
static void block_overflow2() {
|
||||
void* p[100];
|
||||
for (int i = 0; i < 100; i++) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user