summaryrefslogtreecommitdiffstats
path: root/sys/ia64
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2003-08-15 05:52:48 +0000
committermarcel <marcel@FreeBSD.org>2003-08-15 05:52:48 +0000
commitcae6951d007d5c3530a5cecf47d8efe63e0e8434 (patch)
tree033489340211683b6f1208281c3ac50631101cc5 /sys/ia64
parent5fbc98d240f5b39f16a9b3516deb35dfac88f11a (diff)
downloadFreeBSD-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.c39
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)
{
OpenPOWER on IntegriCloud