Skip to content

Commit

Permalink
Add support for custom panic handler (#8711)
Browse files Browse the repository at this point in the history
* Add support for custom panic handler

* Resolve comments
  • Loading branch information
me-no-dev authored Oct 6, 2023
1 parent e2487b1 commit 9a28c93
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 1 deletion.
90 changes: 90 additions & 0 deletions cores/esp32/esp32-hal-misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -322,3 +322,93 @@ const char * ARDUINO_ISR_ATTR pathToFileName(const char * path)
return path+pos;
}

#include "esp_rom_sys.h"
#include "esp_debug_helpers.h"
#if CONFIG_IDF_TARGET_ARCH_XTENSA
#include "esp_cpu_utils.h"
#else
#include "riscv/rvruntime-frames.h"
#endif
#include "esp_memory_utils.h"
#include "esp_private/panic_internal.h"

static arduino_panic_handler_t _panic_handler = NULL;
static void * _panic_handler_arg = NULL;

void set_arduino_panic_handler(arduino_panic_handler_t handler, void * arg){
_panic_handler = handler;
_panic_handler_arg = arg;
}

arduino_panic_handler_t get_arduino_panic_handler(void){
return _panic_handler;
}

void * get_arduino_panic_handler_arg(void){
return _panic_handler_arg;
}

static void handle_custom_backtrace(panic_info_t* info){
arduino_panic_info_t p_info;
p_info.reason = info->reason;
p_info.core = info->core;
p_info.pc = info->addr;
p_info.backtrace_len = 0;
p_info.backtrace_corrupt = false;
p_info.backtrace_continues = false;

#if CONFIG_IDF_TARGET_ARCH_XTENSA
XtExcFrame *xt_frame = (XtExcFrame *) info->frame;
esp_backtrace_frame_t stk_frame = {.pc = xt_frame->pc, .sp = xt_frame->a1, .next_pc = xt_frame->a0, .exc_frame = xt_frame};
uint32_t i = 100, pc_ptr = esp_cpu_process_stack_pc(stk_frame.pc);
p_info.backtrace[p_info.backtrace_len++] = pc_ptr;

bool corrupted = !(esp_stack_ptr_is_sane(stk_frame.sp) &&
(esp_ptr_executable((void *)esp_cpu_process_stack_pc(stk_frame.pc)) ||
/* Ignore the first corrupted PC in case of InstrFetchProhibited */
(stk_frame.exc_frame && ((XtExcFrame *)stk_frame.exc_frame)->exccause == EXCCAUSE_INSTR_PROHIBITED)));

while (i-- > 0 && stk_frame.next_pc != 0 && !corrupted) {
if (!esp_backtrace_get_next_frame(&stk_frame)) {
corrupted = true;
}
pc_ptr = esp_cpu_process_stack_pc(stk_frame.pc);
if(esp_ptr_executable((void *)pc_ptr)){
p_info.backtrace[p_info.backtrace_len++] = pc_ptr;
if(p_info.backtrace_len == 60){
break;
}
}
}

if (corrupted) {
p_info.backtrace_corrupt = true;
} else if (stk_frame.next_pc != 0) {
p_info.backtrace_continues = true;
}
#elif CONFIG_IDF_TARGET_ARCH_RISCV
uint32_t sp = (uint32_t)((RvExcFrame *)info->frame)->sp;
p_info.backtrace[p_info.backtrace_len++] = sp;
uint32_t *spptr = (uint32_t *)(sp);
for (int i = 0; i < 256; i++){
if(esp_ptr_executable((void *)spptr[i])){
p_info.backtrace[p_info.backtrace_len++] = spptr[i];
if(p_info.backtrace_len == 60){
if(i < 255){
p_info.backtrace_continues = true;
}
break;
}
}
}
#endif
_panic_handler(&p_info, _panic_handler_arg);
}

void __real_esp_panic_handler(panic_info_t*);
void __wrap_esp_panic_handler(panic_info_t* info) {
if(_panic_handler != NULL){
handle_custom_backtrace(info);
}
__real_esp_panic_handler(info);
}
16 changes: 16 additions & 0 deletions cores/esp32/esp32-hal.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,22 @@ void arduino_phy_init();
void initArduino();
#endif

typedef struct {
int core; // core which triggered panic
const char* reason; // exception string
const void* pc; // instruction address that triggered the exception
bool backtrace_corrupt; // if backtrace is corrupt
bool backtrace_continues; // if backtrace continues, but did not fit
unsigned int backtrace_len; // number of backtrace addresses
unsigned int backtrace[60]; // backtrace addresses array
} arduino_panic_info_t;

typedef void (*arduino_panic_handler_t)(arduino_panic_info_t * info, void * arg);

void set_arduino_panic_handler(arduino_panic_handler_t handler, void * arg);
arduino_panic_handler_t get_arduino_panic_handler(void);
void * get_arduino_panic_handler_arg(void);

#ifdef __cplusplus
}
#endif
Expand Down
2 changes: 1 addition & 1 deletion platform.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ compiler.size.cmd={compiler.prefix}size
compiler.c.extra_flags=-MMD -c
compiler.cpp.extra_flags=-MMD -c
compiler.S.extra_flags=-MMD -c -x assembler-with-cpp
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}"
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"
compiler.ar.extra_flags=
compiler.objcopy.eep.extra_flags=
compiler.elf2hex.extra_flags=
Expand Down

0 comments on commit 9a28c93

Please sign in to comment.