diff --git a/os/include/tinyara/mm/mm.h b/os/include/tinyara/mm/mm.h index d9d99faffd..a0e2cff0d9 100644 --- a/os/include/tinyara/mm/mm.h +++ b/os/include/tinyara/mm/mm.h @@ -691,7 +691,9 @@ void mm_addfreechunk(FAR struct mm_heap_s *heap, FAR struct mm_freenode_s *node) int mm_size2ndx(size_t size); +void mm_dump_node(struct mm_allocnode_s *node, char *node_type); void mm_dump_heap_region(uint32_t start, uint32_t end); +void mm_dump_heap_free_node_list(struct mm_heap_s *heap); int heap_dbg(const char *fmt, ...); #ifdef CONFIG_DEBUG_MM_HEAPINFO /* Functions contained in kmm_mallinfo.c . Used to display memory allocation details */ diff --git a/os/mm/mm_heap/mm_check_heap_corruption.c b/os/mm/mm_heap/mm_check_heap_corruption.c index 99089f171d..9e1662c13c 100644 --- a/os/mm/mm_heap/mm_check_heap_corruption.c +++ b/os/mm/mm_heap/mm_check_heap_corruption.c @@ -80,41 +80,6 @@ * Private Functions ****************************************************************************/ -static void dump_node(struct mm_allocnode_s *node, char *node_type) -{ -#if defined(CONFIG_DEBUG_MM_HEAPINFO) && (CONFIG_TASK_NAME_SIZE > 0) - char myname[CONFIG_TASK_NAME_SIZE + 1]; - char is_stack[9] = "'s stack"; -#endif - - if (!node) { - mfdbg("Unable to dump NULL node\n"); - return; - } - - mfdbg("%s: addr = 0x%08x, type = %c, size = %u, preceding size = %u\n", node_type, node, IS_ALLOCATED_NODE(node) ? 'A' : 'F', node->size, MM_PREV_NODE_SIZE(node)); - -#ifdef CONFIG_DEBUG_MM_HEAPINFO - pid_t pid = node->pid; - if (pid < 0) { - /* For stack allocated node, pid is negative value. - * To use the pid, change it to original positive value. - */ - pid = (-1) * pid; - } else { - is_stack[0] = '\0'; - } -#if CONFIG_TASK_NAME_SIZE > 0 - if (prctl(PR_GET_NAME_BYPID, myname, pid) == OK) { - mfdbg("%s owner pid = %d (%s%s), allocated by code at addr = 0x%08x\n", node_type, node->pid, myname, is_stack, node->alloc_call_addr); - } else { - mfdbg("%s owner pid = %d (Exited Task%s), allocated by code at addr = 0x%08x\n", node_type, node->pid, is_stack, node->alloc_call_addr); - } -#else - mfdbg("%s owner pid = %d%s, allocated by code at addr = 0x%08x\n", node_type, node->pid, is_stack, node->alloc_call_addr); -#endif -#endif -} /**************************************************************************** * Public Functions @@ -166,7 +131,7 @@ int mm_check_heap_corruption(struct mm_heap_s *heap) mfdbg("ERROR: Heap corruption detected in mm_heapstart node.\n"); mfdbg("ERROR: Check for overflow during backward traversal of heap\n"); mfdbg("=========================================================================================\n"); - dump_node(heap->mm_heapstart[region], "HEAP START NODE"); + mm_dump_node(heap->mm_heapstart[region], "HEAP START NODE"); iscorrupt_f = true; start_corrupt = (uint32_t)(heap->mm_heapstart[region]); mfdbg("=========================================================================================\n"); @@ -180,8 +145,8 @@ int mm_check_heap_corruption(struct mm_heap_s *heap) mfdbg("ERROR: Heap corruption detected. Check below nodes for possible corruption.\n"); mfdbg("ERROR: Forward traversal of heap\n"); mfdbg("=========================================================================================\n"); - dump_node(prev, "PREV NODE"); - dump_node(node, "CORRUPT NODE"); + mm_dump_node(prev, "PREV NODE"); + mm_dump_node(node, "CORRUPT NODE"); iscorrupt_f = true; if (prev->size <= MM_LAST_CORRUPT_SIZE) { start_corrupt = (uint32_t)prev; @@ -198,8 +163,8 @@ int mm_check_heap_corruption(struct mm_heap_s *heap) mfdbg("ERROR: Heap corruption detected. Check below nodes for possible corruption.\n"); mfdbg("ERROR: Forward traversal of heap without reaching heapend\n"); mfdbg("=========================================================================================\n"); - dump_node((struct mm_allocnode_s *)((char *)prev - MM_PREV_NODE_SIZE(prev)), "PREV NODE"); - dump_node(prev, "CORRUPT NODE"); + mm_dump_node((struct mm_allocnode_s *)((char *)prev - MM_PREV_NODE_SIZE(prev)), "PREV NODE"); + mm_dump_node(prev, "CORRUPT NODE"); iscorrupt_f = true; start_corrupt = (uint32_t)prev - (MM_PREV_NODE_SIZE(prev) <= MM_LAST_CORRUPT_SIZE ? MM_PREV_NODE_SIZE(prev) : MM_LAST_CORRUPT_SIZE); mfdbg("=========================================================================================\n"); @@ -210,7 +175,7 @@ int mm_check_heap_corruption(struct mm_heap_s *heap) mfdbg("ERROR: Heap corruption detected in mm_heapend node.\n"); mfdbg("ERROR: Check for overflow from PREV node in forward traversal of heap\n"); mfdbg("=========================================================================================\n"); - dump_node(heap->mm_heapend[region], "HEAP END NODE"); + mm_dump_node(heap->mm_heapend[region], "HEAP END NODE"); iscorrupt_r = true; end_corrupt = (uint32_t)(heap->mm_heapend[region]) + SIZEOF_MM_ALLOCNODE; mfdbg("#########################################################################################\n"); @@ -223,8 +188,8 @@ int mm_check_heap_corruption(struct mm_heap_s *heap) ((MM_PREV_NODE_SIZE(node) < SIZEOF_MM_ALLOCNODE) &&(node != heap->mm_heapstart[region]))) { mfdbg("ERROR: Backward traversal of heap\n"); mfdbg("=========================================================================================\n"); - dump_node(node, "CORRUPT NODE"); - dump_node(prev, "PREV NODE"); + mm_dump_node(node, "CORRUPT NODE"); + mm_dump_node(prev, "PREV NODE"); iscorrupt_r = true; end_corrupt = (uint32_t)prev + (prev->size <= MM_LAST_CORRUPT_SIZE ? prev->size : MM_LAST_CORRUPT_SIZE); mfdbg("#########################################################################################\n"); @@ -235,8 +200,8 @@ int mm_check_heap_corruption(struct mm_heap_s *heap) if (!iscorrupt_r && prev != heap->mm_heapstart[region]) { mfdbg("ERROR: Backward traversal of heap without reaching heapstart\n"); mfdbg("=========================================================================================\n"); - dump_node(prev, "CORRUPT NODE"); - dump_node((struct mm_allocnode_s *)((char *)prev + prev->size), "PREV NODE"); + mm_dump_node(prev, "CORRUPT NODE"); + mm_dump_node((struct mm_allocnode_s *)((char *)prev + prev->size), "PREV NODE"); iscorrupt_r = true; node = (struct mm_allocnode_s *)((char *)prev + prev->size); end_corrupt = (uint32_t)node + (node->size <= MM_LAST_CORRUPT_SIZE ? node->size : MM_LAST_CORRUPT_SIZE); diff --git a/os/mm/mm_heap/mm_free.c b/os/mm/mm_heap/mm_free.c index b60e9a707e..295ecda11d 100644 --- a/os/mm/mm_heap/mm_free.c +++ b/os/mm/mm_heap/mm_free.c @@ -154,7 +154,7 @@ void mm_free(FAR struct mm_heap_s *heap, FAR void *mem) /* Remove the next node. There must be a predecessor, * but there may not be a successor node. */ - + DEBUGASSERT_MM_FREE_NODE(heap, next); REMOVE_NODE_FROM_LIST(next); /* Then merge the two chunks */ @@ -173,7 +173,7 @@ void mm_free(FAR struct mm_heap_s *heap, FAR void *mem) /* Remove the node. There must be a predecessor, but there may * not be a successor node. */ - + DEBUGASSERT_MM_FREE_NODE(heap, prev); REMOVE_NODE_FROM_LIST(prev); /* Then merge the two chunks */ diff --git a/os/mm/mm_heap/mm_heap_dbg.c b/os/mm/mm_heap/mm_heap_dbg.c index 8d2e3e3f99..67ea592623 100644 --- a/os/mm/mm_heap/mm_heap_dbg.c +++ b/os/mm/mm_heap/mm_heap_dbg.c @@ -74,3 +74,68 @@ void mm_dump_heap_region(uint32_t start, uint32_t end) heap_dbg("#########################################################################################\n"); } +/************************************************************************ + * Name: mm_dump_heap_free_node_list + * + * Description: Print the hex value contents of heap free nodes. + ************************************************************************/ +void mm_dump_heap_free_node_list(struct mm_heap_s *heap) +{ + struct mm_freenode_s *node; + heap_dbg("#########################################################################################\n"); + heap_dbg("Dump heap free node list\n"); + heap_dbg("[ndx], [HEAD]: [FREE NODES(SIZE)]\n"); + heap_dbg("#########################################################################################\n"); + for (uint8_t ndx = 0; ndx < MM_NNODES; ndx++) { + heap_dbg("%3d, %08x:", ndx, &heap->mm_nodelist[ndx]); + for (node = heap->mm_nodelist[ndx].flink; node; node = node->flink) { + heap_dbg(" %08x(%d)", node, node->size); + } + heap_dbg("\n"); + if (heap->mm_nodelist[ndx].size != 0) { + mfdbg(" Corrupted HEAD of free node link %08x\n", &heap->mm_nodelist[ndx]); + } + } + heap_dbg("#########################################################################################\n"); +} + +/************************************************************************ + * Name: mm_dump_node + * + * Description: Print the information of heap node. + ************************************************************************/ +void mm_dump_node(struct mm_allocnode_s *node, char *node_type) +{ +#if defined(CONFIG_DEBUG_MM_HEAPINFO) && (CONFIG_TASK_NAME_SIZE > 0) + char myname[CONFIG_TASK_NAME_SIZE + 1]; + char is_stack[9] = "'s stack"; +#endif + + if (!node) { + mfdbg("Unable to dump NULL node\n"); + return; + } + + mfdbg("%s: addr = 0x%08x, type = %c, size = %u, preceding size = %u\n", node_type, node, node->preceding & MM_ALLOC_BIT ? 'A' : 'F', node->size, node->preceding & ~MM_ALLOC_BIT); + +#ifdef CONFIG_DEBUG_MM_HEAPINFO + pid_t pid = node->pid; + if (pid < 0) { + /* For stack allocated node, pid is negative value. + * To use the pid, change it to original positive value. + */ + pid = (-1) * pid; + } else { + is_stack[0] = '\0'; + } +#if CONFIG_TASK_NAME_SIZE > 0 + if (prctl(PR_GET_NAME_BYPID, myname, pid) == OK) { + mfdbg("%s owner pid = %d (%s%s), allocated by code at addr = 0x%08x\n", node_type, node->pid, myname, is_stack, node->alloc_call_addr); + } else { + mfdbg("%s owner pid = %d (Exited Task%s), allocated by code at addr = 0x%08x\n", node_type, node->pid, is_stack, node->alloc_call_addr); + } +#else + mfdbg("%s owner pid = %d%s, allocated by code at addr = 0x%08x\n", node_type, node->pid, is_stack, node->alloc_call_addr); +#endif +#endif +} diff --git a/os/mm/mm_heap/mm_malloc.c b/os/mm/mm_heap/mm_malloc.c index 7de9653347..80333eedb8 100644 --- a/os/mm/mm_heap/mm_malloc.c +++ b/os/mm/mm_heap/mm_malloc.c @@ -170,7 +170,7 @@ FAR void *mm_malloc(FAR struct mm_heap_s *heap, size_t size) /* Remove the node. There must be a predecessor, but there may not be * a successor node. */ - + DEBUGASSERT_MM_FREE_NODE(heap, node); REMOVE_NODE_FROM_LIST(node); /* Check if we have to split the free node into one of the allocated diff --git a/os/mm/mm_heap/mm_memalign.c b/os/mm/mm_heap/mm_memalign.c index 944fce2af0..8f4cc22070 100644 --- a/os/mm/mm_heap/mm_memalign.c +++ b/os/mm/mm_heap/mm_memalign.c @@ -216,7 +216,7 @@ FAR void *mm_memalign(FAR struct mm_heap_s *heap, size_t alignment, size_t size) /* Remove the node. There must be a predecessor, but there may not be * a successor node. */ - + DEBUGASSERT_MM_FREE_NODE(heap, node); REMOVE_NODE_FROM_LIST(node); /* Check if there is free space at the beginning of the aligned chunk */ diff --git a/os/mm/mm_heap/mm_node.h b/os/mm/mm_heap/mm_node.h index e225b207df..75503f887e 100644 --- a/os/mm/mm_heap/mm_node.h +++ b/os/mm/mm_heap/mm_node.h @@ -24,14 +24,48 @@ ****************************************************************************/ #include +#include + +#include /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ +#if defined(CONFIG_BUILD_FLAT) || defined(__KERNEL__) +#define DEBUGASSERT_MM_FREE_NODE(heap, node) \ + do { \ + DEBUGASSERT(node); \ + if (!((node)->blink)) { \ + abort_mode = true; \ + mfdbg("Corrupted free node %08x\n", node); \ + mm_dump_heap_free_node_list(heap); \ + mm_dump_node((struct mm_allocnode_s *)node, "CORRUPT NODE"); \ + mm_dump_node((struct mm_allocnode_s *)((char *)node - (node->preceding & ~MM_ALLOC_BIT)), "PREV NODE"); \ + mm_dump_node((struct mm_allocnode_s *)((char *)node + node->size), "NEXT NODE"); \ + DEBUGPANIC(); \ + } \ + } while (0) + +#else +#define DEBUGASSERT_MM_FREE_NODE(heap, node) \ + do { \ + DEBUGASSERT(node); \ + if (!((node)->blink)) { \ + mfdbg("Corrupted free node %08x\n", node); \ + mm_dump_heap_free_node_list(heap); \ + mm_dump_node((struct mm_allocnode_s *)node, "CORRUPT NODE"); \ + mm_dump_node((struct mm_allocnode_s *)((char *)node - (node->preceding & ~MM_ALLOC_BIT)), "PREV NODE"); \ + mm_dump_node((struct mm_allocnode_s *)((char *)node + node->size), "NEXT NODE"); \ + DEBUGPANIC(); \ + } \ + } while (0) + +#endif + + #define REMOVE_NODE_FROM_LIST(node) \ do { \ - DEBUGASSERT((node)->blink); \ (node)->blink->flink = (node)->flink; \ if ((node)->flink) { \ (node)->flink->blink = (node)->blink; \ diff --git a/os/mm/mm_heap/mm_realloc.c b/os/mm/mm_heap/mm_realloc.c index 7c2b739a71..d0be7696d9 100644 --- a/os/mm/mm_heap/mm_realloc.c +++ b/os/mm/mm_heap/mm_realloc.c @@ -266,7 +266,7 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, size_t size) /* Remove the previous node. There must be a predecessor, but * there may not be a successor node. */ - + DEBUGASSERT_MM_FREE_NODE(heap, prev); REMOVE_NODE_FROM_LIST(prev); /* Extend the node into the previous free chunk */ @@ -320,7 +320,7 @@ FAR void *mm_realloc(FAR struct mm_heap_s *heap, FAR void *oldmem, size_t size) /* Remove the next node. There must be a predecessor, but there * may not be a successor node. */ - + DEBUGASSERT_MM_FREE_NODE(heap, next); REMOVE_NODE_FROM_LIST(next); /* Extend the node into the next chunk */ diff --git a/os/mm/mm_heap/mm_shrinkchunk.c b/os/mm/mm_heap/mm_shrinkchunk.c index ed1b82b6fa..3f1ced3e4b 100644 --- a/os/mm/mm_heap/mm_shrinkchunk.c +++ b/os/mm/mm_heap/mm_shrinkchunk.c @@ -104,7 +104,7 @@ void mm_shrinkchunk(FAR struct mm_heap_s *heap, FAR struct mm_allocnode_s *node, /* Remove the next node. There must be a predecessor, but there may * not be a successor node. */ - + DEBUGASSERT_MM_FREE_NODE(heap, next); REMOVE_NODE_FROM_LIST(next); /* Create a new chunk that will hold both the next chunk and the