core_dump_common.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. // Copyright 2015-2016 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. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include <string.h>
  14. #include <stdbool.h>
  15. #include "rom/crc.h"
  16. #include "esp_panic.h"
  17. #include "esp_partition.h"
  18. #include "esp_core_dump_priv.h"
  19. const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_common";
  20. #if CONFIG_ESP32_ENABLE_COREDUMP
  21. static esp_err_t esp_core_dump_write_binary(void *frame, core_dump_write_config_t *write_cfg)
  22. {
  23. esp_err_t err;
  24. core_dump_task_header_t tasks[CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM];
  25. uint32_t tcb_sz, task_num, tcb_sz_padded;
  26. bool task_is_valid = false;
  27. uint32_t data_len = 0, i;
  28. union
  29. {
  30. core_dump_header_t hdr;
  31. core_dump_task_header_t task_hdr;
  32. } dump_data;
  33. task_num = esp_core_dump_get_tasks_snapshot(tasks, CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM, &tcb_sz);
  34. ESP_COREDUMP_LOGI("Found tasks: (%d)!", task_num);
  35. // Take TCB padding into account, actual TCB size will be stored in header
  36. if (tcb_sz % sizeof(uint32_t))
  37. tcb_sz_padded = (tcb_sz / sizeof(uint32_t) + 1) * sizeof(uint32_t);
  38. else
  39. tcb_sz_padded = tcb_sz;
  40. // Verifies all tasks in the snapshot
  41. for (i = 0; i < task_num; i++) {
  42. task_is_valid = esp_core_dump_process_tcb(frame, &tasks[i], tcb_sz);
  43. // Check if task tcb is corrupted
  44. if (!task_is_valid) {
  45. write_cfg->bad_tasks_num++;
  46. continue;
  47. } else {
  48. data_len += (tcb_sz_padded + sizeof(core_dump_task_header_t));
  49. }
  50. uint32_t len = 0;
  51. task_is_valid = esp_core_dump_process_stack(&tasks[i], &len);
  52. if (task_is_valid) {
  53. // Increase core dump size by task stack size
  54. data_len += len;
  55. } else {
  56. // If task tcb is ok but stack is corrupted
  57. write_cfg->bad_tasks_num++;
  58. }
  59. }
  60. // Add core dump header size
  61. data_len += sizeof(core_dump_header_t);
  62. ESP_COREDUMP_LOG_PROCESS("Core dump len = %lu (%d %d)", data_len, task_num, write_cfg->bad_tasks_num);
  63. // Prepare write
  64. if (write_cfg->prepare) {
  65. err = write_cfg->prepare(write_cfg->priv, &data_len);
  66. if (err != ESP_OK) {
  67. ESP_COREDUMP_LOGE("Failed to prepare core dump (%d)!", err);
  68. return err;
  69. }
  70. }
  71. // Write start
  72. if (write_cfg->start) {
  73. err = write_cfg->start(write_cfg->priv);
  74. if (err != ESP_OK) {
  75. ESP_COREDUMP_LOGE("Failed to start core dump (%d)!", err);
  76. return err;
  77. }
  78. }
  79. // Write header
  80. dump_data.hdr.data_len = data_len;
  81. dump_data.hdr.version = COREDUMP_VERSION;
  82. dump_data.hdr.tasks_num = task_num - write_cfg->bad_tasks_num;
  83. dump_data.hdr.tcb_sz = tcb_sz;
  84. err = write_cfg->write(write_cfg->priv, &dump_data, sizeof(core_dump_header_t));
  85. if (err != ESP_OK) {
  86. ESP_COREDUMP_LOGE("Failed to write core dump header (%d)!", err);
  87. return err;
  88. }
  89. // Write tasks
  90. for (i = 0; i < task_num; i++) {
  91. if (!esp_tcb_addr_is_sane((uint32_t)tasks[i].tcb_addr, tcb_sz)) {
  92. ESP_COREDUMP_LOG_PROCESS("Skip TCB with bad addr %x!", tasks[i].tcb_addr);
  93. continue;
  94. }
  95. ESP_COREDUMP_LOG_PROCESS("Dump task %x", tasks[i].tcb_addr);
  96. // Save TCB address, stack base and stack top addr
  97. dump_data.task_hdr.tcb_addr = tasks[i].tcb_addr;
  98. dump_data.task_hdr.stack_start = tasks[i].stack_start;
  99. dump_data.task_hdr.stack_end = tasks[i].stack_end;
  100. err = write_cfg->write(write_cfg->priv, (void*)&dump_data, sizeof(core_dump_task_header_t));
  101. if (err != ESP_OK) {
  102. ESP_COREDUMP_LOGE("Failed to write task header (%d)!", err);
  103. return err;
  104. }
  105. // Save TCB
  106. err = write_cfg->write(write_cfg->priv, tasks[i].tcb_addr, tcb_sz);
  107. if (err != ESP_OK) {
  108. ESP_COREDUMP_LOGE("Failed to write TCB (%d)!", err);
  109. return err;
  110. }
  111. // Save task stack
  112. if (tasks[i].stack_start != 0 && tasks[i].stack_end != 0) {
  113. err = write_cfg->write(write_cfg->priv, (void*)tasks[i].stack_start,
  114. tasks[i].stack_end - tasks[i].stack_start);
  115. if (err != ESP_OK) {
  116. ESP_COREDUMP_LOGE("Failed to write task stack (%d)!", err);
  117. return err;
  118. }
  119. } else {
  120. ESP_COREDUMP_LOG_PROCESS("Skip corrupted task %x stack!", tasks[i].tcb_addr);
  121. }
  122. }
  123. // write end
  124. if (write_cfg->end) {
  125. err = write_cfg->end(write_cfg->priv);
  126. if (err != ESP_OK) {
  127. ESP_COREDUMP_LOGE("Failed to end core dump (%d)!", err);
  128. return err;
  129. }
  130. }
  131. if (write_cfg->bad_tasks_num) {
  132. ESP_COREDUMP_LOGE("Skipped %d tasks with bad TCB!", write_cfg->bad_tasks_num);
  133. }
  134. return err;
  135. }
  136. inline void esp_core_dump_write(void *frame, core_dump_write_config_t *write_cfg)
  137. {
  138. esp_err_t err = esp_core_dump_write_binary(frame, write_cfg);
  139. if (err != ESP_OK) {
  140. ESP_COREDUMP_LOGE("Core dump write binary failed with error: %d", err);
  141. }
  142. }
  143. #endif
  144. void esp_core_dump_init()
  145. {
  146. #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
  147. esp_core_dump_flash_init();
  148. #endif
  149. #if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART
  150. ESP_COREDUMP_LOGI("Init core dump to UART");
  151. #endif
  152. }
  153. esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
  154. {
  155. esp_err_t err;
  156. const void *core_data;
  157. spi_flash_mmap_handle_t core_data_handle;
  158. if (out_addr == NULL || out_size == NULL) {
  159. return ESP_ERR_INVALID_ARG;
  160. }
  161. const esp_partition_t *core_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_COREDUMP, NULL);
  162. if (!core_part) {
  163. ESP_LOGE(TAG, "No core dump partition found!");
  164. return ESP_FAIL;
  165. }
  166. if (core_part->size < sizeof(uint32_t)) {
  167. ESP_LOGE(TAG, "Too small core dump partition!");
  168. return ESP_FAIL;
  169. }
  170. err = esp_partition_mmap(core_part, 0, sizeof(uint32_t),
  171. SPI_FLASH_MMAP_DATA, &core_data, &core_data_handle);
  172. if (err != ESP_OK) {
  173. ESP_LOGE(TAG, "Failed to mmap core dump data (%d)!", err);
  174. return err;
  175. }
  176. uint32_t *dw = (uint32_t *)core_data;
  177. *out_size = *dw;
  178. spi_flash_munmap(core_data_handle);
  179. if (*out_size == 0xFFFFFFFF) {
  180. ESP_LOGD(TAG, "Blank core dump partition!");
  181. return ESP_ERR_INVALID_SIZE;
  182. } else if ((*out_size < sizeof(uint32_t)) || (*out_size > core_part->size)) {
  183. ESP_LOGE(TAG, "Incorrect size of core dump image: %d", *out_size);
  184. return ESP_ERR_INVALID_SIZE;
  185. }
  186. // remap full core dump with CRC
  187. err = esp_partition_mmap(core_part, 0, *out_size,
  188. SPI_FLASH_MMAP_DATA, &core_data, &core_data_handle);
  189. if (err != ESP_OK) {
  190. ESP_LOGE(TAG, "Failed to mmap core dump data (%d)!", err);
  191. return err;
  192. }
  193. uint32_t *crc = (uint32_t *)(((uint8_t *)core_data) + *out_size);
  194. crc--; // Point to CRC field
  195. // Calc CRC over core dump data except for CRC field
  196. core_dump_crc_t cur_crc = crc32_le(0, (uint8_t const *)core_data, *out_size - sizeof(core_dump_crc_t));
  197. if (*crc != cur_crc) {
  198. ESP_LOGE(TAG, "Core dump data CRC check failed: 0x%x -> 0x%x!", *crc, cur_crc);
  199. spi_flash_munmap(core_data_handle);
  200. return ESP_FAIL;
  201. }
  202. spi_flash_munmap(core_data_handle);
  203. *out_addr = core_part->address;
  204. return ESP_OK;
  205. }