summaryrefslogtreecommitdiffstats
path: root/sys/kern/imgact_elf.c
diff options
context:
space:
mode:
authorjdp <jdp@FreeBSD.org>1998-09-15 22:23:12 +0000
committerjdp <jdp@FreeBSD.org>1998-09-15 22:23:12 +0000
commit3ff15d56a400b32f6b4a2fdcdfda55b5fd6b5ae8 (patch)
tree4fe674b6a1c54a06811f2750e8e54c794bf23aa1 /sys/kern/imgact_elf.c
parent5e2468870954157c6bebeb864aeed47fa9a2dd20 (diff)
downloadFreeBSD-src-3ff15d56a400b32f6b4a2fdcdfda55b5fd6b5ae8.zip
FreeBSD-src-3ff15d56a400b32f6b4a2fdcdfda55b5fd6b5ae8.tar.gz
Erk. Revert back to 1.31, dumping only data and stack to the core
file, until I can solve a panic that has just cropped up.
Diffstat (limited to 'sys/kern/imgact_elf.c')
-rw-r--r--sys/kern/imgact_elf.c268
1 files changed, 68 insertions, 200 deletions
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index 5c93c5d..342ed02 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -26,7 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $Id: imgact_elf.c,v 1.32 1998/09/15 21:46:34 jdp Exp $
+ * $Id: imgact_elf.c,v 1.31 1998/09/14 22:46:04 jdp Exp $
*/
#include "opt_rlimit.h"
@@ -59,7 +59,6 @@
#include <vm/pmap.h>
#include <sys/lock.h>
#include <vm/vm_map.h>
-#include <vm/vm_object.h>
#include <vm/vm_prot.h>
#include <vm/vm_extern.h>
@@ -685,40 +684,13 @@ elf_freebsd_fixup(long **stack_base, struct image_params *imgp)
* Code for generating ELF core dumps.
*/
-typedef void (*segment_callback) __P((vm_map_entry_t, void *));
-
-/* Closure for cb_put_phdr(). */
-struct phdr_closure {
- Elf_Phdr *phdr; /* Program header to fill in */
- Elf_Off offset; /* Offset of segment in core file */
-};
-
-/* Closure for cb_size_segment(). */
-struct sseg_closure {
- int count; /* Count of writable segments. */
- size_t size; /* Total size of all writable segments. */
-};
-
-/* Closure for cb_write_segment(). */
-struct wseg_closure {
- struct proc *p;
- struct vnode *vp;
- struct ucred *cred;
- off_t offset; /* Position in file at which to write. */
- int error;
-};
-
-static void cb_put_phdr __P((vm_map_entry_t, void *));
-static void cb_size_segment __P((vm_map_entry_t, void *));
-static void cb_write_segment __P((vm_map_entry_t, void *));
-static void each_writable_segment __P((struct proc *, segment_callback,
- void *));
-static int elf_corehdr __P((struct proc *, struct vnode *, struct ucred *,
- int, size_t));
-static void elf_puthdr __P((struct proc *, void *, size_t *,
- const prstatus_t *, const prfpregset_t *, const prpsinfo_t *, int));
-static void elf_putnote __P((void *, size_t *, const char *, int,
- const void *, size_t));
+static int elf_corehdr __P((struct proc *, struct vnode *, struct ucred *));
+static size_t elf_hdrsize(void);
+static void elf_puthdr(void *, size_t *, const prstatus_t *,
+ const prfpregset_t *, const prpsinfo_t *, const void *, size_t,
+ const void *, size_t);
+static void elf_putnote(void *, size_t *, const char *, int, const void *,
+ size_t);
extern int osreldate;
@@ -733,30 +705,15 @@ elf_coredump(p)
struct vattr vattr;
int error, error1;
char *name; /* name of corefile */
- struct sseg_closure seginfo;
size_t hdrsize;
STOPEVENT(p, S_CORE, 0);
if (sugid_coredump == 0 && p->p_flag & P_SUGID)
return (EFAULT);
-
- /* Size the program segments. */
- seginfo.count = 0;
- seginfo.size = 0;
- each_writable_segment(p, cb_size_segment, &seginfo);
-
- /*
- * Calculate the size of the core file header area by making
- * a dry run of generating it. Nothing is written, but the
- * size is calculated.
- */
- hdrsize = 0;
- elf_puthdr((struct proc *)NULL, (void *)NULL, &hdrsize,
- (const prstatus_t *)NULL, (const prfpregset_t *)NULL,
- (const prpsinfo_t *)NULL, seginfo.count);
-
- if (hdrsize + seginfo.size >= p->p_rlimit[RLIMIT_CORE].rlim_cur)
+ hdrsize = elf_hdrsize();
+ if (hdrsize + ctob(vm->vm_dsize + vm->vm_ssize) >=
+ p->p_rlimit[RLIMIT_CORE].rlim_cur)
return (EFAULT);
name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
if (name == NULL)
@@ -780,20 +737,17 @@ elf_coredump(p)
VOP_LEASE(vp, p, cred, LEASE_WRITE);
VOP_SETATTR(vp, &vattr, cred, p);
p->p_acflag |= ACORE;
- error = elf_corehdr(p, vp, cred, seginfo.count, hdrsize);
- if (error == 0) {
- struct wseg_closure wsc;
-
- wsc.p = p;
- wsc.vp = vp;
- wsc.cred = cred;
- wsc.offset = hdrsize;
- wsc.error = 0;
-
- each_writable_segment(p, cb_write_segment, &wsc);
- error = wsc.error;
- }
-
+ error = elf_corehdr(p, vp, cred);
+ if (error == 0)
+ error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr,
+ (int)ctob(vm->vm_dsize), (off_t)hdrsize, UIO_USERSPACE,
+ IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p);
+ if (error == 0)
+ error = vn_rdwr(UIO_WRITE, vp,
+ (caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)),
+ round_page(ctob(vm->vm_ssize)),
+ (off_t)hdrsize + ctob(vm->vm_dsize), UIO_USERSPACE,
+ IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p);
out:
VOP_UNLOCK(vp, 0, p);
error1 = vn_close(vp, FWRITE, cred, p);
@@ -802,132 +756,15 @@ out:
return (error);
}
-/*
- * A callback for each_writable_segment() to write out the segment's
- * program header entry.
- */
-static void
-cb_put_phdr(entry, closure)
- vm_map_entry_t entry;
- void *closure;
-{
- struct phdr_closure *phc = (struct phdr_closure *)closure;
- Elf_Phdr *phdr = phc->phdr;
-
- phc->offset = round_page(phc->offset);
-
- phdr->p_type = PT_LOAD;
- phdr->p_offset = phc->offset;
- phdr->p_vaddr = entry->start;
- phdr->p_paddr = 0;
- phdr->p_filesz = phdr->p_memsz = entry->end - entry->start;
- phdr->p_align = PAGE_SIZE;
- phdr->p_flags = 0;
- if (entry->protection & VM_PROT_READ)
- phdr->p_flags |= PF_R;
- if (entry->protection & VM_PROT_WRITE)
- phdr->p_flags |= PF_W;
- if (entry->protection & VM_PROT_EXECUTE)
- phdr->p_flags |= PF_X;
-
- phc->offset += phdr->p_filesz;
- phc->phdr++;
-}
-
-/*
- * A callback for each_writable_segment() to gather information about
- * the number of segments and their total size.
- */
-static void
-cb_size_segment(entry, closure)
- vm_map_entry_t entry;
- void *closure;
-{
- struct sseg_closure *ssc = (struct sseg_closure *)closure;
-
- ssc->count++;
- ssc->size += entry->end - entry->start;
-}
-
-/*
- * A callback for each_writable_segment() to write out the segment contents.
- */
-static void
-cb_write_segment(entry, closure)
- vm_map_entry_t entry;
- void *closure;
-{
- struct wseg_closure *wsc = (struct wseg_closure *)closure;
-
- if (wsc->error == 0) {
- wsc->error = vn_rdwr(UIO_WRITE, wsc->vp, (caddr_t)entry->start,
- entry->end - entry->start, wsc->offset, UIO_USERSPACE,
- IO_NODELOCKED|IO_UNIT, wsc->cred, (int *)NULL, wsc->p);
- if (wsc->error == 0)
- wsc->offset += entry->end - entry->start;
- }
-}
-
-/*
- * For each writable segment in the process's memory map, call the given
- * function with a pointer to the map entry and some arbitrary
- * caller-supplied data.
- */
-static void
-each_writable_segment(p, func, closure)
- struct proc *p;
- segment_callback func;
- void *closure;
-{
- vm_map_t map = &p->p_vmspace->vm_map;
- vm_map_entry_t entry;
-
- if (map != &curproc->p_vmspace->vm_map)
- vm_map_lock_read(map);
-
- for (entry = map->header.next; entry != &map->header;
- entry = entry->next) {
- vm_object_t obj;
- vm_object_t backobj;
-
- if (entry->eflags & (MAP_ENTRY_IS_A_MAP|MAP_ENTRY_IS_SUB_MAP) ||
- (entry->protection & (VM_PROT_READ|VM_PROT_WRITE)) !=
- (VM_PROT_READ|VM_PROT_WRITE))
- continue;
-
- /* Find the deepest backing object. */
- backobj = obj = entry->object.vm_object;
- if (backobj != NULL)
- while (backobj->backing_object != NULL)
- backobj = backobj->backing_object;
-
- /* Ignore memory-mapped devices and such things. */
- if (backobj->type != OBJT_DEFAULT &&
- backobj->type != OBJT_SWAP &&
- backobj->type != OBJT_VNODE)
- continue;
-
- (*func)(entry, closure);
- }
-
- if (map != &curproc->p_vmspace->vm_map)
- vm_map_unlock_read(map);
-}
-
-/*
- * Write the core file header to the file, including padding up to
- * the page boundary.
- */
static int
-elf_corehdr(p, vp, cred, numsegs, hdrsize)
+elf_corehdr(p, vp, cred)
struct proc *p;
struct vnode *vp;
struct ucred *cred;
- int numsegs;
- size_t hdrsize;
{
struct vmspace *vm = p->p_vmspace;
size_t off;
+ size_t hdrsize;
prstatus_t status;
prfpregset_t fpregset;
prpsinfo_t psinfo;
@@ -951,10 +788,10 @@ elf_corehdr(p, vp, cred, numsegs, hdrsize)
psinfo.pr_version = PRPSINFO_VERSION;
psinfo.pr_psinfosz = sizeof(prpsinfo_t);
strncpy(psinfo.pr_fname, p->p_comm, MAXCOMLEN);
- /* XXX - We don't fill in the command line arguments properly yet. */
- strncpy(psinfo.pr_psargs, p->p_comm, PRARGSZ);
+ psinfo.pr_psargs[0] = '\0'; /* XXX - args not implemented yet */
/* Allocate memory for building the header. */
+ hdrsize = elf_hdrsize();
hdr = malloc(hdrsize, M_TEMP, M_WAITOK);
if (hdr == NULL)
return EINVAL;
@@ -962,7 +799,10 @@ elf_corehdr(p, vp, cred, numsegs, hdrsize)
/* Fill in the header. */
off = 0;
- elf_puthdr(p, hdr, &off, &status, &fpregset, &psinfo, numsegs);
+ elf_puthdr(hdr, &off, &status, &fpregset, &psinfo,
+ vm->vm_daddr, ctob(vm->vm_dsize),
+ (void *)trunc_page(USRSTACK - ctob(vm->vm_ssize)),
+ ctob(vm->vm_ssize));
/* Write it to the core file. */
error = vn_rdwr(UIO_WRITE, vp, hdr, hdrsize, (off_t)0,
@@ -972,20 +812,34 @@ elf_corehdr(p, vp, cred, numsegs, hdrsize)
return error;
}
+static size_t
+elf_hdrsize(void)
+{
+ size_t off;
+
+ off = 0;
+ elf_puthdr(NULL, &off, NULL, NULL, NULL, NULL, 0, NULL, 0);
+ return off;
+}
+
static void
-elf_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status,
- const prfpregset_t *fpregset, const prpsinfo_t *psinfo, int numsegs)
+elf_puthdr(void *dst, size_t *off, const prstatus_t *status,
+ const prfpregset_t *fpregset, const prpsinfo_t *psinfo,
+ const void *data, size_t datasz, const void *stack, size_t stacksz)
{
size_t ehoff;
size_t phoff;
size_t noteoff;
size_t notesz;
+ size_t dataoff;
+ size_t stackoff;
+ int numsegs = 3;
ehoff = *off;
*off += sizeof(Elf_Ehdr);
phoff = *off;
- *off += (numsegs + 1) * sizeof(Elf_Phdr);
+ *off += numsegs * sizeof(Elf_Phdr);
noteoff = *off;
elf_putnote(dst, off, "FreeBSD", NT_PRSTATUS, status,
@@ -996,13 +850,12 @@ elf_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status,
sizeof *psinfo);
notesz = *off - noteoff;
- /* Align up to a page boundary for the program segments. */
+ /* Align up to a page boundary for the data segment. */
*off = round_page(*off);
if (dst != NULL) {
Elf_Ehdr *ehdr;
Elf_Phdr *phdr;
- struct phdr_closure phc;
/*
* Fill in the ELF header.
@@ -1026,7 +879,7 @@ elf_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status,
ehdr->e_flags = 0;
ehdr->e_ehsize = sizeof(Elf_Ehdr);
ehdr->e_phentsize = sizeof(Elf_Phdr);
- ehdr->e_phnum = numsegs + 1;
+ ehdr->e_phnum = numsegs;
ehdr->e_shentsize = sizeof(Elf_Shdr);
ehdr->e_shnum = 0;
ehdr->e_shstrndx = SHN_UNDEF;
@@ -1047,10 +900,25 @@ elf_puthdr(struct proc *p, void *dst, size_t *off, const prstatus_t *status,
phdr->p_align = 0;
phdr++;
- /* All the writable segments from the program. */
- phc.phdr = phdr;
- phc.offset = *off;
- each_writable_segment(p, cb_put_phdr, &phc);
+ /* The data segment. */
+ phdr->p_type = PT_LOAD;
+ phdr->p_offset = *off;
+ phdr->p_vaddr = (Elf_Addr)data;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = phdr->p_memsz = datasz;
+ phdr->p_align = PAGE_SIZE;
+ phdr->p_flags = PF_R | PF_W | PF_X;
+ phdr++;
+
+ /* The stack segment. */
+ phdr->p_type = PT_LOAD;
+ phdr->p_offset = *off + datasz;
+ phdr->p_vaddr = (Elf_Addr)stack;
+ phdr->p_paddr = 0;
+ phdr->p_filesz = phdr->p_memsz = stacksz;
+ phdr->p_align = PAGE_SIZE;
+ phdr->p_flags = PF_R | PF_W | PF_X;
+ phdr++;
}
}
OpenPOWER on IntegriCloud