• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
esp_backtrace_get_next_frame(esp_backtrace_frame_t * frame)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 
esp_backtrace_print(int depth)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 }
77