Skip to content

Add support for custom panic handler #8711

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Oct 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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