Skip to content

Commit 6402a58

Browse files
Damian-Nordicnashif
authored andcommitted
debug: coredump: stack top limit for current thread
Extend the functionality to limit the number of stack bytes included in the core dump by allowing the limit to be different for the current thread and remaining threads. This is useful because it is more likely that we need more call frames of the thread that was running when the exception occurred than of the other threads in order to analyze the exception. Signed-off-by: Damian Krolik <[email protected]>
1 parent a0045c5 commit 6402a58

File tree

2 files changed

+46
-23
lines changed

2 files changed

+46
-23
lines changed

subsys/debug/coredump/Kconfig

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -151,20 +151,33 @@ config DEBUG_COREDUMP_THREAD_STACK_TOP
151151
DEBUG_COREDUMP_MEMORY_DUMP_THREADS
152152
depends on ARCH_SUPPORTS_COREDUMP_STACK_PTR
153153
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.
154+
Dump only the top part of each thread's stack instead of the entire
155+
stack region. The top of the stack is defined as the area starting
156+
from the stack pointer and extending up to the smaller of the stack
157+
end or the limit configured by either
158+
DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT_FOR_CURRENT (for the current
159+
thread) or DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT (for remaining ones).
160+
161+
if DEBUG_COREDUMP_THREAD_STACK_TOP
162+
163+
config DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT_FOR_CURRENT
164+
int "Stack top size limit for current thread"
165+
default DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT
166+
help
167+
The maximum number of stack bytes to be dumped for the thread running
168+
when the exception occurred.
169+
A negative value indicates that there is no limit, meaning that the
170+
stack is dumped till the end of its region.
159171

160172
config DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT
161-
int "Stack top size limit"
173+
int "Stack top size limit for non-current threads"
162174
default -1
163-
depends on DEBUG_COREDUMP_THREAD_STACK_TOP
164175
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.
176+
The maximum number of stack bytes to be dumped for threads that were
177+
not running when the exception occurred.
178+
A negative value indicates that there is no limit, meaning that the
179+
stack is dumped till the end of its region.
168180

181+
endif # DEBUG_COREDUMP_THREAD_STACK_TOP
169182

170183
endif # DEBUG_COREDUMP

subsys/debug/coredump/coredump_core.c

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,16 @@ 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_FOR_CURRENT) && \
45+
CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT_FOR_CURRENT >= 0
46+
#define STACK_TOP_LIMIT_FOR_CURRENT \
47+
((size_t)CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT_FOR_CURRENT)
48+
#else
49+
#define STACK_TOP_LIMIT_FOR_CURRENT SIZE_MAX
50+
#endif
51+
4452
#if defined(CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT) && \
45-
CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT > 0
53+
CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT >= 0
4654
#define STACK_TOP_LIMIT ((size_t)CONFIG_DEBUG_COREDUMP_THREAD_STACK_TOP_LIMIT)
4755
#else
4856
#define STACK_TOP_LIMIT SIZE_MAX
@@ -80,10 +88,11 @@ static void dump_header(unsigned int reason)
8088
#if defined(CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN) || \
8189
defined(CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_THREADS)
8290

83-
static inline void select_stack_region(const struct k_thread *thread, uintptr_t *start,
84-
uintptr_t *end)
91+
static inline void select_stack_region(const struct k_thread *thread, bool is_current,
92+
uintptr_t *start, uintptr_t *end)
8593
{
8694
uintptr_t sp;
95+
size_t limit;
8796

8897
*start = thread->stack_info.start;
8998
*end = thread->stack_info.start + thread->stack_info.size;
@@ -99,11 +108,12 @@ static inline void select_stack_region(const struct k_thread *thread, uintptr_t
99108
*start = sp;
100109
}
101110

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);
111+
/* Make sure no more than STACK_TOP_LIMIT[_FOR_CURRENT] bytes of the stack are dumped. */
112+
limit = (is_current ? STACK_TOP_LIMIT_FOR_CURRENT : STACK_TOP_LIMIT);
113+
*end = *start + MIN((size_t)(*end - *start), limit);
104114
}
105115

106-
static void dump_thread(struct k_thread *thread)
116+
static void dump_thread(struct k_thread *thread, bool is_current)
107117
{
108118
uintptr_t start_addr;
109119
uintptr_t end_addr;
@@ -122,7 +132,7 @@ static void dump_thread(struct k_thread *thread)
122132
end_addr = start_addr + sizeof(*thread);
123133
coredump_memory_dump(start_addr, end_addr);
124134

125-
select_stack_region(thread, &start_addr, &end_addr);
135+
select_stack_region(thread, is_current, &start_addr, &end_addr);
126136
coredump_memory_dump(start_addr, end_addr);
127137

128138
#if defined(CONFIG_DEBUG_COREDUMP_DUMP_THREAD_PRIV_STACK)
@@ -140,7 +150,7 @@ static void process_coredump_dev_memory(const struct device *dev)
140150
}
141151
#endif
142152

143-
void process_memory_region_list(void)
153+
void process_memory_region_list(struct k_thread *current)
144154
{
145155
#ifdef CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_LINKER_RAM
146156
unsigned int idx = 0;
@@ -164,10 +174,10 @@ void process_memory_region_list(void)
164174
* Content of _kernel.threads not being modified during dump
165175
* capture so no need to lock z_thread_monitor_lock.
166176
*/
167-
struct k_thread *current;
177+
struct k_thread *thread;
168178

169-
for (current = _kernel.threads; current; current = current->next_thread) {
170-
dump_thread(current);
179+
for (thread = _kernel.threads; thread; thread = thread->next_thread) {
180+
dump_thread(thread, thread == current);
171181
}
172182

173183
/* Also add interrupt stack, in case error occurred in an interrupt */
@@ -216,11 +226,11 @@ void coredump(unsigned int reason, const struct arch_esf *esf,
216226

217227
if (thread != NULL) {
218228
#ifdef CONFIG_DEBUG_COREDUMP_MEMORY_DUMP_MIN
219-
dump_thread(thread);
229+
dump_thread(thread, /* is_current */ true);
220230
#endif
221231
}
222232

223-
process_memory_region_list();
233+
process_memory_region_list(thread);
224234

225235
z_coredump_end();
226236
}

0 commit comments

Comments
 (0)