Quellcode durchsuchen

coredump: Makes compatible with legacy binary core dumps

Also:
 - improves coredump versioning scheme
 - Moves some API funtions to respective flash/UART dependent code
Alexey Gerenkov vor 6 Jahren
Ursprung
Commit
e092d6f858

+ 0 - 5
components/esp32/cpu_start.c

@@ -444,11 +444,6 @@ void start_cpu0_default(void)
 
 #if CONFIG_ESP32_ENABLE_COREDUMP
     esp_core_dump_init();
-    size_t core_data_sz = 0;
-    size_t core_data_addr = 0;
-    if (esp_core_dump_image_get(&core_data_addr, &core_data_sz) == ESP_OK && core_data_sz > 0) {
-        ESP_LOGI(TAG, "Found core dump %d bytes in flash @ 0x%x", core_data_sz, core_data_addr);
-    }
 #endif
 
 #if CONFIG_ESP32_WIFI_SW_COEXIST_ENABLE

+ 66 - 48
components/espcoredump/espcoredump.py

@@ -557,16 +557,26 @@ class ESPCoreDumpLoaderError(ESPCoreDumpError):
         super(ESPCoreDumpLoaderError, self).__init__(message)
 
 
+def esp_core_dump_ver(chip, maj, min):
+    return (((chip & 0xFFFF) << 16) | ((maj & 0xFF) << 8) | ((min & 0xFF) << 0))
+
+
 class ESPCoreDumpLoader(object):
     """Core dump loader base class
     """
-    ESP32_COREDUMP_VERSION_BIN = 1
-    ESP32_COREDUMP_VERSION_ELF_CRC32 = 2
-    ESP32_COREDUMP_VERSION_ELF_SHA256 = 3
+    # TODO: add class for core dump version and move all version-dependent params to it
+    ESP_CORE_DUMP_CHIP_ESP32 = 0
+    # "legacy" stands for core dumps v0.1 (before IDF v4.1)
+    ESP32_COREDUMP_VERSION_BIN_V1 = esp_core_dump_ver(ESP_CORE_DUMP_CHIP_ESP32, 0, 1)
+    ESP32_COREDUMP_VERSION_BIN_V2 = esp_core_dump_ver(ESP_CORE_DUMP_CHIP_ESP32, 0, 2)
+    ESP32_COREDUMP_VERSION_ELF_CRC32 = esp_core_dump_ver(ESP_CORE_DUMP_CHIP_ESP32, 1, 0)
+    ESP32_COREDUMP_VERSION_ELF_SHA256 = esp_core_dump_ver(ESP_CORE_DUMP_CHIP_ESP32, 1, 1)
     ESP_CORE_DUMP_INFO_TYPE = 8266
     ESP_CORE_DUMP_TASK_INFO_TYPE = 678
     ESP_CORE_DUMP_EXTRA_INFO_TYPE = 677
     ESP_COREDUMP_CURR_TASK_MARKER = 0xdeadbeef
+    ESP32_COREDUMP_BIN_V1_HDR_FMT = '<4L'
+    ESP32_COREDUMP_BIN_V1_HDR_SZ = struct.calcsize(ESP32_COREDUMP_BIN_V1_HDR_FMT)
     ESP32_COREDUMP_HDR_FMT = '<5L'
     ESP32_COREDUMP_HDR_SZ = struct.calcsize(ESP32_COREDUMP_HDR_FMT)
     ESP32_COREDUMP_TSK_HDR_FMT = '<3L'
@@ -584,6 +594,7 @@ class ESPCoreDumpLoader(object):
         """Base constructor for core dump loader
         """
         self.fcore = None
