]> Zhao Yanbai Git Server - minix.git/commitdiff
ELF core files
authorAdriana Szekeres <adriana.szekeres@gmail.com>
Sat, 30 Jul 2011 06:03:23 +0000 (06:03 +0000)
committerBen Gras <ben@minix3.org>
Tue, 22 Nov 2011 21:07:40 +0000 (22:07 +0100)
17 files changed:
common/include/arch/i386/Makefile.inc
common/include/arch/i386/elf_machdep.h [new file with mode: 0644]
common/include/minix/com.h
common/include/sys/Makefile.inc
common/include/sys/elf_core.h [new file with mode: 0644]
common/include/sys/elf_generic.h
common/include/sys/exec_elf.h [moved from nbsd_include/sys/exec_elf.h with 100% similarity]
common/include/sys/procfs.h [new file with mode: 0644]
include/sys/param.h
nbsd_include/sys/Makefile
servers/pm/forkexit.c
servers/vfs/Makefile
servers/vfs/elf_core_dump.c [new file with mode: 0644]
servers/vfs/main.c
servers/vfs/misc.c
servers/vfs/open.c
servers/vfs/proto.h

index bc6e15d55a115175143d24b96f29315010d30d70..be3cd8728ecf9170d021163972fe6644a39bea64 100644 (file)
@@ -4,5 +4,5 @@
 INCS+= archtypes.h bios.h cmos.h cpu.h diskparm.h fpu.h int86.h \
        interrupt.h memory.h multiboot.h partition.h \
        pci.h pci_amd.h pci_intel.h pci_sis.h pci_via.h \
-       ports.h stackframe.h vm.h elf.h
+       ports.h stackframe.h vm.h elf.h elf_machdep.h
 
diff --git a/common/include/arch/i386/elf_machdep.h b/common/include/arch/i386/elf_machdep.h
new file mode 100644 (file)
index 0000000..442c561
--- /dev/null
@@ -0,0 +1,63 @@
+/*     $NetBSD: elf_machdep.h,v 1.10 2009/05/30 05:56:52 skrll Exp $   */
+
+#define        ELF32_MACHDEP_ENDIANNESS        ELFDATA2LSB
+#define        ELF32_MACHDEP_ID_CASES                                          \
+               case EM_386:                                            \
+               case EM_486:                                            \
+                       break;
+
+#define        ELF64_MACHDEP_ENDIANNESS        XXX     /* break compilation */
+#define        ELF64_MACHDEP_ID_CASES                                          \
+               /* no 64-bit ELF machine types supported */
+
+#define        ELF32_MACHDEP_ID                EM_386
+
+#define ARCH_ELFSIZE           32      /* MD native binary size */
+
+/* i386 relocations */
+#define        R_386_NONE      0
+#define        R_386_32        1
+#define        R_386_PC32      2
+#define        R_386_GOT32     3
+#define        R_386_PLT32     4
+#define        R_386_COPY      5
+#define        R_386_GLOB_DAT  6
+#define        R_386_JMP_SLOT  7
+#define        R_386_RELATIVE  8
+#define        R_386_GOTOFF    9
+#define        R_386_GOTPC     10
+
+/* TLS relocations */
+#define        R_386_TLS_TPOFF 14
+#define        R_386_TLS_IE    15
+#define        R_386_TLS_GOTIE 16
+#define        R_386_TLS_LE    17
+#define        R_386_TLS_GD    18
+#define        R_386_TLS_LDM   19
+
+/* The following relocations are GNU extensions. */
+#define        R_386_16        20
+#define        R_386_PC16      21
+#define        R_386_8         22
+#define        R_386_PC8       23
+
+/* More TLS relocations */
+#define        R_386_TLS_GD_32         24
+#define        R_386_TLS_GD_PUSH       25
+#define        R_386_TLS_GD_CALL       26
+#define        R_386_TLS_GD_POP        27
+#define        R_386_TLS_LDM_32        28
+#define        R_386_TLS_LDM_PUSH      29
+#define        R_386_TLS_LDM_CALL      30
+#define        R_386_TLS_LDM_POP       31
+#define        R_386_TLS_LDO_32        32
+#define        R_386_TLS_IE_32         33
+#define        R_386_TLS_LE_32         34
+#define        R_386_TLS_DTPMOD32      35
+#define        R_386_TLS_DTPOFF32      36
+#define        R_386_TLS_TPOFF32       37
+#define        R_386_TLS_GOTDESC       39
+#define        R_386_TLS_DESC_CALL     40
+#define        R_386_TLS_DESC          41
+
+#define        R_TYPE(name)    __CONCAT(R_386_,name)
index 3bfe6d87c3a35cd5a59b09a240acf596552d123f..b82433f42170020e72be1fdb5b14e0dda6250bdf 100644 (file)
 #  define PM_PPROC             m1_i2   /* parent process endpoint */
 #  define PM_CPID              m1_i3   /* child pid */
 
