diff options
author | marcel <marcel@FreeBSD.org> | 2003-08-15 05:52:48 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2003-08-15 05:52:48 +0000 |
commit | cae6951d007d5c3530a5cecf47d8efe63e0e8434 (patch) | |
tree | 033489340211683b6f1208281c3ac50631101cc5 /sys/ia64 | |
parent | 5fbc98d240f5b39f16a9b3516deb35dfac88f11a (diff) | |
download | FreeBSD-src-cae6951d007d5c3530a5cecf47d8efe63e0e8434.zip FreeBSD-src-cae6951d007d5c3530a5cecf47d8efe63e0e8434.tar.gz |
Fix the generation of coredumps. We did not take the dirty registers
that were on the kernel stack into account. For now we write them
out to the register stack of the process before creating the dump.
This however is not the final solution. The problem is that we may
invalidate the coredump by overwriting vital information due to an
invalid backing store pointer. Instead we need to write the dirty
registers to an unused region of VM which will result in a seperate
segment in the coredump. For now we can at least get to all the
registers from a coredump.
Diffstat (limited to 'sys/ia64')
-rw-r--r-- | sys/ia64/ia64/elf_machdep.c | 39 |
1 files changed, 38 insertions, 1 deletions
diff --git a/sys/ia64/ia64/elf_machdep.c b/sys/ia64/ia64/elf_machdep.c index 6cecfb0..e295db2 100644 --- a/sys/ia64/ia64/elf_machdep.c +++ b/sys/ia64/ia64/elf_machdep.c @@ -45,9 +45,12 @@ #include <vm/vm_param.h> #include <machine/elf.h> +#include <machine/frame.h> #include <machine/md_var.h> #include <machine/unwind.h> +static int ia64_coredump(struct thread *, struct vnode *, off_t); + struct sysentvec elf64_freebsd_sysvec = { SYS_MAXSYSCALL, sysent, @@ -63,7 +66,7 @@ struct sysentvec elf64_freebsd_sysvec = { NULL, /* &szsigcode */ NULL, "FreeBSD ELF64", - __elfN(coredump), + ia64_coredump, NULL, MINSIGSTKSZ, PAGE_SIZE, @@ -93,6 +96,40 @@ Elf_Addr link_elf_get_gp(linker_file_t); extern Elf_Addr fptr_storage[]; +static int +ia64_coredump(struct thread *td, struct vnode *vp, off_t limit) +{ + struct trapframe *tf; + uint64_t *kstk, *ustk; + uint64_t bspst, ndirty; + + tf = td->td_frame; + ndirty = tf->tf_special.ndirty; + if (ndirty != 0) { + __asm __volatile("mov ar.rsc=0;;"); + __asm __volatile("mov %0=ar.bspstore" : "=r"(bspst)); + /* Make sure we have all the user registers written out. */ + if (bspst - td->td_kstack < ndirty) + __asm __volatile("flushrs;;"); + __asm __volatile("mov ar.rsc=3"); + ustk = (uint64_t*)tf->tf_special.bspstore; + kstk = (uint64_t*)td->td_kstack; + while (ndirty > 0) { + *ustk++ = *kstk++; + if (((uintptr_t)ustk & 0x1ff) == 0x1f8) + *ustk++ = 0; + if (((uintptr_t)kstk & 0x1ff) == 0x1f8) { + kstk++; + ndirty -= 8; + } + ndirty -= 8; + } + tf->tf_special.bspstore = (uintptr_t)ustk; + tf->tf_special.ndirty = 0; + } + return (elf64_coredump(td, vp, limit)); +} + static Elf_Addr lookup_fdesc(linker_file_t lf, Elf_Word symidx) { |