ELF core files
This commit is contained in:
parent
ebdac755af
commit
eaa29370f4
17 changed files with 544 additions and 17 deletions
|
@ -4,5 +4,5 @@
|
||||||
INCS+= archtypes.h bios.h cmos.h cpu.h diskparm.h fpu.h int86.h \
|
INCS+= archtypes.h bios.h cmos.h cpu.h diskparm.h fpu.h int86.h \
|
||||||
interrupt.h memory.h multiboot.h partition.h \
|
interrupt.h memory.h multiboot.h partition.h \
|
||||||
pci.h pci_amd.h pci_intel.h pci_sis.h pci_via.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
|
||||||
|
|
||||||
|
|
63
common/include/arch/i386/elf_machdep.h
Normal file
63
common/include/arch/i386/elf_machdep.h
Normal file
|
@ -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)
|
|
@ -792,6 +792,9 @@
|
||||||
# define PM_PPROC m1_i2 /* parent process endpoint */
|
# define PM_PPROC m1_i2 /* parent process endpoint */
|
||||||
# define PM_CPID m1_i3 /* child pid */
|
# 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 */
|
/* Parameters for the EXEC_NEWMEM call */
|
||||||
#define EXC_NM_PROC m1_i1 /* process that needs new map */
|
#define EXC_NM_PROC m1_i1 /* process that needs new map */
|
||||||
#define EXC_NM_PTR m1_p1 /* parameters in struct exec_newmem */
|
#define EXC_NM_PTR m1_p1 /* parameters in struct exec_newmem */
|
||||||
|
|
|
@ -5,5 +5,5 @@
|
||||||
INCS+= elf32.h elf64.h elf_common.h elf_generic.h \
|
INCS+= elf32.h elf64.h elf_common.h elf_generic.h \
|
||||||
ioc_file.h ioc_tape.h ioc_disk.h \
|
ioc_file.h ioc_tape.h ioc_disk.h \
|
||||||
ioc_memory.h ioc_sound.h ioc_tty.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
|
||||||
|
|
||||||
|
|
50
common/include/sys/elf_core.h
Normal file
50
common/include/sys/elf_core.h
Normal file
|
@ -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_ */
|
||||||
|
|
|
@ -70,6 +70,7 @@ __ElfType(Sword);
|
||||||
__ElfType(Word);
|
__ElfType(Word);
|
||||||
__ElfType(Ehdr);
|
__ElfType(Ehdr);
|
||||||
__ElfType(Shdr);
|
__ElfType(Shdr);
|
||||||
|
__ElfType(Nhdr);
|
||||||
__ElfType(Phdr);
|
__ElfType(Phdr);
|
||||||
__ElfType(Dyn);
|
__ElfType(Dyn);
|
||||||
__ElfType(Rel);
|
__ElfType(Rel);
|
||||||
|
|
61
common/include/sys/procfs.h
Normal file
61
common/include/sys/procfs.h
Normal file
|
@ -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_ */
|
||||||
|
|
|
@ -11,6 +11,7 @@ sys/param.h
|
||||||
#define MAXHOSTNAMELEN 256 /* max hostname size */
|
#define MAXHOSTNAMELEN 256 /* max hostname size */
|
||||||
#define NGROUPS 8 /* max number of supplementary groups */
|
#define NGROUPS 8 /* max number of supplementary groups */
|
||||||
#define MAXPATHLEN __MINIX_PATH_MAX
|
#define MAXPATHLEN __MINIX_PATH_MAX
|
||||||
|
#define MAXCOMLEN 16 /* max command length */
|
||||||
|
|
||||||
#include <machine/param.h>
|
#include <machine/param.h>
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,7 @@ INCS+= ioc_net.h statfs.h
|
||||||
INCS+= ansi.h atomic.h \
|
INCS+= ansi.h atomic.h \
|
||||||
bitops.h bswap.h \
|
bitops.h bswap.h \
|
||||||
cdefs.h cdefs_aout.h cdefs_elf.h ctype_bits.h ctype_inline.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 \
|
endian.h errno.h \
|
||||||
fcntl.h fd_set.h featuretest.h file.h \
|
fcntl.h fd_set.h featuretest.h file.h \
|
||||||
float_ieee754.h gcq.h gmon.h hash.h \
|
float_ieee754.h gcq.h gmon.h hash.h \
|
||||||
|
|
|
@ -318,6 +318,11 @@ int dump_core; /* flag indicating whether to dump core */
|
||||||
m.m_type = dump_core ? PM_DUMPCORE : PM_EXIT;
|
m.m_type = dump_core ? PM_DUMPCORE : PM_EXIT;
|
||||||
m.PM_PROC = rmp->mp_endpoint;
|
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);
|
tell_vfs(rmp, &m);
|
||||||
|
|
||||||
if (rmp->mp_flags & PRIV_PROC)
|
if (rmp->mp_flags & PRIV_PROC)
|
||||||
|
|
|
@ -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 \
|
path.c device.c mount.c link.c exec.c \
|
||||||
filedes.c stadir.c protect.c time.c \
|
filedes.c stadir.c protect.c time.c \
|
||||||
lock.c misc.c utility.c select.c table.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"
|
.if ${MKCOVERAGE} != "no"
|
||||||
SRCS+= gcov.c
|
SRCS+= gcov.c
|
||||||
|
|
317
servers/vfs/elf_core_dump.c
Normal file
317
servers/vfs/elf_core_dump.c
Normal file
|
@ -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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -553,8 +553,7 @@ PRIVATE void service_pm()
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case PM_DUMPCORE:
|
case PM_DUMPCORE:
|
||||||
r = pm_dumpcore(m_in.PM_PROC,
|
r = pm_dumpcore(m_in.PM_PROC, m_in.PM_TERM_SIG, m_in.PM_PATH);
|
||||||
NULL /* (struct mem_map *) m_in.PM_SEGPTR */);
|
|
||||||
|
|
||||||
/* Reply status to PM */
|
/* Reply status to PM */
|
||||||
m_out.m_type = PM_CORE_REPLY;
|
m_out.m_type = PM_CORE_REPLY;
|
||||||
|
|
|
@ -575,17 +575,41 @@ PUBLIC int do_svrctl()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* pm_dumpcore *
|
* pm_dumpcore *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC int pm_dumpcore(proc_e, seg_ptr)
|
PUBLIC int pm_dumpcore(proc_e, csig, exe_name)
|
||||||
int proc_e;
|
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);
|
||||||
okendpt(proc_e, &proc_s);
|
fp = &fproc[proc_s];
|
||||||
free_proc(&fproc[proc_s], FP_EXITING);
|
|
||||||
|
/* Open the core file */
|
||||||
return OK;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
|
|
||||||
PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
|
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( struct vnode *new_node, (int oflags, mode_t bits) );
|
||||||
FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags));
|
FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags));
|
||||||
|
|
||||||
|
@ -75,7 +74,7 @@ PUBLIC int do_open()
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* common_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. */
|
/* Common code from do_creat and do_open. */
|
||||||
int b, r, exist = TRUE;
|
int b, r, exist = TRUE;
|
||||||
|
|
|
@ -104,7 +104,7 @@ _PROTOTYPE( int do_fsync, (void) );
|
||||||
_PROTOTYPE( void pm_reboot, (void) );
|
_PROTOTYPE( void pm_reboot, (void) );
|
||||||
_PROTOTYPE( int do_svrctl, (void) );
|
_PROTOTYPE( int do_svrctl, (void) );
|
||||||
_PROTOTYPE( int do_getsysinfo, (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) );
|
_PROTOTYPE( void ds_event, (void) );
|
||||||
|
|
||||||
/* mount.c */
|
/* mount.c */
|
||||||
|
@ -123,6 +123,7 @@ _PROTOTYPE( int do_llseek, (void) );
|
||||||
_PROTOTYPE( int do_mknod, (void) );
|
_PROTOTYPE( int do_mknod, (void) );
|
||||||
_PROTOTYPE( int do_mkdir, (void) );
|
_PROTOTYPE( int do_mkdir, (void) );
|
||||||
_PROTOTYPE( int do_open, (void) );
|
_PROTOTYPE( int do_open, (void) );
|
||||||
|
_PROTOTYPE( int common_open, (register int oflags, mode_t omode) );
|
||||||
_PROTOTYPE( int do_slink, (void) );
|
_PROTOTYPE( int do_slink, (void) );
|
||||||
_PROTOTYPE( int do_vm_open, (void) );
|
_PROTOTYPE( int do_vm_open, (void) );
|
||||||
_PROTOTYPE( int do_vm_close, (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_reply2, (endpoint_t driver_e, int minor, int status));
|
||||||
_PROTOTYPE( void select_timeout_check, (timer_t *) );
|
_PROTOTYPE( void select_timeout_check, (timer_t *) );
|
||||||
_PROTOTYPE( void select_unsuspend_by_endpt, (endpoint_t proc) );
|
_PROTOTYPE( void select_unsuspend_by_endpt, (endpoint_t proc) );
|
||||||
|
|
||||||
|
/* elf_core_dump.c */
|
||||||
|
_PROTOTYPE( void write_elf_core_file, (int csig, char *exe_name) );
|
||||||
|
|
Loading…
Reference in a new issue