+        self.hdr = {}
 
     def _get_registers_from_stack(self, data, grows_down):
         """Returns list of registers (in GDB format) from xtensa stack frame
@@ -713,21 +724,18 @@ class ESPCoreDumpLoader(object):
             if self.fcore_name:
                 self.remove_tmp_file(self.fcore_name)
 
-    def extract_elf_corefile(self, core_fname=None, exe_name=None, off=0):
+    def _extract_elf_corefile(self, core_fname=None, off=0, exe_name=None):
         """ Reads the ELF formatted core dump image and parse it
         """
         core_off = off
-        data = self.read_data(core_off, self.ESP32_COREDUMP_HDR_SZ)
-        tot_len,coredump_ver,task_num,tcbsz,segs_num = struct.unpack_from(self.ESP32_COREDUMP_HDR_FMT, data)
-        if coredump_ver == self.ESP32_COREDUMP_VERSION_ELF_CRC32:
+        if self.hdr['ver'] == self.ESP32_COREDUMP_VERSION_ELF_CRC32:
             checksum_len = self.ESP32_COREDUMP_CRC_SZ
-        elif coredump_ver == self.ESP32_COREDUMP_VERSION_ELF_SHA256:
+        elif self.hdr['ver'] == self.ESP32_COREDUMP_VERSION_ELF_SHA256:
             checksum_len = self.ESP32_COREDUMP_SHA256_SZ
         else:
-            raise ESPCoreDumpLoaderError("Core dump version '%d' is not supported!" % coredump_ver)
-        core_off += self.ESP32_COREDUMP_HDR_SZ
+            raise ESPCoreDumpLoaderError("Core dump version '%d' is not supported!" % self.hdr['ver'])
         core_elf = ESPCoreDumpElfFile()
-        data = self.read_data(core_off, tot_len - checksum_len - self.ESP32_COREDUMP_HDR_SZ)
+        data = self.read_data(core_off, self.hdr['tot_len'] - checksum_len - self.ESP32_COREDUMP_HDR_SZ)
         with open(core_fname, 'w+b') as fce:
             try:
                 fce.write(data)
@@ -750,39 +758,27 @@ class ESPCoreDumpLoader(object):
                             n_ver_len = struct.calcsize("<L")
                             n_sha256_len = self.ESP32_COREDUMP_SHA256_SZ * 2  # SHA256 as hex string
                             n_ver,coredump_sha256 = struct.unpack("<L%ds" % (n_sha256_len), note.desc[:n_ver_len + n_sha256_len])
-                            if coredump_sha256 != app_sha256 or n_ver != coredump_ver:
+                            if coredump_sha256 != app_sha256 or n_ver != self.hdr['ver']:
                                 raise ESPCoreDumpError("Invalid application image for coredump: app_SHA256(%s) != coredump_SHA256(%s)." %
                                                        (app_sha256, coredump_sha256))
             except ESPCoreDumpError as e:
                 logging.warning("Failed to extract ELF core dump image into file %s. (Reason: %s)" % (core_fname, e))
         return core_fname
 
-    def create_corefile(self, core_fname=None, exe_name=None, rom_elf=None, off=0):
+    def _extract_bin_corefile(self, core_fname=None, rom_elf=None, off=0):
         """Creates core dump ELF file
         """
         core_off = off
-        data = self.read_data(core_off, self.ESP32_COREDUMP_HDR_SZ)
-        tot_len,coredump_ver,task_num,tcbsz,segs_num = struct.unpack_from(self.ESP32_COREDUMP_HDR_FMT, data)
-        if not core_fname:
-            fce = tempfile.NamedTemporaryFile(mode='w+b', delete=False)
-            core_fname = fce.name
-        if coredump_ver == self.ESP32_COREDUMP_VERSION_ELF_CRC32 or coredump_ver == self.ESP32_COREDUMP_VERSION_ELF_SHA256:
-            return self.extract_elf_corefile(core_fname, exe_name)
-        elif coredump_ver > self.ESP32_COREDUMP_VERSION_ELF_SHA256:
-            raise ESPCoreDumpLoaderError("Core dump version '%d' is not supported! Should be up to '%d'." %
-                                         (coredump_ver, self.ESP32_COREDUMP_VERSION_ELF_SHA256))
         with open(core_fname, 'w+b') as fce:
-            tcbsz_aligned = tcbsz
+            tcbsz_aligned = self.hdr['tcbsz']
             if tcbsz_aligned % 4:
                 tcbsz_aligned = 4 * (old_div(tcbsz_aligned,4) + 1)
-            # The version of core dump is ESP32_COREDUMP_VERSION_BIN
-            core_off += self.ESP32_COREDUMP_HDR_SZ
             core_elf = ESPCoreDumpElfFile()
             notes = b''
             core_dump_info_notes = b''
             task_info_notes = b''
             task_status = EspCoreDumpTaskStatus()
-            for i in range(task_num):
+            for i in range(self.hdr['task_num']):
                 task_status.task_index = i
                 task_status.task_flags = EspCoreDumpTaskStatus.TASK_STATUS_CORRECT
                 data = self.read_data(core_off, self.ESP32_COREDUMP_TSK_HDR_SZ)
@@ -803,8 +799,8 @@ class ESPCoreDumpLoader(object):
                 task_status.task_tcb_addr = tcb_addr
                 try:
                     if self.tcb_is_sane(tcb_addr, tcbsz_aligned):
-                        if tcbsz != tcbsz_aligned:
-                            core_elf.add_program_segment(tcb_addr, data[:tcbsz - tcbsz_aligned],
+                        if self.hdr['tcbsz'] != tcbsz_aligned:
+                            core_elf.add_program_segment(tcb_addr, data[:self.hdr['tcbsz'] - tcbsz_aligned],
                                                          ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W)
                         else:
                             core_elf.add_program_segment(tcb_addr, data, ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W)
@@ -844,20 +840,21 @@ class ESPCoreDumpLoader(object):
                 notes += note
                 if ESPCoreDumpElfFile.REG_EXCCAUSE_IDX in extra_regs and len(core_dump_info_notes) == 0:
                     # actually there will be only one such note - for crashed task
-                    core_dump_info_notes += Elf32NoteDesc("ESP_CORE_DUMP_INFO", self.ESP_CORE_DUMP_INFO_TYPE, struct.pack("<L", coredump_ver)).dump()
+                    core_dump_info_notes += Elf32NoteDesc("ESP_CORE_DUMP_INFO", self.ESP_CORE_DUMP_INFO_TYPE, struct.pack("<L", self.hdr['ver'])).dump()
                     exc_regs = []
                     for reg_id in extra_regs:
                         exc_regs.extend([reg_id, extra_regs[reg_id]])
                     core_dump_info_notes += Elf32NoteDesc("EXTRA_INFO", self.ESP_CORE_DUMP_EXTRA_INFO_TYPE,
                                                           struct.pack("<%dL" % (1 + len(exc_regs)), tcb_addr, *exc_regs)).dump()
-            for i in range(segs_num):
-                data = self.read_data(core_off, self.ESP32_COREDUMP_MEM_SEG_HDR_SZ)
-                core_off += self.ESP32_COREDUMP_MEM_SEG_HDR_SZ
-                mem_start,mem_sz = struct.unpack_from(self.ESP32_COREDUMP_MEM_SEG_HDR_FMT, data)
-                logging.debug("Read memory segment %d bytes @ 0x%x" % (mem_sz, mem_start))
-                data = self.read_data(core_off, stack_len_aligned)
-                core_elf.add_program_segment(mem_start, data, ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W)
-                core_off += mem_sz
+            if self.hdr['ver'] == self.ESP32_COREDUMP_VERSION_BIN_V2:
+                for i in range(self.hdr['segs_num']):
+                    data = self.read_data(core_off, self.ESP32_COREDUMP_MEM_SEG_HDR_SZ)
+                    core_off += self.ESP32_COREDUMP_MEM_SEG_HDR_SZ
+                    mem_start,mem_sz = struct.unpack_from(self.ESP32_COREDUMP_MEM_SEG_HDR_FMT, data)
+                    logging.debug("Read memory segment %d bytes @ 0x%x" % (mem_sz, mem_start))
+                    data = self.read_data(core_off, stack_len_aligned)
+                    core_elf.add_program_segment(mem_start, data, ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W)
+                    core_off += mem_sz
             # add notes
             try:
                 core_elf.add_aux_segment(notes, ESPCoreDumpElfFile.PT_NOTE, 0)
@@ -875,17 +872,35 @@ class ESPCoreDumpLoader(object):
             # add ROM text sections
             if rom_elf:
                 for ps in rom_elf.program_segments:
-                    if ps.flags & ESPCoreDumpSegment.PF_X:
-                        try:
-                            core_elf.add_program_segment(ps.addr, ps.data, ESPCoreDumpElfFile.PT_LOAD, ps.flags)
-                        except ESPCoreDumpError as e:
-                            logging.warning("Skip ROM segment %d bytes @ 0x%x. (Reason: %s)" % (len(ps.data), ps.addr, e))
-
+                    if (ps.flags & ESPCoreDumpSegment.PF_X) == 0:
+                        continue
+                    try:
+                        core_elf.add_program_segment(ps.addr, ps.data, ESPCoreDumpElfFile.PT_LOAD, ps.flags)
+                    except ESPCoreDumpError as e:
+                        logging.warning("Skip ROM segment %d bytes @ 0x%x. (Reason: %s)" % (len(ps.data), ps.addr, e))
+            # dump core ELF
             core_elf.e_type = ESPCoreDumpElfFile.ET_CORE
             core_elf.e_machine = ESPCoreDumpElfFile.EM_XTENSA
             core_elf.dump(fce)
         return core_fname
 
+    def create_corefile(self, core_fname=None, exe_name=None, rom_elf=None, off=0):
+        """Creates core dump ELF file
+        """
+        data = self.read_data(off, self.ESP32_COREDUMP_HDR_SZ)
+        vals = struct.unpack_from(self.ESP32_COREDUMP_HDR_FMT, data)
+        self.hdr = dict(zip(('tot_len', 'ver', 'task_num', 'tcbsz', 'segs_num'), vals))
+        if not core_fname:
+            fce = tempfile.NamedTemporaryFile(mode='w+b', delete=False)
+            core_fname = fce.name
+        if self.hdr['ver'] == self.ESP32_COREDUMP_VERSION_ELF_CRC32 or self.hdr['ver'] == self.ESP32_COREDUMP_VERSION_ELF_SHA256:
+            return self._extract_elf_corefile(core_fname, off + self.ESP32_COREDUMP_HDR_SZ, exe_name)
+        elif self.hdr['ver'] == self.ESP32_COREDUMP_VERSION_BIN_V2:
+            return self._extract_bin_corefile(core_fname, rom_elf, off + self.ESP32_COREDUMP_HDR_SZ)
+        elif self.hdr['ver'] == self.ESP32_COREDUMP_VERSION_BIN_V1:
+            return self._extract_bin_corefile(core_fname, rom_elf, off + self.ESP32_COREDUMP_BIN_V1_HDR_SZ)
+        raise ESPCoreDumpLoaderError("Core dump version '0x%x' is not supported!" % (self.hdr['ver']))
+
     def read_data(self, off, sz):
         """Reads data from raw core dump got from flash or UART
         """
@@ -1101,7 +1116,8 @@ class ESPCoreDumpFlashLoader(ESPCoreDumpLoader):
         data = self.read_data(0, self.ESP32_COREDUMP_HDR_SZ)
         self.checksum_len = 0
         _,coredump_ver,_,_,_ = struct.unpack_from(self.ESP32_COREDUMP_HDR_FMT, data)
-        if coredump_ver == self.ESP32_COREDUMP_VERSION_ELF_CRC32 or coredump_ver == self.ESP32_COREDUMP_VERSION_BIN:
+        if coredump_ver == self.ESP32_COREDUMP_VERSION_ELF_CRC32 or coredump_ver == self.ESP32_COREDUMP_VERSION_BIN_V1 \
+                or coredump_ver == self.ESP32_COREDUMP_VERSION_BIN_V2:
             logging.debug("Dump size = %d, crc off = 0x%x", self.dump_sz, self.dump_sz - self.ESP32_COREDUMP_CRC_SZ)
             data = self.read_data(self.dump_sz - self.ESP32_COREDUMP_CRC_SZ, self.ESP32_COREDUMP_CRC_SZ)
             dump_crc, = struct.unpack_from(self.ESP32_COREDUMP_CRC_FMT, data)
@@ -1470,7 +1486,7 @@ def info_corefile(args):
 
     def gdbmi_freertos_get_task_name(p, tcb_addr):
         p,res = gdbmi_data_evaluate_expression(p, "(char*)((TCB_t *)0x%x)->pcTaskName" % tcb_addr)
-        result = re.match('0x[a-fA-F0-9]+[ \t]*\'([^\']*)\'', res.value)
+        result = re.match("0x[a-fA-F0-9]+[^']*'([^']*)'", res.value)
         if result:
             return p,result.group(1)
         return p,''
@@ -1691,7 +1707,8 @@ def main():
     parser_debug_coredump.add_argument('--gdb', '-g', help='Path to gdb', default='xtensa-esp32-elf-gdb')
     parser_debug_coredump.add_argument('--core', '-c', help='Path to core dump file (if skipped core dump will be read from flash)', type=str)
     parser_debug_coredump.add_argument('--core-format', '-t', help='(elf, raw or b64). File specified with "-c" is an ELF ("elf"), '
-                                                                   'raw (raw) or base64-encoded (b64) binary', type=str, default='elf')
+                                                                   'raw (raw) or base64-encoded (b64) binary',
+                                                                   choices=['b64', 'elf', 'raw'], type=str, default='elf')
     parser_debug_coredump.add_argument('--off', '-o', help='Ofsset of coredump partition in flash '
                                                            '(type "make partition_table" to see).', type=int, default=None)
     parser_debug_coredump.add_argument('--save-core', '-s', help='Save core to file. Othwerwise temporary core file will be deleted. '
@@ -1706,7 +1723,8 @@ def main():
     parser_info_coredump.add_argument('--gdb', '-g', help='Path to gdb', default='xtensa-esp32-elf-gdb')
     parser_info_coredump.add_argument('--core', '-c', help='Path to core dump file (if skipped core dump will be read from flash)', type=str)
     parser_info_coredump.add_argument('--core-format', '-t', help='(elf, raw or b64). File specified with "-c" is an ELF ("elf"), '
-                                                                  'raw (raw) or base64-encoded (b64) binary', type=str, default='elf')
+                                                                  'raw (raw) or base64-encoded (b64) binary',
+                                                                  choices=['b64', 'elf', 'raw'], type=str, default='elf')
     parser_info_coredump.add_argument('--off', '-o', help='Offset of coredump partition in flash (type '
                                                           '"make partition_table" to see).', type=int, default=None)
     parser_info_coredump.add_argument('--save-core', '-s', help='Save core to file. Othwerwise temporary core file will be deleted. '

+ 8 - 0
components/espcoredump/include_core_dump/esp_core_dump_port.h

@@ -27,11 +27,19 @@
 #include "esp_core_dump_priv.h"
 #include "soc/cpu.h"
 #include "esp_debug_helpers.h"
+#include "esp_app_format.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#if CONFIG_IDF_TARGET_ESP32
+#define COREDUMP_VERSION_CHIP ESP_CHIP_ID_ESP32
+#elif CONFIG_IDF_TARGET_ESP32S2BETA
+// TODO: set to ESP32-S2 chip ID
+#define COREDUMP_VERSION_CHIP ~ESP_CHIP_ID_ESP32
+#endif
+
 #define COREDUMP_TCB_SIZE   sizeof(StaticTask_t)
 
 // Gets RTOS tasks snapshot

+ 10 - 4
components/espcoredump/include_core_dump/esp_core_dump_priv.h

@@ -41,9 +41,15 @@ extern "C" {
 #endif
 
 #define COREDUMP_MAX_TASK_STACK_SIZE        (64*1024)
-#define COREDUMP_VERSION_BIN                1
-#define COREDUMP_VERSION_ELF_CRC32          2
-#define COREDUMP_VERSION_ELF_SHA256         3
+// COREDUMP_VERSION_CHIP is defined in ports
+#define COREDUMP_VERSION_MAKE(_maj_, _min_)    ((((COREDUMP_VERSION_CHIP)&0xFFFF) << 16) | (((_maj_)&0xFF) << 8) | (((_min_)&0xFF) << 0))
+#define COREDUMP_VERSION_BIN                0
+#define COREDUMP_VERSION_ELF                1
+// legacy bin coredumps (before IDF v4.1) has version set to 1
+#define COREDUMP_VERSION_BIN_LEGACY         COREDUMP_VERSION_MAKE(COREDUMP_VERSION_BIN, 1) // -> 0x0001
+#define COREDUMP_VERSION_BIN_CURRENT        COREDUMP_VERSION_MAKE(COREDUMP_VERSION_BIN, 2) // -> 0x0002
+#define COREDUMP_VERSION_ELF_CRC32          COREDUMP_VERSION_MAKE(COREDUMP_VERSION_ELF, 0) // -> 0x0100
+#define COREDUMP_VERSION_ELF_SHA256         COREDUMP_VERSION_MAKE(COREDUMP_VERSION_ELF, 1) // -> 0x0101
 #define COREDUMP_CURR_TASK_MARKER           0xDEADBEEF
 #define COREDUMP_CURR_TASK_NOT_FOUND        -1
 
@@ -55,7 +61,7 @@ extern "C" {
 #define COREDUMP_SHA256_LEN                 32
 #endif
 #else
-#define COREDUMP_VERSION                    COREDUMP_VERSION_BIN
+#define COREDUMP_VERSION                    COREDUMP_VERSION_BIN_CURRENT
 #endif
 
 typedef esp_err_t (*esp_core_dump_write_prepare_t)(void *priv, uint32_t *data_len);

+ 3 - 91
components/espcoredump/src/core_dump_common.c

@@ -13,7 +13,6 @@
 // limitations under the License.
 #include <string.h>
 #include <stdbool.h>
-#include "esp_partition.h"
 #include "sdkconfig.h"
 #include "esp_core_dump_priv.h"
 #include "core_dump_elf.h"
@@ -256,94 +255,7 @@ inline void esp_core_dump_write(void *frame, core_dump_write_config_t *write_cfg
     esp_core_dump_report_stack_usage();
 }
 
-void esp_core_dump_init(void)
+void __attribute__((weak)) esp_core_dump_init(void)
 {
-#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
-    esp_core_dump_flash_init();
-#endif
-#if CONFIG_ESP32_ENABLE_COREDUMP_TO_UART
-    ESP_COREDUMP_LOGI("Init core dump to UART");
-#endif
-}
-
-esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
-{
-    esp_err_t err;
-    const void *core_data;
-    spi_flash_mmap_handle_t core_data_handle;
-
-    if (out_addr == NULL || out_size == NULL) {
-        return ESP_ERR_INVALID_ARG;
-    }
-
-    const esp_partition_t *core_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
-                                                                ESP_PARTITION_SUBTYPE_DATA_COREDUMP,
-                                                                NULL);
-    if (!core_part) {
-        ESP_LOGE(TAG, "No core dump partition found!");
-        return ESP_ERR_NOT_FOUND;
-    }
-    if (core_part->size < sizeof(uint32_t)) {
-        ESP_LOGE(TAG, "Too small core dump partition!");
-        return ESP_ERR_INVALID_SIZE;
-    }
-
-    err = esp_partition_mmap(core_part, 0,  sizeof(uint32_t),
-                             SPI_FLASH_MMAP_DATA, &core_data, &core_data_handle);
-    if (err != ESP_OK) {
-        ESP_LOGE(TAG, "Failed to mmap core dump data (%d)!", err);
-        return err;
-    }
-
-    uint32_t *dw = (uint32_t *)core_data;
-    *out_size = *dw;
-    spi_flash_munmap(core_data_handle);
-    if ((*out_size < sizeof(uint32_t)) || (*out_size > core_part->size)) {
-        ESP_LOGE(TAG, "Incorrect size of core dump image: %d", *out_size);
-        return ESP_ERR_INVALID_SIZE;
-    }
-
-    // remap full core dump with CRC
-    err = esp_partition_mmap(core_part, 0, *out_size,
-                             SPI_FLASH_MMAP_DATA, &core_data, &core_data_handle);
-    if (err != ESP_OK) {
-        ESP_LOGE(TAG, "Failed to mmap core dump data (%d)!", err);
-        return err;
-    }
-#if CONFIG_ESP32_COREDUMP_CHECKSUM_CRC32
-    uint32_t *crc = (uint32_t *)(((uint8_t *)core_data) + *out_size);
-    crc--; // Point to CRC field
-
-    // Calculate CRC over core dump data except for CRC field
-    core_dump_crc_t cur_crc = crc32_le(0, (uint8_t const *)core_data, *out_size - sizeof(core_dump_crc_t));
-    if (*crc != cur_crc) {
-        ESP_LOGD(TAG, "Core dump CRC offset 0x%x, data size: %u",
-                (uint32_t)((uint32_t)crc - (uint32_t)core_data), *out_size);
-        ESP_LOGE(TAG, "Core dump data CRC check failed: 0x%x -> 0x%x!", *crc, cur_crc);
-        spi_flash_munmap(core_data_handle);
-        return ESP_ERR_INVALID_CRC;
-    }
-#elif CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256
-    uint8_t* sha256_ptr = (uint8_t*)(((uint8_t *)core_data) + *out_size);
-    sha256_ptr -= COREDUMP_SHA256_LEN;
-    ESP_LOGD(TAG, "Core dump data offset, size: %d, %u!",
-                    (uint32_t)((uint32_t)sha256_ptr - (uint32_t)core_data), *out_size);
-    unsigned char sha_output[COREDUMP_SHA256_LEN];
-    mbedtls_sha256_context ctx;
-    ESP_LOGI(TAG, "Calculate SHA256 for coredump:");
-    (void)esp_core_dump_sha(&ctx, core_data, *out_size - COREDUMP_SHA256_LEN, sha_output);
-    if (memcmp((uint8_t*)sha256_ptr, (uint8_t*)sha_output, COREDUMP_SHA256_LEN) != 0) {
-        ESP_LOGE(TAG, "Core dump data SHA256 check failed:");
-        esp_core_dump_print_sha256("Calculated SHA256", (uint8_t*)sha_output);
-        esp_core_dump_print_sha256("Image SHA256",(uint8_t*)sha256_ptr);
-        spi_flash_munmap(core_data_handle);
-        return ESP_ERR_INVALID_CRC;
-    } else {
-        ESP_LOGI(TAG, "Core dump data SHA256 is correct");
-    }
-#endif
-    spi_flash_munmap(core_data_handle);
-
-    *out_addr = core_part->address;
-    return ESP_OK;
-}
+    /* do nothing by default */
+}

+ 99 - 1
components/espcoredump/src/core_dump_flash.c

@@ -13,9 +13,14 @@
 // limitations under the License.
 #include <string.h>
 #include "esp_partition.h"
-#include "esp32/rom/crc.h"
+#include "esp_log.h"
 #include "esp_core_dump_priv.h"
 #include "esp_flash_internal.h"
+#if CONFIG_IDF_TARGET_ESP32
+#include "esp32/rom/crc.h"
+#elif CONFIG_IDF_TARGET_ESP32S2BETA
+#include "esp32s2beta/rom/crc.h"
+#endif
 
 const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_flash";
 
@@ -50,6 +55,7 @@ static core_dump_flash_config_t s_core_flash_config;
 #define ESP_COREDUMP_FLASH_ERASE(_off_, _len_)          esp_flash_erase_region(esp_flash_default_chip, _off_, _len_)
 #endif
 
+esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size);
 
 static inline core_dump_crc_t esp_core_dump_calc_flash_config_crc(void)
 {
@@ -251,5 +257,97 @@ void esp_core_dump_to_flash(void *frame)
     esp_core_dump_write(frame, &wr_cfg);
     ESP_COREDUMP_LOGI("Core dump has been saved to flash.");
 }
+
+void esp_core_dump_init(void)
+{
+    size_t core_data_sz = 0;
+    size_t core_data_addr = 0;
+    esp_core_dump_flash_init();
+    if (esp_core_dump_image_get(&core_data_addr, &core_data_sz) == ESP_OK && core_data_sz > 0) {
+        ESP_COREDUMP_LOGI("Found core dump %d bytes in flash @ 0x%x", core_data_sz, core_data_addr);
+    }
+}
 #endif
 
+esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size)
+{
+    esp_err_t err;
+    const void *core_data;
+    spi_flash_mmap_handle_t core_data_handle;
+
+    if (out_addr == NULL || out_size == NULL) {
+        return ESP_ERR_INVALID_ARG;
+    }
+
+    const esp_partition_t *core_part = esp_partition_find_first(ESP_PARTITION_TYPE_DATA,
+                                                                ESP_PARTITION_SUBTYPE_DATA_COREDUMP,
+                                                                NULL);
+    if (!core_part) {
+        ESP_LOGE(TAG, "No core dump partition found!");
+        return ESP_ERR_NOT_FOUND;
+    }
+    if (core_part->size < sizeof(uint32_t)) {
+        ESP_LOGE(TAG, "Too small core dump partition!");
+        return ESP_ERR_INVALID_SIZE;
+    }
+
+    err = esp_partition_mmap(core_part, 0,  sizeof(uint32_t),
+                             SPI_FLASH_MMAP_DATA, &core_data, &core_data_handle);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to mmap core dump data (%d)!", err);
+        return err;
+    }
+
+    uint32_t *dw = (uint32_t *)core_data;
+    *out_size = *dw;
+    spi_flash_munmap(core_data_handle);
+    if ((*out_size < sizeof(uint32_t)) || (*out_size > core_part->size)) {
+        ESP_LOGE(TAG, "Incorrect size of core dump image: %d", *out_size);
+        return ESP_ERR_INVALID_SIZE;
+    }
+
+    // remap full core dump with CRC
+    err = esp_partition_mmap(core_part, 0, *out_size,
+                             SPI_FLASH_MMAP_DATA, &core_data, &core_data_handle);
+    if (err != ESP_OK) {
+        ESP_LOGE(TAG, "Failed to mmap core dump data (%d)!", err);
+        return err;
+    }
+    // TODO: check CRC or SHA basing on the version of coredump image stored in flash
+#if CONFIG_ESP32_COREDUMP_CHECKSUM_CRC32
+    uint32_t *crc = (uint32_t *)(((uint8_t *)core_data) + *out_size);
+    crc--; // Point to CRC field
+
+    // Calculate CRC over core dump data except for CRC field
+    core_dump_crc_t cur_crc = crc32_le(0, (uint8_t const *)core_data, *out_size - sizeof(core_dump_crc_t));
+    if (*crc != cur_crc) {
+        ESP_LOGD(TAG, "Core dump CRC offset 0x%x, data size: %u",
+                (uint32_t)((uint32_t)crc - (uint32_t)core_data), *out_size);
+        ESP_LOGE(TAG, "Core dump data CRC check failed: 0x%x -> 0x%x!", *crc, cur_crc);
+        spi_flash_munmap(core_data_handle);
+        return ESP_ERR_INVALID_CRC;
+    }
+#elif CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256
+    uint8_t* sha256_ptr = (uint8_t*)(((uint8_t *)core_data) + *out_size);
+    sha256_ptr -= COREDUMP_SHA256_LEN;
+    ESP_LOGD(TAG, "Core dump data offset, size: %d, %u!",
+                    (uint32_t)((uint32_t)sha256_ptr - (uint32_t)core_data), *out_size);
+    unsigned char sha_output[COREDUMP_SHA256_LEN];
+    mbedtls_sha256_context ctx;
+    ESP_LOGI(TAG, "Calculate SHA256 for coredump:");
+    (void)esp_core_dump_sha(&ctx, core_data, *out_size - COREDUMP_SHA256_LEN, sha_output);
+    if (memcmp((uint8_t*)sha256_ptr, (uint8_t*)sha_output, COREDUMP_SHA256_LEN) != 0) {
+        ESP_LOGE(TAG, "Core dump data SHA256 check failed:");
+        esp_core_dump_print_sha256("Calculated SHA256", (uint8_t*)sha_output);
+        esp_core_dump_print_sha256("Image SHA256",(uint8_t*)sha256_ptr);
+        spi_flash_munmap(core_data_handle);
+        return ESP_ERR_INVALID_CRC;
+    } else {
+        ESP_LOGI(TAG, "Core dump data SHA256 is correct");
+    }
+#endif
+    spi_flash_munmap(core_data_handle);
+
+    *out_addr = core_part->address;
+    return ESP_OK;
+}

+ 5 - 0
components/espcoredump/src/core_dump_uart.c

@@ -166,4 +166,9 @@ void esp_core_dump_to_uart(XtExcFrame *frame)
     esp_core_dump_write((void*)frame, &wr_cfg);
     ESP_COREDUMP_LOGI("Core dump has been written to uart.");
 }
+
+void esp_core_dump_init(void)
+{
+    ESP_COREDUMP_LOGI("Init core dump to UART");
+}
 #endif

+ 182 - 181
components/espcoredump/test/coredump.b64

@@ -1,38 +1,38 @@
-UD0AAAIAAAAKAAAAfAEAAAAAAAA=
+ID0AAAABAAAKAAAAfAEAAAAAAAA=
 f0VMRgEBAQAAAAAAAAAAAAQAXgABAAAAAAAAADQAAAAAAAAAAAAAADQAIAAWACgA
 AAAAAA==
 BAAAAPQCAAAAAAAAAAAAAMAXAADAFwAABgAAAAAAAAA=
-AQAAALQaAACgavs/oGr7P3wBAAB8AQAABgAAAAAAAAA=
-AQAAADAcAAAgtPs/ILT7P/gBAAD4AQAABgAAAAAAAAA=
-AQAAACgeAACQrPs/kKz7P3wBAAB8AQAABgAAAAAAAAA=
-AQAAAKQfAABwqfs/cKn7PwwDAAAMAwAABgAAAAAAAAA=
-AQAAALAiAABMgPs/TID7P3wBAAB8AQAABgAAAAAAAAA=
-AQAAACwkAACQfvs/kH77P6gBAACoAQAABgAAAAAAAAA=
-AQAAANQlAACwePs/sHj7P3wBAAB8AQAABgAAAAAAAAA=
-AQAAAFAnAADwdvs/8Hb7P6wBAACsAQAABgAAAAAAAAA=
-AQAAAPwoAAAUafs/FGn7P3wBAAB8AQAABgAAAAAAAAA=
-AQAAAHgqAABgZ/s/YGf7P6ABAACgAQAABgAAAAAAAAA=
-AQAAABgsAACYbPs/mGz7P3wBAAB8AQAABgAAAAAAAAA=
-AQAAAJQtAACAvPs/gLz7P6gBAACoAQAABgAAAAAAAAA=
-AQAAADwvAAD0ivs/9Ir7P3wBAAB8AQAABgAAAAAAAAA=
-AQAAALgwAAAgifs/IIn7P8ABAADAAQAABgAAAAAAAAA=
-AQAAAHgyAAA0+/o/NPv6P3wBAAB8AQAABgAAAAAAAAA=
-AQAAAPQzAABg+fo/YPn6P8ABAADAAQAABgAAAAAAAAA=
-AQAAALQ1AABwWPs/cFj7P3wBAAB8AQAABgAAAAAAAAA=
-AQAAADA3AACwVvs/sFb7P6wBAACsAQAABgAAAAAAAAA=
-AQAAANw4AACQUfs/kFH7P3wBAAB8AQAABgAAAAAAAAA=
-AQAAAFg6AACwT/s/sE/7P8wBAADMAQAABgAAAAAAAAA=
-BAAAACQ8AAAAAAAAAAAAABQBAAAUAQAABgAAAAAAAAA=
+AQAAALQaAABgYvs/YGL7P3wBAAB8AQAABgAAAAAAAAA=
+AQAAADAcAAAQqvs/EKr7P/ABAADwAQAABgAAAAAAAAA=
+AQAAACAeAAB4ovs/eKL7P3wBAAB8AQAABgAAAAAAAAA=
+AQAAAJwfAABgn/s/YJ/7PwQDAAAEAwAABgAAAAAAAAA=
+AQAAAKAiAAA0dvs/NHb7P3wBAAB8AQAABgAAAAAAAAA=
+AQAAABwkAACAdPs/gHT7P6ABAACgAQAABgAAAAAAAAA=
+AQAAALwlAACYbvs/mG77P3wBAAB8AQAABgAAAAAAAAA=
+AQAAADgnAADgbPs/4Gz7P6QBAACkAQAABgAAAAAAAAA=
+AQAAANwoAADUYPs/1GD7P3wBAAB8AQAABgAAAAAAAAA=
+AQAAAFgqAAAgX/s/IF/7P6ABAACgAQAABgAAAAAAAAA=
+AQAAAPgrAABYZPs/WGT7P3wBAAB8AQAABgAAAAAAAAA=
+AQAAAHQtAABwsvs/cLL7P6ABAACgAQAABgAAAAAAAAA=
+AQAAABQvAADcgPs/3ID7P3wBAAB8AQAABgAAAAAAAAA=
+AQAAAJAwAAAAf/s/AH/7P8gBAADIAQAABgAAAAAAAAA=
+AQAAAFgyAAA0+/o/NPv6P3wBAAB8AQAABgAAAAAAAAA=
+AQAAANQzAABg+fo/YPn6P8ABAADAAQAABgAAAAAAAAA=
+AQAAAJQ1AABYUPs/WFD7P3wBAAB8AQAABgAAAAAAAAA=
+AQAAABA3AACgTvs/oE77P6QBAACkAQAABgAAAAAAAAA=
+AQAAALQ4AAB4Sfs/eEn7P3wBAAB8AQAABgAAAAAAAAA=
+AQAAADA6AACgR/s/oEf7P8QBAADEAQAABgAAAAAAAAA=
+BAAAAPQ7AAAAAAAAAAAAABQBAAAUAQAABgAAAAAAAAA=
 CAAAAEwCAAABAAAA
 Q09SRQAAAAA=
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoGr7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfQ4NQCAIBgD9FABADRUAQP////8AAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYGL7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAARQ4NQCAIBgD9FABADRUAQP////8AAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgODYDgtPs/
-AgAAACy1+z8gtfs/cOn6PwAAAAAAAAAABQAAAK3///8gAAAAIGv7PwEAAACAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAODYDQqvs/
+AgAAAByr+z8Qq/s/cOn6PwAAAAAAAAAABQAAAK3///8gAAAA4GL7PwEAAACAAAAA
 AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@@ -40,44 +40,44 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAA
 CAAAAEwCAAABAAAA
 Q09SRQAAAAA=
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkKz7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1pIAQCAFBgD9FABADRUAQP////8XAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeKL7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3JIAQCAFBgD9FABADRUAQP////8XAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+TAIAwqvs/
-rKr7PwAAAAAAAAAAwBsEAFcAAAA3AAAAnAH+PwAA9D8AAAAAAAAAAAAAAADDGwQA
-AAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+TAIAgoPs/
+nKD7PwAAAAAAAAAA0hQBAFcAAAA3AAAA9D8AAAAAAAAAAAAAAAAAAHiDCIDAXvs/
+AAAAAICC+z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAA
 CAAAAEwCAAABAAAA
 Q09SRQAAAAA=
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATID7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABogOQCAABgBsxABAd8QAQP////8AAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANHb7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsoUOQCAABgBsxABAd8QAQP////8AAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM44DYBQf/s/
-AAAAAAAAAAABAAAAAQAAgAMAAAAjAAYA1JcIgEB/+z8DAAAAIwgGACAIBgABAAAA
-IAgGAOCO+z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFI4DYBAdfs/
+AAAAAAAAAAABAAAAAQAAgAMAAAAjAAYAeJcIgDB1+z8DAAAAIwgGACAIBgABAAAA
+IAgGANCE+z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAA
 CAAAAEwCAAABAAAA
 Q09SRQAAAAA=
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsHj7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABogOQCAFBgBsxABAd8QAQP////8AAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmG77PwAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsoUOQCAFBgBsxABAd8QAQP////8AAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM44DYCwd/s/
-AAAAAAMAAAABAAAAAQAAgAMAAAAjAAYAepEIgJB3+z8Ucfs/SB0AQCAEBgABAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFI4DYCgbfs/
+AAAAAAMAAAABAAAAAQAAgAMAAAAjCgYAHpEIgIBt+z/8Zvs/SB0AQCAEBgABAAAA
 IAQGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@@ -85,45 +85,45 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAA
 CAAAAEwCAAABAAAA
 Q09SRQAAAAA=
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFGn7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASBQIQCAFBgD9FABADRUAQPn///8AAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1GD7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQIQCADBgD9FABADRUAQPn///8AAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALqbCIAgaPs/
-AAAAAFojBADUlwiAAFf7PwMAAAAjCAYASBQIgABo+z/cAPA/AQAAADgA+z8BAAAA
-IAUGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF6bCIDgX/s/
+AAAAAGwcAQB4lwiA8E77PwMAAAAjCAYAFBQIgMBf+z/cAPA/AQAAADgA+z8BAAAA
+IAMGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAA
 CAAAAEwCAAABAAAA
 Q09SRQAAAAA=
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmGz7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASBQIQCADBgD9FABADRUAQPj///8AAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWGT7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQIQCABBgD9FABADRUAQPj///8AAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALqbCIBAvfs/
-AAAAAFojBADtWA2A4Kn7PwAIAAAEAPs/SBQIgCC9+z/cAPA/AQAAADgA+z8BAAAA
-IAMGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF6bCIAws/s/
+AAAAAGwcAQBxWA2A0J/7PwAIAAAEAPs/FBQIgBCz+z/cAPA/AQAAADgA+z8BAAAA
+IAEGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAA
 CAAAAEwCAAABAAAA
 Q09SRQAAAAA=
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9Ir7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASBQIQCAABgAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3ID7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQIQCAABgAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF2pCIDgifs/
-AAAAAAAAAAAsgvs/AAAAAAAAAABgXPs/SBQIgMCJ+z/cAPA/AQAAADgA+z9wXPs/
-iCsNQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGpCIDAf/s/
+AAAAAAAAAAAUePs/AAAAAAAAAABQVPs/FBQIgKB/+z/cAPA/AQAAADgA+z9gVPs/
+UCsNQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@@ -131,13 +131,13 @@ AAAAAAAAAAAAAAAA
 CAAAAEwCAAABAAAA
 Q09SRQAAAAA=
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANPv6PwAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASBQIQCAGBgAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQIQCAGBgAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCNCIAg+vo/
-AAAAAAAAAADoQfs/HQAAAFUAAADgUPs/SBQIgAD6+j/cAPA/AQAAADgA+z8BAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADSNCIAg+vo/
+AAAAAAAAAADQOfs/FQAAAFUAAADQSPs/FBQIgAD6+j/cAPA/AQAAADgA+z8BAAAA
 IAYGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@@ -145,14 +145,14 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAA
 CAAAAEwCAAABAAAA
 Q09SRQAAAAA=
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFj7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkI0IQCAIBgAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWFD7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANI0IQCAIBgAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEMdCIBwV/s/
-9FP7PwAAAABIVPs/AAAAAAEAAAAAAAAAkI0IgFBX+z8BAAAABAAAAOxB+z8KAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA8dCIBgT/s/
+3Ev7PwAAAAAwTPs/AAAAAAEAAAAAAAAANI0IgEBP+z8BAAAABAAAANQ5+z8KAAAA
 AACAABwA9D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
@@ -160,150 +160,150 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAA
 CAAAAEwCAAABAAAA
 Q09SRQAAAAA=
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkFH7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASBQIQCAOBgAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAeEn7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFBQIQCAOBgAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCNCIBwUPs/
-AAAAAAAAAADoQfs/zc0AAAEAAAAAAAAASBQIgFBQ+z/cAPA/AQAAADgA+z8BAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADSNCIBgSPs/
+AAAAAAAAAADQOfs/zc0AAAEAAAAAAAAAFBQIgEBI+z/cAPA/AQAAADgA+z8BAAAA
 IAAGAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAA
-kLT7P7C1+z9yHwQAiED7P4hA+z+gavs/gED7PxIAAABYbPs/WGz7P6Bq+z8AAAAA
-BwAAAByu+z91bmFsaWduZWRfcHRyX3QAAQAAABi2+z8AAAAAIAwGAA8AAADOzs7O
+gKr7P6Cr+z+EGAEAcDj7P3A4+z9gYvs/aDj7PxIAAAAYZPs/GGT7P2Bi+z8AAAAA
+BwAAAASk+z91bmFsaWduZWRfcHRyX3QAAQAAAACs+z8AAAAAIAwGAA8AAADOzs7O
 BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOn6P3Dp+j/Y6fo/
 AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4=
-776t3n0ODUAwCAYAWA4NgOC0+z8CAAAALLX7PyC1+z9w6fo/AAAAAAAAAAAFAAAA
-rf///yAAAAAga/s/AQAAAIAAAAABAAAAAAAAAAAAAAAdAAAABQAAAP0UAEANFQBA
-/////wEAAACAAAAAOCQIQFRH+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAEAAACAAAAAAQAAAAAAAABYDg2AELX7PwEAAABw6fo/
-ELgNgBC1+z8KAAAAAwAAACC1+z9w6fo/AAAAAAAAAACgDg2AQLX7PwoAAACUDPs/
-lAJAPx4AAACCWUA/AwAAAACOCIBQZ/s/AQAAANzn68S8gQiAcLX7PwAAAAAAAAAA
-vIEIgHC1+z8AAAAAAwAAACAAAAAAAACAIQAGAAEAAAAAAAAAkLX7P4gODUAAAAAA
-IwAGAIhA+z+gavs/AAAAAAAAAACwtfs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAvLX7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
+776t3kUODUAwCAYAIA4NgNCq+z8CAAAAHKv7PxCr+z9w6fo/AAAAAAAAAAAFAAAA
+rf///yAAAADgYvs/AQAAAIAAAAABAAAAAAAAAAAAAAAdAAAABQAAAP0UAEANFQBA
+/////wEAAACAAAAABCQIQNw++z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAEAAACAAAAAAQAAAAAAAAAgDg2AAKv7PwEAAABw6fo/
+vLUNgACr+z8KAAAAAwAAABCr+z9w6fo/AAAAAAAAAABoDg2AMKv7PwoAAACUDPs/
+lAJAPx4AAADmV0A/AwAAAKSNCIAQX/s/AQAAAO8BvNBggQiAYKv7PwAAAAAAAAAA
+YIEIgGCr+z8AAAAAAwAAACAAAAAAAACAIQAGAAEAAAAAAAAAgKv7P1AODUAAAAAA
+IwAGAHA4+z9gYvs/AAAAAAAAAACgq/s/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAArKv7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-cKn7PxCs+z+PGwQAYED7P2BA+z+QrPs/WED7PxQAAAC0U/s/tFP7P5Cs+z8AAAAA
-BQAAAICM+z91bml0eVRhc2sAzs7Ozs4AAAAAAHys+z8AAAAAIQAGAAwAAADOzs7O
+AAAAAAAAAAAAAAAAAAAAAA==
+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
-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
+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
-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
+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
-AAAAAAAAAAAAAAAA
-kH77P9B/+z/Ozs7O/D/7P7h4+z9MgPs/9D/7PxkAAADOzs7Ozs7OzkyA+z8AAAAA
-AAAAADx6+z9JRExFMQDOzs7Ozs7Ozs4AAQAAADiA+z8AAAAAIQAGAAcAAADOzs7O
+AAAAAA==
+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
-nCQIQAaIDkAwAAYAzjgNgFB/+z8AAAAAAAAAAAEAAAABAACAAwAAACMABgDUlwiA
-QH/7PwMAAAAjCAYAIAgGAAEAAAAgCAYA4I77PwAAAAD//wAAAAAAAGzEAEB3xABA
-/////5wmCEABAAAA/IMIQHQR+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAADcnQhAAAAAAAAAAADlnQiAcH/7PwgAAAABAAAA
-AAAAAAAAAAAAAAAAAAAAALyBCICQf/s/AAAAAAAAAAABAAAAAAAAgCEABgAAAAAA
-AAAAALB/+z/cnQhAAAAAACMABgD8P/s/sHj7PwAAAAAAAAAA0H/7PwAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANx/+z8AAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
-8Hb7PzB4+z/Ozs7OVID7P/w/+z+wePs/9D/7PxkAAADOzs7Ozs7OzrB4+z8AAAAA
-AAAAAKBy+z9JRExFMADOzs7Ozs7Ozs4AAAAAAJx4+z8AAAAAIQAGAAYAAADOzs7O
+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
-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
+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
-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
+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
-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
+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
-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
+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
-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
+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
-AAAAAAAAAAAAAAAAAAAAAA==
-YPn6P8D6+j/Ozs7OeFj7P5hR+z80+/o/cD/7PwMAAADk6vo/5Or6PzT7+j/c6vo/
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+YPn6P8D6+j/Ozs7OYFD7P4BJ+z80+/o/WDf7PwMAAADk6vo/5Or6PzT7+j/c6vo/
 FgAAACTr+j9lc3BfdGltZXIAzs7Ozs4AAAAAACD7+j8AAAAAIQAGAAEAAADOzs7O
 FgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOn6P3Dp+j/Y6fo/
 AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA
@@ -311,59 +311,60 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4=
-nCQIQEgUCEAwBgYAkI0IgCD6+j8AAAAAAAAAAOhB+z8dAAAAVQAAAOBQ+z9IFAiA
+aCQIQBQUCEAwBgYANI0IgCD6+j8AAAAAAAAAANA5+z8VAAAAVQAAANBI+z8UFAiA
 APr6P9wA8D8BAAAAOAD7PwEAAAAgBgYAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA
-AAAAAJwmCEABAAAA/IMIQGSM+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
-AAAAAAAAAAAAAAAAAAAAAJwkCEC0gQhAMAAFAAAAAAAHOA2AQPr6P7jq+j8AAAAA
-AAAAAPQ3DUAAAAAAAAAAALyBCICA+vo/AAAAAAAAAAAAAAAAAAAAAAAAAAD/////
-AAAAAAAAAADz1gMA3OfrxAzr+j8AAAAAAQAAACMOBgAAAAAAoPr6P/Q3DUAAAAAA
-IwAGALRB+z80+/o/AAAAAAAAAADA+vo/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAGgmCEABAAAAoIMIQPyN+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAGgkCEBYgQhAMAAFAAAAAACLNw2AQPr6P7jq+j8AAAAA
+AAAAAHg3DUAAAAAAAAAAAGCBCICA+vo/AAAAAAAAAAAAAAAAAAAAAAAAAAD/////
+AAAAAAAAAACMxAAA7wG80Azr+j8AAAAAAQAAACMOBgAAAAAAoPr6P3g3DUAAAAAA
+IwAGAJw5+z80+/o/AAAAAAAAAADA+vo/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzPr6PwAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAAAAAAAAAAAAAAAAAA==
-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
+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
-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
+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
-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
-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==
+aCQIQBQUCEAwDgYANI0IgGBI+z8AAAAAAAAAANA5+z/NzQAAAQAAAAAAAAAUFAiA
+QEj7P9wA8D8BAAAAOAD7PwEAAAAgAAYAAQAAAAAAAAD//wAAAAAAAAAAAAAAAAAA
+AAAAAGgmCEABAAAAoIMIQDzc+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAGgkCEBYgQhAMAAFAAAAAAAPHQiAgEj7P/xE+z8AAAAA
+AAAAANwcCEAAAAAAAAAAAGCBCIDASPs/AAAAAAAAAAAAAAAAAAAAAAAAAAD/////
+AAAAAAAAAAAAAAAA7wG80FBF+z8AAAAAAQAAAAIAAAAAAAAA4Ej7P9wcCEAAAAAA
+IwMGAMQ5+z94Sfs/AQAAAAAAAAAASfs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+KREIgFA7/j9AN/s/7wG80AAAAAAAAAAADEn7PwAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+AAAAAAAAAAAAAAAAAAAAAAAAAAA=
 FAAAAEgAAABKIAAA
 RVNQX0NPUkVfRFVNUF9JTkZPAAA=
-AgAAADJhYTkyNjY1YTFiNzg5OWMyZjI4NjhmOGRhZWRmZDVhMWUzNWExYWVhMzY1
-ZjkzNmRjODllZThjYzcxNzhhNTMAAAAA
+AAEAADYxNTFkNThkNGUzNmJmYWI5MmM4ZTYzYzgzYTEzOThlZDdhNjFkYzFhYjk0
+NWQxNzI5ZTY3MDUxNmY5N2NiZjQAAAAA
 DAAAAJQAAAClAgAA
 RVhUUkFfSU5GTwAA
-oGr7P+gAAAAdAAAA7gAAAAUAAADCAAAAAAAAAMMAAAAAAAAAxAAAAAAAAADFAAAA
-AAAAAMYAAAAAAAAAxwAAAAAAAACxAAAAm4cOQLIAAAAAAAAAswAAAAAAAAC0AAAA
-AAAAALUAAAAAAAAAtgAAAAAAAAC3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+YGL7P+gAAAAdAAAA7gAAAAUAAADCAAAAAAAAAMMAAAAAAAAAxAAAACAIBgDFAAAA
+AAAAAMYAAAAAAAAAxwAAAAAAAACxAAAAR4UOQLIAAAAAAAAAswAAAAAAAAC0AAAA
+QCwIQLUAAAAAAAAAtgAAAAAAAAC3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
 AAAAAA==
-v1VmGg==
+hvIqKg==
+

Datei-Diff unterdrückt, da er zu groß ist
+ 481 - 480
components/espcoredump/test/expected_output


+ 8 - 7
docs/en/api-guides/core_dump.rst

@@ -7,7 +7,7 @@ Overview
 ESP-IDF provides support to generate core dumps on unrecoverable software errors. This useful technique allows post-mortem analysis of software state at the moment of failure.
 Upon the crash system enters panic state, prints some information and halts or reboots depending configuration. User can choose to generate core dump in order to analyse
 the reason of failure on PC later on. Core dump contains snapshots of all tasks in the system at the moment of failure. Snapshots include tasks control blocks (TCB) and stacks.
-So it is possible to find out what task, at what instruction (line of code) and what callstack of that task lead to the crash. 
+So it is possible to find out what task, at what instruction (line of code) and what callstack of that task lead to the crash.
 ESP-IDF provides special script `espcoredump.py` to help users to retrieve and analyse core dumps. This tool provides two commands for core dumps analysis:
 
 * info_corefile - prints crashed task's registers, callstack, list of available tasks in the system, memory regions and contents of memory stored in core dump (TCBs and stacks)
@@ -29,8 +29,8 @@ There are a number of core dump related configuration options which user can cho
 * ELF format (Executable and Linkable Format file for core dump)
 * Binary format (Basic binary format for core dump)
 
-The ELF format contains extended features and allow to save more information about broken tasks and crashed software but it requires more space in the flash memory. 
-It also stores SHA256 of crashed application image. This format of core dump is recommended for new software designs and is flexible enough to extend saved information for future revisions. 
+The ELF format contains extended features and allow to save more information about broken tasks and crashed software but it requires more space in the flash memory.
+It also stores SHA256 of crashed application image. This format of core dump is recommended for new software designs and is flexible enough to extend saved information for future revisions.
 The Binary format is kept for compatibility standpoint, it uses less space in the memory to keep data and provides better performance.
 
 3. Maximum number of tasks snapshots in core dump (`Components -> Core dump -> Maximum number of tasks`).
@@ -47,8 +47,8 @@ The SHA256 hash algorithm provides greater probability of detecting corruption t
 Save core dump to flash
 -----------------------
 
-When this option is selected core dumps are saved to special partition on flash. When using default partition table files which are provided with ESP-IDF it automatically 
-allocates necessary space on flash, But if user wants to use its own layout file together with core dump feature it should define separate partition for core dump 
+When this option is selected core dumps are saved to special partition on flash. When using default partition table files which are provided with ESP-IDF it automatically
+allocates necessary space on flash, But if user wants to use its own layout file together with core dump feature it should define separate partition for core dump
 as it is shown below::
 
   # Name,   Type, SubType, Offset,  Size
@@ -58,7 +58,7 @@ as it is shown below::
   factory,  app,  factory, 0x10000, 1M
   coredump, data, coredump,,        64K
 
-There are no special requrements for partition name. It can be choosen according to the user application needs, but partition type should be 'data' and 
+There are no special requrements for partition name. It can be choosen according to the user application needs, but partition type should be 'data' and
 sub-type should be 'coredump'. Also when choosing partition size note that core dump data structure introduces constant overhead of 20 bytes and per-task overhead of 12 bytes.
 This overhead does not include size of TCB and stack for every task. So partirion size should be at least 20 + max tasks number x (12 + TCB size + max task stack size) bytes.
 
@@ -68,7 +68,7 @@ or `espcoredump.py -p </path/to/serial/port> dbg_corefile </path/to/program/elf/
 Print core dump to UART
 -----------------------
 
-When this option is selected base64-encoded core dumps are printed on UART upon system panic. In this case user should save core dump text body to some file manually and 
+When this option is selected base64-encoded core dumps are printed on UART upon system panic. In this case user should save core dump text body to some file manually and
 then run the following command: `espcoredump.py info_corefile -t b64 -c </path/to/saved/base64/text> </path/to/program/elf/file>`
 or `espcoredump.py dbg_corefile -t b64 -c </path/to/saved/base64/text> </path/to/program/elf/file>`
 
@@ -112,3 +112,4 @@ Generic command syntax:
     * --save-core,-s SAVE_CORE.     Save core to file. Othwerwise temporary core file will be deleted. Ignored with "-c".
     * --rom-elf,-r ROM_ELF.         Path to ROM ELF file to use (if skipped "esp32_rom.elf" is used).
     * --print-mem,-m                Print memory dump. Used only with "info_corefile".
+    * <prog>                        Path to program ELF file.

Einige Dateien werden nicht angezeigt, da zu viele Dateien in diesem Diff geändert wurden.