+/* Additional parameters for PM_DUMPCORE */
+#  define PM_TERM_SIG          m1_i2   /* process's termination signal */
+
 /* Parameters for the EXEC_NEWMEM call */
 #define EXC_NM_PROC    m1_i1           /* process that needs new map */
 #define EXC_NM_PTR     m1_p1           /* parameters in struct exec_newmem */
index 2f5a5ecf80cdd0abfd85903404d661e0e762eeb0..f8e4c932b7ce851f35a563c5b42816403d61acde 100644 (file)
@@ -5,5 +5,5 @@
 INCS+=         elf32.h elf64.h elf_common.h elf_generic.h \
        ioc_file.h ioc_tape.h ioc_disk.h \
        ioc_memory.h ioc_sound.h ioc_tty.h \
-       kbdio.h mtio.h svrctl.h video.h vm.h
+       kbdio.h mtio.h svrctl.h video.h vm.h procfs.h elf_core.h exec_elf.h
 
diff --git a/common/include/sys/elf_core.h b/common/include/sys/elf_core.h
new file mode 100644 (file)
index 0000000..18a18c2
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+ * This file mainly provides a definition of the structures used
+ * to describe the notes section of an ELF file.
+ *
+ * It is the interface between MINIX core dump and GDB
+ */
+
+#ifndef _SYS_ELF_CORE_H_
+#define _SYS_ELF_CORE_H_
+
+#include <sys/param.h>
+#include <machine/stackframe.h>
+
+/* MINIX core file format:
+ *
+ * The core file is in ELF format. Besides the regular program segments,
+ * it has a NOTE segment which contains two NOTE entries
+ * - one containing a minix_elfcore_info_t and the other one containing
+ * the general purpose registers (a stackframe_s structure)
+ */
+
+typedef struct stackframe_s gregset_t; /* General purpose registers */
+
+/*
+ * A lot more things should be added to these structures.  At present,
+ * they contain the absolute bare minimum required to allow GDB to work
+ * with MINIX ELF core dumps.
+ */
+
+#define ELF_NOTE_MINIX_ELFCORE_NAME    "MINIX-CORE"
+#define NT_MINIX_ELFCORE_INFO          1
+#define NT_MINIX_ELFCORE_GREGS         2
+
+#define MINIX_ELFCORE_VERSION          1  /* Current version of minix_elfcore_info_t */
+#define RESERVED_SIZE                   5
+
+typedef struct minix_elfcore_info {
+  /* Version 1 fields */
+  uint32_t     mei_version;            /* Version number of struct */
+  uint32_t     mei_meisize;            /* sizeof(minix_elfcore_info_t) */
+  uint32_t     mei_signo;              /* killing signal */
+  int32_t      mei_pid;                /* Process ID */
+  int8_t        mei_command[MAXCOMLEN]; /* Command */
+  uint32_t      flags;                  /* Flags */
+  int32_t       reserved[RESERVED_SIZE];/* Reserved space*/
+  /* Put below version 2 fields */
+} minix_elfcore_info_t;
+
+#endif /* _SYS_ELF_CORE_H_ */
+
index a96afe3e19f13c01f1657d34fe7aafd8db602b64..9a715f54604380d0b19f75e49c4ebc84f71f10d1 100644 (file)
@@ -70,6 +70,7 @@ __ElfType(Sword);
 __ElfType(Word);
 __ElfType(Ehdr);
 __ElfType(Shdr);
