forked from espressif/esp-idf
log dump
This commit is contained in:
@@ -458,11 +458,13 @@ class ESPCoreDumpLoaderError(ESPCoreDumpError):
|
|||||||
class ESPCoreDumpLoader(object):
|
class ESPCoreDumpLoader(object):
|
||||||
"""Core dump loader base class
|
"""Core dump loader base class
|
||||||
"""
|
"""
|
||||||
ESP32_COREDUMP_VESION = 1
|
ESP32_COREDUMP_VESION = 2
|
||||||
ESP32_COREDUMP_HDR_FMT = '<4L'
|
ESP32_COREDUMP_HDR_FMT = '<4L'
|
||||||
ESP32_COREDUMP_HDR_SZ = struct.calcsize(ESP32_COREDUMP_HDR_FMT)
|
ESP32_COREDUMP_HDR_SZ = struct.calcsize(ESP32_COREDUMP_HDR_FMT)
|
||||||
ESP32_COREDUMP_TSK_HDR_FMT = '<3L'
|
ESP32_COREDUMP_TSK_HDR_FMT = '<3L'
|
||||||
ESP32_COREDUMP_TSK_HDR_SZ = struct.calcsize(ESP32_COREDUMP_TSK_HDR_FMT)
|
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):
|
def __init__(self):
|
||||||
"""Base constructor for core dump loader
|
"""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()
|
note = Elf32NoteDesc("CORE", 1, prstatus.dump() + struct.pack("<%dL" % len(task_regs), *task_regs)).dump()
|
||||||
notes += note
|
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
|
# add notes
|
||||||
try:
|
try:
|
||||||
core_elf.add_program_segment(0, notes, ESPCoreDumpElfFile.PT_NOTE, 0)
|
core_elf.add_program_segment(0, notes, ESPCoreDumpElfFile.PT_NOTE, 0)
|
||||||
@@ -662,7 +671,7 @@ class ESPCoreDumpLoader(object):
|
|||||||
fce = os.fdopen(fhnd, 'wb')
|
fce = os.fdopen(fhnd, 'wb')
|
||||||
core_elf.dump(fce)
|
core_elf.dump(fce)
|
||||||
fce.close()
|
fce.close()
|
||||||
return core_fname
|
return core_fname, log_saved
|
||||||
|
|
||||||
def read_data(self, off, sz):
|
def read_data(self, off, sz):
|
||||||
"""Reads data from raw core dump got from flash or UART
|
"""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)
|
rom_elf,rom_sym_cmd = load_aux_elf(args.rom_elf)
|
||||||
if not args.core:
|
if not args.core:
|
||||||
loader = ESPCoreDumpFlashLoader(args.off, port=args.port)
|
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:
|
if not core_fname:
|
||||||
logging.error("Failed to create corefile!")
|
logging.error("Failed to create corefile!")
|
||||||
loader.cleanup()
|
loader.cleanup()
|
||||||
@@ -909,7 +918,7 @@ def dbg_corefile(args):
|
|||||||
core_fname = args.core
|
core_fname = args.core
|
||||||
if args.core_format and args.core_format != 'elf':
|
if args.core_format and args.core_format != 'elf':
|
||||||
loader = ESPCoreDumpFileLoader(core_fname, args.core_format == 'b64')
|
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:
|
if not core_fname:
|
||||||
logging.error("Failed to create corefile!")
|
logging.error("Failed to create corefile!")
|
||||||
loader.cleanup()
|
loader.cleanup()
|
||||||
@@ -991,7 +1000,7 @@ def info_corefile(args):
|
|||||||
rom_elf,rom_sym_cmd = load_aux_elf(args.rom_elf)
|
rom_elf,rom_sym_cmd = load_aux_elf(args.rom_elf)
|
||||||
if not args.core:
|
if not args.core:
|
||||||
loader = ESPCoreDumpFlashLoader(args.off, port=args.port)
|
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:
|
if not core_fname:
|
||||||
logging.error("Failed to create corefile!")
|
logging.error("Failed to create corefile!")
|
||||||
loader.cleanup()
|
loader.cleanup()
|
||||||
@@ -1000,7 +1009,7 @@ def info_corefile(args):
|
|||||||
core_fname = args.core
|
core_fname = args.core
|
||||||
if args.core_format and args.core_format != 'elf':
|
if args.core_format and args.core_format != 'elf':
|
||||||
loader = ESPCoreDumpFileLoader(core_fname, args.core_format == 'b64')
|
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:
|
if not core_fname:
|
||||||
logging.error("Failed to create corefile!")
|
logging.error("Failed to create corefile!")
|
||||||
loader.cleanup()
|
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()))
|
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))
|
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("\n===================== ESP32 CORE DUMP END =====================")
|
||||||
print("===============================================================")
|
print("===============================================================")
|
||||||
|
|
||||||
|
@@ -46,7 +46,7 @@ void esp_core_dump_init();
|
|||||||
* The structure of core dump data is described below in details.
|
* The structure of core dump data is described below in details.
|
||||||
* 1) Core dump starts with header:
|
* 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.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.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.
|
* 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.
|
* 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);
|
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
|
#endif
|
||||||
|
@@ -11,8 +11,8 @@
|
|||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
#ifndef ESP_CORE_DUMP_H_
|
#ifndef ESP_CORE_DUMP_PRIV_H_
|
||||||
#define ESP_CORE_DUMP_H_
|
#define ESP_CORE_DUMP_PRIV_H_
|
||||||
|
|
||||||
#include "freertos/FreeRTOS.h"
|
#include "freertos/FreeRTOS.h"
|
||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define COREDUMP_MAX_TASK_STACK_SIZE (64*1024)
|
#define COREDUMP_MAX_TASK_STACK_SIZE (64*1024)
|
||||||
#define COREDUMP_VERSION 1
|
#define COREDUMP_VERSION 2
|
||||||
|
|
||||||
typedef uint32_t core_dump_crc_t;
|
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
|
uint32_t stack_end; // stack end address
|
||||||
} core_dump_task_header_t;
|
} 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
|
#if CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH
|
||||||
|
|
||||||
// Core dump flash init function
|
// 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_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
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@@ -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_header_t hdr;
|
||||||
core_dump_task_header_t task_hdr;
|
core_dump_task_header_t task_hdr;
|
||||||
} dump_data;
|
} 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);
|
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);
|
ESP_COREDUMP_LOGI("Found tasks: (%d)!", task_num);
|
||||||
|
|
||||||
// Take TCB padding into account, actual TCB size will be stored in header
|
// Take TCB padding into account, actual TCB size will be stored in header
|
||||||
if (tcb_sz % sizeof(uint32_t))
|
if (tcb_sz % sizeof(uint32_t))
|
||||||
tcb_sz_padded = (tcb_sz / sizeof(uint32_t) + 1) * sizeof(uint32_t);
|
tcb_sz_padded = (tcb_sz / sizeof(uint32_t) + 1) * sizeof(uint32_t);
|
||||||
else
|
else
|
||||||
tcb_sz_padded = tcb_sz;
|
tcb_sz_padded = tcb_sz;
|
||||||
|
|
||||||
// Verifies all tasks in the snapshot
|
// 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);
|
task_is_valid = esp_core_dump_process_tcb(frame, &tasks[i], tcb_sz);
|
||||||
// Check if task tcb is corrupted
|
// Check if task tcb is corrupted
|
||||||
if (!task_is_valid) {
|
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++;
|
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
|
// Add core dump header size
|
||||||
data_len += sizeof(core_dump_header_t);
|
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 len = %lu (%d %d)", data_len, task_num, write_cfg->bad_tasks_num);
|
||||||
|
|
||||||
// Prepare write
|
// Prepare write
|
||||||
if (write_cfg->prepare) {
|
if (write_cfg->prepare) {
|
||||||
err = write_cfg->prepare(write_cfg->priv, &data_len);
|
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
|
// write end
|
||||||
if (write_cfg->end) {
|
if (write_cfg->end) {
|
||||||
err = write_cfg->end(write_cfg->priv);
|
err = write_cfg->end(write_cfg->priv);
|
||||||
|
@@ -15,6 +15,7 @@
|
|||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "esp_panic.h"
|
#include "esp_panic.h"
|
||||||
#include "esp_core_dump_priv.h"
|
#include "esp_core_dump_priv.h"
|
||||||
|
#include "esp_core_dump.h"
|
||||||
|
|
||||||
const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_port";
|
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)
|
bool esp_core_dump_process_tcb(void *frame, core_dump_task_header_t *task_snaphort, uint32_t tcb_sz)
|
||||||
{
|
{
|
||||||
XtExcFrame *exc_frame = (XtExcFrame*)frame;
|
XtExcFrame *exc_frame = (XtExcFrame*)frame;
|
||||||
|
|
||||||
if (!esp_tcb_addr_is_sane((uint32_t)task_snaphort->tcb_addr, tcb_sz)) {
|
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);
|
ESP_COREDUMP_LOG_PROCESS("Bad TCB addr %x!", task_snaphort->tcb_addr);
|
||||||
return false;
|
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)
|
bool esp_core_dump_process_stack(core_dump_task_header_t* task_snaphort, uint32_t *length)
|
||||||
{
|
{
|
||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
bool task_is_valid = false;
|
bool task_is_valid = false;
|
||||||
len = (uint32_t)task_snaphort->stack_end - (uint32_t)task_snaphort->stack_start;
|
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;
|
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
|
#endif
|
||||||
|
Reference in New Issue
Block a user