You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by xi...@apache.org on 2024/10/12 04:29:19 UTC
(nuttx) 06/20: coredump:Move coredump to sched/misc
This is an automated email from the ASF dual-hosted git repository.
xiaoxiang pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx.git
commit 52126aede114fe0d9264acf3a6fcccbf0a80ba16
Author: anjiahao <an...@xiaomi.com>
AuthorDate: Sat Jul 6 15:22:51 2024 +0800
coredump:Move coredump to sched/misc
1. move coredump form libelf to sched/misc
2. rename core_dump to coredump
Signed-off-by: anjiahao <an...@xiaomi.com>
---
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 +-
.../imx6/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(-)
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 <nuttx/config.h>
-
-#include <nuttx/binfmt/binfmt.h>
-#include <errno.h>
-
-#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 <nuttx/config.h>
-#include <nuttx/arch.h>
-
-#include <sys/stat.h>
-#include <sys/param.h>
-
-#include <stdio.h>
-#include <stdint.h>
-#include <string.h>
-#include <debug.h>
-#include <errno.h>
-
-#include <nuttx/elf.h>
-#include <nuttx/binfmt/elf.h>
-#include <nuttx/binfmt/binfmt.h>
-#include <nuttx/sched.h>
-#include <sched/sched.h>
-
-/****************************************************************************
- * 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 <spawn.h>
#include <sys/types.h>
-#include <sys/utsname.h>
#include <nuttx/sched.h>
-#include <nuttx/streams.h>
-#include <nuttx/memoryregion.h>
/****************************************************************************
* 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 <nuttx/memoryregion.h>
+#include <sys/utsname.h>
#include <unistd.h>
+#include <nuttx/streams.h>
+#include <nuttx/memoryregion.h>
+
+/****************************************************************************
+ * 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 <sys/stat.h>
+#include <sys/param.h>
+
#include <syslog.h>
#include <debug.h>
+#include <nuttx/coredump.h>
+#include <nuttx/elf.h>
+#include <nuttx/sched.h>
+
+#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;
+}