libc/execinfo: extract a common backtrace format function

Add a common method to format backtrace to buffer, so it can be used by both mm, fs and other possoble modules.

Signed-off-by: fangpeina <fangpeina@xiaomi.com>
This commit is contained in:
fangpeina 2024-06-18 18:03:15 +08:00 committed by Xiang Xiao
parent ed099f1cea
commit 242b50f921
6 changed files with 91 additions and 73 deletions

View File

@ -38,6 +38,7 @@
#include <errno.h>
#include <debug.h>
#include <malloc.h>
#include <execinfo.h>
#ifdef CONFIG_SCHED_CRITMONITOR
# include <time.h>

View File

@ -27,15 +27,24 @@
#include <nuttx/sched.h>
#include <assert.h>
#include <stdio.h>
#include <sys/types.h>
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
#define backtrace(buffer, size) sched_backtrace(_SCHED_GETTID(), \
buffer, size, 0)
#define dump_stack() sched_dumpstack(_SCHED_GETTID())
/* 3: ' 0x' prefix */
#define BACKTRACE_PTR_FMT_WIDTH ((int)sizeof(uintptr_t) * 2 + 3)
/* Buffer size needed to hold formatted `depth` backtraces */
#define BACKTRACE_BUFFER_SIZE(d) (BACKTRACE_PTR_FMT_WIDTH * (d) + 1)
#define backtrace(b, s) sched_backtrace(_SCHED_GETTID(), b, s, 0)
#define dump_stack() sched_dumpstack(_SCHED_GETTID())
/****************************************************************************
* Public Function Prototypes
@ -52,6 +61,8 @@ extern "C"
FAR char **backtrace_symbols(FAR void *const *buffer, int size);
void backtrace_symbols_fd(FAR void *const *buffer, int size, int fd);
int backtrace_format(FAR char *buffer, int size,
FAR void *backtrace[], int depth);
#undef EXTERN
#if defined(__cplusplus)

View File

@ -88,3 +88,39 @@ void backtrace_symbols_fd(FAR void *const *buffer, int size, int fd)
dprintf(fd, "%pS\n", buffer[i]);
}
}
/****************************************************************************
* Name: backtrace_format
*
* Description:
* Format a backtrace into a buffer for dumping.
*
****************************************************************************/
int backtrace_format(FAR char *buffer, int size,
FAR void *backtrace[], int depth)
{
FAR const char *format = "%0*p ";
int len = 0;
int i;
if (size < 1)
{
return 0;
}
buffer[0] = '\0';
for (i = 0; i < depth && backtrace[i]; i++)
{
if (i * BACKTRACE_PTR_FMT_WIDTH >= size)
{
break;
}
len += snprintf(buffer + i * BACKTRACE_PTR_FMT_WIDTH,
size - i * BACKTRACE_PTR_FMT_WIDTH,
format, BACKTRACE_PTR_FMT_WIDTH - 1, backtrace[i]);
}
return len;
}

View File

@ -23,6 +23,7 @@
****************************************************************************/
#include <assert.h>
#include <execinfo.h>
#include <stdbool.h>
#include <stdio.h>
#include <syslog.h>
@ -33,12 +34,6 @@
#include "kasan/kasan.h"
#if UINTPTR_MAX <= UINT32_MAX
# define MM_PTR_FMT_WIDTH 11
#elif UINTPTR_MAX <= UINT64_MAX
# define MM_PTR_FMT_WIDTH 19
#endif
#undef ALIGN_UP
#define ALIGN_UP(x, a) (((x) + ((a) - 1)) & (~((a) - 1)))
@ -484,13 +479,13 @@ void mempool_memdump(FAR struct mempool_s *pool,
sq_for_every(&pool->queue, entry)
{
syslog(LOG_INFO, "%12zu%*p\n",
blocksize, MM_PTR_FMT_WIDTH, (FAR char *)entry);
blocksize, BACKTRACE_PTR_FMT_WIDTH, (FAR char *)entry);
}
sq_for_every(&pool->iqueue, entry)
{
syslog(LOG_INFO, "%12zu%*p\n",
blocksize, MM_PTR_FMT_WIDTH, (FAR char *)entry);
blocksize, BACKTRACE_PTR_FMT_WIDTH, (FAR char *)entry);
}
}
#if CONFIG_MM_BACKTRACE >= 0
@ -506,23 +501,19 @@ void mempool_memdump(FAR struct mempool_s *pool,
MM_DUMP_LEAK(dump->pid, buf->pid)) &&
buf->seqno >= dump->seqmin && buf->seqno <= dump->seqmax)
{
char tmp[CONFIG_MM_BACKTRACE * MM_PTR_FMT_WIDTH + 1] = "";
# if CONFIG_MM_BACKTRACE > 0
FAR const char *format = " %0*p";
int i;
char tmp[BACKTRACE_BUFFER_SIZE(CONFIG_MM_BACKTRACE)];
for (i = 0; i < CONFIG_MM_BACKTRACE && buf->backtrace[i]; i++)
{
snprintf(tmp + i * MM_PTR_FMT_WIDTH,
sizeof(tmp) - i * MM_PTR_FMT_WIDTH,
format, MM_PTR_FMT_WIDTH - 1, buf->backtrace[i]);
}
backtrace_format(tmp, sizeof(tmp), buf->backtrace,
CONFIG_MM_BACKTRACE);
# else
char *tmp = "";
# endif
syslog(LOG_INFO, "%6d%12zu%12lu%*p%s\n",
syslog(LOG_INFO, "%6d%12zu%12lu%*p %s\n",
buf->pid, blocksize, buf->seqno,
MM_PTR_FMT_WIDTH, ((FAR char *)buf - blocksize), tmp);
BACKTRACE_PTR_FMT_WIDTH, ((FAR char *)buf - blocksize),
tmp);
}
}
}

