Provide core dumping support for AVFS
This commit is contained in:
parent
5acd97c7e0
commit
0a61519eea
12 changed files with 457 additions and 96 deletions
|
@ -7,7 +7,7 @@ SRCS= main.c open.c read.c write.c pipe.c dmap.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 \
|
||||
tll.c comm.c worker.c
|
||||
tll.c comm.c worker.c coredump.c
|
||||
|
||||
.if ${MKCOVERAGE} != "no"
|
||||
SRCS+= gcov.c
|
||||
|
|
309
servers/avfs/coredump.c
Normal file
309
servers/avfs/coredump.c
Normal file
|
@ -0,0 +1,309 @@
|
|||
#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 ELF headers */
|
||||
#include <sys/elf_core.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, (struct filp *f,
|
||||
Elf32_Ehdr elf_header) );
|
||||
FORWARD _PROTOTYPE( void dump_notes, (struct filp *f, Elf32_Nhdr nhdrs[],
|
||||
int csig, char *proc_name) );
|
||||
FORWARD _PROTOTYPE( void dump_program_headers, (struct filp *f,
|
||||
Elf_Phdr phdrs[], int phnum));
|
||||
FORWARD _PROTOTYPE( void dump_segments, (struct filp *f, Elf32_Phdr phdrs[],
|
||||
int phnum) );
|
||||
FORWARD _PROTOTYPE( void write_buf, (struct filp *f, char *buf, size_t size));
|
||||
|
||||
/*===========================================================================*
|
||||
* write_elf_core_file *
|
||||
*===========================================================================*/
|
||||
PUBLIC void write_elf_core_file(struct filp *f, int csig, char *proc_name)
|
||||
{
|
||||
/* First, fill in all the required headers, second, adjust the offsets,
|
||||
* third, dump everything into the core file
|
||||
*/
|
||||
#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(f, elf_header);
|
||||
|
||||
/* Write Program headers (Including the NOTE) */
|
||||
dump_program_headers(f, phdrs, phnum);
|
||||
|
||||
/* Write NOTE contents */
|
||||
dump_notes(f, nhdrs, csig, proc_name);
|
||||
|
||||
/* Write segments' contents */
|
||||
dump_segments(f, 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(struct filp *f, char *buf, size_t size)
|
||||
{
|
||||
read_write(WRITING, f, buf, size, VFS_PROC_NR);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* get_memory_regions *
|
||||
*===========================================================================*/
|
||||
PRIVATE int get_memory_regions(Elf_Phdr phdrs[])
|
||||
{
|
||||
/* Print the virtual memory regions of a process. */
|
||||
|
||||
/* The same as dump_regions from procfs/pid.c */
|
||||
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(struct filp *f, Elf_Nhdr nhdrs[], int csig,
|
||||
char *proc_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 stackframe_s regs;
|
||||
|
||||
/* 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(f, (char *) &nhdrs[0], sizeof(Elf_Nhdr));
|
||||
write_buf(f, note_name, nhdrs[0].n_namesz);
|
||||
write_buf(f, pad, PAD_LEN(nhdrs[0].n_namesz) - nhdrs[0].n_namesz);
|
||||
write_buf(f, (char *) &mei, mei_len);
|
||||
write_buf(f, pad, PAD_LEN(mei_len) - mei_len);
|
||||
|
||||
/* Get registers */
|
||||
if (sys_getregs(®s, fp->fp_endpoint) != OK)
|
||||
printf("VFS: Could not read registers\n");
|
||||
|
||||
if (sizeof(regs) != gregs_len)
|
||||
printf("VFS: Wrong core register structure size\n");
|
||||
|
||||
/* Dump second note entry - the general registers */
|
||||
write_buf(f, (char *) &nhdrs[1], sizeof(Elf_Nhdr));
|
||||
|
||||
write_buf(f, note_name, nhdrs[1].n_namesz);
|
||||
write_buf(f, pad, PAD_LEN(nhdrs[1].n_namesz) - nhdrs[1].n_namesz);
|
||||
write_buf(f, (char *) ®s, gregs_len);
|
||||
write_buf(f, pad, PAD_LEN(gregs_len) - gregs_len);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* dump_elf_header *
|
||||
*===========================================================================*/
|
||||
PRIVATE void dump_elf_header(struct filp *f, Elf_Ehdr elf_header)
|
||||
{
|
||||
write_buf(f, (char *) &elf_header, sizeof(Elf_Ehdr));
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* dump_program_headers *
|
||||
*===========================================================================*/
|
||||
PRIVATE void dump_program_headers(struct filp *f, Elf_Phdr phdrs[], int phnum)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < phnum; i++)
|
||||
write_buf(f, (char *) &phdrs[i], sizeof(Elf_Phdr));
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* dump_segments *
|
||||
*===========================================================================*/
|
||||
PRIVATE void dump_segments(struct filp *f, 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(f, (char *) buf, (off + CLICK_SIZE <= len) ?
|
||||
CLICK_SIZE : (len - off));
|
||||
}
|
||||
}
|
||||
}
|
|
@ -983,8 +983,8 @@ PUBLIC void cdev_up(int maj)
|
|||
if(rfp->fp_blocked_on != FP_BLOCKED_ON_DOPEN) continue;
|
||||
|
||||
printf("VFS: dev_up: found process in FP_BLOCKED_ON_DOPEN, fd %d\n",
|
||||
rfp->fp_block_fd);
|
||||
fd_nr = rfp->fp_block_fd;
|
||||
rfp->fp_blocked.fd_nr);
|
||||
fd_nr = rfp->fp_blocked.fd_nr;
|
||||
rfilp = rfp->fp_filp[fd_nr];
|
||||
vp = rfilp->filp_vno;
|
||||
if (!vp) panic("VFS: restart_reopen: no vp");
|
||||
|
@ -1090,9 +1090,9 @@ int maj;
|
|||
if (rfp->fp_blocked_on == FP_BLOCKED_ON_DOPEN ||
|
||||
!(rfp->fp_flags & FP_SUSP_REOPEN)) continue;
|
||||
|
||||
printf("VFS: restart_reopen: found process in FP_BLOCKED_ON_DOPEN, fd %d\n",
|
||||
rfp->fp_block_fd);
|
||||
fd_nr = rfp->fp_block_fd;
|
||||
fd_nr = rfp->fp_blocked.fd_nr;
|
||||
printf("VFS: restart_reopen: process in FP_BLOCKED_ON_DOPEN fd=%d\n",
|
||||
fd_nr);
|
||||
rfilp = rfp->fp_filp[fd_nr];
|
||||
|
||||
if (!rfilp) {
|
||||
|
|
|
@ -25,13 +25,16 @@ EXTERN struct fproc {
|
|||
fd_set fp_cloexec_set; /* bit map for POSIX Table 6-2 FD_CLOEXEC */
|
||||
|
||||
dev_t fp_tty; /* major/minor of controlling tty */
|
||||
int fp_block_fd; /* place to save fd if rd/wr can't finish */
|
||||
int fp_blocked_on; /* what is it blocked on */
|
||||
int fp_block_callnr; /* blocked call if rd/wr can't finish */
|
||||
union blocked {
|
||||
int fd_nr; /* place to save fd if rd/wr can't finish */
|
||||
struct filp *bfilp; /* place to save filp if rd/wr can't finish */
|
||||
} fp_blocked;
|
||||
char *fp_buffer; /* place to save buffer if rd/wr can't finish*/
|
||||
int fp_nbytes; /* place to save bytes if rd/wr can't finish */
|
||||
int fp_cum_io_partial; /* partial byte count if rd/wr can't finish */
|
||||
endpoint_t fp_task; /* which task is proc suspended on */
|
||||
int fp_blocked_on; /* what is it blocked on */
|
||||
endpoint_t fp_ioproc; /* proc no. in suspended-on i/o message */
|
||||
|
||||
cp_grant_id_t fp_grant; /* revoke this grant on unsuspend if > -1 */
|
||||
|
|
|
@ -337,9 +337,9 @@ PRIVATE void *do_pm(void *arg)
|
|||
*===========================================================================*/
|
||||
PRIVATE void *do_pending_pipe(void *arg)
|
||||
{
|
||||
int r, fd_nr;
|
||||
struct filp *f;
|
||||
int r, op;
|
||||
struct job my_job;
|
||||
struct filp *f;
|
||||
tll_access_t locktype;
|
||||
|
||||
my_job = *((struct job *) arg);
|
||||
|
@ -348,13 +348,15 @@ PRIVATE void *do_pending_pipe(void *arg)
|
|||
|
||||
lock_proc(fp, 1 /* force lock */);
|
||||
|
||||
fd_nr = fp->fp_block_fd;
|
||||
locktype = (call_nr == READ) ? VNODE_READ : VNODE_WRITE;
|
||||
f = get_filp(fd_nr, locktype);
|
||||
f = fp->fp_blocked.bfilp;
|
||||
assert(f != NULL);
|
||||
fp->fp_blocked.bfilp = NULL;
|
||||
|
||||
r = rw_pipe((call_nr == READ) ? READING : WRITING, who_e, fd_nr, f,
|
||||
fp->fp_buffer, fp->fp_nbytes);
|
||||
locktype = (call_nr == READ) ? VNODE_READ : VNODE_WRITE;
|
||||
op = (call_nr == READ) ? READING : WRITING;
|
||||
lock_filp(f, locktype);
|
||||
|
||||
r = rw_pipe(op, who_e, f, fp->fp_buffer, fp->fp_nbytes);
|
||||
|
||||
if (r != SUSPEND) /* Do we have results to report? */
|
||||
reply(who_e, r);
|
||||
|
@ -391,9 +393,8 @@ PUBLIC void *do_dummy(void *arg)
|
|||
*===========================================================================*/
|
||||
PRIVATE void *do_work(void *arg)
|
||||
{
|
||||
int error, i;
|
||||
int error;
|
||||
struct job my_job;
|
||||
struct fproc *rfp;
|
||||
|
||||
my_job = *((struct job *) arg);
|
||||
fp = my_job.j_fp;
|
||||
|
@ -792,14 +793,6 @@ PRIVATE void service_pm_postponed(void)
|
|||
int r;
|
||||
vir_bytes pc;
|
||||
|
||||
#if 0
|
||||
printf("executing postponed: ");
|
||||
if (call_nr == PM_EXEC) printf("PM_EXEC");
|
||||
if (call_nr == PM_EXIT) printf("PM_EXIT");
|
||||
if (call_nr == PM_DUMPCORE) printf("PM_DUMPCORE");
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
switch(call_nr) {
|
||||
case PM_EXEC:
|
||||
r = pm_exec(m_in.PM_PROC, m_in.PM_PATH, m_in.PM_PATH_LEN,
|
||||
|
@ -823,13 +816,17 @@ PRIVATE void service_pm_postponed(void)
|
|||
break;
|
||||
|
||||
case PM_DUMPCORE:
|
||||
r = pm_dumpcore(m_in.PM_PROC,
|
||||
NULL /* (struct mem_map *) m_in.PM_SEGPTR */);
|
||||
|
||||
/* Reply status to PM */
|
||||
/* Copy parameters first. m_in gets overwritten when creating core
|
||||
* file.
|
||||
*/
|
||||
m_out.m_type = PM_CORE_REPLY;
|
||||
m_out.PM_PROC = m_in.PM_PROC;
|
||||
m_out.PM_TRACED_PROC = m_in.PM_TRACED_PROC;
|
||||
|
||||
r = pm_dumpcore(m_in.PM_PROC, m_in.PM_TERM_SIG,
|
||||
(vir_bytes) m_in.PM_PATH);
|
||||
|
||||
/* Reply status to PM */
|
||||
m_out.PM_STATUS = r;
|
||||
|
||||
break;
|
||||
|
@ -886,14 +883,6 @@ PRIVATE void service_pm()
|
|||
fp->fp_job.j_m_in = m_in;
|
||||
fp->fp_flags |= FP_PM_PENDING;
|
||||
|
||||
#if 0
|
||||
printf("Postponing: ");
|
||||
if (call_nr == PM_EXEC) printf("PM_EXEC");
|
||||
if (call_nr == PM_EXIT) printf("PM_EXIT");
|
||||
if (call_nr == PM_DUMPCORE) printf("PM_DUMPCORE");
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
/* PM requests on behalf of a proc are handled after the system call
|
||||
* that might be in progress for that proc has finished. If the proc
|
||||
* is not busy, we start a dummy call */
|
||||
|
@ -962,7 +951,7 @@ struct fproc *rfp;
|
|||
fp = rfp;
|
||||
blocked_on = rfp->fp_blocked_on;
|
||||
m_in.m_type = rfp->fp_block_callnr;
|
||||
m_in.fd = rfp->fp_block_fd;
|
||||
m_in.fd = rfp->fp_blocked.fd_nr;
|
||||
m_in.buffer = rfp->fp_buffer;
|
||||
m_in.nbytes = rfp->fp_nbytes;
|
||||
|
||||
|
|
|
@ -586,14 +586,33 @@ PUBLIC int do_svrctl()
|
|||
/*===========================================================================*
|
||||
* pm_dumpcore *
|
||||
*===========================================================================*/
|
||||
PUBLIC int pm_dumpcore(proc_e, seg_ptr)
|
||||
int proc_e;
|
||||
struct mem_map *seg_ptr;
|
||||
PUBLIC int pm_dumpcore(endpoint_t proc_e, int csig, vir_bytes exe_name)
|
||||
{
|
||||
int slot;
|
||||
int slot, r, core_fd;
|
||||
struct filp *f;
|
||||
char core_path[PATH_MAX];
|
||||
char proc_name[PROC_NAME_LEN];
|
||||
|
||||
okendpt(proc_e, &slot);
|
||||
free_proc(&fproc[slot], FP_EXITING);
|
||||
fp = &fproc[slot];
|
||||
|
||||
/* open core file */
|
||||
snprintf(core_path, PATH_MAX, "%s.%d", CORE_NAME, fp->fp_pid);
|
||||
core_fd = common_open(core_path, O_WRONLY | O_CREAT | O_TRUNC, CORE_MODE);
|
||||
if (core_fd < 0) return(core_fd);
|
||||
|
||||
/* get process' name */
|
||||
r = sys_datacopy(PM_PROC_NR, exe_name, VFS_PROC_NR, (vir_bytes) proc_name,
|
||||
PROC_NAME_LEN);
|
||||
if (r != OK) return(r);
|
||||
proc_name[PROC_NAME_LEN - 1] = '\0';
|
||||
|
||||
if ((f = get_filp(core_fd, VNODE_WRITE)) == NULL) return(EBADF);
|
||||
write_elf_core_file(f, csig, proc_name);
|
||||
unlock_filp(f);
|
||||
(void) close_fd(fp, core_fd); /* ignore failure, we're exiting anyway */
|
||||
|
||||
free_proc(fp, FP_EXITING);
|
||||
return(OK);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,8 +33,6 @@
|
|||
|
||||
PUBLIC char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
|
||||
|
||||
FORWARD _PROTOTYPE( int common_open, (char path[PATH_MAX], int oflags,
|
||||
mode_t omode) );
|
||||
FORWARD _PROTOTYPE( struct vnode *new_node, (struct lookup *resolve,
|
||||
int oflags, mode_t bits) );
|
||||
FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp, mode_t bits,
|
||||
|
@ -84,7 +82,7 @@ PUBLIC int do_open()
|
|||
/*===========================================================================*
|
||||
* common_open *
|
||||
*===========================================================================*/
|
||||
PRIVATE int common_open(char path[PATH_MAX], int oflags, mode_t omode)
|
||||
PUBLIC int common_open(char path[PATH_MAX], int oflags, mode_t omode)
|
||||
{
|
||||
/* Common code from do_creat and do_open. */
|
||||
int b, r, exist = TRUE, major_dev;
|
||||
|
@ -463,8 +461,7 @@ printf("XXX: dangling symlink needs re-resolving\n");
|
|||
/*===========================================================================*
|
||||
* pipe_open *
|
||||
*===========================================================================*/
|
||||
PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits,
|
||||
register int oflags)
|
||||
PRIVATE int pipe_open(struct vnode *vp, mode_t bits, int oflags)
|
||||
{
|
||||
/* This function is called from common_open. It checks if
|
||||
* there is at least one reader/writer pair for the pipe, if not
|
||||
|
@ -474,7 +471,7 @@ PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits,
|
|||
|
||||
vp->v_pipe = I_PIPE;
|
||||
|
||||
if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) return(ENXIO);
|
||||
if ((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) return(ENXIO);
|
||||
|
||||
/* Find the reader/writer at the other end of the pipe */
|
||||
if (find_filp(vp, bits & W_BIT ? R_BIT : W_BIT) == NULL) {
|
||||
|
@ -483,7 +480,7 @@ PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits,
|
|||
if (bits & W_BIT) return(ENXIO);
|
||||
} else {
|
||||
/* Let's wait for the other side to show up */
|
||||
suspend(FP_BLOCKED_ON_POPEN); /* suspend caller */
|
||||
suspend(FP_BLOCKED_ON_POPEN);
|
||||
return(SUSPEND);
|
||||
}
|
||||
} else if (susp_count > 0) { /* revive blocked processes */
|
||||
|
|
|
@ -298,9 +298,14 @@ PUBLIC void suspend(int why)
|
|||
/* #procs susp'ed on pipe*/
|
||||
susp_count++;
|
||||
|
||||
if (why == FP_BLOCKED_ON_POPEN || why == FP_BLOCKED_ON_DOPEN ||
|
||||
why == FP_BLOCKED_ON_LOCK || why == FP_BLOCKED_ON_OTHER)
|
||||
fp->fp_blocked.fd_nr = m_in.fd;
|
||||
else
|
||||
fp->fp_blocked.fd_nr = 0;
|
||||
|
||||
fp->fp_blocked_on = why;
|
||||
assert(fp->fp_grant == GRANT_INVALID || !GRANT_VALID(fp->fp_grant));
|
||||
fp->fp_block_fd = m_in.fd;
|
||||
fp->fp_block_callnr = call_nr;
|
||||
fp->fp_flags &= ~FP_SUSP_REOPEN; /* Clear this flag. The caller
|
||||
* can set it when needed.
|
||||
|
@ -329,9 +334,9 @@ PUBLIC void wait_for(endpoint_t who)
|
|||
/*===========================================================================*
|
||||
* pipe_suspend *
|
||||
*===========================================================================*/
|
||||
PUBLIC void pipe_suspend(rw_flag, fd_nr, buf, size)
|
||||
PUBLIC void pipe_suspend(rw_flag, filp, buf, size)
|
||||
int rw_flag;
|
||||
int fd_nr;
|
||||
struct filp *filp;
|
||||
char *buf;
|
||||
size_t size;
|
||||
{
|
||||
|
@ -349,8 +354,8 @@ size_t size;
|
|||
susp_count++; /* #procs susp'ed on pipe*/
|
||||
fp->fp_blocked_on = FP_BLOCKED_ON_PIPE;
|
||||
assert(!GRANT_VALID(fp->fp_grant));
|
||||
fp->fp_block_fd = fd_nr;
|
||||
fp->fp_block_callnr = ((rw_flag == READING) ? READ : WRITE);
|
||||
fp->fp_blocked.bfilp = filp;
|
||||
fp->fp_block_callnr = (rw_flag == READING) ? READ : WRITE;
|
||||
fp->fp_buffer = buf;
|
||||
fp->fp_nbytes = size;
|
||||
}
|
||||
|
@ -387,9 +392,8 @@ register struct vnode *vp; /* inode of pipe */
|
|||
int op; /* READ, WRITE, OPEN or CREAT */
|
||||
int count; /* max number of processes to release */
|
||||
{
|
||||
/* Check to see if any process is hanging on the pipe whose inode is in 'ip'.
|
||||
* If one is, and it was trying to perform the call indicated by 'call_nr',
|
||||
* release it.
|
||||
/* Check to see if any process is hanging on vnode 'vp'. If one is, and it
|
||||
* was trying to perform the call indicated by 'call_nr', release it.
|
||||
*/
|
||||
|
||||
register struct fproc *rp;
|
||||
|
@ -417,9 +421,27 @@ int count; /* max number of processes to release */
|
|||
/* Search the proc table. */
|
||||
for (rp = &fproc[0]; rp < &fproc[NR_PROCS] && count > 0; rp++) {
|
||||
if (rp->fp_pid != PID_FREE && fp_is_blocked(rp) &&
|
||||
!(rp->fp_flags & FP_REVIVED) && rp->fp_block_callnr == op &&
|
||||
rp->fp_filp[rp->fp_block_fd] != NULL &&
|
||||
rp->fp_filp[rp->fp_block_fd]->filp_vno == vp) {
|
||||
!(rp->fp_flags & FP_REVIVED) && rp->fp_block_callnr == op) {
|
||||
/* Find the vnode. Depending on the reason the process was
|
||||
* suspended, there are different ways of finding it.
|
||||
*/
|
||||
|
||||
if (rp->fp_blocked_on == FP_BLOCKED_ON_POPEN ||
|
||||
rp->fp_blocked_on == FP_BLOCKED_ON_DOPEN ||
|
||||
rp->fp_blocked_on == FP_BLOCKED_ON_LOCK ||
|
||||
rp->fp_blocked_on == FP_BLOCKED_ON_OTHER) {
|
||||
if (rp->fp_filp[rp->fp_blocked.fd_nr] == NULL)
|
||||
continue;
|
||||
if (rp->fp_filp[rp->fp_blocked.fd_nr]->filp_vno != vp)
|
||||
continue;
|
||||
} else {
|
||||
if (rp->fp_blocked.bfilp == NULL)
|
||||
continue;
|
||||
if (rp->fp_blocked.bfilp->filp_vno != vp)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We found the vnode. Revive process. */
|
||||
revive(rp->fp_endpoint, 0);
|
||||
susp_count--; /* keep track of who is suspended */
|
||||
if(susp_count < 0)
|
||||
|
@ -456,13 +478,14 @@ int returned; /* if hanging on task, how many bytes read */
|
|||
* the proc must be restarted so it can try again.
|
||||
*/
|
||||
blocked_on = rfp->fp_blocked_on;
|
||||
fd_nr = rfp->fp_blocked.fd_nr;
|
||||
if (blocked_on == FP_BLOCKED_ON_PIPE || blocked_on == FP_BLOCKED_ON_LOCK) {
|
||||
/* Revive a process suspended on a pipe or lock. */
|
||||
rfp->fp_flags |= FP_REVIVED;
|
||||
reviving++; /* process was waiting on pipe or lock */
|
||||
} else if (blocked_on == FP_BLOCKED_ON_DOPEN) {
|
||||
rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
|
||||
fd_nr = rfp->fp_block_fd;
|
||||
rfp->fp_blocked.fd_nr = 0;
|
||||
if (returned < 0) {
|
||||
fil_ptr = rfp->fp_filp[fd_nr];
|
||||
lock_filp(fil_ptr, VNODE_OPCL);
|
||||
|
@ -482,9 +505,10 @@ int returned; /* if hanging on task, how many bytes read */
|
|||
}
|
||||
} else {
|
||||
rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
|
||||
rfp->fp_blocked.fd_nr = 0;
|
||||
if (blocked_on == FP_BLOCKED_ON_POPEN) {
|
||||
/* process blocked in open or create */
|
||||
reply(proc_nr_e, rfp->fp_block_fd);
|
||||
reply(proc_nr_e, fd_nr);
|
||||
} else if (blocked_on == FP_BLOCKED_ON_SELECT) {
|
||||
reply(proc_nr_e, returned);
|
||||
} else {
|
||||
|
@ -568,7 +592,7 @@ int proc_nr_e;
|
|||
break;
|
||||
}
|
||||
|
||||
fild = rfp->fp_block_fd;
|
||||
fild = rfp->fp_blocked.fd_nr;
|
||||
if (fild < 0 || fild >= OPEN_MAX)
|
||||
panic("file descriptor out-of-range");
|
||||
f = rfp->fp_filp[fild];
|
||||
|
|
|
@ -67,6 +67,10 @@ _PROTOTYPE( int map_driver, (const char *label, int major, endpoint_t proc_nr,
|
|||
int dev_style, int flags) );
|
||||
_PROTOTYPE( int map_service, (struct rprocpub *rpub) );
|
||||
|
||||
/* elf_core_dump.c */
|
||||
_PROTOTYPE( void write_elf_core_file, (struct filp *f, int csig,
|
||||
char *exe_name) );
|
||||
|
||||
/* exec.c */
|
||||
_PROTOTYPE( int pm_exec, (int proc_e, char *path, vir_bytes path_len,
|
||||
char *frame, vir_bytes frame_len, vir_bytes *pc));
|
||||
|
@ -137,7 +141,8 @@ _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, (endpoint_t proc_e, int sig,
|
||||
vir_bytes exe_name) );
|
||||
_PROTOTYPE( void ds_event, (void) );
|
||||
|
||||
/* mount.c */
|
||||
|
@ -156,6 +161,8 @@ _PROTOTYPE( void unmount_all, (void) );
|
|||
_PROTOTYPE( int do_close, (void) );
|
||||
_PROTOTYPE( int close_fd, (struct fproc *rfp, int fd_nr) );
|
||||
_PROTOTYPE( void close_reply, (void) );
|
||||
_PROTOTYPE( int common_open, (char path[PATH_MAX], int oflags,
|
||||
mode_t omode) );
|
||||
_PROTOTYPE( int do_creat, (void) );
|
||||
_PROTOTYPE( int do_lseek, (void) );
|
||||
_PROTOTYPE( int do_llseek, (void) );
|
||||
|
@ -189,8 +196,8 @@ _PROTOTYPE( int pipe_check, (struct vnode *vp, int rw_flag,
|
|||
_PROTOTYPE( void release, (struct vnode *vp, int call_nr, int count) );
|
||||
_PROTOTYPE( void revive, (int proc_nr, int bytes) );
|
||||
_PROTOTYPE( void suspend, (int task) );
|
||||
_PROTOTYPE( void pipe_suspend, (int rw_flag, int fd_nr, char *buf,
|
||||
size_t size) );
|
||||
_PROTOTYPE( void pipe_suspend, (int rw_flag, struct filp *rfilp,
|
||||
char *buf, size_t size) );
|
||||
_PROTOTYPE( void unsuspend_by_endpt, (endpoint_t) );
|
||||
_PROTOTYPE( void wait_for, (endpoint_t) );
|
||||
#if DO_SANITYCHECKS
|
||||
|
@ -210,9 +217,11 @@ _PROTOTYPE( int do_read, (void) );
|
|||
_PROTOTYPE( int do_getdents, (void) );
|
||||
_PROTOTYPE( void lock_bsf, (void) );
|
||||
_PROTOTYPE( void unlock_bsf, (void) );
|
||||
_PROTOTYPE( int read_write, (int rw_flag) );
|
||||
_PROTOTYPE( int rw_pipe, (int rw_flag, endpoint_t usr,
|
||||
int fd_nr, struct filp *f, char *buf, size_t req_size) );
|
||||
_PROTOTYPE( int do_read_write, (int rw_flag) );
|
||||
_PROTOTYPE( int read_write, (int rw_flag, struct filp *f, char *buffer,
|
||||
size_t nbytes, endpoint_t for_e) );
|
||||
_PROTOTYPE( int rw_pipe, (int rw_flag, endpoint_t usr, struct filp *f,
|
||||
char *buf, size_t req_size) );
|
||||
|
||||
/* request.c */
|
||||
_PROTOTYPE( int req_breadwrite, (endpoint_t fs_e, endpoint_t user_e,
|
||||
|
@ -372,6 +381,7 @@ _PROTOTYPE( struct worker_thread *worker_self, (void) );
|
|||
_PROTOTYPE( void worker_signal, (struct worker_thread *worker) );
|
||||
_PROTOTYPE( void worker_start, (void *(*func)(void *arg)) );
|
||||
_PROTOTYPE( void worker_stop, (struct worker_thread *worker) );
|
||||
_PROTOTYPE( void worker_stop_by_endpt, (endpoint_t proc_e) );
|
||||
_PROTOTYPE( void worker_wait, (void) );
|
||||
_PROTOTYPE( void sys_worker_start, (void *(*func)(void *arg)) );
|
||||
_PROTOTYPE( void dl_worker_start, (void *(*func)(void *arg)) );
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
*===========================================================================*/
|
||||
PUBLIC int do_read()
|
||||
{
|
||||
return(read_write(READING));
|
||||
return(do_read_write(READING));
|
||||
}
|
||||
|
||||
|
||||
|
@ -64,22 +64,19 @@ PUBLIC void unlock_bsf(void)
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* read_write *
|
||||
* do_read_write *
|
||||
*===========================================================================*/
|
||||
PUBLIC int read_write(rw_flag)
|
||||
PUBLIC int do_read_write(rw_flag)
|
||||
int rw_flag; /* READING or WRITING */
|
||||
{
|
||||
/* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
|
||||
register struct filp *f;
|
||||
register struct vnode *vp;
|
||||
u64_t position, res_pos, new_pos;
|
||||
unsigned int cum_io, cum_io_incr, res_cum_io;
|
||||
int op, oflags, r, block_spec, char_spec, regular;
|
||||
struct filp *f;
|
||||
tll_access_t locktype;
|
||||
mode_t mode_word;
|
||||
int r;
|
||||
|
||||
/* If the file descriptor is valid, get the vnode, size and mode. */
|
||||
if (m_in.nbytes < 0) return(EINVAL);
|
||||
|
||||
locktype = (rw_flag == READING) ? VNODE_READ : VNODE_WRITE;
|
||||
if ((f = get_filp(m_in.fd, locktype)) == NULL) return(err_code);
|
||||
if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
|
||||
|
@ -91,6 +88,24 @@ int rw_flag; /* READING or WRITING */
|
|||
return(0); /* so char special files need not check for 0*/
|
||||
}
|
||||
|
||||
r = read_write(rw_flag, f, m_in.buffer, m_in.nbytes, who_e);
|
||||
|
||||
unlock_filp(f);
|
||||
return(r);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* read_write *
|
||||
*===========================================================================*/
|
||||
PUBLIC int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
|
||||
endpoint_t for_e)
|
||||
{
|
||||
register struct vnode *vp;
|
||||
u64_t position, res_pos, new_pos;
|
||||
unsigned int cum_io, cum_io_incr, res_cum_io;
|
||||
int op, oflags, r, block_spec, char_spec, regular;
|
||||
mode_t mode_word;
|
||||
|
||||
position = f->filp_pos;
|
||||
oflags = f->filp_flags;
|
||||
vp = f->filp_vno;
|
||||
|
@ -101,8 +116,7 @@ int rw_flag; /* READING or WRITING */
|
|||
if (fp->fp_cum_io_partial != 0) {
|
||||
panic("VFS: read_write: fp_cum_io_partial not clear");
|
||||
}
|
||||
r = rw_pipe(rw_flag, who_e, m_in.fd, f, m_in.buffer, m_in.nbytes);
|
||||
unlock_filp(f);
|
||||
r = rw_pipe(rw_flag, for_e, f, buf, size);
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
@ -127,7 +141,7 @@ int rw_flag; /* READING or WRITING */
|
|||
suspend_reopen = (f->filp_state != FS_NORMAL);
|
||||
dev = (dev_t) vp->v_sdev;
|
||||
|
||||
r = dev_io(op, dev, who_e, m_in.buffer, position, m_in.nbytes, oflags,
|
||||
r = dev_io(op, dev, for_e, buf, position, size, oflags,
|
||||
suspend_reopen);
|
||||
if (r >= 0) {
|
||||
cum_io = r;
|
||||
|
@ -137,8 +151,8 @@ int rw_flag; /* READING or WRITING */
|
|||
} else if (block_spec) { /* Block special files. */
|
||||
lock_bsf();
|
||||
|
||||
r = req_breadwrite(vp->v_bfs_e, who_e, vp->v_sdev, position,
|
||||
m_in.nbytes, m_in.buffer, rw_flag, &res_pos, &res_cum_io);
|
||||
r = req_breadwrite(vp->v_bfs_e, for_e, vp->v_sdev, position, size,
|
||||
buf, rw_flag, &res_pos, &res_cum_io);
|
||||
if (r == OK) {
|
||||
position = res_pos;
|
||||
cum_io += res_cum_io;
|
||||
|
@ -152,8 +166,8 @@ int rw_flag; /* READING or WRITING */
|
|||
}
|
||||
|
||||
/* Issue request */
|
||||
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position, rw_flag, who_e,
|
||||
m_in.buffer, m_in.nbytes, &new_pos, &cum_io_incr);
|
||||
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position, rw_flag, for_e,
|
||||
buf, size, &new_pos, &cum_io_incr);
|
||||
|
||||
if (r >= 0) {
|
||||
if (ex64hi(new_pos))
|
||||
|
@ -177,13 +191,11 @@ int rw_flag; /* READING or WRITING */
|
|||
}
|
||||
|
||||
f->filp_pos = position;
|
||||
unlock_filp(f);
|
||||
|
||||
if (r == OK) return(cum_io);
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* do_getdents *
|
||||
*===========================================================================*/
|
||||
|
@ -220,10 +232,9 @@ PUBLIC int do_getdents()
|
|||
/*===========================================================================*
|
||||
* rw_pipe *
|
||||
*===========================================================================*/
|
||||
PUBLIC int rw_pipe(rw_flag, usr_e, fd_nr, f, buf, req_size)
|
||||
PUBLIC int rw_pipe(rw_flag, usr_e, f, buf, req_size)
|
||||
int rw_flag; /* READING or WRITING */
|
||||
endpoint_t usr_e;
|
||||
int fd_nr;
|
||||
struct filp *f;
|
||||
char *buf;
|
||||
size_t req_size;
|
||||
|
@ -246,7 +257,7 @@ size_t req_size;
|
|||
|
||||
r = pipe_check(vp, rw_flag, oflags, req_size, position, 0);
|
||||
if (r <= 0) {
|
||||
if (r == SUSPEND) pipe_suspend(rw_flag, fd_nr, buf, req_size);
|
||||
if (r == SUSPEND) pipe_suspend(rw_flag, f, buf, req_size);
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
@ -314,7 +325,7 @@ size_t req_size;
|
|||
* non-atomic
|
||||
*/
|
||||
fp->fp_cum_io_partial = cum_io;
|
||||
pipe_suspend(rw_flag, fd_nr, buf, req_size);
|
||||
pipe_suspend(rw_flag, f, buf, req_size);
|
||||
return(SUSPEND);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,5 +15,5 @@
|
|||
PUBLIC int do_write()
|
||||
{
|
||||
/* Perform the write(fd, buffer, nbytes) system call. */
|
||||
return(read_write(WRITING));
|
||||
return(do_read_write(WRITING));
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
|
||||
/* Include ELF headers */
|
||||
#include <sys/elf_core.h>
|
||||
#include <sys/procfs.h>
|
||||
|
||||
FORWARD _PROTOTYPE( void fill_elf_header, (Elf32_Ehdr *elf_header,
|
||||
int phnum) );
|
||||
|
|
Loading…
Reference in a new issue