+__ElfType(Nhdr);
 __ElfType(Phdr);
 __ElfType(Dyn);
 __ElfType(Rel);
diff --git a/common/include/sys/procfs.h b/common/include/sys/procfs.h
new file mode 100644 (file)
index 0000000..4ec05d2
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * This file mainly provides a definition of the structures used
+ * to describe the notes section of an ELF file. It doesn't have
+ * anything to do with the /proc file system, even though MINIX
+ * has one.
+ *
+ * The whole purpose of this file is for GDB and GDB only.
+ */
+
+#ifndef _SYS_PROCFS_H_
+#define _SYS_PROCFS_H_
+
+#include <sys/param.h>
+#include <i386/stackframe.h>
+
+/*
+ *
+ * These structures define an interface between core files and the debugger.
+ * Never change or delete any elements. These structures are modeled from
+ * the file with the same name from FreeBSD
+ * 
+ * A lot more things should be added to these structures.  At present,
+ * they contain the absolute bare minimum required to allow GDB to work
+ * with ELF core dumps.
+ */
+
+/*
+ * The parenthsized numbers like (1) indicate the minimum version number
+ * for which each element exists in the structure.
+ */
+
+#define PRSTATUS_VERSION       1       /* Current version of prstatus_t */
+
+typedef struct prstatus {
+    int                pr_version;     /* Version number of struct (1) */
+    size_t     pr_statussz;    /* sizeof(prstatus_t) (1) */
+    size_t     pr_gregsetsz;   /* sizeof(gregset_t) (1) */
+    size_t     pr_fpregsetsz;  /* sizeof(fpregset_t) (1) */
+    int                pr_osreldate;   /* Kernel version (1) */
+    int                pr_cursig;      /* Current signal (1) */
+    pid_t      pr_pid;         /* Process ID (1) */
+    gregset_t  pr_reg;         /* General purpose registers (1) */
+} prstatus_t;
+
+#define PRARGSZ                80      /* Maximum argument bytes saved */
+
+#ifndef MAXCOMLEN
+# define MAXCOMLEN      16      /* Maximum command line arguments */
+#endif
+
+#define PRPSINFO_VERSION       1       /* Current version of prpsinfo_t */
+
+typedef struct prpsinfo {
+    int                pr_version;     /* Version number of struct (1) */
+    size_t     pr_psinfosz;    /* sizeof(prpsinfo_t) (1) */
+    char       pr_fname[MAXCOMLEN+1];  /* Command name, null terminated (1) */
+    char       pr_psargs[PRARGSZ+1];   /* Arguments, null terminated (1) */
+} prpsinfo_t;
+
+#endif /* _SYS_PROCFS_H_ */
+
index c820d190c58ea866dae3de0b6816c813c07c37eb..1803084cf8245e220c6f583ab6d7535c13e07a4f 100644 (file)
@@ -11,6 +11,7 @@ sys/param.h
 #define MAXHOSTNAMELEN  256    /* max hostname size */
 #define NGROUPS                8       /* max number of supplementary groups */
 #define MAXPATHLEN     __MINIX_PATH_MAX
+#define MAXCOMLEN       16      /* max command length */
 
 #include <machine/param.h>
 
index 4d5746af25e739c8436d16c3993d51e090bf6993..02af8846fcceec7127619554670a76b1ed6a6aa2 100644 (file)
@@ -12,7 +12,7 @@ INCS+= ioc_net.h statfs.h
 INCS+= ansi.h atomic.h \
        bitops.h bswap.h \
        cdefs.h cdefs_aout.h cdefs_elf.h ctype_bits.h ctype_inline.h \
-       dirent.h exec_elf.h \
+       dirent.h \
        endian.h errno.h \
        fcntl.h fd_set.h featuretest.h file.h \
        float_ieee754.h gcq.h gmon.h hash.h \
