Skip to content

Commit 9a28c93

Browse files
authored
Add support for custom panic handler (espressif#8711)
* Add support for custom panic handler * Resolve comments
1 parent e2487b1 commit 9a28c93

File tree

3 files changed

+107
-1
lines changed

3 files changed

+107
-1
lines changed

cores/esp32/esp32-hal-misc.c

+90
Original file line numberDiff line numberDiff line change
@@ -322,3 +322,93 @@ const char * ARDUINO_ISR_ATTR pathToFileName(const char * path)
322322
return path+pos;
323323
}
324324

325+
#include "esp_rom_sys.h"
326+
#include "esp_debug_helpers.h"
327+
#if CONFIG_IDF_TARGET_ARCH_XTENSA
328+
#include "esp_cpu_utils.h"
329+
#else
330+
#include "riscv/rvruntime-frames.h"
331+
#endif
332+
#include "esp_memory_utils.h"
333+
#include "esp_private/panic_internal.h"
334+
335+
static arduino_panic_handler_t _panic_handler = NULL;
336+
static void * _panic_handler_arg = NULL;
337+
338+
void set_arduino_panic_handler(arduino_panic_handler_t handler, void * arg){
339+
_panic_handler = handler;
340+
_panic_handler_arg = arg;
341+
}
342+
343+
arduino_panic_handler_t get_arduino_panic_handler(void){
344+
return _panic_handler;
345+
}
346+
347+
void * get_arduino_panic_handler_arg(void){
348+
return _panic_handler_arg;
349+
}
350+
351+
static void handle_custom_backtrace(panic_info_t* info){
352+
arduino_panic_info_t p_info;
353+
p_info.reason = info->reason;
354+
p_info.core = info->core;
355+
p_info.pc = info->addr;
356+
p_info.backtrace_len = 0;
357+
p_info.backtrace_corrupt = false;
358+
p_info.backtrace_continues = false;
359+
360+
#if CONFIG_IDF_TARGET_ARCH_XTENSA
361+
XtExcFrame *xt_frame = (XtExcFrame *) info->frame;
362+
esp_backtrace_frame_t stk_frame = {.pc = xt_frame->pc, .sp = xt_frame->a1, .next_pc = xt_frame->a0, .exc_frame = xt_frame};
363+
uint32_t i = 100, pc_ptr = esp_cpu_process_stack_pc(stk_frame.pc);
364+
p_info.backtrace[p_info.backtrace_len++] = pc_ptr;
365+
366+
bool corrupted = !(esp_stack_ptr_is_sane(stk_frame.sp) &&
367+
(esp_ptr_executable((void *)esp_cpu_process_stack_pc(stk_frame.pc)) ||
368+
/* Ignore the first corrupted PC in case of InstrFetchProhibited */
369+
(stk_frame.exc_frame && ((XtExcFrame *)stk_frame.exc_frame)->exccause == EXCCAUSE_INSTR_PROHIBITED)));
370+
371+
while (i-- > 0 && stk_frame.next_pc != 0 && !corrupted) {
372+
if (!esp_backtrace_get_next_frame(&stk_frame)) {
373+
corrupted = true;
374+
}
375+
pc_ptr = esp_cpu_process_stack_pc(stk_frame.pc);
376+
if(esp_ptr_executable((void *)pc_ptr)){
377+
p_info.backtrace[p_info.backtrace_len++] = pc_ptr;
378+
if(p_info.backtrace_len == 60){
379+
break;
380+
}
381+
}
382+
}
383+
384+
if (corrupted) {
385+
p_info.backtrace_corrupt = true;
386+
} else if (stk_frame.next_pc != 0) {
387+
p_info.backtrace_continues = true;
388+
}
389+
#elif CONFIG_IDF_TARGET_ARCH_RISCV
390+
uint32_t sp = (uint32_t)((RvExcFrame *)info->frame)->sp;
391+
p_info.backtrace[p_info.backtrace_len++] = sp;
392+
uint32_t *spptr = (uint32_t *)(sp);
393+
for (int i = 0; i < 256; i++){
394+
if(esp_ptr_executable((void *)spptr[i])){
395+
p_info.backtrace[p_info.backtrace_len++] = spptr[i];
396+
if(p_info.backtrace_len == 60){
397+
if(i < 255){
398+
p_info.backtrace_continues = true;
399+
}
400+
break;
401+
}
402+
}
403+
}
404+
#endif
405+
_panic_handler(&p_info, _panic_handler_arg);
406+
}
407+
408+
void __real_esp_panic_handler(panic_info_t*);
409+
void __wrap_esp_panic_handler(panic_info_t* info) {
410+
if(_panic_handler != NULL){
411+
handle_custom_backtrace(info);
412+
}
413+
__real_esp_panic_handler(info);
414+
}

cores/esp32/esp32-hal.h

+16
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,22 @@ void arduino_phy_init();
137137
void initArduino();
138138
#endif
139139

140+
typedef struct {
141+
int core; // core which triggered panic
142+
const char* reason; // exception string
143+
const void* pc; // instruction address that triggered the exception
144+
bool backtrace_corrupt; // if backtrace is corrupt
145+
bool backtrace_continues; // if backtrace continues, but did not fit
146+
unsigned int backtrace_len; // number of backtrace addresses
147+
unsigned int backtrace[60]; // backtrace addresses array
148+
} arduino_panic_info_t;
149+
150+
typedef void (*arduino_panic_handler_t)(arduino_panic_info_t * info, void * arg);
151+
152+
void set_arduino_panic_handler(arduino_panic_handler_t handler, void * arg);
153+
arduino_panic_handler_t get_arduino_panic_handler(void);
154+
void * get_arduino_panic_handler_arg(void);
155+
140156
#ifdef __cplusplus
141157
}
142158
#endif

platform.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ compiler.size.cmd={compiler.prefix}size
7070
compiler.c.extra_flags=-MMD -c
7171
compiler.cpp.extra_flags=-MMD -c
7272
compiler.S.extra_flags=-MMD -c -x assembler-with-cpp
73-
compiler.c.elf.extra_flags="-Wl,--Map={build.path}/{build.project_name}.map" "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.sdk.path}/{build.memory_type}"
73+
compiler.c.elf.extra_flags="-Wl,--Map={build.path}/{build.project_name}.map" "-L{compiler.sdk.path}/lib" "-L{compiler.sdk.path}/ld" "-L{compiler.sdk.path}/{build.memory_type}" "-Wl,--wrap=esp_panic_handler"
7474
compiler.ar.extra_flags=
7575
compiler.objcopy.eep.extra_flags=
7676
compiler.elf2hex.extra_flags=

0 commit comments

Comments
 (0)