debug: coredump: support dumping stack top only
Add Kconfig option to dump only a portion of stack from the current stack pointer to the stack end. This is enough to let gdb reconstruct the stack trace and can significantly reduce the dump size. This is crucial if the core dump needs to be sent over radio. Additionally, add another option to set the limit for the dumped stack portion. Signed-off-by: Damian Krolik <damian.krolik@nordicsemi.no>
This commit is contained in:
parent
40c75b7d8c
commit
222e0fcd06
6 changed files with 82 additions and 7 deletions
|
@ -33,6 +33,7 @@ config ARM
|
|||
select ARCH_IS_SET
|
||||
select ARCH_SUPPORTS_COREDUMP if CPU_CORTEX_M
|
||||
select ARCH_SUPPORTS_COREDUMP_THREADS if CPU_CORTEX_M
|
||||
select ARCH_SUPPORTS_COREDUMP_STACK_PTR if CPU_CORTEX_M
|
||||
# FIXME: current state of the code for all ARM requires this, but
|
||||
# is really only necessary for Cortex-M with ARM MPU!
|
||||
select GEN_PRIV_STACKS
|
||||
|
@ -705,6 +706,9 @@ config ARCH_SUPPORTS_COREDUMP_THREADS
|
|||
config ARCH_SUPPORTS_COREDUMP_PRIV_STACKS
|
||||
bool
|
||||
|
||||
config ARCH_SUPPORTS_COREDUMP_STACK_PTR
|
||||
bool
|
||||
|
||||
config ARCH_SUPPORTS_ARCH_HW_INIT
|
||||
bool
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <zephyr/debug/coredump.h>
|
||||
#include <zephyr/kernel/thread.h>
|
||||
|
||||
#define ARCH_HDR_VER 2
|
||||
|
||||
|
@ -96,3 +97,8 @@ uint16_t arch_coredump_tgt_code_get(void)
|
|||
{
|
||||
return COREDUMP_TGT_ARM_CORTEX_M;
|
||||
}
|
||||
|
||||
uintptr_t arch_coredump_stack_ptr_get(const struct k_thread *thread)
|
||||
{
|
||||
return (thread == _current) ? z_arm_coredump_fault_sp : thread->callee_saved.psp;
|
||||
}
|
||||
|
|
|
@ -226,6 +226,12 @@ New APIs and options
|
|||
|
||||
* :kconfig:option:`CONFIG_NVME_PRP_PAGE_SIZE`
|
||||
|
||||
* Debug
|
||||
|
||||
* Core Dump
|
||||
|
||||
* :kconfig:option:`CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP`, enabled by default for ARM Cortex M when :kconfig:option:`CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN` is selected.
|
||||
|
||||
* Other
|
||||
|
||||
* :kconfig:option:`CONFIG_LV_Z_COLOR_MONO_HW_INVERSION`
|
||||
|
|
|
@ -638,6 +638,11 @@ void arch_coredump_info_dump(const struct arch_esf *esf);
|
|||
*/
|
||||
uint16_t arch_coredump_tgt_code_get(void);
|
||||
|
||||
/**
|
||||
* @brief Get the stack pointer of the thread.
|
||||
*/
|
||||
uintptr_t arch_coredump_stack_ptr_get(const struct k_thread *thread);
|
||||
|
||||
#if defined(CONFIG_USERSPACE) || defined(__DOXYGEN__)
|
||||
|
||||
/**
|
||||
|
|
|
@ -144,4 +144,27 @@ module = DEBUG_COREDUMP
|
|||
module-str = coredump
|
||||
source "subsys/logging/Kconfig.template.log_config"
|
||||
|
||||
config DEBUG_COREDUMP_THREAD_STACK_TOP
|
||||
bool "Dump top of stack only"
|
||||
default y if DEBUG_COREDUMP_MEMORY_DUMP_MIN
|
||||
depends on DEBUG_COREDUMP_MEMORY_DUMP_MIN || \
|
||||
DEBUG_COREDUMP_MEMORY_DUMP_THREADS
|
||||
depends on ARCH_SUPPORTS_COREDUMP_STACK_PTR
|
||||
help
|
||||
This option enables dumping only the top portion of each thread's
|
||||
stack, rather than the entire stack region. The top of the stack is
|
||||
defined as the area from the stack pointer to the stack end, but the
|
||||
size of this region can additionally be constrained using the
|
||||
DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT option.
|
||||
|
||||
config DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT
|
||||
int "Stack top size limit"
|
||||
default -1
|
||||
depends on DEBUG_COREDUMP_THREAD_STACK_TOP
|
||||
help
|
||||
See the description of the DEBUG_COREDUMP_THREAD_STACK_TOP option.
|
||||
The value -1 indicates that there is no limit, meaning that the stack
|
||||
is dumped till the end of its region.
|
||||
|
||||
|
||||
endif # DEBUG_COREDUMP
|
||||
|
|
|
@ -41,6 +41,13 @@ static struct coredump_backend_api
|
|||
#define DT_DRV_COMPAT zephyr_coredump
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT) && \
|
||||
CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT > 0
|
||||
#define STACK_TOP_LIMIT ((size_t)CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT)
|
||||
#else
|
||||
#define STACK_TOP_LIMIT SIZE_MAX
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_DEBUG_COREDUMP_DUMP_THREAD_PRIV_STACK)
|
||||
__weak void arch_coredump_priv_stack_dump(struct k_thread *thread)
|
||||
{
|
||||
|
@ -70,10 +77,35 @@ static void dump_header(unsigned int reason)
|
|||
backend_api->buffer_output((uint8_t *)&hdr, sizeof(hdr));
|
||||
}
|
||||
|
||||
#if defined(CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN) || \
|
||||
#if defined(CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN) || \
|
||||
defined(CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_THREADS)
|
||||
|
||||
static inline void select_stack_region(const struct k_thread *thread, uintptr_t *start,
|
||||
uintptr_t *end)
|
||||
{
|
||||
uintptr_t sp;
|
||||
|
||||
*start = thread->stack_info.start;
|
||||
*end = thread->stack_info.start + thread->stack_info.size;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP)) {
|
||||
return;
|
||||
}
|
||||
|
||||
sp = arch_coredump_stack_ptr_get(thread);
|
||||
|
||||
if (IN_RANGE(sp, *start, *end)) {
|
||||
/* Skip ahead to the stack pointer. */
|
||||
*start = sp;
|
||||
}
|
||||
|
||||
/* Make sure no more than STACK_TOP_LIMIT bytes of the stack are dumped. */
|
||||
*end = *start + MIN((size_t)(*end - *start), STACK_TOP_LIMIT);
|
||||
}
|
||||
|
||||
static void dump_thread(struct k_thread *thread)
|
||||
{
|
||||
uintptr_t start_addr;
|
||||
uintptr_t end_addr;
|
||||
|
||||
/*
|
||||
|
@ -86,13 +118,12 @@ static void dump_thread(struct k_thread *thread)
|
|||
return;
|
||||
}
|
||||
|
||||
end_addr = POINTER_TO_UINT(thread) + sizeof(*thread);
|
||||
start_addr = POINTER_TO_UINT(thread);
|
||||
end_addr = start_addr + sizeof(*thread);
|
||||
coredump_memory_dump(start_addr, end_addr);
|
||||
|
||||
coredump_memory_dump(POINTER_TO_UINT(thread), end_addr);
|
||||
|
||||
end_addr = thread->stack_info.start + thread->stack_info.size;
|
||||
|
||||
coredump_memory_dump(thread->stack_info.start, end_addr);
|
||||
select_stack_region(thread, &start_addr, &end_addr);
|
||||
coredump_memory_dump(start_addr, end_addr);
|
||||
|
||||
#if defined(CONFIG_DEBUG_COREDUMP_DUMP_THREAD_PRIV_STACK)
|
||||
if ((thread->base.user_options & K_USER) == K_USER) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue