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 }