@@ -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+ }
0 commit comments