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