Index: imgact_elf.c =================================================================== RCS file: /home/dcvs/src/sys/kern/imgact_elf.c,v retrieving revision 1.9 diff -b -B -u -r1.9 imgact_elf.c --- imgact_elf.c 23 Sep 2003 05:03:51 -0000 1.9 +++ imgact_elf.c 12 Oct 2003 02:17:07 -0000 @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,7 @@ #include #include #include +#include #include #include @@ -185,7 +187,9 @@ } static int -elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, vm_prot_t prot) +elf_load_section(struct proc *p, struct vmspace *vmspace, struct vnode *vp, + vm_offset_t offset, caddr_t vmaddr, size_t memsz, size_t filsz, + vm_prot_t prot) { size_t map_len; vm_offset_t map_addr; @@ -767,23 +771,32 @@ static void cb_size_segment (vm_map_entry_t, void *); static void each_writable_segment (struct proc *, segment_callback, void *); -static int elf_corehdr (struct proc *, struct vnode *, struct ucred *, +static int elf_corehdr (struct proc *, struct file *, struct ucred *, int, void *, size_t); static void elf_puthdr (struct proc *, void *, size_t *, const prstatus_t *, const prfpregset_t *, const prpsinfo_t *, int); static void elf_putnote (void *, size_t *, const char *, int, const void *, size_t); +static void elf_putsigs(struct proc *, void *, int *); + +static void elf_putfiles(struct proc *, void *, int *); + + extern int osreldate; int -elf_coredump(p, vp, limit) - struct proc *p; - struct vnode *vp; - off_t limit; +elf_coredump(struct proc *p, struct vnode *vp, off_t limit) { + struct file *fp; + fp = (struct file *)vp->v_data; + return generic_elf_coredump(p, fp, limit); +} +int +generic_elf_coredump(struct proc *p, struct file *fp, off_t limit) +{ + struct ucred *cred = p->p_ucred; - struct thread *td = p->p_thread; int error = 0; struct sseg_closure seginfo; void *hdr; @@ -815,7 +828,7 @@ if (hdr == NULL) { return EINVAL; } - error = elf_corehdr(p, vp, cred, seginfo.count, hdr, hdrsize); + error = elf_corehdr(p, fp, cred, seginfo.count, hdr, hdrsize); /* Write the contents of all of the writable segments. */ if (error == 0) { @@ -826,11 +839,9 @@ php = (Elf_Phdr *)((char *)hdr + sizeof(Elf_Ehdr)) + 1; offset = hdrsize; for (i = 0; i < seginfo.count; i++) { - error = vn_rdwr_inchunks(UIO_WRITE, vp, - (caddr_t)php->p_vaddr, - php->p_filesz, offset, UIO_USERSPACE, - IO_UNIT | IO_DIRECT | IO_CORE, cred, - (int *)NULL, td); + int nbytes; + error = fp_write(fp, (caddr_t)php->p_vaddr, php->p_filesz, + offset, &nbytes); if (error != 0) break; offset += php->p_filesz; @@ -847,9 +858,7 @@ * program header entry. */ static void -cb_put_phdr(entry, closure) - vm_map_entry_t entry; - void *closure; +cb_put_phdr(vm_map_entry_t entry, void *closure) { struct phdr_closure *phc = (struct phdr_closure *)closure; Elf_Phdr *phdr = phc->phdr; @@ -879,9 +888,7 @@ * the number of segments and their total size. */ static void -cb_size_segment(entry, closure) - vm_map_entry_t entry; - void *closure; +cb_size_segment(vm_map_entry_t entry, void *closure) { struct sseg_closure *ssc = (struct sseg_closure *)closure; @@ -895,10 +902,7 @@ * caller-supplied data. */ static void -each_writable_segment(p, func, closure) - struct proc *p; - segment_callback func; - void *closure; +each_writable_segment(struct proc *p, segment_callback func, void *closure) { vm_map_t map = &p->p_vmspace->vm_map; vm_map_entry_t entry; @@ -954,13 +958,8 @@ * the page boundary. */ static int -elf_corehdr(p, vp, cred, numsegs, hdr, hdrsize) - struct proc *p; - struct vnode *vp; - struct ucred *cred; - int numsegs; - size_t hdrsize; - void *hdr; +elf_corehdr(struct proc *p, struct file *fp, struct ucred *cred, int numsegs, + void *hdr, size_t hdrsize) { struct { prstatus_t status; @@ -971,8 +970,7 @@ prstatus_t *status; prfpregset_t *fpregset; prpsinfo_t *psinfo; - struct thread *td = p->p_thread; - + int nbytes; tempdata = malloc(sizeof(*tempdata), M_TEMP, M_ZERO | M_WAITOK); status = &tempdata->status; fpregset = &tempdata->fpregset; @@ -1005,8 +1003,7 @@ free(tempdata, M_TEMP); /* Write it to the core file. */ - return vn_rdwr_inchunks(UIO_WRITE, vp, hdr, hdrsize, (off_t)0, - UIO_SYSSPACE, IO_UNIT | IO_DIRECT | IO_CORE, cred, NULL, td); + return fp_write(fp, hdr, hdrsize, (off_t)0, &nbytes); } static void @@ -1033,6 +1030,15 @@ sizeof *psinfo); notesz = *off - noteoff; + /* put extra cruft for dumping process state here + * - we really want it be before all the program + * mappings + * - we just need to update the offset accordingly + * and GDB will be none the wiser. + */ + elf_putsigs(p, dst, off); + elf_putfiles(p, dst, off); + /* Align up to a page boundary for the program segments. */ *off = round_page(*off); @@ -1110,6 +1116,65 @@ bcopy(desc, (char *)dst + *off, note.n_descsz); *off += roundup2(note.n_descsz, sizeof(Elf_Size)); } + + +static void +elf_putsigs(struct proc *p, void *dst, int *off) +{ + struct ckpt_siginfo *csi; + + *off += sizeof(struct ckpt_siginfo); + if (dst == NULL) + return; + csi = (struct ckpt_siginfo *)dst; + + csi->csi_ckptpisz = sizeof(struct ckpt_siginfo); + bcopy(p->p_procsig, &csi->csi_procsig, sizeof(struct procsig)); + bcopy(p->p_procsig->ps_sigacts, &csi->csi_sigacts, sizeof(struct sigacts)); + bcopy(&p->p_realtimer, &csi->csi_itimerval, sizeof(struct itimerval)); + csi->csi_sigparent = p->p_sigparent; + +} + +static void +elf_putfiles(struct proc *p, void *dst, int *off) +{ + int i, size = 0; + struct ckpt_filehdr *cfh; + struct ckpt_fileinfo *cfi; + struct stat *sb; + struct file *fp; + size += sizeof(struct ckpt_filehdr); + /* + * the duplicated loop is gross, but it was the only way + * to eliminate uninitialized variable warnings + */ + if (dst) { + cfh = (struct ckpt_filehdr *)dst; + cfh->cfh_nfiles = 0; + sb = malloc(sizeof(struct stat), M_TEMP, M_WAITOK); + + for (i = 0; i < p->p_fd->fd_nfiles; i++) { + if ((fp = p->p_fd->fd_ofiles[i]) != NULL) { + cfh->cfh_nfiles++; + cfi = (struct ckpt_fileinfo *)((char *)dst + size); + cfi->cfi_index = i; + fp_stat(fp, sb); + cfi->cfi_dev = sb->st_dev; + cfi->cfi_ino = sb->st_ino; + size += sizeof(struct ckpt_fileinfo); + } + } + free(sb, M_TEMP); + } else { + for (i = 0; i < p->p_fd->fd_nfiles; i++) + if ((fp = p->p_fd->fd_ofiles[i]) != NULL) + size += sizeof(struct ckpt_fileinfo); + } + + *off += size; +} + /* * Tell kern_execve.c about it, with a little help from the linker.