gcore command to coredump a process
This commit is contained in:
parent
eaa29370f4
commit
c30f014a89
11 changed files with 113 additions and 5 deletions
|
@ -12,7 +12,7 @@ SUBDIR= aal add_route arp ash at autil awk \
|
||||||
dhrystone diff dirname dis386 dis88 diskctl du dumpcore \
|
dhrystone diff dirname dis386 dis88 diskctl du dumpcore \
|
||||||
ed eject elle elvis env expand factor file \
|
ed eject elle elvis env expand factor file \
|
||||||
find finger fingerd fix fold format fortune fsck.mfs \
|
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 \
|
hostaddr id ifconfig ifdef install \
|
||||||
intr ipcrm ipcs irdpd isoread join kill last leave \
|
intr ipcrm ipcs irdpd isoread join kill last leave \
|
||||||
less lex loadkeys loadramdisk logger login look lp \
|
less lex loadkeys loadramdisk logger login look lp \
|
||||||
|
|
4
commands/gcore/Makefile
Normal file
4
commands/gcore/Makefile
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
PROG= gcore
|
||||||
|
MAN=
|
||||||
|
|
||||||
|
.include <bsd.prog.mk>
|
66
commands/gcore/gcore.c
Normal file
66
commands/gcore/gcore.c
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
/* 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;
|
||||||
|
}
|
|
@ -794,6 +794,7 @@
|
||||||
|
|
||||||
/* Additional parameters for PM_DUMPCORE */
|
/* Additional parameters for PM_DUMPCORE */
|
||||||
# define PM_TERM_SIG m1_i2 /* process's termination signal */
|
# 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 */
|
/* Parameters for the EXEC_NEWMEM call */
|
||||||
#define EXC_NM_PROC m1_i1 /* process that needs new map */
|
#define EXC_NM_PROC m1_i1 /* process that needs new map */
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#define T_SETOPT 13 /* set trace options */
|
#define T_SETOPT 13 /* set trace options */
|
||||||
#define T_GETRANGE 14 /* get range of values */
|
#define T_GETRANGE 14 /* get range of values */
|
||||||
#define T_SETRANGE 15 /* set 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
|
#define T_READB_INS 100 /* Read a byte from the text segment of an
|
||||||
* untraced process (only for root)
|
* untraced process (only for root)
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#define T_SETOPT 13 /* set trace options */
|
#define T_SETOPT 13 /* set trace options */
|
||||||
#define T_GETRANGE 14 /* get range of values */
|
#define T_GETRANGE 14 /* get range of values */
|
||||||
#define T_SETRANGE 15 /* set 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
|
#define T_READB_INS 100 /* Read a byte from the text segment of an
|
||||||
* untraced process (only for root)
|
* untraced process (only for root)
|
||||||
|
|
|
@ -317,6 +317,7 @@ int dump_core; /* flag indicating whether to dump core */
|
||||||
/* Tell VFS about the exiting process. */
|
/* Tell VFS about the exiting process. */
|
||||||
m.m_type = dump_core ? PM_DUMPCORE : PM_EXIT;
|
m.m_type = dump_core ? PM_DUMPCORE : PM_EXIT;
|
||||||
m.PM_PROC = rmp->mp_endpoint;
|
m.PM_PROC = rmp->mp_endpoint;
|
||||||
|
m.PM_TRACED_PROC = rmp->mp_endpoint;
|
||||||
|
|
||||||
if (dump_core) {
|
if (dump_core) {
|
||||||
m.PM_TERM_SIG = rmp->mp_sigstatus;
|
m.PM_TERM_SIG = rmp->mp_sigstatus;
|
||||||
|
|
|
@ -477,7 +477,15 @@ PRIVATE void handle_vfs_reply()
|
||||||
if (m_in.PM_STATUS == OK)
|
if (m_in.PM_STATUS == OK)
|
||||||
rmp->mp_sigstatus |= DUMPED;
|
rmp->mp_sigstatus |= DUMPED;
|
||||||
|
|
||||||
|
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*/);
|
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;
|
break;
|
||||||
|
|
||||||
|
|
|
@ -42,6 +42,7 @@ PUBLIC int do_trace()
|
||||||
register struct mproc *child;
|
register struct mproc *child;
|
||||||
struct ptrace_range pr;
|
struct ptrace_range pr;
|
||||||
int i, r, seg, req;
|
int i, r, seg, req;
|
||||||
|
message m;
|
||||||
|
|
||||||
req = m_in.request;
|
req = m_in.request;
|
||||||
|
|
||||||
|
@ -90,6 +91,27 @@ PUBLIC int do_trace()
|
||||||
mp->mp_reply.reply_trace = 0;
|
mp->mp_reply.reply_trace = 0;
|
||||||
return(OK);
|
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 */
|
case T_STOP: /* stop the process */
|
||||||
/* This call is not exposed to user programs, because its effect can be
|
/* 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).
|
* achieved better by sending the traced process a signal with kill(2).
|
||||||
|
|
|
@ -558,6 +558,7 @@ PRIVATE void service_pm()
|
||||||
/* Reply status to PM */
|
/* Reply status to PM */
|
||||||
m_out.m_type = PM_CORE_REPLY;
|
m_out.m_type = PM_CORE_REPLY;
|
||||||
m_out.PM_PROC = m_in.PM_PROC;
|
m_out.PM_PROC = m_in.PM_PROC;
|
||||||
|
m_out.PM_TRACED_PROC = m_in.PM_TRACED_PROC;
|
||||||
m_out.PM_STATUS = r;
|
m_out.PM_STATUS = r;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -581,8 +581,9 @@ int csig;
|
||||||
char *exe_name;
|
char *exe_name;
|
||||||
{
|
{
|
||||||
int proc_s, r, old_who_e;
|
int proc_s, r, old_who_e;
|
||||||
|
int traced_proc_e = m_in.PM_TRACED_PROC;
|
||||||
|
|
||||||
okendpt(proc_e, &proc_s);
|
okendpt(traced_proc_e, &proc_s);
|
||||||
fp = &fproc[proc_s];
|
fp = &fproc[proc_s];
|
||||||
|
|
||||||
/* Open the core file */
|
/* Open the core file */
|
||||||
|
@ -603,10 +604,12 @@ char *exe_name;
|
||||||
close_fd(fp, r);
|
close_fd(fp, r);
|
||||||
|
|
||||||
/* Terminate the process */
|
/* Terminate the process */
|
||||||
|
if (traced_proc_e == proc_e)
|
||||||
free_proc(&fproc[proc_s], FP_EXITING);
|
free_proc(&fproc[proc_s], FP_EXITING);
|
||||||
|
|
||||||
/* Restore the important variables that have been overwritten */
|
/* Restore the important variables that have been overwritten */
|
||||||
m_in.PM_PROC = proc_e;
|
m_in.PM_PROC = proc_e;
|
||||||
|
m_in.PM_TRACED_PROC = traced_proc_e;
|
||||||
who_e = old_who_e;
|
who_e = old_who_e;
|
||||||
|
|
||||||
return OK;
|
return OK;
|
||||||
|
|
Loading…
Reference in a new issue