summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/amd64/amd64/trap.c4
-rw-r--r--sys/include/sys/proc.h22
-rw-r--r--sys/kern/kern_proc.c39
3 files changed, 65 insertions, 0 deletions
diff --git a/sys/arch/amd64/amd64/trap.c b/sys/arch/amd64/amd64/trap.c
index c57b5d2..37efad4 100644
--- a/sys/arch/amd64/amd64/trap.c
+++ b/sys/arch/amd64/amd64/trap.c
@@ -127,6 +127,7 @@ static void
trap_user(struct trapframe *tf)
{
struct proc *td = this_td();
+ uintptr_t fault_addr;
sigset_t sigset;
sigemptyset(&sigset);
@@ -148,6 +149,9 @@ trap_user(struct trapframe *tf)
break;
}
+ fault_addr = pf_faultaddr();
+ proc_coredump(td, fault_addr);
+
/*
* Send the signal then flush the signal queue right
* away as these types of events are critical.
diff --git a/sys/include/sys/proc.h b/sys/include/sys/proc.h
index 7aa04b2..54764d0 100644
--- a/sys/include/sys/proc.h
+++ b/sys/include/sys/proc.h
@@ -53,6 +53,26 @@
#define PROC_MAX_FILEDES 256
#define PROC_SIGMAX 64
+/*
+ * The coredump structure, contains information
+ * about crashes.
+ *
+ * @pid: PID of process that has crashed
+ * @fault_addr: Address of faulting memory access
+ * @tf: Copy of the programs trapframe
+ * @checksum: CRC32 checksum of entire coredump
+ *
+ * XXX: DO NOT REORDER (always add to the end before 'checksum')
+ */
+struct __packed coredump {
+ pid_t pid;
+ uintptr_t fault_addr;
+ struct trapframe tf;
+
+ /* XXX: Add entries above the checksum */
+ uint32_t checksum;
+};
+
struct proc {
pid_t pid;
struct exec_prog exec;
@@ -88,7 +108,9 @@ struct proc {
struct proc *this_td(void);
struct proc *get_child(struct proc *cur, pid_t pid);
+
void proc_reap(struct proc *td);
+void proc_coredump(struct proc *td, uintptr_t fault_addr);
pid_t getpid(void);
pid_t getppid(void);
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 3cf2af8..16cd4b2 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -29,7 +29,13 @@
#include <sys/types.h>
#include <sys/proc.h>
+#include <sys/cdefs.h>
+#include <sys/vnode.h>
#include <sys/syscall.h>
+#include <sys/filedesc.h>
+#include <sys/fcntl.h>
+#include <string.h>
+#include <crc32.h>
pid_t
getpid(void)
@@ -61,6 +67,39 @@ getppid(void)
return td->parent->pid;
}
+void
+proc_coredump(struct proc *td, uintptr_t fault_addr)
+{
+ struct coredump core;
+ struct sio_txn sio;
+ struct vnode *vp;
+ char pathname[128];
+ int fd;
+
+ snprintf(pathname, sizeof(pathname), "/tmp/core.%d", td->pid);
+ fd = fd_open(pathname, O_RDWR | O_CREAT);
+
+ /* ... Hopefully not */
+ if (__unlikely(fd < 0)) {
+ return;
+ }
+
+ core.pid = td->pid;
+ core.fault_addr = fault_addr;
+ memcpy(&core.tf, &td->tf, sizeof(td->tf));
+
+ core.checksum = crc32(&core, sizeof(core) - sizeof(core.checksum));
+ vp = fd_get(fd)->vp;
+
+ sio.buf = &core;
+ sio.len = sizeof(core);
+ sio.offset = 0;
+
+ /* Write the core file */
+ vfs_vop_write(vp, &sio);
+ fd_close(fd);
+}
+
scret_t
sys_getpid(struct syscall_args *scargs)
{