From ba18502b933e6e9b01c07103de07b3efe718be00 Mon Sep 17 00:00:00 2001 From: xuxingliang Date: Tue, 24 Dec 2024 18:30:53 +0800 Subject: [PATCH] misc/coredump: move coredump info to note Add a custom note for NuttX information including magic and coredump file data size, so when system reboots, we can check if the block device contains valid coredump file, and save it to file system. Signed-off-by: xuxingliang --- include/nuttx/coredump.h | 12 ++--- sched/misc/coredump.c | 105 +++++++++++++++++++++++---------------- 2 files changed, 67 insertions(+), 50 deletions(-) diff --git a/include/nuttx/coredump.h b/include/nuttx/coredump.h index 2fdd7af46f..dadfff6613 100644 --- a/include/nuttx/coredump.h +++ b/include/nuttx/coredump.h @@ -27,21 +27,20 @@ * Included Files ****************************************************************************/ -#include +#include #include +#include +#include #include #include -#ifdef CONFIG_ARM_COREDUMP_REGION -# include -#endif - /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ -#define COREDUMP_MAGIC 0x434f5245 +#define COREDUMP_MAGIC 0x434f5245 +#define COREDUMP_INFONAME_SIZE ALIGN_UP(CONFIG_TASK_NAME_SIZE, 8) /**************************************************************************** * Public Types @@ -51,7 +50,6 @@ struct coredump_info_s { - uint32_t magic; struct utsname name; struct timespec time; size_t size; diff --git a/sched/misc/coredump.c b/sched/misc/coredump.c index 22d2f9f687..368346bb3a 100644 --- a/sched/misc/coredump.c +++ b/sched/misc/coredump.c @@ -144,7 +144,7 @@ static int elf_emit(FAR struct elf_dumpinfo_s *cinfo, { FAR const uint8_t *ptr = buf; size_t total = len; - int ret; + int ret = 0; while (total > 0) { @@ -263,13 +263,19 @@ static int elf_get_note_size(int stksegs) { int total; - total = stksegs * (sizeof(Elf_Nhdr) + ALIGN_UP(CONFIG_TASK_NAME_SIZE, 8) + + total = stksegs * (sizeof(Elf_Nhdr) + COREDUMP_INFONAME_SIZE + sizeof(elf_prstatus_t)); - total += stksegs * (sizeof(Elf_Nhdr) + ALIGN_UP(CONFIG_TASK_NAME_SIZE, 8) + + total += stksegs * (sizeof(Elf_Nhdr) + COREDUMP_INFONAME_SIZE + sizeof(elf_prpsinfo_t)); return total; } +static int elf_get_info_note_size(void) +{ + return sizeof(Elf_Nhdr) + COREDUMP_INFONAME_SIZE + + sizeof(struct coredump_info_s); +} + /**************************************************************************** * Name: elf_emit_tcb_note * @@ -281,7 +287,7 @@ static int elf_get_note_size(int stksegs) static void elf_emit_tcb_note(FAR struct elf_dumpinfo_s *cinfo, FAR struct tcb_s *tcb) { - char name[ALIGN_UP(CONFIG_TASK_NAME_SIZE, 8)]; + char name[COREDUMP_INFONAME_SIZE]; elf_prstatus_t status; elf_prpsinfo_t info; FAR uintptr_t *regs; @@ -507,6 +513,39 @@ static void elf_emit_memory(FAR struct elf_dumpinfo_s *cinfo, int memsegs) } } +/**************************************************************************** + * Name: elf_emit_info_note + * + * Description: + * Fill the core info note + * + ****************************************************************************/ + +static void elf_emit_info_note(FAR struct elf_dumpinfo_s *cinfo) +{ + struct coredump_info_s info; + Elf_Nhdr nhdr; + char name[COREDUMP_INFONAME_SIZE]; + + memset(&info, 0x0, sizeof(info)); + memset(name, 0x0, sizeof(name)); + + nhdr.n_namesz = sizeof(name); + nhdr.n_descsz = sizeof(info); + nhdr.n_type = COREDUMP_MAGIC; + + elf_emit(cinfo, &nhdr, sizeof(nhdr)); + + strlcpy(name, "NuttX", sizeof(name)); + elf_emit(cinfo, name, sizeof(name)); + + info.size = cinfo->stream->nput + sizeof(info); + clock_gettime(CLOCK_REALTIME, &info.time); + uname(&info.name); + + elf_emit(cinfo, &info, sizeof(info)); +} + /**************************************************************************** * Name: elf_emit_tcb_phdr * @@ -578,7 +617,7 @@ static void elf_emit_phdr(FAR struct elf_dumpinfo_s *cinfo, int stksegs, int memsegs) { off_t offset = cinfo->stream->nput + - (stksegs + memsegs + 1) * sizeof(Elf_Phdr); + (stksegs + memsegs + 1 + 1) * sizeof(Elf_Phdr); Elf_Phdr phdr; int i; @@ -622,6 +661,14 @@ static void elf_emit_phdr(FAR struct elf_dumpinfo_s *cinfo, offset += ALIGN_UP(phdr.p_memsz, ELF_PAGESIZE); elf_emit(cinfo, &phdr, sizeof(phdr)); } + + memset(&phdr, 0, sizeof(Elf_Phdr)); + phdr.p_type = PT_NOTE; + phdr.p_offset = ALIGN_UP(offset, ELF_PAGESIZE); + phdr.p_filesz = elf_get_info_note_size(); + offset += phdr.p_filesz; + + elf_emit(cinfo, &phdr, sizeof(phdr)); } /**************************************************************************** @@ -692,7 +739,6 @@ static void coredump_dump_syslog(pid_t pid) static void coredump_dump_dev(pid_t pid) { FAR void *stream = &g_devstream; - struct coredump_info_s info; int ret; if (g_devstream.inode == NULL) @@ -705,6 +751,7 @@ static void coredump_dump_dev(pid_t pid) lib_lzfoutstream(&g_lzfstream, stream); stream = &g_lzfstream; #endif + ret = coredump(g_regions, stream, pid); if (ret < 0) { @@ -712,42 +759,8 @@ static void coredump_dump_dev(pid_t pid) return; } - info.magic = COREDUMP_MAGIC; - info.size = g_devstream.common.nput; - clock_gettime(CLOCK_REALTIME, &info.time); - uname(&info.name); - - ret = lib_stream_seek(&g_devstream, -(off_t)sizeof(info), SEEK_END); - if (ret < 0) - { - _alert("Coredump info seek fail %d\n", ret); - return; - } - - if (info.size > ret) - { - _alert("Coredump no enough space for info\n"); - return; - } - - ret = lib_stream_puts(&g_devstream, &info, sizeof(info)); - if (ret < 0) - { - _alert("Coredump information write fail %d\n", ret); - return; - } - - /* Flush to ensure outstream write all data to storage device */ - - ret = lib_stream_flush(&g_devstream); - if (ret < 0) - { - _alert("Coredump flush fail %d\n", ret); - return; - } - _alert("Finish coredump, write %zu bytes to %s\n", - info.size, CONFIG_BOARD_COREDUMP_DEVPATH); + g_devstream.common.nput, CONFIG_BOARD_COREDUMP_DEVPATH); } #endif @@ -959,9 +972,11 @@ int coredump(FAR const struct memory_region_s *regions, cinfo.regions[memsegs].end; memsegs++); } - /* Fill notes section */ + /* Fill notes section, with additional one for program header, + * and one for the core file info defined by NuttX. + */ - elf_emit_hdr(&cinfo, stksegs + memsegs + 1); + elf_emit_hdr(&cinfo, stksegs + memsegs + 1 + 1); /* Fill all the program information about the process for the * notes. This also sets up the file header. @@ -988,6 +1003,10 @@ int coredump(FAR const struct memory_region_s *regions, elf_emit_memory(&cinfo, memsegs); } + /* Emit core info note */ + + elf_emit_info_note(&cinfo); + /* Flush the dump */ elf_flush(&cinfo);