1 // Copyright (C) 2022 Beken Corporation
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 <string.h>
16 #include <stdint.h>
17 #include "boot.h"
18 #include "bk_arch.h"
19 #include "bk_uart.h"
20 #include <components/log.h>
21 #include <common/bk_assert.h>
22
23 #define STACK_DUMP_MEMORY 0
24 #define STACK_CALLBACK_BUF_SIZE 32
25
26 extern char __executable_start;
27 extern char __etext;
28 extern char _itcm_ema_start, _itcm_ema_end;
29
addr_is_in_flash_txt(uint32_t addr)30 static int addr_is_in_flash_txt(uint32_t addr)
31 {
32 return ((addr > 0x100) && (addr < (uint32_t)&__etext));
33 }
34
addr_is_in_itcm_txt(uint32_t addr)35 static int addr_is_in_itcm_txt(uint32_t addr)
36 {
37 return ((addr > (uint32_t)&_itcm_ema_start) && (addr < (uint32_t)&_itcm_ema_end));
38 }
39
code_addr_is_valid(uint32_t addr)40 static int code_addr_is_valid(uint32_t addr)
41 {
42 return (addr_is_in_flash_txt(addr) || addr_is_in_itcm_txt(addr));
43 }
44
stack_mem_dump(uint32_t stack_top,uint32_t stack_bottom)45 void stack_mem_dump(uint32_t stack_top, uint32_t stack_bottom)
46 {
47 unsigned char *data;
48 uint32_t cnt = 0;
49 uint32_t sp = stack_top;
50 uint32_t fp = stack_bottom;
51
52 BK_DUMP_OUT(">>>>stack mem dump begin, stack_top=%08x, stack end=%08x\r\n", stack_top, stack_bottom);
53 for (; sp < fp; sp += sizeof(size_t)) {
54 data = ((unsigned char *) sp);
55
56 if ((cnt++ & 0x7) == 0) {
57 BK_DUMP_OUT("\r\n");
58 }
59
60 BK_DUMP_OUT("%02x %02x %02x %02x ", data[0], data[1], data[2], data[3]);
61 }
62 BK_DUMP_OUT("\r\n");
63 BK_DUMP_OUT("<<<<stack mem dump end. stack_top=%08x, stack end=%08x\r\n", stack_top, stack_bottom);
64 BK_DUMP_OUT("\r\n");
65 }
66
67
68 /* The stack is grow from bottom to top
69 *
70 * | . | <- bottom, (big address) (x8 fp)
71 * | . |
72 * | . |
73 * | | <- top (x2 sp)
74 * | |
75 * | |
76 * | | <- minimum_addr = (bottom - stack_size)
77 *
78 * */
arch_parse_stack_backtrace(const char * str_type,uint32_t stack_top,uint32_t stack_bottom,uint32_t stack_size,bool thumb_mode)79 void arch_parse_stack_backtrace(const char *str_type, uint32_t stack_top, uint32_t stack_bottom,
80 uint32_t stack_size, bool thumb_mode)
81 {
82 uint32_t call_stack_buf[STACK_CALLBACK_BUF_SIZE] = {0};
83 uint32_t stack_minimum = stack_bottom - stack_size;
84 uint32_t pc;
85 int call_stack_index = 0;
86 uint32_t init_stack_top = stack_top;
87
88 #if STACK_DUMP_MEMORY
89 stack_mem_dump(stack_top, stack_bottom);
90 #endif
91 for (; stack_top < stack_bottom && (call_stack_index < STACK_CALLBACK_BUF_SIZE); stack_top += sizeof(size_t)) {
92 pc = *((uint32_t *) stack_top);
93
94 if (code_addr_is_valid(pc)) {
95 if (pc & 1)
96 pc = pc - 1;
97
98 call_stack_buf[call_stack_index] = pc;
99 call_stack_index++;
100 }
101 }
102
103 if (call_stack_index > 0) {
104 int index;
105
106 BK_DUMP_OUT("%-16s [0x%-6x ~ 0x%-6x] 0x%-6x %-4d %-8d ",
107 str_type, stack_minimum, stack_bottom, init_stack_top, stack_size, init_stack_top < stack_minimum);
108
109 for (index = 0; index < call_stack_index; index++)
110 BK_DUMP_OUT("%lx ", call_stack_buf[index]);
111 BK_DUMP_OUT("\r\n");
112 } else if (init_stack_top < stack_minimum) {
113 BK_DUMP_OUT("%-16s [0x%-6x ~ 0x%-6x] 0x%-6x %-4d %-8d ",
114 str_type, stack_minimum, stack_bottom, init_stack_top, stack_size, init_stack_top < stack_minimum);
115 }
116 }
117
118
119