index aa19ab22a2340d06cbcd147222e6190bfd7a9c89..c3d0c7bb292322b6e52e48bb5f3806f83a23e006 100644 (file)
@@ -318,6 +318,11 @@ int dump_core;                     /* flag indicating whether to dump core */
   m.m_type = dump_core ? PM_DUMPCORE : PM_EXIT;
   m.PM_PROC = rmp->mp_endpoint;
 
+  if (dump_core) {
+    m.PM_TERM_SIG = rmp->mp_sigstatus;
+    m.PM_PATH = rmp->mp_name;
+  }
+
   tell_vfs(rmp, &m);
 
   if (rmp->mp_flags & PRIV_PROC)
index a3f08d01a6bb08815d0e800426824272ca9a1955..1dc9057230ccc9079923e6c2177671931449b94b 100644 (file)
@@ -6,7 +6,7 @@ SRCS=   main.c open.c read.c write.c pipe.c dmap.c \
        path.c device.c mount.c link.c exec.c \
        filedes.c stadir.c protect.c time.c \
        lock.c misc.c utility.c select.c table.c \
-       vnode.c vmnt.c request.c fscall.c
+       vnode.c vmnt.c request.c fscall.c elf_core_dump.c
 
 .if ${MKCOVERAGE} != "no"
 SRCS+= gcov.c
