symbol_analysis.c 8.6 KB

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