/ components / xtensa / debug_helpers.c
debug_helpers.c
 1  // Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
 2  //
 3  // Licensed under the Apache License, Version 2.0 (the "License");
 4  // you may not use this file except in compliance with the License.
 5  // You may obtain a copy of the License at
 6  
 7  //     http://www.apache.org/licenses/LICENSE-2.0
 8  //
 9  // Unless required by applicable law or agreed to in writing, software
10  // distributed under the License is distributed on an "AS IS" BASIS,
11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  // See the License for the specific language governing permissions and
13  // limitations under the License.
14  
15  #include "sdkconfig.h"
16  #include "esp_types.h"
17  #include "esp_attr.h"
18  #include "esp_err.h"
19  #include "esp_debug_helpers.h"
20  #include "soc/soc_memory_layout.h"
21  #include "soc/cpu.h"
22  
23  #include "sdkconfig.h"
24  
25  #include "esp_rom_sys.h"
26  
27  bool IRAM_ATTR esp_backtrace_get_next_frame(esp_backtrace_frame_t *frame)
28  {
29      //Use frame(i-1)'s BS area located below frame(i)'s sp to get frame(i-1)'s sp and frame(i-2)'s pc
30      void *base_save = (void *)frame->sp;     //Base save area consists of 4 words under SP
31      frame->pc = frame->next_pc;
32      frame->next_pc = *((uint32_t *)(base_save - 16));     //If next_pc = 0, indicates frame(i-1) is the last frame on the stack
33      frame->sp =  *((uint32_t *)(base_save - 12));
34  
35      //Return true if both sp and pc of frame(i-1) are sane, false otherwise
36      return (esp_stack_ptr_is_sane(frame->sp) && esp_ptr_executable((void*)esp_cpu_process_stack_pc(frame->pc)));
37  }
38  
39  esp_err_t IRAM_ATTR esp_backtrace_print(int depth)
40  {
41      //Check arguments
42      if (depth <= 0) {
43          return ESP_ERR_INVALID_ARG;
44      }
45  
46      //Initialize stk_frame with first frame of stack
47      esp_backtrace_frame_t stk_frame;
48      esp_backtrace_get_start(&(stk_frame.pc), &(stk_frame.sp), &(stk_frame.next_pc));
49      //esp_cpu_get_backtrace_start(&stk_frame);
50      esp_rom_printf("\r\n\r\nBacktrace:");
51      esp_rom_printf("0x%08X:0x%08X ", esp_cpu_process_stack_pc(stk_frame.pc), stk_frame.sp);
52  
53      //Check if first frame is valid
54      bool corrupted = (esp_stack_ptr_is_sane(stk_frame.sp) &&
55                        esp_ptr_executable((void*)esp_cpu_process_stack_pc(stk_frame.pc))) ?
56                        false : true;
57  
58      uint32_t i = (depth <= 0) ? INT32_MAX : depth;
59      while (i-- > 0 && stk_frame.next_pc != 0 && !corrupted) {
60          if (!esp_backtrace_get_next_frame(&stk_frame)) {    //Get previous stack frame
61              corrupted = true;
62          }
63          esp_rom_printf("0x%08X:0x%08X ", esp_cpu_process_stack_pc(stk_frame.pc), stk_frame.sp);
64      }
65  
66      //Print backtrace termination marker
67      esp_err_t ret = ESP_OK;
68      if (corrupted) {
69          esp_rom_printf(" |<-CORRUPTED");
70          ret =  ESP_FAIL;
71      } else if (stk_frame.next_pc != 0) {    //Backtrace continues
72          esp_rom_printf(" |<-CONTINUES");
73      }
74      esp_rom_printf("\r\n\r\n");
75      return ret;
76  }