diff --git a/servers/vfs/elf_core_dump.c b/servers/vfs/elf_core_dump.c
new file mode 100644 (file)
index 0000000..8f3489f
--- /dev/null
@@ -0,0 +1,317 @@
+#include "fs.h"
+#include <fcntl.h>
+#include <string.h>
+#include "fproc.h"
+#include <minix/vm.h>
+#include <sys/mman.h>
+#include <machine/elf.h>
+#include "param.h"
+
+#include <machine/archtypes.h>
+#include "../../kernel/const.h"
+#include "../../kernel/config.h"
+#include "../../kernel/type.h"
+#include "../../kernel/proc.h"
+
+/* Include ELF headers */
+#include <sys/elf_core.h>
+#include <sys/procfs.h>
+
+FORWARD _PROTOTYPE( void fill_elf_header, (Elf32_Ehdr *elf_header,
+               int phnum)                                                 );
+FORWARD _PROTOTYPE( void fill_prog_header, (Elf32_Phdr *prog_header,
+       Elf32_Word p_type, Elf32_Off p_offset, Elf32_Addr p_vaddr,
+       Elf32_Word p_flags, Elf32_Word p_filesz, Elf32_Word p_memsz)       );
+FORWARD _PROTOTYPE( int get_memory_regions, (Elf32_Phdr phdrs[])           );
+FORWARD _PROTOTYPE( void fill_note_segment_and_entries_hdrs,
+       (Elf32_Phdr phdrs[], Elf32_Nhdr nhdrs[])                              );
+FORWARD _PROTOTYPE( void adjust_offsets, (Elf32_Phdr phdrs[], int phnum)   );
+FORWARD _PROTOTYPE( void dump_elf_header, (Elf32_Ehdr elf_header)          );
+FORWARD _PROTOTYPE( void dump_notes, (Elf32_Nhdr nhdrs[], int csig,
+       char *exe_name)                                                    );
+FORWARD _PROTOTYPE( void dump_segments, (Elf32_Phdr phdrs[], int phnum)    );
+
+/*===========================================================================*
+ *                             write_elf_core_file                          *
+ *===========================================================================*/
+/* First, fill in all the required headers, second, adjust the offsets,
+ * third, dump everything into the core file
+ */
+PUBLIC void write_elf_core_file(int csig, char *exe_name)
+{
+#define MAX_REGIONS 20
+#define NR_NOTE_ENTRIES 2
+  Elf_Ehdr elf_header;
+  Elf_Phdr phdrs[MAX_REGIONS + 1];
+  Elf_Nhdr nhdrs[NR_NOTE_ENTRIES];
+  int phnum;
+
+  /* Fill in the NOTE Program Header - at phdrs[0] - and
+   * note entries' headers
+   */
+  fill_note_segment_and_entries_hdrs(phdrs, nhdrs);
+
+  /* Get the memory segments and fill in the Program headers */
+  phnum = get_memory_regions(phdrs) + 1;
+
+  /* Fill in the ELF header */
+  fill_elf_header(&elf_header, phnum);
+
+  /* Adjust offsets in program headers - The layout in the ELF core file
+   * is the following: the ELF Header, the Note Program Header,
+   * the rest of Program Headers (memory segments), Note contents,
+   * the program segments' contents
+   */
+  adjust_offsets(phdrs, phnum);
+
+  /* Write ELF header */
+  dump_elf_header(elf_header);
+
+  /* Write Program headers (Including the NOTE) */
+  dump_program_headers(phdrs, phnum);
+
+  /* Write NOTE contents */
+  dump_notes(nhdrs, csig, exe_name);
+
+  /* Write segments' contents */
+  dump_segments(phdrs, phnum);
+}
+
+/*===========================================================================*
+ *                             fill_elf_header                              *
+ *===========================================================================*/
+PRIVATE void fill_elf_header (Elf_Ehdr *elf_header, int phnum)
+{
+  memset((void *) elf_header, 0, sizeof(Elf_Ehdr));
+
+  elf_header->e_ident[EI_MAG0] = ELFMAG0;
+  elf_header->e_ident[EI_MAG1] = ELFMAG1;
+  elf_header->e_ident[EI_MAG2] = ELFMAG2;
+  elf_header->e_ident[EI_MAG3] = ELFMAG3;
+  elf_header->e_ident[EI_CLASS] = ELF_TARG_CLASS;
+  elf_header->e_ident[EI_DATA] = ELF_TARG_DATA;
+  elf_header->e_ident[EI_VERSION] = EV_CURRENT;
+  elf_header->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
+  elf_header->e_type = ET_CORE;
+  elf_header->e_machine = ELF_TARG_MACH;
+  elf_header->e_version = EV_CURRENT;
+  elf_header->e_ehsize = sizeof(Elf_Ehdr);
+  elf_header->e_phoff = sizeof(Elf_Ehdr);
+  elf_header->e_phentsize = sizeof(Elf_Phdr);
+  elf_header->e_phnum = phnum;
+}
+
+/*===========================================================================*
+ *                             fill_prog_header                             *
+ *===========================================================================*/
+PRIVATE void fill_prog_header (Elf_Phdr *prog_header, Elf_Word p_type,
+       Elf_Off p_offset, Elf_Addr p_vaddr, Elf_Word p_flags,
+       Elf_Word p_filesz, Elf_Word p_memsz)
+{
+
+  memset((void *) prog_header, 0, sizeof(Elf_Phdr));
+
+  prog_header->p_type = p_type;
+  prog_header->p_offset = p_offset;
+  prog_header->p_vaddr = p_vaddr;
+  prog_header->p_flags = p_flags;
+  prog_header->p_filesz = p_filesz;
+  prog_header->p_memsz = p_memsz;
+
+}
+
+#define PADBYTES    4
+#define PAD_LEN(x)  ((x + (PADBYTES - 1)) & ~(PADBYTES - 1))
+
+/*===========================================================================*
+ *                     fill_note_segment_and_entries_hdrs                   *
+ *===========================================================================*/
+PRIVATE void fill_note_segment_and_entries_hdrs(Elf_Phdr phdrs[],
+                               Elf_Nhdr nhdrs[])
+{
+  int filesize;
+  const char *note_name = ELF_NOTE_MINIX_ELFCORE_NAME "\0";
+  int name_len, mei_len, gregs_len;
+
+  /* Size of notes in the core file is rather fixed:
+   * sizeof(minix_elfcore_info_t) +
+   * 2 * sizeof(Elf_Nhdr) + the size of the padded name of the note
+   * - i.e. "MINIX-CORE\0" padded to 4-byte alignment => 2 * 8 bytes
+   */
+
+  name_len = strlen(note_name) + 1;
+  mei_len = sizeof(minix_elfcore_info_t);
+  gregs_len = sizeof(gregset_t);
+
+  /* Make sure to also count the padding bytes */
+  filesize = PAD_LEN(mei_len) + PAD_LEN(gregs_len) +
+       2 * sizeof(Elf_Nhdr) + 2 * PAD_LEN(name_len);
+  fill_prog_header(&phdrs[0], PT_NOTE, 0, 0, PF_R, filesize, 0);
+
+  /* First note entry header */
+  nhdrs[0].n_namesz = name_len;
+  nhdrs[0].n_descsz = sizeof(minix_elfcore_info_t);
+  nhdrs[0].n_type = NT_MINIX_ELFCORE_INFO;
+
+  /* Second note entry header */
+  nhdrs[1].n_namesz = name_len;
+  nhdrs[1].n_descsz = sizeof(gregset_t);
+  nhdrs[1].n_type = NT_MINIX_ELFCORE_GREGS;
+}
+
+/*===========================================================================*
+ *                             adjust_offset                                *
+ *===========================================================================*/
+PRIVATE void adjust_offsets(Elf_Phdr phdrs[], int phnum)
+{
+  int i;
+  long offset = sizeof(Elf_Ehdr) + phnum * sizeof(Elf_Phdr);
+
+  for (i = 0; i < phnum; i++) {
+       phdrs[i].p_offset = offset;
+       offset += phdrs[i].p_filesz;
+  }
+}
+
+/*===========================================================================*
+ *                             write_buf                                    *
+ *===========================================================================*/
+PRIVATE void write_buf(char *buf, int size)
+{
+  m_in.buffer = buf;
+  m_in.nbytes = size;
+  read_write(WRITING);
+}
+
+/*===========================================================================*
+ *                             get_memory_regions                           *
+ *===========================================================================*/
+/* The same as dump_regions from procfs/pid.c */
+PRIVATE int get_memory_regions(Elf_Phdr phdrs[])
+{
+  /* Print the virtual memory regions of a process. */
+  struct vm_region_info vri[MAX_VRI_COUNT];
+  vir_bytes next;
+  int i, r, count;
+  Elf_Word pflags;
+
+  count = 0;
+  next = 0;
+
+  do {
+       r = vm_info_region(fp->fp_endpoint, vri, MAX_VRI_COUNT,
+                       &next);
+       if (r < 0) return r;
+       if (r == 0) break;
+
+       for (i = 0; i < r; i++) {
+
+               pflags = (vri[i].vri_prot & PROT_READ ? PF_R : 0)
+                       | (vri[i].vri_prot & PROT_WRITE ? PF_W : 0)
+                       | (vri[i].vri_prot & PROT_EXEC ? PF_X : 0);
+
+               fill_prog_header (&phdrs[count + 1], PT_LOAD,
+                               0, vri[i].vri_addr, pflags,
+                               vri[i].vri_length, vri[i].vri_length);
+               count++;
+
+               if (count >= MAX_REGIONS) {
+                       printf("VFS: get_memory_regions Warning: "
+                               "Program has too many regions\n");
+                       return count;
+               }
+       }
+  } while (r == MAX_VRI_COUNT);
+
+  return count;
+}
+
+/*===========================================================================*
+ *                             dump_notes                                   *
+ *===========================================================================*/
+PRIVATE void dump_notes(Elf_Nhdr nhdrs[], int csig, char *exe_name)
+{
+  char *note_name = ELF_NOTE_MINIX_ELFCORE_NAME "\0";
+  char pad[4];
+  minix_elfcore_info_t mei;
+  int mei_len = sizeof(minix_elfcore_info_t);
+  int gregs_len = sizeof(gregset_t);
+  struct proc p;
+  char proc_name[PROC_NAME_LEN];
+
+  /* Get process's name */
+  if (sys_datacopy(PM_PROC_NR, (vir_bytes) exe_name,
+               VFS_PROC_NR, (vir_bytes) proc_name, PROC_NAME_LEN) != OK)
+       printf("VFS: Cannot get porcess's name\n");
+
+  /* Dump first note entry */
+  mei.mei_version = MINIX_ELFCORE_VERSION;
+  mei.mei_meisize = mei_len;
+  mei.mei_signo = csig;
+  mei.mei_pid = fp->fp_pid;
+  memcpy(mei.mei_command, proc_name, sizeof(mei.mei_command));
+
+  write_buf((char *)&nhdrs[0], sizeof(Elf_Nhdr));
+  write_buf(note_name, nhdrs[0].n_namesz);
+  write_buf(pad, PAD_LEN(nhdrs[0].n_namesz) - nhdrs[0].n_namesz);
+  write_buf((char *)&mei, mei_len);
+  write_buf(pad, PAD_LEN(mei_len) - mei_len);
+
+  /* XXX: Other way to read registries ? */
+  /* Get registers */
+  if (sys_getproc(&p, fp->fp_endpoint) != OK)
+       printf("VFS: Could not read registers\n");
+
+  /* Dump second note entry - the general registers */
+  write_buf((char *)&nhdrs[1], sizeof(Elf_Nhdr));
+  write_buf(note_name, nhdrs[1].n_namesz);
+  write_buf(pad, PAD_LEN(nhdrs[1].n_namesz) - nhdrs[1].n_namesz);
+  write_buf((char *)&(p.p_reg), gregs_len);
+  write_buf(pad, PAD_LEN(gregs_len) - gregs_len);
+}
+
+/*===========================================================================*
+ *                             dump_elf_header                              *
+ *===========================================================================*/
+PRIVATE void dump_elf_header(Elf_Ehdr elf_header)
+{
+  write_buf((char *)&elf_header, sizeof(Elf_Ehdr));
+}
+
+/*===========================================================================*
+ *                       dump_program_headers                               *
+ *===========================================================================*/
+PRIVATE void dump_program_headers(Elf_Phdr phdrs[], int phnum)
+{
+  int i;
+
+  for (i = 0; i < phnum; i++)
+       write_buf((char *)&phdrs[i], sizeof(Elf_Phdr));
+}
+
+/*===========================================================================*
+ *                           dump_segments                                  *
+ *===========================================================================*/
+PRIVATE void dump_segments(Elf_Phdr phdrs[], int phnum)
+{
+  int i;
+  vir_bytes len;
+  off_t off, seg_off;
+  int r;
+  static u8_t buf[CLICK_SIZE];
+
+  for (i = 1; i < phnum; i++) {
+       len = phdrs[i].p_memsz;
+       seg_off = phdrs[i].p_vaddr;
+
+       for (off = 0; off < len; off += CLICK_SIZE) {
+               r = sys_vircopy(fp->fp_endpoint, D,
+                       (vir_bytes) (seg_off + off),
+                       SELF, D, (vir_bytes) buf,
+                       (phys_bytes) CLICK_SIZE);
+
+               write_buf((char *)buf, (off + CLICK_SIZE <= len) ?
+                                       CLICK_SIZE : (len - off));
+       }
+  }
+}
index 55447a954b2bbbafb9cf36692719b9ec20378357..06b7536f566a52e47ce79f6134e352ec38fdac76 100644 (file)
@@ -553,8 +553,7 @@ PRIVATE void service_pm()
        break;
 
   case PM_DUMPCORE:
-       r = pm_dumpcore(m_in.PM_PROC,
-               NULL /* (struct mem_map *) m_in.PM_SEGPTR */);
+       r = pm_dumpcore(m_in.PM_PROC, m_in.PM_TERM_SIG, m_in.PM_PATH);
 
        /* Reply status to PM */
        m_out.m_type = PM_CORE_REPLY;
index cd07878029e6fb7e3f629a6b3fcafca01fd49d37..b41fc0d281be273001b08ae4e7332b5eefa9f4b4 100644 (file)
@@ -575,17 +575,41 @@ PUBLIC int do_svrctl()
 /*===========================================================================*
  *                             pm_dumpcore                                  *
  *===========================================================================*/
-PUBLIC int pm_dumpcore(proc_e, seg_ptr)
+PUBLIC int pm_dumpcore(proc_e, csig, exe_name)
 int proc_e;
-struct mem_map *seg_ptr;
+int csig;
+char *exe_name;
 {
-       int proc_s;
+  int proc_s, r, old_who_e;
        
-       /* Terminate the process */
-       okendpt(proc_e, &proc_s);
-       free_proc(&fproc[proc_s], FP_EXITING);
-        
-       return OK;
+  okendpt(proc_e, &proc_s);
+  fp = &fproc[proc_s];
+
+  /* Open the core file */
+  sprintf(user_fullpath, "%s.%d", CORE_NAME, fproc[proc_s].fp_pid);
+  r = common_open(O_WRONLY | O_CREAT | O_TRUNC, CORE_MODE);
+  if (r < 0) {
+       printf("VFS: Cannot open file to dump core\n");
+       return r;
+  }
+
+  old_who_e = who_e;
+  who_e = VFS_PROC_NR;
+
+  /* Write the core file in ELF format */
+  write_elf_core_file(csig, exe_name);
+
+  /* Close file */
+  close_fd(fp, r);
+
+  /* Terminate the process */
+  free_proc(&fproc[proc_s], FP_EXITING);
+
+  /* Restore the important variables that have been overwritten */
+  m_in.PM_PROC = proc_e;
+  who_e = old_who_e;
+
+  return OK;
 }
 
 /*===========================================================================*
index ae116b252ec0184df7a9333e01c9957df1430fca..d62e5bf4ef3d6e4b03cf5c23f83bf3122dce8a62 100644 (file)
@@ -30,7 +30,6 @@
 
 PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
 
-FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode)                );
 FORWARD _PROTOTYPE( struct vnode *new_node, (int oflags, mode_t bits)          );
 FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags));
 
@@ -75,7 +74,7 @@ PUBLIC int do_open()
 /*===========================================================================*
  *                             common_open                                  *
  *===========================================================================*/