View File

@ -27,6 +27,7 @@
#include <stdio.h>
#include <assert.h>
#include <debug.h>
#include <execinfo.h>
#include <nuttx/mm/mm.h>
@ -36,12 +37,6 @@
* Pre-processor Definitions
****************************************************************************/
#if UINTPTR_MAX <= UINT32_MAX
# define MM_PTR_FMT_WIDTH 11
#elif UINTPTR_MAX <= UINT64_MAX
# define MM_PTR_FMT_WIDTH 19
#endif
/****************************************************************************
* Private Types
****************************************************************************/
@ -62,7 +57,7 @@ static void memdump_handler(FAR struct mm_allocnode_s *node, FAR void *arg)
if (dump->pid == PID_MM_ALLOC)
{
syslog(LOG_INFO, "%12zu%*p\n",
nodesize, MM_PTR_FMT_WIDTH,
nodesize, BACKTRACE_PTR_FMT_WIDTH,
((FAR char *)node + MM_SIZEOF_ALLOCNODE));
}
#elif CONFIG_MM_BACKTRACE == 0
@ -73,7 +68,7 @@ static void memdump_handler(FAR struct mm_allocnode_s *node, FAR void *arg)
{
syslog(LOG_INFO, "%6d%12zu%12lu%*p\n",
node->pid, nodesize, node->seqno,
MM_PTR_FMT_WIDTH,
BACKTRACE_PTR_FMT_WIDTH,
((FAR char *)node + MM_SIZEOF_ALLOCNODE));
}
#else
@ -82,21 +77,13 @@ static void memdump_handler(FAR struct mm_allocnode_s *node, FAR void *arg)
MM_DUMP_LEAK(dump->pid, node->pid)) &&
node->seqno >= dump->seqmin && node->seqno <= dump->seqmax)
{
char buf[CONFIG_MM_BACKTRACE * MM_PTR_FMT_WIDTH + 1] = "";
char buf[BACKTRACE_BUFFER_SIZE(CONFIG_MM_BACKTRACE)];
backtrace_format(buf, sizeof(buf), node->backtrace,
CONFIG_MM_BACKTRACE);
FAR const char *format = " %0*p";
int i;
for (i = 0; i < CONFIG_MM_BACKTRACE && node->backtrace[i]; i++)
{
snprintf(buf + i * MM_PTR_FMT_WIDTH,
sizeof(buf) - i * MM_PTR_FMT_WIDTH,
format, MM_PTR_FMT_WIDTH - 1, node->backtrace[i]);
}
syslog(LOG_INFO, "%6d%12zu%12lu%*p%s\n",
syslog(LOG_INFO, "%6d%12zu%12lu%*p %s\n",
node->pid, nodesize, node->seqno,
MM_PTR_FMT_WIDTH,
BACKTRACE_PTR_FMT_WIDTH,
((FAR char *)node + MM_SIZEOF_ALLOCNODE), buf);
}
#endif
@ -115,7 +102,7 @@ static void memdump_handler(FAR struct mm_allocnode_s *node, FAR void *arg)
MM_SIZEOF_NODE(fnode->flink) >= nodesize);
syslog(LOG_INFO, "%12zu%*p\n",
nodesize, MM_PTR_FMT_WIDTH,
nodesize, BACKTRACE_PTR_FMT_WIDTH,
((FAR char *)node + MM_SIZEOF_ALLOCNODE));
}
}
@ -144,16 +131,18 @@ void mm_memdump(FAR struct mm_heap_s *heap,
{
syslog(LOG_INFO, "Dump all used memory node info:\n");
#if CONFIG_MM_BACKTRACE < 0
syslog(LOG_INFO, "%12s%*s\n", "Size", MM_PTR_FMT_WIDTH, "Address");
syslog(LOG_INFO, "%12s%*s\n", "Size", BACKTRACE_PTR_FMT_WIDTH,
"Address");
#else
syslog(LOG_INFO, "%6s%12s%12s%*s %s\n", "PID", "Size", "Sequence",
MM_PTR_FMT_WIDTH, "Address", "Backtrace");
BACKTRACE_PTR_FMT_WIDTH, "Address", "Backtrace");
#endif
}
else
{
syslog(LOG_INFO, "Dump all free memory node info:\n");
syslog(LOG_INFO, "%12s%*s\n", "Size", MM_PTR_FMT_WIDTH, "Address");
syslog(LOG_INFO, "%12s%*s\n", "Size", BACKTRACE_PTR_FMT_WIDTH,
"Address");
}
#ifdef CONFIG_MM_HEAP_MEMPOOL

