diff --git a/components/espcoredump/CMakeLists.txt b/components/espcoredump/CMakeLists.txt index aa3b32eea..bce1224b0 100644 --- a/components/espcoredump/CMakeLists.txt +++ b/components/espcoredump/CMakeLists.txt @@ -1,8 +1,9 @@ -idf_component_register(SRCS "src/core_dump_common.c" +idf_component_register(SRCS "src/core_dump_common.c" "src/core_dump_flash.c" "src/core_dump_port.c" "src/core_dump_uart.c" + "src/core_dump_elf.c" INCLUDE_DIRS "include" PRIV_INCLUDE_DIRS "include_core_dump" LDFRAGMENTS linker.lf - PRIV_REQUIRES spi_flash soc) + PRIV_REQUIRES spi_flash app_update mbedtls esp_rom soc) diff --git a/components/espcoredump/Kconfig b/components/espcoredump/Kconfig index 991bf18f7..7e6094476 100644 --- a/components/espcoredump/Kconfig +++ b/components/espcoredump/Kconfig @@ -20,6 +20,35 @@ menu "Core dump" bool "None" endchoice + choice ESP32_COREDUMP_DATA_FORMAT + prompt "Core dump data format" + default ESP32_COREDUMP_DATA_FORMAT_ELF + depends on !ESP32_ENABLE_COREDUMP_TO_NONE + help + Select the data format for core dump. + config ESP32_COREDUMP_DATA_FORMAT_BIN + bool "Binary format" + select ESP32_ENABLE_COREDUMP + config ESP32_COREDUMP_DATA_FORMAT_ELF + bool "ELF format" + select ESP32_ENABLE_COREDUMP + endchoice + + choice ESP32_COREDUMP_CHECKSUM + prompt "Core dump data integrity check" + default ESP32_COREDUMP_CHECKSUM_CRC32 + depends on !ESP32_ENABLE_COREDUMP_TO_NONE + help + Select the integrity check for the core dump. + config ESP32_COREDUMP_CHECKSUM_CRC32 + bool "Use CRC32 for integrity verification" + select ESP32_ENABLE_COREDUMP + config ESP32_COREDUMP_CHECKSUM_SHA256 + bool "Use SHA256 for integrity verification" + select ESP32_ENABLE_COREDUMP + depends on ESP32_COREDUMP_DATA_FORMAT_ELF + endchoice + config ESP32_ENABLE_COREDUMP bool default F @@ -41,5 +70,15 @@ menu "Core dump" Config delay (in ms) before printing core dump to UART. Delay can be interrupted by pressing Enter key. + config ESP32_CORE_DUMP_STACK_SIZE + int "Reserved stack size" + depends on ESP32_ENABLE_COREDUMP + default 0 + help + Size of the memory to be reserved for core dump stack. If 0 core dump process will run on + the stack of crashed task/ISR, otherwise special stack will be allocated. + To ensure that core dump itself will not overflow task/ISR stack set this to the value above 800. + NOTE: It eats DRAM. + endmenu diff --git a/components/espcoredump/espcoredump.py b/components/espcoredump/espcoredump.py index fb79185f9..42074a70b 100755 --- a/components/espcoredump/espcoredump.py +++ b/components/espcoredump/espcoredump.py @@ -5,6 +5,7 @@ from __future__ import print_function from __future__ import unicode_literals from __future__ import division +from hashlib import sha256 import sys try: from builtins import zip @@ -25,6 +26,7 @@ import errno import base64 import binascii import logging +import re idf_path = os.getenv('IDF_PATH') if idf_path: @@ -32,17 +34,56 @@ if idf_path: try: import esptool + except ImportError: - print("Esptool is not found! Set proper $IDF_PATH in environment.") + print("esptool is not found! Set proper $IDF_PATH in environment.") sys.exit(2) -__version__ = "0.3-dev" +__version__ = "0.4-dev" if os.name == 'nt': CLOSE_FDS = False else: CLOSE_FDS = True +INVALID_CAUSE_VALUE = 0xFFFF + +# Exception cause dictionary to get translation of exccause register +# From 4.4.1.5 table 4-64 Exception Causes of Xtensa +# Instruction Set Architecture (ISA) Reference Manual +xtensa_exception_cause_dict = { + 0: ("IllegalInstructionCause", "Illegal instruction"), + 1: ("SyscallCause", "SYSCALL instruction"), + 2: ("InstructionFetchErrorCause", "Processor internal physical address or data error during instruction fetch. (See EXCVADDR for more information)"), + 3: ("LoadStoreErrorCause", "Processor internal physical address or data error during load or store. (See EXCVADDR for more information)"), + 4: ("Level1InterruptCause", "Level-1 interrupt as indicated by set level-1 bits in the INTERRUPT register"), + 5: ("AllocaCause", "MOVSP instruction, if caller`s registers are not in the register file"), + 6: ("IntegerDivideByZeroCause", "QUOS: QUOU, REMS: or REMU divisor operand is zero"), + 8: ("PrivilegedCause", "Attempt to execute a privileged operation when CRING ? 0"), + 9: ("LoadStoreAlignmentCause", "Load or store to an unaligned address. (See EXCVADDR for more information)"), + 12: ("InstrPIFDataErrorCause", "PIF data error during instruction fetch. (See EXCVADDR for more information)"), + 13: ("LoadStorePIFDataErrorCause", "Synchronous PIF data error during LoadStore access. (See EXCVADDR for more information)"), + 14: ("InstrPIFAddrErrorCause", "PIF address error during instruction fetch. (See EXCVADDR for more information)"), + 15: ("LoadStorePIFAddrErrorCause", "Synchronous PIF address error during LoadStore access. (See EXCVADDR for more information)"), + 16: ("InstTLBMissCause", "Error during Instruction TLB refill. (See EXCVADDR for more information)"), + 17: ("InstTLBMultiHitCause", "Multiple instruction TLB entries matched. (See EXCVADDR for more information)"), + 18: ("InstFetchPrivilegeCause", "An instruction fetch referenced a virtual address at a ring level less than CRING. (See EXCVADDR for more information)"), + 20: ("InstFetchProhibitedCause", "An instruction fetch referenced a page mapped with an attribute that does not permit instruction fetch (EXCVADDR)."), + 24: ("LoadStoreTLBMissCause", "Error during TLB refill for a load or store. (See EXCVADDR for more information)"), + 25: ("LoadStoreTLBMultiHitCause", "Multiple TLB entries matched for a load or store. (See EXCVADDR for more information)"), + 26: ("LoadStorePrivilegeCause", "A load or store referenced a virtual address at a ring level less than CRING. (See EXCVADDR for more information)"), + 28: ("LoadProhibitedCause", "A load referenced a page mapped with an attribute that does not permit loads. (See EXCVADDR for more information)"), + 29: ("StoreProhibitedCause", "A store referenced a page mapped with an attribute that does not permit stores [Region Protection Option or MMU Option]."), + 32: ("Coprocessor0Disabled", "Coprocessor 0 instruction when cp0 disabled"), + 33: ("Coprocessor1Disabled", "Coprocessor 1 instruction when cp1 disabled"), + 34: ("Coprocessor2Disabled", "Coprocessor 2 instruction when cp2 disabled"), + 35: ("Coprocessor3Disabled", "Coprocessor 3 instruction when cp3 disabled"), + 36: ("Coprocessor4Disabled", "Coprocessor 4 instruction when cp4 disabled"), + 37: ("Coprocessor5Disabled", "Coprocessor 5 instruction when cp5 disabled"), + 38: ("Coprocessor6Disabled", "Coprocessor 6 instruction when cp6 disabled"), + 39: ("Coprocessor7Disabled", "Coprocessor 7 instruction when cp7 disabled"), + INVALID_CAUSE_VALUE: ("InvalidCauseRegister", "Invalid EXCCAUSE register value or current task is broken and was skipped")} + class ESPCoreDumpError(RuntimeError): """Core dump runtime error class @@ -143,19 +184,31 @@ class Elf32NoteDesc(object): def __init__(self, name, type, desc): """Constructor for ELF32 note descriptor """ - self.name = bytearray(name, encoding='ascii') + b'\0' + self.name = name self.type = type self.desc = desc def dump(self): """Returns binary representation of ELF32 note descriptor """ - hdr = struct.pack(" 0: self._read_sections(f, shoff, shstrndx) if phnum > 0: @@ -373,7 +460,6 @@ class ESPCoreDumpElfFile(esptool.ELFFile): raise ESPCoreDumpError("No program header table found at offset %04x in ELF file." % seg_table_offs) if len(seg_table) % LEN_SEG_HEADER != 0: logging.warning('Unexpected ELF program header table length %04x is not mod-%02x' % (len(seg_table),LEN_SEG_HEADER)) - # walk through the program segment table and extract all segments seg_table_offs = range(0, len(seg_table), LEN_SEG_HEADER) @@ -387,8 +473,11 @@ class ESPCoreDumpElfFile(esptool.ELFFile): f.seek(offs) return f.read(size) + # read loadable segments self.program_segments = [ESPCoreDumpSegment(vaddr, read_data(offset, filesz), type, flags) for (type, offset, vaddr, filesz,flags) in prog_segments if vaddr != 0] + self.aux_segments = [ESPCoreDumpSegment(vaddr, read_data(offset, filesz), type, flags) + for (type, offset, vaddr, filesz, flags) in prog_segments if type == ESPCoreDumpElfFile.PT_NOTE and vaddr == 0] def add_program_segment(self, addr, data, type, flags): """Adds new program segment @@ -408,6 +497,26 @@ class ESPCoreDumpElfFile(esptool.ELFFile): # append self.program_segments.append(ESPCoreDumpSegment(addr, data, type, flags)) + def add_aux_segment(self, data, type, flags): + """Adds new note segment + """ + self.aux_segments.append(ESPCoreDumpSegment(0, data, type, flags)) + + def write_program_headers(self, f, off, segs): + for seg in segs: + phdr = Elf32ProgramHeader() + phdr.p_type = seg.type + phdr.p_offset = off + phdr.p_vaddr = seg.addr + phdr.p_paddr = phdr.p_vaddr # TODO + phdr.p_filesz = len(seg.data) + phdr.p_memsz = phdr.p_filesz # TODO + phdr.p_flags = seg.flags + phdr.p_align = 0 # TODO + f.write(phdr.dump()) + off += phdr.p_filesz + return off + def dump(self, f): """Write core dump contents to file """ @@ -422,28 +531,21 @@ class ESPCoreDumpElfFile(esptool.ELFFile): ehdr.e_shoff = 0 ehdr.e_flags = 0 ehdr.e_phentsize = Elf32ProgramHeader().sizeof() - ehdr.e_phnum = len(self.program_segments) + ehdr.e_phnum = len(self.program_segments) + len(self.aux_segments) ehdr.e_shentsize = 0 ehdr.e_shnum = 0 ehdr.e_shstrndx = self.SHN_UNDEF f.write(ehdr.dump()) # write program header table cur_off = ehdr.e_ehsize + ehdr.e_phnum * ehdr.e_phentsize - for i in range(len(self.program_segments)): - phdr = Elf32ProgramHeader() - phdr.p_type = self.program_segments[i].type - phdr.p_offset = cur_off - phdr.p_vaddr = self.program_segments[i].addr - phdr.p_paddr = phdr.p_vaddr # TODO - phdr.p_filesz = len(self.program_segments[i].data) - phdr.p_memsz = phdr.p_filesz # TODO - phdr.p_flags = self.program_segments[i].flags - phdr.p_align = 0 # TODO - f.write(phdr.dump()) - cur_off += phdr.p_filesz + cur_off = self.write_program_headers(f, cur_off, self.program_segments) + cur_off = self.write_program_headers(f, cur_off, self.aux_segments) # write program segments - for i in range(len(self.program_segments)): - f.write(self.program_segments[i].data) + for segment in self.program_segments: + f.write(segment.data) + # write aux program segments + for segment in self.aux_segments: + f.write(segment.data) class ESPCoreDumpLoaderError(ESPCoreDumpError): @@ -458,11 +560,25 @@ class ESPCoreDumpLoaderError(ESPCoreDumpError): class ESPCoreDumpLoader(object): """Core dump loader base class """ - ESP32_COREDUMP_VESION = 1 - ESP32_COREDUMP_HDR_FMT = '<4L' - ESP32_COREDUMP_HDR_SZ = struct.calcsize(ESP32_COREDUMP_HDR_FMT) - ESP32_COREDUMP_TSK_HDR_FMT = '<3L' - ESP32_COREDUMP_TSK_HDR_SZ = struct.calcsize(ESP32_COREDUMP_TSK_HDR_FMT) + ESP32_COREDUMP_VERSION_BIN = 1 + ESP32_COREDUMP_VERSION_ELF_CRC32 = 2 + ESP32_COREDUMP_VERSION_ELF_SHA256 = 3 + 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_HDR_FMT = '<5L' + ESP32_COREDUMP_HDR_SZ = struct.calcsize(ESP32_COREDUMP_HDR_FMT) + ESP32_COREDUMP_TSK_HDR_FMT = '<3L' + ESP32_COREDUMP_TSK_HDR_SZ = struct.calcsize(ESP32_COREDUMP_TSK_HDR_FMT) + ESP32_COREDUMP_MEM_SEG_HDR_FMT = '<2L' + ESP32_COREDUMP_MEM_SEG_HDR_SZ = struct.calcsize(ESP32_COREDUMP_MEM_SEG_HDR_FMT) + ESP32_COREDUMP_NOTE_HDR_FMT = '<3L' + ESP32_COREDUMP_NOTE_HDR_SZ = struct.calcsize(ESP32_COREDUMP_NOTE_HDR_FMT) + ESP32_COREDUMP_CRC_FMT = ' 0x40000000) + + def stack_is_sane(self, sp): + """Check stack address if it is correct + """ + return not(sp < 0x3ffae010 or sp > 0x3fffffff) + + def addr_is_fake(self, addr): + """Check if address is in fake area + """ + return ((addr < 0x3f3fffff and addr >= 0x20000000) or addr >= 0x80000000) def remove_tmp_file(self, fname): """Silently removes temporary file @@ -577,91 +713,177 @@ class ESPCoreDumpLoader(object): if self.fcore_name: self.remove_tmp_file(self.fcore_name) - def create_corefile(self, core_fname=None, off=0, rom_elf=None): + def extract_elf_corefile(self, core_fname=None, exe_name=None, off=0): + """ 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: + checksum_len = self.ESP32_COREDUMP_CRC_SZ + elif coredump_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 + core_elf = ESPCoreDumpElfFile() + data = self.read_data(core_off, tot_len - checksum_len - self.ESP32_COREDUMP_HDR_SZ) + with open(core_fname, 'w+b') as fce: + try: + fce.write(data) + fce.flush() + fce.seek(0) + core_elf._read_elf_file(fce) + if exe_name: + exe_elf = ESPCoreDumpElfFile(exe_name) + # Read note segments from core file which are belong to tasks (TCB or stack) + for ns in core_elf.aux_segments: + if ns.type != ESPCoreDumpElfFile.PT_NOTE: + continue + note_read = 0 + while note_read < len(ns.data): + note = Elf32NoteDesc("", 0, None) + note_read += note.read(ns.data[note_read:]) + # Check for version info note + if 'ESP_CORE_DUMP_INFO' == note.name and note.type == self.ESP_CORE_DUMP_INFO_TYPE and exe_name: + app_sha256 = binascii.hexlify(exe_elf.sha256()) + n_ver_len = struct.calcsize(" self.ESP32_COREDUMP_VESION: - raise ESPCoreDumpLoaderError("Core dump version '%d' is not supported! Should be up to '%d'." % (coredump_ver, self.ESP32_COREDUMP_VESION)) - tcbsz_aligned = tcbsz - if tcbsz_aligned % 4: - tcbsz_aligned = 4 * (old_div(tcbsz_aligned,4) + 1) - core_off += self.ESP32_COREDUMP_HDR_SZ - core_elf = ESPCoreDumpElfFile() - notes = b'' - for i in range(task_num): - data = self.read_data(core_off, self.ESP32_COREDUMP_TSK_HDR_SZ) - tcb_addr,stack_top,stack_end = struct.unpack_from(self.ESP32_COREDUMP_TSK_HDR_FMT, data) - if stack_end > stack_top: - stack_len = stack_end - stack_top - stack_base = stack_top - else: - stack_len = stack_top - stack_end - stack_base = stack_end - - stack_len_aligned = stack_len - if stack_len_aligned % 4: - stack_len_aligned = 4 * (old_div(stack_len_aligned,4) + 1) - - core_off += self.ESP32_COREDUMP_TSK_HDR_SZ - logging.info("Read TCB %d bytes @ 0x%x" % (tcbsz_aligned, tcb_addr)) - data = self.read_data(core_off, tcbsz_aligned) - try: - if tcbsz != tcbsz_aligned: - core_elf.add_program_segment(tcb_addr, data[:tcbsz - tcbsz_aligned], - ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W) + 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 + 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): + 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) + tcb_addr,stack_top,stack_end = struct.unpack_from(self.ESP32_COREDUMP_TSK_HDR_FMT, data) + if stack_end > stack_top: + stack_len = stack_end - stack_top + stack_base = stack_top else: - core_elf.add_program_segment(tcb_addr, data, ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W) - except ESPCoreDumpError as e: - logging.warning("Skip TCB %d bytes @ 0x%x. (Reason: %s)" % (tcbsz_aligned, tcb_addr, e)) + stack_len = stack_top - stack_end + stack_base = stack_end + stack_len_aligned = stack_len + if stack_len_aligned % 4: + stack_len_aligned = 4 * (old_div(stack_len_aligned,4) + 1) - core_off += tcbsz_aligned - logging.info("Read stack %d bytes @ 0x%x" % (stack_len_aligned, stack_base)) - data = self.read_data(core_off, stack_len_aligned) - if stack_len != stack_len_aligned: - data = data[:stack_len - stack_len_aligned] + core_off += self.ESP32_COREDUMP_TSK_HDR_SZ + logging.debug("Read TCB %d bytes @ 0x%x" % (tcbsz_aligned, tcb_addr)) + data = self.read_data(core_off, tcbsz_aligned) + 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], + 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) + # task_status.task_name = bytearray("%s\0" % task_name_str, encoding='ascii') + elif tcb_addr and self.addr_is_fake(tcb_addr): + task_status.task_flags |= EspCoreDumpTaskStatus.TASK_STATUS_TCB_CORRUPTED + except ESPCoreDumpError as e: + logging.warning("Skip TCB %d bytes @ 0x%x. (Reason: %s)" % (tcbsz_aligned, tcb_addr, e)) + + core_off += tcbsz_aligned + logging.debug("Read stack %d bytes @ 0x%x" % (stack_len_aligned, stack_base)) + data = self.read_data(core_off, stack_len_aligned) + if stack_len != stack_len_aligned: + data = data[:stack_len - stack_len_aligned] + task_status.task_stack_start = stack_base + task_status.task_stack_len = stack_len_aligned + try: + if self.stack_is_sane(stack_base): + core_elf.add_program_segment(stack_base, data, ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W) + elif stack_base and self.addr_is_fake(stack_base): + task_status.task_flags |= EspCoreDumpTaskStatus.TASK_STATUS_STACK_CORRUPTED + core_elf.add_program_segment(stack_base, data, ESPCoreDumpElfFile.PT_LOAD, ESPCoreDumpSegment.PF_R | ESPCoreDumpSegment.PF_W) + except ESPCoreDumpError as e: + logging.warning("Skip task's (%x) stack %d bytes @ 0x%x. (Reason: %s)" % (tcb_addr, stack_len_aligned, stack_base, e)) + core_off += stack_len_aligned + try: + logging.debug("Stack start_end: 0x%x @ 0x%x" % (stack_top, stack_end)) + task_regs,extra_regs = self._get_registers_from_stack(data, stack_end > stack_top) + except Exception as e: + logging.error(e) + return None + task_info_notes += Elf32NoteDesc("TASK_INFO", self.ESP_CORE_DUMP_TASK_INFO_TYPE, task_status.dump()).dump() + prstatus = XtensaPrStatus() + prstatus.pr_cursig = 0 # TODO: set sig only for current/failed task + prstatus.pr_pid = tcb_addr + note = Elf32NoteDesc("CORE", 1, prstatus.dump() + struct.pack("<%dL" % len(task_regs), *task_regs)).dump() + 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(" stack_top) - except Exception as e: - print(e) - return None - prstatus = XtensaPrStatus() - prstatus.pr_cursig = 0 # TODO: set sig only for current/failed task - prstatus.pr_pid = i # TODO: use pid assigned by OS - note = Elf32NoteDesc("CORE", 1, prstatus.dump() + struct.pack("<%dL" % len(task_regs), *task_regs)).dump() - notes += note + core_elf.add_aux_segment(core_dump_info_notes, ESPCoreDumpElfFile.PT_NOTE, 0) + except ESPCoreDumpError as e: + logging.warning("Skip core dump info NOTES segment %d bytes @ 0x%x. (Reason: %s)" % (len(core_dump_info_notes), 0, e)) + try: + core_elf.add_aux_segment(task_info_notes, ESPCoreDumpElfFile.PT_NOTE, 0) + except ESPCoreDumpError as e: + logging.warning("Skip failed tasks info NOTES segment %d bytes @ 0x%x. (Reason: %s)" % (len(task_info_notes), 0, e)) + # 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)) - # add notes - try: - core_elf.add_program_segment(0, notes, ESPCoreDumpElfFile.PT_NOTE, 0) - except ESPCoreDumpError as e: - logging.warning("Skip NOTES segment %d bytes @ 0x%x. (Reason: %s)" % (len(notes), 0, e)) - # 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)) - - core_elf.e_type = ESPCoreDumpElfFile.ET_CORE - core_elf.e_machine = ESPCoreDumpElfFile.EM_XTENSA - if core_fname: - fce = open(core_fname, 'wb') - else: - fhnd,core_fname = tempfile.mkstemp() - fce = os.fdopen(fhnd, 'wb') - core_elf.dump(fce) - fce.close() + core_elf.e_type = ESPCoreDumpElfFile.ET_CORE + core_elf.e_machine = ESPCoreDumpElfFile.EM_XTENSA + core_elf.dump(fce) return core_fname def read_data(self, off, sz): @@ -684,6 +906,7 @@ class ESPCoreDumpFileLoader(ESPCoreDumpLoader): def _load_coredump(self, path, b64): """Loads core dump from (raw binary or base64-encoded) file """ + logging.debug("Load core dump from '%s'", path) self.fcore_name = None if b64: fhnd,self.fcore_name = tempfile.mkstemp() @@ -712,61 +935,159 @@ class ESPCoreDumpFileLoader(ESPCoreDumpLoader): class ESPCoreDumpFlashLoader(ESPCoreDumpLoader): """Core dump flash loader class """ - ESP32_COREDUMP_FLASH_CRC_FMT = ' part_size: + logging.error("Incorrect size of core dump image: %d, use partition size instead: %d", self.dump_sz, part_size) + self.dump_sz = part_size + # set actual size of core dump image and read it from flash + tool_args[-2] = str(self.dump_sz) et_out = subprocess.check_output(tool_args) - print(et_out.decode('utf-8')) + if len(et_out): + logging.info(et_out.decode('utf-8')) except subprocess.CalledProcessError as e: logging.error("esptool script execution failed with err %d" % e.returncode) - logging.info("Command ran: '%s'" % e.cmd) - logging.info("Command out:") - logging.info(e.output) + logging.debug("Command ran: '%s'" % e.cmd) + logging.debug("Command out:") + logging.debug(e.output) if self.fcore_name: + f.close() self.remove_tmp_file(self.fcore_name) raise e return f + def _load_coredump(self, off=None): + """Loads core dump from flash using parttool or elftool (if offset is set) + """ + tool_path = None + try: + if off: + tool_path = '' + logging.info("Invoke esptool to read image.") + f = self.invoke_esptool(tool_path=tool_path, off=off) + else: + tool_path = '' + logging.info("Invoke parttool to read image.") + f = self.invoke_parttool(tool_path=tool_path) + except subprocess.CalledProcessError as e: + if len(e.output): + logging.info(e.output) + logging.warning("System path is not set. Try to use predefined path.") + if off: + tool_path = self.get_tool_path(use_esptool=True) + f = self.invoke_esptool(tool_path=tool_path, off=off) + else: + tool_path = self.get_tool_path(use_esptool=False) + f = self.invoke_parttool(tool_path=tool_path) + return f + def _read_core_dump_length(self, f): """Reads core dump length """ @@ -774,16 +1095,29 @@ class ESPCoreDumpFlashLoader(ESPCoreDumpLoader): tot_len, = struct.unpack_from(self.ESP32_COREDUMP_FLASH_LEN_FMT, data) return tot_len - def create_corefile(self, core_fname=None, rom_elf=None): + def create_corefile(self, core_fname=None, exe_name=None, rom_elf=None): """Checks flash coredump data integrity and creates ELF file """ - data = self.read_data(self.dump_sz - self.ESP32_COREDUMP_FLASH_CRC_SZ, self.ESP32_COREDUMP_FLASH_CRC_SZ) - dump_crc, = struct.unpack_from(self.ESP32_COREDUMP_FLASH_CRC_FMT, data) - data = self.read_data(0, self.dump_sz - self.ESP32_COREDUMP_FLASH_CRC_SZ) - data_crc = binascii.crc32(data) & 0xffffffff - if dump_crc != data_crc: - raise ESPCoreDumpLoaderError("Invalid core dump CRC %x, should be %x" % (data_crc, dump_crc)) - return super(ESPCoreDumpFlashLoader, self).create_corefile(core_fname) + 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: + 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) + data = self.read_data(0, self.dump_sz - self.ESP32_COREDUMP_CRC_SZ) + data_crc = binascii.crc32(data) & 0xffffffff + if dump_crc != data_crc: + raise ESPCoreDumpLoaderError("Invalid core dump CRC %x, should be %x" % (data_crc, dump_crc)) + elif coredump_ver == self.ESP32_COREDUMP_VERSION_ELF_SHA256: + dump_sha256 = self.read_data(self.dump_sz - self.ESP32_COREDUMP_SHA256_SZ, self.ESP32_COREDUMP_SHA256_SZ) + data = self.read_data(0, self.dump_sz - self.ESP32_COREDUMP_SHA256_SZ) + data_sha256 = sha256(data) + data_sha256_str = data_sha256.hexdigest() + dump_sha256_str = binascii.hexlify(dump_sha256).decode('ascii') + if dump_sha256_str != data_sha256_str: + raise ESPCoreDumpLoaderError("Invalid core dump SHA256 '%s', should be '%s'" % (dump_sha256_str, data_sha256_str)) + return super(ESPCoreDumpFlashLoader, self).create_corefile(core_fname, exe_name) class GDBMIOutRecordHandler(object): @@ -800,7 +1134,7 @@ class GDBMIOutRecordHandler(object): """Base method to execute GDB/MI output record handler function """ if self.verbose: - print("%s.execute: [[%s]]" % (self.__class__.__name__, ln)) + logging.debug("%s.execute: [[%s]]" % (self.__class__.__name__, ln)) class GDBMIOutStreamHandler(GDBMIOutRecordHandler): @@ -835,26 +1169,25 @@ class GDBMIResultHandler(GDBMIOutRecordHandler): """Constructor for GDB/MI result handler """ super(GDBMIResultHandler, self).__init__(None, verbose) - self.result_class = None - self.result_str = None + self.result_class = '' + self.result_str = '' def _parse_rc(self, ln, rc): """Parses result code """ rc_str = "{0}{1}".format(self.TAG, rc) - if ln.startswith(rc_str): - self.result_class = rc - sl = len(rc_str) - if len(ln) > sl: - self.result_str = ln[sl:] - if self.result_str.startswith(','): - self.result_str = self.result_str[1:] - else: - logging.error("Invalid result format: '%s'" % ln) + if not ln.startswith(rc_str): + return False + self.result_class = rc + if len(ln) > len(rc_str): + self.result_str = ln[len(rc_str):] + if self.result_str.startswith(','): + self.result_str = self.result_str[1:] else: - self.result_str = '' - return True - return False + logging.error("Invalid result format: '%s'" % ln) + else: + self.result_str = '' + return True def execute(self, ln): """Executes GDB/MI result handler function @@ -873,6 +1206,116 @@ class GDBMIResultHandler(GDBMIOutRecordHandler): logging.error("Unknown GDB/MI result: '%s'" % ln) +class GDBMIThreadListIdsHandler(GDBMIResultHandler): + """GDB/MI thread-list-ids handler class + """ + def __init__(self, verbose=False): + """Constructor for GDB/MI result handler + """ + super(GDBMIThreadListIdsHandler, self).__init__(verbose) + self.threads = [] + self.current_thread = '' + + def execute(self, ln): + """Executes GDB/MI thread-list-ids handler function + """ + GDBMIResultHandler.execute(self, ln) + if self.result_class != self.RC_DONE: + return + # simple parsing method + result = re.search(r'thread-ids\s*=\s*\{([^\{\}]*)\}', self.result_str) + if result: + for tid in re.finditer(r'thread-id="(\d+)"', result.group(1)): + self.threads.append(tid.group(1)) + result = re.search(r'current-thread-id="(\d+)"', self.result_str) + if result: + self.current_thread = result.group(1) + + +class GDBMIThreadSelectHandler(GDBMIResultHandler): + """GDB/MI thread-select handler class + """ + def execute(self, ln): + """Executes GDB/MI thread-select handler function + """ + GDBMIResultHandler.execute(self, ln) + if self.result_class != self.RC_DONE: + return + + +class GDBMIThreadInfoHandler(GDBMIResultHandler): + """GDB/MI thread-info handler class + """ + def __init__(self, verbose=False): + """Constructor for GDB/MI result handler + """ + super(GDBMIThreadInfoHandler, self).__init__(verbose) + self.current = False + self.id = '' + self.target_id = '' + self.details = '' + self.name = '' + self.frame = '' + self.state = '' + self.core = '' + + def execute(self, ln): + """Executes GDB/MI thread-info handler function + """ + GDBMIResultHandler.execute(self, ln) + if self.result_class != self.RC_DONE: + return + # simple parsing method + result = re.search(r'id="(\d+)"', self.result_str) + if result: + self.id = result.group(1) + result = re.search(r'current="\*"', self.result_str) + if result: + self.current = True + result = re.search(r'target-id="([^"]+)"', self.result_str) + if result: + self.target_id = result.group(1) + + +class GDBMIDataEvalHandler(GDBMIResultHandler): + """GDB/MI data-evaluate-expression handler class + """ + def __init__(self, verbose=False): + """Constructor for GDB/MI result handler + """ + super(GDBMIDataEvalHandler, self).__init__(verbose) + self.value = '' + + def execute(self, ln): + """Executes GDB/MI data-evaluate-expression handler function + """ + GDBMIResultHandler.execute(self, ln) + if self.result_class != self.RC_DONE: + return + # simple parsing method + if self.verbose: + logging.debug("GDBMIDataEvalHandler: result '%s'", self.result_str) + pos = 0 + r = re.compile(r'([a-zA-Z_]+)=(.+)\,') + while True: + m = r.search(self.result_str, pos=pos) + if not m: + break + if m.group(1) == 'value': + if self.verbose: + logging.debug("GDBMIDataEvalHandler: found value = '%s'", m.group(2)) + self.value = self.result.group(1) + return + pos = m.end(2) + 1 + res_str = self.result_str[pos:] + res_str = res_str.replace(r'\"', '\'') + m = re.search(r'value="([^"]+)"', res_str) + if m: + if self.verbose: + logging.debug("GDBMIDataEvalHandler: found value = '%s'", m.group(1)) + self.value = m.group(1) + + class GDBMIStreamConsoleHandler(GDBMIOutStreamHandler): """GDB/MI console stream handler class """ @@ -899,8 +1342,8 @@ def dbg_corefile(args): loader = None rom_elf,rom_sym_cmd = load_aux_elf(args.rom_elf) if not args.core: - loader = ESPCoreDumpFlashLoader(args.off, port=args.port) - core_fname = loader.create_corefile(args.save_core, rom_elf=rom_elf) + loader = ESPCoreDumpFlashLoader(args.off, port=args.port, baud=args.baud) + core_fname = loader.create_corefile(args.save_core, exe_name=args.prog, rom_elf=rom_elf) if not core_fname: logging.error("Failed to create corefile!") loader.cleanup() @@ -909,7 +1352,7 @@ def dbg_corefile(args): core_fname = args.core if args.core_format and args.core_format != 'elf': loader = ESPCoreDumpFileLoader(core_fname, args.core_format == 'b64') - core_fname = loader.create_corefile(args.save_core, rom_elf=rom_elf) + core_fname = loader.create_corefile(args.save_core, exe_name=args.prog, rom_elf=rom_elf) if not core_fname: logging.error("Failed to create corefile!") loader.cleanup() @@ -973,10 +1416,10 @@ def info_corefile(args): gdbmi_read2prompt(p.stdout, handlers) return p - def gdbmi_getinfo(p, handlers, gdb_cmd): + def gdbmi_cmd_exec(p, handlers, gdbmi_cmd): for t in handlers: handlers[t].result_class = None - p.stdin.write(bytearray("-interpreter-exec console \"%s\"\n" % gdb_cmd, encoding='utf-8')) + p.stdin.write(bytearray("%s\n" % gdbmi_cmd, encoding='utf-8')) gdbmi_read2prompt(p.stdout, handlers) if not handlers[GDBMIResultHandler.TAG].result_class or handlers[GDBMIResultHandler.TAG].result_class == GDBMIResultHandler.RC_EXIT: logging.error("GDB exited (%s / %s)!" % (handlers[GDBMIResultHandler.TAG].result_class, handlers[GDBMIResultHandler.TAG].result_str)) @@ -987,11 +1430,59 @@ def info_corefile(args): logging.error("GDB/MI command failed (%s / %s)!" % (handlers[GDBMIResultHandler.TAG].result_class, handlers[GDBMIResultHandler.TAG].result_str)) return p + def gdbmi_getinfo(p, handlers, gdb_cmd): + return gdbmi_cmd_exec(p, handlers, "-interpreter-exec console \"%s\"" % gdb_cmd) + + def gdbmi_get_thread_ids(p): + handlers = {} + result = GDBMIThreadListIdsHandler(verbose=False) + handlers[GDBMIResultHandler.TAG] = result + handlers[GDBMIStreamConsoleHandler.TAG] = GDBMIStreamConsoleHandler(None, verbose=False) + p = gdbmi_cmd_exec(p, handlers, "-thread-list-ids") + return p,result.threads,result.current_thread + + def gdbmi_switch_thread(p, thr_id): + handlers = {} + result = GDBMIThreadSelectHandler(verbose=False) + handlers[GDBMIResultHandler.TAG] = result + handlers[GDBMIStreamConsoleHandler.TAG] = GDBMIStreamConsoleHandler(None, verbose=False) + return gdbmi_cmd_exec(p, handlers, "-thread-select %s" % thr_id) + + def gdbmi_get_thread_info(p, thr_id): + handlers = {} + result = GDBMIThreadInfoHandler(verbose=False) + handlers[GDBMIResultHandler.TAG] = result + handlers[GDBMIStreamConsoleHandler.TAG] = GDBMIStreamConsoleHandler(None, verbose=False) + if thr_id: + cmd = "-thread-info %s" % thr_id + else: + cmd = "-thread-info" + p = gdbmi_cmd_exec(p, handlers, cmd) + return p,result + + def gdbmi_data_evaluate_expression(p, expr): + handlers = {} + result = GDBMIDataEvalHandler(verbose=False) + handlers[GDBMIResultHandler.TAG] = result + handlers[GDBMIStreamConsoleHandler.TAG] = GDBMIStreamConsoleHandler(None, verbose=False) + p = gdbmi_cmd_exec(p, handlers, "-data-evaluate-expression \"%s\"" % expr) + return p,result + + 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) + if result: + return p,result.group(1) + return p,'' + + def gdb2freertos_thread_id(gdb_thread_id): + return int(gdb_thread_id.replace("process ", ""), 0) + loader = None rom_elf,rom_sym_cmd = load_aux_elf(args.rom_elf) if not args.core: - loader = ESPCoreDumpFlashLoader(args.off, port=args.port) - core_fname = loader.create_corefile(args.save_core, rom_elf=rom_elf) + loader = ESPCoreDumpFlashLoader(args.off, port=args.port, baud=args.baud) + core_fname = loader.create_corefile(args.save_core, exe_name=args.prog, rom_elf=rom_elf) if not core_fname: logging.error("Failed to create corefile!") loader.cleanup() @@ -1000,7 +1491,7 @@ def info_corefile(args): core_fname = args.core if args.core_format and args.core_format != 'elf': loader = ESPCoreDumpFileLoader(core_fname, args.core_format == 'b64') - core_fname = loader.create_corefile(args.save_core, rom_elf=rom_elf) + core_fname = loader.create_corefile(args.save_core, exe_name=args.prog, rom_elf=rom_elf) if not core_fname: logging.error("Failed to create corefile!") loader.cleanup() @@ -1055,18 +1546,84 @@ def info_corefile(args): handlers[GDBMIResultHandler.TAG] = GDBMIResultHandler(verbose=False) handlers[GDBMIStreamConsoleHandler.TAG] = GDBMIStreamConsoleHandler(None, verbose=False) p = gdbmi_start(handlers, [rom_sym_cmd]) - + extra_note = None + task_info = [] + for seg in core_elf.aux_segments: + if seg.type != ESPCoreDumpElfFile.PT_NOTE: + continue + note_read = 0 + while note_read < len(seg.data): + note = Elf32NoteDesc("", 0, None) + note_read += note.read(seg.data[note_read:]) + if note.type == ESPCoreDumpLoader.ESP_CORE_DUMP_EXTRA_INFO_TYPE and 'EXTRA_INFO' in note.name: + extra_note = note + if note.type == ESPCoreDumpLoader.ESP_CORE_DUMP_TASK_INFO_TYPE and 'TASK_INFO' in note.name: + task_info_struct = EspCoreDumpTaskStatus(buf=note.desc) + task_info.append(task_info_struct) print("===============================================================") print("==================== ESP32 CORE DUMP START ====================") handlers[GDBMIResultHandler.TAG].result_class = None handlers[GDBMIStreamConsoleHandler.TAG].func = gdbmi_console_stream_handler + if extra_note: + extra_info = struct.unpack("<%dL" % (len(extra_note.desc) / struct.calcsize(" + +#ifndef elf_read_implies_exec +#define elf_read_implies_exec(ex, have_pt_gnu_stack) 0 +#endif + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; + +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef int16_t Elf64_SHalf; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +#define PT_NULL 0 +#define PT_LOAD 1 +#define PT_DYNAMIC 2 +#define PT_INTERP 3 +#define PT_NOTE 4 +#define PT_SHLIB 5 +#define PT_PHDR 6 +#define PT_TLS 7 +#define PT_LOOS 0x60000000 +#define PT_HIOS 0x6fffffff +#define PT_LOPROC 0x70000000 +#define PT_HIPROC 0x7fffffff +#define PT_GNU_EH_FRAME 0x6474e550 + +#define PT_GNU_STACK (PT_LOOS + 0x474e551) + +#define ET_NONE 0 +#define ET_REL 1 +#define ET_EXEC 2 +#define ET_DYN 3 +#define ET_CORE 4 +#define ET_LOPROC 0xff00 +#define ET_HIPROC 0xffff + +#define DT_NULL 0 +#define DT_NEEDED 1 +#define DT_PLTRELSZ 2 +#define DT_PLTGOT 3 +#define DT_HASH 4 +#define DT_STRTAB 5 +#define DT_SYMTAB 6 +#define DT_RELA 7 +#define DT_RELASZ 8 +#define DT_RELAENT 9 +#define DT_STRSZ 10 +#define DT_SYMENT 11 +#define DT_INIT 12 +#define DT_FINI 13 +#define DT_SONAME 14 +#define DT_RPATH 15 +#define DT_SYMBOLIC 16 +#define DT_REL 17 +#define DT_RELSZ 18 +#define DT_RELENT 19 +#define DT_PLTREL 20 +#define DT_DEBUG 21 +#define DT_TEXTREL 22 +#define DT_JMPREL 23 +#define DT_LOPROC 0x70000000 +#define DT_HIPROC 0x7fffffff + +#define STB_LOCAL 0 +#define STB_GLOBAL 1 +#define STB_WEAK 2 + +#define STT_NOTYPE 0 +#define STT_OBJECT 1 +#define STT_FUNC 2 +#define STT_SECTION 3 +#define STT_FILE 4 +#define STT_COMMON 5 +#define STT_TLS 6 + +#define ELF_ST_BIND(x) ((x) >> 4) +#define ELF_ST_TYPE(x) (((unsigned int) x) & 0xf) +#define ELF32_ST_BIND(x) ELF_ST_BIND(x) +#define ELF32_ST_TYPE(x) ELF_ST_TYPE(x) +#define ELF64_ST_BIND(x) ELF_ST_BIND(x) +#define ELF64_ST_TYPE(x) ELF_ST_TYPE(x) + +typedef struct dynamic{ + Elf32_Sword d_tag; + union{ + Elf32_Sword d_val; + Elf32_Addr d_ptr; + } d_un; +} Elf32_Dyn; + +typedef struct { + Elf64_Sxword d_tag; + union { + Elf64_Xword d_val; + Elf64_Addr d_ptr; + } d_un; +} Elf64_Dyn; + +#define ELF32_R_SYM(x) ((x) >> 8) +#define ELF32_R_TYPE(x) ((x) & 0xff) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) + +typedef struct elf32_rel { + Elf32_Addr r_offset; + Elf32_Word r_info; +} Elf32_Rel; + +typedef struct elf64_rel { + Elf64_Addr r_offset; + Elf64_Xword r_info; +} Elf64_Rel; + +typedef struct elf32_rela{ + Elf32_Addr r_offset; + Elf32_Word r_info; + Elf32_Sword r_addend; +} Elf32_Rela; + +typedef struct elf64_rela { + Elf64_Addr r_offset; + Elf64_Xword r_info; + Elf64_Sxword r_addend; +} Elf64_Rela; + +typedef struct elf32_sym{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +} Elf32_Sym; + +typedef struct elf64_sym { + Elf64_Word st_name; + unsigned char st_info; + unsigned char st_other; + Elf64_Half st_shndx; + Elf64_Addr st_value; + Elf64_Xword st_size; +} Elf64_Sym; + +#define EI_NIDENT 16 + +typedef struct elf32_hdr{ + unsigned char e_ident[EI_NIDENT]; + Elf32_Half e_type; + Elf32_Half e_machine; + Elf32_Word e_version; + Elf32_Addr e_entry; + Elf32_Off e_phoff; + Elf32_Off e_shoff; + Elf32_Word e_flags; + Elf32_Half e_ehsize; + Elf32_Half e_phentsize; + Elf32_Half e_phnum; + Elf32_Half e_shentsize; + Elf32_Half e_shnum; + Elf32_Half e_shstrndx; +} Elf32_Ehdr; + +typedef struct elf64_hdr { + unsigned char e_ident[16]; + Elf64_Half e_type; + Elf64_Half e_machine; + Elf64_Word e_version; + Elf64_Addr e_entry; + Elf64_Off e_phoff; + Elf64_Off e_shoff; + Elf64_Word e_flags; + Elf64_Half e_ehsize; + Elf64_Half e_phentsize; + Elf64_Half e_phnum; + Elf64_Half e_shentsize; + Elf64_Half e_shnum; + Elf64_Half e_shstrndx; +} Elf64_Ehdr; + +#define PF_R 0x4 +#define PF_W 0x2 +#define PF_X 0x1 + +typedef struct elf32_phdr{ + Elf32_Word p_type; + Elf32_Off p_offset; + Elf32_Addr p_vaddr; + Elf32_Addr p_paddr; + Elf32_Word p_filesz; + Elf32_Word p_memsz; + Elf32_Word p_flags; + Elf32_Word p_align; +} Elf32_Phdr; + +typedef struct elf64_phdr { + Elf64_Word p_type; + Elf64_Word p_flags; + Elf64_Off p_offset; + Elf64_Addr p_vaddr; + Elf64_Addr p_paddr; + Elf64_Xword p_filesz; + Elf64_Xword p_memsz; + Elf64_Xword p_align; +} Elf64_Phdr; + +#define SHT_NULL 0 +#define SHT_PROGBITS 1 +#define SHT_SYMTAB 2 +#define SHT_STRTAB 3 +#define SHT_RELA 4 +#define SHT_HASH 5 +#define SHT_DYNAMIC 6 +#define SHT_NOTE 7 +#define SHT_NOBITS 8 +#define SHT_REL 9 +#define SHT_SHLIB 10 +#define SHT_DYNSYM 11 +#define SHT_NUM 12 +#define SHT_LOPROC 0x70000000 +#define SHT_HIPROC 0x7fffffff +#define SHT_LOUSER 0x80000000 +#define SHT_HIUSER 0xffffffff + +#define SHF_WRITE 0x1 +#define SHF_ALLOC 0x2 +#define SHF_EXECINSTR 0x4 +#define SHF_MASKPROC 0xf0000000 + +#define SHN_UNDEF 0 +#define SHN_LORESERVE 0xff00 +#define SHN_LOPROC 0xff00 +#define SHN_HIPROC 0xff1f +#define SHN_ABS 0xfff1 +#define SHN_COMMON 0xfff2 +#define SHN_HIRESERVE 0xffff + +typedef struct elf32_shdr{ + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +} Elf32_Shdr; + +typedef struct elf64_shdr { + Elf64_Word sh_name; + Elf64_Word sh_type; + Elf64_Xword sh_flags; + Elf64_Addr sh_addr; + Elf64_Off sh_offset; + Elf64_Xword sh_size; + Elf64_Word sh_link; + Elf64_Word sh_info; + Elf64_Xword sh_addralign; + Elf64_Xword sh_entsize; +} Elf64_Shdr; + +#define EI_MAG0 0 +#define EI_MAG1 1 +#define EI_MAG2 2 +#define EI_MAG3 3 +#define EI_CLASS 4 +#define EI_DATA 5 +#define EI_VERSION 6 +#define EI_OSABI 7 +#define EI_PAD 8 + +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define ELFCLASSNONE 0 +#define ELFCLASS32 1 +#define ELFCLASS64 2 +#define ELFCLASSNUM 3 + +#define ELFDATANONE 0 +#define ELFDATA2LSB 1 +#define ELFDATA2MSB 2 + +#define EV_NONE 0 +#define EV_CURRENT 1 +#define EV_NUM 2 + +#define ELFOSABI_NONE 0 +#define ELFOSABI_LINUX 3 + +#ifndef ELF_OSABI +#define ELF_OSABI ELFOSABI_NONE +#endif + +#define NT_PRSTATUS 1 +#define NT_PRFPREG 2 +#define NT_PRPSINFO 3 +#define NT_TASKSTRUCT 4 +#define NT_AUXV 6 +#define NT_PRXFPREG 0x46e62b7f + +typedef struct elf32_note { + Elf32_Word n_namesz; + Elf32_Word n_descsz; + Elf32_Word n_type; +} Elf32_Nhdr; + +typedef struct elf64_note { + Elf64_Word n_namesz; + Elf64_Word n_descsz; + Elf64_Word n_type; +} Elf64_Nhdr; + +#if ELF_CLASS == ELFCLASS32 + +#define elfhdr Elf32_Ehdr +#define elf_phdr Elf32_Phdr +#define elf_note Elf32_Nhdr +#define elf_shdr Elf32_Shdr + +#else + +#define elfhdr Elf64_Ehdr +#define elf_phdr Elf64_Phdr +#define elf_note Elf64_Nhdr +#define elf_shdr Elf64_Shdr + +#endif + +#endif diff --git a/components/espcoredump/include_core_dump/esp_core_dump_port.h b/components/espcoredump/include_core_dump/esp_core_dump_port.h new file mode 100644 index 000000000..37dd15dfb --- /dev/null +++ b/components/espcoredump/include_core_dump/esp_core_dump_port.h @@ -0,0 +1,122 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#ifndef ESP_CORE_DUMP_PORT_H_ +#define ESP_CORE_DUMP_PORT_H_ + +#include "freertos/FreeRTOS.h" +#if CONFIG_ESP32_COREDUMP_CHECKSUM_CRC32 +#if CONFIG_IDF_TARGET_ESP32 +#include "esp32/rom/crc.h" +#elif CONFIG_IDF_TARGET_ESP32S2BETA +#include "esp32s2beta/rom/crc.h" +#endif +#elif CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256 +#include "mbedtls/sha256.h" +#endif +#include "esp_core_dump_priv.h" +#include "soc/cpu.h" +#include "esp_debug_helpers.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define COREDUMP_TCB_SIZE sizeof(StaticTask_t) + +// Gets RTOS tasks snapshot +uint32_t esp_core_dump_get_tasks_snapshot(core_dump_task_header_t* const tasks, + const uint32_t snapshot_size); + +// Checks TCB consistency +bool esp_core_dump_tcb_addr_is_sane(uint32_t addr); +// Checks stack address +bool esp_core_dump_task_stack_end_is_sane(uint32_t sp); +bool esp_core_dump_mem_seg_is_sane(uint32_t addr, uint32_t sz); +void *esp_core_dump_get_current_task_handle(void); +bool esp_core_dump_check_task(void *frame, core_dump_task_header_t *task_snaphort, bool* is_current, bool* stack_is_valid); +bool esp_core_dump_check_stack(uint32_t stack_start, uint32_t stack_end); +uint32_t esp_core_dump_get_stack(core_dump_task_header_t* task_snapshot, uint32_t* stk_base, uint32_t* stk_len); + +uint16_t esp_core_dump_get_arch_id(void); +uint32_t esp_core_dump_get_task_regs_dump(core_dump_task_header_t *task, void **reg_dump); +void esp_core_dump_init_extra_info(void); +uint32_t esp_core_dump_get_extra_info(void **info); + +// Data integrity check functions +void esp_core_dump_checksum_init(core_dump_write_data_t* wr_data); +void esp_core_dump_checksum_update(core_dump_write_data_t* wr_data, void* data, size_t data_len); +size_t esp_core_dump_checksum_finish(core_dump_write_data_t* wr_data, void** chs_ptr); + +#if CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256 +void esp_core_dump_print_sha256(const char* msg, const uint8_t* sha_output); +int esp_core_dump_sha(mbedtls_sha256_context *ctx, + const unsigned char *input, size_t ilen, unsigned char output[32]); +#endif + +#define esp_core_dump_in_isr_context() xPortInterruptedFromISRContext() +uint32_t esp_core_dump_get_isr_stack_end(void); + +#if CONFIG_ESP32_CORE_DUMP_STACK_SIZE > 0 +#if LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG +// increase stack size in verbose mode +#define ESP32_CORE_DUMP_STACK_SIZE (CONFIG_ESP32_CORE_DUMP_STACK_SIZE+100) +#else +#define ESP32_CORE_DUMP_STACK_SIZE CONFIG_ESP32_CORE_DUMP_STACK_SIZE +#endif +#endif + +void esp_core_dump_report_stack_usage(void); + +#if ESP32_CORE_DUMP_STACK_SIZE > 0 +#define COREDUMP_STACK_FILL_BYTE (0xa5U) +extern uint8_t s_coredump_stack[]; +extern uint8_t *s_core_dump_sp; + +#if LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG +#define esp_core_dump_fill_stack() \ + memset(s_coredump_stack, COREDUMP_STACK_FILL_BYTE, ESP32_CORE_DUMP_STACK_SIZE) +#else +#define esp_core_dump_fill_stack() +#endif + +#define esp_core_dump_setup_stack() \ +{ \ + s_core_dump_sp = (uint8_t *)((uint32_t)(s_coredump_stack + ESP32_CORE_DUMP_STACK_SIZE - 1) & ~0xf); \ + esp_core_dump_fill_stack(); \ + /* watchpoint 1 can be used for task stack overflow detection, re-use it, it is no more necessary */ \ + esp_clear_watchpoint(1); \ + esp_set_watchpoint(1, s_coredump_stack, 1, ESP_WATCHPOINT_STORE); \ + asm volatile ("mov sp, %0" :: "r"(s_core_dump_sp)); \ + ESP_COREDUMP_LOGD("Use core dump stack @ 0x%x", get_sp()); \ +} +#else +#define esp_core_dump_setup_stack() \ +{ \ + /* if we are in ISR set watchpoint to the end of ISR stack */ \ + if (xPortInterruptedFromISRContext()) { \ + extern uint8_t port_IntStack; \ + esp_clear_watchpoint(1); \ + esp_set_watchpoint(1, &port_IntStack+xPortGetCoreID()*configISR_STACK_SIZE, 1, ESP_WATCHPOINT_STORE); \ + } else { \ + /* for tasks user should enable stack overflow detection in menuconfig + TODO: if not enabled in menuconfig enable it ourselves */ \ + } \ +} +#endif + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/espcoredump/include_core_dump/esp_core_dump_priv.h b/components/espcoredump/include_core_dump/esp_core_dump_priv.h index 59568e004..cc149b5d2 100644 --- a/components/espcoredump/include_core_dump/esp_core_dump_priv.h +++ b/components/espcoredump/include_core_dump/esp_core_dump_priv.h @@ -1,4 +1,4 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,10 +14,18 @@ #ifndef ESP_CORE_DUMP_H_ #define ESP_CORE_DUMP_H_ -#include "freertos/FreeRTOS.h" -#include "freertos/task.h" -#include "sdkconfig.h" +#ifdef __cplusplus +extern "C" { +#endif + +#include "esp_err.h" +#include "esp_attr.h" #include "esp_log.h" +#include "sdkconfig.h" +#if CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256 +// TODO: move this to portable part of the code +#include "mbedtls/sha256.h" +#endif #define ESP_COREDUMP_LOG( level, format, ... ) if (LOG_LOCAL_LEVEL >= level) { ets_printf(DRAM_STR(format), esp_log_early_timestamp(), (const char *)TAG, ##__VA_ARGS__); } #define ESP_COREDUMP_LOGE( format, ... ) ESP_COREDUMP_LOG(ESP_LOG_ERROR, LOG_FORMAT(E, format), ##__VA_ARGS__) @@ -33,18 +41,50 @@ #endif #define COREDUMP_MAX_TASK_STACK_SIZE (64*1024) -#define COREDUMP_VERSION 1 +#define COREDUMP_VERSION_BIN 1 +#define COREDUMP_VERSION_ELF_CRC32 2 +#define COREDUMP_VERSION_ELF_SHA256 3 +#define COREDUMP_CURR_TASK_MARKER 0xDEADBEEF +#define COREDUMP_CURR_TASK_NOT_FOUND -1 -typedef uint32_t core_dump_crc_t; - -#if CONFIG_ESP32_ENABLE_COREDUMP +#if CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF +#if CONFIG_ESP32_COREDUMP_CHECKSUM_CRC32 +#define COREDUMP_VERSION COREDUMP_VERSION_ELF_CRC32 +#elif CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256 +#define COREDUMP_VERSION COREDUMP_VERSION_ELF_SHA256 +#define COREDUMP_SHA256_LEN 32 +#endif +#else +#define COREDUMP_VERSION COREDUMP_VERSION_BIN +#endif typedef esp_err_t (*esp_core_dump_write_prepare_t)(void *priv, uint32_t *data_len); typedef esp_err_t (*esp_core_dump_write_start_t)(void *priv); typedef esp_err_t (*esp_core_dump_write_end_t)(void *priv); typedef esp_err_t (*esp_core_dump_flash_write_data_t)(void *priv, void * data, uint32_t data_len); -/** core dump emitter control structure */ +typedef uint32_t core_dump_crc_t; + +typedef struct _core_dump_write_data_t +{ + // TODO: move flash related data to flash-specific code + uint32_t off; // current offset in partition + union + { + uint8_t data8[4]; + uint32_t data32; + } cached_data; + uint8_t cached_bytes; +#if CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256 + // TODO: move this to portable part of the code + mbedtls_sha256_context ctx; + char sha_output[COREDUMP_SHA256_LEN]; +#elif CONFIG_ESP32_COREDUMP_CHECKSUM_CRC32 + core_dump_crc_t crc; // CRC of dumped data +#endif +} core_dump_write_data_t; + +// core dump emitter control structure typedef struct _core_dump_write_config_t { // this function is called before core dump data writing @@ -69,37 +109,34 @@ typedef struct _core_dump_header_t uint32_t version; // core dump struct version uint32_t tasks_num; // number of tasks uint32_t tcb_sz; // size of TCB + uint32_t mem_segs_num; // number of memory segments } core_dump_header_t; /** core dump task data header */ typedef struct _core_dump_task_header_t { - void * tcb_addr; // TCB address + void* tcb_addr; // TCB address uint32_t stack_start; // stack start address uint32_t stack_end; // stack end address } core_dump_task_header_t; -#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH +/** core dump memory segment header */ +typedef struct _core_dump_mem_seg_header_t +{ + uint32_t start; // memory region start address + uint32_t size; // memory region size +} core_dump_mem_seg_header_t; // Core dump flash init function void esp_core_dump_flash_init(void); -#endif - // Common core dump write function void esp_core_dump_write(void *frame, core_dump_write_config_t *write_cfg); -// Gets RTOS tasks snapshot -uint32_t esp_core_dump_get_tasks_snapshot(core_dump_task_header_t* const tasks, - const uint32_t snapshot_size, uint32_t* const tcb_sz); - -// Checks TCB consistency -bool esp_tcb_addr_is_sane(uint32_t addr, uint32_t sz); - -bool esp_core_dump_process_tcb(void *frame, core_dump_task_header_t *task_snaphort, uint32_t tcb_sz); - -bool esp_core_dump_process_stack(core_dump_task_header_t* task_snaphort, uint32_t *length); +#include "esp_core_dump_port.h" +#ifdef __cplusplus +} #endif #endif diff --git a/components/espcoredump/linker.lf b/components/espcoredump/linker.lf index 96a6dd259..0221e9bd9 100644 --- a/components/espcoredump/linker.lf +++ b/components/espcoredump/linker.lf @@ -6,6 +6,7 @@ entries: core_dump_flash (noflash_text) core_dump_common (noflash_text) core_dump_port (noflash_text) + core_dump_elf (noflash_text) else: * (default) @@ -17,3 +18,14 @@ entries: esp_flash_spi_init (noflash_text) else: * (default) + +[mapping:mbedtls] +archive: libmbedtls.a +entries: + if ESP32_COREDUMP_CHECKSUM_SHA256 = y : + if MBEDTLS_HARDWARE_SHA = n: + sha256 (noflash_text) + else: + esp_sha256 (noflash_text) + else: + * (default) diff --git a/components/espcoredump/src/core_dump_common.c b/components/espcoredump/src/core_dump_common.c index 056f3417b..4fc51d916 100644 --- a/components/espcoredump/src/core_dump_common.c +++ b/components/espcoredump/src/core_dump_common.c @@ -13,145 +13,248 @@ // limitations under the License. #include #include -#include "esp32/rom/crc.h" -#include "esp_debug_helpers.h" #include "esp_partition.h" +#include "sdkconfig.h" #include "esp_core_dump_priv.h" +#include "core_dump_elf.h" const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_common"; -#if CONFIG_ESP32_ENABLE_COREDUMP +#if CONFIG_ESP32_COREDUMP_DATA_FORMAT_BIN + +static inline uint32_t esp_core_dump_get_tcb_len() +{ + if (COREDUMP_TCB_SIZE % sizeof(uint32_t)) { + return ((COREDUMP_TCB_SIZE / sizeof(uint32_t) + 1) * sizeof(uint32_t)); + } + return COREDUMP_TCB_SIZE; +} + +static inline uint32_t esp_core_dump_get_stack_len(uint32_t stack_start, uint32_t stack_end) +{ + uint32_t len = stack_end - stack_start; + // Take stack padding into account + return (len + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1); +} + +static esp_err_t esp_core_dump_save_task(core_dump_write_config_t *write_cfg, + core_dump_task_header_t *task) +{ + esp_err_t err = ESP_FAIL; + uint32_t stk_vaddr, stk_len; + uint32_t stk_paddr = esp_core_dump_get_stack(task, &stk_vaddr, &stk_len); + + stk_len = esp_core_dump_get_stack_len(stk_vaddr, stk_vaddr+stk_len); + + // Save TCB address, stack base and stack top addr + err = write_cfg->write(write_cfg->priv, (void*)task, sizeof(core_dump_task_header_t)); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to write task header, error=%d!", err); + return err; + } + // Save TCB block + err = write_cfg->write(write_cfg->priv, task->tcb_addr, esp_core_dump_get_tcb_len()); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to write TCB, error=%d!", err); + return err; + } + // Save task stack + err = write_cfg->write(write_cfg->priv, (void*)stk_paddr, stk_len); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to write stack for task (TCB:%x), stack_start=%x, error=%d!", + task->tcb_addr, + stk_vaddr, + err); + return err; + } + + ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x) dump is saved.", + task->tcb_addr); + return ESP_OK; +} + +static esp_err_t esp_core_dump_save_mem_segment(core_dump_write_config_t* write_cfg, + core_dump_mem_seg_header_t* seg) +{ + esp_err_t err = ESP_FAIL; + + if (!esp_core_dump_mem_seg_is_sane(seg->start, seg->size)) { + ESP_COREDUMP_LOGE("Failed to write memory segment, (%x, %lu)!", + seg->start, seg->size); + return ESP_FAIL; + } + // Save TCB address, stack base and stack top addr + err = write_cfg->write(write_cfg->priv, (void*)seg, sizeof(core_dump_mem_seg_header_t)); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to write memory segment header, error=%d!", err); + return err; + } + // Save memory contents + err = write_cfg->write(write_cfg->priv, (void*)seg->start, seg->size); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to write memory segment, (%x, %lu), error=%d!", + seg->start, seg->size, err); + return err; + } + ESP_COREDUMP_LOG_PROCESS("Memory segment (%x, %lu) is saved.", + seg->start, seg->size); + return ESP_OK; +} static esp_err_t esp_core_dump_write_binary(void *frame, core_dump_write_config_t *write_cfg) { esp_err_t err; - core_dump_task_header_t tasks[CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM]; - uint32_t tcb_sz, task_num, tcb_sz_padded; - bool task_is_valid = false; - uint32_t data_len = 0, i; - union - { - core_dump_header_t hdr; - core_dump_task_header_t task_hdr; - } dump_data; + static core_dump_task_header_t tasks[CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM]; + uint32_t task_num, tcb_sz = esp_core_dump_get_tcb_len(); + uint32_t data_len = 0, task_id; + int curr_task_index = COREDUMP_CURR_TASK_NOT_FOUND; + core_dump_header_t hdr; + core_dump_mem_seg_header_t interrupted_task_stack; - task_num = esp_core_dump_get_tasks_snapshot(tasks, CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM, &tcb_sz); - ESP_COREDUMP_LOGI("Found tasks: (%d)!", task_num); - - // Take TCB padding into account, actual TCB size will be stored in header - if (tcb_sz % sizeof(uint32_t)) - tcb_sz_padded = (tcb_sz / sizeof(uint32_t) + 1) * sizeof(uint32_t); - else - tcb_sz_padded = tcb_sz; + task_num = esp_core_dump_get_tasks_snapshot(tasks, CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM); + ESP_COREDUMP_LOGI("Found tasks: %d!", task_num); // Verifies all tasks in the snapshot - for (i = 0; i < task_num; i++) { - task_is_valid = esp_core_dump_process_tcb(frame, &tasks[i], tcb_sz); - // Check if task tcb is corrupted - if (!task_is_valid) { - write_cfg->bad_tasks_num++; - continue; - } else { - data_len += (tcb_sz_padded + sizeof(core_dump_task_header_t)); - } - uint32_t len = 0; - task_is_valid = esp_core_dump_process_stack(&tasks[i], &len); - if (task_is_valid) { - // Increase core dump size by task stack size - data_len += len; - } else { - // If task tcb is ok but stack is corrupted + for (task_id = 0; task_id < task_num; task_id++) { + bool is_current_task = false, stack_is_valid = false; + bool tcb_is_valid = esp_core_dump_check_task(frame, &tasks[task_id], &is_current_task, &stack_is_valid); + // Check if task tcb or stack is corrupted + if (!tcb_is_valid || !stack_is_valid) { + // If tcb or stack for task is corrupted count task as broken write_cfg->bad_tasks_num++; } + if (is_current_task) { + curr_task_index = task_id; // save current crashed task index in the snapshot + ESP_COREDUMP_LOG_PROCESS("Task #%d (TCB:%x) is first crashed task.", + task_id, + tasks[task_id].tcb_addr); + } + // Increase core dump size by task stack size + uint32_t stk_vaddr, stk_len; + esp_core_dump_get_stack(&tasks[task_id], &stk_vaddr, &stk_len); + data_len += esp_core_dump_get_stack_len(stk_vaddr, stk_vaddr+stk_len); + // Add tcb size + data_len += (tcb_sz + sizeof(core_dump_task_header_t)); } + + if (esp_core_dump_in_isr_context()) { + interrupted_task_stack.start = tasks[curr_task_index].stack_start; + interrupted_task_stack.size = esp_core_dump_get_stack_len(tasks[curr_task_index].stack_start, tasks[curr_task_index].stack_end); + // size of the task's stack has been already taken into account, also addresses have also been checked + data_len += sizeof(core_dump_mem_seg_header_t); + tasks[curr_task_index].stack_start = (uint32_t)frame; + tasks[curr_task_index].stack_end = esp_core_dump_get_isr_stack_end(); + ESP_COREDUMP_LOG_PROCESS("Add ISR stack %lu to %lu", tasks[curr_task_index].stack_end - tasks[curr_task_index].stack_start, data_len); + // take into account size of the ISR stack + data_len += esp_core_dump_get_stack_len(tasks[curr_task_index].stack_start, tasks[curr_task_index].stack_end); + } + + // Check if current task TCB is broken + if (curr_task_index == COREDUMP_CURR_TASK_NOT_FOUND) { + ESP_COREDUMP_LOG_PROCESS("The current crashed task is broken."); + curr_task_index = 0; + } + // Add core dump header size data_len += sizeof(core_dump_header_t); - ESP_COREDUMP_LOG_PROCESS("Core dump len = %lu (%d %d)", data_len, task_num, write_cfg->bad_tasks_num); + ESP_COREDUMP_LOG_PROCESS("Core dump length=%lu, tasks processed: %d, broken tasks: %d", + data_len, task_num, write_cfg->bad_tasks_num); // Prepare write if (write_cfg->prepare) { err = write_cfg->prepare(write_cfg->priv, &data_len); if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to prepare core dump (%d)!", err); + ESP_COREDUMP_LOGE("Failed to prepare core dump, error=%d!", err); return err; } } + // Write start if (write_cfg->start) { err = write_cfg->start(write_cfg->priv); if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to start core dump (%d)!", err); + ESP_COREDUMP_LOGE("Failed to start core dump, error=%d!", err); return err; } } - // Write header - dump_data.hdr.data_len = data_len; - dump_data.hdr.version = COREDUMP_VERSION; - dump_data.hdr.tasks_num = task_num - write_cfg->bad_tasks_num; - dump_data.hdr.tcb_sz = tcb_sz; - err = write_cfg->write(write_cfg->priv, &dump_data, sizeof(core_dump_header_t)); - if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to write core dump header (%d)!", err); - return err; - } - // Write tasks - for (i = 0; i < task_num; i++) { - if (!esp_tcb_addr_is_sane((uint32_t)tasks[i].tcb_addr, tcb_sz)) { - ESP_COREDUMP_LOG_PROCESS("Skip TCB with bad addr %x!", tasks[i].tcb_addr); - continue; - } - ESP_COREDUMP_LOG_PROCESS("Dump task %x", tasks[i].tcb_addr); - // Save TCB address, stack base and stack top addr - dump_data.task_hdr.tcb_addr = tasks[i].tcb_addr; - dump_data.task_hdr.stack_start = tasks[i].stack_start; - dump_data.task_hdr.stack_end = tasks[i].stack_end; - err = write_cfg->write(write_cfg->priv, (void*)&dump_data, sizeof(core_dump_task_header_t)); - if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to write task header (%d)!", err); - return err; - } - // Save TCB - err = write_cfg->write(write_cfg->priv, tasks[i].tcb_addr, tcb_sz); - if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to write TCB (%d)!", err); - return err; - } - // Save task stack - if (tasks[i].stack_start != 0 && tasks[i].stack_end != 0) { - err = write_cfg->write(write_cfg->priv, (void*)tasks[i].stack_start, - tasks[i].stack_end - tasks[i].stack_start); - if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to write task stack (%d)!", err); - return err; - } - } else { - ESP_COREDUMP_LOG_PROCESS("Skip corrupted task %x stack!", tasks[i].tcb_addr); - } - } - // write end + // Write header + hdr.data_len = data_len; + hdr.version = COREDUMP_VERSION; + hdr.tasks_num = task_num; // save all the tasks in snapshot even broken + hdr.mem_segs_num = 0; + if (xPortInterruptedFromISRContext()) { + hdr.mem_segs_num++; // stack of interrupted task + } + hdr.tcb_sz = tcb_sz; + err = write_cfg->write(write_cfg->priv, &hdr, sizeof(core_dump_header_t)); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to write core dump header error=%d!", err); + return err; + } + + // Write first crashed task data first (not always first task in the snapshot) + err = esp_core_dump_save_task(write_cfg, &tasks[curr_task_index]); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to save first crashed task #%d (TCB:%x), error=%d!", + curr_task_index, tasks[curr_task_index].tcb_addr, err); + return err; + } + + // Write all other tasks in the snapshot + for (task_id = 0; task_id < task_num; task_id++) { + // Skip first crashed task + if (task_id == curr_task_index) { + continue; + } + err = esp_core_dump_save_task(write_cfg, &tasks[task_id]); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to save core dump task #%d (TCB:%x), error=%d!", + task_id, tasks[curr_task_index].tcb_addr, err); + return err; + } + } + if (xPortInterruptedFromISRContext()) { + err = esp_core_dump_save_mem_segment(write_cfg, &interrupted_task_stack); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to save interrupted task stack, error=%d!", err); + return err; + } + } + + // Write end if (write_cfg->end) { err = write_cfg->end(write_cfg->priv); if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to end core dump (%d)!", err); + ESP_COREDUMP_LOGE("Failed to end core dump error=%d!", err); return err; } } if (write_cfg->bad_tasks_num) { - ESP_COREDUMP_LOGE("Skipped %d tasks with bad TCB!", write_cfg->bad_tasks_num); + ESP_COREDUMP_LOGE("Found %d broken tasks!", write_cfg->bad_tasks_num); } return err; } +#endif inline void esp_core_dump_write(void *frame, core_dump_write_config_t *write_cfg) { - esp_err_t err = esp_core_dump_write_binary(frame, write_cfg); - if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Core dump write binary failed with error: %d", err); - } -} + esp_core_dump_setup_stack(); +#ifndef CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE + esp_err_t err = ESP_ERR_NOT_SUPPORTED; +#if CONFIG_ESP32_COREDUMP_DATA_FORMAT_BIN + err = esp_core_dump_write_binary(frame, write_cfg); +#elif CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF + err = esp_core_dump_write_elf(frame, write_cfg); #endif + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Core dump write binary failed with error=%d", err); + } +#endif + + esp_core_dump_report_stack_usage(); +} void esp_core_dump_init(void) { @@ -173,14 +276,16 @@ esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size) 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); + 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_FAIL; + return ESP_ERR_NOT_FOUND; } if (core_part->size < sizeof(uint32_t)) { ESP_LOGE(TAG, "Too small core dump partition!"); - return ESP_FAIL; + return ESP_ERR_INVALID_SIZE; } err = esp_partition_mmap(core_part, 0, sizeof(uint32_t), @@ -189,9 +294,14 @@ esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size) 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, @@ -200,16 +310,38 @@ esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size) 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 - // Calc CRC over core dump data except for 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_FAIL; + 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; diff --git a/components/espcoredump/src/core_dump_elf.c b/components/espcoredump/src/core_dump_elf.c new file mode 100644 index 000000000..ad471db5c --- /dev/null +++ b/components/espcoredump/src/core_dump_elf.c @@ -0,0 +1,670 @@ +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +#include +#include "esp_attr.h" +#include "esp_partition.h" +#include "esp_ota_ops.h" +#include "sdkconfig.h" +#include "core_dump_elf.h" + +#define ELF_CLASS ELFCLASS32 + +#include "elf.h" // for ELF file types + +#define ELF_SEG_HEADERS_COUNT(_self_, _task_num_) (uint32_t)((_task_num_) * 2/*stack + tcb*/ \ + + 1/* regs notes */ + 1/* ver info + extra note */ + ((_self_)->interrupted_task.stack_start ? 1 : 0)) + +#define ELF_HLEN 52 +#define ELF_CORE_SEC_TYPE 1 +#define ELF_PR_STATUS_SEG_NUM 0 +#define ELF_ESP_CORE_DUMP_INFO_TYPE 8266 +#define ELF_ESP_CORE_DUMP_EXTRA_INFO_TYPE 677 +#define ELF_NOTE_NAME_MAX_SIZE 32 +#define ELF_APP_SHA256_SIZE 66 + +#define ELF_CHECK_ERR(a, ret_val, str, ...) \ + if (!(a)) { \ + ESP_COREDUMP_LOGE("%s(%u): " str, __FUNCTION__, __LINE__, ##__VA_ARGS__); \ + return (ret_val); \ + } + +typedef enum +{ + ELF_STAGE_CALC_SPACE = 0, + ELF_STAGE_PLACE_HEADERS = 1, + ELF_STAGE_PLACE_DATA = 2 +} core_dump_elf_stages_t; + +typedef enum _elf_err_t +{ + ELF_PROC_ERR_SKIP_HEADER = 0, + ELF_PROC_ERR_STACK_CORRUPTED = -1, + ELF_PROC_ERR_WRITE_FAIL = -2, + ELF_PROC_ERR_OTHER = -3 +} core_dump_elf_proc_err_t; + +typedef struct _core_dump_task_info_t +{ + elf_phdr* phdr; + void* frame; + core_dump_task_header_t* task_hdr; + uint32_t task_id; + size_t tcb_sz; + int* size_ptr; +} core_dump_task_data_t; + +typedef struct +{ + uint32_t version; // coredump version + uint8_t app_elf_sha256[ELF_APP_SHA256_SIZE]; // sha256 of elf file +} core_dump_elf_version_info_t; + +const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_elf"; + +// Main ELF handle type +typedef struct _core_dump_elf_t +{ + core_dump_elf_version_info_t elf_version_info; + uint16_t elf_stage; + uint32_t elf_next_data_offset; + uint32_t bad_tasks_num; + core_dump_task_header_t interrupted_task; + core_dump_write_config_t * write_cfg; +} core_dump_elf_t; + +// Represents lightweight implementation to save core dump data into ELF formatted binary + +#define ALIGN(b, var) var = align(b, var) + +#if CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF + +static inline uint32_t align(uint32_t width, uint32_t in) +{ + return (in + (width - 1)) & -width; +} + +// Builds elf header and check all data offsets +static int elf_write_file_header(core_dump_elf_t *self, uint32_t seg_count) +{ + elfhdr elf_hdr; // declare as static to save stack space + + if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) { + ESP_COREDUMP_LOG_PROCESS("Segment count %u", seg_count); + memset(&elf_hdr, 0, sizeof(elfhdr)); + elf_hdr.e_ident[0] = ELFMAG0; + elf_hdr.e_ident[1] = ELFMAG1; + elf_hdr.e_ident[2] = ELFMAG2; + elf_hdr.e_ident[3] = ELFMAG3; + elf_hdr.e_ident[4] = ELFCLASS32; + elf_hdr.e_ident[5] = ELFDATA2LSB; + elf_hdr.e_ident[6] = EV_CURRENT; + elf_hdr.e_ident[7] = ELFOSABI_NONE; + elf_hdr.e_ident[8] = 0; + elf_hdr.e_type = ET_CORE; + elf_hdr.e_machine = esp_core_dump_get_arch_id(); + elf_hdr.e_flags = 0; + elf_hdr.e_version = EV_CURRENT; + elf_hdr.e_entry = 0; + _Static_assert(sizeof(elfhdr) == ELF_HLEN, "Invalid ELF header struct length!"); + elf_hdr.e_phoff = sizeof(elfhdr); // program header table's file offset in bytes. + elf_hdr.e_phentsize = sizeof(elf_phdr); // size in bytes of one entry in the file program header table + elf_hdr.e_phnum = seg_count; // number of program segments + elf_hdr.e_shoff = 0; // section header table's file offset in bytes. + elf_hdr.e_ehsize = sizeof(elfhdr); // elf header size + elf_hdr.e_shentsize = sizeof(elf_shdr); // section header's size in bytes. + elf_hdr.e_shnum = 0; // initial section counter is 0 + elf_hdr.e_shstrndx = SHN_UNDEF; // do not use string table + // write built elf header into elf image + esp_err_t err = self->write_cfg->write(self->write_cfg->priv, (void*)&elf_hdr, sizeof(elf_hdr)); + ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, + "Write ELF header failure (%d)", err); + ESP_COREDUMP_LOG_PROCESS("Add file header %u bytes", sizeof(elf_hdr)); + } + + return self->elf_stage == ELF_STAGE_PLACE_DATA ? 0 : sizeof(elf_hdr); +} + +static int elf_write_segment_header(core_dump_elf_t *self, elf_phdr* phdr) +{ + ELF_CHECK_ERR(phdr, ELF_PROC_ERR_SKIP_HEADER, + "Header is skipped, stage=(%d).", self->elf_stage); + + phdr->p_offset = self->elf_next_data_offset; + // set segment data information and write it into image + esp_err_t err = self->write_cfg->write(self->write_cfg->priv, (void*)phdr, sizeof(elf_phdr)); + ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, + "Write ELF segment header failure (%d)", err); + ESP_COREDUMP_LOG_PROCESS("Add segment header %u bytes: type %d, sz %u, off = 0x%x", + sizeof(elf_phdr), phdr->p_type, phdr->p_filesz, phdr->p_offset); + + return sizeof(elf_phdr); +} + +static int elf_add_segment(core_dump_elf_t *self, + uint32_t type, uint32_t vaddr, + void* data, uint32_t data_sz) +{ + esp_err_t err = ESP_FAIL; + elf_phdr seg_hdr = { 0 }; + int data_len = data_sz; + + ELF_CHECK_ERR((data != NULL), ELF_PROC_ERR_OTHER, + "Invalid data for segment."); + + ALIGN(4, data_len); + + if (self->elf_stage == ELF_STAGE_CALC_SPACE) { + return data_len + sizeof(elf_phdr); + } + if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) { + seg_hdr.p_type = type; + seg_hdr.p_vaddr = vaddr; + seg_hdr.p_paddr = vaddr; + seg_hdr.p_filesz = data_len; + seg_hdr.p_memsz = data_len; + seg_hdr.p_flags = (PF_R | PF_W); + int ret = elf_write_segment_header(self, &seg_hdr); + ELF_CHECK_ERR((ret > 0), ret, + "Write ELF segment data failure (%d)", ret); + self->elf_next_data_offset += data_len; + return ret; + } + ESP_COREDUMP_LOG_PROCESS("Add segment size=%u, start_off=0x%x", + (uint32_t)data_len, self->elf_next_data_offset); + // write segment data only when write function is set and phdr = NULL + // write data into segment + err = self->write_cfg->write(self->write_cfg->priv, data, (uint32_t)data_len); + ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, + "Write ELF segment data failure (%d)", err); + self->elf_next_data_offset += data_len; + return data_len; +} + +static int elf_write_note(core_dump_elf_t *self, + const char* name, + uint32_t type, + void* data, + uint32_t data_sz) +{ + esp_err_t err = ESP_FAIL; + // temporary buffer for note name + static char name_buffer[ELF_NOTE_NAME_MAX_SIZE] = { 0 }; + elf_note note_hdr = { 0 }; + uint32_t name_len = strlen(name) + 1; // get name length including terminator + uint32_t data_len = data_sz; + + ELF_CHECK_ERR(data, ELF_PROC_ERR_OTHER, + "Invalid data pointer %x.", (uint32_t)data); + ELF_CHECK_ERR((name_len <= ELF_NOTE_NAME_MAX_SIZE), 0, + "Segment note name is too long %d.", name_len); + + ALIGN(4, data_len); + ALIGN(4, name_len); + uint32_t note_size = name_len + data_len + sizeof(elf_note); + ALIGN(4, note_size); + + // write segment data during second pass + if (self->elf_stage == ELF_STAGE_PLACE_DATA) { + memcpy((void*)name_buffer, (void*)name, name_len); + note_hdr.n_namesz = name_len; + note_hdr.n_descsz = data_sz; + note_hdr.n_type = type; + // write note header + err = self->write_cfg->write(self->write_cfg->priv, (void*)¬e_hdr, sizeof(note_hdr)); + ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, + "Write ELF note header failure (%d)", err); + // write note name + err = self->write_cfg->write(self->write_cfg->priv, (void*)name_buffer, name_len); + ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, + "Write ELF note name failure (%d)", err); + // write note data + err = self->write_cfg->write(self->write_cfg->priv, (void*)data, data_len); + ELF_CHECK_ERR((err == ESP_OK), ELF_PROC_ERR_WRITE_FAIL, + "Write ELF note data failure (%d)", err); + ESP_COREDUMP_LOG_PROCESS("Add note size=%d, start_off=0x%x", + note_size, self->elf_next_data_offset); + } + return note_size; // return actual note size +} + +static int elf_add_note(core_dump_elf_t *self, + const char* name, + uint32_t type, + void* data, + uint32_t data_sz) +{ + ELF_CHECK_ERR((data != NULL), ELF_PROC_ERR_OTHER, + "Invalid data pointer for segment"); + + int note_size = elf_write_note(self, name, type, data, data_sz); + ELF_CHECK_ERR((note_size > 0), note_size, + "Write ELF note data failure, returned (%d)", note_size); + return note_size; // return actual note segment size +} + +// Append note with registers dump to segment note +static int elf_add_regs(core_dump_elf_t *self, core_dump_task_header_t *task) +{ + void *reg_dump; + + uint32_t len = esp_core_dump_get_task_regs_dump(task, ®_dump); + if (len == 0) { + ESP_COREDUMP_LOGE("Zero size register dump for task 0x%x!", task->tcb_addr); + return ELF_PROC_ERR_OTHER; + } + + // append note data with dump to existing note + return elf_add_note(self, + "CORE", // note name + ELF_CORE_SEC_TYPE, // note type for reg dump + reg_dump, // register dump with pr_status + len); +} + +static int elf_add_stack(core_dump_elf_t *self, core_dump_task_header_t *task) +{ + uint32_t stack_vaddr, stack_len = 0, stack_paddr = 0; + + ELF_CHECK_ERR((task), ELF_PROC_ERR_OTHER, "Invalid task pointer."); + + stack_paddr = esp_core_dump_get_stack(task, &stack_vaddr, &stack_len); + ESP_COREDUMP_LOG_PROCESS("Add stack for task 0x%x: addr 0x%x, sz %u", + task->tcb_addr, stack_vaddr, stack_len); + int ret = elf_add_segment(self, PT_LOAD, + (uint32_t)stack_vaddr, + (void*)stack_paddr, + (uint32_t) stack_len); + return ret; +} + +static int elf_add_tcb(core_dump_elf_t *self, core_dump_task_header_t *task) +{ + ELF_CHECK_ERR((task), ELF_PROC_ERR_OTHER, "Invalid task pointer."); + // add task tcb data into program segment of ELF + ESP_COREDUMP_LOG_PROCESS("Add TCB for task 0x%x: addr 0x%x, sz %u", + task->tcb_addr, task->tcb_addr, COREDUMP_TCB_SIZE); + int ret = elf_add_segment(self, PT_LOAD, + (uint32_t)task->tcb_addr, + (void*)task->tcb_addr, + COREDUMP_TCB_SIZE); + return ret; +} + +// get index of current crashed task (not always first task in the snapshot) +static int elf_get_current_task_index(core_dump_task_header_t *tasks, + uint32_t task_num) +{ + int task_id; + int curr_task_index = COREDUMP_CURR_TASK_NOT_FOUND; + void* curr_task_handle = esp_core_dump_get_current_task_handle(); + + // get index of current crashed task (not always first task in the snapshot) + for (task_id = 0; task_id < task_num; task_id++) { + bool tcb_is_valid = esp_core_dump_tcb_addr_is_sane((uint32_t)tasks[task_id].tcb_addr); + bool stack_is_valid = esp_core_dump_check_stack(tasks[task_id].stack_start, tasks[task_id].stack_end); + if (stack_is_valid && tcb_is_valid && curr_task_handle == tasks[task_id].tcb_addr) { + curr_task_index = task_id; // save current crashed task index in the snapshot + ESP_COREDUMP_LOG_PROCESS("Task #%d, (TCB:%x) is current crashed task.", + task_id, + tasks[task_id].tcb_addr); + } + } + return curr_task_index; +} + +static int elf_process_task_regdump(core_dump_elf_t *self, void *frame, core_dump_task_header_t *task) +{ + bool task_is_valid = false; + bool task_is_current = false; + + ELF_CHECK_ERR((task), ELF_PROC_ERR_OTHER, "Invalid input data."); + + if (self->elf_stage == ELF_STAGE_CALC_SPACE) { + // Check if task tcb is corrupted (do not update the header, save as is) + task_is_valid = esp_core_dump_check_task(frame, task, &task_is_current, NULL); + if (!task_is_valid) { + if (task_is_current) { + ESP_COREDUMP_LOG_PROCESS("Task has incorrect (TCB:%x)!", + task->tcb_addr); + } else { + ESP_COREDUMP_LOG_PROCESS("The current crashed task has broken (TCB:%x)!", + task->tcb_addr); + } + self->bad_tasks_num++; + } + } + // extract registers from stack and apply elf data size for stack section + return elf_add_regs(self, task); +} + +static int elf_process_task_tcb(core_dump_elf_t *self, core_dump_task_header_t *task) +{ + int ret = ELF_PROC_ERR_OTHER; + + ELF_CHECK_ERR((task), ELF_PROC_ERR_OTHER, "Invalid input data."); + + // save tcb of the task as is and apply segment size + ret = elf_add_tcb(self, task); + if (ret > 0) { + ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x) processing completed.", + task->tcb_addr); + } else { + ESP_COREDUMP_LOGE("Task (TCB:%x) processing failure = %d", + task->tcb_addr, + ret); + } + return ret; +} + +static int elf_process_task_stack(core_dump_elf_t *self, core_dump_task_header_t *task) +{ + int ret = ELF_PROC_ERR_OTHER; + + ELF_CHECK_ERR((task), ELF_PROC_ERR_OTHER, "Invalid input data."); + + ret = elf_add_stack(self, task); + if (ret > 0) { + ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), (Stack:%x) stack is processed.", + task->tcb_addr, + task->stack_start); + } else { + ESP_COREDUMP_LOGE("Task (TCB:%x), (Stack:%x), stack processing failure = %d.", + task->tcb_addr, + task->stack_start, + ret); + } + return ret; +} + +static int elf_process_note_segment(core_dump_elf_t *self, int notes_size) +{ + int ret; + elf_phdr seg_hdr = { 0 }; + + if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) { + // segment header for PR_STATUS notes + seg_hdr.p_type = PT_NOTE; + seg_hdr.p_vaddr = 0; + seg_hdr.p_paddr = 0; + seg_hdr.p_filesz = notes_size; + seg_hdr.p_memsz = notes_size; + seg_hdr.p_flags = (PF_R | PF_W); + ret = elf_write_segment_header(self, &seg_hdr); + ELF_CHECK_ERR((ret > 0), ret, "NOTE segment header write failure, returned (%d).", ret); + self->elf_next_data_offset += notes_size; + return sizeof(seg_hdr); + } else if (self->elf_stage == ELF_STAGE_CALC_SPACE) { + notes_size += sizeof(seg_hdr); + } else { + // in "Place Data" phase segment body is been already filled by other functions + ESP_COREDUMP_LOG_PROCESS("Add NOTE segment, size=%d, start_off=0x%x", + notes_size, self->elf_next_data_offset); + self->elf_next_data_offset += notes_size; + } + return (int)notes_size; +} + +static int elf_process_tasks_regs(core_dump_elf_t *self, void* frame, + core_dump_task_header_t* tasks, + uint32_t task_num) +{ + int len = 0; + + uint32_t curr_task_index = elf_get_current_task_index(tasks, task_num); + if (curr_task_index == COREDUMP_CURR_TASK_NOT_FOUND) { + ESP_COREDUMP_LOG_PROCESS("The current crashed task is broken."); + curr_task_index = 0; + } + + // place current task dump first + int ret = elf_process_task_regdump(self, frame, &tasks[curr_task_index]); + if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) { + // when writing segments headers this function writes nothing + ELF_CHECK_ERR((ret >= 0), ret, "Task #%d, PR_STATUS write failed, return (%d).", curr_task_index, ret); + } else { + ELF_CHECK_ERR((ret > 0), ret, "Task #%d, PR_STATUS write failed, return (%d).", curr_task_index, ret); + } + len += ret; + + // processes PR_STATUS and register dump for each task + // each call to the processing function appends PR_STATUS note into note segment + // and writes data or updates the segment note header accordingly (if phdr is set) + for (int task_id = 0; task_id < task_num; task_id++) { + if (task_id == curr_task_index) { + continue; // skip current task (already processed) + } + ret = elf_process_task_regdump(self, frame, &tasks[task_id]); + if (self->elf_stage == ELF_STAGE_PLACE_HEADERS) { + // when writing segments headers this function writes nothing + ELF_CHECK_ERR((ret >= 0), ret, "Task #%d, PR_STATUS write failed, return (%d).", task_id, ret); + } else { + ELF_CHECK_ERR((ret > 0), ret, "Task #%d, PR_STATUS write failed, return (%d).", task_id, ret); + } + len += ret; + } + ret = elf_process_note_segment(self, len); + ELF_CHECK_ERR((ret > 0), ret, + "PR_STATUS note segment processing failure, returned(%d).", ret); + + if (esp_core_dump_in_isr_context()) { + if (self->elf_stage == ELF_STAGE_CALC_SPACE) { + // in this stage we can safely replace task's stack with IRQ's one + // if task had corrupted stack it was replaced with fake one in HW dependent code called by elf_process_task_regdump() + // in the "write data" stage registers from ISR's stack will be saved in PR_STATUS + self->interrupted_task.stack_start = tasks[curr_task_index].stack_start; + self->interrupted_task.stack_end = tasks[curr_task_index].stack_end; + uint32_t isr_stk_end = esp_core_dump_get_isr_stack_end(); + ESP_COREDUMP_LOG_PROCESS("Add ISR stack %lu (%x - %x)", isr_stk_end - (uint32_t)frame, (uint32_t)frame, isr_stk_end); + tasks[curr_task_index].stack_start = (uint32_t)frame; + tasks[curr_task_index].stack_end = isr_stk_end; + } + + // actually we write current task's stack here which was replaced by ISR's + len = elf_add_stack(self, &self->interrupted_task); + ELF_CHECK_ERR((len > 0), len, "Interrupted task stack write failed, return (%d).", len); + ret += len; + } + return ret; +} + +static int elf_write_tasks_data(core_dump_elf_t *self, void* frame, + core_dump_task_header_t* tasks, + uint32_t task_num) +{ + int elf_len = 0; + int task_id; + int ret = ELF_PROC_ERR_OTHER; + + ELF_CHECK_ERR((frame && tasks), ELF_PROC_ERR_OTHER, "Invalid input data."); + + ret = elf_process_tasks_regs(self, frame, tasks, task_num); + ELF_CHECK_ERR((ret > 0), ret, "Tasks regs addition failed, return (%d).", ret); + elf_len += ret; + self->bad_tasks_num = 0; // reset bad task counter + + // processes all task's stack data and writes segment data into partition + // if flash configuration is set + for (task_id = 0; task_id < task_num; task_id++) { + ret = elf_process_task_tcb(self, &tasks[task_id]); + ELF_CHECK_ERR((ret > 0), ret, + "Task #%d, TCB write failed, return (%d).", task_id, ret); + elf_len += ret; + ret = elf_process_task_stack(self, &tasks[task_id]); + ELF_CHECK_ERR((ret != ELF_PROC_ERR_WRITE_FAIL), ELF_PROC_ERR_WRITE_FAIL, + "Task #%d, stack write failed, return (%d).", task_id, ret); + elf_len += ret; + } + return elf_len; +} + +static int elf_write_core_dump_info(core_dump_elf_t *self) +{ + void *extra_info; + + int data_len = (int)sizeof(self->elf_version_info.app_elf_sha256); + data_len = esp_ota_get_app_elf_sha256((char*)self->elf_version_info.app_elf_sha256, (size_t)data_len); + ESP_COREDUMP_LOG_PROCESS("Application SHA256='%s', length=%d.", + self->elf_version_info.app_elf_sha256, data_len); + self->elf_version_info.version = COREDUMP_VERSION; + int ret = elf_add_note(self, + "ESP_CORE_DUMP_INFO", + ELF_ESP_CORE_DUMP_INFO_TYPE, + &self->elf_version_info, + sizeof(self->elf_version_info)); + ELF_CHECK_ERR((ret > 0), ret, "Version info note write failed. Returned (%d).", ret); + data_len = ret; + + uint32_t extra_info_len = esp_core_dump_get_extra_info(&extra_info); + if (extra_info_len == 0) { + ESP_COREDUMP_LOGE("Zero size extra info!"); + return ELF_PROC_ERR_OTHER; + } + + ret = elf_add_note(self, + "EXTRA_INFO", + ELF_ESP_CORE_DUMP_EXTRA_INFO_TYPE, + extra_info, + extra_info_len); + ELF_CHECK_ERR((ret > 0), ret, "Extra info note write failed. Returned (%d).", ret); + data_len += ret; + + ret = elf_process_note_segment(self, data_len); + ELF_CHECK_ERR((ret > 0), ret, + "EXTRA_INFO note segment processing failure, returned(%d).", ret); + return ret; +} + +static int esp_core_dump_do_write_elf_pass(core_dump_elf_t *self, void* frame, + core_dump_task_header_t* tasks, + uint32_t task_num) +{ + int tot_len = 0; + + int data_sz = elf_write_file_header(self, ELF_SEG_HEADERS_COUNT(self, task_num)); + if (self->elf_stage == ELF_STAGE_PLACE_DATA) { + ELF_CHECK_ERR((data_sz >= 0), data_sz, "ELF header writing error, returned (%d).", data_sz); + } else { + ELF_CHECK_ERR((data_sz > 0), data_sz, "ELF header writing error, returned (%d).", data_sz); + } + tot_len += data_sz; + // Calculate whole size include headers for all tasks and main elf header + data_sz = elf_write_tasks_data(self, frame, tasks, task_num); + ELF_CHECK_ERR((data_sz > 0), data_sz, "ELF Size writing error, returned (%d).", data_sz); + tot_len += data_sz; + // write data with version control information and some extra info + // this should go after tasks processing + data_sz = elf_write_core_dump_info(self); + ELF_CHECK_ERR((data_sz > 0), data_sz, "Version info writing failed. Returned (%d).", data_sz); + tot_len += data_sz; + + return tot_len; +} + +esp_err_t esp_core_dump_write_elf(void *frame, core_dump_write_config_t *write_cfg) +{ + esp_err_t err = ESP_OK; + static core_dump_task_header_t tasks[CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM]; + static core_dump_elf_t self; + core_dump_header_t dump_hdr; + uint32_t tcb_sz = COREDUMP_TCB_SIZE, task_num; + int tot_len = sizeof(dump_hdr); + int write_len = sizeof(dump_hdr); + + ELF_CHECK_ERR((frame && write_cfg), ESP_ERR_INVALID_ARG, "Invalid input data."); + + task_num = esp_core_dump_get_tasks_snapshot(tasks, CONFIG_ESP32_CORE_DUMP_MAX_TASKS_NUM); + ESP_COREDUMP_LOGI("Found tasks: %d", task_num); + + self.write_cfg = write_cfg; + + esp_core_dump_init_extra_info(); + // On first pass (do not write actual data), but calculate data length needed to allocate memory + self.elf_stage = ELF_STAGE_CALC_SPACE; + ESP_COREDUMP_LOG_PROCESS("================= Calc data size ==============="); + int ret = esp_core_dump_do_write_elf_pass(&self, frame, tasks, task_num); + if (ret < 0) return ret; + tot_len += ret; + ESP_COREDUMP_LOG_PROCESS("Core dump tot_len=%lu, tasks processed: %d, broken tasks: %d", + tot_len, task_num, self.bad_tasks_num); + ESP_COREDUMP_LOG_PROCESS("============== Data size = %d bytes ============", tot_len); + + // Prepare write elf + if (write_cfg->prepare) { + err = write_cfg->prepare(write_cfg->priv, (uint32_t*)&tot_len); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to prepare core dump storage (%d)!", err); + return err; + } + } + + // Write start + if (write_cfg->start) { + err = write_cfg->start(write_cfg->priv); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to start core dump (%d)!", err); + return err; + } + } + + write_cfg->bad_tasks_num = self.bad_tasks_num; + + // Write core dump header + ALIGN(4, tot_len); + ALIGN(4, tcb_sz); + dump_hdr.data_len = tot_len; + dump_hdr.version = COREDUMP_VERSION; + dump_hdr.tasks_num = task_num; // broken tasks are repaired + dump_hdr.tcb_sz = tcb_sz; + dump_hdr.mem_segs_num = 0; + err = write_cfg->write(write_cfg->priv, + (void*)&dump_hdr, + sizeof(core_dump_header_t)); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to write core dump header (%d)!", err); + return err; + } + + self.elf_stage = ELF_STAGE_PLACE_HEADERS; + // set initial offset to elf segments data area + self.elf_next_data_offset = sizeof(elfhdr) + ELF_SEG_HEADERS_COUNT(&self, task_num) * sizeof(elf_phdr); + ret = esp_core_dump_do_write_elf_pass(&self, frame, tasks, task_num); + if (ret < 0) return ret; + write_len += ret; + ESP_COREDUMP_LOG_PROCESS("============== Headers size = %d bytes ============", write_len); + + self.elf_stage = ELF_STAGE_PLACE_DATA; + // set initial offset to elf segments data area, this is not necessary in this stage, just for pretty debug output + self.elf_next_data_offset = sizeof(elfhdr) + ELF_SEG_HEADERS_COUNT(&self, task_num) * sizeof(elf_phdr); + ret = esp_core_dump_do_write_elf_pass(&self, frame, tasks, task_num); + if (ret < 0) return ret; + write_len += ret; + ESP_COREDUMP_LOG_PROCESS("=========== Data written size = %d bytes ==========", write_len); + + // Get checksum size + write_len += esp_core_dump_checksum_finish(write_cfg->priv, NULL); + if (write_len != tot_len) { + ESP_COREDUMP_LOGD("Write ELF failed (wrong length): %d != %d.", tot_len, write_len); + } + // Write end, update checksum + if (write_cfg->end) { + err = write_cfg->end(write_cfg->priv); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to end core dump (%d)!", err); + return err; + } + } + return err; +} + +#endif //CONFIG_ESP32_COREDUMP_DATA_FORMAT_ELF diff --git a/components/espcoredump/src/core_dump_flash.c b/components/espcoredump/src/core_dump_flash.c index 569852536..c1de15a71 100644 --- a/components/espcoredump/src/core_dump_flash.c +++ b/components/espcoredump/src/core_dump_flash.c @@ -12,23 +12,15 @@ // See the License for the specific language governing permissions and // limitations under the License. #include -#include "esp32/rom/crc.h" #include "esp_partition.h" +#include "esp32/rom/crc.h" #include "esp_core_dump_priv.h" #include "esp_flash_internal.h" -#include "sdkconfig.h" - const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_flash"; #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH -typedef struct _core_dump_write_flash_data_t -{ - uint32_t off; // current offset in partition - core_dump_crc_t crc; // CRC of dumped data -} core_dump_write_flash_data_t; - typedef struct _core_dump_partition_t { // core dump partition start @@ -48,6 +40,17 @@ typedef struct _core_dump_flash_config_t // core dump flash data static core_dump_flash_config_t s_core_flash_config; +#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL +#define ESP_COREDUMP_FLASH_WRITE(_off_, _data_, _len_) spi_flash_write(_off_, _data_, _len_) +#define ESP_COREDUMP_FLASH_READ(_off_, _data_, _len_) spi_flash_read(_off_, _data_, _len_) +#define ESP_COREDUMP_FLASH_ERASE(_off_, _len_) spi_flash_erase_range(_off_, _len_) +#else +#define ESP_COREDUMP_FLASH_WRITE(_off_, _data_, _len_) esp_flash_write(esp_flash_default_chip, _data_, _off_, _len_) +#define ESP_COREDUMP_FLASH_READ(_off_, _data_, _len_) esp_flash_read(esp_flash_default_chip, _data_, _off_, _len_) +#define ESP_COREDUMP_FLASH_ERASE(_off_, _len_) esp_flash_erase_region(esp_flash_default_chip, _off_, _len_) +#endif + + static inline core_dump_crc_t esp_core_dump_calc_flash_config_crc(void) { return crc32_le(0, (uint8_t const *)&s_core_flash_config.partition, sizeof(s_core_flash_config.partition)); @@ -69,80 +72,87 @@ void esp_core_dump_flash_init(void) s_core_flash_config.partition_config_crc = esp_core_dump_calc_flash_config_crc(); } -static uint32_t esp_core_dump_write_flash_padded(size_t off, uint8_t *data, uint32_t data_size) +static esp_err_t esp_core_dump_flash_write_data(void *priv, uint8_t *data, uint32_t data_size) { esp_err_t err; - uint32_t data_len = 0, k, len; - union - { - uint8_t data8[4]; - uint32_t data32; - } rom_data; + core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv; + uint32_t written = 0, wr_sz; - data_len = (data_size / sizeof(uint32_t)) * sizeof(uint32_t); + assert((wr_data->off + data_size) < s_core_flash_config.partition.size); - assert(off >= s_core_flash_config.partition.start); - assert((off + data_len + (data_size % sizeof(uint32_t) ? sizeof(uint32_t) : 0)) <= - s_core_flash_config.partition.start + s_core_flash_config.partition.size); - -#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL - err = spi_flash_write(off, data, data_len); -#else - err = esp_flash_write(esp_flash_default_chip, data, off, data_len); -#endif - if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to write data to flash (%d)!", err); - return 0; + if (wr_data->cached_bytes) { + if ((sizeof(wr_data->cached_data)-wr_data->cached_bytes) > data_size) + wr_sz = data_size; + else + wr_sz = sizeof(wr_data->cached_data)-wr_data->cached_bytes; + // append to data cache + memcpy(&wr_data->cached_data.data8[wr_data->cached_bytes], data, wr_sz); + wr_data->cached_bytes += wr_sz; + if (wr_data->cached_bytes == sizeof(wr_data->cached_data)) { + err = ESP_COREDUMP_FLASH_WRITE(s_core_flash_config.partition.start + wr_data->off, &wr_data->cached_data, sizeof(wr_data->cached_data)); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to write cached data to flash (%d)!", err); + return err; + } + // update checksum according to padding + esp_core_dump_checksum_update(wr_data, &wr_data->cached_data, sizeof(wr_data->cached_data)); + // reset data cache + wr_data->cached_bytes = 0; + memset(&wr_data->cached_data, 0, sizeof(wr_data->cached_data)); + } + wr_data->off += sizeof(wr_data->cached_data); + written += wr_sz; + data_size -= wr_sz; } - len = data_size % sizeof(uint32_t); - if (len) { - // write last bytes with padding, actual TCB len can be retrieved by esptool from core dump header - rom_data.data32 = 0; - for (k = 0; k < len; k++) { - rom_data.data8[k] = *(data + data_len + k); - } -#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL - err = spi_flash_write(off + data_len, &rom_data, sizeof(uint32_t)); -#else - err = esp_flash_write(esp_flash_default_chip, &rom_data, off + data_len, sizeof(uint32_t)); -#endif + wr_sz = (data_size / sizeof(wr_data->cached_data)) * sizeof(wr_data->cached_data); + if (wr_sz) { + err = ESP_COREDUMP_FLASH_WRITE(s_core_flash_config.partition.start + wr_data->off, data + written, wr_sz); if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to finish write data to flash (%d)!", err); - return 0; + ESP_COREDUMP_LOGE("Failed to write data to flash (%d)!", err); + return err; } - data_len += sizeof(uint32_t); + // update checksum of data written + esp_core_dump_checksum_update(wr_data, data + written, wr_sz); + wr_data->off += wr_sz; + written += wr_sz; + data_size -= wr_sz; } - return data_len; + if (data_size > 0) { + // append to data cache + memcpy(&wr_data->cached_data, data + written, data_size); + wr_data->cached_bytes = data_size; + } + + return ESP_OK; } static esp_err_t esp_core_dump_flash_write_prepare(void *priv, uint32_t *data_len) { esp_err_t err; uint32_t sec_num; - core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv; + core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv; + uint32_t cs_len; + cs_len = esp_core_dump_checksum_finish(wr_data, NULL); // check for available space in partition - if ((*data_len + sizeof(uint32_t)) > s_core_flash_config.partition.size) { + if ((*data_len + cs_len) > s_core_flash_config.partition.size) { ESP_COREDUMP_LOGE("Not enough space to save core dump!"); return ESP_ERR_NO_MEM; } - // add space for CRC - *data_len += sizeof(core_dump_crc_t); + // add space for checksum + *data_len += cs_len; - memset(wr_data, 0, sizeof(*wr_data)); + memset(wr_data, 0, sizeof(core_dump_write_data_t)); sec_num = *data_len / SPI_FLASH_SEC_SIZE; if (*data_len % SPI_FLASH_SEC_SIZE) { sec_num++; } + ESP_COREDUMP_LOGI("Erase flash %d bytes @ 0x%x", sec_num * SPI_FLASH_SEC_SIZE, s_core_flash_config.partition.start + 0); assert(sec_num * SPI_FLASH_SEC_SIZE <= s_core_flash_config.partition.size); -#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL - err = spi_flash_erase_range(s_core_flash_config.partition.start + 0, sec_num * SPI_FLASH_SEC_SIZE); -#else - err = esp_flash_erase_region(esp_flash_default_chip, s_core_flash_config.partition.start + 0, sec_num * SPI_FLASH_SEC_SIZE); -#endif + err = ESP_COREDUMP_FLASH_ERASE(s_core_flash_config.partition.start + 0, sec_num * SPI_FLASH_SEC_SIZE); if (err != ESP_OK) { ESP_COREDUMP_LOGE("Failed to erase flash (%d)!", err); return err; @@ -150,81 +160,70 @@ static esp_err_t esp_core_dump_flash_write_prepare(void *priv, uint32_t *data_le return err; } -static esp_err_t esp_core_dump_flash_write_word(core_dump_write_flash_data_t *wr_data, uint32_t word) -{ - esp_err_t err = ESP_OK; - uint32_t data32 = word; - - assert(wr_data->off + sizeof(uint32_t) <= s_core_flash_config.partition.size); -#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL - err = spi_flash_write(s_core_flash_config.partition.start + wr_data->off, &data32, sizeof(uint32_t)); -#else - err = esp_flash_write(esp_flash_default_chip, &data32, s_core_flash_config.partition.start + wr_data->off, sizeof(uint32_t)); -#endif - if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to write to flash (%d)!", err); - return err; - } - wr_data->off += sizeof(uint32_t); - - return err; -} - static esp_err_t esp_core_dump_flash_write_start(void *priv) { + core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv; + esp_core_dump_checksum_init(wr_data); return ESP_OK; } static esp_err_t esp_core_dump_flash_write_end(void *priv) { - core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv; + esp_err_t err; + core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv; + void* checksum; + uint32_t cs_len = esp_core_dump_checksum_finish(wr_data, &checksum); + + // flush cached bytes with zero padding + if (wr_data->cached_bytes) { + err = ESP_COREDUMP_FLASH_WRITE(s_core_flash_config.partition.start + wr_data->off, &wr_data->cached_data, sizeof(wr_data->cached_data)); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to flush cached data to flash (%d)!", err); + return err; + } + // update checksum according to padding + esp_core_dump_checksum_update(wr_data, &wr_data->cached_data, sizeof(wr_data->cached_data)); + wr_data->off += sizeof(wr_data->cached_data); + } + err = ESP_COREDUMP_FLASH_WRITE(s_core_flash_config.partition.start + wr_data->off, checksum, cs_len); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to flush cached data to flash (%d)!", err); + return err; + } + wr_data->off += cs_len; + ESP_COREDUMP_LOGI("Write end offset 0x%x, check sum length %d", wr_data->off, cs_len); #if LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG union { - uint8_t data8[16]; - uint32_t data32[4]; + uint8_t data8[sizeof(core_dump_header_t)]; + uint32_t data32[sizeof(core_dump_header_t)/sizeof(uint32_t)]; } rom_data; - -#ifdef CONFIG_SPI_FLASH_USE_LEGACY_IMPL - esp_err_t err = spi_flash_read(s_core_flash_config.partition.start + 0, &rom_data, sizeof(rom_data)); -#else - esp_err_t err = esp_flash_read(esp_flash_default_chip, &rom_data, s_core_flash_config.partition.start + 0, sizeof(rom_data)); -#endif + err = ESP_COREDUMP_FLASH_READ(s_core_flash_config.partition.start + 0, &rom_data, sizeof(rom_data)); if (err != ESP_OK) { - ESP_COREDUMP_LOGE("Failed to read flash (%d)!", err); + ESP_COREDUMP_LOGE("Failed to read back coredump header (%d)!", err); return err; } else { - ESP_COREDUMP_LOG_PROCESS("Data from flash:"); - for (uint32_t i = 0; i < sizeof(rom_data)/sizeof(rom_data.data32[0]); i++) { - ESP_COREDUMP_LOG_PROCESS("%x", rom_data.data32[i]); + ESP_COREDUMP_LOG_PROCESS("Core dump header words from flash:"); + for (uint32_t i = 0; i < sizeof(rom_data)/sizeof(uint32_t); i++) { + ESP_COREDUMP_LOG_PROCESS("0x%x", rom_data.data32[i]); } } -#endif - // write core dump CRC - ESP_COREDUMP_LOG_PROCESS("Dump data CRC = 0x%x", wr_data->crc); - return esp_core_dump_flash_write_word(wr_data, wr_data->crc); -} - -static esp_err_t esp_core_dump_flash_write_data(void *priv, void * data, uint32_t data_len) -{ - esp_err_t err = ESP_OK; - core_dump_write_flash_data_t *wr_data = (core_dump_write_flash_data_t *)priv; - - uint32_t len = esp_core_dump_write_flash_padded(s_core_flash_config.partition.start + wr_data->off, data, data_len); - if (len != data_len) { - return ESP_FAIL; + uint32_t crc; + err = ESP_COREDUMP_FLASH_READ(s_core_flash_config.partition.start + wr_data->off - cs_len, &crc, sizeof(crc)); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to read back checksum word (%d)!", err); + return err; + } else { + ESP_COREDUMP_LOG_PROCESS("Checksum word from flash: 0x%x @ 0x%x", crc, wr_data->off - cs_len); } - - wr_data->off += len; - wr_data->crc = crc32_le(wr_data->crc, data, data_len); - +#endif return err; } -void esp_core_dump_to_flash(XtExcFrame *frame) +void esp_core_dump_to_flash(void *frame) { static core_dump_write_config_t wr_cfg; - static core_dump_write_flash_data_t wr_data; + static core_dump_write_data_t wr_data; core_dump_crc_t crc = esp_core_dump_calc_flash_config_crc(); if (s_core_flash_config.partition_config_crc != crc) { @@ -245,11 +244,11 @@ void esp_core_dump_to_flash(XtExcFrame *frame) wr_cfg.prepare = esp_core_dump_flash_write_prepare; wr_cfg.start = esp_core_dump_flash_write_start; wr_cfg.end = esp_core_dump_flash_write_end; - wr_cfg.write = esp_core_dump_flash_write_data; + wr_cfg.write = (esp_core_dump_flash_write_data_t)esp_core_dump_flash_write_data; wr_cfg.priv = &wr_data; ESP_COREDUMP_LOGI("Save core dump to flash..."); - esp_core_dump_write((void*)frame, &wr_cfg); + esp_core_dump_write(frame, &wr_cfg); ESP_COREDUMP_LOGI("Core dump has been saved to flash."); } #endif diff --git a/components/espcoredump/src/core_dump_port.c b/components/espcoredump/src/core_dump_port.c index 1e6ab6a90..1424a3fe6 100644 --- a/components/espcoredump/src/core_dump_port.c +++ b/components/espcoredump/src/core_dump_port.c @@ -1,4 +1,4 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,92 +14,544 @@ #include #include #include "soc/soc_memory_layout.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "freertos/xtensa_context.h" // for exception register stack structure #include "esp_core_dump_priv.h" const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_port"; +#define COREDUMP_EM_XTENSA 0x5E +#define COREDUMP_INVALID_CAUSE_VALUE 0xFFFF +#define COREDUMP_EXTRA_REG_NUM 16 +#define COREDUMP_FAKE_STACK_START 0x20000000 +#define COREDUMP_FAKE_STACK_LIMIT 0x30000000 + +#define COREDUMP_GET_REG_PAIR(reg_idx, reg_ptr) { *(uint32_t*)(reg_ptr++) = (uint32_t)reg_idx; \ + RSR(reg_idx, *(uint32_t*)(reg_ptr++)); \ + } + +// Enumeration of registers of exception stack frame +// and solicited stack frame +typedef enum +{ + // XT_SOL_EXIT = 0, + XT_SOL_PC = 1, + XT_SOL_PS = 2, + // XT_SOL_NEXT = 3, + XT_SOL_AR_START = 4, + XT_SOL_AR_NUM = 4, + // XT_SOL_FRMSZ = 8, + XT_STK_EXIT = 0, + XT_STK_PC = 1, + XT_STK_PS = 2, + XT_STK_AR_START = 3, + XT_STK_AR_NUM = 16, + XT_STK_SAR = 19, + XT_STK_EXCCAUSE = 20, + XT_STK_EXCVADDR = 21, + XT_STK_LBEG = 22, + XT_STK_LEND = 23, + XT_STK_LCOUNT = 24, + //XT_STK_FRMSZ = 25, +} stk_frame_t; + +// Xtensa ELF core file register set representation ('.reg' section). +// Copied from target-side ELF header . +typedef struct +{ + uint32_t pc; + uint32_t ps; + uint32_t lbeg; + uint32_t lend; + uint32_t lcount; + uint32_t sar; + uint32_t windowstart; + uint32_t windowbase; + uint32_t reserved[8+48]; + uint32_t ar[XCHAL_NUM_AREGS]; +} __attribute__((packed)) xtensa_gregset_t; + +typedef struct +{ + uint32_t reg_index; + uint32_t reg_val; +} __attribute__((packed)) core_dump_reg_pair_t; + +typedef struct +{ + uint32_t crashed_task_tcb; + core_dump_reg_pair_t exccause; + core_dump_reg_pair_t excvaddr; + core_dump_reg_pair_t extra_regs[COREDUMP_EXTRA_REG_NUM]; +} __attribute__((packed)) xtensa_extra_info_t; + +// Xtensa Program Status for GDB +typedef struct +{ + uint32_t si_signo; + uint32_t si_code; + uint32_t si_errno; + uint16_t pr_cursig; + uint16_t pr_pad0; + uint32_t pr_sigpend; + uint32_t pr_sighold; + uint32_t pr_pid; + uint32_t pr_ppid; + uint32_t pr_pgrp; + uint32_t pr_sid; + uint64_t pr_utime; + uint64_t pr_stime; + uint64_t pr_cutime; + uint64_t pr_cstime; +} __attribute__((packed)) xtensa_pr_status_t; + +typedef struct +{ + xtensa_pr_status_t pr_status; + xtensa_gregset_t regs; + // Todo: acc to xtensa_gregset_t number of regs must be 128, + // but gdb complains when it less than 129 + uint32_t reserved; +} __attribute__((packed)) xtensa_elf_reg_dump_t; + +extern uint8_t port_IntStack; + #if CONFIG_ESP32_ENABLE_COREDUMP -inline bool esp_task_stack_start_is_sane(uint32_t sp) +static uint32_t s_total_length = 0; + +static XtExcFrame s_fake_stack_frame = { + .pc = (UBaseType_t) COREDUMP_FAKE_STACK_START, // task entrypoint fake_ptr + .a0 = (UBaseType_t) 0, // to terminate GDB backtrace + .a1 = (UBaseType_t) (COREDUMP_FAKE_STACK_START + sizeof(XtExcFrame)), // physical top of stack frame + .exit = (UBaseType_t) 0, // user exception exit dispatcher + .ps = (PS_UM | PS_EXCM), + .exccause = (UBaseType_t) COREDUMP_INVALID_CAUSE_VALUE, +}; +static uint32_t s_fake_stacks_num; + +static xtensa_extra_info_t s_extra_info; + +#if ESP32_CORE_DUMP_STACK_SIZE > 0 +uint8_t s_coredump_stack[ESP32_CORE_DUMP_STACK_SIZE]; +uint8_t *s_core_dump_sp; + +static uint32_t esp_core_dump_free_stack_space(const uint8_t *pucStackByte) { - return !(sp < 0x3ffae010UL || sp > 0x3fffffffUL); + uint32_t ulCount = 0U; + while( *pucStackByte == (uint8_t)COREDUMP_STACK_FILL_BYTE ) { + pucStackByte -= portSTACK_GROWTH; + ulCount++; + } + ulCount /= (uint32_t)sizeof(uint8_t); + return (uint32_t)ulCount; +} +#endif + +void esp_core_dump_report_stack_usage(void) +{ +#if ESP32_CORE_DUMP_STACK_SIZE > 0 + uint32_t bytes_free = esp_core_dump_free_stack_space(s_coredump_stack); + ESP_COREDUMP_LOGD("Core dump used %u bytes on stack. %u bytes left free.", + s_core_dump_sp - s_coredump_stack - bytes_free, bytes_free); +#endif } -inline bool esp_tcb_addr_is_sane(uint32_t addr, uint32_t sz) +#if CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256 + +// function to calculate SHA256 for solid data array +int esp_core_dump_sha(mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen, + unsigned char output[32] ) { - //TODO: currently core dump supports TCBs in DRAM only, external SRAM not supported yet - return !(addr < 0x3ffae000UL || (addr + sz) > 0x40000000UL); + assert(input); + mbedtls_sha256_init(ctx); + if((mbedtls_sha256_starts_ret(ctx, 0) != 0)) goto exit; +#if CONFIG_MBEDTLS_HARDWARE_SHA + // set software mode for SHA calculation + ctx->mode = ESP_MBEDTLS_SHA256_SOFTWARE; +#endif + if((mbedtls_sha256_update_ret(ctx, input, ilen) != 0)) goto exit; + if((mbedtls_sha256_finish_ret(ctx, output) != 0)) goto exit; + esp_core_dump_print_sha256(DRAM_STR("Coredump SHA256"), (void*)output); + s_total_length = ilen; +exit: + mbedtls_sha256_free(ctx); + return ilen; +} + +void esp_core_dump_print_sha256(const char* msg, const uint8_t* sha_output) +{ + ets_printf(DRAM_STR("%s='"), msg); + for (int i = 0; i < COREDUMP_SHA256_LEN; i++) { + ets_printf(DRAM_STR("%02x"), sha_output[i]); + } + ets_printf(DRAM_STR("'\r\n")); +} +#endif + +void esp_core_dump_checksum_init(core_dump_write_data_t* wr_data) +{ + if (wr_data) { +#if CONFIG_ESP32_COREDUMP_CHECKSUM_CRC32 + wr_data->crc = 0; +#elif CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256 + mbedtls_sha256_init(&wr_data->ctx); + (void)mbedtls_sha256_starts_ret(&wr_data->ctx, 0); +#endif + s_total_length = 0; + } +} + +void esp_core_dump_checksum_update(core_dump_write_data_t* wr_data, void* data, size_t data_len) +{ + if (wr_data && data) { +#if CONFIG_ESP32_COREDUMP_CHECKSUM_CRC32 + wr_data->crc = crc32_le(wr_data->crc, data, data_len); +#elif CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256 +#if CONFIG_MBEDTLS_HARDWARE_SHA + // set software mode of SHA calculation + wr_data->ctx.mode = ESP_MBEDTLS_SHA256_SOFTWARE; +#endif + (void)mbedtls_sha256_update_ret(&wr_data->ctx, data, data_len); +#endif + s_total_length += data_len; // keep counter of cashed bytes + } else { + ESP_COREDUMP_LOGE("Wrong write data info!"); + } +} + +uint32_t esp_core_dump_checksum_finish(core_dump_write_data_t* wr_data, void** chs_ptr) +{ + // get core dump checksum + uint32_t chs_len = 0; +#if CONFIG_ESP32_COREDUMP_CHECKSUM_CRC32 + if (chs_ptr) { + wr_data->crc = wr_data->crc; + *chs_ptr = (void*)&wr_data->crc; + ESP_COREDUMP_LOG_PROCESS("Dump data CRC = 0x%x, offset = 0x%x", wr_data->crc, wr_data->off); + } + chs_len = sizeof(wr_data->crc); +#elif CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256 + if (chs_ptr) { + ESP_COREDUMP_LOG_PROCESS("Dump data offset = %d", wr_data->off); + (void)mbedtls_sha256_finish_ret(&wr_data->ctx, (uint8_t*)&wr_data->sha_output); + *chs_ptr = (void*)&wr_data->sha_output[0]; + mbedtls_sha256_free(&wr_data->ctx); + } + chs_len = sizeof(wr_data->sha_output); +#endif + ESP_COREDUMP_LOG_PROCESS("Total length of hashed data: %d!", s_total_length); + return chs_len; +} + +inline uint16_t esp_core_dump_get_arch_id() +{ + return COREDUMP_EM_XTENSA; +} + +inline bool esp_core_dump_mem_seg_is_sane(uint32_t addr, uint32_t sz) +{ + //TODO: currently core dump supports memory segments in DRAM only, external SRAM not supported yet + return esp_ptr_in_dram((void *)addr) && esp_ptr_in_dram((void *)(addr+sz-1)); +} + +inline bool esp_core_dump_task_stack_end_is_sane(uint32_t sp) +{ + //TODO: currently core dump supports stacks in DRAM only, external SRAM not supported yet + return esp_ptr_in_dram((void *)sp); +} + +inline bool esp_core_dump_tcb_addr_is_sane(uint32_t addr) +{ + return esp_core_dump_mem_seg_is_sane(addr, COREDUMP_TCB_SIZE); } uint32_t esp_core_dump_get_tasks_snapshot(core_dump_task_header_t* const tasks, - const uint32_t snapshot_size, uint32_t* const tcb_sz) + const uint32_t snapshot_size) { - uint32_t task_num = (uint32_t)uxTaskGetSnapshotAll((TaskSnapshot_t*)tasks, (UBaseType_t)snapshot_size, (UBaseType_t*)tcb_sz); + uint32_t tcb_sz; // unused + uint32_t task_num = (uint32_t)uxTaskGetSnapshotAll((TaskSnapshot_t*)tasks, + (UBaseType_t)snapshot_size, + (UBaseType_t*)&tcb_sz); return task_num; } -bool esp_core_dump_process_tcb(void *frame, core_dump_task_header_t *task_snaphort, uint32_t tcb_sz) +inline uint32_t esp_core_dump_get_isr_stack_end(void) { - XtExcFrame *exc_frame = (XtExcFrame*)frame; + return (uint32_t)((uint8_t *)&port_IntStack + (xPortGetCoreID()+1)*configISR_STACK_SIZE); +} - if (!esp_tcb_addr_is_sane((uint32_t)task_snaphort->tcb_addr, tcb_sz)) { - ESP_COREDUMP_LOG_PROCESS("Bad TCB addr %x!", task_snaphort->tcb_addr); +uint32_t esp_core_dump_get_stack(core_dump_task_header_t *task_snapshot, + uint32_t *stk_vaddr, uint32_t *stk_len) +{ + if (task_snapshot->stack_end > task_snapshot->stack_start) { + *stk_len = task_snapshot->stack_end - task_snapshot->stack_start; + *stk_vaddr = task_snapshot->stack_start; + } else { + *stk_len = task_snapshot->stack_start - task_snapshot->stack_end; + *stk_vaddr = task_snapshot->stack_end; + } + if (*stk_vaddr >= COREDUMP_FAKE_STACK_START && *stk_vaddr < COREDUMP_FAKE_STACK_LIMIT) { + return (uint32_t)&s_fake_stack_frame; + } + return *stk_vaddr; +} + +// The function creates small fake stack for task as deep as exception frame size +// It is required for gdb to take task into account but avoid back trace of stack. +// The espcoredump.py script is able to recognize that task is broken +static void *esp_core_dump_get_fake_stack(uint32_t *stk_len) +{ + *stk_len = sizeof(s_fake_stack_frame); + return (uint8_t*)COREDUMP_FAKE_STACK_START + sizeof(s_fake_stack_frame)*s_fake_stacks_num++; +} + +static core_dump_reg_pair_t *esp_core_dump_get_epc_regs(core_dump_reg_pair_t* src) +{ + uint32_t* reg_ptr = (uint32_t*)src; + // get InterruptException program counter registers + COREDUMP_GET_REG_PAIR(EPC_1, reg_ptr); + COREDUMP_GET_REG_PAIR(EPC_2, reg_ptr); + COREDUMP_GET_REG_PAIR(EPC_3, reg_ptr); + COREDUMP_GET_REG_PAIR(EPC_4, reg_ptr); + COREDUMP_GET_REG_PAIR(EPC_5, reg_ptr); + COREDUMP_GET_REG_PAIR(EPC_6, reg_ptr); + COREDUMP_GET_REG_PAIR(EPC_7, reg_ptr); + return (core_dump_reg_pair_t*)reg_ptr; +} + +static core_dump_reg_pair_t *esp_core_dump_get_eps_regs(core_dump_reg_pair_t* src) +{ + uint32_t* reg_ptr = (uint32_t*)src; + // get InterruptException processor state registers + COREDUMP_GET_REG_PAIR(EPS_2, reg_ptr); + COREDUMP_GET_REG_PAIR(EPS_3, reg_ptr); + COREDUMP_GET_REG_PAIR(EPS_4, reg_ptr); + COREDUMP_GET_REG_PAIR(EPS_5, reg_ptr); + COREDUMP_GET_REG_PAIR(EPS_6, reg_ptr); + COREDUMP_GET_REG_PAIR(EPS_7, reg_ptr); + return (core_dump_reg_pair_t*)reg_ptr; +} + +// Returns list of registers (in GDB format) from xtensa stack frame +static esp_err_t esp_core_dump_get_regs_from_stack(void* stack_addr, + size_t size, + xtensa_gregset_t* regs) +{ + XtExcFrame* exc_frame = (XtExcFrame*)stack_addr; + uint32_t* stack_arr = (uint32_t*)stack_addr; + + if (size < sizeof(XtExcFrame)) { + ESP_COREDUMP_LOGE("Too small stack to keep frame: %d bytes!", size); + return ESP_FAIL; + } + + // Stack frame type indicator is always the first item + uint32_t rc = exc_frame->exit; + + // is this current crashed task? + if (rc == COREDUMP_CURR_TASK_MARKER) + { + s_extra_info.exccause.reg_val = exc_frame->exccause; + s_extra_info.exccause.reg_index = EXCCAUSE; + s_extra_info.excvaddr.reg_val = exc_frame->excvaddr; + s_extra_info.excvaddr.reg_index = EXCVADDR; + // get InterruptException registers into extra_info + core_dump_reg_pair_t *regs_ptr = esp_core_dump_get_eps_regs(s_extra_info.extra_regs); + esp_core_dump_get_epc_regs(regs_ptr); + } else { + // initialize EXCCAUSE and EXCVADDR members of frames for all the tasks, + // except for the crashed one + exc_frame->exccause = COREDUMP_INVALID_CAUSE_VALUE; + exc_frame->excvaddr = 0; + } + + if (rc != 0) { + regs->pc = exc_frame->pc; + regs->ps = exc_frame->ps; + for (int i = 0; i < XT_STK_AR_NUM; i++) { + regs->ar[i] = stack_arr[XT_STK_AR_START + i]; + } + regs->sar = exc_frame->sar; +#if CONFIG_IDF_TARGET_ESP32 + regs->lbeg = exc_frame->lbeg; + regs->lend = exc_frame->lend; + regs->lcount = exc_frame->lcount; +#endif + // FIXME: crashed and some running tasks (e.g. prvIdleTask) have EXCM bit set + // and GDB can not unwind callstack properly (it implies not windowed call0) + if (regs->ps & PS_UM) { + regs->ps &= ~PS_EXCM; + } + } else { + regs->pc = stack_arr[XT_SOL_PC]; + regs->ps = stack_arr[XT_SOL_PS]; + for (int i = 0; i < XT_SOL_AR_NUM; i++) { + regs->ar[i] = stack_arr[XT_SOL_AR_START + i]; + } + regs->pc = (regs->pc & 0x3fffffff); + if (regs->pc & 0x80000000) { + regs->pc = (regs->pc & 0x3fffffff); + } + if (regs->ar[0] & 0x80000000) { + regs->ar[0] = (regs->ar[0] & 0x3fffffff); + } + } + return ESP_OK; +} + +uint32_t esp_core_dump_get_task_regs_dump(core_dump_task_header_t *task, void **reg_dump) +{ + uint32_t stack_vaddr, stack_paddr, stack_len; + static xtensa_elf_reg_dump_t s_reg_dump = { 0 }; + + stack_paddr = esp_core_dump_get_stack(task, &stack_vaddr, &stack_len); + + ESP_COREDUMP_LOG_PROCESS("Add regs for task 0x%x", task->tcb_addr); + + // initialize program status for the task + s_reg_dump.pr_status.pr_cursig = 0; + s_reg_dump.pr_status.pr_pid = (uint32_t)task->tcb_addr; + + // fill the gdb registers structure from stack + esp_err_t err = esp_core_dump_get_regs_from_stack((void*)stack_paddr, + stack_len, + &s_reg_dump.regs); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Error while registers processing."); + } + *reg_dump = &s_reg_dump; + return sizeof(s_reg_dump); +} + +inline void* esp_core_dump_get_current_task_handle() +{ + return (void*)xTaskGetCurrentTaskHandleForCPU(xPortGetCoreID()); +} + +bool esp_core_dump_check_task(void *frame, + core_dump_task_header_t *task, + bool* is_current, + bool* stack_is_valid) +{ + XtExcFrame *exc_frame = frame; + bool is_curr_task = false; + bool stack_is_sane = false; + uint32_t stk_size = 0; + + if (!esp_core_dump_tcb_addr_is_sane((uint32_t)task->tcb_addr)) { + ESP_COREDUMP_LOG_PROCESS("Bad TCB addr=%x!", task->tcb_addr); return false; } - if (task_snaphort->tcb_addr == xTaskGetCurrentTaskHandleForCPU(xPortGetCoreID())) { - // Set correct stack top for current task - task_snaphort->stack_start = (uint32_t)exc_frame; - // This field is not initialized for crashed task, but stack frame has the structure of interrupt one, - // so make workaround to allow espcoredump to parse it properly. - if (exc_frame->exit == 0) - exc_frame->exit = -1; - ESP_COREDUMP_LOG_PROCESS("Current task %x EXIT/PC/PS/A0/SP %x %x %x %x %x", - task_snaphort->tcb_addr, exc_frame->exit, exc_frame->pc, exc_frame->ps, exc_frame->a0, exc_frame->a1); - } - else { - XtSolFrame *task_frame = (XtSolFrame *)task_snaphort->stack_start; - if (task_frame->exit == 0) { - ESP_COREDUMP_LOG_PROCESS("Task %x EXIT/PC/PS/A0/SP %x %x %x %x %x", - task_snaphort->tcb_addr, task_frame->exit, task_frame->pc, task_frame->ps, task_frame->a0, task_frame->a1); + + is_curr_task = task->tcb_addr == esp_core_dump_get_current_task_handle(); + if (is_curr_task) { + // Set correct stack top for current task; only modify if we came from the task, + // and not an ISR that crashed. + if (!xPortInterruptedFromISRContext()) { + task->stack_start = (uint32_t)exc_frame; } - else { + exc_frame->exit = COREDUMP_CURR_TASK_MARKER; + s_extra_info.crashed_task_tcb = (uint32_t)task->tcb_addr; + } + + stack_is_sane = esp_core_dump_check_stack(task->stack_start, task->stack_end); + if (!stack_is_sane) { + // Skip saving of invalid task if stack corrupted + ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), stack is corrupted (%x, %x)", + task->tcb_addr, + task->stack_start, + task->stack_end); + task->stack_start = (uint32_t)esp_core_dump_get_fake_stack(&stk_size); + task->stack_end = (uint32_t)(task->stack_start + stk_size); + ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), use start, end (%x, %x)", + task->tcb_addr, + task->stack_start, + task->stack_end); + } + + if (is_curr_task) { + if (!stack_is_sane) + ESP_COREDUMP_LOG_PROCESS("Current task 0x%x is broken!", task->tcb_addr); + ESP_COREDUMP_LOG_PROCESS("Current task (TCB:%x), EXIT/PC/PS/A0/SP %x %x %x %x %x", + task->tcb_addr, + exc_frame->exit, + exc_frame->pc, + exc_frame->ps, + exc_frame->a0, + exc_frame->a1); + } else { + XtSolFrame *task_frame = (XtSolFrame *)task->stack_start; + if (stack_is_sane) { + if (task_frame->exit == 0) { + ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), EXIT/PC/PS/A0/SP %x %x %x %x %x", + task->tcb_addr, + task_frame->exit, + task_frame->pc, + task_frame->ps, + task_frame->a0, + task_frame->a1); + } else { #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH - XtExcFrame *task_frame2 = (XtExcFrame *)task_snaphort->stack_start; - ESP_COREDUMP_LOG_PROCESS("Task %x EXIT/PC/PS/A0/SP %x %x %x %x %x", - task_snaphort->tcb_addr, task_frame2->exit, task_frame2->pc, task_frame2->ps, task_frame2->a0, task_frame2->a1); + XtExcFrame *task_frame2 = (XtExcFrame *)task->stack_start; + task_frame2->exccause = COREDUMP_INVALID_CAUSE_VALUE; + ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x) EXIT/PC/PS/A0/SP %x %x %x %x %x", + task->tcb_addr, + task_frame2->exit, + task_frame2->pc, + task_frame2->ps, + task_frame2->a0, + task_frame2->a1); #endif + } + } else { + ESP_COREDUMP_LOG_PROCESS("Task (TCB:%x), stack_start=%x is incorrect, skip registers printing.", + task->tcb_addr, task->stack_start); + } } + + if (is_current) { + *is_current = is_curr_task; + } + if (stack_is_valid) { + *stack_is_valid = stack_is_sane; + } + return true; } -bool esp_core_dump_process_stack(core_dump_task_header_t* task_snaphort, uint32_t *length) +bool esp_core_dump_check_stack(uint32_t stack_start, uint32_t stack_end) { - uint32_t len = 0; + uint32_t len = stack_end - stack_start; bool task_is_valid = false; - len = (uint32_t)task_snaphort->stack_end - (uint32_t)task_snaphort->stack_start; // Check task's stack - if (!esp_stack_ptr_is_sane(task_snaphort->stack_start) || - !esp_task_stack_start_is_sane((uint32_t)task_snaphort->stack_end) || + if (!esp_stack_ptr_is_sane(stack_start) || !esp_core_dump_task_stack_end_is_sane(stack_end) || (len > COREDUMP_MAX_TASK_STACK_SIZE)) { - // Check if current task stack corrupted - if (task_snaphort->tcb_addr == xTaskGetCurrentTaskHandleForCPU(xPortGetCoreID())) { - ESP_COREDUMP_LOG_PROCESS("Crashed task will be skipped!"); - } - ESP_COREDUMP_LOG_PROCESS("Corrupted TCB %x: stack len %lu, top %x, end %x!", - task_snaphort->tcb_addr, len, task_snaphort->stack_start, task_snaphort->stack_end); - task_snaphort->tcb_addr = 0; // make TCB addr invalid to skip it in dump + // Check if current task stack is corrupted task_is_valid = false; } else { - ESP_COREDUMP_LOG_PROCESS("Stack len = %lu (%x %x)", len, - task_snaphort->stack_start, task_snaphort->stack_end); - // Take stack padding into account - if (length) { - *length = (len + sizeof(uint32_t) - 1) & ~(sizeof(uint32_t) - 1); - } + ESP_COREDUMP_LOG_PROCESS("Stack len = %lu (%x %x)", len, stack_start, stack_end); task_is_valid = true; } return task_is_valid; } +void esp_core_dump_init_extra_info() +{ + s_extra_info.crashed_task_tcb = COREDUMP_CURR_TASK_MARKER; + // Initialize exccause register to default value (required if current task corrupted) + s_extra_info.exccause.reg_val = COREDUMP_INVALID_CAUSE_VALUE; + s_extra_info.exccause.reg_index = EXCCAUSE; +} + +uint32_t esp_core_dump_get_extra_info(void **info) +{ + *info = &s_extra_info; + return sizeof(s_extra_info); +} + #endif diff --git a/components/espcoredump/src/core_dump_uart.c b/components/espcoredump/src/core_dump_uart.c index 0c89ca6c6..ebd44b3c1 100644 --- a/components/espcoredump/src/core_dump_uart.c +++ b/components/espcoredump/src/core_dump_uart.c @@ -1,4 +1,4 @@ -// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -16,9 +16,12 @@ #include "soc/gpio_periph.h" #include "driver/gpio.h" #include "esp_core_dump_priv.h" +// TODO: move chip dependent part to portable code #if CONFIG_IDF_TARGET_ESP32 +#include "esp32/rom/crc.h" #include "esp32/clk.h" #elif CONFIG_IDF_TARGET_ESP32S2BETA +#include "esp32s2beta/rom/crc.h" #include "esp32s2beta/clk.h" #endif @@ -54,22 +57,49 @@ static void esp_core_dump_b64_encode(const uint8_t *src, uint32_t src_len, uint8 static esp_err_t esp_core_dump_uart_write_start(void *priv) { esp_err_t err = ESP_OK; + core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv; + esp_core_dump_checksum_init(wr_data); ets_printf(DRAM_STR("================= CORE DUMP START =================\r\n")); return err; } +static esp_err_t esp_core_dump_uart_write_prepare(void *priv, uint32_t *data_len) +{ + core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv; + uint32_t cs_len; + cs_len = esp_core_dump_checksum_finish(wr_data, NULL); + *data_len += cs_len; + return ESP_OK; +} + static esp_err_t esp_core_dump_uart_write_end(void *priv) { esp_err_t err = ESP_OK; + char buf[64 + 4]; + void* cs_addr = NULL; + core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv; + if (wr_data) { + size_t cs_len = esp_core_dump_checksum_finish(wr_data, &cs_addr); + wr_data->off += cs_len; + esp_core_dump_b64_encode((const uint8_t *)cs_addr, cs_len, (uint8_t*)&buf[0]); + ets_printf(DRAM_STR("%s\r\n"), buf); + } ets_printf(DRAM_STR("================= CORE DUMP END =================\r\n")); +#if CONFIG_ESP32_COREDUMP_CHECKSUM_SHA256 + if (cs_addr) { + esp_core_dump_print_sha256(DRAM_STR("Coredump SHA256"), (uint8_t*)(cs_addr)); + } +#endif return err; } static esp_err_t esp_core_dump_uart_write_data(void *priv, void * data, uint32_t data_len) { esp_err_t err = ESP_OK; - char buf[64 + 4], *addr = data; + char buf[64 + 4]; + char *addr = data; char *end = addr + data_len; + core_dump_write_data_t *wr_data = (core_dump_write_data_t *)priv; while (addr < end) { size_t len = end - addr; @@ -82,6 +112,10 @@ static esp_err_t esp_core_dump_uart_write_data(void *priv, void * data, uint32_t ets_printf(DRAM_STR("%s\r\n"), buf); } + if (wr_data) { + wr_data->off += data_len; + esp_core_dump_checksum_update(wr_data, data, data_len); + } return err; } @@ -99,16 +133,18 @@ static int esp_core_dump_uart_get_char(void) { void esp_core_dump_to_uart(XtExcFrame *frame) { core_dump_write_config_t wr_cfg; + core_dump_write_data_t wr_data; uint32_t tm_end, tm_cur; int ch; memset(&wr_cfg, 0, sizeof(wr_cfg)); - wr_cfg.prepare = NULL; + wr_cfg.prepare = esp_core_dump_uart_write_prepare; wr_cfg.start = esp_core_dump_uart_write_start; wr_cfg.end = esp_core_dump_uart_write_end; wr_cfg.write = esp_core_dump_uart_write_data; - wr_cfg.priv = NULL; + wr_cfg.priv = (void*)&wr_data; + // TODO: move chip dependent code to portable part //Make sure txd/rxd are enabled // use direct reg access instead of gpio_pullup_dis which can cause exception when flash cache is disabled REG_CLR_BIT(GPIO_PIN_REG_1, FUN_PU); diff --git a/components/espcoredump/test/coredump.b64 b/components/espcoredump/test/coredump.b64 index 3dc766f33..bd06aec60 100644 --- a/components/espcoredump/test/coredump.b64 +++ b/components/espcoredump/test/coredump.b64 @@ -1,192 +1,369 @@ -YCEAAAEAAAAKAAAAfAEAAA== -dFT7PwCd+z/0nvs/ -cJ37P5Ce+z/cHQAAeC/7P3gv+z90VPs/cC/7PxIAAADOzs7Ozs7OznRU+z8AAAAA -BwAAAPiW+z91bmFsaWduZWRfcHRyX3QAAQAAAPSe+z8AAAAAIAAGAA8AAADOzs7O -BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/Oj6P2Tp+j/M6fo/ -AAAAAAAAAAABAAAAAAAAAGg6QD8AAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA +UD0AAAIAAAAKAAAAfAEAAAAAAAA= +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= +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoGr7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAfQ4NQCAIBgD9FABADRUAQP////8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFgODYDgtPs/ +AgAAACy1+z8gtfs/cOn6PwAAAAAAAAAABQAAAK3///8gAAAAIGv7PwEAAACAAAAA +AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkKz7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1pIAQCAFBgD9FABADRUAQP////8XAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA+TAIAwqvs/ +rKr7PwAAAAAAAAAAwBsEAFcAAAA3AAAAnAH+PwAA9D8AAAAAAAAAAAAAAADDGwQA +AAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATID7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABogOQCAABgBsxABAd8QAQP////8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM44DYBQf/s/ +AAAAAAAAAAABAAAAAQAAgAMAAAAjAAYA1JcIgEB/+z8DAAAAIwgGACAIBgABAAAA +IAgGAOCO+z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsHj7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABogOQCAFBgBsxABAd8QAQP////8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM44DYCwd/s/ +AAAAAAMAAAABAAAAAQAAgAMAAAAjAAYAepEIgJB3+z8Ucfs/SB0AQCAEBgABAAAA +IAQGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFGn7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASBQIQCAFBgD9FABADRUAQPn///8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALqbCIAgaPs/ +AAAAAFojBADUlwiAAFf7PwMAAAAjCAYASBQIgABo+z/cAPA/AQAAADgA+z8BAAAA +IAUGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmGz7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASBQIQCADBgD9FABADRUAQPj///8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALqbCIBAvfs/ +AAAAAFojBADtWA2A4Kn7PwAIAAAEAPs/SBQIgCC9+z/cAPA/AQAAADgA+z8BAAAA +IAMGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9Ir7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASBQIQCAABgAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF2pCIDgifs/ +AAAAAAAAAAAsgvs/AAAAAAAAAABgXPs/SBQIgMCJ+z/cAPA/AQAAADgA+z9wXPs/ +iCsNQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANPv6PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASBQIQCAGBgAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCNCIAg+vo/ +AAAAAAAAAADoQfs/HQAAAFUAAADgUPs/SBQIgAD6+j/cAPA/AQAAADgA+z8BAAAA +IAYGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcFj7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkI0IQCAIBgAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEMdCIBwV/s/ +9FP7PwAAAABIVPs/AAAAAAEAAAAAAAAAkI0IgFBX+z8BAAAABAAAAOxB+z8KAAAA +AACAABwA9D8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +CAAAAEwCAAABAAAA +Q09SRQAAAAA= +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkFH7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAASBQIQCAOBgAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJCNCIBwUPs/ +AAAAAAAAAADoQfs/zc0AAAEAAAAAAAAASBQIgFBQ+z/cAPA/AQAAADgA+z8BAAAA +IAAGAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +kLT7P7C1+z9yHwQAiED7P4hA+z+gavs/gED7PxIAAABYbPs/WGz7P6Bq+z8AAAAA +BwAAAByu+z91bmFsaWduZWRfcHRyX3QAAQAAABi2+z8AAAAAIAwGAA8AAADOzs7O +BwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOn6P3Dp+j/Y6fo/ +AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4= -ZFNAP4EiDkAwDAYAXCIOgMCd+z8CAAAAvStAPwCe+z9k6fo/AAAAAAAAAAAFAAAA -rf///yAAAAD0VPs/AQAAAIAAAAABAAAAAAAAAAAAAAAdAAAABQAAAP0UAEANFQBA -/////wEAAACAAAAAYCAIQFgL+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAEAAACAAAAAAQAAAAAAAABcIg6A8J37PwEAAABk6fo/ -WCcNgPCd+z8KAAAAZ+n6PwCe+z9k6fo/AAAAAAAAAACkIg6AIJ77PwoAAAABAAAA -jFNAPx4AAAC8K0A/BAAAACAAAAAgAACACAAAAAEAAAC8gQiAUJ77PwAAAAAAAAAA -vIEIgFCe+z8AAAAAAwAAAEAE+z8gAACAIQAGAAEAAAAAAAAAcJ77P4wiDkAAAAAA -IwAGAHRU+z8AAAAAAAAAAAAAAACQnvs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnJ77PwAAAAAAAAAAAAAAAAAAAAAAAAAA +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 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAA= -bJX7P1CS+z9Ylfs/ -UJL7P/CU+z/5GQAAUC/7P1Av+z9slfs/SC/7PxQAAAA0//o/NP/6P2yV+z8AAAAA -BQAAAFx1+z91bml0eVRhc2sAzs7Ozs4AAAAAAFiV+z8AAAAAIQAGAAwAAADOzs7O -BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/Oj6P2Tp+j/M6fo/ -AAAAAAAAAAABAAAAAAAAAGg6QD8AAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +cKn7PxCs+z+PGwQAYED7P2BA+z+QrPs/WED7PxQAAAC0U/s/tFP7P5Cs+z8AAAAA +BQAAAICM+z91bml0eVRhc2sAzs7Ozs4AAAAAAHys+z8AAAAAIQAGAAwAAADOzs7O +BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOn6P3Dp+j/Y6fo/ +AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4= -xCAIQOaSAEAwCQYAD5MAgBCT+z+Mk/s/AAAAADwu+z8KAAAAVwAAADcAAAD0PwAA -AAD0PwDAAOAAAAAAPC77P8zMzAwAAAAABAAAABMAAAAQk/s/jJP7P/0UAEANFQBA -/////8QiCEDMzMwMHI4IQLgB+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAP//P7MAAAAAAAAAAAAAAAC/Bw6AMJP7P4yT+z//AAAA -uAH7PwAAAAAAAAAAAAAAAAIMDoBQk/s/jJP7P/8AAAB1bATAAP8AAAAA/wAAAAD/ -PwMOgICT+z8BAAAAkJT7Pz8DDoCAk/s/AQAAANbEGZb+AAAAjJT7PwAAAAAQAAAA -vIEIgLCU+z8AAAAAAAAAAKWlpaWlpaWlpaWlpQAAAAAAAAAAAAAAAAAAAAAAAAAA +nCQIQNaSAEAwBQYAD5MAgDCq+z+sqvs/AAAAAAAAAADAGwQAVwAAADcAAACcAf4/ +AAD0PwAAAAAAAAAAAAAAAMMbBAAAAAAABAAAABcAAAD//wAAAAAAAP0UAEANFQBA +/////5wmCEDDGwQA/IMIQLQ9+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAP//P7MAAAAAAAAAAAAAAAAzYQ2AUKr7P6yq+z//AAAA +tD37PwAAAAAAAAAAAAAAADZdDYBwqvs/rKr7P/8AAABVVQTAAP8AAAAA/wAAAAD/ +o2ENgKCq+z8BAAAAsKv7P6NhDYCgqvs/AQAAANzn68T+AAAArKv7P////38QAAAA +vIEIgNCr+z8AAAAAAAAAAKWlpaWlpaWlpaWlpQAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADWxBmW -jJP7PyAAAIAhAAYA4En7PwAAAADQlPs/NAMOQAAAAAAjAAYAbJX7PwAAAAAAAAAA -AAAAAPCU+z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAD8lPs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc5+vE +rKr7PwAAAIAhAAYAIGH7PwAAAADwq/s/mGENQAAAAAAjAAYAYED7P5Cs+z8AAAAA +AAAAABCs+z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAcrPs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAA= -DGn7P1Bn+z/4aPs/ -UGf7P5Bo+z/Ozs7O7C77P3hh+z8Mafs/5C77PxkAAADOzs7Ozs7Ozgxp+z8AAAAA -AAAAAPxi+z9JRExFMQDOzs7Ozs7Ozs4AAQAAAPho+z8AAAAAIQAGAAcAAADOzs7O -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/Oj6P2Tp+j/M6fo/ -AAAAAAAAAAABAAAAAAAAAGg6QD8AAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAA +kH77P9B/+z/Ozs7O/D/7P7h4+z9MgPs/9D/7PxkAAADOzs7Ozs7OzkyA+z8AAAAA +AAAAADx6+z9JRExFMQDOzs7Ozs7Ozs4AAQAAADiA+z8AAAAAIQAGAAcAAADOzs7O +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOn6P3Dp+j/Y6fo/ +AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4= -xCAIQCJrDkAwBAYAAhENgBBo+z8AAAAAAQAAgAAAAAABAAAAAwAAACMABgCZcwiA -AGj7PwMAAAAjCAYAIAgGAAEAAAAgCAYAwHf7PwAAAAClpaWlpaWlpWzEAEB3xABA -/////8QiCEABAAAAHI4IQFjV+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAACQeQhAAAAAAAAAAACZeQiAMGj7PwgAAAABAAAA -AQAAAAEAAAADAAAAIwAGALyBCIBQaPs/AAAAAAAAAAABAAAAIAAAgCEABgAAAAAA -AAAAAHBo+z+QeQhAAAAAACMABgBwYfs/AAAAAAEAAAAAAAAAkGj7PwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJxo+z8AAAAA +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== -cGH7P7Bf+z9cYfs/ -sF/7P/Bg+z/Ozs7OFGn7P+wu+z9wYfs/5C77PxkAAADOzs7Ozs7OznBh+z8AAAAA -AAAAAGBb+z9JRExFMADOzs7Ozs7Ozs4AAAAAAFxh+z8AAAAAIQAGAAYAAADOzs7O -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/Oj6P2Tp+j/M6fo/ -AAAAAAAAAAABAAAAAAAAAGg6QD8AAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA +8Hb7PzB4+z/Ozs7OVID7P/w/+z+wePs/9D/7PxkAAADOzs7Ozs7OzrB4+z8AAAAA +AAAAAKBy+z9JRExFMADOzs7Ozs7Ozs4AAAAAAJx4+z8AAAAAIQAGAAYAAADOzs7O +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOn6P3Dp+j/Y6fo/ +AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4= -xCAIQCJrDkAwBwYAAhENgHBg+z8AAAAAAwAAAAAAAAABAAAAAwAAACMBBgAjAAYA -DGn7PwAAAAABAAAA2IMIgJCO+z8AAAAAYFv7PwAAAACILfs/AAAAAGzEAEB3xABA -/////8QiCECQjvs/HI4IQLjN+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAP//P7MAAAAAAAAAAAAAAACZeQiAkGD7PwgAAAAAAAAA -AAAAAAEAAAADAAAAIwEGALyBCICwYPs/AAAAAAAAAAABAAAAIAAAgCEABgAAAAAA -AAAAANBg+z+QeQhAAAAAACMABgAMafs/AAAAAAAAAAAAAAAA8GD7PwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPxg+z8AAAAA +nCQIQAaIDkAwBQYAzjgNgLB3+z8AAAAAAwAAAAEAAAABAACAAwAAACMABgB6kQiA +kHf7PxRx+z9IHQBAIAQGAAEAAAAgBAYAAAAAAAAAAAD//wAAAAAAAGzEAEB3xABA +/////5wmCEABAAAA/IMIQNQJ+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAADcnQhAAAAAAAAAAADlnQiA0Hf7PwgAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAALyBCIDwd/s/AAAAAAAAAAABAAAAAAAAgAAAAAAAAAAA +AAAAABB4+z/cnQhAAAAAACMABgD8P/s/sHj7PwEAAAAAAAAAMHj7PwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADx4+z8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= -6FL7P1BR+z/UUvs/ -UFH7P3BS+z/EIQAA2C77P3RW+z/oUvs/0C77PxQAAAAsVvs/LFb7P+hS+z8AAAAA -BQAAANhK+z9iYWRfcHRyX3Rhc2sAzs4A////f9RS+z8AAAAAIQAGAA4AAADOzs7O -BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/Oj6P2Tp+j/M6fo/ -AAAAAAAAAAABAAAAAAAAAGg6QD8AAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA +YGf7P6Bo+z9aIwQA6D/7P6Bs+z8Uafs/4D/7PxQAAADOzs7Ozs7OzhRp+z8AAAAA +BQAAAARh+z9iYWRfcHRyX3Rhc2sAzs4A////fwBp+z8AAAAAIQAGAA4AAADOzs7O +BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOn6P3Dp+j/Y6fo/ +AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4= -xCAIQIJ3CEAwBwYAJyIOgBBS+z/EIQAAAAAAAEAE+z8gAACAIQAGACMIBgCCdwiA -8FH7PwAAAADEIQAA7BwIgDA/+z/cAPA/AQAAAAAAAABYJw2A0FH7P/0UAEANFQBA -+f///8QiCEAwP/s/HI4IQDi/+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAOwcCIAwP/s/3ADwPwEAAAC8gQiAMFL7PwAAAAAAAAAA -QAT7PyAAAIAhAAYAIwgGAAAAAABQUvs/GCIOQAAAAAAjAAYAbJX7PwAAAAAAAAAA -AAAAAHBS+z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAB8Uvs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAA== -bFb7P4Cl+z8Ep/s/ -gKX7P6Cm+z/EIQAA8FL7P9gu+z9sVvs/0C77Pw8AAADOzs7Ozs7OzmxW+z8AAAAA -CgAAAAif+z9mYWlsZWRfYXNzZXJ0X3QAAAAAAASn+z8AAAAAIQAGABAAAADOzs7O -CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/Oj6P2Tp+j/M6fo/ -AAAAAAAAAAABAAAAAAAAAGg6QD8AAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4= -xCAIQIJ3CEAwCQYAayEOgECm+z/EIQAAAAAAAEAE+z8gAACAIQAGAAAAAACCdwiA -IKb7PwAAAADEIQAAeAYOgMCS+z8ACAAAQBb7PwAAAABYJw2AAKb7P/0UAEANFQBA -+P///8QiCEDAkvs/HI4IQGgT+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAHgGDoDAkvs/AAgAAEAW+z+8gQiAYKb7PwAAAAAAAAAA -QAT7PyAAAIAhAAYAAAAAAAAAAACApvs/XCEOQAAAAAAjAAYAbFb7PwAAAAAAAAAA -AAAAAKCm+z8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAACspvs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAA== -tHP7PwBy+z+gc/s/ -AHL7P0Bz+z8AAAAAxC77P8Qu+z+0c/s/vC77PxgAAADEavs/xGr7P7Rz+z+8avs/ -AQAAAKRr+z9UbXIgU3ZjAM7Ozs7Ozs4AAAAAAKBz+z8AAAAAIQAGAAgAAADOzs7O -AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/Oj6P2Tp+j/M6fo/ -AAAAAAAAAAABAAAAAAAAAGg6QD8AAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4= -xCAIQPKTCEAwCgYAJ5UIgMBy+z8wMfs/AAAAAAEAAAAgAACAIQAGAAAAAADykwiA -oHL7PwAAAAA8Lvs/7Gr7PwAAAAAAAAAAIwAGAAAAAAClpaWlpaWlpQAAAAAAAAAA -AAAAAMQiCEAAAAAAHI4IQAjg+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAMlQhAAAAAAAAAAAC8gQiA8HL7PwAAAAAAAAAA -AAAAAAAAAAAAAAAA1sQZlgAAAAAAAAAAAAAAAAAAAAAAAAAAIHP7PwyVCEAAAAAA -COD6PwAAAAABAAAA1sQZliMABgDUWfs/AAAAAAEAAAAAAAAAQHP7PwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAExz+z8AAAAA +nCQIQEgUCEAwBQYAupsIgCBo+z8AAAAAWiMEANSXCIAAV/s/AwAAACMIBgBIFAiA +AGj7P9wA8D8BAAAAOAD7PwEAAAAgBQYAAAAAAAAAAAD//wAAAAAAAP0UAEANFQBA ++f///5wmCEABAAAA/IMIQET6+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAADACQD8YAAAAgllAPwEAAAAbDg2AQGj7P1ojBACUDPs/ +1JcIgABX+z8DAAAAIwgGALyBCIBgaPs/AAAAAAAAAAAgAAAAAAAAgCEABgAAAAAA +AAAAAIBo+z8MDg1AAAAAACMABgBgQPs/kKz7PwAAAAAAAAAAoGj7PwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKxo+z8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= -lPv6P+D5+j+A+/o/ -4Pn6PyD7+j/Ozs7OzED7P8Q6+z+U+/o/YC77PwMAAADY6vo/2Or6P5T7+j/Q6vo/ -FgAAAITr+j9lc3BfdGltZXIAzs7Ozs4AAAAAAID7+j8AAAAAIQAGAAEAAADOzs7O -FgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/Oj6P2Tp+j/M6fo/ -AAAAAAAAAAABAAAAAAAAAGg6QD8AAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA +gLz7P8C9+z9aIwQAHGn7P+g/+z+YbPs/4D/7Pw8AAAC8avs/WGz7P5hs+z8AAAAA +CgAAACy2+z9mYWlsZWRfYXNzZXJ0X3QAAAAAACi++z8AAAAAIQAGABAAAADOzs7O +CgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOn6P3Dp+j/Y6fo/ +AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4= -xCAIQLSLCEAwAAYAmw8NgKD6+j+s6vo/AAAAAADr+j8AAAAAAQAAAAAAAAC0iwiA -gPr6PwAAAADYMPs/2DD7P1A5+z8DAAAAIw4GAAAAAAClpaWlpaWlpQAAAAAAAAAA -AAAAAMQiCEBQOfs/HI4IQOhn+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAACIDw1AAAAAAAAAAAC8gQiA4Pr6PwAAAAAAAAAA -AAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAANbEGZYAAAAAAAAAAAAAAAAAAAAA -AAAAAAD7+j+IDw1AAAAAACMABgCU+/o/AAAAAAEAAAAAAAAAIPv6PwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACz7+j8AAAAA +nCQIQEgUCEAwAwYAupsIgEC9+z8AAAAAWiMEAO1YDYDgqfs/AAgAAAQA+z9IFAiA +IL37P9wA8D8BAAAAOAD7PwEAAAAgAwYAAAAAAAAAAAD//wAAAAAAAP0UAEANFQBA ++P///5wmCEABAAAA/IMIQGRP+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAEQBQD8eAAAAgllAPwEAAABbDQ2AYL37P1ojBACUDPs/ +7VgNgOCp+z8ACAAABAD7P7yBCICAvfs/AAAAAAAAAAAgAAAAAAAAgCEABgAAAAAA +AAAAAKC9+z9MDQ1AAAAAACMABgDEQPs/mGz7PwAAAAAAAAAAwL37PwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMy9+z8AAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= -xED7P/A++z+wQPs/ -8D77P1BA+z/Ozs7OaC77P5z7+j/EQPs/YC77PwEAAAB0PPs/dDz7P8RA+z9sPPs/ -GAAAALQ8+z9pcGMxAM7Ozs7Ozs7Ozs4AAQAAALBA+z8AAAAAIQAGAAMAAADOzs7O -GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/Oj6P2Tp+j/M6fo/ -AAAAAAAAAAABAAAAAAAAAGg6QD8AAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +IIn7P4CK+z8AAAAA1D/7P9Q/+z/0ivs/zD/7PxgAAAAEgvs/BIL7P/SK+z/8gfs/ +AQAAAOSC+z9UbXIgU3ZjAM7Ozs7Ozs4AAAAAAOCK+z8AAAAAIQAGAAgAAADOzs7O +AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOn6P3Dp+j/Y6fo/ +AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4= -xCAIQOwcCEAwCAYAtIsIgLA/+z8BAAAA2DD7P9ww+z8KAAAAAACAABwA9D/sHAiA -kD/7P+AA8D8BAAAAKAD7PwEAAAAgCAYAwDz7PwAAAACwP/s/AQAAAAAAAAAAAAAA -AAAAAMQiCEABAAAAHI4IQBit+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAP//P7MAAAAAAAAAAAAAAAA3HwiA0D/7P0g8+z8AAAAA -3DD7PwoAAAAAAIAAHAD0P7yBCIAQQPs/AQAAAMw1CEB0lfs/CgAAAAAAgAD///// -vIEIgAAAAAD0GQAA1sQZlpw8+z8AAAAAAQAAAAAAAAAAAAAAMED7PwgfCEABAAAA -AQAAAMRA+z8AAAAAAAAAAAAAAABQQPs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -RBAIgIB9/j8oAAAAKAAAAAAAAAAAAAAAXED7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +nCQIQEgUCEAwAAYAXakIgOCJ+z8AAAAAAAAAACyC+z8AAAAAAAAAAGBc+z9IFAiA +wIn7P9wA8D8BAAAAOAD7P3Bc+z+IKw1AAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA +AAAAAJwmCEBwXPs//IMIQCQc+z8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAJwkCEC0gQhAMAAFANzn68SPqgiAAIr7P/RB+z8AAAAA +AAAAAHSqCEAAAAAAAAAAALyBCIAwivs/AAAAAAAAAAAAAAAAAAAAAAAAAADc5+vE +AQAAAAAAAIAhAAYAIwAGAAAAAABgivs/dKoIQAAAAAAkHPs/AAAAAAEAAADc5+vE +IwAGABBA+z8Ucfs/AAAAAAAAAACAivs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAjIr7PwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAA== -vDr7PwA5+z+oOvs/ -ADn7P0A6+z/Ozs7OnPv6P2gu+z+8Ovs/YC77PwEAAACg//o/oP/6P7w6+z+Y//o/ -GAAAAKw2+z9pcGMwAM7Ozs7Ozs7Ozs4AAAAAAKg6+z8AAAAAIQAGAAIAAADOzs7O -GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/Oj6P2Tp+j/M6fo/ -AAAAAAAAAAABAAAAAAAAAGg6QD8AAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA +YPn6P8D6+j/Ozs7OeFj7P5hR+z80+/o/cD/7PwMAAADk6vo/5Or6PzT7+j/c6vo/ +FgAAACTr+j9lc3BfdGltZXIAzs7Ozs4AAAAAACD7+j8AAAAAIQAGAAEAAADOzs7O +FgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOn6P3Dp+j/Y6fo/ +AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4= -xCAIQLSLCEAwDgYANx8IgMA5+z90//o/AAAAAMj/+j8AAAAAAQAAAAIAAAC0iwiA -oDn7PwAAAADYMPs/2DD7P83NAAABAAAAAAAAAAAAAAClpaWlpaWlpQAAAAAAAAAA -AAAAAMQiCEDNzQAAHI4IQAin+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAIHwhAAAAAAAAAAAC8gQiAADr7PwAAAAAAAAAA -AAAAAAAAAAAAAAAA/////wAAAAAAAAAAAAAAANbEGZYAAAAAAAAAAAAAAAAAAAAA -AAAAACA6+z8IHwhAAAAAACMDBgC8Ovs/AQAAAAEAAAAAAAAAQDr7PwAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAL4PCICAO/4/SC77P9bEGZYAAAAAAAAAAEw6+z8AAAAA +nCQIQEgUCEAwBgYAkI0IgCD6+j8AAAAAAAAAAOhB+z8dAAAAVQAAAOBQ+z9IFAiA +APr6P9wA8D8BAAAAOAD7PwEAAAAgBgYAAAAAAAAAAAD//wAAAAAAAAAAAAAAAAAA +AAAAAJwmCEABAAAA/IMIQGSM+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAJwkCEC0gQhAMAAFAAAAAAAHOA2AQPr6P7jq+j8AAAAA +AAAAAPQ3DUAAAAAAAAAAALyBCICA+vo/AAAAAAAAAAAAAAAAAAAAAAAAAAD///// +AAAAAAAAAADz1gMA3OfrxAzr+j8AAAAAAQAAACMOBgAAAAAAoPr6P/Q3DUAAAAAA +IwAGALRB+z80+/o/AAAAAAAAAADA+vo/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzPr6PwAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA -AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== \ No newline at end of file +AAAAAAAAAAAAAAAAAAAAAA== +sFb7P/BX+z/Ozs7OeD/7Pzz7+j9wWPs/cD/7PwEAAAAgVPs/IFT7P3BY+z8YVPs/ +GAAAAGBU+z9pcGMxAM7Ozs7Ozs7Ozs4AAQAAAFxY+z8AAAAAIQAGAAMAAADOzs7O +GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOn6P3Dp+j/Y6fo/ +AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4= +nCQIQJCNCEAwCAYAQx0IgHBX+z/0U/s/AAAAAEhU+z8AAAAAAQAAAAAAAACQjQiA +UFf7PwEAAAAEAAAA7EH7PwoAAAAAAIAAHAD0PwAAAAD//wAAAAAAAAAAAAAAAAAA +AAAAAJwmCEAKAAAA/IMIQJTp+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAJis+z8KAAAAAACAABwA9D+8gQiAsFf7PwEAAAAAAAAA +mKz7PwoAAAAAAIAA/////7yBCIAAAAAAiRsEANzn68RIVPs/AAAAAAEAAAAAAAAA +AAAAANBX+z8QHQhAAQAAAAEAAADcQfs/cFj7PwAAAAAAAAAA8Ff7PwAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAOARCICAff4/KAAAACgAAAAAAAAAAAAAAPxX+z8AAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA= +sE/7PxBR+z/Ozs7OPPv6P3g/+z+QUfs/cD/7PwEAAABATfs/QE37P5BR+z84Tfs/ +GAAAAIBN+z9pcGMwAM7Ozs7Ozs7Ozs4AAAAAAHxR+z8AAAAAIQAGAAIAAADOzs7O +GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACOn6P3Dp+j/Y6fo/ +AAAAAAAAAAABAAAAAAAAAAAAAAAAAAAASB0AQAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADOzs4= +nCQIQEgUCEAwDgYAkI0IgHBQ+z8AAAAAAAAAAOhB+z/NzQAAAQAAAAAAAABIFAiA +UFD7P9wA8D8BAAAAOAD7PwEAAAAgAAYAAQAAAAAAAAD//wAAAAAAAAAAAAAAAAAA +AAAAAJwmCEABAAAA/IMIQLTi+j8AAAAAAAAAAAAAAAD//z+zAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAJwkCEC0gQhAMAAFAAAAAABDHQiAkFD7PxRN+z8AAAAA +AAAAABAdCEAAAAAAAAAAALyBCIDQUPs/AAAAAAAAAAAAAAAAAAAAAAAAAAD///// +AAAAAAAAAAAAAAAA3OfrxGhN+z8AAAAAAQAAAAIAAAAAAAAA8FD7PxAdCEAAAAAA +IwMGANxB+z+QUfs/AQAAAAAAAAAQUfs/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +WhEIgFA7/j9YP/s/3OfrxAAAAAAAAAAAHFH7PwAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA== +FAAAAEgAAABKIAAA +RVNQX0NPUkVfRFVNUF9JTkZPAAA= +AgAAADJhYTkyNjY1YTFiNzg5OWMyZjI4NjhmOGRhZWRmZDVhMWUzNWExYWVhMzY1 +ZjkzNmRjODllZThjYzcxNzhhNTMAAAAA +DAAAAJQAAAClAgAA +RVhUUkFfSU5GTwAA +oGr7P+gAAAAdAAAA7gAAAAUAAADCAAAAAAAAAMMAAAAAAAAAxAAAAAAAAADFAAAA +AAAAAMYAAAAAAAAAxwAAAAAAAACxAAAAm4cOQLIAAAAAAAAAswAAAAAAAAC0AAAA +AAAAALUAAAAAAAAAtgAAAAAAAAC3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA +AAAAAA== +v1VmGg== \ No newline at end of file diff --git a/components/espcoredump/test/expected_output b/components/espcoredump/test/expected_output index eaa14f83c..625fb2489 100644 --- a/components/espcoredump/test/expected_output +++ b/components/espcoredump/test/expected_output @@ -1,14 +1,31 @@ -espcoredump.py v0.3-dev +espcoredump.py v0.4-dev =============================================================== ==================== ESP32 CORE DUMP START ==================== +Crashed task handle: 0x3ffb6aa0, name: 'unaligned_ptr_t', GDB name: 'process 1073441440' + ================== CURRENT THREAD REGISTERS =================== -pc 0x400e2281 0x400e2281 +exccause 0x1d (StoreProhibitedCause) +excvaddr 0x5 +epc1 0x400e879b +epc2 0x0 +epc3 0x0 +epc4 0x0 +epc5 0x0 +epc6 0x0 +epc7 0x0 +eps2 0x0 +eps3 0x0 +eps4 0x0 +eps5 0x0 +eps6 0x0 +eps7 0x0 +pc 0x400d0e7d 0x400d0e7d lbeg 0x400014fd 1073747197 lend 0x4000150d 1073747213 lcount 0xffffffff 4294967295 sar 0x0 0 -ps 0x60c20 396320 +ps 0x60820 395296 threadptr br scompare1 @@ -24,42 +41,97 @@ f64r_hi f64s fcr fsr -a0 0x400e225c 1074668124 -a1 0x3ffb9dc0 1073454528 +a0 0x800d0e58 -2146628008 +a1 0x3ffbb4e0 1073460448 a2 0x2 2 -a3 0x3f402bbd 1061170109 -a4 0x3ffb9e00 1073454592 -a5 0x3ffae964 1073408356 +a3 0x3ffbb52c 1073460524 +a4 0x3ffbb520 1073460512 +a5 0x3ffae970 1073408368 a6 0x0 0 a7 0x0 0 a8 0x5 5 a9 0xffffffad -83 a10 0x20 32 -a11 0x3ffb54f4 1073435892 +a11 0x3ffb6b20 1073441568 a12 0x1 1 a13 0x80 128 a14 0x1 1 a15 0x0 0 ==================== CURRENT THREAD STACK ===================== -#0 0x400e2281 in recur_func () at C:/msys32/home/alex/esp/esp-idf4/components/espcoredump/test/test_core_dump.c:70 -#1 0x400e225c in recur_func () at C:/msys32/home/alex/esp/esp-idf4/components/espcoredump/test/test_core_dump.c:63 -#2 0x400e225c in recur_func () at C:/msys32/home/alex/esp/esp-idf4/components/espcoredump/test/test_core_dump.c:63 -#3 0x400e22a4 in unaligned_ptr_task (pvParameter=0x0) at C:/msys32/home/alex/esp/esp-idf4/components/espcoredump/test/test_core_dump.c:80 -#4 0x400881bc in vPortTaskWrapper (pxCode=0x400e228c , pvParameters=0x0) at C:/msys32/home/alex/esp/esp-idf4/components/freertos/port.c:143 +#0 0x400d0e7d in recur_func () at /home/alexey/projects/esp/esp-idf/components/espcoredump/test/test_core_dump.c:70 +#1 0x400d0e58 in recur_func () at /home/alexey/projects/esp/esp-idf/components/espcoredump/test/test_core_dump.c:63 +#2 0x400d0e58 in recur_func () at /home/alexey/projects/esp/esp-idf/components/espcoredump/test/test_core_dump.c:63 +#3 0x400d0ea0 in unaligned_ptr_task (pvParameter=0x0) at /home/alexey/projects/esp/esp-idf/components/espcoredump/test/test_core_dump.c:80 +#4 0x400881bc in vPortTaskWrapper (pxCode=0x400d0e88 , pvParameters=0x0) at /home/alexey/projects/esp/esp-idf/components/freertos/port.c:143 ======================== THREADS INFO ========================= Id Target Id Frame -* 1
0x400e2281 in recur_func () at C:/msys32/home/alex/esp/esp-idf4/components/espcoredump/test/test_core_dump.c:70 - 2 process 1 0x400092e6 in ?? () - 3 process 2 0x400e6b22 in esp_pm_impl_waiti () at C:/msys32/home/alex/esp/esp-idf4/components/esp32/pm_esp32.c:487 - 4 process 3 0x400e6b22 in esp_pm_impl_waiti () at C:/msys32/home/alex/esp/esp-idf4/components/esp32/pm_esp32.c:487 - 5 process 4 0x40087782 in vTaskDelay (xTicksToDelay=) at C:/msys32/home/alex/esp/esp-idf4/components/freertos/tasks.c:1484 - 6 process 5 0x40087782 in vTaskDelay (xTicksToDelay=) at C:/msys32/home/alex/esp/esp-idf4/components/freertos/tasks.c:1484 - 7 process 6 0x400893f2 in prvProcessTimerOrBlockTask (xNextExpireTime=, xListWasEmpty=) at C:/msys32/home/alex/esp/esp-idf4/components/freertos/timers.c:588 - 8 process 7 0x40088bb4 in xQueueGenericReceive (xQueue=0x3ffaeaac, pvBuffer=0x0, xTicksToWait=4294967295, xJustPeeking=0) at C:/msys32/home/alex/esp/esp-idf4/components/freertos/queue.c:1591 - 9 process 8 0x40081cec in esp_crosscore_int_send_yield (core_id=1) at C:/msys32/home/alex/esp/esp-idf4/components/esp32/crosscore_int.c:112 - 10 process 9 0x40088bb4 in xQueueGenericReceive (xQueue=0x3ffaff74, pvBuffer=0x0, xTicksToWait=4294967295, xJustPeeking=0) at C:/msys32/home/alex/esp/esp-idf4/components/freertos/queue.c:1591 +* 1 process 1073441440 0x400d0e7d in recur_func () at /home/alexey/projects/esp/esp-idf/components/espcoredump/test/test_core_dump.c:70 + 2 process 1073458320 0x400092d6 in ?? () + 3 process 1073446988 0x400e8806 in esp_pm_impl_waiti () at /home/alexey/projects/esp/esp-idf/components/esp32/pm_esp32.c:484 + 4 process 1073445040 0x400e8806 in esp_pm_impl_waiti () at /home/alexey/projects/esp/esp-idf/components/esp32/pm_esp32.c:484 + 5 process 1073441044 0x40081448 in esp_crosscore_int_send_yield (core_id=0) at /home/alexey/projects/esp/esp-idf/components/esp32/crosscore_int.c:111 + 6 process 1073441944 0x40081448 in esp_crosscore_int_send_yield (core_id=0) at /home/alexey/projects/esp/esp-idf/components/esp32/crosscore_int.c:111 + 7 process 1073449716 0x40081448 in esp_crosscore_int_send_yield (core_id=0) at /home/alexey/projects/esp/esp-idf/components/esp32/crosscore_int.c:111 + 8 process 1073412916 0x40081448 in esp_crosscore_int_send_yield (core_id=0) at /home/alexey/projects/esp/esp-idf/components/esp32/crosscore_int.c:111 + 9 process 1073436784 0x40088d90 in xQueueGenericReceive (xQueue=0x3ffb53f4, pvBuffer=0x0, xTicksToWait=, xJustPeeking=0) at ../../../components/freertos/include/freertos/portable.h:214 + 10 process 1073435024 0x40081448 in esp_crosscore_int_send_yield (core_id=0) at /home/alexey/projects/esp/esp-idf/components/esp32/crosscore_int.c:111 + +==================== THREAD 2 (TCB: 0x3ffbac90, name: 'unityTask') ===================== +#0 0x400092d6 in ?? () +#1 0x4000930f in ?? () +#2 0x400d6133 in unity_gets (dst=0x3ffbaaac \"\", len=255) at /home/alexey/projects/esp/esp-idf/components/unity/unity_port_esp32.c:72 +#3 0x400d5d36 in unity_run_menu () at /home/alexey/projects/esp/esp-idf/components/unity/unity_runner.c:278 +#4 0x400d61a3 in unity_task (pvParameters=0x0) at ../components/test_utils/test_runner.c:37 +#5 0x400881bc in vPortTaskWrapper (pxCode=0x400d6198 , pvParameters=0x0) at /home/alexey/projects/esp/esp-idf/components/freertos/port.c:143 + +==================== THREAD 3 (TCB: 0x3ffb804c, name: 'IDLE1') ===================== +#0 0x400e8806 in esp_pm_impl_waiti () at /home/alexey/projects/esp/esp-idf/components/esp32/pm_esp32.c:484 +#1 0x400d38ce in esp_vApplicationIdleHook () at /home/alexey/projects/esp/esp-idf/components/esp_common/src/freertos_hooks.c:63 +#2 0x40089de5 in prvIdleTask (pvParameters=0x0) at /home/alexey/projects/esp/esp-idf/components/freertos/tasks.c:3381 +#3 0x400881bc in vPortTaskWrapper (pxCode=0x40089ddc , pvParameters=0x0) at /home/alexey/projects/esp/esp-idf/components/freertos/port.c:143 + +==================== THREAD 4 (TCB: 0x3ffb78b0, name: 'IDLE0') ===================== +#0 0x400e8806 in esp_pm_impl_waiti () at /home/alexey/projects/esp/esp-idf/components/esp32/pm_esp32.c:484 +#1 0x400d38ce in esp_vApplicationIdleHook () at /home/alexey/projects/esp/esp-idf/components/esp_common/src/freertos_hooks.c:63 +#2 0x40089de5 in prvIdleTask (pvParameters=0x0) at /home/alexey/projects/esp/esp-idf/components/freertos/tasks.c:3381 +#3 0x400881bc in vPortTaskWrapper (pxCode=0x40089ddc , pvParameters=0x0) at /home/alexey/projects/esp/esp-idf/components/freertos/port.c:143 + +==================== THREAD 5 (TCB: 0x3ffb6914, name: 'bad_ptr_task') ===================== +#0 0x40081448 in esp_crosscore_int_send_yield (core_id=0) at /home/alexey/projects/esp/esp-idf/components/esp32/crosscore_int.c:111 +#1 0x40089bba in vTaskDelay (xTicksToDelay=) at ../../../components/freertos/include/freertos/portable.h:214 +#2 0x400d0e1b in bad_ptr_task (pvParameter=0x0) at /home/alexey/projects/esp/esp-idf/components/espcoredump/test/test_core_dump.c:43 +#3 0x400881bc in vPortTaskWrapper (pxCode=0x400d0e0c , pvParameters=0x0) at /home/alexey/projects/esp/esp-idf/components/freertos/port.c:143 + +==================== THREAD 6 (TCB: 0x3ffb6c98, name: 'failed_assert_t') ===================== +#0 0x40081448 in esp_crosscore_int_send_yield (core_id=0) at /home/alexey/projects/esp/esp-idf/components/esp32/crosscore_int.c:111 +#1 0x40089bba in vTaskDelay (xTicksToDelay=) at ../../../components/freertos/include/freertos/portable.h:214 +#2 0x400d0d5b in failed_assert_task (pvParameter=0x0) at /home/alexey/projects/esp/esp-idf/components/espcoredump/test/test_core_dump.c:89 +#3 0x400881bc in vPortTaskWrapper (pxCode=0x400d0d4c , pvParameters=0x0) at /home/alexey/projects/esp/esp-idf/components/freertos/port.c:143 + +==================== THREAD 7 (TCB: 0x3ffb8af4, name: 'Tmr Svc') ===================== +#0 0x40081448 in esp_crosscore_int_send_yield (core_id=0) at /home/alexey/projects/esp/esp-idf/components/esp32/crosscore_int.c:111 +#1 0x4008a95d in prvProcessTimerOrBlockTask (xNextExpireTime=, xListWasEmpty=) at ../../../components/freertos/include/freertos/portable.h:214 +#2 0x4008aa8f in prvTimerTask (pvParameters=0x0) at /home/alexey/projects/esp/esp-idf/components/freertos/timers.c:544 +#3 0x400881bc in vPortTaskWrapper (pxCode=0x4008aa74 , pvParameters=0x0) at /home/alexey/projects/esp/esp-idf/components/freertos/port.c:143 + +==================== THREAD 8 (TCB: 0x3ffafb34, name: 'esp_timer') ===================== +#0 0x40081448 in esp_crosscore_int_send_yield (core_id=0) at /home/alexey/projects/esp/esp-idf/components/esp32/crosscore_int.c:111 +#1 0x40088d90 in xQueueGenericReceive (xQueue=0x3ffaeab8, pvBuffer=0x0, xTicksToWait=, xJustPeeking=0) at ../../../components/freertos/include/freertos/portable.h:214 +#2 0x400d3807 in timer_task (arg=0x0) at /home/alexey/projects/esp/esp-idf/components/esp_common/src/esp_timer.c:323 +#3 0x400881bc in vPortTaskWrapper (pxCode=0x400d37f4 , pvParameters=0x0) at /home/alexey/projects/esp/esp-idf/components/freertos/port.c:143 + +==================== THREAD 9 (TCB: 0x3ffb5870, name: 'ipc1') ===================== +#0 0x40088d90 in xQueueGenericReceive (xQueue=0x3ffb53f4, pvBuffer=0x0, xTicksToWait=, xJustPeeking=0) at ../../../components/freertos/include/freertos/portable.h:214 +#1 0x40081d43 in ipc_task (arg=0x1) at /home/alexey/projects/esp/esp-idf/components/esp_common/src/ipc.c:51 +#2 0x400881bc in vPortTaskWrapper (pxCode=0x40081d10 , pvParameters=0x1) at /home/alexey/projects/esp/esp-idf/components/freertos/port.c:143 + +==================== THREAD 10 (TCB: 0x3ffb5190, name: 'ipc0') ===================== +#0 0x40081448 in esp_crosscore_int_send_yield (core_id=0) at /home/alexey/projects/esp/esp-idf/components/esp32/crosscore_int.c:111 +#1 0x40088d90 in xQueueGenericReceive (xQueue=0x3ffb4d14, pvBuffer=0x0, xTicksToWait=, xJustPeeking=0) at ../../../components/freertos/include/freertos/portable.h:214 +#2 0x40081d43 in ipc_task (arg=0x0) at /home/alexey/projects/esp/esp-idf/components/esp_common/src/ipc.c:51 +#3 0x400881bc in vPortTaskWrapper (pxCode=0x40081d10 , pvParameters=0x0) at /home/alexey/projects/esp/esp-idf/components/freertos/port.c:143 ======================= ALL MEMORY REGIONS ======================== Name Address Size Attrs @@ -68,586 +140,596 @@ Name Address Size Attrs .rtc.force_fast 0x3ff80000 0x0 RW .rtc_noinit 0x50000200 0x0 RW .rtc.force_slow 0x50000200 0x0 RW -.iram0.vectors 0x40080000 0x400 R XA -.iram0.text 0x40080400 0x9eb4 RWXA -.dram0.data 0x3ffb0000 0x24d8 RW A -.noinit 0x3ffb24d8 0x0 RW -.flash.rodata 0x3f400020 0x9328 RW A -.flash.text 0x400d0018 0x16d50 R XA -.coredump.tasks.data 0x3ffb5474 0x17c RW -.coredump.tasks.data 0x3ffb9d00 0x1f4 RW -.coredump.tasks.data 0x3ffb956c 0x17c RW -.coredump.tasks.data 0x3ffb9250 0x308 RW -.coredump.tasks.data 0x3ffb690c 0x17c RW -.coredump.tasks.data 0x3ffb6750 0x1a8 RW -.coredump.tasks.data 0x3ffb6170 0x17c RW -.coredump.tasks.data 0x3ffb5fb0 0x1ac RW -.coredump.tasks.data 0x3ffb52e8 0x17c RW -.coredump.tasks.data 0x3ffb5150 0x184 RW -.coredump.tasks.data 0x3ffb566c 0x17c RW -.coredump.tasks.data 0x3ffba580 0x184 RW -.coredump.tasks.data 0x3ffb73b4 0x17c RW -.coredump.tasks.data 0x3ffb7200 0x1a0 RW -.coredump.tasks.data 0x3ffafb94 0x17c RW -.coredump.tasks.data 0x3ffaf9e0 0x1a0 RW -.coredump.tasks.data 0x3ffb40c4 0x17c RW -.coredump.tasks.data 0x3ffb3ef0 0x1c0 RW -.coredump.tasks.data 0x3ffb3abc 0x17c RW -.coredump.tasks.data 0x3ffb3900 0x1a8 RW +.iram0.vectors 0x40080000 0x404 R XA +.iram0.text 0x40080404 0xa970 RWXA +.dram0.data 0x3ffb0000 0x3474 RW A +.noinit 0x3ffb3474 0x0 RW +.flash.rodata 0x3f400020 0x6e4c RW A +.flash.text 0x400d0020 0x188f0 R XA +.iram0.text_end 0x4008ad74 0x0 RW +.dram0.heap_start 0x3ffb4cf0 0x0 RW +.coredump.tasks.data 0x3ffb6aa0 0x17c RW +.coredump.tasks.data 0x3ffbb420 0x1f8 RW +.coredump.tasks.data 0x3ffbac90 0x17c RW +.coredump.tasks.data 0x3ffba970 0x30c RW +.coredump.tasks.data 0x3ffb804c 0x17c RW +.coredump.tasks.data 0x3ffb7e90 0x1a8 RW +.coredump.tasks.data 0x3ffb78b0 0x17c RW +.coredump.tasks.data 0x3ffb76f0 0x1ac RW +.coredump.tasks.data 0x3ffb6914 0x17c RW +.coredump.tasks.data 0x3ffb6760 0x1a0 RW +.coredump.tasks.data 0x3ffb6c98 0x17c RW +.coredump.tasks.data 0x3ffbbc80 0x1a8 RW +.coredump.tasks.data 0x3ffb8af4 0x17c RW +.coredump.tasks.data 0x3ffb8920 0x1c0 RW +.coredump.tasks.data 0x3ffafb34 0x17c RW +.coredump.tasks.data 0x3ffaf960 0x1c0 RW +.coredump.tasks.data 0x3ffb5870 0x17c RW +.coredump.tasks.data 0x3ffb56b0 0x1ac RW +.coredump.tasks.data 0x3ffb5190 0x17c RW +.coredump.tasks.data 0x3ffb4fb0 0x1cc RW ====================== CORE DUMP MEMORY CONTENTS ======================== -.coredump.tasks.data 0x3ffb5474 0x17c RW -0x3ffb5474: 0x3ffb9d70 0x3ffb9e90 0x00001ddc 0x3ffb2f78 -0x3ffb5484: 0x3ffb2f78 0x3ffb5474 0x3ffb2f70 0x00000012 -0x3ffb5494: 0xcececece 0xcececece 0x3ffb5474 0x00000000 -0x3ffb54a4: 0x00000007 0x3ffb96f8 0x6c616e75 0x656e6769 -0x3ffb54b4: 0x74705f64 0x00745f72 0x00000001 0x3ffb9ef4 -0x3ffb54c4: 0x00000000 0x00060020 0x0000000f 0xcececece -0x3ffb54d4: 0x00000007 0x00000000 0x00000000 0x00000000 -0x3ffb54e4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb54f4: 0x00000000 0x3ffae8fc 0x3ffae964 0x3ffae9cc -0x3ffb5504: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb5514: 0x3f403a68 0x00000000 0x40001d48 0x00000000 -0x3ffb5524: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5534: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5544: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5554: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5564: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5574: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5584: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5594: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb55a4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb55b4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb55c4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb55d4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb55e4: 0x00000000 0x00000000 0xcecece00 -.coredump.tasks.data 0x3ffb9d00 0x1f4 RW -0x3ffb9d00: 0x3f405364 0x400e2281 0x00060c30 0x800e225c -0x3ffb9d10: 0x3ffb9dc0 0x00000002 0x3f402bbd 0x3ffb9e00 -0x3ffb9d20: 0x3ffae964 0x00000000 0x00000000 0x00000005 -0x3ffb9d30: 0xffffffad 0x00000020 0x3ffb54f4 0x00000001 -0x3ffb9d40: 0x00000080 0x00000001 0x00000000 0x00000000 -0x3ffb9d50: 0x0000001d 0x00000005 0x400014fd 0x4000150d -0x3ffb9d60: 0xffffffff 0x00000001 0x00000080 0x40082060 -0x3ffb9d70: 0x3ffb0b58 0x00000000 0x00000000 0x00000000 -0x3ffb9d80: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb9d90: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9da0: 0x00000001 0x00000080 0x00000001 0x00000000 -0x3ffb9db0: 0x800e225c 0x3ffb9df0 0x00000001 0x3ffae964 -0x3ffb9dc0: 0x800d2758 0x3ffb9df0 0x0000000a 0x3ffae967 -0x3ffb9dd0: 0x3ffb9e00 0x3ffae964 0x00000000 0x00000000 -0x3ffb9de0: 0x800e22a4 0x3ffb9e20 0x0000000a 0x00000001 -0x3ffb9df0: 0x3f40538c 0x0000001e 0x3f402bbc 0x00000004 -0x3ffb9e00: 0x00000020 0x80000020 0x00000008 0x00000001 -0x3ffb9e10: 0x800881bc 0x3ffb9e50 0x00000000 0x00000000 -0x3ffb9e20: 0x800881bc 0x3ffb9e50 0x00000000 0x00000003 -0x3ffb9e30: 0x3ffb0440 0x80000020 0x00060021 0x00000001 -0x3ffb9e40: 0x00000000 0x3ffb9e70 0x400e228c 0x00000000 -0x3ffb9e50: 0x00060023 0x3ffb5474 0x00000000 0x00000000 -0x3ffb9e60: 0x00000000 0x3ffb9e90 0x00000000 0x00000000 -0x3ffb9e70: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9e80: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9e90: 0x00000000 0x00000000 0x3ffb9e9c 0x00000000 -0x3ffb9ea0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9eb0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9ec0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9ed0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9ee0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9ef0: 0x00000000 -.coredump.tasks.data 0x3ffb956c 0x17c RW -0x3ffb956c: 0x3ffb9250 0x3ffb94f0 0x000019f9 0x3ffb2f50 -0x3ffb957c: 0x3ffb2f50 0x3ffb956c 0x3ffb2f48 0x00000014 -0x3ffb958c: 0x3ffaff34 0x3ffaff34 0x3ffb956c 0x00000000 -0x3ffb959c: 0x00000005 0x3ffb755c 0x74696e75 0x73615479 -0x3ffb95ac: 0xcece006b 0x00cecece 0x00000000 0x3ffb9558 -0x3ffb95bc: 0x00000000 0x00060021 0x0000000c 0xcececece -0x3ffb95cc: 0x00000005 0x00000000 0x00000000 0x00000000 -0x3ffb95dc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb95ec: 0x00000000 0x3ffae8fc 0x3ffae964 0x3ffae9cc -0x3ffb95fc: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb960c: 0x3f403a68 0x00000000 0x40001d48 0x00000000 -0x3ffb961c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb962c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb963c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb964c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb965c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb966c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb967c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb968c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb969c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb96ac: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb96bc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb96cc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb96dc: 0x00000000 0x00000000 0xcecece00 -.coredump.tasks.data 0x3ffb9250 0x308 RW -0x3ffb9250: 0x400820c4 0x400092e6 0x00060930 0x8000930f -0x3ffb9260: 0x3ffb9310 0x3ffb938c 0x00000000 0x3ffb2e3c -0x3ffb9270: 0x0000000a 0x00000057 0x00000037 0x00003ff4 -0x3ffb9280: 0x3ff40000 0xe000c000 0x00000000 0x3ffb2e3c -0x3ffb9290: 0x0ccccccc 0x00000000 0x00000004 0x00000013 -0x3ffb92a0: 0x3ffb9310 0x3ffb938c 0x400014fd 0x4000150d -0x3ffb92b0: 0xffffffff 0x400822c4 0x0ccccccc 0x40088e1c -0x3ffb92c0: 0x3ffb01b8 0x00000000 0x00000000 0x00000000 -0x3ffb92d0: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb92e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb92f0: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb9300: 0x800e07bf 0x3ffb9330 0x3ffb938c 0x000000ff -0x3ffb9310: 0x3ffb01b8 0x00000000 0x00000000 0x00000000 -0x3ffb9320: 0x800e0c02 0x3ffb9350 0x3ffb938c 0x000000ff -0x3ffb9330: 0xc0046c75 0x0000ff00 0x00ff0000 0xff000000 -0x3ffb9340: 0x800e033f 0x3ffb9380 0x00000001 0x3ffb9490 -0x3ffb9350: 0x800e033f 0x3ffb9380 0x00000001 0x9619c4d6 -0x3ffb9360: 0x000000fe 0x3ffb948c 0x00000000 0x00000010 -0x3ffb9370: 0x800881bc 0x3ffb94b0 0x00000000 0x00000000 -0x3ffb9380: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0x00000000 -0x3ffb9390: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb93a0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb93b0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb93c0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb93d0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb93e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb93f0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9400: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9410: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9420: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9430: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9440: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9450: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9460: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9470: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9480: 0x00000000 0x00000000 0x00000000 0x9619c4d6 -0x3ffb9490: 0x3ffb938c 0x80000020 0x00060021 0x3ffb49e0 -0x3ffb94a0: 0x00000000 0x3ffb94d0 0x400e0334 0x00000000 -0x3ffb94b0: 0x00060023 0x3ffb956c 0x00000000 0x00000000 -0x3ffb94c0: 0x00000000 0x3ffb94f0 0x00000000 0x00000000 -0x3ffb94d0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb94e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb94f0: 0x00000000 0x00000000 0x3ffb94fc 0x00000000 -0x3ffb9500: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9510: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9520: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9530: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9540: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb9550: 0x00000000 0x00000000 -.coredump.tasks.data 0x3ffb690c 0x17c RW -0x3ffb690c: 0x3ffb6750 0x3ffb6890 0xcececece 0x3ffb2eec -0x3ffb691c: 0x3ffb6178 0x3ffb690c 0x3ffb2ee4 0x00000019 -0x3ffb692c: 0xcececece 0xcececece 0x3ffb690c 0x00000000 -0x3ffb693c: 0x00000000 0x3ffb62fc 0x454c4449 0xcece0031 -0x3ffb694c: 0xcececece 0x00cecece 0x00000001 0x3ffb68f8 -0x3ffb695c: 0x00000000 0x00060021 0x00000007 0xcececece -0x3ffb696c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb697c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb698c: 0x00000000 0x3ffae8fc 0x3ffae964 0x3ffae9cc -0x3ffb699c: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb69ac: 0x3f403a68 0x00000000 0x40001d48 0x00000000 -0x3ffb69bc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb69cc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb69dc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb69ec: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb69fc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6a0c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6a1c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6a2c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6a3c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6a4c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6a5c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6a6c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6a7c: 0x00000000 0x00000000 0xcecece00 -.coredump.tasks.data 0x3ffb6750 0x1a8 RW -0x3ffb6750: 0x400820c4 0x400e6b22 0x00060430 0x800d1102 -0x3ffb6760: 0x3ffb6810 0x00000000 0x80000001 0x00000000 -0x3ffb6770: 0x00000001 0x00000003 0x00060023 0x80087399 -0x3ffb6780: 0x3ffb6800 0x00000003 0x00060823 0x00060820 -0x3ffb6790: 0x00000001 0x00060820 0x3ffb77c0 0x00000000 -0x3ffb67a0: 0xa5a5a5a5 0xa5a5a5a5 0x4000c46c 0x4000c477 -0x3ffb67b0: 0xffffffff 0x400822c4 0x00000001 0x40088e1c -0x3ffb67c0: 0x3ffad558 0x00000000 0x00000000 0x00000000 -0x3ffb67d0: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb67e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb67f0: 0x00000000 0x40087990 0x00000000 0x00000000 -0x3ffb6800: 0x80087999 0x3ffb6830 0x00000008 0x00000001 -0x3ffb6810: 0x00000001 0x00000001 0x00000003 0x00060023 -0x3ffb6820: 0x800881bc 0x3ffb6850 0x00000000 0x00000000 -0x3ffb6830: 0x00000001 0x80000020 0x00060021 0x00000000 -0x3ffb6840: 0x00000000 0x3ffb6870 0x40087990 0x00000000 -0x3ffb6850: 0x00060023 0x3ffb6170 0x00000000 0x00000001 -0x3ffb6860: 0x00000000 0x3ffb6890 0x00000000 0x00000000 -0x3ffb6870: 0x00000000 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb6aa0 0x17c RW +0x3ffb6aa0: 0x3ffbb490 0x3ffbb5b0 0x00041f72 0x3ffb4088 +0x3ffb6ab0: 0x3ffb4088 0x3ffb6aa0 0x3ffb4080 0x00000012 +0x3ffb6ac0: 0x3ffb6c58 0x3ffb6c58 0x3ffb6aa0 0x00000000 +0x3ffb6ad0: 0x00000007 0x3ffbae1c 0x6c616e75 0x656e6769 +0x3ffb6ae0: 0x74705f64 0x00745f72 0x00000001 0x3ffbb618 +0x3ffb6af0: 0x00000000 0x00060c20 0x0000000f 0xcececece +0x3ffb6b00: 0x00000007 0x00000000 0x00000000 0x00000000 +0x3ffb6b10: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6b20: 0x00000000 0x3ffae908 0x3ffae970 0x3ffae9d8 +0x3ffb6b30: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb6b40: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb6b50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6b60: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6b70: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6b80: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6b90: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6ba0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6bb0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6bc0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6bd0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6be0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6bf0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6c00: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6c10: 0x00000000 0x00000000 0xcecece00 +.coredump.tasks.data 0x3ffbb420 0x1f8 RW +0x3ffbb420: 0xdeadbeef 0x400d0e7d 0x00060830 0x800d0e58 +0x3ffbb430: 0x3ffbb4e0 0x00000002 0x3ffbb52c 0x3ffbb520 +0x3ffbb440: 0x3ffae970 0x00000000 0x00000000 0x00000005 +0x3ffbb450: 0xffffffad 0x00000020 0x3ffb6b20 0x00000001 +0x3ffbb460: 0x00000080 0x00000001 0x00000000 0x00000000 +0x3ffbb470: 0x0000001d 0x00000005 0x400014fd 0x4000150d +0x3ffbb480: 0xffffffff 0x00000001 0x00000080 0x40082438 +0x3ffbb490: 0x3ffb4754 0x00000000 0x00000000 0x00000000 +0x3ffbb4a0: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffbb4b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbb4c0: 0x00000001 0x00000080 0x00000001 0x00000000 +0x3ffbb4d0: 0x800d0e58 0x3ffbb510 0x00000001 0x3ffae970 +0x3ffbb4e0: 0x800db810 0x3ffbb510 0x0000000a 0x00000003 +0x3ffbb4f0: 0x3ffbb520 0x3ffae970 0x00000000 0x00000000 +0x3ffbb500: 0x800d0ea0 0x3ffbb540 0x0000000a 0x3ffb0c94 +0x3ffbb510: 0x3f400294 0x0000001e 0x3f405982 0x00000003 +0x3ffbb520: 0x80088e00 0x3ffb6750 0x00000001 0xc4ebe7dc +0x3ffbb530: 0x800881bc 0x3ffbb570 0x00000000 0x00000000 +0x3ffbb540: 0x800881bc 0x3ffbb570 0x00000000 0x00000003 +0x3ffbb550: 0x00000020 0x80000000 0x00060021 0x00000001 +0x3ffbb560: 0x00000000 0x3ffbb590 0x400d0e88 0x00000000 +0x3ffbb570: 0x00060023 0x3ffb4088 0x3ffb6aa0 0x00000000 +0x3ffbb580: 0x00000000 0x3ffbb5b0 0x00000000 0x00000000 +0x3ffbb590: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbb5a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbb5b0: 0x00000000 0x00000000 0x3ffbb5bc 0x00000000 +0x3ffbb5c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbb5d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbb5e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbb5f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbb600: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbb610: 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffbac90 0x17c RW +0x3ffbac90: 0x3ffba970 0x3ffbac10 0x00041b8f 0x3ffb4060 +0x3ffbaca0: 0x3ffb4060 0x3ffbac90 0x3ffb4058 0x00000014 +0x3ffbacb0: 0x3ffb53b4 0x3ffb53b4 0x3ffbac90 0x00000000 +0x3ffbacc0: 0x00000005 0x3ffb8c80 0x74696e75 0x73615479 +0x3ffbacd0: 0xcece006b 0x00cecece 0x00000000 0x3ffbac7c +0x3ffbace0: 0x00000000 0x00060021 0x0000000c 0xcececece +0x3ffbacf0: 0x00000005 0x00000000 0x00000000 0x00000000 +0x3ffbad00: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbad10: 0x00000000 0x3ffae908 0x3ffae970 0x3ffae9d8 +0x3ffbad20: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffbad30: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffbad40: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbad50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbad60: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbad70: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbad80: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbad90: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbada0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbadb0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbadc0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbadd0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbade0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbadf0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbae00: 0x00000000 0x00000000 0xcecece00 +.coredump.tasks.data 0x3ffba970 0x30c RW +0x3ffba970: 0x4008249c 0x400092d6 0x00060530 0x8000930f +0x3ffba980: 0x3ffbaa30 0x3ffbaaac 0x00000000 0x00000000 +0x3ffba990: 0x00041bc0 0x00000057 0x00000037 0x3ffe019c +0x3ffba9a0: 0x3ff40000 0x00000000 0x00000000 0x00000000 +0x3ffba9b0: 0x00041bc3 0x00000000 0x00000004 0x00000017 +0x3ffba9c0: 0x0000ffff 0x00000000 0x400014fd 0x4000150d +0x3ffba9d0: 0xffffffff 0x4008269c 0x00041bc3 0x400883fc +0x3ffba9e0: 0x3ffb3db4 0x00000000 0x00000000 0x00000000 +0x3ffba9f0: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffbaa00: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbaa10: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffbaa20: 0x800d6133 0x3ffbaa50 0x3ffbaaac 0x000000ff +0x3ffbaa30: 0x3ffb3db4 0x00000000 0x00000000 0x00000000 +0x3ffbaa40: 0x800d5d36 0x3ffbaa70 0x3ffbaaac 0x000000ff +0x3ffbaa50: 0xc0045555 0x0000ff00 0x00ff0000 0xff000000 +0x3ffbaa60: 0x800d61a3 0x3ffbaaa0 0x00000001 0x3ffbabb0 +0x3ffbaa70: 0x800d61a3 0x3ffbaaa0 0x00000001 0xc4ebe7dc +0x3ffbaa80: 0x000000fe 0x3ffbabac 0x7fffffff 0x00000010 +0x3ffbaa90: 0x800881bc 0x3ffbabd0 0x00000000 0x00000000 +0x3ffbaaa0: 0xa5a5a5a5 0xa5a5a5a5 0xa5a5a5a5 0x00000000 +0x3ffbaab0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbaac0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbaad0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbaae0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbaaf0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbab00: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbab10: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbab20: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbab30: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbab40: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbab50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbab60: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbab70: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbab80: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbab90: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbaba0: 0x00000000 0x00000000 0x00000000 0xc4ebe7dc +0x3ffbabb0: 0x3ffbaaac 0x80000000 0x00060021 0x3ffb6120 +0x3ffbabc0: 0x00000000 0x3ffbabf0 0x400d6198 0x00000000 +0x3ffbabd0: 0x00060023 0x3ffb4060 0x3ffbac90 0x00000000 +0x3ffbabe0: 0x00000000 0x3ffbac10 0x00000000 0x00000000 +0x3ffbabf0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbac00: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbac10: 0x00000000 0x00000000 0x3ffbac1c 0x00000000 +0x3ffbac20: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbac30: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbac40: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbac50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbac60: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbac70: 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb804c 0x17c RW +0x3ffb804c: 0x3ffb7e90 0x3ffb7fd0 0xcececece 0x3ffb3ffc +0x3ffb805c: 0x3ffb78b8 0x3ffb804c 0x3ffb3ff4 0x00000019 +0x3ffb806c: 0xcececece 0xcececece 0x3ffb804c 0x00000000 +0x3ffb807c: 0x00000000 0x3ffb7a3c 0x454c4449 0xcece0031 +0x3ffb808c: 0xcececece 0x00cecece 0x00000001 0x3ffb8038 +0x3ffb809c: 0x00000000 0x00060021 0x00000007 0xcececece +0x3ffb80ac: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb80bc: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb80cc: 0x00000000 0x3ffae908 0x3ffae970 0x3ffae9d8 +0x3ffb80dc: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb80ec: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb80fc: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb810c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb811c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb812c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb813c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb814c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb815c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb816c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb817c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb818c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb819c: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb81ac: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb81bc: 0x00000000 0x00000000 0xcecece00 +.coredump.tasks.data 0x3ffb7e90 0x1a8 RW +0x3ffb7e90: 0x4008249c 0x400e8806 0x00060030 0x800d38ce +0x3ffb7ea0: 0x3ffb7f50 0x00000000 0x00000000 0x00000001 +0x3ffb7eb0: 0x80000001 0x00000003 0x00060023 0x800897d4 +0x3ffb7ec0: 0x3ffb7f40 0x00000003 0x00060823 0x00060820 +0x3ffb7ed0: 0x00000001 0x00060820 0x3ffb8ee0 0x00000000 +0x3ffb7ee0: 0x0000ffff 0x00000000 0x4000c46c 0x4000c477 +0x3ffb7ef0: 0xffffffff 0x4008269c 0x00000001 0x400883fc +0x3ffb7f00: 0x3ffb1174 0x00000000 0x00000000 0x00000000 +0x3ffb7f10: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb7f20: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7f30: 0x00000000 0x40089ddc 0x00000000 0x00000000 +0x3ffb7f40: 0x80089de5 0x3ffb7f70 0x00000008 0x00000001 +0x3ffb7f50: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7f60: 0x800881bc 0x3ffb7f90 0x00000000 0x00000000 +0x3ffb7f70: 0x00000001 0x80000000 0x00060021 0x00000000 +0x3ffb7f80: 0x00000000 0x3ffb7fb0 0x40089ddc 0x00000000 +0x3ffb7f90: 0x00060023 0x3ffb3ffc 0x3ffb78b0 0x00000000 +0x3ffb7fa0: 0x00000000 0x3ffb7fd0 0x00000000 0x00000000 +0x3ffb7fb0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7fc0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7fd0: 0x00000000 0x00000000 0x3ffb7fdc 0x00000000 +0x3ffb7fe0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7ff0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8000: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8010: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8020: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8030: 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb78b0 0x17c RW +0x3ffb78b0: 0x3ffb76f0 0x3ffb7830 0xcececece 0x3ffb8054 +0x3ffb78c0: 0x3ffb3ffc 0x3ffb78b0 0x3ffb3ff4 0x00000019 +0x3ffb78d0: 0xcececece 0xcececece 0x3ffb78b0 0x00000000 +0x3ffb78e0: 0x00000000 0x3ffb72a0 0x454c4449 0xcece0030 +0x3ffb78f0: 0xcececece 0x00cecece 0x00000000 0x3ffb789c +0x3ffb7900: 0x00000000 0x00060021 0x00000006 0xcececece +0x3ffb7910: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7920: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7930: 0x00000000 0x3ffae908 0x3ffae970 0x3ffae9d8 +0x3ffb7940: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb7950: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb7960: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7970: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7980: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7990: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb79a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb79b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb79c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb79d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb79e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb79f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7a00: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7a10: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7a20: 0x00000000 0x00000000 0xcecece00 +.coredump.tasks.data 0x3ffb76f0 0x1ac RW +0x3ffb76f0: 0x4008249c 0x400e8806 0x00060530 0x800d38ce +0x3ffb7700: 0x3ffb77b0 0x00000000 0x00000003 0x00000001 +0x3ffb7710: 0x80000001 0x00000003 0x00060023 0x8008917a +0x3ffb7720: 0x3ffb7790 0x3ffb7114 0x40001d48 0x00060420 +0x3ffb7730: 0x00000001 0x00060420 0x00000000 0x00000000 +0x3ffb7740: 0x0000ffff 0x00000000 0x4000c46c 0x4000c477 +0x3ffb7750: 0xffffffff 0x4008269c 0x00000001 0x400883fc +0x3ffb7760: 0x3ffb09d4 0x00000000 0x00000000 0x00000000 +0x3ffb7770: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb7780: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7790: 0x00000000 0x40089ddc 0x00000000 0x00000000 +0x3ffb77a0: 0x80089de5 0x3ffb77d0 0x00000008 0x00000000 +0x3ffb77b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb77c0: 0x800881bc 0x3ffb77f0 0x00000000 0x00000000 +0x3ffb77d0: 0x00000001 0x80000000 0x00000000 0x00000000 +0x3ffb77e0: 0x00000000 0x3ffb7810 0x40089ddc 0x00000000 +0x3ffb77f0: 0x00060023 0x3ffb3ffc 0x3ffb78b0 0x00000001 +0x3ffb7800: 0x00000000 0x3ffb7830 0x00000000 0x00000000 +0x3ffb7810: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7820: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7830: 0x00000000 0x00000000 0x3ffb783c 0x00000000 +0x3ffb7840: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7850: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7860: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7870: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7880: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb7890: 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb6914 0x17c RW +0x3ffb6914: 0x3ffb6760 0x3ffb68a0 0x0004235a 0x3ffb3fe8 +0x3ffb6924: 0x3ffb6ca0 0x3ffb6914 0x3ffb3fe0 0x00000014 +0x3ffb6934: 0xcececece 0xcececece 0x3ffb6914 0x00000000 +0x3ffb6944: 0x00000005 0x3ffb6104 0x5f646162 0x5f727470 +0x3ffb6954: 0x6b736174 0x00cece00 0x7fffffff 0x3ffb6900 +0x3ffb6964: 0x00000000 0x00060021 0x0000000e 0xcececece +0x3ffb6974: 0x00000005 0x00000000 0x00000000 0x00000000 +0x3ffb6984: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6994: 0x00000000 0x3ffae908 0x3ffae970 0x3ffae9d8 +0x3ffb69a4: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb69b4: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb69c4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb69d4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb69e4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb69f4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6a04: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6a14: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6a24: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6a34: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6a44: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6a54: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6a64: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6a74: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6a84: 0x00000000 0x00000000 0xcecece00 +.coredump.tasks.data 0x3ffb6760 0x1a0 RW +0x3ffb6760: 0x4008249c 0x40081448 0x00060530 0x80089bba +0x3ffb6770: 0x3ffb6820 0x00000000 0x0004235a 0x800897d4 +0x3ffb6780: 0x3ffb5700 0x00000003 0x00060823 0x80081448 +0x3ffb6790: 0x3ffb6800 0x3ff000dc 0x00000001 0x3ffb0038 +0x3ffb67a0: 0x00000001 0x00060520 0x00000000 0x00000000 +0x3ffb67b0: 0x0000ffff 0x00000000 0x400014fd 0x4000150d +0x3ffb67c0: 0xfffffff9 0x4008269c 0x00000001 0x400883fc +0x3ffb67d0: 0x3ffafa44 0x00000000 0x00000000 0x00000000 +0x3ffb67e0: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb67f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6800: 0x3f400230 0x00000018 0x3f405982 0x00000001 +0x3ffb6810: 0x800d0e1b 0x3ffb6840 0x0004235a 0x3ffb0c94 +0x3ffb6820: 0x800897d4 0x3ffb5700 0x00000003 0x00060823 +0x3ffb6830: 0x800881bc 0x3ffb6860 0x00000000 0x00000000 +0x3ffb6840: 0x00000020 0x80000000 0x00060021 0x00000000 +0x3ffb6850: 0x00000000 0x3ffb6880 0x400d0e0c 0x00000000 +0x3ffb6860: 0x00060023 0x3ffb4060 0x3ffbac90 0x00000000 +0x3ffb6870: 0x00000000 0x3ffb68a0 0x00000000 0x00000000 0x3ffb6880: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6890: 0x00000000 0x00000000 0x3ffb689c 0x00000000 -0x3ffb68a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6890: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb68a0: 0x00000000 0x00000000 0x3ffb68ac 0x00000000 0x3ffb68b0: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffb68c0: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffb68d0: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffb68e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb68f0: 0x00000000 0x00000000 -.coredump.tasks.data 0x3ffb6170 0x17c RW -0x3ffb6170: 0x3ffb5fb0 0x3ffb60f0 0xcececece 0x3ffb6914 -0x3ffb6180: 0x3ffb2eec 0x3ffb6170 0x3ffb2ee4 0x00000019 -0x3ffb6190: 0xcececece 0xcececece 0x3ffb6170 0x00000000 -0x3ffb61a0: 0x00000000 0x3ffb5b60 0x454c4449 0xcece0030 -0x3ffb61b0: 0xcececece 0x00cecece 0x00000000 0x3ffb615c -0x3ffb61c0: 0x00000000 0x00060021 0x00000006 0xcececece -0x3ffb61d0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb61e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb61f0: 0x00000000 0x3ffae8fc 0x3ffae964 0x3ffae9cc -0x3ffb6200: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb6210: 0x3f403a68 0x00000000 0x40001d48 0x00000000 -0x3ffb6220: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6230: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6240: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6250: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6260: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6270: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6280: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6290: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb62a0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb62b0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb62c0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb62d0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb62e0: 0x00000000 0x00000000 0xcecece00 -.coredump.tasks.data 0x3ffb5fb0 0x1ac RW -0x3ffb5fb0: 0x400820c4 0x400e6b22 0x00060730 0x800d1102 -0x3ffb5fc0: 0x3ffb6070 0x00000000 0x00000003 0x00000000 -0x3ffb5fd0: 0x00000001 0x00000003 0x00060123 0x00060023 -0x3ffb5fe0: 0x3ffb690c 0x00000000 0x00000001 0x800883d8 -0x3ffb5ff0: 0x3ffb8e90 0x00000000 0x3ffb5b60 0x00000000 -0x3ffb6000: 0x3ffb2d88 0x00000000 0x4000c46c 0x4000c477 -0x3ffb6010: 0xffffffff 0x400822c4 0x3ffb8e90 0x40088e1c -0x3ffb6020: 0x3ffacdb8 0x00000000 0x00000000 0x00000000 -0x3ffb6030: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb6040: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6050: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb6060: 0x80087999 0x3ffb6090 0x00000008 0x00000000 -0x3ffb6070: 0x00000000 0x00000001 0x00000003 0x00060123 -0x3ffb6080: 0x800881bc 0x3ffb60b0 0x00000000 0x00000000 -0x3ffb6090: 0x00000001 0x80000020 0x00060021 0x00000000 -0x3ffb60a0: 0x00000000 0x3ffb60d0 0x40087990 0x00000000 -0x3ffb60b0: 0x00060023 0x3ffb690c 0x00000000 0x00000000 -0x3ffb60c0: 0x00000000 0x3ffb60f0 0x00000000 0x00000000 -0x3ffb60d0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb60e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb60f0: 0x00000000 0x00000000 0x3ffb60fc 0x00000000 -0x3ffb6100: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6110: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6120: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6130: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6140: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb6150: 0x00000000 0x00000000 0x00000000 -.coredump.tasks.data 0x3ffb52e8 0x17c RW -0x3ffb52e8: 0x3ffb5150 0x3ffb5270 0x000021c4 0x3ffb2ed8 -0x3ffb52f8: 0x3ffb5674 0x3ffb52e8 0x3ffb2ed0 0x00000014 -0x3ffb5308: 0x3ffb562c 0x3ffb562c 0x3ffb52e8 0x00000000 -0x3ffb5318: 0x00000005 0x3ffb4ad8 0x5f646162 0x5f727470 -0x3ffb5328: 0x6b736174 0x00cece00 0x7fffffff 0x3ffb52d4 -0x3ffb5338: 0x00000000 0x00060021 0x0000000e 0xcececece -0x3ffb5348: 0x00000005 0x00000000 0x00000000 0x00000000 -0x3ffb5358: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5368: 0x00000000 0x3ffae8fc 0x3ffae964 0x3ffae9cc -0x3ffb5378: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb5388: 0x3f403a68 0x00000000 0x40001d48 0x00000000 -0x3ffb5398: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb53a8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb53b8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb53c8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb53d8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb53e8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb53f8: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5408: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5418: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5428: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5438: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5448: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5458: 0x00000000 0x00000000 0xcecece00 -.coredump.tasks.data 0x3ffb5150 0x184 RW -0x3ffb5150: 0x400820c4 0x40087782 0x00060730 0x800e2227 -0x3ffb5160: 0x3ffb5210 0x000021c4 0x00000000 0x3ffb0440 -0x3ffb5170: 0x80000020 0x00060021 0x00060823 0x80087782 -0x3ffb5180: 0x3ffb51f0 0x00000000 0x000021c4 0x80081cec -0x3ffb5190: 0x3ffb3f30 0x3ff000dc 0x00000001 0x00000000 -0x3ffb51a0: 0x800d2758 0x3ffb51d0 0x400014fd 0x4000150d -0x3ffb51b0: 0xfffffff9 0x400822c4 0x3ffb3f30 0x40088e1c -0x3ffb51c0: 0x3ffabf38 0x00000000 0x00000000 0x00000000 -0x3ffb51d0: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb51e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb51f0: 0x80081cec 0x3ffb3f30 0x3ff000dc 0x00000001 -0x3ffb5200: 0x800881bc 0x3ffb5230 0x00000000 0x00000000 -0x3ffb5210: 0x3ffb0440 0x80000020 0x00060021 0x00060823 -0x3ffb5220: 0x00000000 0x3ffb5250 0x400e2218 0x00000000 -0x3ffb5230: 0x00060023 0x3ffb956c 0x00000000 0x00000000 -0x3ffb5240: 0x00000000 0x3ffb5270 0x00000000 0x00000000 -0x3ffb5250: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5260: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5270: 0x00000000 0x00000000 0x3ffb527c 0x00000000 -0x3ffb5280: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb5290: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb52a0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb52b0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb52c0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb52d0: 0x00000000 -.coredump.tasks.data 0x3ffb566c 0x17c RW -0x3ffb566c: 0x3ffba580 0x3ffba6a0 0x000021c4 0x3ffb52f0 -0x3ffb567c: 0x3ffb2ed8 0x3ffb566c 0x3ffb2ed0 0x0000000f -0x3ffb568c: 0xcececece 0xcececece 0x3ffb566c 0x00000000 -0x3ffb569c: 0x0000000a 0x3ffb9f08 0x6c696166 0x615f6465 -0x3ffb56ac: 0x72657373 0x00745f74 0x00000000 0x3ffba704 -0x3ffb56bc: 0x00000000 0x00060021 0x00000010 0xcececece -0x3ffb56cc: 0x0000000a 0x00000000 0x00000000 0x00000000 -0x3ffb56dc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb56ec: 0x00000000 0x3ffae8fc 0x3ffae964 0x3ffae9cc -0x3ffb56fc: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb570c: 0x3f403a68 0x00000000 0x40001d48 0x00000000 -0x3ffb571c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb572c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb573c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb574c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb575c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb576c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb577c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb578c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb579c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb57ac: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb57bc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb57cc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb57dc: 0x00000000 0x00000000 0xcecece00 -.coredump.tasks.data 0x3ffba580 0x184 RW -0x3ffba580: 0x400820c4 0x40087782 0x00060930 0x800e216b -0x3ffba590: 0x3ffba640 0x000021c4 0x00000000 0x3ffb0440 -0x3ffba5a0: 0x80000020 0x00060021 0x00000000 0x80087782 -0x3ffba5b0: 0x3ffba620 0x00000000 0x000021c4 0x800e0678 -0x3ffba5c0: 0x3ffb92c0 0x00000800 0x3ffb1640 0x00000000 -0x3ffba5d0: 0x800d2758 0x3ffba600 0x400014fd 0x4000150d -0x3ffba5e0: 0xfffffff8 0x400822c4 0x3ffb92c0 0x40088e1c -0x3ffba5f0: 0x3ffb1368 0x00000000 0x00000000 0x00000000 -0x3ffba600: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffba610: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffba620: 0x800e0678 0x3ffb92c0 0x00000800 0x3ffb1640 -0x3ffba630: 0x800881bc 0x3ffba660 0x00000000 0x00000000 -0x3ffba640: 0x3ffb0440 0x80000020 0x00060021 0x00000000 -0x3ffba650: 0x00000000 0x3ffba680 0x400e215c 0x00000000 -0x3ffba660: 0x00060023 0x3ffb566c 0x00000000 0x00000000 -0x3ffba670: 0x00000000 0x3ffba6a0 0x00000000 0x00000000 -0x3ffba680: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffba690: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffba6a0: 0x00000000 0x00000000 0x3ffba6ac 0x00000000 -0x3ffba6b0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffba6c0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffba6d0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffba6e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffba6f0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffba700: 0x00000000 -.coredump.tasks.data 0x3ffb73b4 0x17c RW -0x3ffb73b4: 0x3ffb7200 0x3ffb7340 0x00000000 0x3ffb2ec4 -0x3ffb73c4: 0x3ffb2ec4 0x3ffb73b4 0x3ffb2ebc 0x00000018 -0x3ffb73d4: 0x3ffb6ac4 0x3ffb6ac4 0x3ffb73b4 0x3ffb6abc -0x3ffb73e4: 0x00000001 0x3ffb6ba4 0x20726d54 0x00637653 -0x3ffb73f4: 0xcececece 0x00cecece 0x00000000 0x3ffb73a0 -0x3ffb7404: 0x00000000 0x00060021 0x00000008 0xcececece -0x3ffb7414: 0x00000001 0x00000000 0x00000000 0x00000000 -0x3ffb7424: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7434: 0x00000000 0x3ffae8fc 0x3ffae964 0x3ffae9cc -0x3ffb7444: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb7454: 0x3f403a68 0x00000000 0x40001d48 0x00000000 -0x3ffb7464: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7474: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7484: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7494: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb74a4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb74b4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb74c4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb74d4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb74e4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb74f4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7504: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7514: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7524: 0x00000000 0x00000000 0xcecece00 -.coredump.tasks.data 0x3ffb7200 0x1a0 RW -0x3ffb7200: 0x400820c4 0x400893f2 0x00060a30 0x80089527 -0x3ffb7210: 0x3ffb72c0 0x3ffb3130 0x00000000 0x00000001 -0x3ffb7220: 0x80000020 0x00060021 0x00000000 0x800893f2 -0x3ffb7230: 0x3ffb72a0 0x00000000 0x3ffb2e3c 0x3ffb6aec -0x3ffb7240: 0x00000000 0x00000000 0x00060023 0x00000000 -0x3ffb7250: 0xa5a5a5a5 0xa5a5a5a5 0x00000000 0x00000000 -0x3ffb7260: 0x00000000 0x400822c4 0x00000000 0x40088e1c -0x3ffb7270: 0x3ffae008 0x00000000 0x00000000 0x00000000 -0x3ffb7280: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb7290: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb72a0: 0x00000000 0x4008950c 0x00000000 0x00000000 -0x3ffb72b0: 0x800881bc 0x3ffb72f0 0x00000000 0x00000000 -0x3ffb72c0: 0x00000000 0x00000000 0x00000000 0x9619c4d6 -0x3ffb72d0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb72e0: 0x00000000 0x3ffb7320 0x4008950c 0x00000000 -0x3ffb72f0: 0x3ffae008 0x00000000 0x00000001 0x9619c4d6 -0x3ffb7300: 0x00060023 0x3ffb59d4 0x00000000 0x00000001 -0x3ffb7310: 0x00000000 0x3ffb7340 0x00000000 0x00000000 -0x3ffb7320: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7330: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7340: 0x00000000 0x00000000 0x3ffb734c 0x00000000 -0x3ffb7350: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7360: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7370: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7380: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb7390: 0x00000000 0x00000000 0x00000000 0x00000000 -.coredump.tasks.data 0x3ffafb94 0x17c RW -0x3ffafb94: 0x3ffaf9e0 0x3ffafb20 0xcececece 0x3ffb40cc -0x3ffafba4: 0x3ffb3ac4 0x3ffafb94 0x3ffb2e60 0x00000003 -0x3ffafbb4: 0x3ffaead8 0x3ffaead8 0x3ffafb94 0x3ffaead0 -0x3ffafbc4: 0x00000016 0x3ffaeb84 0x5f707365 0x656d6974 -0x3ffafbd4: 0xcece0072 0x00cecece 0x00000000 0x3ffafb80 -0x3ffafbe4: 0x00000000 0x00060021 0x00000001 0xcececece -0x3ffafbf4: 0x00000016 0x00000000 0x00000000 0x00000000 +0x3ffb68f0: 0x00000000 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb6c98 0x17c RW +0x3ffb6c98: 0x3ffbbc80 0x3ffbbdc0 0x0004235a 0x3ffb691c +0x3ffb6ca8: 0x3ffb3fe8 0x3ffb6c98 0x3ffb3fe0 0x0000000f +0x3ffb6cb8: 0x3ffb6abc 0x3ffb6c58 0x3ffb6c98 0x00000000 +0x3ffb6cc8: 0x0000000a 0x3ffbb62c 0x6c696166 0x615f6465 +0x3ffb6cd8: 0x72657373 0x00745f74 0x00000000 0x3ffbbe28 +0x3ffb6ce8: 0x00000000 0x00060021 0x00000010 0xcececece +0x3ffb6cf8: 0x0000000a 0x00000000 0x00000000 0x00000000 +0x3ffb6d08: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6d18: 0x00000000 0x3ffae908 0x3ffae970 0x3ffae9d8 +0x3ffb6d28: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb6d38: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb6d48: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6d58: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6d68: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6d78: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6d88: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6d98: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6da8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6db8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6dc8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6dd8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6de8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6df8: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb6e08: 0x00000000 0x00000000 0xcecece00 +.coredump.tasks.data 0x3ffbbc80 0x1a8 RW +0x3ffbbc80: 0x4008249c 0x40081448 0x00060330 0x80089bba +0x3ffbbc90: 0x3ffbbd40 0x00000000 0x0004235a 0x800d58ed +0x3ffbbca0: 0x3ffba9e0 0x00000800 0x3ffb0004 0x80081448 +0x3ffbbcb0: 0x3ffbbd20 0x3ff000dc 0x00000001 0x3ffb0038 +0x3ffbbcc0: 0x00000001 0x00060320 0x00000000 0x00000000 +0x3ffbbcd0: 0x0000ffff 0x00000000 0x400014fd 0x4000150d +0x3ffbbce0: 0xfffffff8 0x4008269c 0x00000001 0x400883fc +0x3ffbbcf0: 0x3ffb4f64 0x00000000 0x00000000 0x00000000 +0x3ffbbd00: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffbbd10: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbbd20: 0x3f400144 0x0000001e 0x3f405982 0x00000001 +0x3ffbbd30: 0x800d0d5b 0x3ffbbd60 0x0004235a 0x3ffb0c94 +0x3ffbbd40: 0x800d58ed 0x3ffba9e0 0x00000800 0x3ffb0004 +0x3ffbbd50: 0x800881bc 0x3ffbbd80 0x00000000 0x00000000 +0x3ffbbd60: 0x00000020 0x80000000 0x00060021 0x00000000 +0x3ffbbd70: 0x00000000 0x3ffbbda0 0x400d0d4c 0x00000000 +0x3ffbbd80: 0x00060023 0x3ffb40c4 0x3ffb6c98 0x00000000 +0x3ffbbd90: 0x00000000 0x3ffbbdc0 0x00000000 0x00000000 +0x3ffbbda0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbbdb0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbbdc0: 0x00000000 0x00000000 0x3ffbbdcc 0x00000000 +0x3ffbbdd0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbbde0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbbdf0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbbe00: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbbe10: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffbbe20: 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb8af4 0x17c RW +0x3ffb8af4: 0x3ffb8920 0x3ffb8a80 0x00000000 0x3ffb3fd4 +0x3ffb8b04: 0x3ffb3fd4 0x3ffb8af4 0x3ffb3fcc 0x00000018 +0x3ffb8b14: 0x3ffb8204 0x3ffb8204 0x3ffb8af4 0x3ffb81fc +0x3ffb8b24: 0x00000001 0x3ffb82e4 0x20726d54 0x00637653 +0x3ffb8b34: 0xcececece 0x00cecece 0x00000000 0x3ffb8ae0 +0x3ffb8b44: 0x00000000 0x00060021 0x00000008 0xcececece +0x3ffb8b54: 0x00000001 0x00000000 0x00000000 0x00000000 +0x3ffb8b64: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8b74: 0x00000000 0x3ffae908 0x3ffae970 0x3ffae9d8 +0x3ffb8b84: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb8b94: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb8ba4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8bb4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8bc4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8bd4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8be4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8bf4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8c04: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8c14: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8c24: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8c34: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8c44: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8c54: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8c64: 0x00000000 0x00000000 0xcecece00 +.coredump.tasks.data 0x3ffb8920 0x1c0 RW +0x3ffb8920: 0x4008249c 0x40081448 0x00060030 0x8008a95d +0x3ffb8930: 0x3ffb89e0 0x00000000 0x00000000 0x3ffb822c +0x3ffb8940: 0x00000000 0x00000000 0x3ffb5c60 0x80081448 +0x3ffb8950: 0x3ffb89c0 0x3ff000dc 0x00000001 0x3ffb0038 +0x3ffb8960: 0x3ffb5c70 0x400d2b88 0x00000000 0x00000000 +0x3ffb8970: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3ffb8980: 0x00000000 0x4008269c 0x3ffb5c70 0x400883fc +0x3ffb8990: 0x3ffb1c24 0x00000000 0x00000000 0x00000000 +0x3ffb89a0: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb89b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb89c0: 0x4008249c 0x400881b4 0x00050030 0xc4ebe7dc +0x3ffb89d0: 0x8008aa8f 0x3ffb8a00 0x3ffb41f4 0x00000000 +0x3ffb89e0: 0x00000000 0x4008aa74 0x00000000 0x00000000 +0x3ffb89f0: 0x800881bc 0x3ffb8a30 0x00000000 0x00000000 +0x3ffb8a00: 0x00000000 0x00000000 0x00000000 0xc4ebe7dc +0x3ffb8a10: 0x00000001 0x80000000 0x00060021 0x00060023 +0x3ffb8a20: 0x00000000 0x3ffb8a60 0x4008aa74 0x00000000 +0x3ffb8a30: 0x3ffb1c24 0x00000000 0x00000001 0xc4ebe7dc +0x3ffb8a40: 0x00060023 0x3ffb4010 0x3ffb7114 0x00000000 +0x3ffb8a50: 0x00000000 0x3ffb8a80 0x00000000 0x00000000 +0x3ffb8a60: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8a70: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8a80: 0x00000000 0x00000000 0x3ffb8a8c 0x00000000 +0x3ffb8a90: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8aa0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8ab0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8ac0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb8ad0: 0x00000000 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffafb34 0x17c RW +0x3ffafb34: 0x3ffaf960 0x3ffafac0 0xcececece 0x3ffb5878 +0x3ffafb44: 0x3ffb5198 0x3ffafb34 0x3ffb3f70 0x00000003 +0x3ffafb54: 0x3ffaeae4 0x3ffaeae4 0x3ffafb34 0x3ffaeadc +0x3ffafb64: 0x00000016 0x3ffaeb24 0x5f707365 0x656d6974 +0x3ffafb74: 0xcece0072 0x00cecece 0x00000000 0x3ffafb20 +0x3ffafb84: 0x00000000 0x00060021 0x00000001 0xcececece +0x3ffafb94: 0x00000016 0x00000000 0x00000000 0x00000000 +0x3ffafba4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafbb4: 0x00000000 0x3ffae908 0x3ffae970 0x3ffae9d8 +0x3ffafbc4: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffafbd4: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffafbe4: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafbf4: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffafc04: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafc14: 0x00000000 0x3ffae8fc 0x3ffae964 0x3ffae9cc -0x3ffafc24: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffafc34: 0x3f403a68 0x00000000 0x40001d48 0x00000000 +0x3ffafc14: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafc24: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafc34: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffafc44: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffafc54: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffafc64: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffafc74: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffafc84: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffafc94: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafca4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafcb4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafcc4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafcd4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafce4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafcf4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafd04: 0x00000000 0x00000000 0xcecece00 -.coredump.tasks.data 0x3ffaf9e0 0x1a0 RW -0x3ffaf9e0: 0x400820c4 0x40088bb4 0x00060030 0x800d0f9b -0x3ffaf9f0: 0x3ffafaa0 0x3ffaeaac 0x00000000 0x3ffaeb00 -0x3ffafa00: 0x00000000 0x00000001 0x00000000 0x80088bb4 -0x3ffafa10: 0x3ffafa80 0x00000000 0x3ffb30d8 0x3ffb30d8 -0x3ffafa20: 0x3ffb3950 0x00000003 0x00060e23 0x00000000 -0x3ffafa30: 0xa5a5a5a5 0xa5a5a5a5 0x00000000 0x00000000 -0x3ffafa40: 0x00000000 0x400822c4 0x3ffb3950 0x40088e1c -0x3ffafa50: 0x3ffa67e8 0x00000000 0x00000000 0x00000000 -0x3ffafa60: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffafa70: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafa80: 0x00000000 0x400d0f88 0x00000000 0x00000000 -0x3ffafa90: 0x800881bc 0x3ffafae0 0x00000000 0x00000000 -0x3ffafaa0: 0x00000000 0x00000000 0x00000000 0xffffffff -0x3ffafab0: 0x00000000 0x00000000 0x00000000 0x9619c4d6 -0x3ffafac0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafad0: 0x00000000 0x3ffafb00 0x400d0f88 0x00000000 -0x3ffafae0: 0x00060023 0x3ffafb94 0x00000000 0x00000001 -0x3ffafaf0: 0x00000000 0x3ffafb20 0x00000000 0x00000000 +0x3ffafca4: 0x00000000 0x00000000 0xcecece00 +.coredump.tasks.data 0x3ffaf960 0x1c0 RW +0x3ffaf960: 0x4008249c 0x40081448 0x00060630 0x80088d90 +0x3ffaf970: 0x3ffafa20 0x00000000 0x00000000 0x3ffb41e8 +0x3ffaf980: 0x0000001d 0x00000055 0x3ffb50e0 0x80081448 +0x3ffaf990: 0x3ffafa00 0x3ff000dc 0x00000001 0x3ffb0038 +0x3ffaf9a0: 0x00000001 0x00060620 0x00000000 0x00000000 +0x3ffaf9b0: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3ffaf9c0: 0x00000000 0x4008269c 0x00000001 0x400883fc +0x3ffaf9d0: 0x3ffa8c64 0x00000000 0x00000000 0x00000000 +0x3ffaf9e0: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffaf9f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafa00: 0x4008249c 0x400881b4 0x00050030 0x00000000 +0x3ffafa10: 0x800d3807 0x3ffafa40 0x3ffaeab8 0x00000000 +0x3ffafa20: 0x00000000 0x400d37f4 0x00000000 0x00000000 +0x3ffafa30: 0x800881bc 0x3ffafa80 0x00000000 0x00000000 +0x3ffafa40: 0x00000000 0x00000000 0x00000000 0xffffffff +0x3ffafa50: 0x00000000 0x00000000 0x0003d6f3 0xc4ebe7dc +0x3ffafa60: 0x3ffaeb0c 0x00000000 0x00000001 0x00060e23 +0x3ffafa70: 0x00000000 0x3ffafaa0 0x400d37f4 0x00000000 +0x3ffafa80: 0x00060023 0x3ffb41b4 0x3ffafb34 0x00000000 +0x3ffafa90: 0x00000000 0x3ffafac0 0x00000000 0x00000000 +0x3ffafaa0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafab0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafac0: 0x00000000 0x00000000 0x3ffafacc 0x00000000 +0x3ffafad0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafae0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffafaf0: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffafb00: 0x00000000 0x00000000 0x00000000 0x00000000 0x3ffafb10: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafb20: 0x00000000 0x00000000 0x3ffafb2c 0x00000000 -0x3ffafb30: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafb40: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafb50: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafb60: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffafb70: 0x00000000 0x00000000 0x00000000 0x00000000 -.coredump.tasks.data 0x3ffb40c4 0x17c RW -0x3ffb40c4: 0x3ffb3ef0 0x3ffb4050 0xcececece 0x3ffb2e68 -0x3ffb40d4: 0x3ffafb9c 0x3ffb40c4 0x3ffb2e60 0x00000001 -0x3ffb40e4: 0x3ffb3c74 0x3ffb3c74 0x3ffb40c4 0x3ffb3c6c -0x3ffb40f4: 0x00000018 0x3ffb3cb4 0x31637069 0xcecece00 -0x3ffb4104: 0xcececece 0x00cecece 0x00000001 0x3ffb40b0 -0x3ffb4114: 0x00000000 0x00060021 0x00000003 0xcececece -0x3ffb4124: 0x00000018 0x00000000 0x00000000 0x00000000 -0x3ffb4134: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb4144: 0x00000000 0x3ffae8fc 0x3ffae964 0x3ffae9cc -0x3ffb4154: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb4164: 0x3f403a68 0x00000000 0x40001d48 0x00000000 -0x3ffb4174: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb4184: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb4194: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb41a4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb41b4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb41c4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb41d4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb41e4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb41f4: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb4204: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb4214: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb4224: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb4234: 0x00000000 0x00000000 0xcecece00 -.coredump.tasks.data 0x3ffb3ef0 0x1c0 RW -0x3ffb3ef0: 0x400820c4 0x40081cec 0x00060830 0x80088bb4 -0x3ffb3f00: 0x3ffb3fb0 0x00000001 0x3ffb30d8 0x3ffb30dc -0x3ffb3f10: 0x0000000a 0x00800000 0x3ff4001c 0x80081cec -0x3ffb3f20: 0x3ffb3f90 0x3ff000e0 0x00000001 0x3ffb0028 -0x3ffb3f30: 0x00000001 0x00060820 0x3ffb3cc0 0x00000000 -0x3ffb3f40: 0x3ffb3fb0 0x00000001 0x00000000 0x00000000 -0x3ffb3f50: 0x00000000 0x400822c4 0x00000001 0x40088e1c -0x3ffb3f60: 0x3ffaad18 0x00000000 0x00000000 0x00000000 -0x3ffb3f70: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb3f80: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3f90: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb3fa0: 0x80081f37 0x3ffb3fd0 0x3ffb3c48 0x00000000 -0x3ffb3fb0: 0x3ffb30dc 0x0000000a 0x00800000 0x3ff4001c -0x3ffb3fc0: 0x800881bc 0x3ffb4010 0x00000001 0x400835cc -0x3ffb3fd0: 0x3ffb9574 0x0000000a 0x00800000 0xffffffff -0x3ffb3fe0: 0x800881bc 0x00000000 0x000019f4 0x9619c4d6 -0x3ffb3ff0: 0x3ffb3c9c 0x00000000 0x00000001 0x00000000 -0x3ffb4000: 0x00000000 0x3ffb4030 0x40081f08 0x00000001 -0x3ffb4010: 0x00000001 0x3ffb40c4 0x00000000 0x00000000 -0x3ffb4020: 0x00000000 0x3ffb4050 0x00000000 0x00000000 -0x3ffb4030: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb4040: 0x80081044 0x3ffe7d80 0x00000028 0x00000028 -0x3ffb4050: 0x00000000 0x00000000 0x3ffb405c 0x00000000 -0x3ffb4060: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb4070: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb4080: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb4090: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb40a0: 0x00000000 0x00000000 0x00000000 0x00000000 -.coredump.tasks.data 0x3ffb3abc 0x17c RW -0x3ffb3abc: 0x3ffb3900 0x3ffb3a40 0xcececece 0x3ffafb9c -0x3ffb3acc: 0x3ffb2e68 0x3ffb3abc 0x3ffb2e60 0x00000001 -0x3ffb3adc: 0x3ffaffa0 0x3ffaffa0 0x3ffb3abc 0x3ffaff98 -0x3ffb3aec: 0x00000018 0x3ffb36ac 0x30637069 0xcecece00 -0x3ffb3afc: 0xcececece 0x00cecece 0x00000000 0x3ffb3aa8 -0x3ffb3b0c: 0x00000000 0x00060021 0x00000002 0xcececece -0x3ffb3b1c: 0x00000018 0x00000000 0x00000000 0x00000000 -0x3ffb3b2c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3b3c: 0x00000000 0x3ffae8fc 0x3ffae964 0x3ffae9cc -0x3ffb3b4c: 0x00000000 0x00000000 0x00000001 0x00000000 -0x3ffb3b5c: 0x3f403a68 0x00000000 0x40001d48 0x00000000 -0x3ffb3b6c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3b7c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3b8c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3b9c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3bac: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3bbc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3bcc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3bdc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3bec: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3bfc: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3c0c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3c1c: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3c2c: 0x00000000 0x00000000 0xcecece00 -.coredump.tasks.data 0x3ffb3900 0x1a8 RW -0x3ffb3900: 0x400820c4 0x40088bb4 0x00060e30 0x80081f37 -0x3ffb3910: 0x3ffb39c0 0x3ffaff74 0x00000000 0x3ffaffc8 -0x3ffb3920: 0x00000000 0x00000001 0x00000002 0x80088bb4 -0x3ffb3930: 0x3ffb39a0 0x00000000 0x3ffb30d8 0x3ffb30d8 -0x3ffb3940: 0x0000cdcd 0x00000001 0x00000000 0x00000000 -0x3ffb3950: 0xa5a5a5a5 0xa5a5a5a5 0x00000000 0x00000000 -0x3ffb3960: 0x00000000 0x400822c4 0x0000cdcd 0x40088e1c -0x3ffb3970: 0x3ffaa708 0x00000000 0x00000000 0x00000000 -0x3ffb3980: 0xb33fffff 0x00000000 0x00000000 0x00000000 -0x3ffb3990: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb39a0: 0x00000000 0x40081f08 0x00000000 0x00000000 -0x3ffb39b0: 0x800881bc 0x3ffb3a00 0x00000000 0x00000000 -0x3ffb39c0: 0x00000000 0x00000000 0x00000000 0xffffffff -0x3ffb39d0: 0x00000000 0x00000000 0x00000000 0x9619c4d6 -0x3ffb39e0: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb39f0: 0x00000000 0x3ffb3a20 0x40081f08 0x00000000 -0x3ffb3a00: 0x00060323 0x3ffb3abc 0x00000001 0x00000001 -0x3ffb3a10: 0x00000000 0x3ffb3a40 0x00000000 0x00000000 -0x3ffb3a20: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3a30: 0x80080fbe 0x3ffe3b80 0x3ffb2e48 0x9619c4d6 -0x3ffb3a40: 0x00000000 0x00000000 0x3ffb3a4c 0x00000000 -0x3ffb3a50: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3a60: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3a70: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3a80: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3a90: 0x00000000 0x00000000 0x00000000 0x00000000 -0x3ffb3aa0: 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb5870 0x17c RW +0x3ffb5870: 0x3ffb56b0 0x3ffb57f0 0xcececece 0x3ffb3f78 +0x3ffb5880: 0x3ffafb3c 0x3ffb5870 0x3ffb3f70 0x00000001 +0x3ffb5890: 0x3ffb5420 0x3ffb5420 0x3ffb5870 0x3ffb5418 +0x3ffb58a0: 0x00000018 0x3ffb5460 0x31637069 0xcecece00 +0x3ffb58b0: 0xcececece 0x00cecece 0x00000001 0x3ffb585c +0x3ffb58c0: 0x00000000 0x00060021 0x00000003 0xcececece +0x3ffb58d0: 0x00000018 0x00000000 0x00000000 0x00000000 +0x3ffb58e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb58f0: 0x00000000 0x3ffae908 0x3ffae970 0x3ffae9d8 +0x3ffb5900: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb5910: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb5920: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5930: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5940: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5950: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5960: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5970: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5980: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5990: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb59a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb59b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb59c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb59d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb59e0: 0x00000000 0x00000000 0xcecece00 +.coredump.tasks.data 0x3ffb56b0 0x1ac RW +0x3ffb56b0: 0x4008249c 0x40088d90 0x00060830 0x80081d43 +0x3ffb56c0: 0x3ffb5770 0x3ffb53f4 0x00000000 0x3ffb5448 +0x3ffb56d0: 0x00000000 0x00000001 0x00000000 0x80088d90 +0x3ffb56e0: 0x3ffb5750 0x00000001 0x00000004 0x3ffb41ec +0x3ffb56f0: 0x0000000a 0x00800000 0x3ff4001c 0x00000000 +0x3ffb5700: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3ffb5710: 0x00000000 0x4008269c 0x0000000a 0x400883fc +0x3ffb5720: 0x3ffae994 0x00000000 0x00000000 0x00000000 +0x3ffb5730: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb5740: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5750: 0x3ffbac98 0x0000000a 0x00800000 0x3ff4001c +0x3ffb5760: 0x800881bc 0x3ffb57b0 0x00000001 0x00000000 +0x3ffb5770: 0x3ffbac98 0x0000000a 0x00800000 0xffffffff +0x3ffb5780: 0x800881bc 0x00000000 0x00041b89 0xc4ebe7dc +0x3ffb5790: 0x3ffb5448 0x00000000 0x00000001 0x00000000 +0x3ffb57a0: 0x00000000 0x3ffb57d0 0x40081d10 0x00000001 +0x3ffb57b0: 0x00000001 0x3ffb41dc 0x3ffb5870 0x00000000 +0x3ffb57c0: 0x00000000 0x3ffb57f0 0x00000000 0x00000000 +0x3ffb57d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb57e0: 0x800811e0 0x3ffe7d80 0x00000028 0x00000028 +0x3ffb57f0: 0x00000000 0x00000000 0x3ffb57fc 0x00000000 +0x3ffb5800: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5810: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5820: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5830: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5840: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5850: 0x00000000 0x00000000 0x00000000 +.coredump.tasks.data 0x3ffb5190 0x17c RW +0x3ffb5190: 0x3ffb4fb0 0x3ffb5110 0xcececece 0x3ffafb3c +0x3ffb51a0: 0x3ffb3f78 0x3ffb5190 0x3ffb3f70 0x00000001 +0x3ffb51b0: 0x3ffb4d40 0x3ffb4d40 0x3ffb5190 0x3ffb4d38 +0x3ffb51c0: 0x00000018 0x3ffb4d80 0x30637069 0xcecece00 +0x3ffb51d0: 0xcececece 0x00cecece 0x00000000 0x3ffb517c +0x3ffb51e0: 0x00000000 0x00060021 0x00000002 0xcececece +0x3ffb51f0: 0x00000018 0x00000000 0x00000000 0x00000000 +0x3ffb5200: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5210: 0x00000000 0x3ffae908 0x3ffae970 0x3ffae9d8 +0x3ffb5220: 0x00000000 0x00000000 0x00000001 0x00000000 +0x3ffb5230: 0x00000000 0x00000000 0x40001d48 0x00000000 +0x3ffb5240: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5250: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5260: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5270: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5280: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5290: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb52a0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb52b0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb52c0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb52d0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb52e0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb52f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5300: 0x00000000 0x00000000 0xcecece00 +.coredump.tasks.data 0x3ffb4fb0 0x1cc RW +0x3ffb4fb0: 0x4008249c 0x40081448 0x00060e30 0x80088d90 +0x3ffb4fc0: 0x3ffb5070 0x00000000 0x00000000 0x3ffb41e8 +0x3ffb4fd0: 0x0000cdcd 0x00000001 0x00000000 0x80081448 +0x3ffb4fe0: 0x3ffb5050 0x3ff000dc 0x00000001 0x3ffb0038 +0x3ffb4ff0: 0x00000001 0x00060020 0x00000001 0x00000000 +0x3ffb5000: 0x0000ffff 0x00000000 0x00000000 0x00000000 +0x3ffb5010: 0x00000000 0x4008269c 0x00000001 0x400883fc +0x3ffb5020: 0x3ffae2b4 0x00000000 0x00000000 0x00000000 +0x3ffb5030: 0xb33fffff 0x00000000 0x00000000 0x00000000 +0x3ffb5040: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5050: 0x4008249c 0x400881b4 0x00050030 0x00000000 +0x3ffb5060: 0x80081d43 0x3ffb5090 0x3ffb4d14 0x00000000 +0x3ffb5070: 0x00000000 0x40081d10 0x00000000 0x00000000 +0x3ffb5080: 0x800881bc 0x3ffb50d0 0x00000000 0x00000000 +0x3ffb5090: 0x00000000 0x00000000 0x00000000 0xffffffff +0x3ffb50a0: 0x00000000 0x00000000 0x00000000 0xc4ebe7dc +0x3ffb50b0: 0x3ffb4d68 0x00000000 0x00000001 0x00000002 +0x3ffb50c0: 0x00000000 0x3ffb50f0 0x40081d10 0x00000000 +0x3ffb50d0: 0x00060323 0x3ffb41dc 0x3ffb5190 0x00000001 +0x3ffb50e0: 0x00000000 0x3ffb5110 0x00000000 0x00000000 +0x3ffb50f0: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5100: 0x8008115a 0x3ffe3b50 0x3ffb3f58 0xc4ebe7dc +0x3ffb5110: 0x00000000 0x00000000 0x3ffb511c 0x00000000 +0x3ffb5120: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5130: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5140: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5150: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5160: 0x00000000 0x00000000 0x00000000 0x00000000 +0x3ffb5170: 0x00000000 0x00000000 0x00000000 ===================== ESP32 CORE DUMP END ===================== =============================================================== diff --git a/components/espcoredump/test/test.elf b/components/espcoredump/test/test.elf index 42652712c..b753b56a8 100644 Binary files a/components/espcoredump/test/test.elf and b/components/espcoredump/test/test.elf differ diff --git a/docs/en/api-guides/core_dump.rst b/docs/en/api-guides/core_dump.rst index f96d4e2cb..e95af8486 100644 --- a/docs/en/api-guides/core_dump.rst +++ b/docs/en/api-guides/core_dump.rst @@ -18,16 +18,31 @@ Configuration There are a number of core dump related configuration options which user can choose in project configuration menu (`idf.py menuconfig`). -1. Core dump data destination (`Components -> ESP32-specific config -> Core dump -> Data destination`): +1. Core dump data destination (`Components -> Core dump -> Data destination`): -* Disable core dump generation -* Save core dump to flash -* Print core dump to UART +* Save core dump to Flash (Flash) +* Print core dump to UART (UART) +* Disable core dump generation (None) -2. Maximum number of tasks snapshots in core dump (`Components -> ESP32-specific config -> Core dump -> Maximum number of tasks`). +2. Core dump data format (`Components -> Core dump -> Core dump data format`): -3. Delay before core dump is printed to UART (`Components -> ESP32-specific config -> Core dump -> Delay before print to UART`). Value is in ms. +* 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 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`). + +4. Delay before core dump is printed to UART (`Components -> Core dump -> Delay before print to UART`). Value is in ms. + +5. Type of data integrity check for core dump (`Components -> Core dump -> Core dump data integrity check`). + +* Use CRC32 for core dump integrity verification +* Use SHA256 for core dump integrity verification + +The SHA256 hash algorithm provides greater probability of detecting corruption than a CRC32 with multiple bit errors. The CRC32 option provides better calculation performance and consumes less memory for storage. Save core dump to flash ----------------------- @@ -75,7 +90,7 @@ To overcome this issue you can use ROM ELF provided by Espressif (https://dl.esp Running 'espcoredump.py' ------------------------------------- +------------------------ Generic command syntax: