From eaa29370f4fd4dcd94a1d159c385e6b530f2d26c Mon Sep 17 00:00:00 2001 From: Adriana Szekeres Date: Sat, 30 Jul 2011 06:03:23 +0000 Subject: [PATCH] ELF core files --- common/include/arch/i386/Makefile.inc | 2 +- common/include/arch/i386/elf_machdep.h | 63 ++++ common/include/minix/com.h | 3 + common/include/sys/Makefile.inc | 2 +- common/include/sys/elf_core.h | 50 +++ common/include/sys/elf_generic.h | 1 + .../include}/sys/exec_elf.h | 0 common/include/sys/procfs.h | 61 ++++ include/sys/param.h | 1 + nbsd_include/sys/Makefile | 2 +- servers/pm/forkexit.c | 5 + servers/vfs/Makefile | 2 +- servers/vfs/elf_core_dump.c | 317 ++++++++++++++++++ servers/vfs/main.c | 3 +- servers/vfs/misc.c | 40 ++- servers/vfs/open.c | 3 +- servers/vfs/proto.h | 6 +- 17 files changed, 544 insertions(+), 17 deletions(-) create mode 100644 common/include/arch/i386/elf_machdep.h create mode 100644 common/include/sys/elf_core.h rename {nbsd_include => common/include}/sys/exec_elf.h (100%) create mode 100644 common/include/sys/procfs.h create mode 100644 servers/vfs/elf_core_dump.c diff --git a/common/include/arch/i386/Makefile.inc b/common/include/arch/i386/Makefile.inc index bc6e15d55..be3cd8728 100644 --- a/common/include/arch/i386/Makefile.inc +++ b/common/include/arch/i386/Makefile.inc @@ -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 index 000000000..442c561a9 --- /dev/null +++ b/common/include/arch/i386/elf_machdep.h @@ -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) diff --git a/common/include/minix/com.h b/common/include/minix/com.h index 3bfe6d87c..b82433f42 100644 --- a/common/include/minix/com.h +++ b/common/include/minix/com.h @@ -792,6 +792,9 @@ # 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 */ diff --git a/common/include/sys/Makefile.inc b/common/include/sys/Makefile.inc index 2f5a5ecf8..f8e4c932b 100644 --- a/common/include/sys/Makefile.inc +++ b/common/include/sys/Makefile.inc @@ -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 index 000000000..18a18c2cd --- /dev/null +++ b/common/include/sys/elf_core.h @@ -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 +#include + +/* 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_ */ + diff --git a/common/include/sys/elf_generic.h b/common/include/sys/elf_generic.h index a96afe3e1..9a715f546 100644 --- a/common/include/sys/elf_generic.h +++ b/common/include/sys/elf_generic.h @@ -70,6 +70,7 @@ __ElfType(Sword); __ElfType(Word); __ElfType(Ehdr); __ElfType(Shdr); +__ElfType(Nhdr); __ElfType(Phdr); __ElfType(Dyn); __ElfType(Rel); diff --git a/nbsd_include/sys/exec_elf.h b/common/include/sys/exec_elf.h similarity index 100% rename from nbsd_include/sys/exec_elf.h rename to common/include/sys/exec_elf.h diff --git a/common/include/sys/procfs.h b/common/include/sys/procfs.h new file mode 100644 index 000000000..4ec05d2fd --- /dev/null +++ b/common/include/sys/procfs.h @@ -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 +#include + +/* + * + * 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_ */ + diff --git a/include/sys/param.h b/include/sys/param.h index c820d190c..1803084cf 100644 --- a/include/sys/param.h +++ b/include/sys/param.h @@ -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 diff --git a/nbsd_include/sys/Makefile b/nbsd_include/sys/Makefile index 4d5746af2..02af8846f 100644 --- a/nbsd_include/sys/Makefile +++ b/nbsd_include/sys/Makefile @@ -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 \ diff --git a/servers/pm/forkexit.c b/servers/pm/forkexit.c index aa19ab22a..c3d0c7bb2 100644 --- a/servers/pm/forkexit.c +++ b/servers/pm/forkexit.c @@ -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) diff --git a/servers/vfs/Makefile b/servers/vfs/Makefile index a3f08d01a..1dc905723 100644 --- a/servers/vfs/Makefile +++ b/servers/vfs/Makefile @@ -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 index 000000000..8f3489f7f --- /dev/null +++ b/servers/vfs/elf_core_dump.c @@ -0,0 +1,317 @@ +#include "fs.h" +#include +#include +#include "fproc.h" +#include +#include +#include +#include "param.h" + +#include +#include "../../kernel/const.h" +#include "../../kernel/config.h" +#include "../../kernel/type.h" +#include "../../kernel/proc.h" + +/* Include ELF headers */ +#include +#include + +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)); + } + } +} diff --git a/servers/vfs/main.c b/servers/vfs/main.c index 55447a954..06b7536f5 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -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; diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index cd0787802..b41fc0d28 100644 --- a/servers/vfs/misc.c +++ b/servers/vfs/misc.c @@ -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; } /*===========================================================================* diff --git a/servers/vfs/open.c b/servers/vfs/open.c index ae116b252..d62e5bf4e 100644 --- a/servers/vfs/open.c +++ b/servers/vfs/open.c @@ -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; diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index e54810f12..db95f0020 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -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) ); -- 2.44.0