diff --git a/components/espcoredump/espcoredump.py b/components/espcoredump/espcoredump.py index fb79185f90..4c62dff2a5 100755 --- a/components/espcoredump/espcoredump.py +++ b/components/espcoredump/espcoredump.py @@ -458,11 +458,13 @@ class ESPCoreDumpLoaderError(ESPCoreDumpError): class ESPCoreDumpLoader(object): """Core dump loader base class """ - ESP32_COREDUMP_VESION = 1 + ESP32_COREDUMP_VESION = 2 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_LOG_HDR_FMT = '<2L' + ESP32_COREDUMP_LOG_HDR_SZ = struct.calcsize(ESP32_COREDUMP_LOG_HDR_FMT) def __init__(self): """Base constructor for core dump loader @@ -639,6 +641,13 @@ class ESPCoreDumpLoader(object): note = Elf32NoteDesc("CORE", 1, prstatus.dump() + struct.pack("<%dL" % len(task_regs), *task_regs)).dump() notes += note + # read log + data = self.read_data(core_off, self.ESP32_COREDUMP_LOG_HDR_SZ) + core_off += self.ESP32_COREDUMP_LOG_HDR_SZ + log_len, log_start = struct.unpack_from(self.ESP32_COREDUMP_LOG_HDR_FMT, data) + log_saved = self.read_data(core_off, log_len) + core_off += log_len + # add notes try: core_elf.add_program_segment(0, notes, ESPCoreDumpElfFile.PT_NOTE, 0) @@ -662,7 +671,7 @@ class ESPCoreDumpLoader(object): fce = os.fdopen(fhnd, 'wb') core_elf.dump(fce) fce.close() - return core_fname + return core_fname, log_saved def read_data(self, off, sz): """Reads data from raw core dump got from flash or UART @@ -900,7 +909,7 @@ def dbg_corefile(args): 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) + core_fname, log_saved = loader.create_corefile(args.save_core, rom_elf=rom_elf) if not core_fname: logging.error("Failed to create corefile!") loader.cleanup() @@ -909,7 +918,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, log_saved = loader.create_corefile(args.save_core, rom_elf=rom_elf) if not core_fname: logging.error("Failed to create corefile!") loader.cleanup() @@ -991,7 +1000,7 @@ def info_corefile(args): 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) + core_fname, log_saved = loader.create_corefile(args.save_core, rom_elf=rom_elf) if not core_fname: logging.error("Failed to create corefile!") loader.cleanup() @@ -1000,7 +1009,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, log_saved = loader.create_corefile(args.save_core, rom_elf=rom_elf) if not core_fname: logging.error("Failed to create corefile!") loader.cleanup() @@ -1089,6 +1098,10 @@ def info_corefile(args): print(".coredump.%s 0x%x 0x%x %s" % (seg_name, cs.addr, len(cs.data), cs.attr_str())) p = gdbmi_getinfo(p, handlers, "x/%dx 0x%x" % (old_div(len(cs.data),4), cs.addr)) + if log_saved: + print("\n====================== CORE DUMP LOG CONTENTS ========================") + print(log_saved) + print("\n===================== ESP32 CORE DUMP END =====================") print("===============================================================") diff --git a/components/espcoredump/include/esp_core_dump.h b/components/espcoredump/include/esp_core_dump.h index e19b45c98a..e47ec34293 100644 --- a/components/espcoredump/include/esp_core_dump.h +++ b/components/espcoredump/include/esp_core_dump.h @@ -46,7 +46,7 @@ void esp_core_dump_init(); * The structure of core dump data is described below in details. * 1) Core dump starts with header: * 1.1) TOTAL_LEN is total length of core dump data in flash including CRC. Size is 4 bytes. - * 1.2) VERSION field keeps 4 byte version of core dump. + * 1.2) VERSION field keeps 4 byte version of core dump. * 1.2) TASKS_NUM is the number of tasks for which data are stored. Size is 4 bytes. * 1.3) TCB_SIZE is the size of task's TCB structure. Size is 4 bytes. * 2) Core dump header is followed by the data for every task in the system. @@ -86,4 +86,9 @@ void esp_core_dump_to_uart(XtExcFrame *frame); */ esp_err_t esp_core_dump_image_get(size_t* out_addr, size_t *out_size); +typedef uint32_t (*log_dump_get_len_t)(void); +typedef int * (*log_dump_get_ptr_t)(void); + +bool esp_log_dump_init(log_dump_get_len_t g_len, log_dump_get_ptr_t g_ptr); + #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 a13dd1707d..608a4ca199 100644 --- a/components/espcoredump/include_core_dump/esp_core_dump_priv.h +++ b/components/espcoredump/include_core_dump/esp_core_dump_priv.h @@ -11,8 +11,8 @@ // 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_H_ -#define ESP_CORE_DUMP_H_ +#ifndef ESP_CORE_DUMP_PRIV_H_ +#define ESP_CORE_DUMP_PRIV_H_ #include "freertos/FreeRTOS.h" #include "freertos/task.h" @@ -33,7 +33,7 @@ #endif #define COREDUMP_MAX_TASK_STACK_SIZE (64*1024) -#define COREDUMP_VERSION 1 +#define COREDUMP_VERSION 2 typedef uint32_t core_dump_crc_t; @@ -79,6 +79,12 @@ typedef struct _core_dump_task_header_t uint32_t stack_end; // stack end address } core_dump_task_header_t; +typedef struct _core_dump_log_header_t +{ + uint32_t len; //bytes + int * start; // +} core_dump_log_header_t; + #if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH // Core dump flash init function @@ -100,6 +106,8 @@ bool esp_core_dump_process_tcb(void *frame, core_dump_task_header_t *task_snapho bool esp_core_dump_process_stack(core_dump_task_header_t* task_snaphort, uint32_t *length); +bool esp_core_dump_process_log(core_dump_log_header_t *log); + #endif #endif diff --git a/components/espcoredump/src/core_dump_common.c b/components/espcoredump/src/core_dump_common.c index 2def79f8b7..c0fad97354 100644 --- a/components/espcoredump/src/core_dump_common.c +++ b/components/espcoredump/src/core_dump_common.c @@ -34,18 +34,22 @@ static esp_err_t esp_core_dump_write_binary(void *frame, core_dump_write_config_ core_dump_header_t hdr; core_dump_task_header_t task_hdr; } dump_data; + union { + uint32_t i32[128]; + char str[512]; + } iram_str; 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; - + // Verifies all tasks in the snapshot - for (i = 0; i < task_num; i++) { + 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) { @@ -64,10 +68,16 @@ static esp_err_t esp_core_dump_write_binary(void *frame, core_dump_write_config_ write_cfg->bad_tasks_num++; } } + + core_dump_log_header_t logs = { 0 }; + if (esp_core_dump_process_log(&logs) == true) { + data_len += (logs.len + sizeof(core_dump_log_header_t)); + } + // 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); - + // Prepare write if (write_cfg->prepare) { err = write_cfg->prepare(write_cfg->priv, &data_len); @@ -129,6 +139,28 @@ static esp_err_t esp_core_dump_write_binary(void *frame, core_dump_write_config_ } } + err = write_cfg->write(write_cfg->priv, (void*)&logs, sizeof(core_dump_log_header_t)); + if (err != ESP_OK) { + ESP_COREDUMP_LOGE("Failed to write LOG Header (%d)!", err); + return err; + } + if (logs.len > 0 && logs.start != NULL) { + for (int i = 0; i < logs.len / 512; i++) { + for (int j = 0; j < 128; j++) { + if (i * 128 + j < logs.len / 4) { + iram_str.i32[j] = logs.start[i * 128+ j]; + } + } + err = write_cfg->write(write_cfg->priv, (void*)iram_str.str, 512); + } + + // err = write_cfg->write(write_cfg->priv, (void*)logs.start, logs.len); + // if (err != ESP_OK) { + // ESP_COREDUMP_LOGE("Failed to write LOG (%d)!", err); + // return err; + // } + } + // write end if (write_cfg->end) { err = write_cfg->end(write_cfg->priv); diff --git a/components/espcoredump/src/core_dump_port.c b/components/espcoredump/src/core_dump_port.c index 34ff582313..ba6af4f5c2 100644 --- a/components/espcoredump/src/core_dump_port.c +++ b/components/espcoredump/src/core_dump_port.c @@ -15,6 +15,7 @@ #include #include "esp_panic.h" #include "esp_core_dump_priv.h" +#include "esp_core_dump.h" const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_port"; @@ -41,7 +42,7 @@ uint32_t esp_core_dump_get_tasks_snapshot(core_dump_task_header_t* const tasks, bool esp_core_dump_process_tcb(void *frame, core_dump_task_header_t *task_snaphort, uint32_t tcb_sz) { XtExcFrame *exc_frame = (XtExcFrame*)frame; - + 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); return false; @@ -74,7 +75,7 @@ bool esp_core_dump_process_tcb(void *frame, core_dump_task_header_t *task_snapho } bool esp_core_dump_process_stack(core_dump_task_header_t* task_snaphort, uint32_t *length) -{ +{ uint32_t len = 0; bool task_is_valid = false; len = (uint32_t)task_snaphort->stack_end - (uint32_t)task_snaphort->stack_start; @@ -99,5 +100,27 @@ bool esp_core_dump_process_stack(core_dump_task_header_t* task_snaphort, uint32_ } return task_is_valid; } +static log_dump_get_len_t get_len = NULL; +static log_dump_get_ptr_t get_ptr = NULL; + +bool esp_log_dump_init(log_dump_get_len_t g_len, log_dump_get_ptr_t g_ptr) +{ + get_len = g_len; + get_ptr = g_ptr; + return true; +} + +bool esp_core_dump_process_log(core_dump_log_header_t *log) +{ + if (get_len && get_ptr) { + log->len = get_len(); + log->start = get_ptr(); + return true; + } else { + log->len = 0; + log->start = NULL; + return false; + } +} #endif