dhrystone diff dirname dis386 dis88 diskctl du dumpcore \
ed eject elle elvis env expand factor file \
find finger fingerd fix fold format fortune fsck.mfs \
- ftp101 gcov-pull getty grep head hexdump host \
+ ftp101 gcore gcov-pull getty grep head hexdump host \
hostaddr id ifconfig ifdef install \
intr ipcrm ipcs irdpd isoread join kill last leave \
less lex loadkeys loadramdisk logger login look lp \
--- /dev/null
+PROG= gcore
+MAN=
+
+.include <bsd.prog.mk>
--- /dev/null
+/* gcore - create core file of running process */
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <minix/config.h>
+#include <minix/type.h>
+#include <minix/ipc.h>
+#include <minix/const.h>
+#include <sys/ptrace.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <timers.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[])
+{
+ pid_t pid;
+ int r, status;
+
+ if(argc != 2) {
+ printf("usage: %s <pid>\n", argv[0]);
+ return 1;
+ }
+
+ pid = atoi(argv[1]);
+
+ if (ptrace(T_ATTACH, pid, 0, 0) != 0) {
+ perror("ptrace(T_ATTACH)");
+ return 1;
+ }
+
+ if (waitpid(pid, &status, 0) != pid) {
+ perror("waitpid");
+ return 1;
+ }
+
+ while (WIFSTOPPED(status) && WSTOPSIG(status) != SIGSTOP) {
+ /* whatever happens here is fine */
+ ptrace(T_RESUME, pid, 0, WSTOPSIG(status));
+
+ if (waitpid(pid, &status, 0) != pid) {
+ perror("waitpid");
+ return 1;
+ }
+ }
+
+ if (!WIFSTOPPED(status)) {
+ fprintf(stderr, "process died while attaching\n");
+ return 1;
+ }
+
+ if (ptrace(T_DUMPCORE, pid, 0, 0)) {
+ fprintf(stderr, "warning, dumpcore failed (%s)\n",
+ strerror(errno));
+ }
+
+ if (ptrace(T_DETACH, pid, 0, 0)) {
+ fprintf(stderr, "warning, detaching failed (%s)\n",
+ strerror(errno));
+ }
+
+ return r;
+}
/* Additional parameters for PM_DUMPCORE */
# define PM_TERM_SIG m1_i2 /* process's termination signal */
+# define PM_TRACED_PROC m1_i3 /* required for T_DUMPCORE */
/* Parameters for the EXEC_NEWMEM call */
#define EXC_NM_PROC m1_i1 /* process that needs new map */
#define T_SETOPT 13 /* set trace options */
#define T_GETRANGE 14 /* get range of values */
#define T_SETRANGE 15 /* set range of values */
+#define T_DUMPCORE 16 /* dumps the core for the process with the given pid */
#define T_READB_INS 100 /* Read a byte from the text segment of an
* untraced process (only for root)
#define T_SETOPT 13 /* set trace options */
#define T_GETRANGE 14 /* get range of values */
#define T_SETRANGE 15 /* set range of values */
+#define T_DUMPCORE 16 /* dumps the core for the process with the given pid */
#define T_READB_INS 100 /* Read a byte from the text segment of an
* untraced process (only for root)
/* Tell VFS about the exiting process. */
m.m_type = dump_core ? PM_DUMPCORE : PM_EXIT;
m.PM_PROC = rmp->mp_endpoint;
+ m.PM_TRACED_PROC = rmp->mp_endpoint;
if (dump_core) {
m.PM_TERM_SIG = rmp->mp_sigstatus;
if (m_in.PM_STATUS == OK)
rmp->mp_sigstatus |= DUMPED;
- exit_restart(rmp, TRUE /*dump_core*/);
+ if (m_in.PM_PROC == m_in.PM_TRACED_PROC)
+ /* The reply is to a core dump request
+ * for a killed process */
+ exit_restart(rmp, TRUE /*dump_core*/);
+ else
+ /* The reply is to a core dump request
+ * for a traced process (T_DUMPCORE) */
+ /* Wake up the original caller */
+ setreply(rmp-mproc, rmp->mp_procgrp);
break;
register struct mproc *child;
struct ptrace_range pr;
int i, r, seg, req;
+ message m;
req = m_in.request;
mp->mp_reply.reply_trace = 0;
return(OK);
+ case T_DUMPCORE:
+ if ((child = find_proc(m_in.pid)) == NULL) return(ESRCH);
+
+ /* Allow dumpcore only if traced! */
+ if (child->mp_tracer != who_p) return(EPERM);
+
+ /* Tell VFS to dump the core. */
+ m.m_type = PM_DUMPCORE;
+ m.PM_PROC = mp->mp_endpoint;
+ m.PM_TRACED_PROC = child->mp_endpoint;
+ /* Note that m.PM_PROC != m.PM_TRACED_PROC
+ * (we use this to differentiate between a VFS core dump reply for a
+ * an exiting process and the one for a traced process) */
+
+ m.PM_TERM_SIG = child->mp_sigstatus;
+ m.PM_PATH = child->mp_name;
+
+ tell_vfs(mp, &m);
+
+ return(SUSPEND); /* Suspend the process until we receive reply from VFS */
+
case T_STOP: /* stop the process */
/* This call is not exposed to user programs, because its effect can be
* achieved better by sending the traced process a signal with kill(2).
/* Reply status to PM */
m_out.m_type = PM_CORE_REPLY;
m_out.PM_PROC = m_in.PM_PROC;
+ m_out.PM_TRACED_PROC = m_in.PM_TRACED_PROC;
m_out.PM_STATUS = r;
break;
char *exe_name;
{
int proc_s, r, old_who_e;
-
- okendpt(proc_e, &proc_s);
+ int traced_proc_e = m_in.PM_TRACED_PROC;
+
+ okendpt(traced_proc_e, &proc_s);
fp = &fproc[proc_s];
/* Open the core file */
close_fd(fp, r);
/* Terminate the process */
- free_proc(&fproc[proc_s], FP_EXITING);
+ if (traced_proc_e == proc_e)
+ free_proc(&fproc[proc_s], FP_EXITING);
/* Restore the important variables that have been overwritten */
m_in.PM_PROC = proc_e;
+ m_in.PM_TRACED_PROC = traced_proc_e;
who_e = old_who_e;
return OK;