-PRIVATE int common_open(register int oflags, mode_t omode)
+PUBLIC int common_open(register int oflags, mode_t omode)
 {
 /* Common code from do_creat and do_open. */
   int b, r, exist = TRUE;
index e54810f1282bee8d64b6662686d3d8e49c8b816d..db95f0020bbe2235586edf48375353058351a5e5 100644 (file)
@@ -104,7 +104,7 @@ _PROTOTYPE( int do_fsync, (void)                                    );
 _PROTOTYPE( void pm_reboot, (void)                                     );
 _PROTOTYPE( int do_svrctl, (void)                                      );
 _PROTOTYPE( int do_getsysinfo, (void)                                  );
-_PROTOTYPE( int pm_dumpcore, (int proc_e, struct mem_map *seg_ptr)     );
+_PROTOTYPE( int pm_dumpcore, (int proc_e, int sig, char *exe_name)      );
 _PROTOTYPE( void ds_event, (void)                                      );
 
 /* mount.c */
@@ -123,6 +123,7 @@ _PROTOTYPE( int do_llseek, (void)                                   );
 _PROTOTYPE( int do_mknod, (void)                                       );
 _PROTOTYPE( int do_mkdir, (void)                                       );
 _PROTOTYPE( int do_open, (void)                                                );
+_PROTOTYPE( int common_open, (register int oflags, mode_t omode)       );
 _PROTOTYPE( int do_slink, (void)                                        );
 _PROTOTYPE( int do_vm_open, (void)                                     );
 _PROTOTYPE( int do_vm_close, (void)                                    );
@@ -295,3 +296,6 @@ _PROTOTYPE( void select_reply1, (endpoint_t driver_e, int minor, int status));
 _PROTOTYPE( void select_reply2, (endpoint_t driver_e, int minor, int status));
 _PROTOTYPE( void select_timeout_check, (timer_t *)                     );
 _PROTOTYPE( void select_unsuspend_by_endpt, (endpoint_t proc)          );
+
+/* elf_core_dump.c */
+_PROTOTYPE( void write_elf_core_file, (int csig, char *exe_name)       );