Skip to content

Commit 222e0fc

Browse files
Damian-Nordickartben
authored andcommitted
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 <[email protected]>
1 parent 40c75b7 commit 222e0fc

File tree

6 files changed

+82
-7
lines changed

6 files changed

+82
-7
lines changed

arch/Kconfig

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ config ARM
3333
select ARCH_IS_SET
3434
select ARCH_SUPPORTS_COREDUMP if CPU_CORTEX_M
3535
select ARCH_SUPPORTS_COREDUMP_THREADS if CPU_CORTEX_M
36+
select ARCH_SUPPORTS_COREDUMP_STACK_PTR if CPU_CORTEX_M
3637
# FIXME: current state of the code for all ARM requires this, but
3738
# is really only necessary for Cortex-M with ARM MPU!
3839
select GEN_PRIV_STACKS
@@ -705,6 +706,9 @@ config ARCH_SUPPORTS_COREDUMP_THREADS
705706
config ARCH_SUPPORTS_COREDUMP_PRIV_STACKS
706707
bool
707708

709+
config ARCH_SUPPORTS_COREDUMP_STACK_PTR
710+
bool
711+
708712
config ARCH_SUPPORTS_ARCH_HW_INIT
709713
bool
710714

arch/arm/core/cortex_m/coredump.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
#include <string.h>
88
#include <zephyr/debug/coredump.h>
9+
#include <zephyr/kernel/thread.h>
910

1011
#define ARCH_HDR_VER 2
1112

@@ -96,3 +97,8 @@ uint16_t arch_coredump_tgt_code_get(void)
9697
{
9798
return COREDUMP_TGT_ARM_CORTEX_M;
9899
}
100+
101+
uintptr_t arch_coredump_stack_ptr_get(const struct k_thread *thread)
102+
{
103+
return (thread == _current) ? z_arm_coredump_fault_sp : thread->callee_saved.psp;
104+
}

doc/releases/release-notes-4.2.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,12 @@ New APIs and options
226226

227227
* :kconfig:option:`CONFIG_NVME_PRP_PAGE_SIZE`
228228

229+
* Debug
230+
231+
* Core Dump
232+
233+
* :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.
234+
229235
* Other
230236

231237
* :kconfig:option:`CONFIG_LV_Z_COLOR_MONO_HW_INVERSION`

kernel/include/kernel_arch_interface.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -638,6 +638,11 @@ void arch_coredump_info_dump(const struct arch_esf *esf);
638638
*/
639639
uint16_t arch_coredump_tgt_code_get(void);
640640

641+
/**
642+
* @brief Get the stack pointer of the thread.
643+
*/
644+
uintptr_t arch_coredump_stack_ptr_get(const struct k_thread *thread);
645+
641646
#if defined(CONFIG_USERSPACE) || defined(__DOXYGEN__)
642647

643648
/**

subsys/debug/coredump/Kconfig

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,27 @@ module = DEBUG_COREDUMP
144144
module-str = coredump
145145
source "subsys/logging/Kconfig.template.log_config"
146146

147+
config DEBUG_COREDUMP_THREAD_STACK_TOP
148+
bool "Dump top of stack only"
149+
default y if DEBUG_COREDUMP_MEMORY_DUMP_MIN
150+
depends on DEBUG_COREDUMP_MEMORY_DUMP_MIN || \
151+
DEBUG_COREDUMP_MEMORY_DUMP_THREADS
152+
depends on ARCH_SUPPORTS_COREDUMP_STACK_PTR
153+
help
154+
This option enables dumping only the top portion of each thread's
155+
stack, rather than the entire stack region. The top of the stack is
156+
defined as the area from the stack pointer to the stack end, but the
157+
size of this region can additionally be constrained using the
158+
DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT option.
159+
160+
config DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT
161+
int "Stack top size limit"
162+
default -1
163+
depends on DEBUG_COREDUMP_THREAD_STACK_TOP
164+
help
165+
See the description of the DEBUG_COREDUMP_THREAD_STACK_TOP option.
166+
The value -1 indicates that there is no limit, meaning that the stack
167+
is dumped till the end of its region.
168+
169+
147170
endif # DEBUG_COREDUMP

subsys/debug/coredump/coredump_core.c

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ static struct coredump_backend_api
4141
#define DT_DRV_COMPAT zephyr_coredump
4242
#endif
4343

44+
#if defined(CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT) && \
45+
CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT > 0
46+
#define STACK_TOP_LIMIT ((size_t)CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT)
47+
#else
48+
#define STACK_TOP_LIMIT SIZE_MAX
49+
#endif
50+
4451
#if defined(CONFIG_DEBUG_COREDUMP_DUMP_THREAD_PRIV_STACK)
4552
__weak void arch_coredump_priv_stack_dump(struct k_thread *thread)
4653
{
@@ -70,10 +77,35 @@ static void dump_header(unsigned int reason)
7077
backend_api->buffer_output((uint8_t *)&hdr, sizeof(hdr));
7178
}
7279

73-
#if defined(CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN) || \
80+
#if defined(CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN) || \
7481
defined(CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_THREADS)
82+
83+
static inline void select_stack_region(const struct k_thread *thread, uintptr_t *start,
84+
uintptr_t *end)
85+
{
86+
uintptr_t sp;
87+
88+
*start = thread->stack_info.start;
89+
*end = thread->stack_info.start + thread->stack_info.size;
90+
91+
if (!IS_ENABLED(CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP)) {
92+
return;
93+
}
94+
95+
sp = arch_coredump_stack_ptr_get(thread);
96+
97+
if (IN_RANGE(sp, *start, *end)) {
98+
/* Skip ahead to the stack pointer. */
99+
*start = sp;
100+
}
101+
102+
/* Make sure no more than STACK_TOP_LIMIT bytes of the stack are dumped. */
103+
*end = *start + MIN((size_t)(*end - *start), STACK_TOP_LIMIT);
104+
}
105+
75106
static void dump_thread(struct k_thread *thread)
76107
{
108+
uintptr_t start_addr;
77109
uintptr_t end_addr;
78110

79111
/*
@@ -86,13 +118,12 @@ static void dump_thread(struct k_thread *thread)
86118
return;
87119
}
88120

89-
end_addr = POINTER_TO_UINT(thread) + sizeof(*thread);
90-
91-
coredump_memory_dump(POINTER_TO_UINT(thread), end_addr);
92-
93-
end_addr = thread->stack_info.start + thread->stack_info.size;
121+
start_addr = POINTER_TO_UINT(thread);
122+
end_addr = start_addr + sizeof(*thread);
123+
coredump_memory_dump(start_addr, end_addr);
94124

95-
coredump_memory_dump(thread->stack_info.start, end_addr);
125+
select_stack_region(thread, &start_addr, &end_addr);
126+
coredump_memory_dump(start_addr, end_addr);
96127

97128
#if defined(CONFIG_DEBUG_COREDUMP_DUMP_THREAD_PRIV_STACK)
98129
if ((thread->base.user_options & K_USER) == K_USER) {

0 commit comments

Comments
 (0)