From 52126aede114fe0d9264acf3a6fcccbf0a80ba16 Mon Sep 17 00:00:00 2001 From: anjiahao Date: Sat, 6 Jul 2024 15:22:51 +0800 Subject: [PATCH] coredump:Move coredump to sched/misc 1. move coredump form libelf to sched/misc 2. rename core_dump to coredump Signed-off-by: anjiahao --- Documentation/guides/coredump.rst | 4 +- binfmt/CMakeLists.txt | 3 +- binfmt/Makefile | 1 - binfmt/binfmt_coredump.c | 72 -- binfmt/elf.c | 34 - binfmt/libelf/CMakeLists.txt | 5 - binfmt/libelf/Kconfig | 11 - binfmt/libelf/Make.defs | 6 - binfmt/libelf/libelf_coredump.c | 666 ------------------ binfmt/nxflat.c | 1 - boards/Kconfig | 4 +- .../sabre-6quad/configs/coredump/defconfig | 3 +- include/nuttx/binfmt/binfmt.h | 37 - include/nuttx/binfmt/elf.h | 31 - include/nuttx/coredump.h | 37 +- include/nuttx/elf.h | 2 +- sched/Kconfig | 12 + sched/misc/CMakeLists.txt | 2 +- sched/misc/Make.defs | 2 +- sched/misc/coredump.c | 643 ++++++++++++++++- 20 files changed, 697 insertions(+), 879 deletions(-) delete mode 100644 binfmt/binfmt_coredump.c delete mode 100644 binfmt/libelf/libelf_coredump.c diff --git a/Documentation/guides/coredump.rst b/Documentation/guides/coredump.rst index 94dfa7fc30..9b68c755cc 100644 --- a/Documentation/guides/coredump.rst +++ b/Documentation/guides/coredump.rst @@ -16,9 +16,7 @@ Enable Kconfig .. code-block:: console - CONFIG_ELF=y /* Enable ELF */ - - CONFIG_ELF_COREDUMP=y /* Enable ELF Coredump */ + CONFIG_COREDUMP=y /* Enable Coredump */ CONFIG_BOARD_COREDUMP_SYSLOG=y /* Enable Board Coredump, if exceptions and assertions occur, */ diff --git a/binfmt/CMakeLists.txt b/binfmt/CMakeLists.txt index 35f8f9cdb3..0f0578ebce 100644 --- a/binfmt/CMakeLists.txt +++ b/binfmt/CMakeLists.txt @@ -39,8 +39,7 @@ list( binfmt_exec.c binfmt_copyargv.c binfmt_copyactions.c - binfmt_dumpmodule.c - binfmt_coredump.c) + binfmt_dumpmodule.c) if(CONFIG_BINFMT_LOADABLE) list(APPEND SRCS binfmt_exit.c) diff --git a/binfmt/Makefile b/binfmt/Makefile index 8916865990..02b48c2b13 100644 --- a/binfmt/Makefile +++ b/binfmt/Makefile @@ -27,7 +27,6 @@ include $(TOPDIR)/Make.defs CSRCS = binfmt_globals.c binfmt_initialize.c binfmt_register.c binfmt_unregister.c CSRCS += binfmt_loadmodule.c binfmt_unloadmodule.c binfmt_execmodule.c CSRCS += binfmt_exec.c binfmt_copyargv.c binfmt_copyactions.c binfmt_dumpmodule.c -CSRCS += binfmt_coredump.c ifeq ($(CONFIG_BINFMT_LOADABLE),y) CSRCS += binfmt_exit.c diff --git a/binfmt/binfmt_coredump.c b/binfmt/binfmt_coredump.c deleted file mode 100644 index a4fd7eea59..0000000000 --- a/binfmt/binfmt_coredump.c +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** - * binfmt/binfmt_coredump.c - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you 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. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include - -#include -#include - -#include "binfmt.h" - -#ifndef CONFIG_BINFMT_DISABLE - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: core_dump - * - * Description: - * This function for generating core dump stream. - * - ****************************************************************************/ - -int core_dump(FAR const struct memory_region_s *regions, - FAR struct lib_outstream_s *stream, - pid_t pid) -{ - FAR struct binfmt_s *binfmt; - int ret = -ENOENT; - - for (binfmt = g_binfmts; binfmt; binfmt = binfmt->next) - { - /* Use this handler to try to load the format */ - - if (binfmt->coredump) - { - ret = binfmt->coredump(regions, stream, pid); - if (ret == OK) - { - break; - } - } - } - - return ret; -} - -#endif /* CONFIG_BINFMT_DISABLE */ diff --git a/binfmt/elf.c b/binfmt/elf.c index 42fbaca0c4..2ae29db77b 100644 --- a/binfmt/elf.c +++ b/binfmt/elf.c @@ -69,11 +69,6 @@ static int elf_loadbinary(FAR struct binary_s *binp, FAR const char *filename, FAR const struct symtab_s *exports, int nexports); -#ifdef CONFIG_ELF_COREDUMP -static int elf_dumpbinary(FAR const struct memory_region_s *regions, - FAR struct lib_outstream_s *stream, - pid_t pid); -#endif #if defined(CONFIG_DEBUG_FEATURES) && defined(CONFIG_DEBUG_BINFMT) static void elf_dumploadinfo(FAR struct elf_loadinfo_s *loadinfo); #endif @@ -87,9 +82,6 @@ static struct binfmt_s g_elfbinfmt = NULL, /* next */ elf_loadbinary, /* load */ NULL, /* unload */ -#ifdef CONFIG_ELF_COREDUMP - elf_dumpbinary, /* coredump */ -#endif }; /**************************************************************************** @@ -370,32 +362,6 @@ errout_with_init: return ret; } -/**************************************************************************** - * Name: elf_dumpbinary - * - * Description: - * Generat the core dump stream as ELF structure. - * - * Returned Value: - * Zero (OK) on success; a negated errno value on failure. - * - ****************************************************************************/ - -#ifdef CONFIG_ELF_COREDUMP -static int elf_dumpbinary(FAR const struct memory_region_s *regions, - FAR struct lib_outstream_s *stream, - pid_t pid) -{ - struct elf_dumpinfo_s dumpinfo; - - dumpinfo.regions = regions; - dumpinfo.stream = stream; - dumpinfo.pid = pid; - - return elf_coredump(&dumpinfo); -} -#endif - /**************************************************************************** * Public Functions ****************************************************************************/ diff --git a/binfmt/libelf/CMakeLists.txt b/binfmt/libelf/CMakeLists.txt index aa6fedd582..8df1a0bd52 100644 --- a/binfmt/libelf/CMakeLists.txt +++ b/binfmt/libelf/CMakeLists.txt @@ -40,11 +40,6 @@ if(CONFIG_ELF) libelf_unload.c libelf_verify.c) - if(CONFIG_ELF_COREDUMP) - list(APPEND SRCS libelf_coredump.c) - target_include_directories(binfmt PRIVATE ${NUTTX_DIR}/sched) - endif() - if(CONFIG_BINFMT_CONSTRUCTORS) list(APPEND SRCS libelf_ctors.c libelf_dtors.c) endif() diff --git a/binfmt/libelf/Kconfig b/binfmt/libelf/Kconfig index dbba7921e4..f33d737021 100644 --- a/binfmt/libelf/Kconfig +++ b/binfmt/libelf/Kconfig @@ -63,17 +63,6 @@ config ELF_SYMBOL_CACHECOUNT This is a cache that is used to store elf symbol table to reduce access fs. Default: 256 -config ELF_COREDUMP - bool "ELF Coredump" - depends on ARCH_HAVE_TCBINFO - default n - ---help--- - Generate ELF core dump to provide information about the CPU state and the - memory state of program. - The memory state embeds a snapshot of all segments mapped in the - memory space of the program. The CPU state contains register values - when the core dump has been generated. - config ELF_LOADTO_LMA bool "ELF load sections to LMA" default n diff --git a/binfmt/libelf/Make.defs b/binfmt/libelf/Make.defs index ee138761bc..8c1a53182d 100644 --- a/binfmt/libelf/Make.defs +++ b/binfmt/libelf/Make.defs @@ -28,12 +28,6 @@ CSRCS += libelf_bind.c libelf_init.c libelf_addrenv.c libelf_iobuffer.c CSRCS += libelf_load.c libelf_read.c libelf_sections.c libelf_symbols.c CSRCS += libelf_uninit.c libelf_unload.c libelf_verify.c -ifeq ($(CONFIG_ELF_COREDUMP),y) -CSRCS += libelf_coredump.c - -CFLAGS += ${INCDIR_PREFIX}$(TOPDIR)$(DELIM)sched -endif - ifeq ($(CONFIG_BINFMT_CONSTRUCTORS),y) CSRCS += libelf_ctors.c libelf_dtors.c endif diff --git a/binfmt/libelf/libelf_coredump.c b/binfmt/libelf/libelf_coredump.c deleted file mode 100644 index a37bbdeada..0000000000 --- a/binfmt/libelf/libelf_coredump.c +++ /dev/null @@ -1,666 +0,0 @@ -/**************************************************************************** - * binfmt/libelf/libelf_coredump.c - * - * SPDX-License-Identifier: Apache-2.0 - * - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. The - * ASF licenses this file to you 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. - * - ****************************************************************************/ - -/**************************************************************************** - * Included Files - ****************************************************************************/ - -#include -#include - -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/**************************************************************************** - * Pre-processor Definitions - ****************************************************************************/ - -#ifdef PAGESIZE -# define ELF_PAGESIZE PAGESIZE -#else -# define ELF_PAGESIZE 1024 -#endif - -#define PROGRAM_ALIGNMENT 64 - -#define ROUNDUP(x, y) ((x + (y - 1)) / (y)) * (y) -#define ROUNDDOWN(x ,y) (((x) / (y)) * (y)) - -/**************************************************************************** - * Private Data - ****************************************************************************/ - -static uint8_t g_running_regs[XCPTCONTEXT_SIZE] aligned_data(16); - -/**************************************************************************** - * Private Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: elf_flush - * - * Description: - * Flush the out stream - * - ****************************************************************************/ - -static int elf_flush(FAR struct elf_dumpinfo_s *cinfo) -{ - return lib_stream_flush(cinfo->stream); -} - -/**************************************************************************** - * Name: elf_emit - * - * Description: - * Send the dump data to binfmt_outstream_s - * - ****************************************************************************/ - -static int elf_emit(FAR struct elf_dumpinfo_s *cinfo, - FAR const void *buf, size_t len) -{ - FAR const uint8_t *ptr = buf; - size_t total = len; - int ret = 0; - - while (total > 0) - { - ret = lib_stream_puts(cinfo->stream, ptr, total); - if (ret < 0) - { - break; - } - - total -= ret; - ptr += ret; - } - - return ret < 0 ? ret : len - total; -} - -/**************************************************************************** - * Name: elf_emit_align - * - * Description: - * Align the filled data according to the current offset - * - ****************************************************************************/ - -static int elf_emit_align(FAR struct elf_dumpinfo_s *cinfo) -{ - off_t align = ROUNDUP(cinfo->stream->nput, - ELF_PAGESIZE) - cinfo->stream->nput; - unsigned char null[256]; - off_t total = align; - off_t ret = 0; - - memset(null, 0, sizeof(null)); - - while (total > 0) - { - ret = elf_emit(cinfo, null, total > sizeof(null) ? - sizeof(null) : total); - if (ret <= 0) - { - break; - } - - total -= ret; - } - - return ret < 0 ? ret : align; -} - -/**************************************************************************** - * Name: elf_emit_hdr - * - * Description: - * Fill the elf header - * - ****************************************************************************/ - -static int elf_emit_hdr(FAR struct elf_dumpinfo_s *cinfo, - int segs) -{ - Elf_Ehdr ehdr; - - memset(&ehdr, 0, sizeof(ehdr)); - memcpy(ehdr.e_ident, ELFMAG, EI_MAGIC_SIZE); - - ehdr.e_ident[EI_CLASS] = ELF_CLASS; - ehdr.e_ident[EI_DATA] = ELF_DATA; - ehdr.e_ident[EI_VERSION] = EV_CURRENT; - ehdr.e_ident[EI_OSABI] = ELF_OSABI; - - ehdr.e_type = ET_CORE; - ehdr.e_machine = EM_ARCH; - ehdr.e_version = EV_CURRENT; - ehdr.e_phoff = sizeof(Elf_Ehdr); - ehdr.e_flags = EF_FLAG; - ehdr.e_ehsize = sizeof(Elf_Ehdr); - ehdr.e_phentsize = sizeof(Elf_Phdr); - ehdr.e_phnum = segs; - - return elf_emit(cinfo, &ehdr, sizeof(ehdr)); -} - -/**************************************************************************** - * Name: elf_get_ntcb - * - * Description: - * Calculate the note segment size - * - ****************************************************************************/ - -static int elf_get_ntcb(void) -{ - int count = 0; - int i; - - for (i = 0; i < g_npidhash; i++) - { - if (g_pidhash[i] != NULL) - { - count++; - } - } - - return count; -} - -/**************************************************************************** - * Name: elf_get_note_size - * - * Description: - * Calculate the note segment size - * - ****************************************************************************/ - -static int elf_get_note_size(int stksegs) -{ - int total; - - total = stksegs * (sizeof(Elf_Nhdr) + ROUNDUP(CONFIG_TASK_NAME_SIZE, 8) + - sizeof(elf_prstatus_t)); - total += stksegs * (sizeof(Elf_Nhdr) + ROUNDUP(CONFIG_TASK_NAME_SIZE, 8) + - sizeof(elf_prpsinfo_t)); - return total; -} - -/**************************************************************************** - * Name: elf_emit_tcb_note - * - * Description: - * Fill the note segment information from tcb - * - ****************************************************************************/ - -static void elf_emit_tcb_note(FAR struct elf_dumpinfo_s *cinfo, - FAR struct tcb_s *tcb) -{ - char name[ROUNDUP(CONFIG_TASK_NAME_SIZE, 8)]; - elf_prstatus_t status; - elf_prpsinfo_t info; - FAR uintptr_t *regs; - Elf_Nhdr nhdr; - int i; - - memset(&info, 0x0, sizeof(info)); - memset(&status, 0x0, sizeof(status)); - - /* Fill Process info */ - - nhdr.n_namesz = sizeof(name); - nhdr.n_descsz = sizeof(info); - nhdr.n_type = NT_PRPSINFO; - - elf_emit(cinfo, &nhdr, sizeof(nhdr)); - - strlcpy(name, get_task_name(tcb), sizeof(name)); - elf_emit(cinfo, name, sizeof(name)); - - info.pr_pid = tcb->pid; - strlcpy(info.pr_fname, get_task_name(tcb), sizeof(info.pr_fname)); - elf_emit(cinfo, &info, sizeof(info)); - - /* Fill Process status */ - - nhdr.n_descsz = sizeof(status); - nhdr.n_type = NT_PRSTATUS; - - elf_emit(cinfo, &nhdr, sizeof(nhdr)); - elf_emit(cinfo, name, sizeof(name)); - - status.pr_pid = tcb->pid; - - if (running_task() == tcb) - { - if (up_interrupt_context()) - { - regs = (FAR uintptr_t *)up_current_regs(); - } - else - { - up_saveusercontext(g_running_regs); - regs = (FAR uintptr_t *)g_running_regs; - } - } - else - { - regs = (FAR uintptr_t *)tcb->xcp.regs; - } - - if (regs != NULL) - { - for (i = 0; i < nitems(status.pr_regs); i++) - { - if (g_tcbinfo.reg_off.p[i] == UINT16_MAX) - { - continue; - } - else - { - status.pr_regs[i] = *(FAR uintptr_t *) - ((FAR uint8_t *)regs + g_tcbinfo.reg_off.p[i]); - } - } - } - - elf_emit(cinfo, &status, sizeof(status)); -} - -/**************************************************************************** - * Name: elf_emit_note - * - * Description: - * Fill the note segment information - * - ****************************************************************************/ - -static void elf_emit_note(FAR struct elf_dumpinfo_s *cinfo) -{ - int i; - - if (cinfo->pid == INVALID_PROCESS_ID) - { - for (i = 0; i < g_npidhash; i++) - { - if (g_pidhash[i] != NULL) - { - elf_emit_tcb_note(cinfo, g_pidhash[i]); - } - } - } - else - { - elf_emit_tcb_note(cinfo, nxsched_get_tcb(cinfo->pid)); - } -} - -/**************************************************************************** - * Name: elf_emit_tcb_stack - * - * Description: - * Fill the task stack information from tcb - * - ****************************************************************************/ - -static void elf_emit_tcb_stack(FAR struct elf_dumpinfo_s *cinfo, - FAR struct tcb_s *tcb) -{ - uintptr_t buf = 0; - uintptr_t sp; - size_t len; - - if (running_task() != tcb) - { - sp = up_getusrsp(tcb->xcp.regs); - - if (sp > (uintptr_t)tcb->stack_base_ptr && - sp < (uintptr_t)tcb->stack_base_ptr + tcb->adj_stack_size) - { - len = ((uintptr_t)tcb->stack_base_ptr + - tcb->adj_stack_size) - sp; - buf = sp; - } -#ifdef CONFIG_STACK_COLORATION - else - { - len = up_check_tcbstack(tcb); - buf = (uintptr_t)tcb->stack_base_ptr + - (tcb->adj_stack_size - len); - } -#endif - } - - if (buf == 0) - { - buf = (uintptr_t)tcb->stack_alloc_ptr; - len = tcb->adj_stack_size + - (tcb->stack_base_ptr - tcb->stack_alloc_ptr); - } - - sp = ROUNDDOWN(buf, PROGRAM_ALIGNMENT); - len = ROUNDUP(len + (buf - sp), PROGRAM_ALIGNMENT); - buf = sp; - - elf_emit(cinfo, (FAR void *)buf, len); - - /* Align to page */ - - elf_emit_align(cinfo); -} - -/**************************************************************************** - * Name: elf_emit_stack - * - * Description: - * Fill the task stack information - * - ****************************************************************************/ - -static void elf_emit_stack(FAR struct elf_dumpinfo_s *cinfo) -{ - int i; - - if (cinfo->pid == INVALID_PROCESS_ID) - { - for (i = 0; i < g_npidhash; i++) - { - if (g_pidhash[i] != NULL) - { - elf_emit_tcb_stack(cinfo, g_pidhash[i]); - } - } - } - else - { - elf_emit_tcb_stack(cinfo, nxsched_get_tcb(cinfo->pid)); - } -} - -/**************************************************************************** - * Name: elf_emit_memory - * - * Description: - * Fill the note segment information - * - ****************************************************************************/ - -static void elf_emit_memory(FAR struct elf_dumpinfo_s *cinfo, int memsegs) -{ - int i; - - for (i = 0; i < memsegs; i++) - { - if (cinfo->regions[i].flags & PF_REGISTER) - { - FAR uintptr_t *start = (FAR uintptr_t *)cinfo->regions[i].start; - FAR uintptr_t *end = (FAR uintptr_t *)cinfo->regions[i].end; - uintptr_t buf[64]; - size_t offset = 0; - - while (start < end) - { - buf[offset++] = *start++; - - if (offset % (sizeof(buf) / sizeof(uintptr_t)) == 0) - { - elf_emit(cinfo, buf, sizeof(buf)); - offset = 0; - } - } - - if (offset != 0) - { - elf_emit(cinfo, buf, offset * sizeof(uintptr_t)); - } - } - else - { - elf_emit(cinfo, (FAR void *)cinfo->regions[i].start, - cinfo->regions[i].end - cinfo->regions[i].start); - } - - /* Align to page */ - - elf_emit_align(cinfo); - } -} - -/**************************************************************************** - * Name: elf_emit_tcb_phdr - * - * Description: - * Fill the program segment header from tcb - * - ****************************************************************************/ - -static void elf_emit_tcb_phdr(FAR struct elf_dumpinfo_s *cinfo, - FAR struct tcb_s *tcb, - FAR Elf_Phdr *phdr, FAR off_t *offset) -{ - uintptr_t sp; - - phdr->p_vaddr = 0; - - if (running_task() != tcb) - { - sp = up_getusrsp(tcb->xcp.regs); - - if (sp > (uintptr_t)tcb->stack_base_ptr && - sp < (uintptr_t)tcb->stack_base_ptr + tcb->adj_stack_size) - { - phdr->p_filesz = ((uintptr_t)tcb->stack_base_ptr + - tcb->adj_stack_size) - sp; - phdr->p_vaddr = sp; - } -#ifdef CONFIG_STACK_COLORATION - else - { - phdr->p_filesz = up_check_tcbstack(tcb); - phdr->p_vaddr = (uintptr_t)tcb->stack_base_ptr + - (tcb->adj_stack_size - phdr->p_filesz); - } -#endif - } - - if (phdr->p_vaddr == 0) - { - phdr->p_vaddr = (uintptr_t)tcb->stack_alloc_ptr; - phdr->p_filesz = tcb->adj_stack_size + - (tcb->stack_base_ptr - tcb->stack_alloc_ptr); - } - - sp = ROUNDDOWN(phdr->p_vaddr, PROGRAM_ALIGNMENT); - phdr->p_filesz = ROUNDUP(phdr->p_filesz + - (phdr->p_vaddr - sp), PROGRAM_ALIGNMENT); - phdr->p_vaddr = sp; - - phdr->p_type = PT_LOAD; - phdr->p_offset = ROUNDUP(*offset, ELF_PAGESIZE); - phdr->p_paddr = phdr->p_vaddr; - phdr->p_memsz = phdr->p_filesz; - phdr->p_flags = PF_X | PF_W | PF_R; - phdr->p_align = ELF_PAGESIZE; - *offset += ROUNDUP(phdr->p_memsz, ELF_PAGESIZE); - - elf_emit(cinfo, phdr, sizeof(*phdr)); -} - -/**************************************************************************** - * Name: elf_emit_phdr - * - * Description: - * Fill the program segment header - * - ****************************************************************************/ - -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); - Elf_Phdr phdr; - int i; - - memset(&phdr, 0, sizeof(Elf_Phdr)); - - phdr.p_type = PT_NOTE; - phdr.p_offset = offset; - phdr.p_filesz = elf_get_note_size(stksegs); - offset += phdr.p_filesz; - - elf_emit(cinfo, &phdr, sizeof(phdr)); - - if (cinfo->pid == INVALID_PROCESS_ID) - { - for (i = 0; i < g_npidhash; i++) - { - if (g_pidhash[i] != NULL) - { - elf_emit_tcb_phdr(cinfo, g_pidhash[i], &phdr, &offset); - } - } - } - else - { - elf_emit_tcb_phdr(cinfo, nxsched_get_tcb(cinfo->pid), - &phdr, &offset); - } - - /* Write program headers for segments dump */ - - for (i = 0; i < memsegs; i++) - { - phdr.p_type = PT_LOAD; - phdr.p_offset = ROUNDUP(offset, ELF_PAGESIZE); - phdr.p_vaddr = cinfo->regions[i].start; - phdr.p_paddr = phdr.p_vaddr; - phdr.p_filesz = cinfo->regions[i].end - cinfo->regions[i].start; - phdr.p_memsz = phdr.p_filesz; - phdr.p_flags = cinfo->regions[i].flags; - phdr.p_align = ELF_PAGESIZE; - offset += ROUNDUP(phdr.p_memsz, ELF_PAGESIZE); - elf_emit(cinfo, &phdr, sizeof(phdr)); - } -} - -/**************************************************************************** - * Public Functions - ****************************************************************************/ - -/**************************************************************************** - * Name: elf_coredump - * - * Description: - * Generat the core dump stream as ELF structure. - * - * Input Parameters: - * dumpinfo - elf coredump informations - * - * Returned Value: - * Zero (OK) on success; a negated errno value on failure. - * - ****************************************************************************/ - -int elf_coredump(FAR struct elf_dumpinfo_s *cinfo) -{ - irqstate_t flags; - int memsegs = 0; - int stksegs; - - flags = enter_critical_section(); - - if (cinfo->pid != INVALID_PROCESS_ID) - { - if (nxsched_get_tcb(cinfo->pid) == NULL) - { - leave_critical_section(flags); - return -EINVAL; - } - - stksegs = 1; - } - else - { - stksegs = elf_get_ntcb(); - } - - /* Check the memory region */ - - if (cinfo->regions != NULL) - { - for (; cinfo->regions[memsegs].start < - cinfo->regions[memsegs].end; memsegs++); - } - - /* Fill notes section */ - - elf_emit_hdr(cinfo, stksegs + memsegs + 1); - - /* Fill all the program information about the process for the - * notes. This also sets up the file header. - */ - - elf_emit_phdr(cinfo, stksegs, memsegs); - - /* Fill note information */ - - elf_emit_note(cinfo); - - /* Align to page */ - - elf_emit_align(cinfo); - - /* Dump stack */ - - elf_emit_stack(cinfo); - - /* Dump memory segments */ - - if (memsegs > 0) - { - elf_emit_memory(cinfo, memsegs); - } - - /* Flush the dump */ - - elf_flush(cinfo); - - leave_critical_section(flags); - - return OK; -} diff --git a/binfmt/nxflat.c b/binfmt/nxflat.c index b1ec250e63..175c3eb5dd 100644 --- a/binfmt/nxflat.c +++ b/binfmt/nxflat.c @@ -81,7 +81,6 @@ static struct binfmt_s g_nxflatbinfmt = NULL, /* next */ nxflat_loadbinary, /* load */ nxflat_unloadbinary, /* unload */ - NULL, /* coredump */ }; /**************************************************************************** diff --git a/boards/Kconfig b/boards/Kconfig index e98058c9e6..44d2ec5cd0 100644 --- a/boards/Kconfig +++ b/boards/Kconfig @@ -4634,14 +4634,14 @@ config BOARD_CRASHDUMP config BOARD_COREDUMP_SYSLOG bool "Enable Core dump to syslog" default n - depends on ELF_COREDUMP + depends on COREDUMP ---help--- Enable put coredump to syslog when crash. config BOARD_COREDUMP_BLKDEV bool "Enable Core Dump to block device" default n - depends on ELF_COREDUMP + depends on COREDUMP ---help--- Enable save coredump at block device when crash. diff --git a/boards/arm/imx6/sabre-6quad/configs/coredump/defconfig b/boards/arm/imx6/sabre-6quad/configs/coredump/defconfig index da7f72396b..e8112e8b25 100644 --- a/boards/arm/imx6/sabre-6quad/configs/coredump/defconfig +++ b/boards/arm/imx6/sabre-6quad/configs/coredump/defconfig @@ -21,13 +21,12 @@ CONFIG_BOARD_COREDUMP_SYSLOG=y CONFIG_BOARD_LOOPSPERMSEC=99369 CONFIG_BOOT_RUNFROMSDRAM=y CONFIG_BUILTIN=y +CONFIG_COREDUMP=y CONFIG_DEBUG_ASSERTIONS=y CONFIG_DEBUG_FEATURES=y CONFIG_DEBUG_FULLOPT=y CONFIG_DEBUG_SYMBOLS=y CONFIG_DEV_ZERO=y -CONFIG_ELF=y -CONFIG_ELF_COREDUMP=y CONFIG_EXAMPLES_HELLO=y CONFIG_EXPERIMENTAL=y CONFIG_FS_PROCFS=y diff --git a/include/nuttx/binfmt/binfmt.h b/include/nuttx/binfmt/binfmt.h index 044719692f..9582ee1ac4 100644 --- a/include/nuttx/binfmt/binfmt.h +++ b/include/nuttx/binfmt/binfmt.h @@ -31,18 +31,14 @@ #include #include -#include #include -#include -#include /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ #define BINFMT_NALLOC 4 -#define COREDUMP_MAGIC 0x434f5245 /**************************************************************************** * Public Types @@ -138,22 +134,6 @@ struct binfmt_s /* Unload module callback */ CODE int (*unload)(FAR struct binary_s *bin); - - /* Coredump callback */ - - CODE int (*coredump)(FAR const struct memory_region_s *regions, - FAR struct lib_outstream_s *stream, - pid_t pid); -}; - -/* Coredump information for block header */ - -struct coredump_info_s -{ - uint32_t magic; - struct utsname name; - time_t time; - size_t size; }; /**************************************************************************** @@ -209,23 +189,6 @@ int register_binfmt(FAR struct binfmt_s *binfmt); int unregister_binfmt(FAR struct binfmt_s *binfmt); -/**************************************************************************** - * Name: core_dump - * - * Description: - * This function for generating core dump stream. - * - * Returned Value: - * This is a NuttX internal function so it follows the convention that - * 0 (OK) is returned on success and a negated errno is returned on - * failure. - * - ****************************************************************************/ - -int core_dump(FAR const struct memory_region_s *regions, - FAR struct lib_outstream_s *stream, - pid_t pid); - /**************************************************************************** * Name: load_module * diff --git a/include/nuttx/binfmt/elf.h b/include/nuttx/binfmt/elf.h index 854c010688..60793dabc8 100644 --- a/include/nuttx/binfmt/elf.h +++ b/include/nuttx/binfmt/elf.h @@ -129,19 +129,6 @@ struct elf_loadinfo_s struct file file; /* Descriptor for the file being loaded */ }; -/* This struct provides a description of the dump information of - * memory regions. - */ - -#ifdef CONFIG_ELF_COREDUMP -struct elf_dumpinfo_s -{ - FAR const struct memory_region_s *regions; - FAR struct lib_outstream_s *stream; - pid_t pid; -}; -#endif - /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -233,24 +220,6 @@ int elf_bind(FAR struct elf_loadinfo_s *loadinfo, int elf_unload(FAR struct elf_loadinfo_s *loadinfo); -/**************************************************************************** - * Name: elf_coredump - * - * Description: - * Generat the core dump stream as ELF structure. - * - * Input Parameters: - * dumpinfo - elf coredump informations - * - * Returned Value: - * Zero (OK) on success; a negated errno value on failure. - * - ****************************************************************************/ - -#ifdef CONFIG_ELF_COREDUMP -int elf_coredump(FAR struct elf_dumpinfo_s *dumpinfo); -#endif - #undef EXTERN #if defined(__cplusplus) } diff --git a/include/nuttx/coredump.h b/include/nuttx/coredump.h index 46f1fa0975..ee798223a0 100644 --- a/include/nuttx/coredump.h +++ b/include/nuttx/coredump.h @@ -27,9 +27,32 @@ * Included Files ****************************************************************************/ -#include +#include #include +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define COREDUMP_MAGIC 0x434f5245 + +/**************************************************************************** + * Public Types + ****************************************************************************/ + +/* Coredump information for block header */ + +struct coredump_info_s +{ + uint32_t magic; + struct utsname name; + time_t time; + size_t size; +}; + /**************************************************************************** * Public Function Prototypes ****************************************************************************/ @@ -54,4 +77,16 @@ int coredump_set_memory_region(FAR const struct memory_region_s *region); int coredump_add_memory_region(FAR const void *ptr, size_t size); +/**************************************************************************** + * Name: coredump + * + * Description: + * This function for generating core dump stream. + * + ****************************************************************************/ + +int coredump(FAR const struct memory_region_s *regions, + FAR struct lib_outstream_s *stream, + pid_t pid); + #endif /* __INCLUDE_NUTTX_COREDUMP_H */ diff --git a/include/nuttx/elf.h b/include/nuttx/elf.h index 522795de78..0737f5b615 100644 --- a/include/nuttx/elf.h +++ b/include/nuttx/elf.h @@ -40,7 +40,7 @@ * Public Types ****************************************************************************/ -#ifdef CONFIG_ELF_COREDUMP +#ifdef CONFIG_COREDUMP typedef struct elf_prpsinfo_s { char pr_state; /* Numeric process state */ diff --git a/sched/Kconfig b/sched/Kconfig index fe7cd0008a..8b09ca1f02 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -2047,3 +2047,15 @@ config ASSERT_PAUSE_CPU_TIMEOUT ---help--- Timeout in milisecond to pause another CPU when assert. Only available when SMP is enabled. + Enable to support perf events. + +config COREDUMP + bool "Coredump support" + depends on ARCH_HAVE_TCBINFO + default n + ---help--- + Generate ELF core dump to provide information about the CPU state and the + memory state of program. + The memory state embeds a snapshot of all segments mapped in the + memory space of the program. The CPU state contains register values + when the core dump has been generated. diff --git a/sched/misc/CMakeLists.txt b/sched/misc/CMakeLists.txt index d9afdf25ed..43003dee48 100644 --- a/sched/misc/CMakeLists.txt +++ b/sched/misc/CMakeLists.txt @@ -26,7 +26,7 @@ if(CONFIG_ARCH_DEADLOCKDUMP) list(APPEND SRCS deadlock.c) endif() -if(CONFIG_BOARD_COREDUMP_SYSLOG OR CONFIG_BOARD_COREDUMP_BLKDEV) +if(CONFIG_COREDUMP) list(APPEND SRCS coredump.c) endif() diff --git a/sched/misc/Make.defs b/sched/misc/Make.defs index c105d79f96..9a40bec31c 100644 --- a/sched/misc/Make.defs +++ b/sched/misc/Make.defs @@ -26,7 +26,7 @@ ifeq ($(CONFIG_ARCH_DEADLOCKDUMP),y) CSRCS += deadlock.c endif -ifneq ($(CONFIG_BOARD_COREDUMP_SYSLOG)$(CONFIG_BOARD_COREDUMP_BLKDEV),) +ifeq ($(CONFIG_COREDUMP),y) CSRCS += coredump.c endif diff --git a/sched/misc/coredump.c b/sched/misc/coredump.c index 16c6867b58..76d048251c 100644 --- a/sched/misc/coredump.c +++ b/sched/misc/coredump.c @@ -24,15 +24,55 @@ * Included Files ****************************************************************************/ +#include +#include + #include #include +#include +#include +#include + +#include "sched/sched.h" #include "coredump.h" /**************************************************************************** * Private Data ****************************************************************************/ +#ifdef PAGESIZE +# define ELF_PAGESIZE PAGESIZE +#else +# define ELF_PAGESIZE 1024 +#endif + +#define PROGRAM_ALIGNMENT 64 + +#define ROUNDUP(x, y) ((x + (y - 1)) / (y)) * (y) +#define ROUNDDOWN(x ,y) (((x) / (y)) * (y)) + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +/* This struct provides a description of the dump information of + * memory regions. + */ + +struct elf_dumpinfo_s +{ + FAR const struct memory_region_s *regions; + FAR struct lib_outstream_s *stream; + pid_t pid; +}; + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static uint8_t g_running_regs[XCPTCONTEXT_SIZE] aligned_data(16); + #ifdef CONFIG_BOARD_COREDUMP_COMPRESSION static struct lib_lzfoutstream_s g_lzfstream; #endif @@ -63,6 +103,521 @@ static const struct memory_region_s *g_regions; * Private Functions ****************************************************************************/ +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: elf_flush + * + * Description: + * Flush the out stream + * + ****************************************************************************/ + +static int elf_flush(FAR struct elf_dumpinfo_s *cinfo) +{ + return lib_stream_flush(cinfo->stream); +} + +/**************************************************************************** + * Name: elf_emit + * + * Description: + * Send the dump data to binfmt_outstream_s + * + ****************************************************************************/ + +static int elf_emit(FAR struct elf_dumpinfo_s *cinfo, + FAR const void *buf, size_t len) +{ + FAR const uint8_t *ptr = buf; + size_t total = len; + int ret; + + while (total > 0) + { + ret = lib_stream_puts(cinfo->stream, ptr, total); + if (ret < 0) + { + break; + } + + total -= ret; + ptr += ret; + } + + return ret < 0 ? ret : len - total; +} + +/**************************************************************************** + * Name: elf_emit_align + * + * Description: + * Align the filled data according to the current offset + * + ****************************************************************************/ + +static int elf_emit_align(FAR struct elf_dumpinfo_s *cinfo) +{ + off_t align = ROUNDUP(cinfo->stream->nput, + ELF_PAGESIZE) - cinfo->stream->nput; + unsigned char null[256]; + off_t total = align; + off_t ret; + + memset(null, 0, sizeof(null)); + + while (total > 0) + { + ret = elf_emit(cinfo, null, total > sizeof(null) ? + sizeof(null) : total); + if (ret <= 0) + { + break; + } + + total -= ret; + } + + return ret < 0 ? ret : align; +} + +/**************************************************************************** + * Name: elf_emit_hdr + * + * Description: + * Fill the elf header + * + ****************************************************************************/ + +static int elf_emit_hdr(FAR struct elf_dumpinfo_s *cinfo, + int segs) +{ + Elf_Ehdr ehdr; + + memset(&ehdr, 0, sizeof(ehdr)); + memcpy(ehdr.e_ident, ELFMAG, EI_MAGIC_SIZE); + + ehdr.e_ident[EI_CLASS] = ELF_CLASS; + ehdr.e_ident[EI_DATA] = ELF_DATA; + ehdr.e_ident[EI_VERSION] = EV_CURRENT; + ehdr.e_ident[EI_OSABI] = ELF_OSABI; + + ehdr.e_type = ET_CORE; + ehdr.e_machine = EM_ARCH; + ehdr.e_version = EV_CURRENT; + ehdr.e_phoff = sizeof(Elf_Ehdr); + ehdr.e_flags = EF_FLAG; + ehdr.e_ehsize = sizeof(Elf_Ehdr); + ehdr.e_phentsize = sizeof(Elf_Phdr); + ehdr.e_phnum = segs; + + return elf_emit(cinfo, &ehdr, sizeof(ehdr)); +} + +/**************************************************************************** + * Name: elf_get_ntcb + * + * Description: + * Calculate the note segment size + * + ****************************************************************************/ + +static int elf_get_ntcb(void) +{ + int count = 0; + int i; + + for (i = 0; i < g_npidhash; i++) + { + if (g_pidhash[i] != NULL) + { + count++; + } + } + + return count; +} + +/**************************************************************************** + * Name: elf_get_note_size + * + * Description: + * Calculate the note segment size + * + ****************************************************************************/ + +static int elf_get_note_size(int stksegs) +{ + int total; + + total = stksegs * (sizeof(Elf_Nhdr) + ROUNDUP(CONFIG_TASK_NAME_SIZE, 8) + + sizeof(elf_prstatus_t)); + total += stksegs * (sizeof(Elf_Nhdr) + ROUNDUP(CONFIG_TASK_NAME_SIZE, 8) + + sizeof(elf_prpsinfo_t)); + return total; +} + +/**************************************************************************** + * Name: elf_emit_tcb_note + * + * Description: + * Fill the note segment information from tcb + * + ****************************************************************************/ + +static void elf_emit_tcb_note(FAR struct elf_dumpinfo_s *cinfo, + FAR struct tcb_s *tcb) +{ + char name[ROUNDUP(CONFIG_TASK_NAME_SIZE, 8)]; + elf_prstatus_t status; + elf_prpsinfo_t info; + FAR uintptr_t *regs; + Elf_Nhdr nhdr; + int i; + + memset(&info, 0x0, sizeof(info)); + memset(&status, 0x0, sizeof(status)); + + /* Fill Process info */ + + nhdr.n_namesz = sizeof(name); + nhdr.n_descsz = sizeof(info); + nhdr.n_type = NT_PRPSINFO; + + elf_emit(cinfo, &nhdr, sizeof(nhdr)); + + strlcpy(name, tcb->name, sizeof(name)); + elf_emit(cinfo, name, sizeof(name)); + + info.pr_pid = tcb->pid; + strlcpy(info.pr_fname, tcb->name, sizeof(info.pr_fname)); + elf_emit(cinfo, &info, sizeof(info)); + + /* Fill Process status */ + + nhdr.n_descsz = sizeof(status); + nhdr.n_type = NT_PRSTATUS; + + elf_emit(cinfo, &nhdr, sizeof(nhdr)); + elf_emit(cinfo, name, sizeof(name)); + + status.pr_pid = tcb->pid; + + if (running_task() == tcb) + { + if (up_interrupt_context()) + { + regs = (FAR uintptr_t *)up_current_regs(); + } + else + { + up_saveusercontext(g_running_regs); + regs = (FAR uintptr_t *)g_running_regs; + } + } + else + { + regs = (FAR uintptr_t *)tcb->xcp.regs; + } + + if (regs != NULL) + { + for (i = 0; i < nitems(status.pr_regs); i++) + { + if (g_tcbinfo.reg_off.p[i] == UINT16_MAX) + { + continue; + } + else + { + status.pr_regs[i] = + *(uintptr_t *)((uint8_t *)regs + g_tcbinfo.reg_off.p[i]); + } + } + } + + elf_emit(cinfo, &status, sizeof(status)); +} + +/**************************************************************************** + * Name: elf_emit_note + * + * Description: + * Fill the note segment information + * + ****************************************************************************/ + +static void elf_emit_note(FAR struct elf_dumpinfo_s *cinfo) +{ + int i; + + if (cinfo->pid == INVALID_PROCESS_ID) + { + for (i = 0; i < g_npidhash; i++) + { + if (g_pidhash[i] != NULL) + { + elf_emit_tcb_note(cinfo, g_pidhash[i]); + } + } + } + else + { + elf_emit_tcb_note(cinfo, nxsched_get_tcb(cinfo->pid)); + } +} + +/**************************************************************************** + * Name: elf_emit_tcb_stack + * + * Description: + * Fill the task stack information from tcb + * + ****************************************************************************/ + +static void elf_emit_tcb_stack(FAR struct elf_dumpinfo_s *cinfo, + FAR struct tcb_s *tcb) +{ + uintptr_t buf = 0; + uintptr_t sp; + size_t len; + + if (running_task() != tcb) + { + sp = up_getusrsp(tcb->xcp.regs); + + if (sp > (uintptr_t)tcb->stack_base_ptr && + sp < (uintptr_t)tcb->stack_base_ptr + tcb->adj_stack_size) + { + len = ((uintptr_t)tcb->stack_base_ptr + + tcb->adj_stack_size) - sp; + buf = sp; + } +#ifdef CONFIG_STACK_COLORATION + else + { + len = up_check_tcbstack(tcb); + buf = (uintptr_t)tcb->stack_base_ptr + + (tcb->adj_stack_size - len); + } +#endif + } + + if (buf == 0) + { + buf = (uintptr_t)tcb->stack_alloc_ptr; + len = tcb->adj_stack_size + + (tcb->stack_base_ptr - tcb->stack_alloc_ptr); + } + + sp = ROUNDDOWN(buf, PROGRAM_ALIGNMENT); + len = ROUNDUP(len + (buf - sp), PROGRAM_ALIGNMENT); + buf = sp; + + elf_emit(cinfo, (FAR void *)buf, len); + + /* Align to page */ + + elf_emit_align(cinfo); +} + +/**************************************************************************** + * Name: elf_emit_stack + * + * Description: + * Fill the task stack information + * + ****************************************************************************/ + +static void elf_emit_stack(FAR struct elf_dumpinfo_s *cinfo) +{ + int i; + + if (cinfo->pid == INVALID_PROCESS_ID) + { + for (i = 0; i < g_npidhash; i++) + { + if (g_pidhash[i] != NULL) + { + elf_emit_tcb_stack(cinfo, g_pidhash[i]); + } + } + } + else + { + elf_emit_tcb_stack(cinfo, nxsched_get_tcb(cinfo->pid)); + } +} + +/**************************************************************************** + * Name: elf_emit_memory + * + * Description: + * Fill the note segment information + * + ****************************************************************************/ + +static void elf_emit_memory(FAR struct elf_dumpinfo_s *cinfo, int memsegs) +{ + int i; + + for (i = 0; i < memsegs; i++) + { + if (cinfo->regions[i].flags & PF_REGISTER) + { + FAR uintptr_t *start = (FAR uintptr_t *)cinfo->regions[i].start; + FAR uintptr_t *end = (FAR uintptr_t *)cinfo->regions[i].end; + uintptr_t buf[64]; + size_t offset = 0; + + while (start < end) + { + buf[offset++] = *start++; + + if (offset % (sizeof(buf) / sizeof(uintptr_t)) == 0) + { + elf_emit(cinfo, buf, sizeof(buf)); + offset = 0; + } + } + + if (offset != 0) + { + elf_emit(cinfo, buf, offset * sizeof(uintptr_t)); + } + } + else + { + elf_emit(cinfo, (FAR void *)cinfo->regions[i].start, + cinfo->regions[i].end - cinfo->regions[i].start); + } + + /* Align to page */ + + elf_emit_align(cinfo); + } +} + +/**************************************************************************** + * Name: elf_emit_tcb_phdr + * + * Description: + * Fill the program segment header from tcb + * + ****************************************************************************/ + +static void elf_emit_tcb_phdr(FAR struct elf_dumpinfo_s *cinfo, + FAR struct tcb_s *tcb, + FAR Elf_Phdr *phdr, off_t *offset) +{ + uintptr_t sp; + + phdr->p_vaddr = 0; + + if (running_task() != tcb) + { + sp = up_getusrsp(tcb->xcp.regs); + + if (sp > (uintptr_t)tcb->stack_base_ptr && + sp < (uintptr_t)tcb->stack_base_ptr + tcb->adj_stack_size) + { + phdr->p_filesz = ((uintptr_t)tcb->stack_base_ptr + + tcb->adj_stack_size) - sp; + phdr->p_vaddr = sp; + } +#ifdef CONFIG_STACK_COLORATION + else + { + phdr->p_filesz = up_check_tcbstack(tcb); + phdr->p_vaddr = (uintptr_t)tcb->stack_base_ptr + + (tcb->adj_stack_size - phdr->p_filesz); + } +#endif + } + + if (phdr->p_vaddr == 0) + { + phdr->p_vaddr = (uintptr_t)tcb->stack_alloc_ptr; + phdr->p_filesz = tcb->adj_stack_size + + (tcb->stack_base_ptr - tcb->stack_alloc_ptr); + } + + sp = ROUNDDOWN(phdr->p_vaddr, PROGRAM_ALIGNMENT); + phdr->p_filesz = ROUNDUP(phdr->p_filesz + + (phdr->p_vaddr - sp), PROGRAM_ALIGNMENT); + phdr->p_vaddr = sp; + + phdr->p_type = PT_LOAD; + phdr->p_offset = ROUNDUP(*offset, ELF_PAGESIZE); + phdr->p_paddr = phdr->p_vaddr; + phdr->p_memsz = phdr->p_filesz; + phdr->p_flags = PF_X | PF_W | PF_R; + phdr->p_align = ELF_PAGESIZE; + *offset += ROUNDUP(phdr->p_memsz, ELF_PAGESIZE); + + elf_emit(cinfo, phdr, sizeof(*phdr)); +} + +/**************************************************************************** + * Name: elf_emit_phdr + * + * Description: + * Fill the program segment header + * + ****************************************************************************/ + +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); + Elf_Phdr phdr; + int i; + + memset(&phdr, 0, sizeof(Elf_Phdr)); + + phdr.p_type = PT_NOTE; + phdr.p_offset = offset; + phdr.p_filesz = elf_get_note_size(stksegs); + offset += phdr.p_filesz; + + elf_emit(cinfo, &phdr, sizeof(phdr)); + + if (cinfo->pid == INVALID_PROCESS_ID) + { + for (i = 0; i < g_npidhash; i++) + { + if (g_pidhash[i] != NULL) + { + elf_emit_tcb_phdr(cinfo, g_pidhash[i], &phdr, &offset); + } + } + } + else + { + elf_emit_tcb_phdr(cinfo, nxsched_get_tcb(cinfo->pid), + &phdr, &offset); + } + + /* Write program headers for segments dump */ + + for (i = 0; i < memsegs; i++) + { + phdr.p_type = PT_LOAD; + phdr.p_offset = ROUNDUP(offset, ELF_PAGESIZE); + phdr.p_vaddr = cinfo->regions[i].start; + phdr.p_paddr = phdr.p_vaddr; + phdr.p_filesz = cinfo->regions[i].end - cinfo->regions[i].start; + phdr.p_memsz = phdr.p_filesz; + phdr.p_flags = cinfo->regions[i].flags; + phdr.p_align = ELF_PAGESIZE; + offset += ROUNDUP(phdr.p_memsz, ELF_PAGESIZE); + elf_emit(cinfo, &phdr, sizeof(phdr)); + } +} + /**************************************************************************** * Name: coredump_dump_syslog * @@ -106,7 +661,7 @@ static void coredump_dump_syslog(pid_t pid) /* Do core dump */ - core_dump(g_regions, stream, pid); + coredump(g_regions, stream, pid); # ifdef CONFIG_BOARD_COREDUMP_COMPRESSION _alert("Finish coredump (Compression Enabled). %s formatted\n", @@ -161,7 +716,7 @@ static void coredump_dump_blkdev(pid_t pid) stream = &g_lzfstream; #endif - ret = core_dump(g_regions, stream, pid); + ret = coredump(g_regions, stream, pid); if (ret < 0) { _alert("Coredump fail\n"); @@ -352,3 +907,87 @@ void coredump_dump(pid_t pid) coredump_dump_blkdev(pid); #endif } + +/**************************************************************************** + * Name: coredump + * + * Description: + * This function for generating core dump stream. + * + ****************************************************************************/ + +int coredump(FAR const struct memory_region_s *regions, + FAR struct lib_outstream_s *stream, + pid_t pid) +{ + struct elf_dumpinfo_s cinfo; + irqstate_t flags; + int memsegs = 0; + int stksegs; + + cinfo.regions = regions; + cinfo.stream = stream; + cinfo.pid = pid; + + flags = enter_critical_section(); + + if (cinfo.pid != INVALID_PROCESS_ID) + { + if (nxsched_get_tcb(cinfo.pid) == NULL) + { + leave_critical_section(flags); + return -EINVAL; + } + + stksegs = 1; + } + else + { + stksegs = elf_get_ntcb(); + } + + /* Check the memory region */ + + if (cinfo.regions != NULL) + { + for (; cinfo.regions[memsegs].start < + cinfo.regions[memsegs].end; memsegs++); + } + + /* Fill notes section */ + + elf_emit_hdr(&cinfo, stksegs + memsegs + 1); + + /* Fill all the program information about the process for the + * notes. This also sets up the file header. + */ + + elf_emit_phdr(&cinfo, stksegs, memsegs); + + /* Fill note information */ + + elf_emit_note(&cinfo); + + /* Align to page */ + + elf_emit_align(&cinfo); + + /* Dump stack */ + + elf_emit_stack(&cinfo); + + /* Dump memory segments */ + + if (memsegs > 0) + { + elf_emit_memory(&cinfo, memsegs); + } + + /* Flush the dump */ + + elf_flush(&cinfo); + + leave_critical_section(flags); + + return OK; +}