1 /*
2 * Copyright lizhirui
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-05-18 lizhirui the first version
9 * 2021-05-20 lizhirui add os debug support
10 */
11
12 #include <rtthread.h>
13 #include "symbol_analysis.h"
14
15 #define MEMORY_BASE 0x40000000
16 #define MEMORY_SIZE (128 * 0x100000)
17
18 extern rt_size_t _osdebug_start;
19
20 static os_symtab_header *symtab_header = (os_symtab_header *)&_osdebug_start;
21
22 //该函数用于在指定的表中查找某个地址对应的符号的描述结构体指针,返回值的符号遵循规则详见文档
find_symbol_table(rt_size_t symbol_table_addr,rt_size_t symbol_num,rt_size_t address)23 os_symtab_item *find_symbol_table(rt_size_t symbol_table_addr,rt_size_t symbol_num,rt_size_t address)
24 {
25 rt_size_t left = 0;
26 rt_size_t right = symbol_num;
27 os_symtab_item *sym_table = (os_symtab_item *)((rt_size_t)&_osdebug_start + symbol_table_addr);
28
29 while(left < right)
30 {
31 rt_size_t mid = (left + right) >> 1;
32 //rt_kprintf("left = %d,right = %d,mid = %d\n",left,right,mid);
33
34 if(address < sym_table[mid].address)
35 {
36 right = mid;
37
38 while((right < symbol_num) && ((right - 1) >= 0) && (sym_table[right].address == sym_table[right - 1].address))
39 {
40 right--;
41 }
42 }
43 else if(address == sym_table[mid].address)
44 {
45 left = mid + 1;
46 break;
47 }
48 else
49 {
50 left = mid;
51
52 while((left >= 0) && ((left + 1) < symbol_num) && (sym_table[left].address == sym_table[left + 1].address))
53 {
54 left++;
55 }
56
57 left++;
58 }
59 }
60
61 left--;
62
63 if(left == ((rt_size_t)-1))
64 {
65 return RT_NULL;
66 }
67
68 while((left < symbol_num) && ((left - 1) >= 0) && (sym_table[left].address == sym_table[left - 1].address))
69 {
70 left--;
71 }
72
73 return &sym_table[left];
74 }
75
76 //该函数用于根据给定的符号指针从字符串表中找到对应的符号名指针并返回
get_symbol_name(os_symtab_item * symbol)77 const char *get_symbol_name(os_symtab_item *symbol)
78 {
79 return (const char *)((rt_size_t)&_osdebug_start + symtab_header -> string_table_offset + symbol -> name_offset);
80 }
81
82 //该函数可以根据给定的符号和地址向中断打印出标准格式的符号信息
print_symbol(os_symtab_item * symbol,rt_size_t address)83 void print_symbol(os_symtab_item *symbol,rt_size_t address)
84 {
85 rt_kprintf("<%s(0x%p)",get_symbol_name(symbol),symbol -> address);
86
87 if(symbol -> size)
88 {
89 rt_kprintf(" : 0x%x>",symbol -> size);
90 }
91 else
92 {
93 rt_kprintf(">");
94 }
95
96 if(address > symbol -> address)
97 {
98 rt_kprintf(" + 0x%x",address - symbol -> address);
99 }
100 }
101
102 //该函数用于打印出一个地址关联的全部符号信息
print_symbol_info(rt_size_t address,rt_bool_t function)103 void print_symbol_info(rt_size_t address,rt_bool_t function)
104 {
105 os_symtab_item *function_symbol = find_symbol_table(symtab_header -> function_table_offset,symtab_header -> function_table_num,address);
106 os_symtab_item *object_symbol = find_symbol_table(symtab_header -> object_table_offset,symtab_header -> object_table_num,address);
107 os_symtab_item *general_symbol = find_symbol_table(symtab_header -> general_symbol_table_offset,symtab_header -> general_symbol_table_num,address);
108 const char *dot = "";
109 rt_bool_t valid = RT_FALSE;
110
111 if(function)
112 {
113 while(function_symbol != RT_NULL)
114 {
115 if((function_symbol -> address + function_symbol -> size) > address)
116 {
117 rt_kprintf(dot);
118 print_symbol(function_symbol,address);
119 dot = ",";
120 valid = RT_TRUE;
121 }
122
123 if(((rt_size_t)(function_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> function_table_offset + symtab_header -> function_table_num * sizeof(os_symtab_item)))
124 {
125 break;
126 }
127
128 if(function_symbol[0].address == function_symbol[1].address)
129 {
130 function_symbol++;
131 }
132
133 break;
134 }
135
136 if(!valid)
137 {
138 while(general_symbol != RT_NULL)
139 {
140 rt_kprintf(dot);
141 print_symbol(general_symbol,address);
142 dot = ",";
143 valid = RT_TRUE;
144
145 if(((rt_size_t)(general_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> general_symbol_table_offset + symtab_header -> general_symbol_table_num * sizeof(os_symtab_item)))
146 {
147 break;
148 }
149
150 if(general_symbol[0].address == general_symbol[1].address)
151 {
152 general_symbol++;
153 }
154
155 break;
156 }
157
158 while(object_symbol != RT_NULL)
159 {
160 if((object_symbol -> address + object_symbol -> size) > address)
161 {
162 rt_kprintf(dot);
163 print_symbol(object_symbol,address);
164 dot = ",";
165 valid = RT_TRUE;
166 }
167
168 if(((rt_size_t)(object_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> object_table_offset + symtab_header -> object_table_num * sizeof(os_symtab_item)))
169 {
170 break;
171 }
172
173 if(object_symbol[0].address == object_symbol[1].address)
174 {
175 object_symbol++;
176 }
177
178 break;
179 }
180 }
181 }
182 else
183 {
184 while(object_symbol != RT_NULL)
185 {
186 if((object_symbol -> address + object_symbol -> size) > address)
187 {
188 rt_kprintf(dot);
189 print_symbol(object_symbol,address);
190 dot = ",";
191 valid = RT_TRUE;
192 }
193
194 if(((rt_size_t)(object_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> object_table_offset + symtab_header -> object_table_num * sizeof(os_symtab_item)))
195 {
196 break;
197 }
198
199 if(object_symbol[0].address == object_symbol[1].address)
200 {
201 object_symbol++;
202 }
203
204 break;
205 }
206
207 if(!valid)
208 {
209 while(general_symbol != RT_NULL)
210 {
211 rt_kprintf(dot);
212 print_symbol(general_symbol,address);
213 dot = ",";
214 valid = RT_TRUE;
215
216 if(((rt_size_t)(general_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> general_symbol_table_offset + symtab_header -> general_symbol_table_num * sizeof(os_symtab_item)))
217 {
218 break;
219 }
220
221 if(general_symbol[0].address == general_symbol[1].address)
222 {
223 general_symbol++;
224 }
225
226 break;
227 }
228
229 while(function_symbol != RT_NULL)
230 {
231 if((function_symbol -> address + function_symbol -> size) > address)
232 {
233 rt_kprintf(dot);
234 print_symbol(function_symbol,address);
235 dot = ",";
236 valid = RT_TRUE;
237 }
238
239 if(((rt_size_t)(function_symbol + 1)) >= (((rt_size_t)&_osdebug_start) + symtab_header -> function_table_offset + symtab_header -> function_table_num * sizeof(os_symtab_item)))
240 {
241 break;
242 }
243
244 if(function_symbol[0].address == function_symbol[1].address)
245 {
246 function_symbol++;
247 }
248
249 break;
250 }
251 }
252 }
253
254 if(dot == "")
255 {
256 rt_kprintf("<Unknown Symbol>");
257 }
258 }
259
260 //该函数用于在出错时打印出栈跟踪信息
print_stacktrace(rt_size_t epc,rt_size_t fp)261 void print_stacktrace(rt_size_t epc,rt_size_t fp)
262 {
263 rt_kprintf("-----------------------------Dump Stacktrace----------------------------\n\n");
264 rt_size_t sp = fp;
265 rt_size_t i = 0;
266
267 rt_kprintf("address 0x%p(",epc);
268 print_symbol_info(epc,RT_TRUE);
269 rt_kprintf(")\n\n");
270
271 while(1)
272 {
273 if((sp >= MEMORY_BASE) && (sp < (MEMORY_BASE + MEMORY_SIZE)))
274 {
275 //rt_kprintf("%d: 0x%p\n",i,sp);
276 rt_size_t *stack = (rt_size_t *)(sp - sizeof(rt_size_t) * 2);
277 rt_size_t ra = stack[1];
278
279 if(!ra)
280 {
281 break;
282 }
283
284 rt_kprintf("return to 0x%p(",ra);
285 print_symbol_info(ra,RT_TRUE);
286 rt_kprintf(")\n\n");
287 //rt_kprintf("ra = 0x%p,fp = 0x%p\n",stack[1],stack[0]);
288 sp = stack[0];
289 i++;
290 }
291 else
292 {
293 break;
294 }
295 }
296
297 rt_kprintf("---------------------------------Dump OK--------------------------------\n");
298 }
299