exec: add core dump support
authorAlan Cox <alan@linux.intel.com>
Wed, 17 Feb 2016 21:47:47 +0000 (21:47 +0000)
committerAlan Cox <alan@linux.intel.com>
Wed, 17 Feb 2016 21:47:47 +0000 (21:47 +0000)
This adds some minimalistic core dump support to the 16bit code base.

Kernel/include/kernel.h
Kernel/include/level2.h
Kernel/process.c
Kernel/syscall_exec16.c

index c5ad4ca..ee54012 100644 (file)
@@ -47,6 +47,8 @@ From UZI by Doug Braun and UZI280 by Stefan Nitschke.
        (udata.u_ptab->p_uid == (p)->p_uid || super())
 #define pathbuf()      tmpbuf()
 #define pathfree(tb)   brelse(tb)
+#define dump_core(sig)
+
 #endif
 
 #define CPM_EMULATOR_FILENAME    "/usr/cpm/emulator"
@@ -445,6 +447,8 @@ typedef struct u_data {
 #ifdef CONFIG_LEVEL_2
     uint16_t    u_groups[NGROUP]; /* Group list */
     uint8_t    u_ngroup;
+    uint8_t    u_flags;
+#define U_FLAG_NOCORE          1       /* Set if no core dump */
     struct rlimit u_rlimit[NRLIMIT];   /* Resource limits */
 #endif
 } u_data;
index 35f45c4..3aa77cf 100644 (file)
@@ -60,4 +60,21 @@ extern arg_t _setpgid(void);
 extern arg_t _setsid(void);
 extern arg_t _getsid(void);
 
+/* Provided by the execve support */
+extern void write_core_image(void);
+
+/* This will change a lot in future ! */
+struct coredump {
+       uint16_t ch_magic1;
+#define MAGIC1 0xDEAD
+       uint16_t ch_magic2;
+#define MAGIC2 0xC0DE
+       uint8_t ch_type;        /* For now 16 or 32 bit number of bits - will
+                                  change! */
+       uint32_t ch_base;
+       uint32_t ch_break;
+       uint32_t ch_sp;
+       uint32_t ch_top;
+};
+
 #endif
index 38eb74c..dec3072 100644 (file)
@@ -433,6 +433,18 @@ void sgrpsig(uint16_t pgrp, uint8_t sig)
        }
 }
 
+#ifdef CONFIG_LEVEL_2
+static void dump_core(uint8_t sig)
+{
+        if (!(udata.u_flags & U_FLAG_NOCORE) && ((sig == SIGQUIT || sig == SIGILL || sig == SIGTRAP ||
+            sig == SIGABRT || sig == SIGBUS || sig == SIGFPE ||
+            sig == SIGSEGV || sig == SIGXCPU || sig == SIGXFSZ ||
+            sig == SIGSYS))) {
+               write_core_image();
+       }
+}
+#endif                                    
+
 /* This sees if the current process has any signals set, and handles them.
  */
 void chksigs(void)
@@ -477,6 +489,7 @@ void chksigs(void)
 #ifdef DEBUG
                        kprintf("process terminated by signal %d\n", j);
 #endif
+                        dump_core(j);
                        doexit((uint16_t)j << 8);
                } else if (*svec != SIG_IGN) {
                        /* Arrange to call the user routine at return */
index 46e77e6..aa47787 100644 (file)
@@ -111,6 +111,15 @@ arg_t _execve(void)
                goto nogood;
        }
 
+       /* Core dump and ptrace permission logic */
+#ifdef CONFIG_LEVEL_2
+       if ((!getperm(ino) & OTH_RD) ||
+               (ino->c_node.i_mode & (SET_UID | SET_GID)))
+               udata.u_flags |= U_FLAG_NOCORE;
+       else
+               udata.u_flags &= ~U_FLAG_NOCORE;
+#endif
+
        setftime(ino, A_TIME);
 
        if (ino->c_node.i_size == 0) {
@@ -334,3 +343,56 @@ arg_t _memfree(void)
        udata.u_error = ENOMEM;
        return -1;
 }
+
+#ifdef CONFIG_LEVEL_2
+
+/*
+ *     Core dump
+ */
+
+static struct coredump corehdr = {
+       0xDEAD,
+       0xC0DE,
+       16,
+};
+
+void write_core_image(void)
+{
+       inoptr parent = NULLINODE;
+       inoptr ino;
+
+       ino = kn_open("core", &parent);
+       if (ino) {
+               i_deref(parent);
+               return;
+       }
+       if (parent && (ino = newfile(parent, "core"))) {
+               ino->c_node.i_mode = F_REG | 0400;
+               setftime(ino, A_TIME | M_TIME | C_TIME);
+               wr_inode(ino);
+               f_trunc(ino);
+
+               /* FIXME: need to add some arch specific header bits, and
+                  also pull stuff like the true sp and registers out of
+                  the return stack properly */
+
+               corehdr.ch_base = MAPBASE;
+               corehdr.ch_break = udata.u_break;
+               corehdr.ch_sp = udata.u_syscall_sp;
+               corehdr.ch_top = PROGTOP;
+               udata.u_offset = 0;
+               udata.u_base = (uint8_t *)&corehdr;
+               udata.u_sysio = true;
+               udata.u_count = sizeof(corehdr);
+               writei(ino, 0);
+               udata.u_sysio = false;
+               udata.u_base = MAPBASE;
+               udata.u_count = udata.u_break - MAPBASE;
+               writei(ino, 0);
+               udata.u_base = udata.u_sp;
+               udata.u_count = PROGTOP - udata.u_sp;
+               writei(ino, 0);
+               i_deref(ino);
+       }
+}
+#endif