View File

@ -28,6 +28,7 @@
#include <errno.h>
#include <assert.h>
#include <debug.h>
#include <execinfo.h>
#include <sched.h>
#include <stdio.h>
#include <string.h>
@ -47,12 +48,6 @@
* Pre-processor Definitions
****************************************************************************/
#if UINTPTR_MAX <= UINT32_MAX
# define MM_PTR_FMT_WIDTH 11
#elif UINTPTR_MAX <= UINT64_MAX
# define MM_PTR_FMT_WIDTH 19
#endif
#if CONFIG_MM_HEAP_MEMPOOL_THRESHOLD > 0
# define MEMPOOL_NPOOLS (CONFIG_MM_HEAP_MEMPOOL_THRESHOLD / tlsf_align_size())
#endif
@ -444,7 +439,7 @@ static void memdump_handler(FAR void *ptr, size_t size, int used,
#if CONFIG_MM_BACKTRACE < 0
if (dump->pid == PID_MM_ALLOC)
{
syslog(LOG_INFO, "%12zu%*p\n", size, MM_PTR_FMT_WIDTH, ptr);
syslog(LOG_INFO, "%12zu%*p\n", size, BACKTRACE_PTR_FMT_WIDTH, ptr);
}
#elif CONFIG_MM_BACKTRACE == 0
FAR struct memdump_backtrace_s *buf =
@ -456,7 +451,7 @@ static void memdump_handler(FAR void *ptr, size_t size, int used,
buf->seqno >= dump->seqmin && buf->seqno <= dump->seqmax)
{
syslog(LOG_INFO, "%6d%12zu%12lu%*p\n",
buf->pid, size, buf->seqno, MM_PTR_FMT_WIDTH, ptr);
buf->pid, size, buf->seqno, BACKTRACE_PTR_FMT_WIDTH, ptr);
}
#else
FAR struct memdump_backtrace_s *buf =
@ -467,26 +462,19 @@ static void memdump_handler(FAR void *ptr, size_t size, int used,
MM_DUMP_LEAK(dump->pid, buf->pid)) &&
buf->seqno >= dump->seqmin && buf->seqno <= dump->seqmax)
{
char tmp[CONFIG_MM_BACKTRACE * MM_PTR_FMT_WIDTH + 1] = "";
char tmp[BACKTRACE_BUFFER_SIZE(CONFIG_MM_BACKTRACE)];
backtrace_format(tmp, sizeof(tmp), buf->backtrace,
CONFIG_MM_BACKTRACE);
FAR const char *format = " %0*p";
int i;
for (i = 0; i < CONFIG_MM_BACKTRACE && buf->backtrace[i]; i++)
{
snprintf(tmp + i * MM_PTR_FMT_WIDTH,
sizeof(tmp) - i * MM_PTR_FMT_WIDTH,
format, MM_PTR_FMT_WIDTH - 1, buf->backtrace[i]);
}
syslog(LOG_INFO, "%6d%12zu%12lu%*p%s\n",
buf->pid, size, buf->seqno, MM_PTR_FMT_WIDTH, ptr, tmp);
syslog(LOG_INFO, "%6d%12zu%12lu%*p %s\n",
buf->pid, size, buf->seqno, BACKTRACE_PTR_FMT_WIDTH,
ptr, tmp);
}
#endif
}
else if (dump->pid == PID_MM_FREE)
{
syslog(LOG_INFO, "%12zu%*p\n", size, MM_PTR_FMT_WIDTH, ptr);
syslog(LOG_INFO, "%12zu%*p\n", size, BACKTRACE_PTR_FMT_WIDTH, ptr);
}
}
@ -1074,16 +1062,18 @@ void mm_memdump(FAR struct mm_heap_s *heap,
{
syslog(LOG_INFO, "Dump all used memory node info:\n");
#if CONFIG_MM_BACKTRACE < 0
syslog(LOG_INFO, "%12s%*s\n", "Size", MM_PTR_FMT_WIDTH, "Address");
syslog(LOG_INFO, "%12s%*s\n", "Size", BACKTRACE_PTR_FMT_WIDTH,
"Address");
#else
syslog(LOG_INFO, "%6s%12s%12s%*s %s\n", "PID", "Size", "Sequence",
MM_PTR_FMT_WIDTH, "Address", "Backtrace");
BACKTRACE_PTR_FMT_WIDTH, "Address", "Backtrace");
#endif
}
else
{
syslog(LOG_INFO, "Dump all free memory node info:\n");
syslog(LOG_INFO, "%12s%*s\n", "Size", MM_PTR_FMT_WIDTH, "Address");
syslog(LOG_INFO, "%12s%*s\n", "Size", BACKTRACE_PTR_FMT_WIDTH,
"Address");
}
#ifdef CONFIG_MM_HEAP_